2
0
mirror of https://github.com/tdlib/telegram-bot-api synced 2025-08-22 09:57:44 +00:00

Add postStory.

This commit is contained in:
levlam 2025-03-31 13:13:42 +03:00
parent db7c26bd0e
commit 794cae79cd
2 changed files with 167 additions and 1 deletions

View File

@ -250,6 +250,7 @@ bool Client::init_methods() {
methods_.emplace("editmessagereplymarkup", &Client::process_edit_message_reply_markup_query);
methods_.emplace("deletemessage", &Client::process_delete_message_query);
methods_.emplace("deletemessages", &Client::process_delete_messages_query);
methods_.emplace("poststory", &Client::process_post_story_query);
methods_.emplace("createinvoicelink", &Client::process_create_invoice_link_query);
methods_.emplace("getstartransactions", &Client::process_get_star_transactions_query);
methods_.emplace("refundstarpayment", &Client::process_refund_star_payment_query);
@ -5344,6 +5345,45 @@ class Client::TdOnStopBusinessPollCallback final : public TdQueryCallback {
PromisedQueryPtr query_;
};
class Client::TdOnPostStoryCallback final : public TdQueryCallback {
public:
TdOnPostStoryCallback(Client *client, PromisedQueryPtr query) : client_(client), query_(std::move(query)) {
}
void on_result(object_ptr<td_api::Object> result) final {
if (result->get_id() == td_api::error::ID) {
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result));
}
CHECK(result->get_id() == td_api::story::ID);
client_->on_sent_story(move_object_as<td_api::story>(result), std::move(query_));
}
private:
Client *client_;
PromisedQueryPtr query_;
};
class Client::TdOnGetStoryCallback final : public TdQueryCallback {
public:
TdOnGetStoryCallback(Client *client, PromisedQueryPtr query) : client_(client), query_(std::move(query)) {
}
void on_result(object_ptr<td_api::Object> result) final {
if (result->get_id() == td_api::error::ID) {
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result));
}
CHECK(result->get_id() == td_api::story::ID);
auto story = static_cast<const td_api::story *>(result.get());
answer_query(JsonStory(story->sender_chat_id_, story->id_, client_), std::move(query_));
}
private:
Client *client_;
PromisedQueryPtr query_;
};
class Client::TdOnOkQueryCallback final : public TdQueryCallback {
public:
explicit TdOnOkQueryCallback(PromisedQueryPtr query) : query_(std::move(query)) {
@ -7693,6 +7733,16 @@ void Client::on_update(object_ptr<td_api::Object> result) {
std::move(update->error_));
break;
}
case td_api::updateStorySendSucceeded::ID: {
auto update = move_object_as<td_api::updateStorySendSucceeded>(result);
on_story_send_succeeded(std::move(update->story_), update->old_story_id_);
break;
}
case td_api::updateStorySendFailed::ID: {
auto update = move_object_as<td_api::updateStorySendFailed>(result);
on_story_send_failed(update->story_->sender_chat_id_, update->story_->id_, std::move(update->error_));
break;
}
case td_api::updateMessageContent::ID: {
auto update = move_object_as<td_api::updateMessageContent>(result);
update_message_content(update->chat_id_, update->message_id_, std::move(update->new_content_));
@ -10686,6 +10736,53 @@ td::Result<td_api::object_ptr<td_api::InputChatPhoto>> Client::get_input_chat_ph
return get_input_chat_photo(query, r_value.move_as_ok());
}
td::Result<td_api::object_ptr<td_api::InputStoryContent>> Client::get_input_story_content(const Query *query,
td::JsonValue &&value) const {
if (value.type() != td::JsonValue::Type::Object) {
return td::Status::Error(400, "Object expected as story content");
}
auto &object = value.get_object();
TRY_RESULT(type, object.get_required_string_field("type"));
if (type == "photo") {
TRY_RESULT(photo, object.get_required_string_field("photo"));
auto input_file = get_input_file(query, td::Slice(), photo, true);
if (input_file == nullptr) {
return td::Status::Error(400, "Story photo must be uploaded as a file");
}
return make_object<td_api::inputStoryContentPhoto>(std::move(input_file), td::vector<int32>());
}
if (type == "video") {
TRY_RESULT(video, object.get_required_string_field("video"));
TRY_RESULT(duration, object.get_optional_double_field("duration"));
TRY_RESULT(cover_frame_timestamp, object.get_optional_double_field("cover_frame_timestamp"));
TRY_RESULT(is_animation, object.get_optional_bool_field("is_animation"));
auto input_file = get_input_file(query, td::Slice(), video, true);
if (input_file == nullptr) {
return td::Status::Error(400, "Story video must be uploaded as a file");
}
return make_object<td_api::inputStoryContentVideo>(std::move(input_file), td::vector<int32>(), duration,
cover_frame_timestamp, is_animation);
}
return td::Status::Error(400, "Invalid story content type specified");
}
td::Result<td_api::object_ptr<td_api::InputStoryContent>> Client::get_input_story_content(const Query *query) const {
auto content = query->arg("content");
if (content.empty()) {
return td::Status::Error(400, "Story content isn't specified");
}
LOG(INFO) << "Parsing JSON object: " << content;
auto r_value = json_decode(content);
if (r_value.is_error()) {
LOG(INFO) << "Can't parse JSON object: " << r_value.error();
return td::Status::Error(400, "Can't parse story content JSON object");
}
return get_input_story_content(query, r_value.move_as_ok());
}
td::Result<td_api::object_ptr<td_api::acceptedGiftTypes>> Client::get_accepted_gift_types(td::JsonValue &&value) {
if (value.type() != td::JsonValue::Type::Object) {
return td::Status::Error(400, "Object expected as accepted gift types");
@ -10896,6 +10993,24 @@ void Client::on_message_send_failed(int64 chat_id, int64 old_message_id, int64 n
}
}
void Client::on_story_send_succeeded(object_ptr<td_api::story> &&story, int64 old_story_id) {
auto full_story_id = FullMessageId{story->sender_chat_id_, old_story_id};
auto yet_unsent_story_it = yet_unsent_stories_.find(full_story_id);
CHECK(yet_unsent_story_it != yet_unsent_stories_.end());
auto query = std::move(yet_unsent_story_it->second.query);
yet_unsent_stories_.erase(yet_unsent_story_it);
answer_query(JsonStory(story->sender_chat_id_, story->id_, this), std::move(query));
}
void Client::on_story_send_failed(int64 chat_id, int64 story_id, object_ptr<td_api::error> &&error) {
auto full_story_id = FullMessageId{chat_id, story_id};
auto yet_unsent_story_it = yet_unsent_stories_.find(full_story_id);
CHECK(yet_unsent_story_it != yet_unsent_stories_.end());
auto query = std::move(yet_unsent_story_it->second.query);
yet_unsent_stories_.erase(yet_unsent_story_it);
fail_query_with_error(std::move(query), std::move(error));
}
void Client::on_cmd(PromisedQueryPtr query, bool force) {
LOG(DEBUG) << "Process query " << *query;
if (!td_client_.empty() && was_authorized_) {
@ -11926,6 +12041,26 @@ td::Status Client::process_delete_messages_query(PromisedQueryPtr &query) {
return td::Status::OK();
}
td::Status Client::process_post_story_query(PromisedQueryPtr &query) {
auto business_connection_id = query->arg("business_connection_id").str();
TRY_RESULT(content, get_input_story_content(query.get()));
TRY_RESULT(caption, get_formatted_text(query->arg("caption").str(), query->arg("parse_mode").str(),
get_input_entities(query.get(), "caption_entities")));
check_business_connection(business_connection_id, std::move(query),
[this, content = std::move(content), caption = std::move(caption)](
const BusinessConnection *business_connection, PromisedQueryPtr query) mutable {
auto active_period = get_integer_arg(query.get(), "active_period", 0, 0, 1000000000);
auto is_posted_to_chat_page = to_bool(query->arg("post_to_chat_page"));
auto protect_content = to_bool(query->arg("protect_content"));
send_request(make_object<td_api::sendStory>(
business_connection->user_chat_id_, std::move(content), td::Auto(),
std::move(caption), make_object<td_api::storyPrivacySettingsEveryone>(),
active_period, nullptr, is_posted_to_chat_page, protect_content),
td::make_unique<TdOnPostStoryCallback>(this, std::move(query)));
});
return td::Status::OK();
}
td::Status Client::process_create_invoice_link_query(PromisedQueryPtr &query) {
TRY_RESULT(input_message_invoice, get_input_message_invoice(query.get()));
auto business_connection_id = query->arg("business_connection_id").str();
@ -12429,7 +12564,7 @@ td::Status Client::process_set_business_account_gift_settings_query(PromisedQuer
auto business_connection_id = query->arg("business_connection_id").str();
auto show_gift_button = to_bool(query->arg("show_gift_button"));
TRY_RESULT(accepted_gift_types, get_accepted_gift_types(query.get()));
auto settings = td_api::make_object<td_api::giftSettings>(show_gift_button, std::move(accepted_gift_types));
auto settings = make_object<td_api::giftSettings>(show_gift_button, std::move(accepted_gift_types));
check_business_connection(
business_connection_id, std::move(query),
[this, settings = std::move(settings)](const BusinessConnection *business_connection,
@ -13950,6 +14085,18 @@ void Client::on_sent_message(object_ptr<td_api::message> &&message, int64 query_
query.total_message_count++;
}
void Client::on_sent_story(object_ptr<td_api::story> &&story, PromisedQueryPtr query) {
CHECK(story != nullptr);
int64 chat_id = story->sender_chat_id_;
int64 story_id = story->id_;
FullMessageId full_story_id{chat_id, story_id};
YetUnsentStory yet_unsent_story;
yet_unsent_story.query = std::move(query);
auto emplace_result = yet_unsent_stories_.emplace(full_story_id, std::move(yet_unsent_story));
CHECK(emplace_result.second);
}
void Client::abort_long_poll(bool from_set_webhook) {
if (long_poll_query_) {
td::Slice message;

View File

@ -243,6 +243,8 @@ class Client final : public WebhookActor::Callback {
class TdOnEditInlineMessageCallback;
class TdOnStopPollCallback;
class TdOnStopBusinessPollCallback;
class TdOnPostStoryCallback;
class TdOnGetStoryCallback;
class TdOnOkQueryCallback;
class TdOnGetReplyMessageCallback;
class TdOnGetEditedMessageCallback;
@ -627,6 +629,11 @@ class Client final : public WebhookActor::Callback {
td::Result<object_ptr<td_api::InputChatPhoto>> get_input_chat_photo(const Query *query) const;
td::Result<object_ptr<td_api::InputStoryContent>> get_input_story_content(const Query *query,
td::JsonValue &&value) const;
td::Result<object_ptr<td_api::InputStoryContent>> get_input_story_content(const Query *query) const;
static td::Result<object_ptr<td_api::acceptedGiftTypes>> get_accepted_gift_types(td::JsonValue &&value);
static td::Result<object_ptr<td_api::acceptedGiftTypes>> get_accepted_gift_types(const Query *query);
@ -656,6 +663,10 @@ class Client final : public WebhookActor::Callback {
void on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id,
object_ptr<td_api::error> &&error);
void on_story_send_succeeded(object_ptr<td_api::story> &&story, int64 old_story_id);
void on_story_send_failed(int64 chat_id, int64 story_id, object_ptr<td_api::error> &&error);
static bool init_methods();
static bool is_local_method(td::Slice method);
@ -709,6 +720,7 @@ class Client final : public WebhookActor::Callback {
td::Status process_edit_message_reply_markup_query(PromisedQueryPtr &query);
td::Status process_delete_message_query(PromisedQueryPtr &query);
td::Status process_delete_messages_query(PromisedQueryPtr &query);
td::Status process_post_story_query(PromisedQueryPtr &query);
td::Status process_create_invoice_link_query(PromisedQueryPtr &query);
td::Status process_get_star_transactions_query(PromisedQueryPtr &query);
td::Status process_refund_star_payment_query(PromisedQueryPtr &query);
@ -835,6 +847,8 @@ class Client final : public WebhookActor::Callback {
void on_sent_message(object_ptr<td_api::message> &&message, int64 query_id);
void on_sent_story(object_ptr<td_api::story> &&story, PromisedQueryPtr query);
void do_get_file(object_ptr<td_api::file> file, PromisedQueryPtr query);
bool is_file_being_downloaded(int32 file_id) const;
@ -1300,6 +1314,11 @@ class Client final : public WebhookActor::Callback {
td::FlatHashMap<int64, int32> yet_unsent_message_count_; // chat_id -> count
struct YetUnsentStory {
PromisedQueryPtr query;
};
td::FlatHashMap<FullMessageId, YetUnsentStory, FullMessageIdHash> yet_unsent_stories_;
struct PendingSendMessageQuery {
PromisedQueryPtr query;
bool is_multisend = false;