Add messageAnimatedEmoji.

This commit is contained in:
levlam 2021-10-05 16:12:04 +03:00
parent 77158cd7a5
commit ffe03ecb10
5 changed files with 95 additions and 18 deletions

View File

@ -1707,6 +1707,9 @@ messageVenue venue:venue = MessageContent;
//@description A message with a user contact @contact The contact description
messageContact contact:contact = MessageContent;
//@description A message with an animated emoji @sticker The animated sticker with the emoji animation @emoji The corresponding emoji
messageAnimatedEmoji sticker:sticker emoji:string = MessageContent;
//@description A dice message. The dice value is randomly generated by the server
//@initial_state The animated stickers with the initial dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known
//@final_state The animated stickers with the final dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known

View File

@ -1360,6 +1360,7 @@ void StickersManager::load_special_sticker_set_by_type(const SpecialStickerSetTy
}
void StickersManager::load_special_sticker_set(SpecialStickerSet &sticker_set) {
CHECK(!td_->auth_manager_->is_bot());
if (sticker_set.is_being_loaded_) {
return;
}
@ -1407,23 +1408,17 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t
CHECK(sticker_set->was_loaded);
if (type.type_ == SpecialStickerSetType::animated_emoji()) {
for (auto sticker_it : sticker_set->sticker_emojis_map_) {
for (auto &emoji : sticker_it.second) {
auto it = emoji_messages_.find(emoji);
if (it == emoji_messages_.end()) {
continue;
}
vector<FullMessageId> full_message_ids;
for (auto full_message_id : it->second) {
vector<FullMessageId> full_message_ids;
for (const auto &it : emoji_messages_) {
if (get_animated_emoji_sticker(sticker_set, it.first).first.is_valid()) {
for (auto full_message_id : it.second) {
full_message_ids.push_back(full_message_id);
}
CHECK(!full_message_ids.empty());
for (auto full_message_id : full_message_ids) {
td_->messages_manager_->on_external_update_message_content(full_message_id);
}
}
}
for (auto full_message_id : full_message_ids) {
td_->messages_manager_->on_external_update_message_content(full_message_id);
}
return;
}
@ -1916,8 +1911,64 @@ tl_object_ptr<td_api::stickerSetInfo> StickersManager::get_sticker_set_info_obje
std::move(stickers));
}
std::pair<FileId, int> StickersManager::get_animated_emoji_sticker(const StickerSet *sticker_set, const string &emoji) {
auto emoji_without_modifiers = remove_emoji_modifiers(emoji).str();
auto it = sticker_set->emoji_stickers_map_.find(emoji_without_modifiers);
if (it == sticker_set->emoji_stickers_map_.end()) {
return {};
}
// trying to find full emoji match
for (const auto &sticker_id : it->second) {
auto emoji_it = sticker_set->sticker_emojis_map_.find(sticker_id);
CHECK(emoji_it != sticker_set->sticker_emojis_map_.end());
if (td::contains(emoji_it->second, emoji)) {
return {sticker_id, 0};
}
}
// trying to find match without Fitzpatrick modifiers
int modifier_id = get_fitzpatrick_modifier(emoji);
if (modifier_id > 0) {
for (const auto &sticker_id : it->second) {
auto emoji_it = sticker_set->sticker_emojis_map_.find(sticker_id);
CHECK(emoji_it != sticker_set->sticker_emojis_map_.end());
if (td::contains(emoji_it->second, Slice(emoji).remove_suffix(4))) {
return {sticker_id, modifier_id};
}
}
}
// there is no match
return {};
}
std::pair<FileId, int> StickersManager::get_animated_emoji_sticker(const string &emoji) {
if (td_->auth_manager_->is_bot()) {
return {};
}
auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_emoji());
if (!special_sticker_set.id_.is_valid()) {
load_special_sticker_set(special_sticker_set);
return {};
}
auto sticker_set = get_sticker_set(special_sticker_set.id_);
CHECK(sticker_set != nullptr);
if (!sticker_set->was_loaded) {
load_special_sticker_set(special_sticker_set);
return {};
}
return get_animated_emoji_sticker(sticker_set, emoji);
}
td_api::object_ptr<td_api::MessageContent> StickersManager::get_message_content_animated_emoji_object(
const string &emoji) {
auto animated_sticker = get_animated_emoji_sticker(emoji);
if (animated_sticker.first.is_valid()) {
return td_api::make_object<td_api::messageAnimatedEmoji>(get_sticker_object(animated_sticker.first), emoji);
}
return td_api::make_object<td_api::messageText>(
td_api::make_object<td_api::formattedText>(emoji, std::vector<td_api::object_ptr<td_api::textEntity>>()),
nullptr);
@ -4139,7 +4190,7 @@ int StickersManager::get_emoji_number(Slice emoji) {
return emoji[0] - '0';
}
vector<FileId> StickersManager::get_animated_emoji_stickers(const StickerSet *sticker_set, Slice emoji) const {
vector<FileId> StickersManager::get_animated_emoji_click_stickers(const StickerSet *sticker_set, Slice emoji) const {
vector<FileId> result;
for (auto sticker_id : sticker_set->sticker_ids) {
auto s = get_sticker(sticker_id);
@ -4151,7 +4202,7 @@ vector<FileId> StickersManager::get_animated_emoji_stickers(const StickerSet *st
if (result.empty()) {
const static vector<string> heart_emojis{"💛", "💙", "💚", "💜", "🧡", "🖤", "🤎", "🤍"};
if (td::contains(heart_emojis, emoji)) {
return get_animated_emoji_stickers(sticker_set, Slice(""));
return get_animated_emoji_click_stickers(sticker_set, Slice(""));
}
}
return result;
@ -4172,7 +4223,7 @@ void StickersManager::choose_animated_emoji_click_sticker(const StickerSet *stic
return promise.set_value(nullptr);
}
auto all_sticker_ids = get_animated_emoji_stickers(sticker_set, message_text);
auto all_sticker_ids = get_animated_emoji_click_stickers(sticker_set, message_text);
vector<std::pair<int, FileId>> found_stickers;
for (auto sticker_id : all_sticker_ids) {
auto it = sticker_set->sticker_emojis_map_.find(sticker_id);
@ -4322,6 +4373,10 @@ bool StickersManager::is_sent_animated_emoji_click(DialogId dialog_id, Slice emo
}
Status StickersManager::on_animated_emoji_message_clicked(Slice emoji, FullMessageId full_message_id, string data) {
if (td_->auth_manager_->is_bot()) {
return Status::OK();
}
TRY_RESULT(value, json_decode(data));
if (value.type() != JsonValue::Type::Object) {
return Status::Error("Expected an object");
@ -4402,7 +4457,7 @@ void StickersManager::schedule_update_animated_emoji_clicked(const StickerSet *s
return;
}
auto all_sticker_ids = get_animated_emoji_stickers(sticker_set, emoji);
auto all_sticker_ids = get_animated_emoji_click_stickers(sticker_set, emoji);
std::unordered_map<int, FileId> sticker_ids;
for (auto sticker_id : all_sticker_ids) {
auto it = sticker_set->sticker_emojis_map_.find(sticker_id);

View File

@ -603,7 +603,11 @@ class StickersManager final : public Actor {
static int get_emoji_number(Slice emoji);
vector<FileId> get_animated_emoji_stickers(const StickerSet *sticker_set, Slice emoji) const;
static std::pair<FileId, int> get_animated_emoji_sticker(const StickerSet *sticker_set, const string &emoji);
std::pair<FileId, int> get_animated_emoji_sticker(const string &emoji);
vector<FileId> get_animated_emoji_click_stickers(const StickerSet *sticker_set, Slice emoji) const;
void choose_animated_emoji_click_sticker(const StickerSet *sticker_set, Slice message_text,
FullMessageId full_message_id, double start_time,

View File

@ -839,6 +839,18 @@ bool is_emoji(Slice str) {
return emojis.count(str) != 0;
}
int get_fitzpatrick_modifier(Slice emoji) {
if (emoji.size() < 4 || emoji[emoji.size() - 4] != '\xF0' || emoji[emoji.size() - 3] != '\x9F' ||
emoji[emoji.size() - 2] != '\x8F') {
return 0;
}
auto c = static_cast<unsigned char>(emoji.back());
if (c < 0xBB || c > 0xBF) {
return 0;
}
return (c - 0xBB) + 2;
}
Slice remove_emoji_modifiers(Slice emoji) {
static const Slice modifiers[] = {u8"\uFE0E" /* variation selector-15 */,
u8"\uFE0F" /* variation selector-16 */,

View File

@ -14,6 +14,9 @@ namespace td {
// checks whether the string is an emoji; variation selectors are ignored
bool is_emoji(Slice str);
// checks whether emoji ends on a Fitzpatrick modifier and returns it's number or 0
int get_fitzpatrick_modifier(Slice emoji);
// removes all emoji modifiers from the end of the string
Slice remove_emoji_modifiers(Slice emoji);