Compare commits
182 Commits
3f01f7ebbb
...
4cbd9d26c8
Author | SHA1 | Date | |
---|---|---|---|
|
4cbd9d26c8 | ||
|
69bb2b9b9e | ||
|
33131b65c3 | ||
|
ab68dabe74 | ||
|
608b0208af | ||
|
88c26a55f8 | ||
|
0a90633864 | ||
|
215c2bcd13 | ||
|
13648d1fca | ||
|
b41f3219dc | ||
|
44b42cc659 | ||
|
23c7a6caee | ||
|
d326e32a84 | ||
|
874796ef24 | ||
|
d57fdc5155 | ||
|
2c61318a11 | ||
|
1e6c1dbb12 | ||
|
1fba0f0c84 | ||
|
919a1d8329 | ||
|
b1b33cf427 | ||
|
b3b63bbdc1 | ||
|
52d9ac02ba | ||
|
64094e17c0 | ||
|
046ed45152 | ||
|
6e44c27db0 | ||
|
d08ad22a2b | ||
|
a1bcec491d | ||
|
2d43bdf03c | ||
|
bc1a8d2bc2 | ||
|
06831c2836 | ||
|
b255a21733 | ||
|
d1638a0fc4 | ||
|
ef636ea07c | ||
|
b69eaf8669 | ||
|
85f8f5ec87 | ||
|
a9ab6b739c | ||
|
2e0d52f618 | ||
|
e91b946015 | ||
|
eaba45ebcb | ||
|
401318d812 | ||
|
dd06d5ccb2 | ||
|
3d397c1d35 | ||
|
b53fca6284 | ||
|
f1c3bb5c33 | ||
|
c4d92b3f00 | ||
|
8dcf5c4bca | ||
|
f0b745b291 | ||
|
bd97e81c32 | ||
|
5a0a3f2c14 | ||
|
f11ad19a4f | ||
|
464973839e | ||
|
848b907b1a | ||
|
3103a6d82c | ||
|
f43ba61252 | ||
|
84ecc89d20 | ||
|
5c764d1716 | ||
|
d56025f609 | ||
|
261a3d0c22 | ||
|
e78c0aa360 | ||
|
a629700b3c | ||
|
fbc738c8df | ||
|
f03bdc7e50 | ||
|
74c5ba7087 | ||
|
e61c4d03e5 | ||
|
f7b6f81c52 | ||
|
e2eba91ee2 | ||
|
f726ca930b | ||
|
3221d42d7b | ||
|
b9c66aaea6 | ||
|
60ee05aef7 | ||
|
00e9793f09 | ||
|
8a5f4afa91 | ||
|
de6f15c973 | ||
|
3d60b43196 | ||
|
3022da6b83 | ||
|
fd5a6389ec | ||
|
3f85140627 | ||
|
ee25355ba6 | ||
|
29718b5880 | ||
|
cc40178558 | ||
|
b2884dcd0b | ||
|
23af1419d0 | ||
|
fb85728597 | ||
|
3b62a65bea | ||
|
c99dd3d59d | ||
|
b7ee5c2ada | ||
|
2e4a9c11d3 | ||
|
9720651164 | ||
|
aeea69e674 | ||
|
139d1d92ae | ||
|
b7e8584260 | ||
|
4e198f0fe5 | ||
|
f13f409e5f | ||
|
88363b1113 | ||
|
7b257b4def | ||
|
50ba48fbfa | ||
|
66761d1950 | ||
|
44bdcd4920 | ||
|
74fbe7f549 | ||
|
8c82a19ca9 | ||
|
72a4cd0398 | ||
|
0636fb180e | ||
|
5bde9c6fb6 | ||
|
4c469a3f2c | ||
|
3d43bbb80d | ||
|
bdb3088a0c | ||
|
b84c36626a | ||
|
4513cf75b8 | ||
|
7476ff34de | ||
|
693bb5f09e | ||
|
bf01eb3b91 | ||
|
bf825d76cb | ||
|
2c8c883fbf | ||
|
5ef3562533 | ||
|
817a64ce0e | ||
|
274720f395 | ||
|
44366bd208 | ||
|
370d862acf | ||
|
6cecda5d40 | ||
|
5d1dcd204d | ||
|
f0dcf7ebe2 | ||
|
08084f35e3 | ||
|
77abbdba60 | ||
|
70b45fc3db | ||
|
de8afdd0a8 | ||
|
1d76beadeb | ||
|
99f1369e8c | ||
|
c73a19c319 | ||
|
9af1639168 | ||
|
f1fbd90ae6 | ||
|
d478ba05c4 | ||
|
d813b5c438 | ||
|
6b97b9289e | ||
|
dbc7bddf80 | ||
|
c42a9d5652 | ||
|
ef90da3fd1 | ||
|
96ddf0441c | ||
|
a92c34fe30 | ||
|
4fff9a0417 | ||
|
768afb8815 | ||
|
e8f58d7dd4 | ||
|
094066eceb | ||
|
94ae90dcaf | ||
|
5097989a4d | ||
|
ea58ed8831 | ||
|
8d9edcb31d | ||
|
9c51809490 | ||
|
d5af2f6ced | ||
|
ab1b7cf20f | ||
|
552e6ba35a | ||
|
dc2300d7ae | ||
|
1c06f69a03 | ||
|
0e8f076bab | ||
|
d66e3657a3 | ||
|
b788136508 | ||
|
1e8e2fcecc | ||
|
958f6ddffd | ||
|
854b054ed6 | ||
|
22d9c86b57 | ||
|
6399c64252 | ||
|
d809329044 | ||
|
3d9d6f51f4 | ||
|
82e109a4d5 | ||
|
465fdd8505 | ||
|
29a8e8062b | ||
|
0761329c61 | ||
|
0a3fa80e40 | ||
|
e82007e708 | ||
|
f8342527ca | ||
|
36e95649cc | ||
|
555aa71f59 | ||
|
49674bb431 | ||
|
3d80f1ae6f | ||
|
899587e4fa | ||
|
fe6201556b | ||
|
0862f03be2 | ||
|
ba2f63f8b0 | ||
|
62d87ab433 | ||
|
edb552df68 | ||
|
69908ae3c4 | ||
|
3967634933 | ||
|
fe749cfb9b |
50
.github/workflows/build.yaml
vendored
Normal file
50
.github/workflows/build.yaml
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
name: Build TDLib
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # weekly
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [linux/386, linux/amd64, linux/arm/v6, linux/arm/v7, linux/arm64, linux/ppc64le]
|
||||
|
||||
steps:
|
||||
- name: Setup variables
|
||||
run: |
|
||||
ARCH=${{ matrix.arch }}
|
||||
SAFE_ARCH=$(echo $ARCH | sed 's/\//\-/g')
|
||||
echo "SAFE_ARCH=$SAFE_ARCH" >> $GITHUB_ENV
|
||||
- name: Install sudo package
|
||||
run: |
|
||||
(apt-get update || true) 2>/dev/null
|
||||
(apt-get install -y sudo || true) 2>/dev/null
|
||||
sudo apt update
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: "recursive"
|
||||
- name: Cache ccache
|
||||
id: cache-ccache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ${{ runner.os }}-${{ env.SAFE_ARCH }}-ccache-all
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ env.SAFE_ARCH }}-ccache-
|
||||
- name: Install build tools
|
||||
run: sudo apt-get install -y make git zlib1g-dev libssl-dev gperf php-cli cmake clang-6.0 libc++-dev libc++abi-dev ccache
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
CXXFLAGS="-stdlib=libc++" CC=/usr/bin/clang-10 CXX=/usr/bin/clang++-10 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../tdlib ..
|
||||
cmake --build . --target install -- -j4
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: tdlight-${{ env.SAFE_ARCH }}
|
||||
path: tdlib/lib
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -4,4 +4,14 @@
|
||||
**/auto/
|
||||
docs/
|
||||
tdlib/
|
||||
.idea/
|
||||
vcpkg/
|
||||
*.tlo
|
||||
|
||||
td.binlog
|
||||
|
||||
tg_cli.log
|
||||
|
||||
tg_cli.log.old
|
||||
|
||||
.attach_pid*
|
||||
|
@ -1024,7 +1024,7 @@ Changes in 1.5.0 (9 Sep 2019):
|
||||
* Added the class `chatEventPollStopped` representing the closing of a poll in a message in the chat event log.
|
||||
* Added ability to specify the exact types of problems with a call in the method `sendCallRating` and
|
||||
the new class `CallProblem`.
|
||||
* Changes in [tdweb](https://github.com/tdlib/td/blob/master/example/web/):
|
||||
* Changes in [tdweb](https://github.com/tdlight-team/tdlight/blob/master/example/web/):
|
||||
- Supported non-zero `offset` and `limit` in `readFilePart`.
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
@ -1034,7 +1034,7 @@ Changes in 1.4.0 (1 May 2019):
|
||||
* Added a [TDLib build instructions generator](https://tdlib.github.io/td/build.html), covering in details
|
||||
TDLib building on the most popular operating systems.
|
||||
* Added an example of TDLib building and usage from a browser.
|
||||
See https://github.com/tdlib/td/blob/master/example/web/ for more details.
|
||||
See https://github.com/tdlight-team/tdlight/blob/master/example/web/ for more details.
|
||||
* Allowed to pass NULL pointer to `td_json_client_execute` instead of a previously created JSON client.
|
||||
Now you can use synchronous TDLib methods through a JSON interface before creating a TDLib JSON client.
|
||||
* Added support for media streaming by allowing to download any part of a file:
|
||||
@ -1285,7 +1285,7 @@ Changes in 1.4.0 (1 May 2019):
|
||||
|
||||
Changes in 1.3.0 (5 Sep 2018):
|
||||
|
||||
* Added a review of existing TDLib based [frameworks](https://github.com/tdlib/td/blob/master/example/README.md)
|
||||
* Added a review of existing TDLib based [frameworks](https://github.com/tdlight-team/tdlight/blob/master/example/README.md)
|
||||
in different programming languages.
|
||||
* Added a [Getting started](https://core.telegram.org/tdlib/getting-started) guide describing the main TDLib concepts
|
||||
and basic principles required for library usage.
|
||||
|
@ -7,50 +7,56 @@
|
||||
# riscv64 specific:
|
||||
# * https://lists.debian.org/debian-riscv/2022/01/msg00009.html
|
||||
#
|
||||
# ATOMICS_FOUND - system has c++ atomics
|
||||
# ATOMICS_LIBRARIES - libraries needed to use c++ atomics
|
||||
# ATOMICS_LIBRARY_FLAGS - flags required to link with c++ atomics library
|
||||
# ATOMICS_FOUND - system has C++ atomics
|
||||
# ATOMICS_LIBRARIES - libraries needed to use C++ atomics
|
||||
|
||||
if (ATOMICS_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
# RISC-V only has 32-bit and 64-bit atomic instructions. GCC is supposed
|
||||
# to convert smaller atomics to those larger ones via masking and
|
||||
# shifting like LLVM, but it’s a known bug that it does not. This means
|
||||
# shifting like LLVM, but it's a known bug that it does not. This means
|
||||
# anything that wants to use atomics on 1-byte or 2-byte types needs
|
||||
# -latomic, but not 4-byte or 8-byte (though it does no harm).
|
||||
set(atomic_code
|
||||
# to link atomic library, but not 4-byte or 8-byte (though it does no harm).
|
||||
set(ATOMIC_CODE
|
||||
"
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
std::atomic<uint8_t> n8 (0); // riscv64
|
||||
std::atomic<uint64_t> n64 (0); // armel, mipsel, powerpc
|
||||
int main() {
|
||||
++n8;
|
||||
++n64;
|
||||
return 0;
|
||||
}")
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
std::atomic<std::uint8_t> n8{0}; // riscv64
|
||||
std::atomic<std::uint64_t> n64{0}; // armel, mipsel, powerpc
|
||||
int main() {
|
||||
++n8;
|
||||
++n64;
|
||||
}")
|
||||
|
||||
check_cxx_source_compiles("${atomic_code}" ATOMICS_LOCK_FREE_INSTRUCTIONS)
|
||||
|
||||
if (ATOMICS_LOCK_FREE_INSTRUCTIONS)
|
||||
set(ATOMICS_FOUND TRUE)
|
||||
set(ATOMICS_LIBRARIES)
|
||||
set(ATOMICS_LIBRARY_FLAGS)
|
||||
else()
|
||||
set(CMAKE_REQUIRED_LIBRARIES "-latomic")
|
||||
check_cxx_source_compiles("${atomic_code}" ATOMICS_IN_LIBRARY)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
if (ATOMICS_IN_LIBRARY)
|
||||
set(ATOMICS_LIBRARY atomic)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Atomics DEFAULT_MSG ATOMICS_LIBRARY)
|
||||
set(ATOMICS_LIBRARIES ${ATOMICS_LIBRARY})
|
||||
set(ATOMICS_LIBRARY_FLAGS "-latomic")
|
||||
unset(ATOMICS_LIBRARY)
|
||||
else()
|
||||
if (Atomics_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Neither lock free instructions nor -latomic found.")
|
||||
endif()
|
||||
endif()
|
||||
set(ATOMICS_LIBS " " "-latomic")
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
set(ATOMICS_LIBS "${ATOMICS_LIBS}" /usr/pkg/gcc12/x86_64--netbsd/lib/libatomic.so /usr/pkg/gcc12/i486--netbsdelf/lib/libatomic.so)
|
||||
endif()
|
||||
unset(atomic_code)
|
||||
|
||||
foreach (ATOMICS_LIBRARY ${ATOMICS_LIBS})
|
||||
unset(ATOMICS_FOUND CACHE)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${ATOMICS_LIBRARY}")
|
||||
check_cxx_source_compiles("${ATOMIC_CODE}" ATOMICS_FOUND)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
if (ATOMICS_FOUND)
|
||||
if (NOT ATOMICS_LIBRARY STREQUAL " ")
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Atomics DEFAULT_MSG ATOMICS_LIBRARY)
|
||||
set(ATOMICS_LIBRARIES "${ATOMICS_LIBRARY}" CACHE STRING "Atomic library" FORCE)
|
||||
else()
|
||||
set(ATOMICS_LIBRARIES "" CACHE STRING "Atomic operations library" FORCE)
|
||||
endif()
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if (Atomics_FIND_REQUIRED AND NOT ATOMICS_FOUND)
|
||||
message(FATAL_ERROR "Atomic operations library isn't found.")
|
||||
endif()
|
||||
|
||||
unset(ATOMICS_LIBRARY)
|
||||
unset(ATOMICS_LIBS)
|
||||
unset(ATOMIC_CODE)
|
||||
|
@ -114,6 +114,23 @@ elseif (IOS_PLATFORM STREQUAL "TVSIMULATOR")
|
||||
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-tvsimulator")
|
||||
|
||||
set (APPLE_TV True)
|
||||
elseif (IOS_PLATFORM STREQUAL "VISIONOS")
|
||||
set (IOS_PLATFORM_LOCATION "XROS.platform")
|
||||
set (XCODE_IOS_PLATFORM xros)
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-xros")
|
||||
|
||||
set (APPLE_VISION True)
|
||||
elseif (IOS_PLATFORM STREQUAL "VISIONSIMULATOR")
|
||||
set (SIMULATOR_FLAG true)
|
||||
set (IOS_PLATFORM_LOCATION "XRSimulator.platform")
|
||||
set (XCODE_IOS_PLATFORM xros-simulator)
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-xrsimulator")
|
||||
|
||||
set (APPLE_VISION True)
|
||||
else (IOS_PLATFORM STREQUAL "OS")
|
||||
message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS, SIMULATOR, or WATCHOS.")
|
||||
endif ()
|
||||
@ -212,6 +229,10 @@ if (NOT DEFINED IOS_ARCH)
|
||||
set (IOS_ARCH "arm64")
|
||||
elseif (IOS_PLATFORM STREQUAL "TVSIMULATOR")
|
||||
set (IOS_ARCH "x86_64;arm64")
|
||||
elseif (IOS_PLATFORM STREQUAL "VISIONOS")
|
||||
set (IOS_ARCH "arm64")
|
||||
elseif (IOS_PLATFORM STREQUAL "VISIONSIMULATOR")
|
||||
set (IOS_ARCH "x86_64;arm64")
|
||||
endif()
|
||||
endif()
|
||||
message (STATUS "The iOS architectures: ${IOS_ARCH}")
|
||||
|
@ -6,7 +6,7 @@ if (POLICY CMP0065)
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
endif()
|
||||
|
||||
project(TDLib VERSION 1.8.25 LANGUAGES CXX C)
|
||||
project(TDLib VERSION 1.8.26 LANGUAGES CXX C)
|
||||
|
||||
if (NOT DEFINED CMAKE_MODULE_PATH)
|
||||
set(CMAKE_MODULE_PATH "")
|
||||
@ -73,15 +73,15 @@ if (POLICY CMP0069)
|
||||
endif()
|
||||
|
||||
# Configure CCache if available
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
#find_program(CCACHE_FOUND ccache)
|
||||
#set(CCACHE_FOUND 0)
|
||||
if (CCACHE_FOUND)
|
||||
message(STATUS "Found ccache")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
else()
|
||||
message(STATUS "Could NOT find ccache (this is NOT an error)")
|
||||
endif()
|
||||
#if (CCACHE_FOUND)
|
||||
# message(STATUS "Found ccache")
|
||||
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
# set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
#else()
|
||||
# message(STATUS "Could NOT find ccache (this is NOT an error)")
|
||||
#endif()
|
||||
|
||||
set(MEMPROF "" CACHE STRING "Use one of \"ON\", \"FAST\" or \"SAFE\" to enable memory profiling. \
|
||||
Works under macOS and Linux when compiled using glibc. \
|
||||
@ -129,11 +129,6 @@ if (THREADS_HAVE_PTHREAD_ARG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
endif()
|
||||
|
||||
find_package(Atomics REQUIRED)
|
||||
if (ATOMICS_LIBRARY_FLAGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ATOMICS_LIBRARY_FLAGS}")
|
||||
endif()
|
||||
|
||||
include(TdSetUpCompiler)
|
||||
td_set_up_compiler()
|
||||
|
||||
@ -212,9 +207,13 @@ add_subdirectory(sqlite)
|
||||
|
||||
add_subdirectory(tddb)
|
||||
|
||||
add_subdirectory(test)
|
||||
option(TD_SKIP_TEST "Use \"ON\" to skip building/running the test harness.")
|
||||
if (NOT TD_SKIP_TEST)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
option(TD_SKIP_BENCHMARK "Use \"ON\" to skip building/running the benchmarks.")
|
||||
if (NOT CMAKE_CROSSCOMPILING AND NOT TD_SKIP_BENCHMARK)
|
||||
add_subdirectory(benchmark)
|
||||
endif()
|
||||
|
||||
@ -306,6 +305,14 @@ set(TDLIB_SOURCE
|
||||
td/telegram/BotCommandScope.cpp
|
||||
td/telegram/BotInfoManager.cpp
|
||||
td/telegram/BotMenuButton.cpp
|
||||
td/telegram/BusinessAwayMessage.cpp
|
||||
td/telegram/BusinessAwayMessageSchedule.cpp
|
||||
td/telegram/BusinessConnectedBot.cpp
|
||||
td/telegram/BusinessGreetingMessage.cpp
|
||||
td/telegram/BusinessInfo.cpp
|
||||
td/telegram/BusinessManager.cpp
|
||||
td/telegram/BusinessRecipients.cpp
|
||||
td/telegram/BusinessWorkHours.cpp
|
||||
td/telegram/CallActor.cpp
|
||||
td/telegram/CallbackQueriesManager.cpp
|
||||
td/telegram/CallDiscardReason.cpp
|
||||
@ -456,6 +463,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PasswordManager.cpp
|
||||
td/telegram/Payments.cpp
|
||||
td/telegram/PeerColor.cpp
|
||||
td/telegram/PeopleNearbyManager.cpp
|
||||
td/telegram/PhoneNumberManager.cpp
|
||||
td/telegram/Photo.cpp
|
||||
td/telegram/PhotoSize.cpp
|
||||
@ -466,6 +474,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PrivacyManager.cpp
|
||||
td/telegram/QueryCombiner.cpp
|
||||
td/telegram/QueryMerger.cpp
|
||||
td/telegram/QuickReplyManager.cpp
|
||||
td/telegram/ReactionListType.cpp
|
||||
td/telegram/ReactionManager.cpp
|
||||
td/telegram/ReactionType.cpp
|
||||
@ -500,6 +509,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/StickersManager.cpp
|
||||
td/telegram/StickerType.cpp
|
||||
td/telegram/StorageManager.cpp
|
||||
td/telegram/MemoryManager.cpp
|
||||
td/telegram/StoryContent.cpp
|
||||
td/telegram/StoryContentType.cpp
|
||||
td/telegram/StoryDb.cpp
|
||||
@ -514,6 +524,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/TdDb.cpp
|
||||
td/telegram/TermsOfService.cpp
|
||||
td/telegram/ThemeManager.cpp
|
||||
td/telegram/TimeZoneManager.cpp
|
||||
td/telegram/TopDialogCategory.cpp
|
||||
td/telegram/TopDialogManager.cpp
|
||||
td/telegram/TranscriptionInfo.cpp
|
||||
@ -582,6 +593,14 @@ set(TDLIB_SOURCE
|
||||
td/telegram/BotCommandScope.h
|
||||
td/telegram/BotInfoManager.h
|
||||
td/telegram/BotMenuButton.h
|
||||
td/telegram/BusinessAwayMessage.h
|
||||
td/telegram/BusinessAwayMessageSchedule.h
|
||||
td/telegram/BusinessConnectedBot.h
|
||||
td/telegram/BusinessGreetingMessage.h
|
||||
td/telegram/BusinessInfo.h
|
||||
td/telegram/BusinessManager.h
|
||||
td/telegram/BusinessRecipients.h
|
||||
td/telegram/BusinessWorkHours.h
|
||||
td/telegram/CallActor.h
|
||||
td/telegram/CallDiscardReason.h
|
||||
td/telegram/CallId.h
|
||||
@ -777,6 +796,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PasswordManager.h
|
||||
td/telegram/Payments.h
|
||||
td/telegram/PeerColor.h
|
||||
td/telegram/PeopleNearbyManager.h
|
||||
td/telegram/PhoneNumberManager.h
|
||||
td/telegram/Photo.h
|
||||
td/telegram/PhotoFormat.h
|
||||
@ -791,6 +811,9 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PublicDialogType.h
|
||||
td/telegram/QueryCombiner.h
|
||||
td/telegram/QueryMerger.h
|
||||
td/telegram/QuickReplyManager.h
|
||||
td/telegram/QuickReplyMessageFullId.h
|
||||
td/telegram/QuickReplyShortcutId.h
|
||||
td/telegram/ReactionListType.h
|
||||
td/telegram/ReactionManager.h
|
||||
td/telegram/ReactionType.h
|
||||
@ -832,6 +855,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/StickersManager.h
|
||||
td/telegram/StickerType.h
|
||||
td/telegram/StorageManager.h
|
||||
td/telegram/MemoryManager.h
|
||||
td/telegram/StoryContent.h
|
||||
td/telegram/StoryContentType.h
|
||||
td/telegram/StoryDb.h
|
||||
@ -851,6 +875,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/TdDb.h
|
||||
td/telegram/TermsOfService.h
|
||||
td/telegram/ThemeManager.h
|
||||
td/telegram/TimeZoneManager.h
|
||||
td/telegram/TopDialogCategory.h
|
||||
td/telegram/TopDialogManager.h
|
||||
td/telegram/TranscriptionInfo.h
|
||||
@ -877,6 +902,13 @@ set(TDLIB_SOURCE
|
||||
td/telegram/AuthManager.hpp
|
||||
td/telegram/BackgroundInfo.hpp
|
||||
td/telegram/BackgroundType.hpp
|
||||
td/telegram/BusinessAwayMessage.hpp
|
||||
td/telegram/BusinessAwayMessageSchedule.hpp
|
||||
td/telegram/BusinessConnectedBot.hpp
|
||||
td/telegram/BusinessGreetingMessage.hpp
|
||||
td/telegram/BusinessInfo.hpp
|
||||
td/telegram/BusinessRecipients.hpp
|
||||
td/telegram/BusinessWorkHours.hpp
|
||||
td/telegram/ChatReactions.hpp
|
||||
td/telegram/DialogNotificationSettings.hpp
|
||||
td/telegram/DialogFilter.hpp
|
||||
@ -1098,6 +1130,8 @@ endif()
|
||||
|
||||
#EXECUTABLES
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
option(TD_SKIP_TG_CLI "Use \"ON\" to skip building tg_cli.")
|
||||
if (NOT CMAKE_CROSSCOMPILING AND NOT TD_SKIP_TG_CLI)
|
||||
add_executable(tg_cli td/telegram/cli.cpp ${TL_TD_JSON_SOURCE})
|
||||
|
||||
if (NOT READLINE_FOUND)
|
||||
@ -1126,6 +1160,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||
target_link_libraries(tg_cli PRIVATE memprof tdclient tdcore)
|
||||
add_dependencies(tg_cli tl_generate_json)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#Exported libraries
|
||||
add_library(TdStatic INTERFACE)
|
||||
|
58
README.md
58
README.md
@ -1,9 +1,12 @@
|
||||
# TDLib
|
||||
# TDLight
|
||||
|
||||
TDLib (Telegram Database library) is a cross-platform library for building [Telegram](https://telegram.org) clients. It can be easily used from almost any programming language.
|
||||
TDLight is a fork of TDLib, a cross-platform library for building [Telegram](https://telegram.org) clients. It can be easily used from almost any programming language.
|
||||
|
||||
## Table of Contents
|
||||
- [Features](#features)
|
||||
- [TDLight extra features](#tdlight-extra-features)
|
||||
- [TDLight extra API functions](#tdlight-extra-api-functions)
|
||||
- [TDLight recommended options](#tdlight-recommended-options)
|
||||
- [Examples and documentation](#usage)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Building](#building)
|
||||
@ -18,7 +21,7 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele
|
||||
|
||||
`TDLib` has many advantages. Notably `TDLib` is:
|
||||
|
||||
* **Cross-platform**: `TDLib` can be used on Android, iOS, Windows, macOS, Linux, FreeBSD, OpenBSD, NetBSD, illumos, Windows Phone, WebAssembly, watchOS, tvOS, Tizen, Cygwin. It should also work on other *nix systems with or without minimal effort.
|
||||
* **Cross-platform**: `TDLib` can be used on Android, iOS, Windows, macOS, Linux, FreeBSD, OpenBSD, NetBSD, illumos, Windows Phone, WebAssembly, watchOS, tvOS, visionOS, Tizen, Cygwin. It should also work on other *nix systems with or without minimal effort.
|
||||
* **Multilanguage**: `TDLib` can be easily used with any programming language that is able to execute C functions. Additionally, it already has native Java (using `JNI`) bindings and .NET (using `C++/CLI` and `C++/CX`) bindings.
|
||||
* **Easy to use**: `TDLib` takes care of all network implementation details, encryption and local data storage.
|
||||
* **High-performance**: in the [Telegram Bot API](https://core.telegram.org/bots/api), each `TDLib` instance handles more than 24000 active bots simultaneously.
|
||||
@ -28,17 +31,42 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele
|
||||
* **Secure**: all local data is encrypted using a user-provided encryption key.
|
||||
* **Fully-asynchronous**: requests to `TDLib` don't block each other or anything else, responses are sent when they are available.
|
||||
|
||||
<a name="tdlight-extra-features"></a>
|
||||
### TDLight extra features
|
||||
#### TDLight extra options
|
||||
* **disable_minithumbnails** (true/**false**) This setting removes minithumbnails everywhere. It reduces memory usage because tdlib keeps them in RAM
|
||||
* **disable_document_filenames** (true/**false**) If you don't care about having the original filenames of every file stored in RAM, you can disable them using this option. It reduces memory usage
|
||||
* **disable_notifications** (true/**false**) In TDLib pending notification updates are stored in ram until you "read" them. This option disables completely notifications and keeps the pending notifications queue empty, reducing memory usage
|
||||
* **ignore_update_chat_last_message** (true/**false**) If you don't care about have updateChatLastMessage updates enable this
|
||||
* **ignore_update_chat_read_inbox** (true/**false**) If you don't care about have updateChatReadInbox updates enable this
|
||||
* **ignore_update_user_chat_action** (true/**false**) If you don't care about have updateUserChatAction updates enable this
|
||||
* **ignore_server_deletes_and_reads** (true/**false**) If you don't care about receiving read receipts and remote deletes from other users, enable this, it will reduce memory usage
|
||||
* **receive_access_hashes** (true/**false**) Receive chats and users access hash as updates
|
||||
* **disable_auto_download** (true/**false**) Forcefully ignore auto download settings of all sessions
|
||||
<a name="tdlight-extra-api-functions"></a>
|
||||
### TDLight extra API functions
|
||||
#### TdApi.GetMemoryStatistics
|
||||
This method is used to read the size of all the internal TDLib data structures.
|
||||
The output contains a string that can be parsed as a JSON.
|
||||
<a name="tdlight-recommended-options"></a>
|
||||
## TDLight recommended options
|
||||
* Options:
|
||||
* ignore_inline_thumbnails: true
|
||||
* disable_top_chats: true
|
||||
* ignore_platform_restrictions: true
|
||||
* ignore_sensitive_content_restrictions: true
|
||||
* Disable all the databases (messages_db, users_db, files_db)
|
||||
<a name="usage"></a>
|
||||
## Examples and documentation
|
||||
See our [Getting Started](https://core.telegram.org/tdlib/getting-started) tutorial for a description of basic TDLib concepts.
|
||||
|
||||
Take a look at our [examples](https://github.com/tdlib/td/blob/master/example/README.md#tdlib-usage-and-build-examples).
|
||||
Take a look at our [examples](https://github.com/tdlight-team/tdlight/blob/master/example/README.md#tdlib-usage-and-build-examples).
|
||||
|
||||
See a [TDLib build instructions generator](https://tdlib.github.io/td/build.html) for detailed instructions on how to build TDLib.
|
||||
See a [TDLight build instructions generator](https://tdlight-team.github.io/tdlight/build.html) for detailed instructions on how to build TDLib.
|
||||
|
||||
See description of our [JSON](#using-json), [C++](#using-cxx), [Java](#using-java) and [.NET](#using-dotnet) interfaces.
|
||||
|
||||
See the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html)
|
||||
See the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html)
|
||||
for a list of all available `TDLib` [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
|
||||
|
||||
<a name="dependencies"></a>
|
||||
@ -55,7 +83,7 @@ for a list of all available `TDLib` [methods](https://core.telegram.org/tdlib/do
|
||||
<a name="building"></a>
|
||||
## Building
|
||||
|
||||
The simplest way to build `TDLib` is to use our [TDLib build instructions generator](https://tdlib.github.io/td/build.html).
|
||||
The simplest way to build `TDLight` is to use our [TDLight build instructions generator](https://tdlight-team.github.io/tdlight/build.html).
|
||||
You need only to choose your programming language and target operating system to receive complete build instructions.
|
||||
|
||||
In general, you need to install all `TDLib` [dependencies](#dependencies), enter directory containing `TDLib` sources and compile them using CMake:
|
||||
@ -67,7 +95,7 @@ cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
To build `TDLib` on low memory devices you can run [SplitSource.php](https://github.com/tdlib/td/blob/master/SplitSource.php) script
|
||||
To build `TDLib` on low memory devices you can run [SplitSource.php](https://github.com/tdlight-team/tdlight/blob/master/SplitSource.php) script
|
||||
before compiling main `TDLib` source code and compile only needed targets:
|
||||
```
|
||||
mkdir build
|
||||
@ -103,24 +131,24 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||
|
||||
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
||||
```
|
||||
find_package(Td 1.8.25 REQUIRED)
|
||||
find_package(Td 1.8.26 REQUIRED)
|
||||
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||
```
|
||||
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/blob/master/example/cpp/CMakeLists.txt).
|
||||
See [example/cpp/CMakeLists.txt](https://github.com/tdlight-team/tdlight/blob/master/example/cpp/CMakeLists.txt).
|
||||
|
||||
<a name="using-java"></a>
|
||||
## Using in Java projects
|
||||
`TDLib` provides native Java interface through JNI. To enable it, specify option `-DTD_ENABLE_JNI=ON` to CMake.
|
||||
|
||||
See [example/java](https://github.com/tdlib/td/tree/master/example/java) for example of using `TDLib` from Java and detailed build and usage instructions.
|
||||
See [example/java](https://github.com/tdlight-team/tdlight/tree/master/example/java) for example of using `TDLib` from Java and detailed build and usage instructions.
|
||||
|
||||
<a name="using-dotnet"></a>
|
||||
## Using in .NET projects
|
||||
`TDLib` provides native .NET interface through `C++/CLI` and `C++/CX`. To enable it, specify option `-DTD_ENABLE_DOTNET=ON` to CMake.
|
||||
.NET Core supports `C++/CLI` only since version 3.1 and only on Windows, so if older .NET Core is used or portability is needed, then `TDLib` JSON interface should be used through P/Invoke instead.
|
||||
|
||||
See [example/csharp](https://github.com/tdlib/td/tree/master/example/csharp) for example of using `TDLib` from C# and detailed build and usage instructions.
|
||||
See [example/uwp](https://github.com/tdlib/td/tree/master/example/uwp) for example of using `TDLib` from C# UWP application and detailed build and usage instructions for Visual Studio Extension "TDLib for Universal Windows Platform".
|
||||
See [example/csharp](https://github.com/tdlight-team/tdlight/tree/master/example/csharp) for example of using `TDLib` from C# and detailed build and usage instructions.
|
||||
See [example/uwp](https://github.com/tdlight-team/tdlight/tree/master/example/uwp) for example of using `TDLib` from C# UWP application and detailed build and usage instructions for Visual Studio Extension "TDLib for Universal Windows Platform".
|
||||
|
||||
When `TDLib` is built with `TD_ENABLE_DOTNET` option enabled, `C++` documentation is removed from some files. You need to checkout these files to return `C++` documentation back:
|
||||
```
|
||||
@ -132,13 +160,13 @@ git checkout td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
|
||||
`TDLib` provides efficient native C++, Java, and .NET interfaces.
|
||||
But for most use cases we suggest to use the JSON interface, which can be easily used with any programming language that is able to execute C functions.
|
||||
See [td_json_client](https://core.telegram.org/tdlib/docs/td__json__client_8h.html) documentation for detailed JSON interface description,
|
||||
the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of
|
||||
the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of
|
||||
all available `TDLib` [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
|
||||
|
||||
`TDLib` JSON interface adheres to semantic versioning and versions with the same major version number are binary and backward compatible, but the underlying `TDLib` API can be different for different minor and even patch versions.
|
||||
If you need to support different `TDLib` versions, then you can use a value of the `version` option to find exact `TDLib` version to use appropriate API methods.
|
||||
|
||||
See [example/python/tdjson_example.py](https://github.com/tdlib/td/blob/master/example/python/tdjson_example.py) for an example of such usage.
|
||||
See [example/python/tdjson_example.py](https://github.com/tdlight-team/tdlight/tree/master/example/python/tdjson_example.py) for an example of such usage.
|
||||
|
||||
<a name="license"></a>
|
||||
## License
|
||||
|
@ -309,6 +309,13 @@ function split_file($file, $chunks, $undo) {
|
||||
'BotMenuButton|[a-z_]*_menu_button' => 'BotMenuButton',
|
||||
'boost_manager[_(-](?![.]get[(][)])|BoostManager' => 'BoostManager',
|
||||
'bot_info_manager[_(-](?![.]get[(][)])|BotInfoManager' => 'BotInfoManager',
|
||||
'BusinessAwayMessage' => 'BusinessAwayMessage',
|
||||
'BusinessConnectedBot' => 'BusinessConnectedBot',
|
||||
'BusinessGreetingMessage' => 'BusinessGreetingMessage',
|
||||
'BusinessInfo|business_info' => 'BusinessInfo',
|
||||
'business_manager[_(-](?![.]get[(][)])|BusinessManager' => 'BusinessManager',
|
||||
'BusinessRecipients' => 'BusinessRecipients',
|
||||
'BusinessWorkHours' => 'BusinessWorkHours',
|
||||
'callback_queries_manager[_(-](?![.]get[(][)])|CallbackQueriesManager' => 'CallbackQueriesManager',
|
||||
'CallId' => 'CallId',
|
||||
'call_manager[_(-](?![.]get[(][)])|CallManager' => 'CallManager',
|
||||
@ -367,11 +374,13 @@ function split_file($file, $chunks, $undo) {
|
||||
'notification_settings_manager[_(-](?![.]get[(][)])|NotificationSettingsManager' => 'NotificationSettingsManager',
|
||||
'option_manager[_(-](?![.]get[(][)])|OptionManager' => 'OptionManager',
|
||||
'password_manager[_(-](?![.]get[(][)])|PasswordManager' => 'PasswordManager',
|
||||
'people_nearby_manager[_(-](?![.]get[(][)])|PeopleNearbyManager' => 'PeopleNearbyManager',
|
||||
'[a-z_]*phone_number_manager[_(-](?![.]get[(][)])|PhoneNumberManager' => 'PhoneNumberManager',
|
||||
'PhotoSizeSource' => 'PhotoSizeSource',
|
||||
'poll_manager[_(-](?![.]get[(][)])|PollManager' => 'PollManager',
|
||||
'privacy_manager[_(-](?![.]get[(][)])|PrivacyManager' => 'PrivacyManager',
|
||||
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
||||
'quick_reply_manager[_(-](?![.]get[(][)])|QuickReplyManager' => 'QuickReplyManager',
|
||||
'ReactionListType|[a-z_]*_reaction_list_type' => 'ReactionListType',
|
||||
'reaction_manager[_(-](?![.]get[(][)])|ReactionManager' => 'ReactionManager',
|
||||
'ReactionType|[a-z_]*_reaction_type' => 'ReactionType',
|
||||
@ -396,6 +405,7 @@ function split_file($file, $chunks, $undo) {
|
||||
'td_db[(][)]|TdDb[^A-Za-z]' => 'TdDb',
|
||||
'telegram_api' => 'telegram_api',
|
||||
'theme_manager[_(-](?![.]get[(][)])|ThemeManager' => 'ThemeManager',
|
||||
'time_zone_manager[_(-](?![.]get[(][)])|TimeZoneManager' => 'TimeZoneManager',
|
||||
'TopDialogCategory|get_top_dialog_category' => 'TopDialogCategory',
|
||||
'top_dialog_manager[_(-](?![.]get[(][)])|TopDialogManager' => 'TopDialogManager',
|
||||
'translation_manager[_(-](?![.]get[(][)])|TranslationManager' => 'TranslationManager',
|
||||
|
378
UpdateMemoryManager.javash
Executable file
378
UpdateMemoryManager.javash
Executable file
@ -0,0 +1,378 @@
|
||||
#!/usr/bin/java --source 21
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.SequencedSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class UpdateMemoryManager {
|
||||
|
||||
static final Set<String> EXCLUDED_MANAGERS = Set.of("Memory",
|
||||
"Call",
|
||||
"DeviceToken",
|
||||
"LanguagePack",
|
||||
"Pts",
|
||||
"Password",
|
||||
"SecretChats",
|
||||
"Secure",
|
||||
"Config",
|
||||
"Storage",
|
||||
"FileLoad",
|
||||
"Parts",
|
||||
"FileGenerate",
|
||||
"Resource",
|
||||
"NetStats",
|
||||
"DcAuth",
|
||||
"State",
|
||||
"PhoneNumber"
|
||||
);
|
||||
|
||||
record Manager(Path directory, String name) {
|
||||
String includePath() {
|
||||
return directory.toString().substring(2) + "/" + name + "Manager.h";
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
System.err.println("Arguments: PATH");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
var path = Path.of(args[0]);
|
||||
var telegramPath = path.resolve("td/telegram");
|
||||
|
||||
var memoryManager = new Manager(telegramPath, "Memory");
|
||||
SequencedSet<Manager> managers;
|
||||
try (var stream = Files.walk(telegramPath, 16)) {
|
||||
var endNamePattern = "Manager.h";
|
||||
managers = stream
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(p -> p.getFileName().toString().endsWith(endNamePattern))
|
||||
.map(p -> new Manager(p.getParent(), p.getFileName().toString().substring(0, p.getFileName().toString().length() - endNamePattern.length())))
|
||||
.filter(name -> !EXCLUDED_MANAGERS.contains(name.name))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
System.out.printf("Found %d managers%n", managers.size());
|
||||
|
||||
int fieldsFound = 0;
|
||||
int updatedManagers = 0;
|
||||
int totalManagers = 0;
|
||||
List<Manager> invalidManagers = new ArrayList<>();
|
||||
for (Manager manager : managers) {
|
||||
totalManagers++;
|
||||
var result = updateManagerJson(manager);
|
||||
if (result != null) {
|
||||
fieldsFound += result.fieldsFound();
|
||||
if (result.changed) {
|
||||
updatedManagers++;
|
||||
}
|
||||
} else {
|
||||
invalidManagers.add(manager);
|
||||
}
|
||||
}
|
||||
|
||||
updateMemoryManagerJson(memoryManager, managers);
|
||||
|
||||
System.out.printf("%n%nDone.%n");
|
||||
|
||||
if (!invalidManagers.isEmpty()) {
|
||||
System.out.printf("%d invalid managers found:%n%s",
|
||||
invalidManagers.size(),
|
||||
invalidManagers.stream()
|
||||
.map(x -> "\t\"" + x.directory + "\": " + x.name + "\n")
|
||||
.collect(Collectors.joining(", ")));
|
||||
}
|
||||
System.out.printf("%d/%d managers updated, %d total fields%n", updatedManagers, totalManagers, fieldsFound);
|
||||
}
|
||||
|
||||
enum FieldType {
|
||||
WaitFreeHashMap("WaitFreeHashMap", "calc_size"),
|
||||
WaitFreeHashSet("WaitFreeHashSet", "calc_size"),
|
||||
Vector("vector", "size"),
|
||||
FlatHashMap("FlatHashMap", "size"),
|
||||
FlatHashSet("FlatHashSet", "size")
|
||||
;
|
||||
|
||||
private final String fieldName;
|
||||
private final String sizeMethodName;
|
||||
public final Pattern pattern;
|
||||
|
||||
FieldType(String fieldName, String sizeMethodName) {
|
||||
this.fieldName = fieldName;
|
||||
this.sizeMethodName = sizeMethodName;
|
||||
this.pattern = Pattern.compile("^ {2}(mutable )?" + fieldName + "(<([^ ]|, )+>)? +(?<field>[a-zA-Z_]+);?[ \t/]*$");
|
||||
}
|
||||
|
||||
Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
|
||||
record FoundField(FieldType type, String name) {}
|
||||
record UpdateResult(boolean changed, int fieldsFound) {}
|
||||
|
||||
private static UpdateResult updateManagerJson(Manager manager) throws IOException {
|
||||
Path hFile = manager.directory.resolve(manager.name + "Manager.h");
|
||||
Path cppFile = manager.directory.resolve(manager.name + "Manager.cpp");
|
||||
|
||||
System.out.printf("Updating manager \"%s\" files: [\"%s\", \"%s\"]%n", manager.name, hFile, cppFile);
|
||||
|
||||
if (Files.notExists(hFile)) {
|
||||
System.out.printf("File not found, ignoring manager \"%s\": \"%s\"%n", manager.name, hFile);
|
||||
return null;
|
||||
}
|
||||
if (Files.notExists(cppFile)) {
|
||||
System.out.printf("File not found, ignoring manager \"%s\": \"%s\"%n", manager.name, cppFile);
|
||||
return null;
|
||||
}
|
||||
|
||||
List<FoundField> fields = new ArrayList<>();
|
||||
|
||||
var hLines = normalizeSourceFile(readSourceFile(hFile));
|
||||
|
||||
boolean currentClass = false;
|
||||
for (String hLine : hLines) {
|
||||
FoundField field = null;
|
||||
if (hLine.startsWith("class ")) {
|
||||
currentClass = hLine.contains(" " + manager.name + "Manager");
|
||||
}
|
||||
|
||||
if (currentClass) {
|
||||
for (FieldType possibleFieldType : FieldType.values()) {
|
||||
var m = possibleFieldType.getPattern().matcher(hLine);
|
||||
if (m.matches()) {
|
||||
var fieldName = m.group("field");
|
||||
field = new FoundField(possibleFieldType, fieldName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (field != null) {
|
||||
System.out.println("\tFound field: (%s) %s".formatted(field.type, field.name));
|
||||
fields.add(field);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StringBuilder memoryStatsMethod = new StringBuilder();
|
||||
|
||||
memoryStatsMethod.append("void %sManager::memory_stats(vector<string> &output) {\n".formatted(manager.name));
|
||||
memoryStatsMethod.append(fields.stream()
|
||||
.map(field -> " output.emplace_back(\"\\\"%s\\\":\"); output.emplace_back(std::to_string(this->%s.%s()));\n".formatted(field.name, field.name, field.type.sizeMethodName))
|
||||
.collect(Collectors.joining(" output.emplace_back(\",\");\n")));
|
||||
memoryStatsMethod.append("}\n");
|
||||
|
||||
List<String> memoryStatsMethodLines = Arrays.asList(memoryStatsMethod.toString().split("\n"));
|
||||
|
||||
var cppLines = readSourceFile(cppFile);
|
||||
var inputCppLines = new ArrayList<>(cppLines);
|
||||
|
||||
// Remove the old memory_stats method
|
||||
var indexOfMemoryStatsStart = -1;
|
||||
var indexOfMemoryStatsEnd = -1;
|
||||
for (int i = 0; i < cppLines.size(); i++) {
|
||||
if (cppLines.get(i).contains("::memory_stats(")) {
|
||||
indexOfMemoryStatsStart = i;
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
if (cppLines.get(j).isBlank()) {
|
||||
indexOfMemoryStatsStart = j;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (indexOfMemoryStatsStart != -1) {
|
||||
for (int i = indexOfMemoryStatsStart + 1; i < cppLines.size(); i++) {
|
||||
if (cppLines.get(i).trim().equals("}")) {
|
||||
indexOfMemoryStatsEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (indexOfMemoryStatsEnd == -1) {
|
||||
throw new IllegalStateException("memory_stats method end not found");
|
||||
}
|
||||
cppLines.subList(indexOfMemoryStatsStart, indexOfMemoryStatsEnd + 1).clear();
|
||||
}
|
||||
|
||||
var last = cppLines.removeLast();
|
||||
cppLines.addAll(memoryStatsMethodLines);
|
||||
cppLines.add("");
|
||||
cppLines.addLast(last);
|
||||
|
||||
boolean changed = !Objects.equals(inputCppLines, cppLines);
|
||||
|
||||
if (changed) {
|
||||
System.out.printf("\tDone: %s.cpp file has been updated!%n", manager.name);
|
||||
Files.write(cppFile, cppLines, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
System.out.printf("\tDone: %s.cpp file did not change.%n", manager.name);
|
||||
}
|
||||
|
||||
return new UpdateResult(changed, fields.size());
|
||||
}
|
||||
|
||||
private static void updateMemoryManagerJson(Manager manager, SequencedSet<Manager> managers) throws IOException {
|
||||
Path hFile = manager.directory.resolve(manager.name + "Manager.h");
|
||||
Path cppFile = manager.directory.resolve(manager.name + "Manager.cpp");
|
||||
|
||||
System.out.printf("Updating memory manager \"%s\" files: [\"%s\", \"%s\"]%n", manager.name, hFile, cppFile);
|
||||
|
||||
if (Files.notExists(hFile)) {
|
||||
System.out.printf("File not found for manager \"%s\": \"%s\"%n", manager.name, hFile);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
if (Files.notExists(cppFile)) {
|
||||
System.out.printf("File not found for manager \"%s\": \"%s\"%n", manager.name, cppFile);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder memoryStatsMethod = new StringBuilder();
|
||||
|
||||
memoryStatsMethod.append("void %sManager::print_managers_memory_stats(vector<string> &output) const {\n".formatted(manager.name));
|
||||
memoryStatsMethod.append(managers.stream()
|
||||
.map(m -> """
|
||||
output.emplace_back("\\"%s_manager_\\":{"); td_->%s_manager_->memory_stats(output); output.emplace_back("}");
|
||||
""".formatted(toSnakeCase(m.name), toSnakeCase(m.name)))
|
||||
.collect(Collectors.joining(" output.emplace_back(\",\");\n")));
|
||||
memoryStatsMethod.append("}\n");
|
||||
|
||||
List<String> memoryStatsMethodLines = Arrays.asList(memoryStatsMethod.toString().split("\n"));
|
||||
|
||||
var cppLines = readSourceFile(cppFile);
|
||||
var inputCppLines = new ArrayList<>(cppLines);
|
||||
|
||||
// Remove the old memory_stats method
|
||||
var indexOfMemoryStatsStart = -1;
|
||||
var indexOfMemoryStatsEnd = -1;
|
||||
for (int i = 0; i < cppLines.size(); i++) {
|
||||
if (cppLines.get(i).contains("::print_managers_memory_stats(")) {
|
||||
indexOfMemoryStatsStart = i;
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
if (cppLines.get(j).isBlank()) {
|
||||
indexOfMemoryStatsStart = j;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (indexOfMemoryStatsStart != -1) {
|
||||
for (int i = indexOfMemoryStatsStart + 1; i < cppLines.size(); i++) {
|
||||
if (cppLines.get(i).trim().equals("}")) {
|
||||
indexOfMemoryStatsEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (indexOfMemoryStatsEnd == -1) {
|
||||
throw new IllegalStateException("print_managers_memory_stats method end not found");
|
||||
}
|
||||
cppLines.subList(indexOfMemoryStatsStart, indexOfMemoryStatsEnd + 1).clear();
|
||||
}
|
||||
|
||||
var last = cppLines.removeLast();
|
||||
cppLines.addAll(memoryStatsMethodLines);
|
||||
cppLines.add("");
|
||||
cppLines.addLast(last);
|
||||
|
||||
for (Manager m : managers) {
|
||||
var mInclude = "#include \"%s\"".formatted(m.includePath());
|
||||
if (!cppLines.contains(mInclude)) {
|
||||
System.out.printf("\tMissing include, adding \"" + m.includePath() + "\"%n");
|
||||
int includeInsertIndex = -1;
|
||||
for (int i = 0; i < cppLines.size(); i++) {
|
||||
if (cppLines.get(i).startsWith("#include")) {
|
||||
includeInsertIndex = i;
|
||||
}
|
||||
}
|
||||
if (includeInsertIndex == -1) {
|
||||
throw new IllegalStateException("Cannot find a place to put the include");
|
||||
}
|
||||
cppLines.add(includeInsertIndex + 1, mInclude);
|
||||
}
|
||||
}
|
||||
|
||||
boolean changed = !Objects.equals(inputCppLines, cppLines);
|
||||
|
||||
if (changed) {
|
||||
System.out.printf("\tDone: %s.cpp file has been updated!%n", manager.name);
|
||||
Files.write(cppFile, cppLines, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
System.out.printf("\tDone: %s.cpp file did not change.%n", manager.name);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toSnakeCase(String name) {
|
||||
var initialChar = name.codePoints()
|
||||
.limit(1)
|
||||
.map(Character::toLowerCase);
|
||||
var restOfString = name.codePoints()
|
||||
.skip(1)
|
||||
.flatMap(codePoint -> {
|
||||
if (Character.isUpperCase(codePoint)) {
|
||||
return IntStream.of('_', Character.toLowerCase(codePoint));
|
||||
} else {
|
||||
return IntStream.of(codePoint);
|
||||
}
|
||||
});
|
||||
var resultStream = IntStream.concat(initialChar, restOfString);
|
||||
return resultStream.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
|
||||
}
|
||||
|
||||
private static List<String> readSourceFile(Path path) throws IOException {
|
||||
return Files.readAllLines(path, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static List<String> normalizeSourceFile(List<String> lines) throws IOException {
|
||||
List<String> srcLines = new ArrayList<>(lines);
|
||||
|
||||
// Remove empty lines
|
||||
srcLines.removeIf(String::isBlank);
|
||||
|
||||
// Remove unexpected newlines
|
||||
List<String> srcLinesWithoutNewlines = new ArrayList<>();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (String srcLine : srcLines) {
|
||||
if (!buf.isEmpty()) {
|
||||
buf.append(" ");
|
||||
}
|
||||
buf.append(srcLine);
|
||||
var trimmedLine = srcLine.trim();
|
||||
if (!trimmedLine.endsWith(">")) {
|
||||
srcLinesWithoutNewlines.add(buf.toString());
|
||||
buf.setLength(0);
|
||||
}
|
||||
}
|
||||
if (!buf.isEmpty()) {
|
||||
srcLinesWithoutNewlines.add(buf.toString());
|
||||
}
|
||||
|
||||
srcLinesWithoutNewlines.replaceAll(p -> {
|
||||
var commentStart = p.indexOf("//");
|
||||
if (commentStart >= 0) {
|
||||
return p.substring(0, commentStart);
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
});
|
||||
|
||||
return srcLinesWithoutNewlines;
|
||||
}
|
||||
}
|
56
build.html
56
build.html
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>TDLib build instructions</title>
|
||||
<title>TDLight build instructions</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style>
|
||||
:root {
|
||||
@ -193,7 +193,7 @@
|
||||
|
||||
<div class="main">
|
||||
<div id="languageSelectDiv">
|
||||
<p>Choose a programming language from which you want to use TDLib:</p>
|
||||
<p>Choose a programming language from which you want to use TDLight:</p>
|
||||
<select id="languageSelect" onchange="onLanguageChanged(false)" autofocus class="large">
|
||||
<option>Choose a programming language:</option>
|
||||
<option>Python</option>
|
||||
@ -226,7 +226,7 @@
|
||||
</div>
|
||||
|
||||
<div id="osSelectDiv" class="hide">
|
||||
<p>Choose an operating system on which you want to use TDLib:</p>
|
||||
<p>Choose an operating system on which you want to use TDLight:</p>
|
||||
<select id="osSelect" onchange="onOsChanged()" class="large">
|
||||
<option>Choose an operating system:</option>
|
||||
</select>
|
||||
@ -234,7 +234,7 @@
|
||||
</div>
|
||||
|
||||
<div id="linuxSelectDiv" class="hide">
|
||||
<p>Choose a Linux distro on which you want to use TDLib:</p>
|
||||
<p>Choose a Linux distro on which you want to use TDLight:</p>
|
||||
<select id="linuxSelect" onchange="onOsChanged()" class="large">
|
||||
<option>Choose a Linux distro:</option>
|
||||
<option>Alpine</option>
|
||||
@ -263,13 +263,13 @@
|
||||
</div>
|
||||
|
||||
<div id="buildInstallLocalDiv" class="hide">
|
||||
<label><input type="checkbox" id="buildInstallLocalCheckbox" onchange="onOptionsChanged()"/>Install built TDLib to /usr/local instead of placing the files to td/tdlib.</label>
|
||||
<label><input type="checkbox" id="buildInstallLocalCheckbox" onchange="onOptionsChanged()"/>Install built TDLight to /usr/local instead of placing the files to td/tdlib.</label>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<div id="buildCompilerDiv" class="hide">
|
||||
<span>Choose which compiler you want to use to build TDLib:</span><br>
|
||||
<span>Choose which compiler you want to use to build TDLight:</span><br>
|
||||
<label><input type="radio" id="buildCompilerRadioGcc" name="buildCompilerRadio" onchange="onOptionsChanged()" checked/>g++</label>
|
||||
<label><input type="radio" id="buildCompilerRadioClang" name="buildCompilerRadio" onchange="onOptionsChanged()"/>clang (recommended)</label>
|
||||
<p></p>
|
||||
@ -305,7 +305,7 @@
|
||||
</div>
|
||||
|
||||
<div id="buildBitnessDiv" class="hide">
|
||||
<span>Choose for which bitness you want to build TDLib:</span><br>
|
||||
<span>Choose for which bitness you want to build TDLight:</span><br>
|
||||
<label><input type="radio" id="buildBitnessRadio32" name="buildBitnessRadio" onchange="onOptionsChanged()" checked/>32</label>
|
||||
<label><input type="radio" id="buildBitnessRadio64" name="buildBitnessRadio" onchange="onOptionsChanged()"/>64</label>
|
||||
<p></p>
|
||||
@ -327,7 +327,7 @@
|
||||
</div>
|
||||
|
||||
<div id="buildCommandsDiv" class="hide">
|
||||
<p id="buildCommandsHeader">Here is complete instruction for TDLib binaries building:</p>
|
||||
<p id="buildCommandsHeader">Here is complete instruction for TDLight binaries building:</p>
|
||||
<p id="buildPre">Hidden text</p>
|
||||
<code id="buildCommands">Empty commands</code>
|
||||
<button id="copyBuildCommandsButton" onclick="copyBuildInstructions()">
|
||||
@ -368,10 +368,10 @@ function getSupportedOs(language) {
|
||||
case 'C#':
|
||||
return ['Windows (through C++/CLI)', 'Universal Windows Platform (through C++/CX)', 'Windows (.NET Core)', 'Linux (.NET Core)', 'macOS (.NET Core)', 'FreeBSD (.NET Core)'];
|
||||
case 'Dart':
|
||||
return ['Android', 'iOS', 'Windows', 'Linux', 'macOS', 'tvOS', 'watchOS'];
|
||||
return ['Android', 'iOS', 'Windows', 'Linux', 'macOS', 'tvOS', 'visionOS', 'watchOS'];
|
||||
case 'Swift':
|
||||
case 'Objective-C':
|
||||
return ['Windows', 'Linux', 'macOS', 'iOS', 'tvOS', 'watchOS'];
|
||||
return ['Windows', 'Linux', 'macOS', 'iOS', 'tvOS', 'visionOS', 'watchOS'];
|
||||
default:
|
||||
return ['Windows', 'Linux', 'macOS', 'FreeBSD', 'OpenBSD', 'NetBSD'];
|
||||
}
|
||||
@ -474,7 +474,7 @@ function getTarget(language, os) {
|
||||
if (os.includes('Android')) {
|
||||
return 'Android';
|
||||
}
|
||||
if (os.includes('iOS') || os.includes('tvOS') || os.includes('watchOS')) {
|
||||
if (os.includes('iOS') || os.includes('tvOS') || os.includes('visionOS') || os.includes('watchOS')) {
|
||||
return 'iOS';
|
||||
}
|
||||
|
||||
@ -494,14 +494,14 @@ function getTargetName(target) {
|
||||
case 'tdjson':
|
||||
case 'WebAssembly':
|
||||
case 'iOS':
|
||||
return '<a href="https://github.com/tdlib/td#using-json">JSON</a>';
|
||||
return '<a href="https://github.com/tdlight-team/tdlight#using-json">JSON</a>';
|
||||
case 'tdclient':
|
||||
return '<a href="https://github.com/tdlib/td#using-cxx">a simple and convenient C++11-interface</a>';
|
||||
return '<a href="https://github.com/tdlight-team/tdlight#using-cxx">a simple and convenient C++11-interface</a>';
|
||||
case 'JNI':
|
||||
case 'Android':
|
||||
return '<a href="https://github.com/tdlib/td#using-java">native ' + target + '</a>';
|
||||
return '<a href="https://github.com/tdlight-team/tdlight#using-java">native ' + target + '</a>';
|
||||
default:
|
||||
return '<a href="https://github.com/tdlib/td#using-dotnet">native ' + target + '</a>';
|
||||
return '<a href="https://github.com/tdlight-team/tdlight#using-dotnet">native ' + target + '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
@ -515,17 +515,17 @@ function onOsChanged() {
|
||||
if (language === 'Other') {
|
||||
language = 'any other programming language';
|
||||
}
|
||||
var text = 'TDLib can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' +
|
||||
'See <a href="https://github.com/tdlib/td/blob/master/example/README.md#' + getExampleAnchor(language) + '">examples</a> of such usage and already available third-party frameworks.<br>';
|
||||
var text = 'TDLight can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' +
|
||||
'See <a href="https://github.com/tdlight-team/tdlight/blob/master/example/README.md#' + getExampleAnchor(language) + '">examples</a> of such usage and already available third-party frameworks.<br>';
|
||||
|
||||
if (target === 'WebAssembly') {
|
||||
text = 'TDLib is available in a prebuilt form as an <a href="https://www.npmjs.com/">NPM</a> package <a href="https://www.npmjs.com/package/tdweb">tdweb</a>.<br>' +
|
||||
'If you want to build it manually, take a look at our <a href="https://github.com/tdlib/td/tree/master/example/web">example</a>.';
|
||||
text = 'TDLight is available in a prebuilt form as an <a href="https://www.npmjs.com/">NPM</a> package <a href="https://www.npmjs.com/package/tdweb">tdweb</a>.<br>' +
|
||||
'If you want to build it manually, take a look at our <a href="https://github.com/tdlight-team/tdlight/tree/master/example/web">example</a>.';
|
||||
target = '';
|
||||
}
|
||||
if (target === 'Android') {
|
||||
text = 'TDLib for Android is available in a prebuilt form and can be downloaded from <a href="https://core.telegram.org/tdlib/tdlib.zip">there</a>.<br>' +
|
||||
'See <a href="https://github.com/tdlib/td/issues/77#issuecomment-640719893">build instructions</a> if you want to build the latest TDLib version or want to build TDLib with different interface.';
|
||||
text = 'TDLight for Android is available in a prebuilt form and can be downloaded from <a href="https://core.telegram.org/tdlight-team/tdlightlib.zip">there</a>.<br>' +
|
||||
'See <a href="https://github.com/tdlight-team/tdlight/issues/77#issuecomment-640719893">build instructions</a> if you want to build the latest TDLight version or want to build TDLight with different interface.';
|
||||
target = '';
|
||||
}
|
||||
if (target === 'iOS') {
|
||||
@ -590,7 +590,7 @@ function onOptionsChanged() {
|
||||
if (os_linux || os_freebsd || os_netbsd) {
|
||||
low_memory = document.getElementById('buildLowMemoryCheckbox').checked;
|
||||
document.getElementById('buildLowMemoryText').innerHTML = 'I have less than ' + (use_clang ? '1.5' : '3.5') +' GB of RAM.' +
|
||||
(low_memory ? ' Now you will need only ' + (use_clang ? '0.5' : '1') +' GB of RAM to build TDLib.' : '');
|
||||
(low_memory ? ' Now you will need only ' + (use_clang ? '0.5' : '1') +' GB of RAM to build TDLight.' : '');
|
||||
document.getElementById('buildLowMemoryDiv').style.display = 'block';
|
||||
} else {
|
||||
if (os_openbsd) {
|
||||
@ -751,8 +751,8 @@ function onOptionsChanged() {
|
||||
pre_text.push('Note that the following instruction is for NetBSD 8+ and default SH shell.');
|
||||
}
|
||||
if (os_mac) {
|
||||
pre_text.push('Note that the following instruction will build TDLib only for ' + os_mac_host_name + '.');
|
||||
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.');
|
||||
pre_text.push('Note that the following instruction will build TDLight only for ' + os_mac_host_name + '.');
|
||||
pre_text.push('If you want to create a universal XCFramework, take a look at our <a href="https://github.com/tdlight-team/tdlight/tree/master/example/ios">example</a> instead.');
|
||||
}
|
||||
|
||||
var terminal_name = (function () {
|
||||
@ -776,12 +776,12 @@ function onOptionsChanged() {
|
||||
if (os_windows) {
|
||||
pre_text.push('Close and re-open ' + terminal_name + ' if the PATH environment variable was changed.');
|
||||
}
|
||||
pre_text.push('Run these commands in ' + terminal_name + ' to build TDLib and to install it to ' + install_dir + ':');
|
||||
pre_text.push('Run these commands in ' + terminal_name + ' to build TDLight and to install it to ' + install_dir + ':');
|
||||
document.getElementById('buildPre').innerHTML = '<ul><li>' + pre_text.join('</li><li>') + '</li></ul>';
|
||||
document.getElementById('buildPre').style.display = 'block';
|
||||
|
||||
if (install_dir && install_dir !== '/usr/local') {
|
||||
install_dir = '../tdlib';
|
||||
install_dir = '../tdlight';
|
||||
if (target === 'JNI' || target === 'C++/CX') {
|
||||
install_dir = '../../' + install_dir;
|
||||
}
|
||||
@ -926,9 +926,9 @@ function onOptionsChanged() {
|
||||
commands.push('exit');
|
||||
}
|
||||
}
|
||||
commands.push('git clone https://github.com/tdlib/td.git');
|
||||
commands.push('git clone https://github.com/tdlight-team/tdlight.git');
|
||||
|
||||
commands.push('cd td');
|
||||
commands.push('cd tdlight');
|
||||
// commands.push('git checkout v1.8.0');
|
||||
|
||||
if (use_vcpkg) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
# TDLib usage and build examples
|
||||
|
||||
This directory contains basic examples of TDLib usage from different programming languages and examples of library building for different platforms.
|
||||
If you are looking for documentation of all available TDLib methods, see the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or the
|
||||
If you are looking for documentation of all available TDLib methods, see the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or the
|
||||
automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of all available TDLib
|
||||
[methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
|
||||
Also, take a look at our [Getting Started](https://core.telegram.org/tdlib/getting-started) tutorial for a description of basic TDLib concepts.
|
||||
@ -54,13 +54,13 @@ If you want to use TDLib with asyncio and Python >= 3.9, take a look at [aiotdli
|
||||
For older Python versions you can use [pytdlib](https://github.com/pytdlib/pytdlib).
|
||||
This wrapper contains generator for TDLib API classes and basic interface for interaction with TDLib.
|
||||
|
||||
You can also check out [example/python/tdjson_example.py](https://github.com/tdlib/td/blob/master/example/python/tdjson_example.py),
|
||||
You can also check out [example/python/tdjson_example.py](https://github.com/tdlight-team/tdlight/blob/master/example/python/tdjson_example.py),
|
||||
[tdlib-python](https://github.com/JunaidBabu/tdlib-python), or [Python Wrapper TDLib](https://github.com/alvhix/pywtdlib) for some basic examples of TDLib JSON interface integration with Python.
|
||||
|
||||
<a name="javascript"></a>
|
||||
## Using TDLib in JavaScript projects
|
||||
|
||||
TDLib can be compiled to WebAssembly or asm.js and used in a browser from JavaScript. See [tdweb](https://github.com/tdlib/td/tree/master/example/web) as a convenient wrapper for TDLib in a browser
|
||||
TDLib can be compiled to WebAssembly or asm.js and used in a browser from JavaScript. See [tdweb](https://github.com/tdlight-team/tdlight/tree/master/example/web) as a convenient wrapper for TDLib in a browser
|
||||
and [telegram-react](https://github.com/evgeny-nadymov/telegram-react) as an example of a TDLib-based Telegram client.
|
||||
|
||||
See also [Svelte-tdweb-starter](https://github.com/gennadypolakov/svelte-tdweb-starter) - Svelte wrapper for tdweb, and [Telegram-Photoframe](https://github.com/lukefx/telegram-photoframe) - a web application that displays your preferred group or channel as Photoframe.
|
||||
@ -95,7 +95,7 @@ You can also see [github.com/aliforever/go-tdlib](https://github.com/aliforever/
|
||||
TDLib can be used from the Java programming language through native [JNI](https://github.com/tdlib/td#using-java) binding.
|
||||
|
||||
We provide a generator for JNI bridge methods and Java classes for all TDLib API methods and objects.
|
||||
See [example/java](https://github.com/tdlib/td/tree/master/example/java) for an example of using TDLib from desktop Java along with detailed building and usage instructions.
|
||||
See [example/java](https://github.com/tdlight-team/tdlight/tree/master/example/java) for an example of using TDLib from desktop Java along with detailed building and usage instructions.
|
||||
To use TDLib to create Android Java applications, use our [prebuilt library for Android](https://core.telegram.org/tdlib/tdlib.zip).
|
||||
|
||||
<a name="kotlin"></a>
|
||||
@ -112,8 +112,8 @@ See also [td-ktx](https://github.com/tdlibx/td-ktx) - Kotlin coroutines wrapper
|
||||
|
||||
TDLib provides a native [.NET](https://github.com/tdlib/td#using-dotnet) interface through `C++/CLI` and `C++/CX`.
|
||||
See [tdlib-netcore](https://github.com/dantmnf/tdlib-netcore) for a SWIG-like binding with automatically generated classes for TDLib API.
|
||||
See [example/uwp](https://github.com/tdlib/td/tree/master/example/uwp) for an example of building TDLib SDK for the Universal Windows Platform and an example of its usage from C#.
|
||||
See [example/csharp](https://github.com/tdlib/td/tree/master/example/csharp) for an example of building TDLib with `C++/CLI` support and an example of TDLib usage from C# on Windows.
|
||||
See [example/uwp](https://github.com/tdlight-team/tdlight/tree/master/example/uwp) for an example of building TDLib SDK for the Universal Windows Platform and an example of its usage from C#.
|
||||
See [example/csharp](https://github.com/tdlight-team/tdlight/tree/master/example/csharp) for an example of building TDLib with `C++/CLI` support and an example of TDLib usage from C# on Windows.
|
||||
|
||||
If you want to write a cross-platform C# application using .NET Core, see [tdsharp](https://github.com/egramtel/tdsharp). It uses our [JSON](https://github.com/tdlib/td#using-json) interface,
|
||||
provides an asynchronous interface for interaction with TDLib, automatically generated classes for TDLib API and has some examples.
|
||||
@ -127,8 +127,8 @@ Also, see [Unigram](https://github.com/UnigramDev/Unigram), which is a full-feat
|
||||
|
||||
TDLib has a simple and convenient C++11-interface for sending and receiving requests and can be statically linked to your application.
|
||||
|
||||
See [example/cpp](https://github.com/tdlib/td/tree/master/example/cpp) for an example of TDLib usage from C++.
|
||||
[td_example.cpp](https://github.com/tdlib/td/blob/master/example/cpp/td_example.cpp) contains an example of authorization, processing new incoming messages, getting a list of chats and sending a text message.
|
||||
See [example/cpp](https://github.com/tdlight-team/tdlight/tree/master/example/cpp) for an example of TDLib usage from C++.
|
||||
[td_example.cpp](https://github.com/tdlight-team/tdlight/blob/master/example/cpp/td_example.cpp) contains an example of authorization, processing new incoming messages, getting a list of chats and sending a text message.
|
||||
|
||||
See also the source code of [Fernschreiber](https://github.com/Wunderfitz/harbour-fernschreiber) and [Depecher](https://github.com/blacksailer/depecher) – Telegram apps for Sailfish OS,
|
||||
[TELEports](https://gitlab.com/ubports/development/apps/teleports) – a Qt-client for Ubuntu Touch, [tdlib-purple](https://github.com/ars3niy/tdlib-purple) - Telegram plugin for Pidgin,
|
||||
@ -140,20 +140,20 @@ or [MeeGram](https://github.com/qtinsider/meegram2) - a Telegram client for Noki
|
||||
|
||||
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 [example/ios](https://github.com/tdlight-team/tdlight/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, visionOS, and macOS.
|
||||
|
||||
See [TDLibKit](https://github.com/Swiftgram/TDLibKit), [tdlib-swift](https://github.com/modestman/tdlib-swift), or [TDLib-iOS](https://github.com/leoMehlig/TDLib-iOS), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
|
||||
|
||||
See also the source code of [Moc](https://github.com/mock-foundation/moc) - a native and powerful macOS and iPadOS Telegram client, optimized for moderating large communities and personal use.
|
||||
|
||||
See [example/swift](https://github.com/tdlib/td/tree/master/example/swift) for an example of a macOS Swift application.
|
||||
See [example/swift](https://github.com/tdlight-team/tdlight/tree/master/example/swift) for an example of a macOS Swift application.
|
||||
|
||||
<a name="objective-c"></a>
|
||||
## Using TDLib in Objective-C projects
|
||||
|
||||
TDLib can be used from the Objective-C programming language through [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 [example/ios](https://github.com/tdlight-team/tdlight/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, visionOS, and macOS.
|
||||
|
||||
<a name="object-pascal"></a>
|
||||
## Using TDLib in Object Pascal projects with Delphi and Lazarus
|
||||
@ -300,7 +300,7 @@ TDLib can be used from the C programming language through the [JSON](https://git
|
||||
|
||||
See [easy-tg](https://github.com/Trumeet/easy-tg) for an example of such usage.
|
||||
|
||||
You can also try to use our [C](https://github.com/tdlib/td/blob/master/td/telegram/td_c_client.h) client, which was used by the private TDLib-based version of [telegram-cli](https://github.com/vysheng/tg).
|
||||
You can also try to use our [C](https://github.com/tdlight-team/tdlight/blob/master/td/telegram/td_c_client.h) client, which was used by the private TDLib-based version of [telegram-cli](https://github.com/vysheng/tg).
|
||||
|
||||
<a name="g"></a>
|
||||
## Using TDLib from G projects
|
||||
|
@ -21,4 +21,4 @@ You can specify different OpenSSL version as the fourth parameter to the script
|
||||
|
||||
You can build TDLib against shared standard C++ library by specifying "c++_shared" as the fourth parameter to the script `./build-tdlib.sh`. This can reduce total application size if you have a lot of other C++ code and want it to use the same shared library.
|
||||
|
||||
Alternatively, you can use Docker to build TDLib for Android. Use `docker build --output tdlib .` to build the latest TDLib commit from Github, or `docker build --build-arg COMMIT_HASH=<commit-hash> --output tdlib .` to build specific commit. The output archives will be placed in the tdlib directory as specified.
|
||||
Alternatively, you can use Docker to build TDLib for Android. Use `docker build --output tdlib .` to build the latest TDLib commit from Github, or `docker build --build-arg COMMIT_HASH=<commit-hash> --output tdlib .` to build specific commit. The output archives will be placed in the directory "tdlib" as specified.
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
|
||||
|
||||
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
find_package(Td 1.8.25 REQUIRED)
|
||||
find_package(Td 1.8.26 REQUIRED)
|
||||
|
||||
add_executable(tdjson_example tdjson_example.cpp)
|
||||
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
||||
|
@ -1,8 +1,8 @@
|
||||
diff --git a/Makefile b/Makefile
|
||||
index a1d13e9..a0841cf 100644
|
||||
index a1d13e9..8efcf20 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -18,8 +18,11 @@
|
||||
@@ -18,8 +18,13 @@
|
||||
# - OpenSSL - build OpenSSL for all platforms
|
||||
# - OpenSSL-macOS - build OpenSSL for macOS
|
||||
# - OpenSSL-iOS - build OpenSSL for iOS
|
||||
@ -11,10 +11,12 @@ index a1d13e9..a0841cf 100644
|
||||
+# - OpenSSL-tvOS-simulator - build OpenSSL for tvOS-simulator
|
||||
# - OpenSSL-watchOS - build OpenSSL for watchOS
|
||||
+# - OpenSSL-watchOS-simulator - build OpenSSL for watchOS-simulator
|
||||
+# - OpenSSL-visionOS - build OpenSSL for visionOS
|
||||
+# - OpenSSL-visionOS-simulator - build OpenSSL for visionOS-simulator
|
||||
# - libFFI - build libFFI for all platforms (except macOS)
|
||||
# - libFFI-iOS - build libFFI for iOS
|
||||
# - libFFI-tvOS - build libFFI for tvOS
|
||||
@@ -50,7 +53,7 @@ XZ_VERSION=5.4.2
|
||||
@@ -50,7 +55,7 @@ XZ_VERSION=5.4.2
|
||||
# Preference is to use OpenSSL 3; however, Cryptography 3.4.8 (and
|
||||
# probably some other packages as well) only works with 1.1.1, so
|
||||
# we need to preserve the ability to build the older OpenSSL (for now...)
|
||||
@ -23,16 +25,16 @@ index a1d13e9..a0841cf 100644
|
||||
# OPENSSL_VERSION_NUMBER=1.1.1
|
||||
# OPENSSL_REVISION=q
|
||||
# OPENSSL_VERSION=$(OPENSSL_VERSION_NUMBER)$(OPENSSL_REVISION)
|
||||
@@ -59,7 +62,7 @@ LIBFFI_VERSION=3.4.2
|
||||
@@ -59,7 +64,7 @@ LIBFFI_VERSION=3.4.2
|
||||
|
||||
# Supported OS and dependencies
|
||||
DEPENDENCIES=BZip2 XZ OpenSSL libFFI
|
||||
-OS_LIST=macOS iOS tvOS watchOS
|
||||
+OS_LIST=macOS iOS iOS-simulator tvOS tvOS-simulator watchOS watchOS-simulator
|
||||
+OS_LIST=macOS iOS iOS-simulator tvOS tvOS-simulator watchOS watchOS-simulator visionOS visionOS-simulator
|
||||
|
||||
CURL_FLAGS=--disable --fail --location --create-dirs --progress-bar
|
||||
|
||||
@@ -69,22 +72,34 @@ VERSION_MIN-macOS=10.15
|
||||
@@ -69,22 +74,41 @@ VERSION_MIN-macOS=10.15
|
||||
CFLAGS-macOS=-mmacosx-version-min=$(VERSION_MIN-macOS)
|
||||
|
||||
# iOS targets
|
||||
@ -66,11 +68,29 @@ index a1d13e9..a0841cf 100644
|
||||
+# watchOS-simulator targets
|
||||
+TARGETS-watchOS-simulator=watchsimulator.i386 watchsimulator.x86_64 watchsimulator.arm64
|
||||
+CFLAGS-watchOS-simulator=-mwatchos-simulator-version-min=$(VERSION_MIN-watchOS)
|
||||
+
|
||||
+# visionOS targets
|
||||
+TARGETS-visionOS=xros.arm64
|
||||
+PYTHON_CONFIGURE-visionOS=ac_cv_func_sigaltstack=no
|
||||
+
|
||||
+# visionOS-simulator targets
|
||||
+TARGETS-visionOS-simulator=xrsimulator.x86_64 xrsimulator.arm64
|
||||
+
|
||||
# The architecture of the machine doing the build
|
||||
HOST_ARCH=$(shell uname -m)
|
||||
HOST_PYTHON=install/macOS/macosx/python-$(PYTHON_VERSION)
|
||||
@@ -662,7 +677,7 @@ BZIP2_FATLIB-$(sdk)=$$(BZIP2_MERGE-$(sdk))/lib/libbz2.a
|
||||
@@ -212,6 +236,10 @@ ARCH-$(target)=$$(subst .,,$$(suffix $(target)))
|
||||
|
||||
ifeq ($(os),macOS)
|
||||
TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-darwin
|
||||
+else ifeq ($(os),visionOS)
|
||||
+TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-xros
|
||||
+else ifeq ($(os),visionOS-simulator)
|
||||
+TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-xros-simulator
|
||||
else
|
||||
ifeq ($$(findstring simulator,$$(SDK-$(target))),)
|
||||
TARGET_TRIPLE-$(target)=$$(ARCH-$(target))-apple-$$(OS_LOWER-$(target))
|
||||
@@ -662,7 +690,7 @@ BZIP2_FATLIB-$(sdk)=$$(BZIP2_MERGE-$(sdk))/lib/libbz2.a
|
||||
XZ_MERGE-$(sdk)=$(PROJECT_DIR)/merge/$(os)/$(sdk)/xz-$(XZ_VERSION)
|
||||
XZ_FATLIB-$(sdk)=$$(XZ_MERGE-$(sdk))/lib/liblzma.a
|
||||
|
||||
@ -79,7 +99,7 @@ index a1d13e9..a0841cf 100644
|
||||
OPENSSL_FATINCLUDE-$(sdk)=$$(OPENSSL_MERGE-$(sdk))/include
|
||||
OPENSSL_SSL_FATLIB-$(sdk)=$$(OPENSSL_MERGE-$(sdk))/lib/libssl.a
|
||||
OPENSSL_CRYPTO_FATLIB-$(sdk)=$$(OPENSSL_MERGE-$(sdk))/lib/libcrypto.a
|
||||
@@ -716,14 +731,14 @@ $$(OPENSSL_SSL_FATLIB-$(sdk)): $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(OPENS
|
||||
@@ -716,14 +744,14 @@ $$(OPENSSL_SSL_FATLIB-$(sdk)): $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(OPENS
|
||||
mkdir -p $$(OPENSSL_MERGE-$(sdk))/lib
|
||||
lipo -create -output $$@ \
|
||||
$$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(OPENSSL_SSL_LIB-$$(target))) \
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Universal XCFramework build example
|
||||
|
||||
Below are instructions for building TDLib for iOS, watchOS, tvOS, and also macOS.
|
||||
Below are instructions for building TDLib for iOS, watchOS, tvOS, visionOS, and also macOS.
|
||||
|
||||
If you need only a macOS build for the current architecture, take a look at [TDLib build instructions generator](https://tdlib.github.io/td/build.html).
|
||||
|
||||
For example of usage take a look at our [Swift example](https://github.com/tdlib/td/tree/master/example/swift).
|
||||
For example of usage take a look at our [Swift example](https://github.com/tdlight-team/tdlight/tree/master/example/swift).
|
||||
|
||||
To compile `TDLib` you will need to:
|
||||
* Install the latest Xcode via `xcode-select --install` or downloading it from [Xcode website](https://developer.apple.com/xcode/).
|
||||
@ -21,7 +21,7 @@ cd native-build
|
||||
cmake ..
|
||||
cmake --build . --target prepare_cross_compiling
|
||||
```
|
||||
* Build OpenSSL for iOS, watchOS, tvOS, and macOS:
|
||||
* Build OpenSSL for iOS, watchOS, tvOS, visionOS, and macOS:
|
||||
```
|
||||
cd <path to TDLib sources>/example/ios
|
||||
./build-openssl.sh
|
||||
@ -30,14 +30,14 @@ Here we use scripts from [Python Apple support](https://github.com/beeware/Pytho
|
||||
[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 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:
|
||||
* Build TDLib for iOS, watchOS, tvOS, visionOS, and macOS:
|
||||
```
|
||||
cd <path to TDLib sources>/example/ios
|
||||
./build.sh
|
||||
```
|
||||
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.
|
||||
We use [CMake/iOS.cmake](https://github.com/tdlib/td/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
|
||||
We use [CMake/iOS.cmake](https://github.com/tdlight-team/tdlight/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
|
||||
|
||||
Built libraries and XCFramework will be stored in `tdjson` directory.
|
||||
|
||||
|
@ -8,7 +8,7 @@ git reset --hard || exit 1
|
||||
git apply ../Python-Apple-support.patch || exit 1
|
||||
cd ..
|
||||
|
||||
platforms="macOS iOS watchOS tvOS"
|
||||
platforms="macOS iOS watchOS tvOS visionOS"
|
||||
|
||||
for platform in $platforms;
|
||||
do
|
||||
|
@ -21,7 +21,7 @@ set_cmake_options () {
|
||||
options="$options -DCMAKE_BUILD_TYPE=Release"
|
||||
}
|
||||
|
||||
platforms="macOS iOS watchOS tvOS"
|
||||
platforms="macOS iOS watchOS tvOS visionOS"
|
||||
#platforms="watchOS"
|
||||
for platform in $platforms;
|
||||
do
|
||||
@ -41,6 +41,8 @@ do
|
||||
ios_platform="WATCH"
|
||||
elif [[ $platform = "tvOS" ]]; then
|
||||
ios_platform="TV"
|
||||
elif [[ $platform = "visionOS" ]]; then
|
||||
ios_platform="VISION"
|
||||
else
|
||||
ios_platform=""
|
||||
fi
|
||||
|
@ -3,7 +3,7 @@
|
||||
To run this example, you will need installed JDK >= 1.6.
|
||||
For Javadoc documentation generation PHP is needed.
|
||||
|
||||
You can find complete build instructions for your operating system at https://tdlib.github.io/td/build.html?language=Java.
|
||||
You can find complete build instructions for your operating system at https://tdlight-team.github.io/tdlight/build.html?language=Java.
|
||||
|
||||
In general, the build process looks as follows.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Telegram.Td.UWP</id>
|
||||
<version>1.8.25</version>
|
||||
<version>1.8.26</version>
|
||||
<title>TDLib for Universal Windows Platform</title>
|
||||
<authors>Telegram</authors>
|
||||
<owners>Telegram</owners>
|
||||
|
@ -1,12 +1,12 @@
|
||||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
||||
<Metadata>
|
||||
<Identity Id="Telegram.Td.UWP" Version="1.8.25" Language="en-US" Publisher="Telegram LLC" />
|
||||
<Identity Id="Telegram.Td.UWP" Version="1.8.26" Language="en-US" Publisher="Telegram LLC" />
|
||||
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
||||
<Description>TDLib is a library for building Telegram clients</Description>
|
||||
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
||||
<Tags>Telegram, TDLib, library, client, API</Tags>
|
||||
<License>LICENSE_1_0.txt</License>
|
||||
<ReleaseNotes>https://github.com/tdlib/td/blob/master/CHANGELOG.md</ReleaseNotes>
|
||||
<ReleaseNotes>https://github.com/tdlight-team/tdlight/blob/master/CHANGELOG.md</ReleaseNotes>
|
||||
</Metadata>
|
||||
<Installation Scope="Global">
|
||||
<InstallationTarget Id="Microsoft.ExtensionSDK" TargetPlatformIdentifier="UAP" TargetPlatformVersion="v0.8.0.0" SdkName="Telegram.Td.UWP" SdkVersion="1.0" />
|
||||
|
@ -26,4 +26,4 @@ cd <path to TDLib sources>/example/web
|
||||
|
||||
## Using tdweb NPM package
|
||||
|
||||
See [tdweb](https://www.npmjs.com/package/tdweb) or [README.md](https://github.com/tdlib/td/tree/master/example/web/tdweb/README.md) for package documentation.
|
||||
See [tdweb](https://www.npmjs.com/package/tdweb) or [README.md](https://github.com/tdlight-team/tdlight/tree/master/example/web/tdweb/README.md) for package documentation.
|
||||
|
@ -8,11 +8,11 @@ Once this is done, you can send queries to the TDLib instance using the method `
|
||||
|
||||
See [Getting Started](https://core.telegram.org/tdlib/getting-started) for a description of basic TDLib concepts and a short introduction to TDLib usage.
|
||||
|
||||
See the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or
|
||||
See the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or
|
||||
the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of all available
|
||||
TDLib [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
|
||||
The JSON representation of TDLib API objects is straightforward: all API objects are represented as JSON objects with the same keys as the API object field names in the
|
||||
[td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme. Note that in the automatically generated C++ documentation all fields have an additional terminating underscore
|
||||
[td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme. Note that in the automatically generated C++ documentation all fields have an additional terminating underscore
|
||||
which shouldn't be used in the JSON interface. The object type name is stored in the special field '@type' which is optional in places where type is uniquely determined by the context.
|
||||
Fields of Bool type are stored as Boolean, fields of int32, int53, and double types are stored as Number, fields of int64 and string types are stored as String,
|
||||
fields of bytes type are base64 encoded and then stored as String, fields of array type are stored as Array.
|
||||
|
@ -65,7 +65,7 @@ class TdClient {
|
||||
*
|
||||
* If the query contains the field '@extra', the same field will be added into the result.
|
||||
*
|
||||
* @param {Object} query - The query for TDLib. See the [td_api.tl]{@link https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl} scheme or
|
||||
* @param {Object} query - The query for TDLib. See the [td_api.tl]{@link https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl} scheme or
|
||||
* the automatically generated [HTML documentation]{@link https://core.telegram.org/tdlib/docs/td__api_8h.html}
|
||||
* for a list of all available TDLib [methods]{@link https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html} and
|
||||
* [classes]{@link https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html}.
|
||||
|
1
td/generate/scheme/.gitignore
vendored
Normal file
1
td/generate/scheme/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.tlo
|
@ -561,6 +561,21 @@ userTypeBot can_be_edited:Bool can_join_groups:Bool can_read_all_group_messages:
|
||||
//@description No information on the user besides the user identifier is available, yet this user has not been deleted. This object is extremely rare and must be handled like a deleted user. It is not possible to perform any actions on users of this type
|
||||
userTypeUnknown = UserType;
|
||||
|
||||
//@class AccessHashType @description Represents the type of an access hash. The following types are possible: user, channel
|
||||
|
||||
//@description An access hash of an user
|
||||
accessHashTypeUser = AccessHashType;
|
||||
|
||||
//@description An access hash of a channel
|
||||
accessHashTypeChannel = AccessHashType;
|
||||
|
||||
|
||||
//@description Access hash
|
||||
//@chat_id Chat identifier
|
||||
//@type Access hash type
|
||||
//@access_hash Access hash
|
||||
accessHash chat_id:int53 type:AccessHashType access_hash:int64 = AccessHash;
|
||||
|
||||
|
||||
//@description Represents a command supported by a bot @command Text of the bot command @param_description Description of the bot command
|
||||
botCommand command:string description:string = BotCommand;
|
||||
@ -576,6 +591,67 @@ botMenuButton text:string url:string = BotMenuButton;
|
||||
chatLocation location:location address:string = ChatLocation;
|
||||
|
||||
|
||||
//@class BusinessAwayMessageSchedule @description Describes conditions for sending of away messages by a Telegram Business account
|
||||
|
||||
//@description Send away messages always
|
||||
businessAwayMessageScheduleAlways = BusinessAwayMessageSchedule;
|
||||
|
||||
//@description Send away messages outside of the business opening hours
|
||||
businessAwayMessageScheduleOutsideOfOpeningHours = BusinessAwayMessageSchedule;
|
||||
|
||||
//@description Send away messages only in the specified time span
|
||||
//@start_date Point in time (Unix timestamp) when the away messages will start to be sent
|
||||
//@end_date Point in time (Unix timestamp) when the away messages will stop to be sent
|
||||
businessAwayMessageScheduleCustom start_date:int32 end_date:int32 = BusinessAwayMessageSchedule;
|
||||
|
||||
|
||||
//@description Represents a location of a business @location The location; may be null if not specified @address Location address; 1-96 characters
|
||||
businessLocation location:location address:string = BusinessLocation;
|
||||
|
||||
//@description Describes private chats chosen for automatic interaction with a business
|
||||
//@chat_ids Identifiers of selected private chats
|
||||
//@select_existing_chats True, if all existing private chats are selected
|
||||
//@select_new_chats True, if all new private chats are selected
|
||||
//@select_contacts True, if all private chats with contacts are selected
|
||||
//@select_non_contacts True, if all private chats with non-contacts are selected
|
||||
//@exclude_selected If true, then all private chats except the selected are chosen. Otherwise, only the selected chats are chosen
|
||||
businessRecipients chat_ids:vector<int53> select_existing_chats:Bool select_new_chats:Bool select_contacts:Bool select_non_contacts:Bool exclude_selected:Bool = BusinessRecipients;
|
||||
|
||||
//@description Describes settings for messages that are automatically sent by a Telegram Business account when it is away
|
||||
//@shortcut_id Unique quick reply shortcut identifier for the away messages
|
||||
//@recipients Chosen recipients of the away messages
|
||||
//@schedule Settings used to check whether the current user is away
|
||||
//@offline_only True, if the messages must not be sent if the account was online in the last 10 minutes
|
||||
businessAwayMessageSettings shortcut_id:int32 recipients:businessRecipients schedule:BusinessAwayMessageSchedule offline_only:Bool = BusinessAwayMessageSettings;
|
||||
|
||||
//@description Describes settings for greeting messages that are automatically sent by a Telegram Business account as response to incoming messages in an inactive private chat
|
||||
//@shortcut_id Unique quick reply shortcut identifier for the greeting messages
|
||||
//@recipients Chosen recipients of the greeting messages
|
||||
//@inactivity_days The number of days after which a chat will be considered as inactive; currently, must be on of 7, 14, 21, or 28
|
||||
businessGreetingMessageSettings shortcut_id:int32 recipients:businessRecipients inactivity_days:int32 = BusinessGreetingMessageSettings;
|
||||
|
||||
//@description Describes a bot connected to a business account
|
||||
//@bot_user_id User identifier of the bot
|
||||
//@recipients Private chats that will be accessible to the bot
|
||||
//@can_reply True, if the bot can send messages to the private chats; false otherwise
|
||||
businessConnectedBot bot_user_id:int53 recipients:businessRecipients can_reply:Bool = BusinessConnectedBot;
|
||||
|
||||
//@description Describes an interval of time when the business is open
|
||||
//@start_minute The first minute of the interval since start of the week; 0-7*24*60
|
||||
//@end_minute The first minute after the end of the interval since start of the week; 1-8*24*60
|
||||
businessOpeningHoursInterval start_minute:int32 end_minute:int32 = BusinessOpeningHoursInterval;
|
||||
|
||||
//@description Describes opening hours of a business @time_zone_id Unique time zone identifier @opening_hours Intervals of the time when the business is open
|
||||
businessOpeningHours time_zone_id:string opening_hours:vector<businessOpeningHoursInterval> = BusinessOpeningHours;
|
||||
|
||||
//@description Contains information about a Telegram Business account
|
||||
//@location Location of the business; may be null if none
|
||||
//@opening_hours Opening hours of the business; may be null if none. The hours are guaranteed to be valid and has already been split by week days
|
||||
//@greeting_message_settings The greeting message; may be null if none or the Business account is not of the current user
|
||||
//@away_message_settings The away message; may be null if none or the Business account is not of the current user
|
||||
businessInfo location:businessLocation opening_hours:businessOpeningHours greeting_message_settings:businessGreetingMessageSettings away_message_settings:businessAwayMessageSettings = BusinessInfo;
|
||||
|
||||
|
||||
//@class ChatPhotoStickerType @description Describes type of a sticker, which was used to create a chat photo
|
||||
|
||||
//@description Information about the sticker, which was used to create the chat photo
|
||||
@ -847,8 +923,9 @@ botInfo short_description:string description:string photo:photo animation:animat
|
||||
//@bio A short user bio; may be null for bots
|
||||
//@premium_gift_options The list of available options for gifting Telegram Premium to the user
|
||||
//@group_in_common_count Number of group chats where both the other user and the current user are a member; 0 for the current user
|
||||
//@business_info Information about business settings for Telegram Business accounts; may be null if none
|
||||
//@bot_info For bots, information about the bot; may be null if the user isn't a bot
|
||||
userFullInfo personal_photo:chatPhoto photo:chatPhoto public_photo:chatPhoto block_list:BlockList can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool has_restricted_voice_and_video_note_messages:Bool has_pinned_stories:Bool need_phone_number_privacy_exception:Bool set_chat_background:Bool bio:formattedText premium_gift_options:vector<premiumPaymentOption> group_in_common_count:int32 bot_info:botInfo = UserFullInfo;
|
||||
userFullInfo personal_photo:chatPhoto photo:chatPhoto public_photo:chatPhoto block_list:BlockList can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool has_restricted_voice_and_video_note_messages:Bool has_pinned_stories:Bool need_phone_number_privacy_exception:Bool set_chat_background:Bool bio:formattedText premium_gift_options:vector<premiumPaymentOption> group_in_common_count:int32 business_info:businessInfo bot_info:botInfo = UserFullInfo;
|
||||
|
||||
//@description Represents a list of users @total_count Approximate total number of users found @user_ids A list of user identifiers
|
||||
users total_count:int32 user_ids:vector<int53> = Users;
|
||||
@ -1560,6 +1637,7 @@ chatFolderIcon name:string = ChatFolderIcon;
|
||||
//@description Represents a folder for user chats
|
||||
//@title The title of the folder; 1-12 characters without line feeds
|
||||
//@icon The chosen icon for the chat folder; may be null. If null, use getChatFolderDefaultIconName to get default icon name for the folder
|
||||
//@color_id The identifier of the chosen color for the chat folder icon; from -1 to 6. If -1, then color is didabled
|
||||
//@is_shareable True, if at least one link has been created for the folder
|
||||
//@pinned_chat_ids The chat identifiers of pinned chats in the folder. There can be up to getOption("chat_folder_chosen_chat_count_max") pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium
|
||||
//@included_chat_ids The chat identifiers of always included chats in the folder. There can be up to getOption("chat_folder_chosen_chat_count_max") pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium
|
||||
@ -1572,15 +1650,16 @@ chatFolderIcon name:string = ChatFolderIcon;
|
||||
//@include_bots True, if bots need to be included
|
||||
//@include_groups True, if basic groups and supergroups need to be included
|
||||
//@include_channels True, if channels need to be included
|
||||
chatFolder title:string icon:chatFolderIcon is_shareable:Bool pinned_chat_ids:vector<int53> included_chat_ids:vector<int53> excluded_chat_ids:vector<int53> exclude_muted:Bool exclude_read:Bool exclude_archived:Bool include_contacts:Bool include_non_contacts:Bool include_bots:Bool include_groups:Bool include_channels:Bool = ChatFolder;
|
||||
chatFolder title:string icon:chatFolderIcon color_id:int32 is_shareable:Bool pinned_chat_ids:vector<int53> included_chat_ids:vector<int53> excluded_chat_ids:vector<int53> exclude_muted:Bool exclude_read:Bool exclude_archived:Bool include_contacts:Bool include_non_contacts:Bool include_bots:Bool include_groups:Bool include_channels:Bool = ChatFolder;
|
||||
|
||||
//@description Contains basic information about a chat folder
|
||||
//@id Unique chat folder identifier
|
||||
//@title The title of the folder; 1-12 characters without line feeds
|
||||
//@icon The chosen or default icon for the chat folder
|
||||
//@color_id The identifier of the chosen color for the chat folder icon; from -1 to 6. If -1, then color is didabled
|
||||
//@is_shareable True, if at least one link has been created for the folder
|
||||
//@has_my_invite_links True, if the chat folder has invite links created by the current user
|
||||
chatFolderInfo id:int32 title:string icon:chatFolderIcon is_shareable:Bool has_my_invite_links:Bool = ChatFolderInfo;
|
||||
chatFolderInfo id:int32 title:string icon:chatFolderIcon color_id:int32 is_shareable:Bool has_my_invite_links:Bool = ChatFolderInfo;
|
||||
|
||||
//@description Contains a chat folder invite link
|
||||
//@invite_link The chat folder invite link
|
||||
@ -1680,6 +1759,7 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa
|
||||
//@permissions Actions that non-administrator chat members are allowed to take in the chat
|
||||
//@last_message Last message in the chat; may be null if none or unknown
|
||||
//@positions Positions of the chat in chat lists
|
||||
//@chat_lists Chat lists to which the chat belongs. A chat can have a non-zero position in a chat list even it doesn't belong to the chat list and have no position in a chat list even it belongs to the chat list
|
||||
//@message_sender_id Identifier of a user or chat that is selected to send messages in the chat; may be null if the user can't change message sender
|
||||
//@block_list Block list to which the chat is added; may be null if none
|
||||
//@has_protected_content True, if chat content can't be saved locally, forwarded, or copied
|
||||
@ -1708,7 +1788,7 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa
|
||||
//@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat
|
||||
//@draft_message A draft of a message in the chat; may be null if none
|
||||
//@client_data Application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used
|
||||
chat id:int53 type:ChatType title:string photo:chatPhotoInfo accent_color_id:int32 background_custom_emoji_id:int64 profile_accent_color_id:int32 profile_background_custom_emoji_id:int64 permissions:chatPermissions last_message:message positions:vector<chatPosition> message_sender_id:MessageSender block_list:BlockList has_protected_content:Bool is_translatable:Bool is_marked_as_unread:Bool view_as_topics:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 unread_reaction_count:int32 notification_settings:chatNotificationSettings available_reactions:ChatAvailableReactions message_auto_delete_time:int32 emoji_status:emojiStatus background:chatBackground theme_name:string action_bar:ChatActionBar video_chat:videoChat pending_join_requests:chatJoinRequestsInfo reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat;
|
||||
chat id:int53 type:ChatType title:string photo:chatPhotoInfo accent_color_id:int32 background_custom_emoji_id:int64 profile_accent_color_id:int32 profile_background_custom_emoji_id:int64 permissions:chatPermissions last_message:message positions:vector<chatPosition> chat_lists:vector<ChatList> message_sender_id:MessageSender block_list:BlockList has_protected_content:Bool is_translatable:Bool is_marked_as_unread:Bool view_as_topics:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 unread_reaction_count:int32 notification_settings:chatNotificationSettings available_reactions:ChatAvailableReactions message_auto_delete_time:int32 emoji_status:emojiStatus background:chatBackground theme_name:string action_bar:ChatActionBar video_chat:videoChat pending_join_requests:chatJoinRequestsInfo reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat;
|
||||
|
||||
//@description Represents a list of chats @total_count Approximate total number of chats found @chat_ids List of chat identifiers
|
||||
chats total_count:int32 chat_ids:vector<int53> = Chats;
|
||||
@ -3711,6 +3791,25 @@ storyInteraction actor_id:MessageSender interaction_date:int32 block_list:BlockL
|
||||
storyInteractions total_count:int32 total_forward_count:int32 total_reaction_count:int32 interactions:vector<storyInteraction> next_offset:string = StoryInteractions;
|
||||
|
||||
|
||||
//@description Describes a message that can be used for quick reply
|
||||
//@id Unique message identifier among all quick replies
|
||||
//@sending_state The sending state of the message; may be null if the message isn't being sent and didn't fail to be sent
|
||||
//@can_be_edited True, if the message can be edited
|
||||
//@reply_to_message_id Information about the identifier of the quick reply message to which the message replies
|
||||
//@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent
|
||||
//@media_album_id Unique identifier of an album this message belongs to. Only audios, documents, photos and videos can be grouped together in albums
|
||||
//@content Content of the message
|
||||
//@reply_markup Inline keyboard reply markup for the message; may be null if none
|
||||
quickReplyMessage id:int53 sending_state:MessageSendingState can_be_edited:Bool reply_to_message_id:int53 via_bot_user_id:int53 media_album_id:int64 content:MessageContent reply_markup:ReplyMarkup = QuickReplyMessage;
|
||||
|
||||
//@description Describes a shortcut that can be used for a quick reply
|
||||
//@id Unique shortcut identifier
|
||||
//@name The name of the shortcut that can be used to use the shortcut
|
||||
//@first_message The first shortcut message
|
||||
//@message_count The total number of messages in the shortcut
|
||||
quickReplyShortcut id:int32 name:string first_message:quickReplyMessage message_count:int32 = QuickReplyShortcut;
|
||||
|
||||
|
||||
//@class PublicForward @description Describes a public forward or repost of a story
|
||||
|
||||
//@description Contains a public forward as a message @message Information about the message
|
||||
@ -5021,6 +5120,16 @@ themeSettings accent_color:int32 background:background outgoing_message_fill:Bac
|
||||
chatTheme name:string light_settings:themeSettings dark_settings:themeSettings = ChatTheme;
|
||||
|
||||
|
||||
//@description Describes a time zone
|
||||
//@id Unique time zone identifier
|
||||
//@name Time zone name
|
||||
//@utc_time_offset Current UTC time offset for the time zone
|
||||
timeZone id:string name:string utc_time_offset:int32 = TimeZone;
|
||||
|
||||
//@description Contains a list of time zones @time_zones A list of time zones
|
||||
timeZones time_zones:vector<timeZone> = TimeZones;
|
||||
|
||||
|
||||
//@description Contains a list of hashtags @hashtags A list of hashtags
|
||||
hashtags hashtags:vector<string> = Hashtags;
|
||||
|
||||
@ -5955,6 +6064,10 @@ storageStatisticsFast files_size:int53 file_count:int32 database_size:int53 lang
|
||||
//@statistics Database statistics in an unspecified human-readable format
|
||||
databaseStatistics statistics:string = DatabaseStatistics;
|
||||
|
||||
//@description Contains memory statistics
|
||||
//@statistics Memory statistics in an unspecified human-readable format
|
||||
memoryStatistics statistics:string = MemoryStatistics;
|
||||
|
||||
|
||||
//@class NetworkType @description Represents the type of a network
|
||||
|
||||
@ -6450,6 +6563,12 @@ updateChatLastMessage chat_id:int53 last_message:message positions:vector<chatPo
|
||||
//@position New chat position. If new order is 0, then the chat needs to be removed from the list
|
||||
updateChatPosition chat_id:int53 position:chatPosition = Update;
|
||||
|
||||
//@description A chat was added to a chat list @chat_id Chat identifier @chat_list The chat list to which the chat was added
|
||||
updateChatAddedToList chat_id:int53 chat_list:ChatList = Update;
|
||||
|
||||
//@description A chat was removed from a chat list @chat_id Chat identifier @chat_list The chat list from which the chat was removed
|
||||
updateChatRemovedFromList chat_id:int53 chat_list:ChatList = Update;
|
||||
|
||||
//@description Incoming messages were read or the number of unread messages has been changed @chat_id Chat identifier @last_read_inbox_message_id Identifier of the last read incoming message @unread_count The number of unread messages left in the chat
|
||||
updateChatReadInbox chat_id:int53 last_read_inbox_message_id:int53 unread_count:int32 = Update;
|
||||
|
||||
@ -6526,8 +6645,11 @@ updateChatBlockList chat_id:int53 block_list:BlockList = Update;
|
||||
//@description A chat's has_scheduled_messages field has changed @chat_id Chat identifier @has_scheduled_messages New value of has_scheduled_messages
|
||||
updateChatHasScheduledMessages chat_id:int53 has_scheduled_messages:Bool = Update;
|
||||
|
||||
//@description The list of chat folders or a chat folder has changed @chat_folders The new list of chat folders @main_chat_list_position Position of the main chat list among chat folders, 0-based
|
||||
updateChatFolders chat_folders:vector<chatFolderInfo> main_chat_list_position:int32 = Update;
|
||||
//@description The list of chat folders or a chat folder has changed
|
||||
//@chat_folders The new list of chat folders
|
||||
//@main_chat_list_position Position of the main chat list among chat folders, 0-based
|
||||
//@are_tags_enabled True, if folder tags are enabled
|
||||
updateChatFolders chat_folders:vector<chatFolderInfo> main_chat_list_position:int32 are_tags_enabled:Bool = Update;
|
||||
|
||||
//@description The number of online group members has changed. This update with non-zero number of online group members is sent only for currently opened chats.
|
||||
//-There is no guarantee that it is sent just after the number of online users has changed
|
||||
@ -6542,6 +6664,21 @@ updateSavedMessagesTopic topic:savedMessagesTopic = Update;
|
||||
//@description Number of Saved Messages topics has changed @topic_count Approximate total number of Saved Messages topics
|
||||
updateSavedMessagesTopicCount topic_count:int32 = Update;
|
||||
|
||||
//@description Basic information about a quick reply shortcut has changed. This update is guaranteed to come before the quick shortcut name is returned to the application
|
||||
//@shortcut New data about the shortcut
|
||||
updateQuickReplyShortcut shortcut:quickReplyShortcut = Update;
|
||||
|
||||
//@description A quick reply shortcut and all its messages were deleted @shortcut_id The identifier of the deleted shortcut
|
||||
updateQuickReplyShortcutDeleted shortcut_id:int32 = Update;
|
||||
|
||||
//@description The list of quick reply shortcuts has changed @shortcut_ids The new list of identifiers of quick reply shortcuts
|
||||
updateQuickReplyShortcuts shortcut_ids:vector<int32> = Update;
|
||||
|
||||
//@description The list of quick reply shortcut messages has changed
|
||||
//@shortcut_id The identifier of the shortcut
|
||||
//@messages The new list of quick reply messages for the shortcut in order from the first to the last sent
|
||||
updateQuickReplyShortcutMessages shortcut_id:int32 messages:vector<quickReplyMessage> = Update;
|
||||
|
||||
//@description Basic information about a topic in a forum chat was changed @chat_id Chat identifier @info New information about the topic
|
||||
updateForumTopicInfo chat_id:int53 info:forumTopicInfo = Update;
|
||||
|
||||
@ -6590,6 +6727,9 @@ updateUserStatus user_id:int53 status:UserStatus = Update;
|
||||
//@description Some data of a user has changed. This update is guaranteed to come before the user identifier is returned to the application @user New data about the user
|
||||
updateUser user:user = Update;
|
||||
|
||||
//@description Some data of a user or a chat has changed. This update is guaranteed to come before the user or chat identifier is returned to the application @access_hash Access hash
|
||||
updateAccessHash access_hash:accessHash = Update;
|
||||
|
||||
//@description Some data of a basic group has changed. This update is guaranteed to come before the basic group identifier is returned to the application @basic_group New data about the group
|
||||
updateBasicGroup basic_group:basicGroup = Update;
|
||||
|
||||
@ -7565,6 +7705,12 @@ sendInlineQueryResultMessage chat_id:int53 message_thread_id:int53 reply_to:Inpu
|
||||
//@remove_caption Pass true to remove media captions of message copies. Ignored if send_copy is false
|
||||
forwardMessages chat_id:int53 message_thread_id:int53 from_chat_id:int53 message_ids:vector<int53> options:messageSendOptions send_copy:Bool remove_caption:Bool = Messages;
|
||||
|
||||
//@description Sends messages from a quick reply shortcut. Requires Telegram Business subscription
|
||||
//@chat_id Identifier of the chat to which to send messages. The chat must be a private chat with a regular user
|
||||
//@shortcut_id Unique identifier of the quick reply shortcut
|
||||
//@sending_id Non-persistent identifier, which will be returned back in messageSendingStatePending object and can be used to match sent messages and corresponding updateNewMessage updates
|
||||
sendQuickReplyShortcutMessages chat_id:int53 shortcut_id:int32 sending_id:int32 = Messages;
|
||||
|
||||
//@description Resends messages which failed to send. Can be called only for messages for which messageSendingStateFailed.can_retry is true and after specified in messageSendingStateFailed.retry_after time passed.
|
||||
//-If a message is re-sent, the corresponding failed to send message is deleted. Returns the sent messages in the same order as the message identifiers passed in message_ids. If a message can't be re-sent, null will be returned instead of the message
|
||||
//@chat_id Identifier of the chat to send messages
|
||||
@ -7669,6 +7815,31 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup =
|
||||
editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok;
|
||||
|
||||
|
||||
//@description Checks validness of a name for a quick reply shortcut. Can be called synchronously @name The name of the shortcut; 1-32 characters
|
||||
checkQuickReplyShortcutName name:string = Ok;
|
||||
|
||||
//@description Loads quick reply shortcuts created by the current user. The loaded topics will be sent through updateQuickReplyShortcuts
|
||||
loadQuickReplyShortcuts = Ok;
|
||||
|
||||
//@description Changes name of a quick reply shortcut @shortcut_id Unique identifier of the quick reply shortcut @name New name for the shortcut. Use checkQuickReplyShortcutName to check its validness
|
||||
setQuickReplyShortcutName shortcut_id:int32 name:string = Ok;
|
||||
|
||||
//@description Deletes a quick reply shortcut @shortcut_id Unique identifier of the quick reply shortcut
|
||||
deleteQuickReplyShortcut shortcut_id:int32 = Ok;
|
||||
|
||||
//@description Changes the order of quick reply shortcuts @shortcut_ids The new order of quick reply shortcuts
|
||||
reorderQuickReplyShortcuts shortcut_ids:vector<int32> = Ok;
|
||||
|
||||
//@description Loads quick reply messages that can be sent by a given quick reply shortcut. The loaded messages will be sent through updateQuickReplyShortcutMessages
|
||||
//@shortcut_id Unique identifier of the quick reply shortcut
|
||||
loadQuickReplyShortcutMessages shortcut_id:int32 = Ok;
|
||||
|
||||
//@description Deletes specified quick reply messages
|
||||
//@shortcut_id Unique identifier of the quick reply shortcut to which the messages belong
|
||||
//@message_ids Unique identifiers of the messages
|
||||
deleteQuickReplyShortcutMessages shortcut_id:int32 message_ids:vector<int53> = Ok;
|
||||
|
||||
|
||||
//@description Returns list of custom emojis, which can be used as forum topic icon by all users
|
||||
getForumTopicDefaultIcons = Stickers;
|
||||
|
||||
@ -8132,6 +8303,9 @@ getChatFolderChatCount folder:chatFolder = Count;
|
||||
//@description Changes the order of chat folders @chat_folder_ids Identifiers of chat folders in the new correct order @main_chat_list_position Position of the main chat list among chat folders, 0-based. Can be non-zero only for Premium users
|
||||
reorderChatFolders chat_folder_ids:vector<int32> main_chat_list_position:int32 = Ok;
|
||||
|
||||
//@description Toggles whether chat folder tags are enabled @are_tags_enabled Pass true to enable folder tags; pass false to disable them
|
||||
toggleChatFolderTags are_tags_enabled:Bool = Ok;
|
||||
|
||||
//@description Returns recommended chat folders for the current user
|
||||
getRecommendedChatFolders = RecommendedChatFolders;
|
||||
|
||||
@ -9106,7 +9280,7 @@ reorderInstalledStickerSets sticker_type:StickerType sticker_set_ids:vector<int6
|
||||
getRecentStickers is_attached:Bool = Stickers;
|
||||
|
||||
//@description Manually adds a new sticker to the list of recently used stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first.
|
||||
//-Only stickers belonging to a sticker set can be added to this list. Emoji stickers can't be added to recent stickers
|
||||
//-Only stickers belonging to a sticker set or in WEBP format can be added to this list. Emoji stickers can't be added to recent stickers
|
||||
//@is_attached Pass true to add the sticker to the list of stickers recently attached to photo or video files; pass false to add the sticker to the list of recently sent stickers
|
||||
//@sticker Sticker file to add
|
||||
addRecentSticker is_attached:Bool sticker:InputFile = Stickers;
|
||||
@ -9121,7 +9295,7 @@ clearRecentStickers is_attached:Bool = Ok;
|
||||
getFavoriteStickers = Stickers;
|
||||
|
||||
//@description Adds a new sticker to the list of favorite stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first.
|
||||
//-Only stickers belonging to a sticker set can be added to this list. Emoji stickers can't be added to favorite stickers
|
||||
//-Only stickers belonging to a sticker set or in WEBP format can be added to this list. Emoji stickers can't be added to favorite stickers
|
||||
//@sticker Sticker file to add
|
||||
addFavoriteSticker sticker:InputFile = Ok;
|
||||
|
||||
@ -9233,9 +9407,21 @@ reorderActiveUsernames usernames:vector<string> = Ok;
|
||||
//@description Changes the emoji status of the current user; for Telegram Premium users only @emoji_status New emoji status; pass null to switch to the default badge
|
||||
setEmojiStatus emoji_status:emojiStatus = Ok;
|
||||
|
||||
//@description Changes the location of the current user. Needs to be called if getOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user
|
||||
//@description Changes the location of the current user. Needs to be called if getOption("is_location_visible") is true and location changes for more than 1 kilometer. Must not be called if the user has a business location @location The new location of the user
|
||||
setLocation location:location = Ok;
|
||||
|
||||
//@description Changes the business location of the current user. Requires Telegram Business subscription @location The new location of the business; pass null to remove the location
|
||||
setBusinessLocation location:businessLocation = Ok;
|
||||
|
||||
//@description Changes the business opening hours of the current user. Requires Telegram Business subscription @opening_hours The new opening hours of the business; pass null to remove the opening hours
|
||||
setBusinessOpeningHours opening_hours:businessOpeningHours = Ok;
|
||||
|
||||
//@description Changes the business greeting message settings of the current user. Requires Telegram Business subscription @greeting_message_settings The new settings for the greeting message of the business; pass null to disable the greeting message
|
||||
setBusinessGreetingMessageSettings greeting_message_settings:businessGreetingMessageSettings = Ok;
|
||||
|
||||
//@description Changes the business away message settings of the current user. Requires Telegram Business subscription @away_message_settings The new settings for the away message of the business; pass null to disable the away message
|
||||
setBusinessAwayMessageSettings away_message_settings:businessAwayMessageSettings = Ok;
|
||||
|
||||
//@description Changes the phone number of the user and sends an authentication code to the user's new phone number; for official Android and iOS applications only. On success, returns information about the sent code
|
||||
//@phone_number The new phone number of the user in international format
|
||||
//@settings Settings for the authentication of the user's phone number; pass null to use default settings
|
||||
@ -9248,6 +9434,16 @@ resendChangePhoneNumberCode = AuthenticationCodeInfo;
|
||||
checkChangePhoneNumberCode code:string = Ok;
|
||||
|
||||
|
||||
//@description Returns the business bot that is connected to the current user account. Returns a 404 error if there is no connected bot
|
||||
getBusinessConnectedBot = BusinessConnectedBot;
|
||||
|
||||
//@description Adds or changes business bot that is connected to the current user account @bot Connection settings for the bot
|
||||
setBusinessConnectedBot bot:businessConnectedBot = Ok;
|
||||
|
||||
//@description Deletes the business bot that is connected to the current user account @bot_user_id Unique user identifier for the bot
|
||||
deleteBusinessConnectedBot bot_user_id:int53 = Ok;
|
||||
|
||||
|
||||
//@description Returns an HTTPS link, which can be used to get information about the current user
|
||||
getUserLink = UserLink;
|
||||
|
||||
@ -9468,6 +9664,10 @@ closeSecretChat secret_chat_id:int32 = Ok;
|
||||
getChatEventLog chat_id:int53 query:string from_event_id:int64 limit:int32 filters:chatEventLogFilters user_ids:vector<int53> = ChatEvents;
|
||||
|
||||
|
||||
//@description Returns the list of supported time zones
|
||||
getTimeZones = TimeZones;
|
||||
|
||||
|
||||
//@description Returns an invoice payment form. This method must be called when the user presses inline button of the type inlineKeyboardButtonTypeBuy
|
||||
//@input_invoice The invoice
|
||||
//@theme Preferred payment form theme; pass null to use the default theme
|
||||
@ -9694,6 +9894,10 @@ getStorageStatisticsFast = StorageStatisticsFast;
|
||||
//@description Returns database statistics
|
||||
getDatabaseStatistics = DatabaseStatistics;
|
||||
|
||||
//@description Returns memory statistics
|
||||
//@full Full memory statistics calculation
|
||||
getMemoryStatistics full:Bool = MemoryStatistics;
|
||||
|
||||
//@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, 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
|
||||
|
@ -135,7 +135,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
|
||||
|
||||
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
|
||||
message#1e4c8a69 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
|
||||
message#a66c7efc flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int = Message;
|
||||
messageService#2b085862 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction ttl_period:flags.25?int = Message;
|
||||
|
||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||
@ -248,7 +248,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
|
||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
||||
|
||||
userFull#b9b12c6c flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories = UserFull;
|
||||
userFull#22ff3e85 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage = UserFull;
|
||||
|
||||
contact#145ade0b user_id:long mutual:Bool = Contact;
|
||||
|
||||
@ -423,6 +423,12 @@ updateBotMessageReactions#9cb7759 peer:Peer msg_id:int date:int reactions:Vector
|
||||
updateSavedDialogPinned#aeaf9e74 flags:# pinned:flags.0?true peer:DialogPeer = Update;
|
||||
updatePinnedSavedDialogs#686c85a6 flags:# order:flags.0?Vector<DialogPeer> = Update;
|
||||
updateSavedReactionTags#39c67432 = Update;
|
||||
updateSmsJob#f16269d4 job_id:string = Update;
|
||||
updateQuickReplies#f9470ab2 quick_replies:Vector<QuickReply> = Update;
|
||||
updateNewQuickReply#f53da717 quick_reply:QuickReply = Update;
|
||||
updateDeleteQuickReply#53e6f1ec shortcut_id:int = Update;
|
||||
updateQuickReplyMessage#3e050d0f message:Message = Update;
|
||||
updateDeleteQuickReplyMessages#566fe7cd shortcut_id:int messages:Vector<int> = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@ -1249,9 +1255,9 @@ bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;
|
||||
|
||||
payments.bankCardData#3e24e573 title:string open_urls:Vector<BankCardOpenUrl> = payments.BankCardData;
|
||||
|
||||
dialogFilter#7438f7e8 flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> exclude_peers:Vector<InputPeer> = DialogFilter;
|
||||
dialogFilter#5fb5523b flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string color:flags.27?int pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> exclude_peers:Vector<InputPeer> = DialogFilter;
|
||||
dialogFilterDefault#363293ae = DialogFilter;
|
||||
dialogFilterChatlist#d64a04a8 flags:# has_my_invites:flags.26?true id:int title:string emoticon:flags.25?string pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> = DialogFilter;
|
||||
dialogFilterChatlist#9fe28ea4 flags:# has_my_invites:flags.26?true id:int title:string emoticon:flags.25?string color:flags.27?int pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> = DialogFilter;
|
||||
|
||||
dialogFilterSuggested#77744d4a filter:DialogFilter description:string = DialogFilterSuggested;
|
||||
|
||||
@ -1674,6 +1680,53 @@ messages.savedReactionTags#3259950a tags:Vector<SavedReactionTag> hash:long = me
|
||||
|
||||
outboxReadDate#3bb842ac date:int = OutboxReadDate;
|
||||
|
||||
smsjobs.eligibleToJoin#dc8b44cf terms_url:string monthly_sent_sms:int = smsjobs.EligibilityToJoin;
|
||||
|
||||
smsjobs.status#2aee9191 flags:# allow_international:flags.0?true recent_sent:int recent_since:int recent_remains:int total_sent:int total_since:int last_gift_slug:flags.1?string terms_url:string = smsjobs.Status;
|
||||
|
||||
smsJob#e6a1eeb8 job_id:string phone_number:string text:string = SmsJob;
|
||||
|
||||
businessWeeklyOpen#120b1ab9 start_minute:int end_minute:int = BusinessWeeklyOpen;
|
||||
|
||||
businessWorkHours#8c92b098 flags:# open_now:flags.0?true timezone_id:string weekly_open:Vector<BusinessWeeklyOpen> = BusinessWorkHours;
|
||||
|
||||
businessLocation#ac5c1af7 flags:# geo_point:flags.0?GeoPoint address:string = BusinessLocation;
|
||||
|
||||
inputBusinessRecipients#6f8b32aa flags:# existing_chats:flags.0?true new_chats:flags.1?true contacts:flags.2?true non_contacts:flags.3?true exclude_selected:flags.5?true users:flags.4?Vector<InputUser> = InputBusinessRecipients;
|
||||
|
||||
businessRecipients#21108ff7 flags:# existing_chats:flags.0?true new_chats:flags.1?true contacts:flags.2?true non_contacts:flags.3?true exclude_selected:flags.5?true users:flags.4?Vector<long> = BusinessRecipients;
|
||||
|
||||
businessAwayMessageScheduleAlways#c9b9e2b9 = BusinessAwayMessageSchedule;
|
||||
businessAwayMessageScheduleOutsideWorkHours#c3f2f501 = BusinessAwayMessageSchedule;
|
||||
businessAwayMessageScheduleCustom#cc4d9ecc start_date:int end_date:int = BusinessAwayMessageSchedule;
|
||||
|
||||
inputBusinessGreetingMessage#194cb3b shortcut_id:int recipients:InputBusinessRecipients no_activity_days:int = InputBusinessGreetingMessage;
|
||||
|
||||
businessGreetingMessage#e519abab shortcut_id:int recipients:BusinessRecipients no_activity_days:int = BusinessGreetingMessage;
|
||||
|
||||
inputBusinessAwayMessage#832175e0 flags:# offline_only:flags.0?true shortcut_id:int schedule:BusinessAwayMessageSchedule recipients:InputBusinessRecipients = InputBusinessAwayMessage;
|
||||
|
||||
businessAwayMessage#ef156a5c flags:# offline_only:flags.0?true shortcut_id:int schedule:BusinessAwayMessageSchedule recipients:BusinessRecipients = BusinessAwayMessage;
|
||||
|
||||
timezone#ff9289f5 id:string name:string utc_offset:int = Timezone;
|
||||
|
||||
help.timezonesListNotModified#970708cc = help.TimezonesList;
|
||||
help.timezonesList#7b74ed71 timezones:Vector<Timezone> hash:int = help.TimezonesList;
|
||||
|
||||
quickReply#697102b shortcut_id:int shortcut:string top_message:int count:int = QuickReply;
|
||||
|
||||
inputQuickReplyShortcut#24596d41 shortcut:string = InputQuickReplyShortcut;
|
||||
inputQuickReplyShortcutId#1190cf1 shortcut_id:int = InputQuickReplyShortcut;
|
||||
|
||||
messages.quickReplies#c68d6695 quick_replies:Vector<QuickReply> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.QuickReplies;
|
||||
messages.quickRepliesNotModified#5f91eb5b = messages.QuickReplies;
|
||||
|
||||
connectedBot#e7e999e7 flags:# can_reply:flags.0?true bot_id:long recipients:BusinessRecipients = ConnectedBot;
|
||||
|
||||
account.connectedBots#17d7f87b connected_bots:Vector<ConnectedBot> users:Vector<User> = account.ConnectedBots;
|
||||
|
||||
messages.dialogFilters#2ad93719 flags:# tags_enabled:flags.0?true filters:Vector<DialogFilter> = messages.DialogFilters;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@ -1799,6 +1852,12 @@ account.updateColor#7cefa15d flags:# for_profile:flags.1?true color:flags.2?int
|
||||
account.getDefaultBackgroundEmojis#a60ab9ce hash:long = EmojiList;
|
||||
account.getChannelDefaultEmojiStatuses#7727a7d5 hash:long = account.EmojiStatuses;
|
||||
account.getChannelRestrictedStatusEmojis#35a9e0d5 hash:long = EmojiList;
|
||||
account.updateBusinessWorkHours#4b00e066 flags:# business_work_hours:flags.0?BusinessWorkHours = Bool;
|
||||
account.updateBusinessLocation#9e6b131a flags:# geo_point:flags.1?InputGeoPoint address:flags.0?string = Bool;
|
||||
account.updateBusinessGreetingMessage#66cdafc4 flags:# message:flags.0?InputBusinessGreetingMessage = Bool;
|
||||
account.updateBusinessAwayMessage#a26a7fa5 flags:# message:flags.0?InputBusinessAwayMessage = Bool;
|
||||
account.updateConnectedBot#9c2d527d flags:# can_reply:flags.0?true deleted:flags.1?true bot:InputUser recipients:InputBusinessRecipients = Updates;
|
||||
account.getConnectedBots#4ea4c80f = account.ConnectedBots;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||
@ -1840,9 +1899,9 @@ messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?t
|
||||
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
|
||||
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
||||
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
|
||||
messages.sendMessage#280d096f flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
|
||||
messages.sendMedia#72ccc23d flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
|
||||
messages.forwardMessages#c661bbc4 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
|
||||
messages.sendMessage#dff8042c flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
|
||||
messages.sendMedia#7bd66041 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
|
||||
messages.forwardMessages#d5039208 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
|
||||
messages.reportSpam#cf1592db peer:InputPeer = Bool;
|
||||
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
|
||||
messages.report#8953ab4e peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
|
||||
@ -1885,9 +1944,9 @@ messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
|
||||
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
|
||||
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
|
||||
messages.setInlineBotResults#bb12a419 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM switch_webview:flags.4?InlineBotWebView = Bool;
|
||||
messages.sendInlineBotResult#f7bc68ba flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to:flags.0?InputReplyTo random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
|
||||
messages.sendInlineBotResult#3ebee86a flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to:flags.0?InputReplyTo random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
|
||||
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
|
||||
messages.editMessage#48f71778 flags:# no_webpage:flags.1?true invert_media:flags.16?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.15?int = Updates;
|
||||
messages.editMessage#dfd14005 flags:# no_webpage:flags.1?true invert_media:flags.16?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.15?int quick_reply_shortcut_id:flags.17?int = Updates;
|
||||
messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true invert_media:flags.16?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
|
||||
messages.getBotCallbackAnswer#9342ca07 flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes password:flags.2?InputCheckPasswordSRP = messages.BotCallbackAnswer;
|
||||
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
|
||||
@ -1920,7 +1979,7 @@ messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool;
|
||||
messages.getUnreadMentions#f107e790 flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readMentions#36e5bf4d flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.getRecentLocations#702a40e0 peer:InputPeer limit:int hash:long = messages.Messages;
|
||||
messages.sendMultiMedia#456e8987 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true peer:InputPeer reply_to:flags.0?InputReplyTo multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
|
||||
messages.sendMultiMedia#c964709 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true peer:InputPeer reply_to:flags.0?InputReplyTo multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
|
||||
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
|
||||
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
|
||||
@ -1947,7 +2006,7 @@ messages.sendScheduledMessages#bd38850a peer:InputPeer id:Vector<int> = Updates;
|
||||
messages.deleteScheduledMessages#59ae2b16 peer:InputPeer id:Vector<int> = Updates;
|
||||
messages.getPollVotes#b86e380e flags:# peer:InputPeer id:int option:flags.0?bytes offset:flags.1?string limit:int = messages.VotesList;
|
||||
messages.toggleStickerSets#b5052fea flags:# uninstall:flags.0?true archive:flags.1?true unarchive:flags.2?true stickersets:Vector<InputStickerSet> = Bool;
|
||||
messages.getDialogFilters#f19ed96d = Vector<DialogFilter>;
|
||||
messages.getDialogFilters#efd48c89 = messages.DialogFilters;
|
||||
messages.getSuggestedDialogFilters#a29cd42c = Vector<DialogFilterSuggested>;
|
||||
messages.updateDialogFilter#1ad4a04a flags:# id:int filter:flags.0?DialogFilter = Bool;
|
||||
messages.updateDialogFiltersOrder#c563c1e4 order:Vector<int> = Bool;
|
||||
@ -2029,6 +2088,15 @@ messages.getSavedReactionTags#3637e05b flags:# peer:flags.0?InputPeer hash:long
|
||||
messages.updateSavedReactionTag#60297dec flags:# reaction:Reaction title:flags.0?string = Bool;
|
||||
messages.getDefaultTagReactions#bdf93428 hash:long = messages.Reactions;
|
||||
messages.getOutboxReadDate#8c4bfe5d peer:InputPeer msg_id:int = OutboxReadDate;
|
||||
messages.getQuickReplies#d483f2a8 hash:long = messages.QuickReplies;
|
||||
messages.reorderQuickReplies#60331907 order:Vector<int> = Bool;
|
||||
messages.checkQuickReplyShortcut#f1d0fbd3 shortcut:string = Bool;
|
||||
messages.editQuickReplyShortcut#5c003cef shortcut_id:int shortcut:string = Bool;
|
||||
messages.deleteQuickReplyShortcut#3cc04740 shortcut_id:int = Bool;
|
||||
messages.getQuickReplyMessages#94a495c3 flags:# shortcut_id:int id:flags.0?Vector<int> hash:long = messages.Messages;
|
||||
messages.sendQuickReplyMessages#33153ad4 peer:InputPeer shortcut_id:int = Updates;
|
||||
messages.deleteQuickReplyMessages#e105e910 shortcut_id:int id:Vector<int> = Updates;
|
||||
messages.toggleDialogFilterTags#fd2dda49 enabled:Bool = Bool;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
|
||||
@ -2073,6 +2141,7 @@ help.getCountriesList#735787a8 lang_code:string hash:int = help.CountriesList;
|
||||
help.getPremiumPromo#b81b93d4 = help.PremiumPromo;
|
||||
help.getPeerColors#da80f42f hash:int = help.PeerColors;
|
||||
help.getPeerProfileColors#abcfa9fd hash:int = help.PeerColors;
|
||||
help.getTimezonesList#49b30240 hash:int = help.TimezonesList;
|
||||
|
||||
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
|
||||
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
|
||||
@ -2272,3 +2341,11 @@ premium.getMyBoosts#be77b4a = premium.MyBoosts;
|
||||
premium.applyBoost#6b7da746 flags:# slots:flags.0?Vector<int> peer:InputPeer = premium.MyBoosts;
|
||||
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
|
||||
premium.getUserBoosts#39854d1f peer:InputPeer user_id:InputUser = premium.BoostsList;
|
||||
|
||||
smsjobs.isEligibleToJoin#edc39d0 = smsjobs.EligibilityToJoin;
|
||||
smsjobs.join#a74ece2d = Bool;
|
||||
smsjobs.leave#9898ad73 = Bool;
|
||||
smsjobs.updateSettings#93fa0bf flags:# allow_international:flags.0?true = Bool;
|
||||
smsjobs.getStatus#10a698e8 = smsjobs.Status;
|
||||
smsjobs.getSmsJob#778d902f job_id:string = SmsJob;
|
||||
smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
|
||||
|
@ -185,7 +185,7 @@ void tl_print_parse_error (void) {
|
||||
}
|
||||
|
||||
char *parse_lex (void) {
|
||||
while (1) {
|
||||
while (1) {
|
||||
while (curch && is_whitespace (curch)) { nextch (); }
|
||||
if (curch == '/' && nextch () == '/') {
|
||||
while (nextch () != 10);
|
||||
@ -235,7 +235,7 @@ char *parse_lex (void) {
|
||||
case '.':
|
||||
nextch ();
|
||||
parse.lex.len = 1;
|
||||
parse.lex.type = lex_char;
|
||||
parse.lex.type = lex_char;
|
||||
return (parse.lex.ptr = p);
|
||||
case 'a':
|
||||
case 'b':
|
||||
@ -334,10 +334,10 @@ char *parse_lex (void) {
|
||||
int ok = 1;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (!is_hexdigit (nextch())) {
|
||||
if (curch == ' ' && i >= 5) {
|
||||
if (curch == ' ' && i >= 5) {
|
||||
ok = 2;
|
||||
break;
|
||||
} else {
|
||||
} else {
|
||||
parse_error ("Hex digit expected");
|
||||
parse.lex.type = lex_error;
|
||||
return (parse.lex.ptr = (void *)-1);
|
||||
@ -370,7 +370,7 @@ char *parse_lex (void) {
|
||||
parse.lex.type = lex_error;
|
||||
return (parse.lex.ptr = (void *)-1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int expect (char *s) {
|
||||
@ -453,7 +453,7 @@ struct tree *parse_full_combinator_id (void) {
|
||||
} else {
|
||||
parse_error ("Can not parse full combinator id");
|
||||
PARSE_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct tree *parse_combinator_id (void) {
|
||||
@ -467,7 +467,7 @@ struct tree *parse_combinator_id (void) {
|
||||
} else {
|
||||
parse_error ("Can not parse combinator id");
|
||||
PARSE_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct tree *parse_var_ident (void) {
|
||||
@ -595,7 +595,7 @@ struct tree *parse_subexpr (void) {
|
||||
was_term = 1;
|
||||
PARSE_TRY (parse_term);
|
||||
if (S) {
|
||||
tree_add_child (T, S);
|
||||
tree_add_child (T, S);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -714,7 +714,7 @@ struct tree *parse_args4 (void) {
|
||||
if (S) {
|
||||
tree_add_child (T, S);
|
||||
} else {
|
||||
load_parse (so);
|
||||
load_parse (so);
|
||||
}
|
||||
if (LEX_CHAR ('!')) {
|
||||
PARSE_ADD (type_exclam);
|
||||
@ -733,7 +733,7 @@ struct tree *parse_args3 (void) {
|
||||
if (S) {
|
||||
tree_add_child (T, S);
|
||||
} else {
|
||||
load_parse (so);
|
||||
load_parse (so);
|
||||
}
|
||||
if (LEX_CHAR ('!')) {
|
||||
PARSE_ADD (type_exclam);
|
||||
@ -757,7 +757,7 @@ struct tree *parse_args2 (void) {
|
||||
if (S) {
|
||||
tree_add_child (T, S);
|
||||
} else {
|
||||
load_parse (so);
|
||||
load_parse (so);
|
||||
}
|
||||
struct parse save2 = save_parse ();
|
||||
PARSE_TRY (parse_multiplicity);
|
||||
@ -789,7 +789,7 @@ struct tree *parse_args1 (void) {
|
||||
if (S) {
|
||||
tree_add_child (T, S);
|
||||
} else {
|
||||
load_parse (so);
|
||||
load_parse (so);
|
||||
}
|
||||
if (LEX_CHAR ('!')) {
|
||||
PARSE_ADD (type_exclam);
|
||||
@ -1041,7 +1041,7 @@ int tl_add_field (char *id) {
|
||||
|
||||
void tl_clear_fields (void) {
|
||||
// tree_act_tl_field (fields[namespace_level], (void *)free);
|
||||
fields[namespace_level] = tree_clear_tl_field (fields[namespace_level]);
|
||||
fields[namespace_level] = tree_clear_tl_field (fields[namespace_level]);
|
||||
}
|
||||
|
||||
struct tl_var *tl_add_var (char *id, struct tl_combinator_tree *ptr, int type) {
|
||||
@ -1151,9 +1151,9 @@ struct tl_type *tl_add_type (const char *_id, int len, int params_num, long long
|
||||
|
||||
void tl_add_type_param (struct tl_type *t, int x) {
|
||||
assert (t->flags & 4);
|
||||
assert (t->params_num <= 64);
|
||||
assert (t->params_num <= 64);
|
||||
if (x) {
|
||||
t->params_types |= (1ull << (t->params_num ++));
|
||||
t->params_types |= (1ull << (t->params_num ++));
|
||||
} else {
|
||||
t->params_num ++;
|
||||
}
|
||||
@ -1222,7 +1222,7 @@ struct tl_constructor *tl_add_constructor (struct tl_type *a, const char *_id, i
|
||||
struct tl_constructor *t = talloc (sizeof (*t));
|
||||
t->type = a;
|
||||
t->name = magic;
|
||||
t->id = id;
|
||||
t->id = id;
|
||||
t->print_id = tstrdup (id);
|
||||
t->real_id = 0;
|
||||
|
||||
@ -1282,7 +1282,7 @@ struct tl_constructor *tl_add_function (struct tl_type *a, const char *_id, int
|
||||
struct tl_constructor *t = talloc (sizeof (*t));
|
||||
t->type = a;
|
||||
t->name = magic;
|
||||
t->id = id;
|
||||
t->id = id;
|
||||
t->print_id = tstrdup (id);
|
||||
t->real_id = 0;
|
||||
|
||||
@ -1455,7 +1455,7 @@ void tl_buf_add_tree (struct tl_combinator_tree *T, int x) {
|
||||
tl_buf_add_tree (T->right, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
fprintf (stderr, "%s %s\n", TL_ACT (T->act), TL_TYPE (T->type));
|
||||
assert (0);
|
||||
@ -1549,7 +1549,7 @@ struct tl_combinator_tree *tl_union (struct tl_combinator_tree *L, struct tl_com
|
||||
tfree (v, sizeof (*v));
|
||||
R->type_flags += L->type_flags;
|
||||
return R;
|
||||
case type_list_item:
|
||||
case type_list_item:
|
||||
case type_list:
|
||||
if (R->type != type_list_item) {
|
||||
TL_ERROR ("Union: type mistmatch\n");
|
||||
@ -1561,7 +1561,7 @@ struct tl_combinator_tree *tl_union (struct tl_combinator_tree *L, struct tl_com
|
||||
case type_type:
|
||||
if (L->type_len == 0) {
|
||||
TL_ERROR ("Arguments number exceeds type arity\n");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (R->type != type_num && R->type != type_type && R->type != type_num_value) {
|
||||
TL_ERROR ("Union: type mistmatch\n");
|
||||
@ -1574,7 +1574,7 @@ struct tl_combinator_tree *tl_union (struct tl_combinator_tree *L, struct tl_com
|
||||
}
|
||||
if (R->type_len > 0) {
|
||||
TL_ERROR ("Argument type must have full number of arguments\n");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (L->type_len > 0 && ((L->type_flags & 1) != (R->type == type_num || R->type == type_num_value))) {
|
||||
TL_ERROR ("Argument types mistmatch: L->type_flags = %lld, R->type = %s\n", L->flags, TL_TYPE (R->type));
|
||||
@ -1595,7 +1595,7 @@ struct tl_combinator_tree *tl_parse_any_term (struct tree *T, int s);
|
||||
struct tl_combinator_tree *tl_parse_term (struct tree *T, int s) {
|
||||
assert (T->type == type_term);
|
||||
int i = 0;
|
||||
while (i < T->nc && T->c[i]->type == type_percent) { i ++; s ++; }
|
||||
while (i < T->nc && T->c[i]->type == type_percent) { i ++; s ++; }
|
||||
assert (i < T->nc);
|
||||
TL_INIT (L);
|
||||
while (i < T->nc) {
|
||||
@ -1610,7 +1610,7 @@ struct tl_combinator_tree *tl_parse_term (struct tree *T, int s) {
|
||||
struct tl_combinator_tree *tl_parse_type_term (struct tree *T, int s) {
|
||||
assert (T->type == type_type_term);
|
||||
assert (T->nc == 1);
|
||||
struct tl_combinator_tree *Z = tl_parse_term (T->c[0], s);
|
||||
struct tl_combinator_tree *Z = tl_parse_term (T->c[0], s);
|
||||
if (!Z || Z->type != type_type) { if (Z) { TL_ERROR ("type_term: found type %s\n", TL_TYPE (Z->type)); } TL_FAIL; }
|
||||
return Z;
|
||||
}
|
||||
@ -1674,7 +1674,7 @@ struct tl_combinator_tree *tl_parse_ident (struct tree *T, int s) {
|
||||
assert (!T->nc);
|
||||
struct tl_var *v = tl_get_var (T->text, T->len);
|
||||
TL_INIT (L);
|
||||
if (v) {
|
||||
if (v) {
|
||||
L = alloc_ctree_node ();
|
||||
L->act = act_var;
|
||||
L->type = v->type ? type_num : type_type;
|
||||
@ -1733,7 +1733,7 @@ struct tl_combinator_tree *tl_parse_ident (struct tree *T, int s) {
|
||||
L->data = t;
|
||||
L->type = type_type;
|
||||
L->type_len = t->params_num;
|
||||
L->type_flags = t->params_types;
|
||||
L->type_flags = t->params_types;
|
||||
return L;
|
||||
} else {
|
||||
TL_ERROR ("Not a type/var ident `%.*s`\n", T->len, T->text);
|
||||
@ -1761,7 +1761,7 @@ struct tl_combinator_tree *tl_parse_any_term (struct tree *T, int s) {
|
||||
default:
|
||||
fprintf (stderr, "type = %d\n", T->type);
|
||||
assert (0);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1834,11 +1834,11 @@ struct tl_combinator_tree *tl_parse_args2 (struct tree *T) {
|
||||
if (T->c[x]->type == type_var_ident_opt || T->c[x]->type == type_var_ident) {
|
||||
field_name = mystrdup (T->c[x]->text, T->c[x]->len);
|
||||
if (!tl_add_field (field_name)) {
|
||||
TL_ERROR ("Duplicate field name %s\n", field_name);
|
||||
TL_ERROR ("Duplicate field name %s\n", field_name);
|
||||
TL_FAIL;
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
}
|
||||
//fprintf (stderr, "%d %d\n", x, T->nc);
|
||||
if (T->c[x]->type == type_multiplicity) {
|
||||
L = tl_parse_multiplicity (T->c[x]);
|
||||
@ -1846,7 +1846,7 @@ struct tl_combinator_tree *tl_parse_args2 (struct tree *T) {
|
||||
x ++;
|
||||
} else {
|
||||
struct tl_var *v = tl_get_last_num_var ();
|
||||
if (!v) {
|
||||
if (!v) {
|
||||
TL_ERROR ("Expected multiplicity or nat var\n");
|
||||
TL_FAIL;
|
||||
}
|
||||
@ -1880,7 +1880,7 @@ struct tl_combinator_tree *tl_parse_args2 (struct tree *T) {
|
||||
H->right = 0;
|
||||
H->data = field_name;
|
||||
H->type_len = 0;
|
||||
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
@ -1971,7 +1971,7 @@ struct tl_combinator_tree *tl_parse_args134 (struct tree *T) {
|
||||
if (!v) {TL_FAIL;}
|
||||
v->flags |= 2;
|
||||
}
|
||||
|
||||
|
||||
H = tl_union (H, S);
|
||||
}
|
||||
return H;
|
||||
@ -1993,7 +1993,7 @@ struct tl_combinator_tree *tl_parse_args (struct tree *T) {
|
||||
default:
|
||||
assert (0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tl_mark_vars (struct tl_combinator_tree *T) {
|
||||
@ -2012,7 +2012,7 @@ struct tl_combinator_tree *tl_parse_result_type (struct tree *T) {
|
||||
assert (T->type == type_result_type);
|
||||
assert (T->nc >= 1);
|
||||
assert (T->nc <= 64);
|
||||
|
||||
|
||||
TL_INIT (L);
|
||||
|
||||
if (tl_get_var (T->c[0]->text, T->c[0]->len)) {
|
||||
@ -2043,7 +2043,7 @@ struct tl_combinator_tree *tl_parse_result_type (struct tree *T) {
|
||||
int i;
|
||||
for (i = 1; i < T->nc; i++) {
|
||||
TL_TRY (tl_parse_any_term (T->c[i], 0), L);
|
||||
assert (L->right);
|
||||
assert (L->right);
|
||||
assert (L->right->type == type_num || L->right->type == type_num_value || (L->right->type == type_type && L->right->type_len == 0));
|
||||
}
|
||||
}
|
||||
@ -2090,7 +2090,7 @@ int tl_parse_combinator_decl (struct tree *T, int fun) {
|
||||
TL_ERROR ("Only functions can return variables\n");
|
||||
}
|
||||
assert (t || fun);
|
||||
|
||||
|
||||
assert (namespace_level == 0);
|
||||
__ok = 1;
|
||||
tree_act_tl_var (vars[0], tl_var_check_used);
|
||||
@ -2098,7 +2098,7 @@ int tl_parse_combinator_decl (struct tree *T, int fun) {
|
||||
TL_ERROR ("Not all variables are used in right side\n");
|
||||
TL_FAIL;
|
||||
}
|
||||
|
||||
|
||||
if (tl_get_constructor (T->c[0]->text, T->c[0]->len) || tl_get_function (T->c[0]->text, T->c[0]->len)) {
|
||||
TL_ERROR ("Duplicate combinator id %.*s\n", T->c[0]->len, T->c[0]->text);
|
||||
return 0;
|
||||
@ -2107,7 +2107,7 @@ int tl_parse_combinator_decl (struct tree *T, int fun) {
|
||||
if (!c) { TL_FAIL; }
|
||||
c->left = L;
|
||||
c->right = R;
|
||||
|
||||
|
||||
if (!c->name) {
|
||||
tl_count_combinator_name (c);
|
||||
}
|
||||
@ -2163,7 +2163,7 @@ struct tl_combinator_tree *change_first_var (struct tl_combinator_tree *O, struc
|
||||
if (O->data == *X) {
|
||||
struct tl_combinator_tree *R = tl_tree_dup (Y);
|
||||
if (O->type == type_num || O->type == type_num_value) { R->type_flags += O->type_flags; }
|
||||
return R;
|
||||
return R;
|
||||
}
|
||||
}
|
||||
struct tl_combinator_tree *t;
|
||||
@ -2174,7 +2174,7 @@ struct tl_combinator_tree *change_first_var (struct tl_combinator_tree *O, struc
|
||||
if (!t) { return 0;}
|
||||
if (t == (void *)-1l) { return (void *)-1l; }
|
||||
if (t != (void *)-2l) { return t;}
|
||||
return (void *)-1l;
|
||||
return (void *)-1l;
|
||||
}
|
||||
if (t != (void *)-2l) {
|
||||
O->left = t;
|
||||
@ -2182,7 +2182,7 @@ struct tl_combinator_tree *change_first_var (struct tl_combinator_tree *O, struc
|
||||
t = change_first_var (O->right, X, Y);
|
||||
if (!t) { return 0;}
|
||||
if (t == (void *)-1l) {
|
||||
return O->left;
|
||||
return O->left;
|
||||
}
|
||||
if (t != (void *)-2l) {
|
||||
O->right = t;
|
||||
@ -2267,7 +2267,7 @@ struct tl_combinator_tree *change_value_var (struct tl_combinator_tree *O, struc
|
||||
if (!t) { return 0;}
|
||||
if (t == (void *)-1l) { return (void *)-1l; }
|
||||
if (t != (void *)-2l) { return t;}
|
||||
return (void *)-1l;
|
||||
return (void *)-1l;
|
||||
}
|
||||
if (t != (void *)-2l) {
|
||||
O->left = t;
|
||||
@ -2275,7 +2275,7 @@ struct tl_combinator_tree *change_value_var (struct tl_combinator_tree *O, struc
|
||||
t = change_value_var (O->right, X);
|
||||
if (!t) { return 0;}
|
||||
if (t == (void *)-1l) {
|
||||
return O->left;
|
||||
return O->left;
|
||||
}
|
||||
if (t != (void *)-2l) {
|
||||
O->right = t;
|
||||
@ -2324,7 +2324,7 @@ int tl_parse_partial_type_app_decl (struct tree *T) {
|
||||
assert (nt);
|
||||
//snprintf (_buf, 100000, "%s #", t->id);
|
||||
//nt->real_id = strdup (_buf);
|
||||
|
||||
|
||||
for (i = 0; i < t->constructors_num; i++) {
|
||||
struct tl_constructor *c = t->constructors[i];
|
||||
struct tree_var_value *V = 0;
|
||||
@ -2332,7 +2332,7 @@ int tl_parse_partial_type_app_decl (struct tree *T) {
|
||||
TL_INIT (B);
|
||||
A = tl_tree_dup (c->left);
|
||||
B = tl_tree_dup (c->right);
|
||||
|
||||
|
||||
struct tree_var_value *W = 0;
|
||||
change_var_ptrs (c->left, A, &W);
|
||||
change_var_ptrs (c->right, B, &W);
|
||||
@ -2349,7 +2349,7 @@ int tl_parse_partial_type_app_decl (struct tree *T) {
|
||||
struct tl_constructor *r = tl_add_constructor (nt, _buf, strlen (_buf), 1);
|
||||
snprintf (_buf, 100000, "%s", c->id);
|
||||
r->real_id = tstrdup (_buf);
|
||||
|
||||
|
||||
r->left = A;
|
||||
r->right = B;
|
||||
if (!r->name) {
|
||||
@ -2377,8 +2377,8 @@ int tl_parse_partial_comb_app_decl (struct tree *T, int fun) {
|
||||
TL_INIT (R);
|
||||
L = tl_tree_dup (c->left);
|
||||
R = tl_tree_dup (c->right);
|
||||
|
||||
|
||||
|
||||
|
||||
struct tree_var_value *V = 0;
|
||||
change_var_ptrs (c->left, L, &V);
|
||||
change_var_ptrs (c->right, R, &V);
|
||||
@ -2391,7 +2391,7 @@ int tl_parse_partial_comb_app_decl (struct tree *T, int fun) {
|
||||
TL_INIT (Z);
|
||||
X = tl_parse_any_term (T->c[i], 0);
|
||||
struct tl_combinator_tree *K = 0;
|
||||
if (!(Z = change_first_var (L, &K, X))) {
|
||||
if (!(Z = change_first_var (L, &K, X))) {
|
||||
TL_FAIL;
|
||||
}
|
||||
L = Z;
|
||||
@ -2516,7 +2516,7 @@ int tl_parse_builtin_combinator_decl (struct tree *T, int fun) {
|
||||
if (!c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
c->left = alloc_ctree_node ();
|
||||
c->left->act = act_question_mark;
|
||||
c->left->type = type_list_item;
|
||||
@ -2615,7 +2615,7 @@ int uniformize (struct tl_combinator_tree *L, struct tl_combinator_tree *R, stru
|
||||
if (R->act == act_var) {
|
||||
struct tl_combinator_tree *_ = R; R = L; L = _;
|
||||
}
|
||||
|
||||
|
||||
if (L->type == type_type) {
|
||||
if (R->type != type_type || L->type_len != R->type_len || L->type_flags != R->type_flags) {
|
||||
return 0;
|
||||
@ -2695,14 +2695,14 @@ int uniformize (struct tl_combinator_tree *L, struct tl_combinator_tree *R, stru
|
||||
M = tl_get_var_value (T, M->data);
|
||||
}
|
||||
if (K->type == type_num_value && M->type == type_num_value) {
|
||||
return x == y;
|
||||
return x == y;
|
||||
}
|
||||
if (M->type == type_num_value) {
|
||||
tl_set_var_value_num (T, K->data, M, -(x - y + M->type_flags));
|
||||
return 1;
|
||||
return 1;
|
||||
} else if (K->type == type_num_value) {
|
||||
tl_set_var_value_num (T, M->data, K, -(y - x + K->type_flags));
|
||||
return 1;
|
||||
return 1;
|
||||
} else {
|
||||
if (x >= y) {
|
||||
tl_set_var_value_num (T, K->data, M, -(x - y + M->type_flags));
|
||||
@ -2720,7 +2720,7 @@ void tl_type_check (struct tl_type *t) {
|
||||
if (!__ok) return;
|
||||
if (!strcmp (t->id, "#")) { t->name = 0x70659eff; return; }
|
||||
if (!strcmp (t->id, "Type")) { t->name = 0x2cecf817; return; }
|
||||
if (t->constructors_num <= 0 && !(t->flags & FLAG_EMPTY)) {
|
||||
if (t->constructors_num <= 0 && !(t->flags & FLAG_EMPTY)) {
|
||||
TL_ERROR ("Type %s has no constructors\n", t->id);
|
||||
__ok = 0;
|
||||
return;
|
||||
@ -2739,7 +2739,7 @@ void tl_type_check (struct tl_type *t) {
|
||||
}
|
||||
}
|
||||
if ((t->flags & 24) == 24) {
|
||||
TL_WARNING ("Warning: Type %s has overlapping costructors, but it is used with `%%`\n", t->id);
|
||||
TL_WARNING ("Warning: Type %s has overlapping costructors, but it is used with `%%`\n", t->id);
|
||||
}
|
||||
int z = 0;
|
||||
int sid = 0;
|
||||
@ -2907,7 +2907,7 @@ void write_args (struct tl_combinator_tree *T, struct tree_var_value **v, int *l
|
||||
tl_set_var_value_num (v, T, 0, (*last_var) - 1);
|
||||
} else {
|
||||
write_field_flags (f);
|
||||
}
|
||||
}
|
||||
write_tree (T->left, 0, v, last_var);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ int main (int argc, char **argv) {
|
||||
if (argc != optind + 1) {
|
||||
usage ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct parse *P = tl_init_parse_file (argv[optind]);
|
||||
if (!P) {
|
||||
|
@ -1344,4 +1344,7 @@ void AccountManager::get_current_state(vector<td_api::object_ptr<td_api::Update>
|
||||
}
|
||||
}
|
||||
|
||||
void AccountManager::memory_stats(vector<string> &output) {
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -21,6 +21,7 @@ class Td;
|
||||
|
||||
class AccountManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
AccountManager(Td *td, ActorShared<> parent);
|
||||
AccountManager(const AccountManager &) = delete;
|
||||
AccountManager &operator=(const AccountManager &) = delete;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/Document.h"
|
||||
#include "td/telegram/DocumentsManager.h"
|
||||
#include "td/telegram/MemoryManager.h"
|
||||
#include "td/telegram/FileReferenceManager.h"
|
||||
#include "td/telegram/files/FileManager.h"
|
||||
#include "td/telegram/files/FileType.h"
|
||||
@ -191,8 +192,10 @@ FileId AnimationsManager::on_get_animation(unique_ptr<Animation> new_animation,
|
||||
LOG(DEBUG) << "Animation " << file_id << " duration has changed";
|
||||
a->duration = new_animation->duration;
|
||||
}
|
||||
if (a->minithumbnail != new_animation->minithumbnail) {
|
||||
a->minithumbnail = std::move(new_animation->minithumbnail);
|
||||
if (!G()->get_option_boolean("disable_minithumbnails")) {
|
||||
if (a->minithumbnail != new_animation->minithumbnail) {
|
||||
a->minithumbnail = std::move(new_animation->minithumbnail);
|
||||
}
|
||||
}
|
||||
if (a->thumbnail != new_animation->thumbnail) {
|
||||
if (!a->thumbnail.file_id.is_valid()) {
|
||||
@ -295,8 +298,10 @@ void AnimationsManager::create_animation(FileId file_id, string minithumbnail, P
|
||||
a->mime_type = std::move(mime_type);
|
||||
a->duration = max(duration, 0);
|
||||
a->dimensions = dimensions;
|
||||
if (!td_->auth_manager_->is_bot()) {
|
||||
a->minithumbnail = std::move(minithumbnail);
|
||||
if (!G()->get_option_boolean("disable_minithumbnails")) {
|
||||
if (!td_->auth_manager_->is_bot()) {
|
||||
a->minithumbnail = std::move(minithumbnail);
|
||||
}
|
||||
}
|
||||
a->thumbnail = std::move(thumbnail);
|
||||
a->animated_thumbnail = std::move(animated_thumbnail);
|
||||
@ -882,4 +887,16 @@ void AnimationsManager::get_current_state(vector<td_api::object_ptr<td_api::Upda
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationsManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"animations_\":"); output.emplace_back(std::to_string(this->animations_.calc_size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"saved_animation_ids_\":"); output.emplace_back(std::to_string(this->saved_animation_ids_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"saved_animation_file_ids_\":"); output.emplace_back(std::to_string(this->saved_animation_file_ids_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"load_saved_animations_queries_\":"); output.emplace_back(std::to_string(this->load_saved_animations_queries_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"repair_saved_animations_queries_\":"); output.emplace_back(std::to_string(this->repair_saved_animations_queries_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -28,6 +28,7 @@ class Td;
|
||||
|
||||
class AnimationsManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
AnimationsManager(Td *td, ActorShared<> parent);
|
||||
AnimationsManager(const AnimationsManager &) = delete;
|
||||
AnimationsManager &operator=(const AnimationsManager &) = delete;
|
||||
|
@ -55,10 +55,27 @@ FileId AnimationsManager::parse_animation(ParserT &parser) {
|
||||
parse(animation->duration, parser);
|
||||
}
|
||||
parse(animation->dimensions, parser);
|
||||
parse(animation->file_name, parser);
|
||||
|
||||
string tmp_filename;
|
||||
parse(tmp_filename, parser);
|
||||
|
||||
parse(animation->mime_type, parser);
|
||||
|
||||
if ( G()->get_option_boolean("disable_document_filenames") && (
|
||||
animation->mime_type.rfind("image/") == 0 ||
|
||||
animation->mime_type.rfind("video/") == 0 ||
|
||||
animation->mime_type.rfind("audio/") == 0)) {
|
||||
animation->file_name = "0";
|
||||
} else {
|
||||
animation->file_name = tmp_filename;
|
||||
}
|
||||
|
||||
if (parser.version() >= static_cast<int32>(Version::SupportMinithumbnails)) {
|
||||
parse(animation->minithumbnail, parser);
|
||||
string tmp_minithumbnail;
|
||||
parse(tmp_minithumbnail, parser);
|
||||
if (!G()->get_option_boolean("disable_minithumbnails")) {
|
||||
animation->minithumbnail = tmp_minithumbnail;
|
||||
}
|
||||
}
|
||||
parse(animation->thumbnail, parser);
|
||||
parse(animation->file_id, parser);
|
||||
|
@ -1354,4 +1354,16 @@ void AttachMenuManager::get_current_state(vector<td_api::object_ptr<td_api::Upda
|
||||
updates.push_back(get_update_attachment_menu_bots_object());
|
||||
}
|
||||
|
||||
void AttachMenuManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"attach_menu_bots_\":"); output.emplace_back(std::to_string(this->attach_menu_bots_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"attach_menu_bot_file_source_ids_\":"); output.emplace_back(std::to_string(this->attach_menu_bot_file_source_ids_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"reload_attach_menu_bots_queries_\":"); output.emplace_back(std::to_string(this->reload_attach_menu_bots_queries_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"web_app_file_source_ids_\":"); output.emplace_back(std::to_string(this->web_app_file_source_ids_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"opened_web_views_\":"); output.emplace_back(std::to_string(this->opened_web_views_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -29,6 +29,7 @@ class Td;
|
||||
|
||||
class AttachMenuManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
AttachMenuManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void init();
|
||||
|
@ -309,4 +309,8 @@ tl_object_ptr<telegram_api::InputMedia> AudiosManager::get_input_media(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AudiosManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"audios_\":"); output.emplace_back(std::to_string(this->audios_.calc_size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -22,6 +22,7 @@ class Td;
|
||||
|
||||
class AudiosManager {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
explicit AudiosManager(Td *td);
|
||||
AudiosManager(const AudiosManager &) = delete;
|
||||
AudiosManager &operator=(const AudiosManager &) = delete;
|
||||
|
@ -99,7 +99,13 @@ FileId AudiosManager::parse_audio(ParserT &parser) {
|
||||
has_date = false;
|
||||
}
|
||||
if (has_file_name) {
|
||||
parse(audio->file_name, parser);
|
||||
string tmp_filename;
|
||||
parse(tmp_filename, parser);
|
||||
if (G()->get_option_boolean("disable_document_filenames")) {
|
||||
audio->file_name = "0";
|
||||
} else {
|
||||
audio->file_name = tmp_filename;
|
||||
}
|
||||
}
|
||||
if (has_mime_type) {
|
||||
parse(audio->mime_type, parser);
|
||||
@ -114,7 +120,11 @@ FileId AudiosManager::parse_audio(ParserT &parser) {
|
||||
parse(audio->performer, parser);
|
||||
}
|
||||
if (has_minithumbnail) {
|
||||
parse(audio->minithumbnail, parser);
|
||||
string tmp_minithumbnail;
|
||||
parse(tmp_minithumbnail, parser);
|
||||
if (!G()->get_option_boolean("disable_minithumbnails")) {
|
||||
audio->minithumbnail = tmp_minithumbnail;
|
||||
}
|
||||
}
|
||||
if (has_thumbnail) {
|
||||
parse(audio->thumbnail, parser);
|
||||
|
@ -1482,4 +1482,10 @@ void AuthManager::save_state() {
|
||||
G()->td_db()->get_binlog_pmc()->set("auth_state", log_event_store(db_state).as_slice().str());
|
||||
}
|
||||
|
||||
void AuthManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"other_user_ids_\":"); output.emplace_back(std::to_string(this->other_user_ids_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"pending_get_authorization_state_requests_\":"); output.emplace_back(std::to_string(this->pending_get_authorization_state_requests_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -26,6 +26,7 @@ namespace td {
|
||||
|
||||
class AuthManager final : public NetActor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
AuthManager(int32 api_id, const string &api_hash, ActorShared<> parent);
|
||||
|
||||
bool is_bot() const {
|
||||
|
@ -126,14 +126,27 @@ class SaveAutoDownloadSettingsQuery final : public Td::ResultHandler {
|
||||
AutoDownloadSettings get_auto_download_settings(const td_api::object_ptr<td_api::autoDownloadSettings> &settings) {
|
||||
CHECK(settings != nullptr);
|
||||
AutoDownloadSettings result;
|
||||
result.max_photo_file_size = settings->max_photo_file_size_;
|
||||
result.max_video_file_size = settings->max_video_file_size_;
|
||||
result.max_other_file_size = settings->max_other_file_size_;
|
||||
if (G()->get_option_boolean("disable_auto_download")) {
|
||||
result.max_photo_file_size = -1;
|
||||
result.max_video_file_size = -1;
|
||||
result.max_other_file_size = -1;
|
||||
} else {
|
||||
result.max_photo_file_size = settings->max_photo_file_size_;
|
||||
result.max_video_file_size = settings->max_video_file_size_;
|
||||
result.max_other_file_size = settings->max_other_file_size_;
|
||||
}
|
||||
result.video_upload_bitrate = settings->video_upload_bitrate_;
|
||||
result.is_enabled = settings->is_auto_download_enabled_;
|
||||
result.preload_large_videos = settings->preload_large_videos_;
|
||||
result.preload_next_audio = settings->preload_next_audio_;
|
||||
result.preload_stories = settings->preload_stories_;
|
||||
if (G()->get_option_boolean("disable_auto_download")) {
|
||||
result.is_enabled = false;
|
||||
result.preload_large_videos = false;
|
||||
result.preload_next_audio = false;
|
||||
result.preload_stories = false;
|
||||
} else {
|
||||
result.is_enabled = settings->is_auto_download_enabled_;
|
||||
result.preload_large_videos = settings->preload_large_videos_;
|
||||
result.preload_next_audio = settings->preload_next_audio_;
|
||||
result.preload_stories = settings->preload_stories_;
|
||||
}
|
||||
result.use_less_data_for_calls = settings->use_less_data_for_calls_;
|
||||
return result;
|
||||
}
|
||||
|
@ -552,4 +552,8 @@ void AutosaveManager::get_current_state(vector<td_api::object_ptr<td_api::Update
|
||||
}
|
||||
}
|
||||
|
||||
void AutosaveManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"load_settings_queries_\":"); output.emplace_back(std::to_string(this->load_settings_queries_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -23,6 +23,7 @@ class Td;
|
||||
|
||||
class AutosaveManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
AutosaveManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void reload_autosave_settings();
|
||||
|
@ -1491,4 +1491,24 @@ void BackgroundManager::get_current_state(vector<td_api::object_ptr<td_api::Upda
|
||||
updates.push_back(get_update_default_background_object(true));
|
||||
}
|
||||
|
||||
void BackgroundManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"backgrounds_\":"); output.emplace_back(std::to_string(this->backgrounds_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"background_id_to_file_source_id_\":"); output.emplace_back(std::to_string(this->background_id_to_file_source_id_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"name_to_background_id_\":"); output.emplace_back(std::to_string(this->name_to_background_id_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"file_id_to_background_id_\":"); output.emplace_back(std::to_string(this->file_id_to_background_id_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"loaded_from_database_backgrounds_\":"); output.emplace_back(std::to_string(this->loaded_from_database_backgrounds_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"being_loaded_from_database_backgrounds_\":"); output.emplace_back(std::to_string(this->being_loaded_from_database_backgrounds_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"installed_backgrounds_\":"); output.emplace_back(std::to_string(this->installed_backgrounds_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"pending_get_backgrounds_queries_\":"); output.emplace_back(std::to_string(this->pending_get_backgrounds_queries_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"being_uploaded_files_\":"); output.emplace_back(std::to_string(this->being_uploaded_files_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -33,6 +33,7 @@ class Td;
|
||||
|
||||
class BackgroundManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
BackgroundManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void get_backgrounds(bool for_dark_theme, Promise<td_api::object_ptr<td_api::backgrounds>> &&promise);
|
||||
|
@ -510,4 +510,7 @@ void BoostManager::on_update_dialog_boost(DialogId dialog_id, telegram_api::obje
|
||||
td_->dialog_manager_->get_chat_id_object(dialog_id, "updateChatBoost"), std::move(chat_boost_object)));
|
||||
}
|
||||
|
||||
void BoostManager::memory_stats(vector<string> &output) {
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -27,6 +27,7 @@ class Td;
|
||||
|
||||
class BoostManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
BoostManager(Td *td, ActorShared<> parent);
|
||||
|
||||
td_api::object_ptr<td_api::chatBoostLevelFeatures> get_chat_boost_level_features_object(bool for_megagroup,
|
||||
|
@ -442,4 +442,10 @@ void BotInfoManager::get_bot_info_about(UserId bot_user_id, const string &langua
|
||||
add_pending_get_query(bot_user_id, language_code, 2, std::move(promise));
|
||||
}
|
||||
|
||||
void BotInfoManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"pending_set_bot_info_queries_\":"); output.emplace_back(std::to_string(this->pending_set_bot_info_queries_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"pending_get_bot_info_queries_\":"); output.emplace_back(std::to_string(this->pending_get_bot_info_queries_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -20,6 +20,7 @@ class Td;
|
||||
|
||||
class BotInfoManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
BotInfoManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void set_default_group_administrator_rights(AdministratorRights administrator_rights, Promise<Unit> &&promise);
|
||||
|
62
td/telegram/BusinessAwayMessage.cpp
Normal file
62
td/telegram/BusinessAwayMessage.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessAwayMessage.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
BusinessAwayMessage::BusinessAwayMessage(telegram_api::object_ptr<telegram_api::businessAwayMessage> away_message) {
|
||||
if (away_message == nullptr) {
|
||||
return;
|
||||
}
|
||||
shortcut_id_ = QuickReplyShortcutId(away_message->shortcut_id_);
|
||||
recipients_ = BusinessRecipients(std::move(away_message->recipients_));
|
||||
schedule_ = BusinessAwayMessageSchedule(std::move(away_message->schedule_));
|
||||
offline_only_ = away_message->offline_only_;
|
||||
}
|
||||
|
||||
BusinessAwayMessage::BusinessAwayMessage(td_api::object_ptr<td_api::businessAwayMessageSettings> away_message) {
|
||||
if (away_message == nullptr) {
|
||||
return;
|
||||
}
|
||||
shortcut_id_ = QuickReplyShortcutId(away_message->shortcut_id_);
|
||||
recipients_ = BusinessRecipients(std::move(away_message->recipients_));
|
||||
schedule_ = BusinessAwayMessageSchedule(std::move(away_message->schedule_));
|
||||
offline_only_ = away_message->offline_only_;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessAwayMessageSettings> BusinessAwayMessage::get_business_away_message_settings_object(
|
||||
Td *td) const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::businessAwayMessageSettings>(
|
||||
shortcut_id_.get(), recipients_.get_business_recipients_object(td),
|
||||
schedule_.get_business_away_message_schedule_object(), offline_only_);
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputBusinessAwayMessage> BusinessAwayMessage::get_input_business_away_message(
|
||||
Td *td) const {
|
||||
int32 flags = 0;
|
||||
if (offline_only_) {
|
||||
flags |= telegram_api::inputBusinessAwayMessage::OFFLINE_ONLY_MASK;
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::inputBusinessAwayMessage>(
|
||||
flags, false /*ignored*/, shortcut_id_.get(), schedule_.get_input_business_away_message_schedule(),
|
||||
recipients_.get_input_business_recipients(td));
|
||||
}
|
||||
|
||||
bool operator==(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs) {
|
||||
return lhs.shortcut_id_ == rhs.shortcut_id_ && lhs.recipients_ == rhs.recipients_ && lhs.schedule_ == rhs.schedule_ &&
|
||||
lhs.offline_only_ == rhs.offline_only_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessage &away_message) {
|
||||
return string_builder << "away message " << away_message.shortcut_id_ << ' ' << away_message.recipients_ << ' '
|
||||
<< away_message.schedule_ << (away_message.offline_only_ ? " only offline" : "");
|
||||
}
|
||||
|
||||
} // namespace td
|
67
td/telegram/BusinessAwayMessage.h
Normal file
67
td/telegram/BusinessAwayMessage.h
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessAwayMessageSchedule.h"
|
||||
#include "td/telegram/BusinessRecipients.h"
|
||||
#include "td/telegram/QuickReplyShortcutId.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class BusinessAwayMessage {
|
||||
public:
|
||||
BusinessAwayMessage() = default;
|
||||
|
||||
explicit BusinessAwayMessage(telegram_api::object_ptr<telegram_api::businessAwayMessage> away_message);
|
||||
|
||||
explicit BusinessAwayMessage(td_api::object_ptr<td_api::businessAwayMessageSettings> away_message);
|
||||
|
||||
td_api::object_ptr<td_api::businessAwayMessageSettings> get_business_away_message_settings_object(Td *td) const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputBusinessAwayMessage> get_input_business_away_message(Td *td) const;
|
||||
|
||||
bool is_empty() const {
|
||||
return !is_valid();
|
||||
}
|
||||
|
||||
bool is_valid() const {
|
||||
return shortcut_id_.is_server();
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
QuickReplyShortcutId shortcut_id_;
|
||||
BusinessRecipients recipients_;
|
||||
BusinessAwayMessageSchedule schedule_;
|
||||
bool offline_only_ = false;
|
||||
|
||||
friend bool operator==(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessage &away_message);
|
||||
};
|
||||
|
||||
bool operator==(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs);
|
||||
|
||||
inline bool operator!=(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessage &away_message);
|
||||
|
||||
} // namespace td
|
38
td/telegram/BusinessAwayMessage.hpp
Normal file
38
td/telegram/BusinessAwayMessage.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessAwayMessage.h"
|
||||
#include "td/telegram/BusinessAwayMessageSchedule.hpp"
|
||||
#include "td/telegram/BusinessRecipients.hpp"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessAwayMessage::store(StorerT &storer) const {
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(offline_only_);
|
||||
END_STORE_FLAGS();
|
||||
td::store(shortcut_id_, storer);
|
||||
td::store(recipients_, storer);
|
||||
td::store(schedule_, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessAwayMessage::parse(ParserT &parser) {
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(offline_only_);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(shortcut_id_, parser);
|
||||
td::parse(recipients_, parser);
|
||||
td::parse(schedule_, parser);
|
||||
}
|
||||
|
||||
} // namespace td
|
105
td/telegram/BusinessAwayMessageSchedule.cpp
Normal file
105
td/telegram/BusinessAwayMessageSchedule.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessAwayMessageSchedule.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
BusinessAwayMessageSchedule::BusinessAwayMessageSchedule(
|
||||
telegram_api::object_ptr<telegram_api::BusinessAwayMessageSchedule> schedule) {
|
||||
CHECK(schedule != nullptr);
|
||||
switch (schedule->get_id()) {
|
||||
case telegram_api::businessAwayMessageScheduleAlways::ID:
|
||||
type_ = Type::Always;
|
||||
break;
|
||||
case telegram_api::businessAwayMessageScheduleOutsideWorkHours::ID:
|
||||
type_ = Type::OutsideOfWorkHours;
|
||||
break;
|
||||
case telegram_api::businessAwayMessageScheduleCustom::ID: {
|
||||
auto custom_schedule = telegram_api::move_object_as<telegram_api::businessAwayMessageScheduleCustom>(schedule);
|
||||
type_ = Type::Custom;
|
||||
start_date_ = custom_schedule->start_date_;
|
||||
end_date_ = custom_schedule->end_date_;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
BusinessAwayMessageSchedule::BusinessAwayMessageSchedule(
|
||||
td_api::object_ptr<td_api::BusinessAwayMessageSchedule> schedule) {
|
||||
if (schedule == nullptr) {
|
||||
return;
|
||||
}
|
||||
switch (schedule->get_id()) {
|
||||
case td_api::businessAwayMessageScheduleAlways::ID:
|
||||
type_ = Type::Always;
|
||||
break;
|
||||
case td_api::businessAwayMessageScheduleOutsideOfOpeningHours::ID:
|
||||
type_ = Type::OutsideOfWorkHours;
|
||||
break;
|
||||
case td_api::businessAwayMessageScheduleCustom::ID: {
|
||||
auto custom_schedule = td_api::move_object_as<td_api::businessAwayMessageScheduleCustom>(schedule);
|
||||
type_ = Type::Custom;
|
||||
start_date_ = custom_schedule->start_date_;
|
||||
end_date_ = custom_schedule->end_date_;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::BusinessAwayMessageSchedule>
|
||||
BusinessAwayMessageSchedule::get_business_away_message_schedule_object() const {
|
||||
switch (type_) {
|
||||
case Type::Always:
|
||||
return td_api::make_object<td_api::businessAwayMessageScheduleAlways>();
|
||||
case Type::OutsideOfWorkHours:
|
||||
return td_api::make_object<td_api::businessAwayMessageScheduleOutsideOfOpeningHours>();
|
||||
case Type::Custom:
|
||||
return td_api::make_object<td_api::businessAwayMessageScheduleCustom>(start_date_, end_date_);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::BusinessAwayMessageSchedule>
|
||||
BusinessAwayMessageSchedule::get_input_business_away_message_schedule() const {
|
||||
switch (type_) {
|
||||
case Type::Always:
|
||||
return telegram_api::make_object<telegram_api::businessAwayMessageScheduleAlways>();
|
||||
case Type::OutsideOfWorkHours:
|
||||
return telegram_api::make_object<telegram_api::businessAwayMessageScheduleOutsideWorkHours>();
|
||||
case Type::Custom:
|
||||
return telegram_api::make_object<telegram_api::businessAwayMessageScheduleCustom>(start_date_, end_date_);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs) {
|
||||
return lhs.type_ == rhs.type_ && lhs.start_date_ == rhs.start_date_ && lhs.end_date_ == rhs.end_date_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessageSchedule &schedule) {
|
||||
switch (schedule.type_) {
|
||||
case BusinessAwayMessageSchedule::Type::Always:
|
||||
return string_builder << "sent always";
|
||||
case BusinessAwayMessageSchedule::Type::OutsideOfWorkHours:
|
||||
return string_builder << "sent outside of opening hours";
|
||||
case BusinessAwayMessageSchedule::Type::Custom:
|
||||
return string_builder << "sent from " << schedule.start_date_ << " to " << schedule.end_date_;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return string_builder;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
54
td/telegram/BusinessAwayMessageSchedule.h
Normal file
54
td/telegram/BusinessAwayMessageSchedule.h
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class BusinessAwayMessageSchedule {
|
||||
public:
|
||||
BusinessAwayMessageSchedule() = default;
|
||||
|
||||
explicit BusinessAwayMessageSchedule(telegram_api::object_ptr<telegram_api::BusinessAwayMessageSchedule> schedule);
|
||||
|
||||
explicit BusinessAwayMessageSchedule(td_api::object_ptr<td_api::BusinessAwayMessageSchedule> schedule);
|
||||
|
||||
td_api::object_ptr<td_api::BusinessAwayMessageSchedule> get_business_away_message_schedule_object() const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::BusinessAwayMessageSchedule> get_input_business_away_message_schedule() const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
enum class Type : int32 { Always, OutsideOfWorkHours, Custom };
|
||||
Type type_ = Type::Always;
|
||||
int32 start_date_ = 0;
|
||||
int32 end_date_ = 0;
|
||||
|
||||
friend bool operator==(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessageSchedule &schedule);
|
||||
};
|
||||
|
||||
bool operator==(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs);
|
||||
|
||||
inline bool operator!=(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessageSchedule &schedule);
|
||||
|
||||
} // namespace td
|
50
td/telegram/BusinessAwayMessageSchedule.hpp
Normal file
50
td/telegram/BusinessAwayMessageSchedule.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessAwayMessageSchedule.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessAwayMessageSchedule::store(StorerT &storer) const {
|
||||
bool has_start_date = start_date_ != 0;
|
||||
bool has_end_date = end_date_ != 0;
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_start_date);
|
||||
STORE_FLAG(has_end_date);
|
||||
END_STORE_FLAGS();
|
||||
td::store(type_, storer);
|
||||
if (has_start_date) {
|
||||
td::store(start_date_, storer);
|
||||
}
|
||||
if (has_end_date) {
|
||||
td::store(end_date_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessAwayMessageSchedule::parse(ParserT &parser) {
|
||||
bool has_start_date;
|
||||
bool has_end_date;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_start_date);
|
||||
PARSE_FLAG(has_end_date);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(type_, parser);
|
||||
if (has_start_date) {
|
||||
td::parse(start_date_, parser);
|
||||
}
|
||||
if (has_end_date) {
|
||||
td::parse(end_date_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
46
td/telegram/BusinessConnectedBot.cpp
Normal file
46
td/telegram/BusinessConnectedBot.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessConnectedBot.h"
|
||||
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
BusinessConnectedBot::BusinessConnectedBot(telegram_api::object_ptr<telegram_api::connectedBot> connected_bot) {
|
||||
CHECK(connected_bot != nullptr);
|
||||
user_id_ = UserId(connected_bot->bot_id_);
|
||||
recipients_ = BusinessRecipients(std::move(connected_bot->recipients_));
|
||||
can_reply_ = connected_bot->can_reply_;
|
||||
}
|
||||
|
||||
BusinessConnectedBot::BusinessConnectedBot(td_api::object_ptr<td_api::businessConnectedBot> connected_bot) {
|
||||
if (connected_bot == nullptr) {
|
||||
return;
|
||||
}
|
||||
user_id_ = UserId(connected_bot->bot_user_id_);
|
||||
recipients_ = BusinessRecipients(std::move(connected_bot->recipients_));
|
||||
can_reply_ = connected_bot->can_reply_;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessConnectedBot> BusinessConnectedBot::get_business_connected_bot_object(Td *td) const {
|
||||
CHECK(is_valid());
|
||||
return td_api::make_object<td_api::businessConnectedBot>(
|
||||
td->contacts_manager_->get_user_id_object(user_id_, "businessConnectedBot"),
|
||||
recipients_.get_business_recipients_object(td), can_reply_);
|
||||
}
|
||||
|
||||
bool operator==(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs) {
|
||||
return lhs.user_id_ == rhs.user_id_ && lhs.recipients_ == rhs.recipients_ && lhs.can_reply_ == rhs.can_reply_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessConnectedBot &connected_bot) {
|
||||
return string_builder << "coneected bot " << connected_bot.user_id_ << ' ' << connected_bot.recipients_ << ' '
|
||||
<< (connected_bot.can_reply_ ? " that can reply" : " read-only");
|
||||
}
|
||||
|
||||
} // namespace td
|
71
td/telegram/BusinessConnectedBot.h
Normal file
71
td/telegram/BusinessConnectedBot.h
Normal file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessRecipients.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class BusinessConnectedBot {
|
||||
public:
|
||||
BusinessConnectedBot() = default;
|
||||
|
||||
explicit BusinessConnectedBot(telegram_api::object_ptr<telegram_api::connectedBot> connected_bot);
|
||||
|
||||
explicit BusinessConnectedBot(td_api::object_ptr<td_api::businessConnectedBot> connected_bot);
|
||||
|
||||
td_api::object_ptr<td_api::businessConnectedBot> get_business_connected_bot_object(Td *td) const;
|
||||
|
||||
bool is_valid() const {
|
||||
return user_id_.is_valid();
|
||||
}
|
||||
|
||||
UserId get_user_id() const {
|
||||
return user_id_;
|
||||
}
|
||||
|
||||
const BusinessRecipients &get_recipients() const {
|
||||
return recipients_;
|
||||
}
|
||||
|
||||
bool get_can_reply() const {
|
||||
return can_reply_;
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
UserId user_id_;
|
||||
BusinessRecipients recipients_;
|
||||
bool can_reply_ = false;
|
||||
|
||||
friend bool operator==(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessConnectedBot &connected_bot);
|
||||
};
|
||||
|
||||
bool operator==(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs);
|
||||
|
||||
inline bool operator!=(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessConnectedBot &connected_bot);
|
||||
|
||||
} // namespace td
|
35
td/telegram/BusinessConnectedBot.hpp
Normal file
35
td/telegram/BusinessConnectedBot.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessConnectedBot.h"
|
||||
#include "td/telegram/BusinessRecipients.hpp"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessConnectedBot::store(StorerT &storer) const {
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(can_reply_);
|
||||
END_STORE_FLAGS();
|
||||
td::store(user_id_, storer);
|
||||
td::store(recipients_, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessConnectedBot::parse(ParserT &parser) {
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(can_reply_);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(user_id_, parser);
|
||||
td::parse(recipients_, parser);
|
||||
}
|
||||
|
||||
} // namespace td
|
62
td/telegram/BusinessGreetingMessage.cpp
Normal file
62
td/telegram/BusinessGreetingMessage.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessGreetingMessage.h"
|
||||
|
||||
#include "td/utils/misc.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
BusinessGreetingMessage::BusinessGreetingMessage(
|
||||
telegram_api::object_ptr<telegram_api::businessGreetingMessage> greeting_message) {
|
||||
if (greeting_message == nullptr) {
|
||||
return;
|
||||
}
|
||||
shortcut_id_ = QuickReplyShortcutId(greeting_message->shortcut_id_);
|
||||
recipients_ = BusinessRecipients(std::move(greeting_message->recipients_));
|
||||
inactivity_days_ = clamp(greeting_message->no_activity_days_ / 7 * 7, 7, 28);
|
||||
}
|
||||
|
||||
BusinessGreetingMessage::BusinessGreetingMessage(
|
||||
td_api::object_ptr<td_api::businessGreetingMessageSettings> greeting_message) {
|
||||
if (greeting_message == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto inactivity_days = greeting_message->inactivity_days_;
|
||||
if (inactivity_days < 7 || inactivity_days > 28 || inactivity_days % 7 != 0) {
|
||||
return;
|
||||
}
|
||||
shortcut_id_ = QuickReplyShortcutId(greeting_message->shortcut_id_);
|
||||
recipients_ = BusinessRecipients(std::move(greeting_message->recipients_));
|
||||
inactivity_days_ = inactivity_days;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessGreetingMessageSettings>
|
||||
BusinessGreetingMessage::get_business_greeting_message_settings_object(Td *td) const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::businessGreetingMessageSettings>(
|
||||
shortcut_id_.get(), recipients_.get_business_recipients_object(td), inactivity_days_);
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputBusinessGreetingMessage>
|
||||
BusinessGreetingMessage::get_input_business_greeting_message(Td *td) const {
|
||||
return telegram_api::make_object<telegram_api::inputBusinessGreetingMessage>(
|
||||
shortcut_id_.get(), recipients_.get_input_business_recipients(td), inactivity_days_);
|
||||
}
|
||||
|
||||
bool operator==(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs) {
|
||||
return lhs.shortcut_id_ == rhs.shortcut_id_ && lhs.recipients_ == rhs.recipients_ &&
|
||||
lhs.inactivity_days_ == rhs.inactivity_days_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessGreetingMessage &greeting_message) {
|
||||
return string_builder << "greeting message " << greeting_message.shortcut_id_ << ' ' << greeting_message.recipients_
|
||||
<< " after " << greeting_message.inactivity_days_ << " inactivity days";
|
||||
}
|
||||
|
||||
} // namespace td
|
67
td/telegram/BusinessGreetingMessage.h
Normal file
67
td/telegram/BusinessGreetingMessage.h
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessRecipients.h"
|
||||
#include "td/telegram/QuickReplyShortcutId.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class BusinessGreetingMessage {
|
||||
public:
|
||||
BusinessGreetingMessage() = default;
|
||||
|
||||
explicit BusinessGreetingMessage(telegram_api::object_ptr<telegram_api::businessGreetingMessage> greeting_message);
|
||||
|
||||
explicit BusinessGreetingMessage(td_api::object_ptr<td_api::businessGreetingMessageSettings> greeting_message);
|
||||
|
||||
td_api::object_ptr<td_api::businessGreetingMessageSettings> get_business_greeting_message_settings_object(
|
||||
Td *td) const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputBusinessGreetingMessage> get_input_business_greeting_message(
|
||||
Td *td) const;
|
||||
|
||||
bool is_empty() const {
|
||||
return !is_valid();
|
||||
}
|
||||
|
||||
bool is_valid() const {
|
||||
return shortcut_id_.is_server();
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
QuickReplyShortcutId shortcut_id_;
|
||||
BusinessRecipients recipients_;
|
||||
int32 inactivity_days_ = 0;
|
||||
|
||||
friend bool operator==(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessGreetingMessage &greeting_message);
|
||||
};
|
||||
|
||||
bool operator==(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs);
|
||||
|
||||
inline bool operator!=(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessGreetingMessage &greeting_message);
|
||||
|
||||
} // namespace td
|
35
td/telegram/BusinessGreetingMessage.hpp
Normal file
35
td/telegram/BusinessGreetingMessage.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessGreetingMessage.h"
|
||||
#include "td/telegram/BusinessRecipients.hpp"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessGreetingMessage::store(StorerT &storer) const {
|
||||
BEGIN_STORE_FLAGS();
|
||||
END_STORE_FLAGS();
|
||||
td::store(shortcut_id_, storer);
|
||||
td::store(recipients_, storer);
|
||||
td::store(inactivity_days_, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessGreetingMessage::parse(ParserT &parser) {
|
||||
BEGIN_PARSE_FLAGS();
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(shortcut_id_, parser);
|
||||
td::parse(recipients_, parser);
|
||||
td::parse(inactivity_days_, parser);
|
||||
}
|
||||
|
||||
} // namespace td
|
87
td/telegram/BusinessInfo.cpp
Normal file
87
td/telegram/BusinessInfo.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessInfo.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
td_api::object_ptr<td_api::businessInfo> BusinessInfo::get_business_info_object(Td *td) const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::businessInfo>(location_.get_business_location_object(),
|
||||
work_hours_.get_business_opening_hours_object(),
|
||||
greeting_message_.get_business_greeting_message_settings_object(td),
|
||||
away_message_.get_business_away_message_settings_object(td));
|
||||
}
|
||||
|
||||
bool BusinessInfo::is_empty_location(const DialogLocation &location) {
|
||||
return location.empty() && location.get_address().empty();
|
||||
}
|
||||
|
||||
bool BusinessInfo::is_empty() const {
|
||||
return is_empty_location(location_) && work_hours_.is_empty() && away_message_.is_empty() &&
|
||||
greeting_message_.is_empty();
|
||||
}
|
||||
|
||||
bool BusinessInfo::set_location(unique_ptr<BusinessInfo> &business_info, DialogLocation &&location) {
|
||||
if (business_info == nullptr) {
|
||||
if (is_empty_location(location)) {
|
||||
return false;
|
||||
}
|
||||
business_info = make_unique<BusinessInfo>();
|
||||
}
|
||||
if (business_info->location_ != location) {
|
||||
business_info->location_ = std::move(location);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BusinessInfo::set_work_hours(unique_ptr<BusinessInfo> &business_info, BusinessWorkHours &&work_hours) {
|
||||
if (business_info == nullptr) {
|
||||
if (work_hours.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
business_info = make_unique<BusinessInfo>();
|
||||
}
|
||||
if (business_info->work_hours_ != work_hours) {
|
||||
business_info->work_hours_ = std::move(work_hours);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BusinessInfo::set_away_message(unique_ptr<BusinessInfo> &business_info, BusinessAwayMessage &&away_message) {
|
||||
if (business_info == nullptr) {
|
||||
if (away_message.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
business_info = make_unique<BusinessInfo>();
|
||||
}
|
||||
if (business_info->away_message_ != away_message) {
|
||||
business_info->away_message_ = std::move(away_message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BusinessInfo::set_greeting_message(unique_ptr<BusinessInfo> &business_info,
|
||||
BusinessGreetingMessage &&greeting_message) {
|
||||
if (business_info == nullptr) {
|
||||
if (greeting_message.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
business_info = make_unique<BusinessInfo>();
|
||||
}
|
||||
if (business_info->greeting_message_ != greeting_message) {
|
||||
business_info->greeting_message_ = std::move(greeting_message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace td
|
50
td/telegram/BusinessInfo.h
Normal file
50
td/telegram/BusinessInfo.h
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessAwayMessage.h"
|
||||
#include "td/telegram/BusinessGreetingMessage.h"
|
||||
#include "td/telegram/BusinessWorkHours.h"
|
||||
#include "td/telegram/DialogLocation.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class BusinessInfo {
|
||||
public:
|
||||
td_api::object_ptr<td_api::businessInfo> get_business_info_object(Td *td) const;
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
static bool set_location(unique_ptr<BusinessInfo> &business_info, DialogLocation &&location);
|
||||
|
||||
static bool set_work_hours(unique_ptr<BusinessInfo> &business_info, BusinessWorkHours &&work_hours);
|
||||
|
||||
static bool set_away_message(unique_ptr<BusinessInfo> &business_info, BusinessAwayMessage &&away_message);
|
||||
|
||||
static bool set_greeting_message(unique_ptr<BusinessInfo> &business_info, BusinessGreetingMessage &&greeting_message);
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
static bool is_empty_location(const DialogLocation &location);
|
||||
|
||||
DialogLocation location_;
|
||||
BusinessWorkHours work_hours_;
|
||||
BusinessAwayMessage away_message_;
|
||||
BusinessGreetingMessage greeting_message_;
|
||||
};
|
||||
|
||||
} // namespace td
|
72
td/telegram/BusinessInfo.hpp
Normal file
72
td/telegram/BusinessInfo.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessInfo.h"
|
||||
|
||||
#include "td/telegram/BusinessAwayMessage.hpp"
|
||||
#include "td/telegram/BusinessGreetingMessage.hpp"
|
||||
#include "td/telegram/BusinessWorkHours.hpp"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessInfo::store(StorerT &storer) const {
|
||||
bool has_location = !is_empty_location(location_);
|
||||
bool has_work_hours = !work_hours_.is_empty();
|
||||
bool has_away_message = away_message_.is_valid();
|
||||
bool has_greeting_message = greeting_message_.is_valid();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_location);
|
||||
STORE_FLAG(has_work_hours);
|
||||
STORE_FLAG(has_away_message);
|
||||
STORE_FLAG(has_greeting_message);
|
||||
END_STORE_FLAGS();
|
||||
if (has_location) {
|
||||
td::store(location_, storer);
|
||||
}
|
||||
if (has_work_hours) {
|
||||
td::store(work_hours_, storer);
|
||||
}
|
||||
if (has_away_message) {
|
||||
td::store(away_message_, storer);
|
||||
}
|
||||
if (has_greeting_message) {
|
||||
td::store(greeting_message_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessInfo::parse(ParserT &parser) {
|
||||
bool has_location;
|
||||
bool has_work_hours;
|
||||
bool has_away_message;
|
||||
bool has_greeting_message;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_location);
|
||||
PARSE_FLAG(has_work_hours);
|
||||
PARSE_FLAG(has_away_message);
|
||||
PARSE_FLAG(has_greeting_message);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_location) {
|
||||
td::parse(location_, parser);
|
||||
}
|
||||
if (has_work_hours) {
|
||||
td::parse(work_hours_, parser);
|
||||
}
|
||||
if (has_away_message) {
|
||||
td::parse(away_message_, parser);
|
||||
}
|
||||
if (has_greeting_message) {
|
||||
td::parse(greeting_message_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
298
td/telegram/BusinessManager.cpp
Normal file
298
td/telegram/BusinessManager.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
||||
//
|
||||
// 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/BusinessManager.h"
|
||||
|
||||
#include "td/telegram/BusinessAwayMessage.h"
|
||||
#include "td/telegram/BusinessConnectedBot.h"
|
||||
#include "td/telegram/BusinessGreetingMessage.h"
|
||||
#include "td/telegram/BusinessRecipients.h"
|
||||
#include "td/telegram/BusinessWorkHours.h"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogLocation.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/UpdatesManager.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class GetConnectedBotsQuery final : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::businessConnectedBot>> promise_;
|
||||
|
||||
public:
|
||||
explicit GetConnectedBotsQuery(Promise<td_api::object_ptr<td_api::businessConnectedBot>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send() {
|
||||
send_query(G()->net_query_creator().create(telegram_api::account_getConnectedBots(), {{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_getConnectedBots>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto result = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetConnectedBotsQuery: " << to_string(result);
|
||||
|
||||
td_->contacts_manager_->on_get_users(std::move(result->users_), "GetConnectedBotsQuery");
|
||||
if (result->connected_bots_.size() > 1u) {
|
||||
return on_error(Status::Error(500, "Receive invalid response"));
|
||||
}
|
||||
if (result->connected_bots_.empty()) {
|
||||
return promise_.set_value(nullptr);
|
||||
}
|
||||
auto bot = BusinessConnectedBot(std::move(result->connected_bots_[0]));
|
||||
if (!bot.is_valid()) {
|
||||
return on_error(Status::Error(500, "Receive invalid bot"));
|
||||
}
|
||||
promise_.set_value(bot.get_business_connected_bot_object(td_));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateConnectedBotQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
|
||||
public:
|
||||
explicit UpdateConnectedBotQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(const BusinessConnectedBot &bot, telegram_api::object_ptr<telegram_api::InputUser> &&input_user) {
|
||||
int32 flags = 0;
|
||||
if (bot.get_can_reply()) {
|
||||
flags |= telegram_api::account_updateConnectedBot::CAN_REPLY_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::account_updateConnectedBot(flags, false /*ignored*/, false /*ignored*/, std::move(input_user),
|
||||
bot.get_recipients().get_input_business_recipients(td_)),
|
||||
{{"me"}}));
|
||||
}
|
||||
|
||||
void send(telegram_api::object_ptr<telegram_api::InputUser> &&input_user) {
|
||||
int32 flags = telegram_api::account_updateConnectedBot::DELETED_MASK;
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::account_updateConnectedBot(flags, false /*ignored*/, false /*ignored*/, std::move(input_user),
|
||||
BusinessRecipients().get_input_business_recipients(td_)),
|
||||
{{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_updateConnectedBot>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for UpdateConnectedBotQuery: " << to_string(ptr);
|
||||
td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateBusinessLocationQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
DialogLocation location_;
|
||||
|
||||
public:
|
||||
explicit UpdateBusinessLocationQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(DialogLocation &&location) {
|
||||
location_ = std::move(location);
|
||||
int32 flags = 0;
|
||||
if (!location_.empty()) {
|
||||
flags |= telegram_api::account_updateBusinessLocation::GEO_POINT_MASK;
|
||||
}
|
||||
if (!location_.get_address().empty()) {
|
||||
flags |= telegram_api::account_updateBusinessLocation::ADDRESS_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::account_updateBusinessLocation(flags, location_.get_input_geo_point(), location_.get_address()),
|
||||
{{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_updateBusinessLocation>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
td_->contacts_manager_->on_update_user_location(td_->contacts_manager_->get_my_id(), std::move(location_));
|
||||
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateBusinessWorkHoursQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
BusinessWorkHours work_hours_;
|
||||
|
||||
public:
|
||||
explicit UpdateBusinessWorkHoursQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(BusinessWorkHours &&work_hours) {
|
||||
work_hours_ = std::move(work_hours);
|
||||
int32 flags = 0;
|
||||
if (!work_hours_.is_empty()) {
|
||||
flags |= telegram_api::account_updateBusinessWorkHours::BUSINESS_WORK_HOURS_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::account_updateBusinessWorkHours(flags, work_hours_.get_input_business_work_hours()), {{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_updateBusinessWorkHours>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
td_->contacts_manager_->on_update_user_work_hours(td_->contacts_manager_->get_my_id(), std::move(work_hours_));
|
||||
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateBusinessGreetingMessageQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
BusinessGreetingMessage greeting_message_;
|
||||
|
||||
public:
|
||||
explicit UpdateBusinessGreetingMessageQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(BusinessGreetingMessage &&greeting_message) {
|
||||
greeting_message_ = std::move(greeting_message);
|
||||
int32 flags = 0;
|
||||
if (!greeting_message_.is_empty()) {
|
||||
flags |= telegram_api::account_updateBusinessGreetingMessage::MESSAGE_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(telegram_api::account_updateBusinessGreetingMessage(
|
||||
flags, greeting_message_.get_input_business_greeting_message(td_)),
|
||||
{{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_updateBusinessGreetingMessage>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
td_->contacts_manager_->on_update_user_greeting_message(td_->contacts_manager_->get_my_id(),
|
||||
std::move(greeting_message_));
|
||||
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateBusinessAwayMessageQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
BusinessAwayMessage away_message_;
|
||||
|
||||
public:
|
||||
explicit UpdateBusinessAwayMessageQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(BusinessAwayMessage &&away_message) {
|
||||
away_message_ = std::move(away_message);
|
||||
int32 flags = 0;
|
||||
if (!away_message_.is_empty()) {
|
||||
flags |= telegram_api::account_updateBusinessAwayMessage::MESSAGE_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::account_updateBusinessAwayMessage(flags, away_message_.get_input_business_away_message(td_)),
|
||||
{{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_updateBusinessAwayMessage>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
td_->contacts_manager_->on_update_user_away_message(td_->contacts_manager_->get_my_id(), std::move(away_message_));
|
||||
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
BusinessManager::BusinessManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||
}
|
||||
|
||||
void BusinessManager::tear_down() {
|
||||
parent_.reset();
|
||||
}
|
||||
|
||||
void BusinessManager::get_business_connected_bot(Promise<td_api::object_ptr<td_api::businessConnectedBot>> &&promise) {
|
||||
td_->create_handler<GetConnectedBotsQuery>(std::move(promise))->send();
|
||||
}
|
||||
|
||||
void BusinessManager::set_business_connected_bot(td_api::object_ptr<td_api::businessConnectedBot> &&bot,
|
||||
Promise<Unit> &&promise) {
|
||||
if (bot == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Bot must be non-empty"));
|
||||
}
|
||||
BusinessConnectedBot connected_bot(std::move(bot));
|
||||
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(connected_bot.get_user_id()));
|
||||
td_->create_handler<UpdateConnectedBotQuery>(std::move(promise))->send(connected_bot, std::move(input_user));
|
||||
}
|
||||
|
||||
void BusinessManager::delete_business_connected_bot(UserId bot_user_id, Promise<Unit> &&promise) {
|
||||
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(bot_user_id));
|
||||
td_->create_handler<UpdateConnectedBotQuery>(std::move(promise))->send(std::move(input_user));
|
||||
}
|
||||
|
||||
void BusinessManager::set_business_location(DialogLocation &&location, Promise<Unit> &&promise) {
|
||||
td_->create_handler<UpdateBusinessLocationQuery>(std::move(promise))->send(std::move(location));
|
||||
}
|
||||
|
||||
void BusinessManager::set_business_work_hours(BusinessWorkHours &&work_hours, Promise<Unit> &&promise) {
|
||||
td_->create_handler<UpdateBusinessWorkHoursQuery>(std::move(promise))->send(std::move(work_hours));
|
||||
}
|
||||
|
||||
void BusinessManager::set_business_greeting_message(BusinessGreetingMessage &&greeting_message,
|
||||
Promise<Unit> &&promise) {
|
||||
td_->create_handler<UpdateBusinessGreetingMessageQuery>(std::move(promise))->send(std::move(greeting_message));
|
||||
}
|
||||
|
||||
void BusinessManager::set_business_away_message(BusinessAwayMessage &&away_message, Promise<Unit> &&promise) {
|
||||
td_->create_handler<UpdateBusinessAwayMessageQuery>(std::move(promise))->send(std::move(away_message));
|
||||
}
|
||||
|
||||
void BusinessManager::memory_stats(vector<string> &output) {
|
||||
}
|
||||
|
||||
} // namespace td
|
51
td/telegram/BusinessManager.h
Normal file
51
td/telegram/BusinessManager.h
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
||||
//
|
||||
// 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/td_api.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Promise.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class BusinessAwayMessage;
|
||||
class BusinessGreetingMessage;
|
||||
class BusinessWorkHours;
|
||||
class DialogLocation;
|
||||
class Td;
|
||||
|
||||
class BusinessManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
BusinessManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void get_business_connected_bot(Promise<td_api::object_ptr<td_api::businessConnectedBot>> &&promise);
|
||||
|
||||
void set_business_connected_bot(td_api::object_ptr<td_api::businessConnectedBot> &&bot, Promise<Unit> &&promise);
|
||||
|
||||
void delete_business_connected_bot(UserId bot_user_id, Promise<Unit> &&promise);
|
||||
|
||||
void set_business_location(DialogLocation &&location, Promise<Unit> &&promise);
|
||||
|
||||
void set_business_work_hours(BusinessWorkHours &&work_hours, Promise<Unit> &&promise);
|
||||
|
||||
void set_business_greeting_message(BusinessGreetingMessage &&greeting_message, Promise<Unit> &&promise);
|
||||
|
||||
void set_business_away_message(BusinessAwayMessage &&away_message, Promise<Unit> &&promise);
|
||||
|
||||
private:
|
||||
void tear_down() final;
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
};
|
||||
|
||||
} // namespace td
|
104
td/telegram/BusinessRecipients.cpp
Normal file
104
td/telegram/BusinessRecipients.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessRecipients.h"
|
||||
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/DialogManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
BusinessRecipients::BusinessRecipients(telegram_api::object_ptr<telegram_api::businessRecipients> recipients)
|
||||
: user_ids_(UserId::get_user_ids(recipients->users_))
|
||||
, existing_chats_(recipients->existing_chats_)
|
||||
, new_chats_(recipients->new_chats_)
|
||||
, contacts_(recipients->contacts_)
|
||||
, non_contacts_(recipients->non_contacts_)
|
||||
, exclude_selected_(recipients->exclude_selected_) {
|
||||
td::remove_if(user_ids_, [](UserId user_id) { return !user_id.is_valid(); });
|
||||
}
|
||||
|
||||
BusinessRecipients::BusinessRecipients(td_api::object_ptr<td_api::businessRecipients> recipients) {
|
||||
if (recipients == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (auto chat_id : recipients->chat_ids_) {
|
||||
DialogId dialog_id(chat_id);
|
||||
if (dialog_id.get_type() == DialogType::User) {
|
||||
user_ids_.push_back(dialog_id.get_user_id());
|
||||
}
|
||||
}
|
||||
existing_chats_ = recipients->select_existing_chats_;
|
||||
new_chats_ = recipients->select_new_chats_;
|
||||
contacts_ = recipients->select_contacts_;
|
||||
non_contacts_ = recipients->select_non_contacts_;
|
||||
exclude_selected_ = recipients->exclude_selected_;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessRecipients> BusinessRecipients::get_business_recipients_object(Td *td) const {
|
||||
vector<int64> chat_ids;
|
||||
for (auto user_id : user_ids_) {
|
||||
DialogId dialog_id(user_id);
|
||||
td->dialog_manager_->force_create_dialog(dialog_id, "get_business_recipients_object", true);
|
||||
CHECK(td->dialog_manager_->have_dialog_force(dialog_id, "get_business_recipients_object"));
|
||||
chat_ids.push_back(td->dialog_manager_->get_chat_id_object(dialog_id, "businessRecipients"));
|
||||
}
|
||||
return td_api::make_object<td_api::businessRecipients>(std::move(chat_ids), existing_chats_, new_chats_, contacts_,
|
||||
non_contacts_, exclude_selected_);
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputBusinessRecipients> BusinessRecipients::get_input_business_recipients(
|
||||
Td *td) const {
|
||||
int32 flags = 0;
|
||||
if (existing_chats_) {
|
||||
flags |= telegram_api::inputBusinessRecipients::EXISTING_CHATS_MASK;
|
||||
}
|
||||
if (new_chats_) {
|
||||
flags |= telegram_api::inputBusinessRecipients::NEW_CHATS_MASK;
|
||||
}
|
||||
if (contacts_) {
|
||||
flags |= telegram_api::inputBusinessRecipients::CONTACTS_MASK;
|
||||
}
|
||||
if (non_contacts_) {
|
||||
flags |= telegram_api::inputBusinessRecipients::NON_CONTACTS_MASK;
|
||||
}
|
||||
if (exclude_selected_) {
|
||||
flags |= telegram_api::inputBusinessRecipients::EXCLUDE_SELECTED_MASK;
|
||||
}
|
||||
vector<telegram_api::object_ptr<telegram_api::InputUser>> input_users;
|
||||
for (auto user_id : user_ids_) {
|
||||
auto r_input_user = td->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_ok()) {
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
}
|
||||
}
|
||||
if (!input_users.empty()) {
|
||||
flags |= telegram_api::inputBusinessRecipients::USERS_MASK;
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::inputBusinessRecipients>(flags, false /*ignored*/, false /*ignored*/,
|
||||
false /*ignored*/, false /*ignored*/,
|
||||
false /*ignored*/, std::move(input_users));
|
||||
}
|
||||
|
||||
bool operator==(const BusinessRecipients &lhs, const BusinessRecipients &rhs) {
|
||||
return lhs.user_ids_ == rhs.user_ids_ && lhs.existing_chats_ == rhs.existing_chats_ &&
|
||||
lhs.new_chats_ == rhs.new_chats_ && lhs.contacts_ == rhs.contacts_ && lhs.non_contacts_ == rhs.non_contacts_ &&
|
||||
lhs.exclude_selected_ == rhs.exclude_selected_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessRecipients &recipients) {
|
||||
return string_builder << "received by " << (recipients.exclude_selected_ ? "all private chats except " : "")
|
||||
<< recipients.user_ids_ << (recipients.contacts_ ? ", contacts " : "")
|
||||
<< (recipients.non_contacts_ ? ", non-contacts " : "")
|
||||
<< (recipients.existing_chats_ ? ", existing chats " : "")
|
||||
<< (recipients.new_chats_ ? ", new chats " : "");
|
||||
}
|
||||
|
||||
} // namespace td
|
59
td/telegram/BusinessRecipients.h
Normal file
59
td/telegram/BusinessRecipients.h
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class BusinessRecipients {
|
||||
public:
|
||||
BusinessRecipients() = default;
|
||||
|
||||
explicit BusinessRecipients(telegram_api::object_ptr<telegram_api::businessRecipients> recipients);
|
||||
|
||||
explicit BusinessRecipients(td_api::object_ptr<td_api::businessRecipients> recipients);
|
||||
|
||||
td_api::object_ptr<td_api::businessRecipients> get_business_recipients_object(Td *td) const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputBusinessRecipients> get_input_business_recipients(Td *td) const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
vector<UserId> user_ids_;
|
||||
bool existing_chats_ = false;
|
||||
bool new_chats_ = false;
|
||||
bool contacts_ = false;
|
||||
bool non_contacts_ = false;
|
||||
bool exclude_selected_ = false;
|
||||
|
||||
friend bool operator==(const BusinessRecipients &lhs, const BusinessRecipients &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessRecipients &recipients);
|
||||
};
|
||||
|
||||
bool operator==(const BusinessRecipients &lhs, const BusinessRecipients &rhs);
|
||||
|
||||
inline bool operator!=(const BusinessRecipients &lhs, const BusinessRecipients &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessRecipients &recipients);
|
||||
|
||||
} // namespace td
|
48
td/telegram/BusinessRecipients.hpp
Normal file
48
td/telegram/BusinessRecipients.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessRecipients.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessRecipients::store(StorerT &storer) const {
|
||||
bool has_user_ids = !user_ids_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(existing_chats_);
|
||||
STORE_FLAG(new_chats_);
|
||||
STORE_FLAG(contacts_);
|
||||
STORE_FLAG(non_contacts_);
|
||||
STORE_FLAG(exclude_selected_);
|
||||
STORE_FLAG(has_user_ids);
|
||||
END_STORE_FLAGS();
|
||||
if (has_user_ids) {
|
||||
td::store(user_ids_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessRecipients::parse(ParserT &parser) {
|
||||
bool has_user_ids;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(existing_chats_);
|
||||
PARSE_FLAG(new_chats_);
|
||||
PARSE_FLAG(contacts_);
|
||||
PARSE_FLAG(non_contacts_);
|
||||
PARSE_FLAG(exclude_selected_);
|
||||
PARSE_FLAG(has_user_ids);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_user_ids) {
|
||||
td::parse(user_ids_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
179
td/telegram/BusinessWorkHours.cpp
Normal file
179
td/telegram/BusinessWorkHours.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessWorkHours.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace td {
|
||||
|
||||
td_api::object_ptr<td_api::businessOpeningHoursInterval>
|
||||
BusinessWorkHours::WorkHoursInterval::get_business_opening_hours_interval_object() const {
|
||||
return td_api::make_object<td_api::businessOpeningHoursInterval>(start_minute_, end_minute_);
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::businessWeeklyOpen>
|
||||
BusinessWorkHours::WorkHoursInterval::get_input_business_weekly_open() const {
|
||||
return telegram_api::make_object<telegram_api::businessWeeklyOpen>(start_minute_, end_minute_);
|
||||
}
|
||||
|
||||
BusinessWorkHours::BusinessWorkHours(telegram_api::object_ptr<telegram_api::businessWorkHours> &&work_hours) {
|
||||
if (work_hours != nullptr) {
|
||||
work_hours_ = transform(work_hours->weekly_open_,
|
||||
[](const telegram_api::object_ptr<telegram_api::businessWeeklyOpen> &weekly_open) {
|
||||
return WorkHoursInterval(weekly_open->start_minute_, weekly_open->end_minute_);
|
||||
});
|
||||
sanitize_work_hours();
|
||||
time_zone_id_ = std::move(work_hours->timezone_id_);
|
||||
}
|
||||
}
|
||||
|
||||
BusinessWorkHours::BusinessWorkHours(td_api::object_ptr<td_api::businessOpeningHours> &&work_hours) {
|
||||
if (work_hours != nullptr) {
|
||||
work_hours_ = transform(work_hours->opening_hours_,
|
||||
[](const td_api::object_ptr<td_api::businessOpeningHoursInterval> &interval) {
|
||||
return WorkHoursInterval(interval->start_minute_, interval->end_minute_);
|
||||
});
|
||||
sanitize_work_hours();
|
||||
time_zone_id_ = std::move(work_hours->time_zone_id_);
|
||||
}
|
||||
}
|
||||
|
||||
bool BusinessWorkHours::is_empty() const {
|
||||
return work_hours_.empty();
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessOpeningHours> BusinessWorkHours::get_business_opening_hours_object() const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
vector<td_api::object_ptr<td_api::businessOpeningHoursInterval>> intervals;
|
||||
for (const auto &work_hour : work_hours_) {
|
||||
auto interval = work_hour;
|
||||
while (interval.start_minute_ / (24 * 60) + 1 < interval.end_minute_ / (24 * 60)) {
|
||||
auto prefix = interval;
|
||||
prefix.end_minute_ = (interval.start_minute_ / (24 * 60) + 1) * 24 * 60;
|
||||
interval.start_minute_ = prefix.end_minute_;
|
||||
intervals.push_back(prefix.get_business_opening_hours_interval_object());
|
||||
}
|
||||
intervals.push_back(interval.get_business_opening_hours_interval_object());
|
||||
}
|
||||
return td_api::make_object<td_api::businessOpeningHours>(time_zone_id_, std::move(intervals));
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::businessWorkHours> BusinessWorkHours::get_input_business_work_hours() const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::businessWorkHours>(
|
||||
0, false, time_zone_id_, transform(work_hours_, [](const WorkHoursInterval &interval) {
|
||||
return interval.get_input_business_weekly_open();
|
||||
}));
|
||||
}
|
||||
|
||||
void BusinessWorkHours::sanitize_work_hours() {
|
||||
// remove invalid work hour intervals
|
||||
td::remove_if(work_hours_, [](const WorkHoursInterval &interval) {
|
||||
if (interval.start_minute_ >= interval.end_minute_ || interval.start_minute_ < 0 ||
|
||||
interval.end_minute_ > 8 * 24 * 60) {
|
||||
LOG(INFO) << "Ignore interval " << interval;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
combine_work_hour_intervals();
|
||||
}
|
||||
|
||||
void BusinessWorkHours::combine_work_hour_intervals() {
|
||||
if (work_hours_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sort intervals
|
||||
std::sort(work_hours_.begin(), work_hours_.end(), [](const WorkHoursInterval &lhs, const WorkHoursInterval &rhs) {
|
||||
return lhs.start_minute_ < rhs.start_minute_;
|
||||
});
|
||||
|
||||
// combine intersecting intervals
|
||||
size_t j = 0;
|
||||
for (size_t i = 1; i < work_hours_.size(); i++) {
|
||||
CHECK(work_hours_[i].start_minute_ >= work_hours_[j].start_minute_);
|
||||
if (work_hours_[i].start_minute_ <= work_hours_[j].end_minute_) {
|
||||
work_hours_[j].end_minute_ = max(work_hours_[j].end_minute_, work_hours_[i].end_minute_);
|
||||
} else {
|
||||
work_hours_[++j] = work_hours_[i];
|
||||
}
|
||||
}
|
||||
work_hours_.resize(j + 1);
|
||||
|
||||
// there must be no intervals longer than 1 week
|
||||
for (auto &interval : work_hours_) {
|
||||
interval.end_minute_ = min(interval.end_minute_, interval.start_minute_ + 7 * 24 * 60);
|
||||
}
|
||||
|
||||
CHECK(!work_hours_.empty());
|
||||
|
||||
// if the last interval can be exactly merged with the first one, merge them
|
||||
if (work_hours_[0].start_minute_ != 0 &&
|
||||
work_hours_[0].start_minute_ + 7 * 24 * 60 == work_hours_.back().end_minute_) {
|
||||
if (work_hours_.back().start_minute_ >= 7 * 24 * 60) {
|
||||
work_hours_[0].start_minute_ = work_hours_.back().start_minute_ - 7 * 24 * 60;
|
||||
work_hours_.pop_back();
|
||||
CHECK(!work_hours_.empty());
|
||||
} else {
|
||||
work_hours_[0].start_minute_ = 0;
|
||||
work_hours_.back().end_minute_ = 7 * 24 * 60;
|
||||
}
|
||||
}
|
||||
|
||||
// if there are intervals that intersect the first interval or start after the end of the week,
|
||||
// then they must be normalized
|
||||
auto max_minute = work_hours_[0].start_minute_ + 7 * 24 * 60;
|
||||
if (work_hours_.back().end_minute_ > max_minute || work_hours_.back().start_minute_ >= 7 * 24 * 60) {
|
||||
auto size = work_hours_.size();
|
||||
for (size_t i = 1; i < size; i++) {
|
||||
if (work_hours_[i].start_minute_ >= 7 * 24 * 60) {
|
||||
work_hours_[i].start_minute_ -= 7 * 24 * 60;
|
||||
work_hours_[i].end_minute_ -= 7 * 24 * 60;
|
||||
} else if (work_hours_[i].end_minute_ > max_minute) {
|
||||
work_hours_.emplace_back(max_minute - 7 * 24 * 60, work_hours_[i].end_minute_ - 7 * 24 * 60);
|
||||
work_hours_[i].end_minute_ = max_minute;
|
||||
}
|
||||
}
|
||||
combine_work_hour_intervals();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const BusinessWorkHours::WorkHoursInterval &lhs, const BusinessWorkHours::WorkHoursInterval &rhs) {
|
||||
return lhs.start_minute_ == rhs.start_minute_ && lhs.end_minute_ == rhs.end_minute_;
|
||||
}
|
||||
|
||||
bool operator!=(const BusinessWorkHours::WorkHoursInterval &lhs, const BusinessWorkHours::WorkHoursInterval &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessWorkHours::WorkHoursInterval &interval) {
|
||||
return string_builder << '[' << interval.start_minute_ << ',' << interval.end_minute_ << ')';
|
||||
}
|
||||
|
||||
bool operator==(const BusinessWorkHours &lhs, const BusinessWorkHours &rhs) {
|
||||
return lhs.work_hours_ == rhs.work_hours_ && lhs.time_zone_id_ == rhs.time_zone_id_;
|
||||
}
|
||||
|
||||
bool operator!=(const BusinessWorkHours &lhs, const BusinessWorkHours &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessWorkHours &work_hours) {
|
||||
return string_builder << "BusinessWorkHours[" << work_hours.work_hours_ << " in " << work_hours.time_zone_id_ << ']';
|
||||
}
|
||||
|
||||
} // namespace td
|
85
td/telegram/BusinessWorkHours.h
Normal file
85
td/telegram/BusinessWorkHours.h
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class BusinessWorkHours {
|
||||
public:
|
||||
BusinessWorkHours() = default;
|
||||
|
||||
explicit BusinessWorkHours(telegram_api::object_ptr<telegram_api::businessWorkHours> &&work_hours);
|
||||
|
||||
explicit BusinessWorkHours(td_api::object_ptr<td_api::businessOpeningHours> &&work_hours);
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
td_api::object_ptr<td_api::businessOpeningHours> get_business_opening_hours_object() const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::businessWorkHours> get_input_business_work_hours() const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
struct WorkHoursInterval {
|
||||
int32 start_minute_ = 0;
|
||||
int32 end_minute_ = 0;
|
||||
|
||||
WorkHoursInterval() = default;
|
||||
WorkHoursInterval(int32 start_minute, int32 end_minute) : start_minute_(start_minute), end_minute_(end_minute) {
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessOpeningHoursInterval> get_business_opening_hours_interval_object() const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::businessWeeklyOpen> get_input_business_weekly_open() const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
void sanitize_work_hours();
|
||||
|
||||
void combine_work_hour_intervals();
|
||||
|
||||
friend bool operator==(const WorkHoursInterval &lhs, const WorkHoursInterval &rhs);
|
||||
friend bool operator!=(const WorkHoursInterval &lhs, const WorkHoursInterval &rhs);
|
||||
|
||||
friend bool operator==(const BusinessWorkHours &lhs, const BusinessWorkHours &rhs);
|
||||
friend bool operator!=(const BusinessWorkHours &lhs, const BusinessWorkHours &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const WorkHoursInterval &interval);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessWorkHours &work_hours);
|
||||
|
||||
vector<WorkHoursInterval> work_hours_;
|
||||
string time_zone_id_;
|
||||
};
|
||||
|
||||
bool operator==(const BusinessWorkHours::WorkHoursInterval &lhs, const BusinessWorkHours::WorkHoursInterval &rhs);
|
||||
bool operator!=(const BusinessWorkHours::WorkHoursInterval &lhs, const BusinessWorkHours::WorkHoursInterval &rhs);
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessWorkHours::WorkHoursInterval &interval);
|
||||
|
||||
bool operator==(const BusinessWorkHours &lhs, const BusinessWorkHours &rhs);
|
||||
bool operator!=(const BusinessWorkHours &lhs, const BusinessWorkHours &rhs);
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessWorkHours &work_hours);
|
||||
|
||||
} // namespace td
|
43
td/telegram/BusinessWorkHours.hpp
Normal file
43
td/telegram/BusinessWorkHours.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// 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/BusinessWorkHours.h"
|
||||
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessWorkHours::WorkHoursInterval::store(StorerT &storer) const {
|
||||
td::store(start_minute_, storer);
|
||||
td::store(end_minute_, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessWorkHours::WorkHoursInterval::parse(ParserT &parser) {
|
||||
td::parse(start_minute_, parser);
|
||||
td::parse(end_minute_, parser);
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void BusinessWorkHours::store(StorerT &storer) const {
|
||||
BEGIN_STORE_FLAGS();
|
||||
END_STORE_FLAGS();
|
||||
td::store(work_hours_, storer);
|
||||
td::store(time_zone_id_, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void BusinessWorkHours::parse(ParserT &parser) {
|
||||
BEGIN_PARSE_FLAGS();
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(work_hours_, parser);
|
||||
td::parse(time_zone_id_, parser);
|
||||
}
|
||||
|
||||
} // namespace td
|
@ -290,4 +290,7 @@ void CallbackQueriesManager::send_get_callback_answer_query(
|
||||
->send(dialog_id, message_full_id.get_message_id(), payload, std::move(password));
|
||||
}
|
||||
|
||||
void CallbackQueriesManager::memory_stats(vector<string> &output) {
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -23,6 +23,7 @@ class Td;
|
||||
|
||||
class CallbackQueriesManager {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
explicit CallbackQueriesManager(Td *td);
|
||||
|
||||
void answer_callback_query(int64 callback_query_id, const string &text, bool show_alert, const string &url,
|
||||
|
@ -435,8 +435,17 @@ class MultiImplPool {
|
||||
#if TD_OPENBSD
|
||||
max_client_threads = td::min(max_client_threads, 4u);
|
||||
#endif
|
||||
// Start TDLight - increment this to 128, otherwise the memory will not be freed when a session is closed
|
||||
max_client_threads = 128;
|
||||
// End TDLight - increment this to 128, otherwise the memory will not be freed when a session is closed
|
||||
impls_.resize(max_client_threads);
|
||||
// Start TDLight - disable check
|
||||
# if false
|
||||
// End TDLight - disable check
|
||||
CHECK(impls_.size() * (1 + MultiImpl::ADDITIONAL_THREAD_COUNT + 1 /* IOCP */) < 128);
|
||||
// Start TDLight - disable check
|
||||
# endif
|
||||
// End TDLight - disable check
|
||||
|
||||
net_query_stats_ = std::make_shared<NetQueryStats>();
|
||||
}
|
||||
|
@ -221,4 +221,8 @@ void CommonDialogManager::on_get_common_dialogs(UserId user_id, int64 offset_cha
|
||||
common_dialogs.total_count = total_count;
|
||||
}
|
||||
|
||||
void CommonDialogManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"found_common_dialogs_\":"); output.emplace_back(std::to_string(this->found_common_dialogs_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -24,6 +24,7 @@ class Td;
|
||||
|
||||
class CommonDialogManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
CommonDialogManager(Td *td, ActorShared<> parent);
|
||||
CommonDialogManager(const CommonDialogManager &) = delete;
|
||||
CommonDialogManager &operator=(const CommonDialogManager &) = delete;
|
||||
|
@ -1980,6 +1980,16 @@ void ConfigManager::process_app_config(tl_object_ptr<telegram_api::JSONValue> &c
|
||||
G()->set_option_integer(key, get_json_value_int(std::move(key_value->value_), key));
|
||||
continue;
|
||||
}
|
||||
if (key == "quick_replies_limit") {
|
||||
G()->set_option_integer("quick_reply_shortcut_count_max",
|
||||
get_json_value_int(std::move(key_value->value_), key));
|
||||
continue;
|
||||
}
|
||||
if (key == "quick_reply_messages_limit") {
|
||||
G()->set_option_integer("quick_reply_shortcut_message_count_max",
|
||||
get_json_value_int(std::move(key_value->value_), key));
|
||||
continue;
|
||||
}
|
||||
|
||||
new_values.push_back(std::move(key_value));
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class ConfigManager final : public NetQueryCallback {
|
||||
|
||||
private:
|
||||
struct AppConfig {
|
||||
static constexpr int32 CURRENT_VERSION = 30;
|
||||
static constexpr int32 CURRENT_VERSION = 32;
|
||||
int32 version_ = 0;
|
||||
int32 hash_ = 0;
|
||||
telegram_api::object_ptr<telegram_api::JSONValue> config_;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,12 +19,10 @@
|
||||
#include "td/telegram/DialogInviteLink.h"
|
||||
#include "td/telegram/DialogLocation.h"
|
||||
#include "td/telegram/DialogParticipant.h"
|
||||
#include "td/telegram/DialogParticipantFilter.h"
|
||||
#include "td/telegram/EmojiStatus.h"
|
||||
#include "td/telegram/files/FileId.h"
|
||||
#include "td/telegram/files/FileSourceId.h"
|
||||
#include "td/telegram/FolderId.h"
|
||||
#include "td/telegram/Location.h"
|
||||
#include "td/telegram/MessageFullId.h"
|
||||
#include "td/telegram/MessageId.h"
|
||||
#include "td/telegram/MessageTtl.h"
|
||||
@ -67,15 +65,16 @@
|
||||
namespace td {
|
||||
|
||||
struct BinlogEvent;
|
||||
|
||||
class ChannelParticipantFilter;
|
||||
|
||||
class BusinessAwayMessage;
|
||||
class BusinessGreetingMessage;
|
||||
class BusinessInfo;
|
||||
class BusinessWorkHours;
|
||||
struct MinChannel;
|
||||
|
||||
class Td;
|
||||
|
||||
class ContactsManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
ContactsManager(Td *td, ActorShared<> parent);
|
||||
ContactsManager(const ContactsManager &) = delete;
|
||||
ContactsManager &operator=(const ContactsManager &) = delete;
|
||||
@ -113,6 +112,10 @@ class ContactsManager final : public Actor {
|
||||
AccessRights access_rights) const;
|
||||
bool have_input_encrypted_peer(SecretChatId secret_chat_id, AccessRights access_rights) const;
|
||||
|
||||
bool is_user_received_from_server(UserId user_id) const;
|
||||
bool is_chat_received_from_server(ChatId chat_id) const;
|
||||
bool is_channel_received_from_server(ChannelId channel_id) const;
|
||||
|
||||
const DialogPhoto *get_user_dialog_photo(UserId user_id);
|
||||
const DialogPhoto *get_chat_dialog_photo(ChatId chat_id) const;
|
||||
const DialogPhoto *get_channel_dialog_photo(ChannelId channel_id) const;
|
||||
@ -166,13 +169,20 @@ class ContactsManager final : public Actor {
|
||||
bool get_user_stories_hidden(UserId user_id) const;
|
||||
bool get_channel_stories_hidden(ChannelId channel_id) const;
|
||||
|
||||
bool can_poll_user_active_stories(UserId user_id) const;
|
||||
bool can_poll_channel_active_stories(ChannelId channel_id) const;
|
||||
|
||||
bool can_use_premium_custom_emoji_in_channel(ChannelId channel_id) const;
|
||||
|
||||
string get_user_private_forward_name(UserId user_id);
|
||||
|
||||
bool get_user_voice_messages_forbidden(UserId user_id) const;
|
||||
|
||||
bool get_user_read_dates_private(UserId user_id);
|
||||
|
||||
string get_dialog_search_text(DialogId dialog_id) const;
|
||||
string get_user_search_text(UserId user_id) const;
|
||||
|
||||
string get_channel_search_text(ChannelId channel_id) const;
|
||||
|
||||
void for_each_secret_chat_with_user(UserId user_id, const std::function<void(SecretChatId)> &f);
|
||||
|
||||
@ -180,6 +190,8 @@ class ContactsManager final : public Actor {
|
||||
string get_channel_first_username(ChannelId channel_id) const;
|
||||
string get_channel_editable_username(ChannelId channel_id) const;
|
||||
|
||||
bool has_user_fragment_username(UserId user_id) const;
|
||||
|
||||
int32 get_secret_chat_date(SecretChatId secret_chat_id) const;
|
||||
int32 get_secret_chat_ttl(SecretChatId secret_chat_id) const;
|
||||
UserId get_secret_chat_user_id(SecretChatId secret_chat_id) const;
|
||||
@ -244,8 +256,14 @@ class ContactsManager final : public Actor {
|
||||
void on_update_user_is_blocked(UserId user_id, bool is_blocked, bool is_blocked_for_stories);
|
||||
void on_update_user_has_pinned_stories(UserId user_id, bool has_pinned_stories);
|
||||
void on_update_user_common_chat_count(UserId user_id, int32 common_chat_count);
|
||||
void on_update_user_location(UserId user_id, DialogLocation &&location);
|
||||
void on_update_user_work_hours(UserId user_id, BusinessWorkHours &&work_hours);
|
||||
void on_update_user_away_message(UserId user_id, BusinessAwayMessage &&away_message);
|
||||
void on_update_user_greeting_message(UserId user_id, BusinessGreetingMessage &&greeting_message);
|
||||
void on_update_user_need_phone_number_privacy_exception(UserId user_id, bool need_phone_number_privacy_exception);
|
||||
void on_update_user_wallpaper_overridden(UserId user_id, bool wallpaper_overridden);
|
||||
void on_update_user_commands(UserId user_id,
|
||||
vector<telegram_api::object_ptr<telegram_api::botCommand>> &&bot_commands);
|
||||
|
||||
void on_set_profile_photo(UserId user_id, tl_object_ptr<telegram_api::photos_photo> &&photo, bool is_fallback,
|
||||
int64 old_photo_id, Promise<Unit> &&promise);
|
||||
@ -261,6 +279,7 @@ class ContactsManager final : public Actor {
|
||||
void on_update_chat_delete_user(ChatId chat_id, UserId user_id, int32 version);
|
||||
void on_update_chat_default_permissions(ChatId chat_id, RestrictedRights default_permissions, int32 version);
|
||||
void on_update_chat_pinned_message(ChatId chat_id, MessageId pinned_message_id, int32 version);
|
||||
void on_update_chat_bot_commands(ChatId chat_id, BotCommands &&bot_commands);
|
||||
|
||||
void on_update_channel_participant_count(ChannelId channel_id, int32 participant_count);
|
||||
void on_update_channel_editable_username(ChannelId channel_id, string &&username);
|
||||
@ -285,11 +304,7 @@ class ContactsManager final : public Actor {
|
||||
void on_update_channel_has_pinned_stories(ChannelId channel_id, bool has_pinned_stories);
|
||||
void on_update_channel_default_permissions(ChannelId channel_id, RestrictedRights default_permissions);
|
||||
void on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count);
|
||||
|
||||
int32 on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> &&peers, bool from_update);
|
||||
|
||||
void on_update_bot_commands(DialogId dialog_id, UserId bot_user_id,
|
||||
vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands);
|
||||
void on_update_channel_bot_commands(ChannelId channel_id, BotCommands &&bot_commands);
|
||||
|
||||
void on_update_bot_menu_button(UserId bot_user_id, tl_object_ptr<telegram_api::BotMenuButton> &&bot_menu_button);
|
||||
|
||||
@ -320,8 +335,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void unregister_message_channels(MessageFullId message_full_id, vector<ChannelId> channel_ids);
|
||||
|
||||
bool can_use_premium_custom_emoji(DialogId dialog_id) const;
|
||||
|
||||
UserId get_my_id() const;
|
||||
|
||||
void set_my_online_status(bool is_online, bool send_update, bool is_local);
|
||||
@ -355,9 +368,7 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void update_chat_online_member_count(ChatId chat_id, bool is_from_server);
|
||||
|
||||
void update_channel_online_member_count(ChannelId channel_id, bool is_from_server);
|
||||
|
||||
void drop_cached_channel_participants(ChannelId channel_id);
|
||||
void on_update_channel_bot_user_ids(ChannelId channel_id, vector<UserId> &&bot_user_ids);
|
||||
|
||||
void on_update_username_is_active(UserId user_id, string &&username, bool is_active, Promise<Unit> &&promise);
|
||||
|
||||
@ -410,14 +421,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void share_phone_number(UserId user_id, Promise<Unit> &&promise);
|
||||
|
||||
void search_dialogs_nearby(const Location &location, Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
|
||||
|
||||
void set_location(const Location &location, Promise<Unit> &&promise);
|
||||
|
||||
static void set_location_visibility(Td *td);
|
||||
|
||||
void get_is_location_visible(Promise<Unit> &&promise);
|
||||
|
||||
void register_suggested_profile_photo(const Photo &photo);
|
||||
|
||||
FileId get_profile_photo_file_id(int64 photo_id) const;
|
||||
@ -506,7 +509,7 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void set_channel_discussion_group(DialogId dialog_id, DialogId discussion_dialog_id, Promise<Unit> &&promise);
|
||||
|
||||
void set_channel_location(DialogId dialog_id, const DialogLocation &location, Promise<Unit> &&promise);
|
||||
void set_channel_location(ChannelId dialog_id, const DialogLocation &location, Promise<Unit> &&promise);
|
||||
|
||||
void set_channel_slow_mode_delay(DialogId dialog_id, int32 slow_mode_delay, Promise<Unit> &&promise);
|
||||
|
||||
@ -524,18 +527,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
bool can_get_channel_story_statistics(DialogId dialog_id) const;
|
||||
|
||||
struct CanTransferOwnershipResult {
|
||||
enum class Type : uint8 { Ok, PasswordNeeded, PasswordTooFresh, SessionTooFresh };
|
||||
Type type = Type::Ok;
|
||||
int32 retry_after = 0;
|
||||
};
|
||||
void can_transfer_ownership(Promise<CanTransferOwnershipResult> &&promise);
|
||||
|
||||
static td_api::object_ptr<td_api::CanTransferOwnershipResult> get_can_transfer_ownership_result_object(
|
||||
CanTransferOwnershipResult result);
|
||||
|
||||
void transfer_dialog_ownership(DialogId dialog_id, UserId user_id, const string &password, Promise<Unit> &&promise);
|
||||
|
||||
void migrate_dialog_to_megagroup(DialogId dialog_id, Promise<td_api::object_ptr<td_api::chat>> &&promise);
|
||||
|
||||
void get_channel_recommendations(DialogId dialog_id, bool return_local,
|
||||
@ -578,7 +569,9 @@ class ContactsManager final : public Actor {
|
||||
};
|
||||
Result<BotData> get_bot_data(UserId user_id) const TD_WARN_UNUSED_RESULT;
|
||||
|
||||
bool is_user_online(UserId user_id, int32 tolerance = 0, int32 unix_time = 07) const;
|
||||
bool is_user_online(UserId user_id, int32 tolerance = 0, int32 unix_time = 0) const;
|
||||
|
||||
int32 get_user_was_online(UserId user_id, int32 unix_time = 0) const;
|
||||
|
||||
bool is_user_status_exact(UserId user_id) const;
|
||||
|
||||
@ -588,8 +581,6 @@ class ContactsManager final : public Actor {
|
||||
bool have_min_user(UserId user_id) const;
|
||||
bool have_user_force(UserId user_id, const char *source);
|
||||
|
||||
bool is_dialog_info_received_from_server(DialogId dialog_id) const;
|
||||
|
||||
static void send_get_me_query(Td *td, Promise<Unit> &&promise);
|
||||
UserId get_me(Promise<Unit> &&promise);
|
||||
bool get_user(UserId user_id, int left_tries, Promise<Unit> &&promise);
|
||||
@ -621,6 +612,8 @@ class ContactsManager final : public Actor {
|
||||
DialogParticipantStatus get_chat_status(ChatId chat_id) const;
|
||||
DialogParticipantStatus get_chat_permissions(ChatId chat_id) const;
|
||||
bool is_appointed_chat_administrator(ChatId chat_id) const;
|
||||
const DialogParticipant *get_chat_participant(ChatId chat_id, UserId user_id) const;
|
||||
const vector<DialogParticipant> *get_chat_participants(ChatId chat_id) const;
|
||||
|
||||
void create_new_channel(const string &title, bool is_forum, bool is_megagroup, const string &description,
|
||||
const DialogLocation &location, bool for_import, MessageTtl message_ttl,
|
||||
@ -667,25 +660,11 @@ class ContactsManager final : public Actor {
|
||||
bool get_channel_effective_has_hidden_participants(ChannelId channel_id, const char *source);
|
||||
int32 get_channel_my_boost_count(ChannelId channel_id);
|
||||
|
||||
void add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
||||
|
||||
void set_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise<Unit> &&promise);
|
||||
|
||||
void get_chat_participant(ChatId chat_id, UserId user_id, Promise<DialogParticipant> &&promise);
|
||||
|
||||
void speculative_add_channel_user(ChannelId channel_id, UserId user_id, const DialogParticipantStatus &new_status,
|
||||
const DialogParticipantStatus &old_status);
|
||||
|
||||
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void get_channel_participants(ChannelId channel_id, tl_object_ptr<td_api::SupergroupMembersFilter> &&filter,
|
||||
string additional_query, int32 offset, int32 limit, int32 additional_limit,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
int64 get_user_id_object(UserId user_id, const char *source) const;
|
||||
|
||||
tl_object_ptr<td_api::user> get_user_object(UserId user_id) const;
|
||||
@ -721,10 +700,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void get_support_user(Promise<td_api::object_ptr<td_api::user>> &&promise);
|
||||
|
||||
void on_view_dialog_active_stories(vector<DialogId> dialog_ids);
|
||||
|
||||
void on_get_dialog_max_active_story_ids(const vector<DialogId> &dialog_ids, const vector<int32> &max_story_ids);
|
||||
|
||||
void repair_chat_participants(ChatId chat_id);
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
@ -791,8 +766,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
bool is_repaired = false; // whether cached value is rechecked
|
||||
|
||||
bool is_max_active_story_id_being_reloaded = false;
|
||||
|
||||
bool is_name_changed = true;
|
||||
bool is_username_changed = true;
|
||||
bool is_photo_changed = true;
|
||||
@ -850,6 +823,8 @@ class ContactsManager final : public Actor {
|
||||
|
||||
int32 common_chat_count = 0;
|
||||
|
||||
unique_ptr<BusinessInfo> business_info;
|
||||
|
||||
bool is_blocked = false;
|
||||
bool is_blocked_for_stories = false;
|
||||
bool can_be_called = false;
|
||||
@ -1004,8 +979,6 @@ class ContactsManager final : public Actor {
|
||||
bool is_scam = false;
|
||||
bool is_fake = false;
|
||||
|
||||
bool is_max_active_story_id_being_reloaded = false;
|
||||
|
||||
bool is_title_changed = true;
|
||||
bool is_username_changed = true;
|
||||
bool is_photo_changed = true;
|
||||
@ -1155,26 +1128,6 @@ class ContactsManager final : public Actor {
|
||||
vector<PendingGetPhotoRequest> pending_requests;
|
||||
};
|
||||
|
||||
struct DialogNearby {
|
||||
DialogId dialog_id;
|
||||
int32 distance;
|
||||
|
||||
DialogNearby(DialogId dialog_id, int32 distance) : dialog_id(dialog_id), distance(distance) {
|
||||
}
|
||||
|
||||
bool operator<(const DialogNearby &other) const {
|
||||
return distance < other.distance || (distance == other.distance && dialog_id.get() < other.dialog_id.get());
|
||||
}
|
||||
|
||||
bool operator==(const DialogNearby &other) const {
|
||||
return distance == other.distance && dialog_id == other.dialog_id;
|
||||
}
|
||||
|
||||
bool operator!=(const DialogNearby &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct RecommendedDialogs {
|
||||
int32 total_count_ = 0;
|
||||
vector<DialogId> dialog_ids_;
|
||||
@ -1192,11 +1145,10 @@ class ContactsManager final : public Actor {
|
||||
class ChannelLogEvent;
|
||||
class SecretChatLogEvent;
|
||||
|
||||
static constexpr int32 MAX_GET_PROFILE_PHOTOS = 100; // server side limit
|
||||
static constexpr size_t MAX_NAME_LENGTH = 64; // server side limit for first/last name
|
||||
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
||||
static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for chat/channel description
|
||||
static constexpr int32 MAX_GET_CHANNEL_PARTICIPANTS = 200; // server side limit
|
||||
static constexpr int32 MAX_GET_PROFILE_PHOTOS = 100; // server side limit
|
||||
static constexpr size_t MAX_NAME_LENGTH = 64; // server side limit for first/last name
|
||||
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
||||
static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for chat/channel description
|
||||
|
||||
static constexpr int32 MAX_ACTIVE_STORY_ID_RELOAD_TIME = 3600; // some reasonable limit
|
||||
static constexpr int32 CHANNEL_RECOMMENDATIONS_CACHE_TIME = 86400; // some reasonable limit
|
||||
@ -1400,7 +1352,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
SecretChat *add_secret_chat(SecretChatId secret_chat_id);
|
||||
|
||||
string get_user_search_text(UserId user_id) const;
|
||||
static string get_user_search_text(const User *u);
|
||||
|
||||
static DialogParticipantStatus get_chat_status(const Chat *c);
|
||||
@ -1415,9 +1366,6 @@ class ContactsManager final : public Actor {
|
||||
static bool get_channel_join_to_send(const Channel *c);
|
||||
static bool get_channel_join_request(const Channel *c);
|
||||
|
||||
string get_channel_search_text(ChannelId channel_id) const;
|
||||
static string get_channel_search_text(const Channel *c);
|
||||
|
||||
void set_my_id(UserId my_id);
|
||||
|
||||
void on_set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise);
|
||||
@ -1462,6 +1410,11 @@ class ContactsManager final : public Actor {
|
||||
static void on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked,
|
||||
bool is_blocked_for_stories);
|
||||
static void on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id, int32 common_chat_count);
|
||||
static void on_update_user_full_location(UserFull *user_full, UserId user_id, DialogLocation &&location);
|
||||
static void on_update_user_full_work_hours(UserFull *user_full, UserId user_id, BusinessWorkHours &&work_hours);
|
||||
void on_update_user_full_away_message(UserFull *user_full, UserId user_id, BusinessAwayMessage &&away_message) const;
|
||||
void on_update_user_full_greeting_message(UserFull *user_full, UserId user_id,
|
||||
BusinessGreetingMessage &&greeting_message) const;
|
||||
static void on_update_user_full_commands(UserFull *user_full, UserId user_id,
|
||||
vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands);
|
||||
static void on_update_user_full_menu_button(UserFull *user_full, UserId user_id,
|
||||
@ -1522,8 +1475,6 @@ class ContactsManager final : public Actor {
|
||||
StoryId max_read_story_id);
|
||||
void on_update_channel_max_read_story_id(Channel *c, ChannelId channel_id, StoryId max_read_story_id);
|
||||
|
||||
void on_update_channel_bot_user_ids(ChannelId channel_id, vector<UserId> &&bot_user_ids);
|
||||
|
||||
void on_update_channel_full_photo(ChannelFull *channel_full, ChannelId channel_id, Photo photo);
|
||||
void on_update_channel_full_invite_link(ChannelFull *channel_full,
|
||||
tl_object_ptr<telegram_api::ExportedChatInvite> &&invite_link);
|
||||
@ -1673,24 +1624,6 @@ class ContactsManager final : public Actor {
|
||||
void on_clear_imported_contacts(vector<Contact> &&contacts, vector<size_t> contacts_unique_id,
|
||||
std::pair<vector<size_t>, vector<Contact>> &&to_add, Promise<Unit> &&promise);
|
||||
|
||||
vector<td_api::object_ptr<td_api::chatNearby>> get_chats_nearby_object(
|
||||
const vector<DialogNearby> &dialogs_nearby) const;
|
||||
|
||||
void send_update_users_nearby() const;
|
||||
|
||||
void on_get_dialogs_nearby(Result<tl_object_ptr<telegram_api::Updates>> result,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
|
||||
|
||||
void try_send_set_location_visibility_query();
|
||||
|
||||
void on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code);
|
||||
|
||||
void set_location_visibility_expire_date(int32 expire_date);
|
||||
|
||||
void on_get_is_location_visible(Result<tl_object_ptr<telegram_api::Updates>> &&result, Promise<Unit> &&promise);
|
||||
|
||||
void update_is_location_visible();
|
||||
|
||||
bool is_suitable_recommended_channel(DialogId dialog_id) const;
|
||||
|
||||
bool is_suitable_recommended_channel(ChannelId channel_id) const;
|
||||
@ -1735,16 +1668,8 @@ class ContactsManager final : public Actor {
|
||||
vector<BotCommands> get_bot_commands(vector<tl_object_ptr<telegram_api::botInfo>> &&bot_infos,
|
||||
const vector<DialogParticipant> *participants);
|
||||
|
||||
const DialogParticipant *get_chat_participant(ChatId chat_id, UserId user_id) const;
|
||||
|
||||
static const DialogParticipant *get_chat_full_participant(const ChatFull *chat_full, DialogId dialog_id);
|
||||
|
||||
std::pair<int32, vector<DialogId>> search_among_dialogs(const vector<DialogId> &dialog_ids, const string &query,
|
||||
int32 limit) const;
|
||||
|
||||
DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query,
|
||||
int32 limit, DialogParticipantFilter filter) const;
|
||||
|
||||
void finish_get_chat_participant(ChatId chat_id, UserId user_id, Promise<DialogParticipant> &&promise);
|
||||
|
||||
void remove_dialog_suggested_action(SuggestedAction action);
|
||||
@ -1763,6 +1688,10 @@ class ContactsManager final : public Actor {
|
||||
|
||||
tl_object_ptr<td_api::user> get_user_object(UserId user_id, const User *u) const;
|
||||
|
||||
tl_object_ptr<td_api::accessHash> get_user_access_hash_object(UserId user_id, const User *u) const;
|
||||
|
||||
tl_object_ptr<td_api::accessHash> get_channel_access_hash_object(ChannelId channel_id, const Channel *c) const;
|
||||
|
||||
tl_object_ptr<td_api::userFullInfo> get_user_full_info_object(UserId user_id, const UserFull *user_full) const;
|
||||
|
||||
td_api::object_ptr<td_api::updateBasicGroup> get_update_basic_group_object(ChatId chat_id, const Chat *c);
|
||||
@ -1817,23 +1746,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void update_dialogs_for_discussion(DialogId dialog_id, bool is_suitable);
|
||||
|
||||
void send_edit_chat_admin_query(ChatId chat_id, UserId user_id, bool is_administrator, Promise<Unit> &&promise);
|
||||
|
||||
void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void do_search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void on_get_channel_participants(ChannelId channel_id, ChannelParticipantFilter &&filter, int32 offset, int32 limit,
|
||||
string additional_query, int32 additional_limit,
|
||||
tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void transfer_channel_ownership(ChannelId channel_id, UserId user_id,
|
||||
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void get_channel_statistics_dc_id_impl(ChannelId channel_id, bool for_full_statistics, Promise<DcId> &&promise);
|
||||
|
||||
void on_get_support_user(UserId user_id, Promise<td_api::object_ptr<td_api::user>> &&promise);
|
||||
@ -1846,8 +1758,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
|
||||
|
||||
static void on_user_nearby_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
|
||||
|
||||
static void on_slow_mode_delay_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
|
||||
|
||||
void on_user_online_timeout(UserId user_id);
|
||||
@ -1858,12 +1768,8 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void on_channel_unban_timeout(ChannelId channel_id);
|
||||
|
||||
void on_user_nearby_timeout(UserId user_id);
|
||||
|
||||
void on_slow_mode_delay_timeout(ChannelId channel_id);
|
||||
|
||||
void start_up() final;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
Td *td_;
|
||||
@ -1981,8 +1887,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
FlatHashMap<int64, std::pair<vector<UserId>, vector<int32>>> imported_contacts_;
|
||||
|
||||
FlatHashMap<ChannelId, vector<DialogParticipant>, ChannelIdHash> cached_channel_participants_;
|
||||
|
||||
FlatHashMap<string, UserId> resolved_phone_numbers_;
|
||||
|
||||
FlatHashMap<UserId, FlatHashSet<MessageFullId, MessageFullIdHash>, UserIdHash> user_messages_;
|
||||
@ -2005,15 +1909,6 @@ class ContactsManager final : public Actor {
|
||||
bool are_imported_contacts_changing_ = false;
|
||||
bool need_clear_imported_contacts_ = false;
|
||||
|
||||
vector<DialogNearby> users_nearby_;
|
||||
vector<DialogNearby> channels_nearby_;
|
||||
FlatHashSet<UserId, UserIdHash> all_users_nearby_;
|
||||
|
||||
int32 location_visibility_expire_date_ = 0;
|
||||
int32 pending_location_visibility_expire_date_ = -1;
|
||||
bool is_set_location_visibility_request_sent_ = false;
|
||||
Location last_user_location_;
|
||||
|
||||
FlatHashMap<UserId, bool, UserIdHash> user_full_contact_require_premium_;
|
||||
|
||||
WaitFreeHashMap<ChannelId, ChannelId, ChannelIdHash> linked_channel_ids_;
|
||||
@ -2032,7 +1927,6 @@ class ContactsManager final : public Actor {
|
||||
MultiTimeout user_emoji_status_timeout_{"UserEmojiStatusTimeout"};
|
||||
MultiTimeout channel_emoji_status_timeout_{"ChannelEmojiStatusTimeout"};
|
||||
MultiTimeout channel_unban_timeout_{"ChannelUnbanTimeout"};
|
||||
MultiTimeout user_nearby_timeout_{"UserNearbyTimeout"};
|
||||
MultiTimeout slow_mode_delay_timeout_{"SlowModeDelayTimeout"};
|
||||
};
|
||||
|
||||
|
@ -610,4 +610,8 @@ FlatHashMap<string, unique_ptr<CountryInfoManager::CountryList>> CountryInfoMana
|
||||
string CountryInfoManager::fragment_prefixes_str_;
|
||||
vector<string> CountryInfoManager::fragment_prefixes_;
|
||||
|
||||
void CountryInfoManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"pending_load_country_queries_\":"); output.emplace_back(std::to_string(this->pending_load_country_queries_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -25,6 +25,7 @@ class Td;
|
||||
|
||||
class CountryInfoManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
CountryInfoManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void get_countries(Promise<td_api::object_ptr<td_api::countries>> &&promise);
|
||||
|
@ -401,4 +401,10 @@ void DialogActionManager::clear_active_dialog_actions(DialogId dialog_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void DialogActionManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"active_dialog_actions_\":"); output.emplace_back(std::to_string(this->active_dialog_actions_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"set_typing_query_\":"); output.emplace_back(std::to_string(this->set_typing_query_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -25,6 +25,7 @@ class Td;
|
||||
|
||||
class DialogActionManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
DialogActionManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void on_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||
|
@ -48,6 +48,7 @@ unique_ptr<DialogFilter> DialogFilter::get_dialog_filter(
|
||||
dialog_filter->dialog_filter_id_ = dialog_filter_id;
|
||||
dialog_filter->title_ = std::move(filter->title_);
|
||||
dialog_filter->emoji_ = std::move(filter->emoticon_);
|
||||
dialog_filter->color_id_ = (filter->flags_ & telegram_api::dialogFilter::COLOR_MASK) != 0 ? filter->color_ : -1;
|
||||
dialog_filter->pinned_dialog_ids_ = InputDialogId::get_input_dialog_ids(filter->pinned_peers_, &added_dialog_ids);
|
||||
dialog_filter->included_dialog_ids_ =
|
||||
InputDialogId::get_input_dialog_ids(filter->include_peers_, &added_dialog_ids);
|
||||
@ -62,6 +63,10 @@ unique_ptr<DialogFilter> DialogFilter::get_dialog_filter(
|
||||
dialog_filter->include_bots_ = (flags & telegram_api::dialogFilter::BOTS_MASK) != 0;
|
||||
dialog_filter->include_groups_ = (flags & telegram_api::dialogFilter::GROUPS_MASK) != 0;
|
||||
dialog_filter->include_channels_ = (flags & telegram_api::dialogFilter::BROADCASTS_MASK) != 0;
|
||||
if (!is_valid_color_id(dialog_filter->color_id_)) {
|
||||
LOG(ERROR) << "Receive color " << dialog_filter->color_id_;
|
||||
dialog_filter->color_id_ = -1;
|
||||
}
|
||||
return dialog_filter;
|
||||
}
|
||||
case telegram_api::dialogFilterChatlist::ID: {
|
||||
@ -79,11 +84,17 @@ unique_ptr<DialogFilter> DialogFilter::get_dialog_filter(
|
||||
dialog_filter->dialog_filter_id_ = dialog_filter_id;
|
||||
dialog_filter->title_ = std::move(filter->title_);
|
||||
dialog_filter->emoji_ = std::move(filter->emoticon_);
|
||||
dialog_filter->color_id_ =
|
||||
(filter->flags_ & telegram_api::dialogFilterChatlist::COLOR_MASK) != 0 ? filter->color_ : -1;
|
||||
dialog_filter->pinned_dialog_ids_ = InputDialogId::get_input_dialog_ids(filter->pinned_peers_, &added_dialog_ids);
|
||||
dialog_filter->included_dialog_ids_ =
|
||||
InputDialogId::get_input_dialog_ids(filter->include_peers_, &added_dialog_ids);
|
||||
dialog_filter->is_shareable_ = true;
|
||||
dialog_filter->has_my_invites_ = filter->has_my_invites_;
|
||||
if (!is_valid_color_id(dialog_filter->color_id_)) {
|
||||
LOG(ERROR) << "Receive color " << dialog_filter->color_id_;
|
||||
dialog_filter->color_id_ = -1;
|
||||
}
|
||||
return dialog_filter;
|
||||
}
|
||||
default:
|
||||
@ -132,6 +143,10 @@ Result<unique_ptr<DialogFilter>> DialogFilter::create_dialog_filter(Td *td, Dial
|
||||
if (dialog_filter->emoji_.empty() && !icon_name.empty()) {
|
||||
return Status::Error(400, "Invalid icon name specified");
|
||||
}
|
||||
dialog_filter->color_id_ = filter->color_id_;
|
||||
if (!is_valid_color_id(dialog_filter->color_id_)) {
|
||||
return Status::Error(400, "Invalid color identifier specified");
|
||||
}
|
||||
dialog_filter->exclude_muted_ = filter->exclude_muted_;
|
||||
dialog_filter->exclude_read_ = filter->exclude_read_;
|
||||
dialog_filter->exclude_archived_ = filter->exclude_archived_;
|
||||
@ -414,17 +429,23 @@ telegram_api::object_ptr<telegram_api::DialogFilter> DialogFilter::get_input_dia
|
||||
if (!emoji_.empty()) {
|
||||
flags |= telegram_api::dialogFilterChatlist::EMOTICON_MASK;
|
||||
}
|
||||
if (color_id_ != -1) {
|
||||
flags |= telegram_api::dialogFilterChatlist::COLOR_MASK;
|
||||
}
|
||||
if (has_my_invites_) {
|
||||
flags |= telegram_api::dialogFilterChatlist::HAS_MY_INVITES_MASK;
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::dialogFilterChatlist>(
|
||||
flags, false /*ignored*/, dialog_filter_id_.get(), title_, emoji_,
|
||||
flags, false /*ignored*/, dialog_filter_id_.get(), title_, emoji_, color_id_,
|
||||
InputDialogId::get_input_peers(pinned_dialog_ids_), InputDialogId::get_input_peers(included_dialog_ids_));
|
||||
}
|
||||
int32 flags = 0;
|
||||
if (!emoji_.empty()) {
|
||||
flags |= telegram_api::dialogFilter::EMOTICON_MASK;
|
||||
}
|
||||
if (color_id_ != -1) {
|
||||
flags |= telegram_api::dialogFilter::COLOR_MASK;
|
||||
}
|
||||
if (exclude_muted_) {
|
||||
flags |= telegram_api::dialogFilter::EXCLUDE_MUTED_MASK;
|
||||
}
|
||||
@ -452,7 +473,7 @@ telegram_api::object_ptr<telegram_api::DialogFilter> DialogFilter::get_input_dia
|
||||
|
||||
return telegram_api::make_object<telegram_api::dialogFilter>(
|
||||
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
||||
false /*ignored*/, false /*ignored*/, false /*ignored*/, dialog_filter_id_.get(), title_, emoji_,
|
||||
false /*ignored*/, false /*ignored*/, false /*ignored*/, dialog_filter_id_.get(), title_, emoji_, color_id_,
|
||||
InputDialogId::get_input_peers(pinned_dialog_ids_), InputDialogId::get_input_peers(included_dialog_ids_),
|
||||
InputDialogId::get_input_peers(excluded_dialog_ids_));
|
||||
}
|
||||
@ -477,15 +498,15 @@ td_api::object_ptr<td_api::chatFolder> DialogFilter::get_chat_folder_object(
|
||||
icon = td_api::make_object<td_api::chatFolderIcon>(icon_name);
|
||||
}
|
||||
return td_api::make_object<td_api::chatFolder>(
|
||||
title_, std::move(icon), is_shareable_, get_chat_ids(pinned_dialog_ids_), get_chat_ids(included_dialog_ids_),
|
||||
get_chat_ids(excluded_dialog_ids_), exclude_muted_, exclude_read_, exclude_archived_, include_contacts_,
|
||||
include_non_contacts_, include_bots_, include_groups_, include_channels_);
|
||||
title_, std::move(icon), color_id_, is_shareable_, get_chat_ids(pinned_dialog_ids_),
|
||||
get_chat_ids(included_dialog_ids_), get_chat_ids(excluded_dialog_ids_), exclude_muted_, exclude_read_,
|
||||
exclude_archived_, include_contacts_, include_non_contacts_, include_bots_, include_groups_, include_channels_);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::chatFolderInfo> DialogFilter::get_chat_folder_info_object() const {
|
||||
return td_api::make_object<td_api::chatFolderInfo>(
|
||||
dialog_filter_id_.get(), title_, td_api::make_object<td_api::chatFolderIcon>(get_chosen_or_default_icon_name()),
|
||||
is_shareable_, has_my_invites_);
|
||||
color_id_, is_shareable_, has_my_invites_);
|
||||
}
|
||||
|
||||
void DialogFilter::for_each_dialog(std::function<void(const InputDialogId &)> callback) const {
|
||||
@ -656,6 +677,7 @@ unique_ptr<DialogFilter> DialogFilter::merge_dialog_filter_changes(const DialogF
|
||||
|
||||
update_value(new_filter->title_, old_server_filter->title_, new_server_filter->title_);
|
||||
update_value(new_filter->emoji_, old_server_filter->emoji_, new_server_filter->emoji_);
|
||||
update_value(new_filter->color_id_, old_server_filter->color_id_, new_server_filter->color_id_);
|
||||
|
||||
LOG(INFO) << "Old local filter: " << *old_filter;
|
||||
LOG(INFO) << "Old server filter: " << *old_server_filter;
|
||||
@ -873,8 +895,8 @@ bool DialogFilter::are_similar(const DialogFilter &lhs, const DialogFilter &rhs)
|
||||
}
|
||||
|
||||
bool DialogFilter::are_equivalent(const DialogFilter &lhs, const DialogFilter &rhs) {
|
||||
return lhs.title_ == rhs.title_ && lhs.emoji_ == rhs.emoji_ && lhs.is_shareable_ == rhs.is_shareable_ &&
|
||||
lhs.has_my_invites_ == rhs.has_my_invites_ &&
|
||||
return lhs.title_ == rhs.title_ && lhs.emoji_ == rhs.emoji_ && lhs.color_id_ == rhs.color_id_ &&
|
||||
lhs.is_shareable_ == rhs.is_shareable_ && lhs.has_my_invites_ == rhs.has_my_invites_ &&
|
||||
InputDialogId::are_equivalent(lhs.pinned_dialog_ids_, rhs.pinned_dialog_ids_) &&
|
||||
InputDialogId::are_equivalent(lhs.included_dialog_ids_, rhs.included_dialog_ids_) &&
|
||||
InputDialogId::are_equivalent(lhs.excluded_dialog_ids_, rhs.excluded_dialog_ids_) && are_flags_equal(lhs, rhs);
|
||||
@ -918,6 +940,10 @@ void DialogFilter::init_icon_names() {
|
||||
CHECK(is_inited);
|
||||
}
|
||||
|
||||
bool DialogFilter::is_valid_color_id(int32 color_id) {
|
||||
return -1 <= color_id && color_id <= 6;
|
||||
}
|
||||
|
||||
bool DialogFilter::are_flags_equal(const DialogFilter &lhs, const DialogFilter &rhs) {
|
||||
return lhs.exclude_muted_ == rhs.exclude_muted_ && lhs.exclude_read_ == rhs.exclude_read_ &&
|
||||
lhs.exclude_archived_ == rhs.exclude_archived_ && lhs.include_contacts_ == rhs.include_contacts_ &&
|
||||
|
@ -125,6 +125,7 @@ class DialogFilter {
|
||||
vector<InputDialogId> pinned_dialog_ids_;
|
||||
vector<InputDialogId> included_dialog_ids_;
|
||||
vector<InputDialogId> excluded_dialog_ids_;
|
||||
int32 color_id_ = -1;
|
||||
bool exclude_muted_ = false;
|
||||
bool exclude_read_ = false;
|
||||
bool exclude_archived_ = false;
|
||||
@ -139,6 +140,8 @@ class DialogFilter {
|
||||
static FlatHashMap<string, string> emoji_to_icon_name_;
|
||||
static FlatHashMap<string, string> icon_name_to_emoji_;
|
||||
|
||||
static bool is_valid_color_id(int32 color_id);
|
||||
|
||||
static bool are_flags_equal(const DialogFilter &lhs, const DialogFilter &rhs);
|
||||
|
||||
static void init_icon_names();
|
||||
@ -152,9 +155,10 @@ class DialogFilter {
|
||||
|
||||
inline bool operator==(const DialogFilter &lhs, const DialogFilter &rhs) {
|
||||
return lhs.dialog_filter_id_ == rhs.dialog_filter_id_ && lhs.title_ == rhs.title_ && lhs.emoji_ == rhs.emoji_ &&
|
||||
lhs.is_shareable_ == rhs.is_shareable_ && lhs.has_my_invites_ == rhs.has_my_invites_ &&
|
||||
lhs.pinned_dialog_ids_ == rhs.pinned_dialog_ids_ && lhs.included_dialog_ids_ == rhs.included_dialog_ids_ &&
|
||||
lhs.excluded_dialog_ids_ == rhs.excluded_dialog_ids_ && DialogFilter::are_flags_equal(lhs, rhs);
|
||||
lhs.color_id_ == rhs.color_id_ && lhs.is_shareable_ == rhs.is_shareable_ &&
|
||||
lhs.has_my_invites_ == rhs.has_my_invites_ && lhs.pinned_dialog_ids_ == rhs.pinned_dialog_ids_ &&
|
||||
lhs.included_dialog_ids_ == rhs.included_dialog_ids_ && lhs.excluded_dialog_ids_ == rhs.excluded_dialog_ids_ &&
|
||||
DialogFilter::are_flags_equal(lhs, rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const DialogFilter &lhs, const DialogFilter &rhs) {
|
||||
|
@ -19,6 +19,7 @@ void DialogFilter::store(StorerT &storer) const {
|
||||
bool has_pinned_dialog_ids = !pinned_dialog_ids_.empty();
|
||||
bool has_included_dialog_ids = !included_dialog_ids_.empty();
|
||||
bool has_excluded_dialog_ids = !excluded_dialog_ids_.empty();
|
||||
bool has_color_id = color_id_ != -1;
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(exclude_muted_);
|
||||
STORE_FLAG(exclude_read_);
|
||||
@ -33,8 +34,8 @@ void DialogFilter::store(StorerT &storer) const {
|
||||
STORE_FLAG(has_excluded_dialog_ids);
|
||||
STORE_FLAG(is_shareable_);
|
||||
STORE_FLAG(has_my_invites_);
|
||||
STORE_FLAG(has_color_id);
|
||||
END_STORE_FLAGS();
|
||||
|
||||
store(dialog_filter_id_, storer);
|
||||
store(title_, storer);
|
||||
store(emoji_, storer);
|
||||
@ -47,6 +48,9 @@ void DialogFilter::store(StorerT &storer) const {
|
||||
if (has_excluded_dialog_ids) {
|
||||
store(excluded_dialog_ids_, storer);
|
||||
}
|
||||
if (has_color_id) {
|
||||
store(color_id_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
@ -55,6 +59,7 @@ void DialogFilter::parse(ParserT &parser) {
|
||||
bool has_pinned_dialog_ids;
|
||||
bool has_included_dialog_ids;
|
||||
bool has_excluded_dialog_ids;
|
||||
bool has_color_id;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(exclude_muted_);
|
||||
PARSE_FLAG(exclude_read_);
|
||||
@ -69,8 +74,8 @@ void DialogFilter::parse(ParserT &parser) {
|
||||
PARSE_FLAG(has_excluded_dialog_ids);
|
||||
PARSE_FLAG(is_shareable_);
|
||||
PARSE_FLAG(has_my_invites_);
|
||||
PARSE_FLAG(has_color_id);
|
||||
END_PARSE_FLAGS();
|
||||
|
||||
parse(dialog_filter_id_, parser);
|
||||
parse(title_, parser);
|
||||
parse(emoji_, parser);
|
||||
@ -83,6 +88,11 @@ void DialogFilter::parse(ParserT &parser) {
|
||||
if (has_excluded_dialog_ids) {
|
||||
parse(excluded_dialog_ids_, parser);
|
||||
}
|
||||
if (has_color_id) {
|
||||
parse(color_id_, parser);
|
||||
} else {
|
||||
color_id_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -40,10 +40,10 @@
|
||||
namespace td {
|
||||
|
||||
class GetDialogFiltersQuery final : public Td::ResultHandler {
|
||||
Promise<vector<tl_object_ptr<telegram_api::DialogFilter>>> promise_;
|
||||
Promise<telegram_api::object_ptr<telegram_api::messages_dialogFilters>> promise_;
|
||||
|
||||
public:
|
||||
explicit GetDialogFiltersQuery(Promise<vector<tl_object_ptr<telegram_api::DialogFilter>>> &&promise)
|
||||
explicit GetDialogFiltersQuery(Promise<telegram_api::object_ptr<telegram_api::messages_dialogFilters>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
@ -127,6 +127,32 @@ class UpdateDialogFiltersOrderQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class ToggleDialogFilterTagsQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
|
||||
public:
|
||||
explicit ToggleDialogFilterTagsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(bool are_tags_enabled) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_toggleDialogFilterTags(are_tags_enabled)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_toggleDialogFilterTags>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
LOG(INFO) << "Receive result for ToggleDialogFilterTagsQuery: " << result_ptr.ok();
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class ExportChatlistInviteQuery final : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::chatFolderInviteLink>> promise_;
|
||||
|
||||
@ -555,6 +581,8 @@ class DialogFilterManager::DialogFiltersLogEvent {
|
||||
const vector<unique_ptr<DialogFilter>> *dialog_filters_in;
|
||||
vector<unique_ptr<DialogFilter>> server_dialog_filters_out;
|
||||
vector<unique_ptr<DialogFilter>> dialog_filters_out;
|
||||
bool server_are_tags_enabled = false;
|
||||
bool are_tags_enabled = false;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const {
|
||||
@ -567,6 +595,8 @@ class DialogFilterManager::DialogFiltersLogEvent {
|
||||
STORE_FLAG(has_dialog_filters);
|
||||
STORE_FLAG(has_server_main_dialog_list_position);
|
||||
STORE_FLAG(has_main_dialog_list_position);
|
||||
STORE_FLAG(server_are_tags_enabled);
|
||||
STORE_FLAG(are_tags_enabled);
|
||||
END_STORE_FLAGS();
|
||||
td::store(updated_date, storer);
|
||||
if (has_server_dialog_filters) {
|
||||
@ -595,6 +625,8 @@ class DialogFilterManager::DialogFiltersLogEvent {
|
||||
PARSE_FLAG(has_dialog_filters);
|
||||
PARSE_FLAG(has_server_main_dialog_list_position);
|
||||
PARSE_FLAG(has_main_dialog_list_position);
|
||||
PARSE_FLAG(server_are_tags_enabled);
|
||||
PARSE_FLAG(are_tags_enabled);
|
||||
END_PARSE_FLAGS();
|
||||
}
|
||||
td::parse(updated_date, parser);
|
||||
@ -630,14 +662,22 @@ void DialogFilterManager::init() {
|
||||
if (!dialog_filters.empty()) {
|
||||
DialogFiltersLogEvent log_event;
|
||||
if (log_event_parse(log_event, dialog_filters).is_ok()) {
|
||||
server_are_tags_enabled_ = log_event.server_are_tags_enabled;
|
||||
are_tags_enabled_ = log_event.are_tags_enabled;
|
||||
server_main_dialog_list_position_ = log_event.server_main_dialog_list_position;
|
||||
main_dialog_list_position_ = log_event.main_dialog_list_position;
|
||||
if (!td_->option_manager_->get_option_boolean("is_premium") &&
|
||||
(server_main_dialog_list_position_ != 0 || main_dialog_list_position_ != 0)) {
|
||||
LOG(INFO) << "Ignore main chat list position " << server_main_dialog_list_position_ << '/'
|
||||
<< main_dialog_list_position_;
|
||||
server_main_dialog_list_position_ = 0;
|
||||
main_dialog_list_position_ = 0;
|
||||
if (!td_->option_manager_->get_option_boolean("is_premium")) {
|
||||
if (server_main_dialog_list_position_ != 0 || main_dialog_list_position_ != 0) {
|
||||
LOG(INFO) << "Ignore main chat list position " << server_main_dialog_list_position_ << '/'
|
||||
<< main_dialog_list_position_;
|
||||
server_main_dialog_list_position_ = 0;
|
||||
main_dialog_list_position_ = 0;
|
||||
}
|
||||
if (server_are_tags_enabled_ || are_tags_enabled_) {
|
||||
LOG(INFO) << "Ignore enabled tags " << server_are_tags_enabled_ << '/' << are_tags_enabled_;
|
||||
server_are_tags_enabled_ = false;
|
||||
are_tags_enabled_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
dialog_filters_updated_date_ = td_->ignore_background_updates() ? 0 : log_event.updated_date;
|
||||
@ -1134,7 +1174,7 @@ void DialogFilterManager::reload_dialog_filters() {
|
||||
are_dialog_filters_being_reloaded_ = true;
|
||||
need_dialog_filters_reload_ = false;
|
||||
auto promise = PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this)](Result<vector<telegram_api::object_ptr<telegram_api::DialogFilter>>> r_filters) {
|
||||
[actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::messages_dialogFilters>> r_filters) {
|
||||
send_closure(actor_id, &DialogFilterManager::on_get_dialog_filters, std::move(r_filters), false);
|
||||
});
|
||||
td_->create_handler<GetDialogFiltersQuery>(std::move(promise))->send();
|
||||
@ -1187,7 +1227,7 @@ void DialogFilterManager::on_get_dialog_filter(telegram_api::object_ptr<telegram
|
||||
}
|
||||
|
||||
void DialogFilterManager::on_get_dialog_filters(
|
||||
Result<vector<telegram_api::object_ptr<telegram_api::DialogFilter>>> r_filters, bool dummy) {
|
||||
Result<telegram_api::object_ptr<telegram_api::messages_dialogFilters>> r_filters, bool dummy) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
@ -1206,10 +1246,12 @@ void DialogFilterManager::on_get_dialog_filters(
|
||||
return;
|
||||
}
|
||||
|
||||
auto filters = r_filters.move_as_ok();
|
||||
auto dialog_filters = r_filters.move_as_ok();
|
||||
auto filters = std::move(dialog_filters->filters_);
|
||||
vector<unique_ptr<DialogFilter>> new_server_dialog_filters;
|
||||
LOG(INFO) << "Receive chat folders from server: " << to_string(filters);
|
||||
std::unordered_set<DialogFilterId, DialogFilterIdHash> new_dialog_filter_ids;
|
||||
bool server_are_tags_enabled = dialog_filters->tags_enabled_;
|
||||
int32 server_main_dialog_list_position = -1;
|
||||
int32 position = 0;
|
||||
for (auto &filter : filters) {
|
||||
@ -1242,6 +1284,10 @@ void DialogFilterManager::on_get_dialog_filters(
|
||||
LOG(INFO) << "Ignore server main chat list position " << server_main_dialog_list_position;
|
||||
server_main_dialog_list_position = 0;
|
||||
}
|
||||
if (server_are_tags_enabled && !td_->option_manager_->get_option_boolean("is_premium")) {
|
||||
LOG(INFO) << "Ignore server enabled tags";
|
||||
server_are_tags_enabled = false;
|
||||
}
|
||||
|
||||
bool is_changed = false;
|
||||
dialog_filters_updated_date_ = G()->unix_time();
|
||||
@ -1363,6 +1409,15 @@ void DialogFilterManager::on_get_dialog_filters(
|
||||
is_changed = true;
|
||||
}
|
||||
}
|
||||
if (server_are_tags_enabled_ != server_are_tags_enabled) {
|
||||
server_are_tags_enabled_ = server_are_tags_enabled;
|
||||
|
||||
if (server_are_tags_enabled != are_tags_enabled_) {
|
||||
LOG(INFO) << "Change are_tags_enabled_ from " << are_tags_enabled_ << " to " << server_are_tags_enabled;
|
||||
are_tags_enabled_ = server_are_tags_enabled;
|
||||
is_changed = true;
|
||||
}
|
||||
}
|
||||
if (is_changed || !is_update_chat_folders_sent_) {
|
||||
send_update_chat_folders();
|
||||
}
|
||||
@ -1404,6 +1459,10 @@ bool DialogFilterManager::need_synchronize_dialog_filters() const {
|
||||
// need reorder main chat list on server
|
||||
return true;
|
||||
}
|
||||
if (are_tags_enabled_ != server_are_tags_enabled_) {
|
||||
// need enable/disable tags
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1452,6 +1511,10 @@ void DialogFilterManager::synchronize_dialog_filters() {
|
||||
return reorder_dialog_filters_on_server(std::move(dialog_filter_ids), server_main_dialog_list_position);
|
||||
}
|
||||
|
||||
if (are_tags_enabled_ != server_are_tags_enabled_) {
|
||||
return toggle_are_tags_enabled_on_server(are_tags_enabled_);
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
@ -1471,6 +1534,7 @@ td_api::object_ptr<td_api::updateChatFolders> DialogFilterManager::get_update_ch
|
||||
update->chat_folders_.push_back(dialog_filter->get_chat_folder_info_object());
|
||||
}
|
||||
update->main_chat_list_position_ = main_dialog_list_position_;
|
||||
update->are_tags_enabled_ = are_tags_enabled_;
|
||||
return update;
|
||||
}
|
||||
|
||||
@ -1779,6 +1843,50 @@ void DialogFilterManager::on_reorder_dialog_filters(vector<DialogFilterId> dialo
|
||||
synchronize_dialog_filters();
|
||||
}
|
||||
|
||||
void DialogFilterManager::toggle_dialog_filter_tags(bool are_tags_enabled, Promise<Unit> &&promise) {
|
||||
if (!td_->option_manager_->get_option_boolean("is_premium")) {
|
||||
if (!are_tags_enabled) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
return promise.set_error(Status::Error(400, "Method not available"));
|
||||
}
|
||||
|
||||
if (are_tags_enabled_ != are_tags_enabled) {
|
||||
are_tags_enabled_ = are_tags_enabled;
|
||||
|
||||
save_dialog_filters();
|
||||
send_update_chat_folders();
|
||||
|
||||
synchronize_dialog_filters();
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void DialogFilterManager::toggle_are_tags_enabled_on_server(bool are_tags_enabled) {
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
are_dialog_filters_being_synchronized_ = true;
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), are_tags_enabled](Result<Unit> result) mutable {
|
||||
send_closure(actor_id, &DialogFilterManager::on_toggle_are_tags_enabled, are_tags_enabled,
|
||||
result.is_error() ? result.move_as_error() : Status::OK());
|
||||
});
|
||||
td_->create_handler<ToggleDialogFilterTagsQuery>(std::move(promise))->send(are_tags_enabled);
|
||||
}
|
||||
|
||||
void DialogFilterManager::on_toggle_are_tags_enabled(bool are_tags_enabled, Status result) {
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
if (result.is_error()) {
|
||||
are_tags_enabled_ = !are_tags_enabled;
|
||||
} else {
|
||||
if (server_are_tags_enabled_ != are_tags_enabled) {
|
||||
server_are_tags_enabled_ = are_tags_enabled;
|
||||
save_dialog_filters();
|
||||
}
|
||||
}
|
||||
|
||||
are_dialog_filters_being_synchronized_ = false;
|
||||
synchronize_dialog_filters();
|
||||
}
|
||||
|
||||
void DialogFilterManager::add_dialog_filter(unique_ptr<DialogFilter> dialog_filter, bool at_beginning,
|
||||
const char *source) {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
@ -1846,6 +1954,8 @@ void DialogFilterManager::save_dialog_filters() {
|
||||
}
|
||||
|
||||
DialogFiltersLogEvent log_event;
|
||||
log_event.server_are_tags_enabled = server_are_tags_enabled_;
|
||||
log_event.are_tags_enabled = are_tags_enabled_;
|
||||
log_event.server_main_dialog_list_position = server_main_dialog_list_position_;
|
||||
log_event.main_dialog_list_position = main_dialog_list_position_;
|
||||
log_event.updated_date = dialog_filters_updated_date_;
|
||||
@ -2009,7 +2119,7 @@ void DialogFilterManager::on_get_chatlist_invite(
|
||||
icon_name = "Custom";
|
||||
}
|
||||
info = td_api::make_object<td_api::chatFolderInfo>(
|
||||
0, invite->title_, td_api::make_object<td_api::chatFolderIcon>(icon_name), true, false);
|
||||
0, invite->title_, td_api::make_object<td_api::chatFolderIcon>(icon_name), -1, true, false);
|
||||
missing_peers = std::move(invite->peers_);
|
||||
chats = std::move(invite->chats_);
|
||||
users = std::move(invite->users_);
|
||||
@ -2100,4 +2210,14 @@ void DialogFilterManager::get_current_state(vector<td_api::object_ptr<td_api::Up
|
||||
}
|
||||
}
|
||||
|
||||
void DialogFilterManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"server_dialog_filters_\":"); output.emplace_back(std::to_string(this->server_dialog_filters_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"dialog_filters_\":"); output.emplace_back(std::to_string(this->dialog_filters_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"dialog_filter_reload_queries_\":"); output.emplace_back(std::to_string(this->dialog_filter_reload_queries_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"recommended_dialog_filters_\":"); output.emplace_back(std::to_string(this->recommended_dialog_filters_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -28,6 +28,7 @@ class Td;
|
||||
|
||||
class DialogFilterManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
DialogFilterManager(Td *td, ActorShared<> parent);
|
||||
DialogFilterManager(const DialogFilterManager &) = delete;
|
||||
DialogFilterManager &operator=(const DialogFilterManager &) = delete;
|
||||
@ -81,6 +82,8 @@ class DialogFilterManager final : public Actor {
|
||||
void reorder_dialog_filters(vector<DialogFilterId> dialog_filter_ids, int32 main_dialog_list_position,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void toggle_dialog_filter_tags(bool are_tags_enabled, Promise<Unit> &&promise);
|
||||
|
||||
void get_dialogs_for_dialog_filter_invite_link(DialogFilterId dialog_filter_id,
|
||||
Promise<td_api::object_ptr<td_api::chats>> promise);
|
||||
|
||||
@ -152,7 +155,7 @@ class DialogFilterManager final : public Actor {
|
||||
|
||||
void reload_dialog_filters();
|
||||
|
||||
void on_get_dialog_filters(Result<vector<telegram_api::object_ptr<telegram_api::DialogFilter>>> r_filters,
|
||||
void on_get_dialog_filters(Result<telegram_api::object_ptr<telegram_api::messages_dialogFilters>> r_filters,
|
||||
bool dummy);
|
||||
|
||||
bool need_synchronize_dialog_filters() const;
|
||||
@ -186,6 +189,10 @@ class DialogFilterManager final : public Actor {
|
||||
void on_reorder_dialog_filters(vector<DialogFilterId> dialog_filter_ids, int32 main_dialog_list_position,
|
||||
Status result);
|
||||
|
||||
void toggle_are_tags_enabled_on_server(bool are_tags_enabled);
|
||||
|
||||
void on_toggle_are_tags_enabled(bool are_tags_enabled, Status result);
|
||||
|
||||
void save_dialog_filters();
|
||||
|
||||
void add_dialog_filter(unique_ptr<DialogFilter> dialog_filter, bool at_beginning, const char *source);
|
||||
@ -227,6 +234,8 @@ class DialogFilterManager final : public Actor {
|
||||
bool need_dialog_filters_reload_ = false;
|
||||
bool disable_get_dialog_filter_ = false;
|
||||
bool is_update_chat_folders_sent_ = false;
|
||||
bool server_are_tags_enabled_ = false;
|
||||
bool are_tags_enabled_ = false;
|
||||
int32 dialog_filters_updated_date_ = 0;
|
||||
vector<unique_ptr<DialogFilter>> server_dialog_filters_;
|
||||
vector<unique_ptr<DialogFilter>> dialog_filters_;
|
||||
|
@ -1097,4 +1097,10 @@ void DialogInviteLinkManager::delete_all_revoked_dialog_invite_links(DialogId di
|
||||
->send(dialog_id, std::move(input_user));
|
||||
}
|
||||
|
||||
void DialogInviteLinkManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"invite_link_infos_\":"); output.emplace_back(std::to_string(this->invite_link_infos_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"dialog_access_by_invite_link_\":"); output.emplace_back(std::to_string(this->dialog_access_by_invite_link_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -28,6 +28,7 @@ class Td;
|
||||
|
||||
class DialogInviteLinkManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
DialogInviteLinkManager(Td *td, ActorShared<> parent);
|
||||
DialogInviteLinkManager(const DialogInviteLinkManager &) = delete;
|
||||
DialogInviteLinkManager &operator=(const DialogInviteLinkManager &) = delete;
|
||||
|
@ -18,6 +18,13 @@ DialogLocation::DialogLocation(Td *td, telegram_api::object_ptr<telegram_api::Ch
|
||||
}
|
||||
}
|
||||
|
||||
DialogLocation::DialogLocation(Td *td, telegram_api::object_ptr<telegram_api::businessLocation> &&business_location) {
|
||||
if (business_location != nullptr) {
|
||||
location_ = Location(td, business_location->geo_point_);
|
||||
address_ = std::move(business_location->address_);
|
||||
}
|
||||
}
|
||||
|
||||
DialogLocation::DialogLocation(td_api::object_ptr<td_api::chatLocation> &&chat_location) {
|
||||
if (chat_location != nullptr) {
|
||||
location_ = Location(chat_location->location_);
|
||||
@ -28,6 +35,16 @@ DialogLocation::DialogLocation(td_api::object_ptr<td_api::chatLocation> &&chat_l
|
||||
}
|
||||
}
|
||||
|
||||
DialogLocation::DialogLocation(td_api::object_ptr<td_api::businessLocation> &&business_location) {
|
||||
if (business_location != nullptr) {
|
||||
location_ = Location(business_location->location_);
|
||||
address_ = std::move(business_location->address_);
|
||||
if (!clean_input_string(address_)) {
|
||||
address_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DialogLocation::empty() const {
|
||||
return location_.empty();
|
||||
}
|
||||
@ -39,6 +56,13 @@ td_api::object_ptr<td_api::chatLocation> DialogLocation::get_chat_location_objec
|
||||
return td_api::make_object<td_api::chatLocation>(location_.get_location_object(), address_);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::businessLocation> DialogLocation::get_business_location_object() const {
|
||||
if (empty() && address_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::businessLocation>(location_.get_location_object(), address_);
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::InputGeoPoint> DialogLocation::get_input_geo_point() const {
|
||||
return location_.get_input_geo_point();
|
||||
}
|
||||
|
@ -32,12 +32,18 @@ class DialogLocation {
|
||||
|
||||
DialogLocation(Td *td, telegram_api::object_ptr<telegram_api::ChannelLocation> &&channel_location_ptr);
|
||||
|
||||
DialogLocation(Td *td, telegram_api::object_ptr<telegram_api::businessLocation> &&business_location);
|
||||
|
||||
explicit DialogLocation(td_api::object_ptr<td_api::chatLocation> &&chat_location);
|
||||
|
||||
explicit DialogLocation(td_api::object_ptr<td_api::businessLocation> &&business_location);
|
||||
|
||||
bool empty() const;
|
||||
|
||||
td_api::object_ptr<td_api::chatLocation> get_chat_location_object() const;
|
||||
|
||||
td_api::object_ptr<td_api::businessLocation> get_business_location_object() const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::InputGeoPoint> get_input_geo_point() const;
|
||||
|
||||
const string &get_address() const;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/ReportReason.h"
|
||||
#include "td/telegram/SecretChatId.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
@ -103,15 +104,13 @@ class CheckChannelUsernameQuery final : public Td::ResultHandler {
|
||||
};
|
||||
|
||||
class ResolveUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
string username_;
|
||||
Promise<DialogId> promise_;
|
||||
|
||||
public:
|
||||
explicit ResolveUsernameQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
explicit ResolveUsernameQuery(Promise<DialogId> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(const string &username) {
|
||||
username_ = username;
|
||||
send_query(G()->net_query_creator().create(telegram_api::contacts_resolveUsername(username)));
|
||||
}
|
||||
|
||||
@ -126,15 +125,10 @@ class ResolveUsernameQuery final : public Td::ResultHandler {
|
||||
td_->contacts_manager_->on_get_users(std::move(ptr->users_), "ResolveUsernameQuery");
|
||||
td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "ResolveUsernameQuery");
|
||||
|
||||
td_->dialog_manager_->on_resolved_username(username_, DialogId(ptr->peer_));
|
||||
|
||||
promise_.set_value(Unit());
|
||||
promise_.set_value(DialogId(ptr->peer_));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (status.message() == Slice("USERNAME_NOT_OCCUPIED")) {
|
||||
td_->dialog_manager_->drop_username(username_);
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
@ -689,6 +683,19 @@ bool DialogManager::have_dialog_info(DialogId dialog_id) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool DialogManager::is_dialog_info_received_from_server(DialogId dialog_id) const {
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
return td_->contacts_manager_->is_user_received_from_server(dialog_id.get_user_id());
|
||||
case DialogType::Chat:
|
||||
return td_->contacts_manager_->is_chat_received_from_server(dialog_id.get_chat_id());
|
||||
case DialogType::Channel:
|
||||
return td_->contacts_manager_->is_channel_received_from_server(dialog_id.get_channel_id());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DialogManager::have_dialog_info_force(DialogId dialog_id, const char *source) const {
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User: {
|
||||
@ -1107,6 +1114,24 @@ string DialogManager::get_dialog_about(DialogId dialog_id) {
|
||||
}
|
||||
}
|
||||
|
||||
string DialogManager::get_dialog_search_text(DialogId dialog_id) const {
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
return td_->contacts_manager_->get_user_search_text(dialog_id.get_user_id());
|
||||
case DialogType::Chat:
|
||||
return td_->contacts_manager_->get_chat_title(dialog_id.get_chat_id());
|
||||
case DialogType::Channel:
|
||||
return td_->contacts_manager_->get_channel_search_text(dialog_id.get_channel_id());
|
||||
case DialogType::SecretChat:
|
||||
return td_->contacts_manager_->get_user_search_text(
|
||||
td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id()));
|
||||
case DialogType::None:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
bool DialogManager::get_dialog_has_protected_content(DialogId dialog_id) const {
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
@ -1607,6 +1632,24 @@ void DialogManager::set_dialog_description(DialogId dialog_id, const string &des
|
||||
}
|
||||
}
|
||||
|
||||
void DialogManager::set_dialog_location(DialogId dialog_id, const DialogLocation &location, Promise<Unit> &&promise) {
|
||||
if (!have_dialog_force(dialog_id, "set_dialog_location")) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
case DialogType::Chat:
|
||||
case DialogType::SecretChat:
|
||||
return promise.set_error(Status::Error(400, "The chat can't have location"));
|
||||
case DialogType::Channel:
|
||||
return td_->contacts_manager_->set_channel_location(dialog_id.get_channel_id(), location, std::move(promise));
|
||||
case DialogType::None:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
bool DialogManager::can_report_dialog(DialogId dialog_id) const {
|
||||
// doesn't include possibility of report from action bar
|
||||
switch (dialog_id.get_type()) {
|
||||
@ -1730,6 +1773,21 @@ Status DialogManager::can_pin_messages(DialogId dialog_id) const {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
bool DialogManager::can_use_premium_custom_emoji_in_dialog(DialogId dialog_id) const {
|
||||
if (!td_->auth_manager_->is_bot()) {
|
||||
if (dialog_id == get_my_dialog_id() || td_->option_manager_->get_option_boolean("is_premium")) {
|
||||
return true;
|
||||
}
|
||||
if (dialog_id.get_type() == DialogType::Channel &&
|
||||
td_->contacts_manager_->can_use_premium_custom_emoji_in_channel(dialog_id.get_channel_id())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto user_id = td_->contacts_manager_->get_my_id();
|
||||
return !td_->contacts_manager_->have_user(user_id) || td_->contacts_manager_->has_user_fragment_username(user_id);
|
||||
}
|
||||
|
||||
bool DialogManager::is_dialog_removed_from_dialog_list(DialogId dialog_id) const {
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
@ -1748,6 +1806,40 @@ bool DialogManager::is_dialog_removed_from_dialog_list(DialogId dialog_id) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void DialogManager::on_update_dialog_bot_commands(
|
||||
DialogId dialog_id, UserId bot_user_id, vector<telegram_api::object_ptr<telegram_api::botCommand>> &&bot_commands) {
|
||||
if (!bot_user_id.is_valid()) {
|
||||
LOG(ERROR) << "Receive updateBotCommands about invalid " << bot_user_id;
|
||||
return;
|
||||
}
|
||||
if (!td_->contacts_manager_->have_user_force(bot_user_id, "on_update_dialog_bot_commands") ||
|
||||
!td_->contacts_manager_->is_user_bot(bot_user_id)) {
|
||||
return;
|
||||
}
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
if (DialogId(bot_user_id) != dialog_id) {
|
||||
LOG(ERROR) << "Receive commands of " << bot_user_id << " in " << dialog_id;
|
||||
return;
|
||||
}
|
||||
return td_->contacts_manager_->on_update_user_commands(bot_user_id, std::move(bot_commands));
|
||||
case DialogType::Chat:
|
||||
return td_->contacts_manager_->on_update_chat_bot_commands(dialog_id.get_chat_id(),
|
||||
BotCommands(bot_user_id, std::move(bot_commands)));
|
||||
case DialogType::Channel:
|
||||
return td_->contacts_manager_->on_update_channel_bot_commands(dialog_id.get_channel_id(),
|
||||
BotCommands(bot_user_id, std::move(bot_commands)));
|
||||
case DialogType::SecretChat:
|
||||
default:
|
||||
LOG(ERROR) << "Receive updateBotCommands in " << dialog_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DialogManager::on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames,
|
||||
const Usernames &new_usernames) {
|
||||
LOG(INFO) << "Update usernames in " << dialog_id << " from " << old_usernames << " to " << new_usernames;
|
||||
@ -1876,7 +1968,54 @@ td_api::object_ptr<td_api::CheckChatUsernameResult> DialogManager::get_check_cha
|
||||
}
|
||||
|
||||
void DialogManager::send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise) {
|
||||
td_->create_handler<ResolveUsernameQuery>(std::move(promise))->send(username);
|
||||
CHECK(!username.empty());
|
||||
auto &queries = resolve_dialog_username_queries_[username];
|
||||
queries.push_back(std::move(promise));
|
||||
if (queries.size() != 1u) {
|
||||
return;
|
||||
}
|
||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), username](Result<DialogId> r_dialog_id) {
|
||||
send_closure(actor_id, &DialogManager::on_resolved_username, username, std::move(r_dialog_id));
|
||||
});
|
||||
td_->create_handler<ResolveUsernameQuery>(std::move(query_promise))->send(username);
|
||||
}
|
||||
|
||||
void DialogManager::on_resolved_username(const string &username, Result<DialogId> r_dialog_id) {
|
||||
G()->ignore_result_if_closing(r_dialog_id);
|
||||
auto it = resolve_dialog_username_queries_.find(username);
|
||||
CHECK(it != resolve_dialog_username_queries_.end());
|
||||
auto promises = std::move(it->second);
|
||||
CHECK(!promises.empty());
|
||||
resolve_dialog_username_queries_.erase(it);
|
||||
if (r_dialog_id.is_error()) {
|
||||
auto error_message = r_dialog_id.error().message();
|
||||
if (error_message == Slice("USERNAME_NOT_OCCUPIED") || error_message == Slice("USERNAME_INVALID")) {
|
||||
drop_username(username);
|
||||
}
|
||||
return fail_promises(promises, r_dialog_id.move_as_error());
|
||||
}
|
||||
|
||||
auto dialog_id = r_dialog_id.ok();
|
||||
if (!dialog_id.is_valid()) {
|
||||
LOG(ERROR) << "Resolve username \"" << username << "\" to invalid " << dialog_id;
|
||||
return fail_promises(promises, Status::Error(500, "Chat not found"));
|
||||
}
|
||||
|
||||
auto cleaned_username = clean_username(username);
|
||||
if (cleaned_username.empty()) {
|
||||
return fail_promises(promises, Status::Error(500, "Invalid username"));
|
||||
}
|
||||
|
||||
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
||||
if (resolved_username.dialog_id.is_valid()) {
|
||||
LOG_IF(ERROR, resolved_username.dialog_id != dialog_id)
|
||||
<< "Resolve username \"" << username << "\" to " << dialog_id << ", but have it in "
|
||||
<< resolved_username.dialog_id;
|
||||
return set_promises(promises);
|
||||
}
|
||||
|
||||
inaccessible_resolved_usernames_[cleaned_username] = dialog_id;
|
||||
set_promises(promises);
|
||||
}
|
||||
|
||||
void DialogManager::resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> promise) {
|
||||
@ -2002,28 +2141,6 @@ void DialogManager::reload_voice_chat_on_search(const string &username) {
|
||||
}
|
||||
}
|
||||
|
||||
void DialogManager::on_resolved_username(const string &username, DialogId dialog_id) {
|
||||
if (!dialog_id.is_valid()) {
|
||||
LOG(ERROR) << "Resolve username \"" << username << "\" to invalid " << dialog_id;
|
||||
return;
|
||||
}
|
||||
|
||||
auto cleaned_username = clean_username(username);
|
||||
if (cleaned_username.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
||||
if (resolved_username.dialog_id.is_valid()) {
|
||||
LOG_IF(ERROR, resolved_username.dialog_id != dialog_id)
|
||||
<< "Resolve username \"" << username << "\" to " << dialog_id << ", but have it in "
|
||||
<< resolved_username.dialog_id;
|
||||
return;
|
||||
}
|
||||
|
||||
inaccessible_resolved_usernames_[cleaned_username] = dialog_id;
|
||||
}
|
||||
|
||||
void DialogManager::drop_username(const string &username) {
|
||||
auto cleaned_username = clean_username(username);
|
||||
if (cleaned_username.empty()) {
|
||||
@ -2044,4 +2161,16 @@ void DialogManager::drop_username(const string &username) {
|
||||
}
|
||||
}
|
||||
|
||||
void DialogManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"being_uploaded_dialog_photos_\":"); output.emplace_back(std::to_string(this->being_uploaded_dialog_photos_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"resolved_usernames_\":"); output.emplace_back(std::to_string(this->resolved_usernames_.calc_size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"inaccessible_resolved_usernames_\":"); output.emplace_back(std::to_string(this->inaccessible_resolved_usernames_.calc_size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"reload_voice_chat_on_search_usernames_\":"); output.emplace_back(std::to_string(this->reload_voice_chat_on_search_usernames_.size()));
|
||||
output.emplace_back(",");
|
||||
output.emplace_back("\"resolve_dialog_username_queries_\":"); output.emplace_back(std::to_string(this->resolve_dialog_username_queries_.size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "td/telegram/ChannelId.h"
|
||||
#include "td/telegram/CustomEmojiId.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/DialogLocation.h"
|
||||
#include "td/telegram/DialogParticipant.h"
|
||||
#include "td/telegram/EmojiStatus.h"
|
||||
#include "td/telegram/files/FileId.h"
|
||||
@ -41,6 +42,7 @@ class Usernames;
|
||||
|
||||
class DialogManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
DialogManager(Td *td, ActorShared<> parent);
|
||||
DialogManager(const DialogManager &) = delete;
|
||||
DialogManager &operator=(const DialogManager &) = delete;
|
||||
@ -84,6 +86,8 @@ class DialogManager final : public Actor {
|
||||
|
||||
void reload_dialog_info(DialogId dialog_id, Promise<Unit> &&promise);
|
||||
|
||||
bool is_dialog_info_received_from_server(DialogId dialog_id) const;
|
||||
|
||||
void get_dialog_info_full(DialogId dialog_id, Promise<Unit> &&promise, const char *source);
|
||||
|
||||
void reload_dialog_info_full(DialogId dialog_id, const char *source);
|
||||
@ -134,6 +138,8 @@ class DialogManager final : public Actor {
|
||||
|
||||
string get_dialog_about(DialogId dialog_id);
|
||||
|
||||
string get_dialog_search_text(DialogId dialog_id) const;
|
||||
|
||||
bool get_dialog_has_protected_content(DialogId dialog_id) const;
|
||||
|
||||
bool is_dialog_action_unneeded(DialogId dialog_id) const;
|
||||
@ -158,6 +164,8 @@ class DialogManager final : public Actor {
|
||||
|
||||
void set_dialog_description(DialogId dialog_id, const string &description, Promise<Unit> &&promise);
|
||||
|
||||
void set_dialog_location(DialogId dialog_id, const DialogLocation &location, Promise<Unit> &&promise);
|
||||
|
||||
bool can_report_dialog(DialogId dialog_id) const;
|
||||
|
||||
void report_dialog(DialogId dialog_id, const vector<MessageId> &message_ids, ReportReason &&reason,
|
||||
@ -167,11 +175,16 @@ class DialogManager final : public Actor {
|
||||
|
||||
Status can_pin_messages(DialogId dialog_id) const;
|
||||
|
||||
bool can_use_premium_custom_emoji_in_dialog(DialogId dialog_id) const;
|
||||
|
||||
bool is_dialog_removed_from_dialog_list(DialogId dialog_id) const;
|
||||
|
||||
void upload_dialog_photo(DialogId dialog_id, FileId file_id, bool is_animation, double main_frame_timestamp,
|
||||
bool is_reupload, Promise<Unit> &&promise, vector<int> bad_parts = {});
|
||||
|
||||
void on_update_dialog_bot_commands(DialogId dialog_id, UserId bot_user_id,
|
||||
vector<telegram_api::object_ptr<telegram_api::botCommand>> &&bot_commands);
|
||||
|
||||
void on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames, const Usernames &new_usernames);
|
||||
|
||||
void on_dialog_usernames_received(DialogId dialog_id, const Usernames &usernames, bool from_database);
|
||||
@ -199,10 +212,6 @@ class DialogManager final : public Actor {
|
||||
|
||||
void reload_voice_chat_on_search(const string &username);
|
||||
|
||||
void on_resolved_username(const string &username, DialogId dialog_id);
|
||||
|
||||
void drop_username(const string &username);
|
||||
|
||||
private:
|
||||
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
||||
|
||||
@ -220,6 +229,10 @@ class DialogManager final : public Actor {
|
||||
|
||||
void send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise);
|
||||
|
||||
void on_resolved_username(const string &username, Result<DialogId> r_dialog_id);
|
||||
|
||||
void drop_username(const string &username);
|
||||
|
||||
void on_resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> &&promise);
|
||||
|
||||
class UploadDialogPhotoCallback;
|
||||
@ -255,6 +268,8 @@ class DialogManager final : public Actor {
|
||||
WaitFreeHashMap<string, DialogId> inaccessible_resolved_usernames_;
|
||||
FlatHashSet<string> reload_voice_chat_on_search_usernames_;
|
||||
|
||||
FlatHashMap<string, vector<Promise<Unit>>> resolve_dialog_username_queries_;
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,7 @@
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/DialogInviteLink.h"
|
||||
#include "td/telegram/DialogParticipant.h"
|
||||
#include "td/telegram/DialogParticipantFilter.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
@ -24,12 +25,17 @@
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace td {
|
||||
|
||||
class ChannelParticipantFilter;
|
||||
|
||||
class Td;
|
||||
|
||||
class DialogParticipantManager final : public Actor {
|
||||
public:
|
||||
void memory_stats(vector<string> &output);
|
||||
DialogParticipantManager(Td *td, ActorShared<> parent);
|
||||
DialogParticipantManager(const DialogParticipantManager &) = delete;
|
||||
DialogParticipantManager &operator=(const DialogParticipantManager &) = delete;
|
||||
@ -44,6 +50,14 @@ class DialogParticipantManager final : public Actor {
|
||||
|
||||
void on_update_dialog_online_member_count(DialogId dialog_id, int32 online_member_count, bool is_from_server);
|
||||
|
||||
void add_cached_channel_participants(ChannelId channel_id, const vector<UserId> &added_user_ids,
|
||||
UserId inviter_user_id, int32 date);
|
||||
|
||||
void delete_cached_channel_participant(ChannelId channel_id, UserId deleted_user_id);
|
||||
|
||||
void update_cached_channel_participant_status(ChannelId channel_id, UserId user_id,
|
||||
const DialogParticipantStatus &status);
|
||||
|
||||
void on_dialog_opened(DialogId dialog_id);
|
||||
|
||||
void on_dialog_closed(DialogId dialog_id);
|
||||
@ -89,6 +103,13 @@ class DialogParticipantManager final : public Actor {
|
||||
void get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
|
||||
Promise<DialogParticipant> &&promise);
|
||||
|
||||
void get_channel_participants(ChannelId channel_id, td_api::object_ptr<td_api::SupergroupMembersFilter> &&filter,
|
||||
string additional_query, int32 offset, int32 limit, int32 additional_limit,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
||||
|
||||
void add_dialog_participants(DialogId dialog_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);
|
||||
@ -114,6 +135,18 @@ class DialogParticipantManager final : public Actor {
|
||||
|
||||
void drop_channel_participant_cache(ChannelId channel_id);
|
||||
|
||||
struct CanTransferOwnershipResult {
|
||||
enum class Type : uint8 { Ok, PasswordNeeded, PasswordTooFresh, SessionTooFresh };
|
||||
Type type = Type::Ok;
|
||||
int32 retry_after = 0;
|
||||
};
|
||||
void can_transfer_ownership(Promise<CanTransferOwnershipResult> &&promise);
|
||||
|
||||
static td_api::object_ptr<td_api::CanTransferOwnershipResult> get_can_transfer_ownership_result_object(
|
||||
CanTransferOwnershipResult result);
|
||||
|
||||
void transfer_dialog_ownership(DialogId dialog_id, UserId user_id, const string &password, Promise<Unit> &&promise);
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
|
||||
private:
|
||||
@ -123,6 +156,8 @@ class DialogParticipantManager final : public Actor {
|
||||
|
||||
static constexpr int32 CHANNEL_PARTICIPANT_CACHE_TIME = 1800; // some reasonable limit
|
||||
|
||||
static constexpr int32 MAX_GET_CHANNEL_PARTICIPANTS = 200; // server side limit
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
static void on_update_dialog_online_member_count_timeout_callback(void *dialog_participant_manager_ptr,
|
||||
@ -166,6 +201,33 @@ class DialogParticipantManager final : public Actor {
|
||||
void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
|
||||
Promise<DialogParticipant> &&promise);
|
||||
|
||||
std::pair<int32, vector<DialogId>> search_among_dialogs(const vector<DialogId> &dialog_ids, const string &query,
|
||||
int32 limit) const;
|
||||
|
||||
DialogParticipants search_private_chat_participants(UserId peer_user_id, const string &query, int32 limit,
|
||||
DialogParticipantFilter filter) const;
|
||||
|
||||
void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void do_search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void on_get_channel_participants(
|
||||
ChannelId channel_id, ChannelParticipantFilter &&filter, int32 offset, int32 limit, string additional_query,
|
||||
int32 additional_limit,
|
||||
telegram_api::object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
|
||||
Promise<DialogParticipants> &&promise);
|
||||
|
||||
void set_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status, bool is_recursive,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
||||
|
||||
void send_edit_chat_admin_query(ChatId chat_id, UserId user_id, bool is_administrator, Promise<Unit> &&promise);
|
||||
|
||||
void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise<Unit> &&promise);
|
||||
|
||||
void add_channel_participant(ChannelId channel_id, UserId user_id, const DialogParticipantStatus &old_status,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
@ -201,6 +263,16 @@ class DialogParticipantManager final : public Actor {
|
||||
|
||||
void on_channel_participant_cache_timeout(ChannelId channel_id);
|
||||
|
||||
void set_cached_channel_participants(ChannelId channel_id, vector<DialogParticipant> participants);
|
||||
|
||||
void drop_cached_channel_participants(ChannelId channel_id);
|
||||
|
||||
void update_channel_online_member_count(ChannelId channel_id, bool is_from_server);
|
||||
|
||||
void transfer_channel_ownership(ChannelId channel_id, UserId user_id,
|
||||
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
struct OnlineMemberCountInfo {
|
||||
int32 online_member_count = 0;
|
||||
double update_time = 0;
|
||||
@ -226,6 +298,8 @@ class DialogParticipantManager final : public Actor {
|
||||
};
|
||||
FlatHashMap<ChannelId, ChannelParticipants, ChannelIdHash> channel_participants_;
|
||||
|
||||
FlatHashMap<ChannelId, vector<DialogParticipant>, ChannelIdHash> cached_channel_participants_;
|
||||
|
||||
FlatHashMap<ChannelId, vector<Promise<Unit>>, ChannelIdHash> join_channel_queries_;
|
||||
|
||||
MultiTimeout update_dialog_online_member_count_timeout_{"UpdateDialogOnlineMemberCountTimeout"};
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/VideoNotesManager.h"
|
||||
#include "td/telegram/VideosManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
|
||||
@ -36,24 +37,26 @@ void Document::append_file_ids(const Td *td, vector<FileId> &file_ids) const {
|
||||
|
||||
file_ids.push_back(file_id);
|
||||
|
||||
FileId thumbnail_file_id = [&] {
|
||||
switch (type) {
|
||||
case Type::Animation:
|
||||
return td->animations_manager_->get_animation_thumbnail_file_id(file_id);
|
||||
case Type::Audio:
|
||||
return td->audios_manager_->get_audio_thumbnail_file_id(file_id);
|
||||
case Type::General:
|
||||
return td->documents_manager_->get_document_thumbnail_file_id(file_id);
|
||||
case Type::Video:
|
||||
return td->videos_manager_->get_video_thumbnail_file_id(file_id);
|
||||
case Type::VideoNote:
|
||||
return td->video_notes_manager_->get_video_note_thumbnail_file_id(file_id);
|
||||
default:
|
||||
return FileId();
|
||||
if (!G()->get_option_boolean("disable_minithumbnails")) {
|
||||
FileId thumbnail_file_id = [&] {
|
||||
switch (type) {
|
||||
case Type::Animation:
|
||||
return td->animations_manager_->get_animation_thumbnail_file_id(file_id);
|
||||
case Type::Audio:
|
||||
return td->audios_manager_->get_audio_thumbnail_file_id(file_id);
|
||||
case Type::General:
|
||||
return td->documents_manager_->get_document_thumbnail_file_id(file_id);
|
||||
case Type::Video:
|
||||
return td->videos_manager_->get_video_thumbnail_file_id(file_id);
|
||||
case Type::VideoNote:
|
||||
return td->video_notes_manager_->get_video_note_thumbnail_file_id(file_id);
|
||||
default:
|
||||
return FileId();
|
||||
}
|
||||
}();
|
||||
if (thumbnail_file_id.is_valid()) {
|
||||
file_ids.push_back(thumbnail_file_id);
|
||||
}
|
||||
}();
|
||||
if (thumbnail_file_id.is_valid()) {
|
||||
file_ids.push_back(thumbnail_file_id);
|
||||
}
|
||||
|
||||
FileId animated_thumbnail_file_id = [&] {
|
||||
|
@ -757,6 +757,7 @@ void DocumentsManager::merge_documents(FileId new_id, FileId old_id) {
|
||||
LOG_STATUS(td_->file_manager_->merge(new_id, old_id));
|
||||
}
|
||||
|
||||
|
||||
string DocumentsManager::get_document_search_text(FileId file_id) const {
|
||||
auto document = get_document(file_id);
|
||||
CHECK(document);
|
||||
@ -778,4 +779,8 @@ string DocumentsManager::get_document_search_text(FileId file_id) const {
|
||||
return sb.as_cslice().str();
|
||||
}
|
||||
|
||||
void DocumentsManager::memory_stats(vector<string> &output) {
|
||||
output.emplace_back("\"documents_\":"); output.emplace_back(std::to_string(this->documents_.calc_size()));
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user