Add ReactionManager and move there all reaction-related methods from StickersManager.
This commit is contained in:
parent
d2add02ac9
commit
9dcfd9d66d
@ -444,6 +444,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PremiumGiftOption.cpp
|
||||
td/telegram/QueryCombiner.cpp
|
||||
td/telegram/QueryMerger.cpp
|
||||
td/telegram/ReactionManager.cpp
|
||||
td/telegram/ReactionType.cpp
|
||||
td/telegram/RecentDialogList.cpp
|
||||
td/telegram/ReplyMarkup.cpp
|
||||
@ -735,6 +736,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PublicDialogType.h
|
||||
td/telegram/QueryCombiner.h
|
||||
td/telegram/QueryMerger.h
|
||||
td/telegram/ReactionManager.h
|
||||
td/telegram/ReactionType.h
|
||||
td/telegram/RecentDialogList.h
|
||||
td/telegram/ReplyMarkup.h
|
||||
@ -841,6 +843,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PollId.hpp
|
||||
td/telegram/PollManager.hpp
|
||||
td/telegram/PremiumGiftOption.hpp
|
||||
td/telegram/ReactionManager.hpp
|
||||
td/telegram/ReactionType.hpp
|
||||
td/telegram/ReplyMarkup.hpp
|
||||
td/telegram/RequestedDialogType.hpp
|
||||
|
@ -308,6 +308,7 @@ function split_file($file, $chunks, $undo) {
|
||||
'poll_manager[_(-][^.]|PollManager' => "PollManager",
|
||||
'privacy_manager[_(-][^.]|PrivacyManager' => "PrivacyManager",
|
||||
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
||||
'reaction_manager[_(-][^.]|ReactionManager' => 'ReactionManager',
|
||||
'SecretChatActor' => 'SecretChatActor',
|
||||
'secret_chats_manager[_(-]|SecretChatsManager' => 'SecretChatsManager',
|
||||
'sponsored_message_manager[_(-][^.]|SponsoredMessageManager' => 'SponsoredMessageManager',
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/PasswordManager.h"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/SendCodeHelper.hpp"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
@ -1288,6 +1289,7 @@ void AuthManager::on_get_authorization(tl_object_ptr<telegram_api::auth_Authoriz
|
||||
td_->dialog_filter_manager_->on_authorization_success(); // must be after MessagesManager::on_authorization_success()
|
||||
// to have folders created
|
||||
td_->notification_manager_->init();
|
||||
td_->reaction_manager_->init();
|
||||
td_->stickers_manager_->init();
|
||||
td_->theme_manager_->init();
|
||||
td_->top_dialog_manager_->init();
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "td/telegram/Photo.hpp"
|
||||
#include "td/telegram/PhotoSize.h"
|
||||
#include "td/telegram/PremiumGiftOption.hpp"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/SecretChatLayer.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
#include "td/telegram/ServerMessageId.h"
|
||||
@ -11938,7 +11939,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
|
||||
if (td_->option_manager_->get_option_boolean("is_premium") != u->is_premium) {
|
||||
td_->option_manager_->set_option_boolean("is_premium", u->is_premium);
|
||||
send_closure(td_->config_manager_, &ConfigManager::request_config, true);
|
||||
td_->stickers_manager_->reload_top_reactions();
|
||||
td_->reaction_manager_->reload_top_reactions();
|
||||
td_->messages_manager_->update_is_translatable(u->is_premium);
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ class NotificationManager;
|
||||
class NotificationSettingsManager;
|
||||
class OptionManager;
|
||||
class PasswordManager;
|
||||
class ReactionManager;
|
||||
class SecretChatsManager;
|
||||
class SponsoredMessageManager;
|
||||
class StateManager;
|
||||
@ -331,6 +332,13 @@ class Global final : public ActorContext {
|
||||
password_manager_ = password_manager;
|
||||
}
|
||||
|
||||
ActorId<ReactionManager> reaction_manager() const {
|
||||
return reaction_manager_;
|
||||
}
|
||||
void set_reaction_manager(ActorId<ReactionManager> reaction_manager) {
|
||||
reaction_manager_ = reaction_manager;
|
||||
}
|
||||
|
||||
ActorId<SecretChatsManager> secret_chats_manager() const {
|
||||
return secret_chats_manager_;
|
||||
}
|
||||
@ -530,6 +538,7 @@ class Global final : public ActorContext {
|
||||
ActorId<NotificationManager> notification_manager_;
|
||||
ActorId<NotificationSettingsManager> notification_settings_manager_;
|
||||
ActorId<PasswordManager> password_manager_;
|
||||
ActorId<ReactionManager> reaction_manager_;
|
||||
ActorId<SecretChatsManager> secret_chats_manager_;
|
||||
ActorId<SponsoredMessageManager> sponsored_message_manager_;
|
||||
ActorId<StickersManager> stickers_manager_;
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "td/telegram/PollId.h"
|
||||
#include "td/telegram/PollId.hpp"
|
||||
#include "td/telegram/PollManager.h"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/secret_api.hpp"
|
||||
#include "td/telegram/SecureValue.h"
|
||||
#include "td/telegram/SecureValue.hpp"
|
||||
@ -6883,11 +6884,4 @@ void rate_message_content_speech_recognition(Td *td, const MessageContent *conte
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::availableReactions> get_sorted_available_reactions(Td *td, ChatReactions available_reactions,
|
||||
ChatReactions active_reactions,
|
||||
int32 row_size) {
|
||||
return td->stickers_manager_->get_sorted_available_reactions(std::move(available_reactions),
|
||||
std::move(active_reactions), row_size);
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -286,8 +286,4 @@ void recognize_message_content_speech(Td *td, const MessageContent *content, Ful
|
||||
void rate_message_content_speech_recognition(Td *td, const MessageContent *content, FullMessageId full_message_id,
|
||||
bool is_good, Promise<Unit> &&promise);
|
||||
|
||||
td_api::object_ptr<td_api::availableReactions> get_sorted_available_reactions(Td *td, ChatReactions available_reactions,
|
||||
ChatReactions active_reactions,
|
||||
int32 row_size);
|
||||
|
||||
} // namespace td
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/PollId.h"
|
||||
#include "td/telegram/PublicDialogType.h"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/ReplyMarkup.h"
|
||||
#include "td/telegram/ReplyMarkup.hpp"
|
||||
#include "td/telegram/ReportReason.h"
|
||||
@ -13575,7 +13576,7 @@ void MessagesManager::init() {
|
||||
is_inited_ = true;
|
||||
|
||||
td_->notification_settings_manager_->init(); // load scope notification settings
|
||||
init_stickers_manager(td_); // load available reactions
|
||||
td_->reaction_manager_->init(); // load available reactions
|
||||
|
||||
start_time_ = Time::now();
|
||||
last_channel_pts_jump_warning_time_ = start_time_ - 3600;
|
||||
@ -23775,8 +23776,8 @@ Result<td_api::object_ptr<td_api::availableReactions>> MessagesManager::get_mess
|
||||
return Status::Error(400, "Message not found");
|
||||
}
|
||||
|
||||
return get_sorted_available_reactions(td_, get_message_available_reactions(d, m, false),
|
||||
get_message_active_reactions(d, m), row_size);
|
||||
return td_->reaction_manager_->get_sorted_available_reactions(get_message_available_reactions(d, m, false),
|
||||
get_message_active_reactions(d, m), row_size);
|
||||
}
|
||||
|
||||
ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m,
|
||||
|
662
td/telegram/ReactionManager.cpp
Normal file
662
td/telegram/ReactionManager.cpp
Normal file
@ -0,0 +1,662 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
||||
//
|
||||
// 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/ReactionManager.h"
|
||||
|
||||
#include "td/telegram/AuthManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/logevent/LogEvent.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/ReactionManager.hpp"
|
||||
#include "td/telegram/StickerFormat.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/TdDb.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/FlatHashSet.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace td {
|
||||
|
||||
class GetAvailableReactionsQuery final : public Td::ResultHandler {
|
||||
public:
|
||||
void send(int32 hash) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getAvailableReactions(hash)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getAvailableReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetAvailableReactionsQuery: " << to_string(ptr);
|
||||
td_->reaction_manager_->on_get_available_reactions(std::move(ptr));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for GetAvailableReactionsQuery: " << status;
|
||||
td_->reaction_manager_->on_get_available_reactions(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class GetRecentReactionsQuery final : public Td::ResultHandler {
|
||||
public:
|
||||
void send(int32 limit, int64 hash) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getRecentReactions(limit, hash)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getRecentReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetRecentReactionsQuery: " << to_string(ptr);
|
||||
td_->reaction_manager_->on_get_recent_reactions(std::move(ptr));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for GetRecentReactionsQuery: " << status;
|
||||
td_->reaction_manager_->on_get_recent_reactions(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class GetTopReactionsQuery final : public Td::ResultHandler {
|
||||
public:
|
||||
void send(int64 hash) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getTopReactions(50, hash)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getTopReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetTopReactionsQuery: " << to_string(ptr);
|
||||
td_->reaction_manager_->on_get_top_reactions(std::move(ptr));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for GetTopReactionsQuery: " << status;
|
||||
td_->reaction_manager_->on_get_top_reactions(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class ClearRecentReactionsQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
|
||||
public:
|
||||
explicit ClearRecentReactionsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send() {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_clearRecentReactions()));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_clearRecentReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
td_->reaction_manager_->reload_recent_reactions();
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (!G()->is_expected_error(status)) {
|
||||
LOG(ERROR) << "Receive error for clear recent reactions: " << status;
|
||||
}
|
||||
td_->reaction_manager_->reload_recent_reactions();
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
ReactionManager::ReactionManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||
}
|
||||
|
||||
ReactionManager::~ReactionManager() = default;
|
||||
|
||||
void ReactionManager::start_up() {
|
||||
init();
|
||||
}
|
||||
|
||||
void ReactionManager::tear_down() {
|
||||
parent_.reset();
|
||||
}
|
||||
|
||||
void ReactionManager::init() {
|
||||
if (is_inited_ || !td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot() || G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
is_inited_ = true;
|
||||
|
||||
td_->stickers_manager_->init();
|
||||
|
||||
load_active_reactions();
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::emojiReaction> ReactionManager::get_emoji_reaction_object(const string &emoji) const {
|
||||
for (auto &reaction : reactions_.reactions_) {
|
||||
if (reaction.reaction_type_.get_string() == emoji) {
|
||||
return td_api::make_object<td_api::emojiReaction>(
|
||||
reaction.reaction_type_.get_string(), reaction.title_, reaction.is_active_,
|
||||
td_->stickers_manager_->get_sticker_object(reaction.static_icon_),
|
||||
td_->stickers_manager_->get_sticker_object(reaction.appear_animation_),
|
||||
td_->stickers_manager_->get_sticker_object(reaction.select_animation_),
|
||||
td_->stickers_manager_->get_sticker_object(reaction.activate_animation_),
|
||||
td_->stickers_manager_->get_sticker_object(reaction.effect_animation_),
|
||||
td_->stickers_manager_->get_sticker_object(reaction.around_animation_),
|
||||
td_->stickers_manager_->get_sticker_object(reaction.center_animation_));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ReactionManager::get_emoji_reaction(const string &emoji,
|
||||
Promise<td_api::object_ptr<td_api::emojiReaction>> &&promise) {
|
||||
load_reactions();
|
||||
if (reactions_.reactions_.empty() && reactions_.are_being_reloaded_) {
|
||||
pending_get_emoji_reaction_queries_.emplace_back(emoji, std::move(promise));
|
||||
return;
|
||||
}
|
||||
promise.set_value(get_emoji_reaction_object(emoji));
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::availableReactions> ReactionManager::get_sorted_available_reactions(
|
||||
ChatReactions available_reactions, ChatReactions active_reactions, int32 row_size) {
|
||||
if (row_size < 5 || row_size > 25) {
|
||||
row_size = 8;
|
||||
}
|
||||
|
||||
bool is_premium = td_->option_manager_->get_option_boolean("is_premium");
|
||||
bool show_premium = is_premium;
|
||||
|
||||
auto recent_reactions = get_recent_reactions();
|
||||
auto top_reactions = get_top_reactions();
|
||||
LOG(INFO) << "Have available reactions " << available_reactions << " to be sorted by top reactions " << top_reactions
|
||||
<< " and recent reactions " << recent_reactions;
|
||||
if (active_reactions.allow_custom_ && active_reactions.allow_all_) {
|
||||
for (auto &reaction_type : recent_reactions) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
show_premium = true;
|
||||
}
|
||||
}
|
||||
for (auto &reaction_type : top_reactions) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
show_premium = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> all_available_reaction_types;
|
||||
for (const auto &reaction_type : available_reactions.reaction_types_) {
|
||||
CHECK(!reaction_type.is_empty());
|
||||
all_available_reaction_types.insert(reaction_type);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> top_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> recent_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> popular_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> last_reaction_objects;
|
||||
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> added_custom_reaction_types;
|
||||
auto add_reactions = [&](vector<td_api::object_ptr<td_api::availableReaction>> &reaction_objects,
|
||||
const vector<ReactionType> &reaction_types) {
|
||||
for (auto &reaction_type : reaction_types) {
|
||||
if (all_available_reaction_types.erase(reaction_type) != 0) {
|
||||
// add available reaction
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
added_custom_reaction_types.insert(reaction_type);
|
||||
}
|
||||
reaction_objects.push_back(
|
||||
td_api::make_object<td_api::availableReaction>(reaction_type.get_reaction_type_object(), false));
|
||||
} else if (reaction_type.is_custom_reaction() && available_reactions.allow_custom_ &&
|
||||
added_custom_reaction_types.insert(reaction_type).second) {
|
||||
// add implicitly available custom reaction
|
||||
reaction_objects.push_back(
|
||||
td_api::make_object<td_api::availableReaction>(reaction_type.get_reaction_type_object(), !is_premium));
|
||||
} else {
|
||||
// skip the reaction
|
||||
}
|
||||
}
|
||||
};
|
||||
if (show_premium) {
|
||||
if (top_reactions.size() > 2 * static_cast<size_t>(row_size)) {
|
||||
top_reactions.resize(2 * static_cast<size_t>(row_size));
|
||||
}
|
||||
add_reactions(top_reaction_objects, top_reactions);
|
||||
|
||||
if (!recent_reactions.empty()) {
|
||||
add_reactions(recent_reaction_objects, recent_reactions);
|
||||
}
|
||||
} else {
|
||||
add_reactions(top_reaction_objects, top_reactions);
|
||||
}
|
||||
add_reactions(last_reaction_objects, active_reaction_types_);
|
||||
add_reactions(last_reaction_objects, available_reactions.reaction_types_);
|
||||
|
||||
if (show_premium) {
|
||||
if (recent_reactions.empty()) {
|
||||
popular_reaction_objects = std::move(last_reaction_objects);
|
||||
} else {
|
||||
auto max_objects = 10 * static_cast<size_t>(row_size);
|
||||
if (recent_reaction_objects.size() + last_reaction_objects.size() > max_objects) {
|
||||
if (last_reaction_objects.size() < max_objects) {
|
||||
recent_reaction_objects.resize(max_objects - last_reaction_objects.size());
|
||||
} else {
|
||||
recent_reaction_objects.clear();
|
||||
}
|
||||
}
|
||||
append(recent_reaction_objects, std::move(last_reaction_objects));
|
||||
}
|
||||
} else {
|
||||
append(top_reaction_objects, std::move(last_reaction_objects));
|
||||
}
|
||||
|
||||
CHECK(all_available_reaction_types.empty());
|
||||
|
||||
return td_api::make_object<td_api::availableReactions>(
|
||||
std::move(top_reaction_objects), std::move(recent_reaction_objects), std::move(popular_reaction_objects),
|
||||
available_reactions.allow_custom_);
|
||||
}
|
||||
|
||||
vector<ReactionType> ReactionManager::get_recent_reactions() {
|
||||
load_recent_reactions();
|
||||
return recent_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
vector<ReactionType> ReactionManager::get_top_reactions() {
|
||||
load_top_reactions();
|
||||
return top_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
void ReactionManager::add_recent_reaction(const ReactionType &reaction_type) {
|
||||
load_recent_reactions();
|
||||
|
||||
auto &reactions = recent_reactions_.reaction_types_;
|
||||
if (!reactions.empty() && reactions[0] == reaction_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find(reactions.begin(), reactions.end(), reaction_type);
|
||||
if (it == reactions.end()) {
|
||||
if (static_cast<int32>(reactions.size()) == MAX_RECENT_REACTIONS) {
|
||||
reactions.back() = reaction_type;
|
||||
} else {
|
||||
reactions.push_back(reaction_type);
|
||||
}
|
||||
it = reactions.end() - 1;
|
||||
}
|
||||
std::rotate(reactions.begin(), it, it + 1);
|
||||
|
||||
recent_reactions_.hash_ = get_reaction_types_hash(reactions);
|
||||
}
|
||||
|
||||
void ReactionManager::clear_recent_reactions(Promise<Unit> &&promise) {
|
||||
load_recent_reactions();
|
||||
|
||||
if (recent_reactions_.reaction_types_.empty()) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
recent_reactions_.hash_ = 0;
|
||||
recent_reactions_.reaction_types_.clear();
|
||||
|
||||
td_->create_handler<ClearRecentReactionsQuery>(std::move(promise))->send();
|
||||
}
|
||||
|
||||
void ReactionManager::reload_reactions() {
|
||||
if (G()->close_flag() || reactions_.are_being_reloaded_) {
|
||||
return;
|
||||
}
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
reactions_.are_being_reloaded_ = true;
|
||||
load_reactions(); // must be after are_being_reloaded_ is set to true to avoid recursion
|
||||
td_->create_handler<GetAvailableReactionsQuery>()->send(reactions_.hash_);
|
||||
}
|
||||
|
||||
void ReactionManager::reload_recent_reactions() {
|
||||
if (G()->close_flag() || recent_reactions_.is_being_reloaded_) {
|
||||
return;
|
||||
}
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
recent_reactions_.is_being_reloaded_ = true;
|
||||
load_recent_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion
|
||||
td_->create_handler<GetRecentReactionsQuery>()->send(MAX_RECENT_REACTIONS, recent_reactions_.hash_);
|
||||
}
|
||||
|
||||
void ReactionManager::reload_top_reactions() {
|
||||
if (G()->close_flag() || top_reactions_.is_being_reloaded_) {
|
||||
return;
|
||||
}
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
top_reactions_.is_being_reloaded_ = true;
|
||||
load_top_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion
|
||||
td_->create_handler<GetTopReactionsQuery>()->send(top_reactions_.hash_);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::updateActiveEmojiReactions> ReactionManager::get_update_active_emoji_reactions_object()
|
||||
const {
|
||||
return td_api::make_object<td_api::updateActiveEmojiReactions>(
|
||||
transform(active_reaction_types_, [](const ReactionType &reaction_type) { return reaction_type.get_string(); }));
|
||||
}
|
||||
|
||||
void ReactionManager::save_active_reactions() {
|
||||
LOG(INFO) << "Save " << active_reaction_types_.size() << " active reactions";
|
||||
G()->td_db()->get_binlog_pmc()->set("active_reactions", log_event_store(active_reaction_types_).as_slice().str());
|
||||
}
|
||||
|
||||
void ReactionManager::save_reactions() {
|
||||
LOG(INFO) << "Save " << reactions_.reactions_.size() << " available reactions";
|
||||
are_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("reactions", log_event_store(reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void ReactionManager::save_recent_reactions() {
|
||||
LOG(INFO) << "Save " << recent_reactions_.reaction_types_.size() << " recent reactions";
|
||||
are_recent_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("recent_reactions", log_event_store(recent_reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void ReactionManager::save_top_reactions() {
|
||||
LOG(INFO) << "Save " << top_reactions_.reaction_types_.size() << " top reactions";
|
||||
are_top_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("top_reactions", log_event_store(top_reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void ReactionManager::load_active_reactions() {
|
||||
LOG(INFO) << "Loading active reactions";
|
||||
string active_reaction_types = G()->td_db()->get_binlog_pmc()->get("active_reactions");
|
||||
if (active_reaction_types.empty()) {
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(active_reaction_types_, active_reaction_types);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load active reactions: " << status;
|
||||
active_reaction_types_ = {};
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << active_reaction_types_.size() << " active reactions";
|
||||
|
||||
td_->messages_manager_->set_active_reactions(active_reaction_types_);
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object());
|
||||
}
|
||||
|
||||
void ReactionManager::load_reactions() {
|
||||
if (are_reactions_loaded_from_database_) {
|
||||
return;
|
||||
}
|
||||
are_reactions_loaded_from_database_ = true;
|
||||
|
||||
LOG(INFO) << "Loading available reactions";
|
||||
string reactions = G()->td_db()->get_binlog_pmc()->get("reactions");
|
||||
if (reactions.empty()) {
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
auto new_reactions = reactions_;
|
||||
auto status = log_event_parse(new_reactions, reactions);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load available reactions: " << status;
|
||||
return reload_reactions();
|
||||
}
|
||||
for (auto &reaction_type : new_reactions.reactions_) {
|
||||
if (!reaction_type.is_valid()) {
|
||||
LOG(ERROR) << "Loaded invalid reaction";
|
||||
return reload_reactions();
|
||||
}
|
||||
}
|
||||
reactions_ = std::move(new_reactions);
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << reactions_.reactions_.size() << " available reactions";
|
||||
|
||||
update_active_reactions();
|
||||
}
|
||||
|
||||
void ReactionManager::load_recent_reactions() {
|
||||
if (are_recent_reactions_loaded_from_database_) {
|
||||
return;
|
||||
}
|
||||
are_recent_reactions_loaded_from_database_ = true;
|
||||
|
||||
LOG(INFO) << "Loading recent reactions";
|
||||
string recent_reactions = G()->td_db()->get_binlog_pmc()->get("recent_reactions");
|
||||
if (recent_reactions.empty()) {
|
||||
return reload_recent_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(recent_reactions_, recent_reactions);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load recent reactions: " << status;
|
||||
recent_reactions_ = {};
|
||||
return reload_recent_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << recent_reactions_.reaction_types_.size() << " recent reactions";
|
||||
}
|
||||
|
||||
void ReactionManager::load_top_reactions() {
|
||||
if (are_top_reactions_loaded_from_database_) {
|
||||
return;
|
||||
}
|
||||
are_top_reactions_loaded_from_database_ = true;
|
||||
|
||||
LOG(INFO) << "Loading top reactions";
|
||||
string top_reactions = G()->td_db()->get_binlog_pmc()->get("top_reactions");
|
||||
if (top_reactions.empty()) {
|
||||
return reload_top_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(top_reactions_, top_reactions);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load top reactions: " << status;
|
||||
top_reactions_ = {};
|
||||
return reload_top_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << top_reactions_.reaction_types_.size() << " top reactions";
|
||||
}
|
||||
|
||||
void ReactionManager::update_active_reactions() {
|
||||
vector<ReactionType> active_reaction_types;
|
||||
for (auto &reaction : reactions_.reactions_) {
|
||||
if (reaction.is_active_) {
|
||||
active_reaction_types.emplace_back(reaction.reaction_type_);
|
||||
}
|
||||
}
|
||||
if (active_reaction_types == active_reaction_types_) {
|
||||
return;
|
||||
}
|
||||
active_reaction_types_ = active_reaction_types;
|
||||
|
||||
save_active_reactions();
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object());
|
||||
|
||||
td_->messages_manager_->set_active_reactions(std::move(active_reaction_types));
|
||||
}
|
||||
|
||||
void ReactionManager::on_get_available_reactions(
|
||||
tl_object_ptr<telegram_api::messages_AvailableReactions> &&available_reactions_ptr) {
|
||||
CHECK(reactions_.are_being_reloaded_);
|
||||
reactions_.are_being_reloaded_ = false;
|
||||
|
||||
auto get_emoji_reaction_queries = std::move(pending_get_emoji_reaction_queries_);
|
||||
pending_get_emoji_reaction_queries_.clear();
|
||||
SCOPE_EXIT {
|
||||
for (auto &query : get_emoji_reaction_queries) {
|
||||
query.second.set_value(get_emoji_reaction_object(query.first));
|
||||
}
|
||||
};
|
||||
|
||||
if (available_reactions_ptr == nullptr) {
|
||||
// failed to get available reactions
|
||||
return;
|
||||
}
|
||||
|
||||
int32 constructor_id = available_reactions_ptr->get_id();
|
||||
if (constructor_id == telegram_api::messages_availableReactionsNotModified::ID) {
|
||||
LOG(INFO) << "Available reactions are not modified";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_availableReactions::ID);
|
||||
auto available_reactions = move_tl_object_as<telegram_api::messages_availableReactions>(available_reactions_ptr);
|
||||
vector<Reaction> new_reactions;
|
||||
for (auto &available_reaction : available_reactions->reactions_) {
|
||||
Reaction reaction;
|
||||
reaction.is_active_ = !available_reaction->inactive_;
|
||||
reaction.is_premium_ = available_reaction->premium_;
|
||||
reaction.reaction_type_ = ReactionType(std::move(available_reaction->reaction_));
|
||||
reaction.title_ = std::move(available_reaction->title_);
|
||||
reaction.static_icon_ =
|
||||
td_->stickers_manager_
|
||||
->on_get_sticker_document(std::move(available_reaction->static_icon_), StickerFormat::Webp)
|
||||
.second;
|
||||
reaction.appear_animation_ =
|
||||
td_->stickers_manager_
|
||||
->on_get_sticker_document(std::move(available_reaction->appear_animation_), StickerFormat::Tgs)
|
||||
.second;
|
||||
reaction.select_animation_ =
|
||||
td_->stickers_manager_
|
||||
->on_get_sticker_document(std::move(available_reaction->select_animation_), StickerFormat::Tgs)
|
||||
.second;
|
||||
reaction.activate_animation_ =
|
||||
td_->stickers_manager_
|
||||
->on_get_sticker_document(std::move(available_reaction->activate_animation_), StickerFormat::Tgs)
|
||||
.second;
|
||||
reaction.effect_animation_ =
|
||||
td_->stickers_manager_
|
||||
->on_get_sticker_document(std::move(available_reaction->effect_animation_), StickerFormat::Tgs)
|
||||
.second;
|
||||
reaction.around_animation_ =
|
||||
td_->stickers_manager_
|
||||
->on_get_sticker_document(std::move(available_reaction->around_animation_), StickerFormat::Tgs)
|
||||
.second;
|
||||
reaction.center_animation_ =
|
||||
td_->stickers_manager_->on_get_sticker_document(std::move(available_reaction->center_icon_), StickerFormat::Tgs)
|
||||
.second;
|
||||
|
||||
if (!reaction.is_valid()) {
|
||||
LOG(ERROR) << "Receive invalid " << reaction.reaction_type_;
|
||||
continue;
|
||||
}
|
||||
if (reaction.is_premium_) {
|
||||
LOG(ERROR) << "Receive premium " << reaction.reaction_type_;
|
||||
continue;
|
||||
}
|
||||
|
||||
new_reactions.push_back(std::move(reaction));
|
||||
}
|
||||
reactions_.reactions_ = std::move(new_reactions);
|
||||
reactions_.hash_ = available_reactions->hash_;
|
||||
|
||||
save_reactions();
|
||||
|
||||
update_active_reactions();
|
||||
}
|
||||
|
||||
void ReactionManager::on_get_recent_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr) {
|
||||
CHECK(recent_reactions_.is_being_reloaded_);
|
||||
recent_reactions_.is_being_reloaded_ = false;
|
||||
|
||||
if (reactions_ptr == nullptr) {
|
||||
// failed to get recent reactions
|
||||
return;
|
||||
}
|
||||
|
||||
int32 constructor_id = reactions_ptr->get_id();
|
||||
if (constructor_id == telegram_api::messages_reactionsNotModified::ID) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_reactions::ID);
|
||||
auto reactions = move_tl_object_as<telegram_api::messages_reactions>(reactions_ptr);
|
||||
auto new_reaction_types = transform(
|
||||
reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
if (new_reaction_types == recent_reactions_.reaction_types_ && recent_reactions_.hash_ == reactions->hash_) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
recent_reactions_.reaction_types_ = std::move(new_reaction_types);
|
||||
recent_reactions_.hash_ = reactions->hash_;
|
||||
|
||||
auto expected_hash = get_reaction_types_hash(recent_reactions_.reaction_types_);
|
||||
if (recent_reactions_.hash_ != expected_hash) {
|
||||
LOG(ERROR) << "Receive hash " << recent_reactions_.hash_ << " instead of " << expected_hash << " for reactions "
|
||||
<< recent_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
save_recent_reactions();
|
||||
}
|
||||
|
||||
void ReactionManager::on_get_top_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr) {
|
||||
CHECK(top_reactions_.is_being_reloaded_);
|
||||
top_reactions_.is_being_reloaded_ = false;
|
||||
|
||||
if (reactions_ptr == nullptr) {
|
||||
// failed to get top reactions
|
||||
return;
|
||||
}
|
||||
|
||||
int32 constructor_id = reactions_ptr->get_id();
|
||||
if (constructor_id == telegram_api::messages_reactionsNotModified::ID) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_reactions::ID);
|
||||
auto reactions = move_tl_object_as<telegram_api::messages_reactions>(reactions_ptr);
|
||||
auto new_reaction_types = transform(
|
||||
reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
if (new_reaction_types == top_reactions_.reaction_types_ && top_reactions_.hash_ == reactions->hash_) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
top_reactions_.reaction_types_ = std::move(new_reaction_types);
|
||||
top_reactions_.hash_ = reactions->hash_;
|
||||
|
||||
save_top_reactions();
|
||||
}
|
||||
|
||||
bool ReactionManager::is_active_reaction(const ReactionType &reaction_type) const {
|
||||
for (auto &supported_reaction : reactions_.reactions_) {
|
||||
if (supported_reaction.reaction_type_ == reaction_type) {
|
||||
return supported_reaction.is_active_;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReactionManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!active_reaction_types_.empty()) {
|
||||
updates.push_back(get_update_active_emoji_reactions_object());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
161
td/telegram/ReactionManager.h
Normal file
161
td/telegram/ReactionManager.h
Normal file
@ -0,0 +1,161 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/ChatReactions.h"
|
||||
#include "td/telegram/files/FileId.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Promise.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Td;
|
||||
|
||||
class ReactionManager final : public Actor {
|
||||
public:
|
||||
ReactionManager(Td *td, ActorShared<> parent);
|
||||
ReactionManager(const ReactionManager &) = delete;
|
||||
ReactionManager &operator=(const ReactionManager &) = delete;
|
||||
ReactionManager(ReactionManager &&) = delete;
|
||||
ReactionManager &operator=(ReactionManager &&) = delete;
|
||||
~ReactionManager() final;
|
||||
|
||||
void init();
|
||||
|
||||
bool is_active_reaction(const ReactionType &reaction_type) const;
|
||||
|
||||
void get_emoji_reaction(const string &emoji, Promise<td_api::object_ptr<td_api::emojiReaction>> &&promise);
|
||||
|
||||
td_api::object_ptr<td_api::availableReactions> get_sorted_available_reactions(ChatReactions available_reactions,
|
||||
ChatReactions active_reactions,
|
||||
int32 row_size);
|
||||
|
||||
vector<ReactionType> get_recent_reactions();
|
||||
|
||||
vector<ReactionType> get_top_reactions();
|
||||
|
||||
void add_recent_reaction(const ReactionType &reaction_type);
|
||||
|
||||
void clear_recent_reactions(Promise<Unit> &&promise);
|
||||
|
||||
void reload_reactions();
|
||||
|
||||
void reload_recent_reactions();
|
||||
|
||||
void reload_top_reactions();
|
||||
|
||||
void on_get_available_reactions(tl_object_ptr<telegram_api::messages_AvailableReactions> &&available_reactions_ptr);
|
||||
|
||||
void on_get_recent_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr);
|
||||
|
||||
void on_get_top_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr);
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
|
||||
private:
|
||||
static constexpr int32 MAX_RECENT_REACTIONS = 100; // some reasonable value
|
||||
|
||||
struct Reaction {
|
||||
ReactionType reaction_type_;
|
||||
string title_;
|
||||
bool is_active_ = false;
|
||||
bool is_premium_ = false;
|
||||
FileId static_icon_;
|
||||
FileId appear_animation_;
|
||||
FileId select_animation_;
|
||||
FileId activate_animation_;
|
||||
FileId effect_animation_;
|
||||
FileId around_animation_;
|
||||
FileId center_animation_;
|
||||
|
||||
bool is_valid() const {
|
||||
return static_icon_.is_valid() && appear_animation_.is_valid() && select_animation_.is_valid() &&
|
||||
activate_animation_.is_valid() && effect_animation_.is_valid() && !reaction_type_.is_empty();
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct Reactions {
|
||||
int32 hash_ = 0;
|
||||
bool are_being_reloaded_ = false;
|
||||
vector<Reaction> reactions_;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct ReactionList {
|
||||
int64 hash_ = 0;
|
||||
bool is_being_reloaded_ = false;
|
||||
vector<ReactionType> reaction_types_;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
td_api::object_ptr<td_api::emojiReaction> get_emoji_reaction_object(const string &emoji) const;
|
||||
|
||||
void start_up() final;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
void save_active_reactions();
|
||||
|
||||
void save_reactions();
|
||||
|
||||
void save_recent_reactions();
|
||||
|
||||
void save_top_reactions();
|
||||
|
||||
void load_active_reactions();
|
||||
|
||||
void load_reactions();
|
||||
|
||||
void load_recent_reactions();
|
||||
|
||||
void load_top_reactions();
|
||||
|
||||
void update_active_reactions();
|
||||
|
||||
td_api::object_ptr<td_api::updateActiveEmojiReactions> get_update_active_emoji_reactions_object() const;
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
|
||||
bool is_inited_ = false;
|
||||
|
||||
vector<std::pair<string, Promise<td_api::object_ptr<td_api::emojiReaction>>>> pending_get_emoji_reaction_queries_;
|
||||
|
||||
Reactions reactions_;
|
||||
vector<ReactionType> active_reaction_types_;
|
||||
|
||||
ReactionList recent_reactions_;
|
||||
ReactionList top_reactions_;
|
||||
|
||||
bool are_reactions_loaded_from_database_ = false;
|
||||
bool are_recent_reactions_loaded_from_database_ = false;
|
||||
bool are_top_reactions_loaded_from_database_ = false;
|
||||
};
|
||||
|
||||
} // namespace td
|
122
td/telegram/ReactionManager.hpp
Normal file
122
td/telegram/ReactionManager.hpp
Normal file
@ -0,0 +1,122 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
|
||||
#include "td/telegram/ReactionType.hpp"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/StickersManager.hpp"
|
||||
#include "td/telegram/Td.h"
|
||||
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void ReactionManager::Reaction::store(StorerT &storer) const {
|
||||
StickersManager *stickers_manager = storer.context()->td().get_actor_unsafe()->stickers_manager_.get();
|
||||
bool has_around_animation = !around_animation_.empty();
|
||||
bool has_center_animation = !center_animation_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(is_active_);
|
||||
STORE_FLAG(has_around_animation);
|
||||
STORE_FLAG(has_center_animation);
|
||||
STORE_FLAG(is_premium_);
|
||||
END_STORE_FLAGS();
|
||||
td::store(reaction_type_, storer);
|
||||
td::store(title_, storer);
|
||||
stickers_manager->store_sticker(static_icon_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(appear_animation_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(select_animation_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(activate_animation_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(effect_animation_, false, storer, "Reaction");
|
||||
if (has_around_animation) {
|
||||
stickers_manager->store_sticker(around_animation_, false, storer, "Reaction");
|
||||
}
|
||||
if (has_center_animation) {
|
||||
stickers_manager->store_sticker(center_animation_, false, storer, "Reaction");
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void ReactionManager::Reaction::parse(ParserT &parser) {
|
||||
StickersManager *stickers_manager = parser.context()->td().get_actor_unsafe()->stickers_manager_.get();
|
||||
bool has_around_animation;
|
||||
bool has_center_animation;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(is_active_);
|
||||
PARSE_FLAG(has_around_animation);
|
||||
PARSE_FLAG(has_center_animation);
|
||||
PARSE_FLAG(is_premium_);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(reaction_type_, parser);
|
||||
td::parse(title_, parser);
|
||||
static_icon_ = stickers_manager->parse_sticker(false, parser);
|
||||
appear_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
select_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
activate_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
effect_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
if (has_around_animation) {
|
||||
around_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
}
|
||||
if (has_center_animation) {
|
||||
center_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
}
|
||||
|
||||
is_premium_ = false;
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void ReactionManager::Reactions::store(StorerT &storer) const {
|
||||
bool has_reactions = !reactions_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_reactions);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::store(reactions_, storer);
|
||||
td::store(hash_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void ReactionManager::Reactions::parse(ParserT &parser) {
|
||||
bool has_reactions;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_reactions);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::parse(reactions_, parser);
|
||||
td::parse(hash_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void ReactionManager::ReactionList::store(StorerT &storer) const {
|
||||
bool has_reaction_types = !reaction_types_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_reaction_types);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reaction_types) {
|
||||
td::store(reaction_types_, storer);
|
||||
td::store(hash_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void ReactionManager::ReactionList::parse(ParserT &parser) {
|
||||
bool has_reaction_types;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_reaction_types);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reaction_types) {
|
||||
td::parse(reaction_types_, parser);
|
||||
td::parse(hash_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
@ -10,7 +10,7 @@
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
@ -189,7 +189,7 @@ void set_default_reaction(Td *td, ReactionType reaction_type, Promise<Unit> &&pr
|
||||
if (reaction_type.is_empty()) {
|
||||
return promise.set_error(Status::Error(400, "Default reaction must be non-empty"));
|
||||
}
|
||||
if (!reaction_type.is_custom_reaction() && !td->stickers_manager_->is_active_reaction(reaction_type)) {
|
||||
if (!reaction_type.is_custom_reaction() && !td->reaction_manager_->is_active_reaction(reaction_type)) {
|
||||
return promise.set_error(Status::Error(400, "Can't set incative reaction as default"));
|
||||
}
|
||||
|
||||
@ -209,15 +209,15 @@ void send_set_default_reaction_query(Td *td) {
|
||||
}
|
||||
|
||||
vector<ReactionType> get_recent_reactions(Td *td) {
|
||||
return td->stickers_manager_->get_recent_reactions();
|
||||
return td->reaction_manager_->get_recent_reactions();
|
||||
}
|
||||
|
||||
vector<ReactionType> get_top_reactions(Td *td) {
|
||||
return td->stickers_manager_->get_top_reactions();
|
||||
return td->reaction_manager_->get_top_reactions();
|
||||
}
|
||||
|
||||
void add_recent_reaction(Td *td, const ReactionType &reaction_type) {
|
||||
td->stickers_manager_->add_recent_reaction(reaction_type);
|
||||
td->reaction_manager_->add_recent_reaction(reaction_type);
|
||||
}
|
||||
|
||||
int64 get_reaction_types_hash(const vector<ReactionType> &reaction_types) {
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "td/telegram/LanguagePackManager.h"
|
||||
#include "td/telegram/logevent/LogEvent.h"
|
||||
#include "td/telegram/logevent/LogEventHelper.h"
|
||||
#include "td/telegram/MessageReaction.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/net/DcId.h"
|
||||
@ -54,7 +53,6 @@
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/PathView.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/StackAllocator.h"
|
||||
@ -70,105 +68,6 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
class GetAvailableReactionsQuery final : public Td::ResultHandler {
|
||||
public:
|
||||
void send(int32 hash) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getAvailableReactions(hash)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getAvailableReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetAvailableReactionsQuery: " << to_string(ptr);
|
||||
td_->stickers_manager_->on_get_available_reactions(std::move(ptr));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for GetAvailableReactionsQuery: " << status;
|
||||
td_->stickers_manager_->on_get_available_reactions(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class GetRecentReactionsQuery final : public Td::ResultHandler {
|
||||
public:
|
||||
void send(int32 limit, int64 hash) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getRecentReactions(limit, hash)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getRecentReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetRecentReactionsQuery: " << to_string(ptr);
|
||||
td_->stickers_manager_->on_get_recent_reactions(std::move(ptr));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for GetRecentReactionsQuery: " << status;
|
||||
td_->stickers_manager_->on_get_recent_reactions(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class GetTopReactionsQuery final : public Td::ResultHandler {
|
||||
public:
|
||||
void send(int64 hash) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_getTopReactions(50, hash)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_getTopReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for GetTopReactionsQuery: " << to_string(ptr);
|
||||
td_->stickers_manager_->on_get_top_reactions(std::move(ptr));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
LOG(INFO) << "Receive error for GetTopReactionsQuery: " << status;
|
||||
td_->stickers_manager_->on_get_top_reactions(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class ClearRecentReactionsQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
|
||||
public:
|
||||
explicit ClearRecentReactionsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send() {
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_clearRecentReactions()));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_clearRecentReactions>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
td_->stickers_manager_->reload_recent_reactions();
|
||||
promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (!G()->is_expected_error(status)) {
|
||||
LOG(ERROR) << "Receive error for clear recent reactions: " << status;
|
||||
}
|
||||
td_->stickers_manager_->reload_recent_reactions();
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class GetAllStickersQuery final : public Td::ResultHandler {
|
||||
StickerType sticker_type_;
|
||||
|
||||
@ -1778,8 +1677,6 @@ void StickersManager::init() {
|
||||
}
|
||||
send_closure(G()->td(), &Td::send_update, get_update_dice_emojis_object());
|
||||
|
||||
load_active_reactions();
|
||||
|
||||
on_update_dice_success_values();
|
||||
on_update_dice_emojis();
|
||||
|
||||
@ -1810,203 +1707,6 @@ void StickersManager::init() {
|
||||
td_->option_manager_->set_option_empty("animated_emoji_sticker_set_name"); // legacy
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::emojiReaction> StickersManager::get_emoji_reaction_object(const string &emoji) const {
|
||||
for (auto &reaction : reactions_.reactions_) {
|
||||
if (reaction.reaction_type_.get_string() == emoji) {
|
||||
return td_api::make_object<td_api::emojiReaction>(
|
||||
reaction.reaction_type_.get_string(), reaction.title_, reaction.is_active_,
|
||||
get_sticker_object(reaction.static_icon_), get_sticker_object(reaction.appear_animation_),
|
||||
get_sticker_object(reaction.select_animation_), get_sticker_object(reaction.activate_animation_),
|
||||
get_sticker_object(reaction.effect_animation_), get_sticker_object(reaction.around_animation_),
|
||||
get_sticker_object(reaction.center_animation_));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void StickersManager::get_emoji_reaction(const string &emoji,
|
||||
Promise<td_api::object_ptr<td_api::emojiReaction>> &&promise) {
|
||||
load_reactions();
|
||||
if (reactions_.reactions_.empty() && reactions_.are_being_reloaded_) {
|
||||
pending_get_emoji_reaction_queries_.emplace_back(emoji, std::move(promise));
|
||||
return;
|
||||
}
|
||||
promise.set_value(get_emoji_reaction_object(emoji));
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::availableReactions> StickersManager::get_sorted_available_reactions(
|
||||
ChatReactions available_reactions, ChatReactions active_reactions, int32 row_size) {
|
||||
if (row_size < 5 || row_size > 25) {
|
||||
row_size = 8;
|
||||
}
|
||||
|
||||
bool is_premium = td_->option_manager_->get_option_boolean("is_premium");
|
||||
bool show_premium = is_premium;
|
||||
|
||||
auto recent_reactions = get_recent_reactions();
|
||||
auto top_reactions = get_top_reactions();
|
||||
LOG(INFO) << "Have available reactions " << available_reactions << " to be sorted by top reactions " << top_reactions
|
||||
<< " and recent reactions " << recent_reactions;
|
||||
if (active_reactions.allow_custom_ && active_reactions.allow_all_) {
|
||||
for (auto &reaction_type : recent_reactions) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
show_premium = true;
|
||||
}
|
||||
}
|
||||
for (auto &reaction_type : top_reactions) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
show_premium = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> all_available_reaction_types;
|
||||
for (const auto &reaction_type : available_reactions.reaction_types_) {
|
||||
CHECK(!reaction_type.is_empty());
|
||||
all_available_reaction_types.insert(reaction_type);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> top_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> recent_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> popular_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> last_reaction_objects;
|
||||
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> added_custom_reaction_types;
|
||||
auto add_reactions = [&](vector<td_api::object_ptr<td_api::availableReaction>> &reaction_objects,
|
||||
const vector<ReactionType> &reaction_types) {
|
||||
for (auto &reaction_type : reaction_types) {
|
||||
if (all_available_reaction_types.erase(reaction_type) != 0) {
|
||||
// add available reaction
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
added_custom_reaction_types.insert(reaction_type);
|
||||
}
|
||||
reaction_objects.push_back(
|
||||
td_api::make_object<td_api::availableReaction>(reaction_type.get_reaction_type_object(), false));
|
||||
} else if (reaction_type.is_custom_reaction() && available_reactions.allow_custom_ &&
|
||||
added_custom_reaction_types.insert(reaction_type).second) {
|
||||
// add implicitly available custom reaction
|
||||
reaction_objects.push_back(
|
||||
td_api::make_object<td_api::availableReaction>(reaction_type.get_reaction_type_object(), !is_premium));
|
||||
} else {
|
||||
// skip the reaction
|
||||
}
|
||||
}
|
||||
};
|
||||
if (show_premium) {
|
||||
if (top_reactions.size() > 2 * static_cast<size_t>(row_size)) {
|
||||
top_reactions.resize(2 * static_cast<size_t>(row_size));
|
||||
}
|
||||
add_reactions(top_reaction_objects, top_reactions);
|
||||
|
||||
if (!recent_reactions.empty()) {
|
||||
add_reactions(recent_reaction_objects, recent_reactions);
|
||||
}
|
||||
} else {
|
||||
add_reactions(top_reaction_objects, top_reactions);
|
||||
}
|
||||
add_reactions(last_reaction_objects, active_reaction_types_);
|
||||
add_reactions(last_reaction_objects, available_reactions.reaction_types_);
|
||||
|
||||
if (show_premium) {
|
||||
if (recent_reactions.empty()) {
|
||||
popular_reaction_objects = std::move(last_reaction_objects);
|
||||
} else {
|
||||
auto max_objects = 10 * static_cast<size_t>(row_size);
|
||||
if (recent_reaction_objects.size() + last_reaction_objects.size() > max_objects) {
|
||||
if (last_reaction_objects.size() < max_objects) {
|
||||
recent_reaction_objects.resize(max_objects - last_reaction_objects.size());
|
||||
} else {
|
||||
recent_reaction_objects.clear();
|
||||
}
|
||||
}
|
||||
append(recent_reaction_objects, std::move(last_reaction_objects));
|
||||
}
|
||||
} else {
|
||||
append(top_reaction_objects, std::move(last_reaction_objects));
|
||||
}
|
||||
|
||||
CHECK(all_available_reaction_types.empty());
|
||||
|
||||
return td_api::make_object<td_api::availableReactions>(
|
||||
std::move(top_reaction_objects), std::move(recent_reaction_objects), std::move(popular_reaction_objects),
|
||||
available_reactions.allow_custom_);
|
||||
}
|
||||
|
||||
vector<ReactionType> StickersManager::get_recent_reactions() {
|
||||
load_recent_reactions();
|
||||
return recent_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
vector<ReactionType> StickersManager::get_top_reactions() {
|
||||
load_top_reactions();
|
||||
return top_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
void StickersManager::add_recent_reaction(const ReactionType &reaction_type) {
|
||||
load_recent_reactions();
|
||||
|
||||
auto &reactions = recent_reactions_.reaction_types_;
|
||||
if (!reactions.empty() && reactions[0] == reaction_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find(reactions.begin(), reactions.end(), reaction_type);
|
||||
if (it == reactions.end()) {
|
||||
if (static_cast<int32>(reactions.size()) == MAX_RECENT_REACTIONS) {
|
||||
reactions.back() = reaction_type;
|
||||
} else {
|
||||
reactions.push_back(reaction_type);
|
||||
}
|
||||
it = reactions.end() - 1;
|
||||
}
|
||||
std::rotate(reactions.begin(), it, it + 1);
|
||||
|
||||
recent_reactions_.hash_ = get_reaction_types_hash(reactions);
|
||||
}
|
||||
|
||||
void StickersManager::clear_recent_reactions(Promise<Unit> &&promise) {
|
||||
load_recent_reactions();
|
||||
|
||||
if (recent_reactions_.reaction_types_.empty()) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
recent_reactions_.hash_ = 0;
|
||||
recent_reactions_.reaction_types_.clear();
|
||||
|
||||
td_->create_handler<ClearRecentReactionsQuery>(std::move(promise))->send();
|
||||
}
|
||||
|
||||
void StickersManager::reload_reactions() {
|
||||
if (G()->close_flag() || reactions_.are_being_reloaded_) {
|
||||
return;
|
||||
}
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
reactions_.are_being_reloaded_ = true;
|
||||
load_reactions(); // must be after are_being_reloaded_ is set to true to avoid recursion
|
||||
td_->create_handler<GetAvailableReactionsQuery>()->send(reactions_.hash_);
|
||||
}
|
||||
|
||||
void StickersManager::reload_recent_reactions() {
|
||||
if (G()->close_flag() || recent_reactions_.is_being_reloaded_) {
|
||||
return;
|
||||
}
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
recent_reactions_.is_being_reloaded_ = true;
|
||||
load_recent_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion
|
||||
td_->create_handler<GetRecentReactionsQuery>()->send(MAX_RECENT_REACTIONS, recent_reactions_.hash_);
|
||||
}
|
||||
|
||||
void StickersManager::reload_top_reactions() {
|
||||
if (G()->close_flag() || top_reactions_.is_being_reloaded_) {
|
||||
return;
|
||||
}
|
||||
CHECK(!td_->auth_manager_->is_bot());
|
||||
top_reactions_.is_being_reloaded_ = true;
|
||||
load_top_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion
|
||||
td_->create_handler<GetTopReactionsQuery>()->send(top_reactions_.hash_);
|
||||
}
|
||||
|
||||
StickersManager::SpecialStickerSet &StickersManager::add_special_sticker_set(const SpecialStickerSetType &type) {
|
||||
CHECK(!type.is_empty());
|
||||
auto &result_ptr = special_sticker_sets_[type];
|
||||
@ -4236,283 +3936,6 @@ void StickersManager::on_get_special_sticker_set(const SpecialStickerSetType &ty
|
||||
on_load_special_sticker_set(type, Status::OK());
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::updateActiveEmojiReactions> StickersManager::get_update_active_emoji_reactions_object()
|
||||
const {
|
||||
return td_api::make_object<td_api::updateActiveEmojiReactions>(
|
||||
transform(active_reaction_types_, [](const ReactionType &reaction_type) { return reaction_type.get_string(); }));
|
||||
}
|
||||
|
||||
void StickersManager::save_active_reactions() {
|
||||
LOG(INFO) << "Save " << active_reaction_types_.size() << " active reactions";
|
||||
G()->td_db()->get_binlog_pmc()->set("active_reactions", log_event_store(active_reaction_types_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::save_reactions() {
|
||||
LOG(INFO) << "Save " << reactions_.reactions_.size() << " available reactions";
|
||||
are_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("reactions", log_event_store(reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::save_recent_reactions() {
|
||||
LOG(INFO) << "Save " << recent_reactions_.reaction_types_.size() << " recent reactions";
|
||||
are_recent_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("recent_reactions", log_event_store(recent_reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::save_top_reactions() {
|
||||
LOG(INFO) << "Save " << top_reactions_.reaction_types_.size() << " top reactions";
|
||||
are_top_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("top_reactions", log_event_store(top_reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::load_active_reactions() {
|
||||
LOG(INFO) << "Loading active reactions";
|
||||
string active_reaction_types = G()->td_db()->get_binlog_pmc()->get("active_reactions");
|
||||
if (active_reaction_types.empty()) {
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(active_reaction_types_, active_reaction_types);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load active reactions: " << status;
|
||||
active_reaction_types_ = {};
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << active_reaction_types_.size() << " active reactions";
|
||||
|
||||
td_->messages_manager_->set_active_reactions(active_reaction_types_);
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object());
|
||||
}
|
||||
|
||||
void StickersManager::load_reactions() {
|
||||
if (are_reactions_loaded_from_database_) {
|
||||
return;
|
||||
}
|
||||
are_reactions_loaded_from_database_ = true;
|
||||
|
||||
LOG(INFO) << "Loading available reactions";
|
||||
string reactions = G()->td_db()->get_binlog_pmc()->get("reactions");
|
||||
if (reactions.empty()) {
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
auto new_reactions = reactions_;
|
||||
auto status = log_event_parse(new_reactions, reactions);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load available reactions: " << status;
|
||||
return reload_reactions();
|
||||
}
|
||||
for (auto &reaction_type : new_reactions.reactions_) {
|
||||
if (!reaction_type.is_valid()) {
|
||||
LOG(ERROR) << "Loaded invalid reaction";
|
||||
return reload_reactions();
|
||||
}
|
||||
}
|
||||
reactions_ = std::move(new_reactions);
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << reactions_.reactions_.size() << " available reactions";
|
||||
|
||||
update_active_reactions();
|
||||
}
|
||||
|
||||
void StickersManager::load_recent_reactions() {
|
||||
if (are_recent_reactions_loaded_from_database_) {
|
||||
return;
|
||||
}
|
||||
are_recent_reactions_loaded_from_database_ = true;
|
||||
|
||||
LOG(INFO) << "Loading recent reactions";
|
||||
string recent_reactions = G()->td_db()->get_binlog_pmc()->get("recent_reactions");
|
||||
if (recent_reactions.empty()) {
|
||||
return reload_recent_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(recent_reactions_, recent_reactions);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load recent reactions: " << status;
|
||||
recent_reactions_ = {};
|
||||
return reload_recent_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << recent_reactions_.reaction_types_.size() << " recent reactions";
|
||||
}
|
||||
|
||||
void StickersManager::load_top_reactions() {
|
||||
if (are_top_reactions_loaded_from_database_) {
|
||||
return;
|
||||
}
|
||||
are_top_reactions_loaded_from_database_ = true;
|
||||
|
||||
LOG(INFO) << "Loading top reactions";
|
||||
string top_reactions = G()->td_db()->get_binlog_pmc()->get("top_reactions");
|
||||
if (top_reactions.empty()) {
|
||||
return reload_top_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(top_reactions_, top_reactions);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load top reactions: " << status;
|
||||
top_reactions_ = {};
|
||||
return reload_top_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << top_reactions_.reaction_types_.size() << " top reactions";
|
||||
}
|
||||
|
||||
void StickersManager::update_active_reactions() {
|
||||
vector<ReactionType> active_reaction_types;
|
||||
for (auto &reaction : reactions_.reactions_) {
|
||||
if (reaction.is_active_) {
|
||||
active_reaction_types.emplace_back(reaction.reaction_type_);
|
||||
}
|
||||
}
|
||||
if (active_reaction_types == active_reaction_types_) {
|
||||
return;
|
||||
}
|
||||
active_reaction_types_ = active_reaction_types;
|
||||
|
||||
save_active_reactions();
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object());
|
||||
|
||||
td_->messages_manager_->set_active_reactions(std::move(active_reaction_types));
|
||||
}
|
||||
|
||||
void StickersManager::on_get_available_reactions(
|
||||
tl_object_ptr<telegram_api::messages_AvailableReactions> &&available_reactions_ptr) {
|
||||
CHECK(reactions_.are_being_reloaded_);
|
||||
reactions_.are_being_reloaded_ = false;
|
||||
|
||||
auto get_emoji_reaction_queries = std::move(pending_get_emoji_reaction_queries_);
|
||||
pending_get_emoji_reaction_queries_.clear();
|
||||
SCOPE_EXIT {
|
||||
for (auto &query : get_emoji_reaction_queries) {
|
||||
query.second.set_value(get_emoji_reaction_object(query.first));
|
||||
}
|
||||
};
|
||||
|
||||
if (available_reactions_ptr == nullptr) {
|
||||
// failed to get available reactions
|
||||
return;
|
||||
}
|
||||
|
||||
int32 constructor_id = available_reactions_ptr->get_id();
|
||||
if (constructor_id == telegram_api::messages_availableReactionsNotModified::ID) {
|
||||
LOG(INFO) << "Available reactions are not modified";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_availableReactions::ID);
|
||||
auto available_reactions = move_tl_object_as<telegram_api::messages_availableReactions>(available_reactions_ptr);
|
||||
vector<Reaction> new_reactions;
|
||||
for (auto &available_reaction : available_reactions->reactions_) {
|
||||
Reaction reaction;
|
||||
reaction.is_active_ = !available_reaction->inactive_;
|
||||
reaction.is_premium_ = available_reaction->premium_;
|
||||
reaction.reaction_type_ = ReactionType(std::move(available_reaction->reaction_));
|
||||
reaction.title_ = std::move(available_reaction->title_);
|
||||
reaction.static_icon_ =
|
||||
on_get_sticker_document(std::move(available_reaction->static_icon_), StickerFormat::Webp).second;
|
||||
reaction.appear_animation_ =
|
||||
on_get_sticker_document(std::move(available_reaction->appear_animation_), StickerFormat::Tgs).second;
|
||||
reaction.select_animation_ =
|
||||
on_get_sticker_document(std::move(available_reaction->select_animation_), StickerFormat::Tgs).second;
|
||||
reaction.activate_animation_ =
|
||||
on_get_sticker_document(std::move(available_reaction->activate_animation_), StickerFormat::Tgs).second;
|
||||
reaction.effect_animation_ =
|
||||
on_get_sticker_document(std::move(available_reaction->effect_animation_), StickerFormat::Tgs).second;
|
||||
reaction.around_animation_ =
|
||||
on_get_sticker_document(std::move(available_reaction->around_animation_), StickerFormat::Tgs).second;
|
||||
reaction.center_animation_ =
|
||||
on_get_sticker_document(std::move(available_reaction->center_icon_), StickerFormat::Tgs).second;
|
||||
|
||||
if (!reaction.is_valid()) {
|
||||
LOG(ERROR) << "Receive invalid " << reaction.reaction_type_;
|
||||
continue;
|
||||
}
|
||||
if (reaction.is_premium_) {
|
||||
LOG(ERROR) << "Receive premium " << reaction.reaction_type_;
|
||||
continue;
|
||||
}
|
||||
|
||||
new_reactions.push_back(std::move(reaction));
|
||||
}
|
||||
reactions_.reactions_ = std::move(new_reactions);
|
||||
reactions_.hash_ = available_reactions->hash_;
|
||||
|
||||
save_reactions();
|
||||
|
||||
update_active_reactions();
|
||||
}
|
||||
|
||||
void StickersManager::on_get_recent_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr) {
|
||||
CHECK(recent_reactions_.is_being_reloaded_);
|
||||
recent_reactions_.is_being_reloaded_ = false;
|
||||
|
||||
if (reactions_ptr == nullptr) {
|
||||
// failed to get recent reactions
|
||||
return;
|
||||
}
|
||||
|
||||
int32 constructor_id = reactions_ptr->get_id();
|
||||
if (constructor_id == telegram_api::messages_reactionsNotModified::ID) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_reactions::ID);
|
||||
auto reactions = move_tl_object_as<telegram_api::messages_reactions>(reactions_ptr);
|
||||
auto new_reaction_types = transform(
|
||||
reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
if (new_reaction_types == recent_reactions_.reaction_types_ && recent_reactions_.hash_ == reactions->hash_) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
recent_reactions_.reaction_types_ = std::move(new_reaction_types);
|
||||
recent_reactions_.hash_ = reactions->hash_;
|
||||
|
||||
auto expected_hash = get_reaction_types_hash(recent_reactions_.reaction_types_);
|
||||
if (recent_reactions_.hash_ != expected_hash) {
|
||||
LOG(ERROR) << "Receive hash " << recent_reactions_.hash_ << " instead of " << expected_hash << " for reactions "
|
||||
<< recent_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
save_recent_reactions();
|
||||
}
|
||||
|
||||
void StickersManager::on_get_top_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr) {
|
||||
CHECK(top_reactions_.is_being_reloaded_);
|
||||
top_reactions_.is_being_reloaded_ = false;
|
||||
|
||||
if (reactions_ptr == nullptr) {
|
||||
// failed to get top reactions
|
||||
return;
|
||||
}
|
||||
|
||||
int32 constructor_id = reactions_ptr->get_id();
|
||||
if (constructor_id == telegram_api::messages_reactionsNotModified::ID) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_reactions::ID);
|
||||
auto reactions = move_tl_object_as<telegram_api::messages_reactions>(reactions_ptr);
|
||||
auto new_reaction_types = transform(
|
||||
reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
if (new_reaction_types == top_reactions_.reaction_types_ && top_reactions_.hash_ == reactions->hash_) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
top_reactions_.reaction_types_ = std::move(new_reaction_types);
|
||||
top_reactions_.hash_ = reactions->hash_;
|
||||
|
||||
save_top_reactions();
|
||||
}
|
||||
|
||||
void StickersManager::on_get_installed_sticker_sets(StickerType sticker_type,
|
||||
tl_object_ptr<telegram_api::messages_AllStickers> &&stickers_ptr) {
|
||||
auto type = static_cast<int32>(sticker_type);
|
||||
@ -7327,15 +6750,6 @@ void StickersManager::send_update_animated_emoji_clicked(FullMessageId full_mess
|
||||
full_message_id.get_message_id().get(), get_sticker_object(sticker_id, false, true)));
|
||||
}
|
||||
|
||||
bool StickersManager::is_active_reaction(const ReactionType &reaction_type) const {
|
||||
for (auto &supported_reaction : reactions_.reactions_) {
|
||||
if (supported_reaction.reaction_type_ == reaction_type) {
|
||||
return supported_reaction.is_active_;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StickersManager::view_featured_sticker_sets(const vector<StickerSetId> &sticker_set_ids) {
|
||||
for (auto sticker_set_id : sticker_set_ids) {
|
||||
auto set = get_sticker_set(sticker_set_id);
|
||||
@ -10510,9 +9924,6 @@ void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update
|
||||
return;
|
||||
}
|
||||
|
||||
if (!active_reaction_types_.empty()) {
|
||||
updates.push_back(get_update_active_emoji_reactions_object());
|
||||
}
|
||||
for (int32 type = 0; type < MAX_STICKER_TYPE; type++) {
|
||||
if (are_installed_sticker_sets_loaded_[type]) {
|
||||
updates.push_back(get_update_installed_sticker_sets_object(static_cast<StickerType>(type)));
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "td/telegram/FullMessageId.h"
|
||||
#include "td/telegram/PhotoFormat.h"
|
||||
#include "td/telegram/PhotoSize.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/SecretInputMedia.h"
|
||||
#include "td/telegram/SpecialStickerSetType.h"
|
||||
#include "td/telegram/StickerFormat.h"
|
||||
@ -148,8 +147,6 @@ class StickersManager final : public Actor {
|
||||
|
||||
Status on_animated_emoji_message_clicked(string &&emoji, FullMessageId full_message_id, string data);
|
||||
|
||||
bool is_active_reaction(const ReactionType &reaction_type) const;
|
||||
|
||||
void create_sticker(FileId file_id, FileId premium_animation_file_id, string minithumbnail, PhotoSize thumbnail,
|
||||
Dimensions dimensions, tl_object_ptr<telegram_api::documentAttributeSticker> sticker,
|
||||
tl_object_ptr<telegram_api::documentAttributeCustomEmoji> custom_emoji,
|
||||
@ -195,33 +192,10 @@ class StickersManager final : public Actor {
|
||||
|
||||
void view_featured_sticker_sets(const vector<StickerSetId> &sticker_set_ids);
|
||||
|
||||
void get_emoji_reaction(const string &emoji, Promise<td_api::object_ptr<td_api::emojiReaction>> &&promise);
|
||||
|
||||
td_api::object_ptr<td_api::availableReactions> get_sorted_available_reactions(ChatReactions available_reactions,
|
||||
ChatReactions active_reactions,
|
||||
int32 row_size);
|
||||
|
||||
vector<ReactionType> get_recent_reactions();
|
||||
|
||||
vector<ReactionType> get_top_reactions();
|
||||
|
||||
void add_recent_reaction(const ReactionType &reaction_type);
|
||||
|
||||
void clear_recent_reactions(Promise<Unit> &&promise);
|
||||
|
||||
void reload_reactions();
|
||||
|
||||
void reload_recent_reactions();
|
||||
|
||||
void reload_top_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_recent_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr);
|
||||
|
||||
void on_get_top_reactions(tl_object_ptr<telegram_api::messages_Reactions> &&reactions_ptr);
|
||||
std::pair<int64, FileId> on_get_sticker_document(tl_object_ptr<telegram_api::Document> &&document_ptr,
|
||||
StickerFormat expected_format);
|
||||
|
||||
void on_get_installed_sticker_sets(StickerType sticker_type,
|
||||
tl_object_ptr<telegram_api::messages_AllStickers> &&stickers_ptr);
|
||||
@ -463,8 +437,6 @@ class StickersManager final : public Actor {
|
||||
static constexpr int32 EMOJI_KEYWORDS_UPDATE_DELAY = 3600;
|
||||
static constexpr double MIN_ANIMATED_EMOJI_CLICK_DELAY = 0.2;
|
||||
|
||||
static constexpr int32 MAX_RECENT_REACTIONS = 100; // some reasonable value
|
||||
|
||||
class Sticker {
|
||||
public:
|
||||
StickerSetId set_id_;
|
||||
@ -589,55 +561,6 @@ class StickersManager final : public Actor {
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct Reaction {
|
||||
ReactionType reaction_type_;
|
||||
string title_;
|
||||
bool is_active_ = false;
|
||||
bool is_premium_ = false;
|
||||
FileId static_icon_;
|
||||
FileId appear_animation_;
|
||||
FileId select_animation_;
|
||||
FileId activate_animation_;
|
||||
FileId effect_animation_;
|
||||
FileId around_animation_;
|
||||
FileId center_animation_;
|
||||
|
||||
bool is_valid() const {
|
||||
return static_icon_.is_valid() && appear_animation_.is_valid() && select_animation_.is_valid() &&
|
||||
activate_animation_.is_valid() && effect_animation_.is_valid() && !reaction_type_.is_empty();
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct Reactions {
|
||||
int32 hash_ = 0;
|
||||
bool are_being_reloaded_ = false;
|
||||
vector<Reaction> reactions_;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct ReactionList {
|
||||
int64 hash_ = 0;
|
||||
bool is_being_reloaded_ = false;
|
||||
vector<ReactionType> reaction_types_;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
class CustomEmojiLogEvent;
|
||||
class CustomEmojiIdsLogEvent;
|
||||
class StickerListLogEvent;
|
||||
@ -660,8 +583,6 @@ class StickersManager final : public Actor {
|
||||
tl_object_ptr<td_api::stickerSetInfo> get_sticker_set_info_object(StickerSetId sticker_set_id, size_t covers_limit,
|
||||
bool prefer_premium) const;
|
||||
|
||||
td_api::object_ptr<td_api::emojiReaction> get_emoji_reaction_object(const string &emoji) const;
|
||||
|
||||
Sticker *get_sticker(FileId file_id);
|
||||
const Sticker *get_sticker(FileId file_id) const;
|
||||
|
||||
@ -714,9 +635,6 @@ class StickersManager final : public Actor {
|
||||
|
||||
static PhotoFormat get_sticker_set_thumbnail_format(StickerFormat sticker_format);
|
||||
|
||||
std::pair<int64, FileId> on_get_sticker_document(tl_object_ptr<telegram_api::Document> &&document_ptr,
|
||||
StickerFormat expected_format);
|
||||
|
||||
static tl_object_ptr<telegram_api::InputStickerSet> get_input_sticker_set(const StickerSet *set);
|
||||
|
||||
StickerSetId on_get_input_sticker_set(FileId sticker_file_id, tl_object_ptr<telegram_api::InputStickerSet> &&set_ptr,
|
||||
@ -952,26 +870,6 @@ class StickersManager final : public Actor {
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
void save_active_reactions();
|
||||
|
||||
void save_reactions();
|
||||
|
||||
void save_recent_reactions();
|
||||
|
||||
void save_top_reactions();
|
||||
|
||||
void load_active_reactions();
|
||||
|
||||
void load_reactions();
|
||||
|
||||
void load_recent_reactions();
|
||||
|
||||
void load_top_reactions();
|
||||
|
||||
void update_active_reactions();
|
||||
|
||||
td_api::object_ptr<td_api::updateActiveEmojiReactions> get_update_active_emoji_reactions_object() const;
|
||||
|
||||
SpecialStickerSet &add_special_sticker_set(const SpecialStickerSetType &type);
|
||||
|
||||
static void init_special_sticker_set(SpecialStickerSet &sticker_set, int64 sticker_set_id, int64 access_hash,
|
||||
@ -1161,8 +1059,6 @@ class StickersManager final : public Actor {
|
||||
vector<Promise<Unit>> pending_get_default_statuses_queries_;
|
||||
vector<Promise<Unit>> pending_get_default_topic_icons_queries_;
|
||||
|
||||
vector<std::pair<string, Promise<td_api::object_ptr<td_api::emojiReaction>>>> pending_get_emoji_reaction_queries_;
|
||||
|
||||
double next_click_animated_emoji_message_time_ = 0;
|
||||
double next_update_animated_emoji_clicked_time_ = 0;
|
||||
vector<PendingGetAnimatedEmojiClickSticker> pending_get_animated_emoji_click_stickers_;
|
||||
@ -1183,16 +1079,6 @@ class StickersManager final : public Actor {
|
||||
|
||||
FlatHashMap<FileId, std::pair<UserId, Promise<Unit>>, FileIdHash> being_uploaded_files_;
|
||||
|
||||
Reactions reactions_;
|
||||
vector<ReactionType> active_reaction_types_;
|
||||
|
||||
ReactionList recent_reactions_;
|
||||
ReactionList top_reactions_;
|
||||
|
||||
bool are_reactions_loaded_from_database_ = false;
|
||||
bool are_recent_reactions_loaded_from_database_ = false;
|
||||
bool are_top_reactions_loaded_from_database_ = false;
|
||||
|
||||
FlatHashMap<string, vector<string>> emoji_language_codes_;
|
||||
FlatHashMap<string, int32> emoji_language_code_versions_;
|
||||
FlatHashMap<string, double> emoji_language_code_last_difference_times_;
|
||||
|
@ -11,11 +11,8 @@
|
||||
#include "td/telegram/files/FileId.hpp"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/PhotoSize.hpp"
|
||||
#include "td/telegram/ReactionType.hpp"
|
||||
#include "td/telegram/StickerFormat.h"
|
||||
#include "td/telegram/StickerMaskPosition.hpp"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
|
||||
#include "td/utils/emoji.h"
|
||||
#include "td/utils/logging.h"
|
||||
@ -466,106 +463,4 @@ void StickersManager::parse_sticker_set_id(StickerSetId &sticker_set_id, ParserT
|
||||
add_sticker_set(sticker_set_id, sticker_set_access_hash);
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void StickersManager::Reaction::store(StorerT &storer) const {
|
||||
StickersManager *stickers_manager = storer.context()->td().get_actor_unsafe()->stickers_manager_.get();
|
||||
bool has_around_animation = !around_animation_.empty();
|
||||
bool has_center_animation = !center_animation_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(is_active_);
|
||||
STORE_FLAG(has_around_animation);
|
||||
STORE_FLAG(has_center_animation);
|
||||
STORE_FLAG(is_premium_);
|
||||
END_STORE_FLAGS();
|
||||
td::store(reaction_type_, storer);
|
||||
td::store(title_, storer);
|
||||
stickers_manager->store_sticker(static_icon_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(appear_animation_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(select_animation_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(activate_animation_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(effect_animation_, false, storer, "Reaction");
|
||||
if (has_around_animation) {
|
||||
stickers_manager->store_sticker(around_animation_, false, storer, "Reaction");
|
||||
}
|
||||
if (has_center_animation) {
|
||||
stickers_manager->store_sticker(center_animation_, false, storer, "Reaction");
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void StickersManager::Reaction::parse(ParserT &parser) {
|
||||
StickersManager *stickers_manager = parser.context()->td().get_actor_unsafe()->stickers_manager_.get();
|
||||
bool has_around_animation;
|
||||
bool has_center_animation;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(is_active_);
|
||||
PARSE_FLAG(has_around_animation);
|
||||
PARSE_FLAG(has_center_animation);
|
||||
PARSE_FLAG(is_premium_);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(reaction_type_, parser);
|
||||
td::parse(title_, parser);
|
||||
static_icon_ = stickers_manager->parse_sticker(false, parser);
|
||||
appear_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
select_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
activate_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
effect_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
if (has_around_animation) {
|
||||
around_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
}
|
||||
if (has_center_animation) {
|
||||
center_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
}
|
||||
|
||||
is_premium_ = false;
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void StickersManager::Reactions::store(StorerT &storer) const {
|
||||
bool has_reactions = !reactions_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_reactions);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::store(reactions_, storer);
|
||||
td::store(hash_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void StickersManager::Reactions::parse(ParserT &parser) {
|
||||
bool has_reactions;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_reactions);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::parse(reactions_, parser);
|
||||
td::parse(hash_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void StickersManager::ReactionList::store(StorerT &storer) const {
|
||||
bool has_reaction_types = !reaction_types_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_reaction_types);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reaction_types) {
|
||||
td::store(reaction_types_, storer);
|
||||
td::store(hash_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void StickersManager::ReactionList::parse(ParserT &parser) {
|
||||
bool has_reaction_types;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_reaction_types);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reaction_types) {
|
||||
td::parse(reaction_types_, parser);
|
||||
td::parse(hash_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -107,6 +107,7 @@
|
||||
#include "td/telegram/Premium.h"
|
||||
#include "td/telegram/PrivacyManager.h"
|
||||
#include "td/telegram/PublicDialogType.h"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/ReportReason.h"
|
||||
#include "td/telegram/RequestActor.h"
|
||||
@ -3243,6 +3244,8 @@ void Td::dec_actor_refcnt() {
|
||||
LOG(DEBUG) << "PollManager was cleared" << timer;
|
||||
privacy_manager_.reset();
|
||||
LOG(DEBUG) << "PrivacyManager was cleared" << timer;
|
||||
reaction_manager_.reset();
|
||||
LOG(DEBUG) << "ReactionManager was cleared" << timer;
|
||||
sponsored_message_manager_.reset();
|
||||
LOG(DEBUG) << "SponsoredMessageManager was cleared" << timer;
|
||||
stickers_manager_.reset();
|
||||
@ -3445,6 +3448,8 @@ void Td::clear() {
|
||||
LOG(DEBUG) << "PollManager actor was cleared" << timer;
|
||||
privacy_manager_actor_.reset();
|
||||
LOG(DEBUG) << "PrivacyManager actor was cleared" << timer;
|
||||
reaction_manager_actor_.reset();
|
||||
LOG(DEBUG) << "ReactionManager actor was cleared" << timer;
|
||||
sponsored_message_manager_actor_.reset();
|
||||
LOG(DEBUG) << "SponsoredMessageManager actor was cleared" << timer;
|
||||
stickers_manager_actor_.reset();
|
||||
@ -3932,6 +3937,9 @@ void Td::init_managers() {
|
||||
poll_manager_actor_ = register_actor("PollManager", poll_manager_.get());
|
||||
privacy_manager_ = make_unique<PrivacyManager>(this, create_reference());
|
||||
privacy_manager_actor_ = register_actor("PrivacyManager", privacy_manager_.get());
|
||||
reaction_manager_ = make_unique<ReactionManager>(this, create_reference());
|
||||
reaction_manager_actor_ = register_actor("ReactionManager", reaction_manager_.get());
|
||||
G()->set_reaction_manager(reaction_manager_actor_.get());
|
||||
sponsored_message_manager_ = make_unique<SponsoredMessageManager>(this, create_reference());
|
||||
sponsored_message_manager_actor_ = register_actor("SponsoredMessageManager", sponsored_message_manager_.get());
|
||||
G()->set_sponsored_message_manager(sponsored_message_manager_actor_.get());
|
||||
@ -4306,6 +4314,8 @@ void Td::on_request(uint64 id, const td_api::getCurrentState &request) {
|
||||
|
||||
stickers_manager_->get_current_state(updates);
|
||||
|
||||
reaction_manager_->get_current_state(updates);
|
||||
|
||||
notification_settings_manager_->get_current_state(updates);
|
||||
|
||||
dialog_filter_manager_->get_current_state(updates);
|
||||
@ -5323,7 +5333,7 @@ void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request)
|
||||
void Td::on_request(uint64 id, const td_api::getEmojiReaction &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
stickers_manager_->get_emoji_reaction(request.emoji_, std::move(promise));
|
||||
reaction_manager_->get_emoji_reaction(request.emoji_, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getCustomEmojiReactionAnimations &request) {
|
||||
@ -5346,7 +5356,7 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque
|
||||
void Td::on_request(uint64 id, const td_api::clearRecentReactions &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
stickers_manager_->clear_recent_reactions(std::move(promise));
|
||||
reaction_manager_->clear_recent_reactions(std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::addMessageReaction &request) {
|
||||
|
@ -71,6 +71,7 @@ class PasswordManager;
|
||||
class PhoneNumberManager;
|
||||
class PollManager;
|
||||
class PrivacyManager;
|
||||
class ReactionManager;
|
||||
class SecureManager;
|
||||
class SecretChatsManager;
|
||||
class SponsoredMessageManager;
|
||||
@ -191,6 +192,8 @@ class Td final : public Actor {
|
||||
ActorOwn<PollManager> poll_manager_actor_;
|
||||
unique_ptr<PrivacyManager> privacy_manager_;
|
||||
ActorOwn<PrivacyManager> privacy_manager_actor_;
|
||||
unique_ptr<ReactionManager> reaction_manager_;
|
||||
ActorOwn<ReactionManager> reaction_manager_actor_;
|
||||
unique_ptr<SponsoredMessageManager> sponsored_message_manager_;
|
||||
ActorOwn<SponsoredMessageManager> sponsored_message_manager_actor_;
|
||||
unique_ptr<StickersManager> stickers_manager_;
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "td/telegram/PollManager.h"
|
||||
#include "td/telegram/PrivacyManager.h"
|
||||
#include "td/telegram/PublicDialogType.h"
|
||||
#include "td/telegram/ReactionManager.h"
|
||||
#include "td/telegram/ScheduledServerMessageId.h"
|
||||
#include "td/telegram/SecretChatId.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
@ -2233,9 +2234,9 @@ void UpdatesManager::try_reload_data() {
|
||||
Auto());
|
||||
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel,
|
||||
Auto());
|
||||
td_->stickers_manager_->reload_reactions();
|
||||
td_->stickers_manager_->reload_recent_reactions();
|
||||
td_->stickers_manager_->reload_top_reactions();
|
||||
td_->reaction_manager_->reload_reactions();
|
||||
td_->reaction_manager_->reload_recent_reactions();
|
||||
td_->reaction_manager_->reload_top_reactions();
|
||||
for (int32 type = 0; type < MAX_STICKER_TYPE; type++) {
|
||||
auto sticker_type = static_cast<StickerType>(type);
|
||||
td_->stickers_manager_->get_installed_sticker_sets(sticker_type, Auto());
|
||||
@ -3623,7 +3624,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateMessageReaction
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateRecentReactions> update, Promise<Unit> &&promise) {
|
||||
td_->stickers_manager_->reload_recent_reactions();
|
||||
td_->reaction_manager_->reload_recent_reactions();
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user