Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
c06a3d9dcf
@ -60,15 +60,15 @@ if (POLICY CMP0069)
|
|||||||
# set_property(DIRECTORY PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) do not work?
|
# set_property(DIRECTORY PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) do not work?
|
||||||
string(REPLACE ";" " " CXX_FLAGS_IPO "${CMAKE_CXX_COMPILE_OPTIONS_IPO}")
|
string(REPLACE ";" " " CXX_FLAGS_IPO "${CMAKE_CXX_COMPILE_OPTIONS_IPO}")
|
||||||
message(STATUS "Use link time optimization CXX options: ${CXX_FLAGS_IPO}")
|
message(STATUS "Use link time optimization CXX options: ${CXX_FLAGS_IPO}")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_FLAGS_IPO}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS_IPO}")
|
||||||
|
|
||||||
string(REPLACE ";" " " C_FLAGS_IPO "${CMAKE_C_COMPILE_OPTIONS_IPO}")
|
string(REPLACE ";" " " C_FLAGS_IPO "${CMAKE_C_COMPILE_OPTIONS_IPO}")
|
||||||
message(STATUS "Use link time optimization C options: ${C_FLAGS_IPO}")
|
message(STATUS "Use link time optimization C options: ${C_FLAGS_IPO}")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${C_FLAGS_IPO}")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_IPO}")
|
||||||
|
|
||||||
string(REPLACE ";" " " LINK_FLAGS_IPO "${CMAKE_CXX_LINK_OPTIONS_IPO}")
|
string(REPLACE ";" " " LINK_FLAGS_IPO "${CMAKE_CXX_LINK_OPTIONS_IPO}")
|
||||||
message(STATUS "Use link time optimization linker options: ${LINK_FLAGS_IPO}")
|
message(STATUS "Use link time optimization linker options: ${LINK_FLAGS_IPO}")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINK_FLAGS_IPO}")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_FLAGS_IPO}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -335,6 +335,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/files/PartsManager.cpp
|
td/telegram/files/PartsManager.cpp
|
||||||
td/telegram/files/ResourceManager.cpp
|
td/telegram/files/ResourceManager.cpp
|
||||||
td/telegram/Game.cpp
|
td/telegram/Game.cpp
|
||||||
|
td/telegram/GameManager.cpp
|
||||||
td/telegram/Global.cpp
|
td/telegram/Global.cpp
|
||||||
td/telegram/GroupCallManager.cpp
|
td/telegram/GroupCallManager.cpp
|
||||||
td/telegram/GroupCallParticipant.cpp
|
td/telegram/GroupCallParticipant.cpp
|
||||||
@ -403,7 +404,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/SendCodeHelper.cpp
|
td/telegram/SendCodeHelper.cpp
|
||||||
td/telegram/SequenceDispatcher.cpp
|
td/telegram/SequenceDispatcher.cpp
|
||||||
td/telegram/SpecialStickerSetType.cpp
|
td/telegram/SpecialStickerSetType.cpp
|
||||||
td/telegram/SponsoredMessages.cpp
|
td/telegram/SponsoredMessageManager.cpp
|
||||||
td/telegram/StateManager.cpp
|
td/telegram/StateManager.cpp
|
||||||
td/telegram/StickersManager.cpp
|
td/telegram/StickersManager.cpp
|
||||||
td/telegram/StorageManager.cpp
|
td/telegram/StorageManager.cpp
|
||||||
@ -524,6 +525,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/FolderId.h
|
td/telegram/FolderId.h
|
||||||
td/telegram/FullMessageId.h
|
td/telegram/FullMessageId.h
|
||||||
td/telegram/Game.h
|
td/telegram/Game.h
|
||||||
|
td/telegram/GameManager.h
|
||||||
td/telegram/Global.h
|
td/telegram/Global.h
|
||||||
td/telegram/GroupCallId.h
|
td/telegram/GroupCallId.h
|
||||||
td/telegram/GroupCallManager.h
|
td/telegram/GroupCallManager.h
|
||||||
@ -618,7 +620,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/ServerMessageId.h
|
td/telegram/ServerMessageId.h
|
||||||
td/telegram/SetWithPosition.h
|
td/telegram/SetWithPosition.h
|
||||||
td/telegram/SpecialStickerSetType.h
|
td/telegram/SpecialStickerSetType.h
|
||||||
td/telegram/SponsoredMessages.h
|
td/telegram/SponsoredMessageManager.h
|
||||||
td/telegram/StateManager.h
|
td/telegram/StateManager.h
|
||||||
td/telegram/StickerSetId.h
|
td/telegram/StickerSetId.h
|
||||||
td/telegram/StickersManager.h
|
td/telegram/StickersManager.h
|
||||||
|
42
README.md
42
README.md
@ -80,7 +80,6 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele
|
|||||||
- [Examples and documentation](#usage)
|
- [Examples and documentation](#usage)
|
||||||
- [Dependencies](#dependencies)
|
- [Dependencies](#dependencies)
|
||||||
- [Building](#building)
|
- [Building](#building)
|
||||||
- [Installing dependencies](#installing-dependencies)
|
|
||||||
- [Using in CMake C++ projects](#using-cxx)
|
- [Using in CMake C++ projects](#using-cxx)
|
||||||
- [Using in Java projects](#using-java)
|
- [Using in Java projects](#using-java)
|
||||||
- [Using in .NET projects](#using-dotnet)
|
- [Using in .NET projects](#using-dotnet)
|
||||||
@ -132,8 +131,7 @@ for a list of all available `TDLib` [methods](https://core.telegram.org/tdlib/do
|
|||||||
The simplest way to build `TDLight` is to use our [TDLight build instructions generator](https://tdlight-team.github.io/tdlight/build.html).
|
The simplest way to build `TDLight` is to use our [TDLight build instructions generator](https://tdlight-team.github.io/tdlight/build.html).
|
||||||
You need only to choose your programming language and target operating system to receive complete build instructions.
|
You need only to choose your programming language and target operating system to receive complete build instructions.
|
||||||
|
|
||||||
In general, you need to install all `TDLib` [dependencies](#dependencies) as described in [Installing dependencies](#installing-dependencies).
|
In general, you need to install all `TDLib` [dependencies](#dependencies), enter directory containing `TDLib` sources and compile them using CMake:
|
||||||
Then enter directory containing `TDLib` sources and compile them using CMake:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -159,44 +157,6 @@ php SplitSource.php --undo
|
|||||||
```
|
```
|
||||||
In our tests clang 6.0 with libc++ required less than 500 MB of RAM per file and GCC 4.9/6.3 used less than 1 GB of RAM per file.
|
In our tests clang 6.0 with libc++ required less than 500 MB of RAM per file and GCC 4.9/6.3 used less than 1 GB of RAM per file.
|
||||||
|
|
||||||
<a name="installing-dependencies"></a>
|
|
||||||
### Installing dependencies
|
|
||||||
|
|
||||||
<a name="macos"></a>
|
|
||||||
#### macOS
|
|
||||||
* Install the latest Xcode command line tools, for example, via `xcode-select --install`.
|
|
||||||
* Install other [dependencies](#dependencies), for example, using [Homebrew](https://brew.sh):
|
|
||||||
```
|
|
||||||
brew install gperf cmake openssl
|
|
||||||
```
|
|
||||||
* Build `TDLib` with CMake as explained in [building](#building). You will likely need to manually specify path to the installed OpenSSL to CMake, e.g.,
|
|
||||||
```
|
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/ ..
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="windows"></a>
|
|
||||||
#### Windows
|
|
||||||
* Download and install Microsoft Visual Studio 2015 or later.
|
|
||||||
* Download and install [gperf](https://sourceforge.net/projects/gnuwin32/files/gperf/3.0.1/). Add the path to gperf.exe to the PATH environment variable.
|
|
||||||
* Install [vcpkg](https://github.com/Microsoft/vcpkg#quick-start).
|
|
||||||
* Run the following commands to install `TDLib` dependencies using vcpkg:
|
|
||||||
```
|
|
||||||
cd <path to vcpkg>
|
|
||||||
.\vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows
|
|
||||||
```
|
|
||||||
* Download and install [CMake](https://cmake.org/download/); choose "Add CMake to the system PATH" option while installing.
|
|
||||||
* Build `TDLib` with CMake as explained in [building](#building), but instead of `cmake -DCMAKE_BUILD_TYPE=Release ..` use
|
|
||||||
```
|
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=<path to vcpkg>/scripts/buildsystems/vcpkg.cmake ..
|
|
||||||
```
|
|
||||||
|
|
||||||
To build 32-bit/64-bit `TDLib` using MSVC, you will need to additionally specify parameter `-A Win32`/`-A x64` to CMake.
|
|
||||||
To build `TDLib` in Release mode using MSVC, you will need to additionally specify parameter `--config Release` to the `cmake --build .` command.
|
|
||||||
|
|
||||||
<a name="linux"></a>
|
|
||||||
#### Linux
|
|
||||||
* Install all [dependencies](#dependencies) using your package manager.
|
|
||||||
|
|
||||||
<a name="using-cxx"></a>
|
<a name="using-cxx"></a>
|
||||||
## Using in CMake C++ projects
|
## Using in CMake C++ projects
|
||||||
For C++ projects that use CMake, the best approach is to build `TDLib` as part of your project or to install it system-wide.
|
For C++ projects that use CMake, the best approach is to build `TDLib` as part of your project or to install it system-wide.
|
||||||
|
@ -286,6 +286,7 @@ function split_file($file, $chunks, $undo) {
|
|||||||
'file_reference_manager[_(-][^.]|FileReferenceManager|file_references[)]' => 'FileReferenceManager',
|
'file_reference_manager[_(-][^.]|FileReferenceManager|file_references[)]' => 'FileReferenceManager',
|
||||||
'file_manager[_(-][^.]|FileManager([^ ;.]| [^*])|update_file[)]' => 'files/FileManager',
|
'file_manager[_(-][^.]|FileManager([^ ;.]| [^*])|update_file[)]' => 'files/FileManager',
|
||||||
'G[(][)]|Global[^A-Za-z]' => 'Global',
|
'G[(][)]|Global[^A-Za-z]' => 'Global',
|
||||||
|
'game_manager[_(-][^.]|GameManager' => 'GameManager',
|
||||||
'group_call_manager[_(-][^.]|GroupCallManager' => 'GroupCallManager',
|
'group_call_manager[_(-][^.]|GroupCallManager' => 'GroupCallManager',
|
||||||
'HashtagHints' => 'HashtagHints',
|
'HashtagHints' => 'HashtagHints',
|
||||||
'inline_queries_manager[_(-][^.]|InlineQueriesManager' => 'InlineQueriesManager',
|
'inline_queries_manager[_(-][^.]|InlineQueriesManager' => 'InlineQueriesManager',
|
||||||
@ -300,6 +301,7 @@ function split_file($file, $chunks, $undo) {
|
|||||||
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
||||||
'SecretChatActor' => 'SecretChatActor',
|
'SecretChatActor' => 'SecretChatActor',
|
||||||
'secret_chats_manager[_(-][^.]|SecretChatsManager' => 'SecretChatsManager',
|
'secret_chats_manager[_(-][^.]|SecretChatsManager' => 'SecretChatsManager',
|
||||||
|
'sponsored_message_manager[_(-][^.]|SponsoredMessageManager' => 'SponsoredMessageManager',
|
||||||
'stickers_manager[_(-][^.]|StickersManager' => 'StickersManager',
|
'stickers_manager[_(-][^.]|StickersManager' => 'StickersManager',
|
||||||
'[>](td_db[(][)]|get_td_db_impl[(])|TdDb[^A-Za-z]' => 'TdDb',
|
'[>](td_db[(][)]|get_td_db_impl[(])|TdDb[^A-Za-z]' => 'TdDb',
|
||||||
'theme_manager[_(-][^.]|ThemeManager' => "ThemeManager",
|
'theme_manager[_(-][^.]|ThemeManager' => "ThemeManager",
|
||||||
|
@ -542,6 +542,10 @@ function onOptionsChanged() {
|
|||||||
if (os_netbsd) {
|
if (os_netbsd) {
|
||||||
pre_text.push('Note that the following instruction is for NetBSD 8.0 and default SH shell.');
|
pre_text.push('Note that the following instruction is for NetBSD 8.0 and default SH shell.');
|
||||||
}
|
}
|
||||||
|
if (os_mac) {
|
||||||
|
pre_text.push('Note that the following instruction will build TDLib only for the current architecture (x64 or Apple silicon).');
|
||||||
|
pre_text.push('If you want to create a universal XCFramework, take a look at our <a href="https://github.com/tdlib/td/tree/master/example/ios">example</a> instead.');
|
||||||
|
}
|
||||||
|
|
||||||
var terminal_name = (function () {
|
var terminal_name = (function () {
|
||||||
if (os_windows) {
|
if (os_windows) {
|
||||||
|
@ -136,10 +136,11 @@ See also the source code of [Fernschreiber](https://github.com/Wunderfitz/harbou
|
|||||||
|
|
||||||
TDLib can be used from the Swift programming language through the [JSON](https://github.com/tdlib/td#using-json) interface and can be linked statically or dynamically.
|
TDLib can be used from the Swift programming language through the [JSON](https://github.com/tdlib/td#using-json) interface and can be linked statically or dynamically.
|
||||||
|
|
||||||
|
See [example/ios](https://github.com/tdlib/td/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, and macOS.
|
||||||
|
|
||||||
See [TDLib-iOS](https://github.com/leoMehlig/TDLib-iOS) or [tdlib-swift](https://github.com/modestman/tdlib-swift), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
|
See [TDLib-iOS](https://github.com/leoMehlig/TDLib-iOS) or [tdlib-swift](https://github.com/modestman/tdlib-swift), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
|
||||||
|
|
||||||
See [example/swift](https://github.com/tdlib/td/tree/master/example/swift) for an example of a macOS Swift application.
|
See [example/swift](https://github.com/tdlib/td/tree/master/example/swift) for an example of a macOS Swift application.
|
||||||
See [example/ios](https://github.com/tdlib/td/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, and macOS.
|
|
||||||
|
|
||||||
<a name="objective-c"></a>
|
<a name="objective-c"></a>
|
||||||
## Using TDLib in Objective-C projects
|
## Using TDLib in Objective-C projects
|
||||||
|
@ -6,16 +6,12 @@ index 695be54..4efe5e5 100644
|
|||||||
# - iOS - build everything for iOS
|
# - iOS - build everything for iOS
|
||||||
# - tvOS - build everything for tvOS
|
# - tvOS - build everything for tvOS
|
||||||
# - watchOS - build everything for watchOS
|
# - watchOS - build everything for watchOS
|
||||||
-# - OpenSSL-macOS - build OpenSSL for macOS
|
# - OpenSSL-macOS - build OpenSSL for macOS
|
||||||
-# - OpenSSL-iOS - build OpenSSL for iOS
|
# - OpenSSL-iOS - build OpenSSL for iOS
|
||||||
-# - OpenSSL-tvOS - build OpenSSL for tvOS
|
|
||||||
-# - OpenSSL-watchOS - build OpenSSL for watchOS
|
|
||||||
+# - OpenSSL-macOS - build OpenSSL for macOS
|
|
||||||
+# - OpenSSL-iOS - build OpenSSL for iOS
|
|
||||||
+# - OpenSSL-iOS-simulator - build OpenSSL for iOS-simulator
|
+# - OpenSSL-iOS-simulator - build OpenSSL for iOS-simulator
|
||||||
+# - OpenSSL-tvOS - build OpenSSL for tvOS
|
# - OpenSSL-tvOS - build OpenSSL for tvOS
|
||||||
+# - OpenSSL-tvOS-simulator - build OpenSSL for tvOS-simulator
|
+# - OpenSSL-tvOS-simulator - build OpenSSL for tvOS-simulator
|
||||||
+# - OpenSSL-watchOS - build OpenSSL for watchOS
|
# - OpenSSL-watchOS - build OpenSSL for watchOS
|
||||||
+# - OpenSSL-watchOS-simulator - build OpenSSL for watchOS-simulator
|
+# - OpenSSL-watchOS-simulator - build OpenSSL for watchOS-simulator
|
||||||
# - BZip2-macOS - build BZip2 for macOS
|
# - BZip2-macOS - build BZip2 for macOS
|
||||||
# - BZip2-iOS - build BZip2 for iOS
|
# - BZip2-iOS - build BZip2 for iOS
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Build for iOS
|
# Universal XCFramework build example
|
||||||
|
|
||||||
Below are instructions for building TDLib for iOS, watchOS, tvOS, and also macOS.
|
Below are instructions for building TDLib for iOS, watchOS, tvOS, and also macOS.
|
||||||
|
|
||||||
If you need only a macOS build, take a look at our build instructions for [macOS](https://github.com/tdlib/td#macos).
|
If you need only a macOS build for the current architecture, take a look at [TDLib build instructions generator](https://tdlib.github.io/td/build.html).
|
||||||
|
|
||||||
For example of usage take a look at our [Swift example](https://github.com/tdlib/td/tree/master/example/swift).
|
For example of usage take a look at our [Swift example](https://github.com/tdlib/td/tree/master/example/swift).
|
||||||
|
|
||||||
@ -21,24 +21,26 @@ cd native-build
|
|||||||
cmake ..
|
cmake ..
|
||||||
cmake --build . --target prepare_cross_compiling
|
cmake --build . --target prepare_cross_compiling
|
||||||
```
|
```
|
||||||
* Build OpenSSL for iOS, watchOS, tvOS and macOS:
|
* Build OpenSSL for iOS, watchOS, tvOS, and macOS:
|
||||||
```
|
```
|
||||||
cd <path to TDLib sources>/example/ios
|
cd <path to TDLib sources>/example/ios
|
||||||
./build-openssl.sh
|
./build-openssl.sh
|
||||||
```
|
```
|
||||||
Here we use scripts from [Python Apple support](https://github.com/beeware/Python-Apple-support), but any other OpenSSL builds should work too.
|
Here we use scripts from [Python Apple support](https://github.com/beeware/Python-Apple-support), but any other OpenSSL build should work too.
|
||||||
[Python Apple support](https://github.com/beeware/Python-Apple-support) has known problems with spaces in the path to the current directory, so
|
[Python Apple support](https://github.com/beeware/Python-Apple-support) has known problems with spaces in the path to the current directory, so
|
||||||
you need to ensure that there is no spaces in the path.
|
you need to ensure that there are no spaces in the path.
|
||||||
Built libraries should be stored in `third_party/openssl/<platform>`, because the next script will rely on this location.
|
Built OpenSSL libraries should be stored in the directory `third_party/openssl/<platform>`, because the next script will rely on this location.
|
||||||
* Build TDLib for iOS, watchOS, tvOS and macOS:
|
* Build TDLib for iOS, watchOS, tvOS, and macOS:
|
||||||
```
|
```
|
||||||
cd <path to TDLib sources>/example/ios
|
cd <path to TDLib sources>/example/ios
|
||||||
./build.sh
|
./build.sh
|
||||||
```
|
```
|
||||||
This may take a while, because TDLib will be built about 10 times.
|
This may take a while, because TDLib will be built about 16 times.
|
||||||
Resulting library for iOS will work on any architecture (armv7, armv7s, arm64) and even on a simulator (Intel, Apple Silicon).
|
Resulting XCFramework will work on any architecture and even on a simulator (x64, Apple silicon).
|
||||||
We use [CMake/iOS.cmake](https://github.com/tdlib/td/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
|
We use [CMake/iOS.cmake](https://github.com/tdlib/td/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
|
||||||
|
|
||||||
Built libraries will be stored in `tdjson` directory.
|
Built libraries and XCFramework will be stored in `tdjson` directory.
|
||||||
|
|
||||||
Documentation for all available classes and methods can be found at https://core.telegram.org/tdlib/docs.
|
Documentation for all available classes and methods can be found at https://core.telegram.org/tdlib/docs.
|
||||||
|
|
||||||
|
If you receive an "error: SDK "appletvsimulator" cannot be located", you need to run the command "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" before running ./build.sh.
|
||||||
|
@ -26,6 +26,37 @@ for platform in $platforms;
|
|||||||
do
|
do
|
||||||
echo "Platform = ${platform}"
|
echo "Platform = ${platform}"
|
||||||
if [[ $platform = "macOS" ]]; then
|
if [[ $platform = "macOS" ]]; then
|
||||||
|
simulators="0"
|
||||||
|
else
|
||||||
|
simulators="0 1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for simulator in $simulators;
|
||||||
|
do
|
||||||
|
if [[ $platform = "macOS" ]]; then
|
||||||
|
other_options="-DCMAKE_OSX_ARCHITECTURES='x86_64;arm64'"
|
||||||
|
else
|
||||||
|
watchos=""
|
||||||
|
if [[ $platform = "watchOS" ]]; then
|
||||||
|
ios_platform="WATCH"
|
||||||
|
watchos="-DTD_EXPERIMENTAL_WATCH_OS=ON"
|
||||||
|
elif [[ $platform = "tvOS" ]]; then
|
||||||
|
ios_platform="TV"
|
||||||
|
else
|
||||||
|
ios_platform=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $simulator = "1" ]]; then
|
||||||
|
platform="${platform}-simulator"
|
||||||
|
ios_platform="${ios_platform}SIMULATOR"
|
||||||
|
else
|
||||||
|
ios_platform="${ios_platform}OS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "iOS platform = ${ios_platform}"
|
||||||
|
other_options="${watchos} -DIOS_PLATFORM=${ios_platform} -DCMAKE_TOOLCHAIN_FILE=${td_path}/CMake/iOS.cmake"
|
||||||
|
fi
|
||||||
|
|
||||||
set_cmake_options $platform
|
set_cmake_options $platform
|
||||||
build="build-${platform}"
|
build="build-${platform}"
|
||||||
install="install-${platform}"
|
install="install-${platform}"
|
||||||
@ -33,62 +64,15 @@ do
|
|||||||
mkdir -p $build
|
mkdir -p $build
|
||||||
mkdir -p $install
|
mkdir -p $install
|
||||||
cd $build
|
cd $build
|
||||||
cmake $td_path $options -DCMAKE_INSTALL_PREFIX=../${install} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
cmake $td_path $options $other_options -DCMAKE_INSTALL_PREFIX=../${install}
|
||||||
make -j3 install || exit
|
make -j3 install || exit
|
||||||
cd ..
|
cd ..
|
||||||
mkdir -p $platform
|
install_name_tool -id @rpath/libtdjson.dylib ${install}/lib/libtdjson.dylib
|
||||||
cp $build/libtdjson.dylib $platform/libtdjson.dylib
|
|
||||||
install_name_tool -id @rpath/libtdjson.dylib $platform/libtdjson.dylib
|
|
||||||
|
|
||||||
mkdir -p ../tdjson/${platform}/include
|
mkdir -p ../tdjson/${platform}/include
|
||||||
rsync --recursive ${install}/include/ ../tdjson/${platform}/include/
|
rsync --recursive ${install}/include/ ../tdjson/${platform}/include/
|
||||||
mkdir -p ../tdjson/${platform}/lib
|
mkdir -p ../tdjson/${platform}/lib
|
||||||
cp ${platform}/libtdjson.dylib ../tdjson/${platform}/lib/
|
cp ${install}/lib/libtdjson.dylib ../tdjson/${platform}/lib/
|
||||||
else
|
done
|
||||||
simulators="0 1"
|
|
||||||
for simulator in $simulators;
|
|
||||||
do
|
|
||||||
build="build-${platform}"
|
|
||||||
install="install-${platform}"
|
|
||||||
if [[ $simulator = "1" ]]; then
|
|
||||||
build="${build}-simulator"
|
|
||||||
install="${install}-simulator"
|
|
||||||
platform_path="${platform}-simulator"
|
|
||||||
ios_platform="SIMULATOR"
|
|
||||||
lib="${install}/lib/libtdjson.dylib"
|
|
||||||
set_cmake_options ${platform_path}
|
|
||||||
else
|
|
||||||
platform_path=${platform}
|
|
||||||
ios_platform="OS"
|
|
||||||
lib="${install}/lib/libtdjson.dylib"
|
|
||||||
set_cmake_options ${platform_path}
|
|
||||||
fi
|
|
||||||
watchos=""
|
|
||||||
if [[ $platform = "watchOS" ]]; then
|
|
||||||
ios_platform="WATCH${ios_platform}"
|
|
||||||
watchos="-DTD_EXPERIMENTAL_WATCH_OS=ON"
|
|
||||||
fi
|
|
||||||
if [[ $platform = "tvOS" ]]; then
|
|
||||||
ios_platform="TV${ios_platform}"
|
|
||||||
fi
|
|
||||||
echo $ios_platform
|
|
||||||
rm -rf $build
|
|
||||||
mkdir -p $build
|
|
||||||
mkdir -p $install
|
|
||||||
cd $build
|
|
||||||
cmake $td_path $options $watchos -DIOS_PLATFORM=${ios_platform} -DCMAKE_TOOLCHAIN_FILE=${td_path}/CMake/iOS.cmake -DCMAKE_INSTALL_PREFIX=../${install}
|
|
||||||
make -j3 install || exit
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
install_name_tool -id @rpath/libtdjson.dylib $lib
|
|
||||||
|
|
||||||
mkdir -p ../tdjson/${platform_path}/include
|
|
||||||
rsync --recursive ${install}/include/ ../tdjson/${platform_path}/include/
|
|
||||||
mkdir -p ../tdjson/${platform_path}/lib
|
|
||||||
cp ${lib} ../tdjson/${platform_path}/lib/
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
produced_dylibs=(install-*/lib/libtdjson.dylib)
|
produced_dylibs=(install-*/lib/libtdjson.dylib)
|
||||||
|
@ -32,8 +32,8 @@ cd <path to TDLib sources>/example/java/bin
|
|||||||
java '-Djava.library.path=.' org/drinkless/tdlib/example/Example
|
java '-Djava.library.path=.' org/drinkless/tdlib/example/Example
|
||||||
```
|
```
|
||||||
|
|
||||||
If you get "Could NOT find JNI ..." error from CMake, you need to specify to CMake path to the installed JDK, for example, "-DJAVA_HOME=/usr/lib/jvm/java-8-oracle/".
|
If you receive "Could NOT find JNI ..." error from CMake, you need to specify to CMake path to the installed JDK, for example, "-DJAVA_HOME=/usr/lib/jvm/java-8-oracle/".
|
||||||
|
|
||||||
If you get java.lang.UnsatisfiedLinkError with "Can't find dependent libraries", you may also need to copy some dependent shared OpenSSL and zlib libraries to `bin/`.
|
If you receive java.lang.UnsatisfiedLinkError with "Can't find dependent libraries", you may also need to copy some dependent shared OpenSSL and zlib libraries to `bin/`.
|
||||||
|
|
||||||
In case you compiled the example as 32-bit version, you may need to give -d32 parameter to Java.
|
In case you compiled the example as 32-bit version, you may need to give -d32 parameter to Java.
|
||||||
|
@ -7,7 +7,7 @@ You need a Unix shell with `sed`, `tar` and `wget` utilities to run the provided
|
|||||||
## Building tdweb NPM package
|
## Building tdweb NPM package
|
||||||
|
|
||||||
* Install the 2.0.6 [emsdk](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html), which is known to work. Do not use the system-provided `emscripten` package, because it contains a too old emsdk version.
|
* Install the 2.0.6 [emsdk](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html), which is known to work. Do not use the system-provided `emscripten` package, because it contains a too old emsdk version.
|
||||||
* Install all `TDLib` build dependencies as described in [Building](https://github.com/tdlib/td#building).
|
* Install all `TDLib` build dependencies described in [Building](https://github.com/tdlib/td#building).
|
||||||
* Run `source ./emsdk_env.sh` from `emsdk` directory to set up the correct build environment.
|
* Run `source ./emsdk_env.sh` from `emsdk` directory to set up the correct build environment.
|
||||||
* On `macOS`, install the `coreutils` [Homebrew](https://brew.sh) package and replace `realpath` in scripts with `grealpath`:
|
* On `macOS`, install the `coreutils` [Homebrew](https://brew.sh) package and replace `realpath` in scripts with `grealpath`:
|
||||||
```
|
```
|
||||||
|
@ -137,8 +137,8 @@ temporaryPasswordState has_password:Bool valid_for:int32 = TemporaryPasswordStat
|
|||||||
//@is_downloading_active True, if the file is currently being downloaded (or a local copy is being generated by some other means)
|
//@is_downloading_active True, if the file is currently being downloaded (or a local copy is being generated by some other means)
|
||||||
//@is_downloading_completed True, if the local copy is fully available
|
//@is_downloading_completed True, if the local copy is fully available
|
||||||
//@download_offset Download will be started from this offset. downloaded_prefix_size is calculated from this offset
|
//@download_offset Download will be started from this offset. downloaded_prefix_size is calculated from this offset
|
||||||
//@downloaded_prefix_size If is_downloading_completed is false, then only some prefix of the file starting from download_offset is ready to be read. downloaded_prefix_size is the size of that prefix
|
//@downloaded_prefix_size If is_downloading_completed is false, then only some prefix of the file starting from download_offset is ready to be read. downloaded_prefix_size is the size of that prefix in bytes
|
||||||
//@downloaded_size Total downloaded file bytes. Should be used only for calculating download progress. The actual file size may be bigger, and some parts of it may contain garbage
|
//@downloaded_size Total downloaded file size, in bytes. Should be used only for calculating download progress. The actual file size may be bigger, and some parts of it may contain garbage
|
||||||
localFile path:string can_be_downloaded:Bool can_be_deleted:Bool is_downloading_active:Bool is_downloading_completed:Bool download_offset:int32 downloaded_prefix_size:int32 downloaded_size:int32 = LocalFile;
|
localFile path:string can_be_downloaded:Bool can_be_deleted:Bool is_downloading_active:Bool is_downloading_completed:Bool download_offset:int32 downloaded_prefix_size:int32 downloaded_size:int32 = LocalFile;
|
||||||
|
|
||||||
//@description Represents a remote file
|
//@description Represents a remote file
|
||||||
@ -148,13 +148,13 @@ localFile path:string can_be_downloaded:Bool can_be_deleted:Bool is_downloading_
|
|||||||
//@unique_id Unique file identifier; may be empty if unknown. The unique file identifier which is the same for the same file even for different users and is persistent over time
|
//@unique_id Unique file identifier; may be empty if unknown. The unique file identifier which is the same for the same file even for different users and is persistent over time
|
||||||
//@is_uploading_active True, if the file is currently being uploaded (or a remote copy is being generated by some other means)
|
//@is_uploading_active True, if the file is currently being uploaded (or a remote copy is being generated by some other means)
|
||||||
//@is_uploading_completed True, if a remote copy is fully available
|
//@is_uploading_completed True, if a remote copy is fully available
|
||||||
//@uploaded_size Size of the remote available part of the file; 0 if unknown
|
//@uploaded_size Size of the remote available part of the file, in bytes; 0 if unknown
|
||||||
remoteFile id:string unique_id:string is_uploading_active:Bool is_uploading_completed:Bool uploaded_size:int32 = RemoteFile;
|
remoteFile id:string unique_id:string is_uploading_active:Bool is_uploading_completed:Bool uploaded_size:int32 = RemoteFile;
|
||||||
|
|
||||||
//@description Represents a file
|
//@description Represents a file
|
||||||
//@id Unique file identifier
|
//@id Unique file identifier
|
||||||
//@size File size; 0 if unknown
|
//@size File size, in bytes; 0 if unknown
|
||||||
//@expected_size Expected file size in case the exact file size is unknown, but an approximate size is known. Can be used to show download/upload progress
|
//@expected_size Approximate file size in bytes in case the exact file size is unknown. Can be used to show download/upload progress
|
||||||
//@local Information about the local copy of the file
|
//@local Information about the local copy of the file
|
||||||
//@remote Information about the remote copy of the file
|
//@remote Information about the remote copy of the file
|
||||||
file id:int32 size:int32 expected_size:int32 local:localFile remote:remoteFile = File;
|
file id:int32 size:int32 expected_size:int32 local:localFile remote:remoteFile = File;
|
||||||
@ -175,13 +175,13 @@ inputFileLocal path:string = InputFile;
|
|||||||
|
|
||||||
//@description A file generated by the application @original_path Local path to a file from which the file is generated; may be empty if there is no such file
|
//@description A file generated by the application @original_path Local path to a file from which the file is generated; may be empty if there is no such file
|
||||||
//@conversion String specifying the conversion applied to the original file; should be persistent across application restarts. Conversions beginning with '#' are reserved for internal TDLib usage
|
//@conversion String specifying the conversion applied to the original file; should be persistent across application restarts. Conversions beginning with '#' are reserved for internal TDLib usage
|
||||||
//@expected_size Expected size of the generated file; 0 if unknown
|
//@expected_size Expected size of the generated file, in bytes; 0 if unknown
|
||||||
inputFileGenerated original_path:string conversion:string expected_size:int32 = InputFile;
|
inputFileGenerated original_path:string conversion:string expected_size:int32 = InputFile;
|
||||||
|
|
||||||
|
|
||||||
//@description Describes an image in JPEG format @type Image type (see https://core.telegram.org/constructor/photoSize)
|
//@description Describes an image in JPEG format @type Image type (see https://core.telegram.org/constructor/photoSize)
|
||||||
//@photo Information about the image file @width Image width @height Image height
|
//@photo Information about the image file @width Image width @height Image height
|
||||||
//@progressive_sizes Sizes of progressive JPEG file prefixes, which can be used to preliminarily show the image
|
//@progressive_sizes Sizes of progressive JPEG file prefixes, which can be used to preliminarily show the image; in bytes
|
||||||
photoSize type:string photo:file width:int32 height:int32 progressive_sizes:vector<int32> = PhotoSize;
|
photoSize type:string photo:file width:int32 height:int32 progressive_sizes:vector<int32> = PhotoSize;
|
||||||
|
|
||||||
//@description Thumbnail image of a very poor quality and low resolution @width Thumbnail width, usually doesn't exceed 40 @height Thumbnail height, usually doesn't exceed 40 @data The thumbnail in JPEG format
|
//@description Thumbnail image of a very poor quality and low resolution @width Thumbnail width, usually doesn't exceed 40 @height Thumbnail height, usually doesn't exceed 40 @data The thumbnail in JPEG format
|
||||||
@ -1790,7 +1790,7 @@ messagePinMessage message_id:int53 = MessageContent;
|
|||||||
//@description A screenshot of a message in the chat has been taken
|
//@description A screenshot of a message in the chat has been taken
|
||||||
messageScreenshotTaken = MessageContent;
|
messageScreenshotTaken = MessageContent;
|
||||||
|
|
||||||
//@description A theme in the chat has been changed @theme_name If non-empty, name of the new theme set for the chat. Otherwise theme was deleted in the chat
|
//@description A theme in the chat has been changed @theme_name If non-empty, name of the new theme set for the chat. Otherwise chat theme was reset to the default one
|
||||||
messageChatSetTheme theme_name:string = MessageContent;
|
messageChatSetTheme theme_name:string = MessageContent;
|
||||||
|
|
||||||
//@description The TTL (Time To Live) setting for messages in the chat has been changed @ttl New message TTL setting
|
//@description The TTL (Time To Live) setting for messages in the chat has been changed @ttl New message TTL setting
|
||||||
@ -2532,7 +2532,7 @@ chatEventUsernameChanged old_username:string new_username:string = ChatEventActi
|
|||||||
//@description The chat photo was changed @old_photo Previous chat photo value; may be null @new_photo New chat photo value; may be null
|
//@description The chat photo was changed @old_photo Previous chat photo value; may be null @new_photo New chat photo value; may be null
|
||||||
chatEventPhotoChanged old_photo:chatPhoto new_photo:chatPhoto = ChatEventAction;
|
chatEventPhotoChanged old_photo:chatPhoto new_photo:chatPhoto = ChatEventAction;
|
||||||
|
|
||||||
//@description The chat theme was changed @old_theme_name Previous chat theme name; empty if none @new_theme_name New chat theme name; empty if none
|
//@description The chat theme was changed @old_theme_name Previous chat theme name; empty if default one @new_theme_name New chat theme name; empty if default one
|
||||||
chatEventThemeChanged old_theme_name:string new_theme_name:string = ChatEventAction;
|
chatEventThemeChanged old_theme_name:string new_theme_name:string = ChatEventAction;
|
||||||
|
|
||||||
//@description The can_invite_users permission of a supergroup chat was toggled @can_invite_users New value of can_invite_users permission
|
//@description The can_invite_users permission of a supergroup chat was toggled @can_invite_users New value of can_invite_users permission
|
||||||
@ -2893,7 +2893,7 @@ pushMessageContentChatChangePhoto = PushMessageContent;
|
|||||||
//@description A chat title was edited @title New chat title
|
//@description A chat title was edited @title New chat title
|
||||||
pushMessageContentChatChangeTitle title:string = PushMessageContent;
|
pushMessageContentChatChangeTitle title:string = PushMessageContent;
|
||||||
|
|
||||||
//@description A chat theme was edited @theme_name Name of the new chat theme
|
//@description A chat theme was edited @theme_name If non-empty, name of the new theme set for the chat. Otherwise chat theme was reset to the default one
|
||||||
pushMessageContentChatChangeTheme theme_name:string = PushMessageContent;
|
pushMessageContentChatChangeTheme theme_name:string = PushMessageContent;
|
||||||
|
|
||||||
//@description A chat member was deleted @member_name Name of the deleted member @is_current_user True, if the current user was deleted from the group
|
//@description A chat member was deleted @member_name Name of the deleted member @is_current_user True, if the current user was deleted from the group
|
||||||
@ -3194,7 +3194,8 @@ internalLinkTypeUnknownDeepLink link:string = InternalLinkType;
|
|||||||
|
|
||||||
//@description The link is a link to a voice chat. Call searchPublicChat with the given chat username, and then joinGoupCall with the given invite hash to process the link
|
//@description The link is a link to a voice chat. Call searchPublicChat with the given chat username, and then joinGoupCall with the given invite hash to process the link
|
||||||
//@chat_username Username of the chat with the voice chat @invite_hash If non-empty, invite hash to be used to join the voice chat without being muted by administrators
|
//@chat_username Username of the chat with the voice chat @invite_hash If non-empty, invite hash to be used to join the voice chat without being muted by administrators
|
||||||
internalLinkTypeVoiceChat chat_username:string invite_hash:string = InternalLinkType;
|
//@is_live_stream True, if the voice chat is expected to be a live stream in a channel or a broadcast group
|
||||||
|
internalLinkTypeVoiceChat chat_username:string invite_hash:string is_live_stream:Bool = InternalLinkType;
|
||||||
|
|
||||||
|
|
||||||
//@description Contains an HTTPS link to a message in a supergroup or channel @link Message link @is_public True, if the link will work for non-members of the chat
|
//@description Contains an HTTPS link to a message in a supergroup or channel @link Message link @is_public True, if the link will work for non-members of the chat
|
||||||
@ -3265,16 +3266,16 @@ fileTypeVoiceNote = FileType;
|
|||||||
fileTypeWallpaper = FileType;
|
fileTypeWallpaper = FileType;
|
||||||
|
|
||||||
|
|
||||||
//@description Contains the storage usage statistics for a specific file type @file_type File type @size Total size of the files @count Total number of files
|
//@description Contains the storage usage statistics for a specific file type @file_type File type @size Total size of the files, in bytes @count Total number of files
|
||||||
storageStatisticsByFileType file_type:FileType size:int53 count:int32 = StorageStatisticsByFileType;
|
storageStatisticsByFileType file_type:FileType size:int53 count:int32 = StorageStatisticsByFileType;
|
||||||
|
|
||||||
//@description Contains the storage usage statistics for a specific chat @chat_id Chat identifier; 0 if none @size Total size of the files in the chat @count Total number of files in the chat @by_file_type Statistics split by file types
|
//@description Contains the storage usage statistics for a specific chat @chat_id Chat identifier; 0 if none @size Total size of the files in the chat, in bytes @count Total number of files in the chat @by_file_type Statistics split by file types
|
||||||
storageStatisticsByChat chat_id:int53 size:int53 count:int32 by_file_type:vector<storageStatisticsByFileType> = StorageStatisticsByChat;
|
storageStatisticsByChat chat_id:int53 size:int53 count:int32 by_file_type:vector<storageStatisticsByFileType> = StorageStatisticsByChat;
|
||||||
|
|
||||||
//@description Contains the exact storage usage statistics split by chats and file type @size Total size of files @count Total number of files @by_chat Statistics split by chats
|
//@description Contains the exact storage usage statistics split by chats and file type @size Total size of files, in bytes @count Total number of files @by_chat Statistics split by chats
|
||||||
storageStatistics size:int53 count:int32 by_chat:vector<storageStatisticsByChat> = StorageStatistics;
|
storageStatistics size:int53 count:int32 by_chat:vector<storageStatisticsByChat> = StorageStatistics;
|
||||||
|
|
||||||
//@description Contains approximate storage usage statistics, excluding files of unknown file type @files_size Approximate total size of files @file_count Approximate number of files
|
//@description Contains approximate storage usage statistics, excluding files of unknown file type @files_size Approximate total size of files, in bytes @file_count Approximate number of files
|
||||||
//@database_size Size of the database @language_pack_database_size Size of the language pack database @log_size Size of the TDLib internal log
|
//@database_size Size of the database @language_pack_database_size Size of the language pack database @log_size Size of the TDLib internal log
|
||||||
storageStatisticsFast files_size:int53 file_count:int32 database_size:int53 language_pack_database_size:int53 log_size:int53 = StorageStatisticsFast;
|
storageStatisticsFast files_size:int53 file_count:int32 database_size:int53 language_pack_database_size:int53 log_size:int53 = StorageStatisticsFast;
|
||||||
|
|
||||||
@ -3321,9 +3322,9 @@ networkStatistics since_date:int32 entries:vector<NetworkStatisticsEntry> = Netw
|
|||||||
|
|
||||||
//@description Contains auto-download settings
|
//@description Contains auto-download settings
|
||||||
//@is_auto_download_enabled True, if the auto-download is enabled
|
//@is_auto_download_enabled True, if the auto-download is enabled
|
||||||
//@max_photo_file_size The maximum size of a photo file to be auto-downloaded
|
//@max_photo_file_size The maximum size of a photo file to be auto-downloaded, in bytes
|
||||||
//@max_video_file_size The maximum size of a video file to be auto-downloaded
|
//@max_video_file_size The maximum size of a video file to be auto-downloaded, in bytes
|
||||||
//@max_other_file_size The maximum size of other file types to be auto-downloaded
|
//@max_other_file_size The maximum size of other file types to be auto-downloaded, in bytes
|
||||||
//@video_upload_bitrate The maximum suggested bitrate for uploaded videos, in kbit/s
|
//@video_upload_bitrate The maximum suggested bitrate for uploaded videos, in kbit/s
|
||||||
//@preload_large_videos True, if the beginning of video files needs to be preloaded for instant playback
|
//@preload_large_videos True, if the beginning of video files needs to be preloaded for instant playback
|
||||||
//@preload_next_audio True, if the next audio track needs to be preloaded while the user is listening to an audio file
|
//@preload_next_audio True, if the next audio track needs to be preloaded while the user is listening to an audio file
|
||||||
@ -3914,7 +3915,7 @@ logStreamDefault = LogStream;
|
|||||||
|
|
||||||
//@description The log is written to a file
|
//@description The log is written to a file
|
||||||
//@path Path to the file to where the internal TDLib log will be written
|
//@path Path to the file to where the internal TDLib log will be written
|
||||||
//@max_file_size The maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated
|
//@max_file_size The maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated, in bytes
|
||||||
//@redirect_stderr Pass true to additionally redirect stderr to the log file. Ignored on Windows
|
//@redirect_stderr Pass true to additionally redirect stderr to the log file. Ignored on Windows
|
||||||
logStreamFile path:string max_file_size:int53 redirect_stderr:Bool = LogStream;
|
logStreamFile path:string max_file_size:int53 redirect_stderr:Bool = LogStream;
|
||||||
|
|
||||||
@ -4745,7 +4746,7 @@ setPinnedChats chat_list:ChatList chat_ids:vector<int53> = Ok;
|
|||||||
//-the download has succeeded, has failed, has been canceled or a new downloadFile request with different offset/limit parameters was sent
|
//-the download has succeeded, has failed, has been canceled or a new downloadFile request with different offset/limit parameters was sent
|
||||||
downloadFile file_id:int32 priority:int32 offset:int32 limit:int32 synchronous:Bool = File;
|
downloadFile file_id:int32 priority:int32 offset:int32 limit:int32 synchronous:Bool = File;
|
||||||
|
|
||||||
//@description Returns file downloaded prefix size from a given offset @file_id Identifier of the file @offset Offset from which downloaded prefix size should be calculated
|
//@description Returns file downloaded prefix size from a given offset, in bytes @file_id Identifier of the file @offset Offset from which downloaded prefix size should be calculated
|
||||||
getFileDownloadedPrefixSize file_id:int32 offset:int32 = Count;
|
getFileDownloadedPrefixSize file_id:int32 offset:int32 = Count;
|
||||||
|
|
||||||
//@description Stops the downloading of a file. If a file has already been downloaded, does nothing @file_id Identifier of a file to stop downloading @only_if_pending Pass true to stop downloading only if it hasn't been started, i.e. request hasn't been sent to server
|
//@description Stops the downloading of a file. If a file has already been downloaded, does nothing @file_id Identifier of a file to stop downloading @only_if_pending Pass true to stop downloading only if it hasn't been started, i.e. request hasn't been sent to server
|
||||||
@ -5403,7 +5404,7 @@ getMemoryStatistics full:Bool = MemoryStatistics;
|
|||||||
optimizeMemory full:Bool = Ok;
|
optimizeMemory full:Bool = Ok;
|
||||||
|
|
||||||
//@description Optimizes storage usage, i.e. deletes some files and returns new storage usage statistics. Secret thumbnails can't be deleted
|
//@description Optimizes storage usage, i.e. deletes some files and returns new storage usage statistics. Secret thumbnails can't be deleted
|
||||||
//@size Limit on the total size of files after deletion. Pass -1 to use the default limit
|
//@size Limit on the total size of files after deletion, in bytes. Pass -1 to use the default limit
|
||||||
//@ttl Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit
|
//@ttl Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit
|
||||||
//@count Limit on the total count of files after deletion. Pass -1 to use the default limit
|
//@count Limit on the total count of files after deletion. Pass -1 to use the default limit
|
||||||
//@immunity_delay The amount of time after the creation of a file during which it can't be deleted, in seconds. Pass -1 to use the default value
|
//@immunity_delay The amount of time after the creation of a file during which it can't be deleted, in seconds. Pass -1 to use the default value
|
||||||
|
@ -6080,7 +6080,7 @@ void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user
|
|||||||
auto user_full = get_user_full(user_id);
|
auto user_full = get_user_full(user_id);
|
||||||
if (user_full != nullptr) {
|
if (user_full != nullptr) {
|
||||||
on_update_user_full_commands(user_full, user_id, std::move(bot_commands));
|
on_update_user_full_commands(user_full, user_id, std::move(bot_commands));
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "on_update_bot_commands");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6105,7 +6105,7 @@ void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user
|
|||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_update_bot_commands");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6130,7 +6130,7 @@ void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user
|
|||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_bot_commands");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6302,7 +6302,7 @@ void ContactsManager::on_update_profile_success(int32 flags, const string &first
|
|||||||
if (user_full != nullptr) {
|
if (user_full != nullptr) {
|
||||||
user_full->about = about;
|
user_full->about = about;
|
||||||
user_full->is_changed = true;
|
user_full->is_changed = true;
|
||||||
update_user_full(user_full, my_user_id);
|
update_user_full(user_full, my_user_id, "on_update_profile_success");
|
||||||
td_->group_call_manager_->on_update_dialog_about(DialogId(my_user_id), user_full->about, true);
|
td_->group_call_manager_->on_update_dialog_about(DialogId(my_user_id), user_full->about, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8021,7 +8021,7 @@ void ContactsManager::invalidate_user_full(UserId user_id) {
|
|||||||
user_full->expires_at = 0.0;
|
user_full->expires_at = 0.0;
|
||||||
user_full->need_save_to_database = true;
|
user_full->need_save_to_database = true;
|
||||||
|
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "invalidate_user_full");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9375,7 +9375,8 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
|
|||||||
|
|
||||||
td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, false);
|
td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, false);
|
||||||
|
|
||||||
update_user_full(user_full, user_id, true);
|
user_full->is_update_user_full_sent = true;
|
||||||
|
update_user_full(user_full, user_id, "on_load_user_full_from_database", true);
|
||||||
|
|
||||||
if (is_user_deleted(user_id)) {
|
if (is_user_deleted(user_id)) {
|
||||||
drop_user_full(user_id);
|
drop_user_full(user_id);
|
||||||
@ -9488,7 +9489,8 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
|
|||||||
|
|
||||||
on_update_chat_full_photo(chat_full, chat_id, std::move(chat_full->photo));
|
on_update_chat_full_photo(chat_full, chat_id, std::move(chat_full->photo));
|
||||||
|
|
||||||
update_chat_full(chat_full, chat_id, true);
|
chat_full->is_update_chat_full_sent = true;
|
||||||
|
update_chat_full(chat_full, chat_id, "on_load_chat_full_from_database", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactsManager::ChatFull *ContactsManager::get_chat_full_force(ChatId chat_id, const char *source) {
|
ContactsManager::ChatFull *ContactsManager::get_chat_full_force(ChatId chat_id, const char *source) {
|
||||||
@ -9620,7 +9622,8 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
|
|||||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
|
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
|
||||||
channel_full->bot_user_ids, true);
|
channel_full->bot_user_ids, true);
|
||||||
|
|
||||||
update_channel_full(channel_full, channel_id, true);
|
channel_full->is_update_channel_full_sent = true;
|
||||||
|
update_channel_full(channel_full, channel_id, "on_load_channel_full_from_database", true);
|
||||||
|
|
||||||
if (channel_full->expires_at == 0.0) {
|
if (channel_full->expires_at == 0.0) {
|
||||||
load_channel_full(channel_id, true, Auto(), "on_load_channel_full_from_database");
|
load_channel_full(channel_id, true, Auto(), "on_load_channel_full_from_database");
|
||||||
@ -9670,7 +9673,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
|
|||||||
auto user_full = get_user_full(user_id);
|
auto user_full = get_user_full(user_id);
|
||||||
if (user_full != nullptr && user_full->need_phone_number_privacy_exception) {
|
if (user_full != nullptr && user_full->need_phone_number_privacy_exception) {
|
||||||
on_update_user_full_need_phone_number_privacy_exception(user_full, user_id, false);
|
on_update_user_full_need_phone_number_privacy_exception(user_full, user_id, false);
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "update_user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9962,7 +9965,7 @@ void ContactsManager::update_secret_chat(SecretChat *c, SecretChatId secret_chat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, bool from_database) {
|
void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, const char *source, bool from_database) {
|
||||||
CHECK(user_full != nullptr);
|
CHECK(user_full != nullptr);
|
||||||
unavailable_user_fulls_.erase(user_id); // don't needed anymore
|
unavailable_user_fulls_.erase(user_id); // don't needed anymore
|
||||||
if (user_full->is_common_chat_count_changed) {
|
if (user_full->is_common_chat_count_changed) {
|
||||||
@ -9973,11 +9976,18 @@ void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, bool
|
|||||||
user_full->need_send_update |= user_full->is_changed;
|
user_full->need_send_update |= user_full->is_changed;
|
||||||
user_full->need_save_to_database |= user_full->is_changed;
|
user_full->need_save_to_database |= user_full->is_changed;
|
||||||
user_full->is_changed = false;
|
user_full->is_changed = false;
|
||||||
|
if (user_full->need_send_update || user_full->need_save_to_database) {
|
||||||
|
LOG(INFO) << "Update full " << user_id << " from " << source;
|
||||||
|
}
|
||||||
if (user_full->need_send_update) {
|
if (user_full->need_send_update) {
|
||||||
{
|
{
|
||||||
auto u = get_user(user_id);
|
auto u = get_user(user_id);
|
||||||
CHECK(u == nullptr || u->is_update_user_sent);
|
CHECK(u == nullptr || u->is_update_user_sent);
|
||||||
}
|
}
|
||||||
|
if (!user_full->is_update_user_full_sent) {
|
||||||
|
LOG(ERROR) << "Send partial updateUserFullInfo for " << user_id << " from " << source;
|
||||||
|
user_full->is_update_user_full_sent = true;
|
||||||
|
}
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_closure(G()->td(), &Td::send_update,
|
||||||
make_tl_object<td_api::updateUserFullInfo>(get_user_id_object(user_id, "updateUserFullInfo"),
|
make_tl_object<td_api::updateUserFullInfo>(get_user_id_object(user_id, "updateUserFullInfo"),
|
||||||
get_user_full_info_object(user_id, user_full)));
|
get_user_full_info_object(user_id, user_full)));
|
||||||
@ -9991,13 +10001,16 @@ void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool from_database) {
|
void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, const char *source, bool from_database) {
|
||||||
CHECK(chat_full != nullptr);
|
CHECK(chat_full != nullptr);
|
||||||
unavailable_chat_fulls_.erase(chat_id); // don't needed anymore
|
unavailable_chat_fulls_.erase(chat_id); // don't needed anymore
|
||||||
|
|
||||||
chat_full->need_send_update |= chat_full->is_changed;
|
chat_full->need_send_update |= chat_full->is_changed;
|
||||||
chat_full->need_save_to_database |= chat_full->is_changed;
|
chat_full->need_save_to_database |= chat_full->is_changed;
|
||||||
chat_full->is_changed = false;
|
chat_full->is_changed = false;
|
||||||
|
if (chat_full->need_send_update || chat_full->need_save_to_database) {
|
||||||
|
LOG(INFO) << "Update full " << chat_id << " from " << source;
|
||||||
|
}
|
||||||
if (chat_full->need_send_update) {
|
if (chat_full->need_send_update) {
|
||||||
vector<DialogAdministrator> administrators;
|
vector<DialogAdministrator> administrators;
|
||||||
vector<UserId> bot_user_ids;
|
vector<UserId> bot_user_ids;
|
||||||
@ -10026,6 +10039,10 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool
|
|||||||
Chat *c = get_chat(chat_id);
|
Chat *c = get_chat(chat_id);
|
||||||
CHECK(c == nullptr || c->is_update_basic_group_sent);
|
CHECK(c == nullptr || c->is_update_basic_group_sent);
|
||||||
}
|
}
|
||||||
|
if (!chat_full->is_update_chat_full_sent) {
|
||||||
|
LOG(ERROR) << "Send partial updateBasicGroupFullInfo for " << chat_id << " from " << source;
|
||||||
|
chat_full->is_update_chat_full_sent = true;
|
||||||
|
}
|
||||||
send_closure(
|
send_closure(
|
||||||
G()->td(), &Td::send_update,
|
G()->td(), &Td::send_update,
|
||||||
make_tl_object<td_api::updateBasicGroupFullInfo>(get_basic_group_id_object(chat_id, "update_chat_full"),
|
make_tl_object<td_api::updateBasicGroupFullInfo>(get_basic_group_id_object(chat_id, "update_chat_full"),
|
||||||
@ -10040,7 +10057,8 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId channel_id, bool from_database) {
|
void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId channel_id, const char *source,
|
||||||
|
bool from_database) {
|
||||||
if (channel_full == nullptr) {
|
if (channel_full == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -10076,6 +10094,9 @@ void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId c
|
|||||||
channel_full->need_send_update |= channel_full->is_changed;
|
channel_full->need_send_update |= channel_full->is_changed;
|
||||||
channel_full->need_save_to_database |= channel_full->is_changed;
|
channel_full->need_save_to_database |= channel_full->is_changed;
|
||||||
channel_full->is_changed = false;
|
channel_full->is_changed = false;
|
||||||
|
if (channel_full->need_send_update || channel_full->need_save_to_database) {
|
||||||
|
LOG(INFO) << "Update full " << channel_id << " from " << source;
|
||||||
|
}
|
||||||
if (channel_full->need_send_update) {
|
if (channel_full->need_send_update) {
|
||||||
if (channel_full->linked_channel_id.is_valid()) {
|
if (channel_full->linked_channel_id.is_valid()) {
|
||||||
td_->messages_manager_->force_create_dialog(DialogId(channel_full->linked_channel_id), "update_channel_full",
|
td_->messages_manager_->force_create_dialog(DialogId(channel_full->linked_channel_id), "update_channel_full",
|
||||||
@ -10088,6 +10109,10 @@ void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId c
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!channel_full->is_update_channel_full_sent) {
|
||||||
|
LOG(ERROR) << "Send partial updateSupergroupFullInfo for " << channel_id << " from " << source;
|
||||||
|
channel_full->is_update_channel_full_sent = true;
|
||||||
|
}
|
||||||
send_closure(
|
send_closure(
|
||||||
G()->td(), &Td::send_update,
|
G()->td(), &Td::send_update,
|
||||||
make_tl_object<td_api::updateSupergroupFullInfo>(get_supergroup_id_object(channel_id, "update_channel_full"),
|
make_tl_object<td_api::updateSupergroupFullInfo>(get_supergroup_id_object(channel_id, "update_channel_full"),
|
||||||
@ -10207,7 +10232,8 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
|
|||||||
register_user_photo(u, user_id, user_full->photo);
|
register_user_photo(u, user_id, user_full->photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_user_full(user_full, user_id);
|
user_full->is_update_user_full_sent = true;
|
||||||
|
update_user_full(user_full, user_id, "on_get_user_full");
|
||||||
|
|
||||||
// update peer settings after UserFull is created and updated to not update twice need_phone_number_privacy_exception
|
// update peer settings after UserFull is created and updated to not update twice need_phone_number_privacy_exception
|
||||||
td_->messages_manager_->on_get_peer_settings(DialogId(user_id), std::move(user->settings_));
|
td_->messages_manager_->on_get_peer_settings(DialogId(user_id), std::move(user->settings_));
|
||||||
@ -10450,7 +10476,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
|||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_chat_full(chat_full, chat_id);
|
chat_full->is_update_chat_full_sent = true;
|
||||||
|
update_chat_full(chat_full, chat_id, "on_get_chat_full");
|
||||||
} else {
|
} else {
|
||||||
CHECK(chat_full_ptr->get_id() == telegram_api::channelFull::ID);
|
CHECK(chat_full_ptr->get_id() == telegram_api::channelFull::ID);
|
||||||
auto channel = move_tl_object_as<telegram_api::channelFull>(chat_full_ptr);
|
auto channel = move_tl_object_as<telegram_api::channelFull>(chat_full_ptr);
|
||||||
@ -10698,13 +10725,14 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
|||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_channel_full(channel_full, channel_id);
|
channel_full->is_update_channel_full_sent = true;
|
||||||
|
update_channel_full(channel_full, channel_id, "on_get_channel_full");
|
||||||
|
|
||||||
if (linked_channel_id.is_valid()) {
|
if (linked_channel_id.is_valid()) {
|
||||||
auto linked_channel_full = get_channel_full_force(linked_channel_id, true, "on_get_chat_full");
|
auto linked_channel_full = get_channel_full_force(linked_channel_id, true, "on_get_chat_full");
|
||||||
on_update_channel_full_linked_channel_id(linked_channel_full, linked_channel_id, channel_id);
|
on_update_channel_full_linked_channel_id(linked_channel_full, linked_channel_id, channel_id);
|
||||||
if (linked_channel_full != nullptr) {
|
if (linked_channel_full != nullptr) {
|
||||||
update_channel_full(linked_channel_full, linked_channel_id);
|
update_channel_full(linked_channel_full, linked_channel_id, "on_get_channel_full 2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11078,11 +11106,11 @@ void ContactsManager::on_update_user_is_blocked(UserId user_id, bool is_blocked)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserFull *user_full = get_user_full_force(user_id);
|
UserFull *user_full = get_user_full_force(user_id);
|
||||||
if (user_full == nullptr) {
|
if (user_full == nullptr || user_full->is_blocked == is_blocked) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
on_update_user_full_is_blocked(user_full, user_id, is_blocked);
|
on_update_user_full_is_blocked(user_full, user_id, is_blocked);
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "on_update_user_is_blocked");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked) {
|
void ContactsManager::on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked) {
|
||||||
@ -11106,7 +11134,7 @@ void ContactsManager::on_update_user_common_chat_count(UserId user_id, int32 com
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
on_update_user_full_common_chat_count(user_full, user_id, common_chat_count);
|
on_update_user_full_common_chat_count(user_full, user_id, common_chat_count);
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "on_update_user_common_chat_count");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id,
|
void ContactsManager::on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id,
|
||||||
@ -11148,7 +11176,7 @@ void ContactsManager::on_update_user_need_phone_number_privacy_exception(UserId
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
on_update_user_full_need_phone_number_privacy_exception(user_full, user_id, need_phone_number_privacy_exception);
|
on_update_user_full_need_phone_number_privacy_exception(user_full, user_id, need_phone_number_privacy_exception);
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "on_update_user_need_phone_number_privacy_exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_user_full_need_phone_number_privacy_exception(
|
void ContactsManager::on_update_user_full_need_phone_number_privacy_exception(
|
||||||
@ -11240,7 +11268,7 @@ void ContactsManager::add_profile_photo_to_cache(UserId user_id, Photo &&photo)
|
|||||||
user_full->photo = photo;
|
user_full->photo = photo;
|
||||||
user_full->is_changed = true;
|
user_full->is_changed = true;
|
||||||
}
|
}
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "add_profile_photo_to_cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
// update ProfilePhoto in User
|
// update ProfilePhoto in User
|
||||||
@ -11300,7 +11328,7 @@ bool ContactsManager::delete_profile_photo_from_cache(UserId user_id, int64 prof
|
|||||||
load_user_full(user_id, true, Auto(), "delete_profile_photo_from_cache");
|
load_user_full(user_id, true, Auto(), "delete_profile_photo_from_cache");
|
||||||
}
|
}
|
||||||
if (send_updates) {
|
if (send_updates) {
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "delete_profile_photo_from_cache");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11359,7 +11387,7 @@ void ContactsManager::drop_user_photos(UserId user_id, bool is_empty, bool drop_
|
|||||||
}
|
}
|
||||||
load_user_full(user_id, true, Auto(), "drop_user_photos");
|
load_user_full(user_id, true, Auto(), "drop_user_photos");
|
||||||
}
|
}
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "drop_user_photos");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11386,7 +11414,7 @@ void ContactsManager::drop_user_full(UserId user_id) {
|
|||||||
user_full->common_chat_count = 0;
|
user_full->common_chat_count = 0;
|
||||||
user_full->is_changed = true;
|
user_full->is_changed = true;
|
||||||
|
|
||||||
update_user_full(user_full, user_id);
|
update_user_full(user_full, user_id, "drop_user_full");
|
||||||
td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, true);
|
td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11555,7 +11583,7 @@ void ContactsManager::on_get_chat_participants(tl_object_ptr<telegram_api::ChatP
|
|||||||
|
|
||||||
on_update_chat_full_participants(chat_full, chat_id, std::move(new_participants), participants->version_,
|
on_update_chat_full_participants(chat_full, chat_id, std::move(new_participants), participants->version_,
|
||||||
from_update);
|
from_update);
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_get_chat_participants");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -11793,7 +11821,7 @@ void ContactsManager::on_get_channel_participants(
|
|||||||
channel_full->administrator_count = administrator_count;
|
channel_full->administrator_count = administrator_count;
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
}
|
}
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_get_channel_participants");
|
||||||
}
|
}
|
||||||
if (participant_count != -1) {
|
if (participant_count != -1) {
|
||||||
auto c = get_channel(channel_id);
|
auto c = get_channel(channel_id);
|
||||||
@ -11922,7 +11950,7 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id,
|
|||||||
update_channel_online_member_count(channel_id, false);
|
update_channel_online_member_count(channel_id, false);
|
||||||
}
|
}
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "speculative_add_channel_participants");
|
||||||
}
|
}
|
||||||
if (delta_participant_count == 0) {
|
if (delta_participant_count == 0) {
|
||||||
return;
|
return;
|
||||||
@ -11952,7 +11980,7 @@ void ContactsManager::speculative_delete_channel_participant(ChannelId channel_i
|
|||||||
auto channel_full = get_channel_full_force(channel_id, true, "speculative_delete_channel_participant");
|
auto channel_full = get_channel_full_force(channel_id, true, "speculative_delete_channel_participant");
|
||||||
if (channel_full != nullptr && td::remove(channel_full->bot_user_ids, deleted_user_id)) {
|
if (channel_full != nullptr && td::remove(channel_full->bot_user_ids, deleted_user_id)) {
|
||||||
channel_full->need_save_to_database = true;
|
channel_full->need_save_to_database = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "speculative_delete_channel_participant");
|
||||||
|
|
||||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
|
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
|
||||||
channel_full->bot_user_ids, false);
|
channel_full->bot_user_ids, false);
|
||||||
@ -11991,7 +12019,7 @@ void ContactsManager::speculative_add_channel_participant_count(ChannelId channe
|
|||||||
channel_full->speculative_version++;
|
channel_full->speculative_version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "speculative_add_channel_participant_count");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId user_id,
|
void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId user_id,
|
||||||
@ -12107,7 +12135,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "speculative_add_channel_user");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, bool drop_channel_full_photo,
|
void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, bool drop_channel_full_photo,
|
||||||
@ -12126,7 +12154,7 @@ void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, b
|
|||||||
}
|
}
|
||||||
send_get_channel_full_query(channel_full, channel_id, Auto(), "drop_channel_photos");
|
send_get_channel_full_query(channel_full, channel_id, Auto(), "drop_channel_photos");
|
||||||
}
|
}
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "drop_channel_photos");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12135,7 +12163,7 @@ void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool need_dr
|
|||||||
auto channel_full = get_channel_full(channel_id, true, "invalidate_channel_full"); // must not load ChannelFull
|
auto channel_full = get_channel_full(channel_id, true, "invalidate_channel_full"); // must not load ChannelFull
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
do_invalidate_channel_full(channel_full, need_drop_slow_mode_delay);
|
do_invalidate_channel_full(channel_full, need_drop_slow_mode_delay);
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "invalidate_channel_full");
|
||||||
} else {
|
} else {
|
||||||
invalidated_channels_full_.insert(channel_id);
|
invalidated_channels_full_.insert(channel_id);
|
||||||
}
|
}
|
||||||
@ -12236,7 +12264,7 @@ void ContactsManager::on_get_permanent_dialog_invite_link(DialogId dialog_id, co
|
|||||||
auto chat_full = get_chat_full_force(chat_id, "on_get_permanent_dialog_invite_link");
|
auto chat_full = get_chat_full_force(chat_id, "on_get_permanent_dialog_invite_link");
|
||||||
if (chat_full != nullptr && update_permanent_invite_link(chat_full->invite_link, invite_link)) {
|
if (chat_full != nullptr && update_permanent_invite_link(chat_full->invite_link, invite_link)) {
|
||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_get_permanent_dialog_invite_link");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -12245,7 +12273,7 @@ void ContactsManager::on_get_permanent_dialog_invite_link(DialogId dialog_id, co
|
|||||||
auto channel_full = get_channel_full_force(channel_id, true, "on_get_permanent_dialog_invite_link");
|
auto channel_full = get_channel_full_force(channel_id, true, "on_get_permanent_dialog_invite_link");
|
||||||
if (channel_full != nullptr && update_permanent_invite_link(channel_full->invite_link, invite_link)) {
|
if (channel_full != nullptr && update_permanent_invite_link(channel_full->invite_link, invite_link)) {
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_get_permanent_dialog_invite_link");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -12335,7 +12363,8 @@ void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *chan
|
|||||||
if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id == channel_id) {
|
if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id == channel_id) {
|
||||||
linked_channel_full->linked_channel_id = ChannelId();
|
linked_channel_full->linked_channel_id = ChannelId();
|
||||||
linked_channel_full->is_changed = true;
|
linked_channel_full->is_changed = true;
|
||||||
update_channel_full(linked_channel_full, channel_full->linked_channel_id);
|
update_channel_full(linked_channel_full, channel_full->linked_channel_id,
|
||||||
|
"on_update_channel_full_linked_channel_id 3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12356,7 +12385,8 @@ void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *chan
|
|||||||
if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id != channel_id) {
|
if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id != channel_id) {
|
||||||
linked_channel_full->linked_channel_id = channel_id;
|
linked_channel_full->linked_channel_id = channel_id;
|
||||||
linked_channel_full->is_changed = true;
|
linked_channel_full->is_changed = true;
|
||||||
update_channel_full(linked_channel_full, channel_full->linked_channel_id);
|
update_channel_full(linked_channel_full, channel_full->linked_channel_id,
|
||||||
|
"on_update_channel_full_linked_channel_id 4");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12655,7 +12685,7 @@ void ContactsManager::on_update_chat_add_user(ChatId chat_id, UserId inviter_use
|
|||||||
: DialogParticipantStatus::Member()});
|
: DialogParticipantStatus::Member()});
|
||||||
update_chat_online_member_count(chat_full, chat_id, false);
|
update_chat_online_member_count(chat_full, chat_id, false);
|
||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_update_chat_add_user");
|
||||||
|
|
||||||
// Chat is already updated
|
// Chat is already updated
|
||||||
if (chat_full->version == c->version &&
|
if (chat_full->version == c->version &&
|
||||||
@ -12727,7 +12757,7 @@ void ContactsManager::on_update_chat_edit_administrator(ChatId chat_id, UserId u
|
|||||||
if (participant.dialog_id == DialogId(user_id)) {
|
if (participant.dialog_id == DialogId(user_id)) {
|
||||||
participant.status = std::move(status);
|
participant.status = std::move(status);
|
||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_update_chat_edit_administrator");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12780,7 +12810,7 @@ void ContactsManager::on_update_chat_delete_user(ChatId chat_id, UserId user_id,
|
|||||||
chat_full->participants.resize(chat_full->participants.size() - 1);
|
chat_full->participants.resize(chat_full->participants.size() - 1);
|
||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
update_chat_online_member_count(chat_full, chat_id, false);
|
update_chat_online_member_count(chat_full, chat_id, false);
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_update_chat_delete_user");
|
||||||
|
|
||||||
if (static_cast<int32>(chat_full->participants.size()) != c->participant_count) {
|
if (static_cast<int32>(chat_full->participants.size()) != c->participant_count) {
|
||||||
repair_chat_participants(chat_id);
|
repair_chat_participants(chat_id);
|
||||||
@ -12812,7 +12842,7 @@ void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParti
|
|||||||
ChatFull *chat_full = get_chat_full_force(chat_id, "on_update_chat_status");
|
ChatFull *chat_full = get_chat_full_force(chat_id, "on_update_chat_status");
|
||||||
if (chat_full != nullptr) {
|
if (chat_full != nullptr) {
|
||||||
on_update_chat_full_invite_link(chat_full, nullptr);
|
on_update_chat_full_invite_link(chat_full, nullptr);
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_update_chat_status");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (need_reload_group_call) {
|
if (need_reload_group_call) {
|
||||||
@ -13019,7 +13049,7 @@ void ContactsManager::on_update_chat_description(ChatId chat_id, string &&descri
|
|||||||
if (chat_full->description != description) {
|
if (chat_full->description != description) {
|
||||||
chat_full->description = std::move(description);
|
chat_full->description = std::move(description);
|
||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "on_update_chat_description");
|
||||||
td_->group_call_manager_->on_update_dialog_about(DialogId(chat_id), chat_full->description, true);
|
td_->group_call_manager_->on_update_dialog_about(DialogId(chat_id), chat_full->description, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13084,7 +13114,7 @@ void ContactsManager::drop_chat_photos(ChatId chat_id, bool is_empty, bool drop_
|
|||||||
if (!is_empty) {
|
if (!is_empty) {
|
||||||
reload_chat_full(chat_id, Auto());
|
reload_chat_full(chat_id, Auto());
|
||||||
}
|
}
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "drop_chat_photos");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13104,7 +13134,7 @@ void ContactsManager::drop_chat_full(ChatId chat_id) {
|
|||||||
on_update_chat_full_invite_link(chat_full, nullptr);
|
on_update_chat_full_invite_link(chat_full, nullptr);
|
||||||
update_chat_online_member_count(chat_full, chat_id, true);
|
update_chat_online_member_count(chat_full, chat_id, true);
|
||||||
chat_full->is_changed = true;
|
chat_full->is_changed = true;
|
||||||
update_chat_full(chat_full, chat_id);
|
update_chat_full(chat_full, chat_id, "drop_chat_full");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_channel_photo(Channel *c, ChannelId channel_id,
|
void ContactsManager::on_update_channel_photo(Channel *c, ChannelId channel_id,
|
||||||
@ -13154,7 +13184,7 @@ void ContactsManager::on_channel_status_changed(const Channel *c, ChannelId chan
|
|||||||
if (channel_full != nullptr) { // otherwise invite_link will be dropped when the channel is loaded
|
if (channel_full != nullptr) { // otherwise invite_link will be dropped when the channel is loaded
|
||||||
on_update_channel_full_invite_link(channel_full, nullptr);
|
on_update_channel_full_invite_link(channel_full, nullptr);
|
||||||
do_invalidate_channel_full(channel_full, !c->is_slow_mode_enabled);
|
do_invalidate_channel_full(channel_full, !c->is_slow_mode_enabled);
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_channel_status_changed");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
|
invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
|
||||||
@ -13255,7 +13285,7 @@ void ContactsManager::on_update_channel_description(ChannelId channel_id, string
|
|||||||
if (channel_full->description != description) {
|
if (channel_full->description != description) {
|
||||||
channel_full->description = std::move(description);
|
channel_full->description = std::move(description);
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_description");
|
||||||
td_->group_call_manager_->on_update_dialog_about(DialogId(channel_id), channel_full->description, true);
|
td_->group_call_manager_->on_update_dialog_about(DialogId(channel_id), channel_full->description, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13269,7 +13299,7 @@ void ContactsManager::on_update_channel_sticker_set(ChannelId channel_id, Sticke
|
|||||||
if (channel_full->sticker_set_id != sticker_set_id) {
|
if (channel_full->sticker_set_id != sticker_set_id) {
|
||||||
channel_full->sticker_set_id = sticker_set_id;
|
channel_full->sticker_set_id = sticker_set_id;
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_sticker_set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13278,14 +13308,14 @@ void ContactsManager::on_update_channel_linked_channel_id(ChannelId channel_id,
|
|||||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_linked_channel_id 1");
|
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_linked_channel_id 1");
|
||||||
on_update_channel_full_linked_channel_id(channel_full, channel_id, group_channel_id);
|
on_update_channel_full_linked_channel_id(channel_full, channel_id, group_channel_id);
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_linked_channel_id 3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (group_channel_id.is_valid()) {
|
if (group_channel_id.is_valid()) {
|
||||||
auto channel_full = get_channel_full_force(group_channel_id, true, "on_update_channel_linked_channel_id 2");
|
auto channel_full = get_channel_full_force(group_channel_id, true, "on_update_channel_linked_channel_id 2");
|
||||||
on_update_channel_full_linked_channel_id(channel_full, group_channel_id, channel_id);
|
on_update_channel_full_linked_channel_id(channel_full, group_channel_id, channel_id);
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
update_channel_full(channel_full, group_channel_id);
|
update_channel_full(channel_full, group_channel_id, "on_update_channel_linked_channel_id 4");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13294,7 +13324,7 @@ void ContactsManager::on_update_channel_location(ChannelId channel_id, const Dia
|
|||||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_location");
|
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_location");
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
on_update_channel_full_location(channel_full, channel_id, location);
|
on_update_channel_full_location(channel_full, channel_id, location);
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_location");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13306,7 +13336,7 @@ void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, in
|
|||||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay");
|
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay");
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0);
|
on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0);
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_slow_mode_delay");
|
||||||
}
|
}
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
@ -13315,7 +13345,7 @@ void ContactsManager::on_update_channel_slow_mode_next_send_date(ChannelId chann
|
|||||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_next_send_date");
|
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_next_send_date");
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
on_update_channel_full_slow_mode_next_send_date(channel_full, slow_mode_next_send_date);
|
on_update_channel_full_slow_mode_next_send_date(channel_full, slow_mode_next_send_date);
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_slow_mode_next_send_date");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13333,7 +13363,7 @@ void ContactsManager::on_update_channel_bot_user_ids(ChannelId channel_id, vecto
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
on_update_channel_full_bot_user_ids(channel_full, channel_id, std::move(bot_user_ids));
|
on_update_channel_full_bot_user_ids(channel_full, channel_id, std::move(bot_user_ids));
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_bot_user_ids");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_full, ChannelId channel_id,
|
void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_full, ChannelId channel_id,
|
||||||
@ -13357,7 +13387,7 @@ void ContactsManager::on_update_channel_is_all_history_available(ChannelId chann
|
|||||||
if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) {
|
if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) {
|
||||||
channel_full->is_all_history_available = is_all_history_available;
|
channel_full->is_all_history_available = is_all_history_available;
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_is_all_history_available");
|
||||||
}
|
}
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
@ -15240,7 +15270,7 @@ void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_update_channel_administrator_count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15624,7 +15654,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
|
|||||||
if (channel_full != nullptr && channel_full->participant_count != participant_count) {
|
if (channel_full != nullptr && channel_full->participant_count != participant_count) {
|
||||||
channel_full->participant_count = participant_count;
|
channel_full->participant_count = participant_count;
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_chat_update");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15734,7 +15764,7 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
|
|||||||
channel_full->participant_count = 0;
|
channel_full->participant_count = 0;
|
||||||
channel_full->administrator_count = 0;
|
channel_full->administrator_count = 0;
|
||||||
channel_full->is_changed = true;
|
channel_full->is_changed = true;
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id, "on_chat_update 2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (need_invalidate_channel_full) {
|
if (need_invalidate_channel_full) {
|
||||||
|
@ -692,6 +692,7 @@ class ContactsManager final : public Actor {
|
|||||||
bool is_changed = true; // have new changes that need to be sent to the client and database
|
bool is_changed = true; // have new changes that need to be sent to the client and database
|
||||||
bool need_send_update = true; // have new changes that need only to be sent to the client
|
bool need_send_update = true; // have new changes that need only to be sent to the client
|
||||||
bool need_save_to_database = true; // have new changes that need only to be saved to the database
|
bool need_save_to_database = true; // have new changes that need only to be saved to the database
|
||||||
|
bool is_update_user_full_sent = false;
|
||||||
|
|
||||||
double expires_at = 0.0;
|
double expires_at = 0.0;
|
||||||
|
|
||||||
@ -769,6 +770,7 @@ class ContactsManager final : public Actor {
|
|||||||
bool is_changed = true; // have new changes that need to be sent to the client and database
|
bool is_changed = true; // have new changes that need to be sent to the client and database
|
||||||
bool need_send_update = true; // have new changes that need only to be sent to the client
|
bool need_send_update = true; // have new changes that need only to be sent to the client
|
||||||
bool need_save_to_database = true; // have new changes that need only to be saved to the database
|
bool need_save_to_database = true; // have new changes that need only to be saved to the database
|
||||||
|
bool is_update_chat_full_sent = false;
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const;
|
void store(StorerT &storer) const;
|
||||||
@ -876,6 +878,7 @@ class ContactsManager final : public Actor {
|
|||||||
bool is_changed = true; // have new changes that need to be sent to the client and database
|
bool is_changed = true; // have new changes that need to be sent to the client and database
|
||||||
bool need_send_update = true; // have new changes that need only to be sent to the client
|
bool need_send_update = true; // have new changes that need only to be sent to the client
|
||||||
bool need_save_to_database = true; // have new changes that need only to be saved to the database
|
bool need_save_to_database = true; // have new changes that need only to be saved to the database
|
||||||
|
bool is_update_channel_full_sent = false;
|
||||||
|
|
||||||
double expires_at = 0.0;
|
double expires_at = 0.0;
|
||||||
|
|
||||||
@ -1327,9 +1330,10 @@ class ContactsManager final : public Actor {
|
|||||||
void update_secret_chat(SecretChat *c, SecretChatId secret_chat_id, bool from_binlog = false,
|
void update_secret_chat(SecretChat *c, SecretChatId secret_chat_id, bool from_binlog = false,
|
||||||
bool from_database = false);
|
bool from_database = false);
|
||||||
|
|
||||||
void update_user_full(UserFull *user_full, UserId user_id, bool from_database = false);
|
void update_user_full(UserFull *user_full, UserId user_id, const char *source, bool from_database = false);
|
||||||
void update_chat_full(ChatFull *chat_full, ChatId chat_id, bool from_database = false);
|
void update_chat_full(ChatFull *chat_full, ChatId chat_id, const char *source, bool from_database = false);
|
||||||
void update_channel_full(ChannelFull *channel_full, ChannelId channel_id, bool from_database = false);
|
void update_channel_full(ChannelFull *channel_full, ChannelId channel_id, const char *source,
|
||||||
|
bool from_database = false);
|
||||||
|
|
||||||
bool is_chat_full_outdated(const ChatFull *chat_full, const Chat *c, ChatId chat_id);
|
bool is_chat_full_outdated(const ChatFull *chat_full, const Chat *c, ChatId chat_id);
|
||||||
|
|
||||||
|
328
td/telegram/GameManager.cpp
Normal file
328
td/telegram/GameManager.cpp
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#include "td/telegram/GameManager.h"
|
||||||
|
|
||||||
|
#include "td/telegram/AccessRights.h"
|
||||||
|
#include "td/telegram/AuthManager.h"
|
||||||
|
#include "td/telegram/ContactsManager.h"
|
||||||
|
#include "td/telegram/DialogId.h"
|
||||||
|
#include "td/telegram/Global.h"
|
||||||
|
#include "td/telegram/InlineQueriesManager.h"
|
||||||
|
#include "td/telegram/MessageContentType.h"
|
||||||
|
#include "td/telegram/MessageId.h"
|
||||||
|
#include "td/telegram/MessagesManager.h"
|
||||||
|
#include "td/telegram/net/DcId.h"
|
||||||
|
#include "td/telegram/net/NetActor.h"
|
||||||
|
#include "td/telegram/net/NetQueryCreator.h"
|
||||||
|
#include "td/telegram/SequenceDispatcher.h"
|
||||||
|
#include "td/telegram/Td.h"
|
||||||
|
#include "td/telegram/UpdatesManager.h"
|
||||||
|
|
||||||
|
#include "td/utils/buffer.h"
|
||||||
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class SetGameScoreActor final : public NetActorOnce {
|
||||||
|
Promise<Unit> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SetGameScoreActor(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(DialogId dialog_id, MessageId message_id, bool edit_message,
|
||||||
|
tl_object_ptr<telegram_api::InputUser> input_user, int32 score, bool force, uint64 sequence_dispatcher_id) {
|
||||||
|
int32 flags = 0;
|
||||||
|
if (edit_message) {
|
||||||
|
flags |= telegram_api::messages_setGameScore::EDIT_MESSAGE_MASK;
|
||||||
|
}
|
||||||
|
if (force) {
|
||||||
|
flags |= telegram_api::messages_setGameScore::FORCE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
|
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Edit);
|
||||||
|
if (input_peer == nullptr) {
|
||||||
|
on_error(0, Status::Error(400, "Can't access the chat"));
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(input_user != nullptr);
|
||||||
|
auto query = G()->net_query_creator().create(
|
||||||
|
telegram_api::messages_setGameScore(flags, false /*ignored*/, false /*ignored*/, std::move(input_peer),
|
||||||
|
message_id.get_server_message_id().get(), std::move(input_user), score));
|
||||||
|
|
||||||
|
LOG(INFO) << "Set game score to " << score;
|
||||||
|
|
||||||
|
query->debug("send to MultiSequenceDispatcher");
|
||||||
|
send_closure(td->messages_manager_->sequence_dispatcher_, &MultiSequenceDispatcher::send_with_callback,
|
||||||
|
std::move(query), actor_shared(this), sequence_dispatcher_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::messages_setGameScore>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ptr = result_ptr.move_as_ok();
|
||||||
|
LOG(INFO) << "Receive result for SetGameScore: " << to_string(ptr);
|
||||||
|
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
LOG(INFO) << "Receive error for SetGameScore: " << status;
|
||||||
|
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SetGameScoreActor");
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SetInlineGameScoreQuery final : public Td::ResultHandler {
|
||||||
|
Promise<Unit> promise_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SetInlineGameScoreQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(tl_object_ptr<telegram_api::inputBotInlineMessageID> input_bot_inline_message_id, bool edit_message,
|
||||||
|
tl_object_ptr<telegram_api::InputUser> input_user, int32 score, bool force) {
|
||||||
|
CHECK(input_bot_inline_message_id != nullptr);
|
||||||
|
CHECK(input_user != nullptr);
|
||||||
|
|
||||||
|
int32 flags = 0;
|
||||||
|
if (edit_message) {
|
||||||
|
flags |= telegram_api::messages_setInlineGameScore::EDIT_MESSAGE_MASK;
|
||||||
|
}
|
||||||
|
if (force) {
|
||||||
|
flags |= telegram_api::messages_setInlineGameScore::FORCE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dc_id = DcId::internal(input_bot_inline_message_id->dc_id_);
|
||||||
|
send_query(G()->net_query_creator().create(
|
||||||
|
telegram_api::messages_setInlineGameScore(flags, false /*ignored*/, false /*ignored*/,
|
||||||
|
std::move(input_bot_inline_message_id), std::move(input_user), score),
|
||||||
|
dc_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::messages_setInlineGameScore>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_IF(ERROR, !result_ptr.ok()) << "Receive false in result of setInlineGameScore";
|
||||||
|
|
||||||
|
promise_.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
LOG(INFO) << "Receive error for SetInlineGameScoreQuery: " << status;
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GetGameHighScoresQuery final : public Td::ResultHandler {
|
||||||
|
Promise<td_api::object_ptr<td_api::gameHighScores>> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetGameHighScoresQuery(Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise)
|
||||||
|
: promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(DialogId dialog_id, MessageId message_id, tl_object_ptr<telegram_api::InputUser> input_user) {
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
|
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||||
|
CHECK(input_peer != nullptr);
|
||||||
|
|
||||||
|
CHECK(input_user != nullptr);
|
||||||
|
send_query(G()->net_query_creator().create(telegram_api::messages_getGameHighScores(
|
||||||
|
std::move(input_peer), message_id.get_server_message_id().get(), std::move(input_user))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::messages_getGameHighScores>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(td->game_manager_->get_game_high_scores_object(result_ptr.move_as_ok()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetGameHighScoresQuery");
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GetInlineGameHighScoresQuery final : public Td::ResultHandler {
|
||||||
|
Promise<td_api::object_ptr<td_api::gameHighScores>> promise_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetInlineGameHighScoresQuery(Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise)
|
||||||
|
: promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(tl_object_ptr<telegram_api::inputBotInlineMessageID> input_bot_inline_message_id,
|
||||||
|
tl_object_ptr<telegram_api::InputUser> input_user) {
|
||||||
|
CHECK(input_bot_inline_message_id != nullptr);
|
||||||
|
CHECK(input_user != nullptr);
|
||||||
|
|
||||||
|
auto dc_id = DcId::internal(input_bot_inline_message_id->dc_id_);
|
||||||
|
send_query(G()->net_query_creator().create(
|
||||||
|
telegram_api::messages_getInlineGameHighScores(std::move(input_bot_inline_message_id), std::move(input_user)),
|
||||||
|
dc_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::messages_getInlineGameHighScores>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(td->game_manager_->get_game_high_scores_object(result_ptr.move_as_ok()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GameManager::GameManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
GameManager::~GameManager() = default;
|
||||||
|
|
||||||
|
void GameManager::tear_down() {
|
||||||
|
parent_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameManager::set_game_score(FullMessageId full_message_id, bool edit_message, UserId user_id, int32 score,
|
||||||
|
bool force, Promise<td_api::object_ptr<td_api::message>> &&promise) {
|
||||||
|
CHECK(td_->auth_manager_->is_bot());
|
||||||
|
|
||||||
|
if (!td_->messages_manager_->have_message_force(full_message_id, "set_game_score")) {
|
||||||
|
return promise.set_error(Status::Error(5, "Message not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog_id = full_message_id.get_dialog_id();
|
||||||
|
if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Edit)) {
|
||||||
|
return promise.set_error(Status::Error(5, "Can't access the chat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||||
|
if (input_user == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Invalid user identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!td_->messages_manager_->can_set_game_score(full_message_id)) {
|
||||||
|
return promise.set_error(Status::Error(5, "Game score can't be set"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query_promise = PromiseCreator::lambda(
|
||||||
|
[actor_id = actor_id(this), full_message_id, promise = std::move(promise)](Result<Unit> &&result) mutable {
|
||||||
|
if (result.is_error()) {
|
||||||
|
return promise.set_error(result.move_as_error());
|
||||||
|
}
|
||||||
|
send_closure(actor_id, &GameManager::on_set_game_score, full_message_id, std::move(promise));
|
||||||
|
});
|
||||||
|
send_closure(td_->create_net_actor<SetGameScoreActor>(std::move(query_promise)), &SetGameScoreActor::send, dialog_id,
|
||||||
|
full_message_id.get_message_id(), edit_message, std::move(input_user), score, force,
|
||||||
|
MessagesManager::get_sequence_dispatcher_id(dialog_id, MessageContentType::None));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameManager::on_set_game_score(FullMessageId full_message_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::message>> &&promise) {
|
||||||
|
promise.set_value(td_->messages_manager_->get_message_object(full_message_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameManager::set_inline_game_score(const string &inline_message_id, bool edit_message, UserId user_id, int32 score,
|
||||||
|
bool force, Promise<Unit> &&promise) {
|
||||||
|
CHECK(td_->auth_manager_->is_bot());
|
||||||
|
|
||||||
|
auto input_bot_inline_message_id = td_->inline_queries_manager_->get_input_bot_inline_message_id(inline_message_id);
|
||||||
|
if (input_bot_inline_message_id == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||||
|
if (input_user == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->create_handler<SetInlineGameScoreQuery>(std::move(promise))
|
||||||
|
->send(std::move(input_bot_inline_message_id), edit_message, std::move(input_user), score, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameManager::get_game_high_scores(FullMessageId full_message_id, UserId user_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise) {
|
||||||
|
CHECK(td_->auth_manager_->is_bot());
|
||||||
|
|
||||||
|
if (!td_->messages_manager_->have_message_force(full_message_id, "get_game_high_scores")) {
|
||||||
|
return promise.set_error(Status::Error(5, "Message not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialog_id = full_message_id.get_dialog_id();
|
||||||
|
if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
|
return promise.set_error(Status::Error(5, "Can't access the chat"));
|
||||||
|
}
|
||||||
|
auto message_id = full_message_id.get_message_id();
|
||||||
|
if (message_id.is_scheduled() || !message_id.is_server()) {
|
||||||
|
return promise.set_error(Status::Error(5, "Wrong message identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||||
|
if (input_user == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->create_handler<GetGameHighScoresQuery>(std::move(promise))->send(dialog_id, message_id, std::move(input_user));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameManager::get_inline_game_high_scores(const string &inline_message_id, UserId user_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise) {
|
||||||
|
CHECK(td_->auth_manager_->is_bot());
|
||||||
|
|
||||||
|
auto input_bot_inline_message_id = td_->inline_queries_manager_->get_input_bot_inline_message_id(inline_message_id);
|
||||||
|
if (input_bot_inline_message_id == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||||
|
if (input_user == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->create_handler<GetInlineGameHighScoresQuery>(std::move(promise))
|
||||||
|
->send(std::move(input_bot_inline_message_id), std::move(input_user));
|
||||||
|
}
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::gameHighScores> GameManager::get_game_high_scores_object(
|
||||||
|
telegram_api::object_ptr<telegram_api::messages_highScores> &&high_scores) {
|
||||||
|
td_->contacts_manager_->on_get_users(std::move(high_scores->users_), "get_game_high_scores_object");
|
||||||
|
|
||||||
|
auto result = td_api::make_object<td_api::gameHighScores>();
|
||||||
|
for (const auto &high_score : high_scores->scores_) {
|
||||||
|
int32 position = high_score->pos_;
|
||||||
|
UserId user_id(high_score->user_id_);
|
||||||
|
int32 score = high_score->score_;
|
||||||
|
if (position <= 0 || !user_id.is_valid() || score < 0) {
|
||||||
|
LOG(ERROR) << "Receive wrong " << to_string(high_score);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result->scores_.push_back(make_tl_object<td_api::gameHighScore>(
|
||||||
|
position, td_->contacts_manager_->get_user_id_object(user_id, "get_game_high_scores_object"), score));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
56
td/telegram/GameManager.h
Normal file
56
td/telegram/GameManager.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/FullMessageId.h"
|
||||||
|
#include "td/telegram/td_api.h"
|
||||||
|
#include "td/telegram/telegram_api.h"
|
||||||
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
|
#include "td/actor/actor.h"
|
||||||
|
#include "td/actor/PromiseFuture.h"
|
||||||
|
|
||||||
|
#include "td/utils/common.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class Td;
|
||||||
|
|
||||||
|
class GameManager final : public Actor {
|
||||||
|
public:
|
||||||
|
GameManager(Td *td, ActorShared<> parent);
|
||||||
|
GameManager(const GameManager &) = delete;
|
||||||
|
GameManager &operator=(const GameManager &) = delete;
|
||||||
|
GameManager(GameManager &&) = delete;
|
||||||
|
GameManager &operator=(GameManager &&) = delete;
|
||||||
|
~GameManager() final;
|
||||||
|
|
||||||
|
void set_game_score(FullMessageId full_message_id, bool edit_message, UserId user_id, int32 score, bool force,
|
||||||
|
Promise<td_api::object_ptr<td_api::message>> &&promise);
|
||||||
|
|
||||||
|
void set_inline_game_score(const string &inline_message_id, bool edit_message, UserId user_id, int32 score,
|
||||||
|
bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void get_game_high_scores(FullMessageId full_message_id, UserId user_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise);
|
||||||
|
|
||||||
|
void get_inline_game_high_scores(const string &inline_message_id, UserId user_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise);
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::gameHighScores> get_game_high_scores_object(
|
||||||
|
telegram_api::object_ptr<telegram_api::messages_highScores> &&high_scores);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void tear_down() final;
|
||||||
|
|
||||||
|
void on_set_game_score(FullMessageId full_message_id, Promise<td_api::object_ptr<td_api::message>> &&promise);
|
||||||
|
|
||||||
|
Td *td_;
|
||||||
|
ActorShared<> parent_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace td
|
@ -38,6 +38,7 @@ class ConnectionCreator;
|
|||||||
class ContactsManager;
|
class ContactsManager;
|
||||||
class FileManager;
|
class FileManager;
|
||||||
class FileReferenceManager;
|
class FileReferenceManager;
|
||||||
|
class GameManager;
|
||||||
class GroupCallManager;
|
class GroupCallManager;
|
||||||
class LanguagePackManager;
|
class LanguagePackManager;
|
||||||
class LinkManager;
|
class LinkManager;
|
||||||
@ -47,6 +48,7 @@ class NetQueryDispatcher;
|
|||||||
class NotificationManager;
|
class NotificationManager;
|
||||||
class PasswordManager;
|
class PasswordManager;
|
||||||
class SecretChatsManager;
|
class SecretChatsManager;
|
||||||
|
class SponsoredMessageManager;
|
||||||
class StateManager;
|
class StateManager;
|
||||||
class StickersManager;
|
class StickersManager;
|
||||||
class StorageManager;
|
class StorageManager;
|
||||||
@ -219,6 +221,13 @@ class Global final : public ActorContext {
|
|||||||
file_reference_manager_ = std::move(file_reference_manager);
|
file_reference_manager_ = std::move(file_reference_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActorId<GameManager> game_manager() const {
|
||||||
|
return game_manager_;
|
||||||
|
}
|
||||||
|
void set_game_manager(ActorId<GameManager> game_manager) {
|
||||||
|
game_manager_ = game_manager;
|
||||||
|
}
|
||||||
|
|
||||||
ActorId<GroupCallManager> group_call_manager() const {
|
ActorId<GroupCallManager> group_call_manager() const {
|
||||||
return group_call_manager_;
|
return group_call_manager_;
|
||||||
}
|
}
|
||||||
@ -268,6 +277,13 @@ class Global final : public ActorContext {
|
|||||||
secret_chats_manager_ = secret_chats_manager;
|
secret_chats_manager_ = secret_chats_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActorId<SponsoredMessageManager> sponsored_message_manager() const {
|
||||||
|
return sponsored_message_manager_;
|
||||||
|
}
|
||||||
|
void set_sponsored_message_manager(ActorId<SponsoredMessageManager> sponsored_message_manager) {
|
||||||
|
sponsored_message_manager_ = sponsored_message_manager;
|
||||||
|
}
|
||||||
|
|
||||||
ActorId<StickersManager> stickers_manager() const {
|
ActorId<StickersManager> stickers_manager() const {
|
||||||
return stickers_manager_;
|
return stickers_manager_;
|
||||||
}
|
}
|
||||||
@ -417,6 +433,7 @@ class Global final : public ActorContext {
|
|||||||
ActorId<ContactsManager> contacts_manager_;
|
ActorId<ContactsManager> contacts_manager_;
|
||||||
ActorId<FileManager> file_manager_;
|
ActorId<FileManager> file_manager_;
|
||||||
ActorId<FileReferenceManager> file_reference_manager_;
|
ActorId<FileReferenceManager> file_reference_manager_;
|
||||||
|
ActorId<GameManager> game_manager_;
|
||||||
ActorId<GroupCallManager> group_call_manager_;
|
ActorId<GroupCallManager> group_call_manager_;
|
||||||
ActorId<LanguagePackManager> language_pack_manager_;
|
ActorId<LanguagePackManager> language_pack_manager_;
|
||||||
ActorId<LinkManager> link_manager_;
|
ActorId<LinkManager> link_manager_;
|
||||||
@ -424,6 +441,7 @@ class Global final : public ActorContext {
|
|||||||
ActorId<NotificationManager> notification_manager_;
|
ActorId<NotificationManager> notification_manager_;
|
||||||
ActorId<PasswordManager> password_manager_;
|
ActorId<PasswordManager> password_manager_;
|
||||||
ActorId<SecretChatsManager> secret_chats_manager_;
|
ActorId<SecretChatsManager> secret_chats_manager_;
|
||||||
|
ActorId<SponsoredMessageManager> sponsored_message_manager_;
|
||||||
ActorId<StickersManager> stickers_manager_;
|
ActorId<StickersManager> stickers_manager_;
|
||||||
ActorId<StorageManager> storage_manager_;
|
ActorId<StorageManager> storage_manager_;
|
||||||
ActorId<MemoryManager> memory_manager_;
|
ActorId<MemoryManager> memory_manager_;
|
||||||
|
@ -1074,7 +1074,7 @@ tl_object_ptr<td_api::venue> copy(const td_api::venue &obj) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
tl_object_ptr<td_api::formattedText> copy(const td_api::formattedText &obj) {
|
tl_object_ptr<td_api::formattedText> copy(const td_api::formattedText &obj) {
|
||||||
// there is no entities in the game text
|
// there are no entities in the game text
|
||||||
return make_tl_object<td_api::formattedText>(obj.text_, vector<tl_object_ptr<td_api::textEntity>>());
|
return make_tl_object<td_api::formattedText>(obj.text_, vector<tl_object_ptr<td_api::textEntity>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,14 +357,17 @@ class LinkManager::InternalLinkUnknownDeepLink final : public InternalLink {
|
|||||||
class LinkManager::InternalLinkVoiceChat final : public InternalLink {
|
class LinkManager::InternalLinkVoiceChat final : public InternalLink {
|
||||||
string dialog_username_;
|
string dialog_username_;
|
||||||
string invite_hash_;
|
string invite_hash_;
|
||||||
|
bool is_live_stream_;
|
||||||
|
|
||||||
td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
|
td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
|
||||||
return td_api::make_object<td_api::internalLinkTypeVoiceChat>(dialog_username_, invite_hash_);
|
return td_api::make_object<td_api::internalLinkTypeVoiceChat>(dialog_username_, invite_hash_, is_live_stream_);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InternalLinkVoiceChat(string dialog_username, string invite_hash)
|
InternalLinkVoiceChat(string dialog_username, string invite_hash, bool is_live_stream)
|
||||||
: dialog_username_(std::move(dialog_username)), invite_hash_(std::move(invite_hash)) {
|
: dialog_username_(std::move(dialog_username))
|
||||||
|
, invite_hash_(std::move(invite_hash))
|
||||||
|
, is_live_stream_(is_live_stream) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -768,13 +771,13 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
|
|||||||
}
|
}
|
||||||
auto username = get_arg("domain");
|
auto username = get_arg("domain");
|
||||||
for (auto &arg : url_query.args_) {
|
for (auto &arg : url_query.args_) {
|
||||||
if (arg.first == "voicechat") {
|
if (arg.first == "voicechat" || arg.first == "videochat" || arg.first == "livestream") {
|
||||||
// resolve?domain=<username>&voicechat
|
// resolve?domain=<username>&videochat
|
||||||
// resolve?domain=<username>&voicechat=<invite_hash>
|
// resolve?domain=<username>&videochat=<invite_hash>
|
||||||
if (Scheduler::context() != nullptr) {
|
if (Scheduler::context() != nullptr) {
|
||||||
send_closure(G()->messages_manager(), &MessagesManager::reload_voice_chat_on_search, username);
|
send_closure(G()->messages_manager(), &MessagesManager::reload_voice_chat_on_search, username);
|
||||||
}
|
}
|
||||||
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second);
|
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second, arg.first == "livestream");
|
||||||
}
|
}
|
||||||
if (arg.first == "start" && is_valid_start_parameter(arg.second)) {
|
if (arg.first == "start" && is_valid_start_parameter(arg.second)) {
|
||||||
// resolve?domain=<bot_username>?start=<parameter>
|
// resolve?domain=<bot_username>?start=<parameter>
|
||||||
@ -1017,13 +1020,13 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_t_me_link_query(Slice q
|
|||||||
}
|
}
|
||||||
auto username = path[0];
|
auto username = path[0];
|
||||||
for (auto &arg : url_query.args_) {
|
for (auto &arg : url_query.args_) {
|
||||||
if (arg.first == "voicechat") {
|
if (arg.first == "voicechat" || arg.first == "videochat" || arg.first == "livestream") {
|
||||||
// /<username>?voicechat
|
// /<username>?videochat
|
||||||
// /<username>?voicechat=<invite_hash>
|
// /<username>?videochat=<invite_hash>
|
||||||
if (Scheduler::context() != nullptr) {
|
if (Scheduler::context() != nullptr) {
|
||||||
send_closure(G()->messages_manager(), &MessagesManager::reload_voice_chat_on_search, username);
|
send_closure(G()->messages_manager(), &MessagesManager::reload_voice_chat_on_search, username);
|
||||||
}
|
}
|
||||||
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second);
|
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second, arg.first == "livestream");
|
||||||
}
|
}
|
||||||
if (arg.first == "start" && is_valid_start_parameter(arg.second)) {
|
if (arg.first == "start" && is_valid_start_parameter(arg.second)) {
|
||||||
// /<bot_username>?start=<parameter>
|
// /<bot_username>?start=<parameter>
|
||||||
|
@ -4364,7 +4364,12 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
|||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
case MessageContentType::Poll:
|
case MessageContentType::Poll:
|
||||||
return make_unique<MessagePoll>(*static_cast<const MessagePoll *>(content));
|
if (type == MessageContentDupType::Copy) {
|
||||||
|
return make_unique<MessagePoll>(
|
||||||
|
td->poll_manager_->dup_poll(static_cast<const MessagePoll *>(content)->poll_id));
|
||||||
|
} else {
|
||||||
|
return make_unique<MessagePoll>(*static_cast<const MessagePoll *>(content));
|
||||||
|
}
|
||||||
case MessageContentType::Sticker: {
|
case MessageContentType::Sticker: {
|
||||||
auto result = make_unique<MessageSticker>(*static_cast<const MessageSticker *>(content));
|
auto result = make_unique<MessageSticker>(*static_cast<const MessageSticker *>(content));
|
||||||
if (td->stickers_manager_->has_input_media(result->file_id, to_secret)) {
|
if (td->stickers_manager_->has_input_media(result->file_id, to_secret)) {
|
||||||
|
@ -3542,188 +3542,6 @@ class EditInlineMessageQuery final : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SetGameScoreActor final : public NetActorOnce {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
DialogId dialog_id_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SetGameScoreActor(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(DialogId dialog_id, MessageId message_id, bool edit_message,
|
|
||||||
tl_object_ptr<telegram_api::InputUser> input_user, int32 score, bool force, uint64 sequence_dispatcher_id) {
|
|
||||||
int32 flags = 0;
|
|
||||||
if (edit_message) {
|
|
||||||
flags |= telegram_api::messages_setGameScore::EDIT_MESSAGE_MASK;
|
|
||||||
}
|
|
||||||
if (force) {
|
|
||||||
flags |= telegram_api::messages_setGameScore::FORCE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog_id_ = dialog_id;
|
|
||||||
|
|
||||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Edit);
|
|
||||||
if (input_peer == nullptr) {
|
|
||||||
on_error(0, Status::Error(400, "Can't access the chat"));
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(input_user != nullptr);
|
|
||||||
auto query = G()->net_query_creator().create(
|
|
||||||
telegram_api::messages_setGameScore(flags, false /*ignored*/, false /*ignored*/, std::move(input_peer),
|
|
||||||
message_id.get_server_message_id().get(), std::move(input_user), score));
|
|
||||||
|
|
||||||
LOG(INFO) << "Set game score to " << score;
|
|
||||||
|
|
||||||
query->debug("send to MessagesManager::MultiSequenceDispatcher");
|
|
||||||
send_closure(td->messages_manager_->sequence_dispatcher_, &MultiSequenceDispatcher::send_with_callback,
|
|
||||||
std::move(query), actor_shared(this), sequence_dispatcher_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::messages_setGameScore>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(id, result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ptr = result_ptr.move_as_ok();
|
|
||||||
LOG(INFO) << "Receive result for SetGameScore: " << to_string(ptr);
|
|
||||||
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) final {
|
|
||||||
LOG(INFO) << "Receive error for SetGameScore: " << status;
|
|
||||||
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SetGameScoreActor");
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SetInlineGameScoreQuery final : public Td::ResultHandler {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SetInlineGameScoreQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(tl_object_ptr<telegram_api::inputBotInlineMessageID> input_bot_inline_message_id, bool edit_message,
|
|
||||||
tl_object_ptr<telegram_api::InputUser> input_user, int32 score, bool force) {
|
|
||||||
CHECK(input_bot_inline_message_id != nullptr);
|
|
||||||
CHECK(input_user != nullptr);
|
|
||||||
|
|
||||||
int32 flags = 0;
|
|
||||||
if (edit_message) {
|
|
||||||
flags |= telegram_api::messages_setInlineGameScore::EDIT_MESSAGE_MASK;
|
|
||||||
}
|
|
||||||
if (force) {
|
|
||||||
flags |= telegram_api::messages_setInlineGameScore::FORCE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "Set inline game score to " << score;
|
|
||||||
auto dc_id = DcId::internal(input_bot_inline_message_id->dc_id_);
|
|
||||||
send_query(G()->net_query_creator().create(
|
|
||||||
telegram_api::messages_setInlineGameScore(flags, false /*ignored*/, false /*ignored*/,
|
|
||||||
std::move(input_bot_inline_message_id), std::move(input_user), score),
|
|
||||||
dc_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::messages_setInlineGameScore>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(id, result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_IF(ERROR, !result_ptr.ok()) << "Receive false in result of setInlineGameScore";
|
|
||||||
|
|
||||||
promise_.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) final {
|
|
||||||
LOG(INFO) << "Receive error for SetInlineGameScoreQuery: " << status;
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetGameHighScoresQuery final : public Td::ResultHandler {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
DialogId dialog_id_;
|
|
||||||
int64 random_id_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GetGameHighScoresQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(DialogId dialog_id, MessageId message_id, tl_object_ptr<telegram_api::InputUser> input_user,
|
|
||||||
int64 random_id) {
|
|
||||||
dialog_id_ = dialog_id;
|
|
||||||
random_id_ = random_id;
|
|
||||||
|
|
||||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
|
||||||
if (input_peer == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(input_user != nullptr);
|
|
||||||
send_query(G()->net_query_creator().create(telegram_api::messages_getGameHighScores(
|
|
||||||
std::move(input_peer), message_id.get_server_message_id().get(), std::move(input_user))));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::messages_getGameHighScores>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(id, result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
td->messages_manager_->on_get_game_high_scores(random_id_, result_ptr.move_as_ok());
|
|
||||||
promise_.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) final {
|
|
||||||
LOG(INFO) << "Receive error for GetGameHighScoresQuery: " << status;
|
|
||||||
td->messages_manager_->on_get_game_high_scores(random_id_, nullptr);
|
|
||||||
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetGameHighScoresQuery");
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetInlineGameHighScoresQuery final : public Td::ResultHandler {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
int64 random_id_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GetInlineGameHighScoresQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(tl_object_ptr<telegram_api::inputBotInlineMessageID> input_bot_inline_message_id,
|
|
||||||
tl_object_ptr<telegram_api::InputUser> input_user, int64 random_id) {
|
|
||||||
CHECK(input_bot_inline_message_id != nullptr);
|
|
||||||
CHECK(input_user != nullptr);
|
|
||||||
|
|
||||||
random_id_ = random_id;
|
|
||||||
|
|
||||||
auto dc_id = DcId::internal(input_bot_inline_message_id->dc_id_);
|
|
||||||
send_query(G()->net_query_creator().create(
|
|
||||||
telegram_api::messages_getInlineGameHighScores(std::move(input_bot_inline_message_id), std::move(input_user)),
|
|
||||||
dc_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::messages_getInlineGameHighScores>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(id, result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
td->messages_manager_->on_get_game_high_scores(random_id_, result_ptr.move_as_ok());
|
|
||||||
promise_.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) final {
|
|
||||||
LOG(INFO) << "Receive error for GetInlineGameHighScoresQuery: " << status;
|
|
||||||
td->messages_manager_->on_get_game_high_scores(random_id_, nullptr);
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ForwardMessagesActor final : public NetActorOnce {
|
class ForwardMessagesActor final : public NetActorOnce {
|
||||||
Promise<Unit> promise_;
|
Promise<Unit> promise_;
|
||||||
vector<int64> random_ids_;
|
vector<int64> random_ids_;
|
||||||
@ -8808,7 +8626,7 @@ void MessagesManager::get_dialog_statistics_url(DialogId dialog_id, const string
|
|||||||
return promise.set_error(Status::Error(3, "Can't access the chat"));
|
return promise.set_error(Status::Error(3, "Can't access the chat"));
|
||||||
}
|
}
|
||||||
if (dialog_id.get_type() == DialogType::SecretChat) {
|
if (dialog_id.get_type() == DialogType::SecretChat) {
|
||||||
return promise.set_error(Status::Error(500, "There is no statistics for secret chats"));
|
return promise.set_error(Status::Error(500, "There are no statistics for secret chats"));
|
||||||
}
|
}
|
||||||
|
|
||||||
td_->create_handler<GetStatsUrlQuery>(std::move(promise))->send(dialog_id, parameters, is_dark);
|
td_->create_handler<GetStatsUrlQuery>(std::move(promise))->send(dialog_id, parameters, is_dark);
|
||||||
@ -11646,7 +11464,7 @@ void MessagesManager::repair_channel_server_unread_count(Dialog *d) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!need_unread_counter(d->order)) {
|
if (!need_unread_counter(d->order)) {
|
||||||
// there is no unread count in left channels
|
// there are no unread counters in left channels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!d->need_repair_channel_server_unread_count) {
|
if (!d->need_repair_channel_server_unread_count) {
|
||||||
@ -19836,7 +19654,7 @@ Status MessagesManager::view_messages(DialogId dialog_id, MessageId top_thread_m
|
|||||||
return Status::Error(400, "Invalid message thread ID specified");
|
return Status::Error(400, "Invalid message thread ID specified");
|
||||||
}
|
}
|
||||||
if (dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(dialog_id)) {
|
if (dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(dialog_id)) {
|
||||||
return Status::Error(400, "There is no message threads in the chat");
|
return Status::Error(400, "There are no message threads in the chat");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26193,10 +26011,17 @@ int32 MessagesManager::get_message_flags(const Message *m) {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MessagesManager::can_set_game_score(FullMessageId full_message_id) const {
|
||||||
|
return can_set_game_score(full_message_id.get_dialog_id(), get_message(full_message_id));
|
||||||
|
}
|
||||||
|
|
||||||
bool MessagesManager::can_set_game_score(DialogId dialog_id, const Message *m) const {
|
bool MessagesManager::can_set_game_score(DialogId dialog_id, const Message *m) const {
|
||||||
if (m == nullptr) {
|
if (m == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (m->content->get_type() != MessageContentType::Game) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (m->message_id.is_scheduled()) {
|
if (m->message_id.is_scheduled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -26255,181 +26080,7 @@ bool MessagesManager::can_set_game_score(DialogId dialog_id, const Message *m) c
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m->content->get_type() == MessageContentType::Game;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::set_game_score(FullMessageId full_message_id, bool edit_message, UserId user_id, int32 score,
|
|
||||||
bool force, Promise<Unit> &&promise) {
|
|
||||||
if (!td_->auth_manager_->is_bot()) {
|
|
||||||
return promise.set_error(Status::Error(3, "Method is available only for bots"));
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "Begin to set game score of " << user_id << " in " << full_message_id;
|
|
||||||
auto dialog_id = full_message_id.get_dialog_id();
|
|
||||||
Dialog *d = get_dialog_force(dialog_id, "set_game_score");
|
|
||||||
if (d == nullptr) {
|
|
||||||
return promise.set_error(Status::Error(5, "Chat not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!have_input_peer(dialog_id, AccessRights::Edit)) {
|
|
||||||
return promise.set_error(Status::Error(5, "Can't access the chat"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Message *m = get_message_force(d, full_message_id.get_message_id(), "set_game_score");
|
|
||||||
if (m == nullptr) {
|
|
||||||
return promise.set_error(Status::Error(5, "Message not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
|
||||||
if (input_user == nullptr) {
|
|
||||||
return promise.set_error(Status::Error(400, "Invalid user identifier specified"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!can_set_game_score(dialog_id, m)) {
|
|
||||||
return promise.set_error(Status::Error(5, "Game score can't be set"));
|
|
||||||
}
|
|
||||||
|
|
||||||
send_closure(td_->create_net_actor<SetGameScoreActor>(std::move(promise)), &SetGameScoreActor::send, dialog_id,
|
|
||||||
m->message_id, edit_message, std::move(input_user), score, force,
|
|
||||||
get_sequence_dispatcher_id(dialog_id, MessageContentType::None));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::set_inline_game_score(const string &inline_message_id, bool edit_message, UserId user_id,
|
|
||||||
int32 score, bool force, Promise<Unit> &&promise) {
|
|
||||||
if (!td_->auth_manager_->is_bot()) {
|
|
||||||
return promise.set_error(Status::Error(3, "Method is available only for bots"));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto input_bot_inline_message_id = td_->inline_queries_manager_->get_input_bot_inline_message_id(inline_message_id);
|
|
||||||
if (input_bot_inline_message_id == nullptr) {
|
|
||||||
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
|
||||||
if (input_user == nullptr) {
|
|
||||||
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
|
||||||
}
|
|
||||||
|
|
||||||
td_->create_handler<SetInlineGameScoreQuery>(std::move(promise))
|
|
||||||
->send(std::move(input_bot_inline_message_id), edit_message, std::move(input_user), score, force);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 MessagesManager::get_game_high_scores(FullMessageId full_message_id, UserId user_id, Promise<Unit> &&promise) {
|
|
||||||
if (!td_->auth_manager_->is_bot()) {
|
|
||||||
promise.set_error(Status::Error(3, "Method is available only for bots"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "Begin to get game high scores of " << user_id << " in " << full_message_id;
|
|
||||||
auto dialog_id = full_message_id.get_dialog_id();
|
|
||||||
Dialog *d = get_dialog_force(dialog_id, "get_game_high_scores");
|
|
||||||
if (d == nullptr) {
|
|
||||||
promise.set_error(Status::Error(5, "Chat not found"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!have_input_peer(dialog_id, AccessRights::Read)) {
|
|
||||||
promise.set_error(Status::Error(5, "Can't access the chat"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Message *m = get_message_force(d, full_message_id.get_message_id(), "get_game_high_scores");
|
|
||||||
if (m == nullptr) {
|
|
||||||
promise.set_error(Status::Error(5, "Message not found"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (m->message_id.is_scheduled() || !m->message_id.is_server()) {
|
|
||||||
promise.set_error(Status::Error(5, "Wrong message identifier specified"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
|
||||||
if (input_user == nullptr) {
|
|
||||||
promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 random_id = 0;
|
|
||||||
do {
|
|
||||||
random_id = Random::secure_int64();
|
|
||||||
} while (random_id == 0 || game_high_scores_.find(random_id) != game_high_scores_.end());
|
|
||||||
game_high_scores_[random_id]; // reserve place for result
|
|
||||||
|
|
||||||
td_->create_handler<GetGameHighScoresQuery>(std::move(promise))
|
|
||||||
->send(dialog_id, m->message_id, std::move(input_user), random_id);
|
|
||||||
return random_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 MessagesManager::get_inline_game_high_scores(const string &inline_message_id, UserId user_id,
|
|
||||||
Promise<Unit> &&promise) {
|
|
||||||
if (!td_->auth_manager_->is_bot()) {
|
|
||||||
promise.set_error(Status::Error(3, "Method is available only for bots"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto input_bot_inline_message_id = td_->inline_queries_manager_->get_input_bot_inline_message_id(inline_message_id);
|
|
||||||
if (input_bot_inline_message_id == nullptr) {
|
|
||||||
promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
|
||||||
if (input_user == nullptr) {
|
|
||||||
promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 random_id = 0;
|
|
||||||
do {
|
|
||||||
random_id = Random::secure_int64();
|
|
||||||
} while (random_id == 0 || game_high_scores_.find(random_id) != game_high_scores_.end());
|
|
||||||
game_high_scores_[random_id]; // reserve place for result
|
|
||||||
|
|
||||||
td_->create_handler<GetInlineGameHighScoresQuery>(std::move(promise))
|
|
||||||
->send(std::move(input_bot_inline_message_id), std::move(input_user), random_id);
|
|
||||||
return random_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::on_get_game_high_scores(int64 random_id,
|
|
||||||
tl_object_ptr<telegram_api::messages_highScores> &&high_scores) {
|
|
||||||
auto it = game_high_scores_.find(random_id);
|
|
||||||
CHECK(it != game_high_scores_.end());
|
|
||||||
auto &result = it->second;
|
|
||||||
CHECK(result == nullptr);
|
|
||||||
|
|
||||||
if (high_scores == nullptr) {
|
|
||||||
game_high_scores_.erase(it);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
td_->contacts_manager_->on_get_users(std::move(high_scores->users_), "on_get_game_high_scores");
|
|
||||||
|
|
||||||
result = make_tl_object<td_api::gameHighScores>();
|
|
||||||
|
|
||||||
for (auto &high_score : high_scores->scores_) {
|
|
||||||
int32 position = high_score->pos_;
|
|
||||||
if (position <= 0) {
|
|
||||||
LOG(ERROR) << "Receive wrong position = " << position;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
UserId user_id(high_score->user_id_);
|
|
||||||
LOG_IF(WARNING, !td_->contacts_manager_->have_user(user_id)) << "Have no info about " << user_id;
|
|
||||||
int32 score = high_score->score_;
|
|
||||||
if (score < 0) {
|
|
||||||
LOG(ERROR) << "Receive wrong score = " << score;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result->scores_.push_back(make_tl_object<td_api::gameHighScore>(
|
|
||||||
position, td_->contacts_manager_->get_user_id_object(user_id, "gameHighScore"), score));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tl_object_ptr<td_api::gameHighScores> MessagesManager::get_game_high_scores_object(int64 random_id) {
|
|
||||||
auto it = game_high_scores_.find(random_id);
|
|
||||||
CHECK(it != game_high_scores_.end());
|
|
||||||
auto result = std::move(it->second);
|
|
||||||
game_high_scores_.erase(it);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessagesManager::is_forward_info_sender_hidden(const MessageForwardInfo *forward_info) {
|
bool MessagesManager::is_forward_info_sender_hidden(const MessageForwardInfo *forward_info) {
|
||||||
|
@ -467,20 +467,6 @@ class MessagesManager final : public Actor {
|
|||||||
td_api::object_ptr<td_api::MessageSchedulingState> &&scheduling_state,
|
td_api::object_ptr<td_api::MessageSchedulingState> &&scheduling_state,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void set_game_score(FullMessageId full_message_id, bool edit_message, UserId user_id, int32 score, bool force,
|
|
||||||
Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
void set_inline_game_score(const string &inline_message_id, bool edit_message, UserId user_id, int32 score,
|
|
||||||
bool force, Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
int64 get_game_high_scores(FullMessageId full_message_id, UserId user_id, Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
int64 get_inline_game_high_scores(const string &inline_message_id, UserId user_id, Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
void on_get_game_high_scores(int64 random_id, tl_object_ptr<telegram_api::messages_highScores> &&high_scores);
|
|
||||||
|
|
||||||
tl_object_ptr<td_api::gameHighScores> get_game_high_scores_object(int64 random_id);
|
|
||||||
|
|
||||||
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
|
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
@ -917,10 +903,14 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
Result<ServerMessageId> get_payment_successful_message_id(FullMessageId full_message_id);
|
Result<ServerMessageId> get_payment_successful_message_id(FullMessageId full_message_id);
|
||||||
|
|
||||||
|
bool can_set_game_score(FullMessageId full_message_id) const;
|
||||||
|
|
||||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||||
|
|
||||||
ActorOwn<MultiSequenceDispatcher> sequence_dispatcher_;
|
ActorOwn<MultiSequenceDispatcher> sequence_dispatcher_;
|
||||||
|
|
||||||
|
static uint64 get_sequence_dispatcher_id(DialogId dialog_id, MessageContentType message_content_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PendingPtsUpdate {
|
class PendingPtsUpdate {
|
||||||
public:
|
public:
|
||||||
@ -1149,10 +1139,10 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
MessageId last_new_message_id; // identifier of the last known server message received from update, there should be
|
MessageId last_new_message_id; // identifier of the last known server message received from update, there should be
|
||||||
// no server messages after it
|
// no server messages after it
|
||||||
MessageId last_message_id; // identifier of the message after which currently there is no any message, i.e. a
|
MessageId last_message_id; // identifier of the message after which currently there are no messages, i.e. a
|
||||||
// message without a gap after it, memory only
|
// message without a gap after it, memory only
|
||||||
MessageId first_database_message_id; // identifier of the first message in the database, needed
|
MessageId first_database_message_id; // identifier of the first message in the database, needed
|
||||||
// until there is no gaps in the database
|
// until there are no gaps in the database
|
||||||
MessageId last_database_message_id; // identifier of the last local or server message, if last_database_message_id
|
MessageId last_database_message_id; // identifier of the last local or server message, if last_database_message_id
|
||||||
// is known and last_message_id is known, then last_database_message_id <=
|
// is known and last_message_id is known, then last_database_message_id <=
|
||||||
// last_message_id
|
// last_message_id
|
||||||
@ -2985,8 +2975,6 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
void set_sponsored_dialog(DialogId dialog_id, DialogSource source);
|
void set_sponsored_dialog(DialogId dialog_id, DialogSource source);
|
||||||
|
|
||||||
static uint64 get_sequence_dispatcher_id(DialogId dialog_id, MessageContentType message_content_type);
|
|
||||||
|
|
||||||
Dialog *get_service_notifications_dialog();
|
Dialog *get_service_notifications_dialog();
|
||||||
|
|
||||||
void save_auth_notification_ids();
|
void save_auth_notification_ids();
|
||||||
@ -3321,8 +3309,6 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
std::unordered_map<int64, tl_object_ptr<td_api::chatEvents>> chat_events_; // random_id -> chat events
|
std::unordered_map<int64, tl_object_ptr<td_api::chatEvents>> chat_events_; // random_id -> chat events
|
||||||
|
|
||||||
std::unordered_map<int64, tl_object_ptr<td_api::gameHighScores>> game_high_scores_; // random_id -> high scores
|
|
||||||
|
|
||||||
std::unordered_map<DialogId, vector<Promise<Unit>>, DialogIdHash> get_dialog_notification_settings_queries_;
|
std::unordered_map<DialogId, vector<Promise<Unit>>, DialogIdHash> get_dialog_notification_settings_queries_;
|
||||||
|
|
||||||
std::unordered_map<DialogId, vector<Promise<Unit>>, DialogIdHash> get_dialog_queries_;
|
std::unordered_map<DialogId, vector<Promise<Unit>>, DialogIdHash> get_dialog_queries_;
|
||||||
|
@ -1063,7 +1063,7 @@ void NotificationManager::flush_pending_updates(int32 group_id, const char *sour
|
|||||||
// all edits of notifications from edited_notification_ids
|
// all edits of notifications from edited_notification_ids
|
||||||
// deletions of a notification can be removed, only if the addition of the notification has already been deleted
|
// deletions of a notification can be removed, only if the addition of the notification has already been deleted
|
||||||
// deletions of all unkept notifications can be moved to the first updateNotificationGroup
|
// deletions of all unkept notifications can be moved to the first updateNotificationGroup
|
||||||
// after that at every moment there is no more active notifications than in the last moment,
|
// after that at every moment there are no more active notifications than in the last moment,
|
||||||
// so left deletions after add/edit can be safely removed and following additions can be treated as edits
|
// so left deletions after add/edit can be safely removed and following additions can be treated as edits
|
||||||
// we still need to keep deletions coming first, because we can't have 2 consequent additions
|
// we still need to keep deletions coming first, because we can't have 2 consequent additions
|
||||||
// from all additions of the same notification, we need to preserve the first, because it can be with sound,
|
// from all additions of the same notification, we need to preserve the first, because it can be with sound,
|
||||||
@ -2809,6 +2809,9 @@ string NotificationManager::convert_loc_key(const string &loc_key) {
|
|||||||
if (loc_key == "MESSAGE_NOTEXT") {
|
if (loc_key == "MESSAGE_NOTEXT") {
|
||||||
return "MESSAGE";
|
return "MESSAGE";
|
||||||
}
|
}
|
||||||
|
if (loc_key == "MESSAGE_NOTHEME") {
|
||||||
|
return "MESSAGE_CHAT_CHANGE_THEME";
|
||||||
|
}
|
||||||
if (loc_key == "PINNED_INVOICE") {
|
if (loc_key == "PINNED_INVOICE") {
|
||||||
return "PINNED_MESSAGE_INVOICE";
|
return "PINNED_MESSAGE_INVOICE";
|
||||||
}
|
}
|
||||||
|
@ -593,6 +593,10 @@ td_api::object_ptr<td_api::poll> PollManager::get_poll_object(PollId poll_id, co
|
|||||||
open_period = close_date - now;
|
open_period = close_date - now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (poll->is_closed) {
|
||||||
|
open_period = 0;
|
||||||
|
close_date = 0;
|
||||||
|
}
|
||||||
return td_api::make_object<td_api::poll>(
|
return td_api::make_object<td_api::poll>(
|
||||||
poll_id.get(), poll->question, std::move(poll_options), total_voter_count,
|
poll_id.get(), poll->question, std::move(poll_options), total_voter_count,
|
||||||
td_->contacts_manager_->get_user_ids_object(poll->recent_voter_user_ids, "get_poll_object"), poll->is_anonymous,
|
td_->contacts_manager_->get_user_ids_object(poll->recent_voter_user_ids, "get_poll_object"), poll->is_anonymous,
|
||||||
@ -1283,6 +1287,18 @@ void PollManager::on_online() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PollId PollManager::dup_poll(PollId poll_id) {
|
||||||
|
auto poll = get_poll(poll_id);
|
||||||
|
CHECK(poll != nullptr);
|
||||||
|
|
||||||
|
auto question = poll->question;
|
||||||
|
auto options = transform(poll->options, [](auto &option) { return option.text; });
|
||||||
|
auto explanation = poll->explanation;
|
||||||
|
return create_poll(std::move(question), std::move(options), poll->is_anonymous, poll->allow_multiple_answers,
|
||||||
|
poll->is_quiz, poll->correct_option_id, std::move(explanation), poll->open_period,
|
||||||
|
poll->open_period == 0 ? 0 : G()->unix_time(), false);
|
||||||
|
}
|
||||||
|
|
||||||
bool PollManager::has_input_media(PollId poll_id) const {
|
bool PollManager::has_input_media(PollId poll_id) const {
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
if (!(poll != nullptr)) return false;
|
if (!(poll != nullptr)) return false;
|
||||||
@ -1383,6 +1399,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
|||||||
|
|
||||||
auto poll = get_poll_force(poll_id);
|
auto poll = get_poll_force(poll_id);
|
||||||
bool is_changed = false;
|
bool is_changed = false;
|
||||||
|
bool need_save_to_database = false;
|
||||||
if (poll == nullptr) {
|
if (poll == nullptr) {
|
||||||
if (poll_server == nullptr) {
|
if (poll_server == nullptr) {
|
||||||
LOG(INFO) << "Ignore " << poll_id << ", because have no data about it";
|
LOG(INFO) << "Ignore " << poll_id << ", because have no data about it";
|
||||||
@ -1465,13 +1482,16 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
|||||||
}
|
}
|
||||||
if (open_period != poll->open_period) {
|
if (open_period != poll->open_period) {
|
||||||
poll->open_period = open_period;
|
poll->open_period = open_period;
|
||||||
is_changed = true;
|
if (!poll->is_closed) {
|
||||||
|
is_changed = true;
|
||||||
|
} else {
|
||||||
|
need_save_to_database = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (close_date != poll->close_date) {
|
if (close_date != poll->close_date) {
|
||||||
poll->close_date = close_date;
|
poll->close_date = close_date;
|
||||||
is_changed = true;
|
|
||||||
|
|
||||||
if (!poll->is_closed) {
|
if (!poll->is_closed) {
|
||||||
|
is_changed = true;
|
||||||
if (close_date != 0) {
|
if (close_date != 0) {
|
||||||
if (close_date <= G()->server_time()) {
|
if (close_date <= G()->server_time()) {
|
||||||
poll->is_closed = true;
|
poll->is_closed = true;
|
||||||
@ -1481,6 +1501,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
|||||||
} else {
|
} else {
|
||||||
close_poll_timeout_.cancel_timeout(poll_id.get());
|
close_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
need_save_to_database = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool is_anonymous = (poll_server->flags_ & telegram_api::poll::PUBLIC_VOTERS_MASK) == 0;
|
bool is_anonymous = (poll_server->flags_ & telegram_api::poll::PUBLIC_VOTERS_MASK) == 0;
|
||||||
@ -1645,6 +1667,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
|||||||
}
|
}
|
||||||
if (is_changed) {
|
if (is_changed) {
|
||||||
notify_on_poll_update(poll_id);
|
notify_on_poll_update(poll_id);
|
||||||
|
}
|
||||||
|
if (is_changed || need_save_to_database) {
|
||||||
save_poll(poll, poll_id);
|
save_poll(poll, poll_id);
|
||||||
}
|
}
|
||||||
if (need_update_poll && (is_changed || (poll->is_closed && being_closed_polls_.erase(poll_id) != 0))) {
|
if (need_update_poll && (is_changed || (poll->is_closed && being_closed_polls_.erase(poll_id) != 0))) {
|
||||||
|
@ -74,6 +74,8 @@ class PollManager final : public Actor {
|
|||||||
|
|
||||||
void stop_local_poll(PollId poll_id);
|
void stop_local_poll(PollId poll_id);
|
||||||
|
|
||||||
|
PollId dup_poll(PollId poll_id);
|
||||||
|
|
||||||
bool has_input_media(PollId poll_id) const;
|
bool has_input_media(PollId poll_id) const;
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputMedia> get_input_media(PollId poll_id) const;
|
tl_object_ptr<telegram_api::InputMedia> get_input_media(PollId poll_id) const;
|
||||||
|
256
td/telegram/SponsoredMessageManager.cpp
Normal file
256
td/telegram/SponsoredMessageManager.cpp
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#include "td/telegram/SponsoredMessageManager.h"
|
||||||
|
|
||||||
|
#include "td/telegram/ChannelId.h"
|
||||||
|
#include "td/telegram/ContactsManager.h"
|
||||||
|
#include "td/telegram/Global.h"
|
||||||
|
#include "td/telegram/MessageContent.h"
|
||||||
|
#include "td/telegram/MessageEntity.h"
|
||||||
|
#include "td/telegram/MessagesManager.h"
|
||||||
|
#include "td/telegram/net/NetQueryCreator.h"
|
||||||
|
#include "td/telegram/Td.h"
|
||||||
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
|
#include "td/utils/algorithm.h"
|
||||||
|
#include "td/utils/buffer.h"
|
||||||
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class GetSponsoredMessagesQuery final : public Td::ResultHandler {
|
||||||
|
Promise<telegram_api::object_ptr<telegram_api::messages_sponsoredMessages>> promise_;
|
||||||
|
ChannelId channel_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetSponsoredMessagesQuery(
|
||||||
|
Promise<telegram_api::object_ptr<telegram_api::messages_sponsoredMessages>> &&promise)
|
||||||
|
: promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(ChannelId channel_id) {
|
||||||
|
channel_id_ = channel_id;
|
||||||
|
auto input_channel = td->contacts_manager_->get_input_channel(channel_id);
|
||||||
|
if (input_channel == nullptr) {
|
||||||
|
return promise_.set_error(Status::Error(3, "Chat info not found"));
|
||||||
|
}
|
||||||
|
send_query(G()->net_query_creator().create(telegram_api::channels_getSponsoredMessages(std::move(input_channel))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::channels_getSponsoredMessages>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(result_ptr.move_as_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetSponsoredMessagesQuery");
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViewSponsoredMessageQuery final : public Td::ResultHandler {
|
||||||
|
Promise<Unit> promise_;
|
||||||
|
ChannelId channel_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ViewSponsoredMessageQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(ChannelId channel_id, const string &message_id) {
|
||||||
|
channel_id_ = channel_id;
|
||||||
|
auto input_channel = td->contacts_manager_->get_input_channel(channel_id);
|
||||||
|
if (input_channel == nullptr) {
|
||||||
|
return promise_.set_error(Status::Error(3, "Chat info not found"));
|
||||||
|
}
|
||||||
|
send_query(G()->net_query_creator().create(
|
||||||
|
telegram_api::channels_viewSponsoredMessage(std::move(input_channel), BufferSlice(message_id))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::channels_viewSponsoredMessage>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
td->contacts_manager_->on_get_channel_error(channel_id_, status, "ViewSponsoredMessageQuery");
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SponsoredMessageManager::SponsoredMessage {
|
||||||
|
string random_id;
|
||||||
|
DialogId sponsor_dialog_id;
|
||||||
|
string start_param;
|
||||||
|
unique_ptr<MessageContent> content;
|
||||||
|
|
||||||
|
SponsoredMessage() = default;
|
||||||
|
SponsoredMessage(string random_id, DialogId sponsor_dialog_id, string start_param, unique_ptr<MessageContent> content)
|
||||||
|
: random_id(std::move(random_id))
|
||||||
|
, sponsor_dialog_id(sponsor_dialog_id)
|
||||||
|
, start_param(std::move(start_param))
|
||||||
|
, content(std::move(content)) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SponsoredMessageManager::DialogSponsoredMessages {
|
||||||
|
vector<Promise<td_api::object_ptr<td_api::sponsoredMessages>>> promises;
|
||||||
|
vector<SponsoredMessage> messages;
|
||||||
|
};
|
||||||
|
|
||||||
|
SponsoredMessageManager::SponsoredMessageManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||||
|
delete_cached_sponsored_messages_timeout_.set_callback(on_delete_cached_sponsored_messages_timeout_callback);
|
||||||
|
delete_cached_sponsored_messages_timeout_.set_callback_data(static_cast<void *>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
SponsoredMessageManager::~SponsoredMessageManager() = default;
|
||||||
|
|
||||||
|
void SponsoredMessageManager::tear_down() {
|
||||||
|
parent_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SponsoredMessageManager::on_delete_cached_sponsored_messages_timeout_callback(void *sponsored_message_manager_ptr,
|
||||||
|
int64 dialog_id_int) {
|
||||||
|
if (G()->close_flag()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sponsored_message_manager = static_cast<SponsoredMessageManager *>(sponsored_message_manager_ptr);
|
||||||
|
send_closure_later(sponsored_message_manager->actor_id(sponsored_message_manager),
|
||||||
|
&SponsoredMessageManager::delete_cached_sponsored_messages, DialogId(dialog_id_int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SponsoredMessageManager::delete_cached_sponsored_messages(DialogId dialog_id) {
|
||||||
|
if (G()->close_flag()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = dialog_sponsored_messages_.find(dialog_id);
|
||||||
|
CHECK(it != dialog_sponsored_messages_.end());
|
||||||
|
CHECK(it->second->promises.empty());
|
||||||
|
dialog_sponsored_messages_.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::sponsoredMessage> SponsoredMessageManager::get_sponsored_message_object(
|
||||||
|
DialogId dialog_id, const SponsoredMessage &sponsored_message) const {
|
||||||
|
return td_api::make_object<td_api::sponsoredMessage>(
|
||||||
|
sponsored_message.random_id, sponsored_message.sponsor_dialog_id.get(), sponsored_message.start_param,
|
||||||
|
get_message_content_object(sponsored_message.content.get(), td_, dialog_id, 0, false, true, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::sponsoredMessages> SponsoredMessageManager::get_sponsored_messages_object(
|
||||||
|
DialogId dialog_id, const DialogSponsoredMessages &sponsored_messages) const {
|
||||||
|
return td_api::make_object<td_api::sponsoredMessages>(
|
||||||
|
transform(sponsored_messages.messages, [this, dialog_id](const SponsoredMessage &sponsored_message) {
|
||||||
|
return get_sponsored_message_object(dialog_id, sponsored_message);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SponsoredMessageManager::get_dialog_sponsored_messages(
|
||||||
|
DialogId dialog_id, Promise<td_api::object_ptr<td_api::sponsoredMessages>> &&promise) {
|
||||||
|
if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_sponsored_messages")) {
|
||||||
|
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||||
|
}
|
||||||
|
if (dialog_id.get_type() != DialogType::Channel ||
|
||||||
|
td_->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) != ContactsManager::ChannelType::Broadcast) {
|
||||||
|
return promise.set_value(td_api::make_object<td_api::sponsoredMessages>());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &messages = dialog_sponsored_messages_[dialog_id];
|
||||||
|
if (messages != nullptr && messages->promises.empty()) {
|
||||||
|
return promise.set_value(get_sponsored_messages_object(dialog_id, *messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messages == nullptr) {
|
||||||
|
messages = make_unique<DialogSponsoredMessages>();
|
||||||
|
}
|
||||||
|
messages->promises.push_back(std::move(promise));
|
||||||
|
if (messages->promises.size() == 1) {
|
||||||
|
auto query_promise = PromiseCreator::lambda(
|
||||||
|
[actor_id = actor_id(this),
|
||||||
|
dialog_id](Result<telegram_api::object_ptr<telegram_api::messages_sponsoredMessages>> &&result) mutable {
|
||||||
|
send_closure(actor_id, &SponsoredMessageManager::on_get_dialog_sponsored_messages, dialog_id,
|
||||||
|
std::move(result));
|
||||||
|
});
|
||||||
|
td_->create_handler<GetSponsoredMessagesQuery>(std::move(query_promise))->send(dialog_id.get_channel_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SponsoredMessageManager::on_get_dialog_sponsored_messages(
|
||||||
|
DialogId dialog_id, Result<telegram_api::object_ptr<telegram_api::messages_sponsoredMessages>> &&result) {
|
||||||
|
auto &messages = dialog_sponsored_messages_[dialog_id];
|
||||||
|
CHECK(messages != nullptr);
|
||||||
|
auto promises = std::move(messages->promises);
|
||||||
|
reset_to_empty(messages->promises);
|
||||||
|
|
||||||
|
if (result.is_ok() && G()->close_flag()) {
|
||||||
|
result = Status::Error(500, "Request aborted");
|
||||||
|
}
|
||||||
|
if (result.is_error()) {
|
||||||
|
dialog_sponsored_messages_.erase(dialog_id);
|
||||||
|
for (auto &promise : promises) {
|
||||||
|
promise.set_error(result.error().clone());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sponsored_messages = result.move_as_ok();
|
||||||
|
|
||||||
|
td_->contacts_manager_->on_get_users(std::move(sponsored_messages->users_), "on_get_dialog_sponsored_messages");
|
||||||
|
td_->contacts_manager_->on_get_chats(std::move(sponsored_messages->chats_), "on_get_dialog_sponsored_messages");
|
||||||
|
|
||||||
|
reset_to_empty(messages->messages);
|
||||||
|
for (auto &sponsored_message : sponsored_messages->messages_) {
|
||||||
|
DialogId sponsor_dialog_id(sponsored_message->from_id_);
|
||||||
|
if (!sponsor_dialog_id.is_valid() || !td_->messages_manager_->have_dialog_info_force(sponsor_dialog_id)) {
|
||||||
|
LOG(ERROR) << "Receive unknown sponsor " << sponsor_dialog_id;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
td_->messages_manager_->force_create_dialog(sponsor_dialog_id, "on_get_dialog_sponsored_messages");
|
||||||
|
auto message_text = get_message_text(td_->contacts_manager_.get(), std::move(sponsored_message->message_),
|
||||||
|
std::move(sponsored_message->entities_), true, true, 0, false,
|
||||||
|
"on_get_dialog_sponsored_messages");
|
||||||
|
int32 ttl = 0;
|
||||||
|
auto content = get_message_content(td_, std::move(message_text), nullptr, sponsor_dialog_id, true, UserId(), &ttl);
|
||||||
|
if (ttl != 0) {
|
||||||
|
LOG(ERROR) << "Receive sponsored message with TTL " << ttl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
messages->messages.emplace_back(sponsored_message->random_id_.as_slice().str(), sponsor_dialog_id,
|
||||||
|
std::move(sponsored_message->start_param_), std::move(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &promise : promises) {
|
||||||
|
promise.set_value(get_sponsored_messages_object(dialog_id, *messages));
|
||||||
|
}
|
||||||
|
delete_cached_sponsored_messages_timeout_.set_timeout_in(dialog_id.get(), 300.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SponsoredMessageManager::view_sponsored_message(DialogId dialog_id, const string &message_id,
|
||||||
|
Promise<Unit> &&promise) {
|
||||||
|
if (!td_->messages_manager_->have_dialog_force(dialog_id, "view_sponsored_message")) {
|
||||||
|
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||||
|
}
|
||||||
|
if (dialog_id.get_type() != DialogType::Channel ||
|
||||||
|
td_->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) != ContactsManager::ChannelType::Broadcast ||
|
||||||
|
message_id.empty()) {
|
||||||
|
return promise.set_error(Status::Error(400, "Message not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->create_handler<ViewSponsoredMessageQuery>(std::move(promise))->send(dialog_id.get_channel_id(), message_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
68
td/telegram/SponsoredMessageManager.h
Normal file
68
td/telegram/SponsoredMessageManager.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/DialogId.h"
|
||||||
|
#include "td/telegram/td_api.h"
|
||||||
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
|
#include "td/actor/actor.h"
|
||||||
|
#include "td/actor/PromiseFuture.h"
|
||||||
|
#include "td/actor/Timeout.h"
|
||||||
|
|
||||||
|
#include "td/utils/common.h"
|
||||||
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class Td;
|
||||||
|
|
||||||
|
class SponsoredMessageManager final : public Actor {
|
||||||
|
public:
|
||||||
|
SponsoredMessageManager(Td *td, ActorShared<> parent);
|
||||||
|
SponsoredMessageManager(const SponsoredMessageManager &) = delete;
|
||||||
|
SponsoredMessageManager &operator=(const SponsoredMessageManager &) = delete;
|
||||||
|
SponsoredMessageManager(SponsoredMessageManager &&) = delete;
|
||||||
|
SponsoredMessageManager &operator=(SponsoredMessageManager &&) = delete;
|
||||||
|
~SponsoredMessageManager() final;
|
||||||
|
|
||||||
|
void get_dialog_sponsored_messages(DialogId dialog_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::sponsoredMessages>> &&promise);
|
||||||
|
|
||||||
|
void view_sponsored_message(DialogId dialog_id, const string &message_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct SponsoredMessage;
|
||||||
|
struct DialogSponsoredMessages;
|
||||||
|
|
||||||
|
void tear_down() final;
|
||||||
|
|
||||||
|
static void on_delete_cached_sponsored_messages_timeout_callback(void *sponsored_message_manager_ptr,
|
||||||
|
int64 dialog_id_int);
|
||||||
|
|
||||||
|
void delete_cached_sponsored_messages(DialogId dialog_id);
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::sponsoredMessage> get_sponsored_message_object(
|
||||||
|
DialogId dialog_id, const SponsoredMessage &sponsored_message) const;
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::sponsoredMessages> get_sponsored_messages_object(
|
||||||
|
DialogId dialog_id, const DialogSponsoredMessages &sponsored_messages) const;
|
||||||
|
|
||||||
|
void on_get_dialog_sponsored_messages(
|
||||||
|
DialogId dialog_id, Result<telegram_api::object_ptr<telegram_api::messages_sponsoredMessages>> &&result);
|
||||||
|
|
||||||
|
std::unordered_map<DialogId, unique_ptr<DialogSponsoredMessages>, DialogIdHash> dialog_sponsored_messages_;
|
||||||
|
|
||||||
|
MultiTimeout delete_cached_sponsored_messages_timeout_{"DeleteCachedSponsoredMessagesTimeout"};
|
||||||
|
|
||||||
|
Td *td_;
|
||||||
|
ActorShared<> parent_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace td
|
@ -1,145 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
#include "td/telegram/SponsoredMessages.h"
|
|
||||||
|
|
||||||
#include "td/telegram/ChannelId.h"
|
|
||||||
#include "td/telegram/ContactsManager.h"
|
|
||||||
#include "td/telegram/Global.h"
|
|
||||||
#include "td/telegram/MessageContent.h"
|
|
||||||
#include "td/telegram/MessageEntity.h"
|
|
||||||
#include "td/telegram/MessagesManager.h"
|
|
||||||
#include "td/telegram/net/NetQueryCreator.h"
|
|
||||||
#include "td/telegram/Td.h"
|
|
||||||
#include "td/telegram/telegram_api.h"
|
|
||||||
|
|
||||||
#include "td/utils/buffer.h"
|
|
||||||
#include "td/utils/logging.h"
|
|
||||||
#include "td/utils/Status.h"
|
|
||||||
|
|
||||||
namespace td {
|
|
||||||
|
|
||||||
class GetSponsoredMessagesQuery final : public Td::ResultHandler {
|
|
||||||
Promise<td_api::object_ptr<td_api::sponsoredMessages>> promise_;
|
|
||||||
ChannelId channel_id_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GetSponsoredMessagesQuery(Promise<td_api::object_ptr<td_api::sponsoredMessages>> &&promise)
|
|
||||||
: promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(ChannelId channel_id) {
|
|
||||||
channel_id_ = channel_id;
|
|
||||||
auto input_channel = td->contacts_manager_->get_input_channel(channel_id);
|
|
||||||
if (input_channel == nullptr) {
|
|
||||||
return promise_.set_error(Status::Error(3, "Chat info not found"));
|
|
||||||
}
|
|
||||||
send_query(G()->net_query_creator().create(telegram_api::channels_getSponsoredMessages(std::move(input_channel))));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::channels_getSponsoredMessages>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(id, result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto sponsored_messages = result_ptr.move_as_ok();
|
|
||||||
|
|
||||||
td->contacts_manager_->on_get_users(std::move(sponsored_messages->users_), "GetSponsoredMessagesQuery");
|
|
||||||
td->contacts_manager_->on_get_chats(std::move(sponsored_messages->chats_), "GetSponsoredMessagesQuery");
|
|
||||||
|
|
||||||
vector<td_api::object_ptr<td_api::sponsoredMessage>> messages;
|
|
||||||
for (auto &sponsored_message : sponsored_messages->messages_) {
|
|
||||||
DialogId dialog_id(sponsored_message->from_id_);
|
|
||||||
if (!dialog_id.is_valid() || !td->messages_manager_->have_dialog_info_force(dialog_id)) {
|
|
||||||
LOG(ERROR) << "Receive unknown sponsor " << dialog_id;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
td->messages_manager_->force_create_dialog(dialog_id, "GetSponsoredMessagesQuery");
|
|
||||||
auto message_text =
|
|
||||||
get_message_text(td->contacts_manager_.get(), std::move(sponsored_message->message_),
|
|
||||||
std::move(sponsored_message->entities_), true, true, 0, false, "GetSponsoredMessagesQuery");
|
|
||||||
int32 ttl = 0;
|
|
||||||
auto content = get_message_content(td, std::move(message_text), nullptr, dialog_id, true, UserId(), &ttl);
|
|
||||||
if (ttl != 0) {
|
|
||||||
LOG(ERROR) << "Receive sponsored message with TTL " << ttl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
messages.push_back(td_api::make_object<td_api::sponsoredMessage>(
|
|
||||||
sponsored_message->random_id_.as_slice().str(), dialog_id.get(), sponsored_message->start_param_,
|
|
||||||
get_message_content_object(content.get(), td, DialogId(channel_id_), 0, false, true, -1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
promise_.set_value(td_api::make_object<td_api::sponsoredMessages>(std::move(messages)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) final {
|
|
||||||
td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetSponsoredMessagesQuery");
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ViewSponsoredMessageQuery final : public Td::ResultHandler {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
ChannelId channel_id_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ViewSponsoredMessageQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(ChannelId channel_id, const string &message_id) {
|
|
||||||
channel_id_ = channel_id;
|
|
||||||
auto input_channel = td->contacts_manager_->get_input_channel(channel_id);
|
|
||||||
if (input_channel == nullptr) {
|
|
||||||
return promise_.set_error(Status::Error(3, "Chat info not found"));
|
|
||||||
}
|
|
||||||
send_query(G()->net_query_creator().create(
|
|
||||||
telegram_api::channels_viewSponsoredMessage(std::move(input_channel), BufferSlice(message_id))));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::channels_viewSponsoredMessage>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(id, result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
promise_.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) final {
|
|
||||||
td->contacts_manager_->on_get_channel_error(channel_id_, status, "ViewSponsoredMessageQuery");
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void get_dialog_sponsored_messages(Td *td, DialogId dialog_id,
|
|
||||||
Promise<td_api::object_ptr<td_api::sponsoredMessages>> &&promise) {
|
|
||||||
if (!td->messages_manager_->have_dialog_force(dialog_id, "get_sponsored_messages")) {
|
|
||||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
|
||||||
}
|
|
||||||
if (dialog_id.get_type() != DialogType::Channel ||
|
|
||||||
td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) != ContactsManager::ChannelType::Broadcast) {
|
|
||||||
return promise.set_value(td_api::make_object<td_api::sponsoredMessages>());
|
|
||||||
}
|
|
||||||
|
|
||||||
td->create_handler<GetSponsoredMessagesQuery>(std::move(promise))->send(dialog_id.get_channel_id());
|
|
||||||
}
|
|
||||||
|
|
||||||
void view_sponsored_message(Td *td, DialogId dialog_id, const string &message_id, Promise<Unit> &&promise) {
|
|
||||||
if (!td->messages_manager_->have_dialog_force(dialog_id, "view_sponsored_message")) {
|
|
||||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
|
||||||
}
|
|
||||||
if (dialog_id.get_type() != DialogType::Channel ||
|
|
||||||
td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) != ContactsManager::ChannelType::Broadcast ||
|
|
||||||
message_id.empty()) {
|
|
||||||
return promise.set_error(Status::Error(400, "Message not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
td->create_handler<ViewSponsoredMessageQuery>(std::move(promise))->send(dialog_id.get_channel_id(), message_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace td
|
|
@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "td/telegram/DialogId.h"
|
|
||||||
#include "td/telegram/td_api.h"
|
|
||||||
|
|
||||||
#include "td/actor/PromiseFuture.h"
|
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
|
||||||
|
|
||||||
namespace td {
|
|
||||||
|
|
||||||
class Td;
|
|
||||||
|
|
||||||
void get_dialog_sponsored_messages(Td *td, DialogId dialog_id,
|
|
||||||
Promise<td_api::object_ptr<td_api::sponsoredMessages>> &&promise);
|
|
||||||
|
|
||||||
void view_sponsored_message(Td *td, DialogId dialog_id, const string &message_id, Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
} // namespace td
|
|
@ -4071,8 +4071,8 @@ void StickersManager::on_get_archived_sticker_sets(
|
|||||||
LOG(ERROR) << "Receive " << total_count << " as total count of archived sticker sets";
|
LOG(ERROR) << "Receive " << total_count << " as total count of archived sticker sets";
|
||||||
}
|
}
|
||||||
|
|
||||||
// if 0 sticker sets are received, then set offset_sticker_set_id was found and there is no stickers after it
|
// if 0 sticker sets are received, then set offset_sticker_set_id was found and there are no stickers after it
|
||||||
// or it wasn't found and there is no archived sets at all
|
// or it wasn't found and there are no archived sets at all
|
||||||
bool is_last =
|
bool is_last =
|
||||||
sticker_sets.empty() && (!offset_sticker_set_id.is_valid() ||
|
sticker_sets.empty() && (!offset_sticker_set_id.is_valid() ||
|
||||||
(!sticker_set_ids.empty() && offset_sticker_set_id == sticker_set_ids.back()));
|
(!sticker_set_ids.empty() && offset_sticker_set_id == sticker_set_ids.back()));
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "td/telegram/files/FileType.h"
|
#include "td/telegram/files/FileType.h"
|
||||||
#include "td/telegram/FolderId.h"
|
#include "td/telegram/FolderId.h"
|
||||||
#include "td/telegram/FullMessageId.h"
|
#include "td/telegram/FullMessageId.h"
|
||||||
|
#include "td/telegram/GameManager.h"
|
||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
#include "td/telegram/GroupCallId.h"
|
#include "td/telegram/GroupCallId.h"
|
||||||
#include "td/telegram/GroupCallManager.h"
|
#include "td/telegram/GroupCallManager.h"
|
||||||
@ -90,7 +91,7 @@
|
|||||||
#include "td/telegram/SecretChatsManager.h"
|
#include "td/telegram/SecretChatsManager.h"
|
||||||
#include "td/telegram/SecureManager.h"
|
#include "td/telegram/SecureManager.h"
|
||||||
#include "td/telegram/SecureValue.h"
|
#include "td/telegram/SecureValue.h"
|
||||||
#include "td/telegram/SponsoredMessages.h"
|
#include "td/telegram/SponsoredMessageManager.h"
|
||||||
#include "td/telegram/StateManager.h"
|
#include "td/telegram/StateManager.h"
|
||||||
#include "td/telegram/StickerSetId.h"
|
#include "td/telegram/StickerSetId.h"
|
||||||
#include "td/telegram/StickersManager.h"
|
#include "td/telegram/StickersManager.h"
|
||||||
@ -1268,82 +1269,6 @@ class EditMessageReplyMarkupRequest final : public RequestOnceActor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SetGameScoreRequest final : public RequestOnceActor {
|
|
||||||
FullMessageId full_message_id_;
|
|
||||||
bool edit_message_;
|
|
||||||
UserId user_id_;
|
|
||||||
int32 score_;
|
|
||||||
bool force_;
|
|
||||||
|
|
||||||
void do_run(Promise<Unit> &&promise) final {
|
|
||||||
td->messages_manager_->set_game_score(full_message_id_, edit_message_, user_id_, score_, force_,
|
|
||||||
std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_send_result() final {
|
|
||||||
send_result(td->messages_manager_->get_message_object(full_message_id_));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
SetGameScoreRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id, bool edit_message,
|
|
||||||
int32 user_id, int32 score, bool force)
|
|
||||||
: RequestOnceActor(std::move(td), request_id)
|
|
||||||
, full_message_id_(DialogId(dialog_id), MessageId(message_id))
|
|
||||||
, edit_message_(edit_message)
|
|
||||||
, user_id_(user_id)
|
|
||||||
, score_(score)
|
|
||||||
, force_(force) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetGameHighScoresRequest final : public RequestOnceActor {
|
|
||||||
FullMessageId full_message_id_;
|
|
||||||
UserId user_id_;
|
|
||||||
|
|
||||||
int64 random_id_;
|
|
||||||
|
|
||||||
void do_run(Promise<Unit> &&promise) final {
|
|
||||||
random_id_ = td->messages_manager_->get_game_high_scores(full_message_id_, user_id_, std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_send_result() final {
|
|
||||||
CHECK(random_id_ != 0);
|
|
||||||
send_result(td->messages_manager_->get_game_high_scores_object(random_id_));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
GetGameHighScoresRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id, int32 user_id)
|
|
||||||
: RequestOnceActor(std::move(td), request_id)
|
|
||||||
, full_message_id_(DialogId(dialog_id), MessageId(message_id))
|
|
||||||
, user_id_(user_id)
|
|
||||||
, random_id_(0) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetInlineGameHighScoresRequest final : public RequestOnceActor {
|
|
||||||
string inline_message_id_;
|
|
||||||
UserId user_id_;
|
|
||||||
|
|
||||||
int64 random_id_;
|
|
||||||
|
|
||||||
void do_run(Promise<Unit> &&promise) final {
|
|
||||||
random_id_ = td->messages_manager_->get_inline_game_high_scores(inline_message_id_, user_id_, std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_send_result() final {
|
|
||||||
CHECK(random_id_ != 0);
|
|
||||||
send_result(td->messages_manager_->get_game_high_scores_object(random_id_));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
GetInlineGameHighScoresRequest(ActorShared<Td> td, uint64 request_id, string inline_message_id, int32 user_id)
|
|
||||||
: RequestOnceActor(std::move(td), request_id)
|
|
||||||
, inline_message_id_(std::move(inline_message_id))
|
|
||||||
, user_id_(user_id)
|
|
||||||
, random_id_(0) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetChatHistoryRequest final : public RequestActor<> {
|
class GetChatHistoryRequest final : public RequestActor<> {
|
||||||
DialogId dialog_id_;
|
DialogId dialog_id_;
|
||||||
MessageId from_message_id_;
|
MessageId from_message_id_;
|
||||||
@ -3706,6 +3631,8 @@ void Td::dec_actor_refcnt() {
|
|||||||
LOG(DEBUG) << "FileManager was cleared" << timer;
|
LOG(DEBUG) << "FileManager was cleared" << timer;
|
||||||
file_reference_manager_.reset();
|
file_reference_manager_.reset();
|
||||||
LOG(DEBUG) << "FileReferenceManager was cleared" << timer;
|
LOG(DEBUG) << "FileReferenceManager was cleared" << timer;
|
||||||
|
game_manager_.reset();
|
||||||
|
LOG(DEBUG) << "GameManager was cleared" << timer;
|
||||||
group_call_manager_.reset();
|
group_call_manager_.reset();
|
||||||
LOG(DEBUG) << "GroupCallManager was cleared" << timer;
|
LOG(DEBUG) << "GroupCallManager was cleared" << timer;
|
||||||
inline_queries_manager_.reset();
|
inline_queries_manager_.reset();
|
||||||
@ -3718,6 +3645,8 @@ void Td::dec_actor_refcnt() {
|
|||||||
LOG(DEBUG) << "NotificationManager was cleared" << timer;
|
LOG(DEBUG) << "NotificationManager was cleared" << timer;
|
||||||
poll_manager_.reset();
|
poll_manager_.reset();
|
||||||
LOG(DEBUG) << "PollManager was cleared" << timer;
|
LOG(DEBUG) << "PollManager was cleared" << timer;
|
||||||
|
sponsored_message_manager_.reset();
|
||||||
|
LOG(DEBUG) << "SponsoredMessageManager was cleared" << timer;
|
||||||
stickers_manager_.reset();
|
stickers_manager_.reset();
|
||||||
LOG(DEBUG) << "StickersManager was cleared" << timer;
|
LOG(DEBUG) << "StickersManager was cleared" << timer;
|
||||||
memory_manager_.reset();
|
memory_manager_.reset();
|
||||||
@ -3909,6 +3838,8 @@ void Td::clear() {
|
|||||||
LOG(DEBUG) << "FileManager actor was cleared" << timer;
|
LOG(DEBUG) << "FileManager actor was cleared" << timer;
|
||||||
file_reference_manager_actor_.reset();
|
file_reference_manager_actor_.reset();
|
||||||
LOG(DEBUG) << "FileReferenceManager actor was cleared" << timer;
|
LOG(DEBUG) << "FileReferenceManager actor was cleared" << timer;
|
||||||
|
game_manager_actor_.reset();
|
||||||
|
LOG(DEBUG) << "GameManager actor was cleared" << timer;
|
||||||
group_call_manager_actor_.reset();
|
group_call_manager_actor_.reset();
|
||||||
LOG(DEBUG) << "GroupCallManager actor was cleared" << timer;
|
LOG(DEBUG) << "GroupCallManager actor was cleared" << timer;
|
||||||
inline_queries_manager_actor_.reset();
|
inline_queries_manager_actor_.reset();
|
||||||
@ -3921,6 +3852,8 @@ void Td::clear() {
|
|||||||
LOG(DEBUG) << "NotificationManager actor was cleared" << timer;
|
LOG(DEBUG) << "NotificationManager actor was cleared" << timer;
|
||||||
poll_manager_actor_.reset();
|
poll_manager_actor_.reset();
|
||||||
LOG(DEBUG) << "PollManager actor was cleared" << timer;
|
LOG(DEBUG) << "PollManager actor was cleared" << timer;
|
||||||
|
sponsored_message_manager_actor_.reset();
|
||||||
|
LOG(DEBUG) << "SponsoredMessageManager actor was cleared" << timer;
|
||||||
stickers_manager_actor_.reset();
|
stickers_manager_actor_.reset();
|
||||||
LOG(DEBUG) << "StickersManager actor was cleared" << timer;
|
LOG(DEBUG) << "StickersManager actor was cleared" << timer;
|
||||||
memory_manager_actor_.reset();
|
memory_manager_actor_.reset();
|
||||||
@ -4371,6 +4304,9 @@ void Td::init_managers() {
|
|||||||
G()->set_contacts_manager(contacts_manager_actor_.get());
|
G()->set_contacts_manager(contacts_manager_actor_.get());
|
||||||
country_info_manager_ = make_unique<CountryInfoManager>(this, create_reference());
|
country_info_manager_ = make_unique<CountryInfoManager>(this, create_reference());
|
||||||
country_info_manager_actor_ = register_actor("CountryInfoManager", country_info_manager_.get());
|
country_info_manager_actor_ = register_actor("CountryInfoManager", country_info_manager_.get());
|
||||||
|
game_manager_ = make_unique<GameManager>(this, create_reference());
|
||||||
|
game_manager_actor_ = register_actor("GameManager", game_manager_.get());
|
||||||
|
G()->set_game_manager(game_manager_actor_.get());
|
||||||
group_call_manager_ = make_unique<GroupCallManager>(this, create_reference());
|
group_call_manager_ = make_unique<GroupCallManager>(this, create_reference());
|
||||||
group_call_manager_actor_ = register_actor("GroupCallManager", group_call_manager_.get());
|
group_call_manager_actor_ = register_actor("GroupCallManager", group_call_manager_.get());
|
||||||
G()->set_group_call_manager(group_call_manager_actor_.get());
|
G()->set_group_call_manager(group_call_manager_actor_.get());
|
||||||
@ -4387,6 +4323,9 @@ void Td::init_managers() {
|
|||||||
poll_manager_ = make_unique<PollManager>(this, create_reference());
|
poll_manager_ = make_unique<PollManager>(this, create_reference());
|
||||||
poll_manager_actor_ = register_actor("PollManager", poll_manager_.get());
|
poll_manager_actor_ = register_actor("PollManager", poll_manager_.get());
|
||||||
G()->set_notification_manager(notification_manager_actor_.get());
|
G()->set_notification_manager(notification_manager_actor_.get());
|
||||||
|
sponsored_message_manager_ = make_unique<SponsoredMessageManager>(this, create_reference());
|
||||||
|
sponsored_message_manager_actor_ = register_actor("SponsoredMessageManager", sponsored_message_manager_.get());
|
||||||
|
G()->set_sponsored_message_manager(sponsored_message_manager_actor_.get());
|
||||||
stickers_manager_ = make_unique<StickersManager>(this, create_reference());
|
stickers_manager_ = make_unique<StickersManager>(this, create_reference());
|
||||||
stickers_manager_actor_ = register_actor("StickersManager", stickers_manager_.get());
|
stickers_manager_actor_ = register_actor("StickersManager", stickers_manager_.get());
|
||||||
G()->set_stickers_manager(stickers_manager_actor_.get());
|
G()->set_stickers_manager(stickers_manager_actor_.get());
|
||||||
@ -5097,13 +5036,14 @@ void Td::on_request(uint64 id, const td_api::getMessages &request) {
|
|||||||
void Td::on_request(uint64 id, const td_api::getChatSponsoredMessages &request) {
|
void Td::on_request(uint64 id, const td_api::getChatSponsoredMessages &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
get_dialog_sponsored_messages(this, DialogId(request.chat_id_), std::move(promise));
|
sponsored_message_manager_->get_dialog_sponsored_messages(DialogId(request.chat_id_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::viewSponsoredMessage &request) {
|
void Td::on_request(uint64 id, const td_api::viewSponsoredMessage &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
view_sponsored_message(this, DialogId(request.chat_id_), request.message_id_, std::move(promise));
|
sponsored_message_manager_->view_sponsored_message(DialogId(request.chat_id_), request.message_id_,
|
||||||
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getMessageThread &request) {
|
void Td::on_request(uint64 id, const td_api::getMessageThread &request) {
|
||||||
@ -5831,28 +5771,31 @@ void Td::on_request(uint64 id, td_api::editMessageSchedulingState &request) {
|
|||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::setGameScore &request) {
|
void Td::on_request(uint64 id, td_api::setGameScore &request) {
|
||||||
CHECK_IS_BOT();
|
CHECK_IS_BOT();
|
||||||
CREATE_REQUEST(SetGameScoreRequest, request.chat_id_, request.message_id_, request.edit_message_, request.user_id_,
|
CREATE_REQUEST_PROMISE();
|
||||||
request.score_, request.force_);
|
game_manager_->set_game_score({DialogId(request.chat_id_), MessageId(request.message_id_)}, request.edit_message_,
|
||||||
|
UserId(request.user_id_), request.score_, request.force_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::setInlineGameScore &request) {
|
void Td::on_request(uint64 id, td_api::setInlineGameScore &request) {
|
||||||
CHECK_IS_BOT();
|
CHECK_IS_BOT();
|
||||||
CLEAN_INPUT_STRING(request.inline_message_id_);
|
CLEAN_INPUT_STRING(request.inline_message_id_);
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
messages_manager_->set_inline_game_score(std::move(request.inline_message_id_), request.edit_message_,
|
game_manager_->set_inline_game_score(std::move(request.inline_message_id_), request.edit_message_,
|
||||||
UserId(request.user_id_), request.score_, request.force_,
|
UserId(request.user_id_), request.score_, request.force_, std::move(promise));
|
||||||
std::move(promise));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getGameHighScores &request) {
|
void Td::on_request(uint64 id, td_api::getGameHighScores &request) {
|
||||||
CHECK_IS_BOT();
|
CHECK_IS_BOT();
|
||||||
CREATE_REQUEST(GetGameHighScoresRequest, request.chat_id_, request.message_id_, request.user_id_);
|
CREATE_REQUEST_PROMISE();
|
||||||
|
game_manager_->get_game_high_scores({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||||
|
UserId(request.user_id_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getInlineGameHighScores &request) {
|
void Td::on_request(uint64 id, td_api::getInlineGameHighScores &request) {
|
||||||
CHECK_IS_BOT();
|
CHECK_IS_BOT();
|
||||||
CLEAN_INPUT_STRING(request.inline_message_id_);
|
CLEAN_INPUT_STRING(request.inline_message_id_);
|
||||||
CREATE_REQUEST(GetInlineGameHighScoresRequest, std::move(request.inline_message_id_), request.user_id_);
|
CREATE_REQUEST_PROMISE();
|
||||||
|
game_manager_->get_inline_game_high_scores(request.inline_message_id_, UserId(request.user_id_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::deleteChatReplyMarkup &request) {
|
void Td::on_request(uint64 id, const td_api::deleteChatReplyMarkup &request) {
|
||||||
|
@ -57,6 +57,7 @@ class DeviceTokenManager;
|
|||||||
class DocumentsManager;
|
class DocumentsManager;
|
||||||
class FileManager;
|
class FileManager;
|
||||||
class FileReferenceManager;
|
class FileReferenceManager;
|
||||||
|
class GameManager;
|
||||||
class GroupCallManager;
|
class GroupCallManager;
|
||||||
class InlineQueriesManager;
|
class InlineQueriesManager;
|
||||||
class HashtagHints;
|
class HashtagHints;
|
||||||
@ -71,6 +72,7 @@ class PollManager;
|
|||||||
class PrivacyManager;
|
class PrivacyManager;
|
||||||
class SecureManager;
|
class SecureManager;
|
||||||
class SecretChatsManager;
|
class SecretChatsManager;
|
||||||
|
class SponsoredMessageManager;
|
||||||
class StickersManager;
|
class StickersManager;
|
||||||
class StorageManager;
|
class StorageManager;
|
||||||
class MemoryManager;
|
class MemoryManager;
|
||||||
@ -168,6 +170,8 @@ class Td final : public NetQueryCallback {
|
|||||||
ActorOwn<FileManager> file_manager_actor_;
|
ActorOwn<FileManager> file_manager_actor_;
|
||||||
unique_ptr<FileReferenceManager> file_reference_manager_;
|
unique_ptr<FileReferenceManager> file_reference_manager_;
|
||||||
ActorOwn<FileReferenceManager> file_reference_manager_actor_;
|
ActorOwn<FileReferenceManager> file_reference_manager_actor_;
|
||||||
|
unique_ptr<GameManager> game_manager_;
|
||||||
|
ActorOwn<GameManager> game_manager_actor_;
|
||||||
unique_ptr<GroupCallManager> group_call_manager_;
|
unique_ptr<GroupCallManager> group_call_manager_;
|
||||||
ActorOwn<GroupCallManager> group_call_manager_actor_;
|
ActorOwn<GroupCallManager> group_call_manager_actor_;
|
||||||
unique_ptr<InlineQueriesManager> inline_queries_manager_;
|
unique_ptr<InlineQueriesManager> inline_queries_manager_;
|
||||||
@ -180,6 +184,8 @@ class Td final : public NetQueryCallback {
|
|||||||
ActorOwn<NotificationManager> notification_manager_actor_;
|
ActorOwn<NotificationManager> notification_manager_actor_;
|
||||||
unique_ptr<PollManager> poll_manager_;
|
unique_ptr<PollManager> poll_manager_;
|
||||||
ActorOwn<PollManager> poll_manager_actor_;
|
ActorOwn<PollManager> poll_manager_actor_;
|
||||||
|
unique_ptr<SponsoredMessageManager> sponsored_message_manager_;
|
||||||
|
ActorOwn<SponsoredMessageManager> sponsored_message_manager_actor_;
|
||||||
unique_ptr<StickersManager> stickers_manager_;
|
unique_ptr<StickersManager> stickers_manager_;
|
||||||
ActorOwn<StickersManager> stickers_manager_actor_;
|
ActorOwn<StickersManager> stickers_manager_actor_;
|
||||||
unique_ptr<ThemeManager> theme_manager_;
|
unique_ptr<ThemeManager> theme_manager_;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "td/utils/algorithm.h"
|
#include "td/utils/algorithm.h"
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/Time.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ class GetChatThemesQuery final : public Td::ResultHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ThemeManager::ThemeManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
ThemeManager::ThemeManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||||
|
chat_themes_.next_reload_time = Time::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeManager::tear_down() {
|
void ThemeManager::tear_down() {
|
||||||
@ -51,7 +53,16 @@ void ThemeManager::tear_down() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThemeManager::get_chat_themes(Promise<td_api::object_ptr<td_api::chatThemes>> &&promise) {
|
void ThemeManager::get_chat_themes(Promise<td_api::object_ptr<td_api::chatThemes>> &&promise) {
|
||||||
pending_get_chat_themes_queries_.push_back(std::move(promise));
|
if (Time::now() < chat_themes_.next_reload_time) {
|
||||||
|
return promise.set_value(get_chat_themes_object());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chat_themes_.themes.empty()) {
|
||||||
|
promise.set_value(get_chat_themes_object());
|
||||||
|
pending_get_chat_themes_queries_.push_back(Promise<td_api::object_ptr<td_api::chatThemes>>());
|
||||||
|
} else {
|
||||||
|
pending_get_chat_themes_queries_.push_back(std::move(promise));
|
||||||
|
}
|
||||||
if (pending_get_chat_themes_queries_.size() == 1) {
|
if (pending_get_chat_themes_queries_.size() == 1) {
|
||||||
auto request_promise = PromiseCreator::lambda(
|
auto request_promise = PromiseCreator::lambda(
|
||||||
[actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::account_ChatThemes>> result) {
|
[actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::account_ChatThemes>> result) {
|
||||||
@ -106,34 +117,33 @@ void ThemeManager::on_get_chat_themes(Result<telegram_api::object_ptr<telegram_a
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chat_themes_.next_reload_time = Time::now() + THEME_CACHE_TIME;
|
||||||
|
|
||||||
auto chat_themes_ptr = result.move_as_ok();
|
auto chat_themes_ptr = result.move_as_ok();
|
||||||
LOG(DEBUG) << "Receive " << to_string(chat_themes_ptr);
|
LOG(DEBUG) << "Receive " << to_string(chat_themes_ptr);
|
||||||
if (chat_themes_ptr->get_id() == telegram_api::account_chatThemesNotModified::ID) {
|
if (chat_themes_ptr->get_id() != telegram_api::account_chatThemesNotModified::ID) {
|
||||||
for (auto &promise : promises) {
|
CHECK(chat_themes_ptr->get_id() == telegram_api::account_chatThemes::ID);
|
||||||
promise.set_value(get_chat_themes_object());
|
auto chat_themes = telegram_api::move_object_as<telegram_api::account_chatThemes>(chat_themes_ptr);
|
||||||
}
|
chat_themes_.hash = chat_themes->hash_;
|
||||||
return;
|
chat_themes_.themes.clear();
|
||||||
}
|
for (auto &chat_theme : chat_themes->themes_) {
|
||||||
|
if (chat_theme->emoticon_.empty()) {
|
||||||
|
LOG(ERROR) << "Receive " << to_string(chat_theme);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto chat_themes = telegram_api::move_object_as<telegram_api::account_chatThemes>(chat_themes_ptr);
|
ChatTheme theme;
|
||||||
LOG(INFO) << "Receive " << to_string(chat_themes);
|
theme.emoji = std::move(chat_theme->emoticon_);
|
||||||
chat_themes_.hash = chat_themes->hash_;
|
theme.light_theme = get_chat_theme_settings(std::move(chat_theme->theme_->settings_));
|
||||||
chat_themes_.themes.clear();
|
theme.dark_theme = get_chat_theme_settings(std::move(chat_theme->dark_theme_->settings_));
|
||||||
for (auto &chat_theme : chat_themes->themes_) {
|
chat_themes_.themes.push_back(std::move(theme));
|
||||||
if (chat_theme->emoticon_.empty()) {
|
|
||||||
LOG(ERROR) << "Receive " << to_string(chat_theme);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatTheme theme;
|
|
||||||
theme.emoji = std::move(chat_theme->emoticon_);
|
|
||||||
theme.light_theme = get_chat_theme_settings(std::move(chat_theme->theme_->settings_));
|
|
||||||
theme.dark_theme = get_chat_theme_settings(std::move(chat_theme->dark_theme_->settings_));
|
|
||||||
chat_themes_.themes.push_back(std::move(theme));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &promise : promises) {
|
for (auto &promise : promises) {
|
||||||
promise.set_value(get_chat_themes_object());
|
if (promise) {
|
||||||
|
promise.set_value(get_chat_themes_object());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@ class ThemeManager final : public Actor {
|
|||||||
private:
|
private:
|
||||||
enum class BaseTheme : int32 { Classic, Day, Night, Tinted, Arctic };
|
enum class BaseTheme : int32 { Classic, Day, Night, Tinted, Arctic };
|
||||||
|
|
||||||
|
static constexpr int32 THEME_CACHE_TIME = 3600;
|
||||||
|
|
||||||
struct ThemeSettings {
|
struct ThemeSettings {
|
||||||
int32 accent_color = 0;
|
int32 accent_color = 0;
|
||||||
BackgroundId background_id;
|
BackgroundId background_id;
|
||||||
@ -47,6 +49,7 @@ class ThemeManager final : public Actor {
|
|||||||
|
|
||||||
struct ChatThemes {
|
struct ChatThemes {
|
||||||
int32 hash = 0;
|
int32 hash = 0;
|
||||||
|
double next_reload_time = 0;
|
||||||
vector<ChatTheme> themes;
|
vector<ChatTheme> themes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -622,7 +622,7 @@ void WebPagesManager::update_web_page_instant_view(WebPageId web_page_id, WebPag
|
|||||||
auto previous_queries =
|
auto previous_queries =
|
||||||
load_web_page_instant_view_queries.partial.size() + load_web_page_instant_view_queries.full.size();
|
load_web_page_instant_view_queries.partial.size() + load_web_page_instant_view_queries.full.size();
|
||||||
if (previous_queries == 0) {
|
if (previous_queries == 0) {
|
||||||
// try to load it only if there is no pending load queries
|
// try to load it only if there are no pending load queries
|
||||||
load_web_page_instant_view(web_page_id, false, Auto());
|
load_web_page_instant_view(web_page_id, false, Auto());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4191,8 +4191,7 @@ class CliClient final : public Actor {
|
|||||||
string chat_id;
|
string chat_id;
|
||||||
string message_id;
|
string message_id;
|
||||||
string user_id;
|
string user_id;
|
||||||
int32 score;
|
get_args(args, chat_id, message_id, user_id);
|
||||||
get_args(args, chat_id, message_id, user_id, score);
|
|
||||||
send_request(td_api::make_object<td_api::getGameHighScores>(as_chat_id(chat_id), as_message_id(message_id),
|
send_request(td_api::make_object<td_api::getGameHighScores>(as_chat_id(chat_id), as_message_id(message_id),
|
||||||
as_user_id(user_id)));
|
as_user_id(user_id)));
|
||||||
} else if (op == "gmst") {
|
} else if (op == "gmst") {
|
||||||
|
@ -196,6 +196,7 @@ void HttpConnectionBase::on_start_migrate(int32 sched_id) {
|
|||||||
|
|
||||||
void HttpConnectionBase::on_finish_migrate() {
|
void HttpConnectionBase::on_finish_migrate() {
|
||||||
Scheduler::subscribe(fd_.get_poll_info().extract_pollable_fd(this));
|
Scheduler::subscribe(fd_.get_poll_info().extract_pollable_fd(this));
|
||||||
|
live_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
@ -223,7 +223,7 @@ Result<size_t> HttpReader::read_next(HttpQuery *query, bool can_be_slow) {
|
|||||||
return need_size;
|
return need_size;
|
||||||
}
|
}
|
||||||
case State::ReadMultipartFormData: {
|
case State::ReadMultipartFormData: {
|
||||||
if (!content_->empty()) {
|
if (!content_->empty() || flow_sink_.is_ready()) {
|
||||||
TRY_RESULT(result, parse_multipart_form_data(can_be_slow));
|
TRY_RESULT(result, parse_multipart_form_data(can_be_slow));
|
||||||
if (result) {
|
if (result) {
|
||||||
break;
|
break;
|
||||||
|
@ -170,8 +170,8 @@ TEST(Link, parse_internal_link) {
|
|||||||
auto unknown_deep_link = [](td::string link) {
|
auto unknown_deep_link = [](td::string link) {
|
||||||
return td::td_api::make_object<td::td_api::internalLinkTypeUnknownDeepLink>(link);
|
return td::td_api::make_object<td::td_api::internalLinkTypeUnknownDeepLink>(link);
|
||||||
};
|
};
|
||||||
auto voice_chat = [](td::string chat_username, td::string invite_hash) {
|
auto voice_chat = [](td::string chat_username, td::string invite_hash, bool is_live_stream) {
|
||||||
return td::td_api::make_object<td::td_api::internalLinkTypeVoiceChat>(chat_username, invite_hash);
|
return td::td_api::make_object<td::td_api::internalLinkTypeVoiceChat>(chat_username, invite_hash, is_live_stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_internal_link("t.me/levlam/1", message("tg:resolve?domain=levlam&post=1"));
|
parse_internal_link("t.me/levlam/1", message("tg:resolve?domain=levlam&post=1"));
|
||||||
@ -523,23 +523,27 @@ TEST(Link, parse_internal_link) {
|
|||||||
parse_internal_link("tg:socks?server=google.com&port=8%30&user=&pass=2", proxy_socks("google.com", 80, "", "2"));
|
parse_internal_link("tg:socks?server=google.com&port=8%30&user=&pass=2", proxy_socks("google.com", 80, "", "2"));
|
||||||
parse_internal_link("tg:socks?server=google.com&port=80&user=1&pass=2", proxy_socks("google.com", 80, "1", "2"));
|
parse_internal_link("tg:socks?server=google.com&port=80&user=1&pass=2", proxy_socks("google.com", 80, "1", "2"));
|
||||||
|
|
||||||
parse_internal_link("tg:resolve?domain=username&voice%63hat=aasdasd", voice_chat("username", "aasdasd"));
|
parse_internal_link("tg:resolve?domain=username&voice%63hat=aasdasd", voice_chat("username", "aasdasd", false));
|
||||||
parse_internal_link("TG://resolve?domain=username&voicechat=", voice_chat("username", ""));
|
parse_internal_link("tg:resolve?domain=username&video%63hat=aasdasd", voice_chat("username", "aasdasd", false));
|
||||||
|
parse_internal_link("tg:resolve?domain=username&livestream=aasdasd", voice_chat("username", "aasdasd", true));
|
||||||
|
parse_internal_link("TG://resolve?domain=username&voicechat=", voice_chat("username", "", false));
|
||||||
parse_internal_link("TG://test@resolve?domain=username&voicechat=", nullptr);
|
parse_internal_link("TG://test@resolve?domain=username&voicechat=", nullptr);
|
||||||
parse_internal_link("tg:resolve:80?domain=username&voicechat=", nullptr);
|
parse_internal_link("tg:resolve:80?domain=username&voicechat=", nullptr);
|
||||||
parse_internal_link("tg:http://resolve?domain=username&voicechat=", nullptr);
|
parse_internal_link("tg:http://resolve?domain=username&voicechat=", nullptr);
|
||||||
parse_internal_link("tg:https://resolve?domain=username&voicechat=", nullptr);
|
parse_internal_link("tg:https://resolve?domain=username&voicechat=", nullptr);
|
||||||
parse_internal_link("tg:resolve?domain=&voicechat=", unknown_deep_link("tg://resolve?domain=&voicechat="));
|
parse_internal_link("tg:resolve?domain=&voicechat=", unknown_deep_link("tg://resolve?domain=&voicechat="));
|
||||||
parse_internal_link("tg:resolve?domain=telegram&&&&&&&voicechat=%30", voice_chat("telegram", "0"));
|
parse_internal_link("tg:resolve?domain=telegram&&&&&&&voicechat=%30", voice_chat("telegram", "0", false));
|
||||||
|
|
||||||
parse_internal_link("t.me/username/0/a//s/as?voicechat=", voice_chat("username", ""));
|
parse_internal_link("t.me/username/0/a//s/as?voicechat=", voice_chat("username", "", false));
|
||||||
parse_internal_link("t.me/username/aasdas?test=1&voicechat=#12312", voice_chat("username", ""));
|
parse_internal_link("t.me/username/0/a//s/as?videochat=2", voice_chat("username", "2", false));
|
||||||
parse_internal_link("t.me/username/0?voicechat=", voice_chat("username", ""));
|
parse_internal_link("t.me/username/0/a//s/as?livestream=3", voice_chat("username", "3", true));
|
||||||
parse_internal_link("t.me/username/-1?voicechat=asdasd", voice_chat("username", "asdasd"));
|
parse_internal_link("t.me/username/aasdas?test=1&voicechat=#12312", voice_chat("username", "", false));
|
||||||
parse_internal_link("t.me/username?voicechat=", voice_chat("username", ""));
|
parse_internal_link("t.me/username/0?voicechat=", voice_chat("username", "", false));
|
||||||
|
parse_internal_link("t.me/username/-1?voicechat=asdasd", voice_chat("username", "asdasd", false));
|
||||||
|
parse_internal_link("t.me/username?voicechat=", voice_chat("username", "", false));
|
||||||
parse_internal_link("t.me/username#voicechat=asdas", public_chat("username"));
|
parse_internal_link("t.me/username#voicechat=asdas", public_chat("username"));
|
||||||
parse_internal_link("t.me//username?voicechat=", nullptr);
|
parse_internal_link("t.me//username?voicechat=", nullptr);
|
||||||
parse_internal_link("https://telegram.dog/tele%63ram?voi%63e%63hat=t%63st", voice_chat("telecram", "tcst"));
|
parse_internal_link("https://telegram.dog/tele%63ram?voi%63e%63hat=t%63st", voice_chat("telecram", "tcst", false));
|
||||||
|
|
||||||
parse_internal_link("tg:resolve?domain=username&start=aasdasd", bot_start("username", "aasdasd"));
|
parse_internal_link("tg:resolve?domain=username&start=aasdasd", bot_start("username", "aasdasd"));
|
||||||
parse_internal_link("TG://resolve?domain=username&start=", bot_start("username", ""));
|
parse_internal_link("TG://resolve?domain=username&start=", bot_start("username", ""));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user