Apply tdlight patch

This commit is contained in:
Andrea Cavalli 2023-10-08 16:59:20 +02:00
parent b41f3219dc
commit 13648d1fca
70 changed files with 1290 additions and 192 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

8
.gitignore vendored
View File

@ -4,4 +4,12 @@
**/auto/
docs/
tdlib/
.idea/
vcpkg/
*.tlo
td.binlog
tg_cli.log
tg_cli.log.old

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 ability to specify the exact types of problems with a call in the method `sendCallRating` and
the new class `CallProblem`.
* Changes in [tdweb](https://github.com/tdlib/td/blob/master/example/web/):
* Changes in [tdweb](https://github.com/tdlight-team/tdlight/blob/master/example/web/):
- Supported non-zero `offset` and `limit` in `readFilePart`.
-----------------------------------------------------------------------------------------------------------------------
@ -1034,7 +1034,7 @@ Changes in 1.4.0 (1 May 2019):
* Added a [TDLib build instructions generator](https://tdlib.github.io/td/build.html), covering in details
TDLib building on the most popular operating systems.
* Added an example of TDLib building and usage from a browser.
See https://github.com/tdlib/td/blob/master/example/web/ for more details.
See https://github.com/tdlight-team/tdlight/blob/master/example/web/ for more details.
* Allowed to pass NULL pointer to `td_json_client_execute` instead of a previously created JSON client.
Now you can use synchronous TDLib methods through a JSON interface before creating a TDLib JSON client.
* Added support for media streaming by allowing to download any part of a file:
@ -1285,7 +1285,7 @@ Changes in 1.4.0 (1 May 2019):
Changes in 1.3.0 (5 Sep 2018):
* Added a review of existing TDLib based [frameworks](https://github.com/tdlib/td/blob/master/example/README.md)
* Added a review of existing TDLib based [frameworks](https://github.com/tdlight-team/tdlight/blob/master/example/README.md)
in different programming languages.
* Added a [Getting started](https://core.telegram.org/tdlib/getting-started) guide describing the main TDLib concepts
and basic principles required for library usage.

View File

@ -207,9 +207,13 @@ add_subdirectory(sqlite)
add_subdirectory(tddb)
add_subdirectory(test)
option(TD_SKIP_TEST "Use \"ON\" to skip building/running the test harness.")
if (NOT TD_SKIP_TEST)
add_subdirectory(test)
endif()
if (NOT CMAKE_CROSSCOMPILING)
option(TD_SKIP_BENCHMARK "Use \"ON\" to skip building/running the benchmarks.")
if (NOT CMAKE_CROSSCOMPILING AND NOT TD_SKIP_BENCHMARK)
add_subdirectory(benchmark)
endif()
@ -505,6 +509,7 @@ set(TDLIB_SOURCE
td/telegram/StickersManager.cpp
td/telegram/StickerType.cpp
td/telegram/StorageManager.cpp
td/telegram/MemoryManager.cpp
td/telegram/StoryContent.cpp
td/telegram/StoryContentType.cpp
td/telegram/StoryDb.cpp
@ -850,6 +855,7 @@ set(TDLIB_SOURCE
td/telegram/StickersManager.h
td/telegram/StickerType.h
td/telegram/StorageManager.h
td/telegram/MemoryManager.h
td/telegram/StoryContent.h
td/telegram/StoryContentType.h
td/telegram/StoryDb.h
@ -1124,6 +1130,8 @@ endif()
#EXECUTABLES
if (NOT CMAKE_CROSSCOMPILING)
option(TD_SKIP_TG_CLI "Use \"ON\" to skip building tg_cli.")
if (NOT CMAKE_CROSSCOMPILING AND NOT TD_SKIP_TG_CLI)
add_executable(tg_cli td/telegram/cli.cpp ${TL_TD_JSON_SOURCE})
if (NOT READLINE_FOUND)
@ -1152,6 +1160,7 @@ if (NOT CMAKE_CROSSCOMPILING)
target_link_libraries(tg_cli PRIVATE memprof tdclient tdcore)
add_dependencies(tg_cli tl_generate_json)
endif()
endif()
#Exported libraries
add_library(TdStatic INTERFACE)

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
- [Features](#features)
- [TDLight extra features](#tdlight-extra-features)
- [TDLight extra API functions](#tdlight-extra-api-functions)
- [TDLight recommended options](#tdlight-recommended-options)
- [Examples and documentation](#usage)
- [Dependencies](#dependencies)
- [Building](#building)
@ -28,17 +31,42 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele
* **Secure**: all local data is encrypted using a user-provided encryption key.
* **Fully-asynchronous**: requests to `TDLib` don't block each other or anything else, responses are sent when they are available.
<a name="tdlight-extra-features"></a>
### TDLight extra features
#### TDLight extra options
* **disable_minithumbnails** (true/**false**) This setting removes minithumbnails everywhere. It reduces memory usage because tdlib keeps them in RAM
* **disable_document_filenames** (true/**false**) If you don't care about having the original filenames of every file stored in RAM, you can disable them using this option. It reduces memory usage
* **disable_notifications** (true/**false**) In TDLib pending notification updates are stored in ram until you "read" them. This option disables completely notifications and keeps the pending notifications queue empty, reducing memory usage
* **ignore_update_chat_last_message** (true/**false**) If you don't care about have updateChatLastMessage updates enable this
* **ignore_update_chat_read_inbox** (true/**false**) If you don't care about have updateChatReadInbox updates enable this
* **ignore_update_user_chat_action** (true/**false**) If you don't care about have updateUserChatAction updates enable this
* **ignore_server_deletes_and_reads** (true/**false**) If you don't care about receiving read receipts and remote deletes from other users, enable this, it will reduce memory usage
* **receive_access_hashes** (true/**false**) Receive chats and users access hash as updates
* **disable_auto_download** (true/**false**) Forcefully ignore auto download settings of all sessions
<a name="tdlight-extra-api-functions"></a>
### TDLight extra API functions
#### TdApi.GetMemoryStatistics
This method is used to read the size of all the internal TDLib data structures.
The output contains a string that can be parsed as a JSON.
<a name="tdlight-recommended-options"></a>
## TDLight recommended options
* Options:
* ignore_inline_thumbnails: true
* disable_top_chats: true
* ignore_platform_restrictions: true
* ignore_sensitive_content_restrictions: true
* Disable all the databases (messages_db, users_db, files_db)
<a name="usage"></a>
## Examples and documentation
See our [Getting Started](https://core.telegram.org/tdlib/getting-started) tutorial for a description of basic TDLib concepts.
Take a look at our [examples](https://github.com/tdlib/td/blob/master/example/README.md#tdlib-usage-and-build-examples).
Take a look at our [examples](https://github.com/tdlight-team/tdlight/blob/master/example/README.md#tdlib-usage-and-build-examples).
See a [TDLib build instructions generator](https://tdlib.github.io/td/build.html) for detailed instructions on how to build TDLib.
See a [TDLight build instructions generator](https://tdlight-team.github.io/tdlight/build.html) for detailed instructions on how to build TDLib.
See description of our [JSON](#using-json), [C++](#using-cxx), [Java](#using-java) and [.NET](#using-dotnet) interfaces.
See the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html)
See the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html)
for a list of all available `TDLib` [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
<a name="dependencies"></a>
@ -55,7 +83,7 @@ for a list of all available `TDLib` [methods](https://core.telegram.org/tdlib/do
<a name="building"></a>
## Building
The simplest way to build `TDLib` is to use our [TDLib build instructions generator](https://tdlib.github.io/td/build.html).
The simplest way to build `TDLight` is to use our [TDLight build instructions generator](https://tdlight-team.github.io/tdlight/build.html).
You need only to choose your programming language and target operating system to receive complete build instructions.
In general, you need to install all `TDLib` [dependencies](#dependencies), enter directory containing `TDLib` sources and compile them using CMake:
@ -67,7 +95,7 @@ cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
```
To build `TDLib` on low memory devices you can run [SplitSource.php](https://github.com/tdlib/td/blob/master/SplitSource.php) script
To build `TDLib` on low memory devices you can run [SplitSource.php](https://github.com/tdlight-team/tdlight/blob/master/SplitSource.php) script
before compiling main `TDLib` source code and compile only needed targets:
```
mkdir build
@ -106,21 +134,21 @@ Or you could install `TDLib` and then reference it in your CMakeLists.txt like t
find_package(Td 1.8.26 REQUIRED)
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
```
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/blob/master/example/cpp/CMakeLists.txt).
See [example/cpp/CMakeLists.txt](https://github.com/tdlight-team/tdlight/blob/master/example/cpp/CMakeLists.txt).
<a name="using-java"></a>
## Using in Java projects
`TDLib` provides native Java interface through JNI. To enable it, specify option `-DTD_ENABLE_JNI=ON` to CMake.
See [example/java](https://github.com/tdlib/td/tree/master/example/java) for example of using `TDLib` from Java and detailed build and usage instructions.
See [example/java](https://github.com/tdlight-team/tdlight/tree/master/example/java) for example of using `TDLib` from Java and detailed build and usage instructions.
<a name="using-dotnet"></a>
## Using in .NET projects
`TDLib` provides native .NET interface through `C++/CLI` and `C++/CX`. To enable it, specify option `-DTD_ENABLE_DOTNET=ON` to CMake.
.NET Core supports `C++/CLI` only since version 3.1 and only on Windows, so if older .NET Core is used or portability is needed, then `TDLib` JSON interface should be used through P/Invoke instead.
See [example/csharp](https://github.com/tdlib/td/tree/master/example/csharp) for example of using `TDLib` from C# and detailed build and usage instructions.
See [example/uwp](https://github.com/tdlib/td/tree/master/example/uwp) for example of using `TDLib` from C# UWP application and detailed build and usage instructions for Visual Studio Extension "TDLib for Universal Windows Platform".
See [example/csharp](https://github.com/tdlight-team/tdlight/tree/master/example/csharp) for example of using `TDLib` from C# and detailed build and usage instructions.
See [example/uwp](https://github.com/tdlight-team/tdlight/tree/master/example/uwp) for example of using `TDLib` from C# UWP application and detailed build and usage instructions for Visual Studio Extension "TDLib for Universal Windows Platform".
When `TDLib` is built with `TD_ENABLE_DOTNET` option enabled, `C++` documentation is removed from some files. You need to checkout these files to return `C++` documentation back:
```
@ -132,13 +160,13 @@ git checkout td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
`TDLib` provides efficient native C++, Java, and .NET interfaces.
But for most use cases we suggest to use the JSON interface, which can be easily used with any programming language that is able to execute C functions.
See [td_json_client](https://core.telegram.org/tdlib/docs/td__json__client_8h.html) documentation for detailed JSON interface description,
the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of
the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of
all available `TDLib` [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
`TDLib` JSON interface adheres to semantic versioning and versions with the same major version number are binary and backward compatible, but the underlying `TDLib` API can be different for different minor and even patch versions.
If you need to support different `TDLib` versions, then you can use a value of the `version` option to find exact `TDLib` version to use appropriate API methods.
See [example/python/tdjson_example.py](https://github.com/tdlib/td/blob/master/example/python/tdjson_example.py) for an example of such usage.
See [example/python/tdjson_example.py](https://github.com/tdlight-team/tdlight/tree/master/example/python/tdjson_example.py) for an example of such usage.
<a name="license"></a>
## License

View File

@ -2,7 +2,7 @@
<html>
<head>
<title>TDLib build instructions</title>
<title>TDLight build instructions</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
:root {
@ -193,7 +193,7 @@
<div class="main">
<div id="languageSelectDiv">
<p>Choose a programming language from which you want to use TDLib:</p>
<p>Choose a programming language from which you want to use TDLight:</p>
<select id="languageSelect" onchange="onLanguageChanged(false)" autofocus class="large">
<option>Choose a programming language:</option>
<option>Python</option>
@ -226,7 +226,7 @@
</div>
<div id="osSelectDiv" class="hide">
<p>Choose an operating system on which you want to use TDLib:</p>
<p>Choose an operating system on which you want to use TDLight:</p>
<select id="osSelect" onchange="onOsChanged()" class="large">
<option>Choose an operating system:</option>
</select>
@ -234,7 +234,7 @@
</div>
<div id="linuxSelectDiv" class="hide">
<p>Choose a Linux distro on which you want to use TDLib:</p>
<p>Choose a Linux distro on which you want to use TDLight:</p>
<select id="linuxSelect" onchange="onOsChanged()" class="large">
<option>Choose a Linux distro:</option>
<option>Alpine</option>
@ -263,13 +263,13 @@
</div>
<div id="buildInstallLocalDiv" class="hide">
<label><input type="checkbox" id="buildInstallLocalCheckbox" onchange="onOptionsChanged()"/>Install built TDLib to /usr/local instead of placing the files to td/tdlib.</label>
<label><input type="checkbox" id="buildInstallLocalCheckbox" onchange="onOptionsChanged()"/>Install built TDLight to /usr/local instead of placing the files to td/tdlib.</label>
</div>
<p></p>
<div id="buildCompilerDiv" class="hide">
<span>Choose which compiler you want to use to build TDLib:</span><br>
<span>Choose which compiler you want to use to build TDLight:</span><br>
<label><input type="radio" id="buildCompilerRadioGcc" name="buildCompilerRadio" onchange="onOptionsChanged()" checked/>g++</label>
<label><input type="radio" id="buildCompilerRadioClang" name="buildCompilerRadio" onchange="onOptionsChanged()"/>clang (recommended)</label>
<p></p>
@ -305,7 +305,7 @@
</div>
<div id="buildBitnessDiv" class="hide">
<span>Choose for which bitness you want to build TDLib:</span><br>
<span>Choose for which bitness you want to build TDLight:</span><br>
<label><input type="radio" id="buildBitnessRadio32" name="buildBitnessRadio" onchange="onOptionsChanged()" checked/>32</label>
<label><input type="radio" id="buildBitnessRadio64" name="buildBitnessRadio" onchange="onOptionsChanged()"/>64</label>
<p></p>
@ -327,7 +327,7 @@
</div>
<div id="buildCommandsDiv" class="hide">
<p id="buildCommandsHeader">Here is complete instruction for TDLib binaries building:</p>
<p id="buildCommandsHeader">Here is complete instruction for TDLight binaries building:</p>
<p id="buildPre">Hidden text</p>
<code id="buildCommands">Empty commands</code>
<button id="copyBuildCommandsButton" onclick="copyBuildInstructions()">
@ -494,14 +494,14 @@ function getTargetName(target) {
case 'tdjson':
case 'WebAssembly':
case 'iOS':
return '<a href="https://github.com/tdlib/td#using-json">JSON</a>';
return '<a href="https://github.com/tdlight-team/tdlight#using-json">JSON</a>';
case 'tdclient':
return '<a href="https://github.com/tdlib/td#using-cxx">a simple and convenient C++11-interface</a>';
return '<a href="https://github.com/tdlight-team/tdlight#using-cxx">a simple and convenient C++11-interface</a>';
case 'JNI':
case 'Android':
return '<a href="https://github.com/tdlib/td#using-java">native ' + target + '</a>';
return '<a href="https://github.com/tdlight-team/tdlight#using-java">native ' + target + '</a>';
default:
return '<a href="https://github.com/tdlib/td#using-dotnet">native ' + target + '</a>';
return '<a href="https://github.com/tdlight-team/tdlight#using-dotnet">native ' + target + '</a>';
}
}
@ -515,17 +515,17 @@ function onOsChanged() {
if (language === 'Other') {
language = 'any other programming language';
}
var text = 'TDLib can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' +
'See <a href="https://github.com/tdlib/td/blob/master/example/README.md#' + getExampleAnchor(language) + '">examples</a> of such usage and already available third-party frameworks.<br>';
var text = 'TDLight can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' +
'See <a href="https://github.com/tdlight-team/tdlight/blob/master/example/README.md#' + getExampleAnchor(language) + '">examples</a> of such usage and already available third-party frameworks.<br>';
if (target === 'WebAssembly') {
text = 'TDLib is available in a prebuilt form as an <a href="https://www.npmjs.com/">NPM</a> package <a href="https://www.npmjs.com/package/tdweb">tdweb</a>.<br>' +
'If you want to build it manually, take a look at our <a href="https://github.com/tdlib/td/tree/master/example/web">example</a>.';
text = 'TDLight is available in a prebuilt form as an <a href="https://www.npmjs.com/">NPM</a> package <a href="https://www.npmjs.com/package/tdweb">tdweb</a>.<br>' +
'If you want to build it manually, take a look at our <a href="https://github.com/tdlight-team/tdlight/tree/master/example/web">example</a>.';
target = '';
}
if (target === 'Android') {
text = 'TDLib for Android is available in a prebuilt form and can be downloaded from <a href="https://core.telegram.org/tdlib/tdlib.zip">there</a>.<br>' +
'See <a href="https://github.com/tdlib/td/issues/77#issuecomment-640719893">build instructions</a> if you want to build the latest TDLib version or want to build TDLib with different interface.';
text = 'TDLight for Android is available in a prebuilt form and can be downloaded from <a href="https://core.telegram.org/tdlight-team/tdlightlib.zip">there</a>.<br>' +
'See <a href="https://github.com/tdlight-team/tdlight/issues/77#issuecomment-640719893">build instructions</a> if you want to build the latest TDLight version or want to build TDLight with different interface.';
target = '';
}
if (target === 'iOS') {
@ -590,7 +590,7 @@ function onOptionsChanged() {
if (os_linux || os_freebsd || os_netbsd) {
low_memory = document.getElementById('buildLowMemoryCheckbox').checked;
document.getElementById('buildLowMemoryText').innerHTML = 'I have less than ' + (use_clang ? '1.5' : '3.5') +' GB of RAM.' +
(low_memory ? ' Now you will need only ' + (use_clang ? '0.5' : '1') +' GB of RAM to build TDLib.' : '');
(low_memory ? ' Now you will need only ' + (use_clang ? '0.5' : '1') +' GB of RAM to build TDLight.' : '');
document.getElementById('buildLowMemoryDiv').style.display = 'block';
} else {
if (os_openbsd) {
@ -751,8 +751,8 @@ function onOptionsChanged() {
pre_text.push('Note that the following instruction is for NetBSD 8+ and default SH shell.');
}
if (os_mac) {
pre_text.push('Note that the following instruction will build TDLib only for ' + os_mac_host_name + '.');
pre_text.push('If you want to create a universal XCFramework, take a look at our <a href="https://github.com/tdlib/td/tree/master/example/ios">example</a> instead.');
pre_text.push('Note that the following instruction will build TDLight only for ' + os_mac_host_name + '.');
pre_text.push('If you want to create a universal XCFramework, take a look at our <a href="https://github.com/tdlight-team/tdlight/tree/master/example/ios">example</a> instead.');
}
var terminal_name = (function () {
@ -776,12 +776,12 @@ function onOptionsChanged() {
if (os_windows) {
pre_text.push('Close and re-open ' + terminal_name + ' if the PATH environment variable was changed.');
}
pre_text.push('Run these commands in ' + terminal_name + ' to build TDLib and to install it to ' + install_dir + ':');
pre_text.push('Run these commands in ' + terminal_name + ' to build TDLight and to install it to ' + install_dir + ':');
document.getElementById('buildPre').innerHTML = '<ul><li>' + pre_text.join('</li><li>') + '</li></ul>';
document.getElementById('buildPre').style.display = 'block';
if (install_dir && install_dir !== '/usr/local') {
install_dir = '../tdlib';
install_dir = '../tdlight';
if (target === 'JNI' || target === 'C++/CX') {
install_dir = '../../' + install_dir;
}
@ -926,9 +926,9 @@ function onOptionsChanged() {
commands.push('exit');
}
}
commands.push('git clone https://github.com/tdlib/td.git');
commands.push('git clone https://github.com/tdlight-team/tdlight.git');
commands.push('cd td');
commands.push('cd tdlight');
// commands.push('git checkout v1.8.0');
if (use_vcpkg) {

View File

@ -1,7 +1,7 @@
# TDLib usage and build examples
This directory contains basic examples of TDLib usage from different programming languages and examples of library building for different platforms.
If you are looking for documentation of all available TDLib methods, see the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or the
If you are looking for documentation of all available TDLib methods, see the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or the
automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of all available TDLib
[methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
Also, take a look at our [Getting Started](https://core.telegram.org/tdlib/getting-started) tutorial for a description of basic TDLib concepts.
@ -54,13 +54,13 @@ If you want to use TDLib with asyncio and Python >= 3.9, take a look at [aiotdli
For older Python versions you can use [pytdlib](https://github.com/pytdlib/pytdlib).
This wrapper contains generator for TDLib API classes and basic interface for interaction with TDLib.
You can also check out [example/python/tdjson_example.py](https://github.com/tdlib/td/blob/master/example/python/tdjson_example.py),
You can also check out [example/python/tdjson_example.py](https://github.com/tdlight-team/tdlight/blob/master/example/python/tdjson_example.py),
[tdlib-python](https://github.com/JunaidBabu/tdlib-python), or [Python Wrapper TDLib](https://github.com/alvhix/pywtdlib) for some basic examples of TDLib JSON interface integration with Python.
<a name="javascript"></a>
## Using TDLib in JavaScript projects
TDLib can be compiled to WebAssembly or asm.js and used in a browser from JavaScript. See [tdweb](https://github.com/tdlib/td/tree/master/example/web) as a convenient wrapper for TDLib in a browser
TDLib can be compiled to WebAssembly or asm.js and used in a browser from JavaScript. See [tdweb](https://github.com/tdlight-team/tdlight/tree/master/example/web) as a convenient wrapper for TDLib in a browser
and [telegram-react](https://github.com/evgeny-nadymov/telegram-react) as an example of a TDLib-based Telegram client.
See also [Svelte-tdweb-starter](https://github.com/gennadypolakov/svelte-tdweb-starter) - Svelte wrapper for tdweb, and [Telegram-Photoframe](https://github.com/lukefx/telegram-photoframe) - a web application that displays your preferred group or channel as Photoframe.
@ -95,7 +95,7 @@ You can also see [github.com/aliforever/go-tdlib](https://github.com/aliforever/
TDLib can be used from the Java programming language through native [JNI](https://github.com/tdlib/td#using-java) binding.
We provide a generator for JNI bridge methods and Java classes for all TDLib API methods and objects.
See [example/java](https://github.com/tdlib/td/tree/master/example/java) for an example of using TDLib from desktop Java along with detailed building and usage instructions.
See [example/java](https://github.com/tdlight-team/tdlight/tree/master/example/java) for an example of using TDLib from desktop Java along with detailed building and usage instructions.
To use TDLib to create Android Java applications, use our [prebuilt library for Android](https://core.telegram.org/tdlib/tdlib.zip).
<a name="kotlin"></a>
@ -112,8 +112,8 @@ See also [td-ktx](https://github.com/tdlibx/td-ktx) - Kotlin coroutines wrapper
TDLib provides a native [.NET](https://github.com/tdlib/td#using-dotnet) interface through `C++/CLI` and `C++/CX`.
See [tdlib-netcore](https://github.com/dantmnf/tdlib-netcore) for a SWIG-like binding with automatically generated classes for TDLib API.
See [example/uwp](https://github.com/tdlib/td/tree/master/example/uwp) for an example of building TDLib SDK for the Universal Windows Platform and an example of its usage from C#.
See [example/csharp](https://github.com/tdlib/td/tree/master/example/csharp) for an example of building TDLib with `C++/CLI` support and an example of TDLib usage from C# on Windows.
See [example/uwp](https://github.com/tdlight-team/tdlight/tree/master/example/uwp) for an example of building TDLib SDK for the Universal Windows Platform and an example of its usage from C#.
See [example/csharp](https://github.com/tdlight-team/tdlight/tree/master/example/csharp) for an example of building TDLib with `C++/CLI` support and an example of TDLib usage from C# on Windows.
If you want to write a cross-platform C# application using .NET Core, see [tdsharp](https://github.com/egramtel/tdsharp). It uses our [JSON](https://github.com/tdlib/td#using-json) interface,
provides an asynchronous interface for interaction with TDLib, automatically generated classes for TDLib API and has some examples.
@ -127,8 +127,8 @@ Also, see [Unigram](https://github.com/UnigramDev/Unigram), which is a full-feat
TDLib has a simple and convenient C++11-interface for sending and receiving requests and can be statically linked to your application.
See [example/cpp](https://github.com/tdlib/td/tree/master/example/cpp) for an example of TDLib usage from C++.
[td_example.cpp](https://github.com/tdlib/td/blob/master/example/cpp/td_example.cpp) contains an example of authorization, processing new incoming messages, getting a list of chats and sending a text message.
See [example/cpp](https://github.com/tdlight-team/tdlight/tree/master/example/cpp) for an example of TDLib usage from C++.
[td_example.cpp](https://github.com/tdlight-team/tdlight/blob/master/example/cpp/td_example.cpp) contains an example of authorization, processing new incoming messages, getting a list of chats and sending a text message.
See also the source code of [Fernschreiber](https://github.com/Wunderfitz/harbour-fernschreiber) and [Depecher](https://github.com/blacksailer/depecher) Telegram apps for Sailfish OS,
[TELEports](https://gitlab.com/ubports/development/apps/teleports) a Qt-client for Ubuntu Touch, [tdlib-purple](https://github.com/ars3niy/tdlib-purple) - Telegram plugin for Pidgin,
@ -140,20 +140,20 @@ or [MeeGram](https://github.com/qtinsider/meegram2) - a Telegram client for Noki
TDLib can be used from the Swift programming language through the [JSON](https://github.com/tdlib/td#using-json) interface and can be linked statically or dynamically.
See [example/ios](https://github.com/tdlib/td/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, 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 also the source code of [Moc](https://github.com/mock-foundation/moc) - a native and powerful macOS and iPadOS Telegram client, optimized for moderating large communities and personal use.
See [example/swift](https://github.com/tdlib/td/tree/master/example/swift) for an example of a macOS Swift application.
See [example/swift](https://github.com/tdlight-team/tdlight/tree/master/example/swift) for an example of a macOS Swift application.
<a name="objective-c"></a>
## Using TDLib in Objective-C projects
TDLib can be used from the Objective-C programming language through [JSON](https://github.com/tdlib/td#using-json) interface and can be linked statically or dynamically.
See [example/ios](https://github.com/tdlib/td/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, 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>
## Using TDLib in Object Pascal projects with Delphi and Lazarus
@ -300,7 +300,7 @@ TDLib can be used from the C programming language through the [JSON](https://git
See [easy-tg](https://github.com/Trumeet/easy-tg) for an example of such usage.
You can also try to use our [C](https://github.com/tdlib/td/blob/master/td/telegram/td_c_client.h) client, which was used by the private TDLib-based version of [telegram-cli](https://github.com/vysheng/tg).
You can also try to use our [C](https://github.com/tdlight-team/tdlight/blob/master/td/telegram/td_c_client.h) client, which was used by the private TDLib-based version of [telegram-cli](https://github.com/vysheng/tg).
<a name="g"></a>
## Using TDLib from G projects

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).
For example of usage take a look at our [Swift example](https://github.com/tdlib/td/tree/master/example/swift).
For example of usage take a look at our [Swift example](https://github.com/tdlight-team/tdlight/tree/master/example/swift).
To compile `TDLib` you will need to:
* Install the latest Xcode via `xcode-select --install` or downloading it from [Xcode website](https://developer.apple.com/xcode/).
@ -37,7 +37,7 @@ cd <path to TDLib sources>/example/ios
```
This may take a while, because TDLib will be built about 16 times.
Resulting XCFramework will work on any architecture and even on a simulator.
We use [CMake/iOS.cmake](https://github.com/tdlib/td/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
We use [CMake/iOS.cmake](https://github.com/tdlight-team/tdlight/blob/master/CMake/iOS.cmake) toolchain, other toolchains may work too.
Built libraries and XCFramework will be stored in `tdjson` directory.

View File

@ -3,7 +3,7 @@
To run this example, you will need installed JDK >= 1.6.
For Javadoc documentation generation PHP is needed.
You can find complete build instructions for your operating system at https://tdlib.github.io/td/build.html?language=Java.
You can find complete build instructions for your operating system at https://tdlight-team.github.io/tdlight/build.html?language=Java.
In general, the build process looks as follows.

View File

@ -6,7 +6,7 @@
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
<Tags>Telegram, TDLib, library, client, API</Tags>
<License>LICENSE_1_0.txt</License>
<ReleaseNotes>https://github.com/tdlib/td/blob/master/CHANGELOG.md</ReleaseNotes>
<ReleaseNotes>https://github.com/tdlight-team/tdlight/blob/master/CHANGELOG.md</ReleaseNotes>
</Metadata>
<Installation Scope="Global">
<InstallationTarget Id="Microsoft.ExtensionSDK" TargetPlatformIdentifier="UAP" TargetPlatformVersion="v0.8.0.0" SdkName="Telegram.Td.UWP" SdkVersion="1.0" />

View File

@ -26,4 +26,4 @@ cd <path to TDLib sources>/example/web
## Using tdweb NPM package
See [tdweb](https://www.npmjs.com/package/tdweb) or [README.md](https://github.com/tdlib/td/tree/master/example/web/tdweb/README.md) for package documentation.
See [tdweb](https://www.npmjs.com/package/tdweb) or [README.md](https://github.com/tdlight-team/tdlight/tree/master/example/web/tdweb/README.md) for package documentation.

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 the [td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme or
See the [td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme or
the automatically generated [HTML documentation](https://core.telegram.org/tdlib/docs/td__api_8h.html) for a list of all available
TDLib [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) and [classes](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html).
The JSON representation of TDLib API objects is straightforward: all API objects are represented as JSON objects with the same keys as the API object field names in the
[td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme. Note that in the automatically generated C++ documentation all fields have an additional terminating underscore
[td_api.tl](https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl) scheme. Note that in the automatically generated C++ documentation all fields have an additional terminating underscore
which shouldn't be used in the JSON interface. The object type name is stored in the special field '@type' which is optional in places where type is uniquely determined by the context.
Fields of Bool type are stored as Boolean, fields of int32, int53, and double types are stored as Number, fields of int64 and string types are stored as String,
fields of bytes type are base64 encoded and then stored as String, fields of array type are stored as Array.

View File

@ -65,7 +65,7 @@ class TdClient {
*
* If the query contains the field '@extra', the same field will be added into the result.
*
* @param {Object} query - The query for TDLib. See the [td_api.tl]{@link https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl} scheme or
* @param {Object} query - The query for TDLib. See the [td_api.tl]{@link https://github.com/tdlight-team/tdlight/blob/master/td/generate/scheme/td_api.tl} scheme or
* the automatically generated [HTML documentation]{@link https://core.telegram.org/tdlib/docs/td__api_8h.html}
* for a list of all available TDLib [methods]{@link https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html} and
* [classes]{@link https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_object.html}.

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

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

View File

@ -561,6 +561,21 @@ userTypeBot can_be_edited:Bool can_join_groups:Bool can_read_all_group_messages:
//@description No information on the user besides the user identifier is available, yet this user has not been deleted. This object is extremely rare and must be handled like a deleted user. It is not possible to perform any actions on users of this type
userTypeUnknown = UserType;
//@class AccessHashType @description Represents the type of an access hash. The following types are possible: user, channel
//@description An access hash of an user
accessHashTypeUser = AccessHashType;
//@description An access hash of a channel
accessHashTypeChannel = AccessHashType;
//@description Access hash
//@chat_id Chat identifier
//@type Access hash type
//@access_hash Access hash
accessHash chat_id:int53 type:AccessHashType access_hash:int64 = AccessHash;
//@description Represents a command supported by a bot @command Text of the bot command @param_description Description of the bot command
botCommand command:string description:string = BotCommand;
@ -6049,6 +6064,10 @@ storageStatisticsFast files_size:int53 file_count:int32 database_size:int53 lang
//@statistics Database statistics in an unspecified human-readable format
databaseStatistics statistics:string = DatabaseStatistics;
//@description Contains memory statistics
//@statistics Memory statistics in an unspecified human-readable format
memoryStatistics statistics:string = MemoryStatistics;
//@class NetworkType @description Represents the type of a network
@ -6708,6 +6727,9 @@ updateUserStatus user_id:int53 status:UserStatus = Update;
//@description Some data of a user has changed. This update is guaranteed to come before the user identifier is returned to the application @user New data about the user
updateUser user:user = Update;
//@description Some data of a user or a chat has changed. This update is guaranteed to come before the user or chat identifier is returned to the application @access_hash Access hash
updateAccessHash access_hash:accessHash = Update;
//@description Some data of a basic group has changed. This update is guaranteed to come before the basic group identifier is returned to the application @basic_group New data about the group
updateBasicGroup basic_group:basicGroup = Update;
@ -9872,6 +9894,10 @@ getStorageStatisticsFast = StorageStatisticsFast;
//@description Returns database statistics
getDatabaseStatistics = DatabaseStatistics;
//@description Returns memory statistics
//@full Full memory statistics calculation
getMemoryStatistics full:Bool = MemoryStatistics;
//@description Optimizes storage usage, i.e. deletes some files and returns new storage usage statistics. Secret thumbnails can't be deleted
//@size Limit on the total size of files after deletion, in bytes. Pass -1 to use the default limit
//@ttl Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit

View File

@ -10,6 +10,7 @@
#include "td/telegram/DialogId.h"
#include "td/telegram/Document.h"
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileType.h"
@ -191,8 +192,10 @@ FileId AnimationsManager::on_get_animation(unique_ptr<Animation> new_animation,
LOG(DEBUG) << "Animation " << file_id << " duration has changed";
a->duration = new_animation->duration;
}
if (a->minithumbnail != new_animation->minithumbnail) {
a->minithumbnail = std::move(new_animation->minithumbnail);
if (!G()->get_option_boolean("disable_minithumbnails")) {
if (a->minithumbnail != new_animation->minithumbnail) {
a->minithumbnail = std::move(new_animation->minithumbnail);
}
}
if (a->thumbnail != new_animation->thumbnail) {
if (!a->thumbnail.file_id.is_valid()) {
@ -295,8 +298,10 @@ void AnimationsManager::create_animation(FileId file_id, string minithumbnail, P
a->mime_type = std::move(mime_type);
a->duration = max(duration, 0);
a->dimensions = dimensions;
if (!td_->auth_manager_->is_bot()) {
a->minithumbnail = std::move(minithumbnail);
if (!G()->get_option_boolean("disable_minithumbnails")) {
if (!td_->auth_manager_->is_bot()) {
a->minithumbnail = std::move(minithumbnail);
}
}
a->thumbnail = std::move(thumbnail);
a->animated_thumbnail = std::move(animated_thumbnail);
@ -831,7 +836,7 @@ void AnimationsManager::send_update_saved_animations(bool from_database) {
if (animation->animated_thumbnail.file_id.is_valid()) {
new_saved_animation_file_ids.push_back(animation->animated_thumbnail.file_id);
}
}
}
std::sort(new_saved_animation_file_ids.begin(), new_saved_animation_file_ids.end());
if (new_saved_animation_file_ids != saved_animation_file_ids_) {
td_->file_manager_->change_files_source(get_saved_animations_file_source_id(), saved_animation_file_ids_,
@ -882,4 +887,12 @@ 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(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()));
}
} // namespace td

View File

@ -35,6 +35,8 @@ class AnimationsManager final : public Actor {
AnimationsManager &operator=(AnimationsManager &&) = delete;
~AnimationsManager() final;
void memory_stats(vector<string> &output);
int32 get_animation_duration(FileId file_id) const;
tl_object_ptr<td_api::animation> get_animation_object(FileId file_id) const;

View File

@ -15,6 +15,7 @@
#include "td/utils/common.h"
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
@ -55,10 +56,27 @@ FileId AnimationsManager::parse_animation(ParserT &parser) {
parse(animation->duration, parser);
}
parse(animation->dimensions, parser);
parse(animation->file_name, parser);
string tmp_filename;
parse(tmp_filename, parser);
parse(animation->mime_type, parser);
if ( G()->get_option_boolean("disable_document_filenames") && (
animation->mime_type.rfind("image/") == 0 ||
animation->mime_type.rfind("video/") == 0 ||
animation->mime_type.rfind("audio/") == 0)) {
animation->file_name = "0";
} else {
animation->file_name = tmp_filename;
}
if (parser.version() >= static_cast<int32>(Version::SupportMinithumbnails)) {
parse(animation->minithumbnail, parser);
string tmp_minithumbnail;
parse(tmp_minithumbnail, parser);
if (!G()->get_option_boolean("disable_minithumbnails")) {
animation->minithumbnail = tmp_minithumbnail;
}
}
parse(animation->thumbnail, parser);
parse(animation->file_id, parser);

View File

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

View File

@ -29,6 +29,8 @@ class AudiosManager {
AudiosManager &operator=(AudiosManager &&) = delete;
~AudiosManager();
void memory_stats(vector<string> &output);
int32 get_audio_duration(FileId file_id) const;
tl_object_ptr<td_api::audio> get_audio_object(FileId file_id) const;

View File

@ -15,6 +15,7 @@
#include "td/utils/common.h"
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
@ -99,7 +100,13 @@ FileId AudiosManager::parse_audio(ParserT &parser) {
has_date = false;
}
if (has_file_name) {
parse(audio->file_name, parser);
string tmp_filename;
parse(tmp_filename, parser);
if (G()->get_option_boolean("disable_document_filenames")) {
audio->file_name = "0";
} else {
audio->file_name = tmp_filename;
}
}
if (has_mime_type) {
parse(audio->mime_type, parser);
@ -114,7 +121,11 @@ FileId AudiosManager::parse_audio(ParserT &parser) {
parse(audio->performer, parser);
}
if (has_minithumbnail) {
parse(audio->minithumbnail, parser);
string tmp_minithumbnail;
parse(tmp_minithumbnail, parser);
if (!G()->get_option_boolean("disable_minithumbnails")) {
audio->minithumbnail = tmp_minithumbnail;
}
}
if (has_thumbnail) {
parse(audio->thumbnail, parser);

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) {
CHECK(settings != nullptr);
AutoDownloadSettings result;
result.max_photo_file_size = settings->max_photo_file_size_;
result.max_video_file_size = settings->max_video_file_size_;
result.max_other_file_size = settings->max_other_file_size_;
if (G()->get_option_boolean("disable_auto_download")) {
result.max_photo_file_size = -1;
result.max_video_file_size = -1;
result.max_other_file_size = -1;
} else {
result.max_photo_file_size = settings->max_photo_file_size_;
result.max_video_file_size = settings->max_video_file_size_;
result.max_other_file_size = settings->max_other_file_size_;
}
result.video_upload_bitrate = settings->video_upload_bitrate_;
result.is_enabled = settings->is_auto_download_enabled_;
result.preload_large_videos = settings->preload_large_videos_;
result.preload_next_audio = settings->preload_next_audio_;
result.preload_stories = settings->preload_stories_;
if (G()->get_option_boolean("disable_auto_download")) {
result.is_enabled = false;
result.preload_large_videos = false;
result.preload_next_audio = false;
result.preload_stories = false;
} else {
result.is_enabled = settings->is_auto_download_enabled_;
result.preload_large_videos = settings->preload_large_videos_;
result.preload_next_audio = settings->preload_next_audio_;
result.preload_stories = settings->preload_stories_;
}
result.use_less_data_for_calls = settings->use_less_data_for_calls_;
return result;
}

View File

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

View File

@ -35,6 +35,8 @@ class BackgroundManager final : public Actor {
public:
BackgroundManager(Td *td, ActorShared<> parent);
void memory_stats(vector<string> &output);
void get_backgrounds(bool for_dark_theme, Promise<td_api::object_ptr<td_api::backgrounds>> &&promise);
void reload_background(BackgroundId background_id, int64 access_hash, Promise<Unit> &&promise);

View File

@ -38,6 +38,7 @@
#include "td/telegram/LinkManager.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/logevent/LogEventHelper.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/MessageSender.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/MessageTtl.h"
@ -8605,10 +8606,18 @@ class ContactsManager::UserLogEvent {
void ContactsManager::save_user(User *u, UserId user_id, bool from_binlog) {
if (!G()->use_chat_info_database()) {
if (u != nullptr && G()->get_option_boolean("receive_access_hashes", false)) {
send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateAccessHash>(get_user_access_hash_object(user_id, u)));
}
return;
}
CHECK(u != nullptr);
if (!u->is_saved || !u->is_status_saved) { // TODO more effective handling of !u->is_status_saved
if (u != nullptr && G()->get_option_boolean("receive_access_hashes", false)) {
send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateAccessHash>(get_user_access_hash_object(user_id, u)));
}
if (!from_binlog) {
auto log_event = UserLogEvent(user_id, u);
auto storer = get_log_event_storer(log_event);
@ -9184,10 +9193,18 @@ class ContactsManager::ChannelLogEvent {
void ContactsManager::save_channel(Channel *c, ChannelId channel_id, bool from_binlog) {
if (!G()->use_chat_info_database()) {
if (c != nullptr && G()->get_option_boolean("receive_access_hashes", false)) {
send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateAccessHash>(get_channel_access_hash_object(channel_id, c)));
}
return;
}
CHECK(c != nullptr);
if (!c->is_saved) {
if (c != nullptr && G()->get_option_boolean("receive_access_hashes", false)) {
send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateAccessHash>(get_channel_access_hash_object(channel_id, c)));
}
if (!from_binlog) {
auto log_event = ChannelLogEvent(channel_id, c);
auto storer = get_log_event_storer(log_event);
@ -16581,6 +16598,32 @@ tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id) con
return get_user_object(user_id, get_user(user_id));
}
tl_object_ptr<td_api::accessHash> ContactsManager::get_user_access_hash_object(UserId user_id, const User *u) const {
if (u == nullptr) {
return nullptr;
}
if (!u->is_min_access_hash && u->access_hash != 0) {
tl_object_ptr<td_api::AccessHashType> type = make_tl_object<td_api::accessHashTypeUser>();
DialogId dialog_id(user_id);
return make_tl_object<td_api::accessHash>(dialog_id.get(), std::move(type), u->access_hash);
} else {
return nullptr;
}
}
tl_object_ptr<td_api::accessHash> ContactsManager::get_channel_access_hash_object(ChannelId channel_id, const Channel *c) const {
if (c == nullptr) {
return nullptr;
}
if (c->access_hash != 0) {
tl_object_ptr<td_api::AccessHashType> type = make_tl_object<td_api::accessHashTypeChannel>();
DialogId dialog_id(channel_id);
return make_tl_object<td_api::accessHash>(dialog_id.get(), std::move(type), c->access_hash);
} else {
return nullptr;
}
}
tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id, const User *u) const {
if (u == nullptr) {
return nullptr;
@ -16994,4 +17037,102 @@ void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update
});
}
void ContactsManager::memory_stats(vector<string> &output) {
output.push_back("\"users_\":"); output.push_back(std::to_string(users_.calc_size()));
output.push_back(",");
output.push_back("\"users_full_\":"); output.push_back(std::to_string(users_full_.calc_size()));
output.push_back(",");
output.push_back("\"user_photos_\":"); output.push_back(std::to_string(user_photos_.calc_size()));
output.push_back(",");
output.push_back("\"unknown_users_\":"); output.push_back(std::to_string(unknown_users_.size()));
output.push_back(",");
output.push_back("\"pending_user_photos_\":"); output.push_back(std::to_string(pending_user_photos_.calc_size()));
output.push_back(",");
output.push_back("\"user_profile_photo_file_source_ids_\":"); output.push_back(std::to_string(user_profile_photo_file_source_ids_.calc_size()));
output.push_back(",");
output.push_back("\"my_photo_file_id_\":"); output.push_back(std::to_string(my_photo_file_id_.size()));
output.push_back(",");
output.push_back("\"chats_\":"); output.push_back(std::to_string(chats_.calc_size()));
output.push_back(",");
output.push_back("\"chats_full_\":"); output.push_back(std::to_string(chats_full_.calc_size()));
output.push_back(",");
output.push_back("\"unknown_chats_\":"); output.push_back(std::to_string(unknown_chats_.size()));
output.push_back(",");
output.push_back("\"chat_full_file_source_ids_\":"); output.push_back(std::to_string(chat_full_file_source_ids_.calc_size()));
output.push_back(",");
output.push_back("\"min_channels_\":"); output.push_back(std::to_string(min_channels_.calc_size()));
output.push_back(",");
output.push_back("\"channels_\":"); output.push_back(std::to_string(channels_.calc_size()));
output.push_back(",");
output.push_back("\"channels_full_\":"); output.push_back(std::to_string(channels_full_.calc_size()));
output.push_back(",");
output.push_back("\"unknown_channels_\":"); output.push_back(std::to_string(unknown_channels_.size()));
output.push_back(",");
output.push_back("\"channel_full_file_source_ids_\":"); output.push_back(std::to_string(channel_full_file_source_ids_.calc_size()));
output.push_back(",");
output.push_back("\"secret_chats_\":"); output.push_back(std::to_string(secret_chats_.calc_size()));
output.push_back(",");
output.push_back("\"unknown_secret_chats_\":"); output.push_back(std::to_string(unknown_secret_chats_.size()));
output.push_back(",");
output.push_back("\"secret_chats_with_user_\":"); output.push_back(std::to_string(secret_chats_with_user_.size()));
output.push_back(",");
output.push_back("\"invite_link_infos_\":"); output.push_back(std::to_string(invite_link_infos_.size()));
output.push_back(",");
output.push_back("\"dialog_access_by_invite_link_\":"); output.push_back(std::to_string(dialog_access_by_invite_link_.size()));
output.push_back(",");
output.push_back("\"load_user_from_database_queries_\":"); output.push_back(std::to_string(load_user_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_users_\":"); output.push_back(std::to_string(loaded_from_database_users_.size()));
output.push_back(",");
output.push_back("\"unavailable_user_fulls_\":"); output.push_back(std::to_string(unavailable_user_fulls_.size()));
output.push_back(",");
output.push_back("\"load_chat_from_database_queries_\":"); output.push_back(std::to_string(load_chat_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_chats_\":"); output.push_back(std::to_string(loaded_from_database_chats_.size()));
output.push_back(",");
output.push_back("\"unavailable_chat_fulls_\":"); output.push_back(std::to_string(unavailable_chat_fulls_.size()));
output.push_back(",");
output.push_back("\"load_channel_from_database_queries_\":"); output.push_back(std::to_string(load_channel_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_channels_\":"); output.push_back(std::to_string(loaded_from_database_channels_.size()));
output.push_back(",");
output.push_back("\"unavailable_channel_fulls_\":"); output.push_back(std::to_string(unavailable_channel_fulls_.size()));
output.push_back(",");
output.push_back("\"load_secret_chat_from_database_queries_\":"); output.push_back(std::to_string(load_secret_chat_from_database_queries_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_secret_chats_\":"); output.push_back(std::to_string(loaded_from_database_secret_chats_.size()));
output.push_back(",");
output.push_back("\"dialog_administrators_\":"); output.push_back(std::to_string(dialog_administrators_.size()));
output.push_back(",");
output.push_back("\"uploaded_profile_photos_\":"); output.push_back(std::to_string(uploaded_profile_photos_.size()));
output.push_back(",");
output.push_back("\"imported_contacts_\":"); output.push_back(std::to_string(imported_contacts_.size()));
output.push_back(",");
output.push_back("\"cached_channel_participants_\":"); output.push_back(std::to_string(cached_channel_participants_.size()));
output.push_back(",");
output.push_back("\"load_contacts_queries_\":"); output.push_back(std::to_string(load_contacts_queries_.size()));
output.push_back(",");
output.push_back("\"load_imported_contacts_queries_\":"); output.push_back(std::to_string(load_imported_contacts_queries_.size()));
output.push_back(",");
output.push_back("\"all_imported_contacts_\":"); output.push_back(std::to_string(all_imported_contacts_.size()));
output.push_back(",");
output.push_back("\"users_nearby_\":"); output.push_back(std::to_string(users_nearby_.size()));
output.push_back(",");
output.push_back("\"channels_nearby_\":"); output.push_back(std::to_string(channels_nearby_.size()));
output.push_back(",");
output.push_back("\"all_users_nearby_\":"); output.push_back(std::to_string(all_users_nearby_.size()));
output.push_back(",");
output.push_back("\"linked_channel_ids_\":"); output.push_back(std::to_string(linked_channel_ids_.calc_size()));
output.push_back(",");
output.push_back("\"restricted_user_ids_\":"); output.push_back(std::to_string(restricted_user_ids_.calc_size()));
output.push_back(",");
output.push_back("\"restricted_channel_ids_\":"); output.push_back(std::to_string(restricted_channel_ids_.calc_size()));
output.push_back(",");
output.push_back("\"next_all_imported_contacts_\":"); output.push_back(std::to_string(next_all_imported_contacts_.size()));
output.push_back(",");
output.push_back("\"imported_contact_user_ids_\":"); output.push_back(std::to_string(imported_contact_user_ids_.size()));
output.push_back(",");
output.push_back("\"unimported_contact_invites_\":"); output.push_back(std::to_string(unimported_contact_invites_.size()));
}
} // namespace td

View File

@ -83,6 +83,8 @@ class ContactsManager final : public Actor {
static UserId load_my_id();
void memory_stats(vector<string> &output);
static UserId get_user_id(const tl_object_ptr<telegram_api::User> &user);
static ChatId get_chat_id(const tl_object_ptr<telegram_api::Chat> &chat);
static ChannelId get_channel_id(const tl_object_ptr<telegram_api::Chat> &chat);
@ -1687,6 +1689,10 @@ class ContactsManager final : public Actor {
tl_object_ptr<td_api::user> get_user_object(UserId user_id, const User *u) const;
tl_object_ptr<td_api::accessHash> get_user_access_hash_object(UserId user_id, const User *u) const;
tl_object_ptr<td_api::accessHash> get_channel_access_hash_object(ChannelId channel_id, const Channel *c) const;
tl_object_ptr<td_api::userFullInfo> get_user_full_info_object(UserId user_id, const UserFull *user_full) const;
td_api::object_ptr<td_api::updateBasicGroup> get_update_basic_group_object(ChatId chat_id, const Chat *c);

View File

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

View File

@ -757,6 +757,10 @@ void DocumentsManager::merge_documents(FileId new_id, FileId old_id) {
LOG_STATUS(td_->file_manager_->merge(new_id, old_id));
}
void DocumentsManager::memory_stats(vector<string> &output) {
output.push_back("\"documents_\":"); output.push_back(std::to_string(documents_.calc_size()));
}
string DocumentsManager::get_document_search_text(FileId file_id) const {
auto document = get_document(file_id);
CHECK(document);

View File

@ -82,6 +82,7 @@ class DocumentsManager {
tl_object_ptr<td_api::document> get_document_object(FileId file_id, PhotoFormat thumbnail_format) const;
void memory_stats(vector<string> &output);
enum class Subtype : int32 { Background, Pattern, Ringtone, Story, Other };
Document on_get_document(RemoteDocument remote_document, DialogId owner_dialog_id,

View File

@ -14,6 +14,8 @@
#include "td/utils/tl_helpers.h"
#include "td/telegram/ConfigManager.h"
namespace td {
template <class StorerT>
@ -66,13 +68,25 @@ FileId DocumentsManager::parse_document(ParserT &parser) {
has_thumbnail = true;
}
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) {
parse(document->mime_type, parser);
}
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) {
parse(document->thumbnail, parser);

View File

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

View File

@ -94,6 +94,8 @@ class FileReferenceManager final : public Actor {
template <class ParserT>
FileSourceId parse_file_source(Td *td, ParserT &parser);
void memory_stats(vector<string> &output);
private:
struct Destination {
NodeId node_id;

View File

@ -160,6 +160,10 @@ bool Global::use_message_database() const {
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) {
if (error_code != 429) {
return 0;

View File

@ -71,6 +71,7 @@ class SponsoredMessageManager;
class StateManager;
class StickersManager;
class StorageManager;
class MemoryManager;
class StoryManager;
class Td;
class TdDb;
@ -108,6 +109,52 @@ class Global final : public ActorContext {
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_secure_files_dir() const {
@ -448,6 +495,13 @@ class Global final : public ActorContext {
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 {
return story_manager_;
}
@ -517,6 +571,8 @@ class Global final : public ActorContext {
bool use_message_database() const;
bool use_custom_database_format() const;
bool keep_media_order() const {
return use_file_database();
}
@ -653,6 +709,7 @@ class Global final : public ActorContext {
ActorId<SponsoredMessageManager> sponsored_message_manager_;
ActorId<StickersManager> stickers_manager_;
ActorId<StorageManager> storage_manager_;
ActorId<MemoryManager> memory_manager_;
ActorId<StoryManager> story_manager_;
ActorId<ThemeManager> theme_manager_;
ActorId<TimeZoneManager> time_zone_manager_;

View File

@ -8,6 +8,7 @@
#include "td/telegram/AccessRights.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/ConfigManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogAction.h"
#include "td/telegram/DialogActionManager.h"
@ -16,6 +17,7 @@
#include "td/telegram/DialogParticipantManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/MessageSender.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
@ -1004,6 +1006,18 @@ void GroupCallManager::tear_down() {
parent_.reset();
}
void GroupCallManager::memory_stats(vector<string> &output) {
output.push_back("\"group_call_participants_\":"); output.push_back(std::to_string(group_call_participants_.size()));
output.push_back(",");
output.push_back("\"group_call_recent_speakers_\":"); output.push_back(std::to_string(group_call_recent_speakers_.size()));
output.push_back(",");
output.push_back("\"group_calls_\":"); output.push_back(std::to_string(group_calls_.size()));
output.push_back(",");
output.push_back("\"input_group_call_ids_\":"); output.push_back(std::to_string(input_group_call_ids_.size()));
output.push_back(",");
output.push_back("\"pending_join_requests_\":"); output.push_back(std::to_string(pending_join_requests_.size()));
}
void GroupCallManager::on_update_group_call_participant_order_timeout_callback(void *group_call_manager_ptr,
int64 group_call_id_int) {
if (G()->close_flag()) {
@ -1163,7 +1177,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) {
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 add_group_call(input_group_call_id, dialog_id)->group_call_id;
@ -4167,7 +4181,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) {
if (td_->auth_manager_->is_bot()) {
if (G()->get_option_boolean("disable_group_calls") || td_->auth_manager_->is_bot()) {
return;
}
if (dialog_id != DialogId() && !dialog_id.is_valid()) {
@ -4875,18 +4889,27 @@ tl_object_ptr<td_api::updateGroupCallParticipant> GroupCallManager::get_update_g
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;
if (G()->get_option_boolean("disable_group_calls")) {
return;
}
send_closure(G()->td(), &Td::send_update,
get_update_group_call_object(group_call, get_recent_speakers(group_call, true)));
}
void GroupCallManager::send_update_group_call_participant(GroupCallId group_call_id,
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;
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,
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);
CHECK(group_call != nullptr && group_call->is_inited);
send_update_group_call_participant(group_call->group_call_id, participant, source);

View File

@ -39,6 +39,10 @@ class GroupCallManager final : public Actor {
GroupCallManager &operator=(GroupCallManager &&) = delete;
~GroupCallManager() final;
void memory_stats(vector<string> &output);
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_joined(InputGroupCallId input_group_call_id) const;

View File

@ -14,6 +14,7 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogManager.h"
#include "td/telegram/Document.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileType.h"
@ -2219,4 +2220,14 @@ void InlineQueriesManager::remove_recent_inline_bot(UserId bot_user_id, Promise<
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(recently_used_bot_user_ids_.size()));
output.push_back(",");
output.push_back("\"inline_query_results_\":"); output.push_back(std::to_string(inline_query_results_.size()));
output.push_back(",");
output.push_back("\"inline_message_contents_\":"); output.push_back(std::to_string(inline_message_contents_.size()));
output.push_back(",");
output.push_back("\"query_id_to_bot_user_id_\":"); output.push_back(std::to_string(query_id_to_bot_user_id_.size()));
}
} // namespace td

View File

@ -38,6 +38,8 @@ class InlineQueriesManager final : public Actor {
public:
InlineQueriesManager(Td *td, ActorShared<> parent);
void memory_stats(vector<string> &output);
void after_get_difference();
void answer_inline_query(int64 inline_query_id, bool is_personal,

View File

@ -0,0 +1,196 @@
//
// 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/secret_api.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/AccessRights.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/ConfigManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/Document.h"
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/WebPagesManager.h"
#include "td/telegram/StickersManager.h"
#include "td/telegram/VideoNotesManager.h"
#include "td/telegram/VideosManager.h"
#include "td/telegram/AudiosManager.h"
#include "td/telegram/AnimationsManager.h"
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/BackgroundManager.h"
#include "td/telegram/PollManager.h"
#include "td/telegram/InlineQueriesManager.h"
#include "td/telegram/files/FileType.h"
#include "td/telegram/Global.h"
#include "td/telegram/LanguagePackManager.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/net/MtprotoHeader.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
#include "td/actor/MultiPromise.h"
#include "td/actor/PromiseFuture.h"
#include "td/actor/SleepActor.h"
#include "td/db/SqliteKeyValue.h"
#include "td/db/SqliteKeyValueAsync.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/PathView.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/utf8.h"
#include <algorithm>
#include <limits>
#include <type_traits>
#include <unordered_set>
#include <numeric>
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("\"memory_stats\":{");
output.push_back("\"messages_manager_\":{");
td_->messages_manager_->memory_stats(output);
output.push_back("}");
output.push_back(",");
output.push_back("\"contacts_manager_\":{");
td_->contacts_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("}");
output.push_back(",");
output.push_back("\"stickers_manager_\":{");
td_->stickers_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("\"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("\"audios_manager_\":{");
td_->audios_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("\"file_manager_\":{");
td_->file_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("\"group_call_manager_\":{");
td_->group_call_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("\"inline_queries_manager_\":{");
td_->inline_queries_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("}");
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
}
} // namespace td

View File

@ -0,0 +1,63 @@
//
// 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;
Td *td_;
ActorShared<> parent_;
};
} // namespace td

View File

@ -7464,6 +7464,7 @@ void update_message_content_file_id_remote(MessageContent *content, FileId file_
}
FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td) {
if (!G()->get_option_boolean("disable_minithumbnails")) {
switch (content->get_type()) {
case MessageContentType::Animation:
return td->animations_manager_->get_animation_thumbnail_file_id(
@ -7489,6 +7490,7 @@ FileId get_message_content_thumbnail_file_id(const MessageContent *content, cons
return FileId();
default:
break;
}
}
return FileId();
}

View File

@ -42,6 +42,7 @@
#include "td/telegram/LinkManager.h"
#include "td/telegram/Location.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageDb.h"
#include "td/telegram/MessageEntity.h"
@ -5697,6 +5698,82 @@ void MessagesManager::update_message_reply_count(Dialog *d, MessageId message_id
}
}
void MessagesManager::memory_stats(vector<string> &output) {
output.push_back("\"being_sent_messages_\":"); output.push_back(std::to_string(this->being_sent_messages_.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_uploaded_dialog_photos_\":"); output.push_back(std::to_string(this->being_uploaded_dialog_photos_.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()));
output.push_back(",");
output.push_back("\"active_dialog_actions_\":"); output.push_back(std::to_string(this->active_dialog_actions_.size()));
output.push_back(",");
output.push_back("\"created_dialogs_\":"); output.push_back(std::to_string(this->created_dialogs_.size()));
output.push_back(",");
output.push_back("\"dialog_folders_\":"); output.push_back(std::to_string(this->dialog_folders_.size()));
output.push_back(",");
output.push_back("\"dialog_lists_\":"); output.push_back(std::to_string(this->dialog_lists_.size()));
output.push_back(",");
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("\"dialogs_\":"); output.push_back(std::to_string(this->dialogs_.calc_size()));
output.push_back(",");
output.push_back("\"found_call_messages_\":"); output.push_back(std::to_string(this->found_call_messages_.size()));
output.push_back(",");
output.push_back("\"found_common_dialogs_\":"); output.push_back(std::to_string(this->found_common_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("\"found_fts_messages_\":"); output.push_back(std::to_string(this->found_fts_messages_.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("\"get_dialogs_tasks_\":"); output.push_back(std::to_string(this->get_dialogs_tasks_.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("\"pending_message_imports_\":"); output.push_back(std::to_string(this->pending_message_imports_.size()));
output.push_back(",");
output.push_back("\"found_messages_\":"); output.push_back(std::to_string(this->found_messages_.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_public_dialogs_\":"); output.push_back(std::to_string(this->found_public_dialogs_.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("\"search_public_dialogs_queries_\":"); output.push_back(std::to_string(this->search_public_dialogs_queries_.size()));
output.push_back(",");
output.push_back("\"message_embedding_codes_\":"); output.push_back(std::to_string(this->message_embedding_codes_->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("\"get_dialog_message_by_date_results_\":"); output.push_back(std::to_string(this->get_dialog_message_by_date_results_.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("\"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("\"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("\"last_outgoing_forwarded_message_date_\":"); output.push_back(std::to_string(this->last_outgoing_forwarded_message_date_.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("\"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("\"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("\"channel_get_difference_retry_timeouts_\":"); output.push_back(std::to_string(this->channel_get_difference_retry_timeouts_.size()));
}
bool MessagesManager::have_dialog_scheduled_messages_in_memory(const Dialog *d) {
return d->scheduled_messages != nullptr && !d->scheduled_messages->scheduled_messages_.empty();
}
@ -9378,6 +9455,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) {
if (G()->get_option_boolean("ignore_server_deletes_and_reads", false)) {
return;
}
FlatHashMap<DialogId, vector<int64>, DialogIdHash> deleted_message_ids;
FlatHashMap<DialogId, bool, DialogIdHash> need_update_dialog_pos;
vector<unique_ptr<Message>> deleted_messages;
@ -10992,6 +11072,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) {
if (G()->get_option_boolean("ignore_server_deletes_and_reads", false)) {
return;
}
if (!message_id.is_valid() || !message_id.is_server()) {
LOG(ERROR) << "Incoming update tries to read content of " << message_id;
return;
@ -14696,7 +14779,8 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<te
}
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 {
@ -15218,7 +15302,9 @@ void MessagesManager::on_message_deleted(Dialog *d, Message *m, bool is_permanen
case DialogType::User:
case DialogType::Chat:
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;
case DialogType::Channel:
@ -28642,6 +28728,10 @@ void MessagesManager::send_update_chat_last_message_impl(const Dialog *d, const
return;
}
if (G()->get_option_boolean("ignore_update_chat_last_message")) {
return;
}
CHECK(d != nullptr);
LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_last_message from "
<< source;
@ -28786,10 +28876,12 @@ void MessagesManager::send_update_chat_read_inbox(const Dialog *d, bool force, c
LOG(INFO) << "Send updateChatReadInbox in " << d->dialog_id << "("
<< td_->dialog_manager_->get_dialog_title(d->dialog_id) << ") to " << d->server_unread_count << " + "
<< d->local_unread_count << " from " << source;
if (!G()->get_option_boolean("ignore_update_chat_read_inbox")) {
send_closure(G()->td(), &Td::send_update,
td_api::make_object<td_api::updateChatReadInbox>(
get_chat_id_object(d->dialog_id, "updateChatReadInbox"), d->last_read_inbox_message_id.get(),
d->server_unread_count + d->local_unread_count));
}
}
}
@ -37933,6 +38025,10 @@ void MessagesManager::suffix_load_query_ready(DialogId dialog_id) {
LOG(INFO) << "Finished suffix load query in " << 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_;
suffix_load_update_first_message_id(d, queries);
if (is_unchanged && queries->suffix_load_first_message_id_ == queries->suffix_load_query_message_id_) {
@ -38198,7 +38294,10 @@ void MessagesManager::set_sponsored_dialog(DialogId dialog_id, DialogSource sour
CHECK(sponsored_dialog_id_.is_valid());
sponsored_dialog_source_ = std::move(source);
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");
save_sponsored_dialog();
}
@ -38208,7 +38307,10 @@ void MessagesManager::set_sponsored_dialog(DialogId dialog_id, DialogSource sour
bool need_update_total_chat_count = false;
if (sponsored_dialog_id_.is_valid()) {
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);
sponsored_dialog_id_ = DialogId();
sponsored_dialog_source_ = DialogSource();
@ -38221,7 +38323,10 @@ void MessagesManager::set_sponsored_dialog(DialogId dialog_id, DialogSource sour
if (dialog_id.is_valid()) {
force_create_dialog(dialog_id, "set_sponsored_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));
if (is_dialog_sponsored(d)) {
need_update_total_chat_count = !need_update_total_chat_count;

View File

@ -143,6 +143,8 @@ class MessagesManager final : public Actor {
static bool is_invalid_poll_message(const telegram_api::Message *message);
void memory_stats(vector<string> &output);
static int32 get_message_date(const tl_object_ptr<telegram_api::Message> &message_ptr);
void on_get_empty_messages(DialogId dialog_id, const vector<MessageId> &empty_message_ids);

View File

@ -166,7 +166,11 @@ void NotificationManager::on_flush_pending_updates_timeout_callback(void *notifi
}
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();
}
}
StringBuilder &operator<<(StringBuilder &string_builder, const NotificationManager::ActiveNotificationsUpdate &update) {

View File

@ -797,6 +797,26 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
if (set_boolean_option("disable_time_adjustment_protection")) {
return;
}
// Start TDLight options
if (set_boolean_option("disable_document_filenames")) {
return;
}
if (set_boolean_option("disable_minithumbnails")) {
return;
}
if (set_boolean_option("disable_notifications")) {
return;
}
if (set_boolean_option("disable_group_calls")) {
return;
}
if (set_boolean_option("disable_auto_download")) {
return;
}
// End TDLight options
if (set_boolean_option("disable_persistent_network_statistics")) {
return;
}
if (!is_bot && set_boolean_option("disable_top_chats")) {
return;
}
@ -822,6 +842,20 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
if (set_boolean_option("ignore_platform_restrictions")) {
return;
}
// Start TDLight options
if (set_boolean_option("ignore_server_deletes_and_reads")) {
return;
}
if (set_boolean_option("ignore_update_chat_last_message")) {
return;
}
if (set_boolean_option("ignore_update_chat_read_inbox")) {
return;
}
if (set_boolean_option("ignore_update_user_chat_action")) {
return;
}
// End TDLight options
if (set_boolean_option("is_emulator")) {
return;
}
@ -905,6 +939,11 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
if (set_boolean_option("reuse_uploaded_photos_by_hash")) {
return;
}
// Start TDLight options
if (set_boolean_option("receive_access_hashes")) {
return;
}
// End TDLight options
break;
case 's':
if (set_integer_option("storage_max_files_size")) {

View File

@ -55,7 +55,9 @@ ProfilePhoto get_profile_photo(FileManager *file_manager, UserId user_id, int64
result.has_animation = profile_photo->has_video_;
result.is_personal = profile_photo->personal_;
result.id = profile_photo->photo_id_;
result.minithumbnail = profile_photo->stripped_thumb_.as_slice().str();
if (!G()->get_option_boolean("disable_minithumbnails")) {
result.minithumbnail = profile_photo->stripped_thumb_.as_slice().str();
}
result.small_file_id =
register_photo_size(file_manager, PhotoSizeSource::dialog_photo(DialogId(user_id), user_access_hash, false),
result.id, 0 /*access_hash*/, "" /*file_reference*/, DialogId(), 0 /*file_size*/, dc_id,
@ -333,7 +335,11 @@ Photo get_photo(Td *td, tl_object_ptr<telegram_api::photo> &&photo, DialogId own
}
res.photos.push_back(std::move(size));
} else {
res.minithumbnail = std::move(photo_size.get<1>());
if (G()->get_option_boolean("disable_minithumbnails")) {
res.minithumbnail = "";
} else {
res.minithumbnail = std::move(photo_size.get<1>());
}
}
}

View File

@ -23,14 +23,14 @@ void store(const DialogPhoto &dialog_photo, StorerT &storer) {
BEGIN_STORE_FLAGS();
STORE_FLAG(has_file_ids);
STORE_FLAG(dialog_photo.has_animation);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(!G()->get_option_boolean("disable_minithumbnails") && has_minithumbnail);
STORE_FLAG(dialog_photo.is_personal);
END_STORE_FLAGS();
if (has_file_ids) {
store(dialog_photo.small_file_id, storer);
store(dialog_photo.big_file_id, storer);
}
if (has_minithumbnail) {
if (!G()->get_option_boolean("disable_minithumbnails") && has_minithumbnail) {
store(dialog_photo.minithumbnail, storer);
}
}
@ -52,7 +52,11 @@ void parse(DialogPhoto &dialog_photo, ParserT &parser) {
parse(dialog_photo.big_file_id, parser);
}
if (has_minithumbnail) {
parse(dialog_photo.minithumbnail, parser);
std::basic_string<char> minithumbnail;
parse(minithumbnail, parser);
if (!G()->get_option_boolean("disable_minithumbnails")) {
dialog_photo.minithumbnail = minithumbnail;
}
}
}
@ -75,7 +79,7 @@ void store(const Photo &photo, StorerT &storer) {
bool has_sticker_photo_size = photo.sticker_photo_size != nullptr;
BEGIN_STORE_FLAGS();
STORE_FLAG(photo.has_stickers);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(!G()->get_option_boolean("disable_minithumbnails") && has_minithumbnail);
STORE_FLAG(has_animations);
STORE_FLAG(has_sticker_photo_size);
END_STORE_FLAGS();
@ -85,7 +89,7 @@ void store(const Photo &photo, StorerT &storer) {
if (photo.has_stickers) {
store(photo.sticker_file_ids, storer);
}
if (has_minithumbnail) {
if (!G()->get_option_boolean("disable_minithumbnails") && has_minithumbnail) {
store(photo.minithumbnail, storer);
}
if (has_animations) {
@ -116,7 +120,11 @@ void parse(Photo &photo, ParserT &parser) {
parse(photo.sticker_file_ids, parser);
}
if (has_minithumbnail) {
parse(photo.minithumbnail, parser);
std::basic_string<char> minithumbnail;
parse(minithumbnail, parser);
if (!G()->get_option_boolean("disable_minithumbnails")) {
photo.minithumbnail = minithumbnail;
}
}
if (has_animations) {
parse(photo.animations, parser);

View File

@ -46,6 +46,9 @@ bool need_update_dialog_photo_minithumbnail(const string &from, const string &to
}
td_api::object_ptr<td_api::minithumbnail> get_minithumbnail_object(const string &packed) {
if (G()->get_option_boolean("disable_minithumbnails")) {
return nullptr;
}
if (packed.size() < 3) {
return nullptr;
}
@ -195,11 +198,23 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
case telegram_api::photoStrippedSize::ID: {
auto size = move_tl_object_as<telegram_api::photoStrippedSize>(size_ptr);
if (format != PhotoFormat::Jpeg) {
LOG(ERROR) << "Receive unexpected JPEG minithumbnail in photo " << id << " from " << source << " of format "
<< format;
return std::move(res);
if (G()->get_option_boolean("disable_minithumbnails")) {
LOG(DEBUG) << "Receive unexpected JPEG minithumbnail";
} else {
LOG(ERROR) << "Receive unexpected JPEG minithumbnail in photo " << id << " from " << source << " of format "
<< format;
}
if (G()->get_option_boolean("disable_minithumbnails")) {
return std::string("");
} else {
return std::move(res);
}
}
if (G()->get_option_boolean("disable_minithumbnails")) {
return std::string("");
} else {
return size->bytes_.as_slice().str();
}
return size->bytes_.as_slice().str();
}
case telegram_api::photoSizeProgressive::ID: {
auto size = move_tl_object_as<telegram_api::photoSizeProgressive>(size_ptr);

View File

@ -15,6 +15,8 @@
#include "td/telegram/DialogManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/logevent/LogEventHelper.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessageSender.h"
#include "td/telegram/MessagesManager.h"
@ -1967,4 +1969,16 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
}
}
void PollManager::memory_stats(vector<string> &output) {
output.push_back("\"polls_\":"); output.push_back(std::to_string(polls_.calc_size()));
output.push_back(",");
output.push_back("\"pending_answers_\":"); output.push_back(std::to_string(pending_answers_.size()));
output.push_back(",");
output.push_back("\"poll_voters_\":"); output.push_back(std::to_string(poll_voters_.size()));
output.push_back(",");
output.push_back("\"loaded_from_database_polls_\":"); output.push_back(std::to_string(loaded_from_database_polls_.size()));
output.push_back(",");
output.push_back("\"being_closed_polls_\":"); output.push_back(std::to_string(being_closed_polls_.size()));
}
} // namespace td

View File

@ -47,6 +47,8 @@ class PollManager final : public Actor {
PollManager &operator=(PollManager &&) = delete;
~PollManager() final;
void memory_stats(vector<string> &output);
static bool is_local_poll_id(PollId poll_id);
PollId create_poll(string &&question, vector<string> &&options, bool is_anonymous, bool allow_multiple_answers,

View File

@ -10149,4 +10149,30 @@ void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update
}
}
void StickersManager::memory_stats(vector<string> &output) {
output.push_back("\"found_sticker_sets_\":"); output.push_back(std::to_string(found_sticker_sets_.size()));
output.push_back(",");
output.push_back("\"archived_sticker_set_ids_\":"); output.push_back(std::to_string(archived_sticker_set_ids_->size()));
output.push_back(",");
output.push_back("\"attached_sticker_sets_\":"); output.push_back(std::to_string(attached_sticker_sets_.size()));
output.push_back(",");
output.push_back("\"favorite_sticker_file_ids_\":"); output.push_back(std::to_string(favorite_sticker_file_ids_.size()));
output.push_back(",");
output.push_back("\"favorite_sticker_ids_\":"); output.push_back(std::to_string(favorite_sticker_ids_.size()));
output.push_back(",");
output.push_back("\"installed_sticker_set_ids_\":"); output.push_back(std::to_string(installed_sticker_set_ids_->size()));
output.push_back(",");
output.push_back("\"recent_sticker_file_ids_\":"); output.push_back(std::to_string(recent_sticker_file_ids_->size()));
output.push_back(",");
output.push_back("\"recent_sticker_ids_\":"); output.push_back(std::to_string(recent_sticker_ids_->size()));
output.push_back(",");
output.push_back("\"short_name_to_sticker_set_id_\":"); output.push_back(std::to_string(short_name_to_sticker_set_id_.calc_size()));
output.push_back(",");
output.push_back("\"special_sticker_sets_\":"); output.push_back(std::to_string(special_sticker_sets_.size()));
output.push_back(",");
output.push_back("\"sticker_sets_\":"); output.push_back(std::to_string(sticker_sets_.calc_size()));
output.push_back(",");
output.push_back("\"stickers_\":"); output.push_back(std::to_string(stickers_.calc_size()));
}
} // namespace td

View File

@ -57,6 +57,8 @@ class StickersManager final : public Actor {
public:
static constexpr int64 GREAT_MINDS_SET_ID = 1842540969984001;
void memory_stats(vector<string> &output);
static vector<StickerSetId> convert_sticker_set_ids(const vector<int64> &sticker_set_ids);
static vector<int64> convert_sticker_set_ids(const vector<StickerSetId> &sticker_set_ids);

View File

@ -143,6 +143,7 @@
#include "td/telegram/StickersManager.h"
#include "td/telegram/StickerType.h"
#include "td/telegram/StorageManager.h"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/StoryId.h"
#include "td/telegram/StoryListId.h"
#include "td/telegram/StoryManager.h"
@ -2850,6 +2851,7 @@ bool Td::is_preauthentication_request(int32 id) {
case td_api::getStorageStatistics::ID:
case td_api::getStorageStatisticsFast::ID:
case td_api::getDatabaseStatistics::ID:
case td_api::getMemoryStatistics::ID:
case td_api::setNetworkType::ID:
case td_api::getNetworkStatistics::ID:
case td_api::addNetworkStatistics::ID:
@ -2902,12 +2904,15 @@ vector<td_api::object_ptr<td_api::Update>> Td::get_fake_current_state() const {
return updates;
}
DbKey Td::as_db_key(string key) {
DbKey Td::as_db_key(string key, bool custom_db) {
// Database will still be effectively not encrypted, but
// 1. SQLite database will be protected from corruption, because that's how sqlcipher works
// 2. security through obscurity
// 3. no need for reencryption of SQLite database
if (key.empty()) {
if (custom_db) {
return DbKey::empty();
}
return DbKey::raw_key("cucumber");
}
return DbKey::raw_key(std::move(key));
@ -3262,9 +3267,20 @@ void Td::dec_actor_refcnt() {
close_flag_ = 4;
} else if (close_flag_ == 4) {
on_closed();
#ifdef __linux__
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__)
malloc_trim(0);
#endif
#endif
} else {
UNREACHABLE();
}
} else {
#ifdef __linux__
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__)
malloc_trim(0);
#endif
#endif
}
}
@ -3953,6 +3969,9 @@ void Td::init_managers() {
stickers_manager_ = make_unique<StickersManager>(this, create_reference());
stickers_manager_actor_ = register_actor("StickersManager", stickers_manager_.get());
G()->set_stickers_manager(stickers_manager_actor_.get());
memory_manager_ = make_unique<MemoryManager>(this, create_reference());
memory_manager_actor_ = register_actor("MemoryManager", memory_manager_.get());
G()->set_memory_manager(memory_manager_actor_.get());
story_manager_ = make_unique<StoryManager>(this, create_reference());
story_manager_actor_ = register_actor("StoryManager", story_manager_.get());
G()->set_story_manager(story_manager_actor_.get());
@ -4149,8 +4168,9 @@ Result<std::pair<Td::Parameters, TdDb::Parameters>> Td::get_parameters(
result.first.api_hash_ = std::move(parameters->api_hash_);
result.first.use_secret_chats_ = parameters->use_secret_chats_;
result.second.encryption_key_ = as_db_key(std::move(parameters->database_encryption_key_));
result.second.database_directory_ = std::move(parameters->database_directory_);
result.second.encryption_key_ = as_db_key(std::move(parameters->database_encryption_key_), Global::get_use_custom_database(parameters->database_directory_));
result.second.database_directory_ = Global::get_database_directory_path(parameters->database_directory_);
result.second.use_custom_database_format_ = Global::get_use_custom_database(parameters->database_directory_);
result.second.files_directory_ = std::move(parameters->files_directory_);
result.second.is_test_dc_ = parameters->use_test_dc_;
result.second.use_file_database_ = parameters->use_file_database_;
@ -4197,7 +4217,7 @@ void Td::on_request(uint64 id, const td_api::setTdlibParameters &request) {
void Td::on_request(uint64 id, td_api::setDatabaseEncryptionKey &request) {
CREATE_OK_REQUEST_PROMISE();
G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_)), std::move(promise));
G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_), G()->use_custom_database_format()), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getAuthorizationState &request) {
@ -4328,6 +4348,7 @@ void Td::on_request(uint64 id, const td_api::getCurrentState &request) {
dialog_filter_manager_->get_current_state(updates);
memory_manager_->get_current_state(updates);
messages_manager_->get_current_state(updates);
dialog_participant_manager_->get_current_state(updates);
@ -4884,6 +4905,18 @@ void Td::on_request(uint64 id, td_api::getDatabaseStatistics &request) {
});
send_closure(storage_manager_, &StorageManager::get_database_stats, std::move(query_promise));
}
void Td::on_request(uint64 id, td_api::getMemoryStatistics &request) {
CREATE_REQUEST_PROMISE();
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<MemoryStats> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
promise.set_value(result.ok().get_memory_statistics_object());
}
});
memory_manager_->get_memory_stats(request.full_, std::move(query_promise));
}
void Td::on_request(uint64 id, td_api::optimizeStorage &request) {
std::vector<FileType> file_types;

View File

@ -31,6 +31,12 @@
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#ifdef __linux__
#include <malloc.h>
#endif
#ifdef _WIN32
#include <malloc.h>
#endif
#include <memory>
#include <unordered_map>
#include <utility>
@ -91,6 +97,7 @@ class StateManager;
class StatisticsManager;
class StickersManager;
class StorageManager;
class MemoryManager;
class StoryManager;
class ThemeManager;
class TimeZoneManager;
@ -257,6 +264,8 @@ class Td final : public Actor {
ActorOwn<VideoNotesManager> video_notes_manager_actor_;
unique_ptr<VoiceNotesManager> voice_notes_manager_;
ActorOwn<VoiceNotesManager> voice_notes_manager_actor_;
unique_ptr<MemoryManager> memory_manager_;
ActorOwn<MemoryManager> memory_manager_actor_;
unique_ptr<WebPagesManager> web_pages_manager_;
ActorOwn<WebPagesManager> web_pages_manager_actor_;
@ -654,6 +663,8 @@ class Td final : public Actor {
void on_request(uint64 id, td_api::getDatabaseStatistics &request);
void on_request(uint64 id, td_api::getMemoryStatistics &request);
void on_request(uint64 id, td_api::optimizeStorage &request);
void on_request(uint64 id, td_api::getNetworkStatistics &request);
@ -1906,7 +1917,7 @@ class Td final : public Actor {
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request);
static td_api::object_ptr<td_api::Object> do_static_request(td_api::testReturnError &request);
static DbKey as_db_key(string key);
static DbKey as_db_key(string key, bool custom_db);
struct Parameters {
int32 api_id_ = 0;

View File

@ -374,8 +374,16 @@ Status TdDb::init_sqlite(const Parameters &parameters, const DbKey &key, const D
sql_connection_ = std::make_shared<SqliteConnectionSafe>(sql_database_path, key, db_instance.get_cipher_version());
sql_connection_->set(std::move(db_instance));
auto &db = sql_connection_->get();
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
if (parameters.use_custom_database_format_) {
TRY_STATUS(db.exec("PRAGMA journal_mode=OFF"));
TRY_STATUS(db.exec("PRAGMA synchronous=OFF"))
TRY_STATUS(db.exec("PRAGMA temp_store=MEMORY"));
TRY_STATUS(db.exec("PRAGMA secure_delete=0"));
TRY_STATUS(db.exec("PRAGMA mmap_size=30000000000"));
} else {
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
}
// Init databases
// Do initialization once and before everything else to avoid "database is locked" error.

View File

@ -60,6 +60,7 @@ class TdDb {
bool use_file_database_ = false;
bool use_chat_info_database_ = false;
bool use_message_database_ = false;
bool use_custom_database_format_ = false;
};
struct OpenedDatabase {
@ -117,6 +118,10 @@ class TdDb {
return was_dialog_db_created_;
}
bool use_custom_database_format() const {
return parameters_.use_custom_database_format_;
}
std::shared_ptr<FileDbInterface> get_file_db_shared();
std::shared_ptr<SqliteConnectionSafe> &get_sqlite_connection_safe();
#define get_binlog() get_binlog_impl(__FILE__, __LINE__)

View File

@ -82,8 +82,10 @@ FileId VideoNotesManager::on_get_video_note(unique_ptr<VideoNote> new_video_note
v->dimensions = new_video_note->dimensions;
v->waveform = std::move(new_video_note->waveform);
}
if (v->minithumbnail != new_video_note->minithumbnail) {
v->minithumbnail = std::move(new_video_note->minithumbnail);
if (!G()->get_option_boolean("disable_minithumbnails")) {
if (v->minithumbnail != new_video_note->minithumbnail) {
v->minithumbnail = std::move(new_video_note->minithumbnail);
}
}
if (v->thumbnail != new_video_note->thumbnail) {
if (!v->thumbnail.file_id.is_valid()) {
@ -169,7 +171,7 @@ void VideoNotesManager::create_video_note(FileId file_id, string minithumbnail,
LOG(INFO) << "Receive wrong video note dimensions " << dimensions;
}
v->waveform = std::move(waveform);
if (!td_->auth_manager_->is_bot()) {
if (!td_->auth_manager_->is_bot() && !G()->get_option_boolean("disable_minithumbnails")) {
v->minithumbnail = std::move(minithumbnail);
}
v->thumbnail = std::move(thumbnail);
@ -262,4 +264,8 @@ tl_object_ptr<telegram_api::InputMedia> VideoNotesManager::get_input_media(
return nullptr;
}
void VideoNotesManager::memory_stats(vector<string> &output) {
output.push_back("\"video_notes_\":"); output.push_back(std::to_string(video_notes_.calc_size()));
}
} // namespace td

View File

@ -33,6 +33,8 @@ class VideoNotesManager final : public Actor {
VideoNotesManager &operator=(VideoNotesManager &&) = delete;
~VideoNotesManager() final;
void memory_stats(vector<string> &output);
int32 get_video_note_duration(FileId file_id) const;
TranscriptionInfo *get_video_note_transcription_info(FileId file_id, bool allow_creation);

View File

@ -96,8 +96,10 @@ FileId VideosManager::on_get_video(unique_ptr<Video> new_video, bool replace) {
LOG(DEBUG) << "Video " << file_id << " file name has changed";
v->file_name = std::move(new_video->file_name);
}
if (v->minithumbnail != new_video->minithumbnail) {
v->minithumbnail = std::move(new_video->minithumbnail);
if (!G()->get_option_boolean("disable_minithumbnails")) {
if (v->minithumbnail != new_video->minithumbnail) {
v->minithumbnail = std::move(new_video->minithumbnail);
}
}
if (v->thumbnail != new_video->thumbnail) {
if (!v->thumbnail.file_id.is_valid()) {
@ -198,7 +200,7 @@ void VideosManager::create_video(FileId file_id, string minithumbnail, PhotoSize
v->duration = max(duration, 0);
v->precise_duration = duration == 0 ? 0.0 : clamp(precise_duration, duration - 1.0, duration + 0.0);
v->dimensions = dimensions;
if (!td_->auth_manager_->is_bot()) {
if (!td_->auth_manager_->is_bot() && G()->get_option_boolean("disable_minithumbnails")) {
v->minithumbnail = std::move(minithumbnail);
}
v->thumbnail = std::move(thumbnail);
@ -332,4 +334,8 @@ string VideosManager::get_video_search_text(FileId file_id) const {
return video->file_name;
}
void VideosManager::memory_stats(vector<string> &output) {
output.push_back("\"videos_\":"); output.push_back(std::to_string(videos_.calc_size()));
}
} // namespace td

View File

@ -30,6 +30,8 @@ class VideosManager {
VideosManager &operator=(VideosManager &&) = delete;
~VideosManager();
void memory_stats(vector<string> &output);
int32 get_video_duration(FileId file_id) const;
td_api::object_ptr<td_api::video> get_video_object(FileId file_id) const;

View File

@ -67,12 +67,29 @@ FileId VideosManager::parse_video(ParserT &parser) {
PARSE_FLAG(has_precise_duration);
PARSE_FLAG(video->is_animation);
END_PARSE_FLAGS();
parse(video->file_name, parser);
string tmp_filename;
parse(tmp_filename, parser);
parse(video->mime_type, parser);
if ( G()->get_option_boolean("disable_document_filenames") && (
video->mime_type.rfind("image/") == 0 ||
video->mime_type.rfind("video/") == 0 ||
video->mime_type.rfind("audio/") == 0)) {
video->file_name = "0";
} else {
video->file_name = tmp_filename;
}
parse(video->duration, parser);
parse(video->dimensions, parser);
if (parser.version() >= static_cast<int32>(Version::SupportMinithumbnails)) {
parse(video->minithumbnail, parser);
string tmp_minithumbnail;
parse(tmp_minithumbnail, parser);
if (!G()->get_option_boolean("disable_minithumbnails")) {
video->minithumbnail = tmp_minithumbnail;
}
}
parse(video->thumbnail, parser);
parse(video->file_id, parser);

View File

@ -1959,4 +1959,17 @@ vector<FileId> WebPagesManager::get_web_page_file_ids(const WebPage *web_page) c
return result;
}
void WebPagesManager::memory_stats(vector<string> &output) {
output.push_back("\"web_pages_\":"); output.push_back(std::to_string(web_pages_.calc_size()));
output.push_back(",");
output.push_back("\"loaded_from_database_web_pages_\":"); output.push_back(std::to_string(loaded_from_database_web_pages_.size()));
output.push_back(",");
output.push_back("\"web_page_messages_\":"); output.push_back(std::to_string(web_page_messages_.size()));
output.push_back(",");
output.push_back("\"url_to_web_page_id_\":"); output.push_back(std::to_string(url_to_web_page_id_.size()));
output.push_back(",");
output.push_back("\"url_to_file_source_id_\":"); output.push_back(std::to_string(url_to_file_source_id_.size()));
}
} // namespace td

View File

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

View File

@ -14,6 +14,7 @@
#include "td/telegram/files/FileLoaderUtils.h"
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/FileLocation.hpp"
#include "td/telegram/MemoryManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/misc.h"
@ -879,8 +880,8 @@ FileManager::FileManager(unique_ptr<Context> context) : context_(std::move(conte
}
parent_ = context_->create_reference();
next_file_id();
next_file_node_id();
next_file_id();
next_file_node_id();
G()->td_db()->with_db_path([bad_paths = &bad_paths_](CSlice path) { bad_paths->insert(path.str()); });
}
@ -4172,6 +4173,16 @@ void FileManager::hangup() {
stop();
}
void FileManager::memory_stats(vector<string> &output) {
output.push_back("\"file_id_info_\":"); output.push_back(std::to_string(file_id_info_.size()));
output.push_back(",");
output.push_back("\"file_nodes_\":"); output.push_back(std::to_string(file_nodes_.size()));
output.push_back(",");
output.push_back("\"file_hash_to_file_id_\":"); output.push_back(std::to_string(file_hash_to_file_id_.calc_size()));
output.push_back(",");
output.push_back("\"empty_file_ids_\":"); output.push_back(std::to_string(empty_file_ids_.size()));
}
void FileManager::tear_down() {
parent_.reset();

View File

@ -378,6 +378,8 @@ class FileView {
class FileManager final : public FileLoadManager::Callback {
public:
void memory_stats(vector<string> &output);
static constexpr int64 KEEP_DOWNLOAD_LIMIT = -1;
static constexpr int64 KEEP_DOWNLOAD_OFFSET = -1;
static constexpr int64 IGNORE_DOWNLOAD_LIMIT = -2;

View File

@ -395,7 +395,7 @@ if (WIN32)
target_link_libraries(tdutils PRIVATE ws2_32 Mswsock Normaliz psapi)
endif()
if (NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
target_link_libraries(tdutils PRIVATE shell32)
target_link_libraries(tdutils PRIVATE shell32 crypt32)
endif()
endif()

View File

@ -238,6 +238,18 @@ static DefaultLog default_log;
LogInterface *const default_log_interface = &default_log;
LogInterface *log_interface = default_log_interface;
static OnFatalErrorCallback on_fatal_error_callback = nullptr;
static bool use_death_handler = true;
void set_log_fatal_error_callback(OnFatalErrorCallback callback) {
on_fatal_error_callback = callback;
}
void set_log_disable_death_handler(bool disabled) {
use_death_handler = !disabled;
}
void process_fatal_error(CSlice message) {
if (0 <= max_callback_verbosity_level.load(std::memory_order_relaxed)) {
auto callback = on_log_message_callback.load(std::memory_order_relaxed);

View File

@ -173,6 +173,10 @@ class LogInterface {
extern LogInterface *const default_log_interface;
extern LogInterface *log_interface;
using OnFatalErrorCallback = void (*)(CSlice message);
void set_log_fatal_error_callback(OnFatalErrorCallback callback);
void set_log_disable_death_handler(bool disabled);
[[noreturn]] void process_fatal_error(CSlice message);
using OnLogMessageCallback = void (*)(int verbosity_level, CSlice message);