Support search by keywords in getStickers.

This commit is contained in:
levlam 2022-09-27 20:52:47 +03:00
parent 75a021e836
commit e39bd45086
4 changed files with 69 additions and 30 deletions

View File

@ -6050,12 +6050,12 @@ 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. If the emoji is non-empty, then favorite, recently used or trending stickers may also be returned
//@sticker_type Type of the sticker sets to return
//@emoji String representation of emoji. If empty, returns all known installed stickers
//@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
//@sticker_type Type of the stickers to return
//@query Search query; an 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 may be different for different chats
getStickers sticker_type:StickerType emoji:string limit:int32 chat_id:int53 = Stickers;
//@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 a given emoji @emoji String representation of emoji; must be non-empty @limit The maximum number of stickers to be returned; 0-100
searchStickers emoji:string limit:int32 = Stickers;

View File

@ -4199,15 +4199,37 @@ const std::map<string, vector<FileId>> &StickersManager::get_sticker_set_keyword
}
void StickersManager::find_sticker_set_stickers(const StickerSet *sticker_set, const string &query,
vector<FileId> &result) {
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);
}
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);
}
}
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_found_sticker_by_query(FileId sticker_id, const string &query) const {
bool StickersManager::can_found_sticker_by_query(FileId sticker_id, const string &query,
const string &prepared_query) const {
const Sticker *s = get_sticker(sticker_id);
CHECK(s != nullptr);
if (remove_emoji_modifiers(s->alt_) == query) {
@ -4218,12 +4240,26 @@ bool StickersManager::can_found_sticker_by_query(FileId sticker_id, const string
if (sticker_set == nullptr || !sticker_set->was_loaded_) {
return false;
}
auto map_it = sticker_set->emoji_stickers_map_.find(query);
if (map_it != sticker_set->emoji_stickers_map_.end()) {
if (td::contains(map_it->second, sticker_id)) {
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;
}
}
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)) {
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));
}
}
return false;
}
@ -4271,7 +4307,7 @@ std::pair<vector<FileId>, vector<FileId>> StickersManager::split_stickers_by_pre
return {std::move(regular_sticker_ids), std::move(premium_sticker_ids)};
}
vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string emoji, int32 limit, DialogId dialog_id,
vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string query, int32 limit, DialogId dialog_id,
bool force, Promise<Unit> &&promise) {
if (G()->close_flag()) {
promise.set_error(Global::request_aborted_error());
@ -4288,20 +4324,20 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
CHECK(force == false);
load_installed_sticker_sets(
sticker_type,
PromiseCreator::lambda([actor_id = actor_id(this), sticker_type, emoji = std::move(emoji), limit, dialog_id,
PromiseCreator::lambda([actor_id = actor_id(this), sticker_type, query = std::move(query), limit, dialog_id,
force, promise = std::move(promise)](Result<Unit> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
send_closure(actor_id, &StickersManager::get_stickers, sticker_type, std::move(emoji), limit, dialog_id,
send_closure(actor_id, &StickersManager::get_stickers, sticker_type, std::move(query), limit, dialog_id,
force, std::move(promise));
}
}));
return {};
}
remove_emoji_modifiers_in_place(emoji);
if (!emoji.empty()) {
remove_emoji_modifiers_in_place(query);
if (!query.empty()) {
if (sticker_type == StickerType::Regular) {
if (!are_recent_stickers_loaded_[0 /*is_attached*/]) {
load_recent_stickers(false, std::move(promise));
@ -4320,7 +4356,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
}
vector<StickerSetId> examined_sticker_set_ids = installed_sticker_set_ids_[type];
if (!emoji.empty() && sticker_type == StickerType::CustomEmoji) {
if (!query.empty() && sticker_type == StickerType::CustomEmoji) {
append(examined_sticker_set_ids, featured_sticker_set_ids_[type]);
}
@ -4339,7 +4375,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
}
vector<FileId> prepend_sticker_ids;
if (!emoji.empty() && sticker_type == StickerType::Regular) {
if (!query.empty() && 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_) {
@ -4413,7 +4449,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
vector<FileId> result;
auto limit_size_t = static_cast<size_t>(limit);
if (emoji.empty()) {
if (query.empty()) {
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_) {
@ -4427,6 +4463,8 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
}
}
} else {
auto prepared_query = utf8_prepare_search_string(query);
LOG(INFO) << "Search stickers by " << query << " 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);
@ -4449,7 +4487,7 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
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, emoji, result);
find_sticker_set_stickers(sticker_set, query, prepared_query, result);
}
vector<FileId> sorted;
@ -4470,8 +4508,8 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string em
<< (it - result.begin());
*it = FileId();
is_good = true;
} else if (can_found_sticker_by_query(sticker_id, emoji)) {
LOG(INFO) << "Found prepend sticker " << sticker_id << " has matching emoji";
} else if (can_found_sticker_by_query(sticker_id, query, prepared_query)) {
LOG(INFO) << "Found prepend sticker " << sticker_id;
is_good = true;
}

View File

@ -143,7 +143,7 @@ class StickersManager final : public Actor {
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer) const;
vector<FileId> get_stickers(StickerType sticker_type, string emoji, int32 limit, DialogId dialog_id, bool force,
vector<FileId> get_stickers(StickerType sticker_type, string query, int32 limit, DialogId dialog_id, bool force,
Promise<Unit> &&promise);
void search_stickers(string emoji, int32 limit, Promise<td_api::object_ptr<td_api::stickers>> &&promise);
@ -903,9 +903,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, vector<FileId> &result);
static void find_sticker_set_stickers(const StickerSet *sticker_set, const string &query,
const string &prepared_query, vector<FileId> &result);
bool can_found_sticker_by_query(FileId sticker_id, const string &query) const;
bool can_found_sticker_by_query(FileId sticker_id, const string &query, const string &prepared_query) const;
static string get_emoji_language_code_version_database_key(const string &language_code);

View File

@ -1986,14 +1986,14 @@ class GetScopeNotificationSettingsRequest final : public RequestActor<> {
class GetStickersRequest final : public RequestActor<> {
StickerType sticker_type_;
string emoji_;
string query_;
int32 limit_;
DialogId dialog_id_;
vector<FileId> sticker_ids_;
void do_run(Promise<Unit> &&promise) final {
sticker_ids_ = td_->stickers_manager_->get_stickers(sticker_type_, emoji_, limit_, dialog_id_, get_tries() < 2,
sticker_ids_ = td_->stickers_manager_->get_stickers(sticker_type_, query_, limit_, dialog_id_, get_tries() < 2,
std::move(promise));
}
@ -2002,11 +2002,11 @@ class GetStickersRequest final : public RequestActor<> {
}
public:
GetStickersRequest(ActorShared<Td> td, uint64 request_id, StickerType sticker_type, string &&emoji, int32 limit,
GetStickersRequest(ActorShared<Td> td, uint64 request_id, StickerType sticker_type, string &&query, int32 limit,
int64 dialog_id)
: RequestActor(std::move(td), request_id)
, sticker_type_(sticker_type)
, emoji_(std::move(emoji))
, query_(std::move(query))
, limit_(limit)
, dialog_id_(dialog_id) {
set_tries(4);
@ -6887,8 +6887,8 @@ void Td::on_request(uint64 id, td_api::closeSecretChat &request) {
void Td::on_request(uint64 id, td_api::getStickers &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.emoji_);
CREATE_REQUEST(GetStickersRequest, get_sticker_type(request.sticker_type_), std::move(request.emoji_), request.limit_,
CLEAN_INPUT_STRING(request.query_);
CREATE_REQUEST(GetStickersRequest, get_sticker_type(request.sticker_type_), std::move(request.query_), request.limit_,
request.chat_id_);
}