Support creation of animated sticker sets by bots.

GitOrigin-RevId: d75133cf70b667cbdf6dc555cc06f2b43f9c8609
This commit is contained in:
levlam 2020-03-23 18:03:13 +03:00
parent 2f850bc834
commit f153539ea2
5 changed files with 192 additions and 71 deletions

View File

@ -2748,8 +2748,18 @@ proxy id:int32 server:string port:int32 last_used_date:int32 is_enabled:Bool typ
proxies proxies:vector<proxy> = Proxies; proxies proxies:vector<proxy> = Proxies;
//@description Describes a sticker that should be added to a sticker set @png_sticker PNG image with the sticker; must be up to 512 KB in size and fit in a 512x512 square @emojis Emoji corresponding to the sticker @mask_position For masks, position where the mask should be placed; may be null //@class InputSticker @description Describes a sticker that needs to be added to a sticker set
inputSticker png_sticker:InputFile emojis:string mask_position:maskPosition = InputSticker;
//@description A static sticker in PNG format, which will be converted to WEBP server-side
//@sticker PNG image with the sticker; must be up to 512 KB in size and fit in a 512x512 square
//@emojis Emojis corresponding to the sticker
//@mask_position For masks, position where the mask should be placed; may be null
inputStickerStatic sticker:InputFile emojis:string mask_position:maskPosition = InputSticker;
//@description An animated sticker in TGS format
//@sticker File with the animated sticker. Only local or uploaded within a week files are supported. See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements
//@emojis Emojis corresponding to the sticker
inputStickerAnimated sticker:InputFile emojis:string = InputSticker;
//@class Update @description Contains notifications about data changes //@class Update @description Contains notifications about data changes
@ -4247,19 +4257,19 @@ uploadStickerFile user_id:int32 png_sticker:InputFile = File;
//@description Creates a new sticker set; for bots only. Returns the newly created sticker set //@description Creates a new sticker set; for bots only. Returns the newly created sticker set
//@user_id Sticker set owner //@user_id Sticker set owner
//@title Sticker set title; 1-64 characters @name Sticker set name. Can contain only English letters, digits and underscores. Must end with *"_by_<bot username>"* (*<bot_username>* is case insensitive); 1-64 characters //@title Sticker set title; 1-64 characters
//@is_masks True, if stickers are masks //@name Sticker set name. Can contain only English letters, digits and underscores. Must end with *"_by_<bot username>"* (*<bot_username>* is case insensitive); 1-64 characters
//@stickers List of stickers to be added to the set //@is_masks True, if stickers are masks. Animated stickers can't be masks
createNewStickerSet user_id:int32 title:string name:string is_masks:Bool stickers:vector<inputSticker> = StickerSet; //@stickers List of stickers to be added to the set; must be non-empty. All stickers must be of the same type
createNewStickerSet user_id:int32 title:string name:string is_masks:Bool stickers:vector<InputSticker> = StickerSet;
//@description Adds a new sticker to a set; for bots only. Returns the sticker set //@description Adds a new sticker to a set; for bots only. Returns the sticker set
//@user_id Sticker set owner @name Sticker set name //@user_id Sticker set owner @name Sticker set name @sticker Sticker to add to the set
//@sticker Sticker to add to the set addStickerToSet user_id:int32 name:string sticker:InputSticker = StickerSet;
addStickerToSet user_id:int32 name:string sticker:inputSticker = StickerSet;
//@description Sets a sticker set thumbnail; for bots only. Returns the sticker set //@description Sets a sticker set thumbnail; for bots only. Returns the sticker set
//@user_id Sticker set owner @name Sticker set name //@user_id Sticker set owner @name Sticker set name
//@thumbnail Thumbnail to set in PNG format. You can use a zero InputFileId to delete the thumbnail //@thumbnail Thumbnail to set in PNG or TGS format. Animated thumbnail must be set for animated sticker sets and only for them. You can use a zero InputFileId to delete the thumbnail
setStickerSetThumbnail user_id:int32 name:string thumbnail:InputFile = StickerSet; setStickerSetThumbnail user_id:int32 name:string thumbnail:InputFile = StickerSet;
//@description Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot //@description Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot

Binary file not shown.

View File

@ -879,13 +879,17 @@ class CreateNewStickerSetQuery : public Td::ResultHandler {
} }
void send(tl_object_ptr<telegram_api::InputUser> &&input_user, const string &title, const string &short_name, void send(tl_object_ptr<telegram_api::InputUser> &&input_user, const string &title, const string &short_name,
bool is_masks, vector<tl_object_ptr<telegram_api::inputStickerSetItem>> &&input_stickers) { bool is_masks, bool is_animated,
vector<tl_object_ptr<telegram_api::inputStickerSetItem>> &&input_stickers) {
CHECK(input_user != nullptr); CHECK(input_user != nullptr);
int32 flags = 0; int32 flags = 0;
if (is_masks) { if (is_masks) {
flags |= telegram_api::stickers_createStickerSet::MASKS_MASK; flags |= telegram_api::stickers_createStickerSet::MASKS_MASK;
} }
if (is_animated) {
flags |= telegram_api::stickers_createStickerSet::ANIMATED_MASK;
}
send_query(G()->net_query_creator().create( send_query(G()->net_query_creator().create(
telegram_api::stickers_createStickerSet(flags, false /*ignored*/, false /*ignored*/, std::move(input_user), telegram_api::stickers_createStickerSet(flags, false /*ignored*/, false /*ignored*/, std::move(input_user),
@ -3576,31 +3580,54 @@ void StickersManager::reorder_installed_sticker_sets(bool is_masks, const vector
promise.set_value(Unit()); promise.set_value(Unit());
} }
Result<std::tuple<FileId, bool, bool>> StickersManager::prepare_input_sticker(td_api::inputSticker *sticker) { string &StickersManager::get_input_sticker_emojis(td_api::InputSticker *sticker) {
CHECK(sticker != nullptr);
auto constructor_id = sticker->get_id();
if (constructor_id == td_api::inputStickerStatic::ID) {
return static_cast<td_api::inputStickerStatic *>(sticker)->emojis_;
}
CHECK(constructor_id == td_api::inputStickerAnimated::ID);
return static_cast<td_api::inputStickerAnimated *>(sticker)->emojis_;
}
Result<std::tuple<FileId, bool, bool, bool>> StickersManager::prepare_input_sticker(td_api::InputSticker *sticker) {
if (sticker == nullptr) { if (sticker == nullptr) {
return Status::Error(3, "Input sticker must not be empty"); return Status::Error(3, "Input sticker must not be empty");
} }
if (!clean_input_string(sticker->emojis_)) { if (!clean_input_string(get_input_sticker_emojis(sticker))) {
return Status::Error(400, "Emojis must be encoded in UTF-8"); return Status::Error(400, "Emojis must be encoded in UTF-8");
} }
return prepare_input_file(sticker->png_sticker_, false); switch (sticker->get_id()) {
case td_api::inputStickerStatic::ID:
return prepare_input_file(static_cast<td_api::inputStickerStatic *>(sticker)->sticker_, false, false);
case td_api::inputStickerAnimated::ID:
return prepare_input_file(static_cast<td_api::inputStickerAnimated *>(sticker)->sticker_, true, false);
default:
UNREACHABLE();
return {};
}
} }
Result<std::tuple<FileId, bool, bool>> StickersManager::prepare_input_file( Result<std::tuple<FileId, bool, bool, bool>> StickersManager::prepare_input_file(
const tl_object_ptr<td_api::InputFile> &input_file, bool allow_zero) { const tl_object_ptr<td_api::InputFile> &input_file, bool is_animated, bool for_thumbnail) {
auto r_file_id = auto r_file_id = td_->file_manager_->get_input_file_id(is_animated ? FileType::Sticker : FileType::Document,
td_->file_manager_->get_input_file_id(FileType::Document, input_file, DialogId(), allow_zero, false, false); input_file, DialogId(), for_thumbnail, false);
if (r_file_id.is_error()) { if (r_file_id.is_error()) {
return Status::Error(7, r_file_id.error().message()); return Status::Error(7, r_file_id.error().message());
} }
auto file_id = r_file_id.move_as_ok(); auto file_id = r_file_id.move_as_ok();
if (file_id.empty()) { if (file_id.empty()) {
return std::make_tuple(FileId(), false, false); return std::make_tuple(FileId(), false, false, false);
} }
if (is_animated) {
int32 width = for_thumbnail ? 100 : 512;
td_->stickers_manager_->create_sticker(file_id, PhotoSize(), get_dimensions(width, width), nullptr, true, nullptr);
} else {
td_->documents_manager_->create_document(file_id, string(), PhotoSize(), "sticker.png", "image/png", false); td_->documents_manager_->create_document(file_id, string(), PhotoSize(), "sticker.png", "image/png", false);
}
FileView file_view = td_->file_manager_->get_file_view(file_id); FileView file_view = td_->file_manager_->get_file_view(file_id);
if (file_view.is_encrypted()) { if (file_view.is_encrypted()) {
@ -3618,13 +3645,20 @@ Result<std::tuple<FileId, bool, bool>> StickersManager::prepare_input_file(
if (file_view.has_url()) { if (file_view.has_url()) {
is_url = true; is_url = true;
} else { } else {
if (file_view.has_local_location() && file_view.expected_size() > MAX_STICKER_FILE_SIZE) { auto max_file_size = [&] {
if (for_thumbnail) {
return is_animated ? MAX_ANIMATED_THUMBNAIL_FILE_SIZE : MAX_THUMBNAIL_FILE_SIZE;
} else {
return is_animated ? MAX_ANIMATED_STICKER_FILE_SIZE : MAX_STICKER_FILE_SIZE;
}
}();
if (file_view.has_local_location() && file_view.expected_size() > max_file_size) {
return Status::Error(400, "File is too big"); return Status::Error(400, "File is too big");
} }
is_local = true; is_local = true;
} }
} }
return std::make_tuple(file_id, is_url, is_local); return std::make_tuple(file_id, is_url, is_local, is_animated);
} }
FileId StickersManager::upload_sticker_file(UserId user_id, const tl_object_ptr<td_api::InputFile> &sticker, FileId StickersManager::upload_sticker_file(UserId user_id, const tl_object_ptr<td_api::InputFile> &sticker,
@ -3641,7 +3675,7 @@ FileId StickersManager::upload_sticker_file(UserId user_id, const tl_object_ptr<
return FileId(); return FileId();
} }
auto r_file_id = prepare_input_file(sticker, false); auto r_file_id = prepare_input_file(sticker, false, false);
if (r_file_id.is_error()) { if (r_file_id.is_error()) {
promise.set_error(r_file_id.move_as_error()); promise.set_error(r_file_id.move_as_error());
return FileId(); return FileId();
@ -3661,15 +3695,18 @@ FileId StickersManager::upload_sticker_file(UserId user_id, const tl_object_ptr<
return file_id; return file_id;
} }
tl_object_ptr<telegram_api::inputStickerSetItem> StickersManager::get_input_sticker(td_api::inputSticker *sticker, tl_object_ptr<telegram_api::inputStickerSetItem> StickersManager::get_input_sticker(td_api::InputSticker *sticker,
FileId file_id) const { FileId file_id) const {
CHECK(sticker != nullptr);
FileView file_view = td_->file_manager_->get_file_view(file_id); FileView file_view = td_->file_manager_->get_file_view(file_id);
CHECK(file_view.has_remote_location()); CHECK(file_view.has_remote_location());
auto input_document = file_view.main_remote_location().as_input_document(); auto input_document = file_view.main_remote_location().as_input_document();
tl_object_ptr<telegram_api::maskCoords> mask_coords; tl_object_ptr<telegram_api::maskCoords> mask_coords;
if (sticker->mask_position_ != nullptr && sticker->mask_position_->point_ != nullptr) { if (sticker->get_id() == td_api::inputStickerStatic::ID) {
auto point = [mask_point = std::move(sticker->mask_position_->point_)] { auto mask_position = static_cast<td_api::inputStickerStatic *>(sticker)->mask_position_.get();
if (mask_position != nullptr && mask_position->point_ != nullptr) {
auto point = [mask_point = std::move(mask_position->point_)] {
switch (mask_point->get_id()) { switch (mask_point->get_id()) {
case td_api::maskPointForehead::ID: case td_api::maskPointForehead::ID:
return 0; return 0;
@ -3684,8 +3721,9 @@ tl_object_ptr<telegram_api::inputStickerSetItem> StickersManager::get_input_stic
return -1; return -1;
} }
}(); }();
mask_coords = make_tl_object<telegram_api::maskCoords>( mask_coords = make_tl_object<telegram_api::maskCoords>(point, mask_position->x_shift_, mask_position->y_shift_,
point, sticker->mask_position_->x_shift_, sticker->mask_position_->y_shift_, sticker->mask_position_->scale_); mask_position->scale_);
}
} }
int32 flags = 0; int32 flags = 0;
@ -3693,12 +3731,12 @@ tl_object_ptr<telegram_api::inputStickerSetItem> StickersManager::get_input_stic
flags |= telegram_api::inputStickerSetItem::MASK_COORDS_MASK; flags |= telegram_api::inputStickerSetItem::MASK_COORDS_MASK;
} }
return make_tl_object<telegram_api::inputStickerSetItem>(flags, std::move(input_document), sticker->emojis_, return make_tl_object<telegram_api::inputStickerSetItem>(flags, std::move(input_document),
std::move(mask_coords)); get_input_sticker_emojis(sticker), std::move(mask_coords));
} }
void StickersManager::create_new_sticker_set(UserId user_id, string &title, string &short_name, bool is_masks, void StickersManager::create_new_sticker_set(UserId user_id, string &title, string &short_name, bool is_masks,
vector<tl_object_ptr<td_api::inputSticker>> &&stickers, vector<tl_object_ptr<td_api::InputSticker>> &&stickers,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
auto input_user = td_->contacts_manager_->get_input_user(user_id); auto input_user = td_->contacts_manager_->get_input_user(user_id);
if (input_user == nullptr) { if (input_user == nullptr) {
@ -3720,10 +3758,15 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
return promise.set_error(Status::Error(3, "Sticker set name can't be empty")); return promise.set_error(Status::Error(3, "Sticker set name can't be empty"));
} }
if (stickers.empty()) {
return promise.set_error(Status::Error(400, "At least 1 sticker must be specified"));
}
vector<FileId> file_ids; vector<FileId> file_ids;
file_ids.reserve(stickers.size()); file_ids.reserve(stickers.size());
vector<FileId> local_file_ids; vector<FileId> local_file_ids;
vector<FileId> url_file_ids; vector<FileId> url_file_ids;
size_t animated_sticker_count = 0;
for (auto &sticker : stickers) { for (auto &sticker : stickers) {
auto r_file_id = prepare_input_sticker(sticker.get()); auto r_file_id = prepare_input_sticker(sticker.get());
if (r_file_id.is_error()) { if (r_file_id.is_error()) {
@ -3732,6 +3775,13 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
auto file_id = std::get<0>(r_file_id.ok()); auto file_id = std::get<0>(r_file_id.ok());
auto is_url = std::get<1>(r_file_id.ok()); auto is_url = std::get<1>(r_file_id.ok());
auto is_local = std::get<2>(r_file_id.ok()); auto is_local = std::get<2>(r_file_id.ok());
auto is_animated = std::get<3>(r_file_id.ok());
if (is_animated) {
animated_sticker_count++;
if (is_url) {
return promise.set_error(Status::Error(400, "Animated stickers can't be uploaded by URL"));
}
}
file_ids.push_back(file_id); file_ids.push_back(file_id);
if (is_url) { if (is_url) {
@ -3740,12 +3790,17 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
local_file_ids.push_back(file_id); local_file_ids.push_back(file_id);
} }
} }
if (animated_sticker_count != stickers.size() && animated_sticker_count != 0) {
return promise.set_error(Status::Error(400, "All stickers must be either animated or static"));
}
bool is_animated = animated_sticker_count == stickers.size();
auto pending_new_sticker_set = make_unique<PendingNewStickerSet>(); auto pending_new_sticker_set = make_unique<PendingNewStickerSet>();
pending_new_sticker_set->user_id = user_id; pending_new_sticker_set->user_id = user_id;
pending_new_sticker_set->title = std::move(title); pending_new_sticker_set->title = std::move(title);
pending_new_sticker_set->short_name = short_name; pending_new_sticker_set->short_name = short_name;
pending_new_sticker_set->is_masks = is_masks; pending_new_sticker_set->is_masks = is_masks;
pending_new_sticker_set->is_animated = is_animated;
pending_new_sticker_set->file_ids = std::move(file_ids); pending_new_sticker_set->file_ids = std::move(file_ids);
pending_new_sticker_set->stickers = std::move(stickers); pending_new_sticker_set->stickers = std::move(stickers);
pending_new_sticker_set->promise = std::move(promise); pending_new_sticker_set->promise = std::move(promise);
@ -3776,9 +3831,14 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
} }
void StickersManager::upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise) { void StickersManager::upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise) {
FileId upload_file_id;
if (td_->file_manager_->get_file_view(file_id).get_type() == FileType::Sticker) {
CHECK(get_input_media(file_id, nullptr, nullptr) == nullptr);
upload_file_id = dup_sticker(td_->file_manager_->dup_file_id(file_id), file_id);
} else {
CHECK(td_->documents_manager_->get_input_media(file_id, nullptr, nullptr) == nullptr); CHECK(td_->documents_manager_->get_input_media(file_id, nullptr, nullptr) == nullptr);
upload_file_id = td_->documents_manager_->dup_document(td_->file_manager_->dup_file_id(file_id), file_id);
auto upload_file_id = td_->documents_manager_->dup_document(td_->file_manager_->dup_file_id(file_id), file_id); }
being_uploaded_files_[upload_file_id] = {user_id, std::move(promise)}; being_uploaded_files_[upload_file_id] = {user_id, std::move(promise)};
LOG(INFO) << "Ask to upload sticker file " << upload_file_id; LOG(INFO) << "Ask to upload sticker file " << upload_file_id;
@ -3830,8 +3890,12 @@ void StickersManager::do_upload_sticker_file(UserId user_id, FileId file_id,
return promise.set_error(Status::Error(3, "Have no access to the user")); return promise.set_error(Status::Error(3, "Have no access to the user"));
} }
FileView file_view = td_->file_manager_->get_file_view(file_id);
bool is_animated = file_view.get_type() == FileType::Sticker;
bool had_input_file = input_file != nullptr; bool had_input_file = input_file != nullptr;
auto input_media = td_->documents_manager_->get_input_media(file_id, std::move(input_file), nullptr); auto input_media = is_animated ? get_input_media(file_id, std::move(input_file), nullptr)
: td_->documents_manager_->get_input_media(file_id, std::move(input_file), nullptr);
CHECK(input_media != nullptr); CHECK(input_media != nullptr);
if (had_input_file && !FileManager::extract_was_uploaded(input_media)) { if (had_input_file && !FileManager::extract_was_uploaded(input_media)) {
// if we had InputFile, but has failed to use it, then we need to immediately cancel file upload // if we had InputFile, but has failed to use it, then we need to immediately cancel file upload
@ -3846,6 +3910,7 @@ void StickersManager::do_upload_sticker_file(UserId user_id, FileId file_id,
void StickersManager::on_uploaded_sticker_file(FileId file_id, tl_object_ptr<telegram_api::MessageMedia> media, void StickersManager::on_uploaded_sticker_file(FileId file_id, tl_object_ptr<telegram_api::MessageMedia> media,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
CHECK(media != nullptr); CHECK(media != nullptr);
LOG(INFO) << "Receive uploaded sticker file " << to_string(media);
if (media->get_id() != telegram_api::messageMediaDocument::ID) { if (media->get_id() != telegram_api::messageMediaDocument::ID) {
return promise.set_error(Status::Error(400, "Can't upload sticker file: wrong file type")); return promise.set_error(Status::Error(400, "Can't upload sticker file: wrong file type"));
} }
@ -3858,13 +3923,21 @@ void StickersManager::on_uploaded_sticker_file(FileId file_id, tl_object_ptr<tel
} }
CHECK(document_id == telegram_api::document::ID); CHECK(document_id == telegram_api::document::ID);
FileView file_view = td_->file_manager_->get_file_view(file_id);
bool is_animated = file_view.get_type() == FileType::Sticker;
auto expected_document_type = is_animated ? Document::Type::Sticker : Document::Type::General;
auto parsed_document = td_->documents_manager_->on_get_document( auto parsed_document = td_->documents_manager_->on_get_document(
move_tl_object_as<telegram_api::document>(document_ptr), DialogId(), nullptr); move_tl_object_as<telegram_api::document>(document_ptr), DialogId(), nullptr);
if (parsed_document.type != Document::Type::General) { if (parsed_document.type != expected_document_type) {
return promise.set_error(Status::Error(400, "Wrong file type")); return promise.set_error(Status::Error(400, "Wrong file type"));
} }
if (is_animated) {
merge_stickers(parsed_document.file_id, file_id, true);
} else {
td_->documents_manager_->merge_documents(parsed_document.file_id, file_id, true); td_->documents_manager_->merge_documents(parsed_document.file_id, file_id, true);
}
promise.set_value(Unit()); promise.set_value(Unit());
} }
@ -3890,6 +3963,7 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
} }
bool is_masks = pending_new_sticker_set->is_masks; bool is_masks = pending_new_sticker_set->is_masks;
bool is_animated = pending_new_sticker_set->is_animated;
auto sticker_count = pending_new_sticker_set->stickers.size(); auto sticker_count = pending_new_sticker_set->stickers.size();
vector<tl_object_ptr<telegram_api::inputStickerSetItem>> input_stickers; vector<tl_object_ptr<telegram_api::inputStickerSetItem>> input_stickers;
@ -3901,11 +3975,11 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
td_->create_handler<CreateNewStickerSetQuery>(std::move(pending_new_sticker_set->promise)) td_->create_handler<CreateNewStickerSetQuery>(std::move(pending_new_sticker_set->promise))
->send(std::move(input_user), pending_new_sticker_set->title, pending_new_sticker_set->short_name, is_masks, ->send(std::move(input_user), pending_new_sticker_set->title, pending_new_sticker_set->short_name, is_masks,
std::move(input_stickers)); is_animated, std::move(input_stickers));
} }
void StickersManager::add_sticker_to_set(UserId user_id, string &short_name, void StickersManager::add_sticker_to_set(UserId user_id, string &short_name,
tl_object_ptr<td_api::inputSticker> &&sticker, Promise<Unit> &&promise) { tl_object_ptr<td_api::InputSticker> &&sticker, Promise<Unit> &&promise) {
auto input_user = td_->contacts_manager_->get_input_user(user_id); auto input_user = td_->contacts_manager_->get_input_user(user_id);
if (input_user == nullptr) { if (input_user == nullptr) {
return promise.set_error(Status::Error(3, "User not found")); return promise.set_error(Status::Error(3, "User not found"));
@ -3985,12 +4059,40 @@ void StickersManager::set_sticker_set_thumbnail(UserId user_id, string &short_na
return promise.set_error(Status::Error(3, "Have no access to the user")); return promise.set_error(Status::Error(3, "Have no access to the user"));
} }
short_name = strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH); short_name = clean_username(strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH));
if (short_name.empty()) { if (short_name.empty()) {
return promise.set_error(Status::Error(3, "Sticker set name can't be empty")); return promise.set_error(Status::Error(3, "Sticker set name can't be empty"));
} }
auto r_file_id = prepare_input_file(thumbnail, true); auto it = short_name_to_sticker_set_id_.find(short_name);
const StickerSet *sticker_set = it == short_name_to_sticker_set_id_.end() ? nullptr : get_sticker_set(it->second);
if (sticker_set != nullptr && sticker_set->was_loaded) {
return do_set_sticker_set_thumbnail(user_id, short_name, std::move(thumbnail), std::move(promise));
}
do_reload_sticker_set(
StickerSetId(), make_tl_object<telegram_api::inputStickerSetShortName>(short_name),
PromiseCreator::lambda([actor_id = actor_id(this), user_id, short_name, thumbnail = std::move(thumbnail),
promise = std::move(promise)](Result<Unit> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
send_closure(actor_id, &StickersManager::do_set_sticker_set_thumbnail, user_id, std::move(short_name),
std::move(thumbnail), std::move(promise));
}
}));
}
void StickersManager::do_set_sticker_set_thumbnail(UserId user_id, string short_name,
tl_object_ptr<td_api::InputFile> &&thumbnail,
Promise<Unit> &&promise) {
auto it = short_name_to_sticker_set_id_.find(short_name);
const StickerSet *sticker_set = it == short_name_to_sticker_set_id_.end() ? nullptr : get_sticker_set(it->second);
if (sticker_set == nullptr || !sticker_set->was_loaded) {
return promise.set_error(Status::Error(3, "Sticker set not found"));
}
auto r_file_id = prepare_input_file(thumbnail, sticker_set->is_animated, true);
if (r_file_id.is_error()) { if (r_file_id.is_error()) {
return promise.set_error(r_file_id.move_as_error()); return promise.set_error(r_file_id.move_as_error());
} }

View File

@ -147,9 +147,9 @@ class StickersManager : public Actor {
FileId upload_sticker_file(UserId user_id, const tl_object_ptr<td_api::InputFile> &sticker, Promise<Unit> &&promise); FileId upload_sticker_file(UserId user_id, const tl_object_ptr<td_api::InputFile> &sticker, Promise<Unit> &&promise);
void create_new_sticker_set(UserId user_id, string &title, string &short_name, bool is_masks, void create_new_sticker_set(UserId user_id, string &title, string &short_name, bool is_masks,
vector<tl_object_ptr<td_api::inputSticker>> &&stickers, Promise<Unit> &&promise); vector<tl_object_ptr<td_api::InputSticker>> &&stickers, Promise<Unit> &&promise);
void add_sticker_to_set(UserId user_id, string &short_name, tl_object_ptr<td_api::inputSticker> &&sticker, void add_sticker_to_set(UserId user_id, string &short_name, tl_object_ptr<td_api::InputSticker> &&sticker,
Promise<Unit> &&promise); Promise<Unit> &&promise);
void set_sticker_set_thumbnail(UserId user_id, string &short_name, tl_object_ptr<td_api::InputFile> &&thumbnail, void set_sticker_set_thumbnail(UserId user_id, string &short_name, tl_object_ptr<td_api::InputFile> &&thumbnail,
@ -272,6 +272,9 @@ class StickersManager : public Actor {
static constexpr int32 MAX_FOUND_STICKERS = 100; // server side limit static constexpr int32 MAX_FOUND_STICKERS = 100; // server side limit
static constexpr int64 MAX_STICKER_FILE_SIZE = 1 << 19; // server side limit static constexpr int64 MAX_STICKER_FILE_SIZE = 1 << 19; // server side limit
static constexpr int64 MAX_THUMBNAIL_FILE_SIZE = 1 << 17; // server side limit
static constexpr int64 MAX_ANIMATED_STICKER_FILE_SIZE = 1 << 16; // server side limit
static constexpr int64 MAX_ANIMATED_THUMBNAIL_FILE_SIZE = 1 << 15; // server side limit
static constexpr size_t MAX_STICKER_SET_TITLE_LENGTH = 64; // server side limit static constexpr size_t MAX_STICKER_SET_TITLE_LENGTH = 64; // server side limit
static constexpr size_t MAX_STICKER_SET_SHORT_NAME_LENGTH = 64; // server side limit static constexpr size_t MAX_STICKER_SET_SHORT_NAME_LENGTH = 64; // server side limit
@ -334,15 +337,16 @@ class StickersManager : public Actor {
string title; string title;
string short_name; string short_name;
bool is_masks; bool is_masks;
bool is_animated;
vector<FileId> file_ids; vector<FileId> file_ids;
vector<tl_object_ptr<td_api::inputSticker>> stickers; vector<tl_object_ptr<td_api::InputSticker>> stickers;
Promise<> promise; Promise<> promise;
}; };
struct PendingAddStickerToSet { struct PendingAddStickerToSet {
string short_name; string short_name;
FileId file_id; FileId file_id;
tl_object_ptr<td_api::inputSticker> sticker; tl_object_ptr<td_api::InputSticker> sticker;
Promise<> promise; Promise<> promise;
}; };
@ -481,12 +485,14 @@ class StickersManager : public Actor {
template <class ParserT> template <class ParserT>
void parse_sticker_set(StickerSet *sticker_set, ParserT &parser); void parse_sticker_set(StickerSet *sticker_set, ParserT &parser);
Result<std::tuple<FileId, bool, bool>> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file, static string &get_input_sticker_emojis(td_api::InputSticker *sticker);
bool allow_zero);
Result<std::tuple<FileId, bool, bool>> prepare_input_sticker(td_api::inputSticker *sticker); Result<std::tuple<FileId, bool, bool, bool>> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file,
bool is_animated, bool for_thumbnail);
tl_object_ptr<telegram_api::inputStickerSetItem> get_input_sticker(td_api::inputSticker *sticker, Result<std::tuple<FileId, bool, bool, bool>> prepare_input_sticker(td_api::InputSticker *sticker);
tl_object_ptr<telegram_api::inputStickerSetItem> get_input_sticker(td_api::InputSticker *sticker,
FileId file_id) const; FileId file_id) const;
void upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise); void upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise);
@ -504,6 +510,9 @@ class StickersManager : public Actor {
void on_sticker_set_thumbnail_uploaded(int64 random_id, Result<Unit> result); void on_sticker_set_thumbnail_uploaded(int64 random_id, Result<Unit> result);
void do_set_sticker_set_thumbnail(UserId user_id, string short_name, tl_object_ptr<td_api::InputFile> &&thumbnail,
Promise<Unit> &&promise);
bool update_sticker_set_cache(const StickerSet *sticker_set, Promise<Unit> &promise); bool update_sticker_set_cache(const StickerSet *sticker_set, Promise<Unit> &promise);
void start_up() override; void start_up() override;

View File

@ -2495,7 +2495,7 @@ class CreateNewStickerSetRequest : public RequestOnceActor {
string title_; string title_;
string name_; string name_;
bool is_masks_; bool is_masks_;
vector<tl_object_ptr<td_api::inputSticker>> stickers_; vector<tl_object_ptr<td_api::InputSticker>> stickers_;
void do_run(Promise<Unit> &&promise) override { void do_run(Promise<Unit> &&promise) override {
td->stickers_manager_->create_new_sticker_set(user_id_, title_, name_, is_masks_, std::move(stickers_), td->stickers_manager_->create_new_sticker_set(user_id_, title_, name_, is_masks_, std::move(stickers_),
@ -2512,7 +2512,7 @@ class CreateNewStickerSetRequest : public RequestOnceActor {
public: public:
CreateNewStickerSetRequest(ActorShared<Td> td, uint64 request_id, int32 user_id, string &&title, string &&name, CreateNewStickerSetRequest(ActorShared<Td> td, uint64 request_id, int32 user_id, string &&title, string &&name,
bool is_masks, vector<tl_object_ptr<td_api::inputSticker>> &&stickers) bool is_masks, vector<tl_object_ptr<td_api::InputSticker>> &&stickers)
: RequestOnceActor(std::move(td), request_id) : RequestOnceActor(std::move(td), request_id)
, user_id_(user_id) , user_id_(user_id)
, title_(std::move(title)) , title_(std::move(title))
@ -2525,7 +2525,7 @@ class CreateNewStickerSetRequest : public RequestOnceActor {
class AddStickerToSetRequest : public RequestOnceActor { class AddStickerToSetRequest : public RequestOnceActor {
UserId user_id_; UserId user_id_;
string name_; string name_;
tl_object_ptr<td_api::inputSticker> sticker_; tl_object_ptr<td_api::InputSticker> sticker_;
void do_run(Promise<Unit> &&promise) override { void do_run(Promise<Unit> &&promise) override {
td->stickers_manager_->add_sticker_to_set(user_id_, name_, std::move(sticker_), std::move(promise)); td->stickers_manager_->add_sticker_to_set(user_id_, name_, std::move(sticker_), std::move(promise));
@ -2541,7 +2541,7 @@ class AddStickerToSetRequest : public RequestOnceActor {
public: public:
AddStickerToSetRequest(ActorShared<Td> td, uint64 request_id, int32 user_id, string &&name, AddStickerToSetRequest(ActorShared<Td> td, uint64 request_id, int32 user_id, string &&name,
tl_object_ptr<td_api::inputSticker> &&sticker) tl_object_ptr<td_api::InputSticker> &&sticker)
: RequestOnceActor(std::move(td), request_id) : RequestOnceActor(std::move(td), request_id)
, user_id_(user_id) , user_id_(user_id)
, name_(std::move(name)) , name_(std::move(name))