callback, Options options)
+ : callback_(std::move(callback)), options_(std::move(options)) {
+}
+
+void ClientActor::start_up() {
Td::Options td_options;
- td_options.net_query_stats = std::move(options.net_query_stats);
- td_ = create_actor("Td", std::move(callback), std::move(td_options));
+ td_options.net_query_stats = std::move(options_.net_query_stats);
+ td_ = create_actor | ("Td", std::move(callback_), std::move(td_options));
}
void ClientActor::request(uint64 id, td_api::object_ptr request) {
diff --git a/td/telegram/ClientActor.h b/td/telegram/ClientActor.h
index 19fe24bfe..de164cb71 100644
--- a/td/telegram/ClientActor.h
+++ b/td/telegram/ClientActor.h
@@ -81,7 +81,11 @@ class ClientActor final : public Actor {
ClientActor &operator=(const ClientActor &other) = delete;
private:
+ void start_up() final;
+
ActorOwn td_;
+ unique_ptr callback_;
+ Options options_;
};
/**
diff --git a/td/telegram/ClientJson.cpp b/td/telegram/ClientJson.cpp
index d66741383..c2ab41774 100644
--- a/td/telegram/ClientJson.cpp
+++ b/td/telegram/ClientJson.cpp
@@ -48,8 +48,7 @@ static std::pair, string> to_request(Slice
td_api::object_ptr func;
auto status = from_json(func, std::move(json_value));
if (status.is_error()) {
- return {get_return_error_function(PSLICE()
- << "Failed to parse JSON object as TDLib request: " << status.error().message()),
+ return {get_return_error_function(PSLICE() << "Failed to parse JSON object as TDLib request: " << status.message()),
std::move(extra)};
}
return std::make_pair(std::move(func), std::move(extra));
diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp
index 00cd88b1d..492da4f20 100644
--- a/td/telegram/ConfigManager.cpp
+++ b/td/telegram/ConfigManager.cpp
@@ -1467,9 +1467,11 @@ void ConfigManager::process_app_config(tl_object_ptr &c
string autologin_token;
vector autologin_domains;
vector url_auth_domains;
+ vector whitelisted_domains;
vector> new_values;
string ignored_restriction_reasons;
+ string restriction_add_platforms;
vector dice_emojis;
FlatHashMap dice_emoji_index;
FlatHashMap dice_emoji_success_value;
@@ -1489,6 +1491,7 @@ void ConfigManager::process_app_config(tl_object_ptr &c
bool is_premium_available = false;
int32 stickers_premium_by_emoji_num = 0;
int32 stickers_normal_by_emoji_per_premium_num = 2;
+ int32 forum_upgrade_participants_min = 200;
if (config->get_id() == telegram_api::jsonObject::ID) {
for (auto &key_value : static_cast(config.get())->value_) {
Slice key = key_value->key_;
@@ -1518,6 +1521,25 @@ void ConfigManager::process_app_config(tl_object_ptr &c
}
continue;
}
+ if (key == "restriction_add_platforms") {
+ if (value->get_id() == telegram_api::jsonArray::ID) {
+ auto platforms = std::move(static_cast(value)->value_);
+ for (auto &platform : platforms) {
+ auto platform_name = get_json_value_string(std::move(platform), key);
+ if (!platform_name.empty() && platform_name.find(',') == string::npos) {
+ if (!restriction_add_platforms.empty()) {
+ restriction_add_platforms += ',';
+ }
+ restriction_add_platforms += platform_name;
+ } else {
+ LOG(ERROR) << "Receive unexpected restriction platform " << platform_name;
+ }
+ }
+ } else {
+ LOG(ERROR) << "Receive unexpected restriction_add_platforms " << to_string(*value);
+ }
+ continue;
+ }
if (key == "emojies_animated_zoom") {
animated_emoji_zoom = get_json_value_double(std::move(key_value->value_), key);
continue;
@@ -1680,13 +1702,24 @@ void ConfigManager::process_app_config(tl_object_ptr &c
if (value->get_id() == telegram_api::jsonArray::ID) {
auto domains = std::move(static_cast(value)->value_);
for (auto &domain : domains) {
- autologin_domains.push_back(get_json_value_string(std::move(domain), key));
+ url_auth_domains.push_back(get_json_value_string(std::move(domain), key));
}
} else {
LOG(ERROR) << "Receive unexpected url_auth_domains " << to_string(*value);
}
continue;
}
+ if (key == "whitelisted_domains") {
+ if (value->get_id() == telegram_api::jsonArray::ID) {
+ auto domains = std::move(static_cast(value)->value_);
+ for (auto &domain : domains) {
+ whitelisted_domains.push_back(get_json_value_string(std::move(domain), key));
+ }
+ } else {
+ LOG(ERROR) << "Receive unexpected whitelisted_domains " << to_string(*value);
+ }
+ continue;
+ }
if (key == "round_video_encoding") {
if (value->get_id() == telegram_api::jsonObject::ID) {
auto video_note_settings = std::move(static_cast(value)->value_);
@@ -1811,6 +1844,10 @@ void ConfigManager::process_app_config(tl_object_ptr &c
G()->set_option_integer(key, setting_value);
continue;
}
+ if (key == "forum_upgrade_participants_min") {
+ forum_upgrade_participants_min = get_json_value_int(std::move(key_value->value_), key);
+ continue;
+ }
new_values.push_back(std::move(key_value));
}
@@ -1820,7 +1857,7 @@ void ConfigManager::process_app_config(tl_object_ptr &c
config = make_tl_object(std::move(new_values));
send_closure(G()->link_manager(), &LinkManager::update_autologin_domains, std::move(autologin_token),
- std::move(autologin_domains), std::move(url_auth_domains));
+ std::move(autologin_domains), std::move(url_auth_domains), std::move(whitelisted_domains));
Global &options = *G();
@@ -1839,6 +1876,11 @@ void ConfigManager::process_app_config(tl_object_ptr &c
get_content_settings(Auto());
}
}
+ if (restriction_add_platforms.empty()) {
+ options.set_option_empty("restriction_add_platforms");
+ } else {
+ options.set_option_string("restriction_add_platforms", restriction_add_platforms);
+ }
if (!dice_emojis.empty()) {
vector dice_success_values(dice_emojis.size());
@@ -1892,6 +1934,11 @@ void ConfigManager::process_app_config(tl_object_ptr &c
} else {
options.set_option_integer("reactions_uniq_max", reactions_uniq_max);
}
+ if (forum_upgrade_participants_min < 0) {
+ options.set_option_empty("forum_member_count_min");
+ } else {
+ options.set_option_integer("forum_member_count_min", forum_upgrade_participants_min);
+ }
bool is_premium = options.get_option_boolean("is_premium");
diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp
index 8c8a4be00..b17b9d76b 100644
--- a/td/telegram/ContactsManager.cpp
+++ b/td/telegram/ContactsManager.cpp
@@ -626,7 +626,7 @@ class CheckUsernameQuery final : public Td::ResultHandler {
}
void send(const string &username) {
- send_query(G()->net_query_creator().create(telegram_api::account_checkUsername(username)));
+ send_query(G()->net_query_creator().create(telegram_api::account_checkUsername(username), {{"me"}}));
}
void on_result(BufferSlice packet) final {
@@ -674,6 +674,78 @@ class UpdateUsernameQuery final : public Td::ResultHandler {
}
};
+class ToggleUsernameQuery final : public Td::ResultHandler {
+ Promise promise_;
+ string username_;
+ bool is_active_;
+
+ public:
+ explicit ToggleUsernameQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(string &&username, bool is_active) {
+ username_ = std::move(username);
+ is_active_ = is_active;
+ send_query(G()->net_query_creator().create(telegram_api::account_toggleUsername(username_, is_active_), {{"me"}}));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ bool result = result_ptr.ok();
+ LOG(DEBUG) << "Receive result for ToggleUsernameQuery: " << result;
+ td_->contacts_manager_->on_update_username_is_active(std::move(username_), is_active_, std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "USERNAME_NOT_MODIFIED") {
+ td_->contacts_manager_->on_update_username_is_active(std::move(username_), is_active_, std::move(promise_));
+ return;
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
+class ReorderUsernamesQuery final : public Td::ResultHandler {
+ Promise promise_;
+ vector usernames_;
+
+ public:
+ explicit ReorderUsernamesQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(vector &&usernames) {
+ usernames_ = usernames;
+ send_query(G()->net_query_creator().create(telegram_api::account_reorderUsernames(std::move(usernames)), {{"me"}}));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ bool result = result_ptr.ok();
+ LOG(DEBUG) << "Receive result for ReorderUsernamesQuery: " << result;
+ if (!result) {
+ return on_error(Status::Error(500, "Usernames weren't updated"));
+ }
+
+ td_->contacts_manager_->on_update_active_usernames_order(std::move(usernames_), std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "USERNAME_NOT_MODIFIED") {
+ td_->contacts_manager_->on_update_active_usernames_order(std::move(usernames_), std::move(promise_));
+ return;
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
class UpdateEmojiStatusQuery final : public Td::ResultHandler {
Promise promise_;
@@ -759,8 +831,8 @@ class UpdateChannelUsernameQuery final : public Td::ResultHandler {
username_ = username;
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
- send_query(
- G()->net_query_creator().create(telegram_api::channels_updateUsername(std::move(input_channel), username)));
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_updateUsername(std::move(input_channel), username), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -775,13 +847,13 @@ class UpdateChannelUsernameQuery final : public Td::ResultHandler {
return on_error(Status::Error(500, "Supergroup username is not updated"));
}
- td_->contacts_manager_->on_update_channel_username(channel_id_, std::move(username_));
+ td_->contacts_manager_->on_update_channel_editable_username(channel_id_, std::move(username_));
promise_.set_value(Unit());
}
void on_error(Status status) final {
if (status.message() == "USERNAME_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") {
- td_->contacts_manager_->on_update_channel_username(channel_id_, std::move(username_));
+ td_->contacts_manager_->on_update_channel_editable_username(channel_id_, std::move(username_));
if (!td_->auth_manager_->is_bot()) {
promise_.set_value(Unit());
return;
@@ -793,6 +865,134 @@ class UpdateChannelUsernameQuery final : public Td::ResultHandler {
}
};
+class ToggleChannelUsernameQuery final : public Td::ResultHandler {
+ Promise promise_;
+ ChannelId channel_id_;
+ string username_;
+ bool is_active_;
+
+ public:
+ explicit ToggleChannelUsernameQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(ChannelId channel_id, string &&username, bool is_active) {
+ channel_id_ = channel_id;
+ username_ = std::move(username);
+ is_active_ = is_active;
+ auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
+ CHECK(input_channel != nullptr);
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_toggleUsername(std::move(input_channel), username_, is_active_), {{channel_id}}));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ bool result = result_ptr.ok();
+ LOG(DEBUG) << "Receive result for ToggleChannelUsernameQuery: " << result;
+ td_->contacts_manager_->on_update_channel_username_is_active(channel_id_, std::move(username_), is_active_,
+ std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "USERNAME_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") {
+ td_->contacts_manager_->on_update_channel_username_is_active(channel_id_, std::move(username_), is_active_,
+ std::move(promise_));
+ return;
+ } else {
+ td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ToggleChannelUsernameQuery");
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
+class DeactivateAllChannelUsernamesQuery final : public Td::ResultHandler {
+ Promise promise_;
+ ChannelId channel_id_;
+
+ public:
+ explicit DeactivateAllChannelUsernamesQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(ChannelId channel_id) {
+ channel_id_ = channel_id;
+ auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
+ CHECK(input_channel != nullptr);
+ send_query(G()->net_query_creator().create(telegram_api::channels_deactivateAllUsernames(std::move(input_channel)),
+ {{channel_id}}));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ bool result = result_ptr.ok();
+ LOG(DEBUG) << "Receive result for DeactivateAllChannelUsernamesQuery: " << result;
+ td_->contacts_manager_->on_deactivate_channel_usernames(channel_id_, std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "USERNAME_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") {
+ td_->contacts_manager_->on_deactivate_channel_usernames(channel_id_, std::move(promise_));
+ return;
+ } else {
+ td_->contacts_manager_->on_get_channel_error(channel_id_, status, "DeactivateAllChannelUsernamesQuery");
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
+class ReorderChannelUsernamesQuery final : public Td::ResultHandler {
+ Promise promise_;
+ ChannelId channel_id_;
+ vector usernames_;
+
+ public:
+ explicit ReorderChannelUsernamesQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(ChannelId channel_id, vector &&usernames) {
+ channel_id_ = channel_id;
+ usernames_ = usernames;
+ auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
+ CHECK(input_channel != nullptr);
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_reorderUsernames(std::move(input_channel), std::move(usernames)), {{channel_id}}));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ bool result = result_ptr.ok();
+ LOG(DEBUG) << "Receive result for ReorderChannelUsernamesQuery: " << result;
+ if (!result) {
+ return on_error(Status::Error(500, "Supergroup usernames weren't updated"));
+ }
+
+ td_->contacts_manager_->on_update_channel_active_usernames_order(channel_id_, std::move(usernames_),
+ std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "USERNAME_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") {
+ td_->contacts_manager_->on_update_channel_active_usernames_order(channel_id_, std::move(usernames_),
+ std::move(promise_));
+ return;
+ } else {
+ td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ReorderChannelUsernamesQuery");
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
class SetChannelStickerSetQuery final : public Td::ResultHandler {
Promise promise_;
ChannelId channel_id_;
@@ -809,7 +1009,7 @@ class SetChannelStickerSetQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_query(G()->net_query_creator().create(
- telegram_api::channels_setStickers(std::move(input_channel), std::move(input_sticker_set))));
+ telegram_api::channels_setStickers(std::move(input_channel), std::move(input_sticker_set)), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -855,7 +1055,7 @@ class ToggleChannelSignaturesQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_query(G()->net_query_creator().create(
- telegram_api::channels_toggleSignatures(std::move(input_channel), sign_messages)));
+ telegram_api::channels_toggleSignatures(std::move(input_channel), sign_messages), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -895,7 +1095,7 @@ class ToggleChannelJoinToSendQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_query(G()->net_query_creator().create(
- telegram_api::channels_toggleJoinToSend(std::move(input_channel), join_to_send)));
+ telegram_api::channels_toggleJoinToSend(std::move(input_channel), join_to_send), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -935,7 +1135,7 @@ class ToggleChannelJoinRequestQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_query(G()->net_query_creator().create(
- telegram_api::channels_toggleJoinRequest(std::move(input_channel), join_request)));
+ telegram_api::channels_toggleJoinRequest(std::move(input_channel), join_request), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -978,7 +1178,8 @@ class TogglePrehistoryHiddenQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_query(G()->net_query_creator().create(
- telegram_api::channels_togglePreHistoryHidden(std::move(input_channel), !is_all_history_available)));
+ telegram_api::channels_togglePreHistoryHidden(std::move(input_channel), !is_all_history_available),
+ {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1013,6 +1214,47 @@ class TogglePrehistoryHiddenQuery final : public Td::ResultHandler {
}
};
+class ToggleForumQuery final : public Td::ResultHandler {
+ Promise promise_;
+ ChannelId channel_id_;
+
+ public:
+ explicit ToggleForumQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(ChannelId channel_id, bool is_forum) {
+ channel_id_ = channel_id;
+
+ auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
+ CHECK(input_channel != nullptr);
+ send_query(G()->net_query_creator().create(telegram_api::channels_toggleForum(std::move(input_channel), is_forum),
+ {{channel_id}}));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ auto ptr = result_ptr.move_as_ok();
+ LOG(INFO) << "Receive result for ToggleForumQuery: " << to_string(ptr);
+ td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "CHAT_NOT_MODIFIED") {
+ if (!td_->auth_manager_->is_bot()) {
+ promise_.set_value(Unit());
+ return;
+ }
+ } else {
+ td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ToggleForumQuery");
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
class ConvertToGigagroupQuery final : public Td::ResultHandler {
Promise promise_;
ChannelId channel_id_;
@@ -1026,7 +1268,8 @@ class ConvertToGigagroupQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
- send_query(G()->net_query_creator().create(telegram_api::channels_convertToGigagroup(std::move(input_channel))));
+ send_query(G()->net_query_creator().create(telegram_api::channels_convertToGigagroup(std::move(input_channel)),
+ {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1081,7 +1324,8 @@ class EditChatAboutQuery final : public Td::ResultHandler {
if (input_peer == nullptr) {
return on_error(Status::Error(400, "Can't access the chat"));
}
- send_query(G()->net_query_creator().create(telegram_api::messages_editChatAbout(std::move(input_peer), about)));
+ send_query(G()->net_query_creator().create(telegram_api::messages_editChatAbout(std::move(input_peer), about),
+ {{dialog_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1129,7 +1373,8 @@ class SetDiscussionGroupQuery final : public Td::ResultHandler {
broadcast_channel_id_ = broadcast_channel_id;
group_channel_id_ = group_channel_id;
send_query(G()->net_query_creator().create(
- telegram_api::channels_setDiscussionGroup(std::move(broadcast_input_channel), std::move(group_input_channel))));
+ telegram_api::channels_setDiscussionGroup(std::move(broadcast_input_channel), std::move(group_input_channel)),
+ {{broadcast_channel_id}, {group_channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1169,8 +1414,10 @@ class EditLocationQuery final : public Td::ResultHandler {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
- send_query(G()->net_query_creator().create(telegram_api::channels_editLocation(
- std::move(input_channel), location_.get_input_geo_point(), location_.get_address())));
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_editLocation(std::move(input_channel), location_.get_input_geo_point(),
+ location_.get_address()),
+ {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1209,7 +1456,7 @@ class ToggleSlowModeQuery final : public Td::ResultHandler {
CHECK(input_channel != nullptr);
send_query(G()->net_query_creator().create(
- telegram_api::channels_toggleSlowMode(std::move(input_channel), slow_mode_delay)));
+ telegram_api::channels_toggleSlowMode(std::move(input_channel), slow_mode_delay), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1295,7 +1542,7 @@ class DeleteChatQuery final : public Td::ResultHandler {
}
void send(ChatId chat_id) {
- send_query(G()->net_query_creator().create(telegram_api::messages_deleteChat(chat_id.get())));
+ send_query(G()->net_query_creator().create(telegram_api::messages_deleteChat(chat_id.get()), {{chat_id}}));
}
void on_result(BufferSlice packet) final {
@@ -1326,7 +1573,8 @@ class DeleteChannelQuery final : public Td::ResultHandler {
channel_id_ = channel_id;
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
- send_query(G()->net_query_creator().create(telegram_api::channels_deleteChannel(std::move(input_channel))));
+ send_query(G()->net_query_creator().create(telegram_api::channels_deleteChannel(std::move(input_channel)),
+ {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -2198,7 +2446,8 @@ class JoinChannelQuery final : public Td::ResultHandler {
channel_id_ = channel_id;
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
- send_query(G()->net_query_creator().create(telegram_api::channels_joinChannel(std::move(input_channel))));
+ send_query(
+ G()->net_query_creator().create(telegram_api::channels_joinChannel(std::move(input_channel)), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -2350,7 +2599,8 @@ class LeaveChannelQuery final : public Td::ResultHandler {
channel_id_ = channel_id;
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
CHECK(input_channel != nullptr);
- send_query(G()->net_query_creator().create(telegram_api::channels_leaveChannel(std::move(input_channel))));
+ send_query(
+ G()->net_query_creator().create(telegram_api::channels_leaveChannel(std::move(input_channel)), {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -2421,8 +2671,10 @@ class EditChannelCreatorQuery final : public Td::ResultHandler {
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), r_input_user.move_as_ok(), std::move(input_check_password))));
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_editCreator(std::move(input_channel), r_input_user.move_as_ok(),
+ std::move(input_check_password)),
+ {{channel_id}}));
}
void on_result(BufferSlice packet) final {
@@ -2452,7 +2704,7 @@ class MigrateChatQuery final : public Td::ResultHandler {
}
void send(ChatId chat_id) {
- send_query(G()->net_query_creator().create(telegram_api::messages_migrateChat(chat_id.get())));
+ send_query(G()->net_query_creator().create(telegram_api::messages_migrateChat(chat_id.get()), {{chat_id}}));
}
void on_result(BufferSlice packet) final {
@@ -3673,7 +3925,7 @@ template
void ContactsManager::User::store(StorerT &storer) const {
using td::store;
bool has_last_name = !last_name.empty();
- bool has_username = !username.empty();
+ bool legacy_has_username = false;
bool has_photo = photo.small_file_id.is_valid();
bool has_language_code = !language_code.empty();
bool have_access_hash = access_hash != -1;
@@ -3681,6 +3933,7 @@ void ContactsManager::User::store(StorerT &storer) const {
bool has_is_contact = true;
bool has_restriction_reasons = !restriction_reasons.empty();
bool has_emoji_status = !emoji_status.is_empty();
+ bool has_usernames = !usernames.is_empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(is_received);
STORE_FLAG(is_verified);
@@ -3691,7 +3944,7 @@ void ContactsManager::User::store(StorerT &storer) const {
STORE_FLAG(is_inline_bot);
STORE_FLAG(need_location_bot);
STORE_FLAG(has_last_name);
- STORE_FLAG(has_username);
+ STORE_FLAG(legacy_has_username);
STORE_FLAG(has_photo); // 10
STORE_FLAG(false); // legacy is_restricted
STORE_FLAG(has_language_code);
@@ -3710,14 +3963,12 @@ void ContactsManager::User::store(StorerT &storer) const {
STORE_FLAG(is_premium); // 25
STORE_FLAG(attach_menu_enabled);
STORE_FLAG(has_emoji_status);
+ STORE_FLAG(has_usernames);
END_STORE_FLAGS();
store(first_name, storer);
if (has_last_name) {
store(last_name, storer);
}
- if (has_username) {
- store(username, storer);
- }
store(phone_number, storer);
if (have_access_hash) {
store(access_hash, storer);
@@ -3744,13 +3995,16 @@ void ContactsManager::User::store(StorerT &storer) const {
if (has_emoji_status) {
store(emoji_status, storer);
}
+ if (has_usernames) {
+ store(usernames, storer);
+ }
}
template
void ContactsManager::User::parse(ParserT &parser) {
using td::parse;
bool has_last_name;
- bool has_username;
+ bool legacy_has_username;
bool has_photo;
bool legacy_is_restricted;
bool has_language_code;
@@ -3759,6 +4013,7 @@ void ContactsManager::User::parse(ParserT &parser) {
bool has_is_contact;
bool has_restriction_reasons;
bool has_emoji_status;
+ bool has_usernames;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_received);
PARSE_FLAG(is_verified);
@@ -3769,7 +4024,7 @@ void ContactsManager::User::parse(ParserT &parser) {
PARSE_FLAG(is_inline_bot);
PARSE_FLAG(need_location_bot);
PARSE_FLAG(has_last_name);
- PARSE_FLAG(has_username);
+ PARSE_FLAG(legacy_has_username);
PARSE_FLAG(has_photo);
PARSE_FLAG(legacy_is_restricted);
PARSE_FLAG(has_language_code);
@@ -3788,13 +4043,17 @@ void ContactsManager::User::parse(ParserT &parser) {
PARSE_FLAG(is_premium);
PARSE_FLAG(attach_menu_enabled);
PARSE_FLAG(has_emoji_status);
+ PARSE_FLAG(has_usernames);
END_PARSE_FLAGS();
parse(first_name, parser);
if (has_last_name) {
parse(last_name, parser);
}
- if (has_username) {
+ if (legacy_has_username) {
+ CHECK(!has_usernames);
+ string username;
parse(username, parser);
+ usernames = Usernames(std::move(username), vector>());
}
parse(phone_number, parser);
if (parser.version() < static_cast(Version::FixMinUsers)) {
@@ -3842,6 +4101,10 @@ void ContactsManager::User::parse(ParserT &parser) {
if (has_emoji_status) {
parse(emoji_status, parser);
}
+ if (has_usernames) {
+ CHECK(!legacy_has_username);
+ parse(usernames, parser);
+ }
if (!check_utf8(first_name)) {
LOG(ERROR) << "Have invalid first name \"" << first_name << '"';
@@ -3853,11 +4116,6 @@ void ContactsManager::User::parse(ParserT &parser) {
last_name.clear();
cache_version = 0;
}
- if (!check_utf8(username)) {
- LOG(ERROR) << "Have invalid username \"" << username << '"';
- username.clear();
- cache_version = 0;
- }
clean_phone_number(phone_number);
if (first_name.empty() && last_name.empty()) {
@@ -4117,7 +4375,7 @@ void ContactsManager::Chat::parse(ParserT &parser) {
status = DialogParticipantStatus::Member();
}
default_permissions = RestrictedRights(true, true, true, true, true, true, true, true, everyone_is_administrator,
- everyone_is_administrator, everyone_is_administrator);
+ everyone_is_administrator, everyone_is_administrator, false);
}
if (has_default_permissions_version) {
parse(default_permissions_version, parser);
@@ -4214,13 +4472,15 @@ template
void ContactsManager::Channel::store(StorerT &storer) const {
using td::store;
bool has_photo = photo.small_file_id.is_valid();
- bool has_username = !username.empty();
+ bool legacy_has_username = false;
bool use_new_rights = true;
bool has_participant_count = participant_count != 0;
bool have_default_permissions = true;
bool has_cache_version = cache_version != 0;
bool has_restriction_reasons = !restriction_reasons.empty();
bool legacy_has_active_group_call = false;
+ bool has_usernames = !usernames.is_empty();
+ bool has_flags2 = true;
BEGIN_STORE_FLAGS();
STORE_FLAG(false);
STORE_FLAG(false);
@@ -4232,7 +4492,7 @@ void ContactsManager::Channel::store(StorerT &storer) const {
STORE_FLAG(is_megagroup);
STORE_FLAG(is_verified);
STORE_FLAG(has_photo);
- STORE_FLAG(has_username); // 10
+ STORE_FLAG(legacy_has_username); // 10
STORE_FLAG(false);
STORE_FLAG(use_new_rights);
STORE_FLAG(has_participant_count);
@@ -4250,7 +4510,14 @@ void ContactsManager::Channel::store(StorerT &storer) const {
STORE_FLAG(can_be_deleted); // 25
STORE_FLAG(join_to_send);
STORE_FLAG(join_request);
+ STORE_FLAG(has_usernames);
+ STORE_FLAG(has_flags2);
END_STORE_FLAGS();
+ if (has_flags2) {
+ BEGIN_STORE_FLAGS();
+ STORE_FLAG(is_forum);
+ END_STORE_FLAGS();
+ }
store(status, storer);
store(access_hash, storer);
@@ -4258,9 +4525,6 @@ void ContactsManager::Channel::store(StorerT &storer) const {
if (has_photo) {
store(photo, storer);
}
- if (has_username) {
- store(username, storer);
- }
store(date, storer);
if (has_restriction_reasons) {
store(restriction_reasons, storer);
@@ -4274,13 +4538,16 @@ void ContactsManager::Channel::store(StorerT &storer) const {
if (has_cache_version) {
store(cache_version, storer);
}
+ if (has_usernames) {
+ store(usernames, storer);
+ }
}
template
void ContactsManager::Channel::parse(ParserT &parser) {
using td::parse;
bool has_photo;
- bool has_username;
+ bool legacy_has_username;
bool legacy_is_restricted;
bool left;
bool kicked;
@@ -4294,6 +4561,8 @@ void ContactsManager::Channel::parse(ParserT &parser) {
bool has_cache_version;
bool has_restriction_reasons;
bool legacy_has_active_group_call;
+ bool has_usernames;
+ bool has_flags2;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(left);
PARSE_FLAG(kicked);
@@ -4305,7 +4574,7 @@ void ContactsManager::Channel::parse(ParserT &parser) {
PARSE_FLAG(is_megagroup);
PARSE_FLAG(is_verified);
PARSE_FLAG(has_photo);
- PARSE_FLAG(has_username);
+ PARSE_FLAG(legacy_has_username);
PARSE_FLAG(legacy_is_restricted);
PARSE_FLAG(use_new_rights);
PARSE_FLAG(has_participant_count);
@@ -4323,7 +4592,14 @@ void ContactsManager::Channel::parse(ParserT &parser) {
PARSE_FLAG(can_be_deleted);
PARSE_FLAG(join_to_send);
PARSE_FLAG(join_request);
+ PARSE_FLAG(has_usernames);
+ PARSE_FLAG(has_flags2);
END_PARSE_FLAGS();
+ if (has_flags2) {
+ BEGIN_PARSE_FLAGS();
+ PARSE_FLAG(is_forum);
+ END_PARSE_FLAGS();
+ }
if (use_new_rights) {
parse(status, parser);
@@ -4345,8 +4621,11 @@ void ContactsManager::Channel::parse(ParserT &parser) {
if (has_photo) {
parse(photo, parser);
}
- if (has_username) {
+ if (legacy_has_username) {
+ CHECK(!has_usernames);
+ string username;
parse(username, parser);
+ usernames = Usernames(std::move(username), vector>());
}
parse(date, parser);
if (legacy_is_restricted) {
@@ -4364,23 +4643,22 @@ void ContactsManager::Channel::parse(ParserT &parser) {
parse(default_permissions, parser);
} else {
default_permissions =
- RestrictedRights(true, true, true, true, true, true, true, true, false, anyone_can_invite, false);
+ RestrictedRights(true, true, true, true, true, true, true, true, false, anyone_can_invite, false, false);
}
}
if (has_cache_version) {
parse(cache_version, parser);
}
+ if (has_usernames) {
+ CHECK(!legacy_has_username);
+ parse(usernames, parser);
+ }
if (!check_utf8(title)) {
LOG(ERROR) << "Have invalid title \"" << title << '"';
title.clear();
cache_version = 0;
}
- if (!check_utf8(username)) {
- LOG(ERROR) << "Have invalid username \"" << username << '"';
- username.clear();
- cache_version = 0;
- }
if (legacy_has_active_group_call) {
cache_version = 0;
}
@@ -4971,15 +5249,15 @@ string ContactsManager::get_secret_chat_title(SecretChatId secret_chat_id) const
RestrictedRights ContactsManager::get_user_default_permissions(UserId user_id) const {
auto u = get_user(user_id);
if (u == nullptr || user_id == get_replies_bot_user_id()) {
- return RestrictedRights(false, false, false, false, false, false, false, false, false, false, u != nullptr);
+ return RestrictedRights(false, false, false, false, false, false, false, false, false, false, u != nullptr, false);
}
- return RestrictedRights(true, true, true, true, true, true, true, true, false, false, true);
+ return RestrictedRights(true, true, true, true, true, true, true, true, false, false, true, false);
}
RestrictedRights ContactsManager::get_chat_default_permissions(ChatId chat_id) const {
auto c = get_chat(chat_id);
if (c == nullptr) {
- return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
+ return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false);
}
return c->default_permissions;
}
@@ -4987,7 +5265,7 @@ RestrictedRights ContactsManager::get_chat_default_permissions(ChatId chat_id) c
RestrictedRights ContactsManager::get_channel_default_permissions(ChannelId channel_id) const {
auto c = get_channel(channel_id);
if (c == nullptr) {
- return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
+ return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false);
}
return c->default_permissions;
}
@@ -4995,9 +5273,9 @@ RestrictedRights ContactsManager::get_channel_default_permissions(ChannelId chan
RestrictedRights ContactsManager::get_secret_chat_default_permissions(SecretChatId secret_chat_id) const {
auto c = get_secret_chat(secret_chat_id);
if (c == nullptr) {
- return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
+ return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false, false);
}
- return RestrictedRights(true, true, true, true, true, true, true, true, false, false, false);
+ return RestrictedRights(true, true, true, true, true, true, true, true, false, false, false, false);
}
bool ContactsManager::get_chat_has_protected_content(ChatId chat_id) const {
@@ -5072,6 +5350,49 @@ string ContactsManager::get_dialog_about(DialogId dialog_id) {
return string();
}
+string ContactsManager::get_dialog_search_text(DialogId dialog_id) const {
+ switch (dialog_id.get_type()) {
+ case DialogType::User:
+ return get_user_search_text(dialog_id.get_user_id());
+ case DialogType::Chat:
+ return get_chat_title(dialog_id.get_chat_id());
+ case DialogType::Channel:
+ return get_channel_search_text(dialog_id.get_channel_id());
+ case DialogType::SecretChat:
+ return get_user_search_text(get_secret_chat_user_id(dialog_id.get_secret_chat_id()));
+ case DialogType::None:
+ default:
+ UNREACHABLE();
+ }
+ return string();
+}
+
+string ContactsManager::get_user_search_text(UserId user_id) const {
+ auto u = get_user(user_id);
+ if (u == nullptr) {
+ return string();
+ }
+ return get_user_search_text(u);
+}
+
+string ContactsManager::get_user_search_text(const User *u) {
+ CHECK(u != nullptr);
+ return PSTRING() << u->first_name << ' ' << u->last_name << ' ' << implode(u->usernames.get_active_usernames());
+}
+
+string ContactsManager::get_channel_search_text(ChannelId channel_id) const {
+ auto c = get_channel(channel_id);
+ if (c == nullptr) {
+ return get_channel_title(channel_id);
+ }
+ return get_channel_search_text(c);
+}
+
+string ContactsManager::get_channel_search_text(const Channel *c) {
+ CHECK(c != nullptr);
+ return PSTRING() << c->title << ' ' << implode(c->usernames.get_active_usernames());
+}
+
int32 ContactsManager::get_secret_chat_date(SecretChatId secret_chat_id) const {
auto c = get_secret_chat(secret_chat_id);
if (c == nullptr) {
@@ -5088,7 +5409,7 @@ int32 ContactsManager::get_secret_chat_ttl(SecretChatId secret_chat_id) const {
return c->ttl;
}
-string ContactsManager::get_user_username(UserId user_id) const {
+string ContactsManager::get_user_first_username(UserId user_id) const {
if (!user_id.is_valid()) {
return string();
}
@@ -5097,23 +5418,15 @@ string ContactsManager::get_user_username(UserId user_id) const {
if (u == nullptr) {
return string();
}
- return u->username;
+ return u->usernames.get_first_username();
}
-string ContactsManager::get_secret_chat_username(SecretChatId secret_chat_id) const {
- auto c = get_secret_chat(secret_chat_id);
- if (c == nullptr) {
- return string();
- }
- return get_user_username(c->user_id);
-}
-
-string ContactsManager::get_channel_username(ChannelId channel_id) const {
+string ContactsManager::get_channel_first_username(ChannelId channel_id) const {
auto c = get_channel(channel_id);
if (c == nullptr) {
return string();
}
- return c->username;
+ return c->usernames.get_first_username();
}
UserId ContactsManager::get_secret_chat_user_id(SecretChatId secret_chat_id) const {
@@ -5298,7 +5611,7 @@ void ContactsManager::check_dialog_username(DialogId dialog_id, const string &us
return promise.set_error(Status::Error(400, "Not enough rights to change username"));
}
- if (username == c->username) {
+ if (username == c->usernames.get_editable_username()) {
return promise.set_value(CheckDialogUsernameResult::Ok);
}
break;
@@ -5319,7 +5632,7 @@ void ContactsManager::check_dialog_username(DialogId dialog_id, const string &us
if (username.empty()) {
return promise.set_value(CheckDialogUsernameResult::Ok);
}
- if (!is_valid_username(username)) {
+ if (!is_allowed_username(username)) {
return promise.set_value(CheckDialogUsernameResult::Invalid);
}
@@ -5375,29 +5688,18 @@ td_api::object_ptr ContactsManager::get_check_c
}
}
-bool ContactsManager::is_valid_username(const string &username) {
- if (username.size() < 5 || username.size() > 32) {
+bool ContactsManager::is_allowed_username(const string &username) {
+ if (!is_valid_username(username)) {
return false;
}
- if (!is_alpha(username[0])) {
+ if (username.size() < 5) {
return false;
}
- for (auto c : username) {
- if (!is_alpha(c) && !is_digit(c) && c != '_') {
- return false;
- }
- }
- if (username.back() == '_') {
- return false;
- }
- for (size_t i = 1; i < username.size(); i++) {
- if (username[i - 1] == '_' && username[i] == '_') {
- return false;
- }
- }
- if (username.find("admin") == 0 || username.find("telegram") == 0 || username.find("support") == 0 ||
- username.find("security") == 0 || username.find("settings") == 0 || username.find("contacts") == 0 ||
- username.find("service") == 0 || username.find("telegraph") == 0) {
+ auto username_lowered = to_lower(username);
+ if (username_lowered.find("admin") == 0 || username_lowered.find("telegram") == 0 ||
+ username_lowered.find("support") == 0 || username_lowered.find("security") == 0 ||
+ username_lowered.find("settings") == 0 || username_lowered.find("contacts") == 0 ||
+ username_lowered.find("service") == 0 || username_lowered.find("telegraph") == 0) {
return false;
}
return true;
@@ -5909,11 +6211,11 @@ void ContactsManager::on_update_contacts_reset() {
G()->td_db()->get_sqlite_pmc()->erase("user_imported_contacts", Auto());
}
if (!are_imported_contacts_loaded_) {
- CHECK(all_imported_contacts_.empty());
if (load_imported_contacts_queries_.empty()) {
+ CHECK(all_imported_contacts_.empty());
LOG(INFO) << "Imported contacts was never loaded, just clear them";
} else {
- LOG(INFO) << "Imported contacts are being loaded, clear them also when they will be loaded";
+ LOG(INFO) << "Imported contacts are being loaded, clear them after they will be loaded";
need_clear_imported_contacts_ = true;
}
} else {
@@ -5921,7 +6223,7 @@ void ContactsManager::on_update_contacts_reset() {
LOG(INFO) << "Imported contacts was loaded, but aren't changing now, just clear them";
all_imported_contacts_.clear();
} else {
- LOG(INFO) << "Imported contacts are changing now, clear them also after they will be loaded";
+ LOG(INFO) << "Imported contacts are changing now, clear them after they will be changed";
need_clear_imported_contacts_ = true;
}
}
@@ -6618,12 +6920,82 @@ void ContactsManager::on_update_profile_success(int32 flags, const string &first
}
void ContactsManager::set_username(const string &username, Promise &&promise) {
- if (!username.empty() && !is_valid_username(username)) {
+ if (!username.empty() && !is_allowed_username(username)) {
return promise.set_error(Status::Error(400, "Username is invalid"));
}
td_->create_handler(std::move(promise))->send(username);
}
+void ContactsManager::toggle_username_is_active(string &&username, bool is_active, Promise &&promise) {
+ get_me(PromiseCreator::lambda([actor_id = actor_id(this), username = std::move(username), is_active,
+ promise = std::move(promise)](Result &&result) mutable {
+ if (result.is_error()) {
+ promise.set_error(result.move_as_error());
+ } else {
+ send_closure(actor_id, &ContactsManager::toggle_username_is_active_impl, std::move(username), is_active,
+ std::move(promise));
+ }
+ }));
+}
+
+void ContactsManager::toggle_username_is_active_impl(string &&username, bool is_active, Promise &&promise) {
+ TRY_STATUS_PROMISE(promise, G()->close_status());
+ const User *u = get_user(get_my_id());
+ CHECK(u != nullptr);
+ if (!u->usernames.can_toggle(username)) {
+ return promise.set_error(Status::Error(400, "Wrong username specified"));
+ }
+ td_->create_handler(std::move(promise))->send(std::move(username), is_active);
+}
+
+void ContactsManager::reorder_usernames(vector &&usernames, Promise &&promise) {
+ get_me(PromiseCreator::lambda([actor_id = actor_id(this), usernames = std::move(usernames),
+ promise = std::move(promise)](Result &&result) mutable {
+ if (result.is_error()) {
+ promise.set_error(result.move_as_error());
+ } else {
+ send_closure(actor_id, &ContactsManager::reorder_usernames_impl, std::move(usernames), std::move(promise));
+ }
+ }));
+}
+
+void ContactsManager::reorder_usernames_impl(vector &&usernames, Promise &&promise) {
+ TRY_STATUS_PROMISE(promise, G()->close_status());
+ const User *u = get_user(get_my_id());
+ CHECK(u != nullptr);
+ if (!u->usernames.can_reorder_to(usernames)) {
+ return promise.set_error(Status::Error(400, "Invalid username order specified"));
+ }
+ if (usernames.size() <= 1) {
+ return promise.set_value(Unit());
+ }
+ td_->create_handler(std::move(promise))->send(std::move(usernames));
+}
+
+void ContactsManager::on_update_username_is_active(string &&username, bool is_active, Promise &&promise) {
+ auto user_id = get_my_id();
+ User *u = get_user(user_id);
+ CHECK(u != nullptr);
+ if (!u->usernames.can_toggle(username)) {
+ return reload_user(user_id, std::move(promise));
+ }
+ on_update_user_usernames(u, user_id, u->usernames.toggle(username, is_active));
+ update_user(u, user_id);
+ promise.set_value(Unit());
+}
+
+void ContactsManager::on_update_active_usernames_order(vector &&usernames, Promise &&promise) {
+ auto user_id = get_my_id();
+ User *u = get_user(user_id);
+ CHECK(u != nullptr);
+ if (!u->usernames.can_reorder_to(usernames)) {
+ return reload_user(user_id, std::move(promise));
+ }
+ on_update_user_usernames(u, user_id, u->usernames.reorder_to(std::move(usernames)));
+ update_user(u, user_id);
+ promise.set_value(Unit());
+}
+
void ContactsManager::set_emoji_status(EmojiStatus emoji_status, Promise &&promise) {
if (!td_->option_manager_->get_option_boolean("is_premium")) {
return promise.set_error(Status::Error(400, "The method is available only for Telegram Premium users"));
@@ -6664,7 +7036,7 @@ void ContactsManager::set_chat_description(ChatId chat_id, const string &descrip
}
void ContactsManager::set_channel_username(ChannelId channel_id, const string &username, Promise &&promise) {
- auto c = get_channel(channel_id);
+ const auto *c = get_channel(channel_id);
if (c == nullptr) {
return promise.set_error(Status::Error(400, "Supergroup not found"));
}
@@ -6672,11 +7044,11 @@ void ContactsManager::set_channel_username(ChannelId channel_id, const string &u
return promise.set_error(Status::Error(400, "Not enough rights to change supergroup username"));
}
- if (!username.empty() && !is_valid_username(username)) {
+ if (!username.empty() && !is_allowed_username(username)) {
return promise.set_error(Status::Error(400, "Username is invalid"));
}
- if (!username.empty() && c->username.empty()) {
+ if (!username.empty() && !c->usernames.has_editable_username()) {
auto channel_full = get_channel_full(channel_id, false, "set_channel_username");
if (channel_full != nullptr && !channel_full->can_set_username) {
return promise.set_error(Status::Error(400, "Can't set supergroup username"));
@@ -6686,6 +7058,82 @@ void ContactsManager::set_channel_username(ChannelId channel_id, const string &u
td_->create_handler(std::move(promise))->send(channel_id, username);
}
+void ContactsManager::toggle_channel_username_is_active(ChannelId channel_id, string &&username, bool is_active,
+ Promise &&promise) {
+ const auto *c = get_channel(channel_id);
+ if (c == nullptr) {
+ return promise.set_error(Status::Error(400, "Supergroup not found"));
+ }
+ if (!get_channel_status(c).is_creator()) {
+ return promise.set_error(Status::Error(400, "Not enough rights to change username"));
+ }
+ if (!c->usernames.can_toggle(username)) {
+ return promise.set_error(Status::Error(400, "Wrong username specified"));
+ }
+ td_->create_handler(std::move(promise))->send(channel_id, std::move(username), is_active);
+}
+
+void ContactsManager::disable_all_channel_usernames(ChannelId channel_id, Promise &&promise) {
+ const auto *c = get_channel(channel_id);
+ if (c == nullptr) {
+ return promise.set_error(Status::Error(400, "Supergroup not found"));
+ }
+ if (!get_channel_status(c).is_creator()) {
+ return promise.set_error(Status::Error(400, "Not enough rights to disable usernames"));
+ }
+ td_->create_handler(std::move(promise))->send(channel_id);
+}
+
+void ContactsManager::reorder_channel_usernames(ChannelId channel_id, vector &&usernames,
+ Promise &&promise) {
+ const auto *c = get_channel(channel_id);
+ if (c == nullptr) {
+ return promise.set_error(Status::Error(400, "Supergroup not found"));
+ }
+ if (!get_channel_status(c).is_creator()) {
+ return promise.set_error(Status::Error(400, "Not enough rights to reorder usernames"));
+ }
+ if (!c->usernames.can_reorder_to(usernames)) {
+ return promise.set_error(Status::Error(400, "Invalid username order specified"));
+ }
+ if (usernames.size() <= 1) {
+ return promise.set_value(Unit());
+ }
+ td_->create_handler(std::move(promise))->send(channel_id, std::move(usernames));
+}
+
+void ContactsManager::on_update_channel_username_is_active(ChannelId channel_id, string &&username, bool is_active,
+ Promise &&promise) {
+ auto *c = get_channel(channel_id);
+ CHECK(c != nullptr);
+ if (!c->usernames.can_toggle(username)) {
+ return reload_channel(channel_id, std::move(promise));
+ }
+ on_update_channel_usernames(c, channel_id, c->usernames.toggle(username, is_active));
+ update_channel(c, channel_id);
+ promise.set_value(Unit());
+}
+
+void ContactsManager::on_deactivate_channel_usernames(ChannelId channel_id, Promise &&promise) {
+ auto *c = get_channel(channel_id);
+ CHECK(c != nullptr);
+ on_update_channel_usernames(c, channel_id, c->usernames.deactivate_all());
+ update_channel(c, channel_id);
+ promise.set_value(Unit());
+}
+
+void ContactsManager::on_update_channel_active_usernames_order(ChannelId channel_id, vector | |