Support search by multiple emojis in getStickers.

This commit is contained in:
levlam 2023-01-24 15:15:37 +03:00
parent e5b557f55c
commit f51bea81e1
3 changed files with 57 additions and 53 deletions

View File

@ -7209,16 +7209,16 @@ sharePhoneNumber user_id:int53 = Ok;
getUserProfilePhotos user_id:int53 offset:int32 limit:int32 = ChatPhotos;
//@description Returns stickers from the installed sticker sets that correspond to a given emoji or can be found by sticker-specific keywords. If the query is non-empty, then favorite, recently used or trending stickers may also be returned
//@description Returns stickers from the installed sticker sets that correspond to any of the given emoji or can be found by sticker-specific keywords. If the query is non-empty, then favorite, recently used or trending stickers may also be returned
//@sticker_type Type of the stickers to return
//@query Search query; an emoji or a keyword prefix. If empty, returns all known installed stickers
//@query Search query; a space-separated list of emoji or a keyword prefix. If empty, returns all known installed stickers
//@limit The maximum number of stickers to be returned
//@chat_id Chat identifier for which to return stickers. Available custom emoji stickers may be different for different chats
getStickers sticker_type:StickerType query:string limit:int32 chat_id:int53 = Stickers;
//@description Searches for stickers from public sticker sets that correspond to one of the given emoji
//@description Searches for stickers from public sticker sets that correspond to any of the given emoji
//@sticker_type Type of the stickers to return
//@emojis Concatenated list of emoji to search for; must be non-empty
//@emojis Space-separated list of emoji to search for; must be non-empty
//@limit The maximum number of stickers to be returned; 0-100
searchStickers sticker_type:StickerType emojis:string limit:int32 = Stickers;

View File

@ -4351,41 +4351,38 @@ const std::map<string, vector<FileId>> &StickersManager::get_sticker_set_keyword
return sticker_set->keyword_stickers_map_;
}
void StickersManager::find_sticker_set_stickers(const StickerSet *sticker_set, const string &query,
const string &prepared_query, vector<FileId> &result) {
auto it = sticker_set->emoji_stickers_map_.find(query);
if (it != sticker_set->emoji_stickers_map_.end()) {
LOG(INFO) << "Add " << it->second << " stickers from " << sticker_set->id_;
append(result, it->second);
void StickersManager::find_sticker_set_stickers(const StickerSet *sticker_set, const vector<string> &emojis,
const string &query, vector<FileId> &result) {
CHECK(sticker_set != nullptr);
FlatHashSet<FileId, FileIdHash> found_sticker_ids;
for (auto &emoji : emojis) {
auto it = sticker_set->emoji_stickers_map_.find(emoji);
if (it != sticker_set->emoji_stickers_map_.end()) {
found_sticker_ids.insert(it->second.begin(), it->second.end());
}
}
if (!query.empty()) {
const auto &keywords_map = get_sticker_set_keywords(sticker_set);
for (auto it = keywords_map.lower_bound(query); it != keywords_map.end() && begins_with(it->first, query); ++it) {
found_sticker_ids.insert(it->second.begin(), it->second.end());
}
}
if (!prepared_query.empty()) {
const auto &keywords_map = get_sticker_set_keywords(sticker_set);
auto keywords_it = keywords_map.lower_bound(prepared_query);
if (keywords_it != keywords_map.end() && begins_with(keywords_it->first, prepared_query)) {
FlatHashSet<FileId, FileIdHash> found_sticker_ids;
if (it != sticker_set->emoji_stickers_map_.end()) {
for (auto file_id : it->second) {
found_sticker_ids.insert(file_id);
}
if (!found_sticker_ids.empty()) {
for (auto sticker_id : sticker_set->sticker_ids_) {
if (found_sticker_ids.count(sticker_id) != 0) {
LOG(INFO) << "Add " << sticker_id << " sticker from " << sticker_set->id_;
result.push_back(sticker_id);
}
do {
for (auto file_id : keywords_it->second) {
if (found_sticker_ids.insert(file_id).second) {
result.push_back(file_id);
}
}
++keywords_it;
} while (keywords_it != keywords_map.end() && begins_with(keywords_it->first, prepared_query));
}
}
}
bool StickersManager::can_find_sticker_by_query(FileId sticker_id, const string &query,
const string &prepared_query) const {
bool StickersManager::can_find_sticker_by_query(FileId sticker_id, const vector<string> &emojis,
const string &query) const {
const Sticker *s = get_sticker(sticker_id);
CHECK(s != nullptr);
if (remove_emoji_modifiers(s->alt_) == query) {
if (td::contains(emojis, remove_emoji_modifiers(s->alt_))) {
// fast path
return true;
}
@ -4393,23 +4390,21 @@ bool StickersManager::can_find_sticker_by_query(FileId sticker_id, const string
if (sticker_set == nullptr || !sticker_set->was_loaded_) {
return false;
}
auto it = sticker_set->emoji_stickers_map_.find(query);
if (it != sticker_set->emoji_stickers_map_.end()) {
if (td::contains(it->second, sticker_id)) {
return true;
for (auto &emoji : emojis) {
auto it = sticker_set->emoji_stickers_map_.find(emoji);
if (it != sticker_set->emoji_stickers_map_.end()) {
if (td::contains(it->second, sticker_id)) {
return true;
}
}
}
if (!prepared_query.empty()) {
if (!query.empty()) {
const auto &keywords_map = get_sticker_set_keywords(sticker_set);
auto keywords_it = keywords_map.lower_bound(prepared_query);
if (keywords_it != keywords_map.end() && begins_with(keywords_it->first, prepared_query)) {
do {
if (td::contains(keywords_it->second, sticker_id)) {
return true;
}
++keywords_it;
} while (keywords_it != keywords_map.end() && begins_with(keywords_it->first, prepared_query));
for (auto it = keywords_map.lower_bound(query); it != keywords_map.end() && begins_with(it->first, query); ++it) {
if (td::contains(it->second, sticker_id)) {
return true;
}
}
}
@ -4489,8 +4484,17 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
return {};
}
bool return_all_installed = query.empty();
remove_emoji_modifiers_in_place(query);
if (!query.empty()) {
auto emojis = full_split(query, ' ');
for (auto &emoji : emojis) {
if (!is_emoji(emoji)) {
emojis.clear();
break;
}
}
if (!return_all_installed) {
if (sticker_type == StickerType::Regular) {
if (!are_recent_stickers_loaded_[0 /*is_attached*/]) {
load_recent_stickers(false, std::move(promise));
@ -4509,7 +4513,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
}
vector<StickerSetId> examined_sticker_set_ids = installed_sticker_set_ids_[type];
if (!query.empty() && sticker_type == StickerType::CustomEmoji) {
if (!return_all_installed && sticker_type == StickerType::CustomEmoji) {
append(examined_sticker_set_ids, featured_sticker_set_ids_[type]);
}
@ -4528,7 +4532,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
}
vector<FileId> prepend_sticker_ids;
if (!query.empty() && sticker_type == StickerType::Regular) {
if (!return_all_installed && sticker_type == StickerType::Regular) {
prepend_sticker_ids.reserve(favorite_sticker_ids_.size() + recent_sticker_ids_[0].size());
append(prepend_sticker_ids, recent_sticker_ids_[0]);
for (auto sticker_id : favorite_sticker_ids_) {
@ -4602,7 +4606,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
vector<FileId> result;
auto limit_size_t = static_cast<size_t>(limit);
if (query.empty()) {
if (return_all_installed) {
for (const auto &sticker_set_id : examined_sticker_set_ids) {
const StickerSet *sticker_set = get_sticker_set(sticker_set_id);
if (sticker_set == nullptr || !sticker_set->was_loaded_) {
@ -4617,7 +4621,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
}
} else {
auto prepared_query = utf8_prepare_search_string(query);
LOG(INFO) << "Search stickers by " << query << " and keyword " << prepared_query;
LOG(INFO) << "Search stickers by " << emojis << " and keyword " << prepared_query;
vector<const StickerSet *> examined_sticker_sets;
for (const auto &sticker_set_id : examined_sticker_set_ids) {
const StickerSet *sticker_set = get_sticker_set(sticker_set_id);
@ -4640,7 +4644,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
return is_sticker_format_animated(lhs->sticker_format_) && !is_sticker_format_animated(rhs->sticker_format_);
});
for (auto sticker_set : examined_sticker_sets) {
find_sticker_set_stickers(sticker_set, query, prepared_query, result);
find_sticker_set_stickers(sticker_set, emojis, prepared_query, result);
}
vector<FileId> sorted;
@ -4661,7 +4665,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
<< (it - result.begin());
*it = FileId();
is_good = true;
} else if (can_find_sticker_by_query(sticker_id, query, prepared_query)) {
} else if (can_find_sticker_by_query(sticker_id, emojis, prepared_query)) {
LOG(INFO) << "Found prepend sticker " << sticker_id;
is_good = true;
}

View File

@ -952,10 +952,10 @@ class StickersManager final : public Actor {
static const std::map<string, vector<FileId>> &get_sticker_set_keywords(const StickerSet *sticker_set);
static void find_sticker_set_stickers(const StickerSet *sticker_set, const string &query,
const string &prepared_query, vector<FileId> &result);
static void find_sticker_set_stickers(const StickerSet *sticker_set, const vector<string> &emojis,
const string &query, vector<FileId> &result);
bool can_find_sticker_by_query(FileId sticker_id, const string &query, const string &prepared_query) const;
bool can_find_sticker_by_query(FileId sticker_id, const vector<string> &emojis, const string &query) const;
static string get_emoji_language_code_version_database_key(const string &language_code);