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?
|
||||
string(REPLACE ";" " " CXX_FLAGS_IPO "${CMAKE_CXX_COMPILE_OPTIONS_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}")
|
||||
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}")
|
||||
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()
|
||||
@ -335,6 +335,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/files/PartsManager.cpp
|
||||
td/telegram/files/ResourceManager.cpp
|
||||
td/telegram/Game.cpp
|
||||
td/telegram/GameManager.cpp
|
||||
td/telegram/Global.cpp
|
||||
td/telegram/GroupCallManager.cpp
|
||||
td/telegram/GroupCallParticipant.cpp
|
||||
@ -403,7 +404,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/SendCodeHelper.cpp
|
||||
td/telegram/SequenceDispatcher.cpp
|
||||
td/telegram/SpecialStickerSetType.cpp
|
||||
td/telegram/SponsoredMessages.cpp
|
||||
td/telegram/SponsoredMessageManager.cpp
|
||||
td/telegram/StateManager.cpp
|
||||
td/telegram/StickersManager.cpp
|
||||
td/telegram/StorageManager.cpp
|
||||
@ -524,6 +525,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/FolderId.h
|
||||
td/telegram/FullMessageId.h
|
||||
td/telegram/Game.h
|
||||
td/telegram/GameManager.h
|
||||
td/telegram/Global.h
|
||||
td/telegram/GroupCallId.h
|
||||
td/telegram/GroupCallManager.h
|
||||
@ -618,7 +620,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/ServerMessageId.h
|
||||
td/telegram/SetWithPosition.h
|
||||
td/telegram/SpecialStickerSetType.h
|
||||
td/telegram/SponsoredMessages.h
|
||||
td/telegram/SponsoredMessageManager.h
|
||||
td/telegram/StateManager.h
|
||||
td/telegram/StickerSetId.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)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Building](#building)
|
||||
- [Installing dependencies](#installing-dependencies)
|
||||
- [Using in CMake C++ projects](#using-cxx)
|
||||
- [Using in Java projects](#using-java)
|
||||
- [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).
|
||||
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).
|
||||
Then enter directory containing `TDLib` sources and compile them using CMake:
|
||||
In general, you need to install all `TDLib` [dependencies](#dependencies), enter directory containing `TDLib` sources and compile them using CMake:
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
<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>
|
||||
## 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.
|
||||
|
@ -286,6 +286,7 @@ function split_file($file, $chunks, $undo) {
|
||||
'file_reference_manager[_(-][^.]|FileReferenceManager|file_references[)]' => 'FileReferenceManager',
|
||||
'file_manager[_(-][^.]|FileManager([^ ;.]| [^*])|update_file[)]' => 'files/FileManager',
|
||||
'G[(][)]|Global[^A-Za-z]' => 'Global',
|
||||
'game_manager[_(-][^.]|GameManager' => 'GameManager',
|
||||
'group_call_manager[_(-][^.]|GroupCallManager' => 'GroupCallManager',
|
||||
'HashtagHints' => 'HashtagHints',
|
||||
'inline_queries_manager[_(-][^.]|InlineQueriesManager' => 'InlineQueriesManager',
|
||||
@ -300,6 +301,7 @@ function split_file($file, $chunks, $undo) {
|
||||
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
||||
'SecretChatActor' => 'SecretChatActor',
|
||||
'secret_chats_manager[_(-][^.]|SecretChatsManager' => 'SecretChatsManager',
|
||||
'sponsored_message_manager[_(-][^.]|SponsoredMessageManager' => 'SponsoredMessageManager',
|
||||
'stickers_manager[_(-][^.]|StickersManager' => 'StickersManager',
|
||||
'[>](td_db[(][)]|get_td_db_impl[(])|TdDb[^A-Za-z]' => 'TdDb',
|
||||
'theme_manager[_(-][^.]|ThemeManager' => "ThemeManager",
|
||||
|
@ -542,6 +542,10 @@ function onOptionsChanged() {
|
||||
if (os_netbsd) {
|
||||
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 () {
|
||||
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.
|
||||
|
||||
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 [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>
|
||||
## Using TDLib in Objective-C projects
|
||||
|
@ -6,16 +6,12 @@ index 695be54..4efe5e5 100644
|
||||
# - iOS - build everything for iOS
|
||||
# - tvOS - build everything for tvOS
|
||||
# - watchOS - build everything for watchOS
|
||||
-# - OpenSSL-macOS - build OpenSSL for macOS
|
||||
-# - 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-macOS - build OpenSSL for macOS
|
||||
# - OpenSSL-iOS - build OpenSSL for iOS
|
||||
+# - 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-watchOS - build OpenSSL for watchOS
|
||||
# - OpenSSL-watchOS - build OpenSSL for watchOS
|
||||
+# - OpenSSL-watchOS-simulator - build OpenSSL for watchOS-simulator
|
||||
# - BZip2-macOS - build BZip2 for macOS
|
||||
# - 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.
|
||||
|
||||
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).
|
||||
|
||||
@ -21,24 +21,26 @@ cd native-build
|
||||
cmake ..
|
||||
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
|
||||
./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
|
||||
you need to ensure that there is no spaces in the path.
|
||||
Built libraries should be stored in `third_party/openssl/<platform>`, because the next script will rely on this location.
|
||||
* Build TDLib for iOS, watchOS, tvOS and macOS:
|
||||
you need to ensure that there are no spaces in the path.
|
||||
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:
|
||||
```
|
||||
cd <path to TDLib sources>/example/ios
|
||||
./build.sh
|
||||
```
|
||||
This may take a while, because TDLib will be built about 10 times.
|
||||
Resulting library for iOS will work on any architecture (armv7, armv7s, arm64) and even on a simulator (Intel, Apple Silicon).
|
||||
This may take a while, because TDLib will be built about 16 times.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
echo "Platform = ${platform}"
|
||||
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
|
||||
build="build-${platform}"
|
||||
install="install-${platform}"
|
||||
@ -33,62 +64,15 @@ do
|
||||
mkdir -p $build
|
||||
mkdir -p $install
|
||||
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
|
||||
cd ..
|
||||
mkdir -p $platform
|
||||
cp $build/libtdjson.dylib $platform/libtdjson.dylib
|
||||
install_name_tool -id @rpath/libtdjson.dylib $platform/libtdjson.dylib
|
||||
|
||||
install_name_tool -id @rpath/libtdjson.dylib ${install}/lib/libtdjson.dylib
|
||||
mkdir -p ../tdjson/${platform}/include
|
||||
rsync --recursive ${install}/include/ ../tdjson/${platform}/include/
|
||||
mkdir -p ../tdjson/${platform}/lib
|
||||
cp ${platform}/libtdjson.dylib ../tdjson/${platform}/lib/
|
||||
else
|
||||
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/
|
||||
cp ${install}/lib/libtdjson.dylib ../tdjson/${platform}/lib/
|
||||
done
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
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.
|
||||
|
@ -7,7 +7,7 @@ You need a Unix shell with `sed`, `tar` and `wget` utilities to run the provided
|
||||
## 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 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.
|
||||
* 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_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
|
||||
//@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_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_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 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;
|
||||
|
||||
//@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
|
||||
//@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
|
||||
//@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;
|
||||
|
||||
//@description Represents a file
|
||||
//@id Unique file identifier
|
||||
//@size File size; 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
|
||||
//@size File size, in bytes; 0 if unknown
|
||||
//@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
|
||||
//@remote Information about the remote copy of the 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
|
||||
//@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;
|
||||
|
||||
|
||||
//@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
|
||||
//@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;
|
||||
|
||||
//@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
|
||||
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;
|
||||
|
||||
//@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
|
||||
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;
|
||||
|
||||
//@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
|
||||
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;
|
||||
|
||||
//@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
|
||||
//@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
|
||||
@ -3265,16 +3266,16 @@ fileTypeVoiceNote = 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;
|
||||
|
||||
//@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;
|
||||
|
||||
//@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;
|
||||
|
||||
//@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
|
||||
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
|
||||
//@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_video_file_size The maximum size of a video file to be auto-downloaded
|
||||
//@max_other_file_size The maximum size of other file types 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, in bytes
|
||||
//@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
|
||||
//@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
|
||||
@ -3914,7 +3915,7 @@ logStreamDefault = LogStream;
|
||||
|
||||
//@description The log is written to a file
|
||||
//@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
|
||||
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
|
||||
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;
|
||||
|
||||
//@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;
|
||||
|
||||
//@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
|
||||
//@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
|
||||
|
@ -6080,7 +6080,7 @@ void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user
|
||||
auto user_full = get_user_full(user_id);
|
||||
if (user_full != nullptr) {
|
||||
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;
|
||||
}
|
||||
@ -6105,7 +6105,7 @@ void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user
|
||||
chat_full->is_changed = true;
|
||||
}
|
||||
}
|
||||
update_chat_full(chat_full, chat_id);
|
||||
update_chat_full(chat_full, chat_id, "on_update_bot_commands");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -6130,7 +6130,7 @@ void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user
|
||||
channel_full->is_changed = true;
|
||||
}
|
||||
}
|
||||
update_channel_full(channel_full, channel_id);
|
||||
update_channel_full(channel_full, channel_id, "on_update_bot_commands");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -6302,7 +6302,7 @@ void ContactsManager::on_update_profile_success(int32 flags, const string &first
|
||||
if (user_full != nullptr) {
|
||||
user_full->about = about;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -8021,7 +8021,7 @@ void ContactsManager::invalidate_user_full(UserId user_id) {
|
||||
user_full->expires_at = 0.0;
|
||||
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);
|
||||
|
||||
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)) {
|
||||
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));
|
||||
|
||||
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) {
|
||||
@ -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),
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
unavailable_user_fulls_.erase(user_id); // don't needed anymore
|
||||
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_save_to_database |= user_full->is_changed;
|
||||
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) {
|
||||
{
|
||||
auto u = get_user(user_id);
|
||||
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,
|
||||
make_tl_object<td_api::updateUserFullInfo>(get_user_id_object(user_id, "updateUserFullInfo"),
|
||||
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);
|
||||
unavailable_chat_fulls_.erase(chat_id); // don't needed anymore
|
||||
|
||||
chat_full->need_send_update |= chat_full->is_changed;
|
||||
chat_full->need_save_to_database |= chat_full->is_changed;
|
||||
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) {
|
||||
vector<DialogAdministrator> administrators;
|
||||
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);
|
||||
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(
|
||||
G()->td(), &Td::send_update,
|
||||
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) {
|
||||
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_save_to_database |= channel_full->is_changed;
|
||||
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->linked_channel_id.is_valid()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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(
|
||||
G()->td(), &Td::send_update,
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
CHECK(chat_full_ptr->get_id() == telegram_api::channelFull::ID);
|
||||
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;
|
||||
}
|
||||
|
||||
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()) {
|
||||
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);
|
||||
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);
|
||||
if (user_full == nullptr) {
|
||||
if (user_full == nullptr || user_full->is_blocked == is_blocked) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
@ -11106,7 +11134,7 @@ void ContactsManager::on_update_user_common_chat_count(UserId user_id, int32 com
|
||||
return;
|
||||
}
|
||||
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,
|
||||
@ -11148,7 +11176,7 @@ void ContactsManager::on_update_user_need_phone_number_privacy_exception(UserId
|
||||
return;
|
||||
}
|
||||
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(
|
||||
@ -11240,7 +11268,7 @@ void ContactsManager::add_profile_photo_to_cache(UserId user_id, Photo &&photo)
|
||||
user_full->photo = photo;
|
||||
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
|
||||
@ -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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
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->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);
|
||||
}
|
||||
|
||||
@ -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_,
|
||||
from_update);
|
||||
update_chat_full(chat_full, chat_id);
|
||||
update_chat_full(chat_full, chat_id, "on_get_chat_participants");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -11793,7 +11821,7 @@ void ContactsManager::on_get_channel_participants(
|
||||
channel_full->administrator_count = administrator_count;
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
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");
|
||||
if (channel_full != nullptr && td::remove(channel_full->bot_user_ids, deleted_user_id)) {
|
||||
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),
|
||||
channel_full->bot_user_ids, false);
|
||||
@ -11991,7 +12019,7 @@ void ContactsManager::speculative_add_channel_participant_count(ChannelId channe
|
||||
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,
|
||||
@ -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,
|
||||
@ -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");
|
||||
}
|
||||
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
|
||||
if (channel_full != nullptr) {
|
||||
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 {
|
||||
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");
|
||||
if (chat_full != nullptr && update_permanent_invite_link(chat_full->invite_link, invite_link)) {
|
||||
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;
|
||||
}
|
||||
@ -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");
|
||||
if (channel_full != nullptr && update_permanent_invite_link(channel_full->invite_link, invite_link)) {
|
||||
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;
|
||||
}
|
||||
@ -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) {
|
||||
linked_channel_full->linked_channel_id = ChannelId();
|
||||
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) {
|
||||
linked_channel_full->linked_channel_id = channel_id;
|
||||
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()});
|
||||
update_chat_online_member_count(chat_full, chat_id, false);
|
||||
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
|
||||
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)) {
|
||||
participant.status = std::move(status);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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->is_changed = true;
|
||||
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) {
|
||||
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");
|
||||
if (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) {
|
||||
@ -13019,7 +13049,7 @@ void ContactsManager::on_update_chat_description(ChatId chat_id, string &&descri
|
||||
if (chat_full->description != description) {
|
||||
chat_full->description = std::move(description);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -13084,7 +13114,7 @@ void ContactsManager::drop_chat_photos(ChatId chat_id, bool is_empty, bool drop_
|
||||
if (!is_empty) {
|
||||
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);
|
||||
update_chat_online_member_count(chat_full, chat_id, 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,
|
||||
@ -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
|
||||
on_update_channel_full_invite_link(channel_full, nullptr);
|
||||
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 {
|
||||
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) {
|
||||
channel_full->description = std::move(description);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -13269,7 +13299,7 @@ void ContactsManager::on_update_channel_sticker_set(ChannelId channel_id, Sticke
|
||||
if (channel_full->sticker_set_id != sticker_set_id) {
|
||||
channel_full->sticker_set_id = sticker_set_id;
|
||||
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");
|
||||
on_update_channel_full_linked_channel_id(channel_full, channel_id, group_channel_id);
|
||||
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()) {
|
||||
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);
|
||||
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");
|
||||
if (channel_full != nullptr) {
|
||||
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");
|
||||
if (channel_full != nullptr) {
|
||||
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());
|
||||
}
|
||||
@ -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");
|
||||
if (channel_full != nullptr) {
|
||||
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;
|
||||
}
|
||||
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,
|
||||
@ -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) {
|
||||
channel_full->is_all_history_available = is_all_history_available;
|
||||
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());
|
||||
}
|
||||
@ -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) {
|
||||
channel_full->participant_count = participant_count;
|
||||
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->administrator_count = 0;
|
||||
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) {
|
||||
|
@ -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 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 is_update_user_full_sent = false;
|
||||
|
||||
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 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 is_update_chat_full_sent = false;
|
||||
|
||||
template <class StorerT>
|
||||
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 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 is_update_channel_full_sent = false;
|
||||
|
||||
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,
|
||||
bool from_database = false);
|
||||
|
||||
void update_user_full(UserFull *user_full, UserId user_id, bool from_database = false);
|
||||
void update_chat_full(ChatFull *chat_full, ChatId chat_id, bool from_database = false);
|
||||
void update_channel_full(ChannelFull *channel_full, ChannelId channel_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, const char *source, 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);
|
||||
|
||||
|
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 FileManager;
|
||||
class FileReferenceManager;
|
||||
class GameManager;
|
||||
class GroupCallManager;
|
||||
class LanguagePackManager;
|
||||
class LinkManager;
|
||||
@ -47,6 +48,7 @@ class NetQueryDispatcher;
|
||||
class NotificationManager;
|
||||
class PasswordManager;
|
||||
class SecretChatsManager;
|
||||
class SponsoredMessageManager;
|
||||
class StateManager;
|
||||
class StickersManager;
|
||||
class StorageManager;
|
||||
@ -219,6 +221,13 @@ class Global final : public ActorContext {
|
||||
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 {
|
||||
return group_call_manager_;
|
||||
}
|
||||
@ -268,6 +277,13 @@ class Global final : public ActorContext {
|
||||
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 {
|
||||
return stickers_manager_;
|
||||
}
|
||||
@ -417,6 +433,7 @@ class Global final : public ActorContext {
|
||||
ActorId<ContactsManager> contacts_manager_;
|
||||
ActorId<FileManager> file_manager_;
|
||||
ActorId<FileReferenceManager> file_reference_manager_;
|
||||
ActorId<GameManager> game_manager_;
|
||||
ActorId<GroupCallManager> group_call_manager_;
|
||||
ActorId<LanguagePackManager> language_pack_manager_;
|
||||
ActorId<LinkManager> link_manager_;
|
||||
@ -424,6 +441,7 @@ class Global final : public ActorContext {
|
||||
ActorId<NotificationManager> notification_manager_;
|
||||
ActorId<PasswordManager> password_manager_;
|
||||
ActorId<SecretChatsManager> secret_chats_manager_;
|
||||
ActorId<SponsoredMessageManager> sponsored_message_manager_;
|
||||
ActorId<StickersManager> stickers_manager_;
|
||||
ActorId<StorageManager> storage_manager_;
|
||||
ActorId<MemoryManager> memory_manager_;
|
||||
|
@ -1074,7 +1074,7 @@ tl_object_ptr<td_api::venue> copy(const td_api::venue &obj) {
|
||||
|
||||
template <>
|
||||
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>>());
|
||||
}
|
||||
|
||||
|
@ -357,14 +357,17 @@ class LinkManager::InternalLinkUnknownDeepLink final : public InternalLink {
|
||||
class LinkManager::InternalLinkVoiceChat final : public InternalLink {
|
||||
string dialog_username_;
|
||||
string invite_hash_;
|
||||
bool is_live_stream_;
|
||||
|
||||
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:
|
||||
InternalLinkVoiceChat(string dialog_username, string invite_hash)
|
||||
: dialog_username_(std::move(dialog_username)), invite_hash_(std::move(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))
|
||||
, 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");
|
||||
for (auto &arg : url_query.args_) {
|
||||
if (arg.first == "voicechat") {
|
||||
// resolve?domain=<username>&voicechat
|
||||
// resolve?domain=<username>&voicechat=<invite_hash>
|
||||
if (arg.first == "voicechat" || arg.first == "videochat" || arg.first == "livestream") {
|
||||
// resolve?domain=<username>&videochat
|
||||
// resolve?domain=<username>&videochat=<invite_hash>
|
||||
if (Scheduler::context() != nullptr) {
|
||||
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)) {
|
||||
// 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];
|
||||
for (auto &arg : url_query.args_) {
|
||||
if (arg.first == "voicechat") {
|
||||
// /<username>?voicechat
|
||||
// /<username>?voicechat=<invite_hash>
|
||||
if (arg.first == "voicechat" || arg.first == "videochat" || arg.first == "livestream") {
|
||||
// /<username>?videochat
|
||||
// /<username>?videochat=<invite_hash>
|
||||
if (Scheduler::context() != nullptr) {
|
||||
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)) {
|
||||
// /<bot_username>?start=<parameter>
|
||||
|
@ -4364,7 +4364,12 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
||||
return std::move(result);
|
||||
}
|
||||
case MessageContentType::Poll:
|
||||
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: {
|
||||
auto result = make_unique<MessageSticker>(*static_cast<const MessageSticker *>(content));
|
||||
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 {
|
||||
Promise<Unit> promise_;
|
||||
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"));
|
||||
}
|
||||
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);
|
||||
@ -11646,7 +11464,7 @@ void MessagesManager::repair_channel_server_unread_count(Dialog *d) {
|
||||
return;
|
||||
}
|
||||
if (!need_unread_counter(d->order)) {
|
||||
// there is no unread count in left channels
|
||||
// there are no unread counters in left channels
|
||||
return;
|
||||
}
|
||||
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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
if (m == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (m->content->get_type() != MessageContentType::Game) {
|
||||
return false;
|
||||
}
|
||||
if (m->message_id.is_scheduled()) {
|
||||
return false;
|
||||
}
|
||||
@ -26255,181 +26080,7 @@ bool MessagesManager::can_set_game_score(DialogId dialog_id, const Message *m) c
|
||||
return false;
|
||||
}
|
||||
|
||||
return m->content->get_type() == MessageContentType::Game;
|
||||
}
|
||||
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
@ -917,10 +903,14 @@ class MessagesManager final : public Actor {
|
||||
|
||||
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;
|
||||
|
||||
ActorOwn<MultiSequenceDispatcher> sequence_dispatcher_;
|
||||
|
||||
static uint64 get_sequence_dispatcher_id(DialogId dialog_id, MessageContentType message_content_type);
|
||||
|
||||
private:
|
||||
class PendingPtsUpdate {
|
||||
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
|
||||
// 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
|
||||
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
|
||||
// is known and last_message_id is known, then last_database_message_id <=
|
||||
// last_message_id
|
||||
@ -2985,8 +2975,6 @@ class MessagesManager final : public Actor {
|
||||
|
||||
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();
|
||||
|
||||
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::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_queries_;
|
||||
|
@ -1063,7 +1063,7 @@ void NotificationManager::flush_pending_updates(int32 group_id, const char *sour
|
||||
// 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 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
|
||||
// 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,
|
||||
@ -2809,6 +2809,9 @@ string NotificationManager::convert_loc_key(const string &loc_key) {
|
||||
if (loc_key == "MESSAGE_NOTEXT") {
|
||||
return "MESSAGE";
|
||||
}
|
||||
if (loc_key == "MESSAGE_NOTHEME") {
|
||||
return "MESSAGE_CHAT_CHANGE_THEME";
|
||||
}
|
||||
if (loc_key == "PINNED_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;
|
||||
}
|
||||
}
|
||||
if (poll->is_closed) {
|
||||
open_period = 0;
|
||||
close_date = 0;
|
||||
}
|
||||
return td_api::make_object<td_api::poll>(
|
||||
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,
|
||||
@ -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 {
|
||||
auto poll = get_poll(poll_id);
|
||||
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);
|
||||
bool is_changed = false;
|
||||
bool need_save_to_database = false;
|
||||
if (poll == nullptr) {
|
||||
if (poll_server == nullptr) {
|
||||
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) {
|
||||
poll->open_period = open_period;
|
||||
if (!poll->is_closed) {
|
||||
is_changed = true;
|
||||
} else {
|
||||
need_save_to_database = true;
|
||||
}
|
||||
}
|
||||
if (close_date != poll->close_date) {
|
||||
poll->close_date = close_date;
|
||||
is_changed = true;
|
||||
|
||||
if (!poll->is_closed) {
|
||||
is_changed = true;
|
||||
if (close_date != 0) {
|
||||
if (close_date <= G()->server_time()) {
|
||||
poll->is_closed = true;
|
||||
@ -1481,6 +1501,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
} else {
|
||||
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;
|
||||
@ -1645,6 +1667,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
if (is_changed) {
|
||||
notify_on_poll_update(poll_id);
|
||||
}
|
||||
if (is_changed || need_save_to_database) {
|
||||
save_poll(poll, poll_id);
|
||||
}
|
||||
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);
|
||||
|
||||
PollId dup_poll(PollId poll_id);
|
||||
|
||||
bool has_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";
|
||||
}
|
||||
|
||||
// if 0 sticker sets are received, then set offset_sticker_set_id was found and there is no stickers after it
|
||||
// or it wasn't found and there is no archived sets at all
|
||||
// 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 are no archived sets at all
|
||||
bool is_last =
|
||||
sticker_sets.empty() && (!offset_sticker_set_id.is_valid() ||
|
||||
(!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/FolderId.h"
|
||||
#include "td/telegram/FullMessageId.h"
|
||||
#include "td/telegram/GameManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/GroupCallId.h"
|
||||
#include "td/telegram/GroupCallManager.h"
|
||||
@ -90,7 +91,7 @@
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
#include "td/telegram/SecureManager.h"
|
||||
#include "td/telegram/SecureValue.h"
|
||||
#include "td/telegram/SponsoredMessages.h"
|
||||
#include "td/telegram/SponsoredMessageManager.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/StickerSetId.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<> {
|
||||
DialogId dialog_id_;
|
||||
MessageId from_message_id_;
|
||||
@ -3706,6 +3631,8 @@ void Td::dec_actor_refcnt() {
|
||||
LOG(DEBUG) << "FileManager was cleared" << timer;
|
||||
file_reference_manager_.reset();
|
||||
LOG(DEBUG) << "FileReferenceManager was cleared" << timer;
|
||||
game_manager_.reset();
|
||||
LOG(DEBUG) << "GameManager was cleared" << timer;
|
||||
group_call_manager_.reset();
|
||||
LOG(DEBUG) << "GroupCallManager was cleared" << timer;
|
||||
inline_queries_manager_.reset();
|
||||
@ -3718,6 +3645,8 @@ void Td::dec_actor_refcnt() {
|
||||
LOG(DEBUG) << "NotificationManager was cleared" << timer;
|
||||
poll_manager_.reset();
|
||||
LOG(DEBUG) << "PollManager was cleared" << timer;
|
||||
sponsored_message_manager_.reset();
|
||||
LOG(DEBUG) << "SponsoredMessageManager was cleared" << timer;
|
||||
stickers_manager_.reset();
|
||||
LOG(DEBUG) << "StickersManager was cleared" << timer;
|
||||
memory_manager_.reset();
|
||||
@ -3909,6 +3838,8 @@ void Td::clear() {
|
||||
LOG(DEBUG) << "FileManager actor was cleared" << timer;
|
||||
file_reference_manager_actor_.reset();
|
||||
LOG(DEBUG) << "FileReferenceManager actor was cleared" << timer;
|
||||
game_manager_actor_.reset();
|
||||
LOG(DEBUG) << "GameManager actor was cleared" << timer;
|
||||
group_call_manager_actor_.reset();
|
||||
LOG(DEBUG) << "GroupCallManager actor was cleared" << timer;
|
||||
inline_queries_manager_actor_.reset();
|
||||
@ -3921,6 +3852,8 @@ void Td::clear() {
|
||||
LOG(DEBUG) << "NotificationManager actor was cleared" << timer;
|
||||
poll_manager_actor_.reset();
|
||||
LOG(DEBUG) << "PollManager actor was cleared" << timer;
|
||||
sponsored_message_manager_actor_.reset();
|
||||
LOG(DEBUG) << "SponsoredMessageManager actor was cleared" << timer;
|
||||
stickers_manager_actor_.reset();
|
||||
LOG(DEBUG) << "StickersManager actor was cleared" << timer;
|
||||
memory_manager_actor_.reset();
|
||||
@ -4371,6 +4304,9 @@ void Td::init_managers() {
|
||||
G()->set_contacts_manager(contacts_manager_actor_.get());
|
||||
country_info_manager_ = make_unique<CountryInfoManager>(this, create_reference());
|
||||
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_actor_ = register_actor("GroupCallManager", group_call_manager_.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_actor_ = register_actor("PollManager", poll_manager_.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_actor_ = register_actor("StickersManager", stickers_manager_.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) {
|
||||
CHECK_IS_USER();
|
||||
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) {
|
||||
CHECK_IS_USER();
|
||||
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) {
|
||||
@ -5831,28 +5771,31 @@ void Td::on_request(uint64 id, td_api::editMessageSchedulingState &request) {
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setGameScore &request) {
|
||||
CHECK_IS_BOT();
|
||||
CREATE_REQUEST(SetGameScoreRequest, request.chat_id_, request.message_id_, request.edit_message_, request.user_id_,
|
||||
request.score_, request.force_);
|
||||
CREATE_REQUEST_PROMISE();
|
||||
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) {
|
||||
CHECK_IS_BOT();
|
||||
CLEAN_INPUT_STRING(request.inline_message_id_);
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
messages_manager_->set_inline_game_score(std::move(request.inline_message_id_), request.edit_message_,
|
||||
UserId(request.user_id_), request.score_, request.force_,
|
||||
std::move(promise));
|
||||
game_manager_->set_inline_game_score(std::move(request.inline_message_id_), request.edit_message_,
|
||||
UserId(request.user_id_), request.score_, request.force_, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getGameHighScores &request) {
|
||||
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) {
|
||||
CHECK_IS_BOT();
|
||||
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) {
|
||||
|
@ -57,6 +57,7 @@ class DeviceTokenManager;
|
||||
class DocumentsManager;
|
||||
class FileManager;
|
||||
class FileReferenceManager;
|
||||
class GameManager;
|
||||
class GroupCallManager;
|
||||
class InlineQueriesManager;
|
||||
class HashtagHints;
|
||||
@ -71,6 +72,7 @@ class PollManager;
|
||||
class PrivacyManager;
|
||||
class SecureManager;
|
||||
class SecretChatsManager;
|
||||
class SponsoredMessageManager;
|
||||
class StickersManager;
|
||||
class StorageManager;
|
||||
class MemoryManager;
|
||||
@ -168,6 +170,8 @@ class Td final : public NetQueryCallback {
|
||||
ActorOwn<FileManager> file_manager_actor_;
|
||||
unique_ptr<FileReferenceManager> file_reference_manager_;
|
||||
ActorOwn<FileReferenceManager> file_reference_manager_actor_;
|
||||
unique_ptr<GameManager> game_manager_;
|
||||
ActorOwn<GameManager> game_manager_actor_;
|
||||
unique_ptr<GroupCallManager> group_call_manager_;
|
||||
ActorOwn<GroupCallManager> group_call_manager_actor_;
|
||||
unique_ptr<InlineQueriesManager> inline_queries_manager_;
|
||||
@ -180,6 +184,8 @@ class Td final : public NetQueryCallback {
|
||||
ActorOwn<NotificationManager> notification_manager_actor_;
|
||||
unique_ptr<PollManager> poll_manager_;
|
||||
ActorOwn<PollManager> poll_manager_actor_;
|
||||
unique_ptr<SponsoredMessageManager> sponsored_message_manager_;
|
||||
ActorOwn<SponsoredMessageManager> sponsored_message_manager_actor_;
|
||||
unique_ptr<StickersManager> stickers_manager_;
|
||||
ActorOwn<StickersManager> stickers_manager_actor_;
|
||||
unique_ptr<ThemeManager> theme_manager_;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Time.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
@ -44,6 +45,7 @@ class GetChatThemesQuery final : public Td::ResultHandler {
|
||||
};
|
||||
|
||||
ThemeManager::ThemeManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||
chat_themes_.next_reload_time = Time::now();
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
auto request_promise = PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::account_ChatThemes>> result) {
|
||||
@ -106,17 +117,13 @@ void ThemeManager::on_get_chat_themes(Result<telegram_api::object_ptr<telegram_a
|
||||
return;
|
||||
}
|
||||
|
||||
chat_themes_.next_reload_time = Time::now() + THEME_CACHE_TIME;
|
||||
|
||||
auto chat_themes_ptr = result.move_as_ok();
|
||||
LOG(DEBUG) << "Receive " << to_string(chat_themes_ptr);
|
||||
if (chat_themes_ptr->get_id() == telegram_api::account_chatThemesNotModified::ID) {
|
||||
for (auto &promise : promises) {
|
||||
promise.set_value(get_chat_themes_object());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (chat_themes_ptr->get_id() != telegram_api::account_chatThemesNotModified::ID) {
|
||||
CHECK(chat_themes_ptr->get_id() == telegram_api::account_chatThemes::ID);
|
||||
auto chat_themes = telegram_api::move_object_as<telegram_api::account_chatThemes>(chat_themes_ptr);
|
||||
LOG(INFO) << "Receive " << to_string(chat_themes);
|
||||
chat_themes_.hash = chat_themes->hash_;
|
||||
chat_themes_.themes.clear();
|
||||
for (auto &chat_theme : chat_themes->themes_) {
|
||||
@ -131,11 +138,14 @@ void ThemeManager::on_get_chat_themes(Result<telegram_api::object_ptr<telegram_a
|
||||
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) {
|
||||
if (promise) {
|
||||
promise.set_value(get_chat_themes_object());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThemeManager::BaseTheme ThemeManager::get_base_theme(
|
||||
const telegram_api::object_ptr<telegram_api::BaseTheme> &base_theme) {
|
||||
|
@ -30,6 +30,8 @@ class ThemeManager final : public Actor {
|
||||
private:
|
||||
enum class BaseTheme : int32 { Classic, Day, Night, Tinted, Arctic };
|
||||
|
||||
static constexpr int32 THEME_CACHE_TIME = 3600;
|
||||
|
||||
struct ThemeSettings {
|
||||
int32 accent_color = 0;
|
||||
BackgroundId background_id;
|
||||
@ -47,6 +49,7 @@ class ThemeManager final : public Actor {
|
||||
|
||||
struct ChatThemes {
|
||||
int32 hash = 0;
|
||||
double next_reload_time = 0;
|
||||
vector<ChatTheme> themes;
|
||||
};
|
||||
|
||||
|
@ -622,7 +622,7 @@ void WebPagesManager::update_web_page_instant_view(WebPageId web_page_id, WebPag
|
||||
auto previous_queries =
|
||||
load_web_page_instant_view_queries.partial.size() + load_web_page_instant_view_queries.full.size();
|
||||
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());
|
||||
return;
|
||||
}
|
||||
|
@ -4191,8 +4191,7 @@ class CliClient final : public Actor {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string user_id;
|
||||
int32 score;
|
||||
get_args(args, chat_id, message_id, user_id, score);
|
||||
get_args(args, chat_id, message_id, user_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)));
|
||||
} else if (op == "gmst") {
|
||||
|
@ -196,6 +196,7 @@ void HttpConnectionBase::on_start_migrate(int32 sched_id) {
|
||||
|
||||
void HttpConnectionBase::on_finish_migrate() {
|
||||
Scheduler::subscribe(fd_.get_poll_info().extract_pollable_fd(this));
|
||||
live_event();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -223,7 +223,7 @@ Result<size_t> HttpReader::read_next(HttpQuery *query, bool can_be_slow) {
|
||||
return need_size;
|
||||
}
|
||||
case State::ReadMultipartFormData: {
|
||||
if (!content_->empty()) {
|
||||
if (!content_->empty() || flow_sink_.is_ready()) {
|
||||
TRY_RESULT(result, parse_multipart_form_data(can_be_slow));
|
||||
if (result) {
|
||||
break;
|
||||
|
@ -170,8 +170,8 @@ TEST(Link, parse_internal_link) {
|
||||
auto unknown_deep_link = [](td::string link) {
|
||||
return td::td_api::make_object<td::td_api::internalLinkTypeUnknownDeepLink>(link);
|
||||
};
|
||||
auto voice_chat = [](td::string chat_username, td::string invite_hash) {
|
||||
return td::td_api::make_object<td::td_api::internalLinkTypeVoiceChat>(chat_username, 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, is_live_stream);
|
||||
};
|
||||
|
||||
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=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&voicechat=", voice_chat("username", ""));
|
||||
parse_internal_link("tg:resolve?domain=username&voice%63hat=aasdasd", voice_chat("username", "aasdasd", false));
|
||||
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:resolve:80?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: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/aasdas?test=1&voicechat=#12312", voice_chat("username", ""));
|
||||
parse_internal_link("t.me/username/0?voicechat=", voice_chat("username", ""));
|
||||
parse_internal_link("t.me/username/-1?voicechat=asdasd", voice_chat("username", "asdasd"));
|
||||
parse_internal_link("t.me/username?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/0/a//s/as?videochat=2", voice_chat("username", "2", false));
|
||||
parse_internal_link("t.me/username/0/a//s/as?livestream=3", voice_chat("username", "3", true));
|
||||
parse_internal_link("t.me/username/aasdas?test=1&voicechat=#12312", voice_chat("username", "", false));
|
||||
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=", 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=", bot_start("username", ""));
|
||||
|
Loading…
x
Reference in New Issue
Block a user