Add td_api::editStoryCover.

This commit is contained in:
levlam 2024-07-27 22:39:44 +03:00
parent f6e97f83a6
commit 1f29dc7b97
10 changed files with 166 additions and 0 deletions

View File

@ -9692,6 +9692,12 @@ sendStory chat_id:int53 content:InputStoryContent areas:inputStoryAreas caption:
//@caption New story caption; pass null to keep the current caption
editStory story_sender_chat_id:int53 story_id:int32 content:InputStoryContent areas:inputStoryAreas caption:formattedText = Ok;
//@description Changes cover of a video story. Can be called only if story.can_be_edited == true and the story isn't being edited now
//@story_sender_chat_id Identifier of the chat that posted the story
//@story_id Identifier of the story to edit
//@cover_frame_timestamp New timestamp of the frame, which will be used as video thumbnail
editStoryCover story_sender_chat_id:int53 story_id:int32 cover_frame_timestamp:double = Ok;
//@description Changes privacy settings of a story. The method can be called only for stories posted on behalf of the current user and if story.can_be_edited == true
//@story_id Identifier of the story
//@privacy_settings The new privacy settigs for the story

View File

@ -325,6 +325,22 @@ telegram_api::object_ptr<telegram_api::InputMedia> get_story_content_input_media
}
}
telegram_api::object_ptr<telegram_api::InputMedia> get_story_content_document_input_media(Td *td,
const StoryContent *content,
double main_frame_timestamp) {
switch (content->get_type()) {
case StoryContentType::Video: {
const auto *story_content = static_cast<const StoryContentVideo *>(content);
return td->videos_manager_->get_story_document_input_media(story_content->file_id_, main_frame_timestamp);
}
case StoryContentType::Photo:
case StoryContentType::Unsupported:
default:
UNREACHABLE();
return nullptr;
}
}
void compare_story_contents(const StoryContent *old_content, const StoryContent *new_content, bool &is_content_changed,
bool &need_update) {
StoryContentType content_type = new_content->get_type();

View File

@ -50,6 +50,10 @@ Result<unique_ptr<StoryContent>> get_input_story_content(
telegram_api::object_ptr<telegram_api::InputMedia> get_story_content_input_media(
Td *td, const StoryContent *content, telegram_api::object_ptr<telegram_api::InputFile> input_file);
telegram_api::object_ptr<telegram_api::InputMedia> get_story_content_document_input_media(Td *td,
const StoryContent *content,
double main_frame_timestamp);
void compare_story_contents(Td *td, const StoryContent *old_content, const StoryContent *new_content,
bool &is_content_changed, bool &need_update);

View File

@ -590,6 +590,52 @@ class GetPeerStoriesQuery final : public Td::ResultHandler {
}
};
class EditStoryCoverQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
DialogId dialog_id_;
public:
explicit EditStoryCoverQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(DialogId owner_dialog_id, StoryId story_id,
telegram_api::object_ptr<telegram_api::InputMedia> input_media) {
dialog_id_ = owner_dialog_id;
auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id_, AccessRights::Write);
if (input_peer == nullptr) {
return on_error(Status::Error(400, "Can't access the chat"));
}
send_query(G()->net_query_creator().create(
telegram_api::stories_editStory(telegram_api::stories_editStory::MEDIA_MASK, std::move(input_peer),
story_id.get(), std::move(input_media),
vector<telegram_api::object_ptr<telegram_api::MediaArea>>(), string(),
vector<telegram_api::object_ptr<telegram_api::MessageEntity>>(), Auto()),
{{StoryFullId{dialog_id_, story_id}}}));
}
void on_result(BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::stories_editStory>(packet);
if (result_ptr.is_error()) {
return on_error(result_ptr.move_as_error());
}
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditStoryCoverQuery: " << to_string(ptr);
td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(Status status) final {
LOG(INFO) << "Receive error for EditStoryCoverQuery: " << status;
if (!td_->auth_manager_->is_bot() && status.message() == "STORY_NOT_MODIFIED") {
return promise_.set_value(Unit());
}
td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "EditStoryCoverQuery");
promise_.set_error(std::move(status));
}
};
class EditStoryPrivacyQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
DialogId dialog_id_;
@ -5503,6 +5549,33 @@ void StoryManager::do_edit_story(FileId file_id, unique_ptr<PendingStory> &&pend
it->second.get());
}
void StoryManager::edit_story_cover(DialogId owner_dialog_id, StoryId story_id, double main_frame_timestamp,
Promise<Unit> &&promise) {
StoryFullId story_full_id{owner_dialog_id, story_id};
const Story *story = get_story(story_full_id);
if (story == nullptr || story->content_ == nullptr) {
return promise.set_error(Status::Error(400, "Story not found"));
}
if (!can_edit_story(story_full_id, story)) {
return promise.set_error(Status::Error(400, "Story can't be edited"));
}
if (being_edited_stories_.count(story_full_id) > 0) {
return promise.set_error(Status::Error(400, "Story is being edited"));
}
if (main_frame_timestamp < 0.0) {
return promise.set_error(Status::Error(400, "Wrong cover timestamp specified"));
}
if (story->content_->get_type() != StoryContentType::Video) {
return promise.set_error(Status::Error(400, "Cover timestamp can't be edited for the story"));
}
auto input_media = get_story_content_document_input_media(td_, story->content_.get(), main_frame_timestamp);
if (input_media == nullptr) {
return promise.set_error(Status::Error(400, "Can't edit story cover"));
}
td_->create_handler<EditStoryCoverQuery>(std::move(promise))->send(owner_dialog_id, story_id, std::move(input_media));
}
void StoryManager::delete_pending_story(FileId file_id, unique_ptr<PendingStory> &&pending_story, Status status) {
if (G()->close_flag() && G()->use_message_database()) {
return;

View File

@ -228,6 +228,9 @@ class StoryManager final : public Actor {
td_api::object_ptr<td_api::inputStoryAreas> &&input_areas,
td_api::object_ptr<td_api::formattedText> &&input_caption, Promise<Unit> &&promise);
void edit_story_cover(DialogId owner_dialog_id, StoryId story_id, double main_frame_timestamp,
Promise<Unit> &&promise);
void set_story_privacy_settings(StoryId story_id, td_api::object_ptr<td_api::StoryPrivacySettings> &&settings,
Promise<Unit> &&promise);

View File

@ -5978,6 +5978,13 @@ void Td::on_request(uint64 id, td_api::editStory &request) {
std::move(promise));
}
void Td::on_request(uint64 id, const td_api::editStoryCover &request) {
CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE();
story_manager_->edit_story_cover(DialogId(request.story_sender_chat_id_), StoryId(request.story_id_),
request.cover_frame_timestamp_, std::move(promise));
}
void Td::on_request(uint64 id, td_api::setStoryPrivacySettings &request) {
CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE();

View File

@ -967,6 +967,8 @@ class Td final : public Actor {
void on_request(uint64 id, td_api::editStory &request);
void on_request(uint64 id, const td_api::editStoryCover &request);
void on_request(uint64 id, td_api::setStoryPrivacySettings &request);
void on_request(uint64 id, const td_api::toggleStoryIsPostedToChatPage &request);

View File

@ -334,6 +334,52 @@ tl_object_ptr<telegram_api::InputMedia> VideosManager::get_input_media(
return nullptr;
}
telegram_api::object_ptr<telegram_api::InputMedia> VideosManager::get_story_document_input_media(
FileId file_id, double main_frame_timestamp) const {
auto file_view = td_->file_manager_->get_file_view(file_id);
if (file_view.is_encrypted() || !file_view.has_remote_location() || file_view.main_remote_location().is_web()) {
return nullptr;
}
const Video *video = get_video(file_id);
CHECK(video != nullptr);
vector<telegram_api::object_ptr<telegram_api::DocumentAttribute>> attributes;
{
int32 attribute_flags = 0;
if (video->supports_streaming) {
attribute_flags |= telegram_api::documentAttributeVideo::SUPPORTS_STREAMING_MASK;
}
if (video->is_animation) {
attribute_flags |= telegram_api::documentAttributeVideo::NOSOUND_MASK;
}
if (main_frame_timestamp > 0.0) {
attribute_flags |= telegram_api::documentAttributeVideo::VIDEO_START_TS_MASK;
}
attributes.push_back(telegram_api::make_object<telegram_api::documentAttributeVideo>(
attribute_flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, video->precise_duration,
video->dimensions.width, video->dimensions.height, 0, main_frame_timestamp));
}
if (!video->file_name.empty()) {
attributes.push_back(make_tl_object<telegram_api::documentAttributeFilename>(video->file_name));
}
int32 flags = telegram_api::inputMediaUploadedDocument::NOSOUND_VIDEO_MASK;
vector<telegram_api::object_ptr<telegram_api::InputDocument>> added_stickers;
if (video->has_stickers) {
flags |= telegram_api::inputMediaUploadedDocument::STICKERS_MASK;
added_stickers = td_->file_manager_->get_input_documents(video->sticker_file_ids);
}
string mime_type = video->mime_type;
if (!begins_with(mime_type, "video/")) {
mime_type = "video/mp4";
}
return telegram_api::make_object<telegram_api::inputMediaUploadedDocument>(
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/,
telegram_api::make_object<telegram_api::inputFileStoryDocument>(
file_view.main_remote_location().as_input_document()),
nullptr, mime_type, std::move(attributes), std::move(added_stickers), 0);
}
string VideosManager::get_video_search_text(FileId file_id) const {
auto *video = get_video(file_id);
CHECK(video != nullptr);

View File

@ -46,6 +46,9 @@ class VideosManager {
tl_object_ptr<telegram_api::InputFile> input_thumbnail,
int32 ttl, bool has_spoiler) const;
telegram_api::object_ptr<telegram_api::InputMedia> get_story_document_input_media(FileId file_id,
double main_frame_timestamp) const;
SecretInputMedia get_secret_input_media(FileId video_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
const string &caption, BufferSlice thumbnail, int32 layer) const;

View File

@ -4691,6 +4691,12 @@ class CliClient final : public Actor {
td_api::make_object<td_api::inputStoryContentVideo>(
as_input_file(video), to_integers<int32>(sticker_file_ids), duration, 0.0, false),
areas, as_caption(caption)));
} else if (op == "esco") {
ChatId story_sender_chat_id;
StoryId story_id;
double cover_frame_timetamp;
get_args(args, story_sender_chat_id, story_id, cover_frame_timetamp);
send_request(td_api::make_object<td_api::editStoryCover>(story_sender_chat_id, story_id, cover_frame_timetamp));
} else if (op == "ssps") {
StoryId story_id;
StoryPrivacySettings rules;