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/SecretChatDb.cpp
|
||||
td/telegram/SecretChatsManager.cpp
|
||||
td/telegram/SecretInputMedia.cpp
|
||||
td/telegram/SecureManager.cpp
|
||||
td/telegram/SecureStorage.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);
|
||||
CHECK(animation != nullptr);
|
||||
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() || encryption_key.empty()) {
|
||||
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||
return SecretInputMedia{};
|
||||
}
|
||||
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>());
|
||||
|
||||
return SecretInputMedia{
|
||||
std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
std::move(thumbnail), animation->thumbnail.dimensions.width, animation->thumbnail.dimensions.height,
|
||||
animation->mime_type, narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption)};
|
||||
return {std::move(input_file),
|
||||
std::move(thumbnail),
|
||||
animation->thumbnail.dimensions,
|
||||
animation->mime_type,
|
||||
file_view,
|
||||
std::move(attributes),
|
||||
caption};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
|
@ -91,8 +91,6 @@ class AnimationsManager final : public Actor {
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
@ -210,8 +210,7 @@ SecretInputMedia AudiosManager::get_secret_input_media(FileId audio_file_id,
|
||||
auto *audio = get_audio(audio_file_id);
|
||||
CHECK(audio != nullptr);
|
||||
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() || encryption_key.empty()) {
|
||||
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||
return SecretInputMedia{};
|
||||
}
|
||||
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,
|
||||
false /*ignored*/, audio->duration, audio->title, audio->performer, BufferSlice()));
|
||||
|
||||
return SecretInputMedia{
|
||||
std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
std::move(thumbnail), audio->thumbnail.dimensions.width, audio->thumbnail.dimensions.height, audio->mime_type,
|
||||
narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption)};
|
||||
return {std::move(input_file),
|
||||
std::move(thumbnail),
|
||||
audio->thumbnail.dimensions,
|
||||
audio->mime_type,
|
||||
file_view,
|
||||
std::move(attributes),
|
||||
caption};
|
||||
}
|
||||
|
||||
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) {
|
||||
if (set_option(name, PSLICE() << "I" << value)) {
|
||||
if (set_option(name, PSLICE() << 'I' << value)) {
|
||||
on_option_updated(name);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -73,32 +73,32 @@ bool ConfigShared::get_option_boolean(Slice name, bool default_value) const {
|
||||
if (value == "Bfalse") {
|
||||
return false;
|
||||
}
|
||||
LOG(ERROR) << "Found \"" << value << "\" instead of boolean option";
|
||||
LOG(ERROR) << "Found \"" << value << "\" instead of boolean option " << name;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
int64 ConfigShared::get_option_integer(Slice name, int64 default_value) const {
|
||||
auto str_value = get_option(name);
|
||||
if (str_value.empty()) {
|
||||
auto value = get_option(name);
|
||||
if (value.empty()) {
|
||||
return default_value;
|
||||
}
|
||||
if (str_value[0] != 'I') {
|
||||
LOG(ERROR) << "Found \"" << str_value << "\" instead of integer option";
|
||||
if (value[0] != 'I') {
|
||||
LOG(ERROR) << "Found \"" << value << "\" instead of integer option " << name;
|
||||
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 {
|
||||
auto str_value = get_option(name);
|
||||
if (str_value.empty()) {
|
||||
auto value = get_option(name);
|
||||
if (value.empty()) {
|
||||
return default_value;
|
||||
}
|
||||
if (str_value[0] != 'S') {
|
||||
LOG(ERROR) << "Found \"" << str_value << "\" instead of string option";
|
||||
if (value[0] != 'S') {
|
||||
LOG(ERROR) << "Found \"" << value << "\" instead of string option " << name;
|
||||
return default_value;
|
||||
}
|
||||
return str_value.substr(1);
|
||||
return value.substr(1);
|
||||
}
|
||||
|
||||
bool ConfigShared::set_option(Slice name, Slice value) {
|
||||
|
@ -2924,10 +2924,10 @@ class GetChannelAdministratorsQuery final : public Td::ResultHandler {
|
||||
};
|
||||
|
||||
class GetSupportUserQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
Promise<UserId> promise_;
|
||||
|
||||
public:
|
||||
explicit GetSupportUserQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
explicit GetSupportUserQuery(Promise<UserId> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send() {
|
||||
@ -2943,9 +2943,10 @@ class GetSupportUserQuery final : public Td::ResultHandler {
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
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 {
|
||||
@ -4040,6 +4041,7 @@ void ContactsManager::Channel::store(StorerT &storer) const {
|
||||
STORE_FLAG(is_fake);
|
||||
STORE_FLAG(is_gigagroup);
|
||||
STORE_FLAG(noforwards);
|
||||
STORE_FLAG(can_be_deleted); // 25
|
||||
END_STORE_FLAGS();
|
||||
|
||||
store(status, storer);
|
||||
@ -4110,6 +4112,7 @@ void ContactsManager::Channel::parse(ParserT &parser) {
|
||||
PARSE_FLAG(is_fake);
|
||||
PARSE_FLAG(is_gigagroup);
|
||||
PARSE_FLAG(noforwards);
|
||||
PARSE_FLAG(can_be_deleted);
|
||||
END_PARSE_FLAGS();
|
||||
|
||||
if (use_new_rights) {
|
||||
@ -6881,7 +6884,7 @@ void ContactsManager::delete_channel(ChannelId channel_id, Promise<Unit> &&promi
|
||||
if (c == nullptr) {
|
||||
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"));
|
||||
}
|
||||
|
||||
@ -8397,8 +8400,7 @@ DialogId ContactsManager::get_dialog_id(const tl_object_ptr<telegram_api::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,
|
||||
bool expect_support) {
|
||||
void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr, const char *source, bool is_me) {
|
||||
LOG(DEBUG) << "Receive from " << source << ' ' << to_string(user_ptr);
|
||||
int32 constructor_id = user_ptr->get_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 is_received = (flags & USER_FLAG_IS_INACCESSIBLE) == 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 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)
|
||||
<< "Receive not bot " << user_id << " which can't join groups from " << source;
|
||||
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->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 ||
|
||||
(!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),
|
||||
channel_full->bot_user_ids, true);
|
||||
|
||||
update_channel(c, channel_id);
|
||||
|
||||
channel_full->is_update_channel_full_sent = 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_));
|
||||
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(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));
|
||||
if (chat_full->description != 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));
|
||||
// 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));
|
||||
|
||||
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->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;
|
||||
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;
|
||||
|
||||
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->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");
|
||||
}
|
||||
@ -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,
|
||||
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()) {
|
||||
photo.minithumbnail.clear();
|
||||
}
|
||||
@ -13513,6 +13521,20 @@ void ContactsManager::on_update_chat_photo(Chat *c, DialogPhoto &&photo) {
|
||||
c->photo = std::move(photo);
|
||||
c->is_photo_changed = 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,
|
||||
tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
|
||||
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()) {
|
||||
photo.minithumbnail.clear();
|
||||
}
|
||||
@ -13642,6 +13667,24 @@ void ContactsManager::on_update_channel_photo(Channel *c, DialogPhoto &&photo) {
|
||||
c->photo = std::move(photo);
|
||||
c->is_photo_changed = 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
auto channel_full = get_channel_full_const(channel_id);
|
||||
if (channel_full == nullptr) {
|
||||
@ -14875,17 +14930,6 @@ int32 ContactsManager::get_channel_slow_mode_delay(ChannelId channel_id) {
|
||||
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 {
|
||||
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,
|
||||
std::move(promise));
|
||||
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,
|
||||
td_api::make_object<td_api::chatMemberStatusBanned>(banned_until_date),
|
||||
std::move(promise));
|
||||
@ -16710,26 +16755,35 @@ tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_
|
||||
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()) {
|
||||
promise.set_value(Unit());
|
||||
return support_user_id_;
|
||||
return promise.set_value(get_user_object(support_user_id_));
|
||||
}
|
||||
|
||||
td_->create_handler<GetSupportUserQuery>(std::move(promise))->send();
|
||||
return UserId();
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[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() {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
get_user(get_my_id(), 3, Promise<Unit>());
|
||||
void ContactsManager::on_get_support_user(UserId user_id, Promise<td_api::object_ptr<td_api::user>> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
if (td_->is_online()) {
|
||||
reload_created_public_dialogs(PublicDialogType::HasUsername, Promise<td_api::object_ptr<td_api::chats>>());
|
||||
reload_created_public_dialogs(PublicDialogType::IsLocationBased, Promise<td_api::object_ptr<td_api::chats>>());
|
||||
const User *u = get_user(user_id);
|
||||
if (u == nullptr) {
|
||||
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 {
|
||||
|
@ -151,8 +151,7 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void reload_contacts(bool force);
|
||||
|
||||
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_user(tl_object_ptr<telegram_api::User> &&user, const char *source, bool is_me = false);
|
||||
void on_get_users(vector<tl_object_ptr<telegram_api::User>> &&users, const char *source);
|
||||
|
||||
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 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_inactive_channels(Promise<Unit> &&promise);
|
||||
@ -535,9 +536,9 @@ class ContactsManager final : public Actor {
|
||||
int32 get_channel_participant_count(ChannelId channel_id) const;
|
||||
bool get_channel_sign_messages(ChannelId channel_id) const;
|
||||
bool get_channel_has_linked_channel(ChannelId channel_id) const;
|
||||
bool get_channel_can_be_deleted(ChannelId channel_id) const;
|
||||
ChannelId get_channel_linked_channel_id(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);
|
||||
|
||||
@ -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);
|
||||
|
||||
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 after_get_difference();
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
|
||||
static tl_object_ptr<td_api::dateRange> convert_date_range(
|
||||
@ -835,6 +834,7 @@ class ContactsManager final : public Actor {
|
||||
bool sign_messages = false;
|
||||
bool is_slow_mode_enabled = false;
|
||||
bool noforwards = false;
|
||||
bool can_be_deleted = false;
|
||||
|
||||
bool is_megagroup = false;
|
||||
bool is_gigagroup = false;
|
||||
@ -1213,6 +1213,7 @@ class ContactsManager final : public Actor {
|
||||
DialogParticipantStatus get_channel_permissions(const Channel *c) const;
|
||||
static bool get_channel_sign_messages(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);
|
||||
|
||||
@ -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,
|
||||
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, 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_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);
|
||||
@ -1275,7 +1276,7 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void on_update_channel_photo(Channel *c, ChannelId channel_id,
|
||||
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);
|
||||
void on_update_channel_username(Channel *c, ChannelId channel_id, string &&username);
|
||||
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,
|
||||
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 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,
|
||||
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_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,
|
||||
ChannelType channel_type) {
|
||||
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) {
|
||||
case td_api::chatMemberStatusCreator::ID: {
|
||||
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: {
|
||||
auto st = static_cast<const td_api::chatMemberStatusRestricted *>(status.get());
|
||||
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:
|
||||
return DialogParticipantStatus::Left();
|
||||
case td_api::chatMemberStatusBanned::ID: {
|
||||
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:
|
||||
UNREACHABLE();
|
||||
|
@ -593,8 +593,7 @@ SecretInputMedia DocumentsManager::get_secret_input_media(FileId document_file_i
|
||||
const GeneralDocument *document = get_document(document_file_id);
|
||||
CHECK(document != nullptr);
|
||||
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() || encryption_key.empty()) {
|
||||
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||
return SecretInputMedia{};
|
||||
}
|
||||
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()) {
|
||||
attributes.push_back(make_tl_object<secret_api::documentAttributeFilename>(document->file_name));
|
||||
}
|
||||
return SecretInputMedia{
|
||||
std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
std::move(thumbnail), document->thumbnail.dimensions.width, document->thumbnail.dimensions.height,
|
||||
document->mime_type, narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), caption)};
|
||||
return {std::move(input_file),
|
||||
std::move(thumbnail),
|
||||
document->thumbnail.dimensions,
|
||||
document->mime_type,
|
||||
file_view,
|
||||
std::move(attributes),
|
||||
caption};
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::InputMedia> DocumentsManager::get_input_media(
|
||||
|
@ -1647,7 +1647,11 @@ void GroupCallManager::on_get_group_call_participants(
|
||||
if (is_load) {
|
||||
auto *group_call_participants = add_group_call_participants(input_group_call_id);
|
||||
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) {
|
||||
@ -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_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) {
|
||||
GroupCallParticipant participant(group_call_participant, version);
|
||||
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_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 = [&] {
|
||||
while (!pending_mute_updates.empty()) {
|
||||
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,
|
||||
const GroupCallParticipant &participant,
|
||||
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) {
|
||||
return real_order;
|
||||
}
|
||||
@ -2106,7 +2115,7 @@ void GroupCallManager::process_group_call_participants(
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
@ -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();
|
||||
try_clear_group_call_participants(input_group_call_id);
|
||||
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_;
|
||||
}
|
||||
|
||||
GroupCallParticipantOrder GroupCallParticipant::get_real_order(bool can_self_unmute, bool joined_date_asc,
|
||||
bool keep_active_date) const {
|
||||
GroupCallParticipantOrder GroupCallParticipant::get_real_order(bool can_self_unmute, bool joined_date_asc) const {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
|
||||
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 {
|
||||
return dialog_id.is_valid();
|
||||
|
@ -667,7 +667,7 @@ class MessageDice final : public MessageContent {
|
||||
|
||||
MessageDice() = default;
|
||||
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 {
|
||||
@ -2100,10 +2100,10 @@ Result<InputMessageContent> get_input_message_content(
|
||||
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()) {
|
||||
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:
|
||||
return td->poll_manager_->has_input_media(static_cast<const MessagePoll *>(content)->poll_id);
|
||||
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(
|
||||
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) {
|
||||
if (!can_have_input_media(td, content)) {
|
||||
if (!can_have_input_media(td, content, false)) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (content->get_type()) {
|
||||
@ -4358,10 +4358,10 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
||||
MessageContentDupType type, MessageCopyOptions &©_options) {
|
||||
CHECK(content != nullptr);
|
||||
if (copy_options.send_copy) {
|
||||
CHECK(type == MessageContentDupType::Copy);
|
||||
CHECK(type == MessageContentDupType::Copy || type == MessageContentDupType::ServerCopy);
|
||||
}
|
||||
if (type != MessageContentDupType::Forward && type != MessageContentDupType::SendViaBot &&
|
||||
!can_have_input_media(td, content)) {
|
||||
!can_have_input_media(td, content, type == MessageContentDupType::ServerCopy)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -4382,7 +4382,8 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
||||
if (to_secret) {
|
||||
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()) {
|
||||
case MessageContentType::Animation: {
|
||||
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);
|
||||
}
|
||||
case MessageContentType::Poll:
|
||||
if (type == MessageContentDupType::Copy) {
|
||||
if (type == MessageContentDupType::Copy || type == MessageContentDupType::ServerCopy) {
|
||||
return make_unique<MessagePoll>(
|
||||
td->poll_manager_->dup_poll(static_cast<const MessagePoll *>(content)->poll_id));
|
||||
} 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,
|
||||
Slice emoji, string data) {
|
||||
string &&emoji, string &&data) {
|
||||
if (content->get_type() != MessageContentType::Text) {
|
||||
return;
|
||||
}
|
||||
|
||||
emoji = remove_emoji_modifiers(emoji);
|
||||
remove_emoji_modifiers_in_place(emoji);
|
||||
auto &text = static_cast<const MessageText *>(content)->text;
|
||||
if (!text.entities.empty() || remove_emoji_modifiers(text.text) != emoji) {
|
||||
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()) {
|
||||
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(
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -26,6 +26,17 @@ struct MessageCopyOptions {
|
||||
MessageCopyOptions() = default;
|
||||
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) {
|
||||
|
@ -4545,8 +4545,6 @@ class ResolveUsernameQuery final : public Td::ResultHandler {
|
||||
|
||||
class MessagesManager::UploadMediaCallback final : public FileManager::UploadCallback {
|
||||
public:
|
||||
void on_progress(FileId file_id) 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),
|
||||
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))};
|
||||
auto *m = get_message_force(full_message_id, "on_dialog_action");
|
||||
if (m != nullptr) {
|
||||
on_message_content_animated_emoji_clicked(m->content.get(), full_message_id, td_, clicking_info.emoji,
|
||||
std::move(clicking_info.data));
|
||||
on_message_content_animated_emoji_clicked(m->content.get(), full_message_id, td_,
|
||||
std::move(clicking_info.emoji), std::move(clicking_info.data));
|
||||
}
|
||||
}
|
||||
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) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
LOG(DEBUG) << "Receive " << messages.size() << " 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);
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
@ -15138,7 +15136,7 @@ void MessagesManager::remove_dialog_mention_notifications(Dialog *d) {
|
||||
CHECK(m != nullptr);
|
||||
CHECK(m->message_id.is_valid());
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -15150,7 +15148,7 @@ void MessagesManager::remove_dialog_mention_notifications(Dialog *d) {
|
||||
if (message_id != d->pinned_message_notification_message_id) {
|
||||
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)) {
|
||||
CHECK(is_from_mention_notification_group(d, m));
|
||||
CHECK(is_from_mention_notification_group(m));
|
||||
removed_notification_ids_set.insert(m->notification_id);
|
||||
}
|
||||
}
|
||||
@ -15846,7 +15844,7 @@ void MessagesManager::remove_message_notification_id(Dialog *d, Message *m, bool
|
||||
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);
|
||||
if (!group_info.group_id.is_valid()) {
|
||||
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)) {
|
||||
while (*it != nullptr) {
|
||||
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) {
|
||||
bool is_fixed = set_dialog_last_notification(d->dialog_id, group_info, m->date, m->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();
|
||||
if (m->via_bot_user_id.is_valid() || m->hide_via_bot) {
|
||||
// via bot message
|
||||
if (!can_have_input_media(td_, m->content.get())) {
|
||||
if (!can_have_input_media(td_, m->content.get(), false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -27737,10 +27735,16 @@ class MessagesManager::ForwardMessagesLogEvent {
|
||||
DialogId from_dialog_id;
|
||||
vector<MessageId> message_ids;
|
||||
vector<Message *> messages_in;
|
||||
bool drop_author;
|
||||
bool drop_media_captions;
|
||||
vector<unique_ptr<Message>> messages_out;
|
||||
|
||||
template <class StorerT>
|
||||
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(from_dialog_id, storer);
|
||||
td::store(message_ids, storer);
|
||||
@ -27749,6 +27753,12 @@ class MessagesManager::ForwardMessagesLogEvent {
|
||||
|
||||
template <class ParserT>
|
||||
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(from_dialog_id, 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,
|
||||
const vector<Message *> &messages,
|
||||
const vector<MessageId> &message_ids) {
|
||||
ForwardMessagesLogEvent log_event{to_dialog_id, from_dialog_id, message_ids, messages, Auto()};
|
||||
const vector<MessageId> &message_ids, bool drop_author,
|
||||
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,
|
||||
get_log_event_storer(log_event));
|
||||
}
|
||||
|
||||
void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id,
|
||||
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());
|
||||
if (messages.empty()) {
|
||||
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) {
|
||||
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]);
|
||||
@ -27801,6 +27814,12 @@ void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_d
|
||||
if (messages[0]->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 =
|
||||
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,
|
||||
int64 media_album_id) const {
|
||||
m->via_bot_user_id = forwarded_message->via_bot_user_id;
|
||||
int64 media_album_id, bool drop_author) const {
|
||||
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;
|
||||
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->view_count = forwarded_message->view_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 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;
|
||||
result.to_dialog = to_dialog;
|
||||
result.from_dialog = from_dialog;
|
||||
result.message_send_options = message_send_options;
|
||||
auto &copied_messages = result.copied_messages;
|
||||
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_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 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)) {
|
||||
LOG(INFO) << "Forward of " << message_id << " is restricted";
|
||||
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 reply_to_message_id = copy_options[i].reply_to_message_id;
|
||||
auto reply_markup = std::move(copy_options[i].reply_markup);
|
||||
unique_ptr<MessageContent> content =
|
||||
dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), type, std::move(copy_options[i]));
|
||||
if (content == nullptr) {
|
||||
LOG(INFO) << "Can't forward " << message_id;
|
||||
LOG(INFO) << "Can't forward content of " << message_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
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()) {
|
||||
LOG(INFO) << "Can't forward " << message_id << ": " << can_send_status.message();
|
||||
continue;
|
||||
@ -28050,8 +28086,8 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
|
||||
}
|
||||
|
||||
if (forwarded_message->media_album_id != 0) {
|
||||
auto &new_media_album_id = need_copy ? new_copied_media_album_ids[forwarded_message->media_album_id]
|
||||
: new_forwarded_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_media_album_id.second++;
|
||||
if (new_media_album_id.second == 2) { // have at least 2 messages in the new album
|
||||
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,
|
||||
std::move(reply_markup), forwarded_message->media_album_id,
|
||||
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 &copied_messages = forwarded_messages_info.copied_messages;
|
||||
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<Message *> forwarded_messages;
|
||||
@ -28134,7 +28172,8 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::forward_messages(
|
||||
CHECK(forwarded_message != nullptr);
|
||||
|
||||
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()) &&
|
||||
!forward_info->message_id.is_valid() && !forward_info->sender_dialog_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(),
|
||||
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->real_forward_from_dialog_id = from_dialog_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()) {
|
||||
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) {
|
||||
@ -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) {
|
||||
CHECK(d != 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,
|
||||
@ -29107,13 +29148,13 @@ MessagesManager::MessageNotificationGroup MessagesManager::get_message_notificat
|
||||
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;
|
||||
}
|
||||
|
||||
bool MessagesManager::is_message_notification_active(const Dialog *d, const Message *m) {
|
||||
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() &&
|
||||
m->message_id > d->mention_notification_group.max_removed_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;
|
||||
}
|
||||
|
||||
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
|
||||
<< " from another group";
|
||||
continue;
|
||||
@ -29502,7 +29543,7 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog
|
||||
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
|
||||
<< " from another category";
|
||||
continue;
|
||||
@ -29569,7 +29610,7 @@ void MessagesManager::remove_message_notification(DialogId dialog_id, Notificati
|
||||
CHECK(m != nullptr);
|
||||
CHECK(m->notification_id == notification_id);
|
||||
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);
|
||||
}
|
||||
return;
|
||||
@ -29632,8 +29673,8 @@ void MessagesManager::do_remove_message_notification(DialogId dialog_id, bool fr
|
||||
CHECK(d != nullptr);
|
||||
|
||||
auto m = on_get_message_from_database(d, result[0], false, "do_remove_message_notification");
|
||||
if (m != nullptr && m->notification_id == notification_id &&
|
||||
is_from_mention_notification_group(d, m) == from_mentions && is_message_notification_active(d, m)) {
|
||||
if (m != nullptr && m->notification_id == notification_id && is_from_mention_notification_group(m) == from_mentions &&
|
||||
is_message_notification_active(d, m)) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (is_from_mention_notification_group(d, m)) {
|
||||
if (is_from_mention_notification_group(m)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -29830,7 +29871,7 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f
|
||||
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_active =
|
||||
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;
|
||||
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
|
||||
auto sender_dialog_id = get_message_sender(m);
|
||||
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);
|
||||
} else {
|
||||
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) {
|
||||
auto notification_id = message->notification_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()) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
CHECK(!being_added_new_dialog_id_.is_valid());
|
||||
being_added_new_dialog_id_ = dialog_id;
|
||||
|
||||
loaded_dialogs_.erase(dialog_id);
|
||||
|
||||
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);
|
||||
|
||||
being_added_new_dialog_id_ = DialogId();
|
||||
|
||||
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,
|
||||
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);
|
||||
counter_message.first--;
|
||||
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));
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
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,
|
||||
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,
|
||||
const Message *forwarded_message) const;
|
||||
|
||||
void fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message,
|
||||
int64 media_album_id) const;
|
||||
void fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message, int64 media_album_id,
|
||||
bool drop_author) const;
|
||||
|
||||
struct ForwardedMessages {
|
||||
struct CopiedMessage {
|
||||
@ -1966,6 +1967,8 @@ class MessagesManager final : public Actor {
|
||||
size_t index;
|
||||
};
|
||||
vector<ForwardedMessageContent> forwarded_message_contents;
|
||||
bool drop_author = false;
|
||||
bool drop_media_captions = false;
|
||||
|
||||
Dialog *from_dialog;
|
||||
Dialog *to_dialog;
|
||||
@ -2368,7 +2371,7 @@ class MessagesManager final : public Actor {
|
||||
|
||||
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);
|
||||
|
||||
@ -3251,8 +3254,8 @@ class MessagesManager final : public Actor {
|
||||
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,
|
||||
const vector<Message *> &messages,
|
||||
const vector<MessageId> &message_ids);
|
||||
const vector<Message *> &messages, 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);
|
||||
|
||||
@ -3678,6 +3681,7 @@ class MessagesManager final : public Actor {
|
||||
|
||||
DialogId being_added_dialog_id_;
|
||||
DialogId being_added_by_new_message_dialog_id_;
|
||||
DialogId being_added_new_dialog_id_;
|
||||
|
||||
DialogId debug_channel_difference_dialog_;
|
||||
|
||||
|
@ -1472,10 +1472,6 @@ void NotificationSettingsManager::after_get_difference() {
|
||||
if (!channels_notification_settings_.is_synchronized) {
|
||||
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) {
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
namespace td {
|
||||
@ -418,14 +419,14 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
|
||||
if (name != option_name) {
|
||||
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) {
|
||||
G()->shared_config().set_option_empty(option_name);
|
||||
} 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_;
|
||||
if (int_value < min_value || int_value > max_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) {
|
||||
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) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} 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_;
|
||||
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;
|
||||
};
|
||||
|
||||
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) {
|
||||
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) {
|
||||
G()->shared_config().set_option_empty(name);
|
||||
} 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_;
|
||||
if (str_value.empty()) {
|
||||
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 ||
|
||||
static_cast<const td_api::optionValueBoolean *>(value.get())->value_;
|
||||
td_->set_is_online(is_online);
|
||||
if (!is_bot) {
|
||||
send_closure(td_->state_manager_, &StateManager::on_online, is_online);
|
||||
}
|
||||
td_->set_is_online(is_online);
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
break;
|
||||
|
@ -166,7 +166,7 @@ void PhoneNumberManager::process_check_code_result(Result<tl_object_ptr<telegram
|
||||
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",
|
||||
true, false);
|
||||
true);
|
||||
state_ = State::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_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() {
|
||||
@ -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));
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
auto p = polls_.find(poll_id);
|
||||
if (p == polls_.end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
schedule_poll_unload(poll_id);
|
||||
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) {
|
||||
auto it = poll_messages_.find(poll_id);
|
||||
if (it == poll_messages_.end()) {
|
||||
return;
|
||||
auto server_it = server_poll_messages_.find(poll_id);
|
||||
if (server_it != server_poll_messages_.end()) {
|
||||
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) {
|
||||
td_->messages_manager_->on_external_update_message_content(full_message_id);
|
||||
auto other_it = other_poll_messages_.find(poll_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) {
|
||||
CHECK(have_poll(poll_id));
|
||||
if (full_message_id.get_message_id().is_scheduled()) {
|
||||
return;
|
||||
}
|
||||
if (!full_message_id.get_message_id().is_server()) {
|
||||
if (full_message_id.get_message_id().is_scheduled() || !full_message_id.get_message_id().is_server()) {
|
||||
bool is_inserted = other_poll_messages_[poll_id].insert(full_message_id).second;
|
||||
LOG_CHECK(is_inserted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Register " << poll_id << " from " << full_message_id << " from " << source;
|
||||
bool is_inserted = poll_messages_[poll_id].insert(full_message_id).second;
|
||||
LOG_CHECK(is_inserted) << source << " " << poll_id << " " << full_message_id;
|
||||
bool is_inserted = server_poll_messages_[poll_id].insert(full_message_id).second;
|
||||
LOG_CHECK(is_inserted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||
auto poll = get_poll(poll_id);
|
||||
CHECK(poll != nullptr);
|
||||
if (!td_->auth_manager_->is_bot() && !is_local_poll_id(poll_id) &&
|
||||
!(poll->is_closed && poll->is_updated_after_close)) {
|
||||
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) {
|
||||
CHECK(have_poll(poll_id));
|
||||
if (full_message_id.get_message_id().is_scheduled()) {
|
||||
return;
|
||||
}
|
||||
if (!full_message_id.get_message_id().is_server()) {
|
||||
if (full_message_id.get_message_id().is_scheduled() || !full_message_id.get_message_id().is_server()) {
|
||||
auto &message_ids = other_poll_messages_[poll_id];
|
||||
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
LOG_CHECK(is_deleted) << source << " " << poll_id << " " << full_message_id;
|
||||
LOG_CHECK(is_deleted) << source << ' ' << poll_id << ' ' << full_message_id;
|
||||
if (message_ids.empty()) {
|
||||
poll_messages_.erase(poll_id);
|
||||
server_poll_messages_.erase(poll_id);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||
|
||||
auto &pending_answer = pending_answers_[poll_id];
|
||||
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;
|
||||
}
|
||||
|
||||
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||
|
||||
auto query_promise =
|
||||
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 {
|
||||
@ -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));
|
||||
}
|
||||
|
||||
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||
|
||||
bool is_inserted = being_closed_polls_.insert(poll_id).second;
|
||||
CHECK(is_inserted);
|
||||
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));
|
||||
|
||||
auto poll = get_poll(poll_id);
|
||||
CHECK(poll != nullptr);
|
||||
if (poll->is_closed && poll->is_updated_after_close) {
|
||||
if (poll == nullptr || (poll->is_closed && poll->is_updated_after_close)) {
|
||||
return;
|
||||
}
|
||||
if (pending_answers_.count(poll_id) > 0) {
|
||||
@ -1177,8 +1242,8 @@ void PollManager::on_update_poll_timeout(PollId poll_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = poll_messages_.find(poll_id);
|
||||
if (it == poll_messages_.end()) {
|
||||
auto it = server_poll_messages_.find(poll_id);
|
||||
if (it == server_poll_messages_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1198,8 +1263,7 @@ void PollManager::on_close_poll_timeout(PollId poll_id) {
|
||||
CHECK(!is_local_poll_id(poll_id));
|
||||
|
||||
auto poll = get_poll_editable(poll_id);
|
||||
CHECK(poll != nullptr);
|
||||
if (poll->is_closed || poll->close_date == 0) {
|
||||
if (poll == nullptr || poll->is_closed || poll->close_date == 0) {
|
||||
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,
|
||||
Result<tl_object_ptr<telegram_api::Updates>> result) {
|
||||
auto poll = get_poll(poll_id);
|
||||
CHECK(poll != nullptr);
|
||||
if (poll == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (result.is_error()) {
|
||||
if (!(poll->is_closed && poll->is_updated_after_close) && !G()->close_flag() && !td_->auth_manager_->is_bot()) {
|
||||
auto timeout = get_polling_timeout();
|
||||
@ -1250,7 +1338,7 @@ void PollManager::on_online() {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &it : poll_messages_) {
|
||||
for (auto &it : server_poll_messages_) {
|
||||
auto poll_id = it.first;
|
||||
if (update_poll_timeout_.has_timeout(poll_id.get())) {
|
||||
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))) {
|
||||
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;
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ class PollManager final : public Actor {
|
||||
};
|
||||
|
||||
static constexpr int32 MAX_GET_POLL_VOTERS = 50; // server side limit
|
||||
static constexpr int32 UNLOAD_POLL_DELAY = 600; // some reasonable value
|
||||
|
||||
class SetPollAnswerLogEvent;
|
||||
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_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 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);
|
||||
|
||||
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);
|
||||
|
||||
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_unload_poll_timeout(PollId poll_id);
|
||||
|
||||
void on_online();
|
||||
|
||||
Poll *get_poll_force(PollId poll_id);
|
||||
@ -206,12 +217,14 @@ class PollManager final : public Actor {
|
||||
|
||||
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};
|
||||
MultiTimeout close_poll_timeout_{"ClosePollTimeout"};
|
||||
MultiTimeout unload_poll_timeout_{"UnloadPollTimeout"};
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
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 {
|
||||
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
|
||||
|
||||
#include "td/telegram/PhotoSize.h"
|
||||
#include "td/telegram/secret_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class FileView;
|
||||
|
||||
struct SecretInputMedia {
|
||||
tl_object_ptr<telegram_api::InputEncryptedFile> input_file_;
|
||||
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)) {
|
||||
}
|
||||
|
||||
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 {
|
||||
return decrypted_media_ == nullptr;
|
||||
}
|
||||
|
@ -1462,6 +1462,10 @@ void StickersManager::reload_special_sticker_set_by_type(SpecialStickerSetType t
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
if (disable_animated_emojis_ &&
|
||||
(type == SpecialStickerSetType::animated_emoji() || type == SpecialStickerSetType::animated_emoji_click())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &sticker_set = add_special_sticker_set(type);
|
||||
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_);
|
||||
reset_to_empty(pending_get_animated_emoji_click_stickers_);
|
||||
for (auto &pending_request : pending_get_requests) {
|
||||
choose_animated_emoji_click_sticker(sticker_set, pending_request.message_text_, pending_request.full_message_id_,
|
||||
pending_request.start_time_, std::move(pending_request.promise_));
|
||||
choose_animated_emoji_click_sticker(sticker_set, std::move(pending_request.message_text_),
|
||||
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_);
|
||||
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 {};
|
||||
}
|
||||
|
||||
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);
|
||||
if (it == sticker_set->emoji_stickers_map_.end()) {
|
||||
return {};
|
||||
@ -2748,13 +2753,13 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
||||
}
|
||||
|
||||
if (file_view.is_encrypted_secret()) {
|
||||
auto &encryption_key = file_view.encryption_key();
|
||||
return SecretInputMedia{std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
std::move(thumbnail), sticker->s_thumbnail.dimensions.width,
|
||||
sticker->s_thumbnail.dimensions.height, get_sticker_format_mime_type(sticker->format),
|
||||
narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), "")};
|
||||
return {std::move(input_file),
|
||||
std::move(thumbnail),
|
||||
sticker->s_thumbnail.dimensions,
|
||||
get_sticker_format_mime_type(sticker->format),
|
||||
file_view,
|
||||
std::move(attributes),
|
||||
string()};
|
||||
} else {
|
||||
CHECK(!file_view.is_encrypted());
|
||||
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->sticker_emojis_map_.clear();
|
||||
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()) {
|
||||
LOG(ERROR) << "Receive empty emoji in " << set_id << "/" << s->short_name << " from " << source;
|
||||
continue;
|
||||
@ -4640,11 +4645,11 @@ vector<FileId> StickersManager::get_animated_emoji_click_stickers(const StickerS
|
||||
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,
|
||||
Promise<td_api::object_ptr<td_api::sticker>> &&promise) {
|
||||
CHECK(sticker_set->was_loaded);
|
||||
message_text = remove_emoji_modifiers(message_text);
|
||||
remove_emoji_modifiers_in_place(message_text);
|
||||
if (message_text.empty()) {
|
||||
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) {
|
||||
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) {
|
||||
@ -4798,7 +4803,7 @@ void StickersManager::flush_sent_animated_emoji_clicks() {
|
||||
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();
|
||||
for (const auto &click : sent_animated_emoji_clicks_) {
|
||||
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;
|
||||
}
|
||||
|
||||
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_) {
|
||||
return Status::OK();
|
||||
}
|
||||
@ -4871,7 +4876,7 @@ Status StickersManager::on_animated_emoji_message_clicked(Slice emoji, FullMessa
|
||||
load_special_sticker_set(special_sticker_set);
|
||||
|
||||
PendingOnAnimatedEmojiClicked pending_request;
|
||||
pending_request.emoji_ = emoji.str();
|
||||
pending_request.emoji_ = std::move(emoji);
|
||||
pending_request.full_message_id_ = full_message_id;
|
||||
pending_request.clicks_ = std::move(clicks);
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
|
@ -89,9 +89,9 @@ class StickersManager final : public Actor {
|
||||
|
||||
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;
|
||||
|
||||
@ -135,6 +135,10 @@ class StickersManager final : public Actor {
|
||||
|
||||
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_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 after_get_difference();
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
|
||||
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;
|
||||
|
||||
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,
|
||||
Promise<td_api::object_ptr<td_api::sticker>> &&promise);
|
||||
|
||||
@ -704,8 +706,6 @@ class StickersManager final : public Actor {
|
||||
|
||||
void load_reactions();
|
||||
|
||||
void reload_reactions();
|
||||
|
||||
void update_active_reactions();
|
||||
|
||||
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 reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false);
|
||||
|
||||
void reload_special_sticker_set(SpecialStickerSet &sticker_set, int32 hash);
|
||||
|
||||
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;
|
||||
parse(emojis, parser);
|
||||
for (auto &emoji : emojis) {
|
||||
auto cleaned_emoji = remove_emoji_modifiers(emoji).str();
|
||||
auto cleaned_emoji = remove_emoji_modifiers(emoji);
|
||||
if (!cleaned_emoji.empty()) {
|
||||
auto &sticker_ids = sticker_set->emoji_stickers_map_[cleaned_emoji];
|
||||
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<> {
|
||||
string name_;
|
||||
|
||||
@ -3687,9 +3671,6 @@ void Td::close_impl(bool destroy_flag) {
|
||||
|
||||
class Td::DownloadFileCallback final : public FileManager::DownloadCallback {
|
||||
public:
|
||||
void on_progress(FileId file_id) final {
|
||||
}
|
||||
|
||||
void on_download_ok(FileId file_id) final {
|
||||
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 {
|
||||
public:
|
||||
void on_progress(FileId file_id) 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
|
||||
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) {
|
||||
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) {
|
||||
|
@ -38,10 +38,12 @@
|
||||
#include "td/telegram/PollId.h"
|
||||
#include "td/telegram/PollManager.h"
|
||||
#include "td/telegram/PrivacyManager.h"
|
||||
#include "td/telegram/PublicDialogType.h"
|
||||
#include "td/telegram/ScheduledServerMessageId.h"
|
||||
#include "td/telegram/SecretChatId.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
#include "td/telegram/ServerMessageId.h"
|
||||
#include "td/telegram/SpecialStickerSetType.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/StickerSetId.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
@ -181,6 +183,26 @@ void UpdatesManager::tear_down() {
|
||||
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() {
|
||||
ref_cnt_--;
|
||||
if (ref_cnt_ == 0) {
|
||||
@ -1557,15 +1579,65 @@ void UpdatesManager::after_get_difference() {
|
||||
<< 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_->inline_queries_manager_->after_get_difference();
|
||||
td_->messages_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(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,
|
||||
|
@ -221,12 +221,17 @@ class UpdatesManager final : public Actor {
|
||||
int32 retry_time_ = 1;
|
||||
Timeout retry_timeout_;
|
||||
|
||||
double next_data_reload_time_ = 0.0;
|
||||
Timeout data_reload_timeout_;
|
||||
|
||||
bool running_get_difference_ = false;
|
||||
int32 last_get_difference_pts_ = 0;
|
||||
int32 last_get_difference_qts_ = 0;
|
||||
int32 min_postponed_update_pts_ = 0;
|
||||
int32 min_postponed_update_qts_ = 0;
|
||||
|
||||
void start_up() final;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
void hangup_shared() final;
|
||||
@ -331,6 +336,12 @@ class UpdatesManager final : public Actor {
|
||||
|
||||
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 check_pts_update_dialog_id(DialogId dialog_id);
|
||||
|
@ -50,6 +50,7 @@ enum class Version : int32 {
|
||||
AddInviteLinksRequiringApproval,
|
||||
AddKeyboardButtonFlags, // 35
|
||||
AddAudioFlags,
|
||||
UseServerForwardAsCopy,
|
||||
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);
|
||||
CHECK(video_note != nullptr);
|
||||
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() || encryption_key.empty()) {
|
||||
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||
return SecretInputMedia{};
|
||||
}
|
||||
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>(
|
||||
secret_api::documentAttributeVideo66::ROUND_MESSAGE_MASK, true, video_note->duration,
|
||||
video_note->dimensions.width, video_note->dimensions.height));
|
||||
return SecretInputMedia{
|
||||
std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
std::move(thumbnail), video_note->thumbnail.dimensions.width, video_note->thumbnail.dimensions.height,
|
||||
"video/mp4", narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), "")};
|
||||
|
||||
return {std::move(input_file),
|
||||
std::move(thumbnail),
|
||||
video_note->thumbnail.dimensions,
|
||||
"video/mp4",
|
||||
file_view,
|
||||
std::move(attributes),
|
||||
string()};
|
||||
}
|
||||
|
||||
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);
|
||||
CHECK(video != nullptr);
|
||||
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() || encryption_key.empty()) {
|
||||
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||
return SecretInputMedia{};
|
||||
}
|
||||
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()) {
|
||||
return {};
|
||||
}
|
||||
return SecretInputMedia{
|
||||
std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaVideo>(
|
||||
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()),
|
||||
BufferSlice(encryption_key.key_slice()), BufferSlice(encryption_key.iv_slice()), caption)};
|
||||
vector<tl_object_ptr<secret_api::DocumentAttribute>> attributes;
|
||||
attributes.emplace_back(make_tl_object<secret_api::documentAttributeVideo>(video->duration, video->dimensions.width,
|
||||
video->dimensions.height));
|
||||
|
||||
return {std::move(input_file),
|
||||
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(
|
||||
|
@ -133,8 +133,7 @@ SecretInputMedia VoiceNotesManager::get_secret_input_media(FileId voice_file_id,
|
||||
auto *voice_note = get_voice_note(voice_file_id);
|
||||
CHECK(voice_note != nullptr);
|
||||
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() || encryption_key.empty()) {
|
||||
if (!file_view.is_encrypted_secret() || file_view.encryption_key().empty()) {
|
||||
return SecretInputMedia{};
|
||||
}
|
||||
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>(
|
||||
secret_api::documentAttributeAudio::VOICE_MASK | secret_api::documentAttributeAudio::WAVEFORM_MASK,
|
||||
false /*ignored*/, voice_note->duration, "", "", BufferSlice(voice_note->waveform)));
|
||||
return SecretInputMedia{std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
BufferSlice(), 0, 0, voice_note->mime_type, narrow_cast<int32>(file_view.size()),
|
||||
BufferSlice(encryption_key.key_slice()), BufferSlice(encryption_key.iv_slice()),
|
||||
std::move(attributes), caption)};
|
||||
|
||||
return {std::move(input_file), BufferSlice(), Dimensions(), voice_note->mime_type, file_view,
|
||||
std::move(attributes), caption};
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
// explicit upload request with the same file_id.
|
||||
// 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/ConcurrentHashMap.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/EpochBasedMemoryReclamation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/filesystem.cpp
|
||||
|
@ -243,7 +243,13 @@ Slice remove_fitzpatrick_modifier(Slice 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 */,
|
||||
u8"\u200D\u2640" /* zero width joiner + female 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"\U0001F3FE" /* emoji modifier fitzpatrick type-5 */,
|
||||
u8"\U0001F3FF" /* emoji modifier fitzpatrick type-6 */};
|
||||
bool found = true;
|
||||
while (found) {
|
||||
found = false;
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < emoji.size();) {
|
||||
bool is_found = false;
|
||||
for (auto &modifier : modifiers) {
|
||||
if (ends_with(emoji, modifier) && emoji.size() > modifier.size()) {
|
||||
emoji.remove_suffix(modifier.size());
|
||||
found = true;
|
||||
auto length = modifier.size();
|
||||
if (i + length <= emoji.size() && Slice(&emoji[i], length) == modifier) {
|
||||
// skip modifier
|
||||
i += length;
|
||||
is_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_found) {
|
||||
emoji[j++] = emoji[i++];
|
||||
}
|
||||
}
|
||||
return emoji;
|
||||
}
|
||||
|
||||
void remove_emoji_modifiers_in_place(string &emoji) {
|
||||
emoji.resize(remove_emoji_modifiers(emoji).size());
|
||||
emoji.resize(j);
|
||||
}
|
||||
|
||||
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
|
||||
Slice remove_fitzpatrick_modifier(Slice emoji);
|
||||
|
||||
// removes all emoji modifiers from the end of the string
|
||||
Slice remove_emoji_modifiers(Slice emoji);
|
||||
// removes all emoji modifiers from the string
|
||||
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);
|
||||
|
||||
// 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(
|
||||
"012345678901234567890123456789012345678901234567890123456789adsasdasdsaa.01234567890123456789asdasdasdasd",
|
||||
"012345678901234567890123456789012345678901234567890123456789.01234567890123456789");
|
||||
"012345678901234567890123456789012345678901234567890123456789adsa.0123456789012345");
|
||||
test_clean_filename(
|
||||
"01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"01234567890123456789012345678901234567890123456789adsa<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<><<>><><>0123456789asdasdasdasd",
|
||||
"01234567890123456789012345678901234567890123456789.0123456789");
|
||||
"01234567890123456789012345678901234567890123456789adsa.0123456789");
|
||||
test_clean_filename(
|
||||
"01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<><><>0123456789asdasdasdasd",
|
||||
"01234567890123456789012345678901234567890123456789.0123456789 012");
|
||||
"012345678901234567890123456789012345678901234567890123<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<>0123456789asdasdasdasd",
|
||||
"012345678901234567890123456789012345678901234567890123.0123456789 012");
|
||||
test_clean_filename("C:/document.tar.gz", "document.tar.gz");
|
||||
test_clean_filename("test....", "test");
|
||||
test_clean_filename("....test", "test");
|
||||
test_clean_filename("test.exe....", "test.exe"); // extension has changed
|
||||
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("കറുപ്പ്.txt", "കറപപ.txt");
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "td/utils/bits.h"
|
||||
#include "td/utils/CancellationToken.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/emoji.h"
|
||||
#include "td/utils/ExitGuard.h"
|
||||
#include "td/utils/Hash.h"
|
||||
#include "td/utils/HashMap.h"
|
||||
@ -1215,27 +1214,6 @@ TEST(Misc, uname) {
|
||||
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) {
|
||||
td::int32 x = 1;
|
||||
ASSERT_EQ(td::base64_encode(td::serialize(x)), td::base64_encode(td::string("\x01\x00\x00\x00", 4)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user