tdlight-telegram-bot-api/telegram-bot-api/Client.h
2024-09-09 00:34:57 +02:00

1519 lines
63 KiB
C++

//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "telegram-bot-api/Query.h"
#include "telegram-bot-api/Stats.h"
#include "telegram-bot-api/WebhookActor.h"
#include "td/telegram/ClientActor.h"
#include "td/telegram/td_api.h"
#include "td/net/HttpFile.h"
#include "td/actor/actor.h"
#include "td/actor/SignalSlot.h"
#include "td/utils/common.h"
#include "td/utils/Container.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/FlatHashSet.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/Promise.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/WaitFreeHashMap.h"
#include <limits>
#include <memory>
#include <queue>
namespace telegram_bot_api {
struct ClientParameters;
namespace td_api = td::td_api;
class Client final : public WebhookActor::Callback {
public:
Client(td::ActorShared<> parent, const td::string &bot_token, bool is_user, bool is_test_dc, td::int64 tqueue_id,
std::shared_ptr<const ClientParameters> parameters, td::ActorId<BotStatActor> stat_actor);
Client(const Client &) = delete;
Client &operator=(const Client &) = delete;
Client(Client &&) = delete;
Client &operator=(Client &&) = delete;
~Client();
void send(PromisedQueryPtr query) final;
void close();
// for stats
ServerBotInfo get_bot_info() const;
private:
using int32 = td::int32;
using int64 = td::int64;
template <class T>
using object_ptr = td_api::object_ptr<T>;
static constexpr bool USE_MESSAGE_DATABASE = false;
static constexpr int64 GENERAL_MESSAGE_THREAD_ID = 1 << 20;
static constexpr int32 MAX_CERTIFICATE_FILE_SIZE = 3 << 20;
static constexpr int32 MAX_DOWNLOAD_FILE_SIZE = 20 << 20;
static constexpr int32 MAX_CONCURRENTLY_SENT_CHAT_MESSAGES = 310; // some unreasonably big value
static constexpr std::size_t MIN_PENDING_UPDATES_WARNING = 200;
static constexpr int64 GREAT_MINDS_SET_ID = 1842540969984001;
static constexpr td::Slice GREAT_MINDS_SET_NAME = "TelegramGreatMinds";
static constexpr int32 MASK_POINTS_SIZE = 4;
static constexpr td::Slice MASK_POINTS[MASK_POINTS_SIZE] = {"forehead", "eyes", "mouth", "chin"};
static constexpr int32 MAX_LENGTH = 10000; // max width or height
static constexpr int32 MAX_DURATION = 24 * 60 * 60;
static constexpr std::size_t MAX_STICKER_EMOJI_COUNT = 20;
static constexpr int LOGGING_OUT_ERROR_CODE = 401;
static constexpr td::Slice LOGGING_OUT_ERROR_DESCRIPTION = "Unauthorized";
static constexpr td::Slice API_ID_INVALID_ERROR_DESCRIPTION = "Unauthorized: invalid api-id/api-hash";
static constexpr int CLOSING_ERROR_CODE = 500;
static constexpr td::Slice CLOSING_ERROR_DESCRIPTION = "Internal Server Error: restart";
static constexpr int BOT_ONLY_ERROR_CODE = 405;
static constexpr td::Slice BOT_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a bot";
static constexpr int USER_ONLY_ERROR_CODE = 405;
static constexpr td::Slice USER_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a user";
class JsonEmptyObject;
class JsonFile;
class JsonDatedFile;
class JsonDatedFiles;
class JsonUser;
class JsonUsers;
class JsonReactionType;
class JsonReactionCount;
class JsonBirthdate;
class JsonBusinessStartPage;
class JsonBusinessLocation;
class JsonBusinessOpeningHoursInterval;
class JsonBusinessOpeningHours;
class JsonChatPermissions;
class JsonChatPhotoInfo;
class JsonChatLocation;
class JsonChatInviteLink;
class JsonChat;
class JsonMessageSender;
class JsonMessageOrigin;
class JsonExternalReplyInfo;
class JsonTextQuote;
class JsonLinkPreviewOptions;
class JsonAnimation;
class JsonAudio;
class JsonDocument;
class JsonPhotoSize;
class JsonPhoto;
class JsonChatPhoto;
class JsonThumbnail;
class JsonMaskPosition;
class JsonSticker;
class JsonStickers;
class JsonVideo;
class JsonVideoNote;
class JsonVoiceNote;
class JsonPaidMedia;
class JsonPaidMediaInfo;
class JsonContact;
class JsonDice;
class JsonGame;
class JsonInvoice;
class JsonLocation;
class JsonVenue;
class JsonPollOption;
class JsonPoll;
class JsonPollAnswer;
class JsonEntity;
class JsonVectorEntities;
class JsonWebAppInfo;
class JsonInlineKeyboardButton;
class JsonInlineKeyboard;
class JsonReplyMarkup;
class JsonMessage;
class JsonMessages;
class JsonInaccessibleMessage;
class JsonMessageId;
class JsonInlineQuery;
class JsonChosenInlineResult;
class JsonCallbackQuery;
class JsonInlineCallbackQuery;
class JsonShippingQuery;
class JsonPreCheckoutQuery;
class JsonPaidMediaPurchased;
class JsonBotCommand;
class JsonBotMenuButton;
class JsonBotName;
class JsonBotInfoDescription;
class JsonBotInfoShortDescription;
class JsonChatAdministratorRights;
class JsonChatPhotos;
class JsonChatMember;
class JsonChatMembers;
class JsonChatMemberUpdated;
class JsonChatJoinRequest;
class JsonChatBoostSource;
class JsonChatBoost;
class JsonChatBoostUpdated;
class JsonChatBoostRemoved;
class JsonChatBoosts;
class JsonForumTopicCreated;
class JsonForumTopicEdited;
class JsonForumTopicInfo;
class JsonGameHighScore;
class JsonMessageReactionUpdated;
class JsonMessageReactionCountUpdated;
class JsonBusinessConnection;
class JsonBusinessMessagesDeleted;
class JsonAddress;
class JsonOrderInfo;
class JsonStory;
class JsonBackgroundFill;
class JsonBackgroundType;
class JsonChatBackground;
class JsonSuccessfulPaymentBot;
class JsonRefundedPayment;
class JsonEncryptedPassportElement;
class JsonEncryptedCredentials;
class JsonPassportData;
class JsonWebAppData;
class JsonProximityAlertTriggered;
class JsonVideoChatScheduled;
class JsonVideoChatEnded;
class JsonInviteVideoChatParticipants;
class JsonChatSetMessageAutoDeleteTime;
class JsonWriteAccessAllowed;
class JsonUserShared;
class JsonSharedUser;
class JsonUsersShared;
class JsonChatShared;
class JsonGiveawayCreated;
class JsonGiveaway;
class JsonGiveawayWinners;
class JsonGiveawayCompleted;
class JsonChatBoostAdded;
class JsonRevenueWithdrawalState;
class JsonStarTransactionPartner;
class JsonStarTransaction;
class JsonStarTransactions;
class JsonUpdateTypes;
class JsonWebhookInfo;
class JsonStickerSet;
class JsonSentWebAppMessage;
class JsonCustomJson;
//start custom Json objects
class JsonAuthorizationState;
class JsonCallbackQueryAnswer;
class JsonChats;
class JsonChatsNearby;
class JsonMessagesArray;
class JsonFoundMessages;
class JsonProxy;
class JsonProxiesArray;
//stop custom Json objects
class TdOnOkCallback;
class TdOnAuthorizationCallback;
class TdOnAuthorizationQueryCallback;
class TdOnInitCallback;
class TdOnGetUserProfilePhotosCallback;
class TdOnSendMessageCallback;
class TdOnReturnBusinessMessageCallback;
class TdOnSendMessageAlbumCallback;
class TdOnSendBusinessMessageAlbumCallback;
class TdOnForwardMessagesCallback;
class TdOnDeleteFailedToSendMessageCallback;
class TdOnEditMessageCallback;
class TdOnEditInlineMessageCallback;
class TdOnStopPollCallback;
class TdOnStopBusinessPollCallback;
class TdOnOkQueryCallback;
class TdOnGetReplyMessageCallback;
class TdOnGetEditedMessageCallback;
class TdOnGetCallbackQueryMessageCallback;
class TdOnGetStickerSetCallback;
class TdOnGetForumTopicInfoCallback;
class TdOnGetMenuButtonCallback;
class TdOnGetMyCommandsCallback;
class TdOnGetMyDefaultAdministratorRightsCallback;
class TdOnGetMyNameCallback;
class TdOnGetMyDescriptionCallback;
class TdOnGetMyShortDescriptionCallback;
class TdOnGetChatFullInfoCallback;
class TdOnGetChatStickerSetCallback;
class TdOnGetChatCustomEmojiStickerSetCallback;
class TdOnGetChatBusinessStartPageStickerSetCallback;
class TdOnGetChatPinnedMessageCallback;
class TdOnGetChatPinnedMessageToUnpinCallback;
class TdOnGetGroupMembersCallback;
class TdOnGetSupergroupMembersCallback;
class TdOnGetSupergroupMemberCountCallback;
class TdOnGetUserChatBoostsCallback;
class TdOnCreateInvoiceLinkCallback;
class TdOnGetStarTransactionsQueryCallback;
class TdOnReplacePrimaryChatInviteLinkCallback;
class TdOnGetChatInviteLinkCallback;
class TdOnGetGameHighScoresCallback;
class TdOnAnswerWebAppQueryCallback;
class TdOnReturnFileCallback;
class TdOnReturnStickerSetCallback;
class TdOnGetStickerSetPromiseCallback;
class TdOnGetStickersCallback;
class TdOnDownloadFileCallback;
class TdOnCancelDownloadFileCallback;
class TdOnSendCustomRequestCallback;
//start custom callbacks
class TdOnPingCallback;
class TdOnGetMemoryStatisticsCallback;
class TdOnGetChatsCallback;
class TdOnGetChatsNearbyCallback;
class TdOnJoinChatCallback;
class TdOnReturnChatCallback;
class TdOnReturnMessagesCallback;
class TdOnFoundMessagesCallback;
class TdOnGetCallbackQueryAnswerCallback;
class TdOnGetProxiesQueryCallback;
class TdOnAddProxyQueryCallback;
//end custom callbacks
void on_get_reply_message(int64 chat_id, object_ptr<td_api::message> reply_to_message);
void on_get_edited_message(object_ptr<td_api::message> edited_message);
void on_get_callback_query_message(object_ptr<td_api::message> message, int64 user_id, int state);
void on_get_sticker_set(int64 set_id, int64 new_callback_query_user_id, int64 new_message_chat_id,
const td::string &new_message_business_connection_id,
int64 new_business_callback_query_user_id, object_ptr<td_api::text> sticker_set_name);
void on_get_sticker_set_name(int64 set_id, const td::string &name);
void on_get_sticker_set_name(int64 set_id, object_ptr<td_api::Object> sticker_set_name);
class TdQueryCallback {
public:
virtual void on_result(object_ptr<td_api::Object> result) = 0;
TdQueryCallback() = default;
TdQueryCallback(const TdQueryCallback &) = delete;
TdQueryCallback &operator=(const TdQueryCallback &) = delete;
TdQueryCallback(TdQueryCallback &&) = delete;
TdQueryCallback &operator=(TdQueryCallback &&) = delete;
virtual ~TdQueryCallback() = default;
};
struct InputReplyParameters {
td::string reply_in_chat_id;
int64 reply_to_message_id = 0;
bool allow_sending_without_reply = false;
object_ptr<td_api::inputTextQuote> quote;
};
struct CheckedReplyParameters {
int64 reply_in_chat_id = 0;
int64 reply_to_message_id = 0;
object_ptr<td_api::inputTextQuote> quote;
};
struct UserInfo;
struct ChatInfo;
struct BotCommandScope;
struct BotUserIds;
enum class AccessRights { Read, ReadMembers, Edit, Write };
template <class OnSuccess>
class TdOnCheckUserCallback;
template <class OnSuccess>
class TdOnCheckUserNoFailCallback;
template <class OnSuccess>
class TdOnCheckChatCallback;
template <class OnSuccess>
class TdOnEnableInternetConnectionCallback;
template <class OnSuccess>
class TdOnOptimizeMemoryCallback;
template <class OnSuccess>
class TdOnDisableInternetConnectionCallback;
template <class OnSuccess>
class TdOnCheckChatNoFailCallback;
template <class OnSuccess>
class TdOnCheckMessageCallback;
template <class OnSuccess>
class TdOnCheckMessagesCallback;
template <class OnSuccess>
class TdOnCheckMessageThreadCallback;
template <class OnSuccess>
class TdOnCheckBusinessConnectionCallback;
template <class OnSuccess>
class TdOnCheckRemoteFileIdCallback;
template <class OnSuccess>
class TdOnGetChatMemberCallback;
template <class OnSuccess>
class TdOnSearchStickerSetCallback;
class TdOnResolveBotUsernameCallback;
template <class OnSuccess>
void check_user(int64 user_id, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_user_no_fail(int64 user_id, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
static void check_user_read_access(const UserInfo *user_info, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_chat_access(int64 chat_id, AccessRights access_rights, const ChatInfo *chat_info, PromisedQueryPtr query,
OnSuccess on_success) const;
template <class OnSuccess>
void check_chat(td::Slice chat_id_str, AccessRights access_rights, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_chat_no_fail(td::Slice chat_id_str, PromisedQueryPtr query, OnSuccess on_success);
static td::Result<int64> get_business_connection_chat_id(td::Slice chat_id_str);
template <class OnSuccess>
void check_business_connection(const td::string &business_connection_id, PromisedQueryPtr query,
OnSuccess on_success);
template <class OnSuccess>
void check_business_connection_chat_id(const td::string &business_connection_id, const td::string &chat_id_str,
PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_bot_command_scope(BotCommandScope &&scope, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_remote_file_id(td::string file_id, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_message(td::Slice chat_id_str, int64 message_id, bool allow_empty, AccessRights access_rights,
td::Slice message_type, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_messages(td::Slice chat_id_str, td::vector<int64> message_ids, bool allow_empty,
AccessRights access_rights, td::Slice message_type, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void check_reply_parameters(td::Slice chat_id_str, InputReplyParameters &&reply_parameters, int64 message_thread_id,
PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void resolve_sticker_set(const td::string &sticker_set_name, PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void resolve_reply_markup_bot_usernames(object_ptr<td_api::ReplyMarkup> reply_markup, PromisedQueryPtr query,
OnSuccess on_success);
template <class OnSuccess>
void resolve_inline_query_results_bot_usernames(td::vector<object_ptr<td_api::InputInlineQueryResult>> results,
PromisedQueryPtr query, OnSuccess on_success);
template <class OnSuccess>
void get_chat_member(int64 chat_id, int64 user_id, PromisedQueryPtr query, OnSuccess on_success);
void send_request(object_ptr<td_api::Function> &&f, td::unique_ptr<TdQueryCallback> handler);
void do_send_request(object_ptr<td_api::Function> &&f, td::unique_ptr<TdQueryCallback> handler);
static object_ptr<td_api::Object> execute(object_ptr<td_api::Function> &&f);
void on_update(object_ptr<td_api::Object> result);
void on_result(td::uint64 id, object_ptr<td_api::Object> result);
void on_update_authorization_state();
void log_out(int32 error_code, td::Slice error_message);
void on_closed();
void finish_closing();
void clear_tqueue();
bool allow_update_before_authorization(const td_api::Object *update) const;
void update_shared_unix_time_difference();
void on_update_file(object_ptr<td_api::file> file);
static bool to_bool(td::MutableSlice value);
static object_ptr<td_api::InputMessageReplyTo> get_input_message_reply_to(CheckedReplyParameters &&reply_parameters);
static object_ptr<td_api::InputMessageReplyTo> get_input_message_reply_to(InputReplyParameters &&reply_parameters);
static td::Result<InputReplyParameters> get_reply_parameters(const Query *query);
static td::Result<InputReplyParameters> get_reply_parameters(td::JsonValue &&value);
static td::Result<object_ptr<td_api::keyboardButton>> get_keyboard_button(td::JsonValue &button);
static td::Result<object_ptr<td_api::inlineKeyboardButton>> get_inline_keyboard_button(td::JsonValue &button,
BotUserIds &bot_user_ids);
static td::Result<object_ptr<td_api::ReplyMarkup>> get_reply_markup(const Query *query, BotUserIds &bot_user_ids);
static td::Result<object_ptr<td_api::ReplyMarkup>> get_reply_markup(td::JsonValue &&value, BotUserIds &bot_user_ids);
static td::Result<object_ptr<td_api::labeledPricePart>> get_labeled_price_part(td::JsonValue &value);
static td::Result<td::vector<object_ptr<td_api::labeledPricePart>>> get_labeled_price_parts(td::JsonValue &value);
static td::Result<td::vector<int64>> get_suggested_tip_amounts(td::JsonValue &value);
static td::Result<object_ptr<td_api::shippingOption>> get_shipping_option(td::JsonValue &option);
static td::Result<td::vector<object_ptr<td_api::shippingOption>>> get_shipping_options(const Query *query);
static td::Result<td::vector<object_ptr<td_api::shippingOption>>> get_shipping_options(td::JsonValue &&value);
static td::Result<object_ptr<td_api::InputMessageContent>> get_input_message_content(
td::JsonValue &input_message_content, bool is_input_message_content_required);
static object_ptr<td_api::ChatAction> get_chat_action(const Query *query);
static td::string get_local_file_path(td::Slice file_uri);
object_ptr<td_api::InputFile> get_input_file(const Query *query, td::Slice field_name, bool force_file = false) const;
object_ptr<td_api::InputFile> get_input_file(const Query *query, td::Slice field_name, td::Slice file_id,
bool force_file) const;
object_ptr<td_api::inputThumbnail> get_input_thumbnail(const Query *query) const;
static td::Result<td_api::object_ptr<td_api::inlineQueryResultsButton>> get_inline_query_results_button(
td::JsonValue &&value);
static td::Result<td_api::object_ptr<td_api::inlineQueryResultsButton>> get_inline_query_results_button(
td::MutableSlice value);
static td::Result<object_ptr<td_api::InputInlineQueryResult>> get_inline_query_result(const Query *query,
BotUserIds &bot_user_ids);
static td::Result<object_ptr<td_api::InputInlineQueryResult>> get_inline_query_result(td::JsonValue &&value,
BotUserIds &bot_user_ids);
static td::Result<td::vector<object_ptr<td_api::InputInlineQueryResult>>> get_inline_query_results(
const Query *query, BotUserIds &bot_user_ids);
static td::Result<td::vector<object_ptr<td_api::InputInlineQueryResult>>> get_inline_query_results(
td::JsonValue &&value, BotUserIds &bot_user_ids);
struct BotCommandScope {
object_ptr<td_api::BotCommandScope> scope_;
td::string chat_id_;
int64 user_id_ = 0;
explicit BotCommandScope(object_ptr<td_api::BotCommandScope> scope, td::string chat_id = td::string(),
int64 user_id = 0)
: scope_(std::move(scope)), chat_id_(std::move(chat_id)), user_id_(user_id) {
}
};
static td::Result<BotCommandScope> get_bot_command_scope(const Query *query);
static td::Result<BotCommandScope> get_bot_command_scope(td::JsonValue &&value);
static td::Result<object_ptr<td_api::botCommand>> get_bot_command(td::JsonValue &&value);
static td::Result<td::vector<object_ptr<td_api::botCommand>>> get_bot_commands(const Query *query);
static td::Result<object_ptr<td_api::botMenuButton>> get_bot_menu_button(const Query *query);
static td::Result<object_ptr<td_api::botMenuButton>> get_bot_menu_button(td::JsonValue &&value);
static td::Result<object_ptr<td_api::chatAdministratorRights>> get_chat_administrator_rights(td::JsonValue &&value);
static td::Result<object_ptr<td_api::chatAdministratorRights>> get_chat_administrator_rights(const Query *query);
static td::Result<object_ptr<td_api::maskPosition>> get_mask_position(const Query *query, td::Slice field_name);
static td::Result<object_ptr<td_api::maskPosition>> get_mask_position(td::JsonValue &&value);
static int32 mask_point_to_index(const object_ptr<td_api::MaskPoint> &mask_point);
static object_ptr<td_api::MaskPoint> mask_index_to_point(int32 index);
static td::Result<td::string> get_sticker_emojis(td::JsonValue &&value);
static td::Result<td::string> get_sticker_emojis(td::MutableSlice emoji_list);
static td::Result<object_ptr<td_api::StickerFormat>> get_sticker_format(td::Slice sticker_format);
td::Result<object_ptr<td_api::inputSticker>> get_legacy_input_sticker(const Query *query) const;
td::Result<object_ptr<td_api::inputSticker>> get_input_sticker(const Query *query) const;
td::Result<object_ptr<td_api::inputSticker>> get_input_sticker(const Query *query, td::JsonValue &&value,
td::Slice default_sticker_format) const;
td::Result<td::vector<object_ptr<td_api::inputSticker>>> get_input_stickers(const Query *query) const;
static td::Result<object_ptr<td_api::InputFile>> get_sticker_input_file(const Query *query,
td::Slice field_name = "sticker");
static td::Result<td::string> get_passport_element_hash(td::Slice encoded_hash);
static td::Result<object_ptr<td_api::InputPassportElementErrorSource>> get_passport_element_error_source(
td::JsonObject &object);
static td::Result<object_ptr<td_api::inputPassportElementError>> get_passport_element_error(td::JsonValue &&value);
static td::Result<td::vector<object_ptr<td_api::inputPassportElementError>>> get_passport_element_errors(
const Query *query);
static td::JsonValue get_input_entities(const Query *query, td::Slice field_name);
static td::Result<object_ptr<td_api::formattedText>> get_caption(const Query *query);
static td::Result<object_ptr<td_api::TextEntityType>> get_text_entity_type(td::JsonObject &object);
static td::Result<object_ptr<td_api::textEntity>> get_text_entity(td::JsonValue &&value);
static td::Result<object_ptr<td_api::formattedText>> get_formatted_text(td::string text, td::string parse_mode,
td::JsonValue &&input_entities);
static object_ptr<td_api::linkPreviewOptions> get_link_preview_options(bool disable_web_page_preview);
static td::Result<object_ptr<td_api::linkPreviewOptions>> get_link_preview_options(const Query *query);
static td::Result<object_ptr<td_api::linkPreviewOptions>> get_link_preview_options(td::JsonValue &&value);
static td::Result<object_ptr<td_api::inputMessageText>> get_input_message_text(const Query *query);
static td::Result<object_ptr<td_api::inputMessageText>> get_input_message_text(
td::string text, object_ptr<td_api::linkPreviewOptions> link_preview_options, td::string parse_mode,
td::JsonValue &&input_entities);
static td::Result<object_ptr<td_api::location>> get_location(const Query *query);
static td::Result<object_ptr<td_api::chatPermissions>> get_chat_permissions(const Query *query, bool &allow_legacy,
bool use_independent_chat_permissions);
td::Result<object_ptr<td_api::InputMessageContent>> get_input_media(const Query *query, td::JsonValue &&input_media,
bool for_album) const;
td::Result<object_ptr<td_api::InputMessageContent>> get_input_media(const Query *query, td::Slice field_name) const;
td::Result<td::vector<object_ptr<td_api::InputMessageContent>>> get_input_message_contents(
const Query *query, td::Slice field_name) const;
td::Result<td::vector<object_ptr<td_api::InputMessageContent>>> get_input_message_contents(
const Query *query, td::JsonValue &&value) const;
td::Result<object_ptr<td_api::inputPaidMedia>> get_input_paid_media(const Query *query,
td::JsonValue &&input_media) const;
td::Result<object_ptr<td_api::inputPaidMedia>> get_input_paid_media(const Query *query, td::Slice field_name) const;
td::Result<td::vector<object_ptr<td_api::inputPaidMedia>>> get_paid_media(const Query *query,
td::Slice field_name) const;
td::Result<td::vector<object_ptr<td_api::inputPaidMedia>>> get_paid_media(const Query *query,
td::JsonValue &&value) const;
td::Result<object_ptr<td_api::inputMessageInvoice>> get_input_message_invoice(const Query *query) const;
static object_ptr<td_api::messageSendOptions> get_message_send_options(bool disable_notification,
bool protect_content, int64 effect_id,
object_ptr<td_api::MessageSchedulingState> &&scheduling_state);
static td::Result<td::vector<object_ptr<td_api::formattedText>>> get_poll_options(const Query *query);
static td::Result<object_ptr<td_api::ReactionType>> get_reaction_type(td::JsonValue &&value);
static td::Result<td::vector<object_ptr<td_api::ReactionType>>> get_reaction_types(const Query *query);
static int32 get_integer_arg(const Query *query, td::Slice field_name, int32 default_value,
int32 min_value = std::numeric_limits<int32>::min(),
int32 max_value = std::numeric_limits<int32>::max());
static td::Result<td::MutableSlice> get_required_string_arg(const Query *query, td::Slice field_name);
static int64 get_message_id(const Query *query, td::Slice field_name = td::Slice("message_id"));
static td::Result<td::vector<int64>> get_message_ids(const Query *query, size_t max_count,
td::Slice field_name = td::Slice("message_ids"));
static td::Result<td::Slice> get_inline_message_id(const Query *query,
td::Slice field_name = td::Slice("inline_message_id"));
static td::Result<int64> get_user_id(const Query *query, td::Slice field_name = td::Slice("user_id"));
void decrease_yet_unsent_message_count(int64 chat_id, int32 count);
int64 extract_yet_unsent_message_query_id(int64 chat_id, int64 message_id);
// start custom helper methods
static td::Result<object_ptr<td_api::MessageSchedulingState>> get_message_scheduling_state(const Query *query);
template <class T>
static td::Result<td::vector<T>> get_int_array_arg(const Query *query, td::Slice field_name, bool optional = false);
static int64 get_int64_arg(const Query *query, td::Slice field_name, int64 default_value,
int64 min_value = std::numeric_limits<int64>::min(),
int64 max_value = std::numeric_limits<int64>::max());
static td::Result<td_api::object_ptr<td_api::ReportReason>> get_report_reason(const Query *query,
td::Slice field_name = td::Slice("reason"));
static td::Result<td_api::object_ptr<td_api::SearchMessagesFilter>> get_search_messages_filter(
const Query *query, td::Slice field_name = td::Slice("filter"));
// end custom helper methods
void on_message_send_succeeded(object_ptr<td_api::message> &&message, int64 old_message_id);
void on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id,
object_ptr<td_api::error> &&error);
static bool init_methods();
static bool is_local_method(td::Slice method);
void on_cmd(PromisedQueryPtr query, bool force = false);
td::Status process_get_me_query(PromisedQueryPtr &query);
td::Status process_get_my_commands_query(PromisedQueryPtr &query);
td::Status process_set_my_commands_query(PromisedQueryPtr &query);
td::Status process_delete_my_commands_query(PromisedQueryPtr &query);
td::Status process_get_my_default_administrator_rights_query(PromisedQueryPtr &query);
td::Status process_set_my_default_administrator_rights_query(PromisedQueryPtr &query);
td::Status process_get_my_name_query(PromisedQueryPtr &query);
td::Status process_set_my_name_query(PromisedQueryPtr &query);
td::Status process_get_my_description_query(PromisedQueryPtr &query);
td::Status process_set_my_description_query(PromisedQueryPtr &query);
td::Status process_get_my_short_description_query(PromisedQueryPtr &query);
td::Status process_set_my_short_description_query(PromisedQueryPtr &query);
td::Status process_get_chat_menu_button_query(PromisedQueryPtr &query);
td::Status process_set_chat_menu_button_query(PromisedQueryPtr &query);
td::Status process_get_user_profile_photos_query(PromisedQueryPtr &query);
td::Status process_send_message_query(PromisedQueryPtr &query);
td::Status process_send_animation_query(PromisedQueryPtr &query);
td::Status process_send_audio_query(PromisedQueryPtr &query);
td::Status process_send_dice_query(PromisedQueryPtr &query);
td::Status process_send_document_query(PromisedQueryPtr &query);
td::Status process_send_photo_query(PromisedQueryPtr &query);
td::Status process_send_sticker_query(PromisedQueryPtr &query);
td::Status process_send_video_query(PromisedQueryPtr &query);
td::Status process_send_video_note_query(PromisedQueryPtr &query);
td::Status process_send_voice_query(PromisedQueryPtr &query);
td::Status process_send_paid_media_query(PromisedQueryPtr &query);
td::Status process_send_game_query(PromisedQueryPtr &query);
td::Status process_send_invoice_query(PromisedQueryPtr &query);
td::Status process_send_location_query(PromisedQueryPtr &query);
td::Status process_send_venue_query(PromisedQueryPtr &query);
td::Status process_send_contact_query(PromisedQueryPtr &query);
td::Status process_send_poll_query(PromisedQueryPtr &query);
td::Status process_stop_poll_query(PromisedQueryPtr &query);
td::Status process_copy_message_query(PromisedQueryPtr &query);
td::Status process_copy_messages_query(PromisedQueryPtr &query);
td::Status process_forward_message_query(PromisedQueryPtr &query);
td::Status process_forward_messages_query(PromisedQueryPtr &query);
td::Status process_send_media_group_query(PromisedQueryPtr &query);
td::Status process_send_chat_action_query(PromisedQueryPtr &query);
td::Status process_set_message_reaction_query(PromisedQueryPtr &query);
td::Status process_edit_message_text_query(PromisedQueryPtr &query);
td::Status process_edit_message_live_location_query(PromisedQueryPtr &query);
td::Status process_edit_message_media_query(PromisedQueryPtr &query);
td::Status process_edit_message_caption_query(PromisedQueryPtr &query);
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_create_invoice_link_query(PromisedQueryPtr &query);
td::Status process_get_star_transactions_query(PromisedQueryPtr &query);
td::Status process_refund_star_payment_query(PromisedQueryPtr &query);
td::Status process_set_game_score_query(PromisedQueryPtr &query);
td::Status process_get_game_high_scores_query(PromisedQueryPtr &query);
td::Status process_answer_web_app_query_query(PromisedQueryPtr &query);
td::Status process_answer_inline_query_query(PromisedQueryPtr &query);
td::Status process_answer_callback_query_query(PromisedQueryPtr &query);
td::Status process_answer_shipping_query_query(PromisedQueryPtr &query);
td::Status process_answer_pre_checkout_query_query(PromisedQueryPtr &query);
td::Status process_export_chat_invite_link_query(PromisedQueryPtr &query);
td::Status process_create_chat_invite_link_query(PromisedQueryPtr &query);
td::Status process_create_chat_subscription_invite_link_query(PromisedQueryPtr &query);
td::Status process_edit_chat_invite_link_query(PromisedQueryPtr &query);
td::Status process_edit_chat_subscription_invite_link_query(PromisedQueryPtr &query);
td::Status process_revoke_chat_invite_link_query(PromisedQueryPtr &query);
td::Status process_get_business_connection_query(PromisedQueryPtr &query);
td::Status process_get_chat_query(PromisedQueryPtr &query);
td::Status process_set_chat_photo_query(PromisedQueryPtr &query);
td::Status process_delete_chat_photo_query(PromisedQueryPtr &query);
td::Status process_set_chat_title_query(PromisedQueryPtr &query);
td::Status process_set_chat_permissions_query(PromisedQueryPtr &query);
td::Status process_set_chat_description_query(PromisedQueryPtr &query);
td::Status process_pin_chat_message_query(PromisedQueryPtr &query);
td::Status process_unpin_chat_message_query(PromisedQueryPtr &query);
td::Status process_unpin_all_chat_messages_query(PromisedQueryPtr &query);
td::Status process_set_chat_sticker_set_query(PromisedQueryPtr &query);
td::Status process_delete_chat_sticker_set_query(PromisedQueryPtr &query);
td::Status process_get_forum_topic_icon_stickers_query(PromisedQueryPtr &query);
td::Status process_create_forum_topic_query(PromisedQueryPtr &query);
td::Status process_edit_forum_topic_query(PromisedQueryPtr &query);
td::Status process_close_forum_topic_query(PromisedQueryPtr &query);
td::Status process_reopen_forum_topic_query(PromisedQueryPtr &query);
td::Status process_delete_forum_topic_query(PromisedQueryPtr &query);
td::Status process_unpin_all_forum_topic_messages_query(PromisedQueryPtr &query);
td::Status process_edit_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_close_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_reopen_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_hide_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_unhide_general_forum_topic_query(PromisedQueryPtr &query);
td::Status process_unpin_all_general_forum_topic_messages_query(PromisedQueryPtr &query);
td::Status process_get_chat_member_query(PromisedQueryPtr &query);
td::Status process_get_chat_administrators_query(PromisedQueryPtr &query);
td::Status process_get_chat_member_count_query(PromisedQueryPtr &query);
td::Status process_leave_chat_query(PromisedQueryPtr &query);
td::Status process_promote_chat_member_query(PromisedQueryPtr &query);
td::Status process_set_chat_administrator_custom_title_query(PromisedQueryPtr &query);
td::Status process_ban_chat_member_query(PromisedQueryPtr &query);
td::Status process_restrict_chat_member_query(PromisedQueryPtr &query);
td::Status process_unban_chat_member_query(PromisedQueryPtr &query);
td::Status process_ban_chat_sender_chat_query(PromisedQueryPtr &query);
td::Status process_unban_chat_sender_chat_query(PromisedQueryPtr &query);
td::Status process_approve_chat_join_request_query(PromisedQueryPtr &query);
td::Status process_decline_chat_join_request_query(PromisedQueryPtr &query);
td::Status process_get_user_chat_boosts_query(PromisedQueryPtr &query);
td::Status process_get_sticker_set_query(PromisedQueryPtr &query);
td::Status process_get_custom_emoji_stickers_query(PromisedQueryPtr &query);
td::Status process_upload_sticker_file_query(PromisedQueryPtr &query);
td::Status process_create_new_sticker_set_query(PromisedQueryPtr &query);
td::Status process_add_sticker_to_set_query(PromisedQueryPtr &query);
td::Status process_replace_sticker_in_set_query(PromisedQueryPtr &query);
td::Status process_set_sticker_set_title_query(PromisedQueryPtr &query);
td::Status process_set_sticker_set_thumbnail_query(PromisedQueryPtr &query);
td::Status process_set_custom_emoji_sticker_set_thumbnail_query(PromisedQueryPtr &query);
td::Status process_delete_sticker_set_query(PromisedQueryPtr &query);
td::Status process_set_sticker_position_in_set_query(PromisedQueryPtr &query);
td::Status process_delete_sticker_from_set_query(PromisedQueryPtr &query);
td::Status process_set_sticker_emoji_list_query(PromisedQueryPtr &query);
td::Status process_set_sticker_keywords_query(PromisedQueryPtr &query);
td::Status process_set_sticker_mask_position_query(PromisedQueryPtr &query);
td::Status process_set_passport_data_errors_query(PromisedQueryPtr &query);
td::Status process_send_custom_request_query(PromisedQueryPtr &query);
td::Status process_answer_custom_query_query(PromisedQueryPtr &query);
td::Status process_get_updates_query(PromisedQueryPtr &query);
td::Status process_set_webhook_query(PromisedQueryPtr &query);
td::Status process_get_webhook_info_query(PromisedQueryPtr &query);
td::Status process_get_file_query(PromisedQueryPtr &query);
//custom methods
td::Status process_get_message_info_query(PromisedQueryPtr &query);
td::Status process_get_chat_members_query(PromisedQueryPtr &query);
td::Status process_toggle_group_invites_query(PromisedQueryPtr &query);
td::Status process_ping_query(PromisedQueryPtr &query);
td::Status process_get_memory_stats_query(PromisedQueryPtr &query);
td::Status process_get_proxies_query(PromisedQueryPtr &query);
td::Status process_add_proxy_query(PromisedQueryPtr &query);
td::Status process_delete_proxy_query(PromisedQueryPtr &query);
td::Status process_enable_proxy_query(PromisedQueryPtr &query);
td::Status process_disable_proxy_query(PromisedQueryPtr &query);
td::Status process_delete_messages_range_query(PromisedQueryPtr &query);
//custom user methods
td::Status process_get_chats_query(PromisedQueryPtr &query);
td::Status process_get_common_chats_query(PromisedQueryPtr &query);
td::Status process_get_inactive_chats_query(PromisedQueryPtr &query);
td::Status process_get_nearby_chats_query(PromisedQueryPtr &query);
td::Status process_search_public_chats_query(PromisedQueryPtr &query);
td::Status process_set_poll_answer_query(PromisedQueryPtr &query);
td::Status process_join_chat_query(PromisedQueryPtr &query);
td::Status process_add_chat_member_query(PromisedQueryPtr &query);
td::Status process_report_chat_query(PromisedQueryPtr &query);
td::Status process_create_chat_query(PromisedQueryPtr &query);
td::Status process_search_messages_query(PromisedQueryPtr &query);
td::Status process_search_chat_messages_query(PromisedQueryPtr &query);
td::Status process_get_callback_query_answer_query(PromisedQueryPtr &query);
td::Status process_delete_chat_history_query(PromisedQueryPtr &query);
td::Status process_get_scheduled_messages_query(PromisedQueryPtr &query);
td::Status process_edit_message_scheduling_query(PromisedQueryPtr &query);
//custom auth methods
void process_auth_phone_number_query(PromisedQueryPtr &query);
void process_authcode_query(PromisedQueryPtr &query);
void process_2fapassword_query(PromisedQueryPtr &query);
void process_register_user_query(PromisedQueryPtr &query);
void webhook_verified(td::string cached_ip_address) final;
void webhook_success() final;
void webhook_error(td::Status status) final;
void webhook_closed(td::Status status) final;
void hangup_shared() final;
const td::HttpFile *get_webhook_certificate(const Query *query) const;
int32 get_webhook_max_connections(const Query *query) const;
static bool get_webhook_fix_ip_address(const Query *query);
void do_set_webhook(PromisedQueryPtr query, bool was_deleted);
void on_webhook_certificate_copied(td::Status status);
void finish_set_webhook(PromisedQueryPtr query);
void save_webhook() const;
td::string get_webhook_certificate_path() const;
void on_webhook_closed(td::Status status);
void delete_last_send_message_time(td::int64 file_size, double max_delay);
void do_send_message(object_ptr<td_api::InputMessageContent> input_message_content, PromisedQueryPtr query,
bool force = false);
int64 get_send_message_query_id(PromisedQueryPtr query, bool is_multisend);
void on_sent_message(object_ptr<td_api::message> &&message, int64 query_id);
void do_get_file(object_ptr<td_api::file> file, PromisedQueryPtr query);
bool is_file_being_downloaded(int32 file_id) const;
void on_file_download(int32 file_id, td::Result<object_ptr<td_api::file>> r_file);
void return_stickers(object_ptr<td_api::stickers> stickers, PromisedQueryPtr query);
void fix_reply_markup_bot_user_ids(object_ptr<td_api::ReplyMarkup> &reply_markup) const;
void fix_inline_query_results_bot_user_ids(td::vector<object_ptr<td_api::InputInlineQueryResult>> &results) const;
void resolve_bot_usernames(PromisedQueryPtr query, td::Promise<PromisedQueryPtr> on_success);
void on_resolve_bot_username(const td::string &username, int64 user_id);
void abort_long_poll(bool from_set_webhook);
void fail_query_closing(PromisedQueryPtr &&query);
void fail_query_flood_limit_exceeded(PromisedQueryPtr &&query);
void fail_query_conflict(td::Slice message, PromisedQueryPtr &&query);
struct ClosingError {
int code;
int retry_after;
td::Slice message;
};
ClosingError get_closing_error();
static int get_retry_after_time(td::Slice error_message);
static void fail_query_with_error(PromisedQueryPtr query, int32 error_code, td::Slice error_message,
td::Slice default_message = td::Slice());
static void fail_query_with_error(PromisedQueryPtr &&query, object_ptr<td_api::error> error,
td::Slice default_message = td::Slice());
static bool is_special_error_code(int32 error_code);
class JsonUpdates;
void do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQueryPtr query);
void long_poll_wakeup(bool force_flag);
void start_up() final;
void raw_event(const td::Event::Raw &event) final;
void loop() final;
void timeout_expired() final;
struct UserInfo {
enum class Type { Regular, Deleted, Bot, Unknown };
Type type = Type::Unknown;
td::string first_name;
td::string last_name;
td::vector<td::string> active_usernames;
td::string editable_username;
td::string language_code;
object_ptr<td_api::chatPhoto> photo;
td::string bio;
object_ptr<td_api::birthdate> birthdate;
object_ptr<td_api::businessInfo> business_info;
int64 personal_chat_id = 0;
// start custom properties
bool is_verified = false;
bool is_scam = false;
object_ptr<td_api::UserStatus> status;
// end custom properties
bool have_access = false;
bool can_join_groups = false;
bool can_read_all_group_messages = false;
bool can_connect_to_business = false;
bool has_main_web_app = false;
bool has_private_forwards = false;
bool has_restricted_voice_and_video_messages = false;
bool is_inline_bot = false;
bool is_premium = false;
bool added_to_attachment_menu = false;
};
static void add_user(UserInfo *user_info, object_ptr<td_api::user> &&user);
UserInfo *add_user_info(int64 user_id);
const UserInfo *get_user_info(int64 user_id) const;
void set_user_status(int64 user_id, object_ptr<td_api::UserStatus> &&status);
struct GroupInfo {
object_ptr<td_api::chatPhoto> photo;
td::string description;
td::string invite_link;
int32 member_count = 0;
bool left = false;
bool kicked = false;
bool is_active = false;
int64 upgraded_to_supergroup_id = 0;
};
static void add_group(GroupInfo *group_info, object_ptr<td_api::basicGroup> &&group);
GroupInfo *add_group_info(int64 group_id);
const GroupInfo *get_group_info(int64 group_id) const;
struct SupergroupInfo {
td::vector<td::string> active_usernames;
td::string editable_username;
object_ptr<td_api::chatPhoto> photo;
td::string description;
td::string invite_link;
int64 sticker_set_id = 0;
int64 custom_emoji_sticker_set_id = 0;
int32 date = 0;
int32 slow_mode_delay = 0;
int32 unrestrict_boost_count = 0;
int64 linked_chat_id = 0;
object_ptr<td_api::chatLocation> location;
object_ptr<td_api::ChatMemberStatus> status;
bool is_supergroup = false;
bool is_forum = false;
bool can_set_sticker_set = false;
bool is_all_history_available = false;
bool has_location = false;
bool join_to_send_messages = false;
bool join_by_request = false;
bool has_hidden_members = false;
bool has_aggressive_anti_spam_enabled = false;
bool has_paid_media_allowed = false;
// start custom properties
bool is_verified = false;
bool is_scam = false;
// end custom properties
};
static void add_supergroup(SupergroupInfo *supergroup_info, object_ptr<td_api::supergroup> &&supergroup);
SupergroupInfo *add_supergroup_info(int64 supergroup_id);
const SupergroupInfo *get_supergroup_info(int64 supergroup_id) const;
struct ChatInfo {
enum class Type { Private, Group, Supergroup, Unknown };
Type type = Type::Unknown;
td::string title;
int32 message_auto_delete_time = 0;
int64 emoji_status_custom_emoji_id = 0;
int32 emoji_status_expiration_date = 0;
int32 accent_color_id = -1;
int32 profile_accent_color_id = -1;
int64 background_custom_emoji_id = 0;
int64 profile_background_custom_emoji_id = 0;
bool has_protected_content = false;
int32 max_reaction_count = 0;
object_ptr<td_api::chatAvailableReactionsSome> available_reactions;
object_ptr<td_api::chatPhotoInfo> photo_info;
object_ptr<td_api::chatPermissions> permissions;
union {
int64 user_id;
int64 group_id;
int64 supergroup_id;
};
};
ChatInfo *add_chat(int64 chat_id);
const ChatInfo *get_chat(int64 chat_id) const;
void set_chat_available_reactions(ChatInfo *chat_info,
object_ptr<td_api::ChatAvailableReactions> &&available_reactions);
enum class ChatType { Private, Group, Supergroup, Channel, Unknown };
ChatType get_chat_type(int64 chat_id) const;
td::string get_chat_description(int64 chat_id) const;
struct MessageInfo {
int64 id = 0;
int64 sender_user_id = 0;
int64 sender_chat_id = 0;
int64 chat_id = 0;
int64 message_thread_id = 0;
int32 date = 0;
int32 edit_date = 0;
int32 initial_send_date = 0;
int32 sender_boost_count = 0;
object_ptr<td_api::MessageOrigin> forward_origin;
td::string author_signature;
td::unique_ptr<MessageInfo> business_reply_to_message;
object_ptr<td_api::messageReplyToMessage> reply_to_message;
object_ptr<td_api::messageReplyToStory> reply_to_story;
int64 media_album_id = 0;
int64 via_bot_user_id = 0;
object_ptr<td_api::MessageContent> content;
object_ptr<td_api::ReplyMarkup> reply_markup;
td::string business_connection_id;
int64 sender_business_bot_user_id = 0;
int64 effect_id = 0;
// start custom properties
int32 views = 0;
int32 forwards = 0;
bool is_scheduled = false;
int32 scheduled_at = 0;
// end custom properties
bool can_be_saved = false;
bool is_automatic_forward = false;
bool is_topic_message = false;
bool is_from_offline = false;
mutable bool is_content_changed = false;
};
struct BusinessConnection {
td::string id_;
int64 user_id_ = 0;
int64 user_chat_id_ = 0;
int32 date_ = 0;
bool can_reply_ = false;
bool is_enabled_ = false;
};
const BusinessConnection *add_business_connection(object_ptr<td_api::businessConnection> &&business_connection,
bool from_update);
const BusinessConnection *get_business_connection(const td::string &connection_id) const;
static int64 get_same_chat_reply_to_message_id(const td_api::messageReplyToMessage *reply_to,
int64 message_thread_id);
static int64 get_same_chat_reply_to_message_id(const object_ptr<td_api::MessageReplyTo> &reply_to,
int64 message_thread_id);
static int64 get_same_chat_reply_to_message_id(const object_ptr<td_api::message> &message);
static int64 get_same_chat_reply_to_message_id(const MessageInfo *message_info);
static void drop_internal_reply_to_message_in_another_chat(object_ptr<td_api::message> &message);
static td::Slice get_sticker_type(const object_ptr<td_api::StickerType> &type);
static td::Result<object_ptr<td_api::StickerType>> get_sticker_type(td::Slice type);
static td::CSlice get_callback_data(const object_ptr<td_api::InlineKeyboardButtonType> &type);
static bool are_equal_inline_keyboard_buttons(const td_api::inlineKeyboardButton *lhs,
const td_api::inlineKeyboardButton *rhs);
static bool are_equal_inline_keyboards(const td_api::replyMarkupInlineKeyboard *lhs,
const td_api::replyMarkupInlineKeyboard *rhs);
static void set_message_reply_markup(MessageInfo *message_info, object_ptr<td_api::ReplyMarkup> &&reply_markup);
static int64 get_sticker_set_id(const object_ptr<td_api::MessageContent> &content);
bool have_sticker_set_name(int64 sticker_set_id) const;
td::string get_sticker_set_name(int64 sticker_set_id) const;
int64 choose_added_member_id(const td_api::messageChatAddMembers *message_add_members) const;
bool need_skip_update_message(int64 chat_id, const object_ptr<td_api::message> &message, bool is_edited) const;
void json_store_file(td::JsonObjectScope &object, const td_api::file *file, bool with_path = false) const;
void json_store_thumbnail(td::JsonObjectScope &object, const td_api::thumbnail *thumbnail) const;
static void json_store_callback_query_payload(td::JsonObjectScope &object,
const td_api::CallbackQueryPayload *payload);
static void json_store_administrator_rights(td::JsonObjectScope &object,
const td_api::chatAdministratorRights *rights, ChatType chat_type);
static void json_store_permissions(td::JsonObjectScope &object, const td_api::chatPermissions *permissions);
static void json_store_user_status(td::JsonObjectScope &object, const td_api::UserStatus *userStatus);
void remove_replies_to_message(int64 chat_id, int64 reply_to_message_id, bool only_from_cache);
td::unique_ptr<MessageInfo> delete_message(int64 chat_id, int64 message_id, bool only_from_cache);
void add_new_message(object_ptr<td_api::message> &&message, bool is_edited);
void process_new_message_queue(int64 chat_id, int state);
void add_new_business_message(object_ptr<td_api::updateNewBusinessMessage> &&update);
void add_business_message_edited(object_ptr<td_api::updateBusinessMessageEdited> &&update);
void process_new_business_message_queue(const td::string &connection_id);
struct FullMessageId {
int64 chat_id;
int64 message_id;
FullMessageId() : chat_id(0), message_id(0) {
}
FullMessageId(int64 chat_id, int64 message_id) : chat_id(chat_id), message_id(message_id) {
}
bool operator==(const FullMessageId &other) const {
return chat_id == other.chat_id && message_id == other.message_id;
}
};
struct FullMessageIdHash {
td::uint32 operator()(FullMessageId full_message_id) const {
return td::Hash<int64>()(full_message_id.chat_id) * 2023654985u + td::Hash<int64>()(full_message_id.message_id);
}
};
FullMessageId add_message(object_ptr<td_api::message> &&message, bool force_update_content = false);
void init_message(MessageInfo *message_info, object_ptr<td_api::message> &&message, bool force_update_content);
const MessageInfo *get_message(int64 chat_id, int64 message_id, bool force_cache) const;
MessageInfo *get_message_editable(int64 chat_id, int64 message_id);
td::unique_ptr<MessageInfo> create_business_message(td::string business_connection_id,
object_ptr<td_api::businessMessage> &&message);
void update_message_content(int64 chat_id, int64 message_id, object_ptr<td_api::MessageContent> &&content);
void on_update_message_edited(int64 chat_id, int64 message_id, int32 edit_date,
object_ptr<td_api::ReplyMarkup> &&reply_markup);
int32 get_unix_time() const;
static int64 as_tdlib_message_id(int32 message_id);
static int32 as_client_message_id(int64 message_id);
static int32 as_scheduled_message_id(int64 message_id);
static int32 as_client_message_id_unchecked(int64 message_id);
static int64 get_supergroup_chat_id(int64 supergroup_id);
static int64 get_basic_group_chat_id(int64 basic_group_id);
void add_update_poll(object_ptr<td_api::updatePoll> &&update);
void add_update_poll_answer(object_ptr<td_api::updatePollAnswer> &&update);
void add_new_inline_query(int64 inline_query_id, int64 sender_user_id, object_ptr<td_api::location> location,
object_ptr<td_api::ChatType> chat_type, const td::string &query, const td::string &offset);
void add_new_chosen_inline_result(int64 sender_user_id, object_ptr<td_api::location> location,
const td::string &query, const td::string &result_id,
const td::string &inline_message_id);
void add_new_callback_query(object_ptr<td_api::updateNewCallbackQuery> &&query);
void process_new_callback_query_queue(int64 user_id, int state);
void add_new_business_callback_query(object_ptr<td_api::updateNewBusinessCallbackQuery> &&query);
void process_new_business_callback_query_queue(int64 user_id);
void add_new_inline_callback_query(object_ptr<td_api::updateNewInlineCallbackQuery> &&query);
void add_new_shipping_query(object_ptr<td_api::updateNewShippingQuery> &&query);
void add_new_pre_checkout_query(object_ptr<td_api::updateNewPreCheckoutQuery> &&query);
void add_update_purchased_paid_media(object_ptr<td_api::updatePaidMediaPurchased> &&query);
void add_new_custom_event(object_ptr<td_api::updateNewCustomEvent> &&event);
void add_new_custom_query(object_ptr<td_api::updateNewCustomQuery> &&query);
void add_update_chat_member(object_ptr<td_api::updateChatMember> &&update);
void add_update_chat_join_request(object_ptr<td_api::updateNewChatJoinRequest> &&update);
void add_update_chat_boost(object_ptr<td_api::updateChatBoost> &&update);
void add_update_message_reaction(object_ptr<td_api::updateMessageReaction> &&update);
void add_update_message_reaction_count(object_ptr<td_api::updateMessageReactions> &&update);
void add_update_business_connection(object_ptr<td_api::updateBusinessConnection> &&update);
void add_update_business_messages_deleted(object_ptr<td_api::updateBusinessMessagesDeleted> &&update);
// append only before Size
enum class UpdateType : int32 {
Message,
EditedMessage,
ChannelPost,
EditedChannelPost,
InlineQuery,
ChosenInlineResult,
CallbackQuery,
CustomEvent,
CustomQuery,
ShippingQuery,
PreCheckoutQuery,
Poll,
PollAnswer,
MyChatMember,
ChatMember,
ChatJoinRequest,
ChatBoostUpdated,
ChatBoostRemoved,
MessageReaction,
MessageReactionCount,
BusinessConnection,
BusinessMessage,
EditedBusinessMessage,
BusinessMessagesDeleted,
PurchasedPaidMedia,
Size
};
static td::Slice get_update_type_name(UpdateType update_type);
static td::uint32 get_allowed_update_types(td::MutableSlice allowed_updates, bool is_internal);
bool update_allowed_update_types(const Query *query);
template <class T>
void add_update(UpdateType update_type, const T &update, int32 timeout, int64 webhook_queue_id);
void add_update_impl(UpdateType update_type, const td::VirtuallyJsonable &update, int32 timeout,
int64 webhook_queue_id);
std::size_t get_pending_update_count() const;
void update_last_synchronization_error_date();
static bool is_chat_member(const object_ptr<td_api::ChatMemberStatus> &status);
static td::string get_chat_member_status(const object_ptr<td_api::ChatMemberStatus> &status);
static td::string get_passport_element_type(int32 id);
static object_ptr<td_api::PassportElementType> get_passport_element_type(td::Slice type);
bool have_message_access(int64 chat_id) const;
// by default ChatMember, MessageReaction, and MessageReactionCount updates are disabled
static constexpr td::uint32 DEFAULT_ALLOWED_UPDATE_TYPES =
(1 << static_cast<int32>(UpdateType::Size)) - 1 - (1 << static_cast<int32>(UpdateType::ChatMember)) -
(1 << static_cast<int32>(UpdateType::MessageReaction)) -
(1 << static_cast<int32>(UpdateType::MessageReactionCount));
object_ptr<td_api::AuthorizationState> authorization_state_;
bool was_authorized_ = false;
bool closing_ = false;
bool logging_out_ = false;
bool is_api_id_invalid_ = false;
bool need_close_ = false;
bool clear_tqueue_ = false;
bool waiting_for_auth_input_ = false;
td::ActorShared<> parent_;
td::string bot_token_;
td::string bot_token_with_dc_;
td::string bot_token_id_;
bool is_user_;
bool is_test_dc_;
int64 tqueue_id_;
double start_time_ = 0;
int64 my_id_ = -1;
int32 authorization_date_ = -1;
double next_authorization_time_ = 0;
int32 prev_retry_after = 0;
td::string retry_after_error_message;
int64 group_anonymous_bot_user_id_ = 0;
int64 channel_bot_user_id_ = 0;
int64 service_notifications_user_id_ = 0;
static td::FlatHashMap<td::string, td::Status (Client::*)(PromisedQueryPtr &query)> methods_;
td::WaitFreeHashMap<FullMessageId, td::unique_ptr<MessageInfo>, FullMessageIdHash> messages_;
td::WaitFreeHashMap<int64, td::unique_ptr<UserInfo>> users_;
td::WaitFreeHashMap<int64, td::unique_ptr<GroupInfo>> groups_;
td::WaitFreeHashMap<int64, td::unique_ptr<SupergroupInfo>> supergroups_;
td::WaitFreeHashMap<int64, td::unique_ptr<ChatInfo>> chats_;
td::WaitFreeHashMap<td::string, td::unique_ptr<BusinessConnection>> business_connections_;
td::FlatHashMap<int32, td::vector<PromisedQueryPtr>> file_download_listeners_;
td::FlatHashSet<int32> download_started_file_ids_;
struct YetUnsentMessage {
int64 send_message_query_id = 0;
};
td::FlatHashMap<FullMessageId, YetUnsentMessage, FullMessageIdHash> yet_unsent_messages_;
td::FlatHashMap<int64, int32> yet_unsent_message_count_; // chat_id -> count
struct PendingSendMessageQuery {
PromisedQueryPtr query;
bool is_multisend = false;
int32 total_message_count = 0;
int32 awaited_message_count = 0;
td::vector<td::string> messages;
object_ptr<td_api::error> error;
};
td::FlatHashMap<int64, td::unique_ptr<PendingSendMessageQuery>>
pending_send_message_queries_; // query_id -> PendingSendMessageQuery
int64 current_send_message_query_id_ = 1;
struct NewMessage {
object_ptr<td_api::message> message;
bool is_edited = false;
NewMessage(object_ptr<td_api::message> &&message, bool is_edited)
: message(std::move(message)), is_edited(is_edited) {
}
};
struct NewMessageQueue {
std::queue<NewMessage> queue_;
bool has_active_request_ = false;
};
td::FlatHashMap<int64, NewMessageQueue> new_message_queues_; // chat_id -> queue
struct NewBusinessMessage {
object_ptr<td_api::businessMessage> message_;
bool is_edited_ = false;
NewBusinessMessage(object_ptr<td_api::businessMessage> &&message, bool is_edited)
: message_(std::move(message)), is_edited_(is_edited) {
}
};
struct NewBusinessMessageQueue {
std::queue<NewBusinessMessage> queue_;
bool has_active_request_ = false;
};
td::FlatHashMap<td::string, NewBusinessMessageQueue> new_business_message_queues_; // connection_id -> queue
struct NewCallbackQueryQueue {
std::queue<object_ptr<td_api::updateNewCallbackQuery>> queue_;
bool has_active_request_ = false;
};
td::FlatHashMap<int64, NewCallbackQueryQueue> new_callback_query_queues_; // sender_user_id -> queue
struct NewBusinessCallbackQueryQueue {
std::queue<object_ptr<td_api::updateNewBusinessCallbackQuery>> queue_;
bool has_active_request_ = false;
};
td::FlatHashMap<int64, NewBusinessCallbackQueryQueue> new_business_callback_query_queues_; // sender_user_id -> queue
td::WaitFreeHashMap<int64, td::string> sticker_set_names_;
td::WaitFreeHashMap<int64, double> last_send_message_time_;
struct BotUserIds {
int64 default_bot_user_id_ = 0;
int64 cur_temp_bot_user_id_ = 1;
td::FlatHashMap<td::string, int64> bot_user_ids_;
td::FlatHashSet<td::string> unresolved_bot_usernames_;
};
BotUserIds bot_user_ids_;
struct PendingBotResolveQuery {
std::size_t pending_resolve_count = 0;
PromisedQueryPtr query;
td::Promise<PromisedQueryPtr> on_success;
};
td::FlatHashMap<int64, PendingBotResolveQuery> pending_bot_resolve_queries_;
int64 current_bot_resolve_query_id_ = 1;
td::FlatHashMap<td::string, td::vector<int64>> awaiting_bot_resolve_queries_;
td::FlatHashMap<int64, int64> temp_to_real_bot_user_id_;
td::string dir_;
td::ActorOwn<td::ClientActor> td_client_;
td::ActorContext context_;
std::queue<PromisedQueryPtr> cmd_queue_;
td::vector<object_ptr<td_api::Object>> pending_updates_;
td::Container<td::unique_ptr<TdQueryCallback>> handlers_;
static constexpr int32 LONG_POLL_MAX_TIMEOUT = 50;
static constexpr double LONG_POLL_MAX_DELAY = 0.002;
static constexpr double LONG_POLL_WAIT_AFTER = 0.001;
int32 long_poll_limit_ = 0;
int32 long_poll_offset_ = 0;
bool long_poll_was_wakeup_ = false;
double long_poll_hard_timeout_ = 0;
td::Slot long_poll_slot_;
PromisedQueryPtr long_poll_query_;
static constexpr int32 BOT_UPDATES_WARNING_DELAY = 30;
double next_bot_updates_warning_time_ = 0;
bool was_bot_updates_warning_ = false;
td::uint32 allowed_update_types_ = DEFAULT_ALLOWED_UPDATE_TYPES;
bool has_webhook_certificate_ = false;
enum class WebhookQueryType { Cancel, Verify };
WebhookQueryType webhook_query_type_ = WebhookQueryType::Cancel;
td::ActorOwn<WebhookActor> webhook_id_;
PromisedQueryPtr webhook_set_query_;
PromisedQueryPtr active_webhook_set_query_;
td::string webhook_url_;
double webhook_set_time_ = 0;
int32 webhook_max_connections_ = 0;
td::string webhook_ip_address_;
bool webhook_fix_ip_address_ = false;
td::string webhook_secret_token_;
int32 last_webhook_error_date_ = 0;
td::Status last_webhook_error_;
double next_allowed_set_webhook_time_ = 0;
double next_set_webhook_logging_time_ = 0;
double next_webhook_is_not_modified_warning_time_ = 0;
std::size_t last_pending_update_count_ = MIN_PENDING_UPDATES_WARNING;
double local_unix_time_difference_ = 0; // Unix time - now()
double disconnection_time_ = 0; // the time when Connection state changed from "Ready", or 0 if it is "Ready"
double last_update_creation_time_ = 0; // the time when the last update was added
int32 last_synchronization_error_date_ = 0; // the date of the last connection error
int32 previous_get_updates_offset_ = -1;
double previous_get_updates_start_time_ = 0;
double previous_get_updates_finish_time_ = 0;
double next_get_updates_conflict_time_ = 0;
int32 log_in_date_ = 0;
int32 flood_limited_query_count_ = 0;
double next_flood_limit_warning_time_ = 0;
td::uint64 webhook_generation_ = 1;
UpdateType delayed_update_type_ = UpdateType::Size;
int64 delayed_chat_id_ = 0;
int32 delayed_min_date_ = 0;
int32 delayed_max_date_ = 0;
int32 delayed_max_time_ = 0;
size_t delayed_update_count_ = 0;
std::shared_ptr<const ClientParameters> parameters_;
td::ActorId<BotStatActor> stat_actor_;
};
} // namespace telegram_bot_api