Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
6d1329ee7a
@ -9,12 +9,16 @@
|
||||
# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
|
||||
# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch.
|
||||
#
|
||||
# IOS_ARCH = automatic(default) or "arch1;arch2" (e.q. "x86_64;arm64")
|
||||
# By default this value will be automatically chosen based on the IOS_PLATFORM value above.
|
||||
# If set manually, it will override the default and force to build those architectures only.
|
||||
#
|
||||
# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
|
||||
# By default this location is automatcially chosen based on the IOS_PLATFORM value above.
|
||||
# By default this location is automatically chosen based on the IOS_PLATFORM value above.
|
||||
# If set manually, it will override the default location and force the user of a particular Developer Platform
|
||||
#
|
||||
# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
|
||||
# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
|
||||
# By default this location is automatically chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
|
||||
# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
|
||||
# If set manually, this will force the use of a specific SDK version
|
||||
|
||||
@ -191,7 +195,8 @@ set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the select
|
||||
# Set the sysroot default to the most recent SDK
|
||||
set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
|
||||
|
||||
# set the architecture for iOS
|
||||
# Set the architectures unless specified manually with IOS_ARCH
|
||||
if (NOT DEFINED IOS_ARCH)
|
||||
if (IOS_PLATFORM STREQUAL "OS")
|
||||
set (IOS_ARCH "armv7;armv7s;arm64")
|
||||
elseif (IOS_PLATFORM STREQUAL "SIMULATOR")
|
||||
@ -204,10 +209,9 @@ elseif (IOS_PLATFORM STREQUAL "TVOS")
|
||||
set (IOS_ARCH "arm64")
|
||||
elseif (IOS_PLATFORM STREQUAL "TVSIMULATOR")
|
||||
set (IOS_ARCH "x86_64;arm64")
|
||||
else()
|
||||
message (WARNING "Unknown IOS_PLATFORM=<${IOS_PLATFORM}>")
|
||||
endif()
|
||||
message (STATUS ${IOS_ARCH})
|
||||
endif()
|
||||
message (STATUS "The iOS architectures: ${IOS_ARCH}")
|
||||
|
||||
set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS")
|
||||
|
||||
|
@ -389,6 +389,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/NotificationManager.cpp
|
||||
td/telegram/NotificationSettings.cpp
|
||||
td/telegram/NotificationType.cpp
|
||||
td/telegram/OptionManager.cpp
|
||||
td/telegram/Payments.cpp
|
||||
td/telegram/PasswordManager.cpp
|
||||
td/telegram/PhoneNumberManager.cpp
|
||||
@ -604,6 +605,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/NotificationManager.h
|
||||
td/telegram/NotificationSettings.h
|
||||
td/telegram/NotificationType.h
|
||||
td/telegram/OptionManager.h
|
||||
td/telegram/PasswordManager.h
|
||||
td/telegram/Payments.h
|
||||
td/telegram/PhoneNumberManager.h
|
||||
|
@ -297,6 +297,7 @@ function split_file($file, $chunks, $undo) {
|
||||
'MessageCopyOptions' => 'MessageCopyOptions',
|
||||
'messages_manager[_(-][^.]|MessagesManager' => 'MessagesManager',
|
||||
'notification_manager[_(-][^.]|NotificationManager|notifications[)]' => 'NotificationManager',
|
||||
'option_manager[_(-][^.]|OptionManager' => "OptionManager",
|
||||
'phone_number_manager[_(-][^.]|PhoneNumberManager' => "PhoneNumberManager",
|
||||
'poll_manager[_(-][^.]|PollManager' => "PollManager",
|
||||
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
||||
|
@ -843,8 +843,11 @@ messageCalendarDay total_count:int32 message:message = MessageCalendarDay;
|
||||
messageCalendar total_count:int32 days:vector<messageCalendarDay> = MessageCalendar;
|
||||
|
||||
|
||||
//@description Describes a sponsored message @id Unique sponsored message identifier @sponsor_chat_id Chat identifier
|
||||
//@link An internal link to be opened when the sponsored message is clicked; may be null. If null, the sponsor chat needs to be opened instead @content Content of the message. Currently, can be only of the type messageText
|
||||
//@description Describes a sponsored message
|
||||
//@id Unique sponsored message identifier
|
||||
//@sponsor_chat_id Chat identifier
|
||||
//@link An internal link to be opened when the sponsored message is clicked; may be null. If null, the sponsor chat needs to be opened instead
|
||||
//@content Content of the message. Currently, can be only of the type messageText
|
||||
sponsoredMessage id:int32 sponsor_chat_id:int53 link:InternalLinkType content:MessageContent = SponsoredMessage;
|
||||
|
||||
//@description Contains a list of sponsored messages @messages List of sponsored messages
|
||||
|
@ -100,7 +100,9 @@ telegram_api::object_ptr<telegram_api::BotCommandScope> BotCommandScope::get_inp
|
||||
const Td *td) const {
|
||||
auto input_peer =
|
||||
dialog_id_.is_valid() ? td->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read) : nullptr;
|
||||
auto input_user = user_id_.is_valid() ? td->contacts_manager_->get_input_user(user_id_) : nullptr;
|
||||
auto input_user = td->contacts_manager_->have_input_user(user_id_)
|
||||
? td->contacts_manager_->get_input_user(user_id_).move_as_ok()
|
||||
: nullptr;
|
||||
switch (type_) {
|
||||
case Type::Default:
|
||||
return telegram_api::make_object<telegram_api::botCommandScopeDefault>();
|
||||
|
@ -6,8 +6,6 @@
|
||||
//
|
||||
#include "td/telegram/ConfigShared.h"
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
@ -103,10 +101,6 @@ string ConfigShared::get_option_string(Slice name, string default_value) const {
|
||||
return str_value.substr(1);
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::OptionValue> ConfigShared::get_option_value(Slice name) const {
|
||||
return get_option_value_object(get_option(name));
|
||||
}
|
||||
|
||||
bool ConfigShared::set_option(Slice name, Slice value) {
|
||||
if (value.empty()) {
|
||||
return config_pmc_->erase(name.str()) != 0;
|
||||
@ -115,29 +109,6 @@ bool ConfigShared::set_option(Slice name, Slice value) {
|
||||
}
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::OptionValue> ConfigShared::get_option_value_object(Slice value) {
|
||||
if (value.empty()) {
|
||||
return make_tl_object<td_api::optionValueEmpty>();
|
||||
}
|
||||
|
||||
switch (value[0]) {
|
||||
case 'B':
|
||||
if (value == "Btrue") {
|
||||
return make_tl_object<td_api::optionValueBoolean>(true);
|
||||
}
|
||||
if (value == "Bfalse") {
|
||||
return make_tl_object<td_api::optionValueBoolean>(false);
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
return make_tl_object<td_api::optionValueInteger>(to_integer<int64>(value.substr(1)));
|
||||
case 'S':
|
||||
return make_tl_object<td_api::optionValueString>(value.substr(1).str());
|
||||
}
|
||||
|
||||
return make_tl_object<td_api::optionValueString>(value.str());
|
||||
}
|
||||
|
||||
void ConfigShared::on_option_updated(Slice name) const {
|
||||
if (callback_ != nullptr) {
|
||||
callback_->on_option_updated(name.str(), get_option(name));
|
||||
|
@ -6,8 +6,6 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
|
||||
#include "td/db/KeyValueSyncInterface.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
@ -41,24 +39,21 @@ class ConfigShared {
|
||||
void set_option_string(Slice name, Slice value);
|
||||
|
||||
bool have_option(Slice name) const;
|
||||
|
||||
string get_option(Slice name) const;
|
||||
|
||||
std::unordered_map<string, string> get_options() const;
|
||||
|
||||
bool get_option_boolean(Slice name, bool default_value = false) const;
|
||||
int64 get_option_integer(Slice name, int64 default_value = 0) const;
|
||||
string get_option_string(Slice name, string default_value = "") const;
|
||||
|
||||
tl_object_ptr<td_api::OptionValue> get_option_value(Slice name) const;
|
||||
|
||||
static tl_object_ptr<td_api::OptionValue> get_option_value_object(Slice value);
|
||||
|
||||
private:
|
||||
std::shared_ptr<KeyValueSyncInterface> config_pmc_;
|
||||
unique_ptr<Callback> callback_;
|
||||
|
||||
bool set_option(Slice name, Slice value);
|
||||
|
||||
string get_option(Slice name) const;
|
||||
|
||||
void on_option_updated(Slice name) const;
|
||||
};
|
||||
|
||||
|
@ -1432,8 +1432,8 @@ class GetExportedChatInvitesQuery final : public Td::ResultHandler {
|
||||
return on_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(creator_user_id);
|
||||
CHECK(input_user != nullptr);
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(creator_user_id);
|
||||
CHECK(r_input_user.is_ok());
|
||||
|
||||
int32 flags = 0;
|
||||
if (!offset_invite_link.empty() || offset_date != 0) {
|
||||
@ -1443,9 +1443,9 @@ class GetExportedChatInvitesQuery final : public Td::ResultHandler {
|
||||
if (is_revoked) {
|
||||
flags |= telegram_api::messages_getExportedChatInvites::REVOKED_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_getExportedChatInvites(flags, false /*ignored*/, std::move(input_peer),
|
||||
std::move(input_user), offset_date, offset_invite_link, limit)));
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getExportedChatInvites(
|
||||
flags, false /*ignored*/, std::move(input_peer), r_input_user.move_as_ok(), offset_date, offset_invite_link,
|
||||
limit)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -1549,15 +1549,15 @@ class GetChatInviteImportersQuery final : public Td::ResultHandler {
|
||||
return on_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(offset_user_id);
|
||||
if (input_user == nullptr) {
|
||||
input_user = make_tl_object<telegram_api::inputUserEmpty>();
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(offset_user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
r_input_user = make_tl_object<telegram_api::inputUserEmpty>();
|
||||
}
|
||||
|
||||
int32 flags = telegram_api::messages_getChatInviteImporters::LINK_MASK;
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_getChatInviteImporters(flags, false /*ignored*/, std::move(input_peer), invite_link,
|
||||
string(), offset_date, std::move(input_user), limit)));
|
||||
string(), offset_date, r_input_user.move_as_ok(), limit)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -1620,9 +1620,9 @@ class GetChatJoinRequestsQuery final : public Td::ResultHandler {
|
||||
return on_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(offset_user_id);
|
||||
if (input_user == nullptr) {
|
||||
input_user = make_tl_object<telegram_api::inputUserEmpty>();
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(offset_user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
r_input_user = make_tl_object<telegram_api::inputUserEmpty>();
|
||||
}
|
||||
|
||||
int32 flags = telegram_api::messages_getChatInviteImporters::REQUESTED_MASK;
|
||||
@ -1634,7 +1634,7 @@ class GetChatJoinRequestsQuery final : public Td::ResultHandler {
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_getChatInviteImporters(flags, false /*ignored*/, std::move(input_peer), invite_link,
|
||||
query, offset_date, std::move(input_user), limit)));
|
||||
query, offset_date, r_input_user.move_as_ok(), limit)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -1697,9 +1697,9 @@ class HideChatJoinRequestQuery final : public Td::ResultHandler {
|
||||
return on_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return on_error(Status::Error(400, "Can't find user"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return on_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
int32 flags = 0;
|
||||
@ -1707,7 +1707,7 @@ class HideChatJoinRequestQuery final : public Td::ResultHandler {
|
||||
flags |= telegram_api::messages_hideChatJoinRequest::APPROVED_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_hideChatJoinRequest(
|
||||
flags, false /*ignored*/, std::move(input_peer), std::move(input_user))));
|
||||
flags, false /*ignored*/, std::move(input_peer), r_input_user.move_as_ok())));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -1894,11 +1894,11 @@ class DeleteRevokedExportedChatInvitesQuery final : public Td::ResultHandler {
|
||||
return on_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(creator_user_id);
|
||||
CHECK(input_user != nullptr);
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(creator_user_id);
|
||||
CHECK(r_input_user.is_ok());
|
||||
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_deleteRevokedExportedChatInvites(std::move(input_peer), std::move(input_user))));
|
||||
telegram_api::messages_deleteRevokedExportedChatInvites(std::move(input_peer), r_input_user.move_as_ok())));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -2209,10 +2209,10 @@ class CanEditChannelCreatorQuery final : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
void send() {
|
||||
auto input_user = td_->contacts_manager_->get_input_user(td_->contacts_manager_->get_my_id());
|
||||
CHECK(input_user != nullptr);
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(td_->contacts_manager_->get_my_id());
|
||||
CHECK(r_input_user.is_ok());
|
||||
send_query(G()->net_query_creator().create(telegram_api::channels_editCreator(
|
||||
telegram_api::make_object<telegram_api::inputChannelEmpty>(), std::move(input_user),
|
||||
telegram_api::make_object<telegram_api::inputChannelEmpty>(), r_input_user.move_as_ok(),
|
||||
make_tl_object<telegram_api::inputCheckPasswordEmpty>())));
|
||||
}
|
||||
|
||||
@ -2247,12 +2247,12 @@ class EditChannelCreatorQuery final : public Td::ResultHandler {
|
||||
if (input_channel == nullptr) {
|
||||
return promise_.set_error(Status::Error(400, "Have no access to the chat"));
|
||||
}
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise_.set_error(Status::Error(400, "Have no access to the user"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise_.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
send_query(G()->net_query_creator().create(telegram_api::channels_editCreator(
|
||||
std::move(input_channel), std::move(input_user), std::move(input_check_password))));
|
||||
std::move(input_channel), r_input_user.move_as_ok(), std::move(input_check_password))));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -4360,17 +4360,20 @@ void ContactsManager::SecretChat::parse(ParserT &parser) {
|
||||
}
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::InputUser> ContactsManager::get_input_user(UserId user_id) const {
|
||||
Result<tl_object_ptr<telegram_api::InputUser>> ContactsManager::get_input_user(UserId user_id) const {
|
||||
if (user_id == get_my_id()) {
|
||||
return make_tl_object<telegram_api::inputUserSelf>();
|
||||
}
|
||||
|
||||
const User *u = get_user(user_id);
|
||||
if (u == nullptr || u->access_hash == -1 || u->is_min_access_hash) {
|
||||
if (u == nullptr) {
|
||||
return Status::Error(400, "User not found");
|
||||
}
|
||||
if (u->access_hash == -1 || u->is_min_access_hash) {
|
||||
if (td_->auth_manager_->is_bot() && user_id.is_valid()) {
|
||||
return make_tl_object<telegram_api::inputUser>(user_id.get(), 0);
|
||||
}
|
||||
return nullptr;
|
||||
return Status::Error(400, "Have no access to the user");
|
||||
}
|
||||
|
||||
return make_tl_object<telegram_api::inputUser>(user_id.get(), u->access_hash);
|
||||
@ -5167,13 +5170,13 @@ void ContactsManager::add_contact(Contact contact, bool share_phone_number, Prom
|
||||
LOG(INFO) << "Add " << contact << " with share_phone_number = " << share_phone_number;
|
||||
|
||||
auto user_id = contact.get_user_id();
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<AddContactQuery>(std::move(promise))
|
||||
->send(user_id, std::move(input_user), contact, share_phone_number);
|
||||
->send(user_id, r_input_user.move_as_ok(), contact, share_phone_number);
|
||||
}
|
||||
|
||||
std::pair<vector<UserId>, vector<int32>> ContactsManager::import_contacts(const vector<Contact> &contacts,
|
||||
@ -5303,10 +5306,10 @@ void ContactsManager::remove_contacts(const vector<UserId> &user_ids, Promise<Un
|
||||
for (auto &user_id : user_ids) {
|
||||
const User *u = get_user(user_id);
|
||||
if (u != nullptr && u->is_contact) {
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user != nullptr) {
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_ok()) {
|
||||
to_delete_user_ids.push_back(user_id);
|
||||
input_users.push_back(std::move(input_user));
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5653,14 +5656,14 @@ void ContactsManager::share_phone_number(UserId user_id, Promise<Unit> &&promise
|
||||
}
|
||||
|
||||
LOG(INFO) << "Share phone number with " << user_id;
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
td_->messages_manager_->hide_dialog_action_bar(DialogId(user_id));
|
||||
|
||||
td_->create_handler<AcceptContactQuery>(std::move(promise))->send(user_id, std::move(input_user));
|
||||
td_->create_handler<AcceptContactQuery>(std::move(promise))->send(user_id, r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
void ContactsManager::search_dialogs_nearby(const Location &location,
|
||||
@ -6774,13 +6777,13 @@ void ContactsManager::add_chat_participant(ChatId chat_id, UserId user_id, int32
|
||||
}
|
||||
// TODO upper bound on forward_limit
|
||||
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
// TODO invoke after
|
||||
td_->create_handler<AddChatUserQuery>(std::move(promise))->send(chat_id, std::move(input_user), forward_limit);
|
||||
td_->create_handler<AddChatUserQuery>(std::move(promise))->send(chat_id, r_input_user.move_as_ok(), forward_limit);
|
||||
}
|
||||
|
||||
void ContactsManager::add_channel_participant(ChannelId channel_id, UserId user_id,
|
||||
@ -6793,9 +6796,9 @@ void ContactsManager::add_channel_participant(ChannelId channel_id, UserId user_
|
||||
if (c == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Chat info not found"));
|
||||
}
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
if (user_id == get_my_id()) {
|
||||
@ -6815,7 +6818,7 @@ void ContactsManager::add_channel_participant(ChannelId channel_id, UserId user_
|
||||
|
||||
speculative_add_channel_user(channel_id, user_id, DialogParticipantStatus::Member(), old_status);
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> input_users;
|
||||
input_users.push_back(std::move(input_user));
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
td_->create_handler<InviteToChannelQuery>(std::move(promise))->send(channel_id, std::move(input_users));
|
||||
}
|
||||
|
||||
@ -6836,16 +6839,16 @@ void ContactsManager::add_channel_participants(ChannelId channel_id, const vecto
|
||||
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> input_users;
|
||||
for (auto user_id : user_ids) {
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
if (user_id == get_my_id()) {
|
||||
// can't invite self
|
||||
continue;
|
||||
}
|
||||
input_users.push_back(std::move(input_user));
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
if (input_users.empty()) {
|
||||
@ -6922,9 +6925,10 @@ void ContactsManager::set_channel_participant_status_impl(ChannelId channel_id,
|
||||
}
|
||||
if (status.is_member() == old_status.is_member()) {
|
||||
// change rank and is_anonymous
|
||||
auto input_user = get_input_user(get_my_id());
|
||||
CHECK(input_user != nullptr);
|
||||
td_->create_handler<EditChannelAdminQuery>(std::move(promise))->send(channel_id, std::move(input_user), status);
|
||||
auto r_input_user = get_input_user(get_my_id());
|
||||
CHECK(r_input_user.is_ok());
|
||||
td_->create_handler<EditChannelAdminQuery>(std::move(promise))
|
||||
->send(channel_id, r_input_user.move_as_ok(), status);
|
||||
return;
|
||||
}
|
||||
if (status.is_member()) {
|
||||
@ -7003,13 +7007,13 @@ void ContactsManager::promote_channel_participant(ChannelId channel_id, UserId u
|
||||
CHECK(!status.is_creator());
|
||||
}
|
||||
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
speculative_add_channel_user(channel_id, user_id, status, old_status);
|
||||
td_->create_handler<EditChannelAdminQuery>(std::move(promise))->send(channel_id, std::move(input_user), status);
|
||||
td_->create_handler<EditChannelAdminQuery>(std::move(promise))->send(channel_id, r_input_user.move_as_ok(), status);
|
||||
}
|
||||
|
||||
void ContactsManager::set_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status,
|
||||
@ -7081,12 +7085,13 @@ void ContactsManager::set_chat_participant_status(ChatId chat_id, UserId user_id
|
||||
|
||||
void ContactsManager::send_edit_chat_admin_query(ChatId chat_id, UserId user_id, bool is_administrator,
|
||||
Promise<Unit> &&promise) {
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<EditChatAdminQuery>(std::move(promise))->send(chat_id, std::move(input_user), is_administrator);
|
||||
td_->create_handler<EditChatAdminQuery>(std::move(promise))
|
||||
->send(chat_id, r_input_user.move_as_ok(), is_administrator);
|
||||
}
|
||||
|
||||
void ContactsManager::can_transfer_ownership(Promise<CanTransferOwnershipResult> &&promise) {
|
||||
@ -7473,13 +7478,14 @@ void ContactsManager::delete_chat_participant(ChatId chat_id, UserId user_id, bo
|
||||
}
|
||||
}
|
||||
}
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
// TODO invoke after
|
||||
td_->create_handler<DeleteChatUserQuery>(std::move(promise))->send(chat_id, std::move(input_user), revoke_messages);
|
||||
td_->create_handler<DeleteChatUserQuery>(std::move(promise))
|
||||
->send(chat_id, r_input_user.move_as_ok(), revoke_messages);
|
||||
}
|
||||
|
||||
void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
|
||||
@ -10322,6 +10328,8 @@ void ContactsManager::on_get_users(vector<tl_object_ptr<telegram_api::User>> &&u
|
||||
}
|
||||
|
||||
void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&user) {
|
||||
LOG(INFO) << "Receive " << to_string(user);
|
||||
|
||||
UserId user_id(user->id_);
|
||||
User *u = get_user(user_id);
|
||||
if (u == nullptr) {
|
||||
@ -13971,14 +13979,14 @@ bool ContactsManager::get_user(UserId user_id, int left_tries, Promise<Unit> &&p
|
||||
std::move(promise));
|
||||
return false;
|
||||
}
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (left_tries == 1 || input_user == nullptr) {
|
||||
promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (left_tries == 1 || r_input_user.is_error()) {
|
||||
promise.set_error(r_input_user.move_as_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> users;
|
||||
users.push_back(std::move(input_user));
|
||||
users.push_back(r_input_user.move_as_ok());
|
||||
td_->create_handler<GetUsersQuery>(std::move(promise))->send(std::move(users));
|
||||
return false;
|
||||
}
|
||||
@ -14029,14 +14037,14 @@ void ContactsManager::reload_user(UserId user_id, Promise<Unit> &&promise) {
|
||||
}
|
||||
|
||||
have_user_force(user_id);
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User info not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
// there is no much reason to combine different requests into one request
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> users;
|
||||
users.push_back(std::move(input_user));
|
||||
users.push_back(r_input_user.move_as_ok());
|
||||
td_->create_handler<GetUsersQuery>(std::move(promise))->send(std::move(users));
|
||||
}
|
||||
|
||||
@ -14048,30 +14056,30 @@ void ContactsManager::load_user_full(UserId user_id, bool force, Promise<Unit> &
|
||||
|
||||
auto user_full = get_user_full_force(user_id);
|
||||
if (user_full == nullptr) {
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Can't get info about inaccessible user"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
return send_get_user_full_query(user_id, std::move(input_user), std::move(promise), source);
|
||||
return send_get_user_full_query(user_id, r_input_user.move_as_ok(), std::move(promise), source);
|
||||
}
|
||||
if (user_full->is_expired()) {
|
||||
auto input_user = get_input_user(user_id);
|
||||
CHECK(input_user != nullptr);
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
CHECK(r_input_user.is_ok());
|
||||
if (td_->auth_manager_->is_bot() && !force) {
|
||||
return send_get_user_full_query(user_id, std::move(input_user), std::move(promise), "load expired user_full");
|
||||
return send_get_user_full_query(user_id, r_input_user.move_as_ok(), std::move(promise), "load expired user_full");
|
||||
}
|
||||
|
||||
send_get_user_full_query(user_id, std::move(input_user), Auto(), "load expired user_full");
|
||||
send_get_user_full_query(user_id, r_input_user.move_as_ok(), Auto(), "load expired user_full");
|
||||
}
|
||||
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void ContactsManager::reload_user_full(UserId user_id) {
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user != nullptr) {
|
||||
send_get_user_full_query(user_id, std::move(input_user), Auto(), "reload_user_full");
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_ok()) {
|
||||
send_get_user_full_query(user_id, r_input_user.move_as_ok(), Auto(), "reload_user_full");
|
||||
}
|
||||
}
|
||||
|
||||
@ -14104,9 +14112,9 @@ std::pair<int32, vector<const Photo *>> ContactsManager::get_user_profile_photos
|
||||
limit = MAX_GET_PROFILE_PHOTOS;
|
||||
}
|
||||
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
promise.set_error(r_input_user.move_as_error());
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -14156,20 +14164,22 @@ std::pair<int32, vector<const Photo *>> ContactsManager::get_user_profile_photos
|
||||
limit = MAX_GET_PROFILE_PHOTOS / 5; // make limit reasonable
|
||||
}
|
||||
|
||||
td_->create_handler<GetUserPhotosQuery>(std::move(promise))->send(user_id, std::move(input_user), offset, limit, 0);
|
||||
td_->create_handler<GetUserPhotosQuery>(std::move(promise))
|
||||
->send(user_id, r_input_user.move_as_ok(), offset, limit, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ContactsManager::reload_user_profile_photo(UserId user_id, int64 photo_id, Promise<Unit> &&promise) {
|
||||
get_user_force(user_id);
|
||||
auto input_user = get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User info not found"));
|
||||
auto r_input_user = get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
// this request will be needed only to download the photo,
|
||||
// so there is no reason to combine different requests for a photo into one request
|
||||
td_->create_handler<GetUserPhotosQuery>(std::move(promise))->send(user_id, std::move(input_user), -1, 1, photo_id);
|
||||
td_->create_handler<GetUserPhotosQuery>(std::move(promise))
|
||||
->send(user_id, r_input_user.move_as_ok(), -1, 1, photo_id);
|
||||
}
|
||||
|
||||
FileSourceId ContactsManager::get_user_profile_photo_file_source_id(UserId user_id, int64 photo_id) {
|
||||
@ -15169,9 +15179,9 @@ void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId par
|
||||
Promise<DialogParticipant> &&promise) {
|
||||
LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id;
|
||||
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read);
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Know);
|
||||
if (input_peer == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
return promise.set_error(Status::Error(400, "Member not found"));
|
||||
}
|
||||
|
||||
if (have_channel_participant_cache(channel_id)) {
|
||||
|
@ -74,7 +74,7 @@ class ContactsManager final : public Actor {
|
||||
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);
|
||||
|
||||
tl_object_ptr<telegram_api::InputUser> get_input_user(UserId user_id) const;
|
||||
Result<tl_object_ptr<telegram_api::InputUser>> get_input_user(UserId user_id) const;
|
||||
bool have_input_user(UserId user_id) const;
|
||||
|
||||
// TODO get_input_chat ???
|
||||
|
@ -488,11 +488,11 @@ void get_dialog_event_log(Td *td, DialogId dialog_id, const string &query, int64
|
||||
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> input_users;
|
||||
for (auto user_id : user_ids) {
|
||||
auto input_user = td->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = td->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
input_users.push_back(std::move(input_user));
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
td->create_handler<GetChannelAdminLogQuery>(std::move(promise))
|
||||
|
@ -90,10 +90,10 @@ bool Game::has_input_media() const {
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::inputMediaGame> Game::get_input_media_game(const Td *td) const {
|
||||
auto input_user = td->contacts_manager_->get_input_user(bot_user_id_);
|
||||
CHECK(input_user != nullptr);
|
||||
auto r_input_user = td->contacts_manager_->get_input_user(bot_user_id_);
|
||||
CHECK(r_input_user.is_ok());
|
||||
return make_tl_object<telegram_api::inputMediaGame>(
|
||||
make_tl_object<telegram_api::inputGameShortName>(std::move(input_user), short_name_));
|
||||
make_tl_object<telegram_api::inputGameShortName>(r_input_user.move_as_ok(), short_name_));
|
||||
}
|
||||
|
||||
bool operator==(const Game &lhs, const Game &rhs) {
|
||||
|
@ -217,9 +217,9 @@ void GameManager::set_game_score(FullMessageId full_message_id, bool edit_messag
|
||||
return promise.set_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Invalid user identifier specified"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
if (!td_->messages_manager_->can_set_game_score(full_message_id)) {
|
||||
@ -234,7 +234,7 @@ void GameManager::set_game_score(FullMessageId full_message_id, bool edit_messag
|
||||
send_closure(actor_id, &GameManager::on_set_game_score, full_message_id, std::move(promise));
|
||||
});
|
||||
send_closure(td_->create_net_actor<SetGameScoreActor>(std::move(query_promise)), &SetGameScoreActor::send, dialog_id,
|
||||
full_message_id.get_message_id(), edit_message, std::move(input_user), score, force,
|
||||
full_message_id.get_message_id(), edit_message, r_input_user.move_as_ok(), score, force,
|
||||
MessagesManager::get_sequence_dispatcher_id(dialog_id, MessageContentType::None));
|
||||
}
|
||||
|
||||
@ -252,13 +252,13 @@ void GameManager::set_inline_game_score(const string &inline_message_id, bool ed
|
||||
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<SetInlineGameScoreQuery>(std::move(promise))
|
||||
->send(std::move(input_bot_inline_message_id), edit_message, std::move(input_user), score, force);
|
||||
->send(std::move(input_bot_inline_message_id), edit_message, r_input_user.move_as_ok(), score, force);
|
||||
}
|
||||
|
||||
void GameManager::get_game_high_scores(FullMessageId full_message_id, UserId user_id,
|
||||
@ -278,12 +278,13 @@ void GameManager::get_game_high_scores(FullMessageId full_message_id, UserId use
|
||||
return promise.set_error(Status::Error(400, "Wrong message identifier specified"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<GetGameHighScoresQuery>(std::move(promise))->send(dialog_id, message_id, std::move(input_user));
|
||||
td_->create_handler<GetGameHighScoresQuery>(std::move(promise))
|
||||
->send(dialog_id, message_id, r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
void GameManager::get_inline_game_high_scores(const string &inline_message_id, UserId user_id,
|
||||
@ -295,13 +296,13 @@ void GameManager::get_inline_game_high_scores(const string &inline_message_id, U
|
||||
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Wrong user identifier specified"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
td_->create_handler<GetInlineGameHighScoresQuery>(std::move(promise))
|
||||
->send(std::move(input_bot_inline_message_id), std::move(input_user));
|
||||
->send(std::move(input_bot_inline_message_id), r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::gameHighScores> GameManager::get_game_high_scores_object(
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include "td/telegram/net/MtprotoHeader.h"
|
||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||
#include "td/telegram/net/TempAuthKeyWatchdog.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/TdDb.h"
|
||||
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
@ -149,7 +149,7 @@ void Global::update_server_time_difference(double diff) {
|
||||
do_save_server_time_difference();
|
||||
|
||||
CHECK(Scheduler::instance());
|
||||
send_closure(td(), &Td::on_update_server_time_difference);
|
||||
send_closure(option_manager(), &OptionManager::on_update_server_time_difference);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ class MessagesManager;
|
||||
class MtprotoHeader;
|
||||
class NetQueryDispatcher;
|
||||
class NotificationManager;
|
||||
class OptionManager;
|
||||
class PasswordManager;
|
||||
class SecretChatsManager;
|
||||
class SponsoredMessageManager;
|
||||
@ -261,6 +262,13 @@ class Global final : public ActorContext {
|
||||
notification_manager_ = notification_manager;
|
||||
}
|
||||
|
||||
ActorId<OptionManager> option_manager() const {
|
||||
return option_manager_;
|
||||
}
|
||||
void set_option_manager(ActorId<OptionManager> option_manager) {
|
||||
option_manager_ = option_manager;
|
||||
}
|
||||
|
||||
ActorId<PasswordManager> password_manager() const {
|
||||
return password_manager_;
|
||||
}
|
||||
@ -445,6 +453,7 @@ class Global final : public ActorContext {
|
||||
ActorId<LinkManager> link_manager_;
|
||||
ActorId<MessagesManager> messages_manager_;
|
||||
ActorId<NotificationManager> notification_manager_;
|
||||
ActorId<OptionManager> option_manager_;
|
||||
ActorId<PasswordManager> password_manager_;
|
||||
ActorId<SecretChatsManager> secret_chats_manager_;
|
||||
ActorId<SponsoredMessageManager> sponsored_message_manager_;
|
||||
|
@ -3344,16 +3344,16 @@ void GroupCallManager::invite_group_call_participants(GroupCallId group_call_id,
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> input_users;
|
||||
auto my_user_id = td_->contacts_manager_->get_my_id();
|
||||
for (auto user_id : user_ids) {
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
|
||||
if (user_id == my_user_id) {
|
||||
// can't invite self
|
||||
continue;
|
||||
}
|
||||
input_users.push_back(std::move(input_user));
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
if (input_users.empty()) {
|
||||
|
@ -877,17 +877,17 @@ void InlineQueriesManager::loop() {
|
||||
auto now = Time::now();
|
||||
if (now >= next_inline_query_time_) {
|
||||
LOG(INFO) << "Send inline query " << pending_inline_query_->query_hash;
|
||||
auto bot_input_user = td_->contacts_manager_->get_input_user(pending_inline_query_->bot_user_id);
|
||||
if (bot_input_user != nullptr) {
|
||||
auto r_bot_input_user = td_->contacts_manager_->get_input_user(pending_inline_query_->bot_user_id);
|
||||
if (r_bot_input_user.is_ok()) {
|
||||
if (!sent_query_.empty()) {
|
||||
LOG(INFO) << "Cancel inline query request";
|
||||
cancel_query(sent_query_);
|
||||
}
|
||||
sent_query_ =
|
||||
td_->create_handler<GetInlineBotResultsQuery>(std::move(pending_inline_query_->promise))
|
||||
->send(pending_inline_query_->bot_user_id, pending_inline_query_->dialog_id, std::move(bot_input_user),
|
||||
std::move(pending_inline_query_->input_peer), pending_inline_query_->user_location,
|
||||
pending_inline_query_->query, pending_inline_query_->offset, pending_inline_query_->query_hash);
|
||||
sent_query_ = td_->create_handler<GetInlineBotResultsQuery>(std::move(pending_inline_query_->promise))
|
||||
->send(pending_inline_query_->bot_user_id, pending_inline_query_->dialog_id,
|
||||
r_bot_input_user.move_as_ok(), std::move(pending_inline_query_->input_peer),
|
||||
pending_inline_query_->user_location, pending_inline_query_->query,
|
||||
pending_inline_query_->offset, pending_inline_query_->query_hash);
|
||||
|
||||
next_inline_query_time_ = now + INLINE_QUERY_DELAY_MS * 1e-3;
|
||||
}
|
||||
|
@ -4171,10 +4171,10 @@ vector<tl_object_ptr<telegram_api::MessageEntity>> get_input_message_entities(co
|
||||
make_tl_object<telegram_api::messageEntityTextUrl>(entity.offset, entity.length, entity.argument));
|
||||
break;
|
||||
case MessageEntity::Type::MentionName: {
|
||||
auto input_user = contacts_manager->get_input_user(entity.user_id);
|
||||
LOG_CHECK(input_user != nullptr) << source;
|
||||
auto r_input_user = contacts_manager->get_input_user(entity.user_id);
|
||||
LOG_CHECK(r_input_user.is_ok()) << source << ' ' << r_input_user.error();
|
||||
result.push_back(make_tl_object<telegram_api::inputMessageEntityMentionName>(entity.offset, entity.length,
|
||||
std::move(input_user)));
|
||||
r_input_user.move_as_ok()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -838,11 +838,11 @@ class GetCommonDialogsQuery final : public Td::ResultHandler {
|
||||
user_id_ = user_id;
|
||||
offset_chat_id_ = offset_chat_id;
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
CHECK(input_user != nullptr);
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
CHECK(r_input_user.is_ok());
|
||||
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_getCommonChats(std::move(input_user), offset_chat_id, limit)));
|
||||
telegram_api::messages_getCommonChats(r_input_user.move_as_ok(), offset_chat_id, limit)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -13830,7 +13830,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
|
||||
bool has_forward_info = message_info.forward_header != nullptr;
|
||||
|
||||
if (sender_dialog_id.is_valid() && sender_dialog_id != dialog_id && have_dialog_info_force(sender_dialog_id)) {
|
||||
force_create_dialog(sender_dialog_id, "create_message", true);
|
||||
force_create_dialog(sender_dialog_id, "create_message", sender_dialog_id.get_type() != DialogType::User);
|
||||
}
|
||||
|
||||
LOG(INFO) << "Receive " << message_id << " in " << dialog_id << " from " << sender_user_id << "/" << sender_dialog_id;
|
||||
@ -19756,12 +19756,12 @@ DialogId MessagesManager::create_new_group_chat(const vector<UserId> &user_ids,
|
||||
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> input_users;
|
||||
for (auto user_id : user_ids) {
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
promise.set_error(r_input_user.move_as_error());
|
||||
return DialogId();
|
||||
}
|
||||
input_users.push_back(std::move(input_user));
|
||||
input_users.push_back(r_input_user.move_as_ok());
|
||||
}
|
||||
|
||||
do {
|
||||
@ -19815,11 +19815,14 @@ DialogId MessagesManager::create_new_channel_chat(const string &title, bool is_m
|
||||
}
|
||||
|
||||
void MessagesManager::create_new_secret_chat(UserId user_id, Promise<SecretChatId> &&promise) {
|
||||
auto user_base = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (user_base == nullptr || user_base->get_id() != telegram_api::inputUser::ID) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return promise.set_error(r_input_user.move_as_error());
|
||||
}
|
||||
auto user = move_tl_object_as<telegram_api::inputUser>(user_base);
|
||||
if (r_input_user.ok()->get_id() != telegram_api::inputUser::ID) {
|
||||
return promise.set_error(Status::Error(400, "Can't create secret chat with self"));
|
||||
}
|
||||
auto user = static_cast<const telegram_api::inputUser *>(r_input_user.ok().get());
|
||||
|
||||
send_closure(G()->secret_chats_manager(), &SecretChatsManager::create_chat, UserId(user->user_id_),
|
||||
user->access_hash_, std::move(promise));
|
||||
@ -25371,12 +25374,12 @@ void MessagesManager::do_send_bot_start_message(UserId bot_user_id, DialogId dia
|
||||
if (input_peer == nullptr) {
|
||||
return on_send_message_fail(random_id, Status::Error(400, "Have no info about the chat"));
|
||||
}
|
||||
auto bot_input_user = td_->contacts_manager_->get_input_user(bot_user_id);
|
||||
if (bot_input_user == nullptr) {
|
||||
return on_send_message_fail(random_id, Status::Error(400, "Have no info about the bot"));
|
||||
auto r_bot_input_user = td_->contacts_manager_->get_input_user(bot_user_id);
|
||||
if (r_bot_input_user.is_error()) {
|
||||
return on_send_message_fail(random_id, r_bot_input_user.move_as_error());
|
||||
}
|
||||
|
||||
m->send_query_ref = td_->create_handler<StartBotQuery>()->send(std::move(bot_input_user), dialog_id,
|
||||
m->send_query_ref = td_->create_handler<StartBotQuery>()->send(r_bot_input_user.move_as_ok(), dialog_id,
|
||||
std::move(input_peer), parameter, random_id);
|
||||
}
|
||||
|
||||
|
700
td/telegram/OptionManager.cpp
Normal file
700
td/telegram/OptionManager.cpp
Normal file
@ -0,0 +1,700 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/telegram/OptionManager.h"
|
||||
|
||||
#include "td/telegram/AnimationsManager.h"
|
||||
#include "td/telegram/AuthManager.h"
|
||||
#include "td/telegram/ConfigManager.h"
|
||||
#include "td/telegram/ConfigShared.h"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/JsonValue.h"
|
||||
#include "td/telegram/LanguagePackManager.h"
|
||||
#include "td/telegram/net/MtprotoHeader.h"
|
||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/StorageManager.h"
|
||||
#include "td/telegram/SuggestedAction.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/TdDb.h"
|
||||
#include "td/telegram/TopDialogManager.h"
|
||||
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace td {
|
||||
|
||||
OptionManager::OptionManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||
send_unix_time_update();
|
||||
}
|
||||
|
||||
void OptionManager::tear_down() {
|
||||
parent_.reset();
|
||||
}
|
||||
|
||||
OptionManager::~OptionManager() = default;
|
||||
|
||||
td_api::object_ptr<td_api::OptionValue> OptionManager::get_unix_time_option_value_object() {
|
||||
return td_api::make_object<td_api::optionValueInteger>(G()->unix_time());
|
||||
}
|
||||
|
||||
void OptionManager::send_unix_time_update() {
|
||||
last_sent_server_time_difference_ = G()->get_server_time_difference();
|
||||
td_->send_update(td_api::make_object<td_api::updateOption>("unix_time", get_unix_time_option_value_object()));
|
||||
}
|
||||
|
||||
void OptionManager::on_update_server_time_difference() {
|
||||
if (std::abs(G()->get_server_time_difference() - last_sent_server_time_difference_) < 0.5) {
|
||||
return;
|
||||
}
|
||||
|
||||
send_unix_time_update();
|
||||
}
|
||||
|
||||
void OptionManager::clear_options() {
|
||||
for (const auto &option : G()->shared_config().get_options()) {
|
||||
if (!is_internal_option(option.first)) {
|
||||
send_closure(
|
||||
G()->td(), &Td::send_update,
|
||||
td_api::make_object<td_api::updateOption>(option.first, td_api::make_object<td_api::optionValueEmpty>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OptionManager::is_internal_option(Slice name) {
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
return name == "animated_emoji_zoom" || name == "animation_search_emojis" ||
|
||||
name == "animation_search_provider" || name == "auth";
|
||||
case 'b':
|
||||
return name == "base_language_pack_version";
|
||||
case 'c':
|
||||
return name == "call_ring_timeout_ms" || name == "call_receive_timeout_ms" ||
|
||||
name == "channels_read_media_period" || name == "chat_read_mark_expire_period" ||
|
||||
name == "chat_read_mark_size_threshold";
|
||||
case 'd':
|
||||
return name == "dc_txt_domain_name" || name == "dice_emojis" || name == "dice_success_values";
|
||||
case 'e':
|
||||
return name == "edit_time_limit" || name == "emoji_sounds";
|
||||
case 'i':
|
||||
return name == "ignored_restriction_reasons";
|
||||
case 'l':
|
||||
return name == "language_pack_version";
|
||||
case 'm':
|
||||
return name == "my_phone_number";
|
||||
case 'n':
|
||||
return name == "notification_cloud_delay_ms" || name == "notification_default_delay_ms";
|
||||
case 'o':
|
||||
return name == "online_update_period_ms" || name == "online_cloud_timeout_ms" || name == "otherwise_relogin_days";
|
||||
case 'r':
|
||||
return name == "revoke_pm_inbox" || name == "revoke_time_limit" || name == "revoke_pm_time_limit" ||
|
||||
name == "rating_e_decay" || name == "recent_stickers_limit";
|
||||
case 's':
|
||||
return name == "saved_animations_limit" || name == "session_count";
|
||||
case 'v':
|
||||
return name == "video_note_size_max";
|
||||
case 'w':
|
||||
return name == "webfile_dc_id";
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OptionManager::on_option_updated(const string &name) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
if (name == "animated_emoji_zoom") {
|
||||
// nothing to do: animated emoji zoom is updated only at launch
|
||||
}
|
||||
if (name == "animation_search_emojis") {
|
||||
td_->animations_manager_->on_update_animation_search_emojis(G()->shared_config().get_option_string(name));
|
||||
}
|
||||
if (name == "animation_search_provider") {
|
||||
td_->animations_manager_->on_update_animation_search_provider(G()->shared_config().get_option_string(name));
|
||||
}
|
||||
if (name == "auth") {
|
||||
send_closure(td_->auth_manager_actor_, &AuthManager::on_authorization_lost,
|
||||
G()->shared_config().get_option_string(name));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (name == "base_language_pack_version") {
|
||||
send_closure(td_->language_pack_manager_, &LanguagePackManager::on_language_pack_version_changed, true, -1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (name == "connection_parameters") {
|
||||
if (G()->mtproto_header().set_parameters(G()->shared_config().get_option_string(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (name == "dice_emojis") {
|
||||
send_closure(td_->stickers_manager_actor_, &StickersManager::on_update_dice_emojis);
|
||||
}
|
||||
if (name == "dice_success_values") {
|
||||
send_closure(td_->stickers_manager_actor_, &StickersManager::on_update_dice_success_values);
|
||||
}
|
||||
if (name == "disable_animated_emoji") {
|
||||
td_->stickers_manager_->on_update_disable_animated_emojis();
|
||||
}
|
||||
if (name == "disable_contact_registered_notifications") {
|
||||
send_closure(td_->notification_manager_actor_,
|
||||
&NotificationManager::on_disable_contact_registered_notifications_changed);
|
||||
}
|
||||
if (name == "disable_top_chats") {
|
||||
send_closure(td_->top_dialog_manager_actor_, &TopDialogManager::update_is_enabled,
|
||||
!G()->shared_config().get_option_boolean(name));
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
if (name == "emoji_sounds") {
|
||||
send_closure(td_->stickers_manager_actor_, &StickersManager::on_update_emoji_sounds);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (name == "favorite_stickers_limit") {
|
||||
td_->stickers_manager_->on_update_favorite_stickers_limit(
|
||||
narrow_cast<int32>(G()->shared_config().get_option_integer(name)));
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (name == "ignored_restriction_reasons") {
|
||||
send_closure(td_->contacts_manager_actor_, &ContactsManager::on_ignored_restriction_reasons_changed);
|
||||
}
|
||||
if (name == "is_emulator") {
|
||||
if (G()->mtproto_header().set_is_emulator(G()->shared_config().get_option_boolean(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (name == "language_pack_id") {
|
||||
send_closure(td_->language_pack_manager_, &LanguagePackManager::on_language_code_changed);
|
||||
if (G()->mtproto_header().set_language_code(G()->shared_config().get_option_string(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
if (name == "language_pack_version") {
|
||||
send_closure(td_->language_pack_manager_, &LanguagePackManager::on_language_pack_version_changed, false, -1);
|
||||
}
|
||||
if (name == "localization_target") {
|
||||
send_closure(td_->language_pack_manager_, &LanguagePackManager::on_language_pack_changed);
|
||||
if (G()->mtproto_header().set_language_pack(G()->shared_config().get_option_string(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (name == "my_id") {
|
||||
G()->set_my_id(G()->shared_config().get_option_integer(name));
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (name == "notification_cloud_delay_ms") {
|
||||
send_closure(td_->notification_manager_actor_, &NotificationManager::on_notification_cloud_delay_changed);
|
||||
}
|
||||
if (name == "notification_default_delay_ms") {
|
||||
send_closure(td_->notification_manager_actor_, &NotificationManager::on_notification_default_delay_changed);
|
||||
}
|
||||
if (name == "notification_group_count_max") {
|
||||
send_closure(td_->notification_manager_actor_, &NotificationManager::on_notification_group_count_max_changed,
|
||||
true);
|
||||
}
|
||||
if (name == "notification_group_size_max") {
|
||||
send_closure(td_->notification_manager_actor_, &NotificationManager::on_notification_group_size_max_changed);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (name == "online_cloud_timeout_ms") {
|
||||
send_closure(td_->notification_manager_actor_, &NotificationManager::on_online_cloud_timeout_changed);
|
||||
}
|
||||
if (name == "otherwise_relogin_days") {
|
||||
auto days = narrow_cast<int32>(G()->shared_config().get_option_integer(name));
|
||||
if (days > 0) {
|
||||
vector<SuggestedAction> added_actions{SuggestedAction{SuggestedAction::Type::SetPassword, DialogId(), days}};
|
||||
send_closure(G()->td(), &Td::send_update, get_update_suggested_actions_object(added_actions, {}));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (name == "rating_e_decay") {
|
||||
send_closure(td_->top_dialog_manager_actor_, &TopDialogManager::update_rating_e_decay);
|
||||
}
|
||||
if (name == "recent_stickers_limit") {
|
||||
td_->stickers_manager_->on_update_recent_stickers_limit(
|
||||
narrow_cast<int32>(G()->shared_config().get_option_integer(name)));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (name == "saved_animations_limit") {
|
||||
td_->animations_manager_->on_update_saved_animations_limit(
|
||||
narrow_cast<int32>(G()->shared_config().get_option_integer(name)));
|
||||
}
|
||||
if (name == "session_count") {
|
||||
G()->net_query_dispatcher().update_session_count();
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (name == "use_pfs") {
|
||||
G()->net_query_dispatcher().update_use_pfs();
|
||||
}
|
||||
if (name == "use_storage_optimizer") {
|
||||
send_closure(td_->storage_manager_, &StorageManager::update_use_storage_optimizer);
|
||||
}
|
||||
if (name == "utc_time_offset") {
|
||||
if (G()->mtproto_header().set_tz_offset(static_cast<int32>(G()->shared_config().get_option_integer(name)))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_internal_option(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// send_closure was already used in the callback
|
||||
td_->send_update(
|
||||
td_api::make_object<td_api::updateOption>(name, get_option_value_object(G()->shared_config().get_option(name))));
|
||||
}
|
||||
|
||||
void OptionManager::get_option(const string &name, Promise<td_api::object_ptr<td_api::OptionValue>> &&promise) {
|
||||
bool is_bot = td_->auth_manager_ != nullptr && td_->auth_manager_->is_authorized() && td_->auth_manager_->is_bot();
|
||||
auto wrap_promise = [&] {
|
||||
return PromiseCreator::lambda([promise = std::move(promise), name](Unit result) mutable {
|
||||
// the option is already updated on success, ignore errors
|
||||
promise.set_value(get_option_value_object(G()->shared_config().get_option(name)));
|
||||
});
|
||||
};
|
||||
switch (name[0]) {
|
||||
// all these options should be added to getCurrentState
|
||||
case 'a':
|
||||
if (!is_bot && name == "archive_and_mute_new_chats_from_unknown_users") {
|
||||
return send_closure_later(td_->config_manager_, &ConfigManager::get_global_privacy_settings, wrap_promise());
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (!is_bot && name == "can_ignore_sensitive_content_restrictions") {
|
||||
return send_closure_later(td_->config_manager_, &ConfigManager::get_content_settings, wrap_promise());
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (!is_bot && name == "disable_contact_registered_notifications") {
|
||||
return send_closure_later(td_->notification_manager_actor_,
|
||||
&NotificationManager::get_disable_contact_registered_notifications, wrap_promise());
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (!is_bot && name == "ignore_sensitive_content_restrictions") {
|
||||
return send_closure_later(td_->config_manager_, &ConfigManager::get_content_settings, wrap_promise());
|
||||
}
|
||||
if (!is_bot && name == "is_location_visible") {
|
||||
return send_closure_later(td_->contacts_manager_actor_, &ContactsManager::get_is_location_visible,
|
||||
wrap_promise());
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (name == "online") {
|
||||
return promise.set_value(td_api::make_object<td_api::optionValueBoolean>(td_->is_online()));
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (name == "unix_time") {
|
||||
return promise.set_value(get_unix_time_option_value_object());
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
if (name == "version") {
|
||||
return promise.set_value(td_api::make_object<td_api::optionValueString>(Td::TDLIB_VERSION));
|
||||
}
|
||||
break;
|
||||
}
|
||||
wrap_promise().set_value(Unit());
|
||||
}
|
||||
|
||||
void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::OptionValue> &&value,
|
||||
Promise<Unit> &&promise) {
|
||||
int32 value_constructor_id = value == nullptr ? td_api::optionValueEmpty::ID : value->get_id();
|
||||
|
||||
auto set_integer_option = [&](Slice option_name, int64 min_value = 0,
|
||||
int64 max_value = std::numeric_limits<int32>::max()) {
|
||||
if (name != option_name) {
|
||||
return false;
|
||||
}
|
||||
if (value_constructor_id != td_api::optionValueInteger::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have integer value"));
|
||||
return true;
|
||||
}
|
||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||
G()->shared_config().set_option_empty(option_name);
|
||||
} else {
|
||||
int64 int_value = static_cast<td_api::optionValueInteger *>(value.get())->value_;
|
||||
if (int_value < min_value || int_value > max_value) {
|
||||
promise.set_error(Status::Error(400, PSLICE() << "Option's \"" << name << "\" value " << int_value
|
||||
<< " is outside of the valid range [" << min_value << ", "
|
||||
<< max_value << "]"));
|
||||
return true;
|
||||
}
|
||||
G()->shared_config().set_option_integer(name, int_value);
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
return true;
|
||||
};
|
||||
|
||||
auto set_boolean_option = [&](Slice option_name) {
|
||||
if (name != option_name) {
|
||||
return false;
|
||||
}
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have boolean value"));
|
||||
return true;
|
||||
}
|
||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
bool bool_value = static_cast<td_api::optionValueBoolean *>(value.get())->value_;
|
||||
G()->shared_config().set_option_boolean(name, bool_value);
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
return true;
|
||||
};
|
||||
|
||||
auto set_string_option = [&](Slice option_name, auto check_value) {
|
||||
if (name != option_name) {
|
||||
return false;
|
||||
}
|
||||
if (value_constructor_id != td_api::optionValueString::ID && value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have string value"));
|
||||
return true;
|
||||
}
|
||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
const string &str_value = static_cast<td_api::optionValueString *>(value.get())->value_;
|
||||
if (str_value.empty()) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
if (check_value(str_value)) {
|
||||
G()->shared_config().set_option_string(name, str_value);
|
||||
} else {
|
||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" can't have specified value"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
return true;
|
||||
};
|
||||
|
||||
bool is_bot = td_->auth_manager_ != nullptr && td_->auth_manager_->is_authorized() && td_->auth_manager_->is_bot();
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
if (set_boolean_option("always_parse_markdown")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && name == "archive_and_mute_new_chats_from_unknown_users") {
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
return promise.set_error(
|
||||
Status::Error(400, "Option \"archive_and_mute_new_chats_from_unknown_users\" must have boolean value"));
|
||||
}
|
||||
|
||||
auto archive_and_mute = value_constructor_id == td_api::optionValueBoolean::ID &&
|
||||
static_cast<td_api::optionValueBoolean *>(value.get())->value_;
|
||||
send_closure_later(td_->config_manager_, &ConfigManager::set_archive_and_mute, archive_and_mute,
|
||||
std::move(promise));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (!is_bot && set_string_option("connection_parameters", [](Slice value) {
|
||||
string value_copy = value.str();
|
||||
auto r_json_value = get_json_value(value_copy);
|
||||
if (r_json_value.is_error()) {
|
||||
return false;
|
||||
}
|
||||
return r_json_value.ok()->get_id() == td_api::jsonValueObject::ID;
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (!is_bot && set_boolean_option("disable_animated_emoji")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("disable_contact_registered_notifications")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("disable_sent_scheduled_message_notifications")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("disable_top_chats")) {
|
||||
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;
|
||||
}
|
||||
// End TDLight options
|
||||
if (set_boolean_option("disable_persistent_network_statistics")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("disable_time_adjustment_protection")) {
|
||||
return;
|
||||
}
|
||||
if (name == "drop_notification_ids") {
|
||||
G()->td_db()->get_binlog_pmc()->erase("notification_id_current");
|
||||
G()->td_db()->get_binlog_pmc()->erase("notification_group_id_current");
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (set_boolean_option("ignore_background_updates")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("ignore_default_disable_notification")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("ignore_inline_thumbnails")) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (!is_bot && name == "ignore_sensitive_content_restrictions") {
|
||||
if (!G()->shared_config().get_option_boolean("can_ignore_sensitive_content_restrictions")) {
|
||||
return promise.set_error(
|
||||
Status::Error(400, "Option \"ignore_sensitive_content_restrictions\" can't be changed by the user"));
|
||||
}
|
||||
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
return promise.set_error(
|
||||
Status::Error(400, "Option \"ignore_sensitive_content_restrictions\" must have boolean value"));
|
||||
}
|
||||
|
||||
auto ignore_sensitive_content_restrictions = value_constructor_id == td_api::optionValueBoolean::ID &&
|
||||
static_cast<td_api::optionValueBoolean *>(value.get())->value_;
|
||||
send_closure_later(td_->config_manager_, &ConfigManager::set_content_settings,
|
||||
ignore_sensitive_content_restrictions, std::move(promise));
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("is_location_visible")) {
|
||||
td_->contacts_manager_->set_location_visibility();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (!is_bot && set_string_option("language_pack_database_path", [](Slice value) { return true; })) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_string_option("localization_target", LanguagePackManager::check_language_pack_name)) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_string_option("language_pack_id", LanguagePackManager::check_language_code_name)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (set_integer_option("message_unload_delay", 60, 86400)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (!is_bot &&
|
||||
set_integer_option("notification_group_count_max", NotificationManager::MIN_NOTIFICATION_GROUP_COUNT_MAX,
|
||||
NotificationManager::MAX_NOTIFICATION_GROUP_COUNT_MAX)) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot &&
|
||||
set_integer_option("notification_group_size_max", NotificationManager::MIN_NOTIFICATION_GROUP_SIZE_MAX,
|
||||
NotificationManager::MAX_NOTIFICATION_GROUP_SIZE_MAX)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (name == "online") {
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
return promise.set_error(Status::Error(400, "Option \"online\" must have boolean value"));
|
||||
}
|
||||
bool is_online = value_constructor_id == td_api::optionValueEmpty::ID ||
|
||||
static_cast<const td_api::optionValueBoolean *>(value.get())->value_;
|
||||
if (!is_bot) {
|
||||
send_closure(td_->state_manager_, &StateManager::on_online, is_online);
|
||||
}
|
||||
td_->set_is_online(is_online);
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (set_boolean_option("prefer_ipv6")) {
|
||||
send_closure(td_->state_manager_, &StateManager::on_network_updated);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
// temporary option
|
||||
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")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("storage_max_time_from_last_access")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("storage_max_file_count")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("storage_immunity_delay")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("store_all_files_in_files_directory")) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (set_boolean_option("test_flood_wait")) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (set_boolean_option("use_pfs")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("use_quick_ack")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("use_storage_optimizer")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("utc_time_offset", -12 * 60 * 60, 14 * 60 * 60)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
case 'x': {
|
||||
if (name.size() > 255) {
|
||||
return promise.set_error(Status::Error(400, "Option name is too long"));
|
||||
}
|
||||
switch (value_constructor_id) {
|
||||
case td_api::optionValueBoolean::ID:
|
||||
G()->shared_config().set_option_boolean(name,
|
||||
static_cast<const td_api::optionValueBoolean *>(value.get())->value_);
|
||||
break;
|
||||
case td_api::optionValueEmpty::ID:
|
||||
G()->shared_config().set_option_empty(name);
|
||||
break;
|
||||
case td_api::optionValueInteger::ID:
|
||||
G()->shared_config().set_option_integer(name,
|
||||
static_cast<const td_api::optionValueInteger *>(value.get())->value_);
|
||||
break;
|
||||
case td_api::optionValueString::ID:
|
||||
G()->shared_config().set_option_string(name,
|
||||
static_cast<const td_api::optionValueString *>(value.get())->value_);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
}
|
||||
|
||||
promise.set_error(Status::Error(400, "Option can't be set"));
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::OptionValue> OptionManager::get_option_value_object(Slice value) {
|
||||
if (value.empty()) {
|
||||
return td_api::make_object<td_api::optionValueEmpty>();
|
||||
}
|
||||
|
||||
switch (value[0]) {
|
||||
case 'B':
|
||||
if (value == "Btrue") {
|
||||
return td_api::make_object<td_api::optionValueBoolean>(true);
|
||||
}
|
||||
if (value == "Bfalse") {
|
||||
return td_api::make_object<td_api::optionValueBoolean>(false);
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
return td_api::make_object<td_api::optionValueInteger>(to_integer<int64>(value.substr(1)));
|
||||
case 'S':
|
||||
return td_api::make_object<td_api::optionValueString>(value.substr(1).str());
|
||||
}
|
||||
|
||||
return td_api::make_object<td_api::optionValueString>(value.str());
|
||||
}
|
||||
|
||||
void OptionManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
||||
updates.push_back(td_api::make_object<td_api::updateOption>(
|
||||
"version", td_api::make_object<td_api::optionValueString>(Td::TDLIB_VERSION)));
|
||||
|
||||
updates.push_back(td_api::make_object<td_api::updateOption>(
|
||||
"online", td_api::make_object<td_api::optionValueBoolean>(td_->is_online())));
|
||||
|
||||
updates.push_back(td_api::make_object<td_api::updateOption>("unix_time", get_unix_time_option_value_object()));
|
||||
|
||||
for (const auto &option : G()->shared_config().get_options()) {
|
||||
if (!is_internal_option(option.first)) {
|
||||
updates.push_back(
|
||||
td_api::make_object<td_api::updateOption>(option.first, get_option_value_object(option.second)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
60
td/telegram/OptionManager.h
Normal file
60
td/telegram/OptionManager.h
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Slice.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class OptionManager final : public Actor {
|
||||
public:
|
||||
OptionManager(Td *td, ActorShared<> parent);
|
||||
|
||||
OptionManager(const OptionManager &) = delete;
|
||||
OptionManager &operator=(const OptionManager &) = delete;
|
||||
OptionManager(OptionManager &&) = delete;
|
||||
OptionManager &operator=(OptionManager &&) = delete;
|
||||
~OptionManager() final;
|
||||
|
||||
void on_update_server_time_difference();
|
||||
|
||||
void on_option_updated(const string &name);
|
||||
|
||||
void get_option(const string &name, Promise<td_api::object_ptr<td_api::OptionValue>> &&promise);
|
||||
|
||||
void set_option(const string &name, td_api::object_ptr<td_api::OptionValue> &&value, Promise<Unit> &&promise);
|
||||
|
||||
static void clear_options();
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
|
||||
private:
|
||||
void tear_down() final;
|
||||
|
||||
static bool is_internal_option(Slice name);
|
||||
|
||||
static td_api::object_ptr<td_api::OptionValue> get_unix_time_option_value_object();
|
||||
|
||||
static td_api::object_ptr<td_api::OptionValue> get_option_value_object(Slice value);
|
||||
|
||||
void send_unix_time_update();
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
|
||||
double last_sent_server_time_difference_ = 1e100;
|
||||
};
|
||||
|
||||
} // namespace td
|
@ -318,9 +318,9 @@ Result<PrivacyManager::UserPrivacySettingRule> PrivacyManager::UserPrivacySettin
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> PrivacyManager::UserPrivacySettingRule::get_input_users() const {
|
||||
vector<tl_object_ptr<telegram_api::InputUser>> result;
|
||||
for (auto user_id : user_ids_) {
|
||||
auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user != nullptr) {
|
||||
result.push_back(std::move(input_user));
|
||||
auto r_input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_ok()) {
|
||||
result.push_back(r_input_user.move_as_ok());
|
||||
} else {
|
||||
LOG(ERROR) << "Have no access to " << user_id;
|
||||
}
|
||||
|
@ -700,25 +700,26 @@ static tl_object_ptr<telegram_api::KeyboardButton> get_inline_keyboard_button(
|
||||
if (!keyboard_button.forward_text.empty()) {
|
||||
flags |= telegram_api::inputKeyboardButtonUrlAuth::FWD_TEXT_MASK;
|
||||
}
|
||||
auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(UserId(bot_user_id));
|
||||
if (input_user == nullptr) {
|
||||
LOG(ERROR) << "Failed to get InputUser for " << bot_user_id;
|
||||
auto r_input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(UserId(bot_user_id));
|
||||
if (r_input_user.is_error()) {
|
||||
LOG(ERROR) << "Failed to get InputUser for " << bot_user_id << ": " << r_input_user.error();
|
||||
return make_tl_object<telegram_api::keyboardButtonUrl>(keyboard_button.text, keyboard_button.data);
|
||||
}
|
||||
return make_tl_object<telegram_api::inputKeyboardButtonUrlAuth>(flags, false /*ignored*/, keyboard_button.text,
|
||||
keyboard_button.forward_text,
|
||||
keyboard_button.data, std::move(input_user));
|
||||
keyboard_button.data, r_input_user.move_as_ok());
|
||||
}
|
||||
case InlineKeyboardButton::Type::CallbackWithPassword:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case InlineKeyboardButton::Type::User: {
|
||||
auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(keyboard_button.user_id);
|
||||
if (input_user == nullptr) {
|
||||
LOG(ERROR) << "Failed to get InputUser for " << keyboard_button.user_id;
|
||||
input_user = make_tl_object<telegram_api::inputUserEmpty>();
|
||||
auto r_input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(keyboard_button.user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
LOG(ERROR) << "Failed to get InputUser for " << keyboard_button.user_id << ": " << r_input_user.error();
|
||||
r_input_user = make_tl_object<telegram_api::inputUserEmpty>();
|
||||
}
|
||||
return make_tl_object<telegram_api::inputKeyboardButtonUserProfile>(keyboard_button.text, std::move(input_user));
|
||||
return make_tl_object<telegram_api::inputKeyboardButtonUserProfile>(keyboard_button.text,
|
||||
r_input_user.move_as_ok());
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -5453,15 +5453,9 @@ FileId StickersManager::upload_sticker_file(UserId user_id, tl_object_ptr<td_api
|
||||
user_id = td_->contacts_manager_->get_my_id();
|
||||
}
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
promise.set_error(Status::Error(400, "User not found"));
|
||||
return FileId();
|
||||
}
|
||||
DialogId dialog_id(user_id);
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
promise.set_error(Status::Error(400, "Have no access to the user"));
|
||||
auto r_input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
promise.set_error(r_input_user.move_as_error());
|
||||
return FileId();
|
||||
}
|
||||
|
||||
@ -5579,15 +5573,8 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
|
||||
if (!is_bot) {
|
||||
user_id = td_->contacts_manager_->get_my_id();
|
||||
}
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
}
|
||||
DialogId dialog_id(user_id);
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Have no access to the user"));
|
||||
}
|
||||
|
||||
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(user_id));
|
||||
|
||||
title = strip_empty_characters(title, MAX_STICKER_SET_TITLE_LENGTH);
|
||||
if (title.empty()) {
|
||||
@ -5804,10 +5791,8 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
|
||||
|
||||
CHECK(pending_new_sticker_set->upload_files_multipromise.promise_count() == 0);
|
||||
|
||||
auto input_user = td_->contacts_manager_->get_input_user(pending_new_sticker_set->user_id);
|
||||
if (input_user == nullptr) {
|
||||
return pending_new_sticker_set->promise.set_error(Status::Error(400, "User not found"));
|
||||
}
|
||||
auto &promise = pending_new_sticker_set->promise;
|
||||
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(pending_new_sticker_set->user_id));
|
||||
|
||||
bool is_masks = pending_new_sticker_set->is_masks;
|
||||
bool is_animated = pending_new_sticker_set->is_animated;
|
||||
@ -5827,15 +5812,7 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
|
||||
|
||||
void StickersManager::add_sticker_to_set(UserId user_id, string &short_name,
|
||||
tl_object_ptr<td_api::InputSticker> &&sticker, Promise<Unit> &&promise) {
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
}
|
||||
DialogId dialog_id(user_id);
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Have no access to the user"));
|
||||
}
|
||||
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(user_id));
|
||||
|
||||
short_name = strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH);
|
||||
if (short_name.empty()) {
|
||||
@ -5896,15 +5873,7 @@ void StickersManager::on_added_sticker_uploaded(int64 random_id, Result<Unit> re
|
||||
|
||||
void StickersManager::set_sticker_set_thumbnail(UserId user_id, string &short_name,
|
||||
tl_object_ptr<td_api::InputFile> &&thumbnail, Promise<Unit> &&promise) {
|
||||
auto input_user = td_->contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "User not found"));
|
||||
}
|
||||
DialogId dialog_id(user_id);
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Have no access to the user"));
|
||||
}
|
||||
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(user_id));
|
||||
|
||||
short_name = clean_username(strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH));
|
||||
if (short_name.empty()) {
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "td/telegram/NotificationId.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/NotificationSettings.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/PasswordManager.h"
|
||||
#include "td/telegram/Payments.h"
|
||||
#include "td/telegram/PhoneNumberManager.h"
|
||||
@ -147,7 +148,6 @@
|
||||
#include "td/utils/tl_parsers.h"
|
||||
#include "td/utils/utf8.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
@ -2704,17 +2704,6 @@ void Td::on_alarm_timeout_callback(void *td_ptr, int64 alarm_id) {
|
||||
send_closure_later(td_id, &Td::on_alarm_timeout, alarm_id);
|
||||
}
|
||||
|
||||
void Td::on_update_server_time_difference() {
|
||||
auto diff = G()->get_server_time_difference();
|
||||
if (std::abs(diff - last_sent_server_time_difference_) < 0.5) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_sent_server_time_difference_ = diff;
|
||||
send_update(td_api::make_object<td_api::updateOption>(
|
||||
"unix_time", td_api::make_object<td_api::optionValueInteger>(G()->unix_time())));
|
||||
}
|
||||
|
||||
void Td::on_alarm_timeout(int64 alarm_id) {
|
||||
if (alarm_id == ONLINE_ALARM_ID) {
|
||||
on_online_updated(false, true);
|
||||
@ -2878,6 +2867,17 @@ bool Td::is_online() const {
|
||||
return is_online_;
|
||||
}
|
||||
|
||||
void Td::set_is_online(bool is_online) {
|
||||
if (is_online == is_online_) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_online_ = is_online;
|
||||
if (auth_manager_ != nullptr) { // postpone if there is no AuthManager yet
|
||||
on_online_updated(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Td::set_is_bot_online(bool is_bot_online) {
|
||||
if (G()->shared_config().get_option_integer("session_count") > 1) {
|
||||
is_bot_online = false;
|
||||
@ -3240,208 +3240,6 @@ void Td::on_result(NetQueryPtr query) {
|
||||
query->clear();
|
||||
}
|
||||
|
||||
bool Td::is_internal_config_option(Slice name) {
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
return name == "animated_emoji_zoom" || name == "animation_search_emojis" ||
|
||||
name == "animation_search_provider" || name == "auth";
|
||||
case 'b':
|
||||
return name == "base_language_pack_version";
|
||||
case 'c':
|
||||
return name == "call_ring_timeout_ms" || name == "call_receive_timeout_ms" ||
|
||||
name == "channels_read_media_period" || name == "chat_read_mark_expire_period" ||
|
||||
name == "chat_read_mark_size_threshold";
|
||||
case 'd':
|
||||
return name == "dc_txt_domain_name" || name == "dice_emojis" || name == "dice_success_values";
|
||||
case 'e':
|
||||
return name == "edit_time_limit" || name == "emoji_sounds";
|
||||
case 'i':
|
||||
return name == "ignored_restriction_reasons";
|
||||
case 'l':
|
||||
return name == "language_pack_version";
|
||||
case 'm':
|
||||
return name == "my_phone_number";
|
||||
case 'n':
|
||||
return name == "notification_cloud_delay_ms" || name == "notification_default_delay_ms";
|
||||
case 'o':
|
||||
return name == "online_update_period_ms" || name == "online_cloud_timeout_ms" || name == "otherwise_relogin_days";
|
||||
case 'r':
|
||||
return name == "revoke_pm_inbox" || name == "revoke_time_limit" || name == "revoke_pm_time_limit" ||
|
||||
name == "rating_e_decay" || name == "recent_stickers_limit";
|
||||
case 's':
|
||||
return name == "saved_animations_limit" || name == "session_count";
|
||||
case 'v':
|
||||
return name == "video_note_size_max";
|
||||
case 'w':
|
||||
return name == "webfile_dc_id";
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Td::on_config_option_updated(const string &name) {
|
||||
if (close_flag_) {
|
||||
return;
|
||||
}
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
if (name == "animated_emoji_zoom") {
|
||||
// nothing to do: animated emoji zoom is updated only at launch
|
||||
}
|
||||
if (name == "animation_search_emojis") {
|
||||
animations_manager_->on_update_animation_search_emojis(G()->shared_config().get_option_string(name));
|
||||
}
|
||||
if (name == "animation_search_provider") {
|
||||
animations_manager_->on_update_animation_search_provider(G()->shared_config().get_option_string(name));
|
||||
}
|
||||
if (name == "auth") {
|
||||
send_closure(auth_manager_actor_, &AuthManager::on_authorization_lost,
|
||||
G()->shared_config().get_option_string(name));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (name == "base_language_pack_version") {
|
||||
send_closure(language_pack_manager_, &LanguagePackManager::on_language_pack_version_changed, true, -1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (name == "connection_parameters") {
|
||||
if (G()->mtproto_header().set_parameters(G()->shared_config().get_option_string(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (name == "dice_emojis") {
|
||||
send_closure(stickers_manager_actor_, &StickersManager::on_update_dice_emojis);
|
||||
}
|
||||
if (name == "dice_success_values") {
|
||||
send_closure(stickers_manager_actor_, &StickersManager::on_update_dice_success_values);
|
||||
}
|
||||
if (name == "disable_animated_emoji") {
|
||||
stickers_manager_->on_update_disable_animated_emojis();
|
||||
}
|
||||
if (name == "disable_contact_registered_notifications") {
|
||||
send_closure(notification_manager_actor_,
|
||||
&NotificationManager::on_disable_contact_registered_notifications_changed);
|
||||
}
|
||||
if (name == "disable_top_chats") {
|
||||
send_closure(top_dialog_manager_actor_, &TopDialogManager::update_is_enabled,
|
||||
!G()->shared_config().get_option_boolean(name));
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
if (name == "emoji_sounds") {
|
||||
send_closure(stickers_manager_actor_, &StickersManager::on_update_emoji_sounds);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (name == "favorite_stickers_limit") {
|
||||
stickers_manager_->on_update_favorite_stickers_limit(
|
||||
narrow_cast<int32>(G()->shared_config().get_option_integer(name)));
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (name == "ignored_restriction_reasons") {
|
||||
send_closure(contacts_manager_actor_, &ContactsManager::on_ignored_restriction_reasons_changed);
|
||||
}
|
||||
if (name == "is_emulator") {
|
||||
if (G()->mtproto_header().set_is_emulator(G()->shared_config().get_option_boolean(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (name == "language_pack_id") {
|
||||
send_closure(language_pack_manager_, &LanguagePackManager::on_language_code_changed);
|
||||
if (G()->mtproto_header().set_language_code(G()->shared_config().get_option_string(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
if (name == "language_pack_version") {
|
||||
send_closure(language_pack_manager_, &LanguagePackManager::on_language_pack_version_changed, false, -1);
|
||||
}
|
||||
if (name == "localization_target") {
|
||||
send_closure(language_pack_manager_, &LanguagePackManager::on_language_pack_changed);
|
||||
if (G()->mtproto_header().set_language_pack(G()->shared_config().get_option_string(name))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (name == "my_id") {
|
||||
G()->set_my_id(G()->shared_config().get_option_integer(name));
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (name == "notification_cloud_delay_ms") {
|
||||
send_closure(notification_manager_actor_, &NotificationManager::on_notification_cloud_delay_changed);
|
||||
}
|
||||
if (name == "notification_default_delay_ms") {
|
||||
send_closure(notification_manager_actor_, &NotificationManager::on_notification_default_delay_changed);
|
||||
}
|
||||
if (name == "notification_group_count_max") {
|
||||
send_closure(notification_manager_actor_, &NotificationManager::on_notification_group_count_max_changed, true);
|
||||
}
|
||||
if (name == "notification_group_size_max") {
|
||||
send_closure(notification_manager_actor_, &NotificationManager::on_notification_group_size_max_changed);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (name == "online_cloud_timeout_ms") {
|
||||
send_closure(notification_manager_actor_, &NotificationManager::on_online_cloud_timeout_changed);
|
||||
}
|
||||
if (name == "otherwise_relogin_days") {
|
||||
auto days = narrow_cast<int32>(G()->shared_config().get_option_integer(name));
|
||||
if (days > 0) {
|
||||
vector<SuggestedAction> added_actions{SuggestedAction{SuggestedAction::Type::SetPassword, DialogId(), days}};
|
||||
send_closure(G()->td(), &Td::send_update, get_update_suggested_actions_object(added_actions, {}));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (name == "rating_e_decay") {
|
||||
send_closure(top_dialog_manager_actor_, &TopDialogManager::update_rating_e_decay);
|
||||
}
|
||||
if (name == "recent_stickers_limit") {
|
||||
stickers_manager_->on_update_recent_stickers_limit(
|
||||
narrow_cast<int32>(G()->shared_config().get_option_integer(name)));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (name == "saved_animations_limit") {
|
||||
animations_manager_->on_update_saved_animations_limit(
|
||||
narrow_cast<int32>(G()->shared_config().get_option_integer(name)));
|
||||
}
|
||||
if (name == "session_count") {
|
||||
G()->net_query_dispatcher().update_session_count();
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (name == "use_pfs") {
|
||||
G()->net_query_dispatcher().update_use_pfs();
|
||||
}
|
||||
if (name == "use_storage_optimizer") {
|
||||
send_closure(storage_manager_, &StorageManager::update_use_storage_optimizer);
|
||||
}
|
||||
if (name == "utc_time_offset") {
|
||||
if (G()->mtproto_header().set_tz_offset(static_cast<int32>(G()->shared_config().get_option_integer(name)))) {
|
||||
G()->net_query_dispatcher().update_mtproto_header();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_internal_config_option(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// send_closure was already used in the callback
|
||||
send_update(make_tl_object<td_api::updateOption>(name, G()->shared_config().get_option_value(name)));
|
||||
}
|
||||
|
||||
void Td::on_connection_state_changed(ConnectionState new_state) {
|
||||
if (new_state == connection_state_) {
|
||||
LOG(ERROR) << "State manager sends update about unchanged state " << static_cast<int32>(new_state);
|
||||
@ -3558,6 +3356,8 @@ void Td::dec_actor_refcnt() {
|
||||
LOG(DEBUG) << "MessagesManager was cleared" << timer;
|
||||
notification_manager_.reset();
|
||||
LOG(DEBUG) << "NotificationManager was cleared" << timer;
|
||||
option_manager_.reset();
|
||||
LOG(DEBUG) << "OptionManager was cleared" << timer;
|
||||
poll_manager_.reset();
|
||||
LOG(DEBUG) << "PollManager was cleared" << timer;
|
||||
sponsored_message_manager_.reset();
|
||||
@ -3667,11 +3467,7 @@ void Td::clear() {
|
||||
|
||||
Timer timer;
|
||||
if (destroy_flag_) {
|
||||
for (auto &option : G()->shared_config().get_options()) {
|
||||
if (!is_internal_config_option(option.first)) {
|
||||
send_update(make_tl_object<td_api::updateOption>(option.first, make_tl_object<td_api::optionValueEmpty>()));
|
||||
}
|
||||
}
|
||||
OptionManager::clear_options();
|
||||
if (!auth_manager_->is_bot()) {
|
||||
notification_manager_->destroy_all_notifications();
|
||||
}
|
||||
@ -3680,11 +3476,10 @@ void Td::clear() {
|
||||
notification_manager_->flush_all_notifications();
|
||||
}
|
||||
}
|
||||
LOG(DEBUG) << "Options was cleared" << timer;
|
||||
|
||||
G()->net_query_creator().stop_check();
|
||||
result_handlers_.clear();
|
||||
LOG(DEBUG) << "Handlers was cleared" << timer;
|
||||
LOG(DEBUG) << "Handlers were cleared" << timer;
|
||||
G()->net_query_dispatcher().stop();
|
||||
LOG(DEBUG) << "NetQueryDispatcher was stopped" << timer;
|
||||
state_manager_.reset();
|
||||
@ -3697,7 +3492,7 @@ void Td::clear() {
|
||||
alarm_timeout_.cancel_timeout(PING_SERVER_ALARM_ID);
|
||||
alarm_timeout_.cancel_timeout(TERMS_OF_SERVICE_ALARM_ID);
|
||||
alarm_timeout_.cancel_timeout(PROMO_DATA_ALARM_ID);
|
||||
LOG(DEBUG) << "Requests was answered" << timer;
|
||||
LOG(DEBUG) << "Requests were answered" << timer;
|
||||
|
||||
// close all pure actors
|
||||
call_manager_.reset();
|
||||
@ -3761,6 +3556,8 @@ void Td::clear() {
|
||||
LOG(DEBUG) << "MessagesManager actor was cleared" << timer;
|
||||
notification_manager_actor_.reset();
|
||||
LOG(DEBUG) << "NotificationManager actor was cleared" << timer;
|
||||
option_manager_actor_.reset();
|
||||
LOG(DEBUG) << "OptionManager actor was cleared" << timer;
|
||||
poll_manager_actor_.reset();
|
||||
LOG(DEBUG) << "PollManager actor was cleared" << timer;
|
||||
sponsored_message_manager_actor_.reset();
|
||||
@ -3892,9 +3689,6 @@ Status Td::init(DbKey key) {
|
||||
VLOG(td_init) << "Successfully inited database";
|
||||
|
||||
G()->init(parameters_, actor_id(this), r_td_db.move_as_ok()).ensure();
|
||||
last_sent_server_time_difference_ = G()->get_server_time_difference();
|
||||
send_update(td_api::make_object<td_api::updateOption>(
|
||||
"unix_time", td_api::make_object<td_api::optionValueInteger>(G()->unix_time())));
|
||||
|
||||
init_options_and_network();
|
||||
|
||||
@ -4080,11 +3874,16 @@ void Td::init_options_and_network() {
|
||||
config_manager_ = create_actor<ConfigManager>("ConfigManager", create_reference());
|
||||
G()->set_config_manager(config_manager_.get());
|
||||
|
||||
VLOG(td_init) << "Create OptionManager";
|
||||
option_manager_ = make_unique<OptionManager>(this, create_reference());
|
||||
option_manager_actor_ = register_actor("OptionManager", option_manager_.get());
|
||||
G()->set_option_manager(option_manager_actor_.get());
|
||||
|
||||
VLOG(td_init) << "Set ConfigShared callback";
|
||||
class ConfigSharedCallback final : public ConfigShared::Callback {
|
||||
public:
|
||||
void on_option_updated(const string &name, const string &value) const final {
|
||||
send_closure(G()->td(), &Td::on_config_option_updated, name);
|
||||
send_closure_later(G()->option_manager(), &OptionManager::on_option_updated, name);
|
||||
}
|
||||
~ConfigSharedCallback() final {
|
||||
LOG(INFO) << "Destroy ConfigSharedCallback";
|
||||
@ -4233,9 +4032,9 @@ void Td::init_managers() {
|
||||
G()->set_messages_manager(messages_manager_actor_.get());
|
||||
notification_manager_ = make_unique<NotificationManager>(this, create_reference());
|
||||
notification_manager_actor_ = register_actor("NotificationManager", notification_manager_.get());
|
||||
G()->set_notification_manager(notification_manager_actor_.get());
|
||||
poll_manager_ = make_unique<PollManager>(this, create_reference());
|
||||
poll_manager_actor_ = register_actor("PollManager", poll_manager_.get());
|
||||
G()->set_notification_manager(notification_manager_actor_.get());
|
||||
sponsored_message_manager_ = make_unique<SponsoredMessageManager>(this, create_reference());
|
||||
sponsored_message_manager_actor_ = register_actor("SponsoredMessageManager", sponsored_message_manager_.get());
|
||||
G()->set_sponsored_message_manager(sponsored_message_manager_actor_.get());
|
||||
@ -4624,18 +4423,7 @@ void Td::on_request(uint64 id, td_api::confirmQrCodeAuthentication &request) {
|
||||
void Td::on_request(uint64 id, const td_api::getCurrentState &request) {
|
||||
vector<td_api::object_ptr<td_api::Update>> updates;
|
||||
|
||||
updates.push_back(
|
||||
td_api::make_object<td_api::updateOption>("online", make_tl_object<td_api::optionValueBoolean>(is_online_)));
|
||||
updates.push_back(td_api::make_object<td_api::updateOption>(
|
||||
"unix_time", make_tl_object<td_api::optionValueInteger>(G()->unix_time())));
|
||||
updates.push_back(td_api::make_object<td_api::updateOption>(
|
||||
"version", td_api::make_object<td_api::optionValueString>(TDLIB_VERSION)));
|
||||
for (auto &option : G()->shared_config().get_options()) {
|
||||
if (!is_internal_config_option(option.first)) {
|
||||
updates.push_back(td_api::make_object<td_api::updateOption>(
|
||||
option.first, ConfigShared::get_option_value_object(option.second)));
|
||||
}
|
||||
}
|
||||
option_manager_->get_current_state(updates);
|
||||
|
||||
auto state = auth_manager_->get_current_authorization_state_object();
|
||||
if (state != nullptr) {
|
||||
@ -5859,9 +5647,9 @@ void Td::on_request(uint64 id, const td_api::createCall &request) {
|
||||
}
|
||||
|
||||
UserId user_id(request.user_id_);
|
||||
auto input_user = contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return send_error_raw(id, 400, "User not found");
|
||||
auto r_input_user = contacts_manager_->get_input_user(user_id);
|
||||
if (r_input_user.is_error()) {
|
||||
return send_error_raw(id, r_input_user.error().code(), r_input_user.error().message());
|
||||
}
|
||||
|
||||
if (!G()->shared_config().get_option_boolean("calls_enabled")) {
|
||||
@ -5876,7 +5664,7 @@ void Td::on_request(uint64 id, const td_api::createCall &request) {
|
||||
promise.set_value(result.ok().get_call_id_object());
|
||||
}
|
||||
});
|
||||
send_closure(G()->call_manager(), &CallManager::create_call, user_id, std::move(input_user),
|
||||
send_closure(G()->call_manager(), &CallManager::create_call, user_id, r_input_user.move_as_ok(),
|
||||
CallProtocol(*request.protocol_), request.is_video_, std::move(query_promise));
|
||||
}
|
||||
|
||||
@ -7364,420 +7152,14 @@ void Td::on_request(uint64 id, td_api::deleteLanguagePack &request) {
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getOption &request) {
|
||||
CLEAN_INPUT_STRING(request.name_);
|
||||
|
||||
tl_object_ptr<td_api::OptionValue> option_value;
|
||||
bool is_bot = auth_manager_ != nullptr && auth_manager_->is_authorized() && auth_manager_->is_bot();
|
||||
switch (request.name_[0]) {
|
||||
// all these options should be added to getCurrentState
|
||||
case 'a':
|
||||
if (!is_bot && request.name_ == "archive_and_mute_new_chats_from_unknown_users") {
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), id](Result<Unit> &&result) {
|
||||
// the option is already updated on success, ignore errors
|
||||
send_closure(actor_id, &Td::send_result, id,
|
||||
G()->shared_config().get_option_value("archive_and_mute_new_chats_from_unknown_users"));
|
||||
});
|
||||
send_closure_later(config_manager_, &ConfigManager::get_global_privacy_settings, std::move(promise));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (!is_bot && request.name_ == "can_ignore_sensitive_content_restrictions") {
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), id](Result<Unit> &&result) {
|
||||
// the option is already updated on success, ignore errors
|
||||
send_closure(actor_id, &Td::send_result, id,
|
||||
G()->shared_config().get_option_value("can_ignore_sensitive_content_restrictions"));
|
||||
});
|
||||
send_closure_later(config_manager_, &ConfigManager::get_content_settings, std::move(promise));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (!is_bot && request.name_ == "disable_contact_registered_notifications") {
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), id](Result<Unit> &&result) {
|
||||
// the option is already updated on success, ignore errors
|
||||
send_closure(actor_id, &Td::send_result, id,
|
||||
G()->shared_config().get_option_value("disable_contact_registered_notifications"));
|
||||
});
|
||||
send_closure_later(notification_manager_actor_,
|
||||
&NotificationManager::get_disable_contact_registered_notifications, std::move(promise));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (!is_bot && request.name_ == "ignore_sensitive_content_restrictions") {
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), id](Result<Unit> &&result) {
|
||||
// the option is already updated on success, ignore errors
|
||||
send_closure(actor_id, &Td::send_result, id,
|
||||
G()->shared_config().get_option_value("ignore_sensitive_content_restrictions"));
|
||||
});
|
||||
send_closure_later(config_manager_, &ConfigManager::get_content_settings, std::move(promise));
|
||||
return;
|
||||
}
|
||||
if (!is_bot && request.name_ == "is_location_visible") {
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), id](Result<Unit> &&result) {
|
||||
// the option is already updated on success, ignore errors
|
||||
send_closure(actor_id, &Td::send_result, id, G()->shared_config().get_option_value("is_location_visible"));
|
||||
});
|
||||
send_closure_later(contacts_manager_actor_, &ContactsManager::get_is_location_visible, std::move(promise));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (request.name_ == "online") {
|
||||
option_value = make_tl_object<td_api::optionValueBoolean>(is_online_);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (request.name_ == "unix_time") {
|
||||
option_value = make_tl_object<td_api::optionValueInteger>(G()->unix_time());
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
if (request.name_ == "version") {
|
||||
option_value = make_tl_object<td_api::optionValueString>(TDLIB_VERSION);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (option_value == nullptr) {
|
||||
option_value = G()->shared_config().get_option_value(request.name_);
|
||||
}
|
||||
send_closure(actor_id(this), &Td::send_result, id, std::move(option_value));
|
||||
CREATE_REQUEST_PROMISE();
|
||||
option_manager_->get_option(request.name_, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setOption &request) {
|
||||
CLEAN_INPUT_STRING(request.name_);
|
||||
int32 value_constructor_id = request.value_ == nullptr ? td_api::optionValueEmpty::ID : request.value_->get_id();
|
||||
|
||||
LOG(INFO) << "Set option " << request.name_;
|
||||
|
||||
auto set_integer_option = [&](Slice name, int64 min_value = 0, int64 max_value = std::numeric_limits<int32>::max()) {
|
||||
if (request.name_ != name) {
|
||||
return false;
|
||||
}
|
||||
if (value_constructor_id != td_api::optionValueInteger::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
send_error_raw(id, 400, PSLICE() << "Option \"" << name << "\" must have integer value");
|
||||
return true;
|
||||
}
|
||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
int64 value = static_cast<td_api::optionValueInteger *>(request.value_.get())->value_;
|
||||
if (value < min_value || value > max_value) {
|
||||
send_error_raw(id, 400,
|
||||
PSLICE() << "Option's \"" << name << "\" value " << value << " is outside of a valid range ["
|
||||
<< min_value << ", " << max_value << "]");
|
||||
return true;
|
||||
}
|
||||
G()->shared_config().set_option_integer(name, clamp(value, min_value, max_value));
|
||||
}
|
||||
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
|
||||
return true;
|
||||
};
|
||||
|
||||
auto set_boolean_option = [&](Slice name) {
|
||||
if (request.name_ != name) {
|
||||
return false;
|
||||
}
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
send_error_raw(id, 400, PSLICE() << "Option \"" << name << "\" must have boolean value");
|
||||
return true;
|
||||
}
|
||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
bool value = static_cast<td_api::optionValueBoolean *>(request.value_.get())->value_;
|
||||
G()->shared_config().set_option_boolean(name, value);
|
||||
}
|
||||
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
|
||||
return true;
|
||||
};
|
||||
|
||||
auto set_string_option = [&](Slice name, auto check_value) {
|
||||
if (request.name_ != name) {
|
||||
return false;
|
||||
}
|
||||
if (value_constructor_id != td_api::optionValueString::ID && value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
send_error_raw(id, 400, PSLICE() << "Option \"" << name << "\" must have string value");
|
||||
return true;
|
||||
}
|
||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
const string &value = static_cast<td_api::optionValueString *>(request.value_.get())->value_;
|
||||
if (value.empty()) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} else {
|
||||
if (check_value(value)) {
|
||||
G()->shared_config().set_option_string(name, value);
|
||||
} else {
|
||||
send_error_raw(id, 400, PSLICE() << "Option \"" << name << "\" can't have specified value");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
|
||||
return true;
|
||||
};
|
||||
|
||||
bool is_bot = auth_manager_ != nullptr && auth_manager_->is_authorized() && auth_manager_->is_bot();
|
||||
switch (request.name_[0]) {
|
||||
case 'a':
|
||||
if (set_boolean_option("always_parse_markdown")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && request.name_ == "archive_and_mute_new_chats_from_unknown_users") {
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
return send_error_raw(id, 400,
|
||||
"Option \"archive_and_mute_new_chats_from_unknown_users\" must have boolean value");
|
||||
}
|
||||
|
||||
auto archive_and_mute = value_constructor_id == td_api::optionValueBoolean::ID &&
|
||||
static_cast<td_api::optionValueBoolean *>(request.value_.get())->value_;
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
send_closure_later(config_manager_, &ConfigManager::set_archive_and_mute, archive_and_mute, std::move(promise));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (!is_bot && set_string_option("connection_parameters", [](Slice value) {
|
||||
string value_copy = value.str();
|
||||
auto r_json_value = get_json_value(value_copy);
|
||||
if (r_json_value.is_error()) {
|
||||
return false;
|
||||
}
|
||||
return r_json_value.ok()->get_id() == td_api::jsonValueObject::ID;
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (!is_bot && set_boolean_option("disable_animated_emoji")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("disable_contact_registered_notifications")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("disable_sent_scheduled_message_notifications")) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("disable_top_chats")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start custom-patches
|
||||
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;
|
||||
}
|
||||
// End custom-patches
|
||||
if (set_boolean_option("disable_persistent_network_statistics")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("disable_time_adjustment_protection")) {
|
||||
return;
|
||||
}
|
||||
if (request.name_ == "drop_notification_ids") {
|
||||
G()->td_db()->get_binlog_pmc()->erase("notification_id_current");
|
||||
G()->td_db()->get_binlog_pmc()->erase("notification_group_id_current");
|
||||
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (set_boolean_option("ignore_background_updates")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("ignore_default_disable_notification")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("ignore_inline_thumbnails")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("ignore_server_deletes_and_reads")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("ignore_platform_restrictions")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("is_emulator")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start custom-patches
|
||||
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 custom-patches
|
||||
|
||||
if (!is_bot && request.name_ == "ignore_sensitive_content_restrictions") {
|
||||
if (!G()->shared_config().get_option_boolean("can_ignore_sensitive_content_restrictions")) {
|
||||
return send_error_raw(id, 400,
|
||||
"Option \"ignore_sensitive_content_restrictions\" can't be changed by the user");
|
||||
}
|
||||
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
return send_error_raw(id, 400, "Option \"ignore_sensitive_content_restrictions\" must have boolean value");
|
||||
}
|
||||
|
||||
auto ignore_sensitive_content_restrictions =
|
||||
value_constructor_id == td_api::optionValueBoolean::ID &&
|
||||
static_cast<td_api::optionValueBoolean *>(request.value_.get())->value_;
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
send_closure_later(config_manager_, &ConfigManager::set_content_settings, ignore_sensitive_content_restrictions,
|
||||
std::move(promise));
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("is_location_visible")) {
|
||||
contacts_manager_->set_location_visibility();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (!is_bot && set_string_option("language_pack_database_path", [](Slice value) { return true; })) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_string_option("localization_target", LanguagePackManager::check_language_pack_name)) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_string_option("language_pack_id", LanguagePackManager::check_language_code_name)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (set_integer_option("message_unload_delay", 60, 86400)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (!is_bot &&
|
||||
set_integer_option("notification_group_count_max", NotificationManager::MIN_NOTIFICATION_GROUP_COUNT_MAX,
|
||||
NotificationManager::MAX_NOTIFICATION_GROUP_COUNT_MAX)) {
|
||||
return;
|
||||
}
|
||||
if (!is_bot &&
|
||||
set_integer_option("notification_group_size_max", NotificationManager::MIN_NOTIFICATION_GROUP_SIZE_MAX,
|
||||
NotificationManager::MAX_NOTIFICATION_GROUP_SIZE_MAX)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (request.name_ == "online") {
|
||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
||||
return send_error_raw(id, 400, "Option \"online\" must have boolean value");
|
||||
}
|
||||
bool is_online = value_constructor_id == td_api::optionValueEmpty::ID ||
|
||||
static_cast<const td_api::optionValueBoolean *>(request.value_.get())->value_;
|
||||
if (!is_bot) {
|
||||
send_closure(G()->state_manager(), &StateManager::on_online, is_online);
|
||||
}
|
||||
if (is_online != is_online_) {
|
||||
is_online_ = is_online;
|
||||
if (auth_manager_ != nullptr) { // postpone if there is no AuthManager yet
|
||||
on_online_updated(true, true);
|
||||
}
|
||||
}
|
||||
return send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (set_boolean_option("prefer_ipv6")) {
|
||||
send_closure(state_manager_, &StateManager::on_network_updated);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
// temporary option
|
||||
if (set_boolean_option("reuse_uploaded_photos_by_hash")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("receive_access_hashes")) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (set_integer_option("storage_max_files_size")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("storage_max_time_from_last_access")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("storage_max_file_count")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("storage_immunity_delay")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("store_all_files_in_files_directory")) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (set_boolean_option("test_flood_wait")) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (set_boolean_option("use_pfs")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("use_quick_ack")) {
|
||||
return;
|
||||
}
|
||||
if (set_boolean_option("use_storage_optimizer")) {
|
||||
return;
|
||||
}
|
||||
if (set_integer_option("utc_time_offset", -12 * 60 * 60, 14 * 60 * 60)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
case 'x': {
|
||||
if (request.name_.size() > 255) {
|
||||
return send_error_raw(id, 400, "Option name is too long");
|
||||
}
|
||||
switch (value_constructor_id) {
|
||||
case td_api::optionValueBoolean::ID:
|
||||
G()->shared_config().set_option_boolean(
|
||||
request.name_, static_cast<const td_api::optionValueBoolean *>(request.value_.get())->value_);
|
||||
break;
|
||||
case td_api::optionValueEmpty::ID:
|
||||
G()->shared_config().set_option_empty(request.name_);
|
||||
break;
|
||||
case td_api::optionValueInteger::ID:
|
||||
G()->shared_config().set_option_integer(
|
||||
request.name_, static_cast<const td_api::optionValueInteger *>(request.value_.get())->value_);
|
||||
break;
|
||||
case td_api::optionValueString::ID:
|
||||
G()->shared_config().set_option_string(
|
||||
request.name_, static_cast<const td_api::optionValueString *>(request.value_.get())->value_);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
|
||||
}
|
||||
}
|
||||
|
||||
return send_error_raw(id, 400, "Option can't be set");
|
||||
option_manager_->set_option(request.name_, std::move(request.value_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setPollAnswer &request) {
|
||||
@ -7976,13 +7358,12 @@ void Td::on_request(uint64 id, const td_api::deletePassportElement &request) {
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setPassportElementErrors &request) {
|
||||
CHECK_IS_BOT();
|
||||
UserId user_id(request.user_id_);
|
||||
auto input_user = contacts_manager_->get_input_user(user_id);
|
||||
if (input_user == nullptr) {
|
||||
return send_error_raw(id, 400, "User not found");
|
||||
auto r_input_user = contacts_manager_->get_input_user(UserId(request.user_id_));
|
||||
if (r_input_user.is_error()) {
|
||||
return send_error_raw(id, r_input_user.error().code(), r_input_user.error().message());
|
||||
}
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
send_closure(secure_manager_, &SecureManager::set_secure_value_errors, this, std::move(input_user),
|
||||
send_closure(secure_manager_, &SecureManager::set_secure_value_errors, this, r_input_user.move_as_ok(),
|
||||
std::move(request.errors_), std::move(promise));
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ class LinkManager;
|
||||
class MessagesManager;
|
||||
class NetStatsManager;
|
||||
class NotificationManager;
|
||||
class OptionManager;
|
||||
class PasswordManager;
|
||||
class PhoneNumberManager;
|
||||
class PollManager;
|
||||
@ -104,6 +105,8 @@ class Td final : public Actor {
|
||||
Td &operator=(Td &&) = delete;
|
||||
~Td() final;
|
||||
|
||||
static constexpr const char *TDLIB_VERSION = "1.7.10";
|
||||
|
||||
struct Options {
|
||||
std::shared_ptr<NetQueryStats> net_query_stats;
|
||||
};
|
||||
@ -122,13 +125,14 @@ class Td final : public Actor {
|
||||
|
||||
void on_result(NetQueryPtr query);
|
||||
|
||||
void on_update_server_time_difference();
|
||||
|
||||
void on_online_updated(bool force, bool send_update);
|
||||
|
||||
void on_update_status_success(bool is_online);
|
||||
|
||||
bool is_online() const;
|
||||
|
||||
void set_is_online(bool is_online);
|
||||
|
||||
void set_is_bot_online(bool is_bot_online);
|
||||
|
||||
template <class ActorT, class... ArgsT>
|
||||
@ -182,6 +186,8 @@ class Td final : public Actor {
|
||||
ActorOwn<MessagesManager> messages_manager_actor_;
|
||||
unique_ptr<NotificationManager> notification_manager_;
|
||||
ActorOwn<NotificationManager> notification_manager_actor_;
|
||||
unique_ptr<OptionManager> option_manager_;
|
||||
ActorOwn<OptionManager> option_manager_actor_;
|
||||
unique_ptr<PollManager> poll_manager_;
|
||||
ActorOwn<PollManager> poll_manager_actor_;
|
||||
unique_ptr<SponsoredMessageManager> sponsored_message_manager_;
|
||||
@ -259,7 +265,6 @@ class Td final : public Actor {
|
||||
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
||||
|
||||
private:
|
||||
static constexpr const char *TDLIB_VERSION = "1.7.10";
|
||||
static constexpr int64 ONLINE_ALARM_ID = 0;
|
||||
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
||||
static constexpr int32 PING_SERVER_TIMEOUT = 300;
|
||||
@ -320,8 +325,6 @@ class Td final : public Actor {
|
||||
|
||||
TermsOfService pending_terms_of_service_;
|
||||
|
||||
double last_sent_server_time_difference_ = 1e100;
|
||||
|
||||
struct DownloadInfo {
|
||||
int32 offset = -1;
|
||||
int32 limit = -1;
|
||||
@ -357,10 +360,6 @@ class Td final : public Actor {
|
||||
|
||||
void on_file_download_finished(FileId file_id);
|
||||
|
||||
static bool is_internal_config_option(Slice name);
|
||||
|
||||
void on_config_option_updated(const string &name);
|
||||
|
||||
class OnRequest;
|
||||
|
||||
class DownloadFileCallback;
|
||||
|
@ -1003,8 +1003,6 @@ class CliClient final : public Actor {
|
||||
bad_parameters->api_id_ = api_id_;
|
||||
bad_parameters->api_hash_ = api_hash_;
|
||||
send_request(td_api::make_object<td_api::setTdlibParameters>(std::move(bad_parameters)));
|
||||
|
||||
send_closure_later(actor_id(this), &CliClient::create_td, Slice("ClientActor3"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
|
@ -30,7 +30,6 @@ int64 BufferAllocator::get_buffer_slice_size() {
|
||||
}
|
||||
|
||||
void BufferAllocator::track_buffer_slice(int64 size) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t BufferAllocator::get_buffer_mem() {
|
||||
|
@ -191,9 +191,8 @@ class DefaultLog final : public LogInterface {
|
||||
#elif TD_EMSCRIPTEN
|
||||
switch (log_level) {
|
||||
case VERBOSITY_NAME(FATAL):
|
||||
emscripten_log(
|
||||
EM_LOG_ERROR | EM_LOG_CONSOLE | EM_LOG_C_STACK | EM_LOG_JS_STACK | EM_LOG_DEMANGLE | EM_LOG_FUNC_PARAMS,
|
||||
"%s", slice.c_str());
|
||||
emscripten_log(EM_LOG_ERROR | EM_LOG_CONSOLE | EM_LOG_C_STACK | EM_LOG_JS_STACK | EM_LOG_FUNC_PARAMS, "%s",
|
||||
slice.c_str());
|
||||
EM_ASM(throw(UTF8ToString($0)), slice.c_str());
|
||||
break;
|
||||
case VERBOSITY_NAME(ERROR):
|
||||
|
@ -78,12 +78,14 @@ class SocketFdImpl final : private Iocp::Callback {
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (!is_write_waiting_) {
|
||||
if (!is_write_waiting_ && is_connected_) {
|
||||
VLOG(fd) << get_native_fd() << " will close after ongoing write";
|
||||
auto lock = lock_.lock();
|
||||
if (!is_write_waiting_) {
|
||||
need_close_after_write_ = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
notify_iocp_close();
|
||||
}
|
||||
|
||||
@ -168,7 +170,7 @@ class SocketFdImpl final : private Iocp::Callback {
|
||||
bool close_flag_{false};
|
||||
bool need_close_after_write_{false};
|
||||
|
||||
bool is_connected_{false};
|
||||
std::atomic<bool> is_connected_{false};
|
||||
bool is_read_active_{false};
|
||||
ChainBufferWriter input_writer_;
|
||||
ChainBufferReader input_reader_ = input_writer_.extract_reader();
|
||||
|
Loading…
Reference in New Issue
Block a user