diff --git a/td/telegram/ReactionManager.cpp b/td/telegram/ReactionManager.cpp index bb76cb9fb..3da2afca9 100644 --- a/td/telegram/ReactionManager.cpp +++ b/td/telegram/ReactionManager.cpp @@ -12,6 +12,7 @@ #include "td/telegram/Global.h" #include "td/telegram/logevent/LogEvent.h" #include "td/telegram/MessagesManager.h" +#include "td/telegram/misc.h" #include "td/telegram/OptionManager.h" #include "td/telegram/ReactionManager.hpp" #include "td/telegram/StickerFormat.h" @@ -307,9 +308,22 @@ void ReactionManager::SavedReactionTags::update_saved_messages_tags(const vector } if (is_changed) { std::sort(tags_.begin(), tags_.end()); + hash_ = calc_hash(); } } +int64 ReactionManager::SavedReactionTags::calc_hash() const { + vector numbers; + for (const auto &tag : tags_) { + numbers.push_back(tag.reaction_type_.get_hash()); + if (!tag.title_.empty()) { + numbers.push_back(get_md5_string_hash(tag.title_)); + } + numbers.push_back(tag.count_); + } + return get_vector_hash(numbers); +} + ReactionManager::ReactionManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } @@ -859,6 +873,9 @@ void ReactionManager::on_get_saved_messages_tags( tags_.tags_ = std::move(saved_reaction_tags); need_send_update = true; } + if (tags_.hash_ != tags_.calc_hash()) { + LOG(ERROR) << "Receive unexpected Saved Messages tag hash"; + } tags_.is_inited_ = true; break; } diff --git a/td/telegram/ReactionManager.h b/td/telegram/ReactionManager.h index 55d723d75..9bf60d959 100644 --- a/td/telegram/ReactionManager.h +++ b/td/telegram/ReactionManager.h @@ -163,6 +163,8 @@ class ReactionManager final : public Actor { void update_saved_messages_tags(const vector &old_tags, const vector &new_tags, bool &is_changed, bool &need_reload_title); + + int64 calc_hash() const; }; td_api::object_ptr get_emoji_reaction_object(const string &emoji) const; diff --git a/td/telegram/ReactionType.cpp b/td/telegram/ReactionType.cpp index feca56662..d851985fe 100644 --- a/td/telegram/ReactionType.cpp +++ b/td/telegram/ReactionType.cpp @@ -134,6 +134,14 @@ td_api::object_ptr ReactionType::get_update_d return td_api::make_object(get_reaction_type_object()); } +uint64 ReactionType::get_hash() const { + if (is_custom_reaction()) { + return static_cast(get_custom_emoji_id(reaction_)); + } else { + return get_md5_string_hash(remove_emoji_selectors(reaction_)); + } +} + bool ReactionType::is_custom_reaction() const { return reaction_[0] == '#'; } diff --git a/td/telegram/ReactionType.h b/td/telegram/ReactionType.h index 2173cf6b7..0bc0adc9c 100644 --- a/td/telegram/ReactionType.h +++ b/td/telegram/ReactionType.h @@ -55,6 +55,8 @@ class ReactionType { td_api::object_ptr get_update_default_reaction_type() const; + uint64 get_hash() const; + bool is_custom_reaction() const; bool is_active_reaction(const FlatHashMap &active_reaction_pos) const; diff --git a/td/telegram/misc.cpp b/td/telegram/misc.cpp index 6143b9f67..7021e629b 100644 --- a/td/telegram/misc.cpp +++ b/td/telegram/misc.cpp @@ -8,6 +8,7 @@ #include "td/utils/algorithm.h" #include "td/utils/common.h" +#include "td/utils/crypto.h" #include "td/utils/Hints.h" #include "td/utils/misc.h" #include "td/utils/Slice.h" @@ -285,6 +286,16 @@ bool is_allowed_username(Slice username) { return true; } +uint64 get_md5_string_hash(const string &str) { + unsigned char hash[16]; + md5(str, {hash, sizeof(hash)}); + uint64 result = 0; + for (int i = 0; i <= 7; i++) { + result += static_cast(hash[i]) << (56 - 8 * i); + } + return result; +} + int64 get_vector_hash(const vector &numbers) { uint64 acc = 0; for (auto number : numbers) { diff --git a/td/telegram/misc.h b/td/telegram/misc.h index 35790e456..bced1fd60 100644 --- a/td/telegram/misc.h +++ b/td/telegram/misc.h @@ -39,6 +39,9 @@ bool is_valid_username(Slice username); // checks whether a string can be set as a username bool is_allowed_username(Slice username); +// calculates truncated MD5 hash of a string +uint64 get_md5_string_hash(const string &str) TD_WARN_UNUSED_RESULT; + // calculates hash of list of uint64 int64 get_vector_hash(const vector &numbers) TD_WARN_UNUSED_RESULT;