Add td_api::searchEmojis.
GitOrigin-RevId: 01540620ce3e0d7e64cb1ec409774a003cfd42e9
This commit is contained in:
parent
8a2c83cf13
commit
b59abdc9f7
@ -1551,18 +1551,18 @@ userStatusLastMonth = UserStatus;
|
|||||||
//@description Represents a list of stickers @stickers List of stickers
|
//@description Represents a list of stickers @stickers List of stickers
|
||||||
stickers stickers:vector<sticker> = Stickers;
|
stickers stickers:vector<sticker> = Stickers;
|
||||||
|
|
||||||
//@description Represents a list of all emoji corresponding to a sticker in a sticker set. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object @emojis List of emojis
|
//@description Represents a list of emoji @emojis List of emojis
|
||||||
stickerEmojis emojis:vector<string> = StickerEmojis;
|
emojis emojis:vector<string> = Emojis;
|
||||||
|
|
||||||
//@description Represents a sticker set
|
//@description Represents a sticker set
|
||||||
//@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP format; may be null
|
//@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP format with width and height 100; may be null
|
||||||
//@is_installed True, if the sticker set has been installed by the current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
|
//@is_installed True, if the sticker set has been installed by the current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
|
||||||
//@is_official True, if the sticker set is official @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
|
//@is_official True, if the sticker set is official @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
|
||||||
//@stickers List of stickers in this set @emojis A list of emoji corresponding to the stickers in the same order
|
//@stickers List of stickers in this set @emojis A list of emoji corresponding to the stickers in the same order. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object
|
||||||
stickerSet id:int64 title:string name:string thumbnail:photoSize is_installed:Bool is_archived:Bool is_official:Bool is_masks:Bool is_viewed:Bool stickers:vector<sticker> emojis:vector<stickerEmojis> = StickerSet;
|
stickerSet id:int64 title:string name:string thumbnail:photoSize is_installed:Bool is_archived:Bool is_official:Bool is_masks:Bool is_viewed:Bool stickers:vector<sticker> emojis:vector<emojis> = StickerSet;
|
||||||
|
|
||||||
//@description Represents short information about a sticker set
|
//@description Represents short information about a sticker set
|
||||||
//@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP format; may be null
|
//@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP format with width and height 100; may be null
|
||||||
//@is_installed True, if the sticker set has been installed by current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
|
//@is_installed True, if the sticker set has been installed by current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
|
||||||
//@is_official True, if the sticker set is official @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
|
//@is_official True, if the sticker set is official @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
|
||||||
//@size Total number of stickers in the set @covers Contains up to the first 5 stickers from the set, depending on the context. If the client needs more stickers the full set should be requested
|
//@size Total number of stickers in the set @covers Contains up to the first 5 stickers from the set, depending on the context. If the client needs more stickers the full set should be requested
|
||||||
@ -3506,8 +3506,11 @@ addFavoriteSticker sticker:InputFile = Ok;
|
|||||||
//@description Removes a sticker from the list of favorite stickers @sticker Sticker file to delete from the list
|
//@description Removes a sticker from the list of favorite stickers @sticker Sticker file to delete from the list
|
||||||
removeFavoriteSticker sticker:InputFile = Ok;
|
removeFavoriteSticker sticker:InputFile = Ok;
|
||||||
|
|
||||||
//@description Returns emoji corresponding to a sticker @sticker Sticker file identifier
|
//@description Returns emoji corresponding to a sticker. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object @sticker Sticker file identifier
|
||||||
getStickerEmojis sticker:InputFile = StickerEmojis;
|
getStickerEmojis sticker:InputFile = Emojis;
|
||||||
|
|
||||||
|
//@description Searches for emojis by a short text. Supported only if the file database is enabled @text Text to search for @exact_match True, if only emojis, which exactly match text needs to be returned
|
||||||
|
searchEmojis text:string exact_match:Bool = Emojis;
|
||||||
|
|
||||||
|
|
||||||
//@description Returns saved animations
|
//@description Returns saved animations
|
||||||
|
Binary file not shown.
@ -237,6 +237,45 @@ void LanguagePackManager::tear_down() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<string> LanguagePackManager::get_used_language_codes() const {
|
||||||
|
if (language_pack_.empty() || language_code_.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> packs_lock(database_->mutex_);
|
||||||
|
auto pack_it = database_->language_packs_.find(language_pack_);
|
||||||
|
CHECK(pack_it != database_->language_packs_.end());
|
||||||
|
|
||||||
|
LanguageInfo *info = nullptr;
|
||||||
|
LanguagePack *pack = pack_it->second.get();
|
||||||
|
std::lock_guard<std::mutex> languages_lock(pack->mutex_);
|
||||||
|
if (is_custom_language_code(language_code_)) {
|
||||||
|
auto custom_it = pack->custom_language_pack_infos_.find(language_code_);
|
||||||
|
if (custom_it != pack->custom_language_pack_infos_.end()) {
|
||||||
|
info = &custom_it->second;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto &server_info : pack->server_language_pack_infos_) {
|
||||||
|
if (server_info.first == language_code_) {
|
||||||
|
info = &server_info.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK(info != nullptr);
|
||||||
|
|
||||||
|
vector<string> result;
|
||||||
|
if (language_code_.size() <= 2) {
|
||||||
|
result.push_back(language_code_);
|
||||||
|
}
|
||||||
|
if (!info->base_language_code_.empty()) {
|
||||||
|
result.push_back(info->base_language_code_);
|
||||||
|
}
|
||||||
|
if (!info->plural_code_.empty()) {
|
||||||
|
result.push_back(info->plural_code_);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void LanguagePackManager::on_language_pack_changed() {
|
void LanguagePackManager::on_language_pack_changed() {
|
||||||
auto new_language_pack = G()->shared_config().get_option_string("localization_target");
|
auto new_language_pack = G()->shared_config().get_option_string("localization_target");
|
||||||
if (new_language_pack == language_pack_) {
|
if (new_language_pack == language_pack_) {
|
||||||
|
@ -43,6 +43,8 @@ class LanguagePackManager : public NetQueryCallback {
|
|||||||
|
|
||||||
static bool is_custom_language_code(Slice language_code);
|
static bool is_custom_language_code(Slice language_code);
|
||||||
|
|
||||||
|
vector<string> get_used_language_codes() const;
|
||||||
|
|
||||||
void on_language_pack_changed();
|
void on_language_pack_changed();
|
||||||
|
|
||||||
void on_language_code_changed();
|
void on_language_code_changed();
|
||||||
|
@ -25576,6 +25576,7 @@ MessagesManager::Message *MessagesManager::continue_send_message(DialogId dialog
|
|||||||
|
|
||||||
void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||||
for (auto &event : events) {
|
for (auto &event : events) {
|
||||||
|
CHECK(event.id_ != 0);
|
||||||
switch (event.type_) {
|
switch (event.type_) {
|
||||||
case LogEvent::HandlerType::SendMessage: {
|
case LogEvent::HandlerType::SendMessage: {
|
||||||
if (!G()->parameters().use_message_db) {
|
if (!G()->parameters().use_message_db) {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "td/telegram/files/FileType.h"
|
#include "td/telegram/files/FileType.h"
|
||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
#include "td/telegram/logevent/LogEvent.h"
|
#include "td/telegram/logevent/LogEvent.h"
|
||||||
|
#include "td/telegram/LanguagePackManager.h"
|
||||||
#include "td/telegram/MessagesManager.h"
|
#include "td/telegram/MessagesManager.h"
|
||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.h"
|
||||||
#include "td/telegram/net/DcId.h"
|
#include "td/telegram/net/DcId.h"
|
||||||
@ -112,6 +113,59 @@ class SearchStickersQuery : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GetEmojiKeywordsLanguageQuery : public Td::ResultHandler {
|
||||||
|
Promise<vector<string>> promise_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetEmojiKeywordsLanguageQuery(Promise<vector<string>> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(vector<string> &&language_codes) {
|
||||||
|
send_query(G()->net_query_creator().create(
|
||||||
|
create_storer(telegram_api::messages_getEmojiKeywordsLanguages(std::move(language_codes)))));
|
||||||
|
}
|
||||||
|
void on_result(uint64 id, BufferSlice packet) override {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::messages_getEmojiKeywordsLanguages>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result =
|
||||||
|
transform(result_ptr.move_as_ok(), [](auto &&emoji_language) { return std::move(emoji_language->lang_code_); });
|
||||||
|
promise_.set_value(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) override {
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GetEmojiKeywordsQuery : public Td::ResultHandler {
|
||||||
|
Promise<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> promise_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetEmojiKeywordsQuery(Promise<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&promise)
|
||||||
|
: promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(const string &language_code) {
|
||||||
|
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_getEmojiKeywords(language_code))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) override {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::messages_getEmojiKeywords>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(result_ptr.move_as_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) override {
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class GetArchivedStickerSetsQuery : public Td::ResultHandler {
|
class GetArchivedStickerSetsQuery : public Td::ResultHandler {
|
||||||
Promise<Unit> promise_;
|
Promise<Unit> promise_;
|
||||||
int64 offset_sticker_set_id_;
|
int64 offset_sticker_set_id_;
|
||||||
@ -993,7 +1047,7 @@ tl_object_ptr<td_api::stickerSet> StickersManager::get_sticker_set_object(int64
|
|||||||
CHECK(sticker_set->was_loaded);
|
CHECK(sticker_set->was_loaded);
|
||||||
|
|
||||||
std::vector<tl_object_ptr<td_api::sticker>> stickers;
|
std::vector<tl_object_ptr<td_api::sticker>> stickers;
|
||||||
std::vector<tl_object_ptr<td_api::stickerEmojis>> emojis;
|
std::vector<tl_object_ptr<td_api::emojis>> emojis;
|
||||||
for (auto sticker_id : sticker_set->sticker_ids) {
|
for (auto sticker_id : sticker_set->sticker_ids) {
|
||||||
stickers.push_back(get_sticker_object(sticker_id));
|
stickers.push_back(get_sticker_object(sticker_id));
|
||||||
|
|
||||||
@ -1001,7 +1055,7 @@ tl_object_ptr<td_api::stickerSet> StickersManager::get_sticker_set_object(int64
|
|||||||
if (it == sticker_set->sticker_emojis_map_.end()) {
|
if (it == sticker_set->sticker_emojis_map_.end()) {
|
||||||
emojis.push_back(Auto());
|
emojis.push_back(Auto());
|
||||||
} else {
|
} else {
|
||||||
emojis.push_back(make_tl_object<td_api::stickerEmojis>(vector<string>(it->second)));
|
emojis.push_back(make_tl_object<td_api::emojis>(vector<string>(it->second)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return make_tl_object<td_api::stickerSet>(sticker_set->id, sticker_set->title, sticker_set->short_name,
|
return make_tl_object<td_api::stickerSet>(sticker_set->id, sticker_set->title, sticker_set->short_name,
|
||||||
@ -4600,6 +4654,267 @@ vector<string> StickersManager::get_sticker_emojis(const tl_object_ptr<td_api::I
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string StickersManager::get_emoji_language_code_version_database_key(const string &language_code) {
|
||||||
|
return PSTRING() << "emojiv$" << language_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StickersManager::get_emoji_language_code_version(const string &language_code) {
|
||||||
|
auto it = emoji_language_code_versions_.find(language_code);
|
||||||
|
if (it != emoji_language_code_versions_.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
auto &result = emoji_language_code_versions_[language_code];
|
||||||
|
result = to_integer<int32>(
|
||||||
|
G()->td_db()->get_sqlite_sync_pmc()->get(get_emoji_language_code_version_database_key(language_code)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string StickersManager::get_language_emojis_database_key(const string &language_code, const string &text) {
|
||||||
|
return PSTRING() << "emoji$" << language_code << '$' << text;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> StickersManager::search_language_emojis(const string &language_code, const string &text,
|
||||||
|
bool exact_match) const {
|
||||||
|
LOG(INFO) << "Search for \"" << text << "\" in language " << language_code;
|
||||||
|
auto key = get_language_emojis_database_key(language_code, text);
|
||||||
|
if (exact_match) {
|
||||||
|
string emojis = G()->td_db()->get_sqlite_sync_pmc()->get(key);
|
||||||
|
return full_split(emojis, '$');
|
||||||
|
} else {
|
||||||
|
vector<string> result;
|
||||||
|
G()->td_db()->get_sqlite_sync_pmc()->get_by_prefix(key, [&result](Slice key, Slice value) {
|
||||||
|
for (auto &emoji : full_split(value, '$')) {
|
||||||
|
result.push_back(emoji.str());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string StickersManager::get_emoji_language_codes_database_key(const vector<string> &language_codes) {
|
||||||
|
return PSTRING() << "emojilc$" << implode(language_codes, '$');
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersManager::load_language_codes(vector<string> language_codes, string key, Promise<Unit> &&promise) {
|
||||||
|
auto &promises = load_language_codes_queries_[key];
|
||||||
|
promises.push_back(std::move(promise));
|
||||||
|
if (promises.size() != 1) {
|
||||||
|
// query has already been sent, just wait for the result
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query_promise =
|
||||||
|
PromiseCreator::lambda([actor_id = actor_id(this), key = std::move(key)](Result<vector<string>> &&result) {
|
||||||
|
send_closure(actor_id, &StickersManager::on_get_language_codes, key, std::move(result));
|
||||||
|
});
|
||||||
|
td_->create_handler<GetEmojiKeywordsLanguageQuery>(std::move(query_promise))->send(std::move(language_codes));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersManager::on_get_language_codes(const string &key, Result<vector<string>> &&result) {
|
||||||
|
auto queries_it = load_language_codes_queries_.find(key);
|
||||||
|
CHECK(queries_it != load_language_codes_queries_.end());
|
||||||
|
CHECK(!queries_it->second.empty());
|
||||||
|
auto promises = std::move(queries_it->second);
|
||||||
|
load_language_codes_queries_.erase(queries_it);
|
||||||
|
|
||||||
|
if (result.is_error()) {
|
||||||
|
if (!G()->close_flag()) {
|
||||||
|
LOG(ERROR) << "Reseive " << result.error() << " from GetEmojiKeywordsLanguageQuery";
|
||||||
|
}
|
||||||
|
for (auto &promise : promises) {
|
||||||
|
promise.set_error(result.error().clone());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto language_codes = result.move_as_ok();
|
||||||
|
LOG(INFO) << "Receive language codes " << language_codes << " for emojis search";
|
||||||
|
language_codes.erase(std::remove_if(language_codes.begin(), language_codes.end(),
|
||||||
|
[](const auto &language_code) {
|
||||||
|
if (language_code.empty() || language_code.find('$') != string::npos) {
|
||||||
|
LOG(ERROR) << "Receive language_code \"" << language_code << '"';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
language_codes.end());
|
||||||
|
if (language_codes.empty()) {
|
||||||
|
LOG(ERROR) << "Language codes list is empty";
|
||||||
|
language_codes.emplace_back("en");
|
||||||
|
}
|
||||||
|
|
||||||
|
G()->td_db()->get_sqlite_pmc()->set(key, implode(language_codes, '$'), Auto());
|
||||||
|
auto it = emoji_language_codes_.find(key);
|
||||||
|
CHECK(it != emoji_language_codes_.end());
|
||||||
|
it->second = std::move(language_codes);
|
||||||
|
|
||||||
|
for (auto &promise : promises) {
|
||||||
|
promise.set_value(Unit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> StickersManager::get_emoji_language_codes(Promise<Unit> &promise) {
|
||||||
|
vector<string> language_codes = td_->language_pack_manager_->get_actor_unsafe()->get_used_language_codes();
|
||||||
|
auto system_language_code = G()->mtproto_header().get_system_language_code();
|
||||||
|
if (!system_language_code.empty() && system_language_code.find('$') == string::npos) {
|
||||||
|
language_codes.push_back(system_language_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (language_codes.empty()) {
|
||||||
|
LOG(ERROR) << "List of language codes is empty";
|
||||||
|
language_codes.push_back("en");
|
||||||
|
}
|
||||||
|
std::sort(language_codes.begin(), language_codes.end());
|
||||||
|
language_codes.erase(std::unique(language_codes.begin(), language_codes.end()), language_codes.end());
|
||||||
|
|
||||||
|
auto key = get_emoji_language_codes_database_key(language_codes);
|
||||||
|
auto it = emoji_language_codes_.find(key);
|
||||||
|
if (it == emoji_language_codes_.end()) {
|
||||||
|
it = emoji_language_codes_.emplace(key, full_split(G()->td_db()->get_sqlite_sync_pmc()->get(key), '$')).first;
|
||||||
|
}
|
||||||
|
if (it->second.empty()) {
|
||||||
|
load_language_codes(std::move(language_codes), std::move(key), std::move(promise));
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersManager::load_emoji_keywords(const string &language_code, Promise<Unit> &&promise) {
|
||||||
|
auto &promises = load_emoji_keywords_queries_[language_code];
|
||||||
|
promises.push_back(std::move(promise));
|
||||||
|
if (promises.size() != 1) {
|
||||||
|
// query has already been sent, just wait for the result
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query_promise = PromiseCreator::lambda(
|
||||||
|
[actor_id = actor_id(this),
|
||||||
|
language_code](Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result) mutable {
|
||||||
|
send_closure(actor_id, &StickersManager::on_get_emoji_keywords, language_code, std::move(result));
|
||||||
|
});
|
||||||
|
td_->create_handler<GetEmojiKeywordsQuery>(std::move(query_promise))->send(language_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersManager::on_get_emoji_keywords(
|
||||||
|
const string &language_code, Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result) {
|
||||||
|
auto it = load_emoji_keywords_queries_.find(language_code);
|
||||||
|
CHECK(it != load_emoji_keywords_queries_.end());
|
||||||
|
CHECK(!it->second.empty());
|
||||||
|
auto promises = std::move(it->second);
|
||||||
|
load_emoji_keywords_queries_.erase(it);
|
||||||
|
|
||||||
|
if (result.is_error()) {
|
||||||
|
if (!G()->close_flag()) {
|
||||||
|
LOG(ERROR) << "Reseive " << result.error() << " from GetEmojiKeywordsQuery";
|
||||||
|
}
|
||||||
|
for (auto &promise : promises) {
|
||||||
|
promise.set_error(result.error().clone());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto version = get_emoji_language_code_version(language_code);
|
||||||
|
CHECK(version == 0);
|
||||||
|
|
||||||
|
MultiPromiseActorSafe mpas{"SaveEmojiKeywordsMultiPromiseActor"};
|
||||||
|
for (auto &promise : promises) {
|
||||||
|
mpas.add_promise(std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = mpas.get_promise();
|
||||||
|
|
||||||
|
auto keywords = result.move_as_ok();
|
||||||
|
LOG(INFO) << "Receive " << keywords->keywords_.size() << " emoji keywords for language " << language_code;
|
||||||
|
LOG_IF(ERROR, language_code != keywords->lang_code_)
|
||||||
|
<< "Receive keywords for " << keywords->lang_code_ << " instead of " << language_code;
|
||||||
|
LOG_IF(ERROR, keywords->from_version_ != 0) << "Receive keywords from version " << keywords->from_version_;
|
||||||
|
version = keywords->version_;
|
||||||
|
if (version <= 0) {
|
||||||
|
LOG(ERROR) << "Receive keywords to version " << version;
|
||||||
|
version = 1;
|
||||||
|
}
|
||||||
|
for (auto &keyword_ptr : keywords->keywords_) {
|
||||||
|
switch (keyword_ptr->get_id()) {
|
||||||
|
case telegram_api::emojiKeyword::ID: {
|
||||||
|
auto keyword = telegram_api::move_object_as<telegram_api::emojiKeyword>(keyword_ptr);
|
||||||
|
auto text = utf8_to_lower(keyword->keyword_);
|
||||||
|
bool is_good = true;
|
||||||
|
for (auto &emoji : keyword->emoticons_) {
|
||||||
|
if (emoji.find('$') != string::npos) {
|
||||||
|
LOG(ERROR) << "Receive emoji \"" << emoji << "\" from server for " << text;
|
||||||
|
is_good = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_good) {
|
||||||
|
G()->td_db()->get_sqlite_pmc()->set(get_language_emojis_database_key(language_code, text),
|
||||||
|
implode(keyword->emoticons_, '$'), mpas.get_promise());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case telegram_api::emojiKeywordDeleted::ID:
|
||||||
|
LOG(ERROR) << "Receive emojiKeywordDeleted in keywords for " << language_code;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
G()->td_db()->get_sqlite_pmc()->set(get_emoji_language_code_version_database_key(language_code), to_string(version),
|
||||||
|
mpas.get_promise());
|
||||||
|
emoji_language_code_versions_[language_code] = version;
|
||||||
|
|
||||||
|
lock.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> StickersManager::search_emojis(const string &text, bool exact_match, bool force,
|
||||||
|
Promise<Unit> &&promise) {
|
||||||
|
if (text.empty() || !G()->parameters().use_file_db /* have SQLite PMC */) {
|
||||||
|
promise.set_value(Unit());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto language_codes = get_emoji_language_codes(promise);
|
||||||
|
if (language_codes.empty()) {
|
||||||
|
// promise was consumed
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> languages_to_load;
|
||||||
|
for (auto &language_code : language_codes) {
|
||||||
|
auto version = get_emoji_language_code_version(language_code);
|
||||||
|
if (version == 0) {
|
||||||
|
languages_to_load.push_back(language_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!languages_to_load.empty()) {
|
||||||
|
if (!force) {
|
||||||
|
MultiPromiseActorSafe mpas{"LoadEmojiLanguagesMultiPromiseActor"};
|
||||||
|
mpas.add_promise(std::move(promise));
|
||||||
|
|
||||||
|
auto lock = mpas.get_promise();
|
||||||
|
for (auto &language_code : languages_to_load) {
|
||||||
|
load_emoji_keywords(language_code, mpas.get_promise());
|
||||||
|
}
|
||||||
|
lock.set_value(Unit());
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "Have no " << languages_to_load << " emoji keywords";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto text_lowered = utf8_to_lower(text);
|
||||||
|
vector<string> result;
|
||||||
|
for (auto &language_code : language_codes) {
|
||||||
|
combine(result, search_language_emojis(language_code, text_lowered, exact_match));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(result.begin(), result.end());
|
||||||
|
result.erase(std::unique(result.begin(), result.end()), result.end());
|
||||||
|
|
||||||
|
promise.set_value(Unit());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
string StickersManager::remove_emoji_modifiers(string emoji) {
|
string StickersManager::remove_emoji_modifiers(string emoji) {
|
||||||
static const Slice modifiers[] = {u8"\uFE0E" /* variation selector-15 */,
|
static const Slice modifiers[] = {u8"\uFE0E" /* variation selector-15 */,
|
||||||
u8"\uFE0F" /* variation selector-16 */,
|
u8"\uFE0F" /* variation selector-16 */,
|
||||||
|
@ -195,6 +195,8 @@ class StickersManager : public Actor {
|
|||||||
|
|
||||||
vector<string> get_sticker_emojis(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
|
vector<string> get_sticker_emojis(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
vector<string> search_emojis(const string &text, bool exact_match, bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void reload_installed_sticker_sets(bool is_masks, bool force);
|
void reload_installed_sticker_sets(bool is_masks, bool force);
|
||||||
|
|
||||||
void reload_featured_sticker_sets(bool force);
|
void reload_featured_sticker_sets(bool force);
|
||||||
@ -467,6 +469,27 @@ class StickersManager : public Actor {
|
|||||||
|
|
||||||
void tear_down() override;
|
void tear_down() override;
|
||||||
|
|
||||||
|
static string get_emoji_language_code_version_database_key(const string &language_code);
|
||||||
|
|
||||||
|
static string get_language_emojis_database_key(const string &language_code, const string &text);
|
||||||
|
|
||||||
|
static string get_emoji_language_codes_database_key(const vector<string> &language_codes);
|
||||||
|
|
||||||
|
int32 get_emoji_language_code_version(const string &language_code);
|
||||||
|
|
||||||
|
vector<string> get_emoji_language_codes(Promise<Unit> &promise);
|
||||||
|
|
||||||
|
void load_language_codes(vector<string> language_codes, string key, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void on_get_language_codes(const string &key, Result<vector<string>> &&result);
|
||||||
|
|
||||||
|
vector<string> search_language_emojis(const string &language_code, const string &text, bool exact_match) const;
|
||||||
|
|
||||||
|
void load_emoji_keywords(const string &language_code, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void on_get_emoji_keywords(const string &language_code,
|
||||||
|
Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result);
|
||||||
|
|
||||||
static string remove_emoji_modifiers(string emoji);
|
static string remove_emoji_modifiers(string emoji);
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
@ -545,6 +568,11 @@ class StickersManager : public Actor {
|
|||||||
std::shared_ptr<UploadStickerFileCallback> upload_sticker_file_callback_;
|
std::shared_ptr<UploadStickerFileCallback> upload_sticker_file_callback_;
|
||||||
|
|
||||||
std::unordered_map<FileId, std::pair<UserId, Promise<Unit>>, FileIdHash> being_uploaded_files_;
|
std::unordered_map<FileId, std::pair<UserId, Promise<Unit>>, FileIdHash> being_uploaded_files_;
|
||||||
|
|
||||||
|
std::unordered_map<string, vector<string>> emoji_language_codes_;
|
||||||
|
std::unordered_map<string, int32> emoji_language_code_versions_;
|
||||||
|
std::unordered_map<string, vector<Promise<Unit>>> load_emoji_keywords_queries_;
|
||||||
|
std::unordered_map<string, vector<Promise<Unit>>> load_language_codes_queries_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -2597,7 +2597,7 @@ class GetStickerEmojisRequest : public RequestActor<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void do_send_result() override {
|
void do_send_result() override {
|
||||||
send_result(make_tl_object<td_api::stickerEmojis>(std::move(emojis_)));
|
send_result(td_api::make_object<td_api::emojis>(std::move(emojis_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -2607,6 +2607,27 @@ class GetStickerEmojisRequest : public RequestActor<> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SearchEmojisRequest : public RequestActor<> {
|
||||||
|
string text_;
|
||||||
|
bool exact_match_;
|
||||||
|
|
||||||
|
vector<string> emojis_;
|
||||||
|
|
||||||
|
void do_run(Promise<Unit> &&promise) override {
|
||||||
|
emojis_ = td->stickers_manager_->search_emojis(text_, exact_match_, get_tries() < 2, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_send_result() override {
|
||||||
|
send_result(td_api::make_object<td_api::emojis>(std::move(emojis_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SearchEmojisRequest(ActorShared<Td> td, uint64 request_id, string &&text, bool exact_match)
|
||||||
|
: RequestActor(std::move(td), request_id), text_(std::move(text)), exact_match_(exact_match) {
|
||||||
|
set_tries(3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class GetSavedAnimationsRequest : public RequestActor<> {
|
class GetSavedAnimationsRequest : public RequestActor<> {
|
||||||
vector<FileId> animation_ids_;
|
vector<FileId> animation_ids_;
|
||||||
|
|
||||||
@ -6338,6 +6359,12 @@ void Td::on_request(uint64 id, td_api::getStickerEmojis &request) {
|
|||||||
CREATE_REQUEST(GetStickerEmojisRequest, std::move(request.sticker_));
|
CREATE_REQUEST(GetStickerEmojisRequest, std::move(request.sticker_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, td_api::searchEmojis &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CLEAN_INPUT_STRING(request.text_);
|
||||||
|
CREATE_REQUEST(SearchEmojisRequest, std::move(request.text_), request.exact_match_);
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getSavedAnimations &request) {
|
void Td::on_request(uint64 id, const td_api::getSavedAnimations &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_NO_ARGS_REQUEST(GetSavedAnimationsRequest);
|
CREATE_NO_ARGS_REQUEST(GetSavedAnimationsRequest);
|
||||||
|
@ -810,6 +810,8 @@ class Td final : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_request(uint64 id, td_api::getStickerEmojis &request);
|
void on_request(uint64 id, td_api::getStickerEmojis &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, td_api::searchEmojis &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::getFavoriteStickers &request);
|
void on_request(uint64 id, const td_api::getFavoriteStickers &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::addFavoriteSticker &request);
|
void on_request(uint64 id, td_api::addFavoriteSticker &request);
|
||||||
|
@ -2210,6 +2210,10 @@ class CliClient final : public Actor {
|
|||||||
send_request(td_api::make_object<td_api::clearRecentStickers>(as_bool(args)));
|
send_request(td_api::make_object<td_api::clearRecentStickers>(as_bool(args)));
|
||||||
} else if (op == "gse") {
|
} else if (op == "gse") {
|
||||||
send_request(td_api::make_object<td_api::getStickerEmojis>(as_input_file_id(args)));
|
send_request(td_api::make_object<td_api::getStickerEmojis>(as_input_file_id(args)));
|
||||||
|
} else if (op == "se") {
|
||||||
|
send_request(td_api::make_object<td_api::searchEmojis>(args, false));
|
||||||
|
} else if (op == "see") {
|
||||||
|
send_request(td_api::make_object<td_api::searchEmojis>(args, true));
|
||||||
} else {
|
} else {
|
||||||
op_not_found_count++;
|
op_not_found_count++;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,10 @@ class MtprotoHeader {
|
|||||||
return anonymous_header_;
|
return anonymous_header_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string get_system_language_code() const {
|
||||||
|
return options_.system_language_code;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Options options_;
|
Options options_;
|
||||||
string default_header_;
|
string default_header_;
|
||||||
|
Loading…
Reference in New Issue
Block a user