Merge remote-tracking branch 'tdlib/master'

This commit is contained in:
Andrea Cavalli 2021-04-13 16:11:57 +02:00
commit ee7ffd085f
5 changed files with 168 additions and 138 deletions

View File

@ -2789,6 +2789,7 @@ class GetChatsQuery : public Td::ResultHandler {
class GetFullChatQuery : public Td::ResultHandler { class GetFullChatQuery : public Td::ResultHandler {
Promise<Unit> promise_; Promise<Unit> promise_;
ChatId chat_id_;
public: public:
explicit GetFullChatQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) { explicit GetFullChatQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
@ -2812,6 +2813,7 @@ class GetFullChatQuery : public Td::ResultHandler {
} }
void on_error(uint64 id, Status status) override { void on_error(uint64 id, Status status) override {
td->contacts_manager_->on_get_chat_full_failed(chat_id_);
promise_.set_error(std::move(status)); promise_.set_error(std::move(status));
} }
}; };
@ -2896,6 +2898,7 @@ class GetFullChannelQuery : public Td::ResultHandler {
void on_error(uint64 id, Status status) override { void on_error(uint64 id, Status status) override {
td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetFullChannelQuery"); td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetFullChannelQuery");
td->contacts_manager_->on_get_channel_full_failed(channel_id_);
promise_.set_error(std::move(status)); promise_.set_error(std::move(status));
} }
}; };
@ -4744,10 +4747,9 @@ string ContactsManager::get_secret_chat_title(SecretChatId secret_chat_id) const
RestrictedRights ContactsManager::get_user_default_permissions(UserId user_id) const { RestrictedRights ContactsManager::get_user_default_permissions(UserId user_id) const {
auto u = get_user(user_id); auto u = get_user(user_id);
if (u == nullptr) { if (u == nullptr || user_id == get_replies_bot_user_id()) {
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false); return RestrictedRights(false, false, false, false, false, false, false, false, false, false, u != nullptr);
} }
return RestrictedRights(true, true, true, true, true, true, true, true, false, false, true); return RestrictedRights(true, true, true, true, true, true, true, true, false, false, true);
} }
@ -6787,6 +6789,7 @@ void ContactsManager::add_channel_participant(ChannelId channel_id, UserId user_
return promise.set_error(Status::Error(3, "Can't return to kicked from chat")); return promise.set_error(Status::Error(3, "Can't return to kicked from chat"));
} }
speculative_add_channel_user(channel_id, user_id, DialogParticipantStatus::Member(), c->status);
td_->create_handler<JoinChannelQuery>(std::move(promise))->send(channel_id); td_->create_handler<JoinChannelQuery>(std::move(promise))->send(channel_id);
return; return;
} }
@ -7406,6 +7409,7 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, UserId
} }
// leave the channel // leave the channel
speculative_add_channel_user(channel_id, user_id, status, c->status);
td_->create_handler<LeaveChannelQuery>(std::move(promise))->send(channel_id); td_->create_handler<LeaveChannelQuery>(std::move(promise))->send(channel_id);
return; return;
} }
@ -9236,7 +9240,7 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
Dependencies dependencies; Dependencies dependencies;
dependencies.user_ids.insert(user_id); dependencies.user_ids.insert(user_id);
if (!resolve_dependencies_force(td_, dependencies, "user_full")) { if (!resolve_dependencies_force(td_, dependencies, "on_load_user_full_from_database")) {
users_full_.erase(user_id); users_full_.erase(user_id);
G()->td_db()->get_sqlite_pmc()->erase(get_user_full_database_key(user_id), Auto()); G()->td_db()->get_sqlite_pmc()->erase(get_user_full_database_key(user_id), Auto());
return; return;
@ -9427,7 +9431,7 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
dependencies.user_ids.insert(participant.inviter_user_id); dependencies.user_ids.insert(participant.inviter_user_id);
} }
dependencies.user_ids.insert(chat_full->invite_link.get_creator_user_id()); dependencies.user_ids.insert(chat_full->invite_link.get_creator_user_id());
if (!resolve_dependencies_force(td_, dependencies, "chat_full")) { if (!resolve_dependencies_force(td_, dependencies, "on_load_chat_full_from_database")) {
chats_full_.erase(chat_id); chats_full_.erase(chat_id);
G()->td_db()->get_sqlite_pmc()->erase(get_chat_full_database_key(chat_id), Auto()); G()->td_db()->get_sqlite_pmc()->erase(get_chat_full_database_key(chat_id), Auto());
return; return;
@ -9508,8 +9512,9 @@ string ContactsManager::get_channel_full_database_value(const ChannelFull *chann
return log_event_store(*channel_full).as_slice().str(); return log_event_store(*channel_full).as_slice().str();
} }
void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, string value) { void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, string value, const char *source) {
LOG(INFO) << "Successfully loaded full " << channel_id << " of size " << value.size() << " from database"; LOG(INFO) << "Successfully loaded full " << channel_id << " of size " << value.size() << " from database from "
<< source;
// G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto()); // G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto());
// return; // return;
@ -9535,7 +9540,7 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
dependencies.chat_ids.insert(channel_full->migrated_from_chat_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()); dependencies.user_ids.insert(channel_full->bot_user_ids.begin(), channel_full->bot_user_ids.end());
dependencies.user_ids.insert(channel_full->invite_link.get_creator_user_id()); dependencies.user_ids.insert(channel_full->invite_link.get_creator_user_id());
if (!resolve_dependencies_force(td_, dependencies, "channel_full")) { if (!resolve_dependencies_force(td_, dependencies, source)) {
channels_full_.erase(channel_id); channels_full_.erase(channel_id);
G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto()); G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto());
return; return;
@ -9579,6 +9584,10 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
if (channel_full->participant_count < channel_full->administrator_count) { if (channel_full->participant_count < channel_full->administrator_count) {
channel_full->participant_count = channel_full->administrator_count; channel_full->participant_count = channel_full->administrator_count;
channel_full->expires_at = 0.0; channel_full->expires_at = 0.0;
c->participant_count = channel_full->participant_count;
c->is_changed = true;
update_channel(c, channel_id);
} }
} }
@ -9612,7 +9621,7 @@ ContactsManager::ChannelFull *ContactsManager::get_channel_full_force(ChannelId
LOG(INFO) << "Trying to load full " << channel_id << " from database from " << source; LOG(INFO) << "Trying to load full " << channel_id << " from database from " << source;
on_load_channel_full_from_database( on_load_channel_full_from_database(
channel_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_full_database_key(channel_id))); channel_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_full_database_key(channel_id)), source);
return get_channel_full(channel_id, source); return get_channel_full(channel_id, source);
} }
@ -10681,6 +10690,26 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
promise.set_value(Unit()); promise.set_value(Unit());
} }
void ContactsManager::on_get_chat_full_failed(ChatId chat_id) {
if (G()->close_flag()) {
return;
}
LOG(INFO) << "Failed to get " << chat_id;
}
void ContactsManager::on_get_channel_full_failed(ChannelId channel_id) {
if (G()->close_flag()) {
return;
}
LOG(INFO) << "Failed to get " << channel_id;
auto channel_full = get_channel_full(channel_id, "on_get_channel_full");
if (channel_full != nullptr) {
channel_full->repair_request_version = 0;
}
}
bool ContactsManager::is_update_about_username_change_received(UserId user_id) const { bool ContactsManager::is_update_about_username_change_received(UserId user_id) const {
const User *u = get_user(user_id); const User *u = get_user(user_id);
if (u != nullptr) { if (u != nullptr) {
@ -11831,8 +11860,18 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
DialogParticipantStatus new_status, DialogParticipantStatus new_status,
DialogParticipantStatus old_status) { DialogParticipantStatus old_status) {
auto c = get_channel_force(channel_id); auto c = get_channel_force(channel_id);
// channel full must be loaded before c->participant_count is updated, because on_load_channel_full_from_database
// must copy the initial c->participant_count before it is speculatibely updated
auto channel_full = get_channel_full_force(channel_id, "speculative_add_channel_user");
int32 min_count = 0;
if (channel_full != nullptr) {
channel_full->is_changed |= speculative_add_count(channel_full->administrator_count,
new_status.is_administrator() - old_status.is_administrator());
min_count = channel_full->administrator_count;
}
if (c != nullptr && c->participant_count != 0 && if (c != nullptr && c->participant_count != 0 &&
speculative_add_count(c->participant_count, new_status.is_member() - old_status.is_member())) { speculative_add_count(c->participant_count, new_status.is_member() - old_status.is_member(), min_count)) {
c->is_changed = true; c->is_changed = true;
update_channel(c, channel_id); update_channel(c, channel_id);
} }
@ -11895,16 +11934,12 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
} }
} }
auto channel_full = get_channel_full_force(channel_id, "speculative_add_channel_user");
if (channel_full == nullptr) { if (channel_full == nullptr) {
return; return;
} }
channel_full->is_changed |= speculative_add_count(channel_full->administrator_count, channel_full->is_changed |= speculative_add_count(channel_full->participant_count,
new_status.is_administrator() - old_status.is_administrator()); new_status.is_member() - old_status.is_member(), min_count);
channel_full->is_changed |=
speculative_add_count(channel_full->participant_count, new_status.is_member() - old_status.is_member(),
channel_full->administrator_count);
channel_full->is_changed |= channel_full->is_changed |=
speculative_add_count(channel_full->restricted_count, new_status.is_restricted() - old_status.is_restricted()); speculative_add_count(channel_full->restricted_count, new_status.is_restricted() - old_status.is_restricted());
channel_full->is_changed |= channel_full->is_changed |=
@ -12976,6 +13011,10 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
if (old_status.is_member() != new_status.is_member() || new_status.is_banned()) { if (old_status.is_member() != new_status.is_member() || new_status.is_banned()) {
remove_dialog_access_by_invite_link(DialogId(channel_id)); remove_dialog_access_by_invite_link(DialogId(channel_id));
if (new_status.is_member()) {
reload_channel_full(channel_id, Promise<Unit>(), "on_channel_status_changed");
}
} }
if (need_reload_group_call) { if (need_reload_group_call) {
send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights, send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights,
@ -14406,7 +14445,8 @@ void ContactsManager::add_dialog_participant(DialogId dialog_id, UserId user_id,
case DialogType::Chat: case DialogType::Chat:
return add_chat_participant(dialog_id.get_chat_id(), user_id, forward_limit, std::move(promise)); return add_chat_participant(dialog_id.get_chat_id(), user_id, forward_limit, std::move(promise));
case DialogType::Channel: case DialogType::Channel:
return add_channel_participant(dialog_id.get_channel_id(), user_id, std::move(promise)); return add_channel_participant(dialog_id.get_channel_id(), user_id, std::move(promise),
DialogParticipantStatus::Left());
case DialogType::SecretChat: case DialogType::SecretChat:
return promise.set_error(Status::Error(3, "Can't add members to a secret chat")); return promise.set_error(Status::Error(3, "Can't add members to a secret chat"));
case DialogType::None: case DialogType::None:

View File

@ -181,6 +181,8 @@ class ContactsManager : public Actor {
void on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> &&chats, const char *source); void on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> &&chats, const char *source);
void on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full, Promise<Unit> &&promise); void on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full, Promise<Unit> &&promise);
void on_get_chat_full_failed(ChatId chat_id);
void on_get_channel_full_failed(ChannelId channel_id);
void on_update_profile_success(int32 flags, const string &first_name, const string &last_name, const string &about); void on_update_profile_success(int32 flags, const string &first_name, const string &last_name, const string &about);
void on_set_bot_commands_success(vector<std::pair<string, string>> &&commands); void on_set_bot_commands_success(vector<std::pair<string, string>> &&commands);
@ -1336,7 +1338,7 @@ class ContactsManager : public Actor {
void save_channel_full(const ChannelFull *channel_full, ChannelId channel_id); void save_channel_full(const ChannelFull *channel_full, ChannelId channel_id);
static string get_channel_full_database_key(ChannelId channel_id); static string get_channel_full_database_key(ChannelId channel_id);
static string get_channel_full_database_value(const ChannelFull *channel_full); static string get_channel_full_database_value(const ChannelFull *channel_full);
void on_load_channel_full_from_database(ChannelId channel_id, string value); void on_load_channel_full_from_database(ChannelId channel_id, string value, const char *source);
void update_user(User *u, UserId user_id, bool from_binlog = false, bool from_database = false); void update_user(User *u, UserId user_id, bool from_binlog = false, bool from_database = false);
void update_chat(Chat *c, ChatId chat_id, bool from_binlog = false, bool from_database = false); void update_chat(Chat *c, ChatId chat_id, bool from_binlog = false, bool from_database = false);
@ -1413,7 +1415,7 @@ class ContactsManager : public Actor {
void add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise); void add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
void add_channel_participant(ChannelId channel_id, UserId user_id, Promise<Unit> &&promise, void add_channel_participant(ChannelId channel_id, UserId user_id, Promise<Unit> &&promise,
DialogParticipantStatus old_status = DialogParticipantStatus::Left()); DialogParticipantStatus old_status);
void add_channel_participants(ChannelId channel_id, const vector<UserId> &user_ids, Promise<Unit> &&promise); void add_channel_participants(ChannelId channel_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);

View File

@ -3306,7 +3306,9 @@ void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_
} }
group_call->is_being_left = false; group_call->is_being_left = false;
group_call->is_speaking = false; group_call->is_speaking = false;
if (!group_call->is_active) {
group_call->can_be_managed = false; group_call->can_be_managed = false;
}
group_call->joined_date = 0; group_call->joined_date = 0;
group_call->audio_source = 0; group_call->audio_source = 0;
check_group_call_is_joined_timeout_.cancel_timeout(group_call->group_call_id.get()); check_group_call_is_joined_timeout_.cancel_timeout(group_call->group_call_id.get());

View File

@ -12048,8 +12048,7 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
if (d->message_notification_group.group_id.is_valid()) { if (d->message_notification_group.group_id.is_valid()) {
auto total_count = get_dialog_pending_notification_count(d, false); auto total_count = get_dialog_pending_notification_count(d, false);
if (total_count == 0) { if (total_count == 0) {
set_dialog_last_notification(d->dialog_id, d->message_notification_group, 0, NotificationId(), set_dialog_last_notification(d->dialog_id, d->message_notification_group, 0, NotificationId(), source);
"set_dialog_last_read_inbox_message_id");
} }
if (!d->pending_new_message_notifications.empty()) { if (!d->pending_new_message_notifications.empty()) {
for (auto &it : d->pending_new_message_notifications) { for (auto &it : d->pending_new_message_notifications) {
@ -12074,7 +12073,7 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
if (d->mention_notification_group.group_id.is_valid() && d->pinned_message_notification_message_id.is_valid() && if (d->mention_notification_group.group_id.is_valid() && d->pinned_message_notification_message_id.is_valid() &&
d->pinned_message_notification_message_id <= d->last_read_inbox_message_id) { d->pinned_message_notification_message_id <= d->last_read_inbox_message_id) {
// remove pinned message notification when it is read // remove pinned message notification when it is read
remove_dialog_pinned_message_notification(d, "set_dialog_last_read_inbox_message_id 2"); remove_dialog_pinned_message_notification(d, source);
} }
} }
@ -16311,7 +16310,7 @@ void MessagesManager::on_get_dialog_filters(Result<vector<tl_object_ptr<telegram
continue; continue;
} }
sort_dialog_filter_input_dialog_ids(dialog_filter.get()); sort_dialog_filter_input_dialog_ids(dialog_filter.get(), "on_get_dialog_filters 1");
new_server_dialog_filters.push_back(std::move(dialog_filter)); new_server_dialog_filters.push_back(std::move(dialog_filter));
} }
@ -16343,7 +16342,7 @@ void MessagesManager::on_get_dialog_filters(Result<vector<tl_object_ptr<telegram
LOG(INFO) << "Old server filter: " << *old_server_filter; LOG(INFO) << "Old server filter: " << *old_server_filter;
LOG(INFO) << "New server filter: " << *new_server_filter; LOG(INFO) << "New server filter: " << *new_server_filter;
LOG(INFO) << "New local filter: " << *new_filter; LOG(INFO) << "New local filter: " << *new_filter;
sort_dialog_filter_input_dialog_ids(new_filter.get()); sort_dialog_filter_input_dialog_ids(new_filter.get(), "on_get_dialog_filters 2");
if (*new_filter != *old_filter) { if (*new_filter != *old_filter) {
is_changed = true; is_changed = true;
edit_dialog_filter(std::move(new_filter), "on_get_dialog_filters"); edit_dialog_filter(std::move(new_filter), "on_get_dialog_filters");
@ -18060,7 +18059,7 @@ InputDialogId MessagesManager::get_input_dialog_id(DialogId dialog_id) const {
} }
} }
void MessagesManager::sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_filter) const { void MessagesManager::sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_filter, const char *source) const {
auto sort_input_dialog_ids = [contacts_manager = auto sort_input_dialog_ids = [contacts_manager =
td_->contacts_manager_.get()](vector<InputDialogId> &input_dialog_ids) { td_->contacts_manager_.get()](vector<InputDialogId> &input_dialog_ids) {
std::sort(input_dialog_ids.begin(), input_dialog_ids.end(), std::sort(input_dialog_ids.begin(), input_dialog_ids.end(),
@ -18089,7 +18088,10 @@ void MessagesManager::sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_f
for (auto input_dialog_ids : for (auto input_dialog_ids :
{&dialog_filter->pinned_dialog_ids, &dialog_filter->excluded_dialog_ids, &dialog_filter->included_dialog_ids}) { {&dialog_filter->pinned_dialog_ids, &dialog_filter->excluded_dialog_ids, &dialog_filter->included_dialog_ids}) {
for (auto input_dialog_id : *input_dialog_ids) { for (auto input_dialog_id : *input_dialog_ids) {
CHECK(all_dialog_ids.insert(input_dialog_id.get_dialog_id()).second); LOG_CHECK(all_dialog_ids.insert(input_dialog_id.get_dialog_id()).second)
<< source << ' ' << td::contains(dialog_filter->pinned_dialog_ids, input_dialog_id) << ' '
<< td::contains(dialog_filter->excluded_dialog_ids, input_dialog_id) << ' '
<< td::contains(dialog_filter->included_dialog_ids, input_dialog_id);
} }
} }
} }
@ -18152,7 +18154,7 @@ Result<unique_ptr<DialogFilter>> MessagesManager::create_dialog_filter(DialogFil
dialog_filter->include_channels = filter->include_channels_; dialog_filter->include_channels = filter->include_channels_;
TRY_STATUS(dialog_filter->check_limits()); TRY_STATUS(dialog_filter->check_limits());
sort_dialog_filter_input_dialog_ids(dialog_filter.get()); sort_dialog_filter_input_dialog_ids(dialog_filter.get(), "create_dialog_filter");
return std::move(dialog_filter); return std::move(dialog_filter);
} }
@ -18982,7 +18984,7 @@ Status MessagesManager::toggle_dialog_is_pinned(DialogListId dialog_list_id, Dia
} }
TRY_STATUS(new_dialog_filter->check_limits()); TRY_STATUS(new_dialog_filter->check_limits());
sort_dialog_filter_input_dialog_ids(new_dialog_filter.get()); sort_dialog_filter_input_dialog_ids(new_dialog_filter.get(), "toggle_dialog_is_pinned");
edit_dialog_filter(std::move(new_dialog_filter), "toggle_dialog_is_pinned"); edit_dialog_filter(std::move(new_dialog_filter), "toggle_dialog_is_pinned");
save_dialog_filters(); save_dialog_filters();
@ -19138,7 +19140,7 @@ Status MessagesManager::set_pinned_dialogs(DialogListId dialog_list_id, vector<D
append(new_dialog_filter->included_dialog_ids, old_pinned_dialog_ids); append(new_dialog_filter->included_dialog_ids, old_pinned_dialog_ids);
TRY_STATUS(new_dialog_filter->check_limits()); TRY_STATUS(new_dialog_filter->check_limits());
sort_dialog_filter_input_dialog_ids(new_dialog_filter.get()); sort_dialog_filter_input_dialog_ids(new_dialog_filter.get(), "set_pinned_dialogs");
edit_dialog_filter(std::move(new_dialog_filter), "set_pinned_dialogs"); edit_dialog_filter(std::move(new_dialog_filter), "set_pinned_dialogs");
save_dialog_filters(); save_dialog_filters();
@ -23430,73 +23432,50 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa
secret_chat_layer = td_->contacts_manager_->get_secret_chat_layer(secret_chat_id); secret_chat_layer = td_->contacts_manager_->get_secret_chat_layer(secret_chat_id);
} }
bool can_send_messages = true;
bool can_send_media = true;
bool can_send_stickers = true;
bool can_send_animations = true;
bool can_send_games = true;
bool can_send_polls = true;
auto content_type = content->get_type(); auto content_type = content->get_type();
RestrictedRights permissions = [&] {
switch (dialog_type) { switch (dialog_type) {
case DialogType::User: case DialogType::User:
if (content_type == MessageContentType::Poll && !is_forward && !td_->auth_manager_->is_bot() && return td_->contacts_manager_->get_user_default_permissions(dialog_id.get_user_id());
!td_->contacts_manager_->is_user_bot(dialog_id.get_user_id())) {
return Status::Error(400, "Polls can't be sent to the private chat");
}
break;
case DialogType::Chat: case DialogType::Chat:
// ok return td_->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id()).get_restricted_rights();
break; case DialogType::Channel:
case DialogType::Channel: { return td_->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id()).get_restricted_rights();
auto channel_status = td_->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id());
can_send_messages = channel_status.can_send_messages();
can_send_media = channel_status.can_send_media();
can_send_stickers = channel_status.can_send_stickers();
can_send_animations = channel_status.can_send_animations();
can_send_games = channel_status.can_send_games();
can_send_polls = channel_status.can_send_polls();
break;
}
case DialogType::SecretChat: case DialogType::SecretChat:
if (content_type == MessageContentType::Game) { return td_->contacts_manager_->get_secret_chat_default_permissions(dialog_id.get_secret_chat_id());
return Status::Error(400, "Games can't be sent to secret chats");
}
if (content_type == MessageContentType::Poll) {
return Status::Error(400, "Polls can't be sent to secret chats");
}
if (content_type == MessageContentType::Dice) {
return Status::Error(400, "Dice can't be sent to secret chats");
}
break;
case DialogType::None: case DialogType::None:
default: default:
UNREACHABLE(); UNREACHABLE();
return td_->contacts_manager_->get_user_default_permissions(UserId());
} }
}();
switch (content_type) { switch (content_type) {
case MessageContentType::Animation: case MessageContentType::Animation:
if (!can_send_animations) { if (!permissions.can_send_animations()) {
return Status::Error(400, "Not enough rights to send animations to the chat"); return Status::Error(400, "Not enough rights to send animations to the chat");
} }
break; break;
case MessageContentType::Audio: case MessageContentType::Audio:
if (!can_send_media) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send audios to the chat"); return Status::Error(400, "Not enough rights to send audios to the chat");
} }
break; break;
case MessageContentType::Contact: case MessageContentType::Contact:
if (!can_send_messages) { if (!permissions.can_send_messages()) {
return Status::Error(400, "Not enough rights to send contacts to the chat"); return Status::Error(400, "Not enough rights to send contacts to the chat");
} }
break; break;
case MessageContentType::Dice: case MessageContentType::Dice:
if (!can_send_stickers) { if (!permissions.can_send_stickers()) {
return Status::Error(400, "Not enough rights to send dice to the chat"); return Status::Error(400, "Not enough rights to send dice to the chat");
} }
if (dialog_type == DialogType::SecretChat) {
return Status::Error(400, "Dice can't be sent to secret chats");
}
break; break;
case MessageContentType::Document: case MessageContentType::Document:
if (!can_send_media) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send documents to the chat"); return Status::Error(400, "Not enough rights to send documents to the chat");
} }
break; break;
@ -23504,8 +23483,10 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa
if (is_broadcast_channel(dialog_id)) { if (is_broadcast_channel(dialog_id)) {
// return Status::Error(400, "Games can't be sent to channel chats"); // return Status::Error(400, "Games can't be sent to channel chats");
} }
if (dialog_type == DialogType::SecretChat) {
if (!can_send_games) { return Status::Error(400, "Games can't be sent to secret chats");
}
if (!permissions.can_send_games()) {
return Status::Error(400, "Not enough rights to send games to the chat"); return Status::Error(400, "Not enough rights to send games to the chat");
} }
break; break;
@ -23526,50 +23507,57 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa
} }
break; break;
case MessageContentType::LiveLocation: case MessageContentType::LiveLocation:
if (!can_send_messages) { if (!permissions.can_send_messages()) {
return Status::Error(400, "Not enough rights to send live locations to the chat"); return Status::Error(400, "Not enough rights to send live locations to the chat");
} }
break; break;
case MessageContentType::Location: case MessageContentType::Location:
if (!can_send_messages) { if (!permissions.can_send_messages()) {
return Status::Error(400, "Not enough rights to send locations to the chat"); return Status::Error(400, "Not enough rights to send locations to the chat");
} }
break; break;
case MessageContentType::Photo: case MessageContentType::Photo:
if (!can_send_media) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send photos to the chat"); return Status::Error(400, "Not enough rights to send photos to the chat");
} }
break; break;
case MessageContentType::Poll: case MessageContentType::Poll:
if (!can_send_polls) { if (!permissions.can_send_polls()) {
return Status::Error(400, "Not enough rights to send polls to the chat"); return Status::Error(400, "Not enough rights to send polls to the chat");
} }
if (!get_message_content_poll_is_anonymous(td_, content) && is_broadcast_channel(dialog_id)) { if (!get_message_content_poll_is_anonymous(td_, content) && is_broadcast_channel(dialog_id)) {
return Status::Error(400, "Non-anonymous polls can't be sent to channel chats"); return Status::Error(400, "Non-anonymous polls can't be sent to channel chats");
} }
if (dialog_type == DialogType::User && !is_forward && !td_->auth_manager_->is_bot() &&
!td_->contacts_manager_->is_user_bot(dialog_id.get_user_id())) {
return Status::Error(400, "Polls can't be sent to the private chat");
}
if (dialog_type == DialogType::SecretChat) {
return Status::Error(400, "Polls can't be sent to secret chats");
}
break; break;
case MessageContentType::Sticker: case MessageContentType::Sticker:
if (!can_send_stickers) { if (!permissions.can_send_stickers()) {
return Status::Error(400, "Not enough rights to send stickers to the chat"); return Status::Error(400, "Not enough rights to send stickers to the chat");
} }
break; break;
case MessageContentType::Text: case MessageContentType::Text:
if (!can_send_messages) { if (!permissions.can_send_messages()) {
return Status::Error(400, "Not enough rights to send text messages to the chat"); return Status::Error(400, "Not enough rights to send text messages to the chat");
} }
break; break;
case MessageContentType::Venue: case MessageContentType::Venue:
if (!can_send_messages) { if (!permissions.can_send_messages()) {
return Status::Error(400, "Not enough rights to send venues to the chat"); return Status::Error(400, "Not enough rights to send venues to the chat");
} }
break; break;
case MessageContentType::Video: case MessageContentType::Video:
if (!can_send_media) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send videos to the chat"); return Status::Error(400, "Not enough rights to send videos to the chat");
} }
break; break;
case MessageContentType::VideoNote: case MessageContentType::VideoNote:
if (!can_send_media) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send video notes to the chat"); return Status::Error(400, "Not enough rights to send video notes to the chat");
} }
if (secret_chat_layer < SecretChatActor::VIDEO_NOTES_LAYER) { if (secret_chat_layer < SecretChatActor::VIDEO_NOTES_LAYER) {
@ -23578,7 +23566,7 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa
} }
break; break;
case MessageContentType::VoiceNote: case MessageContentType::VoiceNote:
if (!can_send_media) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send voice notes to the chat"); return Status::Error(400, "Not enough rights to send voice notes to the chat");
} }
break; break;
@ -27443,8 +27431,6 @@ NotificationGroupId MessagesManager::get_dialog_notification_group_id(DialogId d
Result<MessagesManager::MessagePushNotificationInfo> MessagesManager::get_message_push_notification_info( Result<MessagesManager::MessagePushNotificationInfo> MessagesManager::get_message_push_notification_info(
DialogId dialog_id, MessageId message_id, int64 random_id, UserId sender_user_id, DialogId sender_dialog_id, DialogId dialog_id, MessageId message_id, int64 random_id, UserId sender_user_id, DialogId sender_dialog_id,
int32 date, bool is_from_scheduled, bool contains_mention, bool is_pinned, bool is_from_binlog) { int32 date, bool is_from_scheduled, bool contains_mention, bool is_pinned, bool is_from_binlog) {
init();
if (!is_from_scheduled && dialog_id == get_my_dialog_id()) { if (!is_from_scheduled && dialog_id == get_my_dialog_id()) {
return Status::Error("Ignore notification in chat with self"); return Status::Error("Ignore notification in chat with self");
} }
@ -27881,8 +27867,6 @@ vector<NotificationGroupKey> MessagesManager::get_message_notification_group_key
return {}; return {};
} }
init();
VLOG(notifications) << "Trying to load " << limit << " message notification groups from database from " VLOG(notifications) << "Trying to load " << limit << " message notification groups from database from "
<< from_group_key; << from_group_key;
@ -31119,7 +31103,7 @@ void MessagesManager::add_dialog_to_list(DialogId dialog_id, DialogListId dialog
if (status.is_error()) { if (status.is_error()) {
return promise.set_error(std::move(status)); return promise.set_error(std::move(status));
} }
sort_dialog_filter_input_dialog_ids(new_dialog_filter.get()); sort_dialog_filter_input_dialog_ids(new_dialog_filter.get(), "add_dialog_to_list");
edit_dialog_filter(std::move(new_dialog_filter), "add_dialog_to_list"); edit_dialog_filter(std::move(new_dialog_filter), "add_dialog_to_list");
save_dialog_filters(); save_dialog_filters();
@ -34250,7 +34234,7 @@ MessagesManager::Dialog *MessagesManager::add_dialog(DialogId dialog_id, const c
auto r_value = G()->td_db()->get_dialog_db_sync()->get_dialog(dialog_id); auto r_value = G()->td_db()->get_dialog_db_sync()->get_dialog(dialog_id);
if (r_value.is_ok()) { if (r_value.is_ok()) {
LOG(INFO) << "Synchronously loaded " << dialog_id << " from database"; LOG(INFO) << "Synchronously loaded " << dialog_id << " from database";
return add_new_dialog(parse_dialog(dialog_id, r_value.ok()), true, source); return add_new_dialog(parse_dialog(dialog_id, r_value.ok(), source), true, source);
} }
} }
@ -34673,36 +34657,6 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
LOG(ERROR) << dialog_id << " has order " << d->order << " instead of saved to database order " << order; LOG(ERROR) << dialog_id << " has order " << d->order << " instead of saved to database order " << order;
} }
// must be after update_dialog_pos, because uses d->order
if (d->pending_read_channel_inbox_pts != 0 && !td_->auth_manager_->is_bot() &&
have_input_peer(dialog_id, AccessRights::Read) && need_unread_counter(d->order)) {
if (d->pts == d->pending_read_channel_inbox_pts) {
read_history_inbox(dialog_id, d->pending_read_channel_inbox_max_message_id,
d->pending_read_channel_inbox_server_unread_count, "fix_new_dialog 12");
d->pending_read_channel_inbox_pts = 0;
on_dialog_updated(dialog_id, "fix_new_dialog 13");
} else if (d->pts > d->pending_read_channel_inbox_pts) {
d->need_repair_channel_server_unread_count = true;
d->pending_read_channel_inbox_pts = 0;
on_dialog_updated(dialog_id, "fix_new_dialog 14");
} else {
channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), 0.001);
}
} else {
d->pending_read_channel_inbox_pts = 0;
}
if (need_get_history && !td_->auth_manager_->is_bot() && dialog_id != being_added_dialog_id_ &&
have_input_peer(dialog_id, AccessRights::Read) && (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) {
get_history_from_the_end(dialog_id, true, false, Auto());
}
if (d->need_repair_server_unread_count && need_unread_counter(d->order)) {
CHECK(dialog_type != DialogType::SecretChat);
repair_server_unread_count(dialog_id, d->server_unread_count);
}
if (d->need_repair_channel_server_unread_count) {
repair_channel_server_unread_count(d);
}
LOG(INFO) << "Loaded " << dialog_id << " with last new " << d->last_new_message_id << ", first database " LOG(INFO) << "Loaded " << dialog_id << " with last new " << d->last_new_message_id << ", first database "
<< d->first_database_message_id << ", last database " << d->last_database_message_id << ", last " << d->first_database_message_id << ", last database " << d->last_database_message_id << ", last "
<< d->last_message_id << " with order " << d->order; << d->last_message_id << " with order " << d->order;
@ -34731,6 +34685,38 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
LOG_CHECK(d->messages->left == nullptr) << get_debug_source(d->messages->left); LOG_CHECK(d->messages->left == nullptr) << get_debug_source(d->messages->left);
LOG_CHECK(d->messages->right == nullptr) << get_debug_source(d->messages->right); LOG_CHECK(d->messages->right == nullptr) << get_debug_source(d->messages->right);
} }
// must be after update_dialog_pos, because uses d->order
// must be after checks that dialog has at most one message, because read_history_inbox can load
// pinned message to remove its notification
if (d->pending_read_channel_inbox_pts != 0 && !td_->auth_manager_->is_bot() &&
have_input_peer(dialog_id, AccessRights::Read) && need_unread_counter(d->order)) {
if (d->pts == d->pending_read_channel_inbox_pts) {
d->pending_read_channel_inbox_pts = 0;
read_history_inbox(dialog_id, d->pending_read_channel_inbox_max_message_id,
d->pending_read_channel_inbox_server_unread_count, "fix_new_dialog 12");
on_dialog_updated(dialog_id, "fix_new_dialog 13");
} else if (d->pts > d->pending_read_channel_inbox_pts) {
d->need_repair_channel_server_unread_count = true;
d->pending_read_channel_inbox_pts = 0;
on_dialog_updated(dialog_id, "fix_new_dialog 14");
} else {
channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), 0.001);
}
} else {
d->pending_read_channel_inbox_pts = 0;
}
if (need_get_history && !td_->auth_manager_->is_bot() && dialog_id != being_added_dialog_id_ &&
have_input_peer(dialog_id, AccessRights::Read) && (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) {
get_history_from_the_end(dialog_id, true, false, Auto());
}
if (d->need_repair_server_unread_count && need_unread_counter(d->order)) {
CHECK(dialog_type != DialogType::SecretChat);
repair_server_unread_count(dialog_id, d->server_unread_count);
}
if (d->need_repair_channel_server_unread_count) {
repair_channel_server_unread_count(d);
}
} }
void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message) { void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message) {
@ -35001,9 +34987,7 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
} }
auto folder_ptr = get_dialog_folder(d->folder_id); auto folder_ptr = get_dialog_folder(d->folder_id);
LOG_CHECK(folder_ptr != nullptr) << is_inited_ << ' ' << G()->close_flag() << ' ' << dialog_id << ' ' << d->folder_id CHECK(folder_ptr != nullptr);
<< ' ' << is_loaded_from_database << ' ' << td_->auth_manager_->is_authorized()
<< ' ' << td_->auth_manager_->was_authorized() << ' ' << source;
auto &folder = *folder_ptr; auto &folder = *folder_ptr;
if (old_date == new_date) { if (old_date == new_date) {
if (new_order == DEFAULT_ORDER) { if (new_order == DEFAULT_ORDER) {
@ -35356,7 +35340,8 @@ bool MessagesManager::have_dialog_force(DialogId dialog_id, const char *source)
} }
MessagesManager::Dialog *MessagesManager::get_dialog_force(DialogId dialog_id, const char *source) { MessagesManager::Dialog *MessagesManager::get_dialog_force(DialogId dialog_id, const char *source) {
// TODO remove most usages of that function, preload dialog asynchronously if possible init();
auto it = dialogs_.find(dialog_id); auto it = dialogs_.find(dialog_id);
if (it != dialogs_.end()) { if (it != dialogs_.end()) {
return it->second.get(); return it->second.get();
@ -35379,8 +35364,9 @@ MessagesManager::Dialog *MessagesManager::get_dialog_force(DialogId dialog_id, c
} }
} }
unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialog_id, const BufferSlice &value) { unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialog_id, const BufferSlice &value,
LOG(INFO) << "Loaded " << dialog_id << " of size " << value.size() << " from database"; const char *source) {
LOG(INFO) << "Loaded " << dialog_id << " of size " << value.size() << " from database from " << source;
auto d = make_unique<Dialog>(); auto d = make_unique<Dialog>();
d->dialog_id = dialog_id; d->dialog_id = dialog_id;
invalidate_message_indexes(d.get()); // must initialize indexes, because some of them could be not parsed invalidate_message_indexes(d.get()); // must initialize indexes, because some of them could be not parsed
@ -35392,7 +35378,7 @@ unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialo
// can't happen unless database is broken, but has been seen in the wild // can't happen unless database is broken, but has been seen in the wild
// if dialog_id is invalid, we can't repair the dialog // if dialog_id is invalid, we can't repair the dialog
LOG_CHECK(dialog_id.is_valid()) << "Can't repair " << dialog_id << ' ' << d->dialog_id << ' ' << status << ' ' LOG_CHECK(dialog_id.is_valid()) << "Can't repair " << dialog_id << ' ' << d->dialog_id << ' ' << status << ' '
<< format::as_hex_dump<4>(value.as_slice()); << source << ' ' << format::as_hex_dump<4>(value.as_slice());
LOG(ERROR) << "Repair broken " << dialog_id << ' ' << format::as_hex_dump<4>(value.as_slice()); LOG(ERROR) << "Repair broken " << dialog_id << ' ' << format::as_hex_dump<4>(value.as_slice());
@ -35405,10 +35391,10 @@ unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialo
have_dialog_info_force(dialog_id); have_dialog_info_force(dialog_id);
if (have_input_peer(dialog_id, AccessRights::Read)) { if (have_input_peer(dialog_id, AccessRights::Read)) {
if (dialog_id.get_type() != DialogType::SecretChat) { if (dialog_id.get_type() != DialogType::SecretChat) {
send_get_dialog_query(dialog_id, Auto(), 0, "parse_dialog"); send_get_dialog_query(dialog_id, Auto(), 0, source);
} }
} else { } else {
LOG(WARNING) << "Have no info about " << dialog_id << " to repair it"; LOG(ERROR) << "Have no info about " << dialog_id << " from " << source << " to repair it";
} }
} }
CHECK(dialog_id == d->dialog_id); CHECK(dialog_id == d->dialog_id);
@ -35424,8 +35410,8 @@ unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialo
if (d->draft_message != nullptr) { if (d->draft_message != nullptr) {
add_formatted_text_dependencies(dependencies, &d->draft_message->input_message_text.text); add_formatted_text_dependencies(dependencies, &d->draft_message->input_message_text.text);
} }
if (!resolve_dependencies_force(td_, dependencies, "parse_dialog")) { if (!resolve_dependencies_force(td_, dependencies, source)) {
send_get_dialog_query(dialog_id, Auto(), 0, "parse_dialog"); send_get_dialog_query(dialog_id, Auto(), 0, source);
} }
return d; return d;
@ -35454,7 +35440,7 @@ MessagesManager::Dialog *MessagesManager::on_load_dialog_from_database(DialogId
} }
LOG(INFO) << "Add new " << dialog_id << " from database from " << source; LOG(INFO) << "Add new " << dialog_id << " from database from " << source;
return add_new_dialog(parse_dialog(dialog_id, value), true, source); return add_new_dialog(parse_dialog(dialog_id, value, source), true, source);
} }
const DialogFilter *MessagesManager::get_server_dialog_filter(DialogFilterId dialog_filter_id) const { const DialogFilter *MessagesManager::get_server_dialog_filter(DialogFilterId dialog_filter_id) const {

View File

@ -2480,7 +2480,7 @@ class MessagesManager : public Actor {
InputDialogId get_input_dialog_id(DialogId dialog_id) const; InputDialogId get_input_dialog_id(DialogId dialog_id) const;
void sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_filter) const; void sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_filter, const char *source) const;
Result<unique_ptr<DialogFilter>> create_dialog_filter(DialogFilterId dialog_filter_id, Result<unique_ptr<DialogFilter>> create_dialog_filter(DialogFilterId dialog_filter_id,
td_api::object_ptr<td_api::chatFilter> filter); td_api::object_ptr<td_api::chatFilter> filter);
@ -2917,7 +2917,7 @@ class MessagesManager : public Actor {
unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled); unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled);
unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value); unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value, const char *source);
void load_calls_db_state(); void load_calls_db_state();
void save_calls_db_state(); void save_calls_db_state();