Merge commit '6d23ea4aa90d6a9815138efb832d45ee91cb984d'

Conflicts:
	td/telegram/files/FileManager.cpp
This commit is contained in:
Andrea Cavalli 2020-10-01 11:52:14 +02:00
commit b922e14de5
17 changed files with 374 additions and 187 deletions

View File

@ -441,11 +441,13 @@ chatPermissions can_send_messages:Bool can_send_media_messages:Bool can_send_pol
//@class ChatMemberStatus @description Provides information about the status of a member in a chat
//@description The user is the owner of a chat and has all the administrator privileges
//@is_anonymous True, if the creator isn't shown in the chat member list and sends messages anonymously
//@custom_title A custom title of the owner; 0-16 characters without emojis; applicable to supergroups only
//@is_member True, if the user is a member of the chat
chatMemberStatusCreator custom_title:string is_member:Bool = ChatMemberStatus;
chatMemberStatusCreator is_anonymous:Bool custom_title:string is_member:Bool = ChatMemberStatus;
//@description The user is a member of a chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, and ban unprivileged members. In supergroups and channels, there are more detailed options for administrator privileges
//@is_anonymous True, if the administrator isn't shown in the chat member list and sends messages anonymously
//@custom_title A custom title of the administrator; 0-16 characters without emojis; applicable to supergroups only
//@can_be_edited True, if the current user can edit the administrator privileges for the called user
//@can_change_info True, if the administrator can change the chat title, photo, and other settings
@ -456,7 +458,7 @@ chatMemberStatusCreator custom_title:string is_member:Bool = ChatMemberStatus;
//@can_restrict_members True, if the administrator can restrict, ban, or unban chat members
//@can_pin_messages True, if the administrator can pin messages; applicable to groups only
//@can_promote_members True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them
chatMemberStatusAdministrator custom_title:string can_be_edited:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool = ChatMemberStatus;
chatMemberStatusAdministrator is_anonymous:Bool custom_title:string can_be_edited:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool = ChatMemberStatus;
//@description The user is a member of a chat, without any additional privileges or restrictions
chatMemberStatusMember = ChatMemberStatus;
@ -676,7 +678,9 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r
//@edit_date Point in time (Unix timestamp) when the message was last edited
//@forward_info Information about the initial message sender; may be null
//@interaction_info Information about interactions with the message; may be null
//@reply_in_chat_id If non-zero, the identifier of the chat to which the replied message belongs; Currently, only messages in the Replies chat can have different reply_in_chat_id and chat_id
//@reply_to_message_id If non-zero, the identifier of the message this message is replying to; can be the identifier of a deleted message
//@message_thread_id If non-zero, the identifier of the message thread the message belongs to
//@ttl For self-destructing messages, the message's TTL (Time To Live), in seconds; 0 if none. TDLib will send updateDeleteMessages or updateMessageContent once the TTL expires
//@ttl_expires_in Time left before the message expires, in seconds
//@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent
@ -685,7 +689,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r
//@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted
//@content Content of the message
//@reply_markup Reply markup for the message; may be null
message id:int53 sender_user_id:int32 sender_chat_id:int53 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool can_get_replies:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_to_message_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message;
message id:int53 sender_user_id:int32 sender_chat_id:int53 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool can_get_replies:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_in_chat_id:int53 reply_to_message_id:int53 message_thread_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message;
//@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null
messages total_count:int32 messages:vector<message> = Messages;
@ -2537,7 +2541,7 @@ notificationTypeNewSecretChat = NotificationType;
notificationTypeNewCall call_id:int32 = NotificationType;
//@description New message was received through a push notification
//@message_id The message identifier. The message will not be available in the chat history, but the ID can be used in viewMessages and as reply_to_message_id
//@message_id The message identifier. The message will not be available in the chat history, but the ID can be used in viewMessages, or as reply_to_message_id
//@sender_user_id Sender of the message; 0 if unknown. Corresponding user may be inaccessible
//@sender_chat_id Sender chat of the message; 0 if none
//@sender_name Name of the sender; can be different from the name of the sender user

Binary file not shown.

View File

@ -3545,7 +3545,7 @@ void ContactsManager::Chat::parse(ParserT &parser) {
} else if (left) {
status = DialogParticipantStatus::Left();
} else if (is_creator) {
status = DialogParticipantStatus::Creator(true, string());
status = DialogParticipantStatus::Creator(true, false, string());
} else if (is_administrator && !everyone_is_administrator) {
status = DialogParticipantStatus::GroupAdministrator(false);
} else {
@ -3724,7 +3724,7 @@ void ContactsManager::Channel::parse(ParserT &parser) {
} else if (left) {
status = DialogParticipantStatus::Left();
} else if (is_creator) {
status = DialogParticipantStatus::Creator(true, string());
status = DialogParticipantStatus::Creator(true, false, string());
} else if (can_edit || can_moderate) {
status = DialogParticipantStatus::ChannelAdministrator(false, is_megagroup);
} else {
@ -4161,6 +4161,14 @@ bool ContactsManager::have_input_peer_channel(const Channel *c, ChannelId channe
if (dialog_access_by_invite_link_.count(DialogId(channel_id))) {
return true;
}
} else {
if (!from_linked && c->is_megagroup) {
auto linked_channel_id = get_linked_channel_id(channel_id);
if (linked_channel_id.is_valid()) {
return !c->username.empty() || c->has_location ||
have_input_peer_channel(get_channel(linked_channel_id), linked_channel_id, AccessRights::Read, true);
}
}
}
if (!c->status.is_member()) {
return false;
@ -6398,9 +6406,9 @@ void ContactsManager::change_channel_participant_status_impl(ChannelId channel_i
return promise.set_error(Status::Error(3, "Can't remove chat owner"));
}
if (status.is_member() == old_status.is_member()) {
// change rank
// change rank and is_anonymous
if (user_id != get_my_id()) {
return promise.set_error(Status::Error(3, "Not enough rights to change chat owner custom title"));
return promise.set_error(Status::Error(3, "Not enough rights to change chat owner rights"));
}
auto input_user = get_input_user(user_id);
@ -8762,7 +8770,7 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
Dependencies dependencies;
dependencies.channel_ids.insert(channel_id);
MessagesManager::add_dialog_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
add_dialog_and_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
dependencies.chat_ids.insert(channel_full->migrated_from_chat_id);
dependencies.user_ids.insert(channel_full->bot_user_ids.begin(), channel_full->bot_user_ids.end());
resolve_dependencies_force(td_, dependencies);
@ -10505,7 +10513,7 @@ void ContactsManager::on_get_chat_participants(tl_object_ptr<telegram_api::ChatP
auto participant = move_tl_object_as<telegram_api::chatParticipantCreator>(participant_ptr);
new_creator_user_id = UserId(participant->user_id_);
dialog_participant = {new_creator_user_id, new_creator_user_id, c->date,
DialogParticipantStatus::Creator(true, string())};
DialogParticipantStatus::Creator(true, false, string())};
break;
}
case telegram_api::chatParticipantAdmin::ID: {
@ -11569,7 +11577,7 @@ void ContactsManager::on_update_chat_add_user(ChatId chat_id, UserId inviter_use
}
chat_full->participants.push_back(DialogParticipant{user_id, inviter_user_id, date,
user_id == chat_full->creator_user_id
? DialogParticipantStatus::Creator(true, string())
? DialogParticipantStatus::Creator(true, false, string())
: DialogParticipantStatus::Member()});
update_chat_online_member_count(chat_full, chat_id, false);
chat_full->is_changed = true;
@ -13037,6 +13045,14 @@ bool ContactsManager::get_channel_has_linked_channel(const Channel *c) {
return c->has_linked_channel;
}
ChannelId ContactsManager::get_channel_linked_channel_id(ChannelId channel_id) {
auto channel_full = get_channel_full_force(channel_id, "get_channel_linked_channel_id");
if (channel_full == nullptr) {
return ChannelId();
}
return channel_full->linked_channel_id;
}
int32 ContactsManager::get_channel_slow_mode_delay(ChannelId channel_id) {
auto channel_full = get_channel_full_force(channel_id, "get_channel_slow_mode_delay");
if (channel_full == nullptr) {
@ -13732,7 +13748,7 @@ void ContactsManager::on_chat_update(telegram_api::chat &chat, const char *sourc
}
if (is_creator) {
return DialogParticipantStatus::Creator(!has_left, string());
return DialogParticipantStatus::Creator(!has_left, false, string());
} else if (chat.admin_rights_ != nullptr) {
return get_dialog_participant_status(false, std::move(chat.admin_rights_), string());
} else if (was_kicked) {
@ -13893,7 +13909,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
bool is_creator = (channel.flags_ & CHANNEL_FLAG_USER_IS_CREATOR) != 0;
if (is_creator) {
return DialogParticipantStatus::Creator(!has_left, string());
return DialogParticipantStatus::Creator(!has_left, false, string());
} else if (channel.admin_rights_ != nullptr) {
return get_dialog_participant_status(false, std::move(channel.admin_rights_), string());
} else if (channel.banned_rights_ != nullptr) {

View File

@ -498,6 +498,7 @@ class ContactsManager : public Actor {
int32 get_channel_participant_count(ChannelId channel_id) const;
bool get_channel_sign_messages(ChannelId channel_id) const;
bool get_channel_has_linked_channel(ChannelId channel_id) const;
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
int32 get_channel_slow_mode_delay(ChannelId channel_id);
std::pair<int32, vector<UserId>> search_among_users(const vector<UserId> &user_ids, const string &query, int32 limit);

View File

@ -15,6 +15,33 @@
namespace td {
void add_dialog_and_dependencies(Dependencies &dependencies, DialogId dialog_id) {
if (dialog_id.is_valid() && dependencies.dialog_ids.insert(dialog_id).second) {
add_dialog_dependencies(dependencies, dialog_id);
}
}
void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id) {
switch (dialog_id.get_type()) {
case DialogType::User:
dependencies.user_ids.insert(dialog_id.get_user_id());
break;
case DialogType::Chat:
dependencies.chat_ids.insert(dialog_id.get_chat_id());
break;
case DialogType::Channel:
dependencies.channel_ids.insert(dialog_id.get_channel_id());
break;
case DialogType::SecretChat:
dependencies.secret_chat_ids.insert(dialog_id.get_secret_chat_id());
break;
case DialogType::None:
break;
default:
UNREACHABLE();
}
}
void resolve_dependencies_force(Td *td, const Dependencies &dependencies) {
for (auto user_id : dependencies.user_ids) {
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {

View File

@ -28,6 +28,10 @@ struct Dependencies {
std::unordered_set<WebPageId, WebPageIdHash> web_page_ids;
};
void add_dialog_and_dependencies(Dependencies &dependencies, DialogId dialog_id);
void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
void resolve_dependencies_force(Td *td, const Dependencies &dependencies);
} // namespace td

View File

@ -27,17 +27,18 @@ int32 DialogParticipantStatus::fix_until_date(int32 date) {
return date;
}
DialogParticipantStatus DialogParticipantStatus::Creator(bool is_member, string rank) {
DialogParticipantStatus DialogParticipantStatus::Creator(bool is_member, bool is_anonymous, string rank) {
return DialogParticipantStatus(Type::Creator,
ALL_ADMINISTRATOR_RIGHTS | ALL_PERMISSION_RIGHTS | (is_member ? IS_MEMBER : 0), 0,
std::move(rank));
ALL_ADMINISTRATOR_RIGHTS | ALL_PERMISSION_RIGHTS | (is_member ? IS_MEMBER : 0) |
(is_anonymous ? IS_ANONYMOUS : 0),
0, std::move(rank));
}
DialogParticipantStatus DialogParticipantStatus::Administrator(string rank, bool can_be_edited, bool can_change_info,
bool can_post_messages, bool can_edit_messages,
bool can_delete_messages, bool can_invite_users,
bool can_restrict_members, bool can_pin_messages,
bool can_promote_members) {
DialogParticipantStatus DialogParticipantStatus::Administrator(bool is_anonymous, string rank, bool can_be_edited,
bool can_change_info, bool can_post_messages,
bool can_edit_messages, bool can_delete_messages,
bool can_invite_users, bool can_restrict_members,
bool can_pin_messages, bool can_promote_members) {
uint32 flags = (static_cast<uint32>(can_be_edited) * CAN_BE_EDITED) |
(static_cast<uint32>(can_change_info) * CAN_CHANGE_INFO_AND_SETTINGS_ADMIN) |
(static_cast<uint32>(can_post_messages) * CAN_POST_MESSAGES) |
@ -50,7 +51,9 @@ DialogParticipantStatus DialogParticipantStatus::Administrator(string rank, bool
if (flags == 0 || flags == CAN_BE_EDITED) {
return Member();
}
return DialogParticipantStatus(Type::Administrator, IS_MEMBER | ALL_RESTRICTED_RIGHTS | flags, 0, std::move(rank));
return DialogParticipantStatus(Type::Administrator,
IS_MEMBER | ALL_RESTRICTED_RIGHTS | flags | (is_anonymous ? IS_ANONYMOUS : 0), 0,
std::move(rank));
}
DialogParticipantStatus DialogParticipantStatus::Member() {
@ -88,14 +91,14 @@ DialogParticipantStatus DialogParticipantStatus::Banned(int32 banned_until_date)
}
DialogParticipantStatus DialogParticipantStatus::GroupAdministrator(bool is_creator) {
return Administrator(string(), is_creator, true, false, false, true, true, true, true, false);
return Administrator(false, string(), is_creator, true, false, false, true, true, true, true, false);
}
DialogParticipantStatus DialogParticipantStatus::ChannelAdministrator(bool is_creator, bool is_megagroup) {
if (is_megagroup) {
return Administrator(string(), is_creator, true, false, false, true, true, true, true, false);
return Administrator(false, string(), is_creator, true, false, false, true, true, true, true, false);
} else {
return Administrator(string(), is_creator, false, true, true, true, false, true, false, false);
return Administrator(false, string(), is_creator, false, true, true, true, false, true, false, false);
}
}
@ -108,11 +111,12 @@ RestrictedRights DialogParticipantStatus::get_restricted_rights() const {
tl_object_ptr<td_api::ChatMemberStatus> DialogParticipantStatus::get_chat_member_status_object() const {
switch (type_) {
case Type::Creator:
return td_api::make_object<td_api::chatMemberStatusCreator>(rank_, is_member());
return td_api::make_object<td_api::chatMemberStatusCreator>(is_anonymous(), rank_, is_member());
case Type::Administrator:
return td_api::make_object<td_api::chatMemberStatusAdministrator>(
rank_, can_be_edited(), can_change_info_and_settings(), can_post_messages(), can_edit_messages(),
can_delete_messages(), can_invite_users(), can_restrict_members(), can_pin_messages(), can_promote_members());
is_anonymous(), rank_, can_be_edited(), can_change_info_and_settings(), can_post_messages(),
can_edit_messages(), can_delete_messages(), can_invite_users(), can_restrict_members(), can_pin_messages(),
can_promote_members());
case Type::Member:
return td_api::make_object<td_api::chatMemberStatusMember>();
case Type::Restricted:
@ -154,6 +158,9 @@ tl_object_ptr<telegram_api::chatAdminRights> DialogParticipantStatus::get_chat_a
if (can_promote_members()) {
flags |= telegram_api::chatAdminRights::ADD_ADMINS_MASK;
}
if (is_anonymous()) {
flags |= telegram_api::chatAdminRights::ANONYMOUS_MASK;
}
LOG(INFO) << "Create chat admin rights " << flags;
return make_tl_object<telegram_api::chatAdminRights>(flags, false /*ignored*/, false /*ignored*/, false /*ignored*/,
@ -278,6 +285,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant
if (!status.rank_.empty()) {
string_builder << " [" << status.rank_ << "]";
}
if (status.is_anonymous()) {
string_builder << "-anonymous";
}
return string_builder;
case DialogParticipantStatus::Type::Administrator:
string_builder << "Administrator: ";
@ -308,6 +318,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant
if (!status.rank_.empty()) {
string_builder << " [" << status.rank_ << "]";
}
if (status.is_anonymous()) {
string_builder << "-anonymous";
}
return string_builder;
case DialogParticipantStatus::Type::Member:
return string_builder << "Member";
@ -377,14 +390,14 @@ DialogParticipantStatus get_dialog_participant_status(const tl_object_ptr<td_api
switch (constructor_id) {
case td_api::chatMemberStatusCreator::ID: {
auto st = static_cast<const td_api::chatMemberStatusCreator *>(status.get());
return DialogParticipantStatus::Creator(st->is_member_, st->custom_title_);
return DialogParticipantStatus::Creator(st->is_member_, st->is_anonymous_, st->custom_title_);
}
case td_api::chatMemberStatusAdministrator::ID: {
auto st = static_cast<const td_api::chatMemberStatusAdministrator *>(status.get());
return DialogParticipantStatus::Administrator(
st->custom_title_, st->can_be_edited_, st->can_change_info_, st->can_post_messages_, st->can_edit_messages_,
st->can_delete_messages_, st->can_invite_users_, st->can_restrict_members_, st->can_pin_messages_,
st->can_promote_members_);
st->is_anonymous_, st->custom_title_, st->can_be_edited_, st->can_change_info_, st->can_post_messages_,
st->can_edit_messages_, st->can_delete_messages_, st->can_invite_users_, st->can_restrict_members_,
st->can_pin_messages_, st->can_promote_members_);
}
case td_api::chatMemberStatusMember::ID:
return DialogParticipantStatus::Member();
@ -425,9 +438,10 @@ DialogParticipantStatus get_dialog_participant_status(bool can_be_edited,
bool can_restrict_members = (admin_rights->flags_ & telegram_api::chatAdminRights::BAN_USERS_MASK) != 0;
bool can_pin_messages = (admin_rights->flags_ & telegram_api::chatAdminRights::PIN_MESSAGES_MASK) != 0;
bool can_promote_members = (admin_rights->flags_ & telegram_api::chatAdminRights::ADD_ADMINS_MASK) != 0;
return DialogParticipantStatus::Administrator(std::move(rank), can_be_edited, can_change_info, can_post_messages,
can_edit_messages, can_delete_messages, can_invite_users,
can_restrict_members, can_pin_messages, can_promote_members);
bool is_anonymous = (admin_rights->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
return DialogParticipantStatus::Administrator(
is_anonymous, std::move(rank), can_be_edited, can_change_info, can_post_messages, can_edit_messages,
can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members);
}
DialogParticipantStatus get_dialog_participant_status(
@ -635,8 +649,9 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticip
}
case telegram_api::channelParticipantCreator::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantCreator>(participant_ptr);
bool is_anonymous = (participant->admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
*this = {UserId(participant->user_id_), UserId(), 0,
DialogParticipantStatus::Creator(true, std::move(participant->rank_))};
DialogParticipantStatus::Creator(true, is_anonymous, std::move(participant->rank_))};
break;
}
case telegram_api::channelParticipantAdmin::ID: {

View File

@ -135,6 +135,7 @@ class DialogParticipantStatus {
static constexpr uint32 IS_MEMBER = 1 << 27;
static constexpr uint32 IS_ANONYMOUS = 1 << 13;
static constexpr uint32 HAS_RANK = 1u << 14;
// bits 28-30 reserved for Type
static constexpr int TYPE_SHIFT = 28;
@ -165,9 +166,9 @@ class DialogParticipantStatus {
DialogParticipantStatus(Type type, uint32 flags, int32 until_date, string rank);
public:
static DialogParticipantStatus Creator(bool is_member, string rank);
static DialogParticipantStatus Creator(bool is_member, bool is_anonymous, string rank);
static DialogParticipantStatus Administrator(string rank, bool can_be_edited, bool can_change_info,
static DialogParticipantStatus Administrator(bool is_anonymous, string rank, bool can_be_edited, bool can_change_info,
bool can_post_messages, bool can_edit_messages, bool can_delete_messages,
bool can_invite_users, bool can_restrict_members, bool can_pin_messages,
bool can_promote_members);
@ -308,6 +309,10 @@ class DialogParticipantStatus {
return until_date_;
}
bool is_anonymous() const {
return (flags_ & IS_ANONYMOUS) != 0;
}
const string &get_rank() const {
return rank_;
}

View File

@ -4209,6 +4209,8 @@ void MessagesManager::Message::store(StorerT &storer) const {
bool has_forward_count = forward_count > 0;
bool has_reply_info = !reply_info.is_empty();
bool has_sender_dialog_id = sender_dialog_id.is_valid();
bool has_reply_in_dialog_id = is_reply && reply_in_dialog_id.is_valid();
bool has_top_reply_message_id = is_reply && top_reply_message_id.is_valid();
BEGIN_STORE_FLAGS();
STORE_FLAG(is_channel_post);
STORE_FLAG(is_outgoing);
@ -4260,6 +4262,8 @@ void MessagesManager::Message::store(StorerT &storer) const {
STORE_FLAG(has_forward_count);
STORE_FLAG(has_reply_info);
STORE_FLAG(has_sender_dialog_id);
STORE_FLAG(has_reply_in_dialog_id);
STORE_FLAG(has_top_reply_message_id);
END_STORE_FLAGS();
}
@ -4347,6 +4351,12 @@ void MessagesManager::Message::store(StorerT &storer) const {
if (has_sender_dialog_id) {
store(sender_dialog_id, storer);
}
if (has_reply_in_dialog_id) {
store(reply_in_dialog_id, storer);
}
if (has_top_reply_message_id) {
store(top_reply_message_id, storer);
}
store_message_content(content.get(), storer);
if (has_reply_markup) {
store(reply_markup, storer);
@ -4383,6 +4393,8 @@ void MessagesManager::Message::parse(ParserT &parser) {
bool has_forward_count = false;
bool has_reply_info = false;
bool has_sender_dialog_id = false;
bool has_reply_in_dialog_id = false;
bool has_top_reply_message_id = false;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_channel_post);
PARSE_FLAG(is_outgoing);
@ -4434,6 +4446,8 @@ void MessagesManager::Message::parse(ParserT &parser) {
PARSE_FLAG(has_forward_count);
PARSE_FLAG(has_reply_info);
PARSE_FLAG(has_sender_dialog_id);
PARSE_FLAG(has_reply_in_dialog_id);
PARSE_FLAG(has_top_reply_message_id);
END_PARSE_FLAGS();
}
@ -4527,6 +4541,12 @@ void MessagesManager::Message::parse(ParserT &parser) {
if (has_sender_dialog_id) {
parse(sender_dialog_id, parser);
}
if (has_reply_in_dialog_id) {
parse(reply_in_dialog_id, parser);
}
if (has_top_reply_message_id) {
parse(top_reply_message_id, parser);
}
parse_message_content(content, parser);
if (has_reply_markup) {
parse(reply_markup, parser);
@ -6136,9 +6156,38 @@ void MessagesManager::update_message_interaction_info(FullMessageId full_message
}
}
bool MessagesManager::is_active_message_reply_info(DialogId dialog_id, const MessageReplyInfo &info) const {
if (info.is_empty()) {
return false;
}
if (dialog_id.get_type() != DialogType::Channel) {
return false;
}
if (!info.is_comment) {
return true;
}
if (!is_broadcast_channel(dialog_id)) {
return true;
}
auto channel_id = dialog_id.get_channel_id();
if (!td_->contacts_manager_->get_channel_has_linked_channel(channel_id)) {
return false;
}
auto linked_channel_id = td_->contacts_manager_->get_channel_linked_channel_id(channel_id);
if (!linked_channel_id.is_valid()) {
// keep the comment button while linked channel is unknown
td_->contacts_manager_->get_channel_full(channel_id, true, Auto());
return true;
}
return linked_channel_id == info.channel_id;
}
td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_interaction_info_object(
DialogId dialog_id, const Message *m) const {
if (m->view_count == 0 && m->forward_count == 0 && m->reply_info.is_empty()) {
bool is_active_reply_info = is_active_message_reply_info(dialog_id, m->reply_info);
if (m->view_count == 0 && m->forward_count == 0 && !is_active_reply_info) {
return nullptr;
}
if (m->message_id.is_scheduled() && (m->forward_info == nullptr || is_broadcast_channel(dialog_id))) {
@ -6148,14 +6197,19 @@ td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_
return nullptr;
}
int32 reply_count = -1;
vector<UserId> recent_replier_user_ids;
if (is_active_reply_info) {
reply_count = m->reply_info.reply_count;
for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) {
if (dialog_id.get_type() == DialogType::User) {
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
}
}
}
return td_api::make_object<td_api::messageInteractionInfo>(
m->view_count, m->forward_count, m->reply_info.reply_count,
m->view_count, m->forward_count, reply_count,
td_->contacts_manager_->get_user_ids_object(recent_replier_user_ids, "get_message_interaction_info_object"));
}
@ -11036,6 +11090,8 @@ void MessagesManager::on_message_ttl_expired_impl(Dialog *d, Message *m) {
update_message_contains_unread_mention(d, m, false, "on_message_ttl_expired_impl");
m->contains_mention = false;
m->reply_to_message_id = MessageId();
m->reply_in_dialog_id = DialogId();
m->top_reply_message_id = MessageId();
m->is_content_secret = false;
}
@ -12011,8 +12067,10 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message(
auto message = move_tl_object_as<telegram_api::message>(message_ptr);
message_info.dialog_id = DialogId(message->peer_id_);
if (message->flags_ & MESSAGE_FLAG_HAS_FROM_ID) {
if (message->from_id_ != nullptr) {
message_info.sender_dialog_id = DialogId(message->from_id_);
} else {
message_info.sender_dialog_id = message_info.dialog_id;
}
message_info.date = message->date_;
message_info.forward_header = std::move(message->fwd_from_);
@ -12064,8 +12122,10 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message(
auto message = move_tl_object_as<telegram_api::messageService>(message_ptr);
message_info.dialog_id = DialogId(message->peer_id_);
if (message->flags_ & MESSAGE_FLAG_HAS_FROM_ID) {
if (message->from_id_ != nullptr) {
message_info.sender_dialog_id = DialogId(message->from_id_);
} else {
message_info.sender_dialog_id = message_info.dialog_id;
}
message_info.date = message->date_;
message_info.flags = message->flags_;
@ -12170,6 +12230,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
MessageId reply_to_message_id = message_info.reply_to_message_id;
DialogId reply_in_dialog_id;
MessageId top_reply_message_id;
if (message_info.reply_header != nullptr) {
reply_to_message_id = MessageId(ServerMessageId(message_info.reply_header->reply_to_msg_id_));
auto reply_to_peer_id = std::move(message_info.reply_header->reply_to_peer_id_);
@ -12178,23 +12239,19 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
if (!reply_in_dialog_id.is_valid()) {
LOG(ERROR) << " Receive reply in invalid " << to_string(reply_to_peer_id);
reply_to_message_id = MessageId();
reply_in_dialog_id = DialogId();
}
}
if (reply_to_message_id.is_valid()) {
if ((message_info.reply_header->flags_ & telegram_api::messageReplyHeader::REPLY_TO_TOP_ID_MASK) != 0) {
top_reply_message_id = MessageId(ServerMessageId(message_info.reply_header->reply_to_top_id_));
} else if (message_info.reply_info != nullptr && !is_broadcast_channel(dialog_id)) {
top_reply_message_id = reply_to_message_id;
}
}
}
CHECK(!reply_to_message_id.is_scheduled());
if (reply_to_message_id != MessageId()) {
if (!reply_to_message_id.is_valid()) {
LOG(ERROR) << "Receive reply to " << reply_to_message_id << " for " << message_id << " in " << dialog_id;
reply_to_message_id = MessageId();
} else {
if (!message_id.is_scheduled() && !reply_in_dialog_id.is_valid() && reply_to_message_id >= message_id) {
if (reply_to_message_id.get() - message_id.get() <= MessageId(ServerMessageId(2000000000)).get()) {
LOG(ERROR) << "Receive reply to wrong " << reply_to_message_id << " in " << message_id;
}
reply_to_message_id = MessageId();
}
}
}
fix_server_reply_to_message_id(dialog_id, message_id, reply_in_dialog_id, reply_to_message_id);
fix_server_reply_to_message_id(dialog_id, message_id, reply_in_dialog_id, top_reply_message_id);
UserId via_bot_user_id = message_info.via_bot_user_id;
if (!via_bot_user_id.is_valid()) {
@ -12256,6 +12313,8 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
message->random_id = message_info.random_id;
message->forward_info = get_message_forward_info(std::move(message_info.forward_header));
message->reply_to_message_id = reply_to_message_id;
message->reply_in_dialog_id = reply_in_dialog_id;
message->top_reply_message_id = top_reply_message_id;
message->via_bot_user_id = via_bot_user_id;
message->restriction_reasons = std::move(message_info.restriction_reasons);
message->author_signature = std::move(message_info.author_signature);
@ -12278,7 +12337,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
message->legacy_layer = (is_legacy ? MTPROTO_LAYER : 0);
message->content = std::move(message_info.content);
message->reply_markup = get_reply_markup(std::move(message_info.reply_markup), td_->auth_manager_->is_bot(), false,
message->contains_mention || dialog_id.get_type() == DialogType::User);
message->contains_mention || dialog_type == DialogType::User);
if (content_type == MessageContentType::ExpiredPhoto || content_type == MessageContentType::ExpiredVideo) {
CHECK(message->ttl == 0); // ttl is ignored/set to 0 if the message has already been expired
@ -12289,6 +12348,8 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
message->reply_markup = nullptr;
}
message->reply_to_message_id = MessageId();
message->reply_in_dialog_id = DialogId();
message->top_reply_message_id = MessageId();
}
if (message_info.media_album_id != 0) {
@ -15228,13 +15289,16 @@ MessagesManager::Message *MessagesManager::get_message_force(FullMessageId full_
return get_message_force(d, full_message_id.get_message_id(), source);
}
MessageId MessagesManager::get_replied_message_id(const Message *m) {
FullMessageId MessagesManager::get_replied_message_id(DialogId dialog_id, const Message *m) {
auto message_id = get_message_content_replied_message_id(m->content.get());
if (message_id.is_valid()) {
CHECK(!m->reply_to_message_id.is_valid());
return message_id;
return {dialog_id, message_id};
}
return m->reply_to_message_id;
if (!m->reply_to_message_id.is_valid()) {
return {};
}
return {m->reply_in_dialog_id.is_valid() ? m->reply_in_dialog_id : dialog_id, m->reply_to_message_id};
}
void MessagesManager::get_message_force_from_server(Dialog *d, MessageId message_id, Promise<Unit> &&promise,
@ -15288,13 +15352,13 @@ void MessagesManager::get_message(FullMessageId full_message_id, Promise<Unit> &
get_message_force_from_server(d, full_message_id.get_message_id(), std::move(promise));
}
MessageId MessagesManager::get_replied_message(DialogId dialog_id, MessageId message_id, bool force,
FullMessageId MessagesManager::get_replied_message(DialogId dialog_id, MessageId message_id, bool force,
Promise<Unit> &&promise) {
LOG(INFO) << "Get replied message to " << message_id << " in " << dialog_id;
Dialog *d = get_dialog_force(dialog_id);
if (d == nullptr) {
promise.set_error(Status::Error(6, "Chat not found"));
return MessageId();
return FullMessageId();
}
auto m = get_message_force(d, message_id, "get_replied_message");
@ -15304,15 +15368,22 @@ MessageId MessagesManager::get_replied_message(DialogId dialog_id, MessageId mes
} else {
get_message_force_from_server(d, message_id, std::move(promise));
}
return MessageId();
return FullMessageId();
}
tl_object_ptr<telegram_api::InputMessage> input_message;
if (m->message_id.is_valid() && m->message_id.is_server()) {
input_message = make_tl_object<telegram_api::inputMessageReplyTo>(m->message_id.get_server_message_id().get());
}
auto replied_message_id = get_replied_message_id(m);
get_message_force_from_server(d, replied_message_id, std::move(promise), std::move(input_message));
auto replied_message_id = get_replied_message_id(dialog_id, m);
if (replied_message_id.get_dialog_id() != dialog_id) {
d = get_dialog_force(replied_message_id.get_dialog_id());
if (d == nullptr) {
promise.set_error(Status::Error(6, "Chat with replied message not found"));
return FullMessageId();
}
}
get_message_force_from_server(d, replied_message_id.get_message_id(), std::move(promise), std::move(input_message));
return replied_message_id;
}
@ -20356,7 +20427,9 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
bool can_get_replies = for_event_log || is_scheduled ? false : !m->reply_info.is_empty() && m->message_id.is_server();
auto via_bot_user_id = td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id");
auto media_album_id = for_event_log ? static_cast<int64>(0) : m->media_album_id;
auto reply_in_dialog_id = m->reply_in_dialog_id.is_valid() ? m->reply_in_dialog_id : dialog_id;
auto reply_to_message_id = for_event_log ? static_cast<int64>(0) : m->reply_to_message_id.get();
auto top_reply_message_id = for_event_log || is_scheduled ? static_cast<int64>(0) : m->top_reply_message_id.get();
bool contains_unread_mention = for_event_log ? false : m->contains_unread_mention;
auto live_location_date = m->is_failed_to_send ? 0 : m->date;
auto date = is_scheduled ? 0 : m->date;
@ -20367,8 +20440,8 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
can_be_edited, can_be_forwarded, can_delete_for_self, can_delete_for_all_users, can_get_statistics,
can_get_replies, m->is_channel_post, contains_unread_mention, date, edit_date,
get_message_forward_info_object(m->forward_info), get_message_interaction_info_object(dialog_id, m),
reply_to_message_id, ttl, ttl_expires_in, via_bot_user_id, m->author_signature, media_album_id,
get_restriction_reason_description(m->restriction_reasons),
reply_in_dialog_id.get(), reply_to_message_id, top_reply_message_id, ttl, ttl_expires_in, via_bot_user_id,
m->author_signature, media_album_id, get_restriction_reason_description(m->restriction_reasons),
get_message_content_object(m->content.get(), td_, live_location_date, m->is_content_secret),
get_reply_markup_object(m->reply_markup));
}
@ -20764,6 +20837,26 @@ MessageId MessagesManager::get_reply_to_message_id(Dialog *d, MessageId message_
return m->message_id;
}
void MessagesManager::fix_server_reply_to_message_id(DialogId dialog_id, MessageId message_id,
DialogId reply_in_dialog_id, MessageId &reply_to_message_id) {
CHECK(!reply_to_message_id.is_scheduled());
if (!reply_to_message_id.is_valid()) {
if (reply_to_message_id != MessageId()) {
LOG(ERROR) << "Receive reply to " << reply_to_message_id << " for " << message_id << " in " << dialog_id;
reply_to_message_id = MessageId();
}
return;
}
if (!message_id.is_scheduled() && !reply_in_dialog_id.is_valid() && reply_to_message_id >= message_id) {
if (reply_to_message_id.get() - message_id.get() <= MessageId(ServerMessageId(2000000000)).get() ||
dialog_id.get_type() == DialogType::Channel) {
LOG(ERROR) << "Receive reply to wrong " << reply_to_message_id << " in " << message_id << " in " << dialog_id;
}
reply_to_message_id = MessageId();
}
}
vector<FileId> MessagesManager::get_message_file_ids(const Message *m) const {
CHECK(m != nullptr);
return get_message_content_file_ids(m->content.get(), td_);
@ -20885,20 +20978,14 @@ bool MessagesManager::is_message_auto_read(DialogId dialog_id, bool is_outgoing)
void MessagesManager::add_message_dependencies(Dependencies &dependencies, DialogId dialog_id, const Message *m) {
dependencies.user_ids.insert(m->sender_user_id);
if (m->sender_dialog_id.is_valid() && dependencies.dialog_ids.insert(m->sender_dialog_id).second) {
add_dialog_dependencies(dependencies, m->sender_dialog_id);
}
add_dialog_and_dependencies(dependencies, m->sender_dialog_id);
add_dialog_and_dependencies(dependencies, m->reply_in_dialog_id);
add_dialog_and_dependencies(dependencies, m->real_forward_from_dialog_id);
dependencies.user_ids.insert(m->via_bot_user_id);
if (m->forward_info != nullptr) {
dependencies.user_ids.insert(m->forward_info->sender_user_id);
if (m->forward_info->sender_dialog_id.is_valid() &&
dependencies.dialog_ids.insert(m->forward_info->sender_dialog_id).second) {
add_dialog_dependencies(dependencies, m->forward_info->sender_dialog_id);
}
if (m->forward_info->from_dialog_id.is_valid() &&
dependencies.dialog_ids.insert(m->forward_info->from_dialog_id).second) {
add_dialog_dependencies(dependencies, m->forward_info->from_dialog_id);
}
add_dialog_and_dependencies(dependencies, m->forward_info->sender_dialog_id);
add_dialog_and_dependencies(dependencies, m->forward_info->from_dialog_id);
}
for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) {
if (dialog_id.get_type() == DialogType::User) {
@ -20908,27 +20995,6 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, Dialo
add_message_content_dependencies(dependencies, m->content.get());
}
void MessagesManager::add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id) {
switch (dialog_id.get_type()) {
case DialogType::User:
dependencies.user_ids.insert(dialog_id.get_user_id());
break;
case DialogType::Chat:
dependencies.chat_ids.insert(dialog_id.get_chat_id());
break;
case DialogType::Channel:
dependencies.channel_ids.insert(dialog_id.get_channel_id());
break;
case DialogType::SecretChat:
dependencies.secret_chat_ids.insert(dialog_id.get_secret_chat_id());
break;
case DialogType::None:
break;
default:
UNREACHABLE();
}
}
class MessagesManager::SendMessageLogEvent {
public:
DialogId dialog_id;
@ -23150,7 +23216,7 @@ unique_ptr<MessagesManager::MessageForwardInfo> MessagesManager::get_message_for
DialogId from_dialog_id;
MessageId from_message_id;
string sender_name;
if ((flags & telegram_api::messageFwdHeader::FROM_ID_MASK) != 0) {
if (forward_header->from_id_ != nullptr) {
sender_dialog_id = DialogId(forward_header->from_id_);
if (!sender_dialog_id.is_valid()) {
LOG(ERROR) << "Receive invalid sender id in message forward header: " << oneline(to_string(forward_header));
@ -28883,7 +28949,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
}
if (d->deleted_message_ids.count(message->reply_to_message_id)) {
// LOG(INFO) << "Remove reply to deleted " << message->reply_to_message_id << " in " << message_id << " from " << dialog_id << " from " << source;
// we don't want to lose information that the message was a reply for now
// we don't want to lose information that the message was a reply
// message->reply_to_message_id = MessageId();
}
@ -30133,7 +30199,30 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr
<< old_message->reply_to_message_id << " to " << new_message->reply_to_message_id
<< ", message content type is " << old_message->content->get_type() << '/'
<< new_message->content->get_type();
dump_debug_message_op(d);
}
}
if (old_message->reply_in_dialog_id != new_message->reply_in_dialog_id) {
if (new_message->reply_in_dialog_id == DialogId() || replace_legacy) {
LOG(DEBUG) << "Drop message reply_in_dialog_id";
old_message->reply_in_dialog_id = DialogId();
need_send_update = true;
} else if (is_new_available && old_message->reply_in_dialog_id.is_valid()) {
LOG(ERROR) << message_id << " in " << dialog_id << " has changed dialog it is reply in from "
<< old_message->reply_in_dialog_id << " to " << new_message->reply_in_dialog_id
<< ", message content type is " << old_message->content->get_type() << '/'
<< new_message->content->get_type();
}
}
if (old_message->top_reply_message_id != new_message->top_reply_message_id) {
if (new_message->top_reply_message_id == MessageId()) {
LOG(DEBUG) << "Drop message top_reply_message_id";
old_message->reply_to_message_id = MessageId();
need_send_update = true;
} else if (is_new_available && old_message->top_reply_message_id.is_valid()) {
LOG(ERROR) << message_id << " in " << dialog_id << " has changed top message it is reply to from "
<< old_message->top_reply_message_id << " to " << new_message->top_reply_message_id
<< ", message content type is " << old_message->content->get_type() << '/'
<< new_message->content->get_type();
}
}
if (old_message->via_bot_user_id != new_message->via_bot_user_id) {
@ -30857,29 +30946,21 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
if (last_database_message != nullptr) {
int32 dependent_dialog_count = 0;
auto depend_on_dialog = [&](DialogId other_dialog_id) {
if (other_dialog_id.is_valid() && !have_dialog(other_dialog_id)) {
LOG(INFO) << "Postpone adding of last message in " << dialog_id << " because of cyclic dependency with "
<< other_dialog_id;
pending_add_dialog_last_database_message_dependent_dialogs_[other_dialog_id].push_back(dialog_id);
dependent_dialog_count++;
}
};
if (last_database_message->forward_info != nullptr) {
auto other_dialog_id = last_database_message->forward_info->sender_dialog_id;
if (other_dialog_id.is_valid() && !have_dialog(other_dialog_id)) {
LOG(INFO) << "Postpone adding of last message in " << dialog_id << " because of cyclic dependency with "
<< other_dialog_id;
pending_add_dialog_last_database_message_dependent_dialogs_[other_dialog_id].push_back(dialog_id);
dependent_dialog_count++;
}
other_dialog_id = last_database_message->forward_info->from_dialog_id;
if (other_dialog_id.is_valid() && !have_dialog(other_dialog_id)) {
LOG(INFO) << "Postpone adding of last message in " << dialog_id << " because of cyclic dependency with "
<< other_dialog_id;
pending_add_dialog_last_database_message_dependent_dialogs_[other_dialog_id].push_back(dialog_id);
dependent_dialog_count++;
}
other_dialog_id = last_database_message->sender_dialog_id;
if (other_dialog_id.is_valid() && !have_dialog(other_dialog_id)) {
LOG(INFO) << "Postpone adding of last message in " << dialog_id << " because of cyclic dependency with "
<< other_dialog_id;
pending_add_dialog_last_database_message_dependent_dialogs_[other_dialog_id].push_back(dialog_id);
dependent_dialog_count++;
}
depend_on_dialog(last_database_message->forward_info->sender_dialog_id);
depend_on_dialog(last_database_message->forward_info->from_dialog_id);
}
depend_on_dialog(last_database_message->sender_dialog_id);
depend_on_dialog(last_database_message->reply_in_dialog_id);
depend_on_dialog(last_database_message->real_forward_from_dialog_id);
if (dependent_dialog_count == 0) {
add_dialog_last_database_message(d, std::move(last_database_message));

View File

@ -549,7 +549,7 @@ class MessagesManager : public Actor {
void get_message(FullMessageId full_message_id, Promise<Unit> &&promise);
MessageId get_replied_message(DialogId dialog_id, MessageId message_id, bool force, Promise<Unit> &&promise);
FullMessageId get_replied_message(DialogId dialog_id, MessageId message_id, bool force, Promise<Unit> &&promise);
MessageId get_dialog_pinned_message(DialogId dialog_id, Promise<Unit> &&promise);
@ -885,8 +885,6 @@ class MessagesManager : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
static void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
ActorOwn<MultiSequenceDispatcher> sequence_dispatcher_;
private:
@ -990,6 +988,8 @@ class MessagesManager : public Actor {
MessageId reply_to_message_id;
int64 reply_to_random_id = 0; // for send_message
DialogId reply_in_dialog_id;
MessageId top_reply_message_id;
UserId via_bot_user_id;
@ -1716,10 +1716,13 @@ class MessagesManager : public Actor {
MessageId get_persistent_message_id(const Dialog *d, MessageId message_id) const;
static MessageId get_replied_message_id(const Message *m);
static FullMessageId get_replied_message_id(DialogId dialog_id, const Message *m);
MessageId get_reply_to_message_id(Dialog *d, MessageId message_id);
static void fix_server_reply_to_message_id(DialogId dialog_id, MessageId message_id, DialogId reply_in_dialog_id,
MessageId &reply_to_message_id);
bool can_set_game_score(DialogId dialog_id, const Message *m) const;
bool check_update_dialog_id(const tl_object_ptr<telegram_api::Update> &update, DialogId dialog_id);
@ -1855,6 +1858,8 @@ class MessagesManager : public Actor {
void update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count,
bool has_reply_info, tl_object_ptr<telegram_api::messageReplies> &&reply_info);
bool is_active_message_reply_info(DialogId dialog_id, const MessageReplyInfo &info) const;
td_api::object_ptr<td_api::messageInteractionInfo> get_message_interaction_info_object(DialogId dialog_id,
const Message *m) const;

View File

@ -1652,7 +1652,7 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
auto dialog_id = log_event.full_message_id_.get_dialog_id();
Dependencies dependencies;
MessagesManager::add_dialog_dependencies(dependencies, dialog_id);
add_dialog_dependencies(dependencies, dialog_id); // do not load the dialog itself
resolve_dependencies_force(td_, dependencies);
do_set_poll_answer(log_event.poll_id_, log_event.full_message_id_, std::move(log_event.options_), event.id_,
@ -1671,7 +1671,7 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
auto dialog_id = log_event.full_message_id_.get_dialog_id();
Dependencies dependencies;
MessagesManager::add_dialog_dependencies(dependencies, dialog_id);
add_dialog_dependencies(dependencies, dialog_id); // do not load the dialog itself
resolve_dependencies_force(td_, dependencies);
do_stop_poll(log_event.poll_id_, log_event.full_message_id_, nullptr, event.id_, Auto());

View File

@ -1032,7 +1032,7 @@ class GetRepliedMessageRequest : public RequestOnceActor {
DialogId dialog_id_;
MessageId message_id_;
MessageId replied_message_id_;
FullMessageId replied_message_id_;
void do_run(Promise<Unit> &&promise) override {
replied_message_id_ =
@ -1040,7 +1040,7 @@ class GetRepliedMessageRequest : public RequestOnceActor {
}
void do_send_result() override {
send_result(td->messages_manager_->get_message_object({dialog_id_, replied_message_id_}));
send_result(td->messages_manager_->get_message_object(replied_message_id_));
}
public:
@ -3778,7 +3778,9 @@ void Td::inc_actor_refcnt() {
void Td::dec_actor_refcnt() {
actor_refcnt_--;
if (actor_refcnt_ < 3) {
LOG(DEBUG) << "Decrease reference count to " << actor_refcnt_;
}
if (actor_refcnt_ == 0) {
if (close_flag_ == 2) {
create_reference();
@ -6100,7 +6102,8 @@ void Td::on_request(uint64 id, const td_api::leaveChat &request) {
return promise.set_value(Unit());
}
new_status = td_api::make_object<td_api::chatMemberStatusCreator>(status.get_rank(), false);
new_status =
td_api::make_object<td_api::chatMemberStatusCreator>(status.is_anonymous(), status.get_rank(), false);
}
}
messages_manager_->set_dialog_participant_status(dialog_id, contacts_manager_->get_my_id(), std::move(new_status),

View File

@ -352,7 +352,12 @@ bool UpdatesManager::is_acceptable_channel(ChannelId channel_id) const {
return td_->contacts_manager_->have_channel_force(channel_id);
}
bool UpdatesManager::is_acceptable_dialog(DialogId dialog_id) const {
bool UpdatesManager::is_acceptable_peer(const tl_object_ptr<telegram_api::Peer> &peer) const {
if (peer == nullptr) {
return true;
}
DialogId dialog_id(peer);
switch (dialog_id.get_type()) {
case DialogType::User:
if (!is_acceptable_user(dialog_id.get_user_id())) {
@ -393,25 +398,30 @@ bool UpdatesManager::is_acceptable_message_entities(
return true;
}
bool UpdatesManager::is_acceptable_message_reply_header(
const telegram_api::object_ptr<telegram_api::messageReplyHeader> &header) const {
if (header == nullptr) {
return true;
}
if (is_acceptable_peer(header->reply_to_peer_id_)) {
return false;
}
return true;
}
bool UpdatesManager::is_acceptable_message_forward_header(
const telegram_api::object_ptr<telegram_api::messageFwdHeader> &header) const {
if (header == nullptr) {
return true;
}
auto flags = header->flags_;
if (flags & telegram_api::messageFwdHeader::FROM_ID_MASK) {
DialogId dialog_id(header->from_id_);
if (!is_acceptable_dialog(dialog_id)) {
if (!is_acceptable_peer(header->from_id_)) {
return false;
}
}
if (flags & telegram_api::messageFwdHeader::SAVED_FROM_PEER_MASK) {
DialogId dialog_id(header->saved_from_peer_);
if (!is_acceptable_dialog(dialog_id)) {
if (!is_acceptable_peer(header->saved_from_peer_)) {
return false;
}
}
return true;
}
@ -425,15 +435,16 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
case telegram_api::message::ID: {
auto message = static_cast<const telegram_api::message *>(message_ptr);
if (!is_acceptable_dialog(DialogId(message->peer_id_))) {
if (!is_acceptable_peer(message->peer_id_)) {
return false;
}
if (message->flags_ & MessagesManager::MESSAGE_FLAG_HAS_FROM_ID) {
if (!is_acceptable_dialog(DialogId(message->from_id_))) {
if (!is_acceptable_peer(message->from_id_)) {
return false;
}
}
if (!is_acceptable_message_reply_header(message->reply_to_)) {
return false;
}
if (!is_acceptable_message_forward_header(message->fwd_from_)) {
return false;
}
@ -501,10 +512,10 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
}
/*
// the users are always min, so no need to check
// the dialogs are always min, so no need to check
if (message->replies_ != nullptr) {
for (auto &user_id : message->replies_->recent_repliers_) {
if (!is_acceptable_user(UserId(user_id))) {
for (auto &peer : message->replies_->recent_repliers_) {
if (!is_acceptable_peer(peer)) {
return false;
}
}
@ -516,14 +527,12 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
case telegram_api::messageService::ID: {
auto message = static_cast<const telegram_api::messageService *>(message_ptr);
if (!is_acceptable_dialog(DialogId(message->peer_id_))) {
if (!is_acceptable_peer(message->peer_id_)) {
return false;
}
if (message->flags_ & MessagesManager::MESSAGE_FLAG_HAS_FROM_ID) {
if (!is_acceptable_dialog(DialogId(message->from_id_))) {
if (!is_acceptable_peer(message->from_id_)) {
return false;
}
}
const telegram_api::MessageAction *action = message->action_.get();
CHECK(action != nullptr);
@ -692,16 +701,13 @@ void UpdatesManager::on_get_updates(tl_object_ptr<telegram_api::Updates> &&updat
auto from_id = update->flags_ & MessagesManager::MESSAGE_FLAG_IS_OUT ? td_->contacts_manager_->get_my_id().get()
: update->user_id_;
auto peer_id = update->flags_ & MessagesManager::MESSAGE_FLAG_IS_OUT ? update->user_id_
: td_->contacts_manager_->get_my_id().get();
update->flags_ |= MessagesManager::MESSAGE_FLAG_HAS_FROM_ID;
on_pending_update(make_tl_object<telegram_api::updateNewMessage>(
make_tl_object<telegram_api::message>(
update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, update->id_, make_tl_object<telegram_api::peerUser>(from_id),
make_tl_object<telegram_api::peerUser>(peer_id), std::move(update->fwd_from_),
make_tl_object<telegram_api::peerUser>(update->user_id_), std::move(update->fwd_from_),
update->via_bot_id_, std::move(update->reply_to_), update->date_, update->message_,
nullptr, nullptr, std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()),
update->pts_, update->pts_count_),

View File

@ -186,10 +186,13 @@ class UpdatesManager : public Actor {
bool is_acceptable_channel(ChannelId channel_id) const;
bool is_acceptable_dialog(DialogId dialog_id) const;
bool is_acceptable_peer(const tl_object_ptr<telegram_api::Peer> &peer) const;
bool is_acceptable_message_entities(const vector<tl_object_ptr<telegram_api::MessageEntity>> &message_entities) const;
bool is_acceptable_message_reply_header(
const telegram_api::object_ptr<telegram_api::messageReplyHeader> &header) const;
bool is_acceptable_message_forward_header(
const telegram_api::object_ptr<telegram_api::messageFwdHeader> &header) const;

View File

@ -510,6 +510,10 @@ class CliClient final : public Actor {
return transform(full_split(trim(message_ids), get_delimiter(message_ids)), as_message_id);
}
static int64 as_message_thread_id(Slice str) {
return as_message_id(str);
}
static int32 as_button_id(Slice str) {
return to_integer<int32>(trim(str));
}
@ -1865,6 +1869,12 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::getChatHistory>(get_history_chat_id_, std::numeric_limits<int64>::max(),
0, 100, false));
} else if (op == "replies") {
string chat_id;
string message_thread_id;
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", 0, 0, 0, 100, nullptr,
as_message_thread_id(message_thread_id)));
} else if (op == "spvf") {
search_chat_id_ = as_chat_id(args);
@ -3722,21 +3732,26 @@ class CliClient final : public Actor {
} else if (status_str == "banned") {
status = td_api::make_object<td_api::chatMemberStatusBanned>(std::numeric_limits<int32>::max());
} else if (status_str == "creator") {
status = td_api::make_object<td_api::chatMemberStatusCreator>("", true);
status = td_api::make_object<td_api::chatMemberStatusCreator>(false, "", true);
} else if (status_str == "creatoranon") {
status = td_api::make_object<td_api::chatMemberStatusCreator>(true, "", true);
} else if (status_str == "uncreator") {
status = td_api::make_object<td_api::chatMemberStatusCreator>("", false);
status = td_api::make_object<td_api::chatMemberStatusCreator>(false, "", false);
} else if (status_str == "anon") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>(true, "anon", true, true, true, true, true,
true, true, true, true);
} else if (status_str == "admin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, true, true, true, true,
true, true, true);
status = td_api::make_object<td_api::chatMemberStatusAdministrator>(false, "", true, true, true, true, true,
true, true, true, true);
} else if (status_str == "adminq") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("title", true, true, true, true, true, true,
true, true, true);
status = td_api::make_object<td_api::chatMemberStatusAdministrator>(false, "title", true, true, true, true,
true, true, true, true, true);
} else if (status_str == "minadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, false, false, false, false,
false, false, false);
status = td_api::make_object<td_api::chatMemberStatusAdministrator>(false, "", true, true, false, false, false,
false, false, false, false);
} else if (status_str == "unadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, false, false, false, false, false,
false, false, false);
status = td_api::make_object<td_api::chatMemberStatusAdministrator>(false, "", true, false, false, false, false,
false, false, false, false);
} else if (status_str == "rest") {
status = td_api::make_object<td_api::chatMemberStatusRestricted>(
true, static_cast<int32>(120 + std::time(nullptr)),

View File

@ -1698,7 +1698,7 @@ Result<FileId> FileManager::merge_internal(FileId x_file_id, FileId y_file_id, b
file_nodes_.erase(node_ids[other_node_i]);
run_generate(node);
run_download(node);
run_download(node, false);
run_upload(node, {});
if (other_pmc_id.is_valid()) {
@ -2238,12 +2238,12 @@ void FileManager::download(FileId file_id, std::shared_ptr<DownloadCallback> cal
// TODO: send current progress?
run_generate(node);
run_download(node);
run_download(node, true);
try_flush_node(node, "download");
}
void FileManager::run_download(FileNodePtr node) {
void FileManager::run_download(FileNodePtr node, bool force_update_priority) {
int8 priority = 0;
for (auto id : node->file_ids_) {
auto *info = get_file_id_info(id);
@ -2286,7 +2286,9 @@ void FileManager::run_download(FileNodePtr node) {
if (old_priority != 0) {
LOG(INFO) << "Update download offset and limits of file " << node->main_file_id_;
CHECK(node->download_id_ != 0);
if (force_update_priority || priority != old_priority) {
send_closure(file_load_manager_, &FileLoadManager::update_priority, node->download_id_, priority);
}
if (need_update_limit || need_update_offset) {
auto download_offset = node->download_offset_;
auto download_limit = node->download_limit_;
@ -3719,7 +3721,7 @@ void FileManager::on_error_impl(FileNodePtr node, Query::Type type, bool was_act
if ((status.message() == "FILE_ID_INVALID" || status.message() == "LOCATION_INVALID") &&
FileView(node).may_reload_photo()) {
node->need_reload_photo_ = true;
run_download(node);
run_download(node, true);
return;
}
@ -3739,7 +3741,7 @@ void FileManager::on_error_impl(FileNodePtr node, Query::Type type, bool was_act
}
CHECK(!node->file_ids_.empty());
delete_file_reference_internal(node->file_ids_.back(), file_reference);
run_download(node);
run_download(node, true);
return;
}
@ -3753,16 +3755,16 @@ void FileManager::on_error_impl(FileNodePtr node, Query::Type type, bool was_act
if (begins_with(status.message(), "FILE_DOWNLOAD_RESTART")) {
if (ends_with(status.message(), "WITH_FILE_REFERENCE")) {
node->download_was_update_file_reference_ = true;
run_download(node);
run_download(node, true);
return;
} else if (ends_with(status.message(), "INCREASE_PART_SIZE")) {
if (try_fix_partial_local_location(node)) {
run_download(node);
run_download(node, true);
return;
}
} else {
node->can_search_locally_ = false;
run_download(node);
run_download(node, true);
return;
}
}

View File

@ -659,7 +659,7 @@ class FileManager : public FileLoadManager::Callback {
void do_cancel_upload(FileNodePtr node);
void do_cancel_generate(FileNodePtr node);
void run_upload(FileNodePtr node, std::vector<int> bad_parts);
void run_download(FileNodePtr node);
void run_download(FileNodePtr node, bool force_update_priority);
void run_generate(FileNodePtr node);
void on_start_download(QueryId query_id) override;