Support mixed-format sticker sets.

This commit is contained in:
levlam 2024-03-15 15:24:59 +03:00
parent c4ceac218f
commit ce124d1a40
5 changed files with 69 additions and 80 deletions

View File

@ -3505,14 +3505,13 @@ emojis emojis:vector<string> = Emojis;
//@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
//@sticker_format Format of the stickers in the set
//@sticker_type Type of the stickers in the set
//@needs_repainting True, if stickers in the sticker set are custom emoji that must be repainted; for custom emoji sticker sets only
//@is_allowed_as_chat_emoji_status True, if stickers in the sticker set are custom emoji that can be used as chat emoji status; for custom emoji sticker sets only
//@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. 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:thumbnail thumbnail_outline:vector<closedVectorPath> is_installed:Bool is_archived:Bool is_official:Bool sticker_format:StickerFormat sticker_type:StickerType needs_repainting:Bool is_allowed_as_chat_emoji_status:Bool is_viewed:Bool stickers:vector<sticker> emojis:vector<emojis> = StickerSet;
stickerSet id:int64 title:string name:string thumbnail:thumbnail thumbnail_outline:vector<closedVectorPath> is_installed:Bool is_archived:Bool is_official:Bool sticker_type:StickerType needs_repainting:Bool is_allowed_as_chat_emoji_status:Bool is_viewed:Bool stickers:vector<sticker> emojis:vector<emojis> = StickerSet;
//@description Represents short information about a sticker set
//@id Identifier of the sticker set
@ -3523,14 +3522,13 @@ stickerSet id:int64 title:string name:string thumbnail:thumbnail thumbnail_outli
//@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
//@sticker_format Format of the stickers in the set
//@sticker_type Type of the stickers in the set
//@needs_repainting True, if stickers in the sticker set are custom emoji that must be repainted; for custom emoji sticker sets only
//@is_allowed_as_chat_emoji_status True, if stickers in the sticker set are custom emoji that can be used as chat emoji status; for custom emoji sticker sets only
//@is_viewed True for already viewed trending sticker sets
//@size Total number of stickers in the set
//@covers Up to the first 5 stickers from the set, depending on the context. If the application needs more stickers the full sticker set needs to be requested
stickerSetInfo id:int64 title:string name:string thumbnail:thumbnail thumbnail_outline:vector<closedVectorPath> is_installed:Bool is_archived:Bool is_official:Bool sticker_format:StickerFormat sticker_type:StickerType needs_repainting:Bool is_allowed_as_chat_emoji_status:Bool is_viewed:Bool size:int32 covers:vector<sticker> = StickerSetInfo;
stickerSetInfo id:int64 title:string name:string thumbnail:thumbnail thumbnail_outline:vector<closedVectorPath> is_installed:Bool is_archived:Bool is_official:Bool sticker_type:StickerType needs_repainting:Bool is_allowed_as_chat_emoji_status:Bool is_viewed:Bool size:int32 covers:vector<sticker> = StickerSetInfo;
//@description Represents a list of sticker sets @total_count Approximate total number of sticker sets found @sets List of sticker sets
stickerSets total_count:int32 sets:vector<stickerSetInfo> = StickerSets;

View File

@ -242,6 +242,16 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
res.type = 0;
}
}
if (format == PhotoFormat::Tgs) {
if (res.type == 's') {
format = PhotoFormat::Webp;
} else if (res.type == 'v') {
format = PhotoFormat::Webm;
} else if (res.type != 'a') {
LOG(ERROR) << "Receive sticker set thumbnail of type " << res.type;
format = PhotoFormat::Webp;
}
}
if (source.get_type("get_photo_size") == PhotoSizeSource::Type::Thumbnail) {
source.thumbnail().thumbnail_type = res.type;
}

View File

@ -1053,7 +1053,7 @@ class CreateNewStickerSetQuery final : public Td::ResultHandler {
}
void send(tl_object_ptr<telegram_api::InputUser> &&input_user, const string &title, const string &short_name,
StickerType sticker_type, bool has_text_color, StickerFormat sticker_format,
StickerType sticker_type, bool has_text_color,
vector<tl_object_ptr<telegram_api::inputStickerSetItem>> &&input_stickers, const string &software) {
CHECK(input_user != nullptr);
@ -2438,24 +2438,33 @@ int32 StickersManager::get_dice_success_animation_frame_number(const string &emo
return result.first == value ? result.second : std::numeric_limits<int32>::max();
}
PhotoFormat StickersManager::get_sticker_set_thumbnail_format(StickerFormat sticker_format) {
switch (sticker_format) {
case StickerFormat::Unknown:
return PhotoFormat::Webp;
case StickerFormat::Webp:
return PhotoFormat::Webp;
case StickerFormat::Tgs:
return PhotoFormat::Tgs;
case StickerFormat::Webm:
return PhotoFormat::Webm;
default:
UNREACHABLE();
return PhotoFormat::Webp;
PhotoFormat StickersManager::get_sticker_set_thumbnail_format(const StickerSet *sticker_set) const {
if (sticker_set->thumbnail_document_id_ != 0 && sticker_set->sticker_type_ == StickerType::CustomEmoji) {
for (auto sticker_id : sticker_set->sticker_ids_) {
auto file_view = td_->file_manager_->get_file_view(sticker_id);
if (file_view.has_remote_location() && !file_view.remote_location().is_web() &&
file_view.remote_location().get_id() == sticker_set->thumbnail_document_id_) {
const Sticker *s = get_sticker(sticker_id);
CHECK(s != nullptr);
return get_sticker_format_photo_format(s->format_);
}
}
}
auto type = sticker_set->thumbnail_.type;
if (type == 's') {
return PhotoFormat::Webp;
}
if (type == 'v') {
return PhotoFormat::Webm;
}
if (type == 'a') {
return PhotoFormat::Tgs;
}
return PhotoFormat::Tgs;
}
double StickersManager::get_sticker_set_minithumbnail_zoom(const StickerSet *sticker_set) {
if (sticker_set->sticker_format_ == StickerFormat::Tgs) {
double StickersManager::get_sticker_set_minithumbnail_zoom(const StickerSet *sticker_set) const {
if (get_sticker_set_thumbnail_format(sticker_set) == PhotoFormat::Tgs) {
return 100.0 / 512.0;
}
return 1.0;
@ -2470,7 +2479,7 @@ td_api::object_ptr<td_api::thumbnail> StickersManager::get_sticker_set_thumbnail
if (file_view.has_remote_location() && !file_view.remote_location().is_web() &&
file_view.remote_location().get_id() == sticker_set->thumbnail_document_id_) {
const Sticker *s = get_sticker(sticker_id);
auto thumbnail_format = get_sticker_set_thumbnail_format(s->format_);
auto thumbnail_format = get_sticker_format_photo_format(s->format_);
PhotoSize thumbnail;
thumbnail.type = 't';
thumbnail.size = static_cast<int32>(file_view.size());
@ -2480,7 +2489,7 @@ td_api::object_ptr<td_api::thumbnail> StickersManager::get_sticker_set_thumbnail
}
}
}
auto thumbnail_format = get_sticker_set_thumbnail_format(sticker_set->sticker_format_);
auto thumbnail_format = get_sticker_set_thumbnail_format(sticker_set);
return get_thumbnail_object(td_->file_manager_.get(), sticker_set->thumbnail_, thumbnail_format);
}
@ -2508,9 +2517,8 @@ tl_object_ptr<td_api::stickerSet> StickersManager::get_sticker_set_object(Sticke
get_sticker_minithumbnail(sticker_set->minithumbnail_, sticker_set->id_, -2,
get_sticker_set_minithumbnail_zoom(sticker_set)),
sticker_set->is_installed_ && !sticker_set->is_archived_, sticker_set->is_archived_, sticker_set->is_official_,
get_sticker_format_object(sticker_set->sticker_format_), get_sticker_type_object(sticker_set->sticker_type_),
sticker_set->has_text_color_, sticker_set->channel_emoji_status_, sticker_set->is_viewed_, std::move(stickers),
std::move(emojis));
get_sticker_type_object(sticker_set->sticker_type_), sticker_set->has_text_color_,
sticker_set->channel_emoji_status_, sticker_set->is_viewed_, std::move(stickers), std::move(emojis));
}
tl_object_ptr<td_api::stickerSets> StickersManager::get_sticker_sets_object(int32 total_count,
@ -2585,8 +2593,8 @@ tl_object_ptr<td_api::stickerSetInfo> StickersManager::get_sticker_set_info_obje
get_sticker_minithumbnail(sticker_set->minithumbnail_, sticker_set->id_, -3,
get_sticker_set_minithumbnail_zoom(sticker_set)),
sticker_set->is_installed_ && !sticker_set->is_archived_, sticker_set->is_archived_, sticker_set->is_official_,
get_sticker_format_object(sticker_set->sticker_format_), get_sticker_type_object(sticker_set->sticker_type_),
sticker_set->has_text_color_, sticker_set->channel_emoji_status_, sticker_set->is_viewed_,
get_sticker_type_object(sticker_set->sticker_type_), sticker_set->has_text_color_,
sticker_set->channel_emoji_status_, sticker_set->is_viewed_,
sticker_set->was_loaded_ ? actual_count : max(actual_count, sticker_set->sticker_count_), std::move(stickers));
}
@ -3591,7 +3599,6 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
bool is_official = set->official_;
bool has_text_color = set->emojis_ && set->text_color_;
bool channel_emoji_status = set->emojis_ && set->channel_emoji_status_;
StickerFormat sticker_format = StickerFormat::Webp;
StickerType sticker_type =
set->emojis_ ? StickerType::CustomEmoji : (set->masks_ ? StickerType::Mask : StickerType::Regular);
@ -3601,8 +3608,7 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
auto photo_size =
get_photo_size(td_->file_manager_.get(),
PhotoSizeSource::sticker_set_thumbnail(set_id.get(), s->access_hash_, set->thumb_version_), 0, 0,
"", DcId::create(set->thumb_dc_id_), DialogId(), std::move(thumbnail_ptr),
get_sticker_set_thumbnail_format(sticker_format));
"", DcId::create(set->thumb_dc_id_), DialogId(), std::move(thumbnail_ptr), PhotoFormat::Tgs);
if (photo_size.get_offset() == 0) {
if (!thumbnail.file_id.is_valid()) {
thumbnail = std::move(photo_size.get<0>());
@ -3626,7 +3632,6 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
s->sticker_count_ = set->count_;
s->hash_ = set->hash_;
s->is_official_ = is_official;
s->sticker_format_ = sticker_format;
s->sticker_type_ = sticker_type;
s->has_text_color_ = has_text_color;
s->channel_emoji_status_ = channel_emoji_status;
@ -3710,12 +3715,6 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
s->channel_emoji_status_ = channel_emoji_status;
s->is_changed_ = true;
}
if (s->sticker_format_ != sticker_format) {
LOG(ERROR) << "Format of stickers in " << set_id << '/' << s->short_name_ << " has changed from "
<< s->sticker_format_ << " to " << sticker_format << " from " << source;
s->sticker_format_ = sticker_format;
s->is_changed_ = true;
}
LOG_IF(ERROR, s->sticker_type_ != sticker_type)
<< "Type of " << set_id << '/' << s->short_name_ << " has changed from " << s->sticker_type_ << " to "
<< sticker_type << " from " << source;
@ -3753,7 +3752,7 @@ StickerSetId StickersManager::on_get_sticker_set_covered(tl_object_ptr<telegram_
auto &sticker_ids = sticker_set->sticker_ids_;
auto sticker_id = on_get_sticker_document(std::move(covered_set->cover_), sticker_set->sticker_format_).second;
auto sticker_id = on_get_sticker_document(std::move(covered_set->cover_), StickerFormat::Unknown).second;
if (sticker_id.is_valid() && !td::contains(sticker_ids, sticker_id)) {
sticker_ids.push_back(sticker_id);
sticker_set->is_changed_ = true;
@ -3777,7 +3776,7 @@ StickerSetId StickersManager::on_get_sticker_set_covered(tl_object_ptr<telegram_
auto &sticker_ids = sticker_set->sticker_ids_;
for (auto &cover : multicovered_set->covers_) {
auto sticker_id = on_get_sticker_document(std::move(cover), sticker_set->sticker_format_).second;
auto sticker_id = on_get_sticker_document(std::move(cover), StickerFormat::Unknown).second;
if (sticker_id.is_valid() && !td::contains(sticker_ids, sticker_id)) {
sticker_ids.push_back(sticker_id);
sticker_set->is_changed_ = true;
@ -3859,7 +3858,7 @@ StickerSetId StickersManager::on_get_messages_sticker_set(StickerSetId sticker_s
s->premium_sticker_positions_.clear();
bool is_bot = td_->auth_manager_->is_bot();
for (auto &document_ptr : set->documents_) {
auto sticker_id = on_get_sticker_document(std::move(document_ptr), s->sticker_format_);
auto sticker_id = on_get_sticker_document(std::move(document_ptr), StickerFormat::Unknown);
if (!sticker_id.second.is_valid() || sticker_id.first == 0) {
continue;
}
@ -4405,16 +4404,16 @@ vector<FileId> StickersManager::get_stickers(StickerType sticker_type, string qu
examined_sticker_sets.push_back(sticker_set);
}
}
std::stable_sort(
examined_sticker_sets.begin(), examined_sticker_sets.end(), [](const StickerSet *lhs, const StickerSet *rhs) {
if (lhs->is_installed_ != rhs->is_installed_) {
return lhs->is_installed_;
}
if (lhs->is_archived_ != rhs->is_archived_) {
return lhs->is_archived_;
}
return is_sticker_format_animated(lhs->sticker_format_) && !is_sticker_format_animated(rhs->sticker_format_);
});
std::stable_sort(examined_sticker_sets.begin(), examined_sticker_sets.end(),
[](const StickerSet *lhs, const StickerSet *rhs) {
if (lhs->is_installed_ != rhs->is_installed_) {
return lhs->is_installed_;
}
if (lhs->is_archived_ != rhs->is_archived_) {
return lhs->is_archived_;
}
return false;
});
for (auto sticker_set : examined_sticker_sets) {
find_sticker_set_stickers(sticker_set, emojis, prepared_query, result);
}
@ -8147,7 +8146,6 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
auto &promise = pending_new_sticker_set->promise_;
TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(pending_new_sticker_set->user_id_));
StickerFormat sticker_format = pending_new_sticker_set->sticker_format_;
StickerType sticker_type = pending_new_sticker_set->sticker_type_;
auto sticker_count = pending_new_sticker_set->stickers_.size();
@ -8160,8 +8158,7 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
td_->create_handler<CreateNewStickerSetQuery>(std::move(promise))
->send(std::move(input_user), pending_new_sticker_set->title_, pending_new_sticker_set->short_name_, sticker_type,
pending_new_sticker_set->has_text_color_, sticker_format, std::move(input_stickers),
pending_new_sticker_set->software_);
pending_new_sticker_set->has_text_color_, std::move(input_stickers), pending_new_sticker_set->software_);
}
void StickersManager::add_sticker_to_set(UserId user_id, string short_name,
@ -8202,7 +8199,7 @@ void StickersManager::do_add_sticker_to_set(UserId user_id, string short_name,
return promise.set_error(Status::Error(400, "Sticker set not found"));
}
auto r_file_id = prepare_input_sticker(sticker.get(), sticker_set->sticker_format_, sticker_set->sticker_type_);
auto r_file_id = prepare_input_sticker(sticker.get(), StickerFormat::Webp, sticker_set->sticker_type_);
if (r_file_id.is_error()) {
return promise.set_error(r_file_id.move_as_error());
}
@ -8298,7 +8295,7 @@ void StickersManager::do_set_sticker_set_thumbnail(UserId user_id, string short_
Status::Error(400, "The method can't be used to set thumbnail of custom emoji sticker sets"));
}
auto r_file_id = prepare_input_file(thumbnail, sticker_set->sticker_format_, sticker_set->sticker_type_, true);
auto r_file_id = prepare_input_file(thumbnail, StickerFormat::Webp, sticker_set->sticker_type_, true);
if (r_file_id.is_error()) {
return promise.set_error(r_file_id.move_as_error());
}

View File

@ -482,7 +482,6 @@ class StickersManager final : public Actor {
int64 access_hash_ = 0;
string title_;
string short_name_;
StickerFormat sticker_format_ = StickerFormat::Unknown;
StickerType sticker_type_ = StickerType::Regular;
int32 sticker_count_ = 0;
int32 hash_ = 0;
@ -591,7 +590,9 @@ class StickersManager final : public Actor {
StickerSetId sticker_set_id,
int64 document_id, double zoom);
static double get_sticker_set_minithumbnail_zoom(const StickerSet *sticker_set);
PhotoFormat get_sticker_set_thumbnail_format(const StickerSet *sticker_set) const;
double get_sticker_set_minithumbnail_zoom(const StickerSet *sticker_set) const;
td_api::object_ptr<td_api::thumbnail> get_sticker_set_thumbnail_object(const StickerSet *sticker_set) const;
@ -651,8 +652,6 @@ class StickersManager final : public Actor {
StickerSet *add_sticker_set(StickerSetId sticker_set_id, int64 access_hash);
static PhotoFormat get_sticker_set_thumbnail_format(StickerFormat sticker_format);
static tl_object_ptr<telegram_api::InputStickerSet> get_input_sticker_set(const StickerSet *set);
StickerSetId on_get_input_sticker_set(FileId sticker_file_id, tl_object_ptr<telegram_api::InputStickerSet> &&set_ptr,

View File

@ -176,8 +176,6 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
bool has_expires_at = !sticker_set->is_installed_ && sticker_set->expires_at_ != 0;
bool has_thumbnail = sticker_set->thumbnail_.file_id.is_valid();
bool has_minithumbnail = !sticker_set->minithumbnail_.empty();
bool is_tgs = sticker_set->sticker_format_ == StickerFormat::Tgs;
bool is_webm = sticker_set->sticker_format_ == StickerFormat::Webm;
bool is_masks = sticker_set->sticker_type_ == StickerType::Mask;
bool is_emojis = sticker_set->sticker_type_ == StickerType::CustomEmoji;
bool has_thumbnail_document_id = sticker_set->thumbnail_document_id_ != 0;
@ -193,10 +191,10 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
STORE_FLAG(has_expires_at);
STORE_FLAG(has_thumbnail);
STORE_FLAG(sticker_set->is_thumbnail_reloaded_);
STORE_FLAG(is_tgs);
STORE_FLAG(false);
STORE_FLAG(sticker_set->are_legacy_sticker_thumbnails_reloaded_);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(is_webm);
STORE_FLAG(false);
STORE_FLAG(is_emojis);
STORE_FLAG(has_thumbnail_document_id);
STORE_FLAG(sticker_set->are_keywords_loaded_);
@ -262,9 +260,9 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
bool is_masks;
bool has_expires_at;
bool has_thumbnail;
bool is_tgs;
bool legacy_is_tgs;
bool has_minithumbnail;
bool is_webm;
bool legacy_is_webm;
bool is_emojis;
bool has_thumbnail_document_id;
bool has_text_color;
@ -281,10 +279,10 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
PARSE_FLAG(has_expires_at);
PARSE_FLAG(has_thumbnail);
PARSE_FLAG(sticker_set->is_thumbnail_reloaded_);
PARSE_FLAG(is_tgs);
PARSE_FLAG(legacy_is_tgs);
PARSE_FLAG(sticker_set->are_legacy_sticker_thumbnails_reloaded_);
PARSE_FLAG(has_minithumbnail);
PARSE_FLAG(is_webm);
PARSE_FLAG(legacy_is_webm);
PARSE_FLAG(is_emojis);
PARSE_FLAG(has_thumbnail_document_id);
PARSE_FLAG(sticker_set->are_keywords_loaded_);
@ -302,14 +300,6 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
}
(void)access_hash; // unused, because only known sticker sets with access hash can be loaded from database
StickerFormat sticker_format = StickerFormat::Unknown;
if (is_webm) {
sticker_format = StickerFormat::Webm;
} else if (is_tgs) {
sticker_format = StickerFormat::Tgs;
} else {
sticker_format = StickerFormat::Webp;
}
auto sticker_type = ::td::get_sticker_type(is_masks, is_emojis);
if (!is_emojis) {
sticker_set->is_sticker_has_text_color_loaded_ = true;
@ -353,7 +343,6 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
sticker_set->expires_at_ = expires_at;
sticker_set->is_official_ = is_official;
sticker_set->sticker_type_ = sticker_type;
sticker_set->sticker_format_ = sticker_format;
sticker_set->has_text_color_ = has_text_color;
sticker_set->channel_emoji_status_ = channel_emoji_status;
@ -378,10 +367,6 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
sticker_set->is_loaded_ = false;
sticker_set->is_changed_ = true;
}
if (sticker_set->sticker_format_ != sticker_format) {
LOG(ERROR) << "Sticker format of " << sticker_set->id_ << " has changed from \"" << sticker_format << "\" to \""
<< sticker_set->sticker_format_ << "\"";
}
if (sticker_set->sticker_type_ != sticker_type) {
LOG(ERROR) << "Type of " << sticker_set->id_ << " has changed from \"" << sticker_type << "\" to \""
<< sticker_set->sticker_type_ << "\"";