Support WEBM stickers.

This commit is contained in:
levlam 2022-01-25 14:58:04 +03:00
parent 0d2b1c2072
commit d6bb83dc0e
9 changed files with 202 additions and 98 deletions

View File

@ -191,31 +191,46 @@ photoSize type:string photo:file width:int32 height:int32 progressive_sizes:vect
minithumbnail width:int32 height:int32 data:bytes = Minithumbnail;
//@class ThumbnailFormat @description Describes format of the thumbnail
//@class ThumbnailFormat @description Describes format of a thumbnail
//@description The thumbnail is in JPEG format
thumbnailFormatJpeg = ThumbnailFormat;
//@description The thumbnail is in PNG format. It will be used only for background patterns
thumbnailFormatPng = ThumbnailFormat;
//@description The thumbnail is in WEBP format. It will be used only for some stickers
thumbnailFormatWebp = ThumbnailFormat;
//@description The thumbnail is in static GIF format. It will be used only for some bot inline results
thumbnailFormatGif = ThumbnailFormat;
//@description The thumbnail is in TGS format. It will be used only for animated sticker sets
thumbnailFormatTgs = ThumbnailFormat;
//@description The thumbnail is in MPEG4 format. It will be used only for some animations and videos
thumbnailFormatMpeg4 = ThumbnailFormat;
//@description The thumbnail is in PNG format. It will be used only for background patterns
thumbnailFormatPng = ThumbnailFormat;
//@description The thumbnail is in TGS format. It will be used only for TGS sticker sets
thumbnailFormatTgs = ThumbnailFormat;
//@description The thumbnail is in WEBM format. It will be used only for WEBM sticker sets
thumbnailFormatWebm = ThumbnailFormat;
//@description The thumbnail is in WEBP format. It will be used only for some stickers
thumbnailFormatWebp = ThumbnailFormat;
//@description Represents a thumbnail @format Thumbnail format @width Thumbnail width @height Thumbnail height @file The thumbnail
thumbnail format:ThumbnailFormat width:int32 height:int32 file:file = Thumbnail;
//@class StickerFormat @description Describes format of a sticker
//@description The sticker is in TGS format
stickerFormatTgs = StickerFormat;
//@description The sticker is in WEBM format
stickerFormatWebm = StickerFormat;
//@description The sticker is in WEBP format
stickerFormatWebp = StickerFormat;
//@class MaskPoint @description Part of the face, relative to which a mask is placed
//@description The mask is placed relatively to the forehead
@ -277,9 +292,9 @@ document file_name:string mime_type:string minithumbnail:minithumbnail thumbnail
photo has_stickers:Bool minithumbnail:minithumbnail sizes:vector<photoSize> = Photo;
//@description Describes a sticker @set_id The identifier of the sticker set to which the sticker belongs; 0 if none @width Sticker width; as defined by the sender @height Sticker height; as defined by the sender
//@emoji Emoji corresponding to the sticker @is_animated True, if the sticker is an animated sticker in TGS format @is_mask True, if the sticker is a mask @mask_position Position where the mask is placed; may be null
//@emoji Emoji corresponding to the sticker @format Sticker format @is_mask True, if the sticker is a mask @mask_position Position where the mask is placed; may be null
//@outline Sticker's outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner @thumbnail Sticker thumbnail in WEBP or JPEG format; may be null @sticker File containing the sticker
sticker set_id:int64 width:int32 height:int32 emoji:string is_animated:Bool is_mask:Bool mask_position:maskPosition outline:vector<closedVectorPath> thumbnail:thumbnail sticker:file = Sticker;
sticker set_id:int64 width:int32 height:int32 emoji:string format:StickerFormat is_mask:Bool mask_position:maskPosition outline:vector<closedVectorPath> thumbnail:thumbnail sticker:file = Sticker;
//@description Describes a video file @duration Duration of the video, in seconds; as defined by the sender @width Video width; as defined by the sender @height Video height; as defined by the sender
//@file_name Original name of the file; as defined by the sender @mime_type MIME type of the file; as defined by the sender
@ -2176,17 +2191,17 @@ emojis emojis:vector<string> = Emojis;
//@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP or TGS format with width and height 100; may be null. The file can be downloaded only before the thumbnail is changed
//@thumbnail_outline Sticker set thumbnail's outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner
//@is_installed True, if the sticker set has been installed by the current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
//@is_official True, if the sticker set is official @is_animated True, is the stickers in the set are animated @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
//@is_official True, if the sticker set is official @sticker_format Format of the stickers in the set @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
//@stickers List of stickers in this set @emojis A list of emoji corresponding to the stickers in the same order. 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 is_animated:Bool is_masks: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_format:StickerFormat is_masks: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 @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP or TGS format with width and height 100; may be null
//@thumbnail_outline Sticker set thumbnail's outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner
//@is_installed True, if the sticker set has been installed by the current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
//@is_official True, if the sticker set is official @is_animated True, is the stickers in the set are animated @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
//@is_official True, if the sticker set is official @sticker_format Format of the stickers in the set @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
//@size Total number of stickers in the set @covers 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 is_animated:Bool is_masks: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_format:StickerFormat is_masks: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

@ -236,16 +236,16 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
string url;
FileLocationSource source = FileLocationSource::FromServer;
auto fix_animated_sticker_type = [&] {
auto fix_tgs_sticker_type = [&] {
if (mime_type != "application/x-tgsticker") {
return;
}
sticker_format = StickerFormat::Tgs;
default_extension = Slice("tgs");
if (document_type == Document::Type::General) {
document_type = Document::Type::Sticker;
file_type = FileType::Sticker;
default_extension = Slice("tgs");
owner_dialog_id = DialogId();
file_name.clear();
thumbnail_format = PhotoFormat::Webp;
@ -262,10 +262,16 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
mime_type = std::move(document->mime_type_);
file_reference = document->file_reference_.as_slice().str();
if (document_type == Document::Type::Sticker && StickersManager::has_webp_thumbnail(document->thumbs_)) {
thumbnail_format = PhotoFormat::Webp;
if (document_type == Document::Type::Sticker) {
if (StickersManager::has_webp_thumbnail(document->thumbs_)) {
thumbnail_format = PhotoFormat::Webp;
}
if (mime_type == "video/webm") {
sticker_format = StickerFormat::Webm;
default_extension = Slice("webm");
}
}
fix_animated_sticker_type();
fix_tgs_sticker_type();
if (owner_dialog_id.get_type() == DialogType::SecretChat) {
// secret_api::decryptedMessageMediaExternalDocument
@ -316,8 +322,8 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
return {};
}
// do not allow encrypted animated stickers
// fix_animated_sticker_type();
// do not allow encrypted TGS stickers
// fix_tgs_sticker_type();
if (document_type != Document::Type::VoiceNote) {
thumbnail = get_secret_thumbnail_photo_size(td_->file_manager_.get(), std::move(document->thumb_),
@ -374,8 +380,8 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
UNREACHABLE();
}
// do not allow web animated stickers
// fix_animated_sticker_type();
// do not allow web TGS stickers
// fix_tgs_sticker_type();
}
LOG(DEBUG) << "Receive document with ID = " << id << " of type " << document_type;

View File

@ -592,7 +592,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe
id = std::move(sticker->id_);
thumbnail_url = std::move(sticker->thumbnail_url_);
content_url = std::move(sticker->sticker_url_);
content_type = "image/webp"; // or "application/x-tgsticker"; not used for previously uploaded files
content_type =
"image/webp"; // or "application/x-tgsticker"/"video/webm"; not used for previously uploaded files
width = sticker->sticker_width_;
height = sticker->sticker_height_;
is_gallery = true;
@ -936,13 +937,13 @@ td_api::object_ptr<td_api::file> copy(const td_api::file &obj) {
template <>
tl_object_ptr<td_api::minithumbnail> copy(const td_api::minithumbnail &obj) {
return make_tl_object<td_api::minithumbnail>(obj.width_, obj.height_, obj.data_);
return td_api::make_object<td_api::minithumbnail>(obj.width_, obj.height_, obj.data_);
}
template <>
tl_object_ptr<td_api::photoSize> copy(const td_api::photoSize &obj) {
return make_tl_object<td_api::photoSize>(obj.type_, copy(obj.photo_), obj.width_, obj.height_,
vector<int32>(obj.progressive_sizes_));
return td_api::make_object<td_api::photoSize>(obj.type_, copy(obj.photo_), obj.width_, obj.height_,
vector<int32>(obj.progressive_sizes_));
}
static tl_object_ptr<td_api::photoSize> copy_photo_size(const tl_object_ptr<td_api::photoSize> &obj) {
@ -971,20 +972,35 @@ tl_object_ptr<td_api::thumbnail> copy(const td_api::thumbnail &obj) {
}
}();
return make_tl_object<td_api::thumbnail>(std::move(format), obj.width_, obj.height_, copy(obj.file_));
return td_api::make_object<td_api::thumbnail>(std::move(format), obj.width_, obj.height_, copy(obj.file_));
}
template <>
tl_object_ptr<td_api::StickerFormat> copy(const td_api::StickerFormat &obj) {
switch (obj.get_id()) {
case td_api::stickerFormatWebp::ID:
return td_api::make_object<td_api::stickerFormatWebp>();
case td_api::stickerFormatTgs::ID:
return td_api::make_object<td_api::stickerFormatTgs>();
case td_api::stickerFormatWebm::ID:
return td_api::make_object<td_api::stickerFormatWebm>();
default:
UNREACHABLE();
}
return nullptr;
}
template <>
tl_object_ptr<td_api::MaskPoint> copy(const td_api::MaskPoint &obj) {
switch (obj.get_id()) {
case td_api::maskPointForehead::ID:
return make_tl_object<td_api::maskPointForehead>();
return td_api::make_object<td_api::maskPointForehead>();
case td_api::maskPointEyes::ID:
return make_tl_object<td_api::maskPointEyes>();
return td_api::make_object<td_api::maskPointEyes>();
case td_api::maskPointMouth::ID:
return make_tl_object<td_api::maskPointMouth>();
return td_api::make_object<td_api::maskPointMouth>();
case td_api::maskPointChin::ID:
return make_tl_object<td_api::maskPointChin>();
return td_api::make_object<td_api::maskPointChin>();
default:
UNREACHABLE();
}
@ -993,12 +1009,12 @@ tl_object_ptr<td_api::MaskPoint> copy(const td_api::MaskPoint &obj) {
template <>
tl_object_ptr<td_api::maskPosition> copy(const td_api::maskPosition &obj) {
return make_tl_object<td_api::maskPosition>(copy(obj.point_), obj.x_shift_, obj.y_shift_, obj.scale_);
return td_api::make_object<td_api::maskPosition>(copy(obj.point_), obj.x_shift_, obj.y_shift_, obj.scale_);
}
template <>
tl_object_ptr<td_api::point> copy(const td_api::point &obj) {
return make_tl_object<td_api::point>(obj.x_, obj.y_);
return td_api::make_object<td_api::point>(obj.x_, obj.y_);
}
template <>
@ -1006,11 +1022,11 @@ tl_object_ptr<td_api::VectorPathCommand> copy(const td_api::VectorPathCommand &o
switch (obj.get_id()) {
case td_api::vectorPathCommandLine::ID: {
auto &command = static_cast<const td_api::vectorPathCommandLine &>(obj);
return make_tl_object<td_api::vectorPathCommandLine>(copy(command.end_point_));
return td_api::make_object<td_api::vectorPathCommandLine>(copy(command.end_point_));
}
case td_api::vectorPathCommandCubicBezierCurve::ID: {
auto &command = static_cast<const td_api::vectorPathCommandCubicBezierCurve &>(obj);
return make_tl_object<td_api::vectorPathCommandCubicBezierCurve>(
return td_api::make_object<td_api::vectorPathCommandCubicBezierCurve>(
copy(command.start_control_point_), copy(command.end_control_point_), copy(command.end_point_));
}
default:
@ -1026,7 +1042,7 @@ static tl_object_ptr<td_api::VectorPathCommand> copy_vector_path_command(
template <>
tl_object_ptr<td_api::closedVectorPath> copy(const td_api::closedVectorPath &obj) {
return make_tl_object<td_api::closedVectorPath>(transform(obj.commands_, copy_vector_path_command));
return td_api::make_object<td_api::closedVectorPath>(transform(obj.commands_, copy_vector_path_command));
}
static tl_object_ptr<td_api::closedVectorPath> copy_closed_vector_path(
@ -1036,137 +1052,139 @@ static tl_object_ptr<td_api::closedVectorPath> copy_closed_vector_path(
template <>
tl_object_ptr<td_api::animation> copy(const td_api::animation &obj) {
return make_tl_object<td_api::animation>(obj.duration_, obj.width_, obj.height_, obj.file_name_, obj.mime_type_,
obj.has_stickers_, copy(obj.minithumbnail_), copy(obj.thumbnail_),
copy(obj.animation_));
return td_api::make_object<td_api::animation>(obj.duration_, obj.width_, obj.height_, obj.file_name_, obj.mime_type_,
obj.has_stickers_, copy(obj.minithumbnail_), copy(obj.thumbnail_),
copy(obj.animation_));
}
template <>
tl_object_ptr<td_api::audio> copy(const td_api::audio &obj) {
return make_tl_object<td_api::audio>(obj.duration_, obj.title_, obj.performer_, obj.file_name_, obj.mime_type_,
copy(obj.album_cover_minithumbnail_), copy(obj.album_cover_thumbnail_),
copy(obj.audio_));
return td_api::make_object<td_api::audio>(obj.duration_, obj.title_, obj.performer_, obj.file_name_, obj.mime_type_,
copy(obj.album_cover_minithumbnail_), copy(obj.album_cover_thumbnail_),
copy(obj.audio_));
}
template <>
tl_object_ptr<td_api::document> copy(const td_api::document &obj) {
return make_tl_object<td_api::document>(obj.file_name_, obj.mime_type_, copy(obj.minithumbnail_),
copy(obj.thumbnail_), copy(obj.document_));
return td_api::make_object<td_api::document>(obj.file_name_, obj.mime_type_, copy(obj.minithumbnail_),
copy(obj.thumbnail_), copy(obj.document_));
}
template <>
tl_object_ptr<td_api::photo> copy(const td_api::photo &obj) {
return make_tl_object<td_api::photo>(obj.has_stickers_, copy(obj.minithumbnail_),
transform(obj.sizes_, copy_photo_size));
return td_api::make_object<td_api::photo>(obj.has_stickers_, copy(obj.minithumbnail_),
transform(obj.sizes_, copy_photo_size));
}
template <>
tl_object_ptr<td_api::sticker> copy(const td_api::sticker &obj) {
return make_tl_object<td_api::sticker>(
obj.set_id_, obj.width_, obj.height_, obj.emoji_, obj.is_animated_, obj.is_mask_, copy(obj.mask_position_),
return td_api::make_object<td_api::sticker>(
obj.set_id_, obj.width_, obj.height_, obj.emoji_, copy(obj.format_), obj.is_mask_, copy(obj.mask_position_),
transform(obj.outline_, copy_closed_vector_path), copy(obj.thumbnail_), copy(obj.sticker_));
}
template <>
tl_object_ptr<td_api::video> copy(const td_api::video &obj) {
return make_tl_object<td_api::video>(obj.duration_, obj.width_, obj.height_, obj.file_name_, obj.mime_type_,
obj.has_stickers_, obj.supports_streaming_, copy(obj.minithumbnail_),
copy(obj.thumbnail_), copy(obj.video_));
return td_api::make_object<td_api::video>(obj.duration_, obj.width_, obj.height_, obj.file_name_, obj.mime_type_,
obj.has_stickers_, obj.supports_streaming_, copy(obj.minithumbnail_),
copy(obj.thumbnail_), copy(obj.video_));
}
template <>
tl_object_ptr<td_api::voiceNote> copy(const td_api::voiceNote &obj) {
return make_tl_object<td_api::voiceNote>(obj.duration_, obj.waveform_, obj.mime_type_, copy(obj.voice_));
return td_api::make_object<td_api::voiceNote>(obj.duration_, obj.waveform_, obj.mime_type_, copy(obj.voice_));
}
template <>
tl_object_ptr<td_api::contact> copy(const td_api::contact &obj) {
return make_tl_object<td_api::contact>(obj.phone_number_, obj.first_name_, obj.last_name_, obj.vcard_, obj.user_id_);
return td_api::make_object<td_api::contact>(obj.phone_number_, obj.first_name_, obj.last_name_, obj.vcard_,
obj.user_id_);
}
template <>
tl_object_ptr<td_api::location> copy(const td_api::location &obj) {
return make_tl_object<td_api::location>(obj.latitude_, obj.longitude_, obj.horizontal_accuracy_);
return td_api::make_object<td_api::location>(obj.latitude_, obj.longitude_, obj.horizontal_accuracy_);
}
template <>
tl_object_ptr<td_api::venue> copy(const td_api::venue &obj) {
return make_tl_object<td_api::venue>(copy(obj.location_), obj.title_, obj.address_, obj.provider_, obj.id_,
obj.type_);
return td_api::make_object<td_api::venue>(copy(obj.location_), obj.title_, obj.address_, obj.provider_, obj.id_,
obj.type_);
}
template <>
tl_object_ptr<td_api::formattedText> copy(const td_api::formattedText &obj) {
// there are no entities in the game text
return make_tl_object<td_api::formattedText>(obj.text_, vector<tl_object_ptr<td_api::textEntity>>());
return td_api::make_object<td_api::formattedText>(obj.text_, vector<tl_object_ptr<td_api::textEntity>>());
}
template <>
tl_object_ptr<td_api::game> copy(const td_api::game &obj) {
return make_tl_object<td_api::game>(obj.id_, obj.short_name_, obj.title_, copy(obj.text_), obj.description_,
copy(obj.photo_), copy(obj.animation_));
return td_api::make_object<td_api::game>(obj.id_, obj.short_name_, obj.title_, copy(obj.text_), obj.description_,
copy(obj.photo_), copy(obj.animation_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultArticle> copy(const td_api::inlineQueryResultArticle &obj) {
return make_tl_object<td_api::inlineQueryResultArticle>(obj.id_, obj.url_, obj.hide_url_, obj.title_,
obj.description_, copy(obj.thumbnail_));
return td_api::make_object<td_api::inlineQueryResultArticle>(obj.id_, obj.url_, obj.hide_url_, obj.title_,
obj.description_, copy(obj.thumbnail_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultContact> copy(const td_api::inlineQueryResultContact &obj) {
return make_tl_object<td_api::inlineQueryResultContact>(obj.id_, copy(obj.contact_), copy(obj.thumbnail_));
return td_api::make_object<td_api::inlineQueryResultContact>(obj.id_, copy(obj.contact_), copy(obj.thumbnail_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultLocation> copy(const td_api::inlineQueryResultLocation &obj) {
return make_tl_object<td_api::inlineQueryResultLocation>(obj.id_, copy(obj.location_), obj.title_,
copy(obj.thumbnail_));
return td_api::make_object<td_api::inlineQueryResultLocation>(obj.id_, copy(obj.location_), obj.title_,
copy(obj.thumbnail_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultVenue> copy(const td_api::inlineQueryResultVenue &obj) {
return make_tl_object<td_api::inlineQueryResultVenue>(obj.id_, copy(obj.venue_), copy(obj.thumbnail_));
return td_api::make_object<td_api::inlineQueryResultVenue>(obj.id_, copy(obj.venue_), copy(obj.thumbnail_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultGame> copy(const td_api::inlineQueryResultGame &obj) {
return make_tl_object<td_api::inlineQueryResultGame>(obj.id_, copy(obj.game_));
return td_api::make_object<td_api::inlineQueryResultGame>(obj.id_, copy(obj.game_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultAnimation> copy(const td_api::inlineQueryResultAnimation &obj) {
return make_tl_object<td_api::inlineQueryResultAnimation>(obj.id_, copy(obj.animation_), obj.title_);
return td_api::make_object<td_api::inlineQueryResultAnimation>(obj.id_, copy(obj.animation_), obj.title_);
}
template <>
tl_object_ptr<td_api::inlineQueryResultAudio> copy(const td_api::inlineQueryResultAudio &obj) {
return make_tl_object<td_api::inlineQueryResultAudio>(obj.id_, copy(obj.audio_));
return td_api::make_object<td_api::inlineQueryResultAudio>(obj.id_, copy(obj.audio_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultDocument> copy(const td_api::inlineQueryResultDocument &obj) {
return make_tl_object<td_api::inlineQueryResultDocument>(obj.id_, copy(obj.document_), obj.title_, obj.description_);
return td_api::make_object<td_api::inlineQueryResultDocument>(obj.id_, copy(obj.document_), obj.title_,
obj.description_);
}
template <>
tl_object_ptr<td_api::inlineQueryResultPhoto> copy(const td_api::inlineQueryResultPhoto &obj) {
return make_tl_object<td_api::inlineQueryResultPhoto>(obj.id_, copy(obj.photo_), obj.title_, obj.description_);
return td_api::make_object<td_api::inlineQueryResultPhoto>(obj.id_, copy(obj.photo_), obj.title_, obj.description_);
}
template <>
tl_object_ptr<td_api::inlineQueryResultSticker> copy(const td_api::inlineQueryResultSticker &obj) {
return make_tl_object<td_api::inlineQueryResultSticker>(obj.id_, copy(obj.sticker_));
return td_api::make_object<td_api::inlineQueryResultSticker>(obj.id_, copy(obj.sticker_));
}
template <>
tl_object_ptr<td_api::inlineQueryResultVideo> copy(const td_api::inlineQueryResultVideo &obj) {
return make_tl_object<td_api::inlineQueryResultVideo>(obj.id_, copy(obj.video_), obj.title_, obj.description_);
return td_api::make_object<td_api::inlineQueryResultVideo>(obj.id_, copy(obj.video_), obj.title_, obj.description_);
}
template <>
tl_object_ptr<td_api::inlineQueryResultVoiceNote> copy(const td_api::inlineQueryResultVoiceNote &obj) {
return make_tl_object<td_api::inlineQueryResultVoiceNote>(obj.id_, copy(obj.voice_note_), obj.title_);
return td_api::make_object<td_api::inlineQueryResultVoiceNote>(obj.id_, copy(obj.voice_note_), obj.title_);
}
static tl_object_ptr<td_api::InlineQueryResult> copy_result(const tl_object_ptr<td_api::InlineQueryResult> &obj_ptr) {
@ -1177,9 +1195,9 @@ static tl_object_ptr<td_api::InlineQueryResult> copy_result(const tl_object_ptr<
template <>
tl_object_ptr<td_api::inlineQueryResults> copy(const td_api::inlineQueryResults &obj) {
return make_tl_object<td_api::inlineQueryResults>(obj.inline_query_id_, obj.next_offset_,
transform(obj.results_, copy_result), obj.switch_pm_text_,
obj.switch_pm_parameter_);
return td_api::make_object<td_api::inlineQueryResults>(obj.inline_query_id_, obj.next_offset_,
transform(obj.results_, copy_result), obj.switch_pm_text_,
obj.switch_pm_parameter_);
}
tl_object_ptr<td_api::inlineQueryResults> InlineQueriesManager::decrease_pending_request_count(uint64 query_hash) {

View File

@ -109,6 +109,8 @@ static td_api::object_ptr<td_api::ThumbnailFormat> get_thumbnail_format_object(P
return td_api::make_object<td_api::thumbnailFormatTgs>();
case PhotoFormat::Mpeg4:
return td_api::make_object<td_api::thumbnailFormatMpeg4>();
case PhotoFormat::Webm:
return td_api::make_object<td_api::thumbnailFormatWebm>();
default:
UNREACHABLE();
return nullptr;
@ -129,6 +131,8 @@ static StringBuilder &operator<<(StringBuilder &string_builder, PhotoFormat form
return string_builder << "tgs";
case PhotoFormat::Mpeg4:
return string_builder << "mp4";
case PhotoFormat::Webm:
return string_builder << "webm";
default:
UNREACHABLE();
return string_builder;
@ -408,7 +412,7 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
}
case telegram_api::photoPathSize::ID: {
auto size = move_tl_object_as<telegram_api::photoPathSize>(size_ptr);
if (format != PhotoFormat::Tgs && format != PhotoFormat::Webp) {
if (format != PhotoFormat::Tgs && format != PhotoFormat::Webp && format != PhotoFormat::Webm) {
LOG(ERROR) << "Receive unexpected SVG minithumbnail in photo " << id << " from " << source << " of format "
<< format;
return std::move(res);

View File

@ -107,7 +107,7 @@ bool operator!=(const DialogPhoto &lhs, const DialogPhoto &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const DialogPhoto &dialog_photo);
enum class PhotoFormat : int32 { Jpeg, Png, Webp, Gif, Tgs, Mpeg4 };
enum class PhotoFormat : int32 { Jpeg, Png, Webp, Gif, Tgs, Mpeg4, Webm };
PhotoSize get_secret_thumbnail_photo_size(FileManager *file_manager, BufferSlice bytes, DialogId owner_dialog_id,
int32 width, int32 height);

View File

@ -6,6 +6,8 @@
//
#include "td/telegram/StickerFormat.h"
#include "td/utils/logging.h"
namespace td {
StickerFormat get_sticker_format(Slice mime_type) {
@ -15,9 +17,29 @@ StickerFormat get_sticker_format(Slice mime_type) {
if (mime_type == "image/webp") {
return StickerFormat::Webp;
}
if (mime_type == "video/webm") {
return StickerFormat::Webm;
}
return StickerFormat::Unknown;
}
td_api::object_ptr<td_api::StickerFormat> get_sticker_format_object(StickerFormat sticker_format) {
switch (sticker_format) {
case StickerFormat::Unknown:
LOG(ERROR) << "Have a sticker of unknown format";
return td_api::make_object<td_api::stickerFormatWebp>();
case StickerFormat::Webp:
return td_api::make_object<td_api::stickerFormatWebp>();
case StickerFormat::Tgs:
return td_api::make_object<td_api::stickerFormatTgs>();
case StickerFormat::Webm:
return td_api::make_object<td_api::stickerFormatWebm>();
default:
UNREACHABLE();
return nullptr;
}
}
string get_sticker_format_mime_type(StickerFormat sticker_format) {
switch (sticker_format) {
case StickerFormat::Unknown:
@ -25,6 +47,8 @@ string get_sticker_format_mime_type(StickerFormat sticker_format) {
return "image/webp";
case StickerFormat::Tgs:
return "application/x-tgsticker";
case StickerFormat::Webm:
return "video/webm";
default:
UNREACHABLE();
return string();
@ -39,6 +63,8 @@ Slice get_sticker_format_extension(StickerFormat sticker_format) {
return Slice(".webp");
case StickerFormat::Tgs:
return Slice(".tgs");
case StickerFormat::Webm:
return Slice(".webm");
default:
UNREACHABLE();
return Slice();
@ -53,6 +79,8 @@ bool is_sticker_format_animated(StickerFormat sticker_format) {
return false;
case StickerFormat::Tgs:
return true;
case StickerFormat::Webm:
return true;
default:
UNREACHABLE();
return false;
@ -67,6 +95,8 @@ bool is_sticker_format_vector(StickerFormat sticker_format) {
return false;
case StickerFormat::Tgs:
return true;
case StickerFormat::Webm:
return false;
default:
UNREACHABLE();
return false;
@ -80,6 +110,8 @@ int64 get_max_sticker_file_size(StickerFormat sticker_format, bool for_thumbnail
return for_thumbnail ? (1 << 17) : (1 << 19);
case StickerFormat::Tgs:
return for_thumbnail ? (1 << 15) : (1 << 16);
case StickerFormat::Webm:
return for_thumbnail ? (1 << 17) : (1 << 18);
default:
UNREACHABLE();
return 0;
@ -94,6 +126,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, StickerFormat sticker_f
return string_builder << "WEBP";
case StickerFormat::Tgs:
return string_builder << "TGS";
case StickerFormat::Webm:
return string_builder << "WEBM";
default:
UNREACHABLE();
return string_builder;

View File

@ -6,6 +6,8 @@
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/StringBuilder.h"
@ -13,10 +15,12 @@
namespace td {
// update store_sticker/store_sticker_set when this type changes
enum class StickerFormat : int32 { Unknown, Webp, Tgs };
enum class StickerFormat : int32 { Unknown, Webp, Tgs, Webm };
StickerFormat get_sticker_format(Slice mime_type);
td_api::object_ptr<td_api::StickerFormat> get_sticker_format_object(StickerFormat sticker_format);
string get_sticker_format_mime_type(StickerFormat sticker_format);
Slice get_sticker_format_extension(StickerFormat sticker_format);

View File

@ -1008,13 +1008,16 @@ class CreateNewStickerSetQuery final : public Td::ResultHandler {
if (sticker_format == StickerFormat::Tgs) {
flags |= telegram_api::stickers_createStickerSet::ANIMATED_MASK;
}
if (sticker_format == StickerFormat::Webm) {
flags |= telegram_api::stickers_createStickerSet::GIFS_MASK;
}
if (!software.empty()) {
flags |= telegram_api::stickers_createStickerSet::SOFTWARE_MASK;
}
send_query(G()->net_query_creator().create(
telegram_api::stickers_createStickerSet(flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(input_user),
title, short_name, nullptr, std::move(input_stickers), software)));
send_query(G()->net_query_creator().create(telegram_api::stickers_createStickerSet(
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(input_user), title, short_name,
nullptr, std::move(input_stickers), software)));
}
void on_result(BufferSlice packet) final {
@ -1848,7 +1851,7 @@ tl_object_ptr<td_api::sticker> StickersManager::get_sticker_object(FileId file_i
height = static_cast<int32>(height * zoom + 0.5);
}
return make_tl_object<td_api::sticker>(
sticker->set_id.get(), width, height, sticker->alt, sticker->format == StickerFormat::Tgs, sticker->is_mask,
sticker->set_id.get(), width, height, sticker->alt, get_sticker_format_object(sticker->format), sticker->is_mask,
std::move(mask_position), get_sticker_minithumbnail(sticker->minithumbnail, sticker->set_id, document_id, zoom),
std::move(thumbnail_object), td_->file_manager_->get_file_object(file_id));
}
@ -1940,6 +1943,8 @@ PhotoFormat StickersManager::get_sticker_set_thumbnail_format(StickerFormat stic
return PhotoFormat::Webp;
case StickerFormat::Tgs:
return PhotoFormat::Tgs;
case StickerFormat::Webm:
return PhotoFormat::Webm;
default:
UNREACHABLE();
return PhotoFormat::Webp;
@ -1970,7 +1975,7 @@ tl_object_ptr<td_api::stickerSet> StickersManager::get_sticker_set_object(Sticke
sticker_set->id.get(), sticker_set->title, sticker_set->short_name, std::move(thumbnail),
get_sticker_minithumbnail(sticker_set->minithumbnail, sticker_set->id, -2, 1.0),
sticker_set->is_installed && !sticker_set->is_archived, sticker_set->is_archived, sticker_set->is_official,
sticker_set->sticker_format == StickerFormat::Tgs, sticker_set->is_masks, sticker_set->is_viewed,
get_sticker_format_object(sticker_set->sticker_format), sticker_set->is_masks, sticker_set->is_viewed,
std::move(stickers), std::move(emojis));
}
@ -2017,7 +2022,7 @@ tl_object_ptr<td_api::stickerSetInfo> StickersManager::get_sticker_set_info_obje
sticker_set->id.get(), sticker_set->title, sticker_set->short_name, std::move(thumbnail),
get_sticker_minithumbnail(sticker_set->minithumbnail, sticker_set->id, -3, 1.0),
sticker_set->is_installed && !sticker_set->is_archived, sticker_set->is_archived, sticker_set->is_official,
sticker_set->sticker_format == StickerFormat::Tgs, sticker_set->is_masks, sticker_set->is_viewed,
get_sticker_format_object(sticker_set->sticker_format), sticker_set->is_masks, sticker_set->is_viewed,
sticker_set->was_loaded ? narrow_cast<int32>(sticker_set->sticker_ids.size()) : sticker_set->sticker_count,
std::move(stickers));
}
@ -2214,6 +2219,11 @@ std::pair<int64, FileId> StickersManager::on_get_sticker_document(tl_object_ptr<
tl_object_ptr<telegram_api::documentAttributeSticker> sticker;
for (auto &attribute : document->attributes_) {
switch (attribute->get_id()) {
case telegram_api::documentAttributeVideo::ID: {
auto video = move_tl_object_as<telegram_api::documentAttributeVideo>(attribute);
dimensions = get_dimensions(video->w_, video->h_, "sticker documentAttributeVideo");
break;
}
case telegram_api::documentAttributeImageSize::ID: {
auto image_size = move_tl_object_as<telegram_api::documentAttributeImageSize>(attribute);
dimensions = get_dimensions(image_size->w_, image_size->h_, "sticker documentAttributeImageSize");
@ -2758,6 +2768,8 @@ tl_object_ptr<telegram_api::InputMedia> StickersManager::get_input_media(
const PathView path_view(suggested_path);
if (path_view.extension() == "tgs") {
mime_type = "application/x-tgsticker";
} else if (path_view.extension() == "webm") {
mime_type = "video/webm";
}
}
return make_tl_object<telegram_api::inputMediaUploadedDocument>(
@ -2779,7 +2791,8 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
bool is_installed = (set->flags_ & telegram_api::stickerSet::INSTALLED_DATE_MASK) != 0;
bool is_archived = set->archived_;
bool is_official = set->official_;
StickerFormat sticker_format = set->animated_ ? StickerFormat::Tgs : StickerFormat::Webp;
StickerFormat sticker_format =
set->gifs_ ? StickerFormat::Webm : (set->animated_ ? StickerFormat::Tgs : StickerFormat::Webp);
bool is_masks = set->masks_;
PhotoSize thumbnail;
@ -3305,13 +3318,11 @@ void StickersManager::on_get_installed_sticker_sets(bool is_masks,
on_load_installed_sticker_sets_finished(is_masks, std::move(installed_sticker_set_ids));
if (installed_sticker_sets_hash_[is_masks] != stickers->hash_) {
LOG(ERROR) << "Sticker sets hash mismatch: server hash list = " << format::as_array(debug_hashes)
<< ", client hash list = "
<< format::as_array(
transform(installed_sticker_set_ids_[is_masks],
[this](StickerSetId sticker_set_id) { return get_sticker_set(sticker_set_id)->hash; }))
<< ", server sticker set list = " << format::as_array(debug_sticker_set_ids)
<< ", client sticker set list = " << format::as_array(installed_sticker_set_ids_[is_masks])
LOG(ERROR) << "Sticker sets hash mismatch: server hash list = " << debug_hashes << ", client hash list = "
<< transform(installed_sticker_set_ids_[is_masks],
[this](StickerSetId sticker_set_id) { return get_sticker_set(sticker_set_id)->hash; })
<< ", server sticker set list = " << debug_sticker_set_ids
<< ", client sticker set list = " << installed_sticker_set_ids_[is_masks]
<< ", server hash = " << stickers->hash_ << ", client hash = " << installed_sticker_sets_hash_[is_masks];
}
}

View File

@ -33,12 +33,14 @@ void StickersManager::store_sticker(FileId file_id, bool in_sticker_set, StorerT
bool has_sticker_set_access_hash = sticker->set_id.is_valid() && !in_sticker_set;
bool has_minithumbnail = !sticker->minithumbnail.empty();
bool is_tgs = sticker->format == StickerFormat::Tgs;
bool is_webm = sticker->format == StickerFormat::Webm;
BEGIN_STORE_FLAGS();
STORE_FLAG(sticker->is_mask);
STORE_FLAG(has_sticker_set_access_hash);
STORE_FLAG(in_sticker_set);
STORE_FLAG(is_tgs);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(is_webm);
END_STORE_FLAGS();
if (!in_sticker_set) {
store(sticker->set_id.get(), storer);
@ -75,14 +77,18 @@ FileId StickersManager::parse_sticker(bool in_sticker_set, ParserT &parser) {
bool in_sticker_set_stored;
bool has_minithumbnail;
bool is_tgs;
bool is_webm;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(sticker->is_mask);
PARSE_FLAG(has_sticker_set_access_hash);
PARSE_FLAG(in_sticker_set_stored);
PARSE_FLAG(is_tgs);
PARSE_FLAG(has_minithumbnail);
PARSE_FLAG(is_webm);
END_PARSE_FLAGS();
if (is_tgs) {
if (is_webm) {
sticker->format = StickerFormat::Webm;
} else if (is_tgs) {
sticker->format = StickerFormat::Tgs;
} else {
sticker->format = StickerFormat::Webp;
@ -145,6 +151,7 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
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;
BEGIN_STORE_FLAGS();
STORE_FLAG(sticker_set->is_inited);
STORE_FLAG(was_loaded);
@ -160,6 +167,7 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
STORE_FLAG(is_tgs);
STORE_FLAG(sticker_set->are_legacy_sticker_thumbnails_reloaded);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(is_webm);
END_STORE_FLAGS();
store(sticker_set->id.get(), storer);
store(sticker_set->access_hash, storer);
@ -209,6 +217,7 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
bool has_thumbnail;
bool is_tgs;
bool has_minithumbnail;
bool is_webm;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(sticker_set->is_inited);
PARSE_FLAG(sticker_set->was_loaded);
@ -224,6 +233,7 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
PARSE_FLAG(is_tgs);
PARSE_FLAG(sticker_set->are_legacy_sticker_thumbnails_reloaded);
PARSE_FLAG(has_minithumbnail);
PARSE_FLAG(is_webm);
END_PARSE_FLAGS();
int64 sticker_set_id;
int64 access_hash;
@ -236,7 +246,9 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
}
StickerFormat sticker_format = StickerFormat::Unknown;
if (is_tgs) {
if (is_webm) {
sticker_format = StickerFormat::Webm;
} else if (is_tgs) {
sticker_format = StickerFormat::Tgs;
} else {
sticker_format = StickerFormat::Webp;