Add bot_commands to *Full.

This commit is contained in:
levlam 2021-06-21 04:01:13 +03:00
parent 5f9fd502b7
commit 1904aa77b1
4 changed files with 109 additions and 36 deletions

View File

@ -609,7 +609,8 @@ basicGroup id:int32 member_count:int32 status:ChatMemberStatus is_active:Bool up
//@creator_user_id User identifier of the creator of the group; 0 if unknown
//@members Group members
//@invite_link Primary invite link for this group; may be null. For chat administrators with can_invite_users right only. Updated only after the basic group is opened
basicGroupFullInfo photo:chatPhoto description:string creator_user_id:int32 members:vector<chatMember> invite_link:chatInviteLink = BasicGroupFullInfo;
//@bot_commands List of commands of bots in the group
basicGroupFullInfo photo:chatPhoto description:string creator_user_id:int32 members:vector<chatMember> invite_link:chatInviteLink bot_commands:vector<botCommands> = BasicGroupFullInfo;
//@description Represents a supergroup or channel with zero or more members (subscribers in the case of channels). From the point of view of the system, a channel is a special kind of a supergroup: only administrators can post and see the list of members, and posts from all administrators use the name and photo of the channel instead of individual names and profile photos. Unlike supergroups, channels can have an unlimited number of subscribers
@ -649,9 +650,10 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co
//@sticker_set_id Identifier of the supergroup sticker set; 0 if none
//@location Location to which the supergroup is connected; may be null
//@invite_link Primary invite link for this chat; may be null. For chat administrators with can_invite_users right only
//@bot_commands List of commands of bots in the group
//@upgraded_from_basic_group_id Identifier of the basic group from which supergroup was upgraded; 0 if none
//@upgraded_from_max_message_id Identifier of the last message in the basic group from which supergroup was upgraded; 0 if none
supergroupFullInfo photo:chatPhoto description:string member_count:int32 administrator_count:int32 restricted_count:int32 banned_count:int32 linked_chat_id:int53 slow_mode_delay:int32 slow_mode_delay_expires_in:double can_get_members:Bool can_set_username:Bool can_set_sticker_set:Bool can_set_location:Bool can_get_statistics:Bool is_all_history_available:Bool sticker_set_id:int64 location:chatLocation invite_link:chatInviteLink upgraded_from_basic_group_id:int32 upgraded_from_max_message_id:int53 = SupergroupFullInfo;
supergroupFullInfo photo:chatPhoto description:string member_count:int32 administrator_count:int32 restricted_count:int32 banned_count:int32 linked_chat_id:int53 slow_mode_delay:int32 slow_mode_delay_expires_in:double can_get_members:Bool can_set_username:Bool can_set_sticker_set:Bool can_set_location:Bool can_get_statistics:Bool is_all_history_available:Bool sticker_set_id:int64 location:chatLocation invite_link:chatInviteLink bot_commands:vector<botCommands> upgraded_from_basic_group_id:int32 upgraded_from_max_message_id:int53 = SupergroupFullInfo;
//@class SecretChatState @description Describes the current secret chat state

View File

@ -62,6 +62,10 @@ class BotCommands {
td_api::object_ptr<td_api::botCommands> get_bot_commands_object(Td *td) const;
UserId get_bot_user_id() const {
return bot_user_id_;
}
template <class StorerT>
void store(StorerT &storer) const {
td::store(bot_user_id_, storer);

View File

@ -4100,12 +4100,14 @@ void ContactsManager::ChatFull::store(StorerT &storer) const {
bool has_legacy_invite_link = false;
bool has_photo = !photo.is_empty();
bool has_invite_link = invite_link.is_valid();
bool has_bot_commands = !bot_commands.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_description);
STORE_FLAG(has_legacy_invite_link);
STORE_FLAG(can_set_username);
STORE_FLAG(has_photo);
STORE_FLAG(has_invite_link);
STORE_FLAG(has_bot_commands);
END_STORE_FLAGS();
store(version, storer);
store(creator_user_id, storer);
@ -4119,6 +4121,9 @@ void ContactsManager::ChatFull::store(StorerT &storer) const {
if (has_invite_link) {
store(invite_link, storer);
}
if (has_bot_commands) {
store(bot_commands, storer);
}
}
template <class ParserT>
@ -4128,12 +4133,14 @@ void ContactsManager::ChatFull::parse(ParserT &parser) {
bool legacy_has_invite_link;
bool has_photo;
bool has_invite_link;
bool has_bot_commands;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_description);
PARSE_FLAG(legacy_has_invite_link);
PARSE_FLAG(can_set_username);
PARSE_FLAG(has_photo);
PARSE_FLAG(has_invite_link);
PARSE_FLAG(has_bot_commands);
END_PARSE_FLAGS();
parse(version, parser);
parse(creator_user_id, parser);
@ -4151,6 +4158,9 @@ void ContactsManager::ChatFull::parse(ParserT &parser) {
if (has_invite_link) {
parse(invite_link, parser);
}
if (has_bot_commands) {
parse(bot_commands, parser);
}
}
template <class StorerT>
@ -4341,6 +4351,7 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const {
bool has_photo = !photo.is_empty();
bool legacy_has_active_group_call_id = false;
bool has_invite_link = invite_link.is_valid();
bool has_bot_commands = !bot_commands.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_description);
STORE_FLAG(has_administrator_count);
@ -4367,6 +4378,7 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const {
STORE_FLAG(can_view_statistics);
STORE_FLAG(legacy_has_active_group_call_id);
STORE_FLAG(has_invite_link);
STORE_FLAG(has_bot_commands);
END_STORE_FLAGS();
if (has_description) {
store(description, storer);
@ -4415,6 +4427,9 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const {
if (has_invite_link) {
store(invite_link, storer);
}
if (has_bot_commands) {
store(bot_commands, storer);
}
}
template <class ParserT>
@ -4438,6 +4453,7 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) {
bool has_photo;
bool legacy_has_active_group_call_id;
bool has_invite_link;
bool has_bot_commands;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_description);
PARSE_FLAG(has_administrator_count);
@ -4464,6 +4480,7 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) {
PARSE_FLAG(can_view_statistics);
PARSE_FLAG(legacy_has_active_group_call_id);
PARSE_FLAG(has_invite_link);
PARSE_FLAG(has_bot_commands);
END_PARSE_FLAGS();
if (has_description) {
parse(description, parser);
@ -4520,6 +4537,9 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) {
if (has_invite_link) {
parse(invite_link, parser);
}
if (has_bot_commands) {
parse(bot_commands, parser);
}
if (legacy_can_view_statistics) {
LOG(DEBUG) << "Ignore legacy can view statistics flag";
@ -9589,12 +9609,6 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
return;
}
for (auto &participant : chat_full->participants) {
if (participant.dialog_id.get_type() == DialogType::User) {
get_bot_info_force(participant.dialog_id.get_user_id());
}
}
Chat *c = get_chat(chat_id);
CHECK(c != nullptr);
@ -9701,10 +9715,6 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
return;
}
for (auto &user_id : channel_full->bot_user_ids) {
get_bot_info_force(user_id);
}
Channel *c = get_channel(channel_id);
CHECK(c != nullptr);
@ -10149,6 +10159,10 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool
}
}
}
td::remove_if(chat_full->bot_commands, [&bot_user_ids](const BotCommands &commands) {
return !td::contains(bot_user_ids, commands.get_bot_user_id());
});
on_update_dialog_administrators(DialogId(chat_id), std::move(administrators), chat_full->version != -1,
from_database);
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(chat_id),
@ -10194,6 +10208,13 @@ void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId c
channel_full->is_slow_mode_next_send_date_changed = false;
}
if (channel_full->need_save_to_database) {
channel_full->is_changed |= td::remove_if(
channel_full->bot_commands, [bot_user_ids = &channel_full->bot_user_ids](const BotCommands &commands) {
return !td::contains(*bot_user_ids, commands.get_bot_user_id());
});
}
channel_full->need_send_update |= channel_full->is_changed;
channel_full->need_save_to_database |= channel_full->is_changed;
channel_full->is_changed = false;
@ -10494,6 +10515,43 @@ void ContactsManager::on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> &&c
}
}
vector<BotCommands> ContactsManager::get_bot_commands(vector<tl_object_ptr<telegram_api::botInfo>> &&bot_infos,
const vector<DialogParticipant> *participants) {
vector<BotCommands> result;
for (auto &bot_info : bot_infos) {
if (bot_info->commands_.empty()) {
continue;
}
auto user_id = UserId(bot_info->user_id_);
if (!have_user_force(user_id)) {
LOG(ERROR) << "Receive unknown " << user_id;
continue;
}
if (!is_user_bot(user_id)) {
if (!is_user_deleted(user_id)) {
LOG(ERROR) << "Receive non-bot " << user_id;
}
continue;
}
if (participants != nullptr) {
bool is_participant = false;
for (auto &participant : *participants) {
if (participant.dialog_id == DialogId(user_id)) {
is_participant = true;
break;
}
}
if (!is_participant) {
LOG(ERROR) << "Skip commands of non-member bot " << user_id;
continue;
}
}
result.emplace_back(user_id, std::move(bot_info->commands_));
}
return result;
}
void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full_ptr, Promise<Unit> &&promise) {
LOG(INFO) << "Receive " << to_string(chat_full_ptr);
if (chat_full_ptr->get_id() == telegram_api::chatFull::ID) {
@ -10562,13 +10620,6 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
on_update_chat_full_invite_link(chat_full, std::move(chat->exported_invite_));
on_update_chat_full_photo(chat_full, chat_id,
get_photo(td_->file_manager_.get(), std::move(chat->chat_photo_), DialogId(chat_id)));
for (auto &bot_info : chat->bot_info_) {
if (on_update_bot_info(std::move(bot_info))) {
chat_full->need_send_update = true;
}
}
if (chat_full->description != chat->about_) {
chat_full->description = std::move(chat->about_);
chat_full->is_changed = true;
@ -10583,6 +10634,12 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
td_->messages_manager_->on_update_dialog_notify_settings(DialogId(chat_id), std::move(chat->notify_settings_),
"on_get_chat_full");
auto bot_commands = get_bot_commands(std::move(chat->bot_info_), &chat_full->participants);
if (chat_full->bot_commands != bot_commands) {
chat_full->bot_commands = std::move(bot_commands);
chat_full->is_changed = true;
}
update_chat_full(chat_full, chat_id);
} else {
CHECK(chat_full_ptr->get_id() == telegram_api::channelFull::ID);
@ -10771,17 +10828,22 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
}
vector<UserId> bot_user_ids;
for (auto &bot_info : channel->bot_info_) {
for (const auto &bot_info : channel->bot_info_) {
UserId user_id(bot_info->user_id_);
if (!is_user_bot(user_id)) {
continue;
}
bot_user_ids.push_back(user_id);
on_update_bot_info(std::move(bot_info));
}
on_update_channel_full_bot_user_ids(channel_full, channel_id, std::move(bot_user_ids));
auto bot_commands = get_bot_commands(std::move(channel->bot_info_), nullptr);
if (channel_full->bot_commands != bot_commands) {
channel_full->bot_commands = std::move(bot_commands);
channel_full->is_changed = true;
}
ChannelId linked_channel_id;
if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_LINKED_CHANNEL_ID) != 0) {
linked_channel_id = ChannelId(channel->linked_chat_id_);
@ -12038,6 +12100,7 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id,
if (channel_full != nullptr && is_user_bot(user_id) && !td::contains(channel_full->bot_user_ids, user_id)) {
channel_full->bot_user_ids.push_back(user_id);
channel_full->need_save_to_database = true;
reload_channel_full(channel_id, Promise<Unit>(), "speculative_add_channel_participants");
}
}
if (is_participants_cache_changed) {
@ -12211,6 +12274,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
if (!td::contains(channel_full->bot_user_ids, user_id)) {
channel_full->bot_user_ids.push_back(user_id);
channel_full->need_save_to_database = true;
reload_channel_full(channel_id, Promise<Unit>(), "speculative_add_channel_user");
}
} else {
if (td::remove(channel_full->bot_user_ids, user_id)) {
@ -13211,6 +13275,7 @@ void ContactsManager::drop_chat_full(ChatId chat_id) {
on_update_chat_full_photo(chat_full, chat_id, Photo());
// chat_full->creator_user_id = UserId();
chat_full->participants.clear();
chat_full->bot_commands.clear();
chat_full->version = -1;
on_update_chat_full_invite_link(chat_full, nullptr);
update_chat_online_member_count(chat_full, chat_id, true);
@ -14181,23 +14246,11 @@ bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Cha
}
if (chat_full->version != c->version) {
LOG(INFO) << "Have outdated ChatFull " << chat_id << " with current version "
<< (chat_full ? chat_full->version : -123456789) << " and chat version " << c->version;
LOG(INFO) << "Have outdated ChatFull " << chat_id << " with current version " << chat_full->version
<< " and chat version " << c->version;
return true;
}
for (const auto &participant : chat_full->participants) {
if (participant.dialog_id.get_type() == DialogType::User) {
auto user_id = participant.dialog_id.get_user_id();
auto u = get_user(user_id);
if (u != nullptr && is_bot_info_expired(user_id, u->bot_info_version)) {
LOG(INFO) << "Have outdated botInfo for " << user_id << " in " << chat_id << "; expected version "
<< u->bot_info_version;
return true;
}
}
}
if (c->is_active && c->status.can_manage_invite_links() && !chat_full->invite_link.is_valid()) {
LOG(INFO) << "Have outdated invite link in " << chat_id;
return true;
@ -16082,12 +16135,15 @@ tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_
tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_info_object(
const ChatFull *chat_full) const {
CHECK(chat_full != nullptr);
auto bot_commands = transform(chat_full->bot_commands, [td = td_](const BotCommands &commands) {
return commands.get_bot_commands_object(td);
});
return make_tl_object<td_api::basicGroupFullInfo>(
get_chat_photo_object(td_->file_manager_.get(), chat_full->photo), chat_full->description,
get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"),
transform(chat_full->participants,
[this](const DialogParticipant &chat_participant) { return get_chat_member_object(chat_participant); }),
chat_full->invite_link.get_chat_invite_link_object(this));
chat_full->invite_link.get_chat_invite_link_object(this), std::move(bot_commands));
}
td_api::object_ptr<td_api::updateSupergroup> ContactsManager::get_update_unknown_supergroup_object(
@ -16132,6 +16188,9 @@ tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_i
if (channel_full->slow_mode_next_send_date != 0) {
slow_mode_delay_expires_in = max(channel_full->slow_mode_next_send_date - G()->server_time(), 1e-3);
}
auto bot_commands = transform(channel_full->bot_commands, [td = td_](const BotCommands &commands) {
return commands.get_bot_commands_object(td);
});
return td_api::make_object<td_api::supergroupFullInfo>(
get_chat_photo_object(td_->file_manager_.get(), channel_full->photo), channel_full->description,
channel_full->participant_count, channel_full->administrator_count, channel_full->restricted_count,
@ -16140,6 +16199,7 @@ tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_i
channel_full->can_set_sticker_set, channel_full->can_set_location, channel_full->can_view_statistics,
channel_full->is_all_history_available, channel_full->sticker_set_id.get(),
channel_full->location.get_chat_location_object(), channel_full->invite_link.get_chat_invite_link_object(this),
std::move(bot_commands),
get_basic_group_id_object(channel_full->migrated_from_chat_id, "get_supergroup_full_info_object"),
channel_full->migrated_from_max_message_id.get());
}

View File

@ -763,6 +763,8 @@ class ContactsManager : public Actor {
DialogInviteLink invite_link;
vector<BotCommands> bot_commands;
bool can_set_username = false;
bool is_changed = true; // have new changes that need to be sent to the client and database
@ -842,6 +844,8 @@ class ContactsManager : public Actor {
DialogInviteLink invite_link;
vector<BotCommands> bot_commands;
uint32 speculative_version = 1;
uint32 repair_request_version = 0;
@ -1421,6 +1425,9 @@ class ContactsManager : public Actor {
void add_channel_participants(ChannelId channel_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);
vector<BotCommands> get_bot_commands(vector<tl_object_ptr<telegram_api::botInfo>> &&bot_infos,
const vector<DialogParticipant> *participants);
const DialogParticipant *get_chat_participant(ChatId chat_id, UserId user_id) const;
static const DialogParticipant *get_chat_full_participant(const ChatFull *chat_full, DialogId dialog_id);