Support reordering of active usernames.

This commit is contained in:
levlam 2022-10-14 15:32:54 +03:00
parent 897032e0fd
commit b3ab397bcd
8 changed files with 245 additions and 7 deletions

View File

@ -6199,6 +6199,9 @@ setBio bio:string = Ok;
//@description Changes the editable username of the current user @username The new value of the username. Use an empty string to remove the username. The username can't be completely removed if there is another active or disabled username //@description Changes the editable username of the current user @username The new value of the username. Use an empty string to remove the username. The username can't be completely removed if there is another active or disabled username
setUsername username:string = Ok; setUsername username:string = Ok;
//@description Changes order of active usernames of the current user @usernames The new order of active usernames. All currently active usernames must be specified
reorderActiveUsernames usernames:vector<string> = Ok;
//@description Changes the emoji status of the current user; for Telegram Premium users only //@description Changes the emoji status of the current user; for Telegram Premium users only
//@emoji_status New emoji status; pass null to switch to the default badge //@emoji_status New emoji status; pass null to switch to the default badge
//@duration Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually //@duration Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually
@ -6281,6 +6284,9 @@ disconnectAllWebsites = Ok;
//@description Changes the editable username of a supergroup or channel, requires owner privileges in the supergroup or channel @supergroup_id Identifier of the supergroup or channel @username New value of the username. Use an empty string to remove the username. The username can't be completely removed if there is another active or disabled username //@description Changes the editable username of a supergroup or channel, requires owner privileges in the supergroup or channel @supergroup_id Identifier of the supergroup or channel @username New value of the username. Use an empty string to remove the username. The username can't be completely removed if there is another active or disabled username
setSupergroupUsername supergroup_id:int53 username:string = Ok; setSupergroupUsername supergroup_id:int53 username:string = Ok;
//@description Changes order of active usernames of a supergroup or channel, requires owner privileges in the supergroup or channel @supergroup_id Identifier of the supergroup or channel @usernames The new order of active usernames. All currently active usernames must be specified
reorderSupergroupActiveUsernames supergroup_id:int53 usernames:vector<string> = Ok;
//@description Changes the sticker set of a supergroup; requires can_change_info administrator right @supergroup_id Identifier of the supergroup @sticker_set_id New value of the supergroup sticker set identifier. Use 0 to remove the supergroup sticker set //@description Changes the sticker set of a supergroup; requires can_change_info administrator right @supergroup_id Identifier of the supergroup @sticker_set_id New value of the supergroup sticker set identifier. Use 0 to remove the supergroup sticker set
setSupergroupStickerSet supergroup_id:int53 sticker_set_id:int64 = Ok; setSupergroupStickerSet supergroup_id:int53 sticker_set_id:int64 = Ok;

View File

@ -673,6 +673,43 @@ class UpdateUsernameQuery final : public Td::ResultHandler {
} }
}; };
class ReorderUsernamesQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
vector<string> usernames_;
public:
explicit ReorderUsernamesQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(vector<string> &&usernames) {
usernames_ = usernames;
send_query(G()->net_query_creator().create(telegram_api::account_reorderUsernames(std::move(usernames))));
}
void on_result(BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::account_reorderUsernames>(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 { class UpdateEmojiStatusQuery final : public Td::ResultHandler {
Promise<Unit> promise_; Promise<Unit> promise_;
@ -792,6 +829,52 @@ class UpdateChannelUsernameQuery final : public Td::ResultHandler {
} }
}; };
class ReorderChannelUsernamesQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
ChannelId channel_id_;
vector<string> usernames_;
public:
explicit ReorderChannelUsernamesQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(ChannelId channel_id, vector<string> &&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))));
}
void on_result(BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::channels_reorderUsernames>(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 { class SetChannelStickerSetQuery final : public Td::ResultHandler {
Promise<Unit> promise_; Promise<Unit> promise_;
ChannelId channel_id_; ChannelId channel_id_;
@ -6659,6 +6742,39 @@ void ContactsManager::set_username(const string &username, Promise<Unit> &&promi
td_->create_handler<UpdateUsernameQuery>(std::move(promise))->send(username); td_->create_handler<UpdateUsernameQuery>(std::move(promise))->send(username);
} }
void ContactsManager::reorder_usernames(vector<string> &&usernames, Promise<Unit> &&promise) {
get_me(PromiseCreator::lambda([actor_id = actor_id(this), usernames = std::move(usernames),
promise = std::move(promise)](Result<Unit> &&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<string> &&usernames, Promise<Unit> &&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"));
}
td_->create_handler<ReorderUsernamesQuery>(std::move(promise))->send(std::move(usernames));
}
void ContactsManager::on_update_active_usernames_order(vector<string> &&usernames, Promise<Unit> &&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<Unit> &&promise) { void ContactsManager::set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise) {
if (!td_->option_manager_->get_option_boolean("is_premium")) { 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")); return promise.set_error(Status::Error(400, "The method is available only for Telegram Premium users"));
@ -6699,7 +6815,7 @@ void ContactsManager::set_chat_description(ChatId chat_id, const string &descrip
} }
void ContactsManager::set_channel_username(ChannelId channel_id, const string &username, Promise<Unit> &&promise) { void ContactsManager::set_channel_username(ChannelId channel_id, const string &username, Promise<Unit> &&promise) {
auto c = get_channel(channel_id); const auto *c = get_channel(channel_id);
if (c == nullptr) { if (c == nullptr) {
return promise.set_error(Status::Error(400, "Supergroup not found")); return promise.set_error(Status::Error(400, "Supergroup not found"));
} }
@ -6721,6 +6837,33 @@ void ContactsManager::set_channel_username(ChannelId channel_id, const string &u
td_->create_handler<UpdateChannelUsernameQuery>(std::move(promise))->send(channel_id, username); td_->create_handler<UpdateChannelUsernameQuery>(std::move(promise))->send(channel_id, username);
} }
void ContactsManager::reorder_channel_usernames(ChannelId channel_id, vector<string> &&usernames,
Promise<Unit> &&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_reorder_to(usernames)) {
return promise.set_error(Status::Error(400, "Invalid username order specified"));
}
td_->create_handler<ReorderChannelUsernamesQuery>(std::move(promise))->send(channel_id, std::move(usernames));
}
void ContactsManager::on_update_channel_active_usernames_order(ChannelId channel_id, vector<string> &&usernames,
Promise<Unit> &&promise) {
auto *c = get_channel(channel_id);
CHECK(c != nullptr);
if (!c->usernames.can_reorder_to(usernames)) {
return reload_channel(channel_id, std::move(promise));
}
on_update_channel_usernames(c, channel_id, c->usernames.reorder_to(std::move(usernames)));
update_channel(c, channel_id);
promise.set_value(Unit());
}
void ContactsManager::set_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id, void ContactsManager::set_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
auto c = get_channel(channel_id); auto c = get_channel(channel_id);
@ -8820,8 +8963,8 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr,
} }
if (is_received || !u->is_received) { if (is_received || !u->is_received) {
on_update_user_name(u, user_id, std::move(user->first_name_), std::move(user->last_name_), on_update_user_name(u, user_id, std::move(user->first_name_), std::move(user->last_name_));
Usernames{std::move(user->username_), std::move(user->usernames_)}); on_update_user_usernames(u, user_id, Usernames{std::move(user->username_), std::move(user->usernames_)});
} }
on_update_user_emoji_status(u, user_id, EmojiStatus(std::move(user->emoji_status_))); on_update_user_emoji_status(u, user_id, EmojiStatus(std::move(user->emoji_status_)));
@ -11681,15 +11824,15 @@ void ContactsManager::on_update_user_name(UserId user_id, string &&first_name, s
User *u = get_user_force(user_id); User *u = get_user_force(user_id);
if (u != nullptr) { if (u != nullptr) {
on_update_user_name(u, user_id, std::move(first_name), std::move(last_name), std::move(usernames)); on_update_user_name(u, user_id, std::move(first_name), std::move(last_name));
on_update_user_usernames(u, user_id, std::move(usernames));
update_user(u, user_id); update_user(u, user_id);
} else { } else {
LOG(INFO) << "Ignore update user name about unknown " << user_id; LOG(INFO) << "Ignore update user name about unknown " << user_id;
} }
} }
void ContactsManager::on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name, void ContactsManager::on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name) {
Usernames &&usernames) {
if (first_name.empty() && last_name.empty()) { if (first_name.empty() && last_name.empty()) {
first_name = u->phone_number; first_name = u->phone_number;
} }
@ -11700,6 +11843,9 @@ void ContactsManager::on_update_user_name(User *u, UserId user_id, string &&firs
LOG(DEBUG) << "Name has changed for " << user_id; LOG(DEBUG) << "Name has changed for " << user_id;
u->is_changed = true; u->is_changed = true;
} }
}
void ContactsManager::on_update_user_usernames(User *u, UserId user_id, Usernames &&usernames) {
td_->messages_manager_->on_dialog_usernames_updated(DialogId(user_id), u->usernames, usernames); td_->messages_manager_->on_dialog_usernames_updated(DialogId(user_id), u->usernames, usernames);
if (u->usernames != usernames) { if (u->usernames != usernames) {
u->usernames = std::move(usernames); u->usernames = std::move(usernames);

View File

@ -284,6 +284,11 @@ class ContactsManager final : public Actor {
UserId add_channel_bot_user(); UserId add_channel_bot_user();
void on_update_active_usernames_order(vector<string> &&usernames, Promise<Unit> &&promise);
void on_update_channel_active_usernames_order(ChannelId channel_id, vector<string> &&usernames,
Promise<Unit> &&promise);
void on_update_online_status_privacy(); void on_update_online_status_privacy();
void on_update_phone_number_privacy(); void on_update_phone_number_privacy();
@ -346,12 +351,16 @@ class ContactsManager final : public Actor {
void set_username(const string &username, Promise<Unit> &&promise); void set_username(const string &username, Promise<Unit> &&promise);
void reorder_usernames(vector<string> &&usernames, Promise<Unit> &&promise);
void set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise); void set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise);
void set_chat_description(ChatId chat_id, const string &description, Promise<Unit> &&promise); void set_chat_description(ChatId chat_id, const string &description, Promise<Unit> &&promise);
void set_channel_username(ChannelId channel_id, const string &username, Promise<Unit> &&promise); void set_channel_username(ChannelId channel_id, const string &username, Promise<Unit> &&promise);
void reorder_channel_usernames(ChannelId channel_id, vector<string> &&usernames, Promise<Unit> &&promise);
void set_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id, Promise<Unit> &&promise); void set_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id, Promise<Unit> &&promise);
void toggle_channel_sign_messages(ChannelId channel_id, bool sign_messages, Promise<Unit> &&promise); void toggle_channel_sign_messages(ChannelId channel_id, bool sign_messages, Promise<Unit> &&promise);
@ -1265,7 +1274,8 @@ class ContactsManager final : public Actor {
void on_set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise); void on_set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise);
void on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name, Usernames &&usernames); void on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name);
void on_update_user_usernames(User *u, UserId user_id, Usernames &&usernames);
void on_update_user_phone_number(User *u, UserId user_id, string &&phone_number); void on_update_user_phone_number(User *u, UserId user_id, string &&phone_number);
void on_update_user_photo(User *u, UserId user_id, tl_object_ptr<telegram_api::UserProfilePhoto> &&photo, void on_update_user_photo(User *u, UserId user_id, tl_object_ptr<telegram_api::UserProfilePhoto> &&photo,
const char *source); const char *source);
@ -1347,6 +1357,8 @@ class ContactsManager final : public Actor {
static void on_update_channel_full_bot_user_ids(ChannelFull *channel_full, ChannelId channel_id, static void on_update_channel_full_bot_user_ids(ChannelFull *channel_full, ChannelId channel_id,
vector<UserId> &&bot_user_ids); vector<UserId> &&bot_user_ids);
void reorder_usernames_impl(vector<string> &&usernames, Promise<Unit> &&promise);
void on_channel_status_changed(Channel *c, ChannelId channel_id, const DialogParticipantStatus &old_status, void on_channel_status_changed(Channel *c, ChannelId channel_id, const DialogParticipantStatus &old_status,
const DialogParticipantStatus &new_status); const DialogParticipantStatus &new_status);
void on_channel_usernames_changed(const Channel *c, ChannelId channel_id, const Usernames &old_usernames, void on_channel_usernames_changed(const Channel *c, ChannelId channel_id, const Usernames &old_usernames,

View File

@ -6737,6 +6737,15 @@ void Td::on_request(uint64 id, td_api::setUsername &request) {
contacts_manager_->set_username(request.username_, std::move(promise)); contacts_manager_->set_username(request.username_, std::move(promise));
} }
void Td::on_request(uint64 id, td_api::reorderActiveUsernames &request) {
CHECK_IS_USER();
for (auto &username : request.usernames_) {
CLEAN_INPUT_STRING(username);
}
CREATE_OK_REQUEST_PROMISE();
contacts_manager_->reorder_usernames(std::move(request.usernames_), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::setEmojiStatus &request) { void Td::on_request(uint64 id, const td_api::setEmojiStatus &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
@ -6843,6 +6852,16 @@ void Td::on_request(uint64 id, td_api::setSupergroupUsername &request) {
contacts_manager_->set_channel_username(ChannelId(request.supergroup_id_), request.username_, std::move(promise)); contacts_manager_->set_channel_username(ChannelId(request.supergroup_id_), request.username_, std::move(promise));
} }
void Td::on_request(uint64 id, td_api::reorderSupergroupActiveUsernames &request) {
CHECK_IS_USER();
for (auto &username : request.usernames_) {
CLEAN_INPUT_STRING(username);
}
CREATE_OK_REQUEST_PROMISE();
contacts_manager_->reorder_channel_usernames(ChannelId(request.supergroup_id_), std::move(request.usernames_),
std::move(promise));
}
void Td::on_request(uint64 id, const td_api::setSupergroupStickerSet &request) { void Td::on_request(uint64 id, const td_api::setSupergroupStickerSet &request) {
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
contacts_manager_->set_channel_sticker_set(ChannelId(request.supergroup_id_), StickerSetId(request.sticker_set_id_), contacts_manager_->set_channel_sticker_set(ChannelId(request.supergroup_id_), StickerSetId(request.sticker_set_id_),

View File

@ -1028,6 +1028,8 @@ class Td final : public Actor {
void on_request(uint64 id, td_api::setUsername &request); void on_request(uint64 id, td_api::setUsername &request);
void on_request(uint64 id, td_api::reorderActiveUsernames &request);
void on_request(uint64 id, const td_api::setEmojiStatus &request); void on_request(uint64 id, const td_api::setEmojiStatus &request);
void on_request(uint64 id, const td_api::getThemedEmojiStatuses &request); void on_request(uint64 id, const td_api::getThemedEmojiStatuses &request);
@ -1062,6 +1064,8 @@ class Td final : public Actor {
void on_request(uint64 id, td_api::setSupergroupUsername &request); void on_request(uint64 id, td_api::setSupergroupUsername &request);
void on_request(uint64 id, td_api::reorderSupergroupActiveUsernames &request);
void on_request(uint64 id, const td_api::setSupergroupStickerSet &request); void on_request(uint64 id, const td_api::setSupergroupStickerSet &request);
void on_request(uint64 id, const td_api::toggleSupergroupSignMessages &request); void on_request(uint64 id, const td_api::toggleSupergroupSignMessages &request);

View File

@ -9,6 +9,8 @@
#include "td/telegram/misc.h" #include "td/telegram/misc.h"
#include "td/telegram/secret_api.h" #include "td/telegram/secret_api.h"
#include "td/utils/misc.h"
namespace td { namespace td {
Usernames::Usernames(string &&first_username, vector<telegram_api::object_ptr<telegram_api::username>> &&usernames) { Usernames::Usernames(string &&first_username, vector<telegram_api::object_ptr<telegram_api::username>> &&usernames) {
@ -68,6 +70,44 @@ tl_object_ptr<td_api::usernames> Usernames::get_usernames_object() const {
active_usernames_[editable_username_pos_]); active_usernames_[editable_username_pos_]);
} }
bool Usernames::can_reorder_to(const vector<string> &new_username_order) const {
if (new_username_order.size() != active_usernames_.size()) {
return false;
}
FlatHashSet<string> active_usernames;
for (auto &username : active_usernames_) {
active_usernames.insert(username);
}
for (auto &username : new_username_order) {
auto it = active_usernames.find(username);
if (it == active_usernames.end()) {
return false;
}
active_usernames.erase(it);
}
CHECK(active_usernames.empty());
return true;
}
Usernames Usernames::reorder_to(vector<string> &&new_username_order) const {
Usernames result;
if (is_empty()) {
CHECK(new_username_order.empty());
return result;
}
result.active_usernames_ = std::move(new_username_order);
result.disabled_usernames_ = disabled_usernames_;
const string &editable_username = active_usernames_[editable_username_pos_];
for (size_t i = 0; i < result.active_usernames_.size(); i++) {
if (result.active_usernames_[i] == editable_username) {
result.editable_username_pos_ = narrow_cast<int32>(i);
break;
}
}
CHECK(!is_empty());
return result;
}
void Usernames::check_utf8_validness() { void Usernames::check_utf8_validness() {
for (auto &username : active_usernames_) { for (auto &username : active_usernames_) {
if (!check_utf8(username)) { if (!check_utf8(username)) {

View File

@ -55,6 +55,10 @@ class Usernames {
return active_usernames_; return active_usernames_;
} }
bool can_reorder_to(const vector<string> &new_username_order) const;
Usernames reorder_to(vector<string> &&new_username_order) const;
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
CHECK(!is_empty()) CHECK(!is_empty())

View File

@ -4514,6 +4514,8 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::setBio>("\n" + args + "\n" + args + "\n")); send_request(td_api::make_object<td_api::setBio>("\n" + args + "\n" + args + "\n"));
} else if (op == "sun") { } else if (op == "sun") {
send_request(td_api::make_object<td_api::setUsername>(args)); send_request(td_api::make_object<td_api::setUsername>(args));
} else if (op == "raun") {
send_request(td_api::make_object<td_api::reorderActiveUsernames>(autosplit_str(args)));
} else if (op == "sese") { } else if (op == "sese") {
send_request(td_api::make_object<td_api::setEmojiStatus>(nullptr, 0)); send_request(td_api::make_object<td_api::setEmojiStatus>(nullptr, 0));
} else if (op == "ses") { } else if (op == "ses") {
@ -4540,6 +4542,11 @@ class CliClient final : public Actor {
string username; string username;
get_args(args, supergroup_id, username); get_args(args, supergroup_id, username);
send_request(td_api::make_object<td_api::setSupergroupUsername>(as_supergroup_id(supergroup_id), username)); send_request(td_api::make_object<td_api::setSupergroupUsername>(as_supergroup_id(supergroup_id), username));
} else if (op == "rsgaun" || op == "rchaun") {
string supergroup_id;
get_args(args, supergroup_id);
send_request(td_api::make_object<td_api::reorderSupergroupActiveUsernames>(as_supergroup_id(supergroup_id),
autosplit_str(args)));
} else if (op == "ssgss") { } else if (op == "ssgss") {
string supergroup_id; string supergroup_id;
int64 sticker_set_id; int64 sticker_set_id;