Add td_api::getEmojiCategories.

This commit is contained in:
levlam 2023-01-24 18:11:02 +03:00
parent f51bea81e1
commit 8730fd6f34
10 changed files with 297 additions and 3 deletions

View File

@ -331,6 +331,7 @@ set(TDLIB_SOURCE
td/telegram/DownloadManagerCallback.cpp
td/telegram/DraftMessage.cpp
td/telegram/EmailVerification.cpp
td/telegram/EmojiGroup.cpp
td/telegram/EmojiStatus.cpp
td/telegram/FileReferenceManager.cpp
td/telegram/files/FileBitmask.cpp
@ -562,6 +563,7 @@ set(TDLIB_SOURCE
td/telegram/DownloadManagerCallback.h
td/telegram/DraftMessage.h
td/telegram/EmailVerification.h
td/telegram/EmojiGroup.h
td/telegram/EmojiStatus.h
td/telegram/EncryptedFile.h
td/telegram/FileReferenceManager.h
@ -761,6 +763,7 @@ set(TDLIB_SOURCE
td/telegram/Document.hpp
td/telegram/DocumentsManager.hpp
td/telegram/DraftMessage.hpp
td/telegram/EmojiGroup.hpp
td/telegram/FileReferenceManager.hpp
td/telegram/files/FileData.hpp
td/telegram/files/FileId.hpp

View File

@ -2940,6 +2940,16 @@ stickerSets total_count:int32 sets:vector<stickerSetInfo> = StickerSets;
trendingStickerSets total_count:int32 sets:vector<stickerSetInfo> is_premium:Bool = TrendingStickerSets;
//@description Contains a list of similar emoji to search for in getStickers and searchStickers
//@name Name of the category
//@icon_custom_emoji_id Unique identifier of the custom emoji, which represents icon of the category
//@emojis List of emojis in the category
emojiCategory name:string icon_custom_emoji_id:int64 emojis:vector<string> = EmojiCategory;
//@description Represents a list of emoji categories @categories List of categories
emojiCategories categories:vector<emojiCategory> = EmojiCategories;
//@class CallDiscardReason @description Describes the reason why a call was discarded
//@description The call wasn't discarded, or the reason is unknown
@ -7296,6 +7306,9 @@ getStickerEmojis sticker:InputFile = Emojis;
//@input_language_codes List of possible IETF language tags of the user's input language; may be empty if unknown
searchEmojis text:string exact_match:Bool input_language_codes:vector<string> = Emojis;
//@description Returns available emojis categories
getEmojiCategories = EmojiCategories;
//@description Returns an animated emoji corresponding to a given emoji. Returns a 404 error if the emoji has no animated emoji @emoji The emoji
getAnimatedEmoji emoji:string = AnimatedEmoji;

View File

@ -0,0 +1,49 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/EmojiGroup.h"
#include "td/utils/algorithm.h"
#include "td/utils/Time.h"
namespace td {
EmojiGroup::EmojiGroup(telegram_api::object_ptr<telegram_api::emojiGroup> &&emoji_group)
: title_(std::move(emoji_group->title_))
, icon_custom_emoji_id_(emoji_group->icon_emoji_id_)
, emojis_(std::move(emoji_group->emoticons_)) {
}
td_api::object_ptr<td_api::emojiCategory> EmojiGroup::get_emoji_category_object() const {
return td_api::make_object<td_api::emojiCategory>(title_, icon_custom_emoji_id_.get(), vector<string>(emojis_));
}
EmojiGroupList::EmojiGroupList(string &&used_language_codes, int32 hash,
vector<telegram_api::object_ptr<telegram_api::emojiGroup>> &&emoji_groups)
: used_language_codes_(std::move(used_language_codes))
, hash_(hash)
, emoji_groups_(transform(std::move(emoji_groups),
[](telegram_api::object_ptr<telegram_api::emojiGroup> &&emoji_group) {
return EmojiGroup(std::move(emoji_group));
}))
, next_reload_time_(Time::now() + 3600) {
}
td_api::object_ptr<td_api::emojiCategories> EmojiGroupList::get_emoji_categories_object() const {
return td_api::make_object<td_api::emojiCategories>(
transform(emoji_groups_, [](const EmojiGroup &emoji_group) { return emoji_group.get_emoji_category_object(); }));
}
bool EmojiGroupList::is_expired() const {
return next_reload_time_ < Time::now();
}
void EmojiGroupList::update_next_reload_time() {
next_reload_time_ = Time::now() + 3600;
}
} // namespace td

69
td/telegram/EmojiGroup.h Normal file
View File

@ -0,0 +1,69 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/CustomEmojiId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
namespace td {
class EmojiGroup {
string title_;
CustomEmojiId icon_custom_emoji_id_;
vector<string> emojis_;
public:
EmojiGroup() = default;
explicit EmojiGroup(telegram_api::object_ptr<telegram_api::emojiGroup> &&emoji_group);
td_api::object_ptr<td_api::emojiCategory> get_emoji_category_object() const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
class EmojiGroupList {
string used_language_codes_;
int32 hash_ = 0;
vector<EmojiGroup> emoji_groups_;
double next_reload_time_ = 0.0;
public:
EmojiGroupList() = default;
EmojiGroupList(string &&used_language_codes, int32 hash,
vector<telegram_api::object_ptr<telegram_api::emojiGroup>> &&emoji_groups);
td_api::object_ptr<td_api::emojiCategories> get_emoji_categories_object() const;
const string &get_used_language_codes() const {
return used_language_codes_;
}
int32 get_hash() const {
return hash_;
}
bool is_expired() const;
void update_next_reload_time();
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
} // namespace td

View File

@ -0,0 +1,43 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/EmojiGroup.h"
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
void EmojiGroup::store(StorerT &storer) const {
td::store(title_, storer);
td::store(icon_custom_emoji_id_, storer);
td::store(emojis_, storer);
}
template <class ParserT>
void EmojiGroup::parse(ParserT &parser) {
td::parse(title_, parser);
td::parse(icon_custom_emoji_id_, parser);
td::parse(emojis_, parser);
}
template <class StorerT>
void EmojiGroupList::store(StorerT &storer) const {
td::store(used_language_codes_, storer);
td::store(hash_, storer);
td::store(emoji_groups_, storer);
}
template <class ParserT>
void EmojiGroupList::parse(ParserT &parser) {
td::parse(used_language_codes_, parser);
td::parse(hash_, parser);
td::parse(emoji_groups_, parser);
}
} // namespace td

View File

@ -1345,6 +1345,32 @@ class GetCustomEmojiDocumentsQuery final : public Td::ResultHandler {
}
};
class GetEmojiGroupsQuery final : public Td::ResultHandler {
Promise<telegram_api::object_ptr<telegram_api::messages_EmojiGroups>> promise_;
public:
explicit GetEmojiGroupsQuery(Promise<telegram_api::object_ptr<telegram_api::messages_EmojiGroups>> &&promise)
: promise_(std::move(promise)) {
}
void send(int32 hash) {
send_query(G()->net_query_creator().create(telegram_api::messages_getEmojiGroups(hash)));
}
void on_result(BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::messages_getEmojiGroups>(packet);
if (result_ptr.is_error()) {
return on_error(result_ptr.move_as_error());
}
promise_.set_value(result_ptr.move_as_ok());
}
void on_error(Status status) final {
promise_.set_error(std::move(status));
}
};
class GetDefaultDialogPhotoEmojisQuery final : public Td::ResultHandler {
Promise<telegram_api::object_ptr<telegram_api::EmojiList>> promise_;
@ -6600,6 +6626,7 @@ void StickersManager::on_get_default_dialog_photo_custom_emoji_ids_success(bool
are_default_dialog_photo_custom_emoji_ids_loaded_[for_user] = true;
auto promises = std::move(default_dialog_photo_custom_emoji_ids_load_queries_[for_user]);
reset_to_empty(default_dialog_photo_custom_emoji_ids_load_queries_[for_user]);
for (auto &promise : promises) {
get_custom_emoji_stickers(default_dialog_photo_custom_emoji_ids_[for_user], true, std::move(promise));
}
@ -9553,8 +9580,7 @@ void StickersManager::on_get_language_codes(const string &key, Result<vector<str
set_promises(promises);
}
vector<string> StickersManager::get_emoji_language_codes(const vector<string> &input_language_codes, Slice text,
Promise<Unit> &promise) {
vector<string> StickersManager::get_used_language_codes(const vector<string> &input_language_codes, Slice text) const {
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.size() >= 2 && system_language_code.find('$') == string::npos &&
@ -9582,12 +9608,18 @@ vector<string> StickersManager::get_emoji_language_codes(const vector<string> &i
}
}
}
td::unique(language_codes);
if (language_codes.empty()) {
LOG(INFO) << "List of language codes is empty";
language_codes.push_back("en");
}
td::unique(language_codes);
return language_codes;
}
vector<string> StickersManager::get_emoji_language_codes(const vector<string> &input_language_codes, Slice text,
Promise<Unit> &promise) {
auto language_codes = get_used_language_codes(input_language_codes, text);
LOG(DEBUG) << "Have language codes " << language_codes;
auto key = get_emoji_language_codes_database_key(language_codes);
@ -9923,6 +9955,70 @@ td_api::object_ptr<td_api::httpUrl> StickersManager::get_emoji_suggestions_url_r
return result;
}
void StickersManager::get_emoji_categories(Promise<td_api::object_ptr<td_api::emojiCategories>> &&promise) {
auto used_language_codes = implode(get_used_language_codes({}, Slice()), '$');
LOG(INFO) << "Have language codes " << used_language_codes;
if (emoji_group_list_.get_used_language_codes() == used_language_codes) {
promise.set_value(emoji_group_list_.get_emoji_categories_object());
if (!emoji_group_list_.is_expired()) {
return;
}
promise = Promise<td_api::object_ptr<td_api::emojiCategories>>();
}
emoji_group_load_queries_.push_back(std::move(promise));
if (emoji_group_load_queries_.size() != 1) {
// query has already been sent, just wait for the result
return;
}
auto query_promise =
PromiseCreator::lambda([actor_id = actor_id(this), used_language_codes = std::move(used_language_codes)](
Result<telegram_api::object_ptr<telegram_api::messages_EmojiGroups>> r_emoji_groups) {
send_closure(actor_id, &StickersManager::on_get_emoji_categories, std::move(used_language_codes),
std::move(r_emoji_groups));
});
td_->create_handler<GetEmojiGroupsQuery>(std::move(query_promise))->send(emoji_group_list_.get_hash());
}
void StickersManager::on_get_emoji_categories(
string used_language_codes, Result<telegram_api::object_ptr<telegram_api::messages_EmojiGroups>> r_emoji_groups) {
if (G()->close_flag()) {
r_emoji_groups = Global::request_aborted_error();
}
if (r_emoji_groups.is_error()) {
if (!G()->is_expected_error(r_emoji_groups.error())) {
LOG(ERROR) << "Receive " << r_emoji_groups.error() << " from GetEmojiGroupsQuery";
}
return fail_promises(emoji_group_load_queries_, r_emoji_groups.move_as_error());
}
auto new_used_language_codes = implode(get_used_language_codes({}, Slice()), '$');
if (new_used_language_codes != used_language_codes) {
used_language_codes.clear();
}
auto emoji_groups = r_emoji_groups.move_as_ok();
switch (emoji_groups->get_id()) {
case telegram_api::messages_emojiGroupsNotModified::ID:
emoji_group_list_.update_next_reload_time();
break;
case telegram_api::messages_emojiGroups::ID: {
auto groups = telegram_api::move_object_as<telegram_api::messages_emojiGroups>(emoji_groups);
emoji_group_list_ = EmojiGroupList(std::move(used_language_codes), groups->hash_, std::move(groups->groups_));
break;
}
default:
UNREACHABLE();
}
auto promises = std::move(emoji_group_load_queries_);
reset_to_empty(emoji_group_load_queries_);
for (auto &promise : promises) {
promise.set_value(emoji_group_list_.get_emoji_categories_object());
}
}
void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
if (td_->auth_manager_->is_bot()) {
return;

View File

@ -9,6 +9,7 @@
#include "td/telegram/CustomEmojiId.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/Dimensions.h"
#include "td/telegram/EmojiGroup.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/FullMessageId.h"
@ -364,6 +365,8 @@ class StickersManager final : public Actor {
int64 get_emoji_suggestions_url(const string &language_code, Promise<Unit> &&promise);
void get_emoji_categories(Promise<td_api::object_ptr<td_api::emojiCategories>> &&promise);
td_api::object_ptr<td_api::httpUrl> get_emoji_suggestions_url_result(int64 random_id);
void reload_sticker_set(StickerSetId sticker_set_id, int64 access_hash, Promise<Unit> &&promise);
@ -971,6 +974,8 @@ class StickersManager final : public Actor {
double get_emoji_language_code_last_difference_time(const string &language_code);
vector<string> get_used_language_codes(const vector<string> &input_language_codes, Slice text) const;
vector<string> get_emoji_language_codes(const vector<string> &input_language_codes, Slice text,
Promise<Unit> &promise);
@ -996,6 +1001,9 @@ class StickersManager final : public Actor {
void on_get_emoji_suggestions_url(int64 random_id, Promise<Unit> &&promise,
Result<telegram_api::object_ptr<telegram_api::emojiURL>> &&r_emoji_url);
void on_get_emoji_categories(string used_language_codes,
Result<telegram_api::object_ptr<telegram_api::messages_EmojiGroups>> r_emoji_groups);
Td *td_;
ActorShared<> parent_;
@ -1173,6 +1181,9 @@ class StickersManager final : public Actor {
string emoji_sounds_str_;
FlatHashMap<string, FileId> emoji_sounds_;
EmojiGroupList emoji_group_list_;
vector<Promise<td_api::object_ptr<td_api::emojiCategories>>> emoji_group_load_queries_;
vector<CustomEmojiId> default_dialog_photo_custom_emoji_ids_[2];
int64 default_dialog_photo_custom_emoji_ids_hash_[2] = {0, 0};
vector<Promise<td_api::object_ptr<td_api::stickers>>> default_dialog_photo_custom_emoji_ids_load_queries_[2];

View File

@ -7348,6 +7348,12 @@ void Td::on_request(uint64 id, td_api::searchEmojis &request) {
std::move(request.input_language_codes_));
}
void Td::on_request(uint64 id, const td_api::getEmojiCategories &request) {
CHECK_IS_USER();
CREATE_REQUEST_PROMISE();
stickers_manager_->get_emoji_categories(std::move(promise));
}
void Td::on_request(uint64 id, td_api::getAnimatedEmoji &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.emoji_);

View File

@ -1213,6 +1213,8 @@ class Td final : public Actor {
void on_request(uint64 id, td_api::searchEmojis &request);
void on_request(uint64 id, const td_api::getEmojiCategories &request);
void on_request(uint64 id, td_api::getAnimatedEmoji &request);
void on_request(uint64 id, td_api::getEmojiSuggestionsUrl &request);

View File

@ -2921,6 +2921,8 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::searchEmojis>(args, true, vector<string>()));
} else if (op == "seru") {
send_request(td_api::make_object<td_api::searchEmojis>(args, false, vector<string>{"ru_RU"}));
} else if (op == "gec") {
send_request(td_api::make_object<td_api::getEmojiCategories>());
} else if (op == "gae") {
send_request(td_api::make_object<td_api::getAnimatedEmoji>(args));
} else if (op == "gesu") {