Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
a156fcfb1d
|
@ -416,6 +416,7 @@ set(TDLIB_SOURCE
|
||||||
td/telegram/SecretChatActor.cpp
|
td/telegram/SecretChatActor.cpp
|
||||||
td/telegram/SecretChatDb.cpp
|
td/telegram/SecretChatDb.cpp
|
||||||
td/telegram/SecretChatsManager.cpp
|
td/telegram/SecretChatsManager.cpp
|
||||||
|
td/telegram/SecretInputMedia.cpp
|
||||||
td/telegram/SecureManager.cpp
|
td/telegram/SecureManager.cpp
|
||||||
td/telegram/SecureStorage.cpp
|
td/telegram/SecureStorage.cpp
|
||||||
td/telegram/SecureValue.cpp
|
td/telegram/SecureValue.cpp
|
||||||
|
|
|
@ -393,8 +393,7 @@ SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file
|
||||||
auto *animation = get_animation(animation_file_id);
|
auto *animation = get_animation(animation_file_id);
|
||||||
CHECK(animation != nullptr);
|
CHECK(animation != nullptr);
|
||||||
auto file_view = td_->file_manager_->get_file_view(animation_file_id);
|
auto file_view = td_->file_manager_->get_file_view(animation_file_id);
|
||||||
auto &encryption_key = file_view.encryption_key();
|
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||||
if (!file_view.is_encrypted_secret() || encryption_key.empty()) {
|
|
||||||
return SecretInputMedia{};
|
return SecretInputMedia{};
|
||||||
}
|
}
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
|
@ -420,12 +419,13 @@ SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file
|
||||||
}
|
}
|
||||||
attributes.push_back(make_tl_object<secret_api::documentAttributeAnimated>());
|
attributes.push_back(make_tl_object<secret_api::documentAttributeAnimated>());
|
||||||
|
|
||||||
return SecretInputMedia{
|
return {std::move(input_file),
|
||||||
std::move(input_file),
|
std::move(thumbnail),
|
||||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
animation->thumbnail.dimensions,
|
||||||
std::move(thumbnail), animation->thumbnail.dimensions.width, animation->thumbnail.dimensions.height,
|
animation->mime_type,
|
||||||
animation->mime_type, narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
file_view,
|
||||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption)};
|
std::move(attributes),
|
||||||
|
caption};
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationsManager::on_update_animation_search_emojis(string animation_search_emojis) {
|
void AnimationsManager::on_update_animation_search_emojis(string animation_search_emojis) {
|
||||||
|
@ -885,12 +885,6 @@ string AnimationsManager::get_animation_search_text(FileId file_id) const {
|
||||||
return animation->file_name;
|
return animation->file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationsManager::after_get_difference() {
|
|
||||||
if (td_->is_online() && !td_->auth_manager_->is_bot()) {
|
|
||||||
get_saved_animations(Auto());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
void AnimationsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
||||||
if (td_->auth_manager_->is_bot()) {
|
if (td_->auth_manager_->is_bot()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -91,8 +91,6 @@ class AnimationsManager final : public Actor {
|
||||||
|
|
||||||
string get_animation_search_text(FileId file_id) const;
|
string get_animation_search_text(FileId file_id) const;
|
||||||
|
|
||||||
void after_get_difference();
|
|
||||||
|
|
||||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -210,8 +210,7 @@ SecretInputMedia AudiosManager::get_secret_input_media(FileId audio_file_id,
|
||||||
auto *audio = get_audio(audio_file_id);
|
auto *audio = get_audio(audio_file_id);
|
||||||
CHECK(audio != nullptr);
|
CHECK(audio != nullptr);
|
||||||
auto file_view = td_->file_manager_->get_file_view(audio_file_id);
|
auto file_view = td_->file_manager_->get_file_view(audio_file_id);
|
||||||
auto &encryption_key = file_view.encryption_key();
|
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||||
if (!file_view.is_encrypted_secret() || encryption_key.empty()) {
|
|
||||||
return SecretInputMedia{};
|
return SecretInputMedia{};
|
||||||
}
|
}
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
|
@ -231,12 +230,13 @@ SecretInputMedia AudiosManager::get_secret_input_media(FileId audio_file_id,
|
||||||
secret_api::documentAttributeAudio::TITLE_MASK | secret_api::documentAttributeAudio::PERFORMER_MASK,
|
secret_api::documentAttributeAudio::TITLE_MASK | secret_api::documentAttributeAudio::PERFORMER_MASK,
|
||||||
false /*ignored*/, audio->duration, audio->title, audio->performer, BufferSlice()));
|
false /*ignored*/, audio->duration, audio->title, audio->performer, BufferSlice()));
|
||||||
|
|
||||||
return SecretInputMedia{
|
return {std::move(input_file),
|
||||||
std::move(input_file),
|
std::move(thumbnail),
|
||||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
audio->thumbnail.dimensions,
|
||||||
std::move(thumbnail), audio->thumbnail.dimensions.width, audio->thumbnail.dimensions.height, audio->mime_type,
|
audio->mime_type,
|
||||||
narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
file_view,
|
||||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption)};
|
std::move(attributes),
|
||||||
|
caption};
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputMedia> AudiosManager::get_input_media(
|
tl_object_ptr<telegram_api::InputMedia> AudiosManager::get_input_media(
|
||||||
|
|
|
@ -39,13 +39,13 @@ void ConfigShared::set_option_empty(Slice name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigShared::set_option_integer(Slice name, int64 value) {
|
void ConfigShared::set_option_integer(Slice name, int64 value) {
|
||||||
if (set_option(name, PSLICE() << "I" << value)) {
|
if (set_option(name, PSLICE() << 'I' << value)) {
|
||||||
on_option_updated(name);
|
on_option_updated(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigShared::set_option_string(Slice name, Slice value) {
|
void ConfigShared::set_option_string(Slice name, Slice value) {
|
||||||
if (set_option(name, PSLICE() << "S" << value)) {
|
if (set_option(name, PSLICE() << 'S' << value)) {
|
||||||
on_option_updated(name);
|
on_option_updated(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,32 +73,32 @@ bool ConfigShared::get_option_boolean(Slice name, bool default_value) const {
|
||||||
if (value == "Bfalse") {
|
if (value == "Bfalse") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LOG(ERROR) << "Found \"" << value << "\" instead of boolean option";
|
LOG(ERROR) << "Found \"" << value << "\" instead of boolean option " << name;
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 ConfigShared::get_option_integer(Slice name, int64 default_value) const {
|
int64 ConfigShared::get_option_integer(Slice name, int64 default_value) const {
|
||||||
auto str_value = get_option(name);
|
auto value = get_option(name);
|
||||||
if (str_value.empty()) {
|
if (value.empty()) {
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
if (str_value[0] != 'I') {
|
if (value[0] != 'I') {
|
||||||
LOG(ERROR) << "Found \"" << str_value << "\" instead of integer option";
|
LOG(ERROR) << "Found \"" << value << "\" instead of integer option " << name;
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
return to_integer<int64>(str_value.substr(1));
|
return to_integer<int64>(value.substr(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
string ConfigShared::get_option_string(Slice name, string default_value) const {
|
string ConfigShared::get_option_string(Slice name, string default_value) const {
|
||||||
auto str_value = get_option(name);
|
auto value = get_option(name);
|
||||||
if (str_value.empty()) {
|
if (value.empty()) {
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
if (str_value[0] != 'S') {
|
if (value[0] != 'S') {
|
||||||
LOG(ERROR) << "Found \"" << str_value << "\" instead of string option";
|
LOG(ERROR) << "Found \"" << value << "\" instead of string option " << name;
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
return str_value.substr(1);
|
return value.substr(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigShared::set_option(Slice name, Slice value) {
|
bool ConfigShared::set_option(Slice name, Slice value) {
|
||||||
|
|
|
@ -2924,10 +2924,10 @@ class GetChannelAdministratorsQuery final : public Td::ResultHandler {
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetSupportUserQuery final : public Td::ResultHandler {
|
class GetSupportUserQuery final : public Td::ResultHandler {
|
||||||
Promise<Unit> promise_;
|
Promise<UserId> promise_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GetSupportUserQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
explicit GetSupportUserQuery(Promise<UserId> &&promise) : promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send() {
|
void send() {
|
||||||
|
@ -2943,9 +2943,10 @@ class GetSupportUserQuery final : public Td::ResultHandler {
|
||||||
auto ptr = result_ptr.move_as_ok();
|
auto ptr = result_ptr.move_as_ok();
|
||||||
LOG(INFO) << "Receive result for GetSupportUserQuery: " << to_string(ptr);
|
LOG(INFO) << "Receive result for GetSupportUserQuery: " << to_string(ptr);
|
||||||
|
|
||||||
td_->contacts_manager_->on_get_user(std::move(ptr->user_), "GetSupportUserQuery", false, true);
|
auto user_id = ContactsManager::get_user_id(ptr->user_);
|
||||||
|
td_->contacts_manager_->on_get_user(std::move(ptr->user_), "GetSupportUserQuery", false);
|
||||||
|
|
||||||
promise_.set_value(Unit());
|
promise_.set_value(std::move(user_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_error(Status status) final {
|
void on_error(Status status) final {
|
||||||
|
@ -4040,6 +4041,7 @@ void ContactsManager::Channel::store(StorerT &storer) const {
|
||||||
STORE_FLAG(is_fake);
|
STORE_FLAG(is_fake);
|
||||||
STORE_FLAG(is_gigagroup);
|
STORE_FLAG(is_gigagroup);
|
||||||
STORE_FLAG(noforwards);
|
STORE_FLAG(noforwards);
|
||||||
|
STORE_FLAG(can_be_deleted); // 25
|
||||||
END_STORE_FLAGS();
|
END_STORE_FLAGS();
|
||||||
|
|
||||||
store(status, storer);
|
store(status, storer);
|
||||||
|
@ -4110,6 +4112,7 @@ void ContactsManager::Channel::parse(ParserT &parser) {
|
||||||
PARSE_FLAG(is_fake);
|
PARSE_FLAG(is_fake);
|
||||||
PARSE_FLAG(is_gigagroup);
|
PARSE_FLAG(is_gigagroup);
|
||||||
PARSE_FLAG(noforwards);
|
PARSE_FLAG(noforwards);
|
||||||
|
PARSE_FLAG(can_be_deleted);
|
||||||
END_PARSE_FLAGS();
|
END_PARSE_FLAGS();
|
||||||
|
|
||||||
if (use_new_rights) {
|
if (use_new_rights) {
|
||||||
|
@ -6881,7 +6884,7 @@ void ContactsManager::delete_channel(ChannelId channel_id, Promise<Unit> &&promi
|
||||||
if (c == nullptr) {
|
if (c == nullptr) {
|
||||||
return promise.set_error(Status::Error(400, "Chat info not found"));
|
return promise.set_error(Status::Error(400, "Chat info not found"));
|
||||||
}
|
}
|
||||||
if (!get_channel_can_be_deleted(channel_id)) {
|
if (!get_channel_can_be_deleted(c)) {
|
||||||
return promise.set_error(Status::Error(400, "The chat can't be deleted"));
|
return promise.set_error(Status::Error(400, "The chat can't be deleted"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8397,8 +8400,7 @@ DialogId ContactsManager::get_dialog_id(const tl_object_ptr<telegram_api::Chat>
|
||||||
return DialogId(get_chat_id(chat));
|
return DialogId(get_chat_id(chat));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr, const char *source, bool is_me,
|
void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr, const char *source, bool is_me) {
|
||||||
bool expect_support) {
|
|
||||||
LOG(DEBUG) << "Receive from " << source << ' ' << to_string(user_ptr);
|
LOG(DEBUG) << "Receive from " << source << ' ' << to_string(user_ptr);
|
||||||
int32 constructor_id = user_ptr->get_id();
|
int32 constructor_id = user_ptr->get_id();
|
||||||
if (constructor_id == telegram_api::userEmpty::ID) {
|
if (constructor_id == telegram_api::userEmpty::ID) {
|
||||||
|
@ -8440,10 +8442,6 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expect_support) {
|
|
||||||
support_user_id_ = user_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool have_access_hash = (flags & USER_FLAG_HAS_ACCESS_HASH) != 0;
|
bool have_access_hash = (flags & USER_FLAG_HAS_ACCESS_HASH) != 0;
|
||||||
bool is_received = (flags & USER_FLAG_IS_INACCESSIBLE) == 0;
|
bool is_received = (flags & USER_FLAG_IS_INACCESSIBLE) == 0;
|
||||||
bool is_contact = (flags & USER_FLAG_IS_CONTACT) != 0;
|
bool is_contact = (flags & USER_FLAG_IS_CONTACT) != 0;
|
||||||
|
@ -8509,7 +8507,6 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr,
|
||||||
bool need_apply_min_photo = (flags & USER_FLAG_NEED_APPLY_MIN_PHOTO) != 0;
|
bool need_apply_min_photo = (flags & USER_FLAG_NEED_APPLY_MIN_PHOTO) != 0;
|
||||||
bool is_fake = (flags & USER_FLAG_IS_FAKE) != 0;
|
bool is_fake = (flags & USER_FLAG_IS_FAKE) != 0;
|
||||||
|
|
||||||
LOG_IF(ERROR, !is_support && expect_support) << "Receive non-support " << user_id << ", but expected a support user";
|
|
||||||
LOG_IF(ERROR, !can_join_groups && !is_bot)
|
LOG_IF(ERROR, !can_join_groups && !is_bot)
|
||||||
<< "Receive not bot " << user_id << " which can't join groups from " << source;
|
<< "Receive not bot " << user_id << " which can't join groups from " << source;
|
||||||
LOG_IF(ERROR, can_read_all_group_messages && !is_bot)
|
LOG_IF(ERROR, can_read_all_group_messages && !is_bot)
|
||||||
|
@ -9960,9 +9957,12 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
|
||||||
|
|
||||||
c->participant_count = channel_full->participant_count;
|
c->participant_count = channel_full->participant_count;
|
||||||
c->is_changed = true;
|
c->is_changed = true;
|
||||||
update_channel(c, channel_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (c->can_be_deleted != channel_full->can_be_deleted) {
|
||||||
|
c->can_be_deleted = channel_full->can_be_deleted;
|
||||||
|
c->need_save_to_database = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (invalidated_channels_full_.erase(channel_id) > 0 ||
|
if (invalidated_channels_full_.erase(channel_id) > 0 ||
|
||||||
(!c->is_slow_mode_enabled && channel_full->slow_mode_delay != 0)) {
|
(!c->is_slow_mode_enabled && channel_full->slow_mode_delay != 0)) {
|
||||||
|
@ -9974,6 +9974,8 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
|
||||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
|
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
|
||||||
channel_full->bot_user_ids, true);
|
channel_full->bot_user_ids, true);
|
||||||
|
|
||||||
|
update_channel(c, channel_id);
|
||||||
|
|
||||||
channel_full->is_update_channel_full_sent = true;
|
channel_full->is_update_channel_full_sent = true;
|
||||||
update_channel_full(channel_full, channel_id, "on_load_channel_full_from_database", true);
|
update_channel_full(channel_full, channel_id, "on_load_channel_full_from_database", true);
|
||||||
|
|
||||||
|
@ -10876,7 +10878,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
||||||
on_update_chat_full_invite_link(chat_full, std::move(chat->exported_invite_));
|
on_update_chat_full_invite_link(chat_full, std::move(chat->exported_invite_));
|
||||||
auto photo = get_photo(td_->file_manager_.get(), std::move(chat->chat_photo_), DialogId(chat_id));
|
auto photo = get_photo(td_->file_manager_.get(), std::move(chat->chat_photo_), DialogId(chat_id));
|
||||||
// on_update_chat_photo should be a no-op if server sent consistent data
|
// on_update_chat_photo should be a no-op if server sent consistent data
|
||||||
on_update_chat_photo(c, as_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, photo));
|
on_update_chat_photo(c, chat_id, as_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, photo), false);
|
||||||
on_update_chat_full_photo(chat_full, chat_id, std::move(photo));
|
on_update_chat_full_photo(chat_full, chat_id, std::move(photo));
|
||||||
if (chat_full->description != chat->about_) {
|
if (chat_full->description != chat->about_) {
|
||||||
chat_full->description = std::move(chat->about_);
|
chat_full->description = std::move(chat->about_);
|
||||||
|
@ -11049,7 +11051,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
||||||
|
|
||||||
auto photo = get_photo(td_->file_manager_.get(), std::move(channel->chat_photo_), DialogId(channel_id));
|
auto photo = get_photo(td_->file_manager_.get(), std::move(channel->chat_photo_), DialogId(channel_id));
|
||||||
// on_update_channel_photo should be a no-op if server sent consistent data
|
// on_update_channel_photo should be a no-op if server sent consistent data
|
||||||
on_update_channel_photo(c, as_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, photo));
|
on_update_channel_photo(
|
||||||
|
c, channel_id, as_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, photo), false);
|
||||||
on_update_channel_full_photo(channel_full, channel_id, std::move(photo));
|
on_update_channel_full_photo(channel_full, channel_id, std::move(photo));
|
||||||
|
|
||||||
td_->messages_manager_->on_read_channel_outbox(channel_id,
|
td_->messages_manager_->on_read_channel_outbox(channel_id,
|
||||||
|
@ -11164,6 +11167,10 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
||||||
channel_full->can_be_deleted = channel->can_delete_channel_;
|
channel_full->can_be_deleted = channel->can_delete_channel_;
|
||||||
channel_full->need_save_to_database = true;
|
channel_full->need_save_to_database = true;
|
||||||
}
|
}
|
||||||
|
if (c->can_be_deleted != channel_full->can_be_deleted) {
|
||||||
|
c->can_be_deleted = channel_full->can_be_deleted;
|
||||||
|
c->need_save_to_database = true;
|
||||||
|
}
|
||||||
|
|
||||||
ChatId migrated_from_chat_id;
|
ChatId migrated_from_chat_id;
|
||||||
MessageId migrated_from_max_message_id;
|
MessageId migrated_from_max_message_id;
|
||||||
|
@ -11383,7 +11390,7 @@ void ContactsManager::do_update_user_photo(User *u, UserId user_id, ProfilePhoto
|
||||||
u->is_changed = true;
|
u->is_changed = true;
|
||||||
|
|
||||||
if (invalidate_photo_cache) {
|
if (invalidate_photo_cache) {
|
||||||
drop_user_photos(user_id, u->photo.id <= 0, true, "do_update_user_photo");
|
drop_user_photos(user_id, !u->photo.small_file_id.is_valid(), true, "do_update_user_photo");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11874,7 +11881,7 @@ void ContactsManager::drop_user_photos(UserId user_id, bool is_empty, bool drop_
|
||||||
user_full->expires_at = 0.0;
|
user_full->expires_at = 0.0;
|
||||||
user_full->need_save_to_database = true;
|
user_full->need_save_to_database = true;
|
||||||
}
|
}
|
||||||
load_user_full(user_id, true, Auto(), "drop_user_photos");
|
reload_user_full(user_id);
|
||||||
}
|
}
|
||||||
update_user_full(user_full, user_id, "drop_user_photos");
|
update_user_full(user_full, user_id, "drop_user_photos");
|
||||||
}
|
}
|
||||||
|
@ -13501,10 +13508,11 @@ void ContactsManager::on_update_chat_participant_count(Chat *c, ChatId chat_id,
|
||||||
|
|
||||||
void ContactsManager::on_update_chat_photo(Chat *c, ChatId chat_id,
|
void ContactsManager::on_update_chat_photo(Chat *c, ChatId chat_id,
|
||||||
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
|
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
|
||||||
on_update_chat_photo(c, get_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, std::move(chat_photo_ptr)));
|
on_update_chat_photo(
|
||||||
|
c, chat_id, get_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, std::move(chat_photo_ptr)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_chat_photo(Chat *c, DialogPhoto &&photo) {
|
void ContactsManager::on_update_chat_photo(Chat *c, ChatId chat_id, DialogPhoto &&photo, bool invalidate_photo_cache) {
|
||||||
if (td_->auth_manager_->is_bot()) {
|
if (td_->auth_manager_->is_bot()) {
|
||||||
photo.minithumbnail.clear();
|
photo.minithumbnail.clear();
|
||||||
}
|
}
|
||||||
|
@ -13513,6 +13521,20 @@ void ContactsManager::on_update_chat_photo(Chat *c, DialogPhoto &&photo) {
|
||||||
c->photo = std::move(photo);
|
c->photo = std::move(photo);
|
||||||
c->is_photo_changed = true;
|
c->is_photo_changed = true;
|
||||||
c->need_save_to_database = true;
|
c->need_save_to_database = true;
|
||||||
|
|
||||||
|
if (invalidate_photo_cache) {
|
||||||
|
auto chat_full = get_chat_full(chat_id); // must not load ChatFull
|
||||||
|
if (chat_full != nullptr) {
|
||||||
|
if (!chat_full->photo.is_empty()) {
|
||||||
|
chat_full->photo = Photo();
|
||||||
|
chat_full->is_changed = true;
|
||||||
|
}
|
||||||
|
if (c->photo.small_file_id.is_valid()) {
|
||||||
|
reload_chat_full(chat_id, Auto());
|
||||||
|
}
|
||||||
|
update_chat_full(chat_full, chat_id, "on_update_chat_photo");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13630,10 +13652,13 @@ void ContactsManager::drop_chat_full(ChatId chat_id) {
|
||||||
void ContactsManager::on_update_channel_photo(Channel *c, ChannelId channel_id,
|
void ContactsManager::on_update_channel_photo(Channel *c, ChannelId channel_id,
|
||||||
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
|
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
|
||||||
on_update_channel_photo(
|
on_update_channel_photo(
|
||||||
c, get_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, std::move(chat_photo_ptr)));
|
c, channel_id,
|
||||||
|
get_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, std::move(chat_photo_ptr)),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_channel_photo(Channel *c, DialogPhoto &&photo) {
|
void ContactsManager::on_update_channel_photo(Channel *c, ChannelId channel_id, DialogPhoto &&photo,
|
||||||
|
bool invalidate_photo_cache) {
|
||||||
if (td_->auth_manager_->is_bot()) {
|
if (td_->auth_manager_->is_bot()) {
|
||||||
photo.minithumbnail.clear();
|
photo.minithumbnail.clear();
|
||||||
}
|
}
|
||||||
|
@ -13642,6 +13667,24 @@ void ContactsManager::on_update_channel_photo(Channel *c, DialogPhoto &&photo) {
|
||||||
c->photo = std::move(photo);
|
c->photo = std::move(photo);
|
||||||
c->is_photo_changed = true;
|
c->is_photo_changed = true;
|
||||||
c->need_save_to_database = true;
|
c->need_save_to_database = true;
|
||||||
|
|
||||||
|
if (invalidate_photo_cache) {
|
||||||
|
auto channel_full = get_channel_full(channel_id, true, "on_update_channel_photo"); // must not load ChannelFull
|
||||||
|
if (channel_full != nullptr) {
|
||||||
|
if (!channel_full->photo.is_empty()) {
|
||||||
|
channel_full->photo = Photo();
|
||||||
|
channel_full->is_changed = true;
|
||||||
|
}
|
||||||
|
if (c->photo.small_file_id.is_valid()) {
|
||||||
|
if (channel_full->expires_at > 0.0) {
|
||||||
|
channel_full->expires_at = 0.0;
|
||||||
|
channel_full->need_save_to_database = true;
|
||||||
|
}
|
||||||
|
reload_channel_full(channel_id, Auto(), "on_update_channel_photo");
|
||||||
|
}
|
||||||
|
update_channel_full(channel_full, channel_id, "on_update_channel_photo");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14853,6 +14896,18 @@ bool ContactsManager::get_channel_has_linked_channel(const Channel *c) {
|
||||||
return c->has_linked_channel;
|
return c->has_linked_channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ContactsManager::get_channel_can_be_deleted(ChannelId channel_id) const {
|
||||||
|
auto c = get_channel(channel_id);
|
||||||
|
if (c == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return get_channel_can_be_deleted(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ContactsManager::get_channel_can_be_deleted(const Channel *c) {
|
||||||
|
return c->can_be_deleted;
|
||||||
|
}
|
||||||
|
|
||||||
ChannelId ContactsManager::get_channel_linked_channel_id(ChannelId channel_id) {
|
ChannelId ContactsManager::get_channel_linked_channel_id(ChannelId channel_id) {
|
||||||
auto channel_full = get_channel_full_const(channel_id);
|
auto channel_full = get_channel_full_const(channel_id);
|
||||||
if (channel_full == nullptr) {
|
if (channel_full == nullptr) {
|
||||||
|
@ -14875,17 +14930,6 @@ int32 ContactsManager::get_channel_slow_mode_delay(ChannelId channel_id) {
|
||||||
return channel_full->slow_mode_delay;
|
return channel_full->slow_mode_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContactsManager::get_channel_can_be_deleted(ChannelId channel_id) {
|
|
||||||
auto channel_full = get_channel_full_const(channel_id);
|
|
||||||
if (channel_full == nullptr) {
|
|
||||||
channel_full = get_channel_full_force(channel_id, true, "get_channel_can_be_deleted");
|
|
||||||
if (channel_full == nullptr) {
|
|
||||||
return get_channel_status(channel_id).is_creator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return channel_full->can_be_deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContactsManager::have_channel(ChannelId channel_id) const {
|
bool ContactsManager::have_channel(ChannelId channel_id) const {
|
||||||
return channels_.count(channel_id) > 0;
|
return channels_.count(channel_id) > 0;
|
||||||
}
|
}
|
||||||
|
@ -15310,6 +15354,7 @@ void ContactsManager::ban_dialog_participant(DialogId dialog_id, DialogId partic
|
||||||
return delete_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), revoke_messages,
|
return delete_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), revoke_messages,
|
||||||
std::move(promise));
|
std::move(promise));
|
||||||
case DialogType::Channel:
|
case DialogType::Channel:
|
||||||
|
// must use td_api::chatMemberStatusBanned to properly fix banned_until_date
|
||||||
return set_channel_participant_status(dialog_id.get_channel_id(), participant_dialog_id,
|
return set_channel_participant_status(dialog_id.get_channel_id(), participant_dialog_id,
|
||||||
td_api::make_object<td_api::chatMemberStatusBanned>(banned_until_date),
|
td_api::make_object<td_api::chatMemberStatusBanned>(banned_until_date),
|
||||||
std::move(promise));
|
std::move(promise));
|
||||||
|
@ -16710,26 +16755,35 @@ tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_
|
||||||
creates_join_request, is_public);
|
creates_join_request, is_public);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserId ContactsManager::get_support_user(Promise<Unit> &&promise) {
|
void ContactsManager::get_support_user(Promise<td_api::object_ptr<td_api::user>> &&promise) {
|
||||||
if (support_user_id_.is_valid()) {
|
if (support_user_id_.is_valid()) {
|
||||||
promise.set_value(Unit());
|
return promise.set_value(get_user_object(support_user_id_));
|
||||||
return support_user_id_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
td_->create_handler<GetSupportUserQuery>(std::move(promise))->send();
|
auto query_promise = PromiseCreator::lambda(
|
||||||
return UserId();
|
[actor_id = actor_id(this), promise = std::move(promise)](Result<UserId> &&result) mutable {
|
||||||
|
if (result.is_error()) {
|
||||||
|
promise.set_error(result.move_as_error());
|
||||||
|
} else {
|
||||||
|
send_closure(actor_id, &ContactsManager::on_get_support_user, result.move_as_ok(), std::move(promise));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
td_->create_handler<GetSupportUserQuery>(std::move(query_promise))->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::after_get_difference() {
|
void ContactsManager::on_get_support_user(UserId user_id, Promise<td_api::object_ptr<td_api::user>> &&promise) {
|
||||||
if (td_->auth_manager_->is_bot()) {
|
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||||
return;
|
|
||||||
}
|
|
||||||
get_user(get_my_id(), 3, Promise<Unit>());
|
|
||||||
|
|
||||||
if (td_->is_online()) {
|
const User *u = get_user(user_id);
|
||||||
reload_created_public_dialogs(PublicDialogType::HasUsername, Promise<td_api::object_ptr<td_api::chats>>());
|
if (u == nullptr) {
|
||||||
reload_created_public_dialogs(PublicDialogType::IsLocationBased, Promise<td_api::object_ptr<td_api::chats>>());
|
return promise.set_error(Status::Error(500, "Can't find support user"));
|
||||||
}
|
}
|
||||||
|
if (!u->is_support) {
|
||||||
|
LOG(ERROR) << "Receive non-support " << user_id << ", but expected a support user";
|
||||||
|
}
|
||||||
|
|
||||||
|
support_user_id_ = user_id;
|
||||||
|
promise.set_value(get_user_object(user_id, u));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
||||||
|
|
|
@ -151,8 +151,7 @@ class ContactsManager final : public Actor {
|
||||||
|
|
||||||
void reload_contacts(bool force);
|
void reload_contacts(bool force);
|
||||||
|
|
||||||
void on_get_user(tl_object_ptr<telegram_api::User> &&user, const char *source, bool is_me = false,
|
void on_get_user(tl_object_ptr<telegram_api::User> &&user, const char *source, bool is_me = false);
|
||||||
bool expect_support = false);
|
|
||||||
void on_get_users(vector<tl_object_ptr<telegram_api::User>> &&users, const char *source);
|
void on_get_users(vector<tl_object_ptr<telegram_api::User>> &&users, const char *source);
|
||||||
|
|
||||||
void on_binlog_user_event(BinlogEvent &&event);
|
void on_binlog_user_event(BinlogEvent &&event);
|
||||||
|
@ -441,6 +440,8 @@ class ContactsManager final : public Actor {
|
||||||
|
|
||||||
void check_created_public_dialogs_limit(PublicDialogType type, Promise<Unit> &&promise);
|
void check_created_public_dialogs_limit(PublicDialogType type, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void reload_created_public_dialogs(PublicDialogType type, Promise<td_api::object_ptr<td_api::chats>> &&promise);
|
||||||
|
|
||||||
vector<DialogId> get_dialogs_for_discussion(Promise<Unit> &&promise);
|
vector<DialogId> get_dialogs_for_discussion(Promise<Unit> &&promise);
|
||||||
|
|
||||||
vector<DialogId> get_inactive_channels(Promise<Unit> &&promise);
|
vector<DialogId> get_inactive_channels(Promise<Unit> &&promise);
|
||||||
|
@ -535,9 +536,9 @@ class ContactsManager final : public Actor {
|
||||||
int32 get_channel_participant_count(ChannelId channel_id) const;
|
int32 get_channel_participant_count(ChannelId channel_id) const;
|
||||||
bool get_channel_sign_messages(ChannelId channel_id) const;
|
bool get_channel_sign_messages(ChannelId channel_id) const;
|
||||||
bool get_channel_has_linked_channel(ChannelId channel_id) const;
|
bool get_channel_has_linked_channel(ChannelId channel_id) const;
|
||||||
|
bool get_channel_can_be_deleted(ChannelId channel_id) const;
|
||||||
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
|
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
|
||||||
int32 get_channel_slow_mode_delay(ChannelId channel_id);
|
int32 get_channel_slow_mode_delay(ChannelId channel_id);
|
||||||
bool get_channel_can_be_deleted(ChannelId channel_id);
|
|
||||||
|
|
||||||
void add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
void add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
@ -599,12 +600,10 @@ class ContactsManager final : public Actor {
|
||||||
|
|
||||||
tl_object_ptr<td_api::chatInviteLinkInfo> get_chat_invite_link_info_object(const string &invite_link);
|
tl_object_ptr<td_api::chatInviteLinkInfo> get_chat_invite_link_info_object(const string &invite_link);
|
||||||
|
|
||||||
UserId get_support_user(Promise<Unit> &&promise);
|
void get_support_user(Promise<td_api::object_ptr<td_api::user>> &&promise);
|
||||||
|
|
||||||
void repair_chat_participants(ChatId chat_id);
|
void repair_chat_participants(ChatId chat_id);
|
||||||
|
|
||||||
void after_get_difference();
|
|
||||||
|
|
||||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||||
|
|
||||||
static tl_object_ptr<td_api::dateRange> convert_date_range(
|
static tl_object_ptr<td_api::dateRange> convert_date_range(
|
||||||
|
@ -835,6 +834,7 @@ class ContactsManager final : public Actor {
|
||||||
bool sign_messages = false;
|
bool sign_messages = false;
|
||||||
bool is_slow_mode_enabled = false;
|
bool is_slow_mode_enabled = false;
|
||||||
bool noforwards = false;
|
bool noforwards = false;
|
||||||
|
bool can_be_deleted = false;
|
||||||
|
|
||||||
bool is_megagroup = false;
|
bool is_megagroup = false;
|
||||||
bool is_gigagroup = false;
|
bool is_gigagroup = false;
|
||||||
|
@ -1213,6 +1213,7 @@ class ContactsManager final : public Actor {
|
||||||
DialogParticipantStatus get_channel_permissions(const Channel *c) const;
|
DialogParticipantStatus get_channel_permissions(const Channel *c) const;
|
||||||
static bool get_channel_sign_messages(const Channel *c);
|
static bool get_channel_sign_messages(const Channel *c);
|
||||||
static bool get_channel_has_linked_channel(const Channel *c);
|
static bool get_channel_has_linked_channel(const Channel *c);
|
||||||
|
static bool get_channel_can_be_deleted(const Channel *c);
|
||||||
|
|
||||||
void set_my_id(UserId my_id);
|
void set_my_id(UserId my_id);
|
||||||
|
|
||||||
|
@ -1260,7 +1261,7 @@ class ContactsManager final : public Actor {
|
||||||
void on_update_chat_participant_count(Chat *c, ChatId chat_id, int32 participant_count, int32 version,
|
void on_update_chat_participant_count(Chat *c, ChatId chat_id, int32 participant_count, int32 version,
|
||||||
const string &debug_str);
|
const string &debug_str);
|
||||||
void on_update_chat_photo(Chat *c, ChatId chat_id, tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr);
|
void on_update_chat_photo(Chat *c, ChatId chat_id, tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr);
|
||||||
void on_update_chat_photo(Chat *c, DialogPhoto &&photo);
|
void on_update_chat_photo(Chat *c, ChatId chat_id, DialogPhoto &&photo, bool invalidate_photo_cache);
|
||||||
static void on_update_chat_title(Chat *c, ChatId chat_id, string &&title);
|
static void on_update_chat_title(Chat *c, ChatId chat_id, string &&title);
|
||||||
static void on_update_chat_active(Chat *c, ChatId chat_id, bool is_active);
|
static void on_update_chat_active(Chat *c, ChatId chat_id, bool is_active);
|
||||||
static void on_update_chat_migrated_to_channel_id(Chat *c, ChatId chat_id, ChannelId migrated_to_channel_id);
|
static void on_update_chat_migrated_to_channel_id(Chat *c, ChatId chat_id, ChannelId migrated_to_channel_id);
|
||||||
|
@ -1275,7 +1276,7 @@ class ContactsManager final : public Actor {
|
||||||
|
|
||||||
void on_update_channel_photo(Channel *c, ChannelId channel_id,
|
void on_update_channel_photo(Channel *c, ChannelId channel_id,
|
||||||
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr);
|
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr);
|
||||||
void on_update_channel_photo(Channel *c, DialogPhoto &&photo);
|
void on_update_channel_photo(Channel *c, ChannelId channel_id, DialogPhoto &&photo, bool invalidate_photo_cache);
|
||||||
static void on_update_channel_title(Channel *c, ChannelId channel_id, string &&title);
|
static void on_update_channel_title(Channel *c, ChannelId channel_id, string &&title);
|
||||||
void on_update_channel_username(Channel *c, ChannelId channel_id, string &&username);
|
void on_update_channel_username(Channel *c, ChannelId channel_id, string &&username);
|
||||||
void on_update_channel_status(Channel *c, ChannelId channel_id, DialogParticipantStatus &&status);
|
void on_update_channel_status(Channel *c, ChannelId channel_id, DialogParticipantStatus &&status);
|
||||||
|
@ -1457,8 +1458,6 @@ class ContactsManager final : public Actor {
|
||||||
static void return_created_public_dialogs(Promise<td_api::object_ptr<td_api::chats>> &&promise,
|
static void return_created_public_dialogs(Promise<td_api::object_ptr<td_api::chats>> &&promise,
|
||||||
const vector<ChannelId> &channel_ids);
|
const vector<ChannelId> &channel_ids);
|
||||||
|
|
||||||
void reload_created_public_dialogs(PublicDialogType type, Promise<td_api::object_ptr<td_api::chats>> &&promise);
|
|
||||||
|
|
||||||
void finish_get_created_public_dialogs(PublicDialogType type, Result<Unit> &&result);
|
void finish_get_created_public_dialogs(PublicDialogType type, Result<Unit> &&result);
|
||||||
|
|
||||||
void update_created_public_channels(Channel *c, ChannelId channel_id);
|
void update_created_public_channels(Channel *c, ChannelId channel_id);
|
||||||
|
@ -1640,6 +1639,8 @@ class ContactsManager final : public Actor {
|
||||||
void send_load_async_graph_query(DcId dc_id, string token, int64 x,
|
void send_load_async_graph_query(DcId dc_id, string token, int64 x,
|
||||||
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise);
|
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise);
|
||||||
|
|
||||||
|
void on_get_support_user(UserId user_id, Promise<td_api::object_ptr<td_api::user>> &&promise);
|
||||||
|
|
||||||
static void on_user_online_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
|
static void on_user_online_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
|
||||||
|
|
||||||
static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
|
static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
|
||||||
|
|
|
@ -569,6 +569,20 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant
|
||||||
DialogParticipantStatus get_dialog_participant_status(const td_api::object_ptr<td_api::ChatMemberStatus> &status,
|
DialogParticipantStatus get_dialog_participant_status(const td_api::object_ptr<td_api::ChatMemberStatus> &status,
|
||||||
ChannelType channel_type) {
|
ChannelType channel_type) {
|
||||||
auto constructor_id = status == nullptr ? td_api::chatMemberStatusMember::ID : status->get_id();
|
auto constructor_id = status == nullptr ? td_api::chatMemberStatusMember::ID : status->get_id();
|
||||||
|
auto fix_until_date = [](int32 until_date) {
|
||||||
|
if (until_date == 0) {
|
||||||
|
// fast path
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user is restricted for more than 366 days or less than 30 seconds from the current time,
|
||||||
|
// they are considered to be restricted forever
|
||||||
|
auto unix_time = G()->unix_time();
|
||||||
|
if (until_date < unix_time + 30 || until_date > unix_time + 366 * 86400) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return until_date;
|
||||||
|
};
|
||||||
switch (constructor_id) {
|
switch (constructor_id) {
|
||||||
case td_api::chatMemberStatusCreator::ID: {
|
case td_api::chatMemberStatusCreator::ID: {
|
||||||
auto st = static_cast<const td_api::chatMemberStatusCreator *>(status.get());
|
auto st = static_cast<const td_api::chatMemberStatusCreator *>(status.get());
|
||||||
|
@ -592,13 +606,13 @@ DialogParticipantStatus get_dialog_participant_status(const td_api::object_ptr<t
|
||||||
case td_api::chatMemberStatusRestricted::ID: {
|
case td_api::chatMemberStatusRestricted::ID: {
|
||||||
auto st = static_cast<const td_api::chatMemberStatusRestricted *>(status.get());
|
auto st = static_cast<const td_api::chatMemberStatusRestricted *>(status.get());
|
||||||
return DialogParticipantStatus::Restricted(RestrictedRights(st->permissions_), st->is_member_,
|
return DialogParticipantStatus::Restricted(RestrictedRights(st->permissions_), st->is_member_,
|
||||||
st->restricted_until_date_);
|
fix_until_date(st->restricted_until_date_));
|
||||||
}
|
}
|
||||||
case td_api::chatMemberStatusLeft::ID:
|
case td_api::chatMemberStatusLeft::ID:
|
||||||
return DialogParticipantStatus::Left();
|
return DialogParticipantStatus::Left();
|
||||||
case td_api::chatMemberStatusBanned::ID: {
|
case td_api::chatMemberStatusBanned::ID: {
|
||||||
auto st = static_cast<const td_api::chatMemberStatusBanned *>(status.get());
|
auto st = static_cast<const td_api::chatMemberStatusBanned *>(status.get());
|
||||||
return DialogParticipantStatus::Banned(st->banned_until_date_);
|
return DialogParticipantStatus::Banned(fix_until_date(st->banned_until_date_));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
|
|
@ -593,8 +593,7 @@ SecretInputMedia DocumentsManager::get_secret_input_media(FileId document_file_i
|
||||||
const GeneralDocument *document = get_document(document_file_id);
|
const GeneralDocument *document = get_document(document_file_id);
|
||||||
CHECK(document != nullptr);
|
CHECK(document != nullptr);
|
||||||
auto file_view = td_->file_manager_->get_file_view(document_file_id);
|
auto file_view = td_->file_manager_->get_file_view(document_file_id);
|
||||||
auto &encryption_key = file_view.encryption_key();
|
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||||
if (!file_view.is_encrypted_secret() || encryption_key.empty()) {
|
|
||||||
return SecretInputMedia{};
|
return SecretInputMedia{};
|
||||||
}
|
}
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
|
@ -610,12 +609,13 @@ SecretInputMedia DocumentsManager::get_secret_input_media(FileId document_file_i
|
||||||
if (!document->file_name.empty()) {
|
if (!document->file_name.empty()) {
|
||||||
attributes.push_back(make_tl_object<secret_api::documentAttributeFilename>(document->file_name));
|
attributes.push_back(make_tl_object<secret_api::documentAttributeFilename>(document->file_name));
|
||||||
}
|
}
|
||||||
return SecretInputMedia{
|
return {std::move(input_file),
|
||||||
std::move(input_file),
|
std::move(thumbnail),
|
||||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
document->thumbnail.dimensions,
|
||||||
std::move(thumbnail), document->thumbnail.dimensions.width, document->thumbnail.dimensions.height,
|
document->mime_type,
|
||||||
document->mime_type, narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
file_view,
|
||||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption)};
|
std::move(attributes),
|
||||||
|
caption};
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputMedia> DocumentsManager::get_input_media(
|
tl_object_ptr<telegram_api::InputMedia> DocumentsManager::get_input_media(
|
||||||
|
|
|
@ -1647,7 +1647,11 @@ void GroupCallManager::on_get_group_call_participants(
|
||||||
if (is_load) {
|
if (is_load) {
|
||||||
auto *group_call_participants = add_group_call_participants(input_group_call_id);
|
auto *group_call_participants = add_group_call_participants(input_group_call_id);
|
||||||
if (group_call_participants->next_offset == offset) {
|
if (group_call_participants->next_offset == offset) {
|
||||||
group_call_participants->next_offset = std::move(participants->next_offset_);
|
if (!offset.empty() && participants->next_offset_.empty() && group_call_participants->joined_date_asc) {
|
||||||
|
LOG(INFO) << "Ignore empty next_offset";
|
||||||
|
} else {
|
||||||
|
group_call_participants->next_offset = std::move(participants->next_offset_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_empty || is_sync) {
|
if (is_empty || is_sync) {
|
||||||
|
@ -1826,6 +1830,8 @@ void GroupCallManager::on_update_group_call_participants(
|
||||||
|
|
||||||
auto &pending_version_updates = group_call_participants->pending_version_updates_[version].updates;
|
auto &pending_version_updates = group_call_participants->pending_version_updates_[version].updates;
|
||||||
auto &pending_mute_updates = group_call_participants->pending_mute_updates_[version].updates;
|
auto &pending_mute_updates = group_call_participants->pending_mute_updates_[version].updates;
|
||||||
|
LOG(INFO) << "Have " << pending_version_updates.size() << " versioned and " << pending_mute_updates.size()
|
||||||
|
<< " mute pending updates for " << input_group_call_id;
|
||||||
for (auto &group_call_participant : participants) {
|
for (auto &group_call_participant : participants) {
|
||||||
GroupCallParticipant participant(group_call_participant, version);
|
GroupCallParticipant participant(group_call_participant, version);
|
||||||
if (!participant.is_valid()) {
|
if (!participant.is_valid()) {
|
||||||
|
@ -1879,6 +1885,9 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
|
||||||
auto &pending_version_updates = participants_it->second->pending_version_updates_;
|
auto &pending_version_updates = participants_it->second->pending_version_updates_;
|
||||||
auto &pending_mute_updates = participants_it->second->pending_mute_updates_;
|
auto &pending_mute_updates = participants_it->second->pending_mute_updates_;
|
||||||
|
|
||||||
|
LOG(INFO) << "Process " << pending_version_updates.size() << " versioned and " << pending_mute_updates.size()
|
||||||
|
<< " mute updates for " << input_group_call_id;
|
||||||
|
|
||||||
auto process_mute_updates = [&] {
|
auto process_mute_updates = [&] {
|
||||||
while (!pending_mute_updates.empty()) {
|
while (!pending_mute_updates.empty()) {
|
||||||
auto it = pending_mute_updates.begin();
|
auto it = pending_mute_updates.begin();
|
||||||
|
@ -2036,7 +2045,7 @@ void GroupCallManager::on_sync_group_call_participants(InputGroupCallId input_gr
|
||||||
GroupCallParticipantOrder GroupCallManager::get_real_participant_order(bool can_self_unmute,
|
GroupCallParticipantOrder GroupCallManager::get_real_participant_order(bool can_self_unmute,
|
||||||
const GroupCallParticipant &participant,
|
const GroupCallParticipant &participant,
|
||||||
const GroupCallParticipants *participants) {
|
const GroupCallParticipants *participants) {
|
||||||
auto real_order = participant.get_real_order(can_self_unmute, participants->joined_date_asc, false);
|
auto real_order = participant.get_real_order(can_self_unmute, participants->joined_date_asc);
|
||||||
if (real_order >= participants->min_order) {
|
if (real_order >= participants->min_order) {
|
||||||
return real_order;
|
return real_order;
|
||||||
}
|
}
|
||||||
|
@ -2106,7 +2115,7 @@ void GroupCallManager::process_group_call_participants(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_load) {
|
if (is_load) {
|
||||||
auto real_order = participant.get_real_order(can_self_unmute, joined_date_asc, true);
|
auto real_order = participant.get_server_order(can_self_unmute, joined_date_asc);
|
||||||
if (real_order > min_order) {
|
if (real_order > min_order) {
|
||||||
LOG(ERROR) << "Receive group call participant " << participant.dialog_id << " with order " << real_order
|
LOG(ERROR) << "Receive group call participant " << participant.dialog_id << " with order " << real_order
|
||||||
<< " after group call participant " << debug_min_order_dialog_id << " with order " << min_order;
|
<< " after group call participant " << debug_min_order_dialog_id << " with order " << min_order;
|
||||||
|
@ -4122,7 +4131,11 @@ void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_
|
||||||
auto input_group_call_id = get_input_group_call_id(group_call->group_call_id).ok();
|
auto input_group_call_id = get_input_group_call_id(group_call->group_call_id).ok();
|
||||||
try_clear_group_call_participants(input_group_call_id);
|
try_clear_group_call_participants(input_group_call_id);
|
||||||
if (!group_call->need_rejoin) {
|
if (!group_call->need_rejoin) {
|
||||||
process_group_call_after_join_requests(input_group_call_id, "on_group_call_left_impl");
|
if (is_group_call_being_joined(input_group_call_id)) {
|
||||||
|
LOG(ERROR) << "Left a being joined group call. Did you change audio_source_id without leaving the group call?";
|
||||||
|
} else {
|
||||||
|
process_group_call_after_join_requests(input_group_call_id, "on_group_call_left_impl");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,10 +75,16 @@ bool GroupCallParticipant::is_versioned_update(const tl_object_ptr<telegram_api:
|
||||||
return participant->just_joined_ || participant->left_ || participant->versioned_;
|
return participant->just_joined_ || participant->left_ || participant->versioned_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallParticipantOrder GroupCallParticipant::get_real_order(bool can_self_unmute, bool joined_date_asc,
|
GroupCallParticipantOrder GroupCallParticipant::get_real_order(bool can_self_unmute, bool joined_date_asc) const {
|
||||||
bool keep_active_date) const {
|
|
||||||
auto sort_active_date = td::max(active_date, local_active_date);
|
auto sort_active_date = td::max(active_date, local_active_date);
|
||||||
if (!keep_active_date && sort_active_date < G()->unix_time() - 300) {
|
if (sort_active_date == 0 && !get_is_muted_by_admin()) { // if the participant isn't muted by admin
|
||||||
|
if (get_is_muted_by_themselves()) {
|
||||||
|
sort_active_date = joined_date;
|
||||||
|
} else {
|
||||||
|
sort_active_date = G()->unix_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sort_active_date < G()->unix_time() - 300) {
|
||||||
sort_active_date = 0;
|
sort_active_date = 0;
|
||||||
}
|
}
|
||||||
auto sort_raise_hand_rating = can_self_unmute ? raise_hand_rating : 0;
|
auto sort_raise_hand_rating = can_self_unmute ? raise_hand_rating : 0;
|
||||||
|
@ -87,6 +93,21 @@ GroupCallParticipantOrder GroupCallParticipant::get_real_order(bool can_self_unm
|
||||||
return GroupCallParticipantOrder(has_video, sort_active_date, sort_raise_hand_rating, sort_joined_date);
|
return GroupCallParticipantOrder(has_video, sort_active_date, sort_raise_hand_rating, sort_joined_date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GroupCallParticipantOrder GroupCallParticipant::get_server_order(bool can_self_unmute, bool joined_date_asc) const {
|
||||||
|
auto sort_active_date = active_date;
|
||||||
|
if (sort_active_date == 0 && !server_is_muted_by_admin) { // if the participant isn't muted by admin
|
||||||
|
if (server_is_muted_by_themselves) {
|
||||||
|
sort_active_date = joined_date;
|
||||||
|
} else {
|
||||||
|
sort_active_date = G()->unix_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto sort_raise_hand_rating = can_self_unmute ? raise_hand_rating : 0;
|
||||||
|
auto sort_joined_date = joined_date_asc ? std::numeric_limits<int32>::max() - joined_date : joined_date;
|
||||||
|
bool has_video = !video_payload.is_empty() || !presentation_payload.is_empty();
|
||||||
|
return GroupCallParticipantOrder(has_video, sort_active_date, sort_raise_hand_rating, sort_joined_date);
|
||||||
|
}
|
||||||
|
|
||||||
bool GroupCallParticipant::get_is_muted_by_themselves() const {
|
bool GroupCallParticipant::get_is_muted_by_themselves() const {
|
||||||
return have_pending_is_muted ? pending_is_muted_by_themselves : server_is_muted_by_themselves;
|
return have_pending_is_muted ? pending_is_muted_by_themselves : server_is_muted_by_themselves;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,9 @@ struct GroupCallParticipant {
|
||||||
|
|
||||||
bool set_pending_is_muted(bool is_muted, bool can_manage, bool is_admin);
|
bool set_pending_is_muted(bool is_muted, bool can_manage, bool is_admin);
|
||||||
|
|
||||||
GroupCallParticipantOrder get_real_order(bool can_self_unmute, bool joined_date_asc, bool keep_active_date) const;
|
GroupCallParticipantOrder get_real_order(bool can_self_unmute, bool joined_date_asc) const;
|
||||||
|
|
||||||
|
GroupCallParticipantOrder get_server_order(bool can_self_unmute, bool joined_date_asc) const;
|
||||||
|
|
||||||
bool is_valid() const {
|
bool is_valid() const {
|
||||||
return dialog_id.is_valid();
|
return dialog_id.is_valid();
|
||||||
|
|
|
@ -667,7 +667,7 @@ class MessageDice final : public MessageContent {
|
||||||
|
|
||||||
MessageDice() = default;
|
MessageDice() = default;
|
||||||
MessageDice(const string &emoji, int32 dice_value)
|
MessageDice(const string &emoji, int32 dice_value)
|
||||||
: emoji(emoji.empty() ? string(DEFAULT_EMOJI) : remove_emoji_modifiers(emoji).str()), dice_value(dice_value) {
|
: emoji(emoji.empty() ? string(DEFAULT_EMOJI) : remove_emoji_modifiers(emoji)), dice_value(dice_value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageContentType get_type() const final {
|
MessageContentType get_type() const final {
|
||||||
|
@ -2100,10 +2100,10 @@ Result<InputMessageContent> get_input_message_content(
|
||||||
std::move(thumbnail), std::move(sticker_file_ids));
|
std::move(thumbnail), std::move(sticker_file_ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_have_input_media(const Td *td, const MessageContent *content) {
|
bool can_have_input_media(const Td *td, const MessageContent *content, bool is_server) {
|
||||||
switch (content->get_type()) {
|
switch (content->get_type()) {
|
||||||
case MessageContentType::Game:
|
case MessageContentType::Game:
|
||||||
return static_cast<const MessageGame *>(content)->game.has_input_media();
|
return is_server || static_cast<const MessageGame *>(content)->game.has_input_media();
|
||||||
case MessageContentType::Poll:
|
case MessageContentType::Poll:
|
||||||
return td->poll_manager_->has_input_media(static_cast<const MessagePoll *>(content)->poll_id);
|
return td->poll_manager_->has_input_media(static_cast<const MessagePoll *>(content)->poll_id);
|
||||||
case MessageContentType::Unsupported:
|
case MessageContentType::Unsupported:
|
||||||
|
@ -2264,7 +2264,7 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
|
||||||
static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
|
static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
|
||||||
const MessageContent *content, Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
|
const MessageContent *content, Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
|
||||||
tl_object_ptr<telegram_api::InputFile> input_thumbnail, int32 ttl, const string &emoji) {
|
tl_object_ptr<telegram_api::InputFile> input_thumbnail, int32 ttl, const string &emoji) {
|
||||||
if (!can_have_input_media(td, content)) {
|
if (!can_have_input_media(td, content, false)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
switch (content->get_type()) {
|
switch (content->get_type()) {
|
||||||
|
@ -4358,10 +4358,10 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
||||||
MessageContentDupType type, MessageCopyOptions &©_options) {
|
MessageContentDupType type, MessageCopyOptions &©_options) {
|
||||||
CHECK(content != nullptr);
|
CHECK(content != nullptr);
|
||||||
if (copy_options.send_copy) {
|
if (copy_options.send_copy) {
|
||||||
CHECK(type == MessageContentDupType::Copy);
|
CHECK(type == MessageContentDupType::Copy || type == MessageContentDupType::ServerCopy);
|
||||||
}
|
}
|
||||||
if (type != MessageContentDupType::Forward && type != MessageContentDupType::SendViaBot &&
|
if (type != MessageContentDupType::Forward && type != MessageContentDupType::SendViaBot &&
|
||||||
!can_have_input_media(td, content)) {
|
!can_have_input_media(td, content, type == MessageContentDupType::ServerCopy)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4382,7 +4382,8 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
||||||
if (to_secret) {
|
if (to_secret) {
|
||||||
thumbnail_file_id = get_message_content_thumbnail_file_id(content, td);
|
thumbnail_file_id = get_message_content_thumbnail_file_id(content, td);
|
||||||
}
|
}
|
||||||
auto replace_caption = type == MessageContentDupType::Copy && copy_options.replace_caption;
|
auto replace_caption = (type == MessageContentDupType::Copy || type == MessageContentDupType::ServerCopy) &&
|
||||||
|
copy_options.replace_caption;
|
||||||
switch (content->get_type()) {
|
switch (content->get_type()) {
|
||||||
case MessageContentType::Animation: {
|
case MessageContentType::Animation: {
|
||||||
auto result = make_unique<MessageAnimation>(*static_cast<const MessageAnimation *>(content));
|
auto result = make_unique<MessageAnimation>(*static_cast<const MessageAnimation *>(content));
|
||||||
|
@ -4512,7 +4513,7 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
case MessageContentType::Poll:
|
case MessageContentType::Poll:
|
||||||
if (type == MessageContentDupType::Copy) {
|
if (type == MessageContentDupType::Copy || type == MessageContentDupType::ServerCopy) {
|
||||||
return make_unique<MessagePoll>(
|
return make_unique<MessagePoll>(
|
||||||
td->poll_manager_->dup_poll(static_cast<const MessagePoll *>(content)->poll_id));
|
td->poll_manager_->dup_poll(static_cast<const MessagePoll *>(content)->poll_id));
|
||||||
} else {
|
} else {
|
||||||
|
@ -5505,17 +5506,17 @@ void get_message_content_animated_emoji_click_sticker(const MessageContent *cont
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_message_content_animated_emoji_clicked(const MessageContent *content, FullMessageId full_message_id, Td *td,
|
void on_message_content_animated_emoji_clicked(const MessageContent *content, FullMessageId full_message_id, Td *td,
|
||||||
Slice emoji, string data) {
|
string &&emoji, string &&data) {
|
||||||
if (content->get_type() != MessageContentType::Text) {
|
if (content->get_type() != MessageContentType::Text) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emoji = remove_emoji_modifiers(emoji);
|
remove_emoji_modifiers_in_place(emoji);
|
||||||
auto &text = static_cast<const MessageText *>(content)->text;
|
auto &text = static_cast<const MessageText *>(content)->text;
|
||||||
if (!text.entities.empty() || remove_emoji_modifiers(text.text) != emoji) {
|
if (!text.entities.empty() || remove_emoji_modifiers(text.text) != emoji) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto error = td->stickers_manager_->on_animated_emoji_message_clicked(emoji, full_message_id, data);
|
auto error = td->stickers_manager_->on_animated_emoji_message_clicked(std::move(emoji), full_message_id, data);
|
||||||
if (error.is_error()) {
|
if (error.is_error()) {
|
||||||
LOG(WARNING) << "Failed to process animated emoji click with data \"" << data << "\": " << error;
|
LOG(WARNING) << "Failed to process animated emoji click with data \"" << data << "\": " << error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ unique_ptr<MessageContent> create_chat_set_ttl_message_content(int32 ttl);
|
||||||
Result<InputMessageContent> get_input_message_content(
|
Result<InputMessageContent> get_input_message_content(
|
||||||
DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Td *td);
|
DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Td *td);
|
||||||
|
|
||||||
bool can_have_input_media(const Td *td, const MessageContent *content);
|
bool can_have_input_media(const Td *td, const MessageContent *content, bool is_server);
|
||||||
|
|
||||||
SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
|
SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
|
||||||
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
|
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
|
||||||
|
@ -192,7 +192,7 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message_tex
|
||||||
DialogId owner_dialog_id, bool is_content_read, UserId via_bot_user_id,
|
DialogId owner_dialog_id, bool is_content_read, UserId via_bot_user_id,
|
||||||
int32 *ttl, bool *disable_web_page_preview);
|
int32 *ttl, bool *disable_web_page_preview);
|
||||||
|
|
||||||
enum class MessageContentDupType : int32 { Send, SendViaBot, Forward, Copy };
|
enum class MessageContentDupType : int32 { Send, SendViaBot, Forward, Copy, ServerCopy };
|
||||||
|
|
||||||
unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content,
|
unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content,
|
||||||
MessageContentDupType type, MessageCopyOptions &©_options);
|
MessageContentDupType type, MessageCopyOptions &©_options);
|
||||||
|
@ -232,7 +232,7 @@ void get_message_content_animated_emoji_click_sticker(const MessageContent *cont
|
||||||
Td *td, Promise<td_api::object_ptr<td_api::sticker>> &&promise);
|
Td *td, Promise<td_api::object_ptr<td_api::sticker>> &&promise);
|
||||||
|
|
||||||
void on_message_content_animated_emoji_clicked(const MessageContent *content, FullMessageId full_message_id, Td *td,
|
void on_message_content_animated_emoji_clicked(const MessageContent *content, FullMessageId full_message_id, Td *td,
|
||||||
Slice emoji, string data);
|
string &&emoji, string &&data);
|
||||||
|
|
||||||
bool need_reget_message_content(const MessageContent *content);
|
bool need_reget_message_content(const MessageContent *content);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,17 @@ struct MessageCopyOptions {
|
||||||
MessageCopyOptions() = default;
|
MessageCopyOptions() = default;
|
||||||
MessageCopyOptions(bool send_copy, bool remove_caption) : send_copy(send_copy), replace_caption(remove_caption) {
|
MessageCopyOptions(bool send_copy, bool remove_caption) : send_copy(send_copy), replace_caption(remove_caption) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_supported_server_side() const {
|
||||||
|
if (!send_copy) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((replace_caption && !new_caption.text.empty()) || top_thread_message_id.is_valid() ||
|
||||||
|
reply_to_message_id.is_valid() || reply_markup != nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline StringBuilder &operator<<(StringBuilder &string_builder, MessageCopyOptions copy_options) {
|
inline StringBuilder &operator<<(StringBuilder &string_builder, MessageCopyOptions copy_options) {
|
||||||
|
|
|
@ -4545,8 +4545,6 @@ class ResolveUsernameQuery final : public Td::ResultHandler {
|
||||||
|
|
||||||
class MessagesManager::UploadMediaCallback final : public FileManager::UploadCallback {
|
class MessagesManager::UploadMediaCallback final : public FileManager::UploadCallback {
|
||||||
public:
|
public:
|
||||||
void on_progress(FileId file_id) final {
|
|
||||||
}
|
|
||||||
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
|
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
|
||||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_upload_media, file_id, std::move(input_file),
|
send_closure_later(G()->messages_manager(), &MessagesManager::on_upload_media, file_id, std::move(input_file),
|
||||||
nullptr);
|
nullptr);
|
||||||
|
@ -7453,8 +7451,8 @@ void MessagesManager::on_dialog_action(DialogId dialog_id, MessageId top_thread_
|
||||||
FullMessageId full_message_id{dialog_id, MessageId(ServerMessageId(clicking_info.message_id))};
|
FullMessageId full_message_id{dialog_id, MessageId(ServerMessageId(clicking_info.message_id))};
|
||||||
auto *m = get_message_force(full_message_id, "on_dialog_action");
|
auto *m = get_message_force(full_message_id, "on_dialog_action");
|
||||||
if (m != nullptr) {
|
if (m != nullptr) {
|
||||||
on_message_content_animated_emoji_clicked(m->content.get(), full_message_id, td_, clicking_info.emoji,
|
on_message_content_animated_emoji_clicked(m->content.get(), full_message_id, td_,
|
||||||
std::move(clicking_info.data));
|
std::move(clicking_info.emoji), std::move(clicking_info.data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -9612,8 +9610,8 @@ void MessagesManager::on_get_messages(vector<tl_object_ptr<telegram_api::Message
|
||||||
bool is_scheduled, Promise<Unit> &&promise, const char *source) {
|
bool is_scheduled, Promise<Unit> &&promise, const char *source) {
|
||||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||||
|
|
||||||
LOG(DEBUG) << "Receive " << messages.size() << " messages";
|
|
||||||
for (auto &message : messages) {
|
for (auto &message : messages) {
|
||||||
|
LOG(INFO) << "Receive " << to_string(message);
|
||||||
on_get_message(std::move(message), false, is_channel_message, is_scheduled, false, false, source);
|
on_get_message(std::move(message), false, is_channel_message, is_scheduled, false, false, source);
|
||||||
}
|
}
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
|
@ -15138,7 +15136,7 @@ void MessagesManager::remove_dialog_mention_notifications(Dialog *d) {
|
||||||
CHECK(m != nullptr);
|
CHECK(m != nullptr);
|
||||||
CHECK(m->message_id.is_valid());
|
CHECK(m->message_id.is_valid());
|
||||||
if (m->notification_id.is_valid() && is_message_notification_active(d, m) &&
|
if (m->notification_id.is_valid() && is_message_notification_active(d, m) &&
|
||||||
is_from_mention_notification_group(d, m)) {
|
is_from_mention_notification_group(m)) {
|
||||||
removed_notification_ids_set.insert(m->notification_id);
|
removed_notification_ids_set.insert(m->notification_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15150,7 +15148,7 @@ void MessagesManager::remove_dialog_mention_notifications(Dialog *d) {
|
||||||
if (message_id != d->pinned_message_notification_message_id) {
|
if (message_id != d->pinned_message_notification_message_id) {
|
||||||
auto m = get_message_force(d, message_id, "remove_dialog_mention_notifications");
|
auto m = get_message_force(d, message_id, "remove_dialog_mention_notifications");
|
||||||
if (m != nullptr && m->notification_id.is_valid() && is_message_notification_active(d, m)) {
|
if (m != nullptr && m->notification_id.is_valid() && is_message_notification_active(d, m)) {
|
||||||
CHECK(is_from_mention_notification_group(d, m));
|
CHECK(is_from_mention_notification_group(m));
|
||||||
removed_notification_ids_set.insert(m->notification_id);
|
removed_notification_ids_set.insert(m->notification_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15846,7 +15844,7 @@ void MessagesManager::remove_message_notification_id(Dialog *d, Message *m, bool
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto from_mentions = is_from_mention_notification_group(d, m);
|
auto from_mentions = is_from_mention_notification_group(m);
|
||||||
auto &group_info = get_notification_group_info(d, m);
|
auto &group_info = get_notification_group_info(d, m);
|
||||||
if (!group_info.group_id.is_valid()) {
|
if (!group_info.group_id.is_valid()) {
|
||||||
return;
|
return;
|
||||||
|
@ -15913,7 +15911,7 @@ void MessagesManager::fix_dialog_last_notification_id(Dialog *d, bool from_menti
|
||||||
if (*it != nullptr && ((*it)->message_id == message_id || (*it)->have_next)) {
|
if (*it != nullptr && ((*it)->message_id == message_id || (*it)->have_next)) {
|
||||||
while (*it != nullptr) {
|
while (*it != nullptr) {
|
||||||
const Message *m = *it;
|
const Message *m = *it;
|
||||||
if (is_from_mention_notification_group(d, m) == from_mentions && m->notification_id.is_valid() &&
|
if (is_from_mention_notification_group(m) == from_mentions && m->notification_id.is_valid() &&
|
||||||
is_message_notification_active(d, m) && m->message_id != message_id) {
|
is_message_notification_active(d, m) && m->message_id != message_id) {
|
||||||
bool is_fixed = set_dialog_last_notification(d->dialog_id, group_info, m->date, m->notification_id,
|
bool is_fixed = set_dialog_last_notification(d->dialog_id, group_info, m->date, m->notification_id,
|
||||||
"fix_dialog_last_notification_id");
|
"fix_dialog_last_notification_id");
|
||||||
|
@ -26567,7 +26565,7 @@ bool MessagesManager::can_resend_message(const Message *m) const {
|
||||||
auto content_type = m->content->get_type();
|
auto content_type = m->content->get_type();
|
||||||
if (m->via_bot_user_id.is_valid() || m->hide_via_bot) {
|
if (m->via_bot_user_id.is_valid() || m->hide_via_bot) {
|
||||||
// via bot message
|
// via bot message
|
||||||
if (!can_have_input_media(td_, m->content.get())) {
|
if (!can_have_input_media(td_, m->content.get(), false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27737,10 +27735,16 @@ class MessagesManager::ForwardMessagesLogEvent {
|
||||||
DialogId from_dialog_id;
|
DialogId from_dialog_id;
|
||||||
vector<MessageId> message_ids;
|
vector<MessageId> message_ids;
|
||||||
vector<Message *> messages_in;
|
vector<Message *> messages_in;
|
||||||
|
bool drop_author;
|
||||||
|
bool drop_media_captions;
|
||||||
vector<unique_ptr<Message>> messages_out;
|
vector<unique_ptr<Message>> messages_out;
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
|
BEGIN_STORE_FLAGS();
|
||||||
|
STORE_FLAG(drop_author);
|
||||||
|
STORE_FLAG(drop_media_captions);
|
||||||
|
END_STORE_FLAGS();
|
||||||
td::store(to_dialog_id, storer);
|
td::store(to_dialog_id, storer);
|
||||||
td::store(from_dialog_id, storer);
|
td::store(from_dialog_id, storer);
|
||||||
td::store(message_ids, storer);
|
td::store(message_ids, storer);
|
||||||
|
@ -27749,6 +27753,12 @@ class MessagesManager::ForwardMessagesLogEvent {
|
||||||
|
|
||||||
template <class ParserT>
|
template <class ParserT>
|
||||||
void parse(ParserT &parser) {
|
void parse(ParserT &parser) {
|
||||||
|
if (parser.version() >= static_cast<int32>(Version::UseServerForwardAsCopy)) {
|
||||||
|
BEGIN_PARSE_FLAGS();
|
||||||
|
PARSE_FLAG(drop_author);
|
||||||
|
PARSE_FLAG(drop_media_captions);
|
||||||
|
END_PARSE_FLAGS();
|
||||||
|
}
|
||||||
td::parse(to_dialog_id, parser);
|
td::parse(to_dialog_id, parser);
|
||||||
td::parse(from_dialog_id, parser);
|
td::parse(from_dialog_id, parser);
|
||||||
td::parse(message_ids, parser);
|
td::parse(message_ids, parser);
|
||||||
|
@ -27758,15 +27768,17 @@ class MessagesManager::ForwardMessagesLogEvent {
|
||||||
|
|
||||||
uint64 MessagesManager::save_forward_messages_log_event(DialogId to_dialog_id, DialogId from_dialog_id,
|
uint64 MessagesManager::save_forward_messages_log_event(DialogId to_dialog_id, DialogId from_dialog_id,
|
||||||
const vector<Message *> &messages,
|
const vector<Message *> &messages,
|
||||||
const vector<MessageId> &message_ids) {
|
const vector<MessageId> &message_ids, bool drop_author,
|
||||||
ForwardMessagesLogEvent log_event{to_dialog_id, from_dialog_id, message_ids, messages, Auto()};
|
bool drop_media_captions) {
|
||||||
|
ForwardMessagesLogEvent log_event{to_dialog_id, from_dialog_id, message_ids, messages,
|
||||||
|
drop_author, drop_media_captions, Auto()};
|
||||||
return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::ForwardMessages,
|
return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::ForwardMessages,
|
||||||
get_log_event_storer(log_event));
|
get_log_event_storer(log_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id,
|
void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id,
|
||||||
const vector<Message *> &messages, const vector<MessageId> &message_ids,
|
const vector<Message *> &messages, const vector<MessageId> &message_ids,
|
||||||
uint64 log_event_id) {
|
bool drop_author, bool drop_media_captions, uint64 log_event_id) {
|
||||||
CHECK(messages.size() == message_ids.size());
|
CHECK(messages.size() == message_ids.size());
|
||||||
if (messages.empty()) {
|
if (messages.empty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -27776,7 +27788,8 @@ void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_d
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_event_id == 0 && G()->parameters().use_message_db) {
|
if (log_event_id == 0 && G()->parameters().use_message_db) {
|
||||||
log_event_id = save_forward_messages_log_event(to_dialog_id, from_dialog_id, messages, message_ids);
|
log_event_id = save_forward_messages_log_event(to_dialog_id, from_dialog_id, messages, message_ids, drop_author,
|
||||||
|
drop_media_captions);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto schedule_date = get_message_schedule_date(messages[0]);
|
auto schedule_date = get_message_schedule_date(messages[0]);
|
||||||
|
@ -27801,6 +27814,12 @@ void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_d
|
||||||
if (messages[0]->noforwards) {
|
if (messages[0]->noforwards) {
|
||||||
flags |= SEND_MESSAGE_FLAG_NOFORWARDS;
|
flags |= SEND_MESSAGE_FLAG_NOFORWARDS;
|
||||||
}
|
}
|
||||||
|
if (drop_author) {
|
||||||
|
flags |= telegram_api::messages_forwardMessages::DROP_AUTHOR_MASK;
|
||||||
|
}
|
||||||
|
if (drop_media_captions) {
|
||||||
|
flags |= telegram_api::messages_forwardMessages::DROP_MEDIA_CAPTIONS_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
vector<int64> random_ids =
|
vector<int64> random_ids =
|
||||||
transform(messages, [this, to_dialog_id](const Message *m) { return begin_send_message(to_dialog_id, m); });
|
transform(messages, [this, to_dialog_id](const Message *m) { return begin_send_message(to_dialog_id, m); });
|
||||||
|
@ -27873,10 +27892,13 @@ unique_ptr<MessagesManager::MessageForwardInfo> MessagesManager::create_message_
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message,
|
void MessagesManager::fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message,
|
||||||
int64 media_album_id) const {
|
int64 media_album_id, bool drop_author) const {
|
||||||
m->via_bot_user_id = forwarded_message->via_bot_user_id;
|
bool is_game = m->content->get_type() == MessageContentType::Game;
|
||||||
|
if (!drop_author || is_game) {
|
||||||
|
m->via_bot_user_id = forwarded_message->via_bot_user_id;
|
||||||
|
}
|
||||||
m->media_album_id = media_album_id;
|
m->media_album_id = media_album_id;
|
||||||
if (forwarded_message->view_count > 0 && m->forward_info != nullptr && m->view_count == 0 &&
|
if (!drop_author && forwarded_message->view_count > 0 && m->forward_info != nullptr && m->view_count == 0 &&
|
||||||
!(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) {
|
!(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) {
|
||||||
m->view_count = forwarded_message->view_count;
|
m->view_count = forwarded_message->view_count;
|
||||||
m->forward_count = forwarded_message->forward_count;
|
m->forward_count = forwarded_message->forward_count;
|
||||||
|
@ -27987,12 +28009,23 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
|
||||||
|
|
||||||
bool to_secret = to_dialog_id.get_type() == DialogType::SecretChat;
|
bool to_secret = to_dialog_id.get_type() == DialogType::SecretChat;
|
||||||
|
|
||||||
|
bool can_use_server_forward = !to_secret;
|
||||||
|
for (auto ©_option : copy_options) {
|
||||||
|
if (!copy_option.is_supported_server_side()) {
|
||||||
|
can_use_server_forward = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK(can_use_server_forward || copy_options.size() == 1);
|
||||||
|
|
||||||
ForwardedMessages result;
|
ForwardedMessages result;
|
||||||
result.to_dialog = to_dialog;
|
result.to_dialog = to_dialog;
|
||||||
result.from_dialog = from_dialog;
|
result.from_dialog = from_dialog;
|
||||||
result.message_send_options = message_send_options;
|
result.message_send_options = message_send_options;
|
||||||
auto &copied_messages = result.copied_messages;
|
auto &copied_messages = result.copied_messages;
|
||||||
auto &forwarded_message_contents = result.forwarded_message_contents;
|
auto &forwarded_message_contents = result.forwarded_message_contents;
|
||||||
|
result.drop_author = can_use_server_forward && copy_options[0].send_copy;
|
||||||
|
result.drop_media_captions = can_use_server_forward && copy_options[0].replace_caption;
|
||||||
|
|
||||||
std::unordered_map<int64, std::pair<int64, int32>> new_copied_media_album_ids;
|
std::unordered_map<int64, std::pair<int64, int32>> new_copied_media_album_ids;
|
||||||
std::unordered_map<int64, std::pair<int64, int32>> new_forwarded_media_album_ids;
|
std::unordered_map<int64, std::pair<int64, int32>> new_forwarded_media_album_ids;
|
||||||
|
@ -28014,25 +28047,28 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy;
|
bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy;
|
||||||
|
bool is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward &&
|
||||||
|
forwarded_message->content->get_type() != MessageContentType::Dice);
|
||||||
if (!(need_copy && td_->auth_manager_->is_bot()) && !can_save_message(from_dialog_id, forwarded_message)) {
|
if (!(need_copy && td_->auth_manager_->is_bot()) && !can_save_message(from_dialog_id, forwarded_message)) {
|
||||||
LOG(INFO) << "Forward of " << message_id << " is restricted";
|
LOG(INFO) << "Forward of " << message_id << " is restricted";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto type = need_copy ? MessageContentDupType::Copy : MessageContentDupType::Forward;
|
auto type = need_copy ? (is_local_copy ? MessageContentDupType::Copy : MessageContentDupType::ServerCopy)
|
||||||
|
: MessageContentDupType::Forward;
|
||||||
auto top_thread_message_id = copy_options[i].top_thread_message_id;
|
auto top_thread_message_id = copy_options[i].top_thread_message_id;
|
||||||
auto reply_to_message_id = copy_options[i].reply_to_message_id;
|
auto reply_to_message_id = copy_options[i].reply_to_message_id;
|
||||||
auto reply_markup = std::move(copy_options[i].reply_markup);
|
auto reply_markup = std::move(copy_options[i].reply_markup);
|
||||||
unique_ptr<MessageContent> content =
|
unique_ptr<MessageContent> content =
|
||||||
dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), type, std::move(copy_options[i]));
|
dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), type, std::move(copy_options[i]));
|
||||||
if (content == nullptr) {
|
if (content == nullptr) {
|
||||||
LOG(INFO) << "Can't forward " << message_id;
|
LOG(INFO) << "Can't forward content of " << message_id;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply_to_message_id = get_reply_to_message_id(to_dialog, top_thread_message_id, reply_to_message_id, false);
|
reply_to_message_id = get_reply_to_message_id(to_dialog, top_thread_message_id, reply_to_message_id, false);
|
||||||
|
|
||||||
auto can_send_status = can_send_message_content(to_dialog_id, content.get(), !need_copy, td_);
|
auto can_send_status = can_send_message_content(to_dialog_id, content.get(), !is_local_copy, td_);
|
||||||
if (can_send_status.is_error()) {
|
if (can_send_status.is_error()) {
|
||||||
LOG(INFO) << "Can't forward " << message_id << ": " << can_send_status.message();
|
LOG(INFO) << "Can't forward " << message_id << ": " << can_send_status.message();
|
||||||
continue;
|
continue;
|
||||||
|
@ -28050,8 +28086,8 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forwarded_message->media_album_id != 0) {
|
if (forwarded_message->media_album_id != 0) {
|
||||||
auto &new_media_album_id = need_copy ? new_copied_media_album_ids[forwarded_message->media_album_id]
|
auto &new_media_album_id = is_local_copy ? new_copied_media_album_ids[forwarded_message->media_album_id]
|
||||||
: new_forwarded_media_album_ids[forwarded_message->media_album_id];
|
: new_forwarded_media_album_ids[forwarded_message->media_album_id];
|
||||||
new_media_album_id.second++;
|
new_media_album_id.second++;
|
||||||
if (new_media_album_id.second == 2) { // have at least 2 messages in the new album
|
if (new_media_album_id.second == 2) { // have at least 2 messages in the new album
|
||||||
CHECK(new_media_album_id.first == 0);
|
CHECK(new_media_album_id.first == 0);
|
||||||
|
@ -28063,7 +28099,7 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_copy) {
|
if (is_local_copy) {
|
||||||
copied_messages.push_back({std::move(content), top_thread_message_id, reply_to_message_id,
|
copied_messages.push_back({std::move(content), top_thread_message_id, reply_to_message_id,
|
||||||
std::move(reply_markup), forwarded_message->media_album_id,
|
std::move(reply_markup), forwarded_message->media_album_id,
|
||||||
get_message_disable_web_page_preview(forwarded_message), i});
|
get_message_disable_web_page_preview(forwarded_message), i});
|
||||||
|
@ -28123,6 +28159,8 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::forward_messages(
|
||||||
auto message_send_options = forwarded_messages_info.message_send_options;
|
auto message_send_options = forwarded_messages_info.message_send_options;
|
||||||
auto &copied_messages = forwarded_messages_info.copied_messages;
|
auto &copied_messages = forwarded_messages_info.copied_messages;
|
||||||
auto &forwarded_message_contents = forwarded_messages_info.forwarded_message_contents;
|
auto &forwarded_message_contents = forwarded_messages_info.forwarded_message_contents;
|
||||||
|
auto drop_author = forwarded_messages_info.drop_author;
|
||||||
|
auto drop_media_captions = forwarded_messages_info.drop_media_captions;
|
||||||
|
|
||||||
vector<td_api::object_ptr<td_api::message>> result(message_ids.size());
|
vector<td_api::object_ptr<td_api::message>> result(message_ids.size());
|
||||||
vector<Message *> forwarded_messages;
|
vector<Message *> forwarded_messages;
|
||||||
|
@ -28134,7 +28172,8 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::forward_messages(
|
||||||
CHECK(forwarded_message != nullptr);
|
CHECK(forwarded_message != nullptr);
|
||||||
|
|
||||||
auto content = std::move(forwarded_message_contents[j].content);
|
auto content = std::move(forwarded_message_contents[j].content);
|
||||||
auto forward_info = create_message_forward_info(from_dialog_id, to_dialog_id, forwarded_message);
|
auto forward_info =
|
||||||
|
drop_author ? nullptr : create_message_forward_info(from_dialog_id, to_dialog_id, forwarded_message);
|
||||||
if (forward_info != nullptr && !forward_info->is_imported && !is_forward_info_sender_hidden(forward_info.get()) &&
|
if (forward_info != nullptr && !forward_info->is_imported && !is_forward_info_sender_hidden(forward_info.get()) &&
|
||||||
!forward_info->message_id.is_valid() && !forward_info->sender_dialog_id.is_valid() &&
|
!forward_info->message_id.is_valid() && !forward_info->sender_dialog_id.is_valid() &&
|
||||||
forward_info->sender_user_id.is_valid()) {
|
forward_info->sender_user_id.is_valid()) {
|
||||||
|
@ -28162,7 +28201,8 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::forward_messages(
|
||||||
&need_update_dialog_pos, j + 1 != forwarded_message_contents.size(),
|
&need_update_dialog_pos, j + 1 != forwarded_message_contents.size(),
|
||||||
std::move(forward_info));
|
std::move(forward_info));
|
||||||
}
|
}
|
||||||
fix_forwarded_message(m, to_dialog_id, forwarded_message, forwarded_message_contents[j].media_album_id);
|
fix_forwarded_message(m, to_dialog_id, forwarded_message, forwarded_message_contents[j].media_album_id,
|
||||||
|
drop_author);
|
||||||
m->in_game_share = in_game_share;
|
m->in_game_share = in_game_share;
|
||||||
m->real_forward_from_dialog_id = from_dialog_id;
|
m->real_forward_from_dialog_id = from_dialog_id;
|
||||||
m->real_forward_from_message_id = message_id;
|
m->real_forward_from_message_id = message_id;
|
||||||
|
@ -28178,7 +28218,8 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::forward_messages(
|
||||||
|
|
||||||
if (!forwarded_messages.empty()) {
|
if (!forwarded_messages.empty()) {
|
||||||
CHECK(!only_preview);
|
CHECK(!only_preview);
|
||||||
do_forward_messages(to_dialog_id, from_dialog_id, forwarded_messages, forwarded_message_ids, 0);
|
do_forward_messages(to_dialog_id, from_dialog_id, forwarded_messages, forwarded_message_ids, drop_author,
|
||||||
|
drop_media_captions, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &copied_message : copied_messages) {
|
for (auto &copied_message : copied_messages) {
|
||||||
|
@ -28837,7 +28878,7 @@ void MessagesManager::send_update_new_message(const Dialog *d, const Message *m)
|
||||||
MessagesManager::NotificationGroupInfo &MessagesManager::get_notification_group_info(Dialog *d, const Message *m) {
|
MessagesManager::NotificationGroupInfo &MessagesManager::get_notification_group_info(Dialog *d, const Message *m) {
|
||||||
CHECK(d != nullptr);
|
CHECK(d != nullptr);
|
||||||
CHECK(m != nullptr);
|
CHECK(m != nullptr);
|
||||||
return is_from_mention_notification_group(d, m) ? d->mention_notification_group : d->message_notification_group;
|
return is_from_mention_notification_group(m) ? d->mention_notification_group : d->message_notification_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationGroupId MessagesManager::get_dialog_notification_group_id(DialogId dialog_id,
|
NotificationGroupId MessagesManager::get_dialog_notification_group_id(DialogId dialog_id,
|
||||||
|
@ -29107,13 +29148,13 @@ MessagesManager::MessageNotificationGroup MessagesManager::get_message_notificat
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessagesManager::is_from_mention_notification_group(const Dialog *d, const Message *m) {
|
bool MessagesManager::is_from_mention_notification_group(const Message *m) {
|
||||||
return m->contains_mention && !m->is_mention_notification_disabled;
|
return m->contains_mention && !m->is_mention_notification_disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessagesManager::is_message_notification_active(const Dialog *d, const Message *m) {
|
bool MessagesManager::is_message_notification_active(const Dialog *d, const Message *m) {
|
||||||
CHECK(!m->message_id.is_scheduled());
|
CHECK(!m->message_id.is_scheduled());
|
||||||
if (is_from_mention_notification_group(d, m)) {
|
if (is_from_mention_notification_group(m)) {
|
||||||
return m->notification_id.get() > d->mention_notification_group.max_removed_notification_id.get() &&
|
return m->notification_id.get() > d->mention_notification_group.max_removed_notification_id.get() &&
|
||||||
m->message_id > d->mention_notification_group.max_removed_message_id &&
|
m->message_id > d->mention_notification_group.max_removed_message_id &&
|
||||||
(m->contains_unread_mention || m->message_id == d->pinned_message_notification_message_id);
|
(m->contains_unread_mention || m->message_id == d->pinned_message_notification_message_id);
|
||||||
|
@ -29244,7 +29285,7 @@ vector<Notification> MessagesManager::get_message_notifications_from_database_fo
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_from_mention_notification_group(d, m) != from_mentions) {
|
if (is_from_mention_notification_group(m) != from_mentions) {
|
||||||
VLOG(notifications) << "Receive from database " << m->message_id << " with " << m->notification_id
|
VLOG(notifications) << "Receive from database " << m->message_id << " with " << m->notification_id
|
||||||
<< " from another group";
|
<< " from another group";
|
||||||
continue;
|
continue;
|
||||||
|
@ -29502,7 +29543,7 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_from_mention_notification_group(d, m) != from_mentions) {
|
if (is_from_mention_notification_group(m) != from_mentions) {
|
||||||
VLOG(notifications) << "Receive from database " << m->message_id << " with " << m->notification_id
|
VLOG(notifications) << "Receive from database " << m->message_id << " with " << m->notification_id
|
||||||
<< " from another category";
|
<< " from another category";
|
||||||
continue;
|
continue;
|
||||||
|
@ -29569,7 +29610,7 @@ void MessagesManager::remove_message_notification(DialogId dialog_id, Notificati
|
||||||
CHECK(m != nullptr);
|
CHECK(m != nullptr);
|
||||||
CHECK(m->notification_id == notification_id);
|
CHECK(m->notification_id == notification_id);
|
||||||
CHECK(!m->message_id.is_scheduled());
|
CHECK(!m->message_id.is_scheduled());
|
||||||
if (is_from_mention_notification_group(d, m) == from_mentions && is_message_notification_active(d, m)) {
|
if (is_from_mention_notification_group(m) == from_mentions && is_message_notification_active(d, m)) {
|
||||||
remove_message_notification_id(d, m, false, false);
|
remove_message_notification_id(d, m, false, false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -29632,8 +29673,8 @@ void MessagesManager::do_remove_message_notification(DialogId dialog_id, bool fr
|
||||||
CHECK(d != nullptr);
|
CHECK(d != nullptr);
|
||||||
|
|
||||||
auto m = on_get_message_from_database(d, result[0], false, "do_remove_message_notification");
|
auto m = on_get_message_from_database(d, result[0], false, "do_remove_message_notification");
|
||||||
if (m != nullptr && m->notification_id == notification_id &&
|
if (m != nullptr && m->notification_id == notification_id && is_from_mention_notification_group(m) == from_mentions &&
|
||||||
is_from_mention_notification_group(d, m) == from_mentions && is_message_notification_active(d, m)) {
|
is_message_notification_active(d, m)) {
|
||||||
remove_message_notification_id(d, m, false, false);
|
remove_message_notification_id(d, m, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29799,7 +29840,7 @@ bool MessagesManager::may_need_message_notification(const Dialog *d, const Messa
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_from_mention_notification_group(d, m)) {
|
if (is_from_mention_notification_group(m)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29830,7 +29871,7 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto from_mentions = is_from_mention_notification_group(d, m);
|
auto from_mentions = is_from_mention_notification_group(m);
|
||||||
bool is_pinned = m->content->get_type() == MessageContentType::PinMessage;
|
bool is_pinned = m->content->get_type() == MessageContentType::PinMessage;
|
||||||
bool is_active =
|
bool is_active =
|
||||||
from_mentions ? m->contains_unread_mention || is_pinned : m->message_id > d->last_read_inbox_message_id;
|
from_mentions ? m->contains_unread_mention || is_pinned : m->message_id > d->last_read_inbox_message_id;
|
||||||
|
@ -29854,7 +29895,7 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f
|
||||||
|
|
||||||
DialogId settings_dialog_id = d->dialog_id;
|
DialogId settings_dialog_id = d->dialog_id;
|
||||||
Dialog *settings_dialog = d;
|
Dialog *settings_dialog = d;
|
||||||
if (is_from_mention_notification_group(d, m)) {
|
if (is_from_mention_notification_group(m)) {
|
||||||
// have a mention, so use notification settings from the dialog with the sender
|
// have a mention, so use notification settings from the dialog with the sender
|
||||||
auto sender_dialog_id = get_message_sender(m);
|
auto sender_dialog_id = get_message_sender(m);
|
||||||
if (sender_dialog_id.is_valid()) {
|
if (sender_dialog_id.is_valid()) {
|
||||||
|
@ -34345,7 +34386,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
|
||||||
add_new_message_notification(d, message.get(), false);
|
add_new_message_notification(d, message.get(), false);
|
||||||
} else {
|
} else {
|
||||||
if (message->from_database && message->notification_id.is_valid() &&
|
if (message->from_database && message->notification_id.is_valid() &&
|
||||||
is_from_mention_notification_group(d, message.get()) && is_message_notification_active(d, message.get()) &&
|
is_from_mention_notification_group(message.get()) && is_message_notification_active(d, message.get()) &&
|
||||||
is_dialog_mention_notifications_disabled(d) && message_id != d->pinned_message_notification_message_id) {
|
is_dialog_mention_notifications_disabled(d) && message_id != d->pinned_message_notification_message_id) {
|
||||||
auto notification_id = message->notification_id;
|
auto notification_id = message->notification_id;
|
||||||
VLOG(notifications) << "Remove mention " << notification_id << " in " << message_id << " in " << dialog_id;
|
VLOG(notifications) << "Remove mention " << notification_id << " in " << message_id << " in " << dialog_id;
|
||||||
|
@ -35039,7 +35080,7 @@ void MessagesManager::delete_message_from_database(Dialog *d, MessageId message_
|
||||||
|
|
||||||
if (m != nullptr && m->notification_id.is_valid()) {
|
if (m != nullptr && m->notification_id.is_valid()) {
|
||||||
CHECK(!message_id.is_scheduled());
|
CHECK(!message_id.is_scheduled());
|
||||||
auto from_mentions = is_from_mention_notification_group(d, m);
|
auto from_mentions = is_from_mention_notification_group(m);
|
||||||
auto &group_info = from_mentions ? d->mention_notification_group : d->message_notification_group;
|
auto &group_info = from_mentions ? d->mention_notification_group : d->message_notification_group;
|
||||||
|
|
||||||
if (group_info.group_id.is_valid()) {
|
if (group_info.group_id.is_valid()) {
|
||||||
|
@ -36014,6 +36055,9 @@ MessagesManager::Dialog *MessagesManager::add_new_dialog(unique_ptr<Dialog> &&d,
|
||||||
|
|
||||||
auto dialog_it = dialogs_.emplace(dialog_id, std::move(d)).first;
|
auto dialog_it = dialogs_.emplace(dialog_id, std::move(d)).first;
|
||||||
|
|
||||||
|
CHECK(!being_added_new_dialog_id_.is_valid());
|
||||||
|
being_added_new_dialog_id_ = dialog_id;
|
||||||
|
|
||||||
loaded_dialogs_.erase(dialog_id);
|
loaded_dialogs_.erase(dialog_id);
|
||||||
|
|
||||||
Dialog *dialog = dialog_it->second.get();
|
Dialog *dialog = dialog_it->second.get();
|
||||||
|
@ -36022,6 +36066,8 @@ MessagesManager::Dialog *MessagesManager::add_new_dialog(unique_ptr<Dialog> &&d,
|
||||||
|
|
||||||
send_update_new_chat(dialog);
|
send_update_new_chat(dialog);
|
||||||
|
|
||||||
|
being_added_new_dialog_id_ = DialogId();
|
||||||
|
|
||||||
fix_new_dialog(dialog, std::move(last_database_message), last_database_message_id, order, last_clear_history_date,
|
fix_new_dialog(dialog, std::move(last_database_message), last_database_message_id, order, last_clear_history_date,
|
||||||
last_clear_history_message_id, default_join_group_call_as_dialog_id, default_send_message_as_dialog_id,
|
last_clear_history_message_id, default_join_group_call_as_dialog_id, default_send_message_as_dialog_id,
|
||||||
need_drop_default_send_message_as_dialog_id, is_loaded_from_database);
|
need_drop_default_send_message_as_dialog_id, is_loaded_from_database);
|
||||||
|
@ -36155,6 +36201,7 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
|
||||||
CHECK(counter_message.first > 0);
|
CHECK(counter_message.first > 0);
|
||||||
counter_message.first--;
|
counter_message.first--;
|
||||||
if (counter_message.first == 0) {
|
if (counter_message.first == 0) {
|
||||||
|
LOG(INFO) << "Add postponed last database message in " << pending_dialog_id;
|
||||||
add_dialog_last_database_message(get_dialog(pending_dialog_id), std::move(counter_message.second));
|
add_dialog_last_database_message(get_dialog(pending_dialog_id), std::move(counter_message.second));
|
||||||
pending_add_dialog_last_database_message_.erase(pending_dialog_id);
|
pending_add_dialog_last_database_message_.erase(pending_dialog_id);
|
||||||
}
|
}
|
||||||
|
@ -38755,7 +38802,8 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||||
send_update_chat_last_message(to_dialog, "on_reforward_message");
|
send_update_chat_last_message(to_dialog, "on_reforward_message");
|
||||||
}
|
}
|
||||||
|
|
||||||
do_forward_messages(to_dialog_id, from_dialog_id, forwarded_messages, log_event.message_ids, event.id_);
|
do_forward_messages(to_dialog_id, from_dialog_id, forwarded_messages, log_event.message_ids,
|
||||||
|
log_event.drop_author, log_event.drop_media_captions, event.id_);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LogEvent::HandlerType::DeleteMessage: {
|
case LogEvent::HandlerType::DeleteMessage: {
|
||||||
|
|
|
@ -1934,7 +1934,8 @@ class MessagesManager final : public Actor {
|
||||||
bool update_message_is_pinned(Dialog *d, Message *m, bool is_pin, const char *source);
|
bool update_message_is_pinned(Dialog *d, Message *m, bool is_pin, const char *source);
|
||||||
|
|
||||||
void do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, const vector<Message *> &messages,
|
void do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, const vector<Message *> &messages,
|
||||||
const vector<MessageId> &message_ids, uint64 log_event_id);
|
const vector<MessageId> &message_ids, bool drop_author, bool drop_media_captions,
|
||||||
|
uint64 log_event_id);
|
||||||
|
|
||||||
Result<td_api::object_ptr<td_api::message>> forward_message(DialogId to_dialog_id, DialogId from_dialog_id,
|
Result<td_api::object_ptr<td_api::message>> forward_message(DialogId to_dialog_id, DialogId from_dialog_id,
|
||||||
MessageId message_id,
|
MessageId message_id,
|
||||||
|
@ -1945,8 +1946,8 @@ class MessagesManager final : public Actor {
|
||||||
unique_ptr<MessageForwardInfo> create_message_forward_info(DialogId from_dialog_id, DialogId to_dialog_id,
|
unique_ptr<MessageForwardInfo> create_message_forward_info(DialogId from_dialog_id, DialogId to_dialog_id,
|
||||||
const Message *forwarded_message) const;
|
const Message *forwarded_message) const;
|
||||||
|
|
||||||
void fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message,
|
void fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message, int64 media_album_id,
|
||||||
int64 media_album_id) const;
|
bool drop_author) const;
|
||||||
|
|
||||||
struct ForwardedMessages {
|
struct ForwardedMessages {
|
||||||
struct CopiedMessage {
|
struct CopiedMessage {
|
||||||
|
@ -1966,6 +1967,8 @@ class MessagesManager final : public Actor {
|
||||||
size_t index;
|
size_t index;
|
||||||
};
|
};
|
||||||
vector<ForwardedMessageContent> forwarded_message_contents;
|
vector<ForwardedMessageContent> forwarded_message_contents;
|
||||||
|
bool drop_author = false;
|
||||||
|
bool drop_media_captions = false;
|
||||||
|
|
||||||
Dialog *from_dialog;
|
Dialog *from_dialog;
|
||||||
Dialog *to_dialog;
|
Dialog *to_dialog;
|
||||||
|
@ -2368,7 +2371,7 @@ class MessagesManager final : public Actor {
|
||||||
|
|
||||||
void send_update_new_message(const Dialog *d, const Message *m);
|
void send_update_new_message(const Dialog *d, const Message *m);
|
||||||
|
|
||||||
static bool is_from_mention_notification_group(const Dialog *d, const Message *m);
|
static bool is_from_mention_notification_group(const Message *m);
|
||||||
|
|
||||||
static bool is_message_notification_active(const Dialog *d, const Message *m);
|
static bool is_message_notification_active(const Dialog *d, const Message *m);
|
||||||
|
|
||||||
|
@ -3251,8 +3254,8 @@ class MessagesManager final : public Actor {
|
||||||
static uint64 save_reget_dialog_log_event(DialogId dialog_id);
|
static uint64 save_reget_dialog_log_event(DialogId dialog_id);
|
||||||
|
|
||||||
static uint64 save_forward_messages_log_event(DialogId to_dialog_id, DialogId from_dialog_id,
|
static uint64 save_forward_messages_log_event(DialogId to_dialog_id, DialogId from_dialog_id,
|
||||||
const vector<Message *> &messages,
|
const vector<Message *> &messages, const vector<MessageId> &message_ids,
|
||||||
const vector<MessageId> &message_ids);
|
bool drop_author, bool drop_media_captions);
|
||||||
|
|
||||||
static uint64 save_unpin_all_dialog_messages_on_server_log_event(DialogId dialog_id);
|
static uint64 save_unpin_all_dialog_messages_on_server_log_event(DialogId dialog_id);
|
||||||
|
|
||||||
|
@ -3678,6 +3681,7 @@ class MessagesManager final : public Actor {
|
||||||
|
|
||||||
DialogId being_added_dialog_id_;
|
DialogId being_added_dialog_id_;
|
||||||
DialogId being_added_by_new_message_dialog_id_;
|
DialogId being_added_by_new_message_dialog_id_;
|
||||||
|
DialogId being_added_new_dialog_id_;
|
||||||
|
|
||||||
DialogId debug_channel_difference_dialog_;
|
DialogId debug_channel_difference_dialog_;
|
||||||
|
|
||||||
|
|
|
@ -1472,10 +1472,6 @@ void NotificationSettingsManager::after_get_difference() {
|
||||||
if (!channels_notification_settings_.is_synchronized) {
|
if (!channels_notification_settings_.is_synchronized) {
|
||||||
send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Promise<>());
|
send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Promise<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (td_->is_online() && !are_saved_ringtones_reloaded_) {
|
|
||||||
reload_saved_ringtones(Auto());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationSettingsManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
void NotificationSettingsManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <functional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
@ -418,14 +419,14 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
|
||||||
if (name != option_name) {
|
if (name != option_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (value_constructor_id != td_api::optionValueInteger::ID &&
|
|
||||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
|
||||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have integer value"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||||
G()->shared_config().set_option_empty(option_name);
|
G()->shared_config().set_option_empty(option_name);
|
||||||
} else {
|
} else {
|
||||||
|
if (value_constructor_id != td_api::optionValueInteger::ID) {
|
||||||
|
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have integer value"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int64 int_value = static_cast<td_api::optionValueInteger *>(value.get())->value_;
|
int64 int_value = static_cast<td_api::optionValueInteger *>(value.get())->value_;
|
||||||
if (int_value < min_value || int_value > max_value) {
|
if (int_value < min_value || int_value > max_value) {
|
||||||
promise.set_error(Status::Error(400, PSLICE() << "Option's \"" << name << "\" value " << int_value
|
promise.set_error(Status::Error(400, PSLICE() << "Option's \"" << name << "\" value " << int_value
|
||||||
|
@ -443,14 +444,14 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
|
||||||
if (name != option_name) {
|
if (name != option_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (value_constructor_id != td_api::optionValueBoolean::ID &&
|
|
||||||
value_constructor_id != td_api::optionValueEmpty::ID) {
|
|
||||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have boolean value"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||||
G()->shared_config().set_option_empty(name);
|
G()->shared_config().set_option_empty(name);
|
||||||
} else {
|
} else {
|
||||||
|
if (value_constructor_id != td_api::optionValueBoolean::ID) {
|
||||||
|
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have boolean value"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool bool_value = static_cast<td_api::optionValueBoolean *>(value.get())->value_;
|
bool bool_value = static_cast<td_api::optionValueBoolean *>(value.get())->value_;
|
||||||
G()->shared_config().set_option_boolean(name, bool_value);
|
G()->shared_config().set_option_boolean(name, bool_value);
|
||||||
}
|
}
|
||||||
|
@ -458,17 +459,18 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto set_string_option = [&](Slice option_name, auto check_value) {
|
auto set_string_option = [&](Slice option_name, std::function<bool(Slice)> check_value) {
|
||||||
if (name != option_name) {
|
if (name != option_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (value_constructor_id != td_api::optionValueString::ID && value_constructor_id != td_api::optionValueEmpty::ID) {
|
|
||||||
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have string value"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
if (value_constructor_id == td_api::optionValueEmpty::ID) {
|
||||||
G()->shared_config().set_option_empty(name);
|
G()->shared_config().set_option_empty(name);
|
||||||
} else {
|
} else {
|
||||||
|
if (value_constructor_id != td_api::optionValueString::ID) {
|
||||||
|
promise.set_error(Status::Error(400, PSLICE() << "Option \"" << name << "\" must have string value"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const string &str_value = static_cast<td_api::optionValueString *>(value.get())->value_;
|
const string &str_value = static_cast<td_api::optionValueString *>(value.get())->value_;
|
||||||
if (str_value.empty()) {
|
if (str_value.empty()) {
|
||||||
G()->shared_config().set_option_empty(name);
|
G()->shared_config().set_option_empty(name);
|
||||||
|
@ -651,10 +653,10 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
|
||||||
}
|
}
|
||||||
bool is_online = value_constructor_id == td_api::optionValueEmpty::ID ||
|
bool is_online = value_constructor_id == td_api::optionValueEmpty::ID ||
|
||||||
static_cast<const td_api::optionValueBoolean *>(value.get())->value_;
|
static_cast<const td_api::optionValueBoolean *>(value.get())->value_;
|
||||||
|
td_->set_is_online(is_online);
|
||||||
if (!is_bot) {
|
if (!is_bot) {
|
||||||
send_closure(td_->state_manager_, &StateManager::on_online, is_online);
|
send_closure(td_->state_manager_, &StateManager::on_online, is_online);
|
||||||
}
|
}
|
||||||
td_->set_is_online(is_online);
|
|
||||||
return promise.set_value(Unit());
|
return promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -166,7 +166,7 @@ void PhoneNumberManager::process_check_code_result(Result<tl_object_ptr<telegram
|
||||||
return on_query_error(result.move_as_error());
|
return on_query_error(result.move_as_error());
|
||||||
}
|
}
|
||||||
send_closure(G()->contacts_manager(), &ContactsManager::on_get_user, result.move_as_ok(), "process_check_code_result",
|
send_closure(G()->contacts_manager(), &ContactsManager::on_get_user, result.move_as_ok(), "process_check_code_result",
|
||||||
true, false);
|
true);
|
||||||
state_ = State::Ok;
|
state_ = State::Ok;
|
||||||
on_query_ok();
|
on_query_ok();
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,9 @@ PollManager::PollManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::m
|
||||||
|
|
||||||
close_poll_timeout_.set_callback(on_close_poll_timeout_callback);
|
close_poll_timeout_.set_callback(on_close_poll_timeout_callback);
|
||||||
close_poll_timeout_.set_callback_data(static_cast<void *>(this));
|
close_poll_timeout_.set_callback_data(static_cast<void *>(this));
|
||||||
|
|
||||||
|
unload_poll_timeout_.set_callback(on_unload_poll_timeout_callback);
|
||||||
|
unload_poll_timeout_.set_callback_data(static_cast<void *>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollManager::start_up() {
|
void PollManager::start_up() {
|
||||||
|
@ -283,6 +286,15 @@ void PollManager::on_close_poll_timeout_callback(void *poll_manager_ptr, int64 p
|
||||||
send_closure_later(poll_manager->actor_id(poll_manager), &PollManager::on_close_poll_timeout, PollId(poll_id_int));
|
send_closure_later(poll_manager->actor_id(poll_manager), &PollManager::on_close_poll_timeout, PollId(poll_id_int));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PollManager::on_unload_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int) {
|
||||||
|
if (G()->close_flag()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto poll_manager = static_cast<PollManager *>(poll_manager_ptr);
|
||||||
|
send_closure_later(poll_manager->actor_id(poll_manager), &PollManager::on_unload_poll_timeout, PollId(poll_id_int));
|
||||||
|
}
|
||||||
|
|
||||||
bool PollManager::is_local_poll_id(PollId poll_id) {
|
bool PollManager::is_local_poll_id(PollId poll_id) {
|
||||||
return poll_id.get() < 0 && poll_id.get() > std::numeric_limits<int32>::min();
|
return poll_id.get() < 0 && poll_id.get() > std::numeric_limits<int32>::min();
|
||||||
}
|
}
|
||||||
|
@ -296,11 +308,22 @@ const PollManager::Poll *PollManager::get_poll(PollId poll_id) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PollManager::Poll *PollManager::get_poll(PollId poll_id) {
|
||||||
|
auto p = polls_.find(poll_id);
|
||||||
|
if (p == polls_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
schedule_poll_unload(poll_id);
|
||||||
|
return p->second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PollManager::Poll *PollManager::get_poll_editable(PollId poll_id) {
|
PollManager::Poll *PollManager::get_poll_editable(PollId poll_id) {
|
||||||
auto p = polls_.find(poll_id);
|
auto p = polls_.find(poll_id);
|
||||||
if (p == polls_.end()) {
|
if (p == polls_.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
|
schedule_poll_unload(poll_id);
|
||||||
return p->second.get();
|
return p->second.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,13 +333,18 @@ bool PollManager::have_poll(PollId poll_id) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollManager::notify_on_poll_update(PollId poll_id) {
|
void PollManager::notify_on_poll_update(PollId poll_id) {
|
||||||
auto it = poll_messages_.find(poll_id);
|
auto server_it = server_poll_messages_.find(poll_id);
|
||||||
if (it == poll_messages_.end()) {
|
if (server_it != server_poll_messages_.end()) {
|
||||||
return;
|
for (const auto &full_message_id : server_it->second) {
|
||||||
|
td_->messages_manager_->on_external_update_message_content(full_message_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &full_message_id : it->second) {
|
auto other_it = other_poll_messages_.find(poll_id);
|
||||||
td_->messages_manager_->on_external_update_message_content(full_message_id);
|
if (other_it != other_poll_messages_.end()) {
|
||||||
|
for (const auto &full_message_id : other_it->second) {
|
||||||
|
td_->messages_manager_->on_external_update_message_content(full_message_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,38 +651,71 @@ PollId PollManager::create_poll(string &&question, vector<string> &&options, boo
|
||||||
|
|
||||||
void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
|
void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
|
||||||
CHECK(have_poll(poll_id));
|
CHECK(have_poll(poll_id));
|
||||||
if (full_message_id.get_message_id().is_scheduled()) {
|
if (full_message_id.get_message_id().is_scheduled() || !full_message_id.get_message_id().is_server()) {
|
||||||
return;
|
bool is_inserted = other_poll_messages_[poll_id].insert(full_message_id).second;
|
||||||
}
|
LOG_CHECK(is_inserted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||||
if (!full_message_id.get_message_id().is_server()) {
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Register " << poll_id << " from " << full_message_id << " from " << source;
|
LOG(INFO) << "Register " << poll_id << " from " << full_message_id << " from " << source;
|
||||||
bool is_inserted = poll_messages_[poll_id].insert(full_message_id).second;
|
bool is_inserted = server_poll_messages_[poll_id].insert(full_message_id).second;
|
||||||
LOG_CHECK(is_inserted) << source << " " << poll_id << " " << full_message_id;
|
LOG_CHECK(is_inserted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
CHECK(poll != nullptr);
|
CHECK(poll != nullptr);
|
||||||
if (!td_->auth_manager_->is_bot() && !is_local_poll_id(poll_id) &&
|
if (!td_->auth_manager_->is_bot() && !is_local_poll_id(poll_id) &&
|
||||||
!(poll->is_closed && poll->is_updated_after_close)) {
|
!(poll->is_closed && poll->is_updated_after_close)) {
|
||||||
update_poll_timeout_.add_timeout_in(poll_id.get(), 0);
|
update_poll_timeout_.add_timeout_in(poll_id.get(), 0);
|
||||||
}
|
}
|
||||||
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
|
void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
|
||||||
CHECK(have_poll(poll_id));
|
CHECK(have_poll(poll_id));
|
||||||
if (full_message_id.get_message_id().is_scheduled()) {
|
if (full_message_id.get_message_id().is_scheduled() || !full_message_id.get_message_id().is_server()) {
|
||||||
return;
|
auto &message_ids = other_poll_messages_[poll_id];
|
||||||
}
|
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
||||||
if (!full_message_id.get_message_id().is_server()) {
|
LOG_CHECK(is_deleted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||||
|
if (message_ids.empty()) {
|
||||||
|
other_poll_messages_.erase(poll_id);
|
||||||
|
|
||||||
|
schedule_poll_unload(poll_id);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Unregister " << poll_id << " from " << full_message_id << " from " << source;
|
LOG(INFO) << "Unregister " << poll_id << " from " << full_message_id << " from " << source;
|
||||||
auto &message_ids = poll_messages_[poll_id];
|
auto &message_ids = server_poll_messages_[poll_id];
|
||||||
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
||||||
LOG_CHECK(is_deleted) << source << " " << poll_id << " " << full_message_id;
|
LOG_CHECK(is_deleted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||||
if (message_ids.empty()) {
|
if (message_ids.empty()) {
|
||||||
poll_messages_.erase(poll_id);
|
server_poll_messages_.erase(poll_id);
|
||||||
update_poll_timeout_.cancel_timeout(poll_id.get());
|
update_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
|
schedule_poll_unload(poll_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PollManager::can_unload_poll(PollId poll_id) {
|
||||||
|
if (is_local_poll_id(poll_id) || server_poll_messages_.count(poll_id) != 0 ||
|
||||||
|
other_poll_messages_.count(poll_id) != 0 || pending_answers_.count(poll_id) != 0 ||
|
||||||
|
being_closed_polls_.count(poll_id) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = poll_voters_.find(poll_id);
|
||||||
|
if (it != poll_voters_.end() && !it->second.empty()) {
|
||||||
|
for (auto &voters : it->second) {
|
||||||
|
if (!voters.pending_queries.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PollManager::schedule_poll_unload(PollId poll_id) {
|
||||||
|
if (can_unload_poll(poll_id)) {
|
||||||
|
unload_poll_timeout_.set_timeout_in(poll_id.get(), UNLOAD_POLL_DELAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,6 +825,7 @@ void PollManager::do_set_poll_answer(PollId poll_id, FullMessageId full_message_
|
||||||
binlog_erase(G()->td_db()->get_binlog(), log_event_id);
|
binlog_erase(G()->td_db()->get_binlog(), log_event_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
auto &pending_answer = pending_answers_[poll_id];
|
auto &pending_answer = pending_answers_[poll_id];
|
||||||
if (!pending_answer.promises_.empty() && pending_answer.options_ == options) {
|
if (!pending_answer.promises_.empty() && pending_answer.options_ == options) {
|
||||||
|
@ -987,6 +1049,8 @@ void PollManager::get_poll_voters(PollId poll_id, FullMessageId full_message_id,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
auto query_promise =
|
auto query_promise =
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this), poll_id, option_id, offset = voters.next_offset,
|
PromiseCreator::lambda([actor_id = actor_id(this), poll_id, option_id, offset = voters.next_offset,
|
||||||
limit](Result<tl_object_ptr<telegram_api::messages_votesList>> &&result) mutable {
|
limit](Result<tl_object_ptr<telegram_api::messages_votesList>> &&result) mutable {
|
||||||
|
@ -1136,6 +1200,8 @@ void PollManager::do_stop_poll(PollId poll_id, FullMessageId full_message_id, un
|
||||||
binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::StopPoll, get_log_event_storer(log_event));
|
binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::StopPoll, get_log_event_storer(log_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
bool is_inserted = being_closed_polls_.insert(poll_id).second;
|
bool is_inserted = being_closed_polls_.insert(poll_id).second;
|
||||||
CHECK(is_inserted);
|
CHECK(is_inserted);
|
||||||
auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise));
|
auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise));
|
||||||
|
@ -1168,8 +1234,7 @@ void PollManager::on_update_poll_timeout(PollId poll_id) {
|
||||||
CHECK(!is_local_poll_id(poll_id));
|
CHECK(!is_local_poll_id(poll_id));
|
||||||
|
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
CHECK(poll != nullptr);
|
if (poll == nullptr || (poll->is_closed && poll->is_updated_after_close)) {
|
||||||
if (poll->is_closed && poll->is_updated_after_close) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pending_answers_.count(poll_id) > 0) {
|
if (pending_answers_.count(poll_id) > 0) {
|
||||||
|
@ -1177,8 +1242,8 @@ void PollManager::on_update_poll_timeout(PollId poll_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = poll_messages_.find(poll_id);
|
auto it = server_poll_messages_.find(poll_id);
|
||||||
if (it == poll_messages_.end()) {
|
if (it == server_poll_messages_.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,8 +1263,7 @@ void PollManager::on_close_poll_timeout(PollId poll_id) {
|
||||||
CHECK(!is_local_poll_id(poll_id));
|
CHECK(!is_local_poll_id(poll_id));
|
||||||
|
|
||||||
auto poll = get_poll_editable(poll_id);
|
auto poll = get_poll_editable(poll_id);
|
||||||
CHECK(poll != nullptr);
|
if (poll == nullptr || poll->is_closed || poll->close_date == 0) {
|
||||||
if (poll->is_closed || poll->close_date == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,10 +1283,34 @@ void PollManager::on_close_poll_timeout(PollId poll_id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PollManager::on_unload_poll_timeout(PollId poll_id) {
|
||||||
|
if (G()->close_flag()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CHECK(!is_local_poll_id(poll_id));
|
||||||
|
|
||||||
|
if (!can_unload_poll(poll_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Unload " << poll_id;
|
||||||
|
|
||||||
|
update_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
close_poll_timeout_.cancel_timeout(poll_id.get());
|
||||||
|
|
||||||
|
auto is_deleted = polls_.erase(poll_id) > 0;
|
||||||
|
CHECK(is_deleted);
|
||||||
|
|
||||||
|
poll_voters_.erase(poll_id);
|
||||||
|
loaded_from_database_polls_.erase(poll_id);
|
||||||
|
}
|
||||||
|
|
||||||
void PollManager::on_get_poll_results(PollId poll_id, uint64 generation,
|
void PollManager::on_get_poll_results(PollId poll_id, uint64 generation,
|
||||||
Result<tl_object_ptr<telegram_api::Updates>> result) {
|
Result<tl_object_ptr<telegram_api::Updates>> result) {
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
CHECK(poll != nullptr);
|
if (poll == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
if (!(poll->is_closed && poll->is_updated_after_close) && !G()->close_flag() && !td_->auth_manager_->is_bot()) {
|
if (!(poll->is_closed && poll->is_updated_after_close) && !G()->close_flag() && !td_->auth_manager_->is_bot()) {
|
||||||
auto timeout = get_polling_timeout();
|
auto timeout = get_polling_timeout();
|
||||||
|
@ -1250,7 +1338,7 @@ void PollManager::on_online() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &it : poll_messages_) {
|
for (auto &it : server_poll_messages_) {
|
||||||
auto poll_id = it.first;
|
auto poll_id = it.first;
|
||||||
if (update_poll_timeout_.has_timeout(poll_id.get())) {
|
if (update_poll_timeout_.has_timeout(poll_id.get())) {
|
||||||
auto timeout = Random::fast(3, 30);
|
auto timeout = Random::fast(3, 30);
|
||||||
|
@ -1643,6 +1731,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||||
}
|
}
|
||||||
if (need_update_poll && (is_changed || (poll->is_closed && being_closed_polls_.erase(poll_id) != 0))) {
|
if (need_update_poll && (is_changed || (poll->is_closed && being_closed_polls_.erase(poll_id) != 0))) {
|
||||||
send_closure(G()->td(), &Td::send_update, td_api::make_object<td_api::updatePoll>(get_poll_object(poll_id, poll)));
|
send_closure(G()->td(), &Td::send_update, td_api::make_object<td_api::updatePoll>(get_poll_object(poll_id, poll)));
|
||||||
|
|
||||||
|
schedule_poll_unload(poll_id);
|
||||||
}
|
}
|
||||||
return poll_id;
|
return poll_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ class PollManager final : public Actor {
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int32 MAX_GET_POLL_VOTERS = 50; // server side limit
|
static constexpr int32 MAX_GET_POLL_VOTERS = 50; // server side limit
|
||||||
|
static constexpr int32 UNLOAD_POLL_DELAY = 600; // some reasonable value
|
||||||
|
|
||||||
class SetPollAnswerLogEvent;
|
class SetPollAnswerLogEvent;
|
||||||
class StopPollLogEvent;
|
class StopPollLogEvent;
|
||||||
|
@ -149,6 +150,8 @@ class PollManager final : public Actor {
|
||||||
|
|
||||||
static void on_close_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int);
|
static void on_close_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int);
|
||||||
|
|
||||||
|
static void on_unload_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int);
|
||||||
|
|
||||||
static td_api::object_ptr<td_api::pollOption> get_poll_option_object(const PollOption &poll_option);
|
static td_api::object_ptr<td_api::pollOption> get_poll_option_object(const PollOption &poll_option);
|
||||||
|
|
||||||
static telegram_api::object_ptr<telegram_api::pollAnswer> get_input_poll_option(const PollOption &poll_option);
|
static telegram_api::object_ptr<telegram_api::pollAnswer> get_input_poll_option(const PollOption &poll_option);
|
||||||
|
@ -161,8 +164,14 @@ class PollManager final : public Actor {
|
||||||
|
|
||||||
const Poll *get_poll(PollId poll_id) const;
|
const Poll *get_poll(PollId poll_id) const;
|
||||||
|
|
||||||
|
const Poll *get_poll(PollId poll_id);
|
||||||
|
|
||||||
Poll *get_poll_editable(PollId poll_id);
|
Poll *get_poll_editable(PollId poll_id);
|
||||||
|
|
||||||
|
bool can_unload_poll(PollId poll_id);
|
||||||
|
|
||||||
|
void schedule_poll_unload(PollId poll_id);
|
||||||
|
|
||||||
void notify_on_poll_update(PollId poll_id);
|
void notify_on_poll_update(PollId poll_id);
|
||||||
|
|
||||||
static string get_poll_database_key(PollId poll_id);
|
static string get_poll_database_key(PollId poll_id);
|
||||||
|
@ -177,6 +186,8 @@ class PollManager final : public Actor {
|
||||||
|
|
||||||
void on_close_poll_timeout(PollId poll_id);
|
void on_close_poll_timeout(PollId poll_id);
|
||||||
|
|
||||||
|
void on_unload_poll_timeout(PollId poll_id);
|
||||||
|
|
||||||
void on_online();
|
void on_online();
|
||||||
|
|
||||||
Poll *get_poll_force(PollId poll_id);
|
Poll *get_poll_force(PollId poll_id);
|
||||||
|
@ -206,12 +217,14 @@ class PollManager final : public Actor {
|
||||||
|
|
||||||
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};
|
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};
|
||||||
MultiTimeout close_poll_timeout_{"ClosePollTimeout"};
|
MultiTimeout close_poll_timeout_{"ClosePollTimeout"};
|
||||||
|
MultiTimeout unload_poll_timeout_{"UnloadPollTimeout"};
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
FlatHashMap<PollId, unique_ptr<Poll>, PollIdHash> polls_;
|
FlatHashMap<PollId, unique_ptr<Poll>, PollIdHash> polls_;
|
||||||
|
|
||||||
FlatHashMap<PollId, FlatHashSet<FullMessageId, FullMessageIdHash>, PollIdHash> poll_messages_;
|
FlatHashMap<PollId, FlatHashSet<FullMessageId, FullMessageIdHash>, PollIdHash> server_poll_messages_;
|
||||||
|
FlatHashMap<PollId, FlatHashSet<FullMessageId, FullMessageIdHash>, PollIdHash> other_poll_messages_;
|
||||||
|
|
||||||
struct PendingPollAnswer {
|
struct PendingPollAnswer {
|
||||||
vector<string> options_;
|
vector<string> options_;
|
||||||
|
|
25
td/telegram/SecretInputMedia.cpp
Normal file
25
td/telegram/SecretInputMedia.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#include "td/telegram/SecretInputMedia.h"
|
||||||
|
|
||||||
|
#include "td/telegram/files/FileManager.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
SecretInputMedia::SecretInputMedia(tl_object_ptr<telegram_api::InputEncryptedFile> input_file, BufferSlice &&thumbnail,
|
||||||
|
Dimensions thumbnail_dimensions, const string &mime_type, const FileView &file_view,
|
||||||
|
vector<tl_object_ptr<secret_api::DocumentAttribute>> &&attributes,
|
||||||
|
const string &caption)
|
||||||
|
: input_file_(std::move(input_file)) {
|
||||||
|
auto &encryption_key = file_view.encryption_key();
|
||||||
|
decrypted_media_ = secret_api::make_object<secret_api::decryptedMessageMediaDocument>(
|
||||||
|
std::move(thumbnail), thumbnail_dimensions.width, thumbnail_dimensions.height, mime_type,
|
||||||
|
narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||||
|
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
|
@ -6,11 +6,17 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/PhotoSize.h"
|
||||||
#include "td/telegram/secret_api.h"
|
#include "td/telegram/secret_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
|
#include "td/utils/buffer.h"
|
||||||
|
#include "td/utils/common.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
class FileView;
|
||||||
|
|
||||||
struct SecretInputMedia {
|
struct SecretInputMedia {
|
||||||
tl_object_ptr<telegram_api::InputEncryptedFile> input_file_;
|
tl_object_ptr<telegram_api::InputEncryptedFile> input_file_;
|
||||||
tl_object_ptr<secret_api::DecryptedMessageMedia> decrypted_media_;
|
tl_object_ptr<secret_api::DecryptedMessageMedia> decrypted_media_;
|
||||||
|
@ -22,6 +28,10 @@ struct SecretInputMedia {
|
||||||
: input_file_(std::move(input_file)), decrypted_media_(std::move(decrypted_media)) {
|
: input_file_(std::move(input_file)), decrypted_media_(std::move(decrypted_media)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SecretInputMedia(tl_object_ptr<telegram_api::InputEncryptedFile> input_file, BufferSlice &&thumbnail,
|
||||||
|
Dimensions thumbnail_dimensions, const string &mime_type, const FileView &file_view,
|
||||||
|
vector<tl_object_ptr<secret_api::DocumentAttribute>> &&attributes, const string &caption);
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return decrypted_media_ == nullptr;
|
return decrypted_media_ == nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1462,6 +1462,10 @@ void StickersManager::reload_special_sticker_set_by_type(SpecialStickerSetType t
|
||||||
if (G()->close_flag()) {
|
if (G()->close_flag()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (disable_animated_emojis_ &&
|
||||||
|
(type == SpecialStickerSetType::animated_emoji() || type == SpecialStickerSetType::animated_emoji_click())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto &sticker_set = add_special_sticker_set(type);
|
auto &sticker_set = add_special_sticker_set(type);
|
||||||
if (sticker_set.is_being_reloaded_) {
|
if (sticker_set.is_being_reloaded_) {
|
||||||
|
@ -1534,8 +1538,9 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t
|
||||||
auto pending_get_requests = std::move(pending_get_animated_emoji_click_stickers_);
|
auto pending_get_requests = std::move(pending_get_animated_emoji_click_stickers_);
|
||||||
reset_to_empty(pending_get_animated_emoji_click_stickers_);
|
reset_to_empty(pending_get_animated_emoji_click_stickers_);
|
||||||
for (auto &pending_request : pending_get_requests) {
|
for (auto &pending_request : pending_get_requests) {
|
||||||
choose_animated_emoji_click_sticker(sticker_set, pending_request.message_text_, pending_request.full_message_id_,
|
choose_animated_emoji_click_sticker(sticker_set, std::move(pending_request.message_text_),
|
||||||
pending_request.start_time_, std::move(pending_request.promise_));
|
pending_request.full_message_id_, pending_request.start_time_,
|
||||||
|
std::move(pending_request.promise_));
|
||||||
}
|
}
|
||||||
auto pending_click_requests = std::move(pending_on_animated_emoji_message_clicked_);
|
auto pending_click_requests = std::move(pending_on_animated_emoji_message_clicked_);
|
||||||
reset_to_empty(pending_on_animated_emoji_message_clicked_);
|
reset_to_empty(pending_on_animated_emoji_message_clicked_);
|
||||||
|
@ -2079,7 +2084,7 @@ std::pair<FileId, int> StickersManager::get_animated_emoji_sticker(const Sticker
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto emoji_without_modifiers = remove_emoji_modifiers(emoji).str();
|
auto emoji_without_modifiers = remove_emoji_modifiers(emoji);
|
||||||
auto it = sticker_set->emoji_stickers_map_.find(emoji_without_modifiers);
|
auto it = sticker_set->emoji_stickers_map_.find(emoji_without_modifiers);
|
||||||
if (it == sticker_set->emoji_stickers_map_.end()) {
|
if (it == sticker_set->emoji_stickers_map_.end()) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -2748,13 +2753,13 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_view.is_encrypted_secret()) {
|
if (file_view.is_encrypted_secret()) {
|
||||||
auto &encryption_key = file_view.encryption_key();
|
return {std::move(input_file),
|
||||||
return SecretInputMedia{std::move(input_file),
|
std::move(thumbnail),
|
||||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
sticker->s_thumbnail.dimensions,
|
||||||
std::move(thumbnail), sticker->s_thumbnail.dimensions.width,
|
get_sticker_format_mime_type(sticker->format),
|
||||||
sticker->s_thumbnail.dimensions.height, get_sticker_format_mime_type(sticker->format),
|
file_view,
|
||||||
narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
std::move(attributes),
|
||||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), "")};
|
string()};
|
||||||
} else {
|
} else {
|
||||||
CHECK(!file_view.is_encrypted());
|
CHECK(!file_view.is_encrypted());
|
||||||
auto &remote_location = file_view.remote_location();
|
auto &remote_location = file_view.remote_location();
|
||||||
|
@ -3084,7 +3089,7 @@ StickerSetId StickersManager::on_get_messages_sticker_set(StickerSetId sticker_s
|
||||||
s->emoji_stickers_map_.clear();
|
s->emoji_stickers_map_.clear();
|
||||||
s->sticker_emojis_map_.clear();
|
s->sticker_emojis_map_.clear();
|
||||||
for (auto &pack : packs) {
|
for (auto &pack : packs) {
|
||||||
auto cleaned_emoji = remove_emoji_modifiers(pack->emoticon_).str();
|
auto cleaned_emoji = remove_emoji_modifiers(pack->emoticon_);
|
||||||
if (cleaned_emoji.empty()) {
|
if (cleaned_emoji.empty()) {
|
||||||
LOG(ERROR) << "Receive empty emoji in " << set_id << "/" << s->short_name << " from " << source;
|
LOG(ERROR) << "Receive empty emoji in " << set_id << "/" << s->short_name << " from " << source;
|
||||||
continue;
|
continue;
|
||||||
|
@ -4640,11 +4645,11 @@ vector<FileId> StickersManager::get_animated_emoji_click_stickers(const StickerS
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersManager::choose_animated_emoji_click_sticker(const StickerSet *sticker_set, Slice message_text,
|
void StickersManager::choose_animated_emoji_click_sticker(const StickerSet *sticker_set, string message_text,
|
||||||
FullMessageId full_message_id, double start_time,
|
FullMessageId full_message_id, double start_time,
|
||||||
Promise<td_api::object_ptr<td_api::sticker>> &&promise) {
|
Promise<td_api::object_ptr<td_api::sticker>> &&promise) {
|
||||||
CHECK(sticker_set->was_loaded);
|
CHECK(sticker_set->was_loaded);
|
||||||
message_text = remove_emoji_modifiers(message_text);
|
remove_emoji_modifiers_in_place(message_text);
|
||||||
if (message_text.empty()) {
|
if (message_text.empty()) {
|
||||||
return promise.set_error(Status::Error(400, "Message is not an animated emoji message"));
|
return promise.set_error(Status::Error(400, "Message is not an animated emoji message"));
|
||||||
}
|
}
|
||||||
|
@ -4682,7 +4687,7 @@ void StickersManager::choose_animated_emoji_click_sticker(const StickerSet *stic
|
||||||
}
|
}
|
||||||
if (last_clicked_animated_emoji_ != message_text) {
|
if (last_clicked_animated_emoji_ != message_text) {
|
||||||
pending_animated_emoji_clicks_.clear();
|
pending_animated_emoji_clicks_.clear();
|
||||||
last_clicked_animated_emoji_ = message_text.str();
|
last_clicked_animated_emoji_ = std::move(message_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pending_animated_emoji_clicks_.empty() && found_stickers.size() >= 2) {
|
if (!pending_animated_emoji_clicks_.empty() && found_stickers.size() >= 2) {
|
||||||
|
@ -4798,7 +4803,7 @@ void StickersManager::flush_sent_animated_emoji_clicks() {
|
||||||
sent_animated_emoji_clicks_.erase(sent_animated_emoji_clicks_.begin(), it);
|
sent_animated_emoji_clicks_.erase(sent_animated_emoji_clicks_.begin(), it);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StickersManager::is_sent_animated_emoji_click(DialogId dialog_id, Slice emoji) {
|
bool StickersManager::is_sent_animated_emoji_click(DialogId dialog_id, const string &emoji) {
|
||||||
flush_sent_animated_emoji_clicks();
|
flush_sent_animated_emoji_clicks();
|
||||||
for (const auto &click : sent_animated_emoji_clicks_) {
|
for (const auto &click : sent_animated_emoji_clicks_) {
|
||||||
if (click.dialog_id == dialog_id && click.emoji == emoji) {
|
if (click.dialog_id == dialog_id && click.emoji == emoji) {
|
||||||
|
@ -4808,7 +4813,7 @@ bool StickersManager::is_sent_animated_emoji_click(DialogId dialog_id, Slice emo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status StickersManager::on_animated_emoji_message_clicked(Slice emoji, FullMessageId full_message_id, string data) {
|
Status StickersManager::on_animated_emoji_message_clicked(string &&emoji, FullMessageId full_message_id, string data) {
|
||||||
if (td_->auth_manager_->is_bot() || disable_animated_emojis_) {
|
if (td_->auth_manager_->is_bot() || disable_animated_emojis_) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
@ -4871,7 +4876,7 @@ Status StickersManager::on_animated_emoji_message_clicked(Slice emoji, FullMessa
|
||||||
load_special_sticker_set(special_sticker_set);
|
load_special_sticker_set(special_sticker_set);
|
||||||
|
|
||||||
PendingOnAnimatedEmojiClicked pending_request;
|
PendingOnAnimatedEmojiClicked pending_request;
|
||||||
pending_request.emoji_ = emoji.str();
|
pending_request.emoji_ = std::move(emoji);
|
||||||
pending_request.full_message_id_ = full_message_id;
|
pending_request.full_message_id_ = full_message_id;
|
||||||
pending_request.clicks_ = std::move(clicks);
|
pending_request.clicks_ = std::move(clicks);
|
||||||
pending_on_animated_emoji_message_clicked_.push_back(std::move(pending_request));
|
pending_on_animated_emoji_message_clicked_.push_back(std::move(pending_request));
|
||||||
|
@ -7627,26 +7632,6 @@ td_api::object_ptr<td_api::httpUrl> StickersManager::get_emoji_suggestions_url_r
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersManager::after_get_difference() {
|
|
||||||
if (td_->auth_manager_->is_bot()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
reload_reactions();
|
|
||||||
if (td_->is_online()) {
|
|
||||||
get_installed_sticker_sets(false, Auto());
|
|
||||||
get_installed_sticker_sets(true, Auto());
|
|
||||||
get_featured_sticker_sets(0, 1000, Auto());
|
|
||||||
get_recent_stickers(false, Auto());
|
|
||||||
get_recent_stickers(true, Auto());
|
|
||||||
get_favorite_stickers(Auto());
|
|
||||||
|
|
||||||
if (!disable_animated_emojis_) {
|
|
||||||
reload_special_sticker_set_by_type(SpecialStickerSetType::animated_emoji());
|
|
||||||
reload_special_sticker_set_by_type(SpecialStickerSetType::animated_emoji_click());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
||||||
if (td_->auth_manager_->is_bot()) {
|
if (td_->auth_manager_->is_bot()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -89,9 +89,9 @@ class StickersManager final : public Actor {
|
||||||
|
|
||||||
void on_send_animated_emoji_clicks(DialogId dialog_id, const string &emoji);
|
void on_send_animated_emoji_clicks(DialogId dialog_id, const string &emoji);
|
||||||
|
|
||||||
bool is_sent_animated_emoji_click(DialogId dialog_id, Slice emoji);
|
bool is_sent_animated_emoji_click(DialogId dialog_id, const string &emoji);
|
||||||
|
|
||||||
Status on_animated_emoji_message_clicked(Slice emoji, FullMessageId full_message_id, string data);
|
Status on_animated_emoji_message_clicked(string &&emoji, FullMessageId full_message_id, string data);
|
||||||
|
|
||||||
bool is_active_reaction(const string &reaction) const;
|
bool is_active_reaction(const string &reaction) const;
|
||||||
|
|
||||||
|
@ -135,6 +135,10 @@ class StickersManager final : public Actor {
|
||||||
|
|
||||||
void view_featured_sticker_sets(const vector<StickerSetId> &sticker_set_ids);
|
void view_featured_sticker_sets(const vector<StickerSetId> &sticker_set_ids);
|
||||||
|
|
||||||
|
void reload_reactions();
|
||||||
|
|
||||||
|
void reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false);
|
||||||
|
|
||||||
void on_get_available_reactions(tl_object_ptr<telegram_api::messages_AvailableReactions> &&available_reactions_ptr);
|
void on_get_available_reactions(tl_object_ptr<telegram_api::messages_AvailableReactions> &&available_reactions_ptr);
|
||||||
|
|
||||||
void on_get_installed_sticker_sets(bool is_masks, tl_object_ptr<telegram_api::messages_AllStickers> &&stickers_ptr);
|
void on_get_installed_sticker_sets(bool is_masks, tl_object_ptr<telegram_api::messages_AllStickers> &&stickers_ptr);
|
||||||
|
@ -321,8 +325,6 @@ class StickersManager final : public Actor {
|
||||||
|
|
||||||
void send_get_attached_stickers_query(FileId file_id, Promise<Unit> &&promise);
|
void send_get_attached_stickers_query(FileId file_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void after_get_difference();
|
|
||||||
|
|
||||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
|
@ -676,7 +678,7 @@ class StickersManager final : public Actor {
|
||||||
|
|
||||||
vector<FileId> get_animated_emoji_click_stickers(const StickerSet *sticker_set, Slice emoji) const;
|
vector<FileId> get_animated_emoji_click_stickers(const StickerSet *sticker_set, Slice emoji) const;
|
||||||
|
|
||||||
void choose_animated_emoji_click_sticker(const StickerSet *sticker_set, Slice message_text,
|
void choose_animated_emoji_click_sticker(const StickerSet *sticker_set, string message_text,
|
||||||
FullMessageId full_message_id, double start_time,
|
FullMessageId full_message_id, double start_time,
|
||||||
Promise<td_api::object_ptr<td_api::sticker>> &&promise);
|
Promise<td_api::object_ptr<td_api::sticker>> &&promise);
|
||||||
|
|
||||||
|
@ -704,8 +706,6 @@ class StickersManager final : public Actor {
|
||||||
|
|
||||||
void load_reactions();
|
void load_reactions();
|
||||||
|
|
||||||
void reload_reactions();
|
|
||||||
|
|
||||||
void update_active_reactions();
|
void update_active_reactions();
|
||||||
|
|
||||||
td_api::object_ptr<td_api::updateReactions> get_update_reactions_object() const;
|
td_api::object_ptr<td_api::updateReactions> get_update_reactions_object() const;
|
||||||
|
@ -721,8 +721,6 @@ class StickersManager final : public Actor {
|
||||||
|
|
||||||
void load_special_sticker_set(SpecialStickerSet &sticker_set);
|
void load_special_sticker_set(SpecialStickerSet &sticker_set);
|
||||||
|
|
||||||
void reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false);
|
|
||||||
|
|
||||||
void reload_special_sticker_set(SpecialStickerSet &sticker_set, int32 hash);
|
void reload_special_sticker_set(SpecialStickerSet &sticker_set, int32 hash);
|
||||||
|
|
||||||
static void add_sticker_thumbnail(Sticker *s, PhotoSize thumbnail);
|
static void add_sticker_thumbnail(Sticker *s, PhotoSize thumbnail);
|
||||||
|
|
|
@ -341,7 +341,7 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
|
||||||
vector<string> emojis;
|
vector<string> emojis;
|
||||||
parse(emojis, parser);
|
parse(emojis, parser);
|
||||||
for (auto &emoji : emojis) {
|
for (auto &emoji : emojis) {
|
||||||
auto cleaned_emoji = remove_emoji_modifiers(emoji).str();
|
auto cleaned_emoji = remove_emoji_modifiers(emoji);
|
||||||
if (!cleaned_emoji.empty()) {
|
if (!cleaned_emoji.empty()) {
|
||||||
auto &sticker_ids = sticker_set->emoji_stickers_map_[cleaned_emoji];
|
auto &sticker_ids = sticker_set->emoji_stickers_map_[cleaned_emoji];
|
||||||
if (sticker_ids.empty() || sticker_ids.back() != sticker_id) {
|
if (sticker_ids.empty() || sticker_ids.back() != sticker_id) {
|
||||||
|
|
|
@ -2676,22 +2676,6 @@ class GetInlineQueryResultsRequest final : public RequestOnceActor {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetSupportUserRequest final : public RequestActor<> {
|
|
||||||
UserId user_id_;
|
|
||||||
|
|
||||||
void do_run(Promise<Unit> &&promise) final {
|
|
||||||
user_id_ = td_->contacts_manager_->get_support_user(std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_send_result() final {
|
|
||||||
send_result(td_->contacts_manager_->get_user_object(user_id_));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
GetSupportUserRequest(ActorShared<Td> td, uint64 request_id) : RequestActor(std::move(td), request_id) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SearchBackgroundRequest final : public RequestActor<> {
|
class SearchBackgroundRequest final : public RequestActor<> {
|
||||||
string name_;
|
string name_;
|
||||||
|
|
||||||
|
@ -3687,9 +3671,6 @@ void Td::close_impl(bool destroy_flag) {
|
||||||
|
|
||||||
class Td::DownloadFileCallback final : public FileManager::DownloadCallback {
|
class Td::DownloadFileCallback final : public FileManager::DownloadCallback {
|
||||||
public:
|
public:
|
||||||
void on_progress(FileId file_id) final {
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_download_ok(FileId file_id) final {
|
void on_download_ok(FileId file_id) final {
|
||||||
send_closure(G()->td(), &Td::on_file_download_finished, file_id);
|
send_closure(G()->td(), &Td::on_file_download_finished, file_id);
|
||||||
}
|
}
|
||||||
|
@ -3701,9 +3682,6 @@ class Td::DownloadFileCallback final : public FileManager::DownloadCallback {
|
||||||
|
|
||||||
class Td::UploadFileCallback final : public FileManager::UploadCallback {
|
class Td::UploadFileCallback final : public FileManager::UploadCallback {
|
||||||
public:
|
public:
|
||||||
void on_progress(FileId file_id) final {
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
|
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
|
||||||
// cancel file upload of the file to allow next upload with the same file to succeed
|
// cancel file upload of the file to allow next upload with the same file to succeed
|
||||||
send_closure(G()->file_manager(), &FileManager::cancel_upload, file_id);
|
send_closure(G()->file_manager(), &FileManager::cancel_upload, file_id);
|
||||||
|
@ -7766,7 +7744,8 @@ void Td::on_request(uint64 id, td_api::checkPhoneNumberConfirmationCode &request
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getSupportUser &request) {
|
void Td::on_request(uint64 id, const td_api::getSupportUser &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_NO_ARGS_REQUEST(GetSupportUserRequest);
|
CREATE_REQUEST_PROMISE();
|
||||||
|
contacts_manager_->get_support_user(std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getBackgrounds &request) {
|
void Td::on_request(uint64 id, const td_api::getBackgrounds &request) {
|
||||||
|
|
|
@ -38,10 +38,12 @@
|
||||||
#include "td/telegram/PollId.h"
|
#include "td/telegram/PollId.h"
|
||||||
#include "td/telegram/PollManager.h"
|
#include "td/telegram/PollManager.h"
|
||||||
#include "td/telegram/PrivacyManager.h"
|
#include "td/telegram/PrivacyManager.h"
|
||||||
|
#include "td/telegram/PublicDialogType.h"
|
||||||
#include "td/telegram/ScheduledServerMessageId.h"
|
#include "td/telegram/ScheduledServerMessageId.h"
|
||||||
#include "td/telegram/SecretChatId.h"
|
#include "td/telegram/SecretChatId.h"
|
||||||
#include "td/telegram/SecretChatsManager.h"
|
#include "td/telegram/SecretChatsManager.h"
|
||||||
#include "td/telegram/ServerMessageId.h"
|
#include "td/telegram/ServerMessageId.h"
|
||||||
|
#include "td/telegram/SpecialStickerSetType.h"
|
||||||
#include "td/telegram/StateManager.h"
|
#include "td/telegram/StateManager.h"
|
||||||
#include "td/telegram/StickerSetId.h"
|
#include "td/telegram/StickerSetId.h"
|
||||||
#include "td/telegram/StickersManager.h"
|
#include "td/telegram/StickersManager.h"
|
||||||
|
@ -181,6 +183,26 @@ void UpdatesManager::tear_down() {
|
||||||
LOG(DEBUG) << "Have " << being_processed_updates_ << " unprocessed updates to apply";
|
LOG(DEBUG) << "Have " << being_processed_updates_ << " unprocessed updates to apply";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdatesManager::start_up() {
|
||||||
|
class StateCallback final : public StateManager::Callback {
|
||||||
|
public:
|
||||||
|
explicit StateCallback(ActorId<UpdatesManager> parent) : parent_(std::move(parent)) {
|
||||||
|
}
|
||||||
|
bool on_online(bool is_online) final {
|
||||||
|
if (is_online) {
|
||||||
|
send_closure(parent_, &UpdatesManager::try_reload_data);
|
||||||
|
}
|
||||||
|
return parent_.is_alive();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActorId<UpdatesManager> parent_;
|
||||||
|
};
|
||||||
|
send_closure(G()->state_manager(), &StateManager::add_callback, make_unique<StateCallback>(actor_id(this)));
|
||||||
|
|
||||||
|
next_data_reload_time_ = Time::now() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void UpdatesManager::hangup_shared() {
|
void UpdatesManager::hangup_shared() {
|
||||||
ref_cnt_--;
|
ref_cnt_--;
|
||||||
if (ref_cnt_ == 0) {
|
if (ref_cnt_ == 0) {
|
||||||
|
@ -1557,15 +1579,65 @@ void UpdatesManager::after_get_difference() {
|
||||||
<< postponed_pts_updates_.size() << " pending pts updates";
|
<< postponed_pts_updates_.size() << " pending pts updates";
|
||||||
}
|
}
|
||||||
|
|
||||||
td_->animations_manager_->after_get_difference();
|
|
||||||
td_->contacts_manager_->after_get_difference();
|
|
||||||
td_->download_manager_->after_get_difference();
|
td_->download_manager_->after_get_difference();
|
||||||
td_->inline_queries_manager_->after_get_difference();
|
td_->inline_queries_manager_->after_get_difference();
|
||||||
td_->messages_manager_->after_get_difference();
|
td_->messages_manager_->after_get_difference();
|
||||||
td_->notification_settings_manager_->after_get_difference();
|
td_->notification_settings_manager_->after_get_difference();
|
||||||
td_->stickers_manager_->after_get_difference();
|
|
||||||
send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference);
|
send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference);
|
||||||
send_closure(G()->state_manager(), &StateManager::on_synchronized, true);
|
send_closure(G()->state_manager(), &StateManager::on_synchronized, true);
|
||||||
|
|
||||||
|
try_reload_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatesManager::schedule_data_reload() {
|
||||||
|
if (data_reload_timeout_.has_timeout()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto timeout = next_data_reload_time_ - Time::now();
|
||||||
|
LOG(INFO) << "Schedule data reload in " << timeout;
|
||||||
|
data_reload_timeout_.set_callback(std::move(try_reload_data_static));
|
||||||
|
data_reload_timeout_.set_callback_data(static_cast<void *>(td_));
|
||||||
|
data_reload_timeout_.set_timeout_in(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatesManager::try_reload_data_static(void *td) {
|
||||||
|
CHECK(td != nullptr);
|
||||||
|
if (G()->close_flag()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_cast<Td *>(td)->updates_manager_->try_reload_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatesManager::try_reload_data() {
|
||||||
|
if (td_->auth_manager_->is_bot() || running_get_difference_ || !td_->is_online()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto now = Time::now();
|
||||||
|
if (now < next_data_reload_time_) {
|
||||||
|
schedule_data_reload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next_data_reload_time_ = now + Random::fast(3000, 4200);
|
||||||
|
|
||||||
|
LOG(INFO) << "Reload data";
|
||||||
|
td_->animations_manager_->get_saved_animations(Auto());
|
||||||
|
td_->contacts_manager_->reload_created_public_dialogs(PublicDialogType::HasUsername, Auto());
|
||||||
|
td_->contacts_manager_->reload_created_public_dialogs(PublicDialogType::IsLocationBased, Auto());
|
||||||
|
td_->notification_settings_manager_->reload_saved_ringtones(Auto());
|
||||||
|
td_->stickers_manager_->reload_reactions();
|
||||||
|
td_->stickers_manager_->get_installed_sticker_sets(false, Auto());
|
||||||
|
td_->stickers_manager_->get_installed_sticker_sets(true, Auto());
|
||||||
|
td_->stickers_manager_->get_featured_sticker_sets(0, 1000, Auto());
|
||||||
|
td_->stickers_manager_->get_recent_stickers(false, Auto());
|
||||||
|
td_->stickers_manager_->get_recent_stickers(true, Auto());
|
||||||
|
td_->stickers_manager_->get_favorite_stickers(Auto());
|
||||||
|
td_->stickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::animated_emoji());
|
||||||
|
td_->stickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::animated_emoji_click());
|
||||||
|
|
||||||
|
schedule_data_reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, int32 seq_begin,
|
void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, int32 seq_begin,
|
||||||
|
|
|
@ -221,12 +221,17 @@ class UpdatesManager final : public Actor {
|
||||||
int32 retry_time_ = 1;
|
int32 retry_time_ = 1;
|
||||||
Timeout retry_timeout_;
|
Timeout retry_timeout_;
|
||||||
|
|
||||||
|
double next_data_reload_time_ = 0.0;
|
||||||
|
Timeout data_reload_timeout_;
|
||||||
|
|
||||||
bool running_get_difference_ = false;
|
bool running_get_difference_ = false;
|
||||||
int32 last_get_difference_pts_ = 0;
|
int32 last_get_difference_pts_ = 0;
|
||||||
int32 last_get_difference_qts_ = 0;
|
int32 last_get_difference_qts_ = 0;
|
||||||
int32 min_postponed_update_pts_ = 0;
|
int32 min_postponed_update_pts_ = 0;
|
||||||
int32 min_postponed_update_qts_ = 0;
|
int32 min_postponed_update_qts_ = 0;
|
||||||
|
|
||||||
|
void start_up() final;
|
||||||
|
|
||||||
void tear_down() final;
|
void tear_down() final;
|
||||||
|
|
||||||
void hangup_shared() final;
|
void hangup_shared() final;
|
||||||
|
@ -331,6 +336,12 @@ class UpdatesManager final : public Actor {
|
||||||
|
|
||||||
void after_get_difference();
|
void after_get_difference();
|
||||||
|
|
||||||
|
void schedule_data_reload();
|
||||||
|
|
||||||
|
static void try_reload_data_static(void *td);
|
||||||
|
|
||||||
|
void try_reload_data();
|
||||||
|
|
||||||
static bool have_update_pts_changed(const vector<tl_object_ptr<telegram_api::Update>> &updates);
|
static bool have_update_pts_changed(const vector<tl_object_ptr<telegram_api::Update>> &updates);
|
||||||
|
|
||||||
static bool check_pts_update_dialog_id(DialogId dialog_id);
|
static bool check_pts_update_dialog_id(DialogId dialog_id);
|
||||||
|
|
|
@ -50,6 +50,7 @@ enum class Version : int32 {
|
||||||
AddInviteLinksRequiringApproval,
|
AddInviteLinksRequiringApproval,
|
||||||
AddKeyboardButtonFlags, // 35
|
AddKeyboardButtonFlags, // 35
|
||||||
AddAudioFlags,
|
AddAudioFlags,
|
||||||
|
UseServerForwardAsCopy,
|
||||||
Next
|
Next
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -162,8 +162,7 @@ SecretInputMedia VideoNotesManager::get_secret_input_media(FileId video_note_fil
|
||||||
const VideoNote *video_note = get_video_note(video_note_file_id);
|
const VideoNote *video_note = get_video_note(video_note_file_id);
|
||||||
CHECK(video_note != nullptr);
|
CHECK(video_note != nullptr);
|
||||||
auto file_view = td_->file_manager_->get_file_view(video_note_file_id);
|
auto file_view = td_->file_manager_->get_file_view(video_note_file_id);
|
||||||
auto &encryption_key = file_view.encryption_key();
|
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||||
if (!file_view.is_encrypted_secret() || encryption_key.empty()) {
|
|
||||||
return SecretInputMedia{};
|
return SecretInputMedia{};
|
||||||
}
|
}
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
|
@ -179,12 +178,14 @@ SecretInputMedia VideoNotesManager::get_secret_input_media(FileId video_note_fil
|
||||||
attributes.push_back(make_tl_object<secret_api::documentAttributeVideo66>(
|
attributes.push_back(make_tl_object<secret_api::documentAttributeVideo66>(
|
||||||
secret_api::documentAttributeVideo66::ROUND_MESSAGE_MASK, true, video_note->duration,
|
secret_api::documentAttributeVideo66::ROUND_MESSAGE_MASK, true, video_note->duration,
|
||||||
video_note->dimensions.width, video_note->dimensions.height));
|
video_note->dimensions.width, video_note->dimensions.height));
|
||||||
return SecretInputMedia{
|
|
||||||
std::move(input_file),
|
return {std::move(input_file),
|
||||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
std::move(thumbnail),
|
||||||
std::move(thumbnail), video_note->thumbnail.dimensions.width, video_note->thumbnail.dimensions.height,
|
video_note->thumbnail.dimensions,
|
||||||
"video/mp4", narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
"video/mp4",
|
||||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), "")};
|
file_view,
|
||||||
|
std::move(attributes),
|
||||||
|
string()};
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputMedia> VideoNotesManager::get_input_media(
|
tl_object_ptr<telegram_api::InputMedia> VideoNotesManager::get_input_media(
|
||||||
|
|
|
@ -208,8 +208,7 @@ SecretInputMedia VideosManager::get_secret_input_media(FileId video_file_id,
|
||||||
const Video *video = get_video(video_file_id);
|
const Video *video = get_video(video_file_id);
|
||||||
CHECK(video != nullptr);
|
CHECK(video != nullptr);
|
||||||
auto file_view = td_->file_manager_->get_file_view(video_file_id);
|
auto file_view = td_->file_manager_->get_file_view(video_file_id);
|
||||||
auto &encryption_key = file_view.encryption_key();
|
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||||
if (!file_view.is_encrypted_secret() || encryption_key.empty()) {
|
|
||||||
return SecretInputMedia{};
|
return SecretInputMedia{};
|
||||||
}
|
}
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
|
@ -221,12 +220,17 @@ SecretInputMedia VideosManager::get_secret_input_media(FileId video_file_id,
|
||||||
if (video->thumbnail.file_id.is_valid() && thumbnail.empty()) {
|
if (video->thumbnail.file_id.is_valid() && thumbnail.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return SecretInputMedia{
|
vector<tl_object_ptr<secret_api::DocumentAttribute>> attributes;
|
||||||
std::move(input_file),
|
attributes.emplace_back(make_tl_object<secret_api::documentAttributeVideo>(video->duration, video->dimensions.width,
|
||||||
make_tl_object<secret_api::decryptedMessageMediaVideo>(
|
video->dimensions.height));
|
||||||
std::move(thumbnail), video->thumbnail.dimensions.width, video->thumbnail.dimensions.height, video->duration,
|
|
||||||
video->mime_type, video->dimensions.width, video->dimensions.height, narrow_cast<int32>(file_view.size()),
|
return {std::move(input_file),
|
||||||
BufferSlice(encryption_key.key_slice()), BufferSlice(encryption_key.iv_slice()), caption)};
|
std::move(thumbnail),
|
||||||
|
video->thumbnail.dimensions,
|
||||||
|
video->mime_type,
|
||||||
|
file_view,
|
||||||
|
std::move(attributes),
|
||||||
|
caption};
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputMedia> VideosManager::get_input_media(
|
tl_object_ptr<telegram_api::InputMedia> VideosManager::get_input_media(
|
||||||
|
|
|
@ -133,8 +133,7 @@ SecretInputMedia VoiceNotesManager::get_secret_input_media(FileId voice_file_id,
|
||||||
auto *voice_note = get_voice_note(voice_file_id);
|
auto *voice_note = get_voice_note(voice_file_id);
|
||||||
CHECK(voice_note != nullptr);
|
CHECK(voice_note != nullptr);
|
||||||
auto file_view = td_->file_manager_->get_file_view(voice_file_id);
|
auto file_view = td_->file_manager_->get_file_view(voice_file_id);
|
||||||
auto &encryption_key = file_view.encryption_key();
|
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||||
if (!file_view.is_encrypted_secret() || encryption_key.empty()) {
|
|
||||||
return SecretInputMedia{};
|
return SecretInputMedia{};
|
||||||
}
|
}
|
||||||
if (file_view.has_remote_location()) {
|
if (file_view.has_remote_location()) {
|
||||||
|
@ -147,11 +146,9 @@ SecretInputMedia VoiceNotesManager::get_secret_input_media(FileId voice_file_id,
|
||||||
attributes.push_back(make_tl_object<secret_api::documentAttributeAudio>(
|
attributes.push_back(make_tl_object<secret_api::documentAttributeAudio>(
|
||||||
secret_api::documentAttributeAudio::VOICE_MASK | secret_api::documentAttributeAudio::WAVEFORM_MASK,
|
secret_api::documentAttributeAudio::VOICE_MASK | secret_api::documentAttributeAudio::WAVEFORM_MASK,
|
||||||
false /*ignored*/, voice_note->duration, "", "", BufferSlice(voice_note->waveform)));
|
false /*ignored*/, voice_note->duration, "", "", BufferSlice(voice_note->waveform)));
|
||||||
return SecretInputMedia{std::move(input_file),
|
|
||||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
return {std::move(input_file), BufferSlice(), Dimensions(), voice_note->mime_type, file_view,
|
||||||
BufferSlice(), 0, 0, voice_note->mime_type, narrow_cast<int32>(file_view.size()),
|
std::move(attributes), caption};
|
||||||
BufferSlice(encryption_key.key_slice()), BufferSlice(encryption_key.iv_slice()),
|
|
||||||
std::move(attributes), caption)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputMedia> VoiceNotesManager::get_input_media(
|
tl_object_ptr<telegram_api::InputMedia> VoiceNotesManager::get_input_media(
|
||||||
|
|
|
@ -373,9 +373,6 @@ class FileManager final : public FileLoadManager::Callback {
|
||||||
UploadCallback &operator=(const UploadCallback &) = delete;
|
UploadCallback &operator=(const UploadCallback &) = delete;
|
||||||
virtual ~UploadCallback() = default;
|
virtual ~UploadCallback() = default;
|
||||||
|
|
||||||
virtual void on_progress(FileId file_id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// After on_upload_ok all uploads of this file will be paused till merge, delete_partial_remote_location or
|
// After on_upload_ok all uploads of this file will be paused till merge, delete_partial_remote_location or
|
||||||
// explicit upload request with the same file_id.
|
// explicit upload request with the same file_id.
|
||||||
// Also upload may be resumed after some other merges.
|
// Also upload may be resumed after some other merges.
|
||||||
|
|
|
@ -305,6 +305,7 @@ set(TDUTILS_TEST_SOURCE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/ChainScheduler.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/ChainScheduler.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/emoji.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/Enumerator.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/Enumerator.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/EpochBasedMemoryReclamation.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/EpochBasedMemoryReclamation.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/filesystem.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/filesystem.cpp
|
||||||
|
|
|
@ -243,7 +243,13 @@ Slice remove_fitzpatrick_modifier(Slice emoji) {
|
||||||
return emoji;
|
return emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice remove_emoji_modifiers(Slice emoji) {
|
string remove_emoji_modifiers(Slice emoji) {
|
||||||
|
string result = emoji.str();
|
||||||
|
remove_emoji_modifiers_in_place(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_emoji_modifiers_in_place(string &emoji) {
|
||||||
static const Slice modifiers[] = {u8"\uFE0F" /* variation selector-16 */,
|
static const Slice modifiers[] = {u8"\uFE0F" /* variation selector-16 */,
|
||||||
u8"\u200D\u2640" /* zero width joiner + female sign */,
|
u8"\u200D\u2640" /* zero width joiner + female sign */,
|
||||||
u8"\u200D\u2642" /* zero width joiner + male sign */,
|
u8"\u200D\u2642" /* zero width joiner + male sign */,
|
||||||
|
@ -252,21 +258,23 @@ Slice remove_emoji_modifiers(Slice emoji) {
|
||||||
u8"\U0001F3FD" /* emoji modifier fitzpatrick type-4 */,
|
u8"\U0001F3FD" /* emoji modifier fitzpatrick type-4 */,
|
||||||
u8"\U0001F3FE" /* emoji modifier fitzpatrick type-5 */,
|
u8"\U0001F3FE" /* emoji modifier fitzpatrick type-5 */,
|
||||||
u8"\U0001F3FF" /* emoji modifier fitzpatrick type-6 */};
|
u8"\U0001F3FF" /* emoji modifier fitzpatrick type-6 */};
|
||||||
bool found = true;
|
size_t j = 0;
|
||||||
while (found) {
|
for (size_t i = 0; i < emoji.size();) {
|
||||||
found = false;
|
bool is_found = false;
|
||||||
for (auto &modifier : modifiers) {
|
for (auto &modifier : modifiers) {
|
||||||
if (ends_with(emoji, modifier) && emoji.size() > modifier.size()) {
|
auto length = modifier.size();
|
||||||
emoji.remove_suffix(modifier.size());
|
if (i + length <= emoji.size() && Slice(&emoji[i], length) == modifier) {
|
||||||
found = true;
|
// skip modifier
|
||||||
|
i += length;
|
||||||
|
is_found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!is_found) {
|
||||||
|
emoji[j++] = emoji[i++];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return emoji;
|
emoji.resize(j);
|
||||||
}
|
|
||||||
|
|
||||||
void remove_emoji_modifiers_in_place(string &emoji) {
|
|
||||||
emoji.resize(remove_emoji_modifiers(emoji).size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string remove_emoji_selectors(Slice emoji) {
|
string remove_emoji_selectors(Slice emoji) {
|
||||||
|
|
|
@ -20,10 +20,10 @@ int get_fitzpatrick_modifier(Slice emoji);
|
||||||
// removes all Fitzpatrick modifier from the end of the string
|
// removes all Fitzpatrick modifier from the end of the string
|
||||||
Slice remove_fitzpatrick_modifier(Slice emoji);
|
Slice remove_fitzpatrick_modifier(Slice emoji);
|
||||||
|
|
||||||
// removes all emoji modifiers from the end of the string
|
// removes all emoji modifiers from the string
|
||||||
Slice remove_emoji_modifiers(Slice emoji);
|
string remove_emoji_modifiers(Slice emoji);
|
||||||
|
|
||||||
// removes all emoji modifiers from the end of the string in place
|
// removes all emoji modifiers from the string in-place
|
||||||
void remove_emoji_modifiers_in_place(string &emoji);
|
void remove_emoji_modifiers_in_place(string &emoji);
|
||||||
|
|
||||||
// removes all emoji selectors from the string if it is an emoji
|
// removes all emoji selectors from the string if it is an emoji
|
||||||
|
|
125
tdutils/test/emoji.cpp
Normal file
125
tdutils/test/emoji.cpp
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#include "td/utils/emoji.h"
|
||||||
|
#include "td/utils/tests.h"
|
||||||
|
|
||||||
|
TEST(Emoji, is_emoji) {
|
||||||
|
ASSERT_TRUE(!td::is_emoji(""));
|
||||||
|
ASSERT_TRUE(td::is_emoji("👩🏼❤💋👩🏻"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("👩🏼❤️💋👩🏻"));
|
||||||
|
ASSERT_TRUE(!td::is_emoji("👩🏼❤️️💋👩🏻"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("⌚"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("↔"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("🪗"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("2️⃣"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("2⃣"));
|
||||||
|
ASSERT_TRUE(!td::is_emoji(" 2⃣"));
|
||||||
|
ASSERT_TRUE(!td::is_emoji("2⃣ "));
|
||||||
|
ASSERT_TRUE(!td::is_emoji(" "));
|
||||||
|
ASSERT_TRUE(!td::is_emoji(""));
|
||||||
|
ASSERT_TRUE(!td::is_emoji("1234567890123456789012345678901234567890123456789012345678901234567890"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("❤️"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("❤"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("⌚"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("🎄"));
|
||||||
|
ASSERT_TRUE(td::is_emoji("🧑🎄"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_get_fitzpatrick_modifier(td::string emoji, int result) {
|
||||||
|
ASSERT_EQ(result, td::get_fitzpatrick_modifier(emoji));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Emoji, get_fitzpatrick_modifier) {
|
||||||
|
test_get_fitzpatrick_modifier("", 0);
|
||||||
|
test_get_fitzpatrick_modifier("👩🏼❤💋👩🏻", 2);
|
||||||
|
test_get_fitzpatrick_modifier("👩🏼❤️💋👩🏻", 2);
|
||||||
|
test_get_fitzpatrick_modifier("👋", 0);
|
||||||
|
test_get_fitzpatrick_modifier("👋🏻", 2);
|
||||||
|
test_get_fitzpatrick_modifier("👋🏼", 3);
|
||||||
|
test_get_fitzpatrick_modifier("👋🏽", 4);
|
||||||
|
test_get_fitzpatrick_modifier("👋🏾", 5);
|
||||||
|
test_get_fitzpatrick_modifier("👋🏿", 6);
|
||||||
|
test_get_fitzpatrick_modifier("🏻", 2);
|
||||||
|
test_get_fitzpatrick_modifier("🏼", 3);
|
||||||
|
test_get_fitzpatrick_modifier("🏽", 4);
|
||||||
|
test_get_fitzpatrick_modifier("🏾", 5);
|
||||||
|
test_get_fitzpatrick_modifier("🏿", 6);
|
||||||
|
test_get_fitzpatrick_modifier("⌚", 0);
|
||||||
|
test_get_fitzpatrick_modifier("↔", 0);
|
||||||
|
test_get_fitzpatrick_modifier("🪗", 0);
|
||||||
|
test_get_fitzpatrick_modifier("2️⃣", 0);
|
||||||
|
test_get_fitzpatrick_modifier("2⃣", 0);
|
||||||
|
test_get_fitzpatrick_modifier("❤️", 0);
|
||||||
|
test_get_fitzpatrick_modifier("❤", 0);
|
||||||
|
test_get_fitzpatrick_modifier("⌚", 0);
|
||||||
|
test_get_fitzpatrick_modifier("🎄", 0);
|
||||||
|
test_get_fitzpatrick_modifier("🧑🎄", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_remove_emoji_modifiers(td::string emoji, const td::string &result) {
|
||||||
|
ASSERT_STREQ(result, td::remove_emoji_modifiers(emoji));
|
||||||
|
td::remove_emoji_modifiers_in_place(emoji);
|
||||||
|
ASSERT_STREQ(result, emoji);
|
||||||
|
ASSERT_STREQ(emoji, td::remove_emoji_modifiers(emoji));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Emoji, remove_emoji_modifiers) {
|
||||||
|
test_remove_emoji_modifiers("", "");
|
||||||
|
test_remove_emoji_modifiers("👩🏼❤💋👩🏻", "👩❤💋👩");
|
||||||
|
test_remove_emoji_modifiers("👩🏼❤️💋👩🏻", "👩❤💋👩");
|
||||||
|
test_remove_emoji_modifiers("👋🏻", "👋");
|
||||||
|
test_remove_emoji_modifiers("👋🏼", "👋");
|
||||||
|
test_remove_emoji_modifiers("👋🏽", "👋");
|
||||||
|
test_remove_emoji_modifiers("👋🏾", "👋");
|
||||||
|
test_remove_emoji_modifiers("👋🏿", "👋");
|
||||||
|
test_remove_emoji_modifiers("🏻", "");
|
||||||
|
test_remove_emoji_modifiers("🏼", "");
|
||||||
|
test_remove_emoji_modifiers("🏽", "");
|
||||||
|
test_remove_emoji_modifiers("🏾", "");
|
||||||
|
test_remove_emoji_modifiers("🏿", "");
|
||||||
|
test_remove_emoji_modifiers("⌚", "⌚");
|
||||||
|
test_remove_emoji_modifiers("↔", "↔");
|
||||||
|
test_remove_emoji_modifiers("🪗", "🪗");
|
||||||
|
test_remove_emoji_modifiers("2️⃣", "2⃣");
|
||||||
|
test_remove_emoji_modifiers("2⃣", "2⃣");
|
||||||
|
test_remove_emoji_modifiers("❤️", "❤");
|
||||||
|
test_remove_emoji_modifiers("❤", "❤");
|
||||||
|
test_remove_emoji_modifiers("⌚", "⌚");
|
||||||
|
test_remove_emoji_modifiers("🎄", "🎄");
|
||||||
|
test_remove_emoji_modifiers("🧑🎄", "🧑🎄");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_remove_emoji_selectors(td::string emoji, const td::string &result) {
|
||||||
|
ASSERT_STREQ(result, td::remove_emoji_selectors(result));
|
||||||
|
ASSERT_STREQ(result, td::remove_emoji_selectors(emoji));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Emoji, remove_emoji_selectors) {
|
||||||
|
test_remove_emoji_selectors("", "");
|
||||||
|
test_remove_emoji_selectors("👩🏼❤💋👩🏻", "👩🏼❤💋👩🏻");
|
||||||
|
test_remove_emoji_selectors("👩🏼❤️💋👩🏻", "👩🏼❤💋👩🏻");
|
||||||
|
test_remove_emoji_selectors("👋🏻", "👋🏻");
|
||||||
|
test_remove_emoji_selectors("👋🏼", "👋🏼");
|
||||||
|
test_remove_emoji_selectors("👋🏽", "👋🏽");
|
||||||
|
test_remove_emoji_selectors("👋🏾", "👋🏾");
|
||||||
|
test_remove_emoji_selectors("👋🏿", "👋🏿");
|
||||||
|
test_remove_emoji_selectors("🏻", "🏻");
|
||||||
|
test_remove_emoji_selectors("🏼", "🏼");
|
||||||
|
test_remove_emoji_selectors("🏽", "🏽");
|
||||||
|
test_remove_emoji_selectors("🏾", "🏾");
|
||||||
|
test_remove_emoji_selectors("🏿", "🏿");
|
||||||
|
test_remove_emoji_selectors("⌚", "⌚");
|
||||||
|
test_remove_emoji_selectors("↔", "↔");
|
||||||
|
test_remove_emoji_selectors("🪗", "🪗");
|
||||||
|
test_remove_emoji_selectors("2️⃣", "2⃣");
|
||||||
|
test_remove_emoji_selectors("2⃣", "2⃣");
|
||||||
|
test_remove_emoji_selectors("❤️", "❤");
|
||||||
|
test_remove_emoji_selectors("❤", "❤");
|
||||||
|
test_remove_emoji_selectors("⌚", "⌚");
|
||||||
|
test_remove_emoji_selectors("🎄", "🎄");
|
||||||
|
test_remove_emoji_selectors("🧑🎄", "🧑🎄");
|
||||||
|
}
|
|
@ -24,24 +24,24 @@ TEST(Misc, clean_filename) {
|
||||||
test_clean_filename("!@#$%^&*()_+-=[]{;|:\"}'<>?,.`~", "!@#$%^ ()_+-=[]{; } ,.~");
|
test_clean_filename("!@#$%^&*()_+-=[]{;|:\"}'<>?,.`~", "!@#$%^ ()_+-=[]{; } ,.~");
|
||||||
test_clean_filename("!@#$%^&*()_+-=[]{}\\|:\";'<>?,.`~", "; ,.~");
|
test_clean_filename("!@#$%^&*()_+-=[]{}\\|:\";'<>?,.`~", "; ,.~");
|
||||||
test_clean_filename("عرفها بعد قد. هذا مع تاريخ اليميني واندونيسيا،, لعدم تاريخ لهيمنة الى",
|
test_clean_filename("عرفها بعد قد. هذا مع تاريخ اليميني واندونيسيا،, لعدم تاريخ لهيمنة الى",
|
||||||
"عرفها بعد قد.هذا مع تاريخ اليميني");
|
"عرفها بعد قد.هذا مع تاريخ الي");
|
||||||
test_clean_filename(
|
test_clean_filename(
|
||||||
"012345678901234567890123456789012345678901234567890123456789adsasdasdsaa.01234567890123456789asdasdasdasd",
|
"012345678901234567890123456789012345678901234567890123456789adsasdasdsaa.01234567890123456789asdasdasdasd",
|
||||||
"012345678901234567890123456789012345678901234567890123456789.01234567890123456789");
|
"012345678901234567890123456789012345678901234567890123456789adsa.0123456789012345");
|
||||||
test_clean_filename(
|
test_clean_filename(
|
||||||
"01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
"01234567890123456789012345678901234567890123456789adsa<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||||
"0123456789`<><<>><><>0123456789asdasdasdasd",
|
"0123456789`<><<>><><>0123456789asdasdasdasd",
|
||||||
"01234567890123456789012345678901234567890123456789.0123456789");
|
"01234567890123456789012345678901234567890123456789adsa.0123456789");
|
||||||
test_clean_filename(
|
test_clean_filename(
|
||||||
"01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
"012345678901234567890123456789012345678901234567890123<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||||
"0123456789`<><><>0123456789asdasdasdasd",
|
"0123456789`<>0123456789asdasdasdasd",
|
||||||
"01234567890123456789012345678901234567890123456789.0123456789 012");
|
"012345678901234567890123456789012345678901234567890123.0123456789 012");
|
||||||
test_clean_filename("C:/document.tar.gz", "document.tar.gz");
|
test_clean_filename("C:/document.tar.gz", "document.tar.gz");
|
||||||
test_clean_filename("test....", "test");
|
test_clean_filename("test....", "test");
|
||||||
test_clean_filename("....test", "test");
|
test_clean_filename("....test", "test");
|
||||||
test_clean_filename("test.exe....", "test.exe"); // extension has changed
|
test_clean_filename("test.exe....", "test.exe"); // extension has changed
|
||||||
test_clean_filename("test.exe01234567890123456789....",
|
test_clean_filename("test.exe01234567890123456789....",
|
||||||
"test.exe01234567890123456789"); // extension may be more than 20 characters
|
"test.exe01234567890123456789"); // extension may be more than 16 characters
|
||||||
test_clean_filename("....test....asdf", "test.asdf");
|
test_clean_filename("....test....asdf", "test.asdf");
|
||||||
test_clean_filename("കറുപ്പ്.txt", "കറപപ.txt");
|
test_clean_filename("കറുപ്പ്.txt", "കറപപ.txt");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "td/utils/bits.h"
|
#include "td/utils/bits.h"
|
||||||
#include "td/utils/CancellationToken.h"
|
#include "td/utils/CancellationToken.h"
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/emoji.h"
|
|
||||||
#include "td/utils/ExitGuard.h"
|
#include "td/utils/ExitGuard.h"
|
||||||
#include "td/utils/Hash.h"
|
#include "td/utils/Hash.h"
|
||||||
#include "td/utils/HashMap.h"
|
#include "td/utils/HashMap.h"
|
||||||
|
@ -1215,27 +1214,6 @@ TEST(Misc, uname) {
|
||||||
ASSERT_TRUE(!first_version.empty());
|
ASSERT_TRUE(!first_version.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Misc, is_emoji) {
|
|
||||||
ASSERT_TRUE(td::is_emoji("👩🏼❤💋👩🏻"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("👩🏼❤️💋👩🏻"));
|
|
||||||
ASSERT_TRUE(!td::is_emoji("👩🏼❤️️💋👩🏻"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("⌚"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("↔"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("🪗"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("2️⃣"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("2⃣"));
|
|
||||||
ASSERT_TRUE(!td::is_emoji(" 2⃣"));
|
|
||||||
ASSERT_TRUE(!td::is_emoji("2⃣ "));
|
|
||||||
ASSERT_TRUE(!td::is_emoji(" "));
|
|
||||||
ASSERT_TRUE(!td::is_emoji(""));
|
|
||||||
ASSERT_TRUE(!td::is_emoji("1234567890123456789012345678901234567890123456789012345678901234567890"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("❤️"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("❤"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("⌚"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("🎄"));
|
|
||||||
ASSERT_TRUE(td::is_emoji("🧑🎄"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Misc, serialize) {
|
TEST(Misc, serialize) {
|
||||||
td::int32 x = 1;
|
td::int32 x = 1;
|
||||||
ASSERT_EQ(td::base64_encode(td::serialize(x)), td::base64_encode(td::string("\x01\x00\x00\x00", 4)));
|
ASSERT_EQ(td::base64_encode(td::serialize(x)), td::base64_encode(td::string("\x01\x00\x00\x00", 4)));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user