Apply tdlight patch

- Memory manager
- TD_SKIP_TEST/TD_SKIP_BENCHMARK/TD_SKIP_TG_CLI
- Rebranding
- github workflow
- .gitignore
- Add crypt32 to windows
- Fatal crash log handler
- optionally unencrypted database
- malloc_trim support
- getMemoryStatistics

Options:
- disable_document_filenames
- disable_minithumbnails
- disable_notifications
- disable_group_calls
- disable_auto_download
- ignore_server_deletes_and_reads
- ignore_update_chat_last_message
- ignore_update_chat_read_inbox
- ignore_update_user_chat_action
- receive_access_hashes
- message_unload_delay modification
This commit is contained in:
Andrea Cavalli 2023-10-08 16:59:20 +02:00
parent 0d3a1552ed
commit b6c5bd07bb
165 changed files with 2277 additions and 189 deletions

50
.github/workflows/build.yaml vendored Normal file
View 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

2
.gitignore vendored
View File

@ -4,7 +4,9 @@
**/auto/ **/auto/
docs/ docs/
/tdlib/ /tdlib/
.idea/
vcpkg/ vcpkg/
*.tlo
td.binlog td.binlog

View File

@ -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 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 * Added ability to specify the exact types of problems with a call in the method `sendCallRating` and
the new class `CallProblem`. 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`. - 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 * Added a [TDLib build instructions generator](https://tdlib.github.io/td/build.html), covering in details
TDLib building on the most popular operating systems. TDLib building on the most popular operating systems.
* Added an example of TDLib building and usage from a browser. * 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. * 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. 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: * 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): 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. in different programming languages.
* Added a [Getting started](https://core.telegram.org/tdlib/getting-started) guide describing the main TDLib concepts * Added a [Getting started](https://core.telegram.org/tdlib/getting-started) guide describing the main TDLib concepts
and basic principles required for library usage. and basic principles required for library usage.

View File

@ -207,9 +207,13 @@ add_subdirectory(sqlite)
add_subdirectory(tddb) 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) add_subdirectory(benchmark)
endif() endif()
@ -569,6 +573,7 @@ set(TDLIB_SOURCE_PART2
td/telegram/StickersManager.cpp td/telegram/StickersManager.cpp
td/telegram/StickerType.cpp td/telegram/StickerType.cpp
td/telegram/StorageManager.cpp td/telegram/StorageManager.cpp
td/telegram/MemoryManager.cpp
td/telegram/StoryContent.cpp td/telegram/StoryContent.cpp
td/telegram/StoryContentType.cpp td/telegram/StoryContentType.cpp
td/telegram/StoryDb.cpp td/telegram/StoryDb.cpp
@ -918,6 +923,7 @@ set(TDLIB_SOURCE_PART2
td/telegram/StickersManager.h td/telegram/StickersManager.h
td/telegram/StickerType.h td/telegram/StickerType.h
td/telegram/StorageManager.h td/telegram/StorageManager.h
td/telegram/MemoryManager.h
td/telegram/StoryContent.h td/telegram/StoryContent.h
td/telegram/StoryContentType.h td/telegram/StoryContentType.h
td/telegram/StoryDb.h td/telegram/StoryDb.h
@ -1241,6 +1247,8 @@ if (EMSCRIPTEN)
endif() endif()
if (NOT CMAKE_CROSSCOMPILING) 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}) add_executable(tg_cli td/telegram/cli.cpp ${TL_TD_JSON_SOURCE})
if (NOT READLINE_FOUND) if (NOT READLINE_FOUND)
@ -1269,6 +1277,7 @@ if (NOT CMAKE_CROSSCOMPILING)
target_link_libraries(tg_cli PRIVATE memprof tdclient tdcore) target_link_libraries(tg_cli PRIVATE memprof tdclient tdcore)
add_dependencies(tg_cli tl_generate_json) add_dependencies(tg_cli tl_generate_json)
endif() endif()
endif()
# Exported libraries # Exported libraries
add_library(TdStatic INTERFACE) add_library(TdStatic INTERFACE)

View File

@ -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 ## Table of Contents
- [Features](#features) - [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) - [Examples and documentation](#usage)
- [Dependencies](#dependencies) - [Dependencies](#dependencies)
- [Building](#building) - [Building](#building)
@ -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. * **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. * **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> <a name="usage"></a>
## Examples and documentation ## Examples and documentation
See our [Getting Started](https://core.telegram.org/tdlib/getting-started) tutorial for a description of basic TDLib concepts. 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 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). 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> <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> <a name="building"></a>
## Building ## 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. 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: 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 . 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: before compiling main `TDLib` source code and compile only needed targets:
``` ```
mkdir build mkdir build
@ -106,21 +134,21 @@ Or you could install `TDLib` and then reference it in your CMakeLists.txt like t
find_package(Td 1.8.35 REQUIRED) find_package(Td 1.8.35 REQUIRED)
target_link_libraries(YourTarget PRIVATE Td::TdStatic) 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> <a name="using-java"></a>
## Using in Java projects ## Using in Java projects
`TDLib` provides native Java interface through JNI. To enable it, specify option `-DTD_ENABLE_JNI=ON` to CMake. `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> <a name="using-dotnet"></a>
## Using in .NET projects ## 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. `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. .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/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/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/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: 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. `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. 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, 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). 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. `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. 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> <a name="license"></a>
## License ## License

381
UpdateMemoryManager.javash Executable file
View File

@ -0,0 +1,381 @@
#!/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",
"FileDownload",
"FileUpload",
"Alarm"
);
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.push_back(\"\\\"%s\\\":\"); output.push_back(std::to_string(this->%s.%s()));\n".formatted(field.name, field.name, field.type.sizeMethodName))
.collect(Collectors.joining(" output.push_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.push_back("\\"%s_manager_\\":{"); td_->%s_manager_->memory_stats(output); output.push_back("}");
""".formatted(toSnakeCase(m.name), toSnakeCase(m.name)))
.collect(Collectors.joining(" output.push_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;
}
}

View File

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>TDLib build instructions</title> <title>TDLight build instructions</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<style> <style>
:root { :root {
@ -193,7 +193,7 @@
<div class="main"> <div class="main">
<div id="languageSelectDiv"> <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"> <select id="languageSelect" onchange="onLanguageChanged(false)" autofocus class="large">
<option>Choose a programming language:</option> <option>Choose a programming language:</option>
<option>Python</option> <option>Python</option>
@ -226,7 +226,7 @@
</div> </div>
<div id="osSelectDiv" class="hide"> <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"> <select id="osSelect" onchange="onOsChanged()" class="large">
<option>Choose an operating system:</option> <option>Choose an operating system:</option>
</select> </select>
@ -234,7 +234,7 @@
</div> </div>
<div id="linuxSelectDiv" class="hide"> <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"> <select id="linuxSelect" onchange="onOsChanged()" class="large">
<option>Choose a Linux distro:</option> <option>Choose a Linux distro:</option>
<option>Alpine</option> <option>Alpine</option>
@ -265,13 +265,13 @@
</div> </div>
<div id="buildInstallLocalDiv" class="hide"> <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> </div>
<p></p> <p></p>
<div id="buildCompilerDiv" class="hide"> <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="buildCompilerRadioGcc" name="buildCompilerRadio" onchange="onOptionsChanged()" checked/>g++</label>
<label><input type="radio" id="buildCompilerRadioClang" name="buildCompilerRadio" onchange="onOptionsChanged()"/>clang (recommended)</label> <label><input type="radio" id="buildCompilerRadioClang" name="buildCompilerRadio" onchange="onOptionsChanged()"/>clang (recommended)</label>
<p></p> <p></p>
@ -307,7 +307,7 @@
</div> </div>
<div id="buildBitnessDiv" class="hide"> <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="buildBitnessRadio32" name="buildBitnessRadio" onchange="onOptionsChanged()" checked/>32</label>
<label><input type="radio" id="buildBitnessRadio64" name="buildBitnessRadio" onchange="onOptionsChanged()"/>64</label> <label><input type="radio" id="buildBitnessRadio64" name="buildBitnessRadio" onchange="onOptionsChanged()"/>64</label>
<p></p> <p></p>
@ -329,7 +329,7 @@
</div> </div>
<div id="buildCommandsDiv" class="hide"> <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> <p id="buildPre">Hidden text</p>
<code id="buildCommands">Empty commands</code> <code id="buildCommands">Empty commands</code>
<button id="copyBuildCommandsButton" onclick="copyBuildInstructions()"> <button id="copyBuildCommandsButton" onclick="copyBuildInstructions()">
@ -505,9 +505,9 @@ function getTargetName(target) {
return '<a href="https://github.com/tdlib/td#using-cxx">simple and convenient C++11</a>'; return '<a href="https://github.com/tdlib/td#using-cxx">simple and convenient C++11</a>';
case 'JNI': case 'JNI':
case 'Android': 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: 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>';
} }
} }
@ -521,12 +521,12 @@ function onOsChanged() {
if (language === 'Other') { if (language === 'Other') {
language = 'any other programming language'; language = 'any other programming language';
} }
var text = 'TDLib can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' + var text = 'TDLight 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>'; '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') { 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>' + 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/tdlib/td/tree/master/example/web">example</a>.'; '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 = ''; target = '';
} }
if (target === 'Android' || target === 'AndroidJson') { if (target === 'Android' || target === 'AndroidJson') {
@ -757,8 +757,8 @@ function onOptionsChanged() {
pre_text.push('Note that the following instruction is for NetBSD 8+ and default SH shell.'); pre_text.push('Note that the following instruction is for NetBSD 8+ and default SH shell.');
} }
if (os_mac) { if (os_mac) {
pre_text.push('Note that the following instruction will build TDLib only for ' + os_mac_host_name + '.'); 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/tdlib/td/tree/master/example/ios">example</a> instead.'); 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 () { var terminal_name = (function () {
@ -782,12 +782,12 @@ function onOptionsChanged() {
if (os_windows) { if (os_windows) {
pre_text.push('Close and re-open ' + terminal_name + ' if the PATH environment variable was changed.'); 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').innerHTML = '<ul><li>' + pre_text.join('</li><li>') + '</li></ul>';
document.getElementById('buildPre').style.display = 'block'; document.getElementById('buildPre').style.display = 'block';
if (install_dir && install_dir !== '/usr/local') { if (install_dir && install_dir !== '/usr/local') {
install_dir = '../tdlib'; install_dir = '../tdlight';
if (target === 'JNI' || target === 'C++/CX') { if (target === 'JNI' || target === 'C++/CX') {
install_dir = '../../' + install_dir; install_dir = '../../' + install_dir;
} }
@ -953,9 +953,9 @@ function onOptionsChanged() {
commands.push('exit'); 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'); // commands.push('git checkout v1.8.0');
if (use_vcpkg) { if (use_vcpkg) {

View File

@ -1,7 +1,7 @@
# TDLib usage and build examples # 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. 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 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). [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. 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). 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. 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. [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> <a name="javascript"></a>
## Using TDLib in JavaScript projects ## 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. 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. 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. 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. 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). 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> <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`. 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 [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/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/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/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, 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. 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. 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++. 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/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. [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, 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, [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. 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, visionOS, 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 [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 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> <a name="objective-c"></a>
## Using TDLib in Objective-C projects ## 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. 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, visionOS, 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> <a name="object-pascal"></a>
## Using TDLib in Object Pascal projects with Delphi and Lazarus ## 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. 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> <a name="g"></a>
## Using TDLib from G projects ## Using TDLib from G projects

View File

@ -4,7 +4,7 @@ Below are instructions for building TDLib for iOS, watchOS, tvOS, visionOS, and
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). 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: 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/). * Install the latest Xcode via `xcode-select --install` or downloading it from [Xcode website](https://developer.apple.com/xcode/).
@ -37,7 +37,7 @@ cd <path to TDLib sources>/example/ios
``` ```
This may take a while, because TDLib will be built about 16 times. 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. 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. Built libraries and XCFramework will be stored in `tdjson` directory.

View File

@ -3,7 +3,7 @@
To run this example, you will need installed JDK >= 1.6. To run this example, you will need installed JDK >= 1.6.
For Javadoc documentation generation PHP is needed. 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. In general, the build process looks as follows.

View File

@ -6,7 +6,7 @@
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo> <MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
<Tags>Telegram, TDLib, library, client, API</Tags> <Tags>Telegram, TDLib, library, client, API</Tags>
<License>LICENSE_1_0.txt</License> <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> </Metadata>
<Installation Scope="Global"> <Installation Scope="Global">
<InstallationTarget Id="Microsoft.ExtensionSDK" TargetPlatformIdentifier="UAP" TargetPlatformVersion="v0.8.0.0" SdkName="Telegram.Td.UWP" SdkVersion="1.0" /> <InstallationTarget Id="Microsoft.ExtensionSDK" TargetPlatformIdentifier="UAP" TargetPlatformVersion="v0.8.0.0" SdkName="Telegram.Td.UWP" SdkVersion="1.0" />

View File

@ -26,4 +26,4 @@ cd <path to TDLib sources>/example/web
## Using tdweb NPM package ## 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.

View File

@ -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 [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 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 [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 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. 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 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. fields of bytes type are base64 encoded and then stored as String, fields of array type are stored as Array.

View File

@ -65,7 +65,7 @@ class TdClient {
* *
* If the query contains the field '@extra', the same field will be added into the result. * 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} * 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 * 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}. * [classes]{@link https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html}.

1
td/generate/scheme/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.tlo

View File

@ -583,6 +583,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 //@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; 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 //@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; botCommand command:string description:string = BotCommand;
@ -6868,6 +6883,10 @@ storageStatisticsFast files_size:int53 file_count:int32 database_size:int53 lang
//@statistics Database statistics in an unspecified human-readable format //@statistics Database statistics in an unspecified human-readable format
databaseStatistics statistics:string = DatabaseStatistics; 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 network //@class NetworkType @description Represents the type of network
@ -7637,6 +7656,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 //@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; 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 //@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; updateBasicGroup basic_group:basicGroup = Update;
@ -11284,6 +11306,10 @@ getStorageStatisticsFast = StorageStatisticsFast;
//@description Returns database statistics //@description Returns database statistics
getDatabaseStatistics = DatabaseStatistics; 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 //@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 //@size Limit on the total size of files after deletion, in bytes. Pass -1 to use the default limit
//@ttl Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit //@ttl Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit

View File

@ -185,7 +185,7 @@ void tl_print_parse_error (void) {
} }
char *parse_lex (void) { char *parse_lex (void) {
while (1) { while (1) {
while (curch && is_whitespace (curch)) { nextch (); } while (curch && is_whitespace (curch)) { nextch (); }
if (curch == '/' && nextch () == '/') { if (curch == '/' && nextch () == '/') {
while (nextch () != 10); while (nextch () != 10);
@ -235,7 +235,7 @@ char *parse_lex (void) {
case '.': case '.':
nextch (); nextch ();
parse.lex.len = 1; parse.lex.len = 1;
parse.lex.type = lex_char; parse.lex.type = lex_char;
return (parse.lex.ptr = p); return (parse.lex.ptr = p);
case 'a': case 'a':
case 'b': case 'b':
@ -334,10 +334,10 @@ char *parse_lex (void) {
int ok = 1; int ok = 1;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (!is_hexdigit (nextch())) { if (!is_hexdigit (nextch())) {
if (curch == ' ' && i >= 5) { if (curch == ' ' && i >= 5) {
ok = 2; ok = 2;
break; break;
} else { } else {
parse_error ("Hex digit expected"); parse_error ("Hex digit expected");
parse.lex.type = lex_error; parse.lex.type = lex_error;
return (parse.lex.ptr = (void *)-1); return (parse.lex.ptr = (void *)-1);
@ -370,7 +370,7 @@ char *parse_lex (void) {
parse.lex.type = lex_error; parse.lex.type = lex_error;
return (parse.lex.ptr = (void *)-1); return (parse.lex.ptr = (void *)-1);
} }
} }
int expect (char *s) { int expect (char *s) {
@ -453,7 +453,7 @@ struct tree *parse_full_combinator_id (void) {
} else { } else {
parse_error ("Can not parse full combinator id"); parse_error ("Can not parse full combinator id");
PARSE_FAIL; PARSE_FAIL;
} }
} }
struct tree *parse_combinator_id (void) { struct tree *parse_combinator_id (void) {
@ -467,7 +467,7 @@ struct tree *parse_combinator_id (void) {
} else { } else {
parse_error ("Can not parse combinator id"); parse_error ("Can not parse combinator id");
PARSE_FAIL; PARSE_FAIL;
} }
} }
struct tree *parse_var_ident (void) { struct tree *parse_var_ident (void) {
@ -595,7 +595,7 @@ struct tree *parse_subexpr (void) {
was_term = 1; was_term = 1;
PARSE_TRY (parse_term); PARSE_TRY (parse_term);
if (S) { if (S) {
tree_add_child (T, S); tree_add_child (T, S);
} else { } else {
break; break;
} }
@ -714,7 +714,7 @@ struct tree *parse_args4 (void) {
if (S) { if (S) {
tree_add_child (T, S); tree_add_child (T, S);
} else { } else {
load_parse (so); load_parse (so);
} }
if (LEX_CHAR ('!')) { if (LEX_CHAR ('!')) {
PARSE_ADD (type_exclam); PARSE_ADD (type_exclam);
@ -733,7 +733,7 @@ struct tree *parse_args3 (void) {
if (S) { if (S) {
tree_add_child (T, S); tree_add_child (T, S);
} else { } else {
load_parse (so); load_parse (so);
} }
if (LEX_CHAR ('!')) { if (LEX_CHAR ('!')) {
PARSE_ADD (type_exclam); PARSE_ADD (type_exclam);
@ -757,7 +757,7 @@ struct tree *parse_args2 (void) {
if (S) { if (S) {
tree_add_child (T, S); tree_add_child (T, S);
} else { } else {
load_parse (so); load_parse (so);
} }
struct parse save2 = save_parse (); struct parse save2 = save_parse ();
PARSE_TRY (parse_multiplicity); PARSE_TRY (parse_multiplicity);
@ -789,7 +789,7 @@ struct tree *parse_args1 (void) {
if (S) { if (S) {
tree_add_child (T, S); tree_add_child (T, S);
} else { } else {
load_parse (so); load_parse (so);
} }
if (LEX_CHAR ('!')) { if (LEX_CHAR ('!')) {
PARSE_ADD (type_exclam); PARSE_ADD (type_exclam);
@ -1041,7 +1041,7 @@ int tl_add_field (char *id) {
void tl_clear_fields (void) { void tl_clear_fields (void) {
// tree_act_tl_field (fields[namespace_level], (void *)free); // 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) { 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) { void tl_add_type_param (struct tl_type *t, int x) {
assert (t->flags & 4); assert (t->flags & 4);
assert (t->params_num <= 64); assert (t->params_num <= 64);
if (x) { if (x) {
t->params_types |= (1ull << (t->params_num ++)); t->params_types |= (1ull << (t->params_num ++));
} else { } else {
t->params_num ++; 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)); struct tl_constructor *t = talloc (sizeof (*t));
t->type = a; t->type = a;
t->name = magic; t->name = magic;
t->id = id; t->id = id;
t->print_id = tstrdup (id); t->print_id = tstrdup (id);
t->real_id = 0; 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)); struct tl_constructor *t = talloc (sizeof (*t));
t->type = a; t->type = a;
t->name = magic; t->name = magic;
t->id = id; t->id = id;
t->print_id = tstrdup (id); t->print_id = tstrdup (id);
t->real_id = 0; 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); tl_buf_add_tree (T->right, 0);
return; return;
} }
default: default:
fprintf (stderr, "%s %s\n", TL_ACT (T->act), TL_TYPE (T->type)); fprintf (stderr, "%s %s\n", TL_ACT (T->act), TL_TYPE (T->type));
assert (0); assert (0);
@ -1549,7 +1549,7 @@ struct tl_combinator_tree *tl_union (struct tl_combinator_tree *L, struct tl_com
tfree (v, sizeof (*v)); tfree (v, sizeof (*v));
R->type_flags += L->type_flags; R->type_flags += L->type_flags;
return R; return R;
case type_list_item: case type_list_item:
case type_list: case type_list:
if (R->type != type_list_item) { if (R->type != type_list_item) {
TL_ERROR ("Union: type mistmatch\n"); 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: case type_type:
if (L->type_len == 0) { if (L->type_len == 0) {
TL_ERROR ("Arguments number exceeds type arity\n"); 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) { if (R->type != type_num && R->type != type_type && R->type != type_num_value) {
TL_ERROR ("Union: type mistmatch\n"); 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) { if (R->type_len > 0) {
TL_ERROR ("Argument type must have full number of arguments\n"); 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))) { 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)); 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) { struct tl_combinator_tree *tl_parse_term (struct tree *T, int s) {
assert (T->type == type_term); assert (T->type == type_term);
int i = 0; 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); assert (i < T->nc);
TL_INIT (L); TL_INIT (L);
while (i < T->nc) { 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) { struct tl_combinator_tree *tl_parse_type_term (struct tree *T, int s) {
assert (T->type == type_type_term); assert (T->type == type_type_term);
assert (T->nc == 1); 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; } if (!Z || Z->type != type_type) { if (Z) { TL_ERROR ("type_term: found type %s\n", TL_TYPE (Z->type)); } TL_FAIL; }
return Z; return Z;
} }
@ -1674,7 +1674,7 @@ struct tl_combinator_tree *tl_parse_ident (struct tree *T, int s) {
assert (!T->nc); assert (!T->nc);
struct tl_var *v = tl_get_var (T->text, T->len); struct tl_var *v = tl_get_var (T->text, T->len);
TL_INIT (L); TL_INIT (L);
if (v) { if (v) {
L = alloc_ctree_node (); L = alloc_ctree_node ();
L->act = act_var; L->act = act_var;
L->type = v->type ? type_num : type_type; 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->data = t;
L->type = type_type; L->type = type_type;
L->type_len = t->params_num; L->type_len = t->params_num;
L->type_flags = t->params_types; L->type_flags = t->params_types;
return L; return L;
} else { } else {
TL_ERROR ("Not a type/var ident `%.*s`\n", T->len, T->text); 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: default:
fprintf (stderr, "type = %d\n", T->type); fprintf (stderr, "type = %d\n", T->type);
assert (0); 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) { 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); field_name = mystrdup (T->c[x]->text, T->c[x]->len);
if (!tl_add_field (field_name)) { 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; TL_FAIL;
} }
x ++; x ++;
} }
//fprintf (stderr, "%d %d\n", x, T->nc); //fprintf (stderr, "%d %d\n", x, T->nc);
if (T->c[x]->type == type_multiplicity) { if (T->c[x]->type == type_multiplicity) {
L = tl_parse_multiplicity (T->c[x]); L = tl_parse_multiplicity (T->c[x]);
@ -1846,7 +1846,7 @@ struct tl_combinator_tree *tl_parse_args2 (struct tree *T) {
x ++; x ++;
} else { } else {
struct tl_var *v = tl_get_last_num_var (); struct tl_var *v = tl_get_last_num_var ();
if (!v) { if (!v) {
TL_ERROR ("Expected multiplicity or nat var\n"); TL_ERROR ("Expected multiplicity or nat var\n");
TL_FAIL; TL_FAIL;
} }
@ -1880,7 +1880,7 @@ struct tl_combinator_tree *tl_parse_args2 (struct tree *T) {
H->right = 0; H->right = 0;
H->data = field_name; H->data = field_name;
H->type_len = 0; H->type_len = 0;
return H; return H;
} }
@ -1971,7 +1971,7 @@ struct tl_combinator_tree *tl_parse_args134 (struct tree *T) {
if (!v) {TL_FAIL;} if (!v) {TL_FAIL;}
v->flags |= 2; v->flags |= 2;
} }
H = tl_union (H, S); H = tl_union (H, S);
} }
return H; return H;
@ -1993,7 +1993,7 @@ struct tl_combinator_tree *tl_parse_args (struct tree *T) {
default: default:
assert (0); assert (0);
return 0; return 0;
} }
} }
void tl_mark_vars (struct tl_combinator_tree *T) { 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->type == type_result_type);
assert (T->nc >= 1); assert (T->nc >= 1);
assert (T->nc <= 64); assert (T->nc <= 64);
TL_INIT (L); TL_INIT (L);
if (tl_get_var (T->c[0]->text, T->c[0]->len)) { 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; int i;
for (i = 1; i < T->nc; i++) { for (i = 1; i < T->nc; i++) {
TL_TRY (tl_parse_any_term (T->c[i], 0), L); 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)); 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"); TL_ERROR ("Only functions can return variables\n");
} }
assert (t || fun); assert (t || fun);
assert (namespace_level == 0); assert (namespace_level == 0);
__ok = 1; __ok = 1;
tree_act_tl_var (vars[0], tl_var_check_used); 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_ERROR ("Not all variables are used in right side\n");
TL_FAIL; 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)) { 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); TL_ERROR ("Duplicate combinator id %.*s\n", T->c[0]->len, T->c[0]->text);
return 0; return 0;
@ -2107,7 +2107,7 @@ int tl_parse_combinator_decl (struct tree *T, int fun) {
if (!c) { TL_FAIL; } if (!c) { TL_FAIL; }
c->left = L; c->left = L;
c->right = R; c->right = R;
if (!c->name) { if (!c->name) {
tl_count_combinator_name (c); 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) { if (O->data == *X) {
struct tl_combinator_tree *R = tl_tree_dup (Y); 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; } 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; 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) { return 0;}
if (t == (void *)-1l) { return (void *)-1l; } if (t == (void *)-1l) { return (void *)-1l; }
if (t != (void *)-2l) { return t;} if (t != (void *)-2l) { return t;}
return (void *)-1l; return (void *)-1l;
} }
if (t != (void *)-2l) { if (t != (void *)-2l) {
O->left = t; 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); t = change_first_var (O->right, X, Y);
if (!t) { return 0;} if (!t) { return 0;}
if (t == (void *)-1l) { if (t == (void *)-1l) {
return O->left; return O->left;
} }
if (t != (void *)-2l) { if (t != (void *)-2l) {
O->right = t; 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) { return 0;}
if (t == (void *)-1l) { return (void *)-1l; } if (t == (void *)-1l) { return (void *)-1l; }
if (t != (void *)-2l) { return t;} if (t != (void *)-2l) { return t;}
return (void *)-1l; return (void *)-1l;
} }
if (t != (void *)-2l) { if (t != (void *)-2l) {
O->left = t; 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); t = change_value_var (O->right, X);
if (!t) { return 0;} if (!t) { return 0;}
if (t == (void *)-1l) { if (t == (void *)-1l) {
return O->left; return O->left;
} }
if (t != (void *)-2l) { if (t != (void *)-2l) {
O->right = t; O->right = t;
@ -2324,7 +2324,7 @@ int tl_parse_partial_type_app_decl (struct tree *T) {
assert (nt); assert (nt);
//snprintf (_buf, 100000, "%s #", t->id); //snprintf (_buf, 100000, "%s #", t->id);
//nt->real_id = strdup (_buf); //nt->real_id = strdup (_buf);
for (i = 0; i < t->constructors_num; i++) { for (i = 0; i < t->constructors_num; i++) {
struct tl_constructor *c = t->constructors[i]; struct tl_constructor *c = t->constructors[i];
struct tree_var_value *V = 0; struct tree_var_value *V = 0;
@ -2332,7 +2332,7 @@ int tl_parse_partial_type_app_decl (struct tree *T) {
TL_INIT (B); TL_INIT (B);
A = tl_tree_dup (c->left); A = tl_tree_dup (c->left);
B = tl_tree_dup (c->right); B = tl_tree_dup (c->right);
struct tree_var_value *W = 0; struct tree_var_value *W = 0;
change_var_ptrs (c->left, A, &W); change_var_ptrs (c->left, A, &W);
change_var_ptrs (c->right, B, &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); struct tl_constructor *r = tl_add_constructor (nt, _buf, strlen (_buf), 1);
snprintf (_buf, 100000, "%s", c->id); snprintf (_buf, 100000, "%s", c->id);
r->real_id = tstrdup (_buf); r->real_id = tstrdup (_buf);
r->left = A; r->left = A;
r->right = B; r->right = B;
if (!r->name) { if (!r->name) {
@ -2377,8 +2377,8 @@ int tl_parse_partial_comb_app_decl (struct tree *T, int fun) {
TL_INIT (R); TL_INIT (R);
L = tl_tree_dup (c->left); L = tl_tree_dup (c->left);
R = tl_tree_dup (c->right); R = tl_tree_dup (c->right);
struct tree_var_value *V = 0; struct tree_var_value *V = 0;
change_var_ptrs (c->left, L, &V); change_var_ptrs (c->left, L, &V);
change_var_ptrs (c->right, R, &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); TL_INIT (Z);
X = tl_parse_any_term (T->c[i], 0); X = tl_parse_any_term (T->c[i], 0);
struct tl_combinator_tree *K = 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; TL_FAIL;
} }
L = Z; L = Z;
@ -2516,7 +2516,7 @@ int tl_parse_builtin_combinator_decl (struct tree *T, int fun) {
if (!c) { if (!c) {
return 0; return 0;
} }
c->left = alloc_ctree_node (); c->left = alloc_ctree_node ();
c->left->act = act_question_mark; c->left->act = act_question_mark;
c->left->type = type_list_item; 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) { if (R->act == act_var) {
struct tl_combinator_tree *_ = R; R = L; L = _; struct tl_combinator_tree *_ = R; R = L; L = _;
} }
if (L->type == type_type) { if (L->type == type_type) {
if (R->type != type_type || L->type_len != R->type_len || L->type_flags != R->type_flags) { if (R->type != type_type || L->type_len != R->type_len || L->type_flags != R->type_flags) {
return 0; 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); M = tl_get_var_value (T, M->data);
} }
if (K->type == type_num_value && M->type == type_num_value) { if (K->type == type_num_value && M->type == type_num_value) {
return x == y; return x == y;
} }
if (M->type == type_num_value) { if (M->type == type_num_value) {
tl_set_var_value_num (T, K->data, M, -(x - y + M->type_flags)); 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) { } else if (K->type == type_num_value) {
tl_set_var_value_num (T, M->data, K, -(y - x + K->type_flags)); tl_set_var_value_num (T, M->data, K, -(y - x + K->type_flags));
return 1; return 1;
} else { } else {
if (x >= y) { if (x >= y) {
tl_set_var_value_num (T, K->data, M, -(x - y + M->type_flags)); 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 (!__ok) return;
if (!strcmp (t->id, "#")) { t->name = 0x70659eff; return; } if (!strcmp (t->id, "#")) { t->name = 0x70659eff; return; }
if (!strcmp (t->id, "Type")) { t->name = 0x2cecf817; 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); TL_ERROR ("Type %s has no constructors\n", t->id);
__ok = 0; __ok = 0;
return; return;
@ -2739,7 +2739,7 @@ void tl_type_check (struct tl_type *t) {
} }
} }
if ((t->flags & 24) == 24) { 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 z = 0;
int sid = 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); tl_set_var_value_num (v, T, 0, (*last_var) - 1);
} else { } else {
write_field_flags (f); write_field_flags (f);
} }
write_tree (T->left, 0, v, last_var); write_tree (T->left, 0, v, last_var);
} }

View File

@ -132,7 +132,7 @@ int main (int argc, char **argv) {
if (argc != optind + 1) { if (argc != optind + 1) {
usage (); usage ();
} }
struct parse *P = tl_init_parse_file (argv[optind]); struct parse *P = tl_init_parse_file (argv[optind]);
if (!P) { if (!P) {

View File

@ -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 } // namespace td

View File

@ -74,6 +74,8 @@ class AccountManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
class UnconfirmedAuthorization; class UnconfirmedAuthorization;
class UnconfirmedAuthorizations; class UnconfirmedAuthorizations;

View File

@ -10,6 +10,7 @@
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/Document.h" #include "td/telegram/Document.h"
#include "td/telegram/DocumentsManager.h" #include "td/telegram/DocumentsManager.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/FileReferenceManager.h" #include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileManager.h" #include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileType.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"; LOG(DEBUG) << "Animation " << file_id << " duration has changed";
a->duration = new_animation->duration; a->duration = new_animation->duration;
} }
if (a->minithumbnail != new_animation->minithumbnail) { if (!G()->get_option_boolean("disable_minithumbnails")) {
a->minithumbnail = std::move(new_animation->minithumbnail); if (a->minithumbnail != new_animation->minithumbnail) {
a->minithumbnail = std::move(new_animation->minithumbnail);
}
} }
if (a->thumbnail != new_animation->thumbnail) { if (a->thumbnail != new_animation->thumbnail) {
if (!a->thumbnail.file_id.is_valid()) { 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->mime_type = std::move(mime_type);
a->duration = max(duration, 0); a->duration = max(duration, 0);
a->dimensions = dimensions; a->dimensions = dimensions;
if (!td_->auth_manager_->is_bot()) { if (!G()->get_option_boolean("disable_minithumbnails")) {
a->minithumbnail = std::move(minithumbnail); if (!td_->auth_manager_->is_bot()) {
a->minithumbnail = std::move(minithumbnail);
}
} }
a->thumbnail = std::move(thumbnail); a->thumbnail = std::move(thumbnail);
a->animated_thumbnail = std::move(animated_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.push_back("\"animations_\":"); output.push_back(std::to_string(this->animations_.calc_size()));
output.push_back(",");
output.push_back("\"saved_animation_ids_\":"); output.push_back(std::to_string(this->saved_animation_ids_.size()));
output.push_back(",");
output.push_back("\"saved_animation_file_ids_\":"); output.push_back(std::to_string(this->saved_animation_file_ids_.size()));
output.push_back(",");
output.push_back("\"load_saved_animations_queries_\":"); output.push_back(std::to_string(this->load_saved_animations_queries_.size()));
output.push_back(",");
output.push_back("\"repair_saved_animations_queries_\":"); output.push_back(std::to_string(this->repair_saved_animations_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -28,6 +28,7 @@ class Td;
class AnimationsManager final : public Actor { class AnimationsManager final : public Actor {
public: public:
void memory_stats(vector<string> &output);
AnimationsManager(Td *td, ActorShared<> parent); AnimationsManager(Td *td, ActorShared<> parent);
AnimationsManager(const AnimationsManager &) = delete; AnimationsManager(const AnimationsManager &) = delete;
AnimationsManager &operator=(const AnimationsManager &) = delete; AnimationsManager &operator=(const AnimationsManager &) = delete;

View File

@ -55,10 +55,27 @@ FileId AnimationsManager::parse_animation(ParserT &parser) {
parse(animation->duration, parser); parse(animation->duration, parser);
} }
parse(animation->dimensions, parser); parse(animation->dimensions, parser);
parse(animation->file_name, parser);
string tmp_filename;
parse(tmp_filename, parser);
parse(animation->mime_type, 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)) { 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->thumbnail, parser);
parse(animation->file_id, parser); parse(animation->file_id, parser);

View File

@ -1449,4 +1449,16 @@ void AttachMenuManager::get_current_state(vector<td_api::object_ptr<td_api::Upda
updates.push_back(get_update_attachment_menu_bots_object()); updates.push_back(get_update_attachment_menu_bots_object());
} }
void AttachMenuManager::memory_stats(vector<string> &output) {
output.push_back("\"attach_menu_bots_\":"); output.push_back(std::to_string(this->attach_menu_bots_.size()));
output.push_back(",");
output.push_back("\"attach_menu_bot_file_source_ids_\":"); output.push_back(std::to_string(this->attach_menu_bot_file_source_ids_.size()));
output.push_back(",");
output.push_back("\"reload_attach_menu_bots_queries_\":"); output.push_back(std::to_string(this->reload_attach_menu_bots_queries_.size()));
output.push_back(",");
output.push_back("\"web_app_file_source_ids_\":"); output.push_back(std::to_string(this->web_app_file_source_ids_.size()));
output.push_back(",");
output.push_back("\"opened_web_views_\":"); output.push_back(std::to_string(this->opened_web_views_.size()));
}
} // namespace td } // namespace td

View File

@ -79,6 +79,8 @@ class AttachMenuManager final : public Actor {
static string get_attach_menu_bots_database_key(); static string get_attach_menu_bots_database_key();
void memory_stats(vector<string> &output);
private: private:
static const int32 PING_WEB_VIEW_TIMEOUT = 60; static const int32 PING_WEB_VIEW_TIMEOUT = 60;

View File

@ -309,4 +309,8 @@ tl_object_ptr<telegram_api::InputMedia> AudiosManager::get_input_media(
return nullptr; return nullptr;
} }
void AudiosManager::memory_stats(vector<string> &output) {
output.push_back("\"audios_\":"); output.push_back(std::to_string(this->audios_.calc_size()));
}
} // namespace td } // namespace td

View File

@ -22,6 +22,7 @@ class Td;
class AudiosManager { class AudiosManager {
public: public:
void memory_stats(vector<string> &output);
explicit AudiosManager(Td *td); explicit AudiosManager(Td *td);
AudiosManager(const AudiosManager &) = delete; AudiosManager(const AudiosManager &) = delete;
AudiosManager &operator=(const AudiosManager &) = delete; AudiosManager &operator=(const AudiosManager &) = delete;

View File

@ -99,7 +99,13 @@ FileId AudiosManager::parse_audio(ParserT &parser) {
has_date = false; has_date = false;
} }
if (has_file_name) { 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) { if (has_mime_type) {
parse(audio->mime_type, parser); parse(audio->mime_type, parser);
@ -114,7 +120,11 @@ FileId AudiosManager::parse_audio(ParserT &parser) {
parse(audio->performer, parser); parse(audio->performer, parser);
} }
if (has_minithumbnail) { 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) { if (has_thumbnail) {
parse(audio->thumbnail, parser); parse(audio->thumbnail, parser);

View File

@ -1493,4 +1493,10 @@ void AuthManager::save_state() {
G()->td_db()->get_binlog_pmc()->set("auth_state", log_event_store(db_state).as_slice().str()); 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.push_back("\"other_user_ids_\":"); output.push_back(std::to_string(this->other_user_ids_.size()));
output.push_back(",");
output.push_back("\"pending_get_authorization_state_requests_\":"); output.push_back(std::to_string(this->pending_get_authorization_state_requests_.size()));
}
} // namespace td } // namespace td

View File

@ -60,6 +60,8 @@ class AuthManager final : public NetActor {
void on_authorization_lost(string source); void on_authorization_lost(string source);
void on_closing(bool destroy_flag); void on_closing(bool destroy_flag);
void memory_stats(vector<string> &output);
// can return nullptr if state isn't initialized yet // can return nullptr if state isn't initialized yet
tl_object_ptr<td_api::AuthorizationState> get_current_authorization_state_object() const; tl_object_ptr<td_api::AuthorizationState> get_current_authorization_state_object() const;

View File

@ -126,14 +126,27 @@ class SaveAutoDownloadSettingsQuery final : public Td::ResultHandler {
AutoDownloadSettings get_auto_download_settings(const td_api::object_ptr<td_api::autoDownloadSettings> &settings) { AutoDownloadSettings get_auto_download_settings(const td_api::object_ptr<td_api::autoDownloadSettings> &settings) {
CHECK(settings != nullptr); CHECK(settings != nullptr);
AutoDownloadSettings result; AutoDownloadSettings result;
result.max_photo_file_size = settings->max_photo_file_size_; if (G()->get_option_boolean("disable_auto_download")) {
result.max_video_file_size = settings->max_video_file_size_; result.max_photo_file_size = -1;
result.max_other_file_size = settings->max_other_file_size_; 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.video_upload_bitrate = settings->video_upload_bitrate_;
result.is_enabled = settings->is_auto_download_enabled_; if (G()->get_option_boolean("disable_auto_download")) {
result.preload_large_videos = settings->preload_large_videos_; result.is_enabled = false;
result.preload_next_audio = settings->preload_next_audio_; result.preload_large_videos = false;
result.preload_stories = settings->preload_stories_; 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_; result.use_less_data_for_calls = settings->use_less_data_for_calls_;
return result; return result;
} }

View File

@ -547,4 +547,8 @@ void AutosaveManager::get_current_state(vector<td_api::object_ptr<td_api::Update
} }
} }
void AutosaveManager::memory_stats(vector<string> &output) {
output.push_back("\"load_settings_queries_\":"); output.push_back(std::to_string(this->load_settings_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -36,6 +36,8 @@ class AutosaveManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
struct DialogAutosaveSettings { struct DialogAutosaveSettings {
bool are_inited_ = false; bool are_inited_ = false;

View File

@ -1508,4 +1508,26 @@ void BackgroundManager::get_current_state(vector<td_api::object_ptr<td_api::Upda
updates.push_back(get_update_default_background_object(true)); updates.push_back(get_update_default_background_object(true));
} }
void BackgroundManager::memory_stats(vector<string> &output) {
output.push_back("\"backgrounds_\":"); output.push_back(std::to_string(this->backgrounds_.size()));
output.push_back(",");
output.push_back("\"background_id_to_file_source_id_\":"); output.push_back(std::to_string(this->background_id_to_file_source_id_.size()));
output.push_back(",");
output.push_back("\"name_to_background_id_\":"); output.push_back(std::to_string(this->name_to_background_id_.size()));
output.push_back(",");
output.push_back("\"file_id_to_background_id_\":"); output.push_back(std::to_string(this->file_id_to_background_id_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_backgrounds_\":"); output.push_back(std::to_string(this->loaded_from_database_backgrounds_.size()));
output.push_back(",");
output.push_back("\"being_loaded_from_database_backgrounds_\":"); output.push_back(std::to_string(this->being_loaded_from_database_backgrounds_.size()));
output.push_back(",");
output.push_back("\"installed_backgrounds_\":"); output.push_back(std::to_string(this->installed_backgrounds_.size()));
output.push_back(",");
output.push_back("\"pending_get_backgrounds_queries_\":"); output.push_back(std::to_string(this->pending_get_backgrounds_queries_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_files_\":"); output.push_back(std::to_string(this->being_uploaded_files_.size()));
output.push_back(",");
output.push_back("\"local_backgrounds_\":"); output.push_back(std::to_string(this->local_backgrounds_.size()));
}
} // namespace td } // namespace td

View File

@ -34,6 +34,7 @@ class Td;
class BackgroundManager final : public Actor { class BackgroundManager final : public Actor {
public: public:
void memory_stats(vector<string> &output);
BackgroundManager(Td *td, ActorShared<> parent); BackgroundManager(Td *td, ActorShared<> parent);
void get_backgrounds(bool for_dark_theme, Promise<td_api::object_ptr<td_api::backgrounds>> &&promise); void get_backgrounds(bool for_dark_theme, Promise<td_api::object_ptr<td_api::backgrounds>> &&promise);

View File

@ -502,4 +502,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))); td_->dialog_manager_->get_chat_id_object(dialog_id, "updateChatBoost"), std::move(chat_boost_object)));
} }
void BoostManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -55,6 +55,8 @@ class BoostManager final : public Actor {
void on_update_dialog_boost(DialogId dialog_id, telegram_api::object_ptr<telegram_api::boost> &&boost); void on_update_dialog_boost(DialogId dialog_id, telegram_api::object_ptr<telegram_api::boost> &&boost);
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -991,4 +991,16 @@ 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)); add_pending_get_query(bot_user_id, language_code, 2, std::move(promise));
} }
void BotInfoManager::memory_stats(vector<string> &output) {
output.push_back("\"pending_set_bot_info_queries_\":"); output.push_back(std::to_string(this->pending_set_bot_info_queries_.size()));
output.push_back(",");
output.push_back("\"pending_get_bot_info_queries_\":"); output.push_back(std::to_string(this->pending_get_bot_info_queries_.size()));
output.push_back(",");
output.push_back("\"bot_media_preview_file_source_ids_\":"); output.push_back(std::to_string(this->bot_media_preview_file_source_ids_.size()));
output.push_back(",");
output.push_back("\"bot_media_preview_info_file_source_ids_\":"); output.push_back(std::to_string(this->bot_media_preview_info_file_source_ids_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_files_\":"); output.push_back(std::to_string(this->being_uploaded_files_.size()));
}
} // namespace td } // namespace td

View File

@ -87,6 +87,8 @@ class BotInfoManager final : public Actor {
void get_bot_info_about(UserId bot_user_id, const string &language_code, Promise<string> &&promise); void get_bot_info_about(UserId bot_user_id, const string &language_code, Promise<string> &&promise);
void memory_stats(vector<string> &output);
private: private:
static constexpr double MAX_QUERY_DELAY = 0.01; static constexpr double MAX_QUERY_DELAY = 0.01;

View File

@ -1458,4 +1458,14 @@ void BusinessConnectionManager::get_current_state(vector<td_api::object_ptr<td_a
}); });
} }
void BusinessConnectionManager::memory_stats(vector<string> &output) {
output.push_back("\"business_connections_\":"); output.push_back(std::to_string(this->business_connections_.calc_size()));
output.push_back(",");
output.push_back("\"media_group_send_requests_\":"); output.push_back(std::to_string(this->media_group_send_requests_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_files_\":"); output.push_back(std::to_string(this->being_uploaded_files_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_thumbnails_\":"); output.push_back(std::to_string(this->being_uploaded_thumbnails_.size()));
}
} // namespace td } // namespace td

View File

@ -105,6 +105,8 @@ class BusinessConnectionManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
struct BusinessConnection; struct BusinessConnection;
struct PendingMessage; struct PendingMessage;

View File

@ -625,4 +625,7 @@ void BusinessManager::set_business_intro(BusinessIntro &&intro, Promise<Unit> &&
td_->create_handler<UpdateBusinessIntroQuery>(std::move(promise))->send(std::move(intro)); td_->create_handler<UpdateBusinessIntroQuery>(std::move(promise))->send(std::move(intro));
} }
void BusinessManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -61,6 +61,8 @@ class BusinessManager final : public Actor {
void set_business_intro(BusinessIntro &&intro, Promise<Unit> &&promise); void set_business_intro(BusinessIntro &&intro, Promise<Unit> &&promise);
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -312,4 +312,7 @@ void CallbackQueriesManager::send_get_callback_answer_query(
->send(dialog_id, message_full_id.get_message_id(), payload, std::move(password)); ->send(dialog_id, message_full_id.get_message_id(), payload, std::move(password));
} }
void CallbackQueriesManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -43,6 +43,8 @@ class CallbackQueriesManager {
void send_callback_query(MessageFullId message_full_id, tl_object_ptr<td_api::CallbackQueryPayload> &&payload, void send_callback_query(MessageFullId message_full_id, tl_object_ptr<td_api::CallbackQueryPayload> &&payload,
Promise<td_api::object_ptr<td_api::callbackQueryAnswer>> &&promise); Promise<td_api::object_ptr<td_api::callbackQueryAnswer>> &&promise);
void memory_stats(vector<string> &output);
private: private:
static constexpr int32 BOT_CALLBACK_ANSWER_FLAG_HAS_MESSAGE = 1 << 0; static constexpr int32 BOT_CALLBACK_ANSWER_FLAG_HAS_MESSAGE = 1 << 0;
static constexpr int32 BOT_CALLBACK_ANSWER_FLAG_NEED_SHOW_ALERT = 1 << 1; static constexpr int32 BOT_CALLBACK_ANSWER_FLAG_NEED_SHOW_ALERT = 1 << 1;

View File

@ -538,4 +538,12 @@ void ChannelRecommendationManager::open_channel_recommended_channel(DialogId dia
telegram_api::make_object<telegram_api::jsonObject>(std::move(data)), std::move(promise)); telegram_api::make_object<telegram_api::jsonObject>(std::move(data)), std::move(promise));
} }
void ChannelRecommendationManager::memory_stats(vector<string> &output) {
output.push_back("\"channel_recommended_dialogs_\":"); output.push_back(std::to_string(this->channel_recommended_dialogs_.size()));
output.push_back(",");
output.push_back("\"get_channel_recommendations_queries_\":"); output.push_back(std::to_string(this->get_channel_recommendations_queries_.size()));
output.push_back(",");
output.push_back("\"get_recommended_channels_queries_\":"); output.push_back(std::to_string(this->get_recommended_channels_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -36,6 +36,8 @@ class ChannelRecommendationManager final : public Actor {
void open_channel_recommended_channel(DialogId dialog_id, DialogId opened_dialog_id, Promise<Unit> &&promise); void open_channel_recommended_channel(DialogId dialog_id, DialogId opened_dialog_id, Promise<Unit> &&promise);
void memory_stats(vector<string> &output);
private: private:
static constexpr int32 CHANNEL_RECOMMENDATIONS_CACHE_TIME = 86400; // some reasonable limit static constexpr int32 CHANNEL_RECOMMENDATIONS_CACHE_TIME = 86400; // some reasonable limit

View File

@ -8959,4 +8959,48 @@ void ChatManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &
}); });
} }
void ChatManager::memory_stats(vector<string> &output) {
output.push_back("\"chats_\":"); output.push_back(std::to_string(this->chats_.calc_size()));
output.push_back(",");
output.push_back("\"chats_full_\":"); output.push_back(std::to_string(this->chats_full_.calc_size()));
output.push_back(",");
output.push_back("\"unknown_chats_\":"); output.push_back(std::to_string(this->unknown_chats_.size()));
output.push_back(",");
output.push_back("\"chat_full_file_source_ids_\":"); output.push_back(std::to_string(this->chat_full_file_source_ids_.calc_size()));
output.push_back(",");
output.push_back("\"min_channels_\":"); output.push_back(std::to_string(this->min_channels_.calc_size()));
output.push_back(",");
output.push_back("\"channels_\":"); output.push_back(std::to_string(this->channels_.calc_size()));
output.push_back(",");
output.push_back("\"channels_full_\":"); output.push_back(std::to_string(this->channels_full_.calc_size()));
output.push_back(",");
output.push_back("\"unknown_channels_\":"); output.push_back(std::to_string(this->unknown_channels_.size()));
output.push_back(",");
output.push_back("\"invalidated_channels_full_\":"); output.push_back(std::to_string(this->invalidated_channels_full_.calc_size()));
output.push_back(",");
output.push_back("\"channel_full_file_source_ids_\":"); output.push_back(std::to_string(this->channel_full_file_source_ids_.calc_size()));
output.push_back(",");
output.push_back("\"dialogs_for_discussion_\":"); output.push_back(std::to_string(this->dialogs_for_discussion_.size()));
output.push_back(",");
output.push_back("\"inactive_channel_ids_\":"); output.push_back(std::to_string(this->inactive_channel_ids_.size()));
output.push_back(",");
output.push_back("\"load_chat_from_database_queries_\":"); output.push_back(std::to_string(this->load_chat_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_chats_\":"); output.push_back(std::to_string(this->loaded_from_database_chats_.size()));
output.push_back(",");
output.push_back("\"unavailable_chat_fulls_\":"); output.push_back(std::to_string(this->unavailable_chat_fulls_.size()));
output.push_back(",");
output.push_back("\"load_channel_from_database_queries_\":"); output.push_back(std::to_string(this->load_channel_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_channels_\":"); output.push_back(std::to_string(this->loaded_from_database_channels_.size()));
output.push_back(",");
output.push_back("\"unavailable_channel_fulls_\":"); output.push_back(std::to_string(this->unavailable_channel_fulls_.size()));
output.push_back(",");
output.push_back("\"channel_messages_\":"); output.push_back(std::to_string(this->channel_messages_.size()));
output.push_back(",");
output.push_back("\"linked_channel_ids_\":"); output.push_back(std::to_string(this->linked_channel_ids_.calc_size()));
output.push_back(",");
output.push_back("\"restricted_channel_ids_\":"); output.push_back(std::to_string(this->restricted_channel_ids_.calc_size()));
}
} // namespace td } // namespace td

View File

@ -385,6 +385,8 @@ class ChatManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
struct Chat { struct Chat {
string title; string title;

View File

@ -222,4 +222,8 @@ void CommonDialogManager::on_get_common_dialogs(UserId user_id, int64 offset_cha
common_dialogs.total_count = total_count; common_dialogs.total_count = total_count;
} }
void CommonDialogManager::memory_stats(vector<string> &output) {
output.push_back("\"found_common_dialogs_\":"); output.push_back(std::to_string(this->found_common_dialogs_.size()));
}
} // namespace td } // namespace td

View File

@ -39,6 +39,8 @@ class CommonDialogManager final : public Actor {
std::pair<int32, vector<DialogId>> get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit, std::pair<int32, vector<DialogId>> get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit,
bool force, Promise<Unit> &&promise); bool force, Promise<Unit> &&promise);
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -58,4 +58,7 @@ void ConnectionStateManager::get_current_state(vector<td_api::object_ptr<td_api:
updates.push_back(get_update_connection_state_object(connection_state_)); updates.push_back(get_update_connection_state_object(connection_state_));
} }
void ConnectionStateManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -23,6 +23,8 @@ class ConnectionStateManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -610,4 +610,8 @@ FlatHashMap<string, unique_ptr<CountryInfoManager::CountryList>> CountryInfoMana
string CountryInfoManager::fragment_prefixes_str_; string CountryInfoManager::fragment_prefixes_str_;
vector<string> CountryInfoManager::fragment_prefixes_; vector<string> CountryInfoManager::fragment_prefixes_;
void CountryInfoManager::memory_stats(vector<string> &output) {
output.push_back("\"pending_load_country_queries_\":"); output.push_back(std::to_string(this->pending_load_country_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -47,6 +47,8 @@ class CountryInfoManager final : public Actor {
CountryInfoManager &operator=(CountryInfoManager &&) = delete; CountryInfoManager &operator=(CountryInfoManager &&) = delete;
~CountryInfoManager() final; ~CountryInfoManager() final;
void memory_stats(vector<string> &output);
private: private:
void start_up() final; void start_up() final;
void tear_down() final; void tear_down() final;

View File

@ -424,4 +424,10 @@ void DialogActionManager::clear_active_dialog_actions(DialogId dialog_id) {
} }
} }
void DialogActionManager::memory_stats(vector<string> &output) {
output.push_back("\"active_dialog_actions_\":"); output.push_back(std::to_string(this->active_dialog_actions_.size()));
output.push_back(",");
output.push_back("\"set_typing_query_\":"); output.push_back(std::to_string(this->set_typing_query_.size()));
}
} // namespace td } // namespace td

View File

@ -41,6 +41,8 @@ class DialogActionManager final : public Actor {
void clear_active_dialog_actions(DialogId dialog_id); void clear_active_dialog_actions(DialogId dialog_id);
void memory_stats(vector<string> &output);
private: private:
static constexpr double DIALOG_ACTION_TIMEOUT = 5.5; static constexpr double DIALOG_ACTION_TIMEOUT = 5.5;

View File

@ -2203,4 +2203,14 @@ void DialogFilterManager::get_current_state(vector<td_api::object_ptr<td_api::Up
} }
} }
void DialogFilterManager::memory_stats(vector<string> &output) {
output.push_back("\"server_dialog_filters_\":"); output.push_back(std::to_string(this->server_dialog_filters_.size()));
output.push_back(",");
output.push_back("\"dialog_filters_\":"); output.push_back(std::to_string(this->dialog_filters_.size()));
output.push_back(",");
output.push_back("\"dialog_filter_reload_queries_\":"); output.push_back(std::to_string(this->dialog_filter_reload_queries_.size()));
output.push_back(",");
output.push_back("\"recommended_dialog_filters_\":"); output.push_back(std::to_string(this->recommended_dialog_filters_.size()));
}
} // namespace td } // namespace td

View File

@ -128,6 +128,8 @@ class DialogFilterManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
static constexpr int32 DIALOG_FILTERS_CACHE_TIME = 86400; static constexpr int32 DIALOG_FILTERS_CACHE_TIME = 86400;

View File

@ -1131,4 +1131,10 @@ void DialogInviteLinkManager::delete_all_revoked_dialog_invite_links(DialogId di
->send(dialog_id, std::move(input_user)); ->send(dialog_id, std::move(input_user));
} }
void DialogInviteLinkManager::memory_stats(vector<string> &output) {
output.push_back("\"invite_link_infos_\":"); output.push_back(std::to_string(this->invite_link_infos_.size()));
output.push_back(",");
output.push_back("\"dialog_access_by_invite_link_\":"); output.push_back(std::to_string(this->dialog_access_by_invite_link_.size()));
}
} // namespace td } // namespace td

View File

@ -85,6 +85,8 @@ class DialogInviteLinkManager final : public Actor {
void delete_all_revoked_dialog_invite_links(DialogId dialog_id, UserId creator_user_id, Promise<Unit> &&promise); void delete_all_revoked_dialog_invite_links(DialogId dialog_id, UserId creator_user_id, Promise<Unit> &&promise);
void memory_stats(vector<string> &output);
private: private:
static constexpr size_t MAX_INVITE_LINK_TITLE_LENGTH = 32; // server side limit static constexpr size_t MAX_INVITE_LINK_TITLE_LENGTH = 32; // server side limit

View File

@ -2340,4 +2340,20 @@ void DialogManager::on_dismiss_suggested_action(SuggestedAction action, Result<U
set_promises(promises); set_promises(promises);
} }
void DialogManager::memory_stats(vector<string> &output) {
output.push_back("\"being_uploaded_dialog_photos_\":"); output.push_back(std::to_string(this->being_uploaded_dialog_photos_.size()));
output.push_back(",");
output.push_back("\"resolved_usernames_\":"); output.push_back(std::to_string(this->resolved_usernames_.calc_size()));
output.push_back(",");
output.push_back("\"inaccessible_resolved_usernames_\":"); output.push_back(std::to_string(this->inaccessible_resolved_usernames_.calc_size()));
output.push_back(",");
output.push_back("\"reload_voice_chat_on_search_usernames_\":"); output.push_back(std::to_string(this->reload_voice_chat_on_search_usernames_.size()));
output.push_back(",");
output.push_back("\"resolve_dialog_username_queries_\":"); output.push_back(std::to_string(this->resolve_dialog_username_queries_.size()));
output.push_back(",");
output.push_back("\"dialog_suggested_actions_\":"); output.push_back(std::to_string(this->dialog_suggested_actions_.size()));
output.push_back(",");
output.push_back("\"dismiss_suggested_action_queries_\":"); output.push_back(std::to_string(this->dismiss_suggested_action_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -227,6 +227,8 @@ class DialogManager final : public Actor {
void remove_dialog_suggested_action(SuggestedAction action); void remove_dialog_suggested_action(SuggestedAction action);
void memory_stats(vector<string> &output);
private: private:
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title

View File

@ -3004,4 +3004,18 @@ void DialogParticipantManager::get_current_state(vector<td_api::object_ptr<td_ap
} }
} }
void DialogParticipantManager::memory_stats(vector<string> &output) {
output.push_back("\"dialog_online_member_counts_\":"); output.push_back(std::to_string(this->dialog_online_member_counts_.size()));
output.push_back(",");
output.push_back("\"user_online_member_dialogs_\":"); output.push_back(std::to_string(this->user_online_member_dialogs_.size()));
output.push_back(",");
output.push_back("\"dialog_administrators_\":"); output.push_back(std::to_string(this->dialog_administrators_.size()));
output.push_back(",");
output.push_back("\"channel_participants_\":"); output.push_back(std::to_string(this->channel_participants_.size()));
output.push_back(",");
output.push_back("\"cached_channel_participants_\":"); output.push_back(std::to_string(this->cached_channel_participants_.size()));
output.push_back(",");
output.push_back("\"join_channel_queries_\":"); output.push_back(std::to_string(this->join_channel_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -152,6 +152,8 @@ class DialogParticipantManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
static constexpr int32 ONLINE_MEMBER_COUNT_CACHE_EXPIRE_TIME = 30 * 60; static constexpr int32 ONLINE_MEMBER_COUNT_CACHE_EXPIRE_TIME = 30 * 60;

View File

@ -13,6 +13,7 @@
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/VideoNotesManager.h" #include "td/telegram/VideoNotesManager.h"
#include "td/telegram/VideosManager.h" #include "td/telegram/VideosManager.h"
#include "td/telegram/Global.h"
#include "td/utils/algorithm.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); file_ids.push_back(file_id);
FileId thumbnail_file_id = [&] { if (!G()->get_option_boolean("disable_minithumbnails")) {
switch (type) { FileId thumbnail_file_id = [&] {
case Type::Animation: switch (type) {
return td->animations_manager_->get_animation_thumbnail_file_id(file_id); case Type::Animation:
case Type::Audio: return td->animations_manager_->get_animation_thumbnail_file_id(file_id);
return td->audios_manager_->get_audio_thumbnail_file_id(file_id); case Type::Audio:
case Type::General: return td->audios_manager_->get_audio_thumbnail_file_id(file_id);
return td->documents_manager_->get_document_thumbnail_file_id(file_id); case Type::General:
case Type::Video: return td->documents_manager_->get_document_thumbnail_file_id(file_id);
return td->videos_manager_->get_video_thumbnail_file_id(file_id); case Type::Video:
case Type::VideoNote: return td->videos_manager_->get_video_thumbnail_file_id(file_id);
return td->video_notes_manager_->get_video_note_thumbnail_file_id(file_id); case Type::VideoNote:
default: return td->video_notes_manager_->get_video_note_thumbnail_file_id(file_id);
return FileId(); 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 = [&] { FileId animated_thumbnail_file_id = [&] {

View File

@ -786,4 +786,8 @@ string DocumentsManager::get_document_search_text(FileId file_id) const {
return sb.as_cslice().str(); return sb.as_cslice().str();
} }
void DocumentsManager::memory_stats(vector<string> &output) {
output.push_back("\"documents_\":"); output.push_back(std::to_string(this->documents_.calc_size()));
}
} // namespace td } // namespace td

View File

@ -31,6 +31,7 @@ class Td;
class DocumentsManager { class DocumentsManager {
public: public:
void memory_stats(vector<string> &output);
explicit DocumentsManager(Td *td); explicit DocumentsManager(Td *td);
DocumentsManager(const DocumentsManager &) = delete; DocumentsManager(const DocumentsManager &) = delete;
DocumentsManager &operator=(const DocumentsManager &) = delete; DocumentsManager &operator=(const DocumentsManager &) = delete;

View File

@ -14,6 +14,8 @@
#include "td/utils/tl_helpers.h" #include "td/utils/tl_helpers.h"
#include "td/telegram/ConfigManager.h"
namespace td { namespace td {
template <class StorerT> template <class StorerT>
@ -66,13 +68,25 @@ FileId DocumentsManager::parse_document(ParserT &parser) {
has_thumbnail = true; has_thumbnail = true;
} }
if (has_file_name) { if (has_file_name) {
parse(document->file_name, parser); string tmp_filename;
parse(tmp_filename, parser);
if (G()->get_option_boolean("disable_document_filenames") &&
(document->mime_type.rfind("image/") == 0 || document->mime_type.rfind("video/") == 0 ||
document->mime_type.rfind("audio/") == 0)) {
document->file_name = "0";
} else {
document->file_name = tmp_filename;
}
} }
if (has_mime_type) { if (has_mime_type) {
parse(document->mime_type, parser); parse(document->mime_type, parser);
} }
if (has_minithumbnail) { if (has_minithumbnail) {
parse(document->minithumbnail, parser); string tmp_minithumbnail;
parse(tmp_minithumbnail, parser);
if (!G()->get_option_boolean("disable_minithumbnails")) {
document->minithumbnail = tmp_minithumbnail;
}
} }
if (has_thumbnail) { if (has_thumbnail) {
parse(document->thumbnail, parser); parse(document->thumbnail, parser);

View File

@ -839,4 +839,7 @@ void DownloadManager::Counters::parse(ParserT &parser) {
td::parse(downloaded_size, parser); td::parse(downloaded_size, parser);
} }
void DownloadManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -107,6 +107,8 @@ class DownloadManager : public Actor {
virtual void update_file_download_state(FileId internal_file_id, int64 downloaded_size, int64 size, virtual void update_file_download_state(FileId internal_file_id, int64 downloaded_size, int64 size,
int64 expected_size, bool is_paused) = 0; int64 expected_size, bool is_paused) = 0;
virtual void update_file_viewed(FileId file_id, FileSourceId file_source_id) = 0; virtual void update_file_viewed(FileId file_id, FileSourceId file_source_id) = 0;
void memory_stats(vector<string> &output);
}; };
} // namespace td } // namespace td

View File

@ -542,4 +542,8 @@ td_api::object_ptr<td_api::message> FileReferenceManager::get_message_object(Fil
return result; return result;
} }
void FileReferenceManager::memory_stats(vector<string> &output) {
output.push_back("\"nodes_\":"); output.push_back(std::to_string(this->nodes_.calc_size()));
}
} // namespace td } // namespace td

View File

@ -39,6 +39,7 @@ extern int VERBOSITY_NAME(file_references);
class FileReferenceManager final : public Actor { class FileReferenceManager final : public Actor {
public: public:
void memory_stats(vector<string> &output);
explicit FileReferenceManager(ActorShared<> parent); explicit FileReferenceManager(ActorShared<> parent);
FileReferenceManager(const FileReferenceManager &) = delete; FileReferenceManager(const FileReferenceManager &) = delete;
FileReferenceManager &operator=(const FileReferenceManager &) = delete; FileReferenceManager &operator=(const FileReferenceManager &) = delete;

View File

@ -1229,4 +1229,8 @@ void ForumTopicManager::on_topic_message_count_changed(DialogId dialog_id, Messa
} }
} }
void ForumTopicManager::memory_stats(vector<string> &output) {
output.push_back("\"dialog_topics_\":"); output.push_back(std::to_string(this->dialog_topics_.calc_size()));
}
} // namespace td } // namespace td

View File

@ -115,6 +115,8 @@ class ForumTopicManager final : public Actor {
void on_topic_message_count_changed(DialogId dialog_id, MessageId top_thread_message_id, int diff); void on_topic_message_count_changed(DialogId dialog_id, MessageId top_thread_message_id, int diff);
void memory_stats(vector<string> &output);
private: private:
static constexpr size_t MAX_FORUM_TOPIC_TITLE_LENGTH = 128; // server side limit for forum topic title static constexpr size_t MAX_FORUM_TOPIC_TITLE_LENGTH = 128; // server side limit for forum topic title

View File

@ -193,4 +193,7 @@ td_api::object_ptr<td_api::gameHighScores> GameManager::get_game_high_scores_obj
return result; return result;
} }
void GameManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -38,6 +38,8 @@ class GameManager final : public Actor {
td_api::object_ptr<td_api::gameHighScores> get_game_high_scores_object( td_api::object_ptr<td_api::gameHighScores> get_game_high_scores_object(
telegram_api::object_ptr<telegram_api::messages_highScores> &&high_scores); telegram_api::object_ptr<telegram_api::messages_highScores> &&high_scores);
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -162,6 +162,10 @@ bool Global::use_message_database() const {
return td_db_->use_message_database(); return td_db_->use_message_database();
} }
bool Global::use_custom_database_format() const {
return td_db_->use_custom_database_format();
}
int32 Global::get_retry_after(int32 error_code, Slice error_message) { int32 Global::get_retry_after(int32 error_code, Slice error_message) {
if (error_code != 429) { if (error_code != 429) {
return 0; return 0;

View File

@ -78,6 +78,7 @@ class StarManager;
class StateManager; class StateManager;
class StickersManager; class StickersManager;
class StorageManager; class StorageManager;
class MemoryManager;
class StoryManager; class StoryManager;
class Td; class Td;
class TdDb; class TdDb;
@ -116,6 +117,52 @@ class Global final : public ActorContext {
Status init(ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) TD_WARN_UNUSED_RESULT; Status init(ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) TD_WARN_UNUSED_RESULT;
static bool get_use_custom_database(const std::string &database_directory) {
auto s = get_database_directory_opts(database_directory);
size_t qmarkpos;
std::string token;
size_t find_start_index = 0;
while ((qmarkpos = s.find_first_of('&'), find_start_index) != std::string::npos) {
token = s.substr(find_start_index, qmarkpos - find_start_index);
find_start_index = qmarkpos;
if ((qmarkpos = token.find_first_of('=')) != std::string::npos) {
std::string propkey = token.substr(0, qmarkpos), propval = token.substr(qmarkpos + 1);
if (propkey == "use_custom_database_format" && propval == "true") {
return true;
}
}
}
return false;
}
static std::string get_database_directory_path(const std::string &database_directory) {
if (database_directory.empty()) {
return database_directory;
}
size_t qmarkpos;
if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
std::string path = database_directory.substr(0, qmarkpos),
opts = database_directory.substr(qmarkpos + 1);
return path;
} else {
return database_directory;
}
}
static std::string get_database_directory_opts(const std::string &database_directory) {
if (database_directory.empty()) {
return database_directory;
}
size_t qmarkpos;
if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
std::string path = database_directory.substr(0, qmarkpos),
opts = database_directory.substr(qmarkpos + 1);
return opts;
} else {
return "";
}
}
Slice get_dir() const; Slice get_dir() const;
Slice get_secure_files_dir() const { Slice get_secure_files_dir() const {
@ -498,6 +545,13 @@ class Global final : public ActorContext {
storage_manager_ = storage_manager; storage_manager_ = storage_manager;
} }
ActorId<MemoryManager> memory_manager() const {
return memory_manager_;
}
void set_memory_manager(ActorId<MemoryManager> memory_manager) {
memory_manager_ = memory_manager;
}
ActorId<StoryManager> story_manager() const { ActorId<StoryManager> story_manager() const {
return story_manager_; return story_manager_;
} }
@ -574,6 +628,8 @@ class Global final : public ActorContext {
bool use_message_database() const; bool use_message_database() const;
bool use_custom_database_format() const;
bool keep_media_order() const { bool keep_media_order() const {
return use_file_database(); return use_file_database();
} }
@ -718,6 +774,7 @@ class Global final : public ActorContext {
ActorId<StarManager> star_manager_; ActorId<StarManager> star_manager_;
ActorId<StickersManager> stickers_manager_; ActorId<StickersManager> stickers_manager_;
ActorId<StorageManager> storage_manager_; ActorId<StorageManager> storage_manager_;
ActorId<MemoryManager> memory_manager_;
ActorId<StoryManager> story_manager_; ActorId<StoryManager> story_manager_;
ActorId<ThemeManager> theme_manager_; ActorId<ThemeManager> theme_manager_;
ActorId<TimeZoneManager> time_zone_manager_; ActorId<TimeZoneManager> time_zone_manager_;

View File

@ -16,6 +16,7 @@
#include "td/telegram/DialogParticipantManager.h" #include "td/telegram/DialogParticipantManager.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/MessageId.h" #include "td/telegram/MessageId.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/MessageSender.h" #include "td/telegram/MessageSender.h"
#include "td/telegram/MessagesManager.h" #include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h" #include "td/telegram/misc.h"
@ -1164,7 +1165,7 @@ bool GroupCallManager::is_group_call_joined(InputGroupCallId input_group_call_id
} }
GroupCallId GroupCallManager::get_group_call_id(InputGroupCallId input_group_call_id, DialogId dialog_id) { GroupCallId GroupCallManager::get_group_call_id(InputGroupCallId input_group_call_id, DialogId dialog_id) {
if (td_->auth_manager_->is_bot() || !input_group_call_id.is_valid()) { if (G()->get_option_boolean("disable_group_calls") || td_->auth_manager_->is_bot() || !input_group_call_id.is_valid()) {
return GroupCallId(); return GroupCallId();
} }
return add_group_call(input_group_call_id, dialog_id)->group_call_id; return add_group_call(input_group_call_id, dialog_id)->group_call_id;
@ -4141,7 +4142,7 @@ void GroupCallManager::on_update_group_call_connection(string &&connection_param
} }
void GroupCallManager::on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id) { void GroupCallManager::on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id) {
if (td_->auth_manager_->is_bot()) { if (G()->get_option_boolean("disable_group_calls") || td_->auth_manager_->is_bot()) {
return; return;
} }
if (dialog_id != DialogId() && !dialog_id.is_valid()) { if (dialog_id != DialogId() && !dialog_id.is_valid()) {
@ -4849,21 +4850,48 @@ tl_object_ptr<td_api::updateGroupCallParticipant> GroupCallManager::get_update_g
void GroupCallManager::send_update_group_call(const GroupCall *group_call, const char *source) { void GroupCallManager::send_update_group_call(const GroupCall *group_call, const char *source) {
LOG(INFO) << "Send update about " << group_call->group_call_id << " from " << source; LOG(INFO) << "Send update about " << group_call->group_call_id << " from " << source;
if (G()->get_option_boolean("disable_group_calls")) {
return;
}
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
get_update_group_call_object(group_call, get_recent_speakers(group_call, true))); get_update_group_call_object(group_call, get_recent_speakers(group_call, true)));
} }
void GroupCallManager::send_update_group_call_participant(GroupCallId group_call_id, void GroupCallManager::send_update_group_call_participant(GroupCallId group_call_id,
const GroupCallParticipant &participant, const char *source) { const GroupCallParticipant &participant, const char *source) {
if (G()->get_option_boolean("disable_group_calls")) {
return;
}
LOG(INFO) << "Send update about " << participant << " in " << group_call_id << " from " << source; LOG(INFO) << "Send update about " << participant << " in " << group_call_id << " from " << source;
send_closure(G()->td(), &Td::send_update, get_update_group_call_participant_object(group_call_id, participant)); send_closure(G()->td(), &Td::send_update, get_update_group_call_participant_object(group_call_id, participant));
} }
void GroupCallManager::send_update_group_call_participant(InputGroupCallId input_group_call_id, void GroupCallManager::send_update_group_call_participant(InputGroupCallId input_group_call_id,
const GroupCallParticipant &participant, const char *source) { const GroupCallParticipant &participant, const char *source) {
if (G()->get_option_boolean("disable_group_calls")) {
return;
}
auto group_call = get_group_call(input_group_call_id); auto group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited); CHECK(group_call != nullptr && group_call->is_inited);
send_update_group_call_participant(group_call->group_call_id, participant, source); send_update_group_call_participant(group_call->group_call_id, participant, source);
} }
void GroupCallManager::memory_stats(vector<string> &output) {
output.push_back("\"input_group_call_ids_\":"); output.push_back(std::to_string(this->input_group_call_ids_.size()));
output.push_back(",");
output.push_back("\"group_calls_\":"); output.push_back(std::to_string(this->group_calls_.size()));
output.push_back(",");
output.push_back("\"group_call_participants_\":"); output.push_back(std::to_string(this->group_call_participants_.size()));
output.push_back(",");
output.push_back("\"participant_id_to_group_call_id_\":"); output.push_back(std::to_string(this->participant_id_to_group_call_id_.size()));
output.push_back(",");
output.push_back("\"group_call_recent_speakers_\":"); output.push_back(std::to_string(this->group_call_recent_speakers_.size()));
output.push_back(",");
output.push_back("\"load_group_call_queries_\":"); output.push_back(std::to_string(this->load_group_call_queries_.size()));
output.push_back(",");
output.push_back("\"pending_join_requests_\":"); output.push_back(std::to_string(this->pending_join_requests_.size()));
output.push_back(",");
output.push_back("\"pending_join_presentation_requests_\":"); output.push_back(std::to_string(this->pending_join_presentation_requests_.size()));
}
} // namespace td } // namespace td

View File

@ -32,6 +32,7 @@ class Td;
class GroupCallManager final : public Actor { class GroupCallManager final : public Actor {
public: public:
void memory_stats(vector<string> &output);
GroupCallManager(Td *td, ActorShared<> parent); GroupCallManager(Td *td, ActorShared<> parent);
GroupCallManager(const GroupCallManager &) = delete; GroupCallManager(const GroupCallManager &) = delete;
GroupCallManager &operator=(const GroupCallManager &) = delete; GroupCallManager &operator=(const GroupCallManager &) = delete;
@ -39,6 +40,8 @@ class GroupCallManager final : public Actor {
GroupCallManager &operator=(GroupCallManager &&) = delete; GroupCallManager &operator=(GroupCallManager &&) = delete;
~GroupCallManager() final; ~GroupCallManager() final;
DialogId get_group_call_participant_id(const td_api::object_ptr<td_api::MessageSender> &message_sender);
bool is_group_call_being_joined(InputGroupCallId input_group_call_id) const; bool is_group_call_being_joined(InputGroupCallId input_group_call_id) const;
bool is_group_call_joined(InputGroupCallId input_group_call_id) const; bool is_group_call_joined(InputGroupCallId input_group_call_id) const;

View File

@ -384,4 +384,7 @@ void InlineMessageManager::get_inline_game_high_scores(const string &inline_mess
->send(std::move(input_bot_inline_message_id), std::move(input_user)); ->send(std::move(input_bot_inline_message_id), std::move(input_user));
} }
void InlineMessageManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -51,6 +51,8 @@ class InlineMessageManager final : public Actor {
void get_inline_game_high_scores(const string &inline_message_id, UserId user_id, void get_inline_game_high_scores(const string &inline_message_id, UserId user_id,
Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise); Promise<td_api::object_ptr<td_api::gameHighScores>> &&promise);
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -15,6 +15,7 @@
#include "td/telegram/Contact.h" #include "td/telegram/Contact.h"
#include "td/telegram/DialogManager.h" #include "td/telegram/DialogManager.h"
#include "td/telegram/Document.h" #include "td/telegram/Document.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/DocumentsManager.h" #include "td/telegram/DocumentsManager.h"
#include "td/telegram/files/FileManager.h" #include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileType.h" #include "td/telegram/files/FileType.h"
@ -2240,4 +2241,14 @@ void InlineQueriesManager::remove_recent_inline_bot(UserId bot_user_id, Promise<
promise.set_value(Unit()); promise.set_value(Unit());
} }
void InlineQueriesManager::memory_stats(vector<string> &output) {
output.push_back("\"recently_used_bot_user_ids_\":"); output.push_back(std::to_string(this->recently_used_bot_user_ids_.size()));
output.push_back(",");
output.push_back("\"inline_query_results_\":"); output.push_back(std::to_string(this->inline_query_results_.size()));
output.push_back(",");
output.push_back("\"inline_message_contents_\":"); output.push_back(std::to_string(this->inline_message_contents_.size()));
output.push_back(",");
output.push_back("\"query_id_to_bot_user_id_\":"); output.push_back(std::to_string(this->query_id_to_bot_user_id_.size()));
}
} // namespace td } // namespace td

View File

@ -36,6 +36,7 @@ class Game;
class InlineQueriesManager final : public Actor { class InlineQueriesManager final : public Actor {
public: public:
void memory_stats(vector<string> &output);
InlineQueriesManager(Td *td, ActorShared<> parent); InlineQueriesManager(Td *td, ActorShared<> parent);
void after_get_difference(); void after_get_difference();

View File

@ -3334,4 +3334,12 @@ Result<MessageLinkInfo> LinkManager::get_message_link_info(Slice url) {
return std::move(info); return std::move(info);
} }
void LinkManager::memory_stats(vector<string> &output) {
output.push_back("\"autologin_domains_\":"); output.push_back(std::to_string(this->autologin_domains_.size()));
output.push_back(",");
output.push_back("\"url_auth_domains_\":"); output.push_back(std::to_string(this->url_auth_domains_.size()));
output.push_back(",");
output.push_back("\"whitelisted_domains_\":"); output.push_back(std::to_string(this->whitelisted_domains_.size()));
}
} // namespace td } // namespace td

View File

@ -116,6 +116,8 @@ class LinkManager final : public Actor {
static Result<MessageLinkInfo> get_message_link_info(Slice url); static Result<MessageLinkInfo> get_message_link_info(Slice url);
void memory_stats(vector<string> &output);
private: private:
void start_up() final; void start_up() final;

View File

@ -0,0 +1,250 @@
//
// Copyright Andrea Cavalli (nospam@warp.ovh) 2020
//
// 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/MemoryManager.h"
#include "td/telegram/td_api.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/ConfigManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/AccountManager.h"
#include "td/telegram/AttachMenuManager.h"
#include "td/telegram/AutosaveManager.h"
#include "td/telegram/BoostManager.h"
#include "td/telegram/BotInfoManager.h"
#include "td/telegram/BusinessConnectionManager.h"
#include "td/telegram/BusinessManager.h"
#include "td/telegram/CallbackQueriesManager.h"
#include "td/telegram/ChannelRecommendationManager.h"
#include "td/telegram/ChatManager.h"
#include "td/telegram/CommonDialogManager.h"
#include "td/telegram/ConnectionStateManager.h"
#include "td/telegram/CountryInfoManager.h"
#include "td/telegram/DialogActionManager.h"
#include "td/telegram/DialogFilterManager.h"
#include "td/telegram/DialogInviteLinkManager.h"
#include "td/telegram/DialogManager.h"
#include "td/telegram/DialogParticipantManager.h"
#include "td/telegram/DownloadManager.h"
#include "td/telegram/ForumTopicManager.h"
#include "td/telegram/GameManager.h"
#include "td/telegram/InlineMessageManager.h"
#include "td/telegram/LinkManager.h"
#include "td/telegram/MessageImportManager.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/OnlineManager.h"
#include "td/telegram/OptionManager.h"
#include "td/telegram/PeopleNearbyManager.h"
#include "td/telegram/PrivacyManager.h"
#include "td/telegram/PromoDataManager.h"
#include "td/telegram/QuickReplyManager.h"
#include "td/telegram/ReactionManager.h"
#include "td/telegram/SavedMessagesManager.h"
#include "td/telegram/SponsoredMessageManager.h"
#include "td/telegram/StarManager.h"
#include "td/telegram/StatisticsManager.h"
#include "td/telegram/StoryManager.h"
#include "td/telegram/TermsOfServiceManager.h"
#include "td/telegram/ThemeManager.h"
#include "td/telegram/TimeZoneManager.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/TranscriptionManager.h"
#include "td/telegram/TranslationManager.h"
#include "td/telegram/UpdatesManager.h"
#include "td/telegram/UserManager.h"
#include "td/telegram/VoiceNotesManager.h"
#include <algorithm>
#include <numeric>
#include "td/telegram/AnimationsManager.h"
#include "td/telegram/AudiosManager.h"
#include "td/telegram/BackgroundManager.h"
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/InlineQueriesManager.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/PollManager.h"
#include "td/telegram/StickersManager.h"
#include "td/telegram/VideoNotesManager.h"
#include "td/telegram/VideosManager.h"
#include "td/telegram/WebPagesManager.h"
namespace td {
tl_object_ptr<td_api::memoryStatistics> MemoryStats::get_memory_statistics_object() const {
return make_tl_object<td_api::memoryStatistics>(debug);
}
MemoryManager::MemoryManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
}
void MemoryManager::start_up() {
}
void MemoryManager::tear_down() {
parent_.reset();
}
void MemoryManager::get_memory_stats(bool full, Promise<MemoryStats> promise) const {
vector<string> output;
output.push_back("{");
output.push_back("\"memory_stats\":{");
this->print_managers_memory_stats(output);
output.push_back("}");
output.push_back("}");
string s;
s = accumulate(output.begin(), output.end(), s);
auto value = MemoryStats(s);
promise.set_value(std::move(value));
}
void MemoryManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
if (td_->auth_manager_->is_bot()) {
return;
}
// Never return updates
}
void MemoryManager::print_managers_memory_stats(vector<string> &output) const {
output.push_back("\"file_manager_\":{"); td_->file_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"business_connection_manager_\":{"); td_->business_connection_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"channel_recommendation_manager_\":{"); td_->channel_recommendation_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"chat_manager_\":{"); td_->chat_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"connection_state_manager_\":{"); td_->connection_state_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"inline_message_manager_\":{"); td_->inline_message_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"online_manager_\":{"); td_->online_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"promo_data_manager_\":{"); td_->promo_data_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"star_manager_\":{"); td_->star_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"terms_of_service_manager_\":{"); td_->terms_of_service_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"user_manager_\":{"); td_->user_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"account_manager_\":{"); td_->account_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"animations_manager_\":{"); td_->animations_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"attach_menu_manager_\":{"); td_->attach_menu_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"audios_manager_\":{"); td_->audios_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"auth_manager_\":{"); td_->auth_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"autosave_manager_\":{"); td_->autosave_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"background_manager_\":{"); td_->background_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"boost_manager_\":{"); td_->boost_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"bot_info_manager_\":{"); td_->bot_info_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"business_manager_\":{"); td_->business_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"callback_queries_manager_\":{"); td_->callback_queries_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"common_dialog_manager_\":{"); td_->common_dialog_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"country_info_manager_\":{"); td_->country_info_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"dialog_action_manager_\":{"); td_->dialog_action_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"dialog_filter_manager_\":{"); td_->dialog_filter_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"dialog_invite_link_manager_\":{"); td_->dialog_invite_link_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"dialog_manager_\":{"); td_->dialog_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"dialog_participant_manager_\":{"); td_->dialog_participant_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"documents_manager_\":{"); td_->documents_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"download_manager_\":{"); td_->download_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"file_reference_manager_\":{"); td_->file_reference_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"forum_topic_manager_\":{"); td_->forum_topic_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"game_manager_\":{"); td_->game_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"group_call_manager_\":{"); td_->group_call_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"inline_queries_manager_\":{"); td_->inline_queries_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"link_manager_\":{"); td_->link_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"message_import_manager_\":{"); td_->message_import_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"messages_manager_\":{"); td_->messages_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"notification_manager_\":{"); td_->notification_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"notification_settings_manager_\":{"); td_->notification_settings_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"option_manager_\":{"); td_->option_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"people_nearby_manager_\":{"); td_->people_nearby_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"poll_manager_\":{"); td_->poll_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"privacy_manager_\":{"); td_->privacy_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"quick_reply_manager_\":{"); td_->quick_reply_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"reaction_manager_\":{"); td_->reaction_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"saved_messages_manager_\":{"); td_->saved_messages_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"sponsored_message_manager_\":{"); td_->sponsored_message_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"statistics_manager_\":{"); td_->statistics_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"stickers_manager_\":{"); td_->stickers_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"story_manager_\":{"); td_->story_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"theme_manager_\":{"); td_->theme_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"time_zone_manager_\":{"); td_->time_zone_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"top_dialog_manager_\":{"); td_->top_dialog_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"transcription_manager_\":{"); td_->transcription_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"translation_manager_\":{"); td_->translation_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"updates_manager_\":{"); td_->updates_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"video_notes_manager_\":{"); td_->video_notes_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"videos_manager_\":{"); td_->videos_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"voice_notes_manager_\":{"); td_->voice_notes_manager_->memory_stats(output); output.push_back("}");
output.push_back(",");
output.push_back("\"web_pages_manager_\":{"); td_->web_pages_manager_->memory_stats(output); output.push_back("}");
}
} // namespace td

View File

@ -0,0 +1,65 @@
//
// Copyright Andrea Cavalli (nospam@warp.ovh) 2020
//
// 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/actor/actor.h"
#include "td/actor/MultiPromise.h"
#include "td/actor/PromiseFuture.h"
#include "td/actor/Timeout.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/Photo.h"
#include "td/telegram/SecretInputMedia.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Hints.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include <memory>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
namespace td {
class Td;
struct MemoryStats {
string debug;
MemoryStats() = default;
explicit MemoryStats(string debug) : debug(std::move(debug)) {
}
tl_object_ptr<td_api::memoryStatistics> get_memory_statistics_object() const;
};
class MemoryManager : public Actor {
public:
MemoryManager(Td *td, ActorShared<> parent);
void get_memory_stats(bool full, Promise<MemoryStats> promise) const;
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
void start_up() override;
void tear_down() override;
void print_managers_memory_stats(vector<string> &output) const;
Td *td_;
ActorShared<> parent_;
};
} // namespace td

View File

@ -8282,6 +8282,7 @@ void update_message_content_file_id_remotes(MessageContent *content, const vecto
} }
FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td) { FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td) {
if (!G()->get_option_boolean("disable_minithumbnails")) {
switch (content->get_type()) { switch (content->get_type()) {
case MessageContentType::Animation: case MessageContentType::Animation:
return td->animations_manager_->get_animation_thumbnail_file_id( return td->animations_manager_->get_animation_thumbnail_file_id(
@ -8310,6 +8311,7 @@ FileId get_message_content_thumbnail_file_id(const MessageContent *content, cons
return FileId(); return FileId();
default: default:
break; break;
}
} }
return FileId(); return FileId();
} }

View File

@ -571,4 +571,12 @@ void MessageImportManager::on_imported_message_attachments_uploaded(int64 random
td_->create_handler<StartImportHistoryQuery>(std::move(promise))->send(dialog_id, pending_message_import->import_id); td_->create_handler<StartImportHistoryQuery>(std::move(promise))->send(dialog_id, pending_message_import->import_id);
} }
void MessageImportManager::memory_stats(vector<string> &output) {
output.push_back("\"being_uploaded_imported_messages_\":"); output.push_back(std::to_string(this->being_uploaded_imported_messages_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_imported_message_attachments_\":"); output.push_back(std::to_string(this->being_uploaded_imported_message_attachments_.size()));
output.push_back(",");
output.push_back("\"pending_message_imports_\":"); output.push_back(std::to_string(this->pending_message_imports_.size()));
}
} // namespace td } // namespace td

View File

@ -40,6 +40,8 @@ class MessageImportManager final : public Actor {
void start_import_messages(DialogId dialog_id, int64 import_id, vector<FileId> &&attached_file_ids, void start_import_messages(DialogId dialog_id, int64 import_id, vector<FileId> &&attached_file_ids,
Promise<Unit> &&promise); Promise<Unit> &&promise);
void memory_stats(vector<string> &output);
private: private:
void tear_down() final; void tear_down() final;

View File

@ -46,6 +46,7 @@
#include "td/telegram/LinkManager.h" #include "td/telegram/LinkManager.h"
#include "td/telegram/Location.h" #include "td/telegram/Location.h"
#include "td/telegram/logevent/LogEvent.h" #include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/MessageContent.h" #include "td/telegram/MessageContent.h"
#include "td/telegram/MessageDb.h" #include "td/telegram/MessageDb.h"
#include "td/telegram/MessageEntity.h" #include "td/telegram/MessageEntity.h"
@ -5949,6 +5950,7 @@ void MessagesManager::update_message_reply_count(Dialog *d, MessageId message_id
} }
} }
bool MessagesManager::have_dialog_scheduled_messages_in_memory(const Dialog *d) { bool MessagesManager::have_dialog_scheduled_messages_in_memory(const Dialog *d) {
return d->scheduled_messages != nullptr && !d->scheduled_messages->scheduled_messages_.empty(); return d->scheduled_messages != nullptr && !d->scheduled_messages->scheduled_messages_.empty();
} }
@ -9664,6 +9666,9 @@ void MessagesManager::on_get_recent_locations(DialogId dialog_id, int32 limit, i
} }
void MessagesManager::delete_messages_from_updates(const vector<MessageId> &message_ids, bool is_permanent) { void MessagesManager::delete_messages_from_updates(const vector<MessageId> &message_ids, bool is_permanent) {
if (G()->get_option_boolean("ignore_server_deletes_and_reads", false)) {
return;
}
FlatHashMap<DialogId, vector<int64>, DialogIdHash> deleted_message_ids; FlatHashMap<DialogId, vector<int64>, DialogIdHash> deleted_message_ids;
FlatHashMap<DialogId, bool, DialogIdHash> need_update_dialog_pos; FlatHashMap<DialogId, bool, DialogIdHash> need_update_dialog_pos;
vector<unique_ptr<Message>> deleted_messages; vector<unique_ptr<Message>> deleted_messages;
@ -11252,6 +11257,9 @@ void MessagesManager::read_all_dialog_reactions_on_server(DialogId dialog_id, ui
} }
void MessagesManager::read_message_content_from_updates(MessageId message_id, int32 read_date) { void MessagesManager::read_message_content_from_updates(MessageId message_id, int32 read_date) {
if (G()->get_option_boolean("ignore_server_deletes_and_reads", false)) {
return;
}
if (!message_id.is_valid() || !message_id.is_server()) { if (!message_id.is_valid() || !message_id.is_server()) {
LOG(ERROR) << "Incoming update tries to read content of " << message_id; LOG(ERROR) << "Incoming update tries to read content of " << message_id;
return; return;
@ -15023,7 +15031,8 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<te
} }
bool MessagesManager::is_message_unload_enabled() const { bool MessagesManager::is_message_unload_enabled() const {
return G()->use_message_database() || td_->auth_manager_->is_bot(); auto has_custom_unload_time = G()->have_option("message_unload_delay");
return G()->use_message_database() || td_->auth_manager_->is_bot() || has_custom_unload_time;
} }
bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) const { bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) const {
@ -15548,7 +15557,9 @@ void MessagesManager::on_message_deleted(Dialog *d, Message *m, bool is_permanen
case DialogType::User: case DialogType::User:
case DialogType::Chat: case DialogType::Chat:
if (m->message_id.is_server()) { if (m->message_id.is_server()) {
message_id_to_dialog_id_.erase(m->message_id); if (!G()->get_option_boolean("ignore_server_deletes_and_reads", false)) {
message_id_to_dialog_id_.erase(m->message_id);
}
} }
break; break;
case DialogType::Channel: case DialogType::Channel:
@ -29072,6 +29083,10 @@ void MessagesManager::send_update_chat_last_message_impl(const Dialog *d, const
return; return;
} }
if (G()->get_option_boolean("ignore_update_chat_last_message")) {
return;
}
CHECK(d != nullptr); CHECK(d != nullptr);
LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_last_message from " LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_last_message from "
<< source; << source;
@ -29216,10 +29231,12 @@ void MessagesManager::send_update_chat_read_inbox(const Dialog *d, bool force, c
LOG(INFO) << "Send updateChatReadInbox in " << d->dialog_id << "(" LOG(INFO) << "Send updateChatReadInbox in " << d->dialog_id << "("
<< td_->dialog_manager_->get_dialog_title(d->dialog_id) << ") to " << d->server_unread_count << " + " << td_->dialog_manager_->get_dialog_title(d->dialog_id) << ") to " << d->server_unread_count << " + "
<< d->local_unread_count << " from " << source; << d->local_unread_count << " from " << source;
if (!G()->get_option_boolean("ignore_update_chat_read_inbox")) {
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
td_api::make_object<td_api::updateChatReadInbox>( td_api::make_object<td_api::updateChatReadInbox>(
get_chat_id_object(d->dialog_id, "updateChatReadInbox"), d->last_read_inbox_message_id.get(), get_chat_id_object(d->dialog_id, "updateChatReadInbox"), d->last_read_inbox_message_id.get(),
d->server_unread_count + d->local_unread_count)); d->server_unread_count + d->local_unread_count));
}
} }
} }
@ -38526,6 +38543,10 @@ void MessagesManager::suffix_load_query_ready(DialogId dialog_id) {
LOG(INFO) << "Finished suffix load query in " << dialog_id; LOG(INFO) << "Finished suffix load query in " << dialog_id;
auto *d = get_dialog(dialog_id); auto *d = get_dialog(dialog_id);
if (d == nullptr) {
LOG(ERROR) << "Unknown dialog " << dialog_id;
return;
}
bool is_unchanged = queries->suffix_load_first_message_id_ == queries->suffix_load_query_message_id_; bool is_unchanged = queries->suffix_load_first_message_id_ == queries->suffix_load_query_message_id_;
suffix_load_update_first_message_id(d, queries); suffix_load_update_first_message_id(d, queries);
if (is_unchanged && queries->suffix_load_first_message_id_ == queries->suffix_load_query_message_id_) { if (is_unchanged && queries->suffix_load_first_message_id_ == queries->suffix_load_query_message_id_) {
@ -38800,7 +38821,10 @@ void MessagesManager::set_sponsored_dialog(DialogId dialog_id, DialogSource sour
CHECK(sponsored_dialog_id_.is_valid()); CHECK(sponsored_dialog_id_.is_valid());
sponsored_dialog_source_ = std::move(source); sponsored_dialog_source_ = std::move(source);
const Dialog *d = get_dialog(sponsored_dialog_id_); const Dialog *d = get_dialog(sponsored_dialog_id_);
CHECK(d != nullptr); if (d == nullptr) {
LOG(ERROR) << "Unknown dialog " << dialog_id;
return;
}
send_update_chat_position(DialogListId(FolderId::main()), d, "set_sponsored_dialog"); send_update_chat_position(DialogListId(FolderId::main()), d, "set_sponsored_dialog");
save_sponsored_dialog(); save_sponsored_dialog();
} }
@ -38810,7 +38834,10 @@ void MessagesManager::set_sponsored_dialog(DialogId dialog_id, DialogSource sour
bool need_update_total_chat_count = false; bool need_update_total_chat_count = false;
if (sponsored_dialog_id_.is_valid()) { if (sponsored_dialog_id_.is_valid()) {
const Dialog *d = get_dialog(sponsored_dialog_id_); const Dialog *d = get_dialog(sponsored_dialog_id_);
CHECK(d != nullptr); if (d == nullptr) {
LOG(ERROR) << "Unknown dialog " << dialog_id;
return;
}
bool was_sponsored = is_dialog_sponsored(d); bool was_sponsored = is_dialog_sponsored(d);
sponsored_dialog_id_ = DialogId(); sponsored_dialog_id_ = DialogId();
sponsored_dialog_source_ = DialogSource(); sponsored_dialog_source_ = DialogSource();
@ -38823,7 +38850,10 @@ void MessagesManager::set_sponsored_dialog(DialogId dialog_id, DialogSource sour
if (dialog_id.is_valid()) { if (dialog_id.is_valid()) {
force_create_dialog(dialog_id, "set_sponsored_dialog_id"); force_create_dialog(dialog_id, "set_sponsored_dialog_id");
const Dialog *d = get_dialog(dialog_id); const Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr); if (d == nullptr) {
LOG(ERROR) << "Unknown dialog " << dialog_id;
return;
}
add_sponsored_dialog(d, std::move(source)); add_sponsored_dialog(d, std::move(source));
if (is_dialog_sponsored(d)) { if (is_dialog_sponsored(d)) {
need_update_total_chat_count = !need_update_total_chat_count; need_update_total_chat_count = !need_update_total_chat_count;
@ -38952,4 +38982,146 @@ void MessagesManager::get_message_file_search_text(MessageFullId message_full_id
return promise.set_error(Status::Error(200, "File not found")); return promise.set_error(Status::Error(200, "File not found"));
} }
void MessagesManager::memory_stats(vector<string> &output) {
output.push_back("\"being_uploaded_files_\":"); output.push_back(std::to_string(this->being_uploaded_files_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_thumbnails_\":"); output.push_back(std::to_string(this->being_uploaded_thumbnails_.size()));
output.push_back(",");
output.push_back("\"being_loaded_secret_thumbnails_\":"); output.push_back(std::to_string(this->being_loaded_secret_thumbnails_.size()));
output.push_back(",");
output.push_back("\"being_sent_messages_\":"); output.push_back(std::to_string(this->being_sent_messages_.size()));
output.push_back(",");
output.push_back("\"update_message_ids_\":"); output.push_back(std::to_string(this->update_message_ids_.size()));
output.push_back(",");
output.push_back("\"pending_message_group_sends_\":"); output.push_back(std::to_string(this->pending_message_group_sends_.size()));
output.push_back(",");
output.push_back("\"pending_paid_media_group_sends_\":"); output.push_back(std::to_string(this->pending_paid_media_group_sends_.size()));
output.push_back(",");
output.push_back("\"message_id_to_dialog_id_\":"); output.push_back(std::to_string(this->message_id_to_dialog_id_.calc_size()));
output.push_back(",");
output.push_back("\"last_clear_history_message_id_to_dialog_id_\":"); output.push_back(std::to_string(this->last_clear_history_message_id_to_dialog_id_.size()));
output.push_back(",");
output.push_back("\"pending_created_dialogs_\":"); output.push_back(std::to_string(this->pending_created_dialogs_.size()));
output.push_back(",");
output.push_back("\"dialogs_\":"); output.push_back(std::to_string(this->dialogs_.calc_size()));
output.push_back(",");
output.push_back("\"loaded_dialogs_\":"); output.push_back(std::to_string(this->loaded_dialogs_.size()));
output.push_back(",");
output.push_back("\"failed_to_load_dialogs_\":"); output.push_back(std::to_string(this->failed_to_load_dialogs_.size()));
output.push_back(",");
output.push_back("\"postponed_chat_read_inbox_updates_\":"); output.push_back(std::to_string(this->postponed_chat_read_inbox_updates_.size()));
output.push_back(",");
output.push_back("\"search_public_dialogs_queries_\":"); output.push_back(std::to_string(this->search_public_dialogs_queries_.size()));
output.push_back(",");
output.push_back("\"found_public_dialogs_\":"); output.push_back(std::to_string(this->found_public_dialogs_.size()));
output.push_back(",");
output.push_back("\"found_on_server_dialogs_\":"); output.push_back(std::to_string(this->found_on_server_dialogs_.size()));
output.push_back(",");
output.push_back("\"found_dialog_messages_\":"); output.push_back(std::to_string(this->found_dialog_messages_.size()));
output.push_back(",");
output.push_back("\"found_dialog_messages_dialog_id_\":"); output.push_back(std::to_string(this->found_dialog_messages_dialog_id_.size()));
output.push_back(",");
output.push_back("\"get_dialog_queries_\":"); output.push_back(std::to_string(this->get_dialog_queries_.size()));
output.push_back(",");
output.push_back("\"get_dialog_query_log_event_id_\":"); output.push_back(std::to_string(this->get_dialog_query_log_event_id_.size()));
output.push_back(",");
output.push_back("\"replied_by_yet_unsent_messages_\":"); output.push_back(std::to_string(this->replied_by_yet_unsent_messages_.size()));
output.push_back(",");
output.push_back("\"replied_yet_unsent_messages_\":"); output.push_back(std::to_string(this->replied_yet_unsent_messages_.size()));
output.push_back(",");
output.push_back("\"message_to_replied_media_timestamp_messages_\":"); output.push_back(std::to_string(this->message_to_replied_media_timestamp_messages_.size()));
output.push_back(",");
output.push_back("\"story_to_replied_media_timestamp_messages_\":"); output.push_back(std::to_string(this->story_to_replied_media_timestamp_messages_.size()));
output.push_back(",");
output.push_back("\"notification_group_id_to_dialog_id_\":"); output.push_back(std::to_string(this->notification_group_id_to_dialog_id_.size()));
output.push_back(",");
output.push_back("\"active_get_channel_differences_\":"); output.push_back(std::to_string(this->active_get_channel_differences_.size()));
output.push_back(",");
output.push_back("\"get_channel_difference_to_log_event_id_\":"); output.push_back(std::to_string(this->get_channel_difference_to_log_event_id_.size()));
output.push_back(",");
output.push_back("\"channel_get_difference_retry_timeouts_\":"); output.push_back(std::to_string(this->channel_get_difference_retry_timeouts_.size()));
output.push_back(",");
output.push_back("\"postponed_channel_updates_\":"); output.push_back(std::to_string(this->postponed_channel_updates_.size()));
output.push_back(",");
output.push_back("\"is_channel_difference_finished_\":"); output.push_back(std::to_string(this->is_channel_difference_finished_.size()));
output.push_back(",");
output.push_back("\"expected_channel_pts_\":"); output.push_back(std::to_string(this->expected_channel_pts_.size()));
output.push_back(",");
output.push_back("\"expected_channel_max_message_id_\":"); output.push_back(std::to_string(this->expected_channel_max_message_id_.size()));
output.push_back(",");
output.push_back("\"active_live_location_message_full_ids_\":"); output.push_back(std::to_string(this->active_live_location_message_full_ids_.size()));
output.push_back(",");
output.push_back("\"load_active_live_location_messages_queries_\":"); output.push_back(std::to_string(this->load_active_live_location_messages_queries_.size()));
output.push_back(",");
output.push_back("\"load_scheduled_messages_from_database_queries_\":"); output.push_back(std::to_string(this->load_scheduled_messages_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"get_dialogs_tasks_\":"); output.push_back(std::to_string(this->get_dialogs_tasks_.size()));
output.push_back(",");
output.push_back("\"pending_on_get_dialogs_\":"); output.push_back(std::to_string(this->pending_on_get_dialogs_.size()));
output.push_back(",");
output.push_back("\"pending_channel_on_get_dialogs_\":"); output.push_back(std::to_string(this->pending_channel_on_get_dialogs_.size()));
output.push_back(",");
output.push_back("\"run_after_get_channel_difference_\":"); output.push_back(std::to_string(this->run_after_get_channel_difference_.size()));
output.push_back(",");
output.push_back("\"pending_secret_message_ids_\":"); output.push_back(std::to_string(this->pending_secret_message_ids_.size()));
output.push_back(",");
output.push_back("\"pending_add_dialog_dependent_dialogs_\":"); output.push_back(std::to_string(this->pending_add_dialog_dependent_dialogs_.size()));
output.push_back(",");
output.push_back("\"pending_add_dialog_data_\":"); output.push_back(std::to_string(this->pending_add_dialog_data_.size()));
output.push_back(",");
output.push_back("\"pending_add_default_join_group_call_as_dialog_id_\":"); output.push_back(std::to_string(this->pending_add_default_join_group_call_as_dialog_id_.size()));
output.push_back(",");
output.push_back("\"pending_add_default_send_message_as_dialog_id_\":"); output.push_back(std::to_string(this->pending_add_default_send_message_as_dialog_id_.size()));
output.push_back(",");
output.push_back("\"dialog_bot_command_message_ids_\":"); output.push_back(std::to_string(this->dialog_bot_command_message_ids_.size()));
output.push_back(",");
output.push_back("\"viewed_live_location_tasks_\":"); output.push_back(std::to_string(this->viewed_live_location_tasks_.size()));
output.push_back(",");
output.push_back("\"pending_viewed_live_locations_\":"); output.push_back(std::to_string(this->pending_viewed_live_locations_.size()));
output.push_back(",");
output.push_back("\"yet_unsent_media_queues_\":"); output.push_back(std::to_string(this->yet_unsent_media_queues_.size()));
output.push_back(",");
output.push_back("\"message_full_id_to_file_source_id_\":"); output.push_back(std::to_string(this->message_full_id_to_file_source_id_.calc_size()));
output.push_back(",");
output.push_back("\"last_outgoing_forwarded_message_date_\":"); output.push_back(std::to_string(this->last_outgoing_forwarded_message_date_.size()));
output.push_back(",");
output.push_back("\"dialog_viewed_messages_\":"); output.push_back(std::to_string(this->dialog_viewed_messages_.size()));
output.push_back(",");
output.push_back("\"being_reloaded_reactions_\":"); output.push_back(std::to_string(this->being_reloaded_reactions_.size()));
output.push_back(",");
output.push_back("\"being_reloaded_fact_checks_\":"); output.push_back(std::to_string(this->being_reloaded_fact_checks_.size()));
output.push_back(",");
output.push_back("\"pending_dialog_group_call_updates_\":"); output.push_back(std::to_string(this->pending_dialog_group_call_updates_.size()));
output.push_back(",");
output.push_back("\"auth_notification_id_date_\":"); output.push_back(std::to_string(this->auth_notification_id_date_.size()));
output.push_back(",");
output.push_back("\"previous_repaired_read_inbox_max_message_id_\":"); output.push_back(std::to_string(this->previous_repaired_read_inbox_max_message_id_.size()));
output.push_back(",");
output.push_back("\"yet_unsent_message_full_id_to_persistent_message_id_\":"); output.push_back(std::to_string(this->yet_unsent_message_full_id_to_persistent_message_id_.size()));
output.push_back(",");
output.push_back("\"yet_unsent_thread_message_ids_\":"); output.push_back(std::to_string(this->yet_unsent_thread_message_ids_.size()));
output.push_back(",");
output.push_back("\"dialog_suffix_load_queries_\":"); output.push_back(std::to_string(this->dialog_suffix_load_queries_.size()));
output.push_back(",");
output.push_back("\"pending_message_views_\":"); output.push_back(std::to_string(this->pending_message_views_.size()));
output.push_back(",");
output.push_back("\"read_history_log_event_ids_\":"); output.push_back(std::to_string(this->read_history_log_event_ids_.size()));
output.push_back(",");
output.push_back("\"updated_read_history_message_ids_\":"); output.push_back(std::to_string(this->updated_read_history_message_ids_.size()));
output.push_back(",");
output.push_back("\"pending_reactions_\":"); output.push_back(std::to_string(this->pending_reactions_.size()));
output.push_back(",");
output.push_back("\"paid_reaction_task_ids_\":"); output.push_back(std::to_string(this->paid_reaction_task_ids_.size()));
output.push_back(",");
output.push_back("\"paid_reaction_tasks_\":"); output.push_back(std::to_string(this->paid_reaction_tasks_.size()));
output.push_back(",");
output.push_back("\"pending_read_reactions_\":"); output.push_back(std::to_string(this->pending_read_reactions_.size()));
output.push_back(",");
output.push_back("\"active_reaction_types_\":"); output.push_back(std::to_string(this->active_reaction_types_.size()));
output.push_back(",");
output.push_back("\"active_reaction_pos_\":"); output.push_back(std::to_string(this->active_reaction_pos_.size()));
output.push_back(",");
output.push_back("\"get_history_queries_\":"); output.push_back(std::to_string(this->get_history_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -126,6 +126,7 @@ class Usernames;
class MessagesManager final : public Actor { class MessagesManager final : public Actor {
public: public:
void memory_stats(vector<string> &output);
static constexpr int32 SEND_MESSAGE_FLAG_DISABLE_WEB_PAGE_PREVIEW = 1 << 1; static constexpr int32 SEND_MESSAGE_FLAG_DISABLE_WEB_PAGE_PREVIEW = 1 << 1;
static constexpr int32 SEND_MESSAGE_FLAG_HAS_REPLY_MARKUP = 1 << 2; static constexpr int32 SEND_MESSAGE_FLAG_HAS_REPLY_MARKUP = 1 << 2;
static constexpr int32 SEND_MESSAGE_FLAG_HAS_ENTITIES = 1 << 3; static constexpr int32 SEND_MESSAGE_FLAG_HAS_ENTITIES = 1 << 3;

View File

@ -167,7 +167,11 @@ void NotificationManager::on_flush_pending_updates_timeout_callback(void *notifi
} }
bool NotificationManager::is_disabled() const { bool NotificationManager::is_disabled() const {
if ( G()->get_option_boolean("disable_notifications")) {
return true;
} else {
return G()->close_flag() || !td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot(); return G()->close_flag() || !td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot();
}
} }
StringBuilder &operator<<(StringBuilder &string_builder, const NotificationManager::ActiveNotificationsUpdate &update) { StringBuilder &operator<<(StringBuilder &string_builder, const NotificationManager::ActiveNotificationsUpdate &update) {
@ -4382,4 +4386,32 @@ void NotificationManager::on_binlog_events(vector<BinlogEvent> &&events) {
VLOG(notifications) << "Finish processing binlog events"; VLOG(notifications) << "Finish processing binlog events";
} }
void NotificationManager::memory_stats(vector<string> &output) {
output.push_back("\"running_get_chat_difference_\":"); output.push_back(std::to_string(this->running_get_chat_difference_.size()));
output.push_back(",");
output.push_back("\"group_keys_\":"); output.push_back(std::to_string(this->group_keys_.size()));
output.push_back(",");
output.push_back("\"pending_updates_\":"); output.push_back(std::to_string(this->pending_updates_.size()));
output.push_back(",");
output.push_back("\"call_notification_group_ids_\":"); output.push_back(std::to_string(this->call_notification_group_ids_.size()));
output.push_back(",");
output.push_back("\"available_call_notification_group_ids_\":"); output.push_back(std::to_string(this->available_call_notification_group_ids_.size()));
output.push_back(",");
output.push_back("\"dialog_id_to_call_notification_group_id_\":"); output.push_back(std::to_string(this->dialog_id_to_call_notification_group_id_.size()));
output.push_back(",");
output.push_back("\"temporary_notification_log_event_ids_\":"); output.push_back(std::to_string(this->temporary_notification_log_event_ids_.size()));
output.push_back(",");
output.push_back("\"temporary_edit_notification_log_event_ids_\":"); output.push_back(std::to_string(this->temporary_edit_notification_log_event_ids_.size()));
output.push_back(",");
output.push_back("\"temporary_notifications_\":"); output.push_back(std::to_string(this->temporary_notifications_.size()));
output.push_back(",");
output.push_back("\"temporary_notification_object_ids_\":"); output.push_back(std::to_string(this->temporary_notification_object_ids_.size()));
output.push_back(",");
output.push_back("\"push_notification_promises_\":"); output.push_back(std::to_string(this->push_notification_promises_.size()));
output.push_back(",");
output.push_back("\"active_call_notifications_\":"); output.push_back(std::to_string(this->active_call_notifications_.size()));
output.push_back(",");
output.push_back("\"announcement_id_date_\":"); output.push_back(std::to_string(this->announcement_id_date_.size()));
}
} // namespace td } // namespace td

View File

@ -135,6 +135,8 @@ class NotificationManager final : public Actor {
void on_binlog_events(vector<BinlogEvent> &&events); void on_binlog_events(vector<BinlogEvent> &&events);
void memory_stats(vector<string> &output);
private: private:
static constexpr int32 DEFAULT_GROUP_COUNT_MAX = 0; static constexpr int32 DEFAULT_GROUP_COUNT_MAX = 0;
static constexpr int32 DEFAULT_GROUP_SIZE_MAX = 10; static constexpr int32 DEFAULT_GROUP_SIZE_MAX = 10;

View File

@ -1756,4 +1756,18 @@ void NotificationSettingsManager::get_current_state(vector<td_api::object_ptr<td
} }
} }
void NotificationSettingsManager::memory_stats(vector<string> &output) {
output.push_back("\"saved_ringtone_file_ids_\":"); output.push_back(std::to_string(this->saved_ringtone_file_ids_.size()));
output.push_back(",");
output.push_back("\"sorted_saved_ringtone_file_ids_\":"); output.push_back(std::to_string(this->sorted_saved_ringtone_file_ids_.size()));
output.push_back(",");
output.push_back("\"being_uploaded_ringtones_\":"); output.push_back(std::to_string(this->being_uploaded_ringtones_.size()));
output.push_back(",");
output.push_back("\"reload_saved_ringtones_queries_\":"); output.push_back(std::to_string(this->reload_saved_ringtones_queries_.size()));
output.push_back(",");
output.push_back("\"repair_saved_ringtones_queries_\":"); output.push_back(std::to_string(this->repair_saved_ringtones_queries_.size()));
output.push_back(",");
output.push_back("\"get_dialog_notification_settings_queries_\":"); output.push_back(std::to_string(this->get_dialog_notification_settings_queries_.size()));
}
} // namespace td } // namespace td

View File

@ -46,7 +46,7 @@ class NotificationSettingsManager final : public Actor {
NotificationSettingsManager &operator=(NotificationSettingsManager &&) = delete; NotificationSettingsManager &operator=(NotificationSettingsManager &&) = delete;
~NotificationSettingsManager() final; ~NotificationSettingsManager() final;
int32 get_scope_mute_until(NotificationSettingsScope scope) const; int32 get_scope_mute_until(NotificationSettingsScope scope) const;
std::pair<bool, bool> get_scope_mute_stories(NotificationSettingsScope scope) const; std::pair<bool, bool> get_scope_mute_stories(NotificationSettingsScope scope) const;
@ -124,6 +124,8 @@ class NotificationSettingsManager final : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const; void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void memory_stats(vector<string> &output);
private: private:
class UpdateScopeNotificationSettingsOnServerLogEvent; class UpdateScopeNotificationSettingsOnServerLogEvent;
class UpdateReactionNotificationSettingsOnServerLogEvent; class UpdateReactionNotificationSettingsOnServerLogEvent;

View File

@ -161,4 +161,7 @@ void OnlineManager::on_ping_server_timeout() {
set_is_bot_online(false); set_is_bot_online(false);
} }
void OnlineManager::memory_stats(vector<string> &output) {
}
} // namespace td } // namespace td

View File

@ -33,6 +33,8 @@ class OnlineManager final : public Actor {
void set_is_bot_online(bool is_bot_online); void set_is_bot_online(bool is_bot_online);
void memory_stats(vector<string> &output);
private: private:
static constexpr int32 PING_SERVER_TIMEOUT = 300; static constexpr int32 PING_SERVER_TIMEOUT = 300;

Some files were not shown because too many files have changed in this diff Show More