Merge remote-tracking branch 'td/master' into dev

This commit is contained in:
Andrea Cavalli 2021-05-27 00:50:41 +02:00
commit 2c77e82300
184 changed files with 1154 additions and 539 deletions

View File

@ -13,6 +13,7 @@
#include "td/utils/common.h"
#include "td/utils/crypto.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#if TD_MSVC
#pragma comment(linker, "/STACK:16777216")

View File

@ -8,10 +8,10 @@
#include "td/utils/common.h"
#include "td/utils/crypto.h"
#include "td/utils/logging.h"
#include "td/utils/port/thread.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/UInt.h"
#include <openssl/evp.h>

View File

@ -21,6 +21,7 @@
#include "td/utils/common.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"

View File

@ -15,6 +15,7 @@
#include "td/utils/port/Stat.h"
#include "td/utils/port/thread.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/telegram_api.hpp"

View File

@ -12,6 +12,7 @@
#include "td/utils/filesystem.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/TsCerr.h"
#include <algorithm>
#include <cstdlib>

View File

@ -16,6 +16,7 @@
#include "td/utils/port/thread.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Time.h"

View File

@ -101,7 +101,10 @@ static constexpr jint JAVA_VERSION = JNI_VERSION_1_6;
static JavaVM *java_vm;
static jclass log_class;
static void on_fatal_error(const char *error_message) {
static void on_log_message(int verbosity_level, const char *error_message) {
if (verbosity_level != 0) {
return;
}
auto env = td::jni::get_jni_env(java_vm, JAVA_VERSION);
if (env == nullptr) {
return;
@ -154,7 +157,7 @@ static jint register_native(JavaVM *vm) {
td::jni::init_vars(env, PACKAGE_NAME);
td::td_api::Object::init_jni_vars(env, PACKAGE_NAME);
td::td_api::Function::init_jni_vars(env, PACKAGE_NAME);
td::Log::set_fatal_error_callback(on_fatal_error);
td::ClientManager::set_log_message_callback(0, on_log_message);
return JAVA_VERSION;
}

View File

@ -34,16 +34,17 @@ _td_execute = tdjson.td_execute
_td_execute.restype = c_char_p
_td_execute.argtypes = [c_char_p]
fatal_error_callback_type = CFUNCTYPE(None, c_char_p)
log_message_callback_type = CFUNCTYPE(None, c_int, c_char_p)
_td_set_log_fatal_error_callback = tdjson.td_set_log_fatal_error_callback
_td_set_log_fatal_error_callback.restype = None
_td_set_log_fatal_error_callback.argtypes = [fatal_error_callback_type]
_td_set_log_message_callback = tdjson.td_set_log_message_callback
_td_set_log_message_callback.restype = None
_td_set_log_message_callback.argtypes = [c_int, log_message_callback_type]
# initialize TDLib log with desired parameters
def on_fatal_error_callback(error_message):
print('TDLib fatal error: ', error_message)
sys.stdout.flush()
def on_log_message_callback(verbosity_level, message):
if verbosity_level == 0:
print('TDLib fatal error: ', message)
sys.stdout.flush()
def td_execute(query):
query = json.dumps(query).encode('utf-8')
@ -52,8 +53,8 @@ def td_execute(query):
result = json.loads(result.decode('utf-8'))
return result
c_on_fatal_error_callback = fatal_error_callback_type(on_fatal_error_callback)
_td_set_log_fatal_error_callback(c_on_fatal_error_callback)
c_on_log_message_callback = log_message_callback_type(on_log_message_callback)
_td_set_log_message_callback(2, c_on_log_message_callback)
# setting TDLib log verbosity level to 1 (errors)
print(str(td_execute({'@type': 'setLogVerbosityLevel', 'new_verbosity_level': 1, '@extra': 1.01234})).encode('utf-8'))

View File

@ -29,6 +29,7 @@ namespace TdApp
Td.Client.Execute(new TdApi.SetLogVerbosityLevel(0));
Td.Client.Execute(new TdApi.SetLogStream(new TdApi.LogStreamFile(Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "log"), 1 << 27, false)));
Td.Client.SetLogMessageCallback(100, LogMessageCallback);
System.Threading.Tasks.Task.Run(() =>
{
@ -63,6 +64,14 @@ namespace TdApp
});
}
private void LogMessageCallback(int verbosity_level, String str)
{
if (verbosity_level < 0) {
return;
}
Print(verbosity_level + ": " + str);
}
private Td.Client _client;
private void AcceptCommand(String command)
@ -107,6 +116,12 @@ namespace TdApp
AcceptCommand(command);
_client.Send(new TdApi.CheckAuthenticationPassword(args[1]), _handler);
}
else if (command.StartsWith("alm"))
{
var args = command.Split(" ".ToCharArray(), 3);
AcceptCommand(command);
_client.Send(new TdApi.AddLogMessage(Int32.Parse(args[1]), args[2]), _handler);
}
else if (command.StartsWith("gco"))
{
var args = command.Split(" ".ToCharArray(), 2);

View File

@ -2,7 +2,8 @@ param (
[string]$vcpkg_root = $(throw "-vcpkg_root=<path to vcpkg> is required"),
[string]$arch = "",
[string]$mode = "all",
[string]$compress = "7z"
[string]$compress = "7z",
[switch]$release_only = $false
)
$ErrorActionPreference = "Stop"
@ -13,6 +14,11 @@ $arch_list = @( "x86", "x64", "ARM" )
if ($arch) {
$arch_list = @(, $arch)
}
$config_list = @( "Debug", "Release" )
if ($release_only) {
$config_list = @(, "RelWithDebInfo")
}
$targets = @{ Debug = "Debug"; Release = "Retail"; RelWithDebInfo = "CommonConfiguration"}
$td_root = Resolve-Path "../.."
@ -47,7 +53,7 @@ function config {
New-Item -ItemType Directory -Force -Path build-uwp
cd build-uwp
ForEach($arch in $arch_list) {
ForEach ($arch in $arch_list) {
echo "Config Arch = [$arch]"
New-Item -ItemType Directory -Force -Path $arch
cd $arch
@ -66,11 +72,12 @@ function config {
function build {
cd build-uwp
ForEach($arch in $arch_list) {
ForEach ($arch in $arch_list) {
echo "Build Arch = [$arch]"
cd $arch
cmake --build . --config Release --target tddotnet
cmake --build . --config Debug --target tddotnet
ForEach ($config in $config_list) {
cmake --build . --config $config --target tddotnet
}
cd ..
}
cd ..
@ -85,23 +92,19 @@ function export {
cp '../`[Content_Types`].xml' vsix
cp ../LICENSE_1_0.txt vsix
ForEach($arch in $arch_list) {
New-Item -ItemType Directory -Force -Path vsix/DesignTime/Debug/${arch}
New-Item -ItemType Directory -Force -Path vsix/DesignTime/Retail/${arch}
New-Item -ItemType Directory -Force -Path vsix/Redist/Debug/${arch}
New-Item -ItemType Directory -Force -Path vsix/Redist/Retail/${arch}
ForEach ($arch in $arch_list) {
New-Item -ItemType Directory -Force -Path vsix/References/CommonConfiguration/${arch}
ForEach ($config in $config_list) {
$target = $targets[$config]
cp ${arch}/Debug/* -include "SSLEAY*","LIBEAY*","libcrypto*","libssl*","zlib*" vsix/Redist/Debug/${arch}/
cp ${arch}/Release/* -include "SSLEAY*","LIBEAY*","libcrypto*","libssl*","zlib*" vsix/Redist/Retail/${arch}/
New-Item -ItemType Directory -Force -Path vsix/DesignTime/${target}/${arch}
cp ${arch}/${config}/Telegram.Td.lib vsix/DesignTime/${target}/${arch}/
cp ${arch}/Debug/* -filter "Telegram.Td.*" -include "*.lib" vsix/DesignTime/Debug/${arch}/
cp ${arch}/Release/* -filter "Telegram.Td.*" -include "*.lib" vsix/DesignTime/Retail/${arch}/
New-Item -ItemType Directory -Force -Path vsix/Redist/${target}/${arch}
cp ${arch}/${config}/* -include "SSLEAY*","LIBEAY*","libcrypto*","libssl*","zlib*","Telegram.Td.pdb","Telegram.Td.dll" vsix/Redist/${target}/${arch}/
cp ${arch}/Debug/* -filter "Telegram.Td.*" -include "*.pdb","*.dll" vsix/Redist/Debug/${arch}/
cp ${arch}/Release/* -filter "Telegram.Td.*" -include "*.pdb","*.dll" vsix/Redist/Retail/${arch}/
cp ${arch}/Release/* -filter "Telegram.Td.*" -include "*.pri","*.winmd","*.xml" vsix/References/CommonConfiguration/${arch}/
cp ${arch}/${config}/* -include "Telegram.Td.pri","Telegram.Td.winmd","Telegram.Td.xml" vsix/References/CommonConfiguration/${arch}/
}
}
cd vsix

View File

@ -1,3 +1,3 @@
./src.ps1 | Select-String -NotMatch "CxCli.h" | Select-String -NotMatch "dotnet" | ForEach-Object {
./src.ps1 | Select-String -NotMatch "CxCli.h" | Select-String -NotMatch "DotNet" | ForEach-Object {
clang-format -verbose -style=file -i $_
}

View File

@ -11,8 +11,8 @@
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/filesystem.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include <utility>

View File

@ -23,6 +23,7 @@ std::string TD_TL_writer_cpp::gen_output_begin() const {
"#include \"td/utils/common.h\"\n"
"#include \"td/utils/format.h\"\n"
"#include \"td/utils/logging.h\"\n"
"#include \"td/utils/SliceBuilder.h\"\n"
"#include \"td/utils/tl_parsers.h\"\n"
"#include \"td/utils/tl_storers.h\"\n\n"
"namespace td {\n"

View File

@ -9,6 +9,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include <algorithm>

View File

@ -18,6 +18,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Time.h"
#include "td/utils/tl_parsers.h"

View File

@ -9,7 +9,7 @@
#include "td/mtproto/HandshakeConnection.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
namespace td {

View File

@ -13,6 +13,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
// TODO: do I need \r\n as delimiter?

View File

@ -13,7 +13,7 @@
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
namespace td {

View File

@ -22,6 +22,7 @@
#include "td/utils/MpscPollableQueue.h"
#include "td/utils/port/EventFd.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"

View File

@ -22,6 +22,7 @@
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_parsers.h"

View File

@ -12,8 +12,8 @@
#include "td/utils/BigNum.h"
#include "td/utils/common.h"
#include "td/utils/crypto.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Span.h"
#include "td/utils/Time.h"

View File

@ -15,6 +15,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include <array>

View File

@ -15,6 +15,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
namespace td {

View File

@ -12,7 +12,7 @@
#include "td/telegram/Version.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {

View File

@ -34,6 +34,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {

View File

@ -8,6 +8,7 @@
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
namespace td {
@ -19,15 +20,33 @@ static string get_color_hex_string(int32 color) {
return result;
}
static BackgroundFill get_background_fill(const td_api::BackgroundFill *fill) {
CHECK(fill != nullptr);
static bool is_valid_color(int32 color) {
return 0 <= color && color <= 0xFFFFFF;
}
static Result<BackgroundFill> get_background_fill(const td_api::BackgroundFill *fill) {
if (fill == nullptr) {
return Status::Error(400, "Background fill info must be non-empty");
}
switch (fill->get_id()) {
case td_api::backgroundFillSolid::ID: {
auto solid = static_cast<const td_api::backgroundFillSolid *>(fill);
if (!is_valid_color(solid->color_)) {
return Status::Error(400, "Invalid solid fill color value");
}
return BackgroundFill(solid->color_);
}
case td_api::backgroundFillGradient::ID: {
auto gradient = static_cast<const td_api::backgroundFillGradient *>(fill);
if (!is_valid_color(gradient->top_color_)) {
return Status::Error(400, "Invalid top gradient color value");
}
if (!is_valid_color(gradient->bottom_color_)) {
return Status::Error(400, "Invalid bottom gradient color value");
}
if (!BackgroundFill::is_valid_rotation_angle(gradient->rotation_angle_)) {
return Status::Error(400, "Invalid rotation angle value");
}
return BackgroundFill(gradient->top_color_, gradient->bottom_color_, gradient->rotation_angle_);
}
default:
@ -37,21 +56,23 @@ static BackgroundFill get_background_fill(const td_api::BackgroundFill *fill) {
}
static string get_background_fill_color_hex_string(const BackgroundFill &fill, bool is_first) {
if (fill.is_solid()) {
return get_color_hex_string(fill.top_color);
} else {
string colors = PSTRING() << get_color_hex_string(fill.top_color) << '-' << get_color_hex_string(fill.bottom_color);
if (fill.rotation_angle != 0) {
colors += (PSTRING() << (is_first ? '?' : '&') << "rotation=" << fill.rotation_angle);
switch (fill.get_type()) {
case BackgroundFill::Type::Solid:
return get_color_hex_string(fill.top_color);
case BackgroundFill::Type::Gradient: {
string colors = PSTRING() << get_color_hex_string(fill.top_color) << '-'
<< get_color_hex_string(fill.bottom_color);
if (fill.rotation_angle != 0) {
colors += (PSTRING() << (is_first ? '?' : '&') << "rotation=" << fill.rotation_angle);
}
return colors;
}
return colors;
default:
UNREACHABLE();
return string();
}
}
static bool is_valid_color(int32 color) {
return 0 <= color && color <= 0xFFFFFF;
}
static bool is_valid_intensity(int32 intensity) {
return 0 <= intensity && intensity <= 100;
}
@ -60,10 +81,16 @@ int64 BackgroundFill::get_id() const {
CHECK(is_valid_color(top_color));
CHECK(is_valid_color(bottom_color));
CHECK(is_valid_rotation_angle(rotation_angle));
if (is_solid()) {
return static_cast<int64>(top_color) + 1;
switch (get_type()) {
case Type::Solid:
return static_cast<int64>(top_color) + 1;
case Type::Gradient:
return (rotation_angle / 45) * 0x1000001000001 + (static_cast<int64>(top_color) << 24) + bottom_color +
(1 << 24) + 1;
default:
UNREACHABLE();
return 0;
}
return (rotation_angle / 45) * 0x1000001000001 + (static_cast<int64>(top_color) << 24) + bottom_color + (1 << 24) + 1;
}
bool BackgroundFill::is_valid_id(int64 id) {
@ -148,35 +175,22 @@ Result<BackgroundType> get_background_type(const td_api::BackgroundType *type) {
}
case td_api::backgroundTypePattern::ID: {
auto pattern = static_cast<const td_api::backgroundTypePattern *>(type);
if (pattern->fill_ == nullptr) {
return Status::Error(400, "Fill info must be non-empty");
TRY_RESULT(background_fill, get_background_fill(pattern->fill_.get()));
if (!is_valid_intensity(pattern->intensity_)) {
return Status::Error(400, "Wrong intensity value");
}
result = BackgroundType(pattern->is_moving_, get_background_fill(pattern->fill_.get()), pattern->intensity_);
result = BackgroundType(pattern->is_moving_, std::move(background_fill), pattern->intensity_);
break;
}
case td_api::backgroundTypeFill::ID: {
auto fill = static_cast<const td_api::backgroundTypeFill *>(type);
if (fill->fill_ == nullptr) {
return Status::Error(400, "Fill info must be non-empty");
}
result = BackgroundType(get_background_fill(fill->fill_.get()));
TRY_RESULT(background_fill, get_background_fill(fill->fill_.get()));
result = BackgroundType(std::move(background_fill));
break;
}
default:
UNREACHABLE();
}
if (!is_valid_intensity(result.intensity)) {
return Status::Error(400, "Wrong intensity value");
}
if (!is_valid_color(result.fill.top_color)) {
return Status::Error(400, result.fill.is_solid() ? Slice("Wrong color value") : ("Wrong top color value"));
}
if (!is_valid_color(result.fill.bottom_color)) {
return Status::Error(400, "Wrong bottom color value");
}
if (!BackgroundFill::is_valid_rotation_angle(result.fill.rotation_angle)) {
return Status::Error(400, "Wrong rotation angle value");
}
return result;
}
@ -233,10 +247,16 @@ BackgroundType get_background_type(bool is_pattern,
}
static td_api::object_ptr<td_api::BackgroundFill> get_background_fill_object(const BackgroundFill &fill) {
if (fill.is_solid()) {
return td_api::make_object<td_api::backgroundFillSolid>(fill.top_color);
switch (fill.get_type()) {
case BackgroundFill::Type::Solid:
return td_api::make_object<td_api::backgroundFillSolid>(fill.top_color);
case BackgroundFill::Type::Gradient:
return td_api::make_object<td_api::backgroundFillGradient>(fill.top_color, fill.bottom_color,
fill.rotation_angle);
default:
UNREACHABLE();
return nullptr;
}
return td_api::make_object<td_api::backgroundFillGradient>(fill.top_color, fill.bottom_color, fill.rotation_angle);
}
td_api::object_ptr<td_api::BackgroundType> get_background_type_object(const BackgroundType &type) {
@ -255,6 +275,8 @@ td_api::object_ptr<td_api::BackgroundType> get_background_type_object(const Back
}
telegram_api::object_ptr<telegram_api::wallPaperSettings> get_input_wallpaper_settings(const BackgroundType &type) {
CHECK(type.is_server());
int32 flags = 0;
if (type.is_blurred) {
flags |= telegram_api::wallPaperSettings::BLUR_MASK;
@ -262,23 +284,22 @@ telegram_api::object_ptr<telegram_api::wallPaperSettings> get_input_wallpaper_se
if (type.is_moving) {
flags |= telegram_api::wallPaperSettings::MOTION_MASK;
}
if (type.fill.top_color != 0 || type.fill.bottom_color != 0) {
flags |= telegram_api::wallPaperSettings::BACKGROUND_COLOR_MASK;
switch (type.fill.get_type()) {
case BackgroundFill::Type::Gradient:
flags |= telegram_api::wallPaperSettings::SECOND_BACKGROUND_COLOR_MASK;
// fallthrough
case BackgroundFill::Type::Solid:
flags |= telegram_api::wallPaperSettings::BACKGROUND_COLOR_MASK;
break;
default:
UNREACHABLE();
}
if (!type.fill.is_solid()) {
flags |= telegram_api::wallPaperSettings::SECOND_BACKGROUND_COLOR_MASK;
}
if (type.intensity) {
if (type.intensity != 0) {
flags |= telegram_api::wallPaperSettings::INTENSITY_MASK;
}
if (type.is_server()) {
return telegram_api::make_object<telegram_api::wallPaperSettings>(flags, false /*ignored*/, false /*ignored*/,
type.fill.top_color, type.fill.bottom_color,
type.intensity, type.fill.rotation_angle);
}
UNREACHABLE();
return nullptr;
return telegram_api::make_object<telegram_api::wallPaperSettings>(flags, false /*ignored*/, false /*ignored*/,
type.fill.top_color, type.fill.bottom_color,
type.intensity, type.fill.rotation_angle);
}
} // namespace td

View File

@ -27,8 +27,12 @@ struct BackgroundFill {
: top_color(top_color), bottom_color(bottom_color), rotation_angle(rotation_angle) {
}
bool is_solid() const {
return top_color == bottom_color;
enum class Type : int32 { Solid, Gradient };
Type get_type() const {
if (top_color == bottom_color) {
return Type::Solid;
}
return Type::Gradient;
}
int64 get_id() const;

View File

@ -16,7 +16,8 @@ template <class StorerT>
void store(const BackgroundType &type, StorerT &storer) {
bool has_fill = type.fill.top_color != 0 || type.fill.bottom_color != 0;
bool has_intensity = type.intensity != 0;
bool is_gradient = !type.fill.is_solid();
auto fill_type = type.fill.get_type();
bool is_gradient = fill_type == BackgroundFill::Type::Gradient;
BEGIN_STORE_FLAGS();
STORE_FLAG(type.is_blurred);
STORE_FLAG(type.is_moving);

View File

@ -30,6 +30,7 @@
#include "td/utils/crypto.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include <tuple>
#include <unordered_set>

View File

@ -10,6 +10,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/telegram/telegram_api.hpp"

View File

@ -660,6 +660,25 @@ td_api::object_ptr<td_api::Object> ClientManager::execute(td_api::object_ptr<td_
return Td::static_request(std::move(request));
}
static std::atomic<ClientManager::LogMessageCallbackPtr> log_message_callback;
static void log_message_callback_wrapper(int verbosity_level, CSlice message) {
auto callback = log_message_callback.load(std::memory_order_relaxed);
if (callback != nullptr) {
callback(verbosity_level, message.c_str());
}
}
void ClientManager::set_log_message_callback(int max_verbosity_level, LogMessageCallbackPtr callback) {
if (callback == nullptr) {
::td::set_log_message_callback(max_verbosity_level, nullptr);
log_message_callback = nullptr;
} else {
log_message_callback = callback;
::td::set_log_message_callback(max_verbosity_level, log_message_callback_wrapper);
}
}
ClientManager::~ClientManager() = default;
ClientManager::ClientManager(ClientManager &&other) = default;
ClientManager &ClientManager::operator=(ClientManager &&other) = default;

View File

@ -238,6 +238,27 @@ class ClientManager final {
*/
static td_api::object_ptr<td_api::Object> execute(td_api::object_ptr<td_api::Function> &&request);
/**
* A type of callback function that will be called when a message is added to the internal TDLib log.
*
* \param verbosity_level Log verbosity level with which the message was added (-1 - 1024).
* If 0, then TDLib will crash as soon as the callback returns.
* None of the TDLib methods can be called from the callback.
* \param message Null-terminated string with the message added to the log.
*/
using LogMessageCallbackPtr = void (*)(int verbosity_level, const char *message);
/**
* Sets the callback that will be called when a message is added to the internal TDLib log.
* None of the TDLib methods can be called from the callback.
* By default the callback is not set.
*
* \param[in] max_verbosity_level Maximum verbosity level of messages for which the callback will be called.
* \param[in] callback Callback that will be called when a message is added to the internal TDLib log.
* Pass nullptr to remove the callback.
*/
static void set_log_message_callback(int max_verbosity_level, LogMessageCallbackPtr callback);
/**
* Destroys the client manager and all TDLib client instances managed by it.
*/

View File

@ -21,6 +21,17 @@ namespace Td {
using namespace CxCli;
#if !TD_CLI
/// <summary>
/// A type of callback function that will be called when a message is added to the internal TDLib log.
/// </summary>
/// <param name="verbosityLevel">Log verbosity level with which the message was added (-1 - 1024).
/// If 0, then TDLib will crash as soon as the callback returns.
/// None of the TDLib methods can be called from the callback.</param>
/// <param name="message">Null-terminated string with the message added to the log.</param>
public delegate void LogMessageCallback(int verbosityLevel, String^ message);
#endif
/// <summary>
/// Interface for handler for results of queries to TDLib and incoming updates from TDLib.
/// </summary>
@ -105,6 +116,26 @@ public:
return REF_NEW Client(updateHandler);
}
#if !TD_CLI
/// <summary>
/// Sets the callback that will be called when a message is added to the internal TDLib log.
/// None of the TDLib methods can be called from the callback.
/// </summary>
/// <param name="max_verbosity_level">Maximum verbosity level of messages for which the callback will be called.</param>
/// <param name="callback">Callback that will be called when a message is added to the internal TDLib log.
/// Pass null to remove the callback.</param>
static void SetLogMessageCallback(std::int32_t max_verbosity_level, LogMessageCallback^ callback) {
std::lock_guard<std::mutex> lock(logMutex);
if (callback == nullptr) {
::td::ClientManager::set_log_message_callback(max_verbosity_level, nullptr);
logMessageCallback = nullptr;
} else {
logMessageCallback = callback;
::td::ClientManager::set_log_message_callback(max_verbosity_level, LogMessageCallbackWrapper);
}
}
#endif
private:
Client(ClientResultHandler^ updateHandler) {
client = new td::Client();
@ -127,7 +158,24 @@ private:
handler->OnResult(object);
}
}
#if !TD_CLI
static std::mutex logMutex;
static LogMessageCallback^ logMessageCallback;
static void LogMessageCallbackWrapper(int verbosity_level, const char *message) {
auto callback = logMessageCallback;
if (callback != nullptr) {
callback(verbosity_level, string_from_unmanaged(message));
}
}
#endif
};
#if !TD_CLI
std::mutex Client::logMutex;
LogMessageCallback^ Client::logMessageCallback;
#endif
} // namespace Td
} // namespace Telegram

View File

@ -11,8 +11,8 @@
#include "td/utils/common.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/logging.h"
#include "td/utils/port/thread_local.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/StringBuilder.h"

View File

@ -18,6 +18,7 @@
namespace td {
// TODO can be made private in TDLib 2.0
class ClientJson final {
public:
void send(Slice request);

View File

@ -53,6 +53,7 @@
#include "td/utils/Parser.h"
#include "td/utils/port/Clocks.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/tl_parsers.h"

View File

@ -10,6 +10,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
namespace td {

View File

@ -62,6 +62,7 @@
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
@ -8597,6 +8598,7 @@ void ContactsManager::save_chat_to_database(Chat *c, ChatId chat_id) {
void ContactsManager::save_chat_to_database_impl(Chat *c, ChatId chat_id, string value) {
CHECK(c != nullptr);
CHECK(load_chat_from_database_queries_.count(chat_id) == 0);
CHECK(!c->is_being_saved);
c->is_being_saved = true;
c->is_saved = true;
LOG(INFO) << "Trying to save to database " << chat_id;
@ -8833,6 +8835,7 @@ void ContactsManager::save_channel_to_database(Channel *c, ChannelId channel_id)
void ContactsManager::save_channel_to_database_impl(Channel *c, ChannelId channel_id, string value) {
CHECK(c != nullptr);
CHECK(load_channel_from_database_queries_.count(channel_id) == 0);
CHECK(!c->is_being_saved);
c->is_being_saved = true;
c->is_saved = true;
LOG(INFO) << "Trying to save to database " << channel_id;
@ -8941,10 +8944,12 @@ void ContactsManager::on_load_channel_from_database(ChannelId channel_id, string
temp_c.status.update_restrictions();
if (temp_c.status != c->status) {
on_channel_status_changed(c, channel_id, temp_c.status, c->status);
CHECK(!c->is_being_saved);
}
if (temp_c.username != c->username) {
on_channel_username_changed(c, channel_id, temp_c.username, c->username);
CHECK(!c->is_being_saved);
}
}
auto new_value = get_channel_database_value(c);
@ -9083,6 +9088,7 @@ void ContactsManager::save_secret_chat_to_database(SecretChat *c, SecretChatId s
void ContactsManager::save_secret_chat_to_database_impl(SecretChat *c, SecretChatId secret_chat_id, string value) {
CHECK(c != nullptr);
CHECK(load_secret_chat_from_database_queries_.count(secret_chat_id) == 0);
CHECK(!c->is_being_saved);
c->is_being_saved = true;
c->is_saved = true;
LOG(INFO) << "Trying to save to database " << secret_chat_id;
@ -9622,6 +9628,11 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
}
}
if (invalidated_channels_full_.erase(channel_id) > 0 ||
(!c->is_slow_mode_enabled && channel_full->slow_mode_delay != 0)) {
do_invalidate_channel_full(channel_full, !c->is_slow_mode_enabled);
}
td_->group_call_manager_->on_update_dialog_about(DialogId(channel_id), channel_full->description, false);
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
@ -10457,6 +10468,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
return promise.set_value(Unit());
}
invalidated_channels_full_.erase(channel_id);
if (!G()->close_flag()) {
auto channel_full = get_channel_full(channel_id, "on_get_channel_full");
if (channel_full != nullptr) {
@ -12045,17 +12058,26 @@ void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, b
void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool need_drop_slow_mode_delay) {
LOG(INFO) << "Invalidate supergroup full for " << channel_id;
// drop channel full cache
auto channel_full = get_channel_full_force(channel_id, "invalidate_channel_full");
auto channel_full = get_channel_full(channel_id, "invalidate_channel_full"); // must not load ChannelFull
if (channel_full != nullptr) {
channel_full->expires_at = 0.0;
if (need_drop_slow_mode_delay && channel_full->slow_mode_delay != 0) {
channel_full->slow_mode_delay = 0;
channel_full->slow_mode_next_send_date = 0;
channel_full->is_slow_mode_next_send_date_changed = true;
channel_full->is_changed = true;
}
do_invalidate_channel_full(channel_full, need_drop_slow_mode_delay);
update_channel_full(channel_full, channel_id);
} else {
invalidated_channels_full_.insert(channel_id);
}
}
void ContactsManager::do_invalidate_channel_full(ChannelFull *channel_full, bool need_drop_slow_mode_delay) {
CHECK(channel_full != nullptr);
if (channel_full->expires_at >= Time::now()) {
channel_full->expires_at = 0.0;
channel_full->need_save_to_database = true;
}
if (need_drop_slow_mode_delay && channel_full->slow_mode_delay != 0) {
channel_full->slow_mode_delay = 0;
channel_full->slow_mode_next_send_date = 0;
channel_full->is_slow_mode_next_send_date_changed = true;
channel_full->is_changed = true;
}
}
@ -13039,17 +13061,18 @@ void ContactsManager::on_update_channel_status(Channel *c, ChannelId channel_id,
}
}
void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id,
void ContactsManager::on_channel_status_changed(const Channel *c, ChannelId channel_id,
const DialogParticipantStatus &old_status,
const DialogParticipantStatus &new_status) {
CHECK(c->is_update_supergroup_sent);
bool have_channel_full = get_channel_full(channel_id) != nullptr;
bool need_reload_group_call = old_status.can_manage_calls() != new_status.can_manage_calls();
if (old_status.can_manage_invite_links() && !new_status.can_manage_invite_links()) {
auto channel_full = get_channel_full_force(channel_id, "on_channel_status_changed");
if (channel_full != nullptr) {
auto channel_full = get_channel_full(channel_id, "on_channel_status_changed");
if (channel_full != nullptr) { // otherwise invite_link will be dropped when the channel is loaded
on_update_channel_full_invite_link(channel_full, nullptr);
invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
do_invalidate_channel_full(channel_full, !c->is_slow_mode_enabled);
update_channel_full(channel_full, channel_id);
}
} else {
@ -13078,6 +13101,9 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights,
DialogId(channel_id));
}
// must not load ChannelFull, because must not change the Channel
CHECK(have_channel_full == (get_channel_full(channel_id) != nullptr));
}
void ContactsManager::on_update_channel_default_permissions(Channel *c, ChannelId channel_id,
@ -13119,12 +13145,16 @@ void ContactsManager::on_update_channel_username(Channel *c, ChannelId channel_i
}
}
void ContactsManager::on_channel_username_changed(Channel *c, ChannelId channel_id, const string &old_username,
void ContactsManager::on_channel_username_changed(const Channel *c, ChannelId channel_id, const string &old_username,
const string &new_username) {
bool have_channel_full = get_channel_full(channel_id) != nullptr;
if (old_username.empty() || new_username.empty()) {
// moving channel from private to public can change availability of chat members
invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
}
// must not load ChannelFull, because must not change the Channel
CHECK(have_channel_full == (get_channel_full(channel_id) != nullptr));
}
void ContactsManager::on_update_channel_description(ChannelId channel_id, string &&description) {

View File

@ -1250,9 +1250,9 @@ class ContactsManager : public Actor {
void on_update_channel_full_bot_user_ids(ChannelFull *channel_full, ChannelId channel_id,
vector<UserId> &&bot_user_ids);
void on_channel_status_changed(Channel *c, ChannelId channel_id, const DialogParticipantStatus &old_status,
void on_channel_status_changed(const Channel *c, ChannelId channel_id, const DialogParticipantStatus &old_status,
const DialogParticipantStatus &new_status);
void on_channel_username_changed(Channel *c, ChannelId channel_id, const string &old_username,
void on_channel_username_changed(const Channel *c, ChannelId channel_id, const string &old_username,
const string &new_username);
void remove_linked_channel_id(ChannelId channel_id);
@ -1270,6 +1270,8 @@ class ContactsManager : public Actor {
void drop_channel_photos(ChannelId channel_id, bool is_empty, bool drop_channel_full_photo, const char *source);
void do_invalidate_channel_full(ChannelFull *channel_full, bool need_drop_slow_mode_delay);
void update_user_online_member_count(User *u);
void update_chat_online_member_count(const ChatFull *chat_full, ChatId chat_id, bool is_from_server);
void update_channel_online_member_count(ChannelId channel_id, bool is_from_server);
@ -1595,6 +1597,7 @@ class ContactsManager : public Actor {
std::unordered_map<ChannelId, unique_ptr<Channel>, ChannelIdHash> channels_;
std::unordered_map<ChannelId, unique_ptr<ChannelFull>, ChannelIdHash> channels_full_;
mutable std::unordered_set<ChannelId, ChannelIdHash> unknown_channels_;
std::unordered_set<ChannelId, ChannelIdHash> invalidated_channels_full_;
std::unordered_map<ChannelId, FileSourceId, ChannelIdHash> channel_full_file_source_ids_;
std::unordered_map<SecretChatId, unique_ptr<SecretChat>, SecretChatIdHash> secret_chats_;

View File

@ -23,6 +23,7 @@
#include "td/utils/JsonBuilder.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/tl_helpers.h"

View File

@ -21,6 +21,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
namespace td {

View File

@ -6,8 +6,8 @@
//
#include "td/telegram/DialogSource.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
namespace td {

View File

@ -23,6 +23,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/overloaded.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
namespace td {

View File

@ -27,6 +27,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include <map>
#include <unordered_set>
@ -1932,7 +1933,7 @@ void GroupCallManager::process_group_call_participants(
}
auto min_order = GroupCallParticipantOrder::max();
DialogId min_order_dialog_id;
DialogId debug_min_order_dialog_id;
bool can_self_unmute = get_group_call_can_self_unmute(input_group_call_id);
bool joined_date_asc = get_group_call_joined_date_asc(input_group_call_id);
for (auto &group_call_participant : participants) {
@ -1952,11 +1953,11 @@ void GroupCallManager::process_group_call_participants(
if (is_load) {
auto real_order = participant.get_real_order(can_self_unmute, joined_date_asc, true);
if (real_order > min_order) {
LOG(ERROR) << "Receive call participant " << participant.dialog_id << " with order " << real_order
<< " after call participant " << min_order_dialog_id << " with order " << min_order;
LOG(ERROR) << "Receive group call participant " << participant.dialog_id << " with order " << real_order
<< " after group call participant " << debug_min_order_dialog_id << " with order " << min_order;
} else {
min_order = real_order;
min_order_dialog_id = participant.dialog_id;
debug_min_order_dialog_id = participant.dialog_id;
}
}
if (is_sync) {
@ -1964,6 +1965,13 @@ void GroupCallManager::process_group_call_participants(
}
process_group_call_participant(input_group_call_id, std::move(participant));
}
if (is_load && participants.empty() && !joined_date_asc) {
// If loaded 0 participants and new participants are added to the beginning of the list,
// then the end of the list was reached.
// Set min_order to the minimum possible value to send updates about all participants with order less than
// the current min_order. There can be such participants if the last loaded participant had a fake active_date.
min_order = GroupCallParticipantOrder::min();
}
if (is_sync) {
auto participants_it = group_call_participants_.find(input_group_call_id);
if (participants_it != group_call_participants_.end()) {
@ -1972,6 +1980,7 @@ void GroupCallManager::process_group_call_participants(
for (auto participant_it = group_participants.begin(); participant_it != group_participants.end();) {
auto &participant = *participant_it;
if (old_participant_dialog_ids.count(participant.dialog_id) == 0) {
// successfully synced old user
++participant_it;
continue;
}
@ -1997,6 +2006,8 @@ void GroupCallManager::process_group_call_participants(
}
if (participants_it->second->min_order < min_order) {
// if previously known more users, adjust min_order
LOG(INFO) << "Decrease min_order from " << participants_it->second->min_order << " to " << min_order << " in "
<< input_group_call_id;
participants_it->second->min_order = min_order;
}
}
@ -2008,11 +2019,17 @@ void GroupCallManager::process_group_call_participants(
auto old_min_order = participants_it->second->min_order;
if (old_min_order > min_order) {
participants_it->second->min_order = min_order;
LOG(INFO) << "Increase min_order from " << old_min_order << " to " << min_order << " in "
<< input_group_call_id;
for (auto &participant : participants_it->second->participants) {
auto real_order = get_real_participant_order(can_self_unmute, participant, participants_it->second.get());
if (old_min_order > real_order && real_order >= min_order) {
CHECK(!participant.order.is_valid() || participant.is_self);
LOG_CHECK(!participant.order.is_valid() || participant.is_self)
<< participant << ' ' << old_min_order << ' ' << real_order << ' ' << min_order << ' '
<< participant.joined_date << ' ' << participant.active_date << ' ' << participant.raise_hand_rating
<< ' ' << participant.local_active_date << ' ' << G()->unix_time() << ' ' << can_self_unmute << ' '
<< participants_it->second->joined_date_asc;
participant.order = real_order;
send_update_group_call_participant(input_group_call_id, participant,
"process_group_call_participants load");

View File

@ -272,7 +272,7 @@ bool operator!=(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs
}
StringBuilder &operator<<(StringBuilder &string_builder, const GroupCallParticipant &group_call_participant) {
return string_builder << '[' << group_call_participant.dialog_id << " with source "
return string_builder << "GroupCallParticipant[" << group_call_participant.dialog_id << " with source "
<< group_call_participant.audio_source << " and order " << group_call_participant.order << ']';
}

View File

@ -6,14 +6,18 @@
//
#include "td/telegram/GroupCallParticipantOrder.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include <limits>
#include <tuple>
namespace td {
GroupCallParticipantOrder GroupCallParticipantOrder::min() {
return GroupCallParticipantOrder(0, 0, 1);
}
GroupCallParticipantOrder GroupCallParticipantOrder::max() {
return GroupCallParticipantOrder(std::numeric_limits<int32>::max(), std::numeric_limits<int64>::max(),
std::numeric_limits<int32>::max());

View File

@ -30,6 +30,8 @@ class GroupCallParticipantOrder {
: active_date(active_date), joined_date(joined_date), raise_hand_rating(raise_hand_rating) {
}
static GroupCallParticipantOrder min();
static GroupCallParticipantOrder max();
bool is_valid() const;

View File

@ -50,6 +50,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/tl_parsers.h"

View File

@ -26,6 +26,7 @@
#include "td/utils/ExitGuard.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include <atomic>

View File

@ -6,6 +6,7 @@
//
#include "td/telegram/Log.h"
#include "td/telegram/Client.h"
#include "td/telegram/Logging.h"
#include "td/telegram/td_api.h"
@ -23,9 +24,13 @@ static string log_file_path;
static int64 max_log_file_size = 10 << 20;
static Log::FatalErrorCallbackPtr fatal_error_callback;
static void fatal_error_callback_wrapper(CSlice message) {
CHECK(fatal_error_callback != nullptr);
fatal_error_callback(message.c_str());
static void fatal_error_callback_wrapper(int verbosity_level, const char *message) {
if (verbosity_level == 0) {
auto callback = fatal_error_callback;
if (callback != nullptr) {
callback(message);
}
}
}
bool Log::set_file_path(string file_path) {
@ -59,11 +64,11 @@ void Log::set_verbosity_level(int new_verbosity_level) {
void Log::set_fatal_error_callback(FatalErrorCallbackPtr callback) {
std::lock_guard<std::mutex> lock(log_mutex);
if (callback == nullptr) {
ClientManager::set_log_message_callback(0, nullptr);
fatal_error_callback = nullptr;
set_log_fatal_error_callback(nullptr);
} else {
fatal_error_callback = callback;
set_log_fatal_error_callback(fatal_error_callback_wrapper);
ClientManager::set_log_message_callback(0, fatal_error_callback_wrapper);
}
}

View File

@ -76,6 +76,7 @@ class Log {
* The TDLib will crash as soon as callback returns.
* By default the callback is not set.
*
* \deprecated Use ClientManager::set_log_message_callback instead.
* \param[in] callback Callback that will be called when a fatal error happens.
* Pass nullptr to remove the callback.
*/

View File

@ -32,9 +32,11 @@
#include "td/utils/algorithm.h"
#include "td/utils/ExitGuard.h"
#include "td/utils/FileLog.h"
#include "td/utils/NullLog.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/port/detail/NativeFd.h"
#include "td/utils/TsLog.h"
#include <atomic>
#include <map>

View File

@ -81,6 +81,7 @@
#include "td/utils/misc.h"
#include "td/utils/PathView.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/utf8.h"

View File

@ -15,6 +15,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/unicode.h"
#include "td/utils/utf8.h"
@ -628,7 +629,7 @@ static vector<Slice> match_urls(Slice str) {
}
path_end_ptr = next_ptr;
}
while (bad_path_end_chars.find(path_end_ptr[-1]) < bad_path_end_chars.size()) {
while (path_end_ptr > url_end_ptr + 1 && bad_path_end_chars.find(path_end_ptr[-1]) < bad_path_end_chars.size()) {
path_end_ptr--;
}
if (url_end_ptr[0] == '/' || path_end_ptr > url_end_ptr + 1) {

View File

@ -22,6 +22,7 @@
#include "td/utils/logging.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"

View File

@ -69,6 +69,7 @@
#include "td/utils/PathView.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/utf8.h"
@ -9463,9 +9464,11 @@ void MessagesManager::after_get_difference() {
auto *list = get_dialog_list(dialog_list_id);
CHECK(list != nullptr);
if (!list->is_dialog_unread_count_inited_) {
get_dialogs(dialog_list_id, MIN_DIALOG_DATE, static_cast<int32>(list->pinned_dialogs_.size() + 2), false,
PromiseCreator::lambda([dialog_list_id](Unit) {
if (!G()->close_flag()) {
int32 limit = list->are_pinned_dialogs_inited_ ? static_cast<int32>(list->pinned_dialogs_.size())
: get_pinned_dialogs_limit(dialog_list_id);
get_dialogs(dialog_list_id, MIN_DIALOG_DATE, limit + 2, false,
PromiseCreator::lambda([dialog_list_id](Result<Unit> result) {
if (!G()->close_flag() && result.is_ok()) {
LOG(INFO) << "Inited total chat count in " << dialog_list_id;
}
}));
@ -13305,6 +13308,10 @@ void MessagesManager::on_get_secret_message(SecretChatId secret_chat_id, UserId
message_info.ttl = message->ttl_;
Dialog *d = get_dialog_force(message_info.dialog_id, "on_get_secret_message");
if (d == nullptr && have_dialog_info_force(message_info.dialog_id)) {
force_create_dialog(message_info.dialog_id, "on_get_secret_message", true, true);
d = get_dialog(message_info.dialog_id);
}
if (d == nullptr) {
LOG(ERROR) << "Ignore secret message in unknown " << message_info.dialog_id;
pending_secret_message->success_promise.set_error(Status::Error(500, "Chat not found"));
@ -13395,6 +13402,10 @@ void MessagesManager::on_secret_chat_screenshot_taken(SecretChatId secret_chat_i
message_info.content = create_screenshot_taken_message_content();
Dialog *d = get_dialog_force(message_info.dialog_id, "on_secret_chat_screenshot_taken");
if (d == nullptr && have_dialog_info_force(message_info.dialog_id)) {
force_create_dialog(message_info.dialog_id, "on_get_secret_message", true, true);
d = get_dialog(message_info.dialog_id);
}
if (d == nullptr) {
LOG(ERROR) << "Ignore secret message in unknown " << message_info.dialog_id;
pending_secret_message->success_promise.set_error(Status::Error(500, "Chat not found"));
@ -13429,6 +13440,10 @@ void MessagesManager::on_secret_chat_ttl_changed(SecretChatId secret_chat_id, Us
message_info.content = create_chat_set_ttl_message_content(ttl);
Dialog *d = get_dialog_force(message_info.dialog_id, "on_secret_chat_ttl_changed");
if (d == nullptr && have_dialog_info_force(message_info.dialog_id)) {
force_create_dialog(message_info.dialog_id, "on_get_secret_message", true, true);
d = get_dialog(message_info.dialog_id);
}
if (d == nullptr) {
LOG(ERROR) << "Ignore secret message in unknown " << message_info.dialog_id;
pending_secret_message->success_promise.set_error(Status::Error(500, "Chat not found"));
@ -14274,12 +14289,29 @@ void MessagesManager::set_dialog_is_empty(Dialog *d, const char *source) {
update_dialog_pos(d, source);
}
bool MessagesManager::is_dialog_pinned(DialogListId dialog_list_id, DialogId dialog_id) const {
if (get_dialog_pinned_order(dialog_list_id, dialog_id) != DEFAULT_ORDER) {
return true;
}
if (dialog_list_id.is_filter()) {
const auto *filter = get_dialog_filter(dialog_list_id.get_filter_id());
if (filter != nullptr) {
for (const auto &input_dialog_id : filter->pinned_dialog_ids) {
if (input_dialog_id.get_dialog_id() == dialog_id) {
return true;
}
}
}
}
return false;
}
int64 MessagesManager::get_dialog_pinned_order(DialogListId dialog_list_id, DialogId dialog_id) const {
return get_dialog_pinned_order(get_dialog_list(dialog_list_id), dialog_id);
}
int64 MessagesManager::get_dialog_pinned_order(const DialogList *list, DialogId dialog_id) {
if (list != nullptr && !list->pinned_dialogs_.empty()) {
if (list != nullptr && !list->pinned_dialog_id_orders_.empty()) {
auto it = list->pinned_dialog_id_orders_.find(dialog_id);
if (it != list->pinned_dialog_id_orders_.end()) {
return it->second;
@ -14301,6 +14333,7 @@ bool MessagesManager::set_dialog_is_pinned(DialogId dialog_id, bool is_pinned) {
return set_dialog_is_pinned(DialogListId(d->folder_id), d, is_pinned);
}
// only removes the Dialog from the dialog list, but changes nothing in the corresponding DialogFilter
bool MessagesManager::set_dialog_is_pinned(DialogListId dialog_list_id, Dialog *d, bool is_pinned,
bool need_update_dialog_lists) {
if (td_->auth_manager_->is_bot()) {
@ -14812,7 +14845,7 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<te
if (!td_->auth_manager_->is_bot() && !from_pinned_dialog_list) {
// set is_pinned only after updating dialog pos to ensure that order is initialized
bool is_pinned = (dialog->flags_ & DIALOG_FLAG_IS_PINNED) != 0;
bool was_pinned = get_dialog_pinned_order(DialogListId(d->folder_id), dialog_id) != DEFAULT_ORDER;
bool was_pinned = is_dialog_pinned(DialogListId(d->folder_id), dialog_id);
if (is_pinned != was_pinned) {
set_dialog_is_pinned(DialogListId(d->folder_id), d, is_pinned);
}
@ -15909,7 +15942,7 @@ std::pair<int32, vector<DialogId>> MessagesManager::get_dialogs(DialogListId dia
auto *filter = get_dialog_filter(dialog_list_id.get_filter_id());
CHECK(filter != nullptr);
vector<InputDialogId> input_dialog_ids;
for (auto &input_dialog_id : filter->pinned_dialog_ids) {
for (const auto &input_dialog_id : filter->pinned_dialog_ids) {
auto dialog_id = input_dialog_id.get_dialog_id();
if (!have_dialog_force(dialog_id, "get_dialogs")) {
if (dialog_id.get_type() == DialogType::SecretChat) {
@ -16223,6 +16256,14 @@ void MessagesManager::preload_folder_dialog_list(FolderId folder_id) {
vector<DialogId> MessagesManager::get_pinned_dialog_ids(DialogListId dialog_list_id) const {
CHECK(!td_->auth_manager_->is_bot());
if (dialog_list_id.is_filter()) {
const auto *filter = get_dialog_filter(dialog_list_id.get_filter_id());
if (filter == nullptr) {
return {};
}
return transform(filter->pinned_dialog_ids, [](auto &input_dialog) { return input_dialog.get_dialog_id(); });
}
auto *list = get_dialog_list(dialog_list_id);
if (list == nullptr || !list->are_pinned_dialogs_inited_) {
return {};
@ -18109,9 +18150,7 @@ void MessagesManager::sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_f
{&dialog_filter->pinned_dialog_ids, &dialog_filter->excluded_dialog_ids, &dialog_filter->included_dialog_ids}) {
for (auto input_dialog_id : *input_dialog_ids) {
LOG_CHECK(all_dialog_ids.insert(input_dialog_id.get_dialog_id()).second)
<< source << ' ' << td::contains(dialog_filter->pinned_dialog_ids, input_dialog_id) << ' '
<< td::contains(dialog_filter->excluded_dialog_ids, input_dialog_id) << ' '
<< td::contains(dialog_filter->included_dialog_ids, input_dialog_id);
<< source << ' ' << input_dialog_id.get_dialog_id() << ' ' << dialog_filter;
}
}
}
@ -18463,7 +18502,7 @@ void MessagesManager::add_dialog_filter(unique_ptr<DialogFilter> dialog_filter,
}
}
for (auto &input_dialog_id : reversed(dialog_filters_.back()->pinned_dialog_ids)) {
for (const auto &input_dialog_id : reversed(dialog_filters_.back()->pinned_dialog_ids)) {
auto dialog_id = input_dialog_id.get_dialog_id();
auto order = get_next_pinned_dialog_order();
list.pinned_dialogs_.emplace_back(order, dialog_id);
@ -18507,7 +18546,7 @@ void MessagesManager::edit_dialog_filter(unique_ptr<DialogFilter> new_dialog_fil
new_list.dialog_list_id = dialog_list_id;
auto old_it = old_list.pinned_dialogs_.rbegin();
for (auto &input_dialog_id : reversed(new_dialog_filter->pinned_dialog_ids)) {
for (const auto &input_dialog_id : reversed(new_dialog_filter->pinned_dialog_ids)) {
auto dialog_id = input_dialog_id.get_dialog_id();
while (old_it < old_list.pinned_dialogs_.rend()) {
if (old_it->get_dialog_id() == dialog_id) {
@ -18979,7 +19018,7 @@ Status MessagesManager::toggle_dialog_is_pinned(DialogListId dialog_list_id, Dia
return Status::Error(6, "Pinned chats must be loaded first");
}
bool was_pinned = get_dialog_pinned_order(dialog_list_id, dialog_id) != DEFAULT_ORDER;
bool was_pinned = is_dialog_pinned(dialog_list_id, dialog_id);
if (is_pinned == was_pinned) {
return Status::OK();
}
@ -18999,7 +19038,8 @@ Status MessagesManager::toggle_dialog_is_pinned(DialogListId dialog_list_id, Dia
td::remove_if(new_dialog_filter->included_dialog_ids, is_changed_dialog);
td::remove_if(new_dialog_filter->excluded_dialog_ids, is_changed_dialog);
} else {
td::remove_if(new_dialog_filter->pinned_dialog_ids, is_changed_dialog);
bool is_removed = td::remove_if(new_dialog_filter->pinned_dialog_ids, is_changed_dialog);
CHECK(is_removed);
new_dialog_filter->included_dialog_ids.push_back(get_input_dialog_id(dialog_id));
}
@ -27417,8 +27457,9 @@ MessagesManager::MessageNotificationGroup MessagesManager::get_message_notificat
d = get_dialog(it->second);
CHECK(d != nullptr);
} else if (G()->parameters().use_message_db) {
G()->td_db()->get_dialog_db_sync()->begin_transaction().ensure();
auto r_value = G()->td_db()->get_dialog_db_sync()->get_notification_group(group_id);
auto *dialog_db = G()->td_db()->get_dialog_db_sync();
dialog_db->begin_transaction().ensure(); // read transaction
auto r_value = dialog_db->get_notification_group(group_id);
if (r_value.is_ok()) {
VLOG(notifications) << "Loaded " << r_value.ok() << " from database by " << group_id;
d = get_dialog_force(r_value.ok().dialog_id, "get_message_notification_group_force");
@ -27426,7 +27467,7 @@ MessagesManager::MessageNotificationGroup MessagesManager::get_message_notificat
CHECK(r_value.error().message() == "Not found");
VLOG(notifications) << "Failed to load " << group_id << " from database";
}
G()->td_db()->get_dialog_db_sync()->commit_transaction().ensure();
dialog_db->commit_transaction().ensure();
}
if (d == nullptr) {
@ -27712,9 +27753,10 @@ vector<NotificationGroupKey> MessagesManager::get_message_notification_group_key
VLOG(notifications) << "Trying to load " << limit << " message notification groups from database from "
<< from_group_key;
G()->td_db()->get_dialog_db_sync()->begin_transaction().ensure();
auto *dialog_db = G()->td_db()->get_dialog_db_sync();
dialog_db->begin_transaction().ensure(); // read transaction
Result<vector<NotificationGroupKey>> r_notification_group_keys =
G()->td_db()->get_dialog_db_sync()->get_notification_groups_by_last_notification_date(from_group_key, limit);
dialog_db->get_notification_groups_by_last_notification_date(from_group_key, limit);
r_notification_group_keys.ensure();
auto group_keys = r_notification_group_keys.move_as_ok();
@ -27733,7 +27775,7 @@ vector<NotificationGroupKey> MessagesManager::get_message_notification_group_key
VLOG(notifications) << "Loaded " << group_key << " from database";
result.push_back(group_key);
}
G()->td_db()->get_dialog_db_sync()->commit_transaction().ensure();
dialog_db->commit_transaction().ensure();
return result;
}
@ -29281,14 +29323,13 @@ void MessagesManager::on_send_message_fail(int64 random_id, Status error) {
if (td_->auth_manager_->is_bot()) {
switch (dialog_id.get_type()) {
case DialogType::User:
case DialogType::SecretChat:
error_message = "Bot was blocked by the user";
break;
case DialogType::Chat:
case DialogType::Channel:
error_message = "Bot was kicked from the chat";
break;
case DialogType::SecretChat:
break;
case DialogType::None:
default:
UNREACHABLE();
@ -29296,14 +29337,13 @@ void MessagesManager::on_send_message_fail(int64 random_id, Status error) {
} else {
switch (dialog_id.get_type()) {
case DialogType::User:
case DialogType::SecretChat:
error_message = "User was blocked by the other user";
break;
case DialogType::Chat:
case DialogType::Channel:
error_message = "User is not in the chat";
break;
case DialogType::SecretChat:
break;
case DialogType::None:
default:
UNREACHABLE();
@ -29311,7 +29351,8 @@ void MessagesManager::on_send_message_fail(int64 random_id, Status error) {
}
// TODO add check to send_message
} else if (error.message() == "USER_IS_BOT") {
if (td_->auth_manager_->is_bot() && dialog_id.get_type() == DialogType::User) {
if (td_->auth_manager_->is_bot() &&
(dialog_id.get_type() == DialogType::User || dialog_id.get_type() == DialogType::SecretChat)) {
error_code = 403;
if (td_->contacts_manager_->is_user_bot(dialog_id.get_user_id())) {
error_message = "Bot can't send messages to bots";
@ -29322,7 +29363,8 @@ void MessagesManager::on_send_message_fail(int64 random_id, Status error) {
}
} else if (error.message() == "PEER_ID_INVALID") {
error_code = 403;
if (td_->auth_manager_->is_bot()) {
if (td_->auth_manager_->is_bot() &&
(dialog_id.get_type() == DialogType::User || dialog_id.get_type() == DialogType::SecretChat)) {
error_message = "Bot can't initiate conversation with a user";
}
} else if (error.message() == "WC_CONVERT_URL_INVALID" || error.message() == "EXTERNAL_URL_INVALID") {
@ -33943,7 +33985,9 @@ MessagesManager::Dialog *MessagesManager::get_dialog_by_message_id(MessageId mes
r_value.ok().second, false, "get_dialog_by_message_id");
if (m != nullptr) {
CHECK(m->message_id == message_id);
CHECK(message_id_to_dialog_id_[message_id] == dialog_id);
LOG_CHECK(message_id_to_dialog_id_[message_id] == dialog_id)
<< message_id << ' ' << dialog_id << ' ' << message_id_to_dialog_id_[message_id] << ' '
<< m->debug_source;
Dialog *d = get_dialog(dialog_id);
if (d == nullptr) {
LOG(ERROR) << "Unknown dialog " << dialog_id;
@ -34523,13 +34567,9 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
<< ", max_notification_message_id = " << d->max_notification_message_id;
if (d->messages != nullptr) {
auto get_debug_source = [](const unique_ptr<Message> &message) {
return message->debug_source != nullptr ? message->debug_source : "null";
};
LOG_CHECK(d->messages->message_id == last_message_id)
<< d->messages->message_id << ' ' << last_message_id << ' ' << get_debug_source(d->messages);
LOG_CHECK(d->messages->left == nullptr) << get_debug_source(d->messages->left);
LOG_CHECK(d->messages->right == nullptr) << get_debug_source(d->messages->right);
CHECK(d->messages->message_id == last_message_id);
CHECK(d->messages->left == nullptr);
CHECK(d->messages->right == nullptr);
}
// must be after update_dialog_pos, because uses d->order
@ -34839,7 +34879,7 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
if (new_order == DEFAULT_ORDER) {
// first addition of a new left dialog
if (folder.ordered_dialogs_.insert(new_date).second) {
for (auto &dialog_list : dialog_lists_) {
for (const auto &dialog_list : dialog_lists_) {
if (get_dialog_pinned_order(&dialog_list.second, d->dialog_id) != DEFAULT_ORDER) {
set_dialog_is_pinned(dialog_list.first, d, false);
}
@ -35502,7 +35542,7 @@ MessagesManager::get_dialog_positions(const Dialog *d) const {
CHECK(d != nullptr);
std::unordered_map<DialogListId, MessagesManager::DialogPositionInList, DialogListIdHash> positions;
if (!td_->auth_manager_->is_bot()) {
for (auto &dialog_list : dialog_lists_) {
for (const auto &dialog_list : dialog_lists_) {
positions.emplace(dialog_list.first, get_dialog_position_in_list(&dialog_list.second, d));
}
}
@ -36164,7 +36204,7 @@ void MessagesManager::on_get_channel_difference(
if (!td_->auth_manager_->is_bot()) {
// set is_pinned only after updating dialog pos to ensure that order is initialized
bool is_pinned = (dialog->flags_ & DIALOG_FLAG_IS_PINNED) != 0;
bool was_pinned = get_dialog_pinned_order(DialogListId(d->folder_id), dialog_id) != DEFAULT_ORDER;
bool was_pinned = is_dialog_pinned(DialogListId(d->folder_id), dialog_id);
if (is_pinned != was_pinned) {
set_dialog_is_pinned(DialogListId(d->folder_id), d, is_pinned);
}

View File

@ -1107,7 +1107,7 @@ class MessagesManager : public Actor {
int32 last_edit_pts = 0;
const char *debug_source = nullptr;
const char *debug_source = "null";
unique_ptr<Message> left;
unique_ptr<Message> right;
@ -1722,6 +1722,8 @@ class MessagesManager : public Actor {
bool is_dialog_mention_notifications_disabled(const Dialog *d) const;
bool is_dialog_pinned(DialogListId dialog_list_id, DialogId dialog_id) const;
int64 get_dialog_pinned_order(DialogListId dialog_list_id, DialogId dialog_id) const;
static int64 get_dialog_pinned_order(const DialogList *list, DialogId dialog_id);

View File

@ -51,6 +51,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/tl_parsers.h"

View File

@ -22,6 +22,7 @@
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
namespace td {

View File

@ -23,6 +23,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include <algorithm>
#include <cmath>

View File

@ -8,7 +8,7 @@
#include "td/telegram/PhotoSizeSource.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {

View File

@ -39,6 +39,7 @@
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/tl_helpers.h"

View File

@ -16,6 +16,7 @@
#include "td/utils/buffer.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include <limits>

View File

@ -33,6 +33,7 @@
#include "td/utils/overloaded.h"
#include "td/utils/Random.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StorerBase.h"
#include "td/utils/Time.h"
#include "td/utils/tl_parsers.h"

View File

@ -8,7 +8,7 @@
#include "td/db/KeyValueSyncInterface.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/tl_helpers.h"

View File

@ -34,6 +34,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Time.h"
@ -352,44 +353,44 @@ unique_ptr<SecretChatActor::Context> SecretChatsManager::make_secret_chat_contex
void on_inbound_message(UserId user_id, MessageId message_id, int32 date,
tl_object_ptr<telegram_api::encryptedFile> file,
tl_object_ptr<secret_api::decryptedMessage> message, Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::on_get_secret_message, secret_chat_id_, user_id,
message_id, date, std::move(file), std::move(message), std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::on_get_secret_message, secret_chat_id_, user_id,
message_id, date, std::move(file), std::move(message), std::move(promise));
}
void on_send_message_error(int64 random_id, Status error, Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::on_send_secret_message_error, random_id, std::move(error),
std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::on_send_secret_message_error, random_id,
std::move(error), std::move(promise));
}
void on_send_message_ack(int64 random_id) override {
send_closure(G()->messages_manager(), &MessagesManager::on_send_message_get_quick_ack, random_id);
send_closure_later(G()->messages_manager(), &MessagesManager::on_send_message_get_quick_ack, random_id);
}
void on_send_message_ok(int64 random_id, MessageId message_id, int32 date,
tl_object_ptr<telegram_api::EncryptedFile> file, Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::on_send_secret_message_success, random_id, message_id,
date, std::move(file), std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::on_send_secret_message_success, random_id,
message_id, date, std::move(file), std::move(promise));
}
void on_delete_messages(std::vector<int64> random_ids, Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::delete_secret_messages, secret_chat_id_,
std::move(random_ids), std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::delete_secret_messages, secret_chat_id_,
std::move(random_ids), std::move(promise));
}
void on_flush_history(bool remove_from_dialog_list, MessageId message_id, Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::delete_secret_chat_history, secret_chat_id_,
remove_from_dialog_list, message_id, std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::delete_secret_chat_history, secret_chat_id_,
remove_from_dialog_list, message_id, std::move(promise));
}
void on_read_message(int64 random_id, Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::open_secret_message, secret_chat_id_, random_id,
std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::open_secret_message, secret_chat_id_, random_id,
std::move(promise));
}
void on_screenshot_taken(UserId user_id, MessageId message_id, int32 date, int64 random_id,
Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::on_secret_chat_screenshot_taken, secret_chat_id_, user_id,
message_id, date, random_id, std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::on_secret_chat_screenshot_taken, secret_chat_id_,
user_id, message_id, date, random_id, std::move(promise));
}
void on_set_ttl(UserId user_id, MessageId message_id, int32 date, int32 ttl, int64 random_id,
Promise<> promise) override {
send_closure(G()->messages_manager(), &MessagesManager::on_secret_chat_ttl_changed, secret_chat_id_, user_id,
message_id, date, ttl, random_id, std::move(promise));
send_closure_later(G()->messages_manager(), &MessagesManager::on_secret_chat_ttl_changed, secret_chat_id_,
user_id, message_id, date, ttl, random_id, std::move(promise));
}
private:

View File

@ -23,6 +23,7 @@
#include "td/utils/misc.h"
#include "td/utils/optional.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include <memory>

View File

@ -13,6 +13,7 @@
#include "td/utils/port/FileFd.h"
#include "td/utils/Random.h"
#include "td/utils/SharedSlice.h"
#include "td/utils/SliceBuilder.h"
namespace td {
namespace secure_storage {

View File

@ -28,6 +28,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/overloaded.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/utf8.h"
#include <limits>

View File

@ -14,6 +14,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include <limits>

View File

@ -6,9 +6,9 @@
//
#include "td/telegram/SpecialStickerSetType.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
namespace td {

View File

@ -48,6 +48,7 @@
#include "td/utils/PathView.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
@ -6452,6 +6453,9 @@ void StickersManager::on_get_emoji_keywords_difference(
version = keywords->version_;
auto *pmc = G()->td_db()->get_sqlite_sync_pmc();
pmc->begin_transaction().ensure();
// set must be the first operation to start a write transaction
pmc->set(get_emoji_language_code_version_database_key(language_code), to_string(version));
pmc->set(get_emoji_language_code_last_difference_time_database_key(language_code), to_string(G()->unix_time()));
for (auto &keyword_ptr : keywords->keywords_) {
switch (keyword_ptr->get_id()) {
case telegram_api::emojiKeyword::ID: {
@ -6504,8 +6508,6 @@ void StickersManager::on_get_emoji_keywords_difference(
UNREACHABLE();
}
}
pmc->set(get_emoji_language_code_version_database_key(language_code), to_string(version));
pmc->set(get_emoji_language_code_last_difference_time_database_key(language_code), to_string(G()->unix_time()));
pmc->commit_transaction().ensure();
emoji_language_code_versions_[language_code] = version;
emoji_language_code_last_difference_times_[language_code] = static_cast<int32>(Time::now_cached());

View File

@ -96,6 +96,7 @@
#include "td/telegram/TopDialogCategory.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/UpdatesManager.h"
#include "td/telegram/Version.h"
#include "td/telegram/VideoNotesManager.h"
#include "td/telegram/VideosManager.h"
#include "td/telegram/VoiceNotesManager.h"
@ -131,6 +132,7 @@
#include "td/utils/port/uname.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Timer.h"
#include "td/utils/tl_parsers.h"
@ -3005,6 +3007,8 @@ class SetBackgroundRequest : public RequestActor<> {
Td::Td(unique_ptr<TdCallback> callback, Options options)
: callback_(std::move(callback)), td_options_(std::move(options)) {
CHECK(callback_ != nullptr);
LOG(INFO) << "Create Td with layer " << MTPROTO_LAYER << ", database version " << current_db_version()
<< " and version " << static_cast<int32>(Version::Next) - 1;
}
Td::~Td() = default;

View File

@ -32,6 +32,7 @@
#include "td/utils/misc.h"
#include "td/utils/port/path.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include <algorithm>

View File

@ -26,6 +26,7 @@
#include "td/utils/port/Clocks.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/tl_helpers.h"

View File

@ -21,6 +21,7 @@
#include "td/telegram/DialogAction.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/DialogInviteLink.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/FolderId.h"
#include "td/telegram/Global.h"
#include "td/telegram/GroupCallManager.h"
@ -56,6 +57,7 @@
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
@ -2618,7 +2620,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatDefaultBann
case DialogType::User:
case DialogType::SecretChat:
default:
LOG(ERROR) << "Receive updateChatDefaultBannedRights in the " << dialog_id;
LOG(ERROR) << "Receive updateChatDefaultBannedRights in " << dialog_id;
break;
}
promise.set_value(Unit());

View File

@ -32,6 +32,7 @@
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
#include <type_traits>

View File

@ -46,6 +46,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/utf8.h"

View File

@ -13,13 +13,14 @@
#include "td/net/HttpReader.h"
#include "td/telegram/ClientActor.h"
#include "td/telegram/Log.h"
#include "td/telegram/Client.h"
#include "td/telegram/Td.h" // for VERBOSITY_NAME(td_requests)
#include "td/telegram/td_api_json.h"
#include "td/utils/algorithm.h"
#include "td/utils/base64.h"
#include "td/utils/buffer.h"
#include "td/utils/CombinedLog.h"
#include "td/utils/common.h"
#include "td/utils/crypto.h"
#include "td/utils/ExitGuard.h"
@ -29,6 +30,7 @@
#include "td/utils/JsonBuilder.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/NullLog.h"
#include "td/utils/OptionParser.h"
#include "td/utils/port/FileFd.h"
#include "td/utils/port/PollFlags.h"
@ -39,9 +41,11 @@
#include "td/utils/Random.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/TsLog.h"
#include "td/utils/utf8.h"
#ifndef USE_READLINE
@ -188,28 +192,19 @@ static char **tg_cli_completion(const char *text, int start, int end) {
#endif
class CliLog : public LogInterface {
public:
void append(CSlice slice, int log_level) override {
void do_append(int log_level, CSlice slice) final {
#ifdef USE_READLINE
deactivate_readline();
SCOPE_EXIT {
reactivate_readline();
};
#endif
if (log_level == VERBOSITY_NAME(PLAIN)) {
#if TD_WINDOWS
TsCerr() << slice;
#else
TsCerr() << TC_GREEN << slice << TC_EMPTY;
#endif
} else {
default_log_interface->append(slice, log_level);
}
}
void rotate() override {
default_log_interface->do_append(log_level, slice);
}
};
static CombinedLog combined_log;
struct SendMessageInfo {
double start_time = 0;
double quick_ack_time = 0;
@ -740,7 +735,7 @@ class CliClient final : public Actor {
}
}
if (id > 0 && GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) {
if (id > 0 && combined_log.get_first_verbosity_level() < VERBOSITY_NAME(td_requests)) {
LOG(ERROR) << "Receive result [" << generation << "][id=" << id << "] " << result_str;
}
@ -859,7 +854,7 @@ class CliClient final : public Actor {
}
void on_error(uint64 generation, uint64 id, td_api::object_ptr<td_api::error> error) {
if (id > 0 && GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) {
if (id > 0 && combined_log.get_first_verbosity_level() < VERBOSITY_NAME(td_requests)) {
LOG(ERROR) << "Receive error [" << generation << "][id=" << id << "] " << to_string(error);
}
}
@ -1561,11 +1556,11 @@ class CliClient final : public Actor {
}
static td_api::object_ptr<td_api::Object> execute(td_api::object_ptr<td_api::Function> f) {
if (GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) {
if (combined_log.get_first_verbosity_level() < VERBOSITY_NAME(td_requests)) {
LOG(ERROR) << "Execute request: " << to_string(f);
}
auto res = ClientActor::execute(std::move(f));
if (GET_VERBOSITY_LEVEL() < VERBOSITY_NAME(td_requests)) {
if (combined_log.get_first_verbosity_level() < VERBOSITY_NAME(td_requests)) {
LOG(ERROR) << "Execute response: " << to_string(res);
}
return res;
@ -4165,12 +4160,10 @@ class CliClient final : public Actor {
<< ", user ticks = " << stats.process_user_ticks_
<< ", system ticks = " << stats.process_system_ticks_;
}
} else if (op == "SetVerbosity" || op == "SV") {
Log::set_verbosity_level(to_integer<int>(args));
} else if (op[0] == 'v' && op[1] == 'v') {
Log::set_verbosity_level(static_cast<int>(op.size()));
} else if (op[0] == 'v' && ('0' <= op[1] && op[1] <= '9')) {
Log::set_verbosity_level(to_integer<int>(op.substr(1)));
} else if (op[0] == 'v' && (op[1] == 'v' || is_digit(op[1]))) {
int new_verbosity_level = op[1] == 'v' ? static_cast<int>(op.size()) : to_integer<int>(op.substr(1));
SET_VERBOSITY_LEVEL(td::max(new_verbosity_level, VERBOSITY_NAME(DEBUG)));
combined_log.set_first_verbosity_level(new_verbosity_level);
} else if (op == "slse") {
execute(td_api::make_object<td_api::setLogStream>(td_api::make_object<td_api::logStreamEmpty>()));
} else if (op == "slsd") {
@ -4370,8 +4363,11 @@ static void fail_signal(int sig) {
}
}
static void on_fatal_error(const char *error) {
std::cerr << "Fatal error: " << error << std::endl;
static void on_log_message(int verbosity_level, const char *message) {
if (verbosity_level == 0) {
std::cerr << "Fatal error: " << message;
}
std::cerr << "Log message: " << message;
}
void main(int argc, char **argv) {
@ -4380,7 +4376,7 @@ void main(int argc, char **argv) {
ignore_signal(SignalType::Pipe).ensure();
set_signal_handler(SignalType::Error, fail_signal).ensure();
set_signal_handler(SignalType::Abort, fail_signal).ensure();
Log::set_fatal_error_callback(on_fatal_error);
ClientManager::set_log_message_callback(0, on_log_message);
init_openssl_threads();
const char *locale_name = (std::setlocale(LC_ALL, "fr-FR") == nullptr ? "C" : "fr-FR");
@ -4393,11 +4389,14 @@ void main(int argc, char **argv) {
};
CliLog cli_log;
log_interface = &cli_log;
FileLog file_log;
TsLog ts_log(&file_log);
combined_log.set_first(&cli_log);
log_interface = &combined_log;
int new_verbosity_level = VERBOSITY_NAME(INFO);
bool use_test_dc = false;
bool get_chat_list = false;
@ -4432,7 +4431,7 @@ void main(int argc, char **argv) {
options.add_option('l', "log", "Log to file", [&](Slice file_name) {
if (file_log.init(file_name.str()).is_ok() && file_log.init(file_name.str()).is_ok() &&
file_log.init(file_name.str(), 1000 << 20).is_ok()) {
log_interface = &ts_log;
combined_log.set_first(&ts_log);
}
});
options.add_option('W', "", "Preload chat list", [&] { get_chat_list = true; });
@ -4454,7 +4453,15 @@ void main(int argc, char **argv) {
return;
}
SET_VERBOSITY_LEVEL(new_verbosity_level);
SET_VERBOSITY_LEVEL(td::max(new_verbosity_level, VERBOSITY_NAME(DEBUG)));
combined_log.set_first_verbosity_level(new_verbosity_level);
if (combined_log.get_first() == &cli_log) {
file_log.init("tg_cli.log", 1000 << 20).ensure();
file_log.lazy_rotate();
combined_log.set_second(&ts_log);
combined_log.set_second_verbosity_level(VERBOSITY_NAME(DEBUG));
}
{
ConcurrentScheduler scheduler;

View File

@ -25,6 +25,7 @@
#include "td/utils/misc.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/Status.h"
#include "td/utils/tl_helpers.h"

View File

@ -27,6 +27,7 @@
#include "td/utils/port/path.h"
#include "td/utils/port/Stat.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/UInt.h"
#include <tuple>

View File

@ -27,6 +27,7 @@
#include "td/utils/port/path.h"
#include "td/utils/port/Stat.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include <cmath>
#include <memory>

View File

@ -12,7 +12,7 @@
#include "td/utils/common.h"
#include "td/utils/filesystem.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
namespace td {

View File

@ -19,6 +19,7 @@
#include "td/utils/port/FileFd.h"
#include "td/utils/port/path.h"
#include "td/utils/Random.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include <tuple>
@ -66,9 +67,9 @@ Result<std::pair<FileFd, string>> open_temp_file(FileType file_type) {
pmc->set("tmp_file_id", to_string(file_id + 1));
auto temp_dir = get_files_temp_dir(file_type);
auto res = try_create_new_file(PSLICE_SAFE() << temp_dir << file_id);
auto res = try_create_new_file(PSLICE() << temp_dir << file_id);
if (res.is_error()) {
res = try_create_new_file(PSLICE_SAFE() << temp_dir << file_id << "_" << RandSuff{6});
res = try_create_new_file(PSLICE() << temp_dir << file_id << "_" << RandSuff{6});
}
return res;
}
@ -88,20 +89,20 @@ bool for_suggested_file_name(CSlice name, bool use_pmc, bool use_random, F &&cal
auto ext = path_view.extension();
bool active = true;
if (!stem.empty() && !G()->parameters().ignore_file_names) {
active = try_callback(PSLICE_SAFE() << stem << Ext{ext});
active = try_callback(PSLICE() << stem << Ext{ext});
for (int i = 0; active && i < 10; i++) {
active = try_callback(PSLICE_SAFE() << stem << "_(" << i << ")" << Ext{ext});
active = try_callback(PSLICE() << stem << "_(" << i << ")" << Ext{ext});
}
for (int i = 2; active && i < 12 && use_random; i++) {
active = try_callback(PSLICE_SAFE() << stem << "_(" << RandSuff{i} << ")" << Ext{ext});
active = try_callback(PSLICE() << stem << "_(" << RandSuff{i} << ")" << Ext{ext});
}
} else if (use_pmc) {
auto pmc = G()->td_db()->get_binlog_pmc();
int32 file_id = to_integer<int32>(pmc->get("perm_file_id"));
pmc->set("perm_file_id", to_string(file_id + 1));
active = try_callback(PSLICE_SAFE() << "file_" << file_id << Ext{ext});
active = try_callback(PSLICE() << "file_" << file_id << Ext{ext});
if (active) {
active = try_callback(PSLICE_SAFE() << "file_" << file_id << "_" << RandSuff{6} << Ext{ext});
active = try_callback(PSLICE() << "file_" << file_id << "_" << RandSuff{6} << Ext{ext});
}
}
return active;
@ -112,7 +113,7 @@ Result<string> create_from_temp(CSlice temp_path, CSlice dir, CSlice name) {
<< temp_path;
Result<std::pair<FileFd, string>> res = Status::Error(500, "Can't find suitable file name");
for_suggested_file_name(name, true, true, [&](CSlice suggested_name) {
res = try_create_new_file(PSLICE_SAFE() << dir << suggested_name);
res = try_create_new_file(PSLICE() << dir << suggested_name);
return res.is_error();
});
TRY_RESULT(tmp, std::move(res));
@ -125,7 +126,7 @@ Result<string> create_from_temp(CSlice temp_path, CSlice dir, CSlice name) {
Result<string> search_file(CSlice dir, CSlice name, int64 expected_size) {
Result<std::string> res = Status::Error(500, "Can't find suitable file name");
for_suggested_file_name(name, false, false, [&](CSlice suggested_name) {
auto r_pair = try_open_file(PSLICE_SAFE() << dir << suggested_name);
auto r_pair = try_open_file(PSLICE() << dir << suggested_name);
if (r_pair.is_error()) {
return false;
}

View File

@ -38,6 +38,7 @@
#include "td/utils/port/path.h"
#include "td/utils/port/Stat.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"

View File

@ -17,6 +17,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {

View File

@ -25,6 +25,7 @@
#include "td/utils/port/path.h"
#include "td/utils/port/Stat.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Time.h"
#include "td/utils/tl_parsers.h"

View File

@ -11,6 +11,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include <limits>
#include <numeric>

View File

@ -15,6 +15,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"
#include "td/utils/StringBuilder.h"

View File

@ -9,9 +9,9 @@
#include "td/utils/algorithm.h"
#include "td/utils/common.h"
#include "td/utils/HttpUrl.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/utf8.h"
#include <cstring>

View File

@ -13,6 +13,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/port/RwMutex.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {

View File

@ -36,6 +36,7 @@
#include "td/utils/port/IPAddress.h"
#include "td/utils/Random.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"

View File

@ -14,6 +14,7 @@
#include "td/utils/algorithm.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#include <algorithm>
#include <set>

View File

@ -11,7 +11,7 @@
#include "td/utils/as.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
namespace td {

View File

@ -25,7 +25,7 @@ NetQueryPtr NetQueryCreator::create(const telegram_api::Function &function, DcId
NetQueryPtr NetQueryCreator::create(uint64 id, const telegram_api::Function &function, DcId dc_id, NetQuery::Type type,
NetQuery::AuthFlag auth_flag) {
LOG(DEBUG) << "Create query " << to_string(function);
LOG(INFO) << "Create query " << to_string(function);
auto storer = DefaultStorer<telegram_api::Function>(function);
BufferSlice slice(storer.size());
auto real_size = storer.store(slice.as_slice().ubegin());

View File

@ -14,6 +14,7 @@
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
namespace td {

View File

@ -26,6 +26,7 @@
#include "td/utils/misc.h"
#include "td/utils/port/thread.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
namespace td {

View File

@ -11,6 +11,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
namespace td {

View File

@ -20,6 +20,7 @@
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td {

View File

@ -10,6 +10,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include <algorithm>

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