Support trending emoji sticker sets.

This commit is contained in:
levlam 2022-07-17 22:39:22 +03:00
parent 1f2e8d7c57
commit 4442293acf
8 changed files with 332 additions and 207 deletions

View File

@ -4399,8 +4399,8 @@ updateStickerSet sticker_set:stickerSet = Update;
//@description The list of installed sticker sets was updated @sticker_type Type of the affected stickers @sticker_set_ids The new list of installed ordinary sticker sets //@description The list of installed sticker sets was updated @sticker_type Type of the affected stickers @sticker_set_ids The new list of installed ordinary sticker sets
updateInstalledStickerSets sticker_type:StickerType sticker_set_ids:vector<int64> = Update; updateInstalledStickerSets sticker_type:StickerType sticker_set_ids:vector<int64> = Update;
//@description The list of trending sticker sets was updated or some of them were viewed @sticker_sets The prefix of the list of trending sticker sets with the newest trending sticker sets //@description The list of trending sticker sets was updated or some of them were viewed @sticker_type Type of the affected stickers @sticker_sets The prefix of the list of trending sticker sets with the newest trending sticker sets
updateTrendingStickerSets sticker_sets:trendingStickerSets = Update; updateTrendingStickerSets sticker_type:StickerType sticker_sets:trendingStickerSets = Update;
//@description The list of recently used stickers was updated @is_attached True, if the list of stickers attached to photo or video files was updated, otherwise the list of sent stickers is updated @sticker_ids The new list of file identifiers of recently used stickers //@description The list of recently used stickers was updated @is_attached True, if the list of stickers attached to photo or video files was updated, otherwise the list of sent stickers is updated @sticker_ids The new list of file identifiers of recently used stickers
updateRecentStickers is_attached:Bool sticker_ids:vector<int32> = Update; updateRecentStickers is_attached:Bool sticker_ids:vector<int32> = Update;
@ -5904,9 +5904,10 @@ getInstalledStickerSets sticker_type:StickerType = StickerSets;
getArchivedStickerSets sticker_type:StickerType offset_sticker_set_id:int64 limit:int32 = StickerSets; getArchivedStickerSets sticker_type:StickerType offset_sticker_set_id:int64 limit:int32 = StickerSets;
//@description Returns a list of trending sticker sets. For optimal performance, the number of returned sticker sets is chosen by TDLib //@description Returns a list of trending sticker sets. For optimal performance, the number of returned sticker sets is chosen by TDLib
//@sticker_type Type of the sticker sets to return
//@offset The offset from which to return the sticker sets; must be non-negative //@offset The offset from which to return the sticker sets; must be non-negative
//@limit The maximum number of sticker sets to be returned; up to 100. For optimal performance, the number of returned sticker sets is chosen by TDLib and can be smaller than the specified limit, even if the end of the list has not been reached //@limit The maximum number of sticker sets to be returned; up to 100. For optimal performance, the number of returned sticker sets is chosen by TDLib and can be smaller than the specified limit, even if the end of the list has not been reached
getTrendingStickerSets offset:int32 limit:int32 = TrendingStickerSets; getTrendingStickerSets sticker_type:StickerType offset:int32 limit:int32 = TrendingStickerSets;
//@description Returns a list of sticker sets attached to a file. Currently, only photos and videos can have attached sticker sets @file_id File identifier //@description Returns a list of sticker sets attached to a file. Currently, only photos and videos can have attached sticker sets @file_id File identifier
getAttachedStickerSets file_id:int32 = StickerSets; getAttachedStickerSets file_id:int32 = StickerSets;

View File

@ -310,12 +310,27 @@ class GetArchivedStickerSetsQuery final : public Td::ResultHandler {
}; };
class GetFeaturedStickerSetsQuery final : public Td::ResultHandler { class GetFeaturedStickerSetsQuery final : public Td::ResultHandler {
StickerType sticker_type_;
public: public:
void send(int64 hash) { void send(StickerType sticker_type, int64 hash) {
send_query(G()->net_query_creator().create(telegram_api::messages_getFeaturedStickers(hash))); sticker_type_ = sticker_type;
switch (sticker_type) {
case StickerType::Regular:
send_query(G()->net_query_creator().create(telegram_api::messages_getFeaturedStickers(hash)));
break;
case StickerType::Emoji:
send_query(G()->net_query_creator().create(telegram_api::messages_getFeaturedEmojiStickers(hash)));
break;
default:
UNREACHABLE();
}
} }
void on_result(BufferSlice packet) final { void on_result(BufferSlice packet) final {
static_assert(std::is_same<telegram_api::messages_getFeaturedStickers::ReturnType,
telegram_api::messages_getFeaturedEmojiStickers::ReturnType>::value,
"");
auto result_ptr = fetch_result<telegram_api::messages_getFeaturedStickers>(packet); auto result_ptr = fetch_result<telegram_api::messages_getFeaturedStickers>(packet);
if (result_ptr.is_error()) { if (result_ptr.is_error()) {
return on_error(result_ptr.move_as_error()); return on_error(result_ptr.move_as_error());
@ -323,11 +338,11 @@ class GetFeaturedStickerSetsQuery final : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok(); auto ptr = result_ptr.move_as_ok();
LOG(DEBUG) << "Receive result for GetFeaturedStickerSetsQuery: " << to_string(ptr); LOG(DEBUG) << "Receive result for GetFeaturedStickerSetsQuery: " << to_string(ptr);
td_->stickers_manager_->on_get_featured_sticker_sets(-1, -1, 0, std::move(ptr)); td_->stickers_manager_->on_get_featured_sticker_sets(sticker_type_, -1, -1, 0, std::move(ptr));
} }
void on_error(Status status) final { void on_error(Status status) final {
td_->stickers_manager_->on_get_featured_sticker_sets_failed(-1, -1, 0, std::move(status)); td_->stickers_manager_->on_get_featured_sticker_sets_failed(sticker_type_, -1, -1, 0, std::move(status));
} }
}; };
@ -337,7 +352,8 @@ class GetOldFeaturedStickerSetsQuery final : public Td::ResultHandler {
uint32 generation_; uint32 generation_;
public: public:
void send(int32 offset, int32 limit, uint32 generation) { void send(StickerType sticker_type, int32 offset, int32 limit, uint32 generation) {
CHECK(sticker_type == StickerType::Regular);
offset_ = offset; offset_ = offset;
limit_ = limit; limit_ = limit;
generation_ = generation; generation_ = generation;
@ -352,11 +368,13 @@ class GetOldFeaturedStickerSetsQuery final : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok(); auto ptr = result_ptr.move_as_ok();
LOG(DEBUG) << "Receive result for GetOldFeaturedStickerSetsQuery: " << to_string(ptr); LOG(DEBUG) << "Receive result for GetOldFeaturedStickerSetsQuery: " << to_string(ptr);
td_->stickers_manager_->on_get_featured_sticker_sets(offset_, limit_, generation_, std::move(ptr)); td_->stickers_manager_->on_get_featured_sticker_sets(StickerType::Regular, offset_, limit_, generation_,
std::move(ptr));
} }
void on_error(Status status) final { void on_error(Status status) final {
td_->stickers_manager_->on_get_featured_sticker_sets_failed(offset_, limit_, generation_, std::move(status)); td_->stickers_manager_->on_get_featured_sticker_sets_failed(StickerType::Regular, offset_, limit_, generation_,
std::move(status));
} }
}; };
@ -898,7 +916,9 @@ class ReadFeaturedStickerSetsQuery final : public Td::ResultHandler {
if (!G()->is_expected_error(status)) { if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for ReadFeaturedStickerSetsQuery: " << status; LOG(ERROR) << "Receive error for ReadFeaturedStickerSetsQuery: " << status;
} }
td_->stickers_manager_->reload_featured_sticker_sets(true); for (int32 type = 0; type < MAX_STICKER_TYPE; type++) {
td_->stickers_manager_->reload_featured_sticker_sets(static_cast<StickerType>(type), true);
}
} }
}; };
@ -1379,10 +1399,11 @@ void StickersManager::init() {
if (G()->parameters().use_file_db) { if (G()->parameters().use_file_db) {
auto old_featured_sticker_set_count_str = G()->td_db()->get_binlog_pmc()->get("old_featured_sticker_set_count"); auto old_featured_sticker_set_count_str = G()->td_db()->get_binlog_pmc()->get("old_featured_sticker_set_count");
if (!old_featured_sticker_set_count_str.empty()) { if (!old_featured_sticker_set_count_str.empty()) {
old_featured_sticker_set_count_ = to_integer<int32>(old_featured_sticker_set_count_str); old_featured_sticker_set_count_[static_cast<int32>(StickerType::Regular)] =
to_integer<int32>(old_featured_sticker_set_count_str);
} }
if (!G()->td_db()->get_binlog_pmc()->get("invalidate_old_featured_sticker_sets").empty()) { if (!G()->td_db()->get_binlog_pmc()->get("invalidate_old_featured_sticker_sets").empty()) {
invalidate_old_featured_sticker_sets(); invalidate_old_featured_sticker_sets(StickerType::Regular);
} }
} else { } else {
G()->td_db()->get_binlog_pmc()->erase("old_featured_sticker_set_count"); G()->td_db()->get_binlog_pmc()->erase("old_featured_sticker_set_count");
@ -2677,26 +2698,31 @@ void StickersManager::reload_installed_sticker_sets(StickerType sticker_type, bo
} }
} }
void StickersManager::reload_featured_sticker_sets(bool force) { void StickersManager::reload_featured_sticker_sets(StickerType sticker_type, bool force) {
if (G()->close_flag()) { if (G()->close_flag()) {
return; return;
} }
auto &next_load_time = next_featured_sticker_sets_load_time_; auto type = static_cast<int32>(sticker_type);
auto &next_load_time = next_featured_sticker_sets_load_time_[type];
if (!td_->auth_manager_->is_bot() && next_load_time >= 0 && (next_load_time < Time::now() || force)) { if (!td_->auth_manager_->is_bot() && next_load_time >= 0 && (next_load_time < Time::now() || force)) {
LOG_IF(INFO, force) << "Reload trending sticker sets"; LOG_IF(INFO, force) << "Reload trending sticker sets";
next_load_time = -1; next_load_time = -1;
td_->create_handler<GetFeaturedStickerSetsQuery>()->send(featured_sticker_sets_hash_); td_->create_handler<GetFeaturedStickerSetsQuery>()->send(sticker_type, featured_sticker_sets_hash_[type]);
} }
} }
void StickersManager::reload_old_featured_sticker_sets(uint32 generation) { void StickersManager::reload_old_featured_sticker_sets(StickerType sticker_type, uint32 generation) {
if (generation != 0 && generation != old_featured_sticker_set_generation_) { if (sticker_type != StickerType::Regular) {
return; return;
} }
td_->create_handler<GetOldFeaturedStickerSetsQuery>()->send(static_cast<int32>(old_featured_sticker_set_ids_.size()), auto type = static_cast<int32>(sticker_type);
OLD_FEATURED_STICKER_SET_SLICE_SIZE, if (generation != 0 && generation != old_featured_sticker_set_generation_[type]) {
old_featured_sticker_set_generation_); return;
}
td_->create_handler<GetOldFeaturedStickerSetsQuery>()->send(
sticker_type, static_cast<int32>(old_featured_sticker_set_ids_[type].size()), OLD_FEATURED_STICKER_SET_SLICE_SIZE,
old_featured_sticker_set_generation_[type]);
} }
StickerSetId StickersManager::on_get_input_sticker_set(FileId sticker_file_id, StickerSetId StickersManager::on_get_input_sticker_set(FileId sticker_file_id,
@ -3638,8 +3664,8 @@ vector<FileId> StickersManager::get_stickers(string emoji, int32 limit, bool for
return {}; return {};
} }
/* /*
if (!are_featured_sticker_sets_loaded_) { if (!are_featured_sticker_sets_loaded_[static_cast<int32>(StickerType::Regular)]) {
load_featured_sticker_sets(std::move(promise)); load_featured_sticker_sets(StickerType::Regular, std::move(promise));
return {}; return {};
} }
*/ */
@ -4505,7 +4531,8 @@ void StickersManager::on_load_sticker_set_from_database(StickerSetId sticker_set
do_reload_sticker_set(sticker_set_id, get_input_sticker_set(sticker_set), 0, Auto()); do_reload_sticker_set(sticker_set_id, get_input_sticker_set(sticker_set), 0, Auto());
} }
if (with_stickers && old_sticker_count < 5 && old_sticker_count < sticker_set->sticker_ids.size()) { if (with_stickers && old_sticker_count < get_max_featured_sticker_count(sticker_set->sticker_type) &&
old_sticker_count < sticker_set->sticker_ids.size()) {
sticker_set->need_save_to_database = true; sticker_set->need_save_to_database = true;
update_sticker_set(sticker_set, "on_load_sticker_set_from_database"); update_sticker_set(sticker_set, "on_load_sticker_set_from_database");
} }
@ -5288,8 +5315,9 @@ void StickersManager::view_featured_sticker_sets(const vector<StickerSetId> &sti
for (auto sticker_set_id : sticker_set_ids) { for (auto sticker_set_id : sticker_set_ids) {
auto set = get_sticker_set(sticker_set_id); auto set = get_sticker_set(sticker_set_id);
if (set != nullptr && !set->is_viewed) { if (set != nullptr && !set->is_viewed) {
if (td::contains(featured_sticker_set_ids_, sticker_set_id)) { auto type = static_cast<int32>(set->sticker_type);
need_update_featured_sticker_sets_ = true; if (td::contains(featured_sticker_set_ids_[type], sticker_set_id)) {
need_update_featured_sticker_sets_[type] = true;
} }
set->is_viewed = true; set->is_viewed = true;
pending_viewed_featured_sticker_set_ids_.insert(sticker_set_id); pending_viewed_featured_sticker_set_ids_.insert(sticker_set_id);
@ -5297,7 +5325,9 @@ void StickersManager::view_featured_sticker_sets(const vector<StickerSetId> &sti
} }
} }
send_update_featured_sticker_sets(); for (int32 type = 0; type < MAX_STICKER_TYPE; type++) {
send_update_featured_sticker_sets(static_cast<StickerType>(type));
}
if (!pending_viewed_featured_sticker_set_ids_.empty() && !pending_featured_sticker_set_views_timeout_.has_timeout()) { if (!pending_viewed_featured_sticker_set_ids_.empty() && !pending_featured_sticker_set_views_timeout_.has_timeout()) {
LOG(INFO) << "Have pending viewed trending sticker sets"; LOG(INFO) << "Have pending viewed trending sticker sets";
@ -5410,7 +5440,8 @@ void StickersManager::on_get_archived_sticker_sets(
send_update_installed_sticker_sets(); send_update_installed_sticker_sets();
} }
td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_featured_sticker_sets(int32 offset, int32 limit, td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_featured_sticker_sets(StickerType sticker_type,
int32 offset, int32 limit,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (offset < 0) { if (offset < 0) {
promise.set_error(Status::Error(400, "Parameter offset must be non-negative")); promise.set_error(Status::Error(400, "Parameter offset must be non-negative"));
@ -5425,37 +5456,44 @@ td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_featured_st
offset = 0; offset = 0;
} }
if (!are_featured_sticker_sets_loaded_) { if (sticker_type == StickerType::Mask) {
load_featured_sticker_sets(std::move(promise)); promise.set_value(Unit());
return get_trending_sticker_sets_object(sticker_type, {});
}
auto type = static_cast<int32>(sticker_type);
if (!are_featured_sticker_sets_loaded_[type]) {
load_featured_sticker_sets(sticker_type, std::move(promise));
return {}; return {};
} }
reload_featured_sticker_sets(false); reload_featured_sticker_sets(sticker_type, false);
auto set_count = static_cast<int32>(featured_sticker_set_ids_.size()); auto set_count = static_cast<int32>(featured_sticker_set_ids_[type].size());
if (offset < set_count) { if (offset < set_count) {
if (limit > set_count - offset) { if (limit > set_count - offset) {
limit = set_count - offset; limit = set_count - offset;
} }
promise.set_value(Unit()); promise.set_value(Unit());
auto begin = featured_sticker_set_ids_.begin() + offset; auto begin = featured_sticker_set_ids_[type].begin() + offset;
return get_trending_sticker_sets_object({begin, begin + limit}); return get_trending_sticker_sets_object(sticker_type, {begin, begin + limit});
} }
if (offset == set_count && are_old_featured_sticker_sets_invalidated_) { if (offset == set_count && are_old_featured_sticker_sets_invalidated_[type]) {
invalidate_old_featured_sticker_sets(); invalidate_old_featured_sticker_sets(sticker_type);
} }
auto total_count = set_count + (old_featured_sticker_set_count_ == -1 ? 1 : old_featured_sticker_set_count_); auto total_count =
if (offset < total_count || old_featured_sticker_set_count_ == -1) { set_count + (old_featured_sticker_set_count_[type] == -1 ? 1 : old_featured_sticker_set_count_[type]);
if (offset < total_count || old_featured_sticker_set_count_[type] == -1) {
offset -= set_count; offset -= set_count;
set_count = static_cast<int32>(old_featured_sticker_set_ids_.size()); set_count = static_cast<int32>(old_featured_sticker_set_ids_[type].size());
if (offset < set_count) { if (offset < set_count) {
if (limit > set_count - offset) { if (limit > set_count - offset) {
limit = set_count - offset; limit = set_count - offset;
} }
promise.set_value(Unit()); promise.set_value(Unit());
auto begin = old_featured_sticker_set_ids_.begin() + offset; auto begin = old_featured_sticker_set_ids_[type].begin() + offset;
return get_trending_sticker_sets_object({begin, begin + limit}); return get_trending_sticker_sets_object(sticker_type, {begin, begin + limit});
} }
if (offset > set_count) { if (offset > set_count) {
promise.set_error( promise.set_error(
@ -5463,17 +5501,22 @@ td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_featured_st
return {}; return {};
} }
load_old_featured_sticker_sets(std::move(promise)); load_old_featured_sticker_sets(sticker_type, std::move(promise));
return {}; return {};
} }
promise.set_value(Unit()); promise.set_value(Unit());
return get_trending_sticker_sets_object({}); return get_trending_sticker_sets_object(sticker_type, {});
} }
void StickersManager::on_old_featured_sticker_sets_invalidated() { void StickersManager::on_old_featured_sticker_sets_invalidated(StickerType sticker_type) {
if (sticker_type != StickerType::Regular) {
return;
}
auto type = static_cast<int32>(sticker_type);
LOG(INFO) << "Invalidate old trending sticker sets"; LOG(INFO) << "Invalidate old trending sticker sets";
are_old_featured_sticker_sets_invalidated_ = true; are_old_featured_sticker_sets_invalidated_[type] = true;
if (!G()->parameters().use_file_db) { if (!G()->parameters().use_file_db) {
return; return;
@ -5482,32 +5525,40 @@ void StickersManager::on_old_featured_sticker_sets_invalidated() {
G()->td_db()->get_binlog_pmc()->set("invalidate_old_featured_sticker_sets", "1"); G()->td_db()->get_binlog_pmc()->set("invalidate_old_featured_sticker_sets", "1");
} }
void StickersManager::invalidate_old_featured_sticker_sets() { void StickersManager::invalidate_old_featured_sticker_sets(StickerType sticker_type) {
if (G()->close_flag()) { if (G()->close_flag()) {
return; return;
} }
if (sticker_type != StickerType::Regular) {
return;
}
auto type = static_cast<int32>(sticker_type);
LOG(INFO) << "Invalidate old featured sticker sets"; LOG(INFO) << "Invalidate old featured sticker sets";
if (G()->parameters().use_file_db) { if (G()->parameters().use_file_db) {
G()->td_db()->get_binlog_pmc()->erase("invalidate_old_featured_sticker_sets"); G()->td_db()->get_binlog_pmc()->erase("invalidate_old_featured_sticker_sets");
G()->td_db()->get_sqlite_pmc()->erase_by_prefix("sssoldfeatured", Auto()); G()->td_db()->get_sqlite_pmc()->erase_by_prefix("sssoldfeatured", Auto());
} }
are_old_featured_sticker_sets_invalidated_ = false; are_old_featured_sticker_sets_invalidated_[type] = false;
old_featured_sticker_set_ids_.clear(); old_featured_sticker_set_ids_[type].clear();
old_featured_sticker_set_generation_++; old_featured_sticker_set_generation_[type]++;
fail_promises(load_old_featured_sticker_sets_queries_, Status::Error(400, "Trending sticker sets were updated")); fail_promises(load_old_featured_sticker_sets_queries_, Status::Error(400, "Trending sticker sets were updated"));
} }
void StickersManager::set_old_featured_sticker_set_count(int32 count) { void StickersManager::set_old_featured_sticker_set_count(StickerType sticker_type, int32 count) {
if (old_featured_sticker_set_count_ == count) { auto type = static_cast<int32>(sticker_type);
if (old_featured_sticker_set_count_[type] == count) {
return;
}
if (sticker_type != StickerType::Regular) {
return; return;
} }
on_old_featured_sticker_sets_invalidated(); on_old_featured_sticker_sets_invalidated(sticker_type);
old_featured_sticker_set_count_ = count; old_featured_sticker_set_count_[type] = count;
need_update_featured_sticker_sets_ = true; need_update_featured_sticker_sets_[type] = true;
if (!G()->parameters().use_file_db) { if (!G()->parameters().use_file_db) {
return; return;
@ -5517,52 +5568,54 @@ void StickersManager::set_old_featured_sticker_set_count(int32 count) {
G()->td_db()->get_binlog_pmc()->set("old_featured_sticker_set_count", to_string(count)); G()->td_db()->get_binlog_pmc()->set("old_featured_sticker_set_count", to_string(count));
} }
void StickersManager::fix_old_featured_sticker_set_count() { void StickersManager::fix_old_featured_sticker_set_count(StickerType sticker_type) {
auto known_count = static_cast<int32>(old_featured_sticker_set_ids_.size()); auto type = static_cast<int32>(sticker_type);
if (old_featured_sticker_set_count_ < known_count) { auto known_count = static_cast<int32>(old_featured_sticker_set_ids_[type].size());
if (old_featured_sticker_set_count_ >= 0) { if (old_featured_sticker_set_count_[type] < known_count) {
LOG(ERROR) << "Have old trending sticker set count " << old_featured_sticker_set_count_ << ", but have " if (old_featured_sticker_set_count_[type] >= 0) {
LOG(ERROR) << "Have old trending sticker set count " << old_featured_sticker_set_count_[type] << ", but have "
<< known_count << " old trending sticker sets"; << known_count << " old trending sticker sets";
} }
set_old_featured_sticker_set_count(known_count); set_old_featured_sticker_set_count(sticker_type, known_count);
} }
if (old_featured_sticker_set_count_ > known_count && known_count % OLD_FEATURED_STICKER_SET_SLICE_SIZE != 0) { if (old_featured_sticker_set_count_[type] > known_count && known_count % OLD_FEATURED_STICKER_SET_SLICE_SIZE != 0) {
LOG(ERROR) << "Have " << known_count << " old sticker sets out of " << old_featured_sticker_set_count_; LOG(ERROR) << "Have " << known_count << " old sticker sets out of " << old_featured_sticker_set_count_[type];
set_old_featured_sticker_set_count(known_count); set_old_featured_sticker_set_count(sticker_type, known_count);
} }
} }
void StickersManager::on_get_featured_sticker_sets( void StickersManager::on_get_featured_sticker_sets(
int32 offset, int32 limit, uint32 generation, StickerType sticker_type, int32 offset, int32 limit, uint32 generation,
tl_object_ptr<telegram_api::messages_FeaturedStickers> &&sticker_sets_ptr) { tl_object_ptr<telegram_api::messages_FeaturedStickers> &&sticker_sets_ptr) {
auto type = static_cast<int32>(sticker_type);
if (offset < 0) { if (offset < 0) {
next_featured_sticker_sets_load_time_ = Time::now_cached() + Random::fast(30 * 60, 50 * 60); next_featured_sticker_sets_load_time_[type] = Time::now_cached() + Random::fast(30 * 60, 50 * 60);
} }
int32 constructor_id = sticker_sets_ptr->get_id(); int32 constructor_id = sticker_sets_ptr->get_id();
if (constructor_id == telegram_api::messages_featuredStickersNotModified::ID) { if (constructor_id == telegram_api::messages_featuredStickersNotModified::ID) {
LOG(INFO) << "Trending sticker sets are not modified"; LOG(INFO) << "Trending sticker sets are not modified";
auto *stickers = static_cast<const telegram_api::messages_featuredStickersNotModified *>(sticker_sets_ptr.get()); auto *stickers = static_cast<const telegram_api::messages_featuredStickersNotModified *>(sticker_sets_ptr.get());
if (offset >= 0 && generation == old_featured_sticker_set_generation_) { if (offset >= 0 && generation == old_featured_sticker_set_generation_[type]) {
set_old_featured_sticker_set_count(stickers->count_); set_old_featured_sticker_set_count(sticker_type, stickers->count_);
fix_old_featured_sticker_set_count(); fix_old_featured_sticker_set_count(sticker_type);
} }
send_update_featured_sticker_sets(); send_update_featured_sticker_sets(sticker_type);
return; return;
} }
CHECK(constructor_id == telegram_api::messages_featuredStickers::ID); CHECK(constructor_id == telegram_api::messages_featuredStickers::ID);
auto featured_stickers = move_tl_object_as<telegram_api::messages_featuredStickers>(sticker_sets_ptr); auto featured_stickers = move_tl_object_as<telegram_api::messages_featuredStickers>(sticker_sets_ptr);
if (featured_stickers->premium_ != are_featured_sticker_sets_premium_) { if (featured_stickers->premium_ != are_featured_sticker_sets_premium_[type]) {
on_old_featured_sticker_sets_invalidated(); on_old_featured_sticker_sets_invalidated(sticker_type);
if (offset >= 0) { if (offset >= 0) {
featured_stickers->premium_ = are_featured_sticker_sets_premium_; featured_stickers->premium_ = are_featured_sticker_sets_premium_[type];
reload_featured_sticker_sets(true); reload_featured_sticker_sets(sticker_type, true);
} }
} }
if (offset >= 0 && generation == old_featured_sticker_set_generation_) { if (offset >= 0 && generation == old_featured_sticker_set_generation_[type]) {
set_old_featured_sticker_set_count(featured_stickers->count_); set_old_featured_sticker_set_count(sticker_type, featured_stickers->count_);
// the count will be fixed in on_load_old_featured_sticker_sets_finished // the count will be fixed in on_load_old_featured_sticker_sets_finished
} }
@ -5597,90 +5650,98 @@ void StickersManager::on_get_featured_sticker_sets(
send_update_installed_sticker_sets(); send_update_installed_sticker_sets();
if (offset >= 0) { if (offset >= 0) {
if (generation == old_featured_sticker_set_generation_) { if (generation == old_featured_sticker_set_generation_[type] && sticker_type == StickerType::Regular) {
if (G()->parameters().use_file_db && !G()->close_flag()) { if (G()->parameters().use_file_db && !G()->close_flag()) {
LOG(INFO) << "Save old trending sticker sets to database with offset " << old_featured_sticker_set_ids_.size(); LOG(INFO) << "Save old trending sticker sets to database with offset "
CHECK(old_featured_sticker_set_ids_.size() % OLD_FEATURED_STICKER_SET_SLICE_SIZE == 0); << old_featured_sticker_set_ids_[type].size();
CHECK(old_featured_sticker_set_ids_[type].size() % OLD_FEATURED_STICKER_SET_SLICE_SIZE == 0);
StickerSetListLogEvent log_event(featured_sticker_set_ids, false); StickerSetListLogEvent log_event(featured_sticker_set_ids, false);
G()->td_db()->get_sqlite_pmc()->set(PSTRING() << "sssoldfeatured" << old_featured_sticker_set_ids_.size(), G()->td_db()->get_sqlite_pmc()->set(PSTRING() << "sssoldfeatured" << old_featured_sticker_set_ids_[type].size(),
log_event_store(log_event).as_slice().str(), Auto()); log_event_store(log_event).as_slice().str(), Auto());
} }
on_load_old_featured_sticker_sets_finished(generation, std::move(featured_sticker_set_ids)); on_load_old_featured_sticker_sets_finished(sticker_type, generation, std::move(featured_sticker_set_ids));
} }
send_update_featured_sticker_sets(); // because of changed count send_update_featured_sticker_sets(sticker_type); // because of changed count
return; return;
} }
on_load_featured_sticker_sets_finished(std::move(featured_sticker_set_ids), featured_stickers->premium_); on_load_featured_sticker_sets_finished(sticker_type, std::move(featured_sticker_set_ids),
featured_stickers->premium_);
LOG_IF(ERROR, featured_sticker_sets_hash_ != featured_stickers->hash_) << "Trending sticker sets hash mismatch"; LOG_IF(ERROR, featured_sticker_sets_hash_[type] != featured_stickers->hash_) << "Trending sticker sets hash mismatch";
if (!G()->parameters().use_file_db || G()->close_flag()) { if (!G()->parameters().use_file_db || G()->close_flag()) {
return; return;
} }
LOG(INFO) << "Save trending sticker sets to database"; LOG(INFO) << "Save trending sticker sets to database";
StickerSetListLogEvent log_event(featured_sticker_set_ids_, are_featured_sticker_sets_premium_); StickerSetListLogEvent log_event(featured_sticker_set_ids_[type], are_featured_sticker_sets_premium_[type]);
G()->td_db()->get_sqlite_pmc()->set("sssfeatured", log_event_store(log_event).as_slice().str(), Auto()); G()->td_db()->get_sqlite_pmc()->set(PSTRING() << "sssfeatured" << get_featured_sticker_suffix(sticker_type),
log_event_store(log_event).as_slice().str(), Auto());
} }
void StickersManager::on_get_featured_sticker_sets_failed(int32 offset, int32 limit, uint32 generation, Status error) { void StickersManager::on_get_featured_sticker_sets_failed(StickerType sticker_type, int32 offset, int32 limit,
uint32 generation, Status error) {
auto type = static_cast<int32>(sticker_type);
CHECK(error.is_error()); CHECK(error.is_error());
if (offset >= 0) { if (offset >= 0) {
if (generation != old_featured_sticker_set_generation_) { if (generation != old_featured_sticker_set_generation_[type] || sticker_type != StickerType::Regular) {
return; return;
} }
fail_promises(load_old_featured_sticker_sets_queries_, std::move(error)); fail_promises(load_old_featured_sticker_sets_queries_, std::move(error));
} else { } else {
next_featured_sticker_sets_load_time_ = Time::now_cached() + Random::fast(5, 10); next_featured_sticker_sets_load_time_[type] = Time::now_cached() + Random::fast(5, 10);
fail_promises(load_featured_sticker_sets_queries_, std::move(error)); fail_promises(load_featured_sticker_sets_queries_[type], std::move(error));
} }
} }
void StickersManager::load_featured_sticker_sets(Promise<Unit> &&promise) { void StickersManager::load_featured_sticker_sets(StickerType sticker_type, Promise<Unit> &&promise) {
auto type = static_cast<int32>(sticker_type);
if (td_->auth_manager_->is_bot()) { if (td_->auth_manager_->is_bot()) {
are_featured_sticker_sets_loaded_ = true; are_featured_sticker_sets_loaded_[type] = true;
old_featured_sticker_set_count_ = 0; old_featured_sticker_set_count_[type] = 0;
} }
if (are_featured_sticker_sets_loaded_) { if (are_featured_sticker_sets_loaded_[type]) {
promise.set_value(Unit()); promise.set_value(Unit());
return; return;
} }
load_featured_sticker_sets_queries_.push_back(std::move(promise)); load_featured_sticker_sets_queries_[type].push_back(std::move(promise));
if (load_featured_sticker_sets_queries_.size() == 1u) { if (load_featured_sticker_sets_queries_[type].size() == 1u) {
if (G()->parameters().use_file_db) { if (G()->parameters().use_file_db) {
LOG(INFO) << "Trying to load trending sticker sets from database"; LOG(INFO) << "Trying to load trending sticker sets from database";
G()->td_db()->get_sqlite_pmc()->get("sssfeatured", PromiseCreator::lambda([](string value) { G()->td_db()->get_sqlite_pmc()->get(PSTRING() << "sssfeatured" << get_featured_sticker_suffix(sticker_type),
PromiseCreator::lambda([sticker_type](string value) {
send_closure(G()->stickers_manager(), send_closure(G()->stickers_manager(),
&StickersManager::on_load_featured_sticker_sets_from_database, &StickersManager::on_load_featured_sticker_sets_from_database,
std::move(value)); sticker_type, std::move(value));
})); }));
} else { } else {
LOG(INFO) << "Trying to load trending sticker sets from server"; LOG(INFO) << "Trying to load trending sticker sets from server";
reload_featured_sticker_sets(true); reload_featured_sticker_sets(sticker_type, true);
} }
} }
} }
void StickersManager::on_load_featured_sticker_sets_from_database(string value) { void StickersManager::on_load_featured_sticker_sets_from_database(StickerType sticker_type, string value) {
if (G()->close_flag()) { if (G()->close_flag()) {
return; return;
} }
if (value.empty()) { if (value.empty()) {
LOG(INFO) << "Trending sticker sets aren't found in database"; LOG(INFO) << "Trending " << sticker_type << " sticker sets aren't found in database";
reload_featured_sticker_sets(true); reload_featured_sticker_sets(sticker_type, true);
return; return;
} }
LOG(INFO) << "Successfully loaded trending sticker set list of size " << value.size() << " from database"; LOG(INFO) << "Successfully loaded trending " << sticker_type << " sticker set list of size " << value.size()
<< " from database";
StickerSetListLogEvent log_event; StickerSetListLogEvent log_event;
auto status = log_event_parse(log_event, value); auto status = log_event_parse(log_event, value);
if (status.is_error()) { if (status.is_error()) {
// can't happen unless database is broken // can't happen unless database is broken
LOG(ERROR) << "Can't load trending sticker set list: " << status << ' ' << format::as_hex_dump<4>(Slice(value)); LOG(ERROR) << "Can't load trending sticker set list: " << status << ' ' << format::as_hex_dump<4>(Slice(value));
return reload_featured_sticker_sets(true); return reload_featured_sticker_sets(sticker_type, true);
} }
vector<StickerSetId> sets_to_load; vector<StickerSetId> sets_to_load;
@ -5693,74 +5754,82 @@ void StickersManager::on_load_featured_sticker_sets_from_database(string value)
} }
load_sticker_sets_without_stickers( load_sticker_sets_without_stickers(
std::move(sets_to_load), PromiseCreator::lambda([sticker_set_ids = std::move(log_event.sticker_set_ids_), std::move(sets_to_load),
is_premium = log_event.is_premium_](Result<> result) mutable { PromiseCreator::lambda([sticker_type, sticker_set_ids = std::move(log_event.sticker_set_ids_),
is_premium = log_event.is_premium_](Result<> result) mutable {
if (result.is_ok()) { if (result.is_ok()) {
send_closure(G()->stickers_manager(), &StickersManager::on_load_featured_sticker_sets_finished, send_closure(G()->stickers_manager(), &StickersManager::on_load_featured_sticker_sets_finished, sticker_type,
std::move(sticker_set_ids), is_premium); std::move(sticker_set_ids), is_premium);
} else { } else {
send_closure(G()->stickers_manager(), &StickersManager::reload_featured_sticker_sets, true); send_closure(G()->stickers_manager(), &StickersManager::reload_featured_sticker_sets, sticker_type, true);
} }
})); }));
} }
void StickersManager::on_load_featured_sticker_sets_finished(vector<StickerSetId> &&featured_sticker_set_ids, void StickersManager::on_load_featured_sticker_sets_finished(StickerType sticker_type,
vector<StickerSetId> &&featured_sticker_set_ids,
bool is_premium) { bool is_premium) {
if (!featured_sticker_set_ids_.empty() && featured_sticker_set_ids != featured_sticker_set_ids_) { auto type = static_cast<int32>(sticker_type);
if (!featured_sticker_set_ids_[type].empty() && featured_sticker_set_ids != featured_sticker_set_ids_[type]) {
// always invalidate old featured sticker sets when current featured sticker sets change // always invalidate old featured sticker sets when current featured sticker sets change
on_old_featured_sticker_sets_invalidated(); on_old_featured_sticker_sets_invalidated(sticker_type);
} }
featured_sticker_set_ids_ = std::move(featured_sticker_set_ids); featured_sticker_set_ids_[type] = std::move(featured_sticker_set_ids);
are_featured_sticker_sets_premium_ = is_premium; are_featured_sticker_sets_premium_[type] = is_premium;
are_featured_sticker_sets_loaded_ = true; are_featured_sticker_sets_loaded_[type] = true;
need_update_featured_sticker_sets_ = true; need_update_featured_sticker_sets_[type] = true;
send_update_featured_sticker_sets(); send_update_featured_sticker_sets(sticker_type);
set_promises(load_featured_sticker_sets_queries_); set_promises(load_featured_sticker_sets_queries_[type]);
} }
void StickersManager::load_old_featured_sticker_sets(Promise<Unit> &&promise) { void StickersManager::load_old_featured_sticker_sets(StickerType sticker_type, Promise<Unit> &&promise) {
CHECK(sticker_type == StickerType::Regular);
CHECK(!td_->auth_manager_->is_bot()); CHECK(!td_->auth_manager_->is_bot());
CHECK(old_featured_sticker_set_ids_.size() % OLD_FEATURED_STICKER_SET_SLICE_SIZE == 0); auto type = static_cast<int32>(sticker_type);
CHECK(old_featured_sticker_set_ids_[type].size() % OLD_FEATURED_STICKER_SET_SLICE_SIZE == 0);
load_old_featured_sticker_sets_queries_.push_back(std::move(promise)); load_old_featured_sticker_sets_queries_.push_back(std::move(promise));
if (load_old_featured_sticker_sets_queries_.size() == 1u) { if (load_old_featured_sticker_sets_queries_.size() == 1u) {
if (G()->parameters().use_file_db) { if (G()->parameters().use_file_db) {
LOG(INFO) << "Trying to load old trending sticker sets from database with offset " LOG(INFO) << "Trying to load old trending sticker sets from database with offset "
<< old_featured_sticker_set_ids_.size(); << old_featured_sticker_set_ids_[type].size();
G()->td_db()->get_sqlite_pmc()->get( G()->td_db()->get_sqlite_pmc()->get(
PSTRING() << "sssoldfeatured" << old_featured_sticker_set_ids_.size(), PSTRING() << "sssoldfeatured" << old_featured_sticker_set_ids_[type].size(),
PromiseCreator::lambda([generation = old_featured_sticker_set_generation_](string value) { PromiseCreator::lambda([sticker_type, generation = old_featured_sticker_set_generation_[type]](string value) {
send_closure(G()->stickers_manager(), &StickersManager::on_load_old_featured_sticker_sets_from_database, send_closure(G()->stickers_manager(), &StickersManager::on_load_old_featured_sticker_sets_from_database,
generation, std::move(value)); sticker_type, generation, std::move(value));
})); }));
} else { } else {
LOG(INFO) << "Trying to load old trending sticker sets from server with offset " LOG(INFO) << "Trying to load old trending sticker sets from server with offset "
<< old_featured_sticker_set_ids_.size(); << old_featured_sticker_set_ids_[type].size();
reload_old_featured_sticker_sets(); reload_old_featured_sticker_sets(sticker_type);
} }
} }
} }
void StickersManager::on_load_old_featured_sticker_sets_from_database(uint32 generation, string value) { void StickersManager::on_load_old_featured_sticker_sets_from_database(StickerType sticker_type, uint32 generation,
string value) {
if (G()->close_flag()) { if (G()->close_flag()) {
return; return;
} }
if (generation != old_featured_sticker_set_generation_) { CHECK(sticker_type == StickerType::Regular);
auto type = static_cast<int32>(sticker_type);
if (generation != old_featured_sticker_set_generation_[type]) {
return; return;
} }
if (value.empty()) { if (value.empty()) {
LOG(INFO) << "Old trending sticker sets aren't found in database"; LOG(INFO) << "Old trending sticker sets aren't found in database";
return reload_old_featured_sticker_sets(); return reload_old_featured_sticker_sets(sticker_type);
} }
LOG(INFO) << "Successfully loaded old trending sticker set list of size " << value.size() LOG(INFO) << "Successfully loaded old trending sticker set list of size " << value.size()
<< " from database with offset " << old_featured_sticker_set_ids_.size(); << " from database with offset " << old_featured_sticker_set_ids_[type].size();
StickerSetListLogEvent log_event; StickerSetListLogEvent log_event;
auto status = log_event_parse(log_event, value); auto status = log_event_parse(log_event, value);
if (status.is_error()) { if (status.is_error()) {
// can't happen unless database is broken // can't happen unless database is broken
LOG(ERROR) << "Can't load old trending sticker set list: " << status << ' ' << format::as_hex_dump<4>(Slice(value)); LOG(ERROR) << "Can't load old trending sticker set list: " << status << ' ' << format::as_hex_dump<4>(Slice(value));
return reload_old_featured_sticker_sets(); return reload_old_featured_sticker_sets(sticker_type);
} }
CHECK(!log_event.is_premium_); CHECK(!log_event.is_premium_);
@ -5776,24 +5845,27 @@ void StickersManager::on_load_old_featured_sticker_sets_from_database(uint32 gen
load_sticker_sets_without_stickers( load_sticker_sets_without_stickers(
std::move(sets_to_load), std::move(sets_to_load),
PromiseCreator::lambda( PromiseCreator::lambda(
[generation, sticker_set_ids = std::move(log_event.sticker_set_ids_)](Result<> result) mutable { [sticker_type, generation, sticker_set_ids = std::move(log_event.sticker_set_ids_)](Result<> result) mutable {
if (result.is_ok()) { if (result.is_ok()) {
send_closure(G()->stickers_manager(), &StickersManager::on_load_old_featured_sticker_sets_finished, send_closure(G()->stickers_manager(), &StickersManager::on_load_old_featured_sticker_sets_finished,
generation, std::move(sticker_set_ids)); sticker_type, generation, std::move(sticker_set_ids));
} else { } else {
send_closure(G()->stickers_manager(), &StickersManager::reload_old_featured_sticker_sets, generation); send_closure(G()->stickers_manager(), &StickersManager::reload_old_featured_sticker_sets, sticker_type,
generation);
} }
})); }));
} }
void StickersManager::on_load_old_featured_sticker_sets_finished(uint32 generation, void StickersManager::on_load_old_featured_sticker_sets_finished(StickerType sticker_type, uint32 generation,
vector<StickerSetId> &&featured_sticker_set_ids) { vector<StickerSetId> &&featured_sticker_set_ids) {
if (generation != old_featured_sticker_set_generation_) { auto type = static_cast<int32>(sticker_type);
fix_old_featured_sticker_set_count(); // must never be needed if (generation != old_featured_sticker_set_generation_[type]) {
fix_old_featured_sticker_set_count(sticker_type); // must never be needed
return; return;
} }
append(old_featured_sticker_set_ids_, std::move(featured_sticker_set_ids)); CHECK(sticker_type == StickerType::Regular);
fix_old_featured_sticker_set_count(); append(old_featured_sticker_set_ids_[type], std::move(featured_sticker_set_ids));
fix_old_featured_sticker_set_count(sticker_type);
set_promises(load_old_featured_sticker_sets_queries_); set_promises(load_old_featured_sticker_sets_queries_);
} }
@ -6641,10 +6713,11 @@ int64 StickersManager::get_sticker_sets_hash(const vector<StickerSetId> &sticker
return get_vector_hash(numbers); return get_vector_hash(numbers);
} }
int64 StickersManager::get_featured_sticker_sets_hash() const { int64 StickersManager::get_featured_sticker_sets_hash(StickerType sticker_type) const {
auto type = static_cast<int32>(sticker_type);
vector<uint64> numbers; vector<uint64> numbers;
numbers.reserve(featured_sticker_set_ids_.size() * 2); numbers.reserve(featured_sticker_set_ids_[type].size() * 2);
for (auto sticker_set_id : featured_sticker_set_ids_) { for (auto sticker_set_id : featured_sticker_set_ids_[type]) {
const StickerSet *sticker_set = get_sticker_set(sticker_set_id); const StickerSet *sticker_set = get_sticker_set(sticker_set_id);
CHECK(sticker_set != nullptr); CHECK(sticker_set != nullptr);
CHECK(sticker_set->is_inited); CHECK(sticker_set->is_inited);
@ -6693,15 +6766,45 @@ void StickersManager::send_update_installed_sticker_sets(bool from_database) {
} }
} }
size_t StickersManager::get_max_featured_sticker_count(StickerType sticker_type) {
switch (sticker_type) {
case StickerType::Regular:
return 5;
case StickerType::Mask:
return 5;
case StickerType::Emoji:
return 16;
default:
UNREACHABLE();
return 0;
}
}
Slice StickersManager::get_featured_sticker_suffix(StickerType sticker_type) {
switch (sticker_type) {
case StickerType::Regular:
return Slice();
case StickerType::Mask:
return Slice("1");
case StickerType::Emoji:
return Slice("2");
default:
UNREACHABLE();
return Slice();
}
}
td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_trending_sticker_sets_object( td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_trending_sticker_sets_object(
const vector<StickerSetId> &sticker_set_ids) const { StickerType sticker_type, const vector<StickerSetId> &sticker_set_ids) const {
auto total_count = static_cast<int32>(featured_sticker_set_ids_.size()) + auto type = static_cast<int32>(sticker_type);
(old_featured_sticker_set_count_ == -1 ? 1 : old_featured_sticker_set_count_); auto total_count = static_cast<int32>(featured_sticker_set_ids_[type].size()) +
(old_featured_sticker_set_count_[type] == -1 ? 1 : old_featured_sticker_set_count_[type]);
vector<tl_object_ptr<td_api::stickerSetInfo>> result; vector<tl_object_ptr<td_api::stickerSetInfo>> result;
result.reserve(sticker_set_ids.size()); result.reserve(sticker_set_ids.size());
for (auto sticker_set_id : sticker_set_ids) { for (auto sticker_set_id : sticker_set_ids) {
auto sticker_set_info = get_sticker_set_info_object(sticker_set_id, 5, are_featured_sticker_sets_premium_); auto sticker_set_info = get_sticker_set_info_object(sticker_set_id, get_max_featured_sticker_count(sticker_type),
are_featured_sticker_sets_premium_[type]);
if (sticker_set_info->size_ != 0) { if (sticker_set_info->size_ != 0) {
result.push_back(std::move(sticker_set_info)); result.push_back(std::move(sticker_set_info));
} }
@ -6710,20 +6813,24 @@ td_api::object_ptr<td_api::trendingStickerSets> StickersManager::get_trending_st
auto result_size = narrow_cast<int32>(result.size()); auto result_size = narrow_cast<int32>(result.size());
CHECK(total_count >= result_size); CHECK(total_count >= result_size);
return td_api::make_object<td_api::trendingStickerSets>(total_count, std::move(result), return td_api::make_object<td_api::trendingStickerSets>(total_count, std::move(result),
are_featured_sticker_sets_premium_); are_featured_sticker_sets_premium_[type]);
} }
td_api::object_ptr<td_api::updateTrendingStickerSets> StickersManager::get_update_trending_sticker_sets_object() const { td_api::object_ptr<td_api::updateTrendingStickerSets> StickersManager::get_update_trending_sticker_sets_object(
StickerType sticker_type) const {
auto type = static_cast<int32>(sticker_type);
return td_api::make_object<td_api::updateTrendingStickerSets>( return td_api::make_object<td_api::updateTrendingStickerSets>(
get_trending_sticker_sets_object(featured_sticker_set_ids_)); get_sticker_type_object(sticker_type),
get_trending_sticker_sets_object(sticker_type, featured_sticker_set_ids_[type]));
} }
void StickersManager::send_update_featured_sticker_sets() { void StickersManager::send_update_featured_sticker_sets(StickerType sticker_type) {
if (need_update_featured_sticker_sets_) { auto type = static_cast<int32>(sticker_type);
need_update_featured_sticker_sets_ = false; if (need_update_featured_sticker_sets_[type]) {
featured_sticker_sets_hash_ = get_featured_sticker_sets_hash(); need_update_featured_sticker_sets_[type] = false;
featured_sticker_sets_hash_[type] = get_featured_sticker_sets_hash(sticker_type);
send_closure(G()->td(), &Td::send_update, get_update_trending_sticker_sets_object()); send_closure(G()->td(), &Td::send_update, get_update_trending_sticker_sets_object(sticker_type));
} }
} }
@ -7997,10 +8104,11 @@ void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update
if (are_installed_sticker_sets_loaded_[type]) { if (are_installed_sticker_sets_loaded_[type]) {
updates.push_back(get_update_installed_sticker_sets_object(static_cast<StickerType>(type))); updates.push_back(get_update_installed_sticker_sets_object(static_cast<StickerType>(type)));
} }
if (are_featured_sticker_sets_loaded_[type]) {
updates.push_back(get_update_trending_sticker_sets_object(static_cast<StickerType>(type)));
}
} }
if (are_featured_sticker_sets_loaded_) {
updates.push_back(get_update_trending_sticker_sets_object());
}
for (int is_attached = 0; is_attached < 2; is_attached++) { for (int is_attached = 0; is_attached < 2; is_attached++) {
if (are_recent_stickers_loaded_[is_attached]) { if (are_recent_stickers_loaded_[is_attached]) {
updates.push_back(get_update_recent_stickers_object(is_attached)); updates.push_back(get_update_recent_stickers_object(is_attached));

View File

@ -199,13 +199,14 @@ class StickersManager final : public Actor {
vector<tl_object_ptr<telegram_api::StickerSetCovered>> &&sticker_sets, vector<tl_object_ptr<telegram_api::StickerSetCovered>> &&sticker_sets,
int32 total_count); int32 total_count);
td_api::object_ptr<td_api::trendingStickerSets> get_featured_sticker_sets(int32 offset, int32 limit, td_api::object_ptr<td_api::trendingStickerSets> get_featured_sticker_sets(StickerType sticker_type, int32 offset,
Promise<Unit> &&promise); int32 limit, Promise<Unit> &&promise);
void on_get_featured_sticker_sets(int32 offset, int32 limit, uint32 generation, void on_get_featured_sticker_sets(StickerType sticker_type, int32 offset, int32 limit, uint32 generation,
tl_object_ptr<telegram_api::messages_FeaturedStickers> &&sticker_sets_ptr); tl_object_ptr<telegram_api::messages_FeaturedStickers> &&sticker_sets_ptr);
void on_get_featured_sticker_sets_failed(int32 offset, int32 limit, uint32 generation, Status error); void on_get_featured_sticker_sets_failed(StickerType sticker_type, int32 offset, int32 limit, uint32 generation,
Status error);
vector<StickerSetId> get_attached_sticker_sets(FileId file_id, Promise<Unit> &&promise); vector<StickerSetId> get_attached_sticker_sets(FileId file_id, Promise<Unit> &&promise);
@ -303,7 +304,7 @@ class StickersManager final : public Actor {
void reload_installed_sticker_sets(StickerType sticker_type, bool force); void reload_installed_sticker_sets(StickerType sticker_type, bool force);
void reload_featured_sticker_sets(bool force); void reload_featured_sticker_sets(StickerType sticker_type, bool force);
void reload_recent_stickers(bool is_attached, bool force); void reload_recent_stickers(bool is_attached, bool force);
@ -572,15 +573,15 @@ class StickersManager final : public Actor {
int64 get_sticker_sets_hash(const vector<StickerSetId> &sticker_set_ids) const; int64 get_sticker_sets_hash(const vector<StickerSetId> &sticker_set_ids) const;
int64 get_featured_sticker_sets_hash() const; int64 get_featured_sticker_sets_hash(StickerType sticker_type) const;
int64 get_recent_stickers_hash(const vector<FileId> &sticker_ids) const; int64 get_recent_stickers_hash(const vector<FileId> &sticker_ids) const;
void load_installed_sticker_sets(StickerType sticker_type, Promise<Unit> &&promise); void load_installed_sticker_sets(StickerType sticker_type, Promise<Unit> &&promise);
void load_featured_sticker_sets(Promise<Unit> &&promise); void load_featured_sticker_sets(StickerType sticker_type, Promise<Unit> &&promise);
void load_old_featured_sticker_sets(Promise<Unit> &&promise); void load_old_featured_sticker_sets(StickerType sticker_type, Promise<Unit> &&promise);
void load_recent_stickers(bool is_attached, Promise<Unit> &&promise); void load_recent_stickers(bool is_attached, Promise<Unit> &&promise);
@ -590,13 +591,14 @@ class StickersManager final : public Actor {
vector<StickerSetId> &&installed_sticker_set_ids, vector<StickerSetId> &&installed_sticker_set_ids,
bool from_database = false); bool from_database = false);
void on_load_featured_sticker_sets_from_database(string value); void on_load_featured_sticker_sets_from_database(StickerType sticker_type, string value);
void on_load_featured_sticker_sets_finished(vector<StickerSetId> &&featured_sticker_set_ids, bool is_premium); void on_load_featured_sticker_sets_finished(StickerType sticker_type, vector<StickerSetId> &&featured_sticker_set_ids,
bool is_premium);
void on_load_old_featured_sticker_sets_from_database(uint32 generation, string value); void on_load_old_featured_sticker_sets_from_database(StickerType sticker_type, uint32 generation, string value);
void on_load_old_featured_sticker_sets_finished(uint32 generation, void on_load_old_featured_sticker_sets_finished(StickerType sticker_type, uint32 generation,
vector<StickerSetId> &&old_featured_sticker_set_ids); vector<StickerSetId> &&old_featured_sticker_set_ids);
void on_load_recent_stickers_from_database(bool is_attached, string value); void on_load_recent_stickers_from_database(bool is_attached, string value);
@ -609,24 +611,29 @@ class StickersManager final : public Actor {
void send_update_installed_sticker_sets(bool from_database = false); void send_update_installed_sticker_sets(bool from_database = false);
void reload_old_featured_sticker_sets(uint32 generation = 0); void reload_old_featured_sticker_sets(StickerType sticker_type, uint32 generation = 0);
void on_old_featured_sticker_sets_invalidated(); void on_old_featured_sticker_sets_invalidated(StickerType sticker_type);
void invalidate_old_featured_sticker_sets(); void invalidate_old_featured_sticker_sets(StickerType sticker_type);
void set_old_featured_sticker_set_count(int32 count); void set_old_featured_sticker_set_count(StickerType sticker_type, int32 count);
// must be called after every call to set_old_featured_sticker_set_count or // must be called after every call to set_old_featured_sticker_set_count or
// any change of old_featured_sticker_set_ids_ size // any change of old_featured_sticker_set_ids_ size
void fix_old_featured_sticker_set_count(); void fix_old_featured_sticker_set_count(StickerType sticker_type);
static size_t get_max_featured_sticker_count(StickerType sticker_type);
static Slice get_featured_sticker_suffix(StickerType sticker_type);
td_api::object_ptr<td_api::trendingStickerSets> get_trending_sticker_sets_object( td_api::object_ptr<td_api::trendingStickerSets> get_trending_sticker_sets_object(
const vector<StickerSetId> &sticker_set_ids) const; StickerType sticker_type, const vector<StickerSetId> &sticker_set_ids) const;
td_api::object_ptr<td_api::updateTrendingStickerSets> get_update_trending_sticker_sets_object() const; td_api::object_ptr<td_api::updateTrendingStickerSets> get_update_trending_sticker_sets_object(
StickerType sticker_type) const;
void send_update_featured_sticker_sets(); void send_update_featured_sticker_sets(StickerType sticker_type);
td_api::object_ptr<td_api::updateRecentStickers> get_update_recent_stickers_object(int is_attached) const; td_api::object_ptr<td_api::updateRecentStickers> get_update_recent_stickers_object(int is_attached) const;
@ -801,36 +808,36 @@ class StickersManager final : public Actor {
FlatHashMap<string, StickerSetId> short_name_to_sticker_set_id_; FlatHashMap<string, StickerSetId> short_name_to_sticker_set_id_;
vector<StickerSetId> installed_sticker_set_ids_[MAX_STICKER_TYPE]; vector<StickerSetId> installed_sticker_set_ids_[MAX_STICKER_TYPE];
vector<StickerSetId> featured_sticker_set_ids_; vector<StickerSetId> featured_sticker_set_ids_[MAX_STICKER_TYPE];
vector<StickerSetId> old_featured_sticker_set_ids_; vector<StickerSetId> old_featured_sticker_set_ids_[MAX_STICKER_TYPE];
vector<FileId> recent_sticker_ids_[2]; vector<FileId> recent_sticker_ids_[2];
vector<FileId> favorite_sticker_ids_; vector<FileId> favorite_sticker_ids_;
double next_installed_sticker_sets_load_time_[MAX_STICKER_TYPE] = {0, 0, 0}; double next_installed_sticker_sets_load_time_[MAX_STICKER_TYPE] = {0, 0, 0};
double next_featured_sticker_sets_load_time_ = 0; double next_featured_sticker_sets_load_time_[MAX_STICKER_TYPE] = {0, 0, 0};
double next_recent_stickers_load_time_[2] = {0, 0}; double next_recent_stickers_load_time_[2] = {0, 0};
double next_favorite_stickers_load_time_ = 0; double next_favorite_stickers_load_time_ = 0;
int64 installed_sticker_sets_hash_[MAX_STICKER_TYPE] = {0, 0, 0}; int64 installed_sticker_sets_hash_[MAX_STICKER_TYPE] = {0, 0, 0};
int64 featured_sticker_sets_hash_ = 0; int64 featured_sticker_sets_hash_[MAX_STICKER_TYPE] = {0, 0, 0};
int64 recent_stickers_hash_[2] = {0, 0}; int64 recent_stickers_hash_[2] = {0, 0};
int32 old_featured_sticker_set_count_ = -1; int32 old_featured_sticker_set_count_[MAX_STICKER_TYPE] = {-1, 0, 0};
uint32 old_featured_sticker_set_generation_ = 1; uint32 old_featured_sticker_set_generation_[MAX_STICKER_TYPE] = {1, 0, 0};
bool need_update_installed_sticker_sets_[MAX_STICKER_TYPE] = {false, false, false}; bool need_update_installed_sticker_sets_[MAX_STICKER_TYPE] = {false, false, false};
bool need_update_featured_sticker_sets_ = false; bool need_update_featured_sticker_sets_[MAX_STICKER_TYPE] = {false, false, false};
bool are_installed_sticker_sets_loaded_[MAX_STICKER_TYPE] = {false, false, false}; bool are_installed_sticker_sets_loaded_[MAX_STICKER_TYPE] = {false, false, false};
bool are_featured_sticker_sets_loaded_ = false; bool are_featured_sticker_sets_loaded_[MAX_STICKER_TYPE] = {false, true, false};
bool are_recent_stickers_loaded_[2] = {false, false}; bool are_recent_stickers_loaded_[2] = {false, false};
bool are_favorite_stickers_loaded_ = false; bool are_favorite_stickers_loaded_ = false;
bool are_featured_sticker_sets_premium_ = false; bool are_featured_sticker_sets_premium_[MAX_STICKER_TYPE] = {false, false, false};
bool are_old_featured_sticker_sets_invalidated_ = false; bool are_old_featured_sticker_sets_invalidated_[MAX_STICKER_TYPE] = {false, false, false};
vector<Promise<Unit>> load_installed_sticker_sets_queries_[MAX_STICKER_TYPE]; vector<Promise<Unit>> load_installed_sticker_sets_queries_[MAX_STICKER_TYPE];
vector<Promise<Unit>> load_featured_sticker_sets_queries_; vector<Promise<Unit>> load_featured_sticker_sets_queries_[MAX_STICKER_TYPE];
vector<Promise<Unit>> load_old_featured_sticker_sets_queries_; vector<Promise<Unit>> load_old_featured_sticker_sets_queries_;
vector<Promise<Unit>> load_recent_stickers_queries_[2]; vector<Promise<Unit>> load_recent_stickers_queries_[2];
vector<Promise<Unit>> repair_recent_stickers_queries_[2]; vector<Promise<Unit>> repair_recent_stickers_queries_[2];

View File

@ -168,7 +168,8 @@ FileId StickersManager::parse_sticker(bool in_sticker_set, ParserT &parser) {
template <class StorerT> template <class StorerT>
void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with_stickers, StorerT &storer, void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with_stickers, StorerT &storer,
const char *source) const { const char *source) const {
size_t stickers_limit = with_stickers ? sticker_set->sticker_ids.size() : 5; size_t stickers_limit =
with_stickers ? sticker_set->sticker_ids.size() : get_max_featured_sticker_count(sticker_set->sticker_type);
bool is_full = sticker_set->sticker_ids.size() <= stickers_limit; bool is_full = sticker_set->sticker_ids.size() <= stickers_limit;
bool was_loaded = sticker_set->was_loaded && is_full; bool was_loaded = sticker_set->was_loaded && is_full;
bool is_loaded = sticker_set->is_loaded && is_full; bool is_loaded = sticker_set->is_loaded && is_full;

View File

@ -2071,11 +2071,12 @@ class GetArchivedStickerSetsRequest final : public RequestActor<> {
class GetTrendingStickerSetsRequest final : public RequestActor<> { class GetTrendingStickerSetsRequest final : public RequestActor<> {
td_api::object_ptr<td_api::trendingStickerSets> result_; td_api::object_ptr<td_api::trendingStickerSets> result_;
StickerType sticker_type_;
int32 offset_; int32 offset_;
int32 limit_; int32 limit_;
void do_run(Promise<Unit> &&promise) final { void do_run(Promise<Unit> &&promise) final {
result_ = td_->stickers_manager_->get_featured_sticker_sets(offset_, limit_, std::move(promise)); result_ = td_->stickers_manager_->get_featured_sticker_sets(sticker_type_, offset_, limit_, std::move(promise));
} }
void do_send_result() final { void do_send_result() final {
@ -2083,8 +2084,9 @@ class GetTrendingStickerSetsRequest final : public RequestActor<> {
} }
public: public:
GetTrendingStickerSetsRequest(ActorShared<Td> td, uint64 request_id, int32 offset, int32 limit) GetTrendingStickerSetsRequest(ActorShared<Td> td, uint64 request_id, StickerType sticker_type, int32 offset,
: RequestActor(std::move(td), request_id), offset_(offset), limit_(limit) { int32 limit)
: RequestActor(std::move(td), request_id), sticker_type_(sticker_type), offset_(offset), limit_(limit) {
set_tries(3); set_tries(3);
} }
}; };
@ -4147,8 +4149,10 @@ void Td::send_update(tl_object_ptr<td_api::Update> &&object) {
VLOG(td_requests) << "Sending update: " << oneline(to_string(object)); VLOG(td_requests) << "Sending update: " << oneline(to_string(object));
break; break;
case td_api::updateTrendingStickerSets::ID: { case td_api::updateTrendingStickerSets::ID: {
auto sticker_sets = static_cast<const td_api::updateTrendingStickerSets *>(object.get())->sticker_sets_.get(); auto update = static_cast<const td_api::updateTrendingStickerSets *>(object.get());
VLOG(td_requests) << "Sending update: updateTrendingStickerSets { total_count = " << sticker_sets->total_count_ auto sticker_sets = update->sticker_sets_.get();
VLOG(td_requests) << "Sending update: updateTrendingStickerSets { " << oneline(to_string(update->sticker_type_))
<< ", total_count = " << sticker_sets->total_count_
<< ", count = " << sticker_sets->sets_.size() << " }"; << ", count = " << sticker_sets->sets_.size() << " }";
break; break;
} }
@ -7002,7 +7006,8 @@ void Td::on_request(uint64 id, const td_api::getArchivedStickerSets &request) {
void Td::on_request(uint64 id, const td_api::getTrendingStickerSets &request) { void Td::on_request(uint64 id, const td_api::getTrendingStickerSets &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CREATE_REQUEST(GetTrendingStickerSetsRequest, request.offset_, request.limit_); CREATE_REQUEST(GetTrendingStickerSetsRequest, get_sticker_type(request.sticker_type_), request.offset_,
request.limit_);
} }
void Td::on_request(uint64 id, const td_api::getAttachedStickerSets &request) { void Td::on_request(uint64 id, const td_api::getAttachedStickerSets &request) {

View File

@ -48,6 +48,7 @@
#include "td/telegram/StateManager.h" #include "td/telegram/StateManager.h"
#include "td/telegram/StickerSetId.h" #include "td/telegram/StickerSetId.h"
#include "td/telegram/StickersManager.h" #include "td/telegram/StickersManager.h"
#include "td/telegram/StickerType.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/TdDb.h" #include "td/telegram/TdDb.h"
@ -1674,10 +1675,11 @@ void UpdatesManager::try_reload_data() {
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel,
Auto()); Auto());
td_->stickers_manager_->reload_reactions(); td_->stickers_manager_->reload_reactions();
td_->stickers_manager_->get_installed_sticker_sets(StickerType::Regular, Auto()); for (int32 type = 0; type < MAX_STICKER_TYPE; type++) {
td_->stickers_manager_->get_installed_sticker_sets(StickerType::Mask, Auto()); auto sticker_type = static_cast<StickerType>(type);
td_->stickers_manager_->get_installed_sticker_sets(StickerType::Emoji, Auto()); td_->stickers_manager_->get_installed_sticker_sets(sticker_type, Auto());
td_->stickers_manager_->get_featured_sticker_sets(0, 1000, Auto()); td_->stickers_manager_->get_featured_sticker_sets(sticker_type, 0, 1000, Auto());
}
td_->stickers_manager_->get_recent_stickers(false, Auto()); td_->stickers_manager_->get_recent_stickers(false, Auto());
td_->stickers_manager_->get_recent_stickers(true, Auto()); td_->stickers_manager_->get_recent_stickers(true, Auto());
td_->stickers_manager_->get_favorite_stickers(Auto()); td_->stickers_manager_->get_favorite_stickers(Auto());
@ -3329,7 +3331,13 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateStickerSetsOrde
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateReadFeaturedStickers> update, void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateReadFeaturedStickers> update,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
td_->stickers_manager_->reload_featured_sticker_sets(true); td_->stickers_manager_->reload_featured_sticker_sets(StickerType::Regular, true);
promise.set_value(Unit());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateReadFeaturedEmojiStickers> update,
Promise<Unit> &&promise) {
td_->stickers_manager_->reload_featured_sticker_sets(StickerType::Emoji, true);
promise.set_value(Unit()); promise.set_value(Unit());
} }
@ -3521,9 +3529,4 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateTranscribedAudi
// unsupported updates // unsupported updates
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateReadFeaturedEmojiStickers> update,
Promise<Unit> &&promise) {
promise.set_value(Unit());
}
} // namespace td } // namespace td

View File

@ -487,6 +487,7 @@ class UpdatesManager final : public Actor {
void on_update(tl_object_ptr<telegram_api::updateStickerSets> update, Promise<Unit> &&promise); void on_update(tl_object_ptr<telegram_api::updateStickerSets> update, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateStickerSetsOrder> update, Promise<Unit> &&promise); void on_update(tl_object_ptr<telegram_api::updateStickerSetsOrder> update, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadFeaturedStickers> update, Promise<Unit> &&promise); void on_update(tl_object_ptr<telegram_api::updateReadFeaturedStickers> update, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadFeaturedEmojiStickers> update, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateRecentStickers> update, Promise<Unit> &&promise); void on_update(tl_object_ptr<telegram_api::updateRecentStickers> update, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotShippingQuery> update, Promise<Unit> &&promise); void on_update(tl_object_ptr<telegram_api::updateBotShippingQuery> update, Promise<Unit> &&promise);
@ -531,8 +532,6 @@ class UpdatesManager final : public Actor {
void on_update(tl_object_ptr<telegram_api::updateTranscribedAudio> update, Promise<Unit> &&promise); void on_update(tl_object_ptr<telegram_api::updateTranscribedAudio> update, Promise<Unit> &&promise);
// unsupported updates // unsupported updates
void on_update(tl_object_ptr<telegram_api::updateReadFeaturedEmojiStickers> update, Promise<Unit> &&promise);
}; };
} // namespace td } // namespace td

View File

@ -2630,11 +2630,12 @@ class CliClient final : public Actor {
get_args(args, offset_sticker_set_id, limit); get_args(args, offset_sticker_set_id, limit);
send_request(td_api::make_object<td_api::getArchivedStickerSets>(as_sticker_type(op), offset_sticker_set_id, send_request(td_api::make_object<td_api::getArchivedStickerSets>(as_sticker_type(op), offset_sticker_set_id,
as_limit(limit))); as_limit(limit)));
} else if (op == "gtss") { } else if (op == "gtss" || op == "gtssm" || op == "gtsse") {
int32 offset; int32 offset;
string limit; string limit;
get_args(args, offset, limit); get_args(args, offset, limit);
send_request(td_api::make_object<td_api::getTrendingStickerSets>(offset, as_limit(limit, 1000))); send_request(
td_api::make_object<td_api::getTrendingStickerSets>(as_sticker_type(op), offset, as_limit(limit, 1000)));
} else if (op == "gatss") { } else if (op == "gatss") {
FileId file_id; FileId file_id;
get_args(args, file_id); get_args(args, file_id);