diff --git a/.clang-format b/.clang-format index 4e23f1d..8f0a588 100644 --- a/.clang-format +++ b/.clang-format @@ -4,15 +4,36 @@ Language: Cpp AccessModifierOffset: -1 AlignAfterOpenBracket: Align AlignArrayOfStructures: None -AlignConsecutiveMacros: None -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: None -AlignConsecutiveDeclarations: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false AlignEscapedNewlines: Left AlignOperands: Align -AlignTrailingComments: true +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 AllowAllArgumentsOnNextLine: true -AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false @@ -25,6 +46,8 @@ AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: Yes +# AttributeMacros: +# - __capability BinPackArguments: true BinPackParameters: true BitFieldColonSpacing: Both @@ -33,12 +56,12 @@ BraceWrapping: AfterClass: false AfterControlStatement: Never AfterEnum: false + AfterExternBlock: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false - AfterExternBlock: false BeforeCatch: false BeforeElse: false BeforeLambdaBody: false @@ -47,24 +70,23 @@ BraceWrapping: SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true +BreakAfterAttributes: Never +# BreakAfterJavaFieldAnnotations: false +BreakArrays: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach -BreakBeforeConceptDeclarations: true -BreakBeforeInheritanceComma: true # false -BreakInheritanceList: BeforeComma # BeforeColon +BreakBeforeConceptDeclarations: Always +BreakBeforeInlineASMColon: OnlyMultiline BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: true # false BreakConstructorInitializers: BeforeComma # BeforeColon -# BreakAfterJavaFieldAnnotations: false +BreakInheritanceList: BeforeComma # BeforeColon BreakStringLiterals: true ColumnLimit: 120 # 80 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true -DeriveLineEnding: true DerivePointerAlignment: true DisableFormat: false EmptyLineAfterAccessModifier: Never @@ -83,14 +105,21 @@ IndentCaseLabels: true IndentExternBlock: AfterExternBlock IndentGotoLabels: true IndentPPDirectives: None -IndentRequires: false +IndentRequiresClause: true IndentWidth: 2 IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false # InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + Decimal: 0 + Hex: 0 # JavaScriptQuotes: Leave # JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false LambdaBodyIndentation: Signature +LineEnding: DeriveLF MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 @@ -100,23 +129,31 @@ NamespaceIndentation: None # ObjCBreakBeforeNestedBlockParam: true # ObjCSpaceAfterProperty: false # ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: NextLine PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyIndentedWhitespace: 0 PenaltyReturnTypeOnItsOwnLine: 200 -PointerAlignment: Right +PointerAlignment: Right # Left PPIndentWidth: -1 +QualifierAlignment: Leave ReferenceAlignment: Pointer ReflowComments: false # true +RemoveBracesLLVM: false +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave ShortNamespaceLines: 0 # 1 SortIncludes: CaseInsensitive # CaseSensitive # SortJavaStaticImport: Before -SortUsingDeclarations: false # true +SortUsingDeclarations: Lexicographic # LexicographicNumeric SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true @@ -127,6 +164,16 @@ SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false SpaceBeforeRangeBasedForLoopColon: true SpaceBeforeSquareBrackets: false SpaceInEmptyBlock: false @@ -143,6 +190,5 @@ SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Auto TabWidth: 100 # 8 -UseCRLF: false UseTab: Never ... diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ad72e5..2a1928a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if (POLICY CMP0065) cmake_policy(SET CMP0065 NEW) endif() -project(TelegramBotApi VERSION 6.5 LANGUAGES CXX) +project(TelegramBotApi VERSION 6.6 LANGUAGES CXX) if (POLICY CMP0069) option(TELEGRAM_BOT_API_ENABLE_LTO "Use \"ON\" to enable Link Time Optimization.") diff --git a/td b/td index 3179d35..70bee08 160000 --- a/td +++ b/td @@ -1 +1 @@ -Subproject commit 3179d35694a28267a0b6273fc9b5bdce3b6b1235 +Subproject commit 70bee089d492437ce931aa78446d89af3da182fc diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index 013f2af..ab657b8 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -15,6 +15,7 @@ #include "td/utils/algorithm.h" #include "td/utils/base64.h" +#include "td/utils/emoji.h" #include "td/utils/filesystem.h" #include "td/utils/HttpUrl.h" #include "td/utils/JsonBuilder.h" @@ -36,30 +37,26 @@ #define CHECK_IS_BOT() \ if (is_user_) { \ - return Status::Error(BOT_ONLY_ERROR_CODE, BOT_ONLY_ERROR_DESCRIPTION); \ + return td::Status::Error(BOT_ONLY_ERROR_CODE, BOT_ONLY_ERROR_DESCRIPTION); \ } #define CHECK_IS_USER() \ if (!is_user_) { \ - return Status::Error(USER_ONLY_ERROR_CODE, USER_ONLY_ERROR_DESCRIPTION); \ + return td::Status::Error(USER_ONLY_ERROR_CODE, USER_ONLY_ERROR_DESCRIPTION); \ } #define CHECK_USER_REPLY_MARKUP() \ if (reply_markup != nullptr && is_user_) { \ - return Status::Error(BOT_ONLY_ERROR_CODE, BOT_ONLY_ERROR_DESCRIPTION); \ + return td::Status::Error(BOT_ONLY_ERROR_CODE, BOT_ONLY_ERROR_DESCRIPTION); \ } namespace telegram_bot_api { -using td::Jsonable; -using td::JsonValueScope; -using td::JsonValue; - using td_api::make_object; using td_api::move_object_as; -int Client::get_retry_after_time(Slice error_message) { - Slice prefix = "Too Many Requests: retry after "; +int Client::get_retry_after_time(td::Slice error_message) { + td::Slice prefix = "Too Many Requests: retry after "; if (begins_with(error_message, prefix)) { auto r_retry_after = td::to_integer_safe(error_message.substr(prefix.size())); if (r_retry_after.is_ok() && r_retry_after.ok() > 0) { @@ -69,8 +66,8 @@ int Client::get_retry_after_time(Slice error_message) { return 0; } -void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Slice error_message, - Slice default_message) { +void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, td::Slice error_message, + td::Slice default_message) { if (error_code == 429) { auto retry_after_time = get_retry_after_time(error_message); if (retry_after_time > 0) { @@ -80,7 +77,7 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Sli return fail_query(500, error_message, std::move(query)); } int32 real_error_code = error_code; - Slice real_error_message = error_message; + td::Slice real_error_message = error_message; if (error_code < 400 || error_code == 404) { if (error_code < 200) { LOG(ERROR) << "Receive error \"" << real_error_message << "\" with code " << error_code << " from " << *query; @@ -106,7 +103,7 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Sli error_message = default_message; } if (error_message == "MESSAGE_NOT_MODIFIED") { - error_message = Slice( + error_message = td::Slice( "message is not modified: specified new message content and reply markup are exactly the same as a current " "content and reply markup of the message"); } else if (error_message == "WC_CONVERT_URL_INVALID" || error_message == "EXTERNAL_URL_INVALID") { @@ -118,56 +115,56 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Sli } else if (error_message == "MEDIA_GROUPED_INVALID") { error_message = "Can't use the media of the specified type in the album"; } else if (error_message == "REPLY_MARKUP_TOO_LONG") { - error_message = Slice("reply markup is too long"); + error_message = td::Slice("reply markup is too long"); } else if (error_message == "INPUT_USER_DEACTIVATED") { error_code = 403; - error_message = Slice("Forbidden: user is deactivated"); + error_message = td::Slice("Forbidden: user is deactivated"); } else if (error_message == "USER_IS_BLOCKED") { error_code = 403; - error_message = Slice("bot was blocked by the user"); + error_message = td::Slice("bot was blocked by the user"); } else if (error_message == "USER_ADMIN_INVALID") { error_code = 400; - error_message = Slice("user is an administrator of the chat"); + error_message = td::Slice("user is an administrator of the chat"); } else if (error_message == "File generation failed") { error_code = 400; - error_message = Slice("can't upload file by URL"); + error_message = td::Slice("can't upload file by URL"); } else if (error_message == "CHAT_ABOUT_NOT_MODIFIED") { error_code = 400; - error_message = Slice("chat description is not modified"); + error_message = td::Slice("chat description is not modified"); } else if (error_message == "PACK_SHORT_NAME_INVALID") { error_code = 400; - error_message = Slice("invalid sticker set name is specified"); + error_message = td::Slice("invalid sticker set name is specified"); } else if (error_message == "PACK_SHORT_NAME_OCCUPIED") { error_code = 400; - error_message = Slice("sticker set name is already occupied"); + error_message = td::Slice("sticker set name is already occupied"); } else if (error_message == "STICKER_EMOJI_INVALID") { error_code = 400; - error_message = Slice("invalid sticker emojis"); + error_message = td::Slice("invalid sticker emojis"); } else if (error_message == "QUERY_ID_INVALID") { error_code = 400; - error_message = Slice("query is too old and response timeout expired or query ID is invalid"); + error_message = td::Slice("query is too old and response timeout expired or query ID is invalid"); } else if (error_message == "MESSAGE_DELETE_FORBIDDEN") { error_code = 400; - error_message = Slice("message can't be deleted"); + error_message = td::Slice("message can't be deleted"); } } - Slice prefix; + td::Slice prefix; switch (error_code) { case 400: - prefix = Slice("Bad Request"); + prefix = td::Slice("Bad Request"); break; case 401: - prefix = Slice("Unauthorized"); + prefix = td::Slice("Unauthorized"); break; case 403: - prefix = Slice("Forbidden"); + prefix = td::Slice("Forbidden"); break; case 405: - prefix = Slice("Method Not Allowed"); + prefix = td::Slice("Method Not Allowed"); break; case 500: - prefix = Slice("Internal Server Error"); - if (real_error_message != Slice("Request aborted")) { + prefix = td::Slice("Internal Server Error"); + if (real_error_message != td::Slice("Request aborted")) { LOG(ERROR) << "Receive Internal Server Error \"" << real_error_message << "\" from " << *query; } break; @@ -196,7 +193,8 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Sli } } -void Client::fail_query_with_error(PromisedQueryPtr &&query, object_ptr error, Slice default_message) { +void Client::fail_query_with_error(PromisedQueryPtr &&query, object_ptr error, + td::Slice default_message) { fail_query_with_error(std::move(query), error->code_, error->message_, default_message); } @@ -227,6 +225,10 @@ bool Client::init_methods() { methods_.emplace("deletemycommands", &Client::process_delete_my_commands_query); methods_.emplace("getmydefaultadministratorrights", &Client::process_get_my_default_administrator_rights_query); methods_.emplace("setmydefaultadministratorrights", &Client::process_set_my_default_administrator_rights_query); + methods_.emplace("getmydescription", &Client::process_get_my_description_query); + methods_.emplace("setmydescription", &Client::process_set_my_description_query); + methods_.emplace("getmyshortdescription", &Client::process_get_my_short_description_query); + methods_.emplace("setmyshortdescription", &Client::process_set_my_short_description_query); methods_.emplace("getchatmenubutton", &Client::process_get_chat_menu_button_query); methods_.emplace("setchatmenubutton", &Client::process_set_chat_menu_button_query); methods_.emplace("getuserprofilephotos", &Client::process_get_user_profile_photos_query); @@ -297,7 +299,6 @@ bool Client::init_methods() { methods_.emplace("getchatadministrators", &Client::process_get_chat_administrators_query); methods_.emplace("getchatmembercount", &Client::process_get_chat_member_count_query); methods_.emplace("getchatmemberscount", &Client::process_get_chat_member_count_query); - methods_.emplace("optimizememory", &Client::process_optimize_memory_query); methods_.emplace("leavechat", &Client::process_leave_chat_query); methods_.emplace("promotechatmember", &Client::process_promote_chat_member_query); methods_.emplace("setchatadministratorcustomtitle", &Client::process_set_chat_administrator_custom_title_query); @@ -314,9 +315,16 @@ bool Client::init_methods() { methods_.emplace("uploadstickerfile", &Client::process_upload_sticker_file_query); methods_.emplace("createnewstickerset", &Client::process_create_new_sticker_set_query); methods_.emplace("addstickertoset", &Client::process_add_sticker_to_set_query); - methods_.emplace("setstickersetthumb", &Client::process_set_sticker_set_thumb_query); + methods_.emplace("setstickersettitle", &Client::process_set_sticker_set_title_query); + methods_.emplace("setstickersetthumb", &Client::process_set_sticker_set_thumbnail_query); + methods_.emplace("setstickersetthumbnail", &Client::process_set_sticker_set_thumbnail_query); + methods_.emplace("setcustomemojistickersetthumbnail", &Client::process_set_custom_emoji_sticker_set_thumbnail_query); + methods_.emplace("deletestickerset", &Client::process_delete_sticker_set_query); methods_.emplace("setstickerpositioninset", &Client::process_set_sticker_position_in_set_query); methods_.emplace("deletestickerfromset", &Client::process_delete_sticker_from_set_query); + methods_.emplace("setstickeremojilist", &Client::process_set_sticker_emoji_list_query); + methods_.emplace("setstickerkeywords", &Client::process_set_sticker_keywords_query); + methods_.emplace("setstickermaskposition", &Client::process_set_sticker_mask_position_query); methods_.emplace("setpassportdataerrors", &Client::process_set_passport_data_errors_query); methods_.emplace("sendcustomrequest", &Client::process_send_custom_request_query); methods_.emplace("answercustomquery", &Client::process_answer_custom_query_query); @@ -361,24 +369,24 @@ bool Client::init_methods() { return true; } -bool Client::is_local_method(Slice method) { +bool Client::is_local_method(td::Slice method) { return method == "close" || method == "logout" || method == "getme" || method == "getupdates" || method == "setwebhook" || method == "deletewebhook" || method == "getwebhookinfo"; } -class Client::JsonEmptyObject final : public Jsonable { +class Client::JsonEmptyObject final : public td::Jsonable { public: - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); } }; -class Client::JsonFile final : public Jsonable { +class Client::JsonFile final : public td::Jsonable { public: JsonFile(const td_api::file *file, const Client *client, bool with_path) : file_(file), client_(client), with_path_(with_path) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); client_->json_store_file(object, file_, with_path_); } @@ -389,11 +397,11 @@ class Client::JsonFile final : public Jsonable { bool with_path_; }; -class Client::JsonDatedFile final : public Jsonable { +class Client::JsonDatedFile final : public td::Jsonable { public: JsonDatedFile(const td_api::datedFile *file, const Client *client) : file_(file), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); client_->json_store_file(object, file_->file_.get()); object("file_date", file_->date_); @@ -404,12 +412,12 @@ class Client::JsonDatedFile final : public Jsonable { const Client *client_; }; -class Client::JsonDatedFiles final : public Jsonable { +class Client::JsonDatedFiles final : public td::Jsonable { public: JsonDatedFiles(const td::vector> &files, const Client *client) : files_(files), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &file : files_) { array << JsonDatedFile(file.get(), client_); @@ -421,12 +429,12 @@ class Client::JsonDatedFiles final : public Jsonable { const Client *client_; }; -class Client::JsonUser final : public Jsonable { +class Client::JsonUser final : public td::Jsonable { public: JsonUser(int64 user_id, const Client *client, bool full_bot_info = false) : user_id_(user_id), client_(client), full_bot_info_(full_bot_info) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); auto user_info = client_->get_user_info(user_id_); object("id", user_id_); @@ -476,11 +484,11 @@ class Client::JsonUser final : public Jsonable { bool full_bot_info_; }; -class Client::JsonUsers final : public Jsonable { +class Client::JsonUsers final : public td::Jsonable { public: JsonUsers(const td::vector &user_ids, const Client *client) : user_ids_(user_ids), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &user_id : user_ids_) { array << JsonUser(user_id, client_); @@ -492,11 +500,11 @@ class Client::JsonUsers final : public Jsonable { const Client *client_; }; -class Client::JsonEntity final : public Jsonable { +class Client::JsonEntity final : public td::Jsonable { public: JsonEntity(const td_api::textEntity *entity, const Client *client) : entity_(entity), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("offset", entity_->offset_); object("length", entity_->length_); @@ -580,12 +588,12 @@ class Client::JsonEntity final : public Jsonable { const Client *client_; }; -class Client::JsonVectorEntities final : public Jsonable { +class Client::JsonVectorEntities final : public td::Jsonable { public: JsonVectorEntities(const td::vector> &entities, const Client *client) : entities_(entities), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &entity : entities_) { auto entity_type = entity->type_->get_id(); @@ -601,7 +609,7 @@ class Client::JsonVectorEntities final : public Jsonable { const Client *client_; }; -class Client::JsonLocation final : public Jsonable { +class Client::JsonLocation final : public td::Jsonable { public: explicit JsonLocation(const td_api::location *location, double expires_in = 0.0, int32 live_period = 0, int32 heading = 0, int32 proximity_alert_radius = 0) @@ -611,7 +619,7 @@ class Client::JsonLocation final : public Jsonable { , heading_(heading) , proximity_alert_radius_(proximity_alert_radius) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("latitude", location_->latitude_); object("longitude", location_->longitude_); @@ -637,11 +645,11 @@ class Client::JsonLocation final : public Jsonable { int32 proximity_alert_radius_; }; -class Client::JsonChatPermissions final : public Jsonable { +class Client::JsonChatPermissions final : public td::Jsonable { public: explicit JsonChatPermissions(const td_api::chatPermissions *chat_permissions) : chat_permissions_(chat_permissions) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); Client::json_store_permissions(object, chat_permissions_); } @@ -650,11 +658,11 @@ class Client::JsonChatPermissions final : public Jsonable { const td_api::chatPermissions *chat_permissions_; }; -class Client::JsonChatPhotoInfo final : public Jsonable { +class Client::JsonChatPhotoInfo final : public td::Jsonable { public: explicit JsonChatPhotoInfo(const td_api::chatPhotoInfo *chat_photo) : chat_photo_(chat_photo) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("small_file_id", chat_photo_->small_->remote_->id_); object("small_file_unique_id", chat_photo_->small_->remote_->unique_id_); @@ -666,11 +674,11 @@ class Client::JsonChatPhotoInfo final : public Jsonable { const td_api::chatPhotoInfo *chat_photo_; }; -class Client::JsonChatLocation final : public Jsonable { +class Client::JsonChatLocation final : public td::Jsonable { public: explicit JsonChatLocation(const td_api::chatLocation *chat_location) : chat_location_(chat_location) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("location", JsonLocation(chat_location_->location_.get())); object("address", chat_location_->address_); @@ -680,12 +688,12 @@ class Client::JsonChatLocation final : public Jsonable { const td_api::chatLocation *chat_location_; }; -class Client::JsonChatInviteLink final : public Jsonable { +class Client::JsonChatInviteLink final : public td::Jsonable { public: JsonChatInviteLink(const td_api::chatInviteLink *chat_invite_link, const Client *client) : chat_invite_link_(chat_invite_link), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("invite_link", chat_invite_link_->invite_link_); if (!chat_invite_link_->name_.empty()) { @@ -711,12 +719,12 @@ class Client::JsonChatInviteLink final : public Jsonable { const Client *client_; }; -class Client::JsonMessage final : public Jsonable { +class Client::JsonMessage final : public td::Jsonable { public: JsonMessage(const MessageInfo *message, bool need_reply, const td::string &source, const Client *client) : message_(message), need_reply_(need_reply), source_(source), client_(client) { } - void store(JsonValueScope *scope) const; + void store(td::JsonValueScope *scope) const; private: const MessageInfo *message_; @@ -742,7 +750,7 @@ class Client::JsonMessage final : public Jsonable { } }; -class Client::JsonChat final : public Jsonable { +class Client::JsonChat final : public td::Jsonable { public: JsonChat(int64 chat_id, bool is_full, const Client *client, int64 pinned_message_id = -1, int32 distance = -1) : chat_id_(chat_id) @@ -751,7 +759,7 @@ class Client::JsonChat final : public Jsonable { , pinned_message_id_(pinned_message_id) , distance_(distance) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto chat_info = client_->get_chat(chat_id_); CHECK(chat_info != nullptr); auto object = scope->enter_object(); @@ -784,7 +792,7 @@ class Client::JsonChat final : public Jsonable { if (is_full_) { if (!user_info->active_usernames.empty()) { object("active_usernames", td::json_array(user_info->active_usernames, - [](Slice username) { return td::JsonString(username); })); + [](td::Slice username) { return td::JsonString(username); })); } if (user_info->emoji_status_custom_emoji_id != 0) { object("emoji_status_custom_emoji_id", td::to_string(user_info->emoji_status_custom_emoji_id)); @@ -820,9 +828,9 @@ class Client::JsonChat final : public Jsonable { object("permissions", JsonChatPermissions(permissions)); } auto everyone_is_administrator = - permissions->can_send_messages_ && permissions->can_send_audios_ && permissions->can_send_documents_ && - permissions->can_send_photos_ && permissions->can_send_videos_ && permissions->can_send_video_notes_ && - permissions->can_send_voice_notes_ && permissions->can_send_polls_ && + permissions->can_send_basic_messages_ && permissions->can_send_audios_ && + permissions->can_send_documents_ && permissions->can_send_photos_ && permissions->can_send_videos_ && + permissions->can_send_video_notes_ && permissions->can_send_voice_notes_ && permissions->can_send_polls_ && permissions->can_send_other_messages_ && permissions->can_add_web_page_previews_ && permissions->can_change_info_ && permissions->can_invite_users_ && permissions->can_pin_messages_; object("all_members_are_administrators", td::JsonBool(everyone_is_administrator)); @@ -859,7 +867,7 @@ class Client::JsonChat final : public Jsonable { if (is_full_) { if (!supergroup_info->active_usernames.empty()) { object("active_usernames", td::json_array(supergroup_info->active_usernames, - [](Slice username) { return td::JsonString(username); })); + [](td::Slice username) { return td::JsonString(username); })); } if (!supergroup_info->description.empty()) { object("description", supergroup_info->description); @@ -973,12 +981,12 @@ class Client::JsonChat final : public Jsonable { int32 distance_; }; -class Client::JsonMessageSender final : public Jsonable { +class Client::JsonMessageSender final : public td::Jsonable { public: JsonMessageSender(const td_api::MessageSender *sender_id, const Client *client) : sender_id_(sender_id), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { CHECK(sender_id_ != nullptr); switch (sender_id_->get_id()) { case td_api::messageSenderUser::ID: { @@ -1001,11 +1009,11 @@ class Client::JsonMessageSender final : public Jsonable { const Client *client_; }; -class Client::JsonMessages final : public Jsonable { +class Client::JsonMessages final : public td::Jsonable { public: explicit JsonMessages(const td::vector &messages) : messages_(messages) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &message : messages_) { array << td::JsonRaw(message); @@ -1016,12 +1024,12 @@ class Client::JsonMessages final : public Jsonable { const td::vector &messages_; }; -class Client::JsonAnimation final : public Jsonable { +class Client::JsonAnimation final : public td::Jsonable { public: JsonAnimation(const td_api::animation *animation, bool as_document, const Client *client) : animation_(animation), as_document_(as_document), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (!animation_->file_name_.empty()) { object("file_name", animation_->file_name_); @@ -1044,11 +1052,11 @@ class Client::JsonAnimation final : public Jsonable { const Client *client_; }; -class Client::JsonAudio final : public Jsonable { +class Client::JsonAudio final : public td::Jsonable { public: JsonAudio(const td_api::audio *audio, const Client *client) : audio_(audio), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("duration", audio_->duration_); if (!audio_->file_name_.empty()) { @@ -1072,11 +1080,11 @@ class Client::JsonAudio final : public Jsonable { const Client *client_; }; -class Client::JsonDocument final : public Jsonable { +class Client::JsonDocument final : public td::Jsonable { public: JsonDocument(const td_api::document *document, const Client *client) : document_(document), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (!document_->file_name_.empty()) { object("file_name", document_->file_name_); @@ -1093,11 +1101,11 @@ class Client::JsonDocument final : public Jsonable { const Client *client_; }; -class Client::JsonPhotoSize final : public Jsonable { +class Client::JsonPhotoSize final : public td::Jsonable { public: JsonPhotoSize(const td_api::photoSize *photo_size, const Client *client) : photo_size_(photo_size), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); client_->json_store_file(object, photo_size_->photo_.get()); object("width", photo_size_->width_); @@ -1109,11 +1117,11 @@ class Client::JsonPhotoSize final : public Jsonable { const Client *client_; }; -class Client::JsonThumbnail final : public Jsonable { +class Client::JsonThumbnail final : public td::Jsonable { public: JsonThumbnail(const td_api::thumbnail *thumbnail, const Client *client) : thumbnail_(thumbnail), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); client_->json_store_file(object, thumbnail_->file_.get()); object("width", thumbnail_->width_); @@ -1125,11 +1133,11 @@ class Client::JsonThumbnail final : public Jsonable { const Client *client_; }; -class Client::JsonPhoto final : public Jsonable { +class Client::JsonPhoto final : public td::Jsonable { public: JsonPhoto(const td_api::photo *photo, const Client *client) : photo_(photo), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &photo_size : photo_->sizes_) { if (photo_size->type_ != "i" && photo_size->type_ != "t" && !photo_size->photo_->remote_->id_.empty()) { @@ -1143,11 +1151,11 @@ class Client::JsonPhoto final : public Jsonable { const Client *client_; }; -class Client::JsonChatPhoto final : public Jsonable { +class Client::JsonChatPhoto final : public td::Jsonable { public: JsonChatPhoto(const td_api::chatPhoto *photo, const Client *client) : photo_(photo), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &photo_size : photo_->sizes_) { if (photo_size->type_ != "i" && photo_size->type_ != "t" && !photo_size->photo_->remote_->id_.empty()) { @@ -1161,11 +1169,11 @@ class Client::JsonChatPhoto final : public Jsonable { const Client *client_; }; -class Client::JsonMaskPosition final : public Jsonable { +class Client::JsonMaskPosition final : public td::Jsonable { public: explicit JsonMaskPosition(const td_api::maskPosition *mask_position) : mask_position_(mask_position) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("point", Client::MASK_POINTS[Client::mask_point_to_index(mask_position_->point_)]); object("x_shift", mask_position_->x_shift_); @@ -1177,11 +1185,11 @@ class Client::JsonMaskPosition final : public Jsonable { const td_api::maskPosition *mask_position_; }; -class Client::JsonSticker final : public Jsonable { +class Client::JsonSticker final : public td::Jsonable { public: JsonSticker(const td_api::sticker *sticker, const Client *client) : sticker_(sticker), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("width", sticker_->width_); object("height", sticker_->height_); @@ -1220,6 +1228,9 @@ class Client::JsonSticker final : public Jsonable { if (full_type->custom_emoji_id_ != 0) { object("custom_emoji_id", td::to_string(full_type->custom_emoji_id_)); } + if (full_type->needs_repainting_) { + object("needs_repainting", td::JsonBool(full_type->needs_repainting_)); + } break; } default: @@ -1236,12 +1247,12 @@ class Client::JsonSticker final : public Jsonable { const Client *client_; }; -class Client::JsonStickers final : public Jsonable { +class Client::JsonStickers final : public td::Jsonable { public: JsonStickers(const td::vector> &stickers, const Client *client) : stickers_(stickers), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &sticker : stickers_) { array << JsonSticker(sticker.get(), client_); @@ -1253,11 +1264,11 @@ class Client::JsonStickers final : public Jsonable { const Client *client_; }; -class Client::JsonVideo final : public Jsonable { +class Client::JsonVideo final : public td::Jsonable { public: JsonVideo(const td_api::video *video, const Client *client) : video_(video), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("duration", video_->duration_); object("width", video_->width_); @@ -1277,11 +1288,11 @@ class Client::JsonVideo final : public Jsonable { const Client *client_; }; -class Client::JsonVideoNote final : public Jsonable { +class Client::JsonVideoNote final : public td::Jsonable { public: JsonVideoNote(const td_api::videoNote *video_note, const Client *client) : video_note_(video_note), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("duration", video_note_->duration_); object("length", video_note_->length_); @@ -1294,11 +1305,11 @@ class Client::JsonVideoNote final : public Jsonable { const Client *client_; }; -class Client::JsonVoiceNote final : public Jsonable { +class Client::JsonVoiceNote final : public td::Jsonable { public: JsonVoiceNote(const td_api::voiceNote *voice_note, const Client *client) : voice_note_(voice_note), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("duration", voice_note_->duration_); if (!voice_note_->mime_type_.empty()) { @@ -1312,11 +1323,11 @@ class Client::JsonVoiceNote final : public Jsonable { const Client *client_; }; -class Client::JsonVenue final : public Jsonable { +class Client::JsonVenue final : public td::Jsonable { public: explicit JsonVenue(const td_api::venue *venue) : venue_(venue) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("location", JsonLocation(venue_->location_.get())); object("title", venue_->title_); @@ -1343,11 +1354,11 @@ class Client::JsonVenue final : public Jsonable { const td_api::venue *venue_; }; -class Client::JsonContact final : public Jsonable { +class Client::JsonContact final : public td::Jsonable { public: explicit JsonContact(const td_api::contact *contact) : contact_(contact) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("phone_number", contact_->phone_number_); object("first_name", contact_->first_name_); @@ -1366,11 +1377,11 @@ class Client::JsonContact final : public Jsonable { const td_api::contact *contact_; }; -class Client::JsonDice final : public Jsonable { +class Client::JsonDice final : public td::Jsonable { public: JsonDice(const td::string &emoji, int32 value) : emoji_(emoji), value_(value) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("emoji", emoji_); object("value", value_); @@ -1381,11 +1392,11 @@ class Client::JsonDice final : public Jsonable { int32 value_; }; -class Client::JsonGame final : public Jsonable { +class Client::JsonGame final : public td::Jsonable { public: JsonGame(const td_api::game *game, const Client *client) : game_(game), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("title", game_->title_); if (!game_->text_->text_.empty()) { @@ -1407,11 +1418,11 @@ class Client::JsonGame final : public Jsonable { const Client *client_; }; -class Client::JsonInvoice final : public Jsonable { +class Client::JsonInvoice final : public td::Jsonable { public: explicit JsonInvoice(const td_api::messageInvoice *invoice) : invoice_(invoice) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("title", invoice_->title_); object("description", invoice_->description_->text_); @@ -1428,11 +1439,11 @@ class Client::JsonInvoice final : public Jsonable { const td_api::messageInvoice *invoice_; }; -class Client::JsonPollOption final : public Jsonable { +class Client::JsonPollOption final : public td::Jsonable { public: explicit JsonPollOption(const td_api::pollOption *option) : option_(option) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("text", option_->text_); object("voter_count", option_->voter_count_); @@ -1443,11 +1454,11 @@ class Client::JsonPollOption final : public Jsonable { const td_api::pollOption *option_; }; -class Client::JsonPoll final : public Jsonable { +class Client::JsonPoll final : public td::Jsonable { public: JsonPoll(const td_api::poll *poll, const Client *client) : poll_(poll), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", td::to_string(poll_->id_)); object("question", poll_->question_); @@ -1490,12 +1501,12 @@ class Client::JsonPoll final : public Jsonable { const Client *client_; }; -class Client::JsonPollAnswer final : public Jsonable { +class Client::JsonPollAnswer final : public td::Jsonable { public: JsonPollAnswer(const td_api::updatePollAnswer *poll_answer, const Client *client) : poll_answer_(poll_answer), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("poll_id", td::to_string(poll_answer_->poll_id_)); object("user", JsonUser(poll_answer_->user_id_, client_)); @@ -1507,12 +1518,12 @@ class Client::JsonPollAnswer final : public Jsonable { const Client *client_; }; -class Client::JsonForumTopicCreated final : public Jsonable { +class Client::JsonForumTopicCreated final : public td::Jsonable { public: explicit JsonForumTopicCreated(const td_api::messageForumTopicCreated *forum_topic_created) : forum_topic_created_(forum_topic_created) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("name", forum_topic_created_->name_); object("icon_color", forum_topic_created_->icon_->color_); @@ -1525,12 +1536,12 @@ class Client::JsonForumTopicCreated final : public Jsonable { const td_api::messageForumTopicCreated *forum_topic_created_; }; -class Client::JsonForumTopicEdited final : public Jsonable { +class Client::JsonForumTopicEdited final : public td::Jsonable { public: explicit JsonForumTopicEdited(const td_api::messageForumTopicEdited *forum_topic_edited) : forum_topic_edited_(forum_topic_edited) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (!forum_topic_edited_->name_.empty()) { object("name", forum_topic_edited_->name_); @@ -1546,11 +1557,11 @@ class Client::JsonForumTopicEdited final : public Jsonable { const td_api::messageForumTopicEdited *forum_topic_edited_; }; -class Client::JsonForumTopicInfo final : public Jsonable { +class Client::JsonForumTopicInfo final : public td::Jsonable { public: explicit JsonForumTopicInfo(const td_api::forumTopicInfo *forum_topic_info) : forum_topic_info_(forum_topic_info) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("message_thread_id", as_client_message_id(forum_topic_info_->message_thread_id_)); object("name", forum_topic_info_->name_); @@ -1564,11 +1575,11 @@ class Client::JsonForumTopicInfo final : public Jsonable { const td_api::forumTopicInfo *forum_topic_info_; }; -class Client::JsonAddress final : public Jsonable { +class Client::JsonAddress final : public td::Jsonable { public: explicit JsonAddress(const td_api::address *address) : address_(address) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("country_code", address_->country_code_); object("state", address_->state_); @@ -1582,11 +1593,11 @@ class Client::JsonAddress final : public Jsonable { const td_api::address *address_; }; -class Client::JsonOrderInfo final : public Jsonable { +class Client::JsonOrderInfo final : public td::Jsonable { public: explicit JsonOrderInfo(const td_api::orderInfo *order_info) : order_info_(order_info) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (!order_info_->name_.empty()) { object("name", order_info_->name_); @@ -1606,12 +1617,12 @@ class Client::JsonOrderInfo final : public Jsonable { const td_api::orderInfo *order_info_; }; -class Client::JsonSuccessfulPaymentBot final : public Jsonable { +class Client::JsonSuccessfulPaymentBot final : public td::Jsonable { public: explicit JsonSuccessfulPaymentBot(const td_api::messagePaymentSuccessfulBot *successful_payment) : successful_payment_(successful_payment) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("currency", successful_payment_->currency_); object("total_amount", successful_payment_->total_amount_); @@ -1636,12 +1647,12 @@ class Client::JsonSuccessfulPaymentBot final : public Jsonable { const td_api::messagePaymentSuccessfulBot *successful_payment_; }; -class Client::JsonEncryptedPassportElement final : public Jsonable { +class Client::JsonEncryptedPassportElement final : public td::Jsonable { public: JsonEncryptedPassportElement(const td_api::encryptedPassportElement *element, const Client *client) : element_(element), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); auto id = element_->type_->get_id(); object("type", Client::get_passport_element_type(id)); @@ -1703,11 +1714,11 @@ class Client::JsonEncryptedPassportElement final : public Jsonable { const Client *client_; }; -class Client::JsonEncryptedCredentials final : public Jsonable { +class Client::JsonEncryptedCredentials final : public td::Jsonable { public: explicit JsonEncryptedCredentials(const td_api::encryptedCredentials *credentials) : credentials_(credentials) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("data", td::base64_encode(credentials_->data_)); object("hash", td::base64_encode(credentials_->hash_)); @@ -1718,12 +1729,12 @@ class Client::JsonEncryptedCredentials final : public Jsonable { const td_api::encryptedCredentials *credentials_; }; -class Client::JsonPassportData final : public Jsonable { +class Client::JsonPassportData final : public td::Jsonable { public: JsonPassportData(const td_api::messagePassportDataReceived *passport_data, const Client *client) : passport_data_(passport_data), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("data", td::json_array(passport_data_->elements_, [client = client_](auto &element) { return JsonEncryptedPassportElement(element.get(), client); @@ -1736,11 +1747,11 @@ class Client::JsonPassportData final : public Jsonable { const Client *client_; }; -class Client::JsonWebAppData final : public Jsonable { +class Client::JsonWebAppData final : public td::Jsonable { public: explicit JsonWebAppData(const td_api::messageWebAppDataReceived *web_app_data) : web_app_data_(web_app_data) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("button_text", web_app_data_->button_text_); object("data", web_app_data_->data_); @@ -1750,13 +1761,13 @@ class Client::JsonWebAppData final : public Jsonable { const td_api::messageWebAppDataReceived *web_app_data_; }; -class Client::JsonProximityAlertTriggered final : public Jsonable { +class Client::JsonProximityAlertTriggered final : public td::Jsonable { public: JsonProximityAlertTriggered(const td_api::messageProximityAlertTriggered *proximity_alert_triggered, const Client *client) : proximity_alert_triggered_(proximity_alert_triggered), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("traveler", JsonMessageSender(proximity_alert_triggered_->traveler_id_.get(), client_)); object("watcher", JsonMessageSender(proximity_alert_triggered_->watcher_id_.get(), client_)); @@ -1768,12 +1779,12 @@ class Client::JsonProximityAlertTriggered final : public Jsonable { const Client *client_; }; -class Client::JsonVideoChatScheduled final : public Jsonable { +class Client::JsonVideoChatScheduled final : public td::Jsonable { public: explicit JsonVideoChatScheduled(const td_api::messageVideoChatScheduled *video_chat_scheduled) : video_chat_scheduled_(video_chat_scheduled) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("start_date", video_chat_scheduled_->start_date_); } @@ -1782,12 +1793,12 @@ class Client::JsonVideoChatScheduled final : public Jsonable { const td_api::messageVideoChatScheduled *video_chat_scheduled_; }; -class Client::JsonVideoChatEnded final : public Jsonable { +class Client::JsonVideoChatEnded final : public td::Jsonable { public: explicit JsonVideoChatEnded(const td_api::messageVideoChatEnded *video_chat_ended) : video_chat_ended_(video_chat_ended) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("duration", video_chat_ended_->duration_); } @@ -1796,13 +1807,13 @@ class Client::JsonVideoChatEnded final : public Jsonable { const td_api::messageVideoChatEnded *video_chat_ended_; }; -class Client::JsonInviteVideoChatParticipants final : public Jsonable { +class Client::JsonInviteVideoChatParticipants final : public td::Jsonable { public: JsonInviteVideoChatParticipants(const td_api::messageInviteVideoChatParticipants *invite_video_chat_participants, const Client *client) : invite_video_chat_participants_(invite_video_chat_participants), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("users", JsonUsers(invite_video_chat_participants_->user_ids_, client_)); } @@ -1812,13 +1823,13 @@ class Client::JsonInviteVideoChatParticipants final : public Jsonable { const Client *client_; }; -class Client::JsonChatSetMessageAutoDeleteTime final : public Jsonable { +class Client::JsonChatSetMessageAutoDeleteTime final : public td::Jsonable { public: explicit JsonChatSetMessageAutoDeleteTime( const td_api::messageChatSetMessageAutoDeleteTime *chat_set_message_auto_delete_time) : chat_set_message_auto_delete_time_(chat_set_message_auto_delete_time) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("message_auto_delete_time", chat_set_message_auto_delete_time_->message_auto_delete_time_); } @@ -1827,11 +1838,27 @@ class Client::JsonChatSetMessageAutoDeleteTime final : public Jsonable { const td_api::messageChatSetMessageAutoDeleteTime *chat_set_message_auto_delete_time_; }; -class Client::JsonUserShared final : public Jsonable { +class Client::JsonWriteAccessAllowed final : public td::Jsonable { + public: + explicit JsonWriteAccessAllowed(const td_api::messageBotWriteAccessAllowed *write_access_allowed) + : write_access_allowed_(write_access_allowed) { + } + void store(td::JsonValueScope *scope) const { + auto object = scope->enter_object(); + if (write_access_allowed_->web_app_ != nullptr) { + object("web_app_name", write_access_allowed_->web_app_->short_name_); + } + } + + private: + const td_api::messageBotWriteAccessAllowed *write_access_allowed_; +}; + +class Client::JsonUserShared final : public td::Jsonable { public: explicit JsonUserShared(const td_api::messageUserShared *user_shared) : user_shared_(user_shared) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("user_id", user_shared_->user_id_); object("request_id", user_shared_->button_id_); @@ -1841,11 +1868,11 @@ class Client::JsonUserShared final : public Jsonable { const td_api::messageUserShared *user_shared_; }; -class Client::JsonChatShared final : public Jsonable { +class Client::JsonChatShared final : public td::Jsonable { public: explicit JsonChatShared(const td_api::messageChatShared *chat_shared) : chat_shared_(chat_shared) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("chat_id", chat_shared_->chat_id_); object("request_id", chat_shared_->button_id_); @@ -1855,11 +1882,11 @@ class Client::JsonChatShared final : public Jsonable { const td_api::messageChatShared *chat_shared_; }; -class Client::JsonWebAppInfo final : public Jsonable { +class Client::JsonWebAppInfo final : public td::Jsonable { public: explicit JsonWebAppInfo(const td::string &url) : url_(url) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("url", url_); } @@ -1868,11 +1895,11 @@ class Client::JsonWebAppInfo final : public Jsonable { const td::string &url_; }; -class Client::JsonInlineKeyboardButton final : public Jsonable { +class Client::JsonInlineKeyboardButton final : public td::Jsonable { public: explicit JsonInlineKeyboardButton(const td_api::inlineKeyboardButton *button) : button_(button) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("text", button_->text_); switch (button_->type_->get_id()) { @@ -1931,12 +1958,12 @@ class Client::JsonInlineKeyboardButton final : public Jsonable { const td_api::inlineKeyboardButton *button_; }; -class Client::JsonInlineKeyboard final : public Jsonable { +class Client::JsonInlineKeyboard final : public td::Jsonable { public: explicit JsonInlineKeyboard(const td_api::replyMarkupInlineKeyboard *inline_keyboard) : inline_keyboard_(inline_keyboard) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &row : inline_keyboard_->rows_) { array << td::json_array(row, [](auto &button) { return JsonInlineKeyboardButton(button.get()); }); @@ -1947,11 +1974,11 @@ class Client::JsonInlineKeyboard final : public Jsonable { const td_api::replyMarkupInlineKeyboard *inline_keyboard_; }; -class Client::JsonReplyMarkup final : public Jsonable { +class Client::JsonReplyMarkup final : public td::Jsonable { public: explicit JsonReplyMarkup(const td_api::ReplyMarkup *reply_markup) : reply_markup_(reply_markup) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { CHECK(reply_markup_->get_id() == td_api::replyMarkupInlineKeyboard::ID); auto object = scope->enter_object(); object("inline_keyboard", @@ -1962,7 +1989,7 @@ class Client::JsonReplyMarkup final : public Jsonable { const td_api::ReplyMarkup *reply_markup_; }; -void Client::JsonMessage::store(JsonValueScope *scope) const { +void Client::JsonMessage::store(td::JsonValueScope *scope) const { CHECK(message_ != nullptr); auto object = scope->enter_object(); if (message_->is_scheduled) { @@ -2342,9 +2369,11 @@ void Client::JsonMessage::store(JsonValueScope *scope) const { break; case td_api::messageSuggestProfilePhoto::ID: break; - case td_api::messageBotWriteAccessAllowed::ID: - object("write_access_allowed", JsonEmptyObject()); + case td_api::messageBotWriteAccessAllowed::ID: { + auto content = static_cast(message_->content.get()); + object("write_access_allowed", JsonWriteAccessAllowed(content)); break; + } case td_api::messageUserShared::ID: { auto content = static_cast(message_->content.get()); object("user_shared", JsonUserShared(content)); @@ -2372,12 +2401,12 @@ void Client::JsonMessage::store(JsonValueScope *scope) const { } } -class Client::JsonDeletedMessage final : public Jsonable { +class Client::JsonDeletedMessage final : public td::Jsonable { public: JsonDeletedMessage(int64 chat_id, int64 message_id, const Client *client) : chat_id_(chat_id), message_id_(message_id), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("message_id", as_client_message_id(message_id_)); object("chat", JsonChat(chat_id_, false, client_)); @@ -2390,11 +2419,11 @@ class Client::JsonDeletedMessage final : public Jsonable { const Client *client_; }; -class Client::JsonMessageId final : public Jsonable { +class Client::JsonMessageId final : public td::Jsonable { public: explicit JsonMessageId(int64 message_id) : message_id_(message_id) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("message_id", as_client_message_id(message_id_)); } @@ -2403,7 +2432,7 @@ class Client::JsonMessageId final : public Jsonable { int64 message_id_; }; -class Client::JsonInlineQuery final : public Jsonable { +class Client::JsonInlineQuery final : public td::Jsonable { public: JsonInlineQuery(int64 inline_query_id, int64 sender_user_id, const td_api::location *user_location, const td_api::ChatType *chat_type, const td::string &query, const td::string &offset, @@ -2417,7 +2446,7 @@ class Client::JsonInlineQuery final : public Jsonable { , client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", td::to_string(inline_query_id_)); object("from", JsonUser(sender_user_id_, client_)); @@ -2469,7 +2498,7 @@ class Client::JsonInlineQuery final : public Jsonable { const Client *client_; }; -class Client::JsonChosenInlineResult final : public Jsonable { +class Client::JsonChosenInlineResult final : public td::Jsonable { public: JsonChosenInlineResult(int64 sender_user_id, const td_api::location *user_location, const td::string &query, const td::string &result_id, const td::string &inline_message_id, const Client *client) @@ -2481,7 +2510,7 @@ class Client::JsonChosenInlineResult final : public Jsonable { , client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("from", JsonUser(sender_user_id_, client_)); if (user_location_ != nullptr) { @@ -2503,7 +2532,7 @@ class Client::JsonChosenInlineResult final : public Jsonable { const Client *client_; }; -class Client::JsonCallbackQuery final : public Jsonable { +class Client::JsonCallbackQuery final : public td::Jsonable { public: JsonCallbackQuery(int64 callback_query_id, int64 sender_user_id, int64 chat_id, int64 message_id, const MessageInfo *message_info, int64 chat_instance, td_api::CallbackQueryPayload *payload, @@ -2518,7 +2547,7 @@ class Client::JsonCallbackQuery final : public Jsonable { , client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", td::to_string(callback_query_id_)); object("from", JsonUser(sender_user_id_, client_)); @@ -2542,7 +2571,7 @@ class Client::JsonCallbackQuery final : public Jsonable { const Client *client_; }; -class Client::JsonInlineCallbackQuery final : public Jsonable { +class Client::JsonInlineCallbackQuery final : public td::Jsonable { public: JsonInlineCallbackQuery(int64 callback_query_id, int64 sender_user_id, const td::string &inline_message_id, int64 chat_instance, td_api::CallbackQueryPayload *payload, const Client *client) @@ -2554,7 +2583,7 @@ class Client::JsonInlineCallbackQuery final : public Jsonable { , client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", td::to_string(callback_query_id_)); object("from", JsonUser(sender_user_id_, client_)); @@ -2572,13 +2601,13 @@ class Client::JsonInlineCallbackQuery final : public Jsonable { const Client *client_; }; -class Client::JsonShippingQuery final : public Jsonable { +class Client::JsonShippingQuery final : public td::Jsonable { public: JsonShippingQuery(const td_api::updateNewShippingQuery *query, const Client *client) : query_(query), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", td::to_string(query_->id_)); object("from", JsonUser(query_->sender_user_id_, client_)); @@ -2596,13 +2625,13 @@ class Client::JsonShippingQuery final : public Jsonable { const Client *client_; }; -class Client::JsonPreCheckoutQuery final : public Jsonable { +class Client::JsonPreCheckoutQuery final : public td::Jsonable { public: JsonPreCheckoutQuery(const td_api::updateNewPreCheckoutQuery *query, const Client *client) : query_(query), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", td::to_string(query_->id_)); object("from", JsonUser(query_->sender_user_id_, client_)); @@ -2627,12 +2656,12 @@ class Client::JsonPreCheckoutQuery final : public Jsonable { const Client *client_; }; -class Client::JsonCustomJson final : public Jsonable { +class Client::JsonCustomJson final : public td::Jsonable { public: explicit JsonCustomJson(const td::string &json) : json_(json) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { *scope << td::JsonRaw(json_); } @@ -2640,11 +2669,11 @@ class Client::JsonCustomJson final : public Jsonable { const td::string &json_; }; -class Client::JsonBotCommand final : public Jsonable { +class Client::JsonBotCommand final : public td::Jsonable { public: explicit JsonBotCommand(const td_api::botCommand *command) : command_(command) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("command", command_->command_); object("description", command_->description_); @@ -2654,11 +2683,11 @@ class Client::JsonBotCommand final : public Jsonable { const td_api::botCommand *command_; }; -class Client::JsonBotMenuButton final : public Jsonable { +class Client::JsonBotMenuButton final : public td::Jsonable { public: explicit JsonBotMenuButton(const td_api::botMenuButton *menu_button) : menu_button_(menu_button) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (menu_button_->text_.empty()) { object("type", menu_button_->url_.empty() ? "commands" : "default"); @@ -2673,13 +2702,39 @@ class Client::JsonBotMenuButton final : public Jsonable { const td_api::botMenuButton *menu_button_; }; -class Client::JsonChatAdministratorRights final : public Jsonable { +class Client::JsonBotInfoDescription final : public td::Jsonable { + public: + explicit JsonBotInfoDescription(const td_api::text *text) : text_(text) { + } + void store(td::JsonValueScope *scope) const { + auto object = scope->enter_object(); + object("description", text_->text_); + } + + private: + const td_api::text *text_; +}; + +class Client::JsonBotInfoShortDescription final : public td::Jsonable { + public: + explicit JsonBotInfoShortDescription(const td_api::text *text) : text_(text) { + } + void store(td::JsonValueScope *scope) const { + auto object = scope->enter_object(); + object("short_description", text_->text_); + } + + private: + const td_api::text *text_; +}; + +class Client::JsonChatAdministratorRights final : public td::Jsonable { public: JsonChatAdministratorRights(const td_api::chatAdministratorRights *rights, Client::ChatType chat_type) : rights_(rights), chat_type_(chat_type) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); td_api::chatAdministratorRights empty_rights; Client::json_store_administrator_rights(object, rights_ == nullptr ? &empty_rights : rights_, chat_type_); @@ -2690,11 +2745,11 @@ class Client::JsonChatAdministratorRights final : public Jsonable { Client::ChatType chat_type_; }; -class Client::JsonChatPhotos final : public Jsonable { +class Client::JsonChatPhotos final : public td::Jsonable { public: JsonChatPhotos(const td_api::chatPhotos *photos, const Client *client) : photos_(photos), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("total_count", photos_->total_count_); object("photos", td::json_array(photos_->photos_, @@ -2706,13 +2761,13 @@ class Client::JsonChatPhotos final : public Jsonable { const Client *client_; }; -class Client::JsonChatMember final : public Jsonable { +class Client::JsonChatMember final : public td::Jsonable { public: JsonChatMember(const td_api::chatMember *member, Client::ChatType chat_type, const Client *client) : member_(member), chat_type_(chat_type), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); CHECK(member_->member_id_ != nullptr); switch (member_->member_id_->get_id()) { @@ -2787,13 +2842,13 @@ class Client::JsonChatMember final : public Jsonable { const Client *client_; }; -class Client::JsonChatMembers final : public Jsonable { +class Client::JsonChatMembers final : public td::Jsonable { public: JsonChatMembers(const td::vector> &members, Client::ChatType chat_type, bool administrators_only, const Client *client) : members_(members), chat_type_(chat_type), administrators_only_(administrators_only), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &member : members_) { CHECK(member != nullptr); @@ -2833,12 +2888,12 @@ class Client::JsonChatMembers final : public Jsonable { const Client *client_; }; -class Client::JsonChatMemberUpdated final : public Jsonable { +class Client::JsonChatMemberUpdated final : public td::Jsonable { public: JsonChatMemberUpdated(const td_api::updateChatMember *update, const Client *client) : update_(update), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("chat", JsonChat(update_->chat_id_, false, client_)); object("from", JsonUser(update_->actor_user_id_, client_)); @@ -2856,12 +2911,12 @@ class Client::JsonChatMemberUpdated final : public Jsonable { const Client *client_; }; -class Client::JsonChatJoinRequest final : public Jsonable { +class Client::JsonChatJoinRequest final : public td::Jsonable { public: JsonChatJoinRequest(const td_api::updateNewChatJoinRequest *update, const Client *client) : update_(update), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("chat", JsonChat(update_->chat_id_, false, client_)); object("from", JsonUser(update_->request_->user_id_, client_)); @@ -2880,12 +2935,12 @@ class Client::JsonChatJoinRequest final : public Jsonable { const Client *client_; }; -class Client::JsonGameHighScore final : public Jsonable { +class Client::JsonGameHighScore final : public td::Jsonable { public: JsonGameHighScore(const td_api::gameHighScore *score, const Client *client) : score_(score), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("position", score_->position_); object("user", JsonUser(score_->user_id_, client_)); @@ -2897,11 +2952,11 @@ class Client::JsonGameHighScore final : public Jsonable { const Client *client_; }; -class Client::JsonUpdateTypes final : public Jsonable { +class Client::JsonUpdateTypes final : public td::Jsonable { public: explicit JsonUpdateTypes(td::uint32 update_types) : update_types_(update_types) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (int32 i = 0; i < static_cast(UpdateType::Size); i++) { if (((update_types_ >> i) & 1) != 0) { @@ -2917,11 +2972,11 @@ class Client::JsonUpdateTypes final : public Jsonable { td::uint32 update_types_; }; -class Client::JsonWebhookInfo final : public Jsonable { +class Client::JsonWebhookInfo final : public td::Jsonable { public: explicit JsonWebhookInfo(const Client *client) : client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); td::CSlice url = client_->webhook_url_; if (td::check_utf8(url)) { @@ -2958,12 +3013,12 @@ class Client::JsonWebhookInfo final : public Jsonable { const Client *client_; }; -class Client::JsonStickerSet final : public Jsonable { +class Client::JsonStickerSet final : public td::Jsonable { public: JsonStickerSet(const td_api::stickerSet *sticker_set, const Client *client) : sticker_set_(sticker_set), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (sticker_set_->id_ == Client::GREAT_MINDS_SET_ID) { object("name", GREAT_MINDS_SET_NAME); @@ -2991,11 +3046,11 @@ class Client::JsonStickerSet final : public Jsonable { const Client *client_; }; -class Client::JsonSentWebAppMessage final : public Jsonable { +class Client::JsonSentWebAppMessage final : public td::Jsonable { public: explicit JsonSentWebAppMessage(const td_api::sentWebAppMessage *message) : message_(message) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (!message_->inline_message_id_.empty()) { object("inline_message_id", message_->inline_message_id_); @@ -3008,13 +3063,13 @@ class Client::JsonSentWebAppMessage final : public Jsonable { // start custom Json objects impl -class Client::JsonAuthorizationState : public Jsonable { +class Client::JsonAuthorizationState : public td::Jsonable { public: JsonAuthorizationState(const td_api::AuthorizationState *state, td::string token = "") : state_(state), token_(token) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); if (!token_.empty()) { object("token", token_); @@ -3061,12 +3116,12 @@ class Client::JsonAuthorizationState : public Jsonable { const td::string token_; }; -class Client::JsonCallbackQueryAnswer : public Jsonable { +class Client::JsonCallbackQueryAnswer : public td::Jsonable { public: JsonCallbackQueryAnswer(const td_api::callbackQueryAnswer *answer) : answer_(answer) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("text", answer_->text_); object("show_alert", td::JsonBool(answer_->show_alert_)); @@ -3077,11 +3132,11 @@ class Client::JsonCallbackQueryAnswer : public Jsonable { const td_api::callbackQueryAnswer *answer_; }; -class Client::JsonChats : public Jsonable { +class Client::JsonChats : public td::Jsonable { public: JsonChats(const object_ptr &chats, const Client *client) : chats_(chats), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &chat : chats_->chat_ids_) { array << JsonChat(chat, false, client_); @@ -3093,12 +3148,12 @@ class Client::JsonChats : public Jsonable { const Client *client_; }; -class Client::JsonChatsNearby : public Jsonable { +class Client::JsonChatsNearby : public td::Jsonable { public: JsonChatsNearby(const object_ptr &chats_nearby, const Client *client) : chats_nearby_(chats_nearby), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &chat : chats_nearby_->users_nearby_) { array << JsonChat(chat->chat_id_, false, client_, -1, chat->distance_); @@ -3113,11 +3168,11 @@ class Client::JsonChatsNearby : public Jsonable { const Client *client_; }; -class Client::JsonMessagesArray : public Jsonable { +class Client::JsonMessagesArray : public td::Jsonable { public: explicit JsonMessagesArray(td::vector> &messages, Client *client) : messages_(messages), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &message : messages_) { auto full_message_id = client_->add_message(std::move(message)); @@ -3131,11 +3186,11 @@ class Client::JsonMessagesArray : public Jsonable { Client *client_; }; -class Client::JsonFoundMessages : public Jsonable { +class Client::JsonFoundMessages : public td::Jsonable { public: explicit JsonFoundMessages(object_ptr &foundMessages, Client *client) : foundMessages_(foundMessages), client_(client) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("next_offset", foundMessages_->next_offset_); object("messages", JsonMessagesArray(foundMessages_->messages_, std::move(client_))); @@ -3146,12 +3201,12 @@ class Client::JsonFoundMessages : public Jsonable { Client *client_; }; -class Client::JsonProxy : public Jsonable { +class Client::JsonProxy : public td::Jsonable { public: explicit JsonProxy(object_ptr &proxy) : proxy_(proxy) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto object = scope->enter_object(); object("id", proxy_->id_); object("last_used_date", proxy_->last_used_date_); @@ -3190,11 +3245,11 @@ class Client::JsonProxy : public Jsonable { object_ptr &proxy_; }; -class Client::JsonProxiesArray : public Jsonable { +class Client::JsonProxiesArray : public td::Jsonable { public: explicit JsonProxiesArray(object_ptr &proxies) : proxies_(proxies) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); for (auto &proxy : proxies_->proxies_) { array << JsonProxy(proxy); @@ -3698,7 +3753,7 @@ class Client::TdOnResolveBotUsernameCallback final : public TdQueryCallback { template class Client::TdOnCheckMessageCallback final : public TdQueryCallback { public: - TdOnCheckMessageCallback(Client *client, int64 chat_id, int64 message_id, bool allow_empty, Slice message_type, + TdOnCheckMessageCallback(Client *client, int64 chat_id, int64 message_id, bool allow_empty, td::Slice message_type, PromisedQueryPtr query, OnSuccess on_success) : client_(client) , chat_id_(chat_id) @@ -3733,7 +3788,7 @@ class Client::TdOnCheckMessageCallback final : public TdQueryCallback { int64 chat_id_; int64 message_id_; bool allow_empty_; - Slice message_type_; + td::Slice message_type_; PromisedQueryPtr query_; OnSuccess on_success_; }; @@ -3837,7 +3892,7 @@ class Client::TdOnDownloadFileCallback final : public TdQueryCallback { void on_result(object_ptr result) final { if (result->get_id() == td_api::error::ID) { auto error = move_object_as(result); - return client_->on_file_download(file_id_, Status::Error(error->code_, error->message_)); + return client_->on_file_download(file_id_, td::Status::Error(error->code_, error->message_)); } CHECK(result->get_id() == td_api::file::ID); if (client_->is_file_being_downloaded(file_id_)) { // if download is yet not finished @@ -4117,6 +4172,44 @@ class Client::TdOnGetMyDefaultAdministratorRightsCallback final : public TdQuery PromisedQueryPtr query_; }; +class Client::TdOnGetMyDescriptionCallback final : public TdQueryCallback { + public: + explicit TdOnGetMyDescriptionCallback(PromisedQueryPtr query) : query_(std::move(query)) { + } + + void on_result(object_ptr result) final { + if (result->get_id() == td_api::error::ID) { + return fail_query_with_error(std::move(query_), move_object_as(result)); + } + + CHECK(result->get_id() == td_api::text::ID); + auto text = move_object_as(result); + answer_query(JsonBotInfoDescription(text.get()), std::move(query_)); + } + + private: + PromisedQueryPtr query_; +}; + +class Client::TdOnGetMyShortDescriptionCallback final : public TdQueryCallback { + public: + explicit TdOnGetMyShortDescriptionCallback(PromisedQueryPtr query) : query_(std::move(query)) { + } + + void on_result(object_ptr result) final { + if (result->get_id() == td_api::error::ID) { + return fail_query_with_error(std::move(query_), move_object_as(result)); + } + + CHECK(result->get_id() == td_api::text::ID); + auto text = move_object_as(result); + answer_query(JsonBotInfoShortDescription(text.get()), std::move(query_)); + } + + private: + PromisedQueryPtr query_; +}; + class Client::TdOnGetForumTopicInfoCallback final : public TdQueryCallback { public: explicit TdOnGetForumTopicInfoCallback(PromisedQueryPtr query) : query_(std::move(query)) { @@ -4405,7 +4498,7 @@ class Client::TdOnGetStickerSetPromiseCallback final : public TdQueryCallback { void on_result(object_ptr result) final { if (result->get_id() == td_api::error::ID) { auto error = move_object_as(result); - return promise_.set_error(Status::Error(error->code_, error->message_)); + return promise_.set_error(td::Status::Error(error->code_, error->message_)); } CHECK(result->get_id() == td_api::stickerSet::ID); @@ -4714,7 +4807,7 @@ void Client::close() { } } -void Client::log_out(int32 error_code, Slice error_message) { +void Client::log_out(int32 error_code, td::Slice error_message) { LOG(WARNING) << "Logging out due to error " << error_code << ": " << error_message; if (error_message == "API_ID_INVALID") { is_api_id_invalid_ = true; @@ -4846,23 +4939,20 @@ void Client::send(PromisedQueryPtr query) { if (!query->is_internal()) { query->set_stat_actor(stat_actor_); if (!parameters_->local_mode_ && !is_local_method(query->method()) && - td::Time::now() > parameters_->start_time_ + 10 * 60) { + td::Time::now() > parameters_->start_time_ + 60) { BotStatActor *stat = stat_actor_.get_actor_unsafe(); auto update_per_minute = static_cast(stat->get_minute_update_count(td::Time::now()) * 60); if (stat->get_active_request_count() > 500 + update_per_minute) { LOG(INFO) << "Fail a query, because there are too many active queries: " << *query; - flood_limited_query_count_++; - return query->set_retry_after_error(60); + return fail_query_flood_limit_exceeded(std::move(query)); } if (stat->get_active_file_upload_bytes() > (static_cast(1) << 32) && !query->files().empty()) { LOG(INFO) << "Fail a query, because the total size of active file uploads is too big: " << *query; - flood_limited_query_count_++; - return query->set_retry_after_error(60); + return fail_query_flood_limit_exceeded(std::move(query)); } if (stat->get_active_file_upload_count() > 100 + update_per_minute / 5 && !query->files().empty()) { LOG(INFO) << "Fail a query, because there are too many active file uploads: " << *query; - flood_limited_query_count_++; - return query->set_retry_after_error(60); + return fail_query_flood_limit_exceeded(std::move(query)); } } } @@ -5094,7 +5184,8 @@ void Client::check_chat_access(int64 chat_id, AccessRights access_rights, const } template -void Client::check_chat(Slice chat_id_str, AccessRights access_rights, PromisedQueryPtr query, OnSuccess on_success) { +void Client::check_chat(td::Slice chat_id_str, AccessRights access_rights, PromisedQueryPtr query, + OnSuccess on_success) { if (chat_id_str.empty()) { return fail_query(400, "Bad Request: chat_id is empty", std::move(query)); } @@ -5116,7 +5207,7 @@ void Client::check_chat(Slice chat_id_str, AccessRights access_rights, PromisedQ } template -void Client::check_chat_no_fail(Slice chat_id_str, PromisedQueryPtr query, OnSuccess on_success) { +void Client::check_chat_no_fail(td::Slice chat_id_str, PromisedQueryPtr query, OnSuccess on_success) { if (chat_id_str.empty()) { return fail_query(400, "Bad Request: sender_chat_id is empty", std::move(query)); } @@ -5209,8 +5300,8 @@ bool Client::have_message_access(int64 chat_id) const { } template -void Client::check_message(Slice chat_id_str, int64 message_id, bool allow_empty, AccessRights access_rights, - Slice message_type, PromisedQueryPtr query, OnSuccess on_success) { +void Client::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) { check_chat(chat_id_str, access_rights, std::move(query), [this, message_id, allow_empty, message_type, on_success = std::move(on_success)]( int64 chat_id, PromisedQueryPtr query) mutable { @@ -5429,7 +5520,7 @@ void Client::on_update_file(object_ptr file) { send_request(make_object(file_id, false), td::make_unique()); } - return on_file_download(file_id, Status::Error(400, "Bad Request: file is too big")); + return on_file_download(file_id, td::Status::Error(400, "Bad Request: file is too big")); } if (file->local_->is_downloading_completed_) { return on_file_download(file_id, std::move(file)); @@ -5438,10 +5529,10 @@ void Client::on_update_file(object_ptr file) { // also includes all 5xx and 429 errors if (closing_ || logging_out_) { auto error = get_closing_error(); - return on_file_download(file_id, Status::Error(error.code, error.message)); + return on_file_download(file_id, td::Status::Error(error.code, error.message)); } - auto error = Status::Error(400, "Bad Request: wrong file_id or the file is temporarily unavailable"); + auto error = td::Status::Error(400, "Bad Request: wrong file_id or the file is temporarily unavailable"); return on_file_download(file_id, std::move(error)); } } @@ -5628,7 +5719,7 @@ void Client::on_update(object_ptr result) { case td_api::updateMessageSendFailed::ID: { auto update = move_object_as(result); on_message_send_failed(update->message_->chat_id_, update->old_message_id_, update->message_->id_, - Status::Error(update->error_code_, update->error_message_)); + td::Status::Error(update->error_code_, update->error_message_)); break; } case td_api::updateMessageContent::ID: { @@ -6055,8 +6146,8 @@ bool Client::to_bool(td::MutableSlice value) { return value == "true" || value == "yes" || value == "1"; } -td::Result> Client::get_keyboard_button(JsonValue &button) { - if (button.type() == JsonValue::Type::Object) { +td::Result> Client::get_keyboard_button(td::JsonValue &button) { + if (button.type() == td::JsonValue::Type::Object) { auto &object = button.get_object(); TRY_RESULT(text, get_json_object_string_field(object, "text", false)); @@ -6075,7 +6166,7 @@ td::Result> Client::get_keyboard_butt if (has_json_object_field(object, "request_poll")) { bool force_regular = false; bool force_quiz = false; - TRY_RESULT(request_poll, get_json_object_field(object, "request_poll", JsonValue::Type::Object, false)); + TRY_RESULT(request_poll, get_json_object_field(object, "request_poll", td::JsonValue::Type::Object, false)); auto &request_poll_object = request_poll.get_object(); if (has_json_object_field(request_poll_object, "type")) { TRY_RESULT(type, get_json_object_string_field(request_poll_object, "type")); @@ -6090,14 +6181,14 @@ td::Result> Client::get_keyboard_butt } if (has_json_object_field(object, "web_app")) { - TRY_RESULT(web_app, get_json_object_field(object, "web_app", JsonValue::Type::Object, false)); + TRY_RESULT(web_app, get_json_object_field(object, "web_app", td::JsonValue::Type::Object, false)); auto &web_app_object = web_app.get_object(); TRY_RESULT(url, get_json_object_string_field(web_app_object, "url", false)); return make_object(text, make_object(url)); } if (has_json_object_field(object, "request_user")) { - TRY_RESULT(request_user, get_json_object_field(object, "request_user", JsonValue::Type::Object, false)); + TRY_RESULT(request_user, get_json_object_field(object, "request_user", td::JsonValue::Type::Object, false)); auto &request_user_object = request_user.get_object(); TRY_RESULT(id, get_json_object_int_field(request_user_object, "request_id", false)); auto restrict_user_is_bot = has_json_object_field(request_user_object, "user_is_bot"); @@ -6110,7 +6201,7 @@ td::Result> Client::get_keyboard_butt } if (has_json_object_field(object, "request_chat")) { - TRY_RESULT(request_chat, get_json_object_field(object, "request_chat", JsonValue::Type::Object, false)); + TRY_RESULT(request_chat, get_json_object_field(object, "request_chat", td::JsonValue::Type::Object, false)); auto &request_chat_object = request_chat.get_object(); TRY_RESULT(id, get_json_object_int_field(request_chat_object, "request_id", false)); TRY_RESULT(chat_is_channel, get_json_object_bool_field(request_chat_object, "chat_is_channel")); @@ -6119,12 +6210,12 @@ td::Result> Client::get_keyboard_butt auto restrict_chat_has_username = has_json_object_field(request_chat_object, "chat_has_username"); TRY_RESULT(chat_has_username, get_json_object_bool_field(request_chat_object, "chat_has_username")); TRY_RESULT(chat_is_created, get_json_object_bool_field(request_chat_object, "chat_is_created")); - td_api::object_ptr user_administrator_rights; + object_ptr user_administrator_rights; if (has_json_object_field(request_chat_object, "user_administrator_rights")) { TRY_RESULT_ASSIGN(user_administrator_rights, get_chat_administrator_rights(get_json_object_field_force( request_chat_object, "user_administrator_rights"))); } - td_api::object_ptr bot_administrator_rights; + object_ptr bot_administrator_rights; if (has_json_object_field(request_chat_object, "bot_administrator_rights")) { TRY_RESULT_ASSIGN(bot_administrator_rights, get_chat_administrator_rights(get_json_object_field_force( request_chat_object, "bot_administrator_rights"))); @@ -6139,16 +6230,16 @@ td::Result> Client::get_keyboard_butt return make_object(text, nullptr); } - if (button.type() == JsonValue::Type::String) { + if (button.type() == td::JsonValue::Type::String) { return make_object(button.get_string().str(), nullptr); } - return Status::Error(400, "KeyboardButton must be a String or an Object"); + return td::Status::Error(400, "KeyboardButton must be a String or an Object"); } -td::Result> Client::get_inline_keyboard_button(JsonValue &button) { - if (button.type() != JsonValue::Type::Object) { - return Status::Error(400, "InlineKeyboardButton must be an Object"); +td::Result> Client::get_inline_keyboard_button(td::JsonValue &button) { + if (button.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "InlineKeyboardButton must be an Object"); } auto &object = button.get_object(); @@ -6190,8 +6281,8 @@ td::Result> Client::get_inline_ } if (has_json_object_field(object, "login_url")) { - TRY_RESULT(login_url, get_json_object_field(object, "login_url", JsonValue::Type::Object, false)); - CHECK(login_url.type() == JsonValue::Type::Object); + TRY_RESULT(login_url, get_json_object_field(object, "login_url", td::JsonValue::Type::Object, false)); + CHECK(login_url.type() == td::JsonValue::Type::Object); auto &login_url_object = login_url.get_object(); TRY_RESULT(url, get_json_object_string_field(login_url_object, "url", false)); TRY_RESULT(bot_username, get_json_object_string_field(login_url_object, "bot_username")); @@ -6206,15 +6297,15 @@ td::Result> Client::get_inline_ bot_username = bot_username.substr(1); } if (bot_username.empty()) { - return Status::Error(400, "LoginUrl bot username is invalid"); + return td::Status::Error(400, "LoginUrl bot username is invalid"); } for (auto c : bot_username) { if (c != '_' && !td::is_alnum(c)) { - return Status::Error(400, "LoginUrl bot username is invalid"); + return td::Status::Error(400, "LoginUrl bot username is invalid"); } } if (cur_temp_bot_user_id_ >= 100000) { - return Status::Error(400, "Too many different LoginUrl bot usernames"); + return td::Status::Error(400, "Too many different LoginUrl bot usernames"); } auto &user_id = bot_user_ids_[bot_username]; if (user_id == 0) { @@ -6234,13 +6325,13 @@ td::Result> Client::get_inline_ } if (has_json_object_field(object, "web_app")) { - TRY_RESULT(web_app, get_json_object_field(object, "web_app", JsonValue::Type::Object, false)); + TRY_RESULT(web_app, get_json_object_field(object, "web_app", td::JsonValue::Type::Object, false)); auto &web_app_object = web_app.get_object(); TRY_RESULT(url, get_json_object_string_field(web_app_object, "url", false)); return make_object(text, make_object(url)); } - return Status::Error(400, "Text buttons are unallowed in the inline keyboard"); + return td::Status::Error(400, "Text buttons are unallowed in the inline keyboard"); } td::Result> Client::get_reply_markup(const Query *query) { @@ -6253,16 +6344,16 @@ td::Result> Client::get_reply_markup(con auto r_value = json_decode(reply_markup); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse reply keyboard markup JSON object"); + return td::Status::Error(400, "Can't parse reply keyboard markup JSON object"); } return get_reply_markup(r_value.move_as_ok()); } -td::Result> Client::get_reply_markup(JsonValue &&value) { +td::Result> Client::get_reply_markup(td::JsonValue &&value) { td::vector>> rows; td::vector>> inline_rows; - Slice input_field_placeholder; + td::Slice input_field_placeholder; bool resize_keyboard = false; bool is_persistent = false; bool one_time = false; @@ -6270,24 +6361,24 @@ td::Result> Client::get_reply_markup(Jso bool is_personal = false; bool force_reply = false; - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "Object expected as reply markup"); + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "Object expected as reply markup"); } for (auto &field_value : value.get_object()) { if (field_value.first == "keyboard") { auto keyboard = std::move(field_value.second); - if (keyboard.type() != JsonValue::Type::Array) { - return Status::Error(400, "Field \"keyboard\" of the ReplyKeyboardMarkup must be an Array"); + if (keyboard.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Field \"keyboard\" of the ReplyKeyboardMarkup must be an Array"); } for (auto &row : keyboard.get_array()) { td::vector> new_row; - if (row.type() != JsonValue::Type::Array) { - return Status::Error(400, "Field \"keyboard\" of the ReplyKeyboardMarkup must be an Array of Arrays"); + if (row.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Field \"keyboard\" of the ReplyKeyboardMarkup must be an Array of Arrays"); } for (auto &button : row.get_array()) { auto r_button = get_keyboard_button(button); if (r_button.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse keyboard button: " << r_button.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse keyboard button: " << r_button.error().message()); } new_row.push_back(r_button.move_as_ok()); } @@ -6296,18 +6387,20 @@ td::Result> Client::get_reply_markup(Jso } } else if (field_value.first == "inline_keyboard") { auto inline_keyboard = std::move(field_value.second); - if (inline_keyboard.type() != JsonValue::Type::Array) { - return Status::Error(400, "Field \"inline_keyboard\" of the InlineKeyboardMarkup must be an Array"); + if (inline_keyboard.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Field \"inline_keyboard\" of the InlineKeyboardMarkup must be an Array"); } for (auto &inline_row : inline_keyboard.get_array()) { td::vector> new_inline_row; - if (inline_row.type() != JsonValue::Type::Array) { - return Status::Error(400, "Field \"inline_keyboard\" of the InlineKeyboardMarkup must be an Array of Arrays"); + if (inline_row.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, + "Field \"inline_keyboard\" of the InlineKeyboardMarkup must be an Array of Arrays"); } for (auto &button : inline_row.get_array()) { auto r_button = get_inline_keyboard_button(button); if (r_button.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse inline keyboard button: " << r_button.error().message()); + return td::Status::Error(400, PSLICE() + << "Can't parse inline keyboard button: " << r_button.error().message()); } new_inline_row.push_back(r_button.move_as_ok()); } @@ -6315,38 +6408,42 @@ td::Result> Client::get_reply_markup(Jso inline_rows.push_back(std::move(new_inline_row)); } } else if (field_value.first == "resize_keyboard") { - if (field_value.second.type() != JsonValue::Type::Boolean) { - return Status::Error(400, "Field \"resize_keyboard\" of the ReplyKeyboardMarkup must be of the type Boolean"); + if (field_value.second.type() != td::JsonValue::Type::Boolean) { + return td::Status::Error(400, + "Field \"resize_keyboard\" of the ReplyKeyboardMarkup must be of the type Boolean"); } resize_keyboard = field_value.second.get_boolean(); } else if (field_value.first == "is_persistent") { - if (field_value.second.type() != JsonValue::Type::Boolean) { - return Status::Error(400, "Field \"is_persistent\" of the ReplyKeyboardMarkup must be of the type Boolean"); + if (field_value.second.type() != td::JsonValue::Type::Boolean) { + return td::Status::Error(400, "Field \"is_persistent\" of the ReplyKeyboardMarkup must be of the type Boolean"); } is_persistent = field_value.second.get_boolean(); } else if (field_value.first == "one_time_keyboard") { - if (field_value.second.type() != JsonValue::Type::Boolean) { - return Status::Error(400, "Field \"one_time_keyboard\" of the ReplyKeyboardMarkup must be of the type Boolean"); + if (field_value.second.type() != td::JsonValue::Type::Boolean) { + return td::Status::Error(400, + "Field \"one_time_keyboard\" of the ReplyKeyboardMarkup must be of the type Boolean"); } one_time = field_value.second.get_boolean(); } else if (field_value.first == "hide_keyboard" || field_value.first == "remove_keyboard") { - if (field_value.second.type() != JsonValue::Type::Boolean) { - return Status::Error(400, "Field \"remove_keyboard\" of the ReplyKeyboardRemove must be of the type Boolean"); + if (field_value.second.type() != td::JsonValue::Type::Boolean) { + return td::Status::Error(400, + "Field \"remove_keyboard\" of the ReplyKeyboardRemove must be of the type Boolean"); } remove = field_value.second.get_boolean(); } else if (field_value.first == "personal_keyboard" || field_value.first == "selective") { - if (field_value.second.type() != JsonValue::Type::Boolean) { - return Status::Error(400, "Field \"selective\" of the reply markup must be of the type Boolean"); + if (field_value.second.type() != td::JsonValue::Type::Boolean) { + return td::Status::Error(400, "Field \"selective\" of the reply markup must be of the type Boolean"); } is_personal = field_value.second.get_boolean(); } else if (field_value.first == "force_reply_keyboard" || field_value.first == "force_reply") { - if (field_value.second.type() != JsonValue::Type::Boolean) { - return Status::Error(400, "Field \"force_reply\" of the reply markup must be of the type Boolean"); + if (field_value.second.type() != td::JsonValue::Type::Boolean) { + return td::Status::Error(400, "Field \"force_reply\" of the reply markup must be of the type Boolean"); } force_reply = field_value.second.get_boolean(); } else if (field_value.first == "input_field_placeholder") { - if (field_value.second.type() != JsonValue::Type::String) { - return Status::Error(400, "Field \"input_field_placeholder\" of the reply markup must be of the type String"); + if (field_value.second.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, + "Field \"input_field_placeholder\" of the reply markup must be of the type String"); } input_field_placeholder = field_value.second.get_string(); } @@ -6370,100 +6467,101 @@ td::Result> Client::get_reply_markup(Jso return std::move(result); } -td::Result> Client::get_labeled_price_part(JsonValue &value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "LabeledPrice must be an Object"); +td::Result> Client::get_labeled_price_part(td::JsonValue &value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "LabeledPrice must be an Object"); } auto &object = value.get_object(); TRY_RESULT(label, get_json_object_string_field(object, "label", false)); if (label.empty()) { - return Status::Error(400, "LabeledPrice label must be non-empty"); + return td::Status::Error(400, "LabeledPrice label must be non-empty"); } - TRY_RESULT(amount, get_json_object_field(object, "amount", JsonValue::Type::Null, false)); - Slice number; - if (amount.type() == JsonValue::Type::Number) { + TRY_RESULT(amount, get_json_object_field(object, "amount", td::JsonValue::Type::Null, false)); + td::Slice number; + if (amount.type() == td::JsonValue::Type::Number) { number = amount.get_number(); - } else if (amount.type() == JsonValue::Type::String) { + } else if (amount.type() == td::JsonValue::Type::String) { number = amount.get_string(); } else { - return Status::Error(400, "Field \"amount\" must be of type Number or String"); + return td::Status::Error(400, "Field \"amount\" must be of type Number or String"); } auto parsed_amount = td::to_integer_safe(number); if (parsed_amount.is_error()) { - return Status::Error(400, "Can't parse \"amount\" as Number"); + return td::Status::Error(400, "Can't parse \"amount\" as Number"); } return make_object(label, parsed_amount.ok()); } -td::Result>> Client::get_labeled_price_parts(JsonValue &value) { - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of labeled prices"); +td::Result>> Client::get_labeled_price_parts( + td::JsonValue &value) { + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of labeled prices"); } td::vector> prices; for (auto &price : value.get_array()) { auto r_labeled_price = get_labeled_price_part(price); if (r_labeled_price.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse labeled price: " << r_labeled_price.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse labeled price: " << r_labeled_price.error().message()); } prices.push_back(r_labeled_price.move_as_ok()); } if (prices.empty()) { - return Status::Error(400, "There must be at least one price"); + return td::Status::Error(400, "There must be at least one price"); } return std::move(prices); } -td::Result> Client::get_suggested_tip_amounts(JsonValue &value) { - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of suggested tip amounts"); +td::Result> Client::get_suggested_tip_amounts(td::JsonValue &value) { + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of suggested tip amounts"); } td::vector suggested_tip_amounts; for (auto &amount : value.get_array()) { - Slice number; - if (amount.type() == JsonValue::Type::Number) { + td::Slice number; + if (amount.type() == td::JsonValue::Type::Number) { number = amount.get_number(); - } else if (amount.type() == JsonValue::Type::String) { + } else if (amount.type() == td::JsonValue::Type::String) { number = amount.get_string(); } else { - return Status::Error(400, "Suggested tip amount must be of type Number or String"); + return td::Status::Error(400, "Suggested tip amount must be of type Number or String"); } auto parsed_amount = td::to_integer_safe(number); if (parsed_amount.is_error()) { - return Status::Error(400, "Can't parse suggested tip amount as Number"); + return td::Status::Error(400, "Can't parse suggested tip amount as Number"); } suggested_tip_amounts.push_back(parsed_amount.ok()); } return std::move(suggested_tip_amounts); } -td::Result> Client::get_shipping_option(JsonValue &option) { - if (option.type() != JsonValue::Type::Object) { - return Status::Error(400, "ShippingOption must be an Object"); +td::Result> Client::get_shipping_option(td::JsonValue &option) { + if (option.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "ShippingOption must be an Object"); } auto &object = option.get_object(); TRY_RESULT(id, get_json_object_string_field(object, "id", false)); if (id.empty()) { - return Status::Error(400, "ShippingOption identifier must be non-empty"); + return td::Status::Error(400, "ShippingOption identifier must be non-empty"); } TRY_RESULT(title, get_json_object_string_field(object, "title", false)); if (title.empty()) { - return Status::Error(400, "ShippingOption title must be non-empty"); + return td::Status::Error(400, "ShippingOption title must be non-empty"); } - TRY_RESULT(prices_json, get_json_object_field(object, "prices", JsonValue::Type::Array, false)); + TRY_RESULT(prices_json, get_json_object_field(object, "prices", td::JsonValue::Type::Array, false)); auto r_prices = get_labeled_price_parts(prices_json); if (r_prices.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse shipping option prices: " << r_prices.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse shipping option prices: " << r_prices.error().message()); } return make_object(id, title, r_prices.move_as_ok()); @@ -6476,27 +6574,27 @@ td::Result>> Client::get_s auto r_value = json_decode(shipping_options); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse shipping options JSON object"); + return td::Status::Error(400, "Can't parse shipping options JSON object"); } return get_shipping_options(r_value.move_as_ok()); } -td::Result>> Client::get_shipping_options(JsonValue &&value) { - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of shipping options"); +td::Result>> Client::get_shipping_options(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of shipping options"); } td::vector> options; for (auto &option : value.get_array()) { auto r_shipping_option = get_shipping_option(option); if (r_shipping_option.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse shipping option: " << r_shipping_option.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse shipping option: " << r_shipping_option.error().message()); } options.push_back(r_shipping_option.move_as_ok()); } if (options.empty()) { - return Status::Error(400, "There must be at least one shipping option"); + return td::Status::Error(400, "There must be at least one shipping option"); } return std::move(options); @@ -6544,12 +6642,12 @@ td_api::object_ptr Client::get_chat_action(const Query *quer return nullptr; } -td_api::object_ptr Client::get_input_file(const Query *query, Slice field_name, +td_api::object_ptr Client::get_input_file(const Query *query, td::Slice field_name, bool force_file) const { return get_input_file(query, field_name, query->arg(field_name), force_file); } -td::string Client::get_local_file_path(Slice file_uri) { +td::string Client::get_local_file_path(td::Slice file_uri) { if (td::begins_with(file_uri, "/")) { file_uri.remove_prefix(td::begins_with(file_uri, "/localhost") ? 10 : 1); } @@ -6564,16 +6662,16 @@ td::string Client::get_local_file_path(Slice file_uri) { return result; } -td_api::object_ptr Client::get_input_file(const Query *query, Slice field_name, Slice file_id, - bool force_file) const { +td_api::object_ptr Client::get_input_file(const Query *query, td::Slice field_name, + td::Slice file_id, bool force_file) const { if (!file_id.empty()) { if (parameters_->local_mode_) { - Slice file_protocol{"file:/"}; + td::Slice file_protocol{"file:/"}; if (td::begins_with(file_id, file_protocol)) { return make_object(get_local_file_path(file_id.substr(file_protocol.size()))); } } - Slice attach_protocol{"attach://"}; + td::Slice attach_protocol{"attach://"}; if (td::begins_with(file_id, attach_protocol)) { field_name = file_id.substr(attach_protocol.size()); } else { @@ -6590,17 +6688,20 @@ td_api::object_ptr Client::get_input_file(const Query *query, return nullptr; } -td_api::object_ptr Client::get_input_thumbnail(const Query *query, Slice field_name) const { - auto input_file = get_input_file(query, field_name, true); +td_api::object_ptr Client::get_input_thumbnail(const Query *query) const { + auto input_file = get_input_file(query, "thumbnail", true); if (input_file == nullptr) { - return nullptr; + input_file = get_input_file(query, "thumb", true); + if (input_file == nullptr) { + return nullptr; + } } return make_object(std::move(input_file), 0, 0); } td::Result> Client::get_input_message_content( - JsonValue &input_message_content, bool is_input_message_content_required) { - CHECK(input_message_content.type() == JsonValue::Type::Object); + td::JsonValue &input_message_content, bool is_input_message_content_required) { + CHECK(input_message_content.type() == td::JsonValue::Type::Object); auto &object = input_message_content.get_object(); TRY_RESULT(message_text, get_json_object_string_field(object, "message_text")); @@ -6667,18 +6768,18 @@ td::Result> Client::get_input_me TRY_RESULT(description, get_json_object_string_field(object, "description", false)); TRY_RESULT(payload, get_json_object_string_field(object, "payload", false)); if (!td::check_utf8(payload)) { - return Status::Error(400, "InputInvoiceMessageContent payload must be encoded in UTF-8"); + return td::Status::Error(400, "InputInvoiceMessageContent payload must be encoded in UTF-8"); } TRY_RESULT(provider_token, get_json_object_string_field(object, "provider_token", false)); TRY_RESULT(currency, get_json_object_string_field(object, "currency", false)); - TRY_RESULT(prices_object, get_json_object_field(object, "prices", JsonValue::Type::Array, false)); + TRY_RESULT(prices_object, get_json_object_field(object, "prices", td::JsonValue::Type::Array, false)); TRY_RESULT(prices, get_labeled_price_parts(prices_object)); TRY_RESULT(provider_data, get_json_object_string_field(object, "provider_data")); TRY_RESULT(max_tip_amount, get_json_object_long_field(object, "max_tip_amount")); td::vector suggested_tip_amounts; TRY_RESULT(suggested_tip_amounts_array, - get_json_object_field(object, "suggested_tip_amounts", JsonValue::Type::Array)); - if (suggested_tip_amounts_array.type() == JsonValue::Type::Array) { + get_json_object_field(object, "suggested_tip_amounts", td::JsonValue::Type::Array)); + if (suggested_tip_amounts_array.type() == td::JsonValue::Type::Array) { TRY_RESULT_ASSIGN(suggested_tip_amounts, get_suggested_tip_amounts(suggested_tip_amounts_array)); } TRY_RESULT(photo_url, get_json_object_string_field(object, "photo_url")); @@ -6703,7 +6804,7 @@ td::Result> Client::get_input_me } if (is_input_message_content_required) { - return Status::Error(400, "Input message content is not specified"); + return td::Status::Error(400, "Input message content is not specified"); } return nullptr; } @@ -6711,7 +6812,55 @@ td::Result> Client::get_input_me td_api::object_ptr Client::get_message_send_options(bool disable_notification, bool protect_content, td_api::object_ptr &&scheduling_state) { - return make_object(disable_notification, false, protect_content, false, std::move(scheduling_state)); + return make_object(disable_notification, false, protect_content, false, std::move(scheduling_state), 0); +} + +td::Result> Client::get_inline_query_results_button( + td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "InlineQueryResultsButton must be an Object"); + } + + auto &object = value.get_object(); + + TRY_RESULT(text, get_json_object_string_field(object, "text", false)); + + if (has_json_object_field(object, "start_parameter")) { + TRY_RESULT(start_parameter, get_json_object_string_field(object, "start_parameter", false)); + return make_object( + text, make_object(start_parameter)); + } + + if (has_json_object_field(object, "web_app")) { + TRY_RESULT(web_app, get_json_object_field(object, "web_app", td::JsonValue::Type::Object, false)); + auto &web_app_object = web_app.get_object(); + TRY_RESULT(url, get_json_object_string_field(web_app_object, "url", false)); + return make_object(text, + make_object(url)); + } + + return td::Status::Error(400, "InlineQueryResultsButton must have exactly one optional field"); +} + +td::Result> Client::get_inline_query_results_button( + td::MutableSlice button) { + if (button.empty()) { + return nullptr; + } + + LOG(INFO) << "Parsing JSON object: " << button; + auto r_value = json_decode(button); + if (r_value.is_error()) { + LOG(INFO) << "Can't parse JSON object: " << r_value.error(); + return td::Status::Error(400, "Can't parse inline query results button JSON object"); + } + + auto r_button = get_inline_query_results_button(r_value.move_as_ok()); + if (r_button.is_error()) { + return td::Status::Error(400, PSLICE() + << "Can't parse inline query results button: " << r_button.error().message()); + } + return r_button.move_as_ok(); } td::Result>> Client::get_inline_query_results( @@ -6724,8 +6873,8 @@ td::Result>> Clien LOG(INFO) << "Parsing JSON object: " << results_encoded; auto r_values = json_decode(results_encoded); if (r_values.is_error()) { - return Status::Error(400, - PSLICE() << "Can't parse JSON encoded inline query results: " << r_values.error().message()); + return td::Status::Error( + 400, PSLICE() << "Can't parse JSON encoded inline query results: " << r_values.error().message()); } return get_inline_query_results(r_values.move_as_ok()); @@ -6733,19 +6882,19 @@ td::Result>> Clien td::Result>> Client::get_inline_query_results( td::JsonValue &&values) { - if (values.type() == JsonValue::Type::Null) { + if (values.type() == td::JsonValue::Type::Null) { return td::vector>(); } - if (values.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of inline query results"); + if (values.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of inline query results"); } td::vector> inline_query_results; for (auto &value : values.get_array()) { auto r_inline_query_result = get_inline_query_result(std::move(value)); if (r_inline_query_result.is_error()) { - return Status::Error(400, - PSLICE() << "Can't parse inline query result: " << r_inline_query_result.error().message()); + return td::Status::Error( + 400, PSLICE() << "Can't parse inline query result: " << r_inline_query_result.error().message()); } inline_query_results.push_back(r_inline_query_result.move_as_ok()); } @@ -6756,22 +6905,22 @@ td::Result>> Clien td::Result> Client::get_inline_query_result(const Query *query) { auto result_encoded = query->arg("result"); if (result_encoded.empty()) { - return Status::Error(400, "Result isn't specified"); + return td::Status::Error(400, "Result isn't specified"); } LOG(INFO) << "Parsing JSON object: " << result_encoded; auto r_value = json_decode(result_encoded); if (r_value.is_error()) { - return Status::Error(400, - PSLICE() << "Can't parse JSON encoded web view query results " << r_value.error().message()); + return td::Status::Error( + 400, PSLICE() << "Can't parse JSON encoded web view query results " << r_value.error().message()); } return get_inline_query_result(r_value.move_as_ok()); } td::Result> Client::get_inline_query_result(td::JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "Inline query result must be an object"); + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "Inline query result must be an object"); } auto &object = value.get_object(); @@ -6785,8 +6934,8 @@ td::Result> Client::get_inlin object_ptr input_message_content; TRY_RESULT(input_message_content_obj, - get_json_object_field(object, "input_message_content", JsonValue::Type::Object)); - if (input_message_content_obj.type() == JsonValue::Type::Null) { + get_json_object_field(object, "input_message_content", td::JsonValue::Type::Object)); + if (input_message_content_obj.type() == td::JsonValue::Type::Null) { TRY_RESULT(message_text, get_json_object_string_field(object, "message_text", !is_input_message_content_required)); TRY_RESULT(disable_web_page_preview, get_json_object_bool_field(object, "disable_web_page_preview")); TRY_RESULT(parse_mode, get_json_object_string_field(object, "parse_mode")); @@ -6807,21 +6956,32 @@ td::Result> Client::get_inlin auto entities = get_json_object_field_force(object, "caption_entities"); TRY_RESULT(caption, get_formatted_text(std::move(input_caption), std::move(parse_mode), std::move(entities))); - TRY_RESULT(reply_markup_object, get_json_object_field(object, "reply_markup", JsonValue::Type::Object)); + TRY_RESULT(reply_markup_object, get_json_object_field(object, "reply_markup", td::JsonValue::Type::Object)); object_ptr reply_markup; - if (reply_markup_object.type() != JsonValue::Type::Null) { + if (reply_markup_object.type() != td::JsonValue::Type::Null) { TRY_RESULT_ASSIGN(reply_markup, get_reply_markup(std::move(reply_markup_object))); } + auto thumbnail_url_field_name = td::Slice("thumbnail_url"); + auto thumbnail_width_field_name = td::Slice("thumbnail_width"); + auto thumbnail_height_field_name = td::Slice("thumbnail_height"); + if (!has_json_object_field(object, thumbnail_url_field_name) && + !has_json_object_field(object, thumbnail_width_field_name) && + !has_json_object_field(object, thumbnail_height_field_name)) { + thumbnail_url_field_name = td::Slice("thumb_url"); + thumbnail_width_field_name = td::Slice("thumb_width"); + thumbnail_height_field_name = td::Slice("thumb_height"); + } + TRY_RESULT(thumbnail_url, get_json_object_string_field(object, thumbnail_url_field_name)); + TRY_RESULT(thumbnail_width, get_json_object_int_field(object, thumbnail_width_field_name)); + TRY_RESULT(thumbnail_height, get_json_object_int_field(object, thumbnail_height_field_name)); + object_ptr result; if (type == "article") { TRY_RESULT(url, get_json_object_string_field(object, "url")); TRY_RESULT(hide_url, get_json_object_bool_field(object, "hide_url")); TRY_RESULT(title, get_json_object_string_field(object, "title", false)); TRY_RESULT(description, get_json_object_string_field(object, "description")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url")); - TRY_RESULT(thumbnail_width, get_json_object_int_field(object, "thumb_width")); - TRY_RESULT(thumbnail_height, get_json_object_int_field(object, "thumb_height")); CHECK(input_message_content != nullptr); return make_object( @@ -6849,9 +7009,6 @@ td::Result> Client::get_inlin TRY_RESULT(first_name, get_json_object_string_field(object, "first_name", false)); TRY_RESULT(last_name, get_json_object_string_field(object, "last_name")); TRY_RESULT(vcard, get_json_object_string_field(object, "vcard")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url")); - TRY_RESULT(thumbnail_width, get_json_object_int_field(object, "thumb_width")); - TRY_RESULT(thumbnail_height, get_json_object_int_field(object, "thumb_height")); if (input_message_content == nullptr) { input_message_content = make_object( @@ -6864,11 +7021,8 @@ td::Result> Client::get_inlin if (type == "document") { TRY_RESULT(title, get_json_object_string_field(object, "title", false)); TRY_RESULT(description, get_json_object_string_field(object, "description")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url")); TRY_RESULT(document_url, get_json_object_string_field(object, "document_url")); TRY_RESULT(mime_type, get_json_object_string_field(object, "mime_type", document_url.empty())); - TRY_RESULT(thumbnail_width, get_json_object_int_field(object, "thumb_width")); - TRY_RESULT(thumbnail_height, get_json_object_int_field(object, "thumb_height")); if (document_url.empty()) { TRY_RESULT_ASSIGN(document_url, get_json_object_string_field(object, "document_file_id", false)); } @@ -6887,8 +7041,11 @@ td::Result> Client::get_inlin if (type == "gif") { TRY_RESULT(title, get_json_object_string_field(object, "title")); TRY_RESULT(gif_url, get_json_object_string_field(object, "gif_url")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url", gif_url.empty())); - TRY_RESULT(thumbnail_mime_type, get_json_object_string_field(object, "thumb_mime_type", true)); + auto thumbnail_mime_type_field_name = td::Slice("thumbnail_mime_type"); + if (!has_json_object_field(object, thumbnail_mime_type_field_name)) { + thumbnail_mime_type_field_name = td::Slice("thumb_mime_type"); + } + TRY_RESULT(thumbnail_mime_type, get_json_object_string_field(object, thumbnail_mime_type_field_name)); TRY_RESULT(gif_duration, get_json_object_int_field(object, "gif_duration")); TRY_RESULT(gif_width, get_json_object_int_field(object, "gif_width")); TRY_RESULT(gif_height, get_json_object_int_field(object, "gif_height")); @@ -6912,9 +7069,6 @@ td::Result> Client::get_inlin TRY_RESULT(heading, get_json_object_int_field(object, "heading")); TRY_RESULT(proximity_alert_radius, get_json_object_int_field(object, "proximity_alert_radius")); TRY_RESULT(title, get_json_object_string_field(object, "title", false)); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url")); - TRY_RESULT(thumbnail_width, get_json_object_int_field(object, "thumb_width")); - TRY_RESULT(thumbnail_height, get_json_object_int_field(object, "thumb_height")); if (input_message_content == nullptr) { auto location = make_object(latitude, longitude, horizontal_accuracy); @@ -6928,8 +7082,11 @@ td::Result> Client::get_inlin if (type == "mpeg4_gif") { TRY_RESULT(title, get_json_object_string_field(object, "title")); TRY_RESULT(mpeg4_url, get_json_object_string_field(object, "mpeg4_url")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url", mpeg4_url.empty())); - TRY_RESULT(thumbnail_mime_type, get_json_object_string_field(object, "thumb_mime_type", true)); + auto thumbnail_mime_type_field_name = td::Slice("thumbnail_mime_type"); + if (!has_json_object_field(object, thumbnail_mime_type_field_name)) { + thumbnail_mime_type_field_name = td::Slice("thumb_mime_type"); + } + TRY_RESULT(thumbnail_mime_type, get_json_object_string_field(object, thumbnail_mime_type_field_name)); TRY_RESULT(mpeg4_duration, get_json_object_int_field(object, "mpeg4_duration")); TRY_RESULT(mpeg4_width, get_json_object_int_field(object, "mpeg4_width")); TRY_RESULT(mpeg4_height, get_json_object_int_field(object, "mpeg4_height")); @@ -6949,7 +7106,6 @@ td::Result> Client::get_inlin TRY_RESULT(title, get_json_object_string_field(object, "title")); TRY_RESULT(description, get_json_object_string_field(object, "description")); TRY_RESULT(photo_url, get_json_object_string_field(object, "photo_url")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url", photo_url.empty())); TRY_RESULT(photo_width, get_json_object_int_field(object, "photo_width")); TRY_RESULT(photo_height, get_json_object_int_field(object, "photo_height")); if (photo_url.empty()) { @@ -6983,9 +7139,6 @@ td::Result> Client::get_inlin TRY_RESULT(foursquare_type, get_json_object_string_field(object, "foursquare_type")); TRY_RESULT(google_place_id, get_json_object_string_field(object, "google_place_id")); TRY_RESULT(google_place_type, get_json_object_string_field(object, "google_place_type")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url")); - TRY_RESULT(thumbnail_width, get_json_object_int_field(object, "thumb_width")); - TRY_RESULT(thumbnail_height, get_json_object_int_field(object, "thumb_height")); td::string provider; td::string venue_id; @@ -7016,7 +7169,6 @@ td::Result> Client::get_inlin TRY_RESULT(title, get_json_object_string_field(object, "title", false)); TRY_RESULT(description, get_json_object_string_field(object, "description")); TRY_RESULT(video_url, get_json_object_string_field(object, "video_url")); - TRY_RESULT(thumbnail_url, get_json_object_string_field(object, "thumb_url", video_url.empty())); TRY_RESULT(mime_type, get_json_object_string_field(object, "mime_type", video_url.empty())); TRY_RESULT(video_width, get_json_object_int_field(object, "video_width")); TRY_RESULT(video_height, get_json_object_int_field(object, "video_height")); @@ -7050,12 +7202,12 @@ td::Result> Client::get_inlin id, title, voice_note_url, voice_note_duration, std::move(reply_markup), std::move(input_message_content)); } - return Status::Error(400, PSLICE() << "type \"" << type << "\" is unsupported for the inline query result"); + return td::Status::Error(400, PSLICE() << "type \"" << type << "\" is unsupported for the inline query result"); } -td::Result Client::get_bot_command_scope(JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "BotCommandScope must be an Object"); +td::Result Client::get_bot_command_scope(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "BotCommandScope must be an Object"); } auto &object = value.get_object(); @@ -7074,12 +7226,12 @@ td::Result Client::get_bot_command_scope(JsonValue &&va return BotCommandScope(make_object()); } if (type != "chat" && type != "chat_administrators" && type != "chat_member") { - return Status::Error(400, "Unsupported type specified"); + return td::Status::Error(400, "Unsupported type specified"); } TRY_RESULT(chat_id, get_json_object_string_field(object, "chat_id", false)); if (chat_id.empty()) { - return Status::Error(400, "Empty chat_id specified"); + return td::Status::Error(400, "Empty chat_id specified"); } if (type == "chat") { return BotCommandScope(make_object(0), std::move(chat_id)); @@ -7090,7 +7242,7 @@ td::Result Client::get_bot_command_scope(JsonValue &&va TRY_RESULT(user_id, get_json_object_long_field(object, "user_id", false)); if (user_id <= 0) { - return Status::Error(400, "Invalid user_id specified"); + return td::Status::Error(400, "Invalid user_id specified"); } CHECK(type == "chat_member"); return BotCommandScope(make_object(0, user_id), std::move(chat_id), user_id); @@ -7106,19 +7258,19 @@ td::Result Client::get_bot_command_scope(const Query *q auto r_value = json_decode(scope); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse BotCommandScope JSON object"); + return td::Status::Error(400, "Can't parse BotCommandScope JSON object"); } auto r_scope = get_bot_command_scope(r_value.move_as_ok()); if (r_scope.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse BotCommandScope: " << r_scope.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse BotCommandScope: " << r_scope.error().message()); } return r_scope.move_as_ok(); } -td::Result> Client::get_bot_command(JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "expected an Object"); +td::Result> Client::get_bot_command(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "expected an Object"); } auto &object = value.get_object(); @@ -7138,74 +7290,74 @@ td::Result>> Client::get_bot_c auto r_value = json_decode(commands); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse commands JSON object"); + return td::Status::Error(400, "Can't parse commands JSON object"); } auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of BotCommand"); + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of BotCommand"); } td::vector> bot_commands; for (auto &command : value.get_array()) { auto r_bot_command = get_bot_command(std::move(command)); if (r_bot_command.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse BotCommand: " << r_bot_command.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse BotCommand: " << r_bot_command.error().message()); } bot_commands.push_back(r_bot_command.move_as_ok()); } return std::move(bot_commands); } -td::Result> Client::get_bot_menu_button(JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "MenuButton must be an Object"); +td::Result> Client::get_bot_menu_button(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "MenuButton must be an Object"); } auto &object = value.get_object(); TRY_RESULT(type, get_json_object_string_field(object, "type", false)); if (type == "default") { - return td_api::make_object("", "default"); + return make_object("", "default"); } if (type == "commands") { return nullptr; } if (type == "web_app") { TRY_RESULT(text, get_json_object_string_field(object, "text", false)); - TRY_RESULT(web_app, get_json_object_field(object, "web_app", JsonValue::Type::Object, false)); + TRY_RESULT(web_app, get_json_object_field(object, "web_app", td::JsonValue::Type::Object, false)); auto &web_app_object = web_app.get_object(); TRY_RESULT(url, get_json_object_string_field(web_app_object, "url", false)); - return td_api::make_object(text, url); + return make_object(text, url); } - return Status::Error(400, "MenuButton has unsupported type"); + return td::Status::Error(400, "MenuButton has unsupported type"); } td::Result> Client::get_bot_menu_button(const Query *query) { auto menu_button = query->arg("menu_button"); if (menu_button.empty()) { - return td_api::make_object("", "default"); + return make_object("", "default"); } LOG(INFO) << "Parsing JSON object: " << menu_button; auto r_value = json_decode(menu_button); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse menu button JSON object"); + return td::Status::Error(400, "Can't parse menu button JSON object"); } auto r_menu_button = get_bot_menu_button(r_value.move_as_ok()); if (r_menu_button.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse menu button: " << r_menu_button.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse menu button: " << r_menu_button.error().message()); } return r_menu_button.move_as_ok(); } td::Result> Client::get_chat_administrator_rights( - JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "ChatAdministratorRights must be an Object"); + td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "ChatAdministratorRights must be an Object"); } auto &object = value.get_object(); @@ -7238,19 +7390,22 @@ td::Result> Client::get_chat auto r_value = json_decode(rights); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse ChatAdministratorRights JSON object"); + return td::Status::Error(400, "Can't parse ChatAdministratorRights JSON object"); } auto r_rights = get_chat_administrator_rights(r_value.move_as_ok()); if (r_rights.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse ChatAdministratorRights: " << r_rights.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse ChatAdministratorRights: " << r_rights.error().message()); } return r_rights.move_as_ok(); } -td::Result> Client::get_mask_position(JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "MaskPosition must be an Object"); +td::Result> Client::get_mask_position(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + if (value.type() == td::JsonValue::Type::Null) { + return nullptr; + } + return td::Status::Error(400, "MaskPosition must be an Object"); } auto &object = value.get_object(); @@ -7264,7 +7419,7 @@ td::Result> Client::get_mask_position(J } } if (point == MASK_POINTS_SIZE) { - return Status::Error(400, "Wrong point specified in MaskPosition"); + return td::Status::Error(400, "Wrong point specified in MaskPosition"); } TRY_RESULT(x_shift, get_json_object_double_field(object, "x_shift", false)); @@ -7307,7 +7462,8 @@ td_api::object_ptr Client::mask_index_to_point(int32 index) { } } -td::Result> Client::get_mask_position(const Query *query, Slice field_name) { +td::Result> Client::get_mask_position(const Query *query, + td::Slice field_name) { auto mask_position = query->arg(field_name); if (mask_position.empty()) { return nullptr; @@ -7317,21 +7473,178 @@ td::Result> Client::get_mask_position(c auto r_value = json_decode(mask_position); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse mask position JSON object"); + return td::Status::Error(400, "Can't parse mask position JSON object"); } auto r_mask_position = get_mask_position(r_value.move_as_ok()); if (r_mask_position.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse mask position: " << r_mask_position.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse mask position: " << r_mask_position.error().message()); } return r_mask_position.move_as_ok(); } -td::Result>> Client::get_input_stickers(const Query *query) const { +td::Result Client::get_sticker_emojis(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "expected an Array of string"); + } + + td::string result; + auto emoji_count = value.get_array().size(); + if (emoji_count == 0) { + return td::Status::Error(400, "emoji list must be non-empty"); + } + if (emoji_count > MAX_STICKER_EMOJI_COUNT) { + return td::Status::Error(400, "too many emoji specified"); + } + for (auto &emoji : value.get_array()) { + if (emoji.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, "emoji must be a string"); + } + if (!td::is_emoji(emoji.get_string())) { + return td::Status::Error(400, "expected a Unicode emoji"); + } + result += emoji.get_string().str(); + } + return std::move(result); +} + +td::Result Client::get_sticker_emojis(td::MutableSlice emoji_list) { + LOG(INFO) << "Parsing JSON object: " << emoji_list; + auto r_value = json_decode(emoji_list); + if (r_value.is_error()) { + LOG(INFO) << "Can't parse JSON object: " << r_value.error(); + return td::Status::Error(400, "Can't parse emoji list JSON array"); + } + + auto r_emojis = get_sticker_emojis(r_value.move_as_ok()); + if (r_emojis.is_error()) { + return td::Status::Error(400, PSLICE() << "Can't parse emoji list: " << r_emojis.error().message()); + } + return r_emojis.move_as_ok(); +} + +td::Result> Client::get_sticker_format(td::Slice sticker_format) { + if (sticker_format == "static") { + return make_object(); + } + if (sticker_format == "animated") { + return make_object(); + } + if (sticker_format == "video") { + return make_object(); + } + return td::Status::Error(400, "Invalid sticker format specified"); +} + +td::Result> Client::get_input_sticker(const Query *query, + td::JsonValue &&value) const { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "InputSticker must be an Object"); + } + + auto &object = value.get_object(); + + TRY_RESULT(sticker, get_json_object_string_field(object, "sticker")); + auto input_file = get_input_file(query, td::Slice(), sticker, false); + if (input_file == nullptr) { + return td::Status::Error(400, "sticker not found"); + } + TRY_RESULT(emoji_list, get_json_object_field(object, "emoji_list", td::JsonValue::Type::Array, false)); + TRY_RESULT(emojis, get_sticker_emojis(std::move(emoji_list))); + TRY_RESULT(mask_position, get_mask_position(get_json_object_field_force(object, "mask_position"))); + td::vector input_keywords; + if (has_json_object_field(object, "keywords")) { + TRY_RESULT(keywords, get_json_object_field(object, "keywords", td::JsonValue::Type::Array, false)); + for (auto &keyword : keywords.get_array()) { + if (keyword.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, "keyword must be a string"); + } + input_keywords.push_back(keyword.get_string().str()); + } + } + return make_object(std::move(input_file), emojis, std::move(mask_position), + std::move(input_keywords)); +} + +td::Result> Client::get_input_sticker(const Query *query) const { + if (query->has_arg("sticker") || query->file("sticker") != nullptr) { + auto sticker = query->arg("sticker"); + LOG(INFO) << "Parsing JSON object: " << sticker; + auto r_value = json_decode(sticker); + if (r_value.is_error()) { + LOG(INFO) << "Can't parse JSON object: " << r_value.error(); + return td::Status::Error(400, "Can't parse sticker JSON object"); + } + + auto r_sticker = get_input_sticker(query, r_value.move_as_ok()); + if (r_sticker.is_error()) { + return td::Status::Error(400, PSLICE() << "Can't parse sticker: " << r_sticker.error().message()); + } + return r_sticker.move_as_ok(); + } + + auto emojis = query->arg("emojis"); + + auto sticker = get_input_file(query, "png_sticker"); + object_ptr mask_position; + if (sticker != nullptr) { + TRY_RESULT_ASSIGN(mask_position, get_mask_position(query, "mask_position")); + } else { + sticker = get_input_file(query, "tgs_sticker", true); + if (sticker == nullptr) { + sticker = get_input_file(query, "webm_sticker", true); + if (sticker == nullptr) { + if (!query->arg("tgs_sticker").empty()) { + return td::Status::Error(400, "Bad Request: animated sticker must be uploaded as an InputFile"); + } + if (!query->arg("webm_sticker").empty()) { + return td::Status::Error(400, "Bad Request: video sticker must be uploaded as an InputFile"); + } + return td::Status::Error(400, "Bad Request: there is no sticker file in the request"); + } + } + } + + return make_object(std::move(sticker), emojis.str(), std::move(mask_position), + td::vector()); +} + +td::Result>> Client::get_input_stickers( + const Query *query, object_ptr &sticker_format) const { + if (query->has_arg("stickers")) { + TRY_RESULT_ASSIGN(sticker_format, get_sticker_format(query->arg("sticker_format"))); + auto stickers = query->arg("stickers"); + LOG(INFO) << "Parsing JSON object: " << stickers; + auto r_value = json_decode(stickers); + if (r_value.is_error()) { + LOG(INFO) << "Can't parse JSON object: " << r_value.error(); + return td::Status::Error(400, "Can't parse stickers JSON object"); + } + auto value = r_value.move_as_ok(); + + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of InputSticker"); + } + + constexpr std::size_t MAX_STICKER_COUNT = 50; + if (value.get_array().size() > MAX_STICKER_COUNT) { + return td::Status::Error(400, "Too many stickers specified"); + } + + td::vector> input_stickers; + for (auto &input_sticker : value.get_array()) { + auto r_input_sticker = get_input_sticker(query, std::move(input_sticker)); + if (r_input_sticker.is_error()) { + return td::Status::Error(400, PSLICE() << "Can't parse InputSticker: " << r_input_sticker.error().message()); + } + input_stickers.push_back(r_input_sticker.move_as_ok()); + } + return std::move(input_stickers); + } + auto emojis = query->arg("emojis"); auto sticker = get_input_file(query, "png_sticker"); - object_ptr sticker_format; object_ptr mask_position; if (sticker != nullptr) { sticker_format = make_object(); @@ -7346,25 +7659,33 @@ td::Result>> Client::get_inp sticker_format = make_object(); } else { if (!query->arg("tgs_sticker").empty()) { - return Status::Error(400, "Bad Request: animated sticker must be uploaded as an InputFile"); + return td::Status::Error(400, "Bad Request: animated sticker must be uploaded as an InputFile"); } if (!query->arg("webm_sticker").empty()) { - return Status::Error(400, "Bad Request: video sticker must be uploaded as an InputFile"); + return td::Status::Error(400, "Bad Request: video sticker must be uploaded as an InputFile"); } - return Status::Error(400, "Bad Request: there is no sticker file in the request"); + return td::Status::Error(400, "Bad Request: there is no sticker file in the request"); } } } td::vector> stickers; - stickers.push_back(make_object(std::move(sticker), emojis.str(), std::move(sticker_format), - std::move(mask_position))); + stickers.push_back(make_object(std::move(sticker), emojis.str(), std::move(mask_position), + td::vector())); return std::move(stickers); } -td::Result Client::get_passport_element_hash(Slice encoded_hash) { +td::Result> Client::get_sticker_input_file(const Query *query) { + auto file_id = trim(query->arg("sticker")); + if (file_id.empty()) { + return td::Status::Error(400, "Sticker is not specified"); + } + return make_object(file_id.str()); +} + +td::Result Client::get_passport_element_hash(td::Slice encoded_hash) { if (!td::is_base64(encoded_hash)) { - return Status::Error(400, "hash isn't a valid base64-encoded string"); + return td::Status::Error(400, "hash isn't a valid base64-encoded string"); } return td::base64_decode(encoded_hash).move_as_ok(); } @@ -7410,10 +7731,10 @@ td::Result> Client:: } if (source == "files" || source == "translation_files") { td::vector input_hashes; - TRY_RESULT(file_hashes, get_json_object_field(object, "file_hashes", JsonValue::Type::Array, false)); + TRY_RESULT(file_hashes, get_json_object_field(object, "file_hashes", td::JsonValue::Type::Array, false)); for (auto &input_hash : file_hashes.get_array()) { - if (input_hash.type() != JsonValue::Type::String) { - return Status::Error(400, "hash must be a string"); + if (input_hash.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, "hash must be a string"); } TRY_RESULT(hash, get_passport_element_hash(input_hash.get_string())); input_hashes.push_back(std::move(hash)); @@ -7426,13 +7747,13 @@ td::Result> Client:: } UNREACHABLE(); } - return Status::Error(400, "wrong source specified"); + return td::Status::Error(400, "wrong source specified"); } td::Result> Client::get_passport_element_error( - JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "expected an Object"); + td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "expected an Object"); } auto &object = value.get_object(); @@ -7440,7 +7761,7 @@ td::Result> Client::get_pa TRY_RESULT(input_type, get_json_object_string_field(object, "type", false)); auto type = get_passport_element_type(input_type); if (type == nullptr) { - return Status::Error(400, "wrong Telegram Passport element type specified"); + return td::Status::Error(400, "wrong Telegram Passport element type specified"); } TRY_RESULT(message, get_json_object_string_field(object, "message", false)); TRY_RESULT(source, get_passport_element_error_source(object)); @@ -7455,26 +7776,26 @@ td::Result>> Cl auto r_value = json_decode(input_errors); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse errors JSON object"); + return td::Status::Error(400, "Can't parse errors JSON object"); } auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of PassportElementError"); + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of PassportElementError"); } td::vector> errors; for (auto &input_error : value.get_array()) { auto r_error = get_passport_element_error(std::move(input_error)); if (r_error.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse PassportElementError: " << r_error.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse PassportElementError: " << r_error.error().message()); } errors.push_back(r_error.move_as_ok()); } return std::move(errors); } -JsonValue Client::get_input_entities(const Query *query, Slice field_name) { +td::JsonValue Client::get_input_entities(const Query *query, td::Slice field_name) { auto entities = query->arg(field_name); if (!entities.empty()) { auto r_value = json_decode(entities); @@ -7485,7 +7806,7 @@ JsonValue Client::get_input_entities(const Query *query, Slice field_name) { LOG(INFO) << "Can't parse entities JSON object: " << r_value.error(); } - return JsonValue(); + return td::JsonValue(); } td::Result> Client::get_caption(const Query *query) { @@ -7496,7 +7817,7 @@ td::Result> Client::get_caption(const td::Result> Client::get_text_entity_type(td::JsonObject &object) { TRY_RESULT(type, get_json_object_string_field(object, "type", false)); if (type.empty()) { - return Status::Error("Type is not specified"); + return td::Status::Error("Type is not specified"); } if (type == "bold") { @@ -7529,8 +7850,8 @@ td::Result> Client::get_text_entity_t return make_object(url); } if (type == "text_mention") { - TRY_RESULT(user, get_json_object_field(object, "user", JsonValue::Type::Object, false)); - CHECK(user.type() == JsonValue::Type::Object); + TRY_RESULT(user, get_json_object_field(object, "user", td::JsonValue::Type::Object, false)); + CHECK(user.type() == td::JsonValue::Type::Object); TRY_RESULT(user_id, get_json_object_long_field(user.get_object(), "id", false)); return make_object(user_id); } @@ -7543,12 +7864,12 @@ td::Result> Client::get_text_entity_t return nullptr; } - return Status::Error("Unsupported type specified"); + return td::Status::Error("Unsupported type specified"); } -td::Result> Client::get_text_entity(JsonValue &&value) { - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "expected an Object"); +td::Result> Client::get_text_entity(td::JsonValue &&value) { + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "expected an Object"); } auto &object = value.get_object(); @@ -7564,7 +7885,7 @@ td::Result> Client::get_text_entity(JsonV } td::Result> Client::get_formatted_text(td::string text, td::string parse_mode, - JsonValue &&input_entities) { + td::JsonValue &&input_entities) { td::to_lower_inplace(parse_mode); if (!text.empty() && !parse_mode.empty() && parse_mode != "none") { object_ptr text_parse_mode; @@ -7575,13 +7896,13 @@ td::Result> Client::get_formatted_text } else if (parse_mode == "html") { text_parse_mode = make_object(); } else { - return Status::Error(400, "Unsupported parse_mode"); + return td::Status::Error(400, "Unsupported parse_mode"); } auto parsed_text = execute(make_object(text, std::move(text_parse_mode))); if (parsed_text->get_id() == td_api::error::ID) { auto error = move_object_as(parsed_text); - return Status::Error(error->code_, error->message_); + return td::Status::Error(error->code_, error->message_); } CHECK(parsed_text->get_id() == td_api::formattedText::ID); @@ -7589,11 +7910,11 @@ td::Result> Client::get_formatted_text } td::vector> entities; - if (input_entities.type() == JsonValue::Type::Array) { + if (input_entities.type() == td::JsonValue::Type::Array) { for (auto &input_entity : input_entities.get_array()) { auto r_entity = get_text_entity(std::move(input_entity)); if (r_entity.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse MessageEntity: " << r_entity.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse MessageEntity: " << r_entity.error().message()); } if (r_entity.ok() == nullptr) { continue; @@ -7610,12 +7931,10 @@ td::Result> Client::get_input_messa query->arg("parse_mode").str(), get_input_entities(query, "entities")); } -td::Result> Client::get_input_message_text(td::string text, - bool disable_web_page_preview, - td::string parse_mode, - JsonValue &&input_entities) { +td::Result> Client::get_input_message_text( + td::string text, bool disable_web_page_preview, td::string parse_mode, td::JsonValue &&input_entities) { if (text.empty()) { - return Status::Error(400, "Message text is empty"); + return td::Status::Error(400, "Message text is empty"); } TRY_RESULT(formatted_text, get_formatted_text(std::move(text), std::move(parse_mode), std::move(input_entities))); @@ -7626,11 +7945,11 @@ td::Result> Client::get_input_messa td::Result> Client::get_location(const Query *query) { auto latitude = trim(query->arg("latitude")); if (latitude.empty()) { - return Status::Error(400, "Bad Request: latitude is empty"); + return td::Status::Error(400, "Bad Request: latitude is empty"); } auto longitude = trim(query->arg("longitude")); if (longitude.empty()) { - return Status::Error(400, "Bad Request: longitude is empty"); + return td::Status::Error(400, "Bad Request: longitude is empty"); } auto horizontal_accuracy = trim(query->arg("horizontal_accuracy")); @@ -7661,12 +7980,12 @@ td::Result> Client::get_chat_permiss auto r_value = json_decode(query->arg("permissions")); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse permissions JSON object"); + return td::Status::Error(400, "Can't parse permissions JSON object"); } auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Object) { - return Status::Error(400, "Object expected as permissions"); + if (value.type() != td::JsonValue::Type::Object) { + return td::Status::Error(400, "Object expected as permissions"); } auto &object = value.get_object(); @@ -7705,11 +8024,11 @@ td::Result> Client::get_chat_permiss can_send_messages = true; } } - return Status::OK(); + return td::Status::OK(); }(); if (status.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse chat permissions: " << status.message()); + return td::Status::Error(400, PSLICE() << "Can't parse chat permissions: " << status.message()); } if ((can_send_other_messages || can_add_web_page_previews) && !use_independent_chat_permissions) { @@ -7765,10 +8084,10 @@ td::Result> Client::get_chat_permiss } td::Result> Client::get_input_media(const Query *query, - JsonValue &&input_media, + td::JsonValue &&input_media, bool for_album) const { - if (input_media.type() != JsonValue::Type::Object) { - return Status::Error("expected an Object"); + if (input_media.type() != td::JsonValue::Type::Object) { + return td::Status::Error("expected an Object"); } auto &object = input_media.get_object(); @@ -7780,25 +8099,33 @@ td::Result> Client::get_input_me // TRY_RESULT(self_destruct_time, get_json_object_int_field(object, "self_destruct_time")); int32 self_destruct_time = 0; TRY_RESULT(has_spoiler, get_json_object_bool_field(object, "has_spoiler")); - TRY_RESULT(media, get_json_object_string_field(object, "media", true)); + TRY_RESULT(media, get_json_object_string_field(object, "media")); - auto input_file = get_input_file(query, Slice(), media, false); + auto input_file = get_input_file(query, td::Slice(), media, false); if (input_file == nullptr) { - return Status::Error("media not found"); + return td::Status::Error("media not found"); } - TRY_RESULT(thumbnail, get_json_object_string_field(object, "thumb")); + TRY_RESULT(thumbnail, get_json_object_string_field(object, "thumbnail")); + if (thumbnail.empty()) { + TRY_RESULT_ASSIGN(thumbnail, get_json_object_string_field(object, "thumb")); + } + auto thumbnail_input_file = get_input_file(query, td::Slice(), thumbnail, true); + if (thumbnail_input_file == nullptr) { + thumbnail_input_file = get_input_file(query, "thumbnail", td::Slice(), true); + if (thumbnail_input_file == nullptr) { + thumbnail_input_file = get_input_file(query, "thumb", td::Slice(), true); + } + } object_ptr input_thumbnail; - auto thumbanil_input_file = get_input_file(query, thumbnail.empty() ? Slice("thumb") : Slice(), thumbnail, true); - if (thumbanil_input_file != nullptr) { - input_thumbnail = make_object(std::move(thumbanil_input_file), 0, 0); + if (thumbnail_input_file != nullptr) { + input_thumbnail = make_object(std::move(thumbnail_input_file), 0, 0); } TRY_RESULT(type, get_json_object_string_field(object, "type", false)); if (type == "photo") { - return make_object(std::move(input_file), std::move(input_thumbnail), - td::vector(), 0, 0, std::move(caption), self_destruct_time, - has_spoiler); + return make_object(std::move(input_file), nullptr, td::vector(), 0, 0, + std::move(caption), self_destruct_time, has_spoiler); } if (type == "video") { TRY_RESULT(width, get_json_object_int_field(object, "width")); @@ -7814,7 +8141,7 @@ td::Result> Client::get_input_me std::move(caption), self_destruct_time, has_spoiler); } if (for_album && type == "animation") { - return Status::Error(PSLICE() << "type \"" << type << "\" can't be used in sendMediaGroup"); + return td::Status::Error(PSLICE() << "type \"" << type << "\" can't be used in sendMediaGroup"); } if (type == "animation") { TRY_RESULT(width, get_json_object_int_field(object, "width")); @@ -7841,52 +8168,53 @@ td::Result> Client::get_input_me disable_content_type_detection || for_album, std::move(caption)); } - return Status::Error(PSLICE() << "type \"" << type << "\" is unsupported"); + return td::Status::Error(PSLICE() << "type \"" << type << "\" is unsupported"); } td::Result> Client::get_input_media(const Query *query, - Slice field_name) const { + td::Slice field_name) const { TRY_RESULT(media, get_required_string_arg(query, field_name)); LOG(INFO) << "Parsing JSON object: " << media; auto r_value = json_decode(media); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse input media JSON object"); + return td::Status::Error(400, "Can't parse input media JSON object"); } auto r_input_message_content = get_input_media(query, r_value.move_as_ok(), false); if (r_input_message_content.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse InputMedia: " << r_input_message_content.error().message()); + return td::Status::Error(400, PSLICE() << "Can't parse InputMedia: " << r_input_message_content.error().message()); } return r_input_message_content.move_as_ok(); } td::Result>> Client::get_input_message_contents( - const Query *query, Slice field_name) const { + const Query *query, td::Slice field_name) const { TRY_RESULT(media, get_required_string_arg(query, field_name)); LOG(INFO) << "Parsing JSON object: " << media; auto r_value = json_decode(media); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse media JSON object"); + return td::Status::Error(400, "Can't parse media JSON object"); } return get_input_message_contents(query, r_value.move_as_ok()); } td::Result>> Client::get_input_message_contents( - const Query *query, JsonValue &&value) const { - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of InputMedia"); + const Query *query, td::JsonValue &&value) const { + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of InputMedia"); } td::vector> contents; for (auto &input_media : value.get_array()) { auto r_input_message_content = get_input_media(query, std::move(input_media), true); if (r_input_message_content.is_error()) { - return Status::Error(400, PSLICE() << "Can't parse InputMedia: " << r_input_message_content.error().message()); + return td::Status::Error(400, PSLICE() + << "Can't parse InputMedia: " << r_input_message_content.error().message()); } contents.push_back(r_input_message_content.move_as_ok()); } @@ -7899,7 +8227,7 @@ td::Result> Client::get_input_me TRY_RESULT(description, get_required_string_arg(query, "description")); TRY_RESULT(payload, get_required_string_arg(query, "payload")); if (!td::check_utf8(payload.str())) { - return Status::Error(400, "The payload must be encoded in UTF-8"); + return td::Status::Error(400, "The payload must be encoded in UTF-8"); } TRY_RESULT(provider_token, get_required_string_arg(query, "provider_token")); auto provider_data = query->arg("provider_data"); @@ -7909,7 +8237,7 @@ td::Result> Client::get_input_me TRY_RESULT(labeled_price_parts, get_required_string_arg(query, "prices")); auto r_labeled_price_parts_value = json_decode(labeled_price_parts); if (r_labeled_price_parts_value.is_error()) { - return Status::Error(400, "Can't parse prices JSON object"); + return td::Status::Error(400, "Can't parse prices JSON object"); } TRY_RESULT(prices, get_labeled_price_parts(r_labeled_price_parts_value.ok_ref())); @@ -7921,7 +8249,7 @@ td::Result> Client::get_input_me if (!max_tip_amount_str.empty()) { auto r_max_tip_amount = td::to_integer_safe(max_tip_amount_str); if (r_max_tip_amount.is_error()) { - return Status::Error(400, "Can't parse \"max_tip_amount\" as Number"); + return td::Status::Error(400, "Can't parse \"max_tip_amount\" as Number"); } max_tip_amount = r_max_tip_amount.ok(); } @@ -7930,7 +8258,7 @@ td::Result> Client::get_input_me if (!suggested_tip_amounts_str.empty()) { auto r_suggested_tip_amounts_value = json_decode(suggested_tip_amounts_str); if (r_suggested_tip_amounts_value.is_error()) { - return Status::Error(400, "Can't parse suggested_tip_amounts JSON object"); + return td::Status::Error(400, "Can't parse suggested_tip_amounts JSON object"); } TRY_RESULT_ASSIGN(suggested_tip_amounts, get_suggested_tip_amounts(r_suggested_tip_amounts_value.ok_ref())); @@ -7970,40 +8298,40 @@ td::Result> Client::get_poll_options(const Query *query) auto r_value = json_decode(input_options); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse options JSON object"); + return td::Status::Error(400, "Can't parse options JSON object"); } auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of String as options"); + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of String as options"); } td::vector options; for (auto &input_option : value.get_array()) { - if (input_option.type() != JsonValue::Type::String) { - return Status::Error(400, "Expected an option to be of type String"); + if (input_option.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, "Expected an option to be of type String"); } options.push_back(input_option.get_string().str()); } return std::move(options); } -td::int32 Client::get_integer_arg(const Query *query, Slice field_name, int32 default_value, int32 min_value, +td::int32 Client::get_integer_arg(const Query *query, td::Slice field_name, int32 default_value, int32 min_value, int32 max_value) { auto s_arg = query->arg(field_name); auto value = s_arg.empty() ? default_value : td::to_integer(s_arg); return td::clamp(value, min_value, max_value); } -td::Result Client::get_required_string_arg(const Query *query, Slice field_name) { +td::Result Client::get_required_string_arg(const Query *query, td::Slice field_name) { auto s_arg = query->arg(field_name); if (s_arg.empty()) { - return Status::Error(400, PSLICE() << "Parameter \"" << field_name << "\" is required"); + return td::Status::Error(400, PSLICE() << "Parameter \"" << field_name << "\" is required"); } return s_arg; } -td::int64 Client::get_message_id(const Query *query, Slice field_name) { +td::int64 Client::get_message_id(const Query *query, td::Slice field_name) { auto s_arg = query->arg(field_name); if (s_arg.empty()) { return 0; @@ -8017,18 +8345,18 @@ td::int64 Client::get_message_id(const Query *query, Slice field_name) { return as_tdlib_message_id(arg); } -td::Result Client::get_inline_message_id(const Query *query, Slice field_name) { +td::Result Client::get_inline_message_id(const Query *query, td::Slice field_name) { auto s_arg = query->arg(field_name); if (s_arg.empty()) { - return Status::Error(400, "Message identifier is not specified"); + return td::Status::Error(400, "Message identifier is not specified"); } return s_arg; } -td::Result Client::get_user_id(const Query *query, Slice field_name) { +td::Result Client::get_user_id(const Query *query, td::Slice field_name) { int64 user_id = td::max(td::to_integer(query->arg(field_name)), static_cast(0)); if (user_id == 0) { - return Status::Error(400, PSLICE() << "Invalid " << field_name << " specified"); + return td::Status::Error(400, PSLICE() << "Invalid " << field_name << " specified"); } return user_id; } @@ -8087,7 +8415,7 @@ td::Result> Client::get_messa } template -td::Result> Client::get_int_array_arg(const Query *query, Slice field_name, bool optional) { +td::Result> Client::get_int_array_arg(const Query *query, td::Slice field_name, bool optional) { auto input_options = query->arg(field_name); if (input_options.empty() && optional) { td::vector array; @@ -8097,25 +8425,25 @@ td::Result> Client::get_int_array_arg(const Query *query, Slice fi auto r_value = json_decode(input_options); if (r_value.is_error()) { LOG(INFO) << "Can't parse JSON object: " << r_value.error(); - return Status::Error(400, "Can't parse option_ids JSON object"); + return td::Status::Error(400, "Can't parse option_ids JSON object"); } auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of Integer as options"); + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of Integer as options"); } td::vector array; for (auto &element : value.get_array()) { - if (element.type() != JsonValue::Type::Number) { - return Status::Error(400, "Expected an elements to be of type Integer"); + if (element.type() != td::JsonValue::Type::Number) { + return td::Status::Error(400, "Expected an elements to be of type Integer"); } array.push_back(td::to_integer_safe(element.get_number()).move_as_ok()); } return std::move(array); } -td::int64 Client::get_int64_arg(const Query *query, Slice field_name, int64 default_value, int64 min_value, +td::int64 Client::get_int64_arg(const Query *query, td::Slice field_name, int64 default_value, int64 min_value, int64 max_value) { auto s_arg = query->arg(field_name); if (s_arg.empty()) { @@ -8126,11 +8454,11 @@ td::int64 Client::get_int64_arg(const Query *query, Slice field_name, int64 defa } td::Result> Client::get_report_reason(const Query *query, - Slice field_name) { + td::Slice field_name) { auto reason = query->arg(field_name); object_ptr result; if (reason.empty()) { - return Status::Error(400, "reason is not specified"); + return td::Status::Error(400, "reason is not specified"); } else if (reason == "child_abuse") { result = make_object(); } else if (reason == "copyright") { @@ -8150,7 +8478,7 @@ td::Result> Client::get_report_reas } td::Result> Client::get_search_messages_filter(const Query *query, - Slice field_name) { + td::Slice field_name) { auto filter = query->arg(field_name); object_ptr result; if (filter.empty()) { @@ -8190,7 +8518,7 @@ td::Result> Client::get_search_ } else if (filter == "voice_note") { result = make_object(); } else { - return Status::Error(400, "Filter not valid"); + return td::Status::Error(400, "Filter not valid"); } return std::move(result); } @@ -8234,7 +8562,7 @@ void Client::on_message_send_succeeded(object_ptr &&message, in } } -void Client::on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id, Status result) { +void Client::on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id, td::Status result) { auto error = make_object(result.code(), result.message().str()); auto query_id = extract_yet_unsent_message_query_id(chat_id, old_message_id, nullptr); @@ -8318,7 +8646,7 @@ void Client::on_cmd(PromisedQueryPtr query) { td::Status Client::process_get_me_query(PromisedQueryPtr &query) { answer_query(JsonUser(my_id_, this, true), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_my_commands_query(PromisedQueryPtr &query) { @@ -8330,7 +8658,7 @@ td::Status Client::process_get_my_commands_query(PromisedQueryPtr &query) { send_request(make_object(std::move(scope), language_code), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_my_commands_query(PromisedQueryPtr &query) { @@ -8346,7 +8674,7 @@ td::Status Client::process_set_my_commands_query(PromisedQueryPtr &query) { send_request(make_object(std::move(scope), language_code, std::move(bot_commands)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_my_commands_query(PromisedQueryPtr &query) { @@ -8358,14 +8686,14 @@ td::Status Client::process_delete_my_commands_query(PromisedQueryPtr &query) { send_request(make_object(std::move(scope), language_code), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_my_default_administrator_rights_query(PromisedQueryPtr &query) { bool for_channels = to_bool(query->arg("for_channels")); send_request(make_object(my_id_), td::make_unique(for_channels, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_my_default_administrator_rights_query(PromisedQueryPtr &query) { @@ -8379,7 +8707,37 @@ td::Status Client::process_set_my_default_administrator_rights_query(PromisedQue send_request(make_object(std::move(rights)), td::make_unique(std::move(query))); } - return Status::OK(); + return td::Status::OK(); +} + +td::Status Client::process_get_my_description_query(PromisedQueryPtr &query) { + auto language_code = query->arg("language_code"); + send_request(make_object(language_code.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_set_my_description_query(PromisedQueryPtr &query) { + auto language_code = query->arg("language_code"); + auto description = query->arg("description"); + send_request(make_object(language_code.str(), description.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_get_my_short_description_query(PromisedQueryPtr &query) { + auto language_code = query->arg("language_code"); + send_request(make_object(language_code.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_set_my_short_description_query(PromisedQueryPtr &query) { + auto language_code = query->arg("language_code"); + auto short_description = query->arg("short_description"); + send_request(make_object(language_code.str(), short_description.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); } td::Status Client::process_get_chat_menu_button_query(PromisedQueryPtr &query) { @@ -8392,7 +8750,7 @@ td::Status Client::process_get_chat_menu_button_query(PromisedQueryPtr &query) { } else { send_request(make_object(0), td::make_unique(std::move(query))); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_menu_button_query(PromisedQueryPtr &query) { @@ -8408,7 +8766,7 @@ td::Status Client::process_set_chat_menu_button_query(PromisedQueryPtr &query) { send_request(make_object(0, std::move(menu_button)), td::make_unique(std::move(query))); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_user_profile_photos_query(PromisedQueryPtr &query) { @@ -8420,7 +8778,7 @@ td::Status Client::process_get_user_profile_photos_query(PromisedQueryPtr &query send_request(make_object(user_id, offset, limit), td::make_unique(this, std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_message_query(PromisedQueryPtr &query) { @@ -8429,23 +8787,22 @@ td::Status Client::process_send_message_query(PromisedQueryPtr &query) { // fast path auto it = yet_unsent_message_count_.find(r_chat_id.ok()); if (it != yet_unsent_message_count_.end() && it->second >= MAX_CONCURRENTLY_SENT_CHAT_MESSAGES) { - flood_limited_query_count_++; - query->set_retry_after_error(60); - return Status::OK(); + fail_query_flood_limit_exceeded(std::move(query)); + return td::Status::OK(); } } TRY_RESULT(input_message_text, get_input_message_text(query.get())); do_send_message(std::move(input_message_text), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_animation_query(PromisedQueryPtr &query) { auto animation = get_input_file(query.get(), "animation"); if (animation == nullptr) { - return Status::Error(400, "There is no animation in the request"); + return td::Status::Error(400, "There is no animation in the request"); } - auto thumbnail = get_input_thumbnail(query.get(), "thumb"); + auto thumbnail = get_input_thumbnail(query.get()); int32 duration = get_integer_arg(query.get(), "duration", 0, 0, MAX_DURATION); int32 width = get_integer_arg(query.get(), "width", 0, 0, MAX_LENGTH); int32 height = get_integer_arg(query.get(), "height", 0, 0, MAX_LENGTH); @@ -8455,15 +8812,15 @@ td::Status Client::process_send_animation_query(PromisedQueryPtr &query) { make_object(std::move(animation), std::move(thumbnail), td::vector(), duration, width, height, std::move(caption), has_spoiler), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_audio_query(PromisedQueryPtr &query) { auto audio = get_input_file(query.get(), "audio"); if (audio == nullptr) { - return Status::Error(400, "There is no audio in the request"); + return td::Status::Error(400, "There is no audio in the request"); } - auto thumbnail = get_input_thumbnail(query.get(), "thumb"); + auto thumbnail = get_input_thumbnail(query.get()); int32 duration = get_integer_arg(query.get(), "duration", 0, 0, MAX_DURATION); auto title = query->arg("title").str(); auto performer = query->arg("performer").str(); @@ -8471,33 +8828,33 @@ td::Status Client::process_send_audio_query(PromisedQueryPtr &query) { do_send_message(make_object(std::move(audio), std::move(thumbnail), duration, title, performer, std::move(caption)), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_dice_query(PromisedQueryPtr &query) { auto emoji = query->arg("emoji"); do_send_message(make_object(emoji.str(), false), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_document_query(PromisedQueryPtr &query) { auto document = get_input_file(query.get(), "document"); if (document == nullptr) { - return Status::Error(400, "There is no document in the request"); + return td::Status::Error(400, "There is no document in the request"); } - auto thumbnail = get_input_thumbnail(query.get(), "thumb"); + auto thumbnail = get_input_thumbnail(query.get()); TRY_RESULT(caption, get_caption(query.get())); bool disable_content_type_detection = to_bool(query->arg("disable_content_type_detection")); do_send_message(make_object(std::move(document), std::move(thumbnail), disable_content_type_detection, std::move(caption)), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_photo_query(PromisedQueryPtr &query) { auto photo = get_input_file(query.get(), "photo"); if (photo == nullptr) { - return Status::Error(400, "There is no photo in the request"); + return td::Status::Error(400, "There is no photo in the request"); } TRY_RESULT(caption, get_caption(query.get())); auto self_destruct_time = 0; @@ -8505,25 +8862,26 @@ td::Status Client::process_send_photo_query(PromisedQueryPtr &query) { do_send_message(make_object(std::move(photo), nullptr, td::vector(), 0, 0, std::move(caption), self_destruct_time, has_spoiler), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_sticker_query(PromisedQueryPtr &query) { auto sticker = get_input_file(query.get(), "sticker"); if (sticker == nullptr) { - return Status::Error(400, "There is no sticker in the request"); + return td::Status::Error(400, "There is no sticker in the request"); } - do_send_message(make_object(std::move(sticker), nullptr, 0, 0, td::string()), + auto emoji = query->arg("emoji"); + do_send_message(make_object(std::move(sticker), nullptr, 0, 0, emoji.str()), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_video_query(PromisedQueryPtr &query) { auto video = get_input_file(query.get(), "video"); if (video == nullptr) { - return Status::Error(400, "There is no video in the request"); + return td::Status::Error(400, "There is no video in the request"); } - auto thumbnail = get_input_thumbnail(query.get(), "thumb"); + auto thumbnail = get_input_thumbnail(query.get()); int32 duration = get_integer_arg(query.get(), "duration", 0, 0, MAX_DURATION); int32 width = get_integer_arg(query.get(), "width", 0, 0, MAX_LENGTH); int32 height = get_integer_arg(query.get(), "height", 0, 0, MAX_LENGTH); @@ -8535,47 +8893,47 @@ td::Status Client::process_send_video_query(PromisedQueryPtr &query) { duration, width, height, supports_streaming, std::move(caption), self_destruct_time, has_spoiler), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_video_note_query(PromisedQueryPtr &query) { auto video_note = get_input_file(query.get(), "video_note"); if (video_note == nullptr) { - return Status::Error(400, "There is no video note in the request"); + return td::Status::Error(400, "There is no video note in the request"); } - auto thumbnail = get_input_thumbnail(query.get(), "thumb"); + auto thumbnail = get_input_thumbnail(query.get()); int32 duration = get_integer_arg(query.get(), "duration", 0, 0, MAX_DURATION); int32 length = get_integer_arg(query.get(), "length", 0, 0, MAX_LENGTH); do_send_message( make_object(std::move(video_note), std::move(thumbnail), duration, length), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_voice_query(PromisedQueryPtr &query) { auto voice_note = get_input_file(query.get(), "voice"); if (voice_note == nullptr) { - return Status::Error(400, "There is no voice in the request"); + return td::Status::Error(400, "There is no voice in the request"); } int32 duration = get_integer_arg(query.get(), "duration", 0, 0, MAX_DURATION); TRY_RESULT(caption, get_caption(query.get())); do_send_message(make_object(std::move(voice_note), duration, "", std::move(caption)), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_game_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); TRY_RESULT(game_short_name, get_required_string_arg(query.get(), "game_short_name")); do_send_message(make_object(my_id_, game_short_name.str()), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_invoice_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); TRY_RESULT(input_message_invoice, get_input_message_invoice(query.get())); do_send_message(std::move(input_message_invoice), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_location_query(PromisedQueryPtr &query) { @@ -8587,7 +8945,7 @@ td::Status Client::process_send_location_query(PromisedQueryPtr &query) { do_send_message( make_object(std::move(location), live_period, heading, proximity_alert_radius), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_venue_query(PromisedQueryPtr &query) { @@ -8617,7 +8975,7 @@ td::Status Client::process_send_venue_query(PromisedQueryPtr &query) { do_send_message(make_object(make_object( std::move(location), title.str(), address.str(), provider, venue_id, venue_type)), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_contact_query(PromisedQueryPtr &query) { @@ -8628,7 +8986,7 @@ td::Status Client::process_send_contact_query(PromisedQueryPtr &query) { do_send_message(make_object(make_object( phone_number.str(), first_name.str(), last_name.str(), vcard.str(), 0)), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_poll_query(PromisedQueryPtr &query) { @@ -8651,7 +9009,7 @@ td::Status Client::process_send_poll_query(PromisedQueryPtr &query) { } else if (type.empty() || type == "regular") { poll_type = make_object(to_bool(query->arg("allows_multiple_answers"))); } else { - return Status::Error(400, "Unsupported poll type specified"); + return td::Status::Error(400, "Unsupported poll type specified"); } int32 open_period = get_integer_arg(query.get(), "open_period", 0, 0, 10 * 60); int32 close_date = get_integer_arg(query.get(), "close_date", 0); @@ -8659,7 +9017,7 @@ td::Status Client::process_send_poll_query(PromisedQueryPtr &query) { do_send_message(make_object(question.str(), std::move(options), is_anonymous, std::move(poll_type), open_period, close_date, is_closed), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_stop_poll_query(PromisedQueryPtr &query) { @@ -8680,7 +9038,7 @@ td::Status Client::process_stop_poll_query(PromisedQueryPtr &query) { td::make_unique(this, chat_id, message_id, std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_copy_message_query(PromisedQueryPtr &query) { @@ -8699,7 +9057,7 @@ td::Status Client::process_copy_message_query(PromisedQueryPtr &query) { do_send_message(make_object(from_chat_id, message_id, false, std::move(options)), std::move(query)); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_forward_message_query(PromisedQueryPtr &query) { @@ -8711,7 +9069,7 @@ td::Status Client::process_forward_message_query(PromisedQueryPtr &query) { do_send_message(make_object(from_chat_id, message_id, false, nullptr), std::move(query)); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_media_group_query(PromisedQueryPtr &query) { @@ -8742,8 +9100,7 @@ td::Status Client::process_send_media_group_query(PromisedQueryPtr &query) { PromisedQueryPtr query) mutable { auto &count = yet_unsent_message_count_[chat_id]; if (count >= MAX_CONCURRENTLY_SENT_CHAT_MESSAGES) { - flood_limited_query_count_++; - return query->set_retry_after_error(60); + return fail_query_flood_limit_exceeded(std::move(query)); } auto message_count = input_message_contents.size(); count += static_cast(message_count); @@ -8760,7 +9117,7 @@ td::Status Client::process_send_media_group_query(PromisedQueryPtr &query) { check_message(chat_id, reply_to_message_id, reply_to_message_id <= 0 || allow_sending_without_reply, AccessRights::Write, "replied message", std::move(query), std::move(on_success)); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_chat_action_query(PromisedQueryPtr &query) { @@ -8768,7 +9125,7 @@ td::Status Client::process_send_chat_action_query(PromisedQueryPtr &query) { auto message_thread_id = get_message_id(query.get(), "message_thread_id"); object_ptr action = get_chat_action(query.get()); if (action == nullptr) { - return Status::Error(400, "Wrong parameter action in request"); + return td::Status::Error(400, "Wrong parameter action in request"); } check_chat(chat_id, AccessRights::Write, std::move(query), @@ -8776,7 +9133,7 @@ td::Status Client::process_send_chat_action_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, message_thread_id, std::move(action)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_message_text_query(PromisedQueryPtr &query) { @@ -8811,7 +9168,7 @@ td::Status Client::process_edit_message_text_query(PromisedQueryPtr &query) { }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_message_live_location_query(PromisedQueryPtr &query) { @@ -8853,7 +9210,7 @@ td::Status Client::process_edit_message_live_location_query(PromisedQueryPtr &qu }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_message_media_query(PromisedQueryPtr &query) { @@ -8888,7 +9245,7 @@ td::Status Client::process_edit_message_media_query(PromisedQueryPtr &query) { }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_message_caption_query(PromisedQueryPtr &query) { @@ -8922,7 +9279,7 @@ td::Status Client::process_edit_message_caption_query(PromisedQueryPtr &query) { }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_message_reply_markup_query(PromisedQueryPtr &query) { @@ -8955,7 +9312,7 @@ td::Status Client::process_edit_message_reply_markup_query(PromisedQueryPtr &que }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_message_query(PromisedQueryPtr &query) { @@ -8963,11 +9320,11 @@ td::Status Client::process_delete_message_query(PromisedQueryPtr &query) { auto message_id = get_message_id(query.get()); if (chat_id.empty()) { - return Status::Error(400, "Chat identifier is not specified"); + return td::Status::Error(400, "Chat identifier is not specified"); } if (message_id == 0) { - return Status::Error(400, "Message identifier is not specified"); + return td::Status::Error(400, "Message identifier is not specified"); } check_message(chat_id, message_id, false, AccessRights::Write, "message to delete", std::move(query), @@ -8975,14 +9332,14 @@ td::Status Client::process_delete_message_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, td::vector{message_id}, true), td::make_unique(std::move(query))); }); - return Status::OK(); + 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())); send_request(make_object(std::move(input_message_invoice)), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_game_score_query(PromisedQueryPtr &query) { @@ -9020,7 +9377,7 @@ td::Status Client::process_set_game_score_query(PromisedQueryPtr &query) { }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_game_high_scores_query(PromisedQueryPtr &query) { @@ -9046,7 +9403,7 @@ td::Status Client::process_get_game_high_scores_query(PromisedQueryPtr &query) { }); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_answer_web_app_query_query(PromisedQueryPtr &query) { @@ -9064,7 +9421,7 @@ td::Status Client::process_answer_web_app_query_query(PromisedQueryPtr &query) { send_request(make_object(web_app_query_id, std::move(results[0])), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_answer_inline_query_query(PromisedQueryPtr &query) { @@ -9073,22 +9430,26 @@ td::Status Client::process_answer_inline_query_query(PromisedQueryPtr &query) { auto is_personal = to_bool(query->arg("is_personal")); int32 cache_time = get_integer_arg(query.get(), "cache_time", 300, 0, 24 * 60 * 60); auto next_offset = query->arg("next_offset"); - auto switch_pm_text = query->arg("switch_pm_text"); - auto switch_pm_parameter = query->arg("switch_pm_parameter"); - + TRY_RESULT(button, get_inline_query_results_button(query->arg("button"))); + if (button == nullptr) { + auto switch_pm_text = query->arg("switch_pm_text"); + if (!switch_pm_text.empty()) { + button = make_object( + switch_pm_text.str(), + make_object(query->arg("switch_pm_parameter").str())); + } + } TRY_RESULT(results, get_inline_query_results(query.get())); resolve_inline_query_results_bot_usernames( std::move(results), std::move(query), - [this, inline_query_id, is_personal, cache_time, next_offset = next_offset.str(), - switch_pm_text = switch_pm_text.str(), switch_pm_parameter = switch_pm_parameter.str()]( - td::vector> results, PromisedQueryPtr query) { - send_request( - make_object(inline_query_id, is_personal, std::move(results), cache_time, - next_offset, switch_pm_text, switch_pm_parameter), - td::make_unique(std::move(query))); + [this, inline_query_id, is_personal, cache_time, next_offset = next_offset.str(), button = std::move(button)]( + td::vector> results, PromisedQueryPtr query) mutable { + send_request(make_object(inline_query_id, is_personal, std::move(button), + std::move(results), cache_time, next_offset), + td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_answer_callback_query_query(PromisedQueryPtr &query) { @@ -9101,7 +9462,7 @@ td::Status Client::process_answer_callback_query_query(PromisedQueryPtr &query) send_request(make_object(callback_query_id, text, show_alert, url, cache_time), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_answer_shipping_query_query(PromisedQueryPtr &query) { @@ -9118,7 +9479,7 @@ td::Status Client::process_answer_shipping_query_query(PromisedQueryPtr &query) send_request( make_object(shipping_query_id, std::move(shipping_options), error_message.str()), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_answer_pre_checkout_query_query(PromisedQueryPtr &query) { @@ -9132,7 +9493,7 @@ td::Status Client::process_answer_pre_checkout_query_query(PromisedQueryPtr &que send_request(make_object(pre_checkout_query_id, error_message.str()), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_export_chat_invite_link_query(PromisedQueryPtr &query) { @@ -9142,7 +9503,7 @@ td::Status Client::process_export_chat_invite_link_query(PromisedQueryPtr &query send_request(make_object(chat_id), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_create_chat_invite_link_query(PromisedQueryPtr &query) { @@ -9159,7 +9520,7 @@ td::Status Client::process_create_chat_invite_link_query(PromisedQueryPtr &query creates_join_request), td::make_unique(this, std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_chat_invite_link_query(PromisedQueryPtr &query) { @@ -9177,7 +9538,7 @@ td::Status Client::process_edit_chat_invite_link_query(PromisedQueryPtr &query) member_limit, creates_join_request), td::make_unique(this, std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_revoke_chat_invite_link_query(PromisedQueryPtr &query) { @@ -9189,7 +9550,7 @@ td::Status Client::process_revoke_chat_invite_link_query(PromisedQueryPtr &query send_request(make_object(chat_id, invite_link), td::make_unique(this, std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_chat_query(PromisedQueryPtr &query) { @@ -9213,7 +9574,7 @@ td::Status Client::process_get_chat_query(PromisedQueryPtr &query) { UNREACHABLE(); } }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_photo_query(PromisedQueryPtr &query) { @@ -9221,9 +9582,9 @@ td::Status Client::process_set_chat_photo_query(PromisedQueryPtr &query) { auto photo = get_input_file(query.get(), "photo", true); if (photo == nullptr) { if (query->arg("photo").empty()) { - return Status::Error(400, "There is no photo in the request"); + return td::Status::Error(400, "There is no photo in the request"); } - return Status::Error(400, "Photo must be uploaded as an InputFile"); + return td::Status::Error(400, "Photo must be uploaded as an InputFile"); } check_chat(chat_id, AccessRights::Write, std::move(query), @@ -9232,7 +9593,7 @@ td::Status Client::process_set_chat_photo_query(PromisedQueryPtr &query) { chat_id, make_object(std::move(photo))), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_chat_photo_query(PromisedQueryPtr &query) { @@ -9242,7 +9603,7 @@ td::Status Client::process_delete_chat_photo_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, nullptr), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_title_query(PromisedQueryPtr &query) { @@ -9254,7 +9615,7 @@ td::Status Client::process_set_chat_title_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, title), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_permissions_query(PromisedQueryPtr &query) { @@ -9269,7 +9630,7 @@ td::Status Client::process_set_chat_permissions_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, std::move(permissions)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_description_query(PromisedQueryPtr &query) { @@ -9281,7 +9642,7 @@ td::Status Client::process_set_chat_description_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, description), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_pin_chat_message_query(PromisedQueryPtr &query) { @@ -9294,7 +9655,7 @@ td::Status Client::process_pin_chat_message_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, message_id, disable_notification, false), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_unpin_chat_message_query(PromisedQueryPtr &query) { @@ -9313,7 +9674,7 @@ td::Status Client::process_unpin_chat_message_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_unpin_all_chat_messages_query(PromisedQueryPtr &query) { @@ -9323,7 +9684,7 @@ td::Status Client::process_unpin_all_chat_messages_query(PromisedQueryPtr &query send_request(make_object(chat_id), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_sticker_set_query(PromisedQueryPtr &query) { @@ -9346,7 +9707,7 @@ td::Status Client::process_set_chat_sticker_set_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_chat_sticker_set_query(PromisedQueryPtr &query) { @@ -9363,13 +9724,13 @@ td::Status Client::process_delete_chat_sticker_set_query(PromisedQueryPtr &query send_request(make_object(chat_info->supergroup_id, 0), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_forum_topic_icon_stickers_query(PromisedQueryPtr &query) { send_request(make_object(), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_create_forum_topic_query(PromisedQueryPtr &query) { @@ -9384,7 +9745,7 @@ td::Status Client::process_create_forum_topic_query(PromisedQueryPtr &query) { chat_id, name, make_object(icon_color, icon_custom_emoji_id)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_forum_topic_query(PromisedQueryPtr &query) { @@ -9401,7 +9762,7 @@ td::Status Client::process_edit_forum_topic_query(PromisedQueryPtr &query) { edit_icon_custom_emoji_id, icon_custom_emoji_id), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_close_forum_topic_query(PromisedQueryPtr &query) { @@ -9413,7 +9774,7 @@ td::Status Client::process_close_forum_topic_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, message_thread_id, true), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_reopen_forum_topic_query(PromisedQueryPtr &query) { @@ -9425,7 +9786,7 @@ td::Status Client::process_reopen_forum_topic_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, message_thread_id, false), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_forum_topic_query(PromisedQueryPtr &query) { @@ -9437,7 +9798,7 @@ td::Status Client::process_delete_forum_topic_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, message_thread_id), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_unpin_all_forum_topic_messages_query(PromisedQueryPtr &query) { @@ -9449,7 +9810,7 @@ td::Status Client::process_unpin_all_forum_topic_messages_query(PromisedQueryPtr send_request(make_object(chat_id, message_thread_id), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_general_forum_topic_query(PromisedQueryPtr &query) { @@ -9461,7 +9822,7 @@ td::Status Client::process_edit_general_forum_topic_query(PromisedQueryPtr &quer send_request(make_object(chat_id, GENERAL_MESSAGE_THREAD_ID, name, false, 0), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_close_general_forum_topic_query(PromisedQueryPtr &query) { @@ -9471,7 +9832,7 @@ td::Status Client::process_close_general_forum_topic_query(PromisedQueryPtr &que send_request(make_object(chat_id, GENERAL_MESSAGE_THREAD_ID, true), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_reopen_general_forum_topic_query(PromisedQueryPtr &query) { @@ -9481,7 +9842,7 @@ td::Status Client::process_reopen_general_forum_topic_query(PromisedQueryPtr &qu send_request(make_object(chat_id, GENERAL_MESSAGE_THREAD_ID, false), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_hide_general_forum_topic_query(PromisedQueryPtr &query) { @@ -9491,7 +9852,7 @@ td::Status Client::process_hide_general_forum_topic_query(PromisedQueryPtr &quer send_request(make_object(chat_id, true), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_unhide_general_forum_topic_query(PromisedQueryPtr &query) { @@ -9501,7 +9862,7 @@ td::Status Client::process_unhide_general_forum_topic_query(PromisedQueryPtr &qu send_request(make_object(chat_id, false), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_chat_member_query(PromisedQueryPtr &query) { @@ -9516,7 +9877,7 @@ td::Status Client::process_get_chat_member_query(PromisedQueryPtr &query) { answer_query(JsonChatMember(chat_member.get(), chat_type, this), std::move(query)); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_chat_administrators_query(PromisedQueryPtr &query) { @@ -9541,7 +9902,7 @@ td::Status Client::process_get_chat_administrators_query(PromisedQueryPtr &query UNREACHABLE(); } }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_chat_member_count_query(PromisedQueryPtr &query) { @@ -9566,36 +9927,7 @@ td::Status Client::process_get_chat_member_count_query(PromisedQueryPtr &query) UNREACHABLE(); } }); - return Status::OK(); -} - -td::Status Client::process_optimize_memory_query(PromisedQueryPtr &query) { - /* - disable_internet_connection(std::move(query), [this](PromisedQueryPtr query) { - optimize_memory(std::move(query), [this](PromisedQueryPtr query) { enable_internet_connection(std::move(query)); }); - }); - */ - return Status::OK(); -} - -template -void Client::disable_internet_connection(PromisedQueryPtr query, OnSuccess on_success) { - send_request(make_object(make_object()), - td::make_unique>(this, std::move(query), - std::move(on_success))); -} - -void Client::enable_internet_connection(PromisedQueryPtr query) { - send_request(make_object(make_object()), - td::make_unique(std::move(query))); -} - -template -void Client::optimize_memory(PromisedQueryPtr query, OnSuccess on_success) { - /* - send_request(make_object(), - td::make_unique>(this, std::move(query), std::move(on_success))); - */ + return td::Status::OK(); } td::Status Client::process_leave_chat_query(PromisedQueryPtr &query) { @@ -9604,7 +9936,7 @@ td::Status Client::process_leave_chat_query(PromisedQueryPtr &query) { check_chat(chat_id, AccessRights::Read, std::move(query), [this](int64 chat_id, PromisedQueryPtr query) { send_request(make_object(chat_id), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_promote_chat_member_query(PromisedQueryPtr &query) { @@ -9653,7 +9985,7 @@ td::Status Client::process_promote_chat_member_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_chat_administrator_custom_title_query(PromisedQueryPtr &query) { @@ -9674,7 +10006,7 @@ td::Status Client::process_set_chat_administrator_custom_title_query(PromisedQue if (chat_member->status_->get_id() != td_api::chatMemberStatusAdministrator::ID) { return fail_query(400, "Bad Request: user is not an administrator", std::move(query)); } - auto administrator = td_api::move_object_as(chat_member->status_); + auto administrator = move_object_as(chat_member->status_); if (!administrator->can_be_edited_) { return fail_query(400, "Bad Request: not enough rights to change custom title of the user", std::move(query)); @@ -9686,7 +10018,7 @@ td::Status Client::process_set_chat_administrator_custom_title_query(PromisedQue td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_ban_chat_member_query(PromisedQueryPtr &query) { @@ -9705,7 +10037,7 @@ td::Status Client::process_ban_chat_member_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_restrict_chat_member_query(PromisedQueryPtr &query) { @@ -9745,7 +10077,7 @@ td::Status Client::process_restrict_chat_member_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_unban_chat_member_query(PromisedQueryPtr &query) { @@ -9784,7 +10116,7 @@ td::Status Client::process_unban_chat_member_query(PromisedQueryPtr &query) { }); } }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_ban_chat_sender_chat_query(PromisedQueryPtr &query) { @@ -9802,7 +10134,7 @@ td::Status Client::process_ban_chat_sender_chat_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_unban_chat_sender_chat_query(PromisedQueryPtr &query) { @@ -9819,7 +10151,7 @@ td::Status Client::process_unban_chat_sender_chat_query(PromisedQueryPtr &query) td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_approve_chat_join_request_query(PromisedQueryPtr &query) { @@ -9832,7 +10164,7 @@ td::Status Client::process_approve_chat_join_request_query(PromisedQueryPtr &que td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_decline_chat_join_request_query(PromisedQueryPtr &query) { @@ -9845,7 +10177,7 @@ td::Status Client::process_decline_chat_join_request_query(PromisedQueryPtr &que td::make_unique(std::move(query))); }); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_sticker_set_query(PromisedQueryPtr &query) { @@ -9857,7 +10189,7 @@ td::Status Client::process_get_sticker_set_query(PromisedQueryPtr &query) { send_request(make_object(name.str()), td::make_unique(this, true, std::move(query))); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_custom_emoji_stickers_query(PromisedQueryPtr &query) { @@ -9866,43 +10198,51 @@ td::Status Client::process_get_custom_emoji_stickers_query(PromisedQueryPtr &que LOG(INFO) << "Parsing JSON object: " << custom_emoji_ids_json; auto r_value = json_decode(custom_emoji_ids_json); if (r_value.is_error()) { - return Status::Error(400, "Can't parse custom emoji identifiers JSON object"); + return td::Status::Error(400, "Can't parse custom emoji identifiers JSON object"); } auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Array) { - return Status::Error(400, "Expected an Array of custom emoji identifiers"); + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Expected an Array of custom emoji identifiers"); } td::vector custom_emoji_ids; for (auto &custom_emoji_id : value.get_array()) { - if (custom_emoji_id.type() != JsonValue::Type::String) { - return Status::Error(400, "Custom emoji identifier must be of type String"); + if (custom_emoji_id.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, "Custom emoji identifier must be of type String"); } auto parsed_id = td::to_integer_safe(custom_emoji_id.get_string()); if (parsed_id.is_error()) { - return Status::Error(400, "Invalid custom emoji identifier specified"); + return td::Status::Error(400, "Invalid custom emoji identifier specified"); } custom_emoji_ids.push_back(parsed_id.ok()); } send_request(make_object(std::move(custom_emoji_ids)), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); TRY_RESULT(user_id, get_user_id(query.get())); - auto png_sticker = get_input_file(query.get(), "png_sticker"); + object_ptr sticker_format; + object_ptr sticker; + if (query->has_arg("sticker") || query->file("sticker") != nullptr) { + TRY_RESULT_ASSIGN(sticker_format, get_sticker_format(query->arg("sticker_format"))); + sticker = get_input_file(query.get(), "sticker", true); + } else { + sticker_format = make_object(); + sticker = get_input_file(query.get(), "png_sticker", true); + } - check_user( - user_id, std::move(query), [this, user_id, png_sticker = std::move(png_sticker)](PromisedQueryPtr query) mutable { - send_request(make_object( - user_id, make_object(std::move(png_sticker), "", - make_object(), nullptr)), - td::make_unique(this, std::move(query))); - }); - return Status::OK(); + check_user(user_id, std::move(query), + [this, user_id, sticker_format = std::move(sticker_format), + sticker = std::move(sticker)](PromisedQueryPtr query) mutable { + send_request( + make_object(user_id, std::move(sticker_format), std::move(sticker)), + td::make_unique(this, std::move(query))); + }); + return td::Status::OK(); } td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) { @@ -9910,76 +10250,142 @@ td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) TRY_RESULT(user_id, get_user_id(query.get())); auto name = query->arg("name"); auto title = query->arg("title"); - TRY_RESULT(stickers, get_input_stickers(query.get())); + auto needs_repainting = to_bool(query->arg("needs_repainting")); + object_ptr sticker_format; + TRY_RESULT(stickers, get_input_stickers(query.get(), sticker_format)); TRY_RESULT(sticker_type, get_sticker_type(query->arg("sticker_type"))); if (to_bool(query->arg("contains_masks"))) { sticker_type = make_object(); } - check_user(user_id, std::move(query), - [this, user_id, title, name, sticker_type = std::move(sticker_type), - stickers = std::move(stickers)](PromisedQueryPtr query) mutable { - send_request( - make_object(user_id, title.str(), name.str(), std::move(sticker_type), - std::move(stickers), PSTRING() << "bot" << my_id_), - td::make_unique(this, false, std::move(query))); - }); - return Status::OK(); + check_user( + user_id, std::move(query), + [this, user_id, title, name, sticker_format = std::move(sticker_format), sticker_type = std::move(sticker_type), + needs_repainting, stickers = std::move(stickers)](PromisedQueryPtr query) mutable { + send_request(make_object( + user_id, title.str(), name.str(), std::move(sticker_format), std::move(sticker_type), + needs_repainting, std::move(stickers), PSTRING() << "bot" << my_id_), + td::make_unique(this, false, std::move(query))); + }); + return td::Status::OK(); } td::Status Client::process_add_sticker_to_set_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); TRY_RESULT(user_id, get_user_id(query.get())); auto name = query->arg("name"); - TRY_RESULT(stickers, get_input_stickers(query.get())); - CHECK(!stickers.empty()); + TRY_RESULT(sticker, get_input_sticker(query.get())); check_user(user_id, std::move(query), - [this, user_id, name, sticker = std::move(stickers[0])](PromisedQueryPtr query) mutable { + [this, user_id, name, sticker = std::move(sticker)](PromisedQueryPtr query) mutable { send_request(make_object(user_id, name.str(), std::move(sticker)), - td::make_unique(this, false, std::move(query))); + td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } -td::Status Client::process_set_sticker_set_thumb_query(PromisedQueryPtr &query) { +td::Status Client::process_set_sticker_set_title_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); + auto name = query->arg("name"); + auto title = query->arg("title"); + send_request(make_object(name.str(), title.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_set_sticker_set_thumbnail_query(PromisedQueryPtr &query) { TRY_RESULT(user_id, get_user_id(query.get())); auto name = query->arg("name"); - auto thumbnail = get_input_file(query.get(), "thumb"); + auto thumbnail = get_input_file(query.get(), "thumbnail"); + if (thumbnail == nullptr) { + thumbnail = get_input_file(query.get(), "thumb"); + } check_user(user_id, std::move(query), [this, user_id, name, thumbnail = std::move(thumbnail)](PromisedQueryPtr query) mutable { send_request(make_object(user_id, name.str(), std::move(thumbnail)), - td::make_unique(this, false, std::move(query))); + td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); +} + +td::Status Client::process_set_custom_emoji_sticker_set_thumbnail_query(PromisedQueryPtr &query) { + auto name = query->arg("name"); + auto custom_emoji_id = td::to_integer(query->arg("custom_emoji_id")); + send_request(make_object(name.str(), custom_emoji_id), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_delete_sticker_set_query(PromisedQueryPtr &query) { + auto name = query->arg("name"); + send_request(make_object(name.str()), + td::make_unique(std::move(query))); + return td::Status::OK(); } td::Status Client::process_set_sticker_position_in_set_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); - auto file_id = trim(query->arg("sticker")); - if (file_id.empty()) { - return Status::Error(400, "Sticker is not specified"); - } + TRY_RESULT(input_file, get_sticker_input_file(query.get())); int32 position = get_integer_arg(query.get(), "position", -1); - send_request( - make_object(make_object(file_id.str()), position), - td::make_unique(std::move(query))); - return Status::OK(); + send_request(make_object(std::move(input_file), position), + td::make_unique(std::move(query))); + return td::Status::OK(); } td::Status Client::process_delete_sticker_from_set_query(PromisedQueryPtr &query) { CHECK_IS_BOT(); - auto file_id = trim(query->arg("sticker")); - if (file_id.empty()) { - return Status::Error(400, "Sticker is not specified"); + TRY_RESULT(input_file, get_sticker_input_file(query.get())); + + send_request(make_object(std::move(input_file)), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_set_sticker_emoji_list_query(PromisedQueryPtr &query) { + TRY_RESULT(input_file, get_sticker_input_file(query.get())); + TRY_RESULT(emojis, get_sticker_emojis(query->arg("emoji_list"))); + + send_request(make_object(std::move(input_file), emojis), + td::make_unique(std::move(query))); + return td::Status::OK(); +} + +td::Status Client::process_set_sticker_keywords_query(PromisedQueryPtr &query) { + TRY_RESULT(input_file, get_sticker_input_file(query.get())); + td::vector input_keywords; + if (query->has_arg("keywords")) { + auto r_value = json_decode(query->arg("keywords")); + if (r_value.is_error()) { + LOG(INFO) << "Can't parse JSON object: " << r_value.error(); + return td::Status::Error(400, "Can't parse keywords JSON object"); + } + auto value = r_value.move_as_ok(); + + if (value.type() != td::JsonValue::Type::Array) { + return td::Status::Error(400, "Field \"keywords\" must be an Array"); + } + for (auto &keyword : value.get_array()) { + if (keyword.type() != td::JsonValue::Type::String) { + return td::Status::Error(400, "keyword must be a string"); + } + input_keywords.push_back(keyword.get_string().str()); + } } - send_request(make_object(make_object(file_id.str())), + send_request(make_object(std::move(input_file), std::move(input_keywords)), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); +} + +td::Status Client::process_set_sticker_mask_position_query(PromisedQueryPtr &query) { + TRY_RESULT(input_file, get_sticker_input_file(query.get())); + TRY_RESULT(mask_position, get_mask_position(query.get(), "mask_position")); + + send_request(make_object(std::move(input_file), std::move(mask_position)), + td::make_unique(std::move(query))); + return td::Status::OK(); } td::Status Client::process_set_passport_data_errors_query(PromisedQueryPtr &query) { @@ -9992,7 +10398,7 @@ td::Status Client::process_set_passport_data_errors_query(PromisedQueryPtr &quer send_request(make_object(user_id, std::move(errors)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_send_custom_request_query(PromisedQueryPtr &query) { @@ -10000,7 +10406,7 @@ td::Status Client::process_send_custom_request_query(PromisedQueryPtr &query) { auto parameters = query->arg("parameters"); send_request(make_object(method.str(), parameters.str()), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_answer_custom_query_query(PromisedQueryPtr &query) { @@ -10008,7 +10414,7 @@ td::Status Client::process_answer_custom_query_query(PromisedQueryPtr &query) { auto data = query->arg("data"); send_request(make_object(custom_query_id, data.str()), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_updates_query(PromisedQueryPtr &query) { @@ -10016,7 +10422,7 @@ td::Status Client::process_get_updates_query(PromisedQueryPtr &query) { fail_query_conflict( "Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first", std::move(query)); - return Status::OK(); + return td::Status::OK(); } int32 offset = get_integer_arg(query.get(), "offset", 0); int32 limit = get_integer_arg(query.get(), "limit", 100, 1, 100); @@ -10034,11 +10440,11 @@ td::Status Client::process_get_updates_query(PromisedQueryPtr &query) { previous_get_updates_offset_ = offset; previous_get_updates_start_time_ = now; do_get_updates(offset, limit, timeout, std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_webhook_query(PromisedQueryPtr &query) { - Slice new_url; + td::Slice new_url; if (query->method() == "setwebhook") { new_url = query->arg("url"); } @@ -10047,7 +10453,7 @@ td::Status Client::process_set_webhook_query(PromisedQueryPtr &query) { if (!new_url.empty() && !query->is_internal()) { if (now < next_allowed_set_webhook_time_) { query->set_retry_after_error(1); - return Status::OK(); + return td::Status::OK(); } next_allowed_set_webhook_time_ = now + 1; } @@ -10059,16 +10465,16 @@ td::Status Client::process_set_webhook_query(PromisedQueryPtr &query) { : (get_webhook_certificate(query.get()) != nullptr || (query->is_internal() && query->arg("certificate") == "previous")); int32 new_max_connections = new_url.empty() ? 0 : get_webhook_max_connections(query.get()); - Slice new_ip_address = new_url.empty() ? Slice() : query->arg("ip_address"); + td::Slice new_ip_address = new_url.empty() ? td::Slice() : query->arg("ip_address"); bool new_fix_ip_address = new_url.empty() ? false : get_webhook_fix_ip_address(query.get()); - Slice new_secret_token = new_url.empty() ? Slice() : query->arg("secret_token"); + td::Slice new_secret_token = new_url.empty() ? td::Slice() : query->arg("secret_token"); bool drop_pending_updates = to_bool(query->arg("drop_pending_updates")); if (webhook_set_query_) { // already updating webhook. Cancel previous request fail_query_conflict("Conflict: terminated by other setWebhook", std::move(webhook_set_query_)); } else if (active_webhook_set_query_) { query->set_retry_after_error(1); - return Status::OK(); + return td::Status::OK(); } else if (webhook_url_ == new_url && !has_webhook_certificate_ && !new_has_certificate && new_max_connections == webhook_max_connections_ && new_fix_ip_address == webhook_fix_ip_address_ && new_secret_token == webhook_secret_token_ && @@ -10080,8 +10486,8 @@ td::Status Client::process_set_webhook_query(PromisedQueryPtr &query) { LOG(WARNING) << "Webhook is not modified: \"" << new_url << '"'; } answer_query(td::JsonTrue(), std::move(query), - new_url.empty() ? Slice("Webhook is already deleted") : Slice("Webhook is already set")); - return Status::OK(); + new_url.empty() ? td::Slice("Webhook is already deleted") : td::Slice("Webhook is already set")); + return td::Status::OK(); } if (now > next_set_webhook_logging_time_ || webhook_url_ != new_url) { @@ -10105,16 +10511,16 @@ td::Status Client::process_set_webhook_query(PromisedQueryPtr &query) { webhook_query_type_ = WebhookQueryType::Cancel; CHECK(!active_webhook_set_query_); webhook_set_query_ = std::move(query); - return Status::OK(); + return td::Status::OK(); } do_set_webhook(std::move(query), false); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_webhook_info_query(PromisedQueryPtr &query) { update_last_synchronization_error_date(); answer_query(JsonWebhookInfo(this), std::move(query)); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_file_query(PromisedQueryPtr &query) { @@ -10122,7 +10528,7 @@ td::Status Client::process_get_file_query(PromisedQueryPtr &query) { check_remote_file_id(file_id, std::move(query), [this](object_ptr file, PromisedQueryPtr query) { do_get_file(std::move(file), std::move(query)); }); - return Status::OK(); + return td::Status::OK(); } //start custom methods impl @@ -10137,7 +10543,7 @@ td::Status Client::process_get_message_info_query(PromisedQueryPtr &query) { answer_query(JsonMessage(message, send_reply, "get message info", this), std::move(query)); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_chat_members_query(PromisedQueryPtr &query) { @@ -10188,29 +10594,29 @@ td::Status Client::process_get_chat_members_query(PromisedQueryPtr &query) { UNREACHABLE(); } }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_messages_query(PromisedQueryPtr &query) { auto chat_id = query->arg("chat_id"); if (chat_id.empty()) { - return Status::Error(400, "Chat identifier is not specified"); + return td::Status::Error(400, "Chat identifier is not specified"); } auto start = as_client_message_id(get_message_id(query.get(), "start")); auto end = as_client_message_id(get_message_id(query.get(), "end")); if (start == 0 || end == 0) { - return Status::Error(400, "Message identifier is not specified"); + return td::Status::Error(400, "Message identifier is not specified"); } if (start >= end) { - return Status::Error(400, "Initial message identifier is not lower than last message identifier"); + return td::Status::Error(400, "Initial message identifier is not lower than last message identifier"); } if (static_cast(end-start) > parameters_->max_batch_operations) { - return Status::Error(400, PSLICE() << "Too many operations: maximum number of batch operation is " << parameters_->max_batch_operations); + return td::Status::Error(400, PSLICE() << "Too many operations: maximum number of batch operation is " << parameters_->max_batch_operations); } check_chat(chat_id, AccessRights::Write, std::move(query), [this, start, end](int64 chat_id, PromisedQueryPtr query) { @@ -10230,17 +10636,17 @@ td::Status Client::process_delete_messages_query(PromisedQueryPtr &query) { } }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_toggle_group_invites_query(PromisedQueryPtr &query) { answer_query(td::JsonFalse(), std::move(query), "Not implemented"); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_ping_query(PromisedQueryPtr &query) { send_request(make_object(), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_memory_stats_query(PromisedQueryPtr &query) { @@ -10248,13 +10654,13 @@ td::Status Client::process_get_memory_stats_query(PromisedQueryPtr &query) { send_request(make_object(), td::make_unique(std::move(query))); */ - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_proxies_query(PromisedQueryPtr &query) { send_request(make_object(), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_add_proxy_query(PromisedQueryPtr &query) { @@ -10262,7 +10668,7 @@ td::Status Client::process_add_proxy_query(PromisedQueryPtr &query) { TRY_RESULT(proxy_type, get_required_string_arg(query.get(), "type")); td::int32 port = get_integer_arg(query.get(), "port", 0, 0, 65535); if (!port) { - return Status::Error(400, PSLICE() << "Parameter port with a value between 1-65535 is required"); + return td::Status::Error(400, PSLICE() << "Parameter port with a value between 1-65535 is required"); } td_api::object_ptr type; @@ -10280,40 +10686,40 @@ td::Status Client::process_add_proxy_query(PromisedQueryPtr &query) { auto proxy_http = query->arg("http_only"); type = td_api::make_object(proxy_user.str(), proxy_pass.str(), to_bool(proxy_http)); } else { - return Status::Error(400, "Unsupported proxy type"); + return td::Status::Error(400, "Unsupported proxy type"); } send_request(make_object(server.str(), port, false, std::move(type)), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_proxy_query(PromisedQueryPtr &query) { auto arg_pid = query->arg("proxy_id"); if (arg_pid.empty()) { - return Status::Error(400, PSLICE() << "No proxy_id specified"); + return td::Status::Error(400, PSLICE() << "No proxy_id specified"); } send_request(make_object(td::to_integer(arg_pid)), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_enable_proxy_query(PromisedQueryPtr &query) { auto arg_pid = query->arg("proxy_id"); if (arg_pid.empty()) { - return Status::Error(400, PSLICE() << "No proxy_id specified"); + return td::Status::Error(400, PSLICE() << "No proxy_id specified"); } send_request(make_object(td::to_integer(arg_pid)), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_disable_proxy_query(PromisedQueryPtr &query) { send_request(make_object(), td::make_unique(std::move(query))); - return Status::OK(); + return td::Status::OK(); } //end custom methods impl //start custom user methods impl @@ -10324,7 +10730,7 @@ td::Status Client::process_get_chats_query(PromisedQueryPtr &query) { send_request(make_object(make_object(), limit), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_common_chats_query(PromisedQueryPtr &query) { @@ -10335,7 +10741,7 @@ td::Status Client::process_get_common_chats_query(PromisedQueryPtr &query) { send_request(make_object(user_id, offset_chat_id, limit), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_inactive_chats_query(PromisedQueryPtr &query) { @@ -10343,7 +10749,7 @@ td::Status Client::process_get_inactive_chats_query(PromisedQueryPtr &query) { send_request(make_object(), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_nearby_chats_query(PromisedQueryPtr &query) { @@ -10352,7 +10758,7 @@ td::Status Client::process_get_nearby_chats_query(PromisedQueryPtr &query) { send_request(make_object(std::move(location)), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_search_public_chats_query(PromisedQueryPtr &query) { @@ -10361,7 +10767,7 @@ td::Status Client::process_search_public_chats_query(PromisedQueryPtr &query) { send_request(make_object(query_.str()), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_set_poll_answer_query(PromisedQueryPtr &query) { @@ -10376,7 +10782,7 @@ td::Status Client::process_set_poll_answer_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_join_chat_query(PromisedQueryPtr &query) { @@ -10396,7 +10802,7 @@ td::Status Client::process_join_chat_query(PromisedQueryPtr &query) { fail_query(400, "Bad request: Please specify chat_id or invite_link", std::move(query)); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_add_chat_member_query(PromisedQueryPtr &query) { @@ -10416,7 +10822,7 @@ td::Status Client::process_add_chat_member_query(PromisedQueryPtr &query) { td::make_unique(std::move(query))); } }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_report_chat_query(PromisedQueryPtr &query) { @@ -10432,7 +10838,7 @@ td::Status Client::process_report_chat_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, std::move(message_ids), std::move(reason), reason->get_id() == td_api::chatReportReasonCustom::ID ? query->arg("reason").str() : td::string()), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_create_chat_query(PromisedQueryPtr &query) { @@ -10452,9 +10858,9 @@ td::Status Client::process_create_chat_query(PromisedQueryPtr &query) { send_request(make_object(std::move(initial_members), title.str(), message_auto_delete_time), td::make_unique(this, std::move(query))); } else { - return Status::Error(400, "Chat type is not specified"); + return td::Status::Error(400, "Chat type is not specified"); } - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_search_messages_query(PromisedQueryPtr &query) { @@ -10467,7 +10873,7 @@ td::Status Client::process_search_messages_query(PromisedQueryPtr &query) { send_request(make_object(nullptr, query_.str(), offset.str(), 100, std::move(filter), min_date, max_date), td::make_unique(this, std::move(query))); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_search_chat_messages_query(PromisedQueryPtr &query) { @@ -10489,7 +10895,7 @@ td::Status Client::process_search_chat_messages_query(PromisedQueryPtr &query) { from_message_id, 0, 100, std::move(filter), 0), td::make_unique(this, std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_callback_query_answer_query(PromisedQueryPtr &query) { @@ -10503,7 +10909,7 @@ td::Status Client::process_get_callback_query_answer_query(PromisedQueryPtr &que send_request(make_object(chat_id, message_id, std::move(payload)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_delete_chat_history_query(PromisedQueryPtr &query) { @@ -10517,7 +10923,7 @@ td::Status Client::process_delete_chat_history_query(PromisedQueryPtr &query) { send_request(make_object(chat_id, for_everyone, remove_from_chat_list), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_get_scheduled_messages_query(PromisedQueryPtr &query) { @@ -10527,7 +10933,7 @@ td::Status Client::process_get_scheduled_messages_query(PromisedQueryPtr &query) send_request(make_object(chat_id), td::make_unique(this, std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } td::Status Client::process_edit_message_scheduling_query(PromisedQueryPtr &query) { @@ -10540,7 +10946,7 @@ td::Status Client::process_edit_message_scheduling_query(PromisedQueryPtr &query send_request(make_object(chat_id, message_id, std::move(send_at)), td::make_unique(std::move(query))); }); - return Status::OK(); + return td::Status::OK(); } //end custom user methods impl @@ -10686,7 +11092,7 @@ void Client::webhook_success() { } } -void Client::webhook_error(Status status) { +void Client::webhook_error(td::Status status) { CHECK(status.is_error()); last_webhook_error_date_ = get_unix_time(); last_webhook_error_ = std::move(status); @@ -10701,7 +11107,7 @@ void Client::webhook_error(Status status) { } } -void Client::webhook_closed(Status status) { +void Client::webhook_closed(td::Status status) { if (has_webhook_certificate_) { td::Scheduler::instance()->run_on_scheduler(SharedData::get_database_scheduler_id(), [actor_id = actor_id(this), path = get_webhook_certificate_path(), @@ -10715,7 +11121,7 @@ void Client::webhook_closed(Status status) { on_webhook_closed(std::move(status)); } -void Client::on_webhook_closed(Status status) { +void Client::on_webhook_closed(td::Status status) { LOG(WARNING) << "Webhook closed: " << status << ", webhook_query_type = " << (webhook_query_type_ == WebhookQueryType::Verify ? "verify" : "change"); webhook_id_.release(); @@ -10727,7 +11133,7 @@ void Client::on_webhook_closed(Status status) { webhook_secret_token_ = td::string(); webhook_set_time_ = td::Time::now(); last_webhook_error_date_ = 0; - last_webhook_error_ = Status::OK(); + last_webhook_error_ = td::Status::OK(); parameters_->shared_data_->webhook_db_->erase(bot_token_with_dc_); if (webhook_set_query_) { @@ -10740,7 +11146,7 @@ void Client::on_webhook_closed(Status status) { } void Client::hangup_shared() { - webhook_closed(Status::Error("Unknown")); + webhook_closed(td::Status::Error("Unknown")); } td::string Client::get_webhook_certificate_path() const { @@ -10751,7 +11157,7 @@ const td::HttpFile *Client::get_webhook_certificate(const Query *query) const { auto file = query->file("certificate"); if (file == nullptr) { auto attach_name = query->arg("certificate"); - Slice attach_protocol{"attach://"}; + td::Slice attach_protocol{"attach://"}; if (td::begins_with(attach_name, attach_protocol)) { file = query->file(attach_name.substr(attach_protocol.size())); } @@ -10780,7 +11186,7 @@ void Client::do_set_webhook(PromisedQueryPtr query, bool was_deleted) { if (to_bool(query->arg("drop_pending_updates"))) { clear_tqueue(); } - Slice new_url; + td::Slice new_url; if (query->method() == "setwebhook") { new_url = query->arg("url"); } @@ -10829,11 +11235,11 @@ void Client::do_set_webhook(PromisedQueryPtr query, bool was_deleted) { finish_set_webhook(std::move(query)); } else { answer_query(td::JsonTrue(), std::move(query), - was_deleted ? Slice("Webhook was deleted") : Slice("Webhook is already deleted")); + was_deleted ? td::Slice("Webhook was deleted") : td::Slice("Webhook is already deleted")); } } -void Client::on_webhook_certificate_copied(Status status) { +void Client::on_webhook_certificate_copied(td::Status status) { CHECK(active_webhook_set_query_); if (status.is_error()) { return fail_query(500, "Internal Server Error: failed to save certificate", std::move(active_webhook_set_query_)); @@ -10849,7 +11255,7 @@ void Client::finish_set_webhook(PromisedQueryPtr query) { if (logging_out_ || closing_) { return fail_query_closing(std::move(query)); } - Slice new_url = query->arg("url"); + td::Slice new_url = query->arg("url"); CHECK(!new_url.empty()); webhook_url_ = new_url.str(); webhook_set_time_ = td::Time::now(); @@ -10858,7 +11264,7 @@ void Client::finish_set_webhook(PromisedQueryPtr query) { webhook_ip_address_ = query->arg("ip_address").str(); webhook_fix_ip_address_ = get_webhook_fix_ip_address(query.get()); last_webhook_error_date_ = 0; - last_webhook_error_ = Status::OK(); + last_webhook_error_ = td::Status::OK(); update_allowed_update_types(query.get()); @@ -10914,8 +11320,7 @@ void Client::do_send_message(object_ptr input_messa int64 reply_to_message_id, PromisedQueryPtr query) mutable { auto &count = yet_unsent_message_count_[chat_id]; if (count >= MAX_CONCURRENTLY_SENT_CHAT_MESSAGES) { - flood_limited_query_count_++; - return query->set_retry_after_error(60); + return fail_query_flood_limit_exceeded(std::move(query)); } count++; @@ -10968,18 +11373,18 @@ void Client::on_sent_message(object_ptr &&message, int64 query_ void Client::abort_long_poll(bool from_set_webhook) { if (long_poll_query_) { - Slice message; + td::Slice message; if (from_set_webhook) { - message = Slice("Conflict: terminated by setWebhook request"); + message = td::Slice("Conflict: terminated by setWebhook request"); } else { - message = - Slice("Conflict: terminated by other getUpdates request; make sure that only one bot instance is running"); + message = td::Slice( + "Conflict: terminated by other getUpdates request; make sure that only one bot instance is running"); } fail_query_conflict(message, std::move(long_poll_query_)); } } -void Client::fail_query_conflict(Slice message, PromisedQueryPtr &&query) { +void Client::fail_query_conflict(td::Slice message, PromisedQueryPtr &&query) { auto now = td::Time::now_cached(); if (now >= next_get_updates_conflict_time_) { fail_query(409, message, std::move(query)); @@ -11003,13 +11408,22 @@ void Client::fail_query_closing(PromisedQueryPtr &&query) { } } +void Client::fail_query_flood_limit_exceeded(PromisedQueryPtr &&query) { + flood_limited_query_count_++; + td::create_actor( + "FailQueryFloodLimitExceededActor", 3.0, + td::PromiseCreator::lambda( + [query = std::move(query)](td::Result result) mutable { query->set_retry_after_error(60); })) + .release(); +} + Client::ClosingError Client::get_closing_error() { ClosingError result; result.retry_after = 0; if (logging_out_) { if (is_api_id_invalid_) { result.code = 401; - result.message = Slice("Unauthorized: invalid api-id/api-hash"); + result.message = td::Slice("Unauthorized: invalid api-id/api-hash"); } else if (next_authorization_time_ > 0.0) { result.code = 429; result.retry_after = td::max(static_cast(next_authorization_time_ - td::Time::now()), 0) + 1; @@ -11020,24 +11434,24 @@ Client::ClosingError Client::get_closing_error() { result.message = retry_after_error_message; } else if (clear_tqueue_) { result.code = 400; - result.message = Slice("Logged out"); + result.message = td::Slice("Logged out"); } else { result.code = 401; - result.message = Slice("Unauthorized"); + result.message = td::Slice("Unauthorized"); } } else { CHECK(closing_); result.code = 500; - result.message = Slice("Internal Server Error: restart"); + result.message = td::Slice("Internal Server Error: restart"); } return result; } -class Client::JsonUpdates final : public Jsonable { +class Client::JsonUpdates final : public td::Jsonable { public: explicit JsonUpdates(td::Span updates) : updates_(updates) { } - void store(JsonValueScope *scope) const { + void store(td::JsonValueScope *scope) const { auto array = scope->enter_array(); int left_len = 1 << 22; for (auto &update : updates_) { @@ -11450,7 +11864,7 @@ void Client::json_store_file(td::JsonObjectScope &object, const td_api::file *fi object("file_path", td::JsonRawString(file->local_->path_)); } } else { - Slice relative_path = td::PathView::relative(file->local_->path_, dir_, true); + td::Slice relative_path = td::PathView::relative(file->local_->path_, dir_, true); if (!relative_path.empty() && (parameters_->local_mode_ || parameters_->no_file_limit_ || file->local_->downloaded_size_ <= MAX_DOWNLOAD_FILE_SIZE)) { object("file_path", relative_path); } @@ -11464,6 +11878,7 @@ void Client::json_store_thumbnail(td::JsonObjectScope &object, const td_api::thu } CHECK(thumbnail->file_->id_ > 0); + object("thumbnail", JsonThumbnail(thumbnail, this)); object("thumb", JsonThumbnail(thumbnail, this)); } @@ -11518,7 +11933,7 @@ void Client::json_store_permissions(td::JsonObjectScope &object, const td_api::c bool can_send_media_messages = permissions->can_send_audios_ || permissions->can_send_documents_ || permissions->can_send_photos_ || permissions->can_send_videos_ || permissions->can_send_video_notes_ || permissions->can_send_voice_notes_; - object("can_send_messages", td::JsonBool(permissions->can_send_messages_)); + object("can_send_messages", td::JsonBool(permissions->can_send_basic_messages_)); object("can_send_media_messages", td::JsonBool(can_send_media_messages)); object("can_send_audios", td::JsonBool(permissions->can_send_audios_)); object("can_send_documents", td::JsonBool(permissions->can_send_documents_)); @@ -11559,43 +11974,43 @@ void Client::json_store_user_status(td::JsonObjectScope &object, const td_api::U } } -Client::Slice Client::get_update_type_name(UpdateType update_type) { +td::Slice Client::get_update_type_name(UpdateType update_type) { switch (update_type) { case UpdateType::Message: - return Slice("message"); + return td::Slice("message"); case UpdateType::EditedMessage: - return Slice("edited_message"); + return td::Slice("edited_message"); case UpdateType::ChannelPost: - return Slice("channel_post"); + return td::Slice("channel_post"); case UpdateType::EditedChannelPost: - return Slice("edited_channel_post"); + return td::Slice("edited_channel_post"); case UpdateType::InlineQuery: - return Slice("inline_query"); + return td::Slice("inline_query"); case UpdateType::ChosenInlineResult: - return Slice("chosen_inline_result"); + return td::Slice("chosen_inline_result"); case UpdateType::CallbackQuery: - return Slice("callback_query"); + return td::Slice("callback_query"); case UpdateType::CustomEvent: - return Slice("custom_event"); + return td::Slice("custom_event"); case UpdateType::CustomQuery: - return Slice("custom_query"); + return td::Slice("custom_query"); case UpdateType::ShippingQuery: - return Slice("shipping_query"); + return td::Slice("shipping_query"); case UpdateType::PreCheckoutQuery: - return Slice("pre_checkout_query"); + return td::Slice("pre_checkout_query"); case UpdateType::Poll: - return Slice("poll"); + return td::Slice("poll"); case UpdateType::PollAnswer: - return Slice("poll_answer"); + return td::Slice("poll_answer"); case UpdateType::MyChatMember: - return Slice("my_chat_member"); + return td::Slice("my_chat_member"); case UpdateType::ChatMember: - return Slice("chat_member"); + return td::Slice("chat_member"); case UpdateType::ChatJoinRequest: - return Slice("chat_join_request"); + return td::Slice("chat_join_request"); default: UNREACHABLE(); - return Slice(); + return td::Slice(); } } @@ -11613,8 +12028,8 @@ td::uint32 Client::get_allowed_update_types(td::MutableSlice allowed_updates, bo td::uint32 result = 0; auto value = r_value.move_as_ok(); - if (value.type() != JsonValue::Type::Array) { - if (value.type() == JsonValue::Type::Number && is_internal) { + if (value.type() != td::JsonValue::Type::Array) { + if (value.type() == td::JsonValue::Type::Number && is_internal) { auto r_number = td::to_integer_safe(value.get_number()); if (r_number.is_ok() && r_number.ok() > 0) { return r_number.ok(); @@ -11623,7 +12038,7 @@ td::uint32 Client::get_allowed_update_types(td::MutableSlice allowed_updates, bo return 0; } for (auto &update_type_name : value.get_array()) { - if (update_type_name.type() != JsonValue::Type::String) { + if (update_type_name.type() != td::JsonValue::Type::String) { return 0; } auto type_name = update_type_name.get_string(); @@ -11663,7 +12078,7 @@ class UpdateJsonable final : public td::VirtuallyJsonable { public: explicit UpdateJsonable(const T &update) : update(update) { } - void store(JsonValueScope *scope) const final { + void store(td::JsonValueScope *scope) const final { *scope << update; } @@ -12083,18 +12498,18 @@ td::Slice Client::get_sticker_type(const object_ptr &type) CHECK(type != nullptr); switch (type->get_id()) { case td_api::stickerTypeRegular::ID: - return Slice("regular"); + return td::Slice("regular"); case td_api::stickerTypeMask::ID: - return Slice("mask"); + return td::Slice("mask"); case td_api::stickerTypeCustomEmoji::ID: - return Slice("custom_emoji"); + return td::Slice("custom_emoji"); default: UNREACHABLE(); - return Slice(); + return td::Slice(); } } -td::Result> Client::get_sticker_type(Slice type) { +td::Result> Client::get_sticker_type(td::Slice type) { if (type.empty() || type == "regular") { return make_object(); } @@ -12104,7 +12519,7 @@ td::Result> Client::get_sticker_type(Sli if (type == "custom_emoji") { return make_object(); } - return Status::Error(400, "Unsupported sticker type specified"); + return td::Status::Error(400, "Unsupported sticker type specified"); } td::CSlice Client::get_callback_data(const object_ptr &type) { @@ -12365,17 +12780,17 @@ td::unique_ptr Client::delete_message(int64 chat_id, int64 auto chat_info = get_chat(chat_id); CHECK(chat_info != nullptr); - Status error = - Status::Error(500, "Internal Server Error: sent message was immediately deleted and can't be returned"); + td::Status error = + td::Status::Error(500, "Internal Server Error: sent message was immediately deleted and can't be returned"); if (chat_info->type == ChatInfo::Type::Supergroup) { auto supergroup_info = get_supergroup_info(chat_info->supergroup_id); CHECK(supergroup_info != nullptr); if (supergroup_info->status->get_id() == td_api::chatMemberStatusBanned::ID || supergroup_info->status->get_id() == td_api::chatMemberStatusLeft::ID) { if (supergroup_info->is_supergroup) { - error = Status::Error(403, "Forbidden: bot is not a member of the supergroup chat"); + error = td::Status::Error(403, "Forbidden: bot is not a member of the supergroup chat"); } else { - error = Status::Error(403, "Forbidden: bot is not a member of the channel chat"); + error = td::Status::Error(403, "Forbidden: bot is not a member of the channel chat"); } } } @@ -12630,7 +13045,7 @@ td::string Client::get_passport_element_type(int32 id) { } } -td_api::object_ptr Client::get_passport_element_type(Slice type) { +td_api::object_ptr Client::get_passport_element_type(td::Slice type) { if (type == "personal_details") { return make_object(); } @@ -12710,22 +13125,22 @@ td::int64 Client::get_basic_group_chat_id(int64 basic_group_id) { constexpr Client::int64 Client::GENERAL_MESSAGE_THREAD_ID; constexpr Client::int64 Client::GREAT_MINDS_SET_ID; -constexpr Client::Slice Client::GREAT_MINDS_SET_NAME; +constexpr td::Slice Client::GREAT_MINDS_SET_NAME; -constexpr Client::Slice Client::MASK_POINTS[MASK_POINTS_SIZE]; +constexpr td::Slice Client::MASK_POINTS[MASK_POINTS_SIZE]; constexpr int Client::LOGGING_OUT_ERROR_CODE; -constexpr Client::Slice Client::LOGGING_OUT_ERROR_DESCRIPTION; -constexpr Client::Slice Client::API_ID_INVALID_ERROR_DESCRIPTION; +constexpr td::Slice Client::LOGGING_OUT_ERROR_DESCRIPTION; +constexpr td::Slice Client::API_ID_INVALID_ERROR_DESCRIPTION; constexpr int Client::CLOSING_ERROR_CODE; -constexpr Client::Slice Client::CLOSING_ERROR_DESCRIPTION; +constexpr td::Slice Client::CLOSING_ERROR_DESCRIPTION; constexpr int Client::BOT_ONLY_ERROR_CODE; -constexpr Client::Slice Client::BOT_ONLY_ERROR_DESCRIPTION; +constexpr td::Slice Client::BOT_ONLY_ERROR_DESCRIPTION; constexpr int Client::USER_ONLY_ERROR_CODE; -constexpr Client::Slice Client::USER_ONLY_ERROR_DESCRIPTION; +constexpr td::Slice Client::USER_ONLY_ERROR_DESCRIPTION; td::FlatHashMap Client::methods_; diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 8088e61..14c993a 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -60,9 +60,6 @@ class Client final : public WebhookActor::Callback { using int32 = td::int32; using int64 = td::int64; - using Slice = td::Slice; - using Status = td::Status; - template using object_ptr = td_api::object_ptr; @@ -78,26 +75,28 @@ class Client final : public WebhookActor::Callback { static constexpr std::size_t MIN_PENDING_UPDATES_WARNING = 200; static constexpr int64 GREAT_MINDS_SET_ID = 1842540969984001; - static constexpr Slice GREAT_MINDS_SET_NAME = "TelegramGreatMinds"; + static constexpr td::Slice GREAT_MINDS_SET_NAME = "TelegramGreatMinds"; static constexpr int32 MASK_POINTS_SIZE = 4; - static constexpr Slice MASK_POINTS[MASK_POINTS_SIZE] = {"forehead", "eyes", "mouth", "chin"}; + 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 Slice LOGGING_OUT_ERROR_DESCRIPTION = "Unauthorized"; - static constexpr Slice API_ID_INVALID_ERROR_DESCRIPTION = "Unauthorized: invalid api-id/api-hash"; + 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 Slice CLOSING_ERROR_DESCRIPTION = "Internal Server Error: restart"; + static constexpr td::Slice CLOSING_ERROR_DESCRIPTION = "Internal Server Error: restart"; static constexpr int BOT_ONLY_ERROR_CODE = 405; - static constexpr Slice BOT_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a bot"; + 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 Slice USER_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a user"; + static constexpr td::Slice USER_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a user"; class JsonEmptyObject; class JsonFile; @@ -151,6 +150,8 @@ class Client final : public WebhookActor::Callback { class JsonPreCheckoutQuery; class JsonBotCommand; class JsonBotMenuButton; + class JsonBotInfoDescription; + class JsonBotInfoShortDescription; class JsonChatAdministratorRights; class JsonChatPhotos; class JsonChatMember; @@ -173,6 +174,7 @@ class Client final : public WebhookActor::Callback { class JsonVideoChatEnded; class JsonInviteVideoChatParticipants; class JsonChatSetMessageAutoDeleteTime; + class JsonWriteAccessAllowed; class JsonUserShared; class JsonChatShared; class JsonUpdateTypes; @@ -212,6 +214,8 @@ class Client final : public WebhookActor::Callback { class TdOnGetMenuButtonCallback; class TdOnGetMyCommandsCallback; class TdOnGetMyDefaultAdministratorRightsCallback; + class TdOnGetMyDescriptionCallback; + class TdOnGetMyShortDescriptionCallback; class TdOnGetChatFullInfoCallback; class TdOnGetChatStickerSetCallback; class TdOnGetChatPinnedMessageCallback; @@ -316,18 +320,10 @@ class Client final : public WebhookActor::Callback { OnSuccess on_success) const; template - void check_chat(Slice chat_id_str, AccessRights access_rights, PromisedQueryPtr query, OnSuccess on_success); + void check_chat(td::Slice chat_id_str, AccessRights access_rights, PromisedQueryPtr query, OnSuccess on_success); template - void disable_internet_connection(PromisedQueryPtr query, OnSuccess on_success); - - template - void optimize_memory(PromisedQueryPtr query, OnSuccess on_success); - - void enable_internet_connection(PromisedQueryPtr query); - - template - void check_chat_no_fail(Slice chat_id_str, PromisedQueryPtr query, OnSuccess on_success); + void check_chat_no_fail(td::Slice chat_id_str, PromisedQueryPtr query, OnSuccess on_success); template void check_bot_command_scope(BotCommandScope &&scope, PromisedQueryPtr query, OnSuccess on_success); @@ -336,8 +332,8 @@ class Client final : public WebhookActor::Callback { void check_remote_file_id(td::string file_id, PromisedQueryPtr query, OnSuccess on_success); template - void check_message(Slice chat_id_str, int64 message_id, bool allow_empty, AccessRights access_rights, - Slice message_type, PromisedQueryPtr query, OnSuccess on_success); + 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 void check_message_thread(int64 chat_id, int64 message_thread_id, int64 reply_to_message_id, PromisedQueryPtr query, @@ -364,7 +360,7 @@ class Client final : public WebhookActor::Callback { void on_result(td::uint64 id, object_ptr result); void on_update_authorization_state(); - void log_out(int32 error_code, Slice error_message); + void log_out(int32 error_code, td::Slice error_message); void on_closed(); void finish_closing(); @@ -402,14 +398,20 @@ class Client final : public WebhookActor::Callback { static object_ptr get_chat_action(const Query *query); - static td::string get_local_file_path(Slice file_uri); + static td::string get_local_file_path(td::Slice file_uri); - object_ptr get_input_file(const Query *query, Slice field_name, bool force_file = false) const; + object_ptr get_input_file(const Query *query, td::Slice field_name, bool force_file = false) const; - object_ptr get_input_file(const Query *query, Slice field_name, Slice file_id, + object_ptr get_input_file(const Query *query, td::Slice field_name, td::Slice file_id, bool force_file) const; - object_ptr get_input_thumbnail(const Query *query, Slice field_name) const; + object_ptr get_input_thumbnail(const Query *query) const; + + static td::Result> get_inline_query_results_button( + td::JsonValue &&value); + + static td::Result> get_inline_query_results_button( + td::MutableSlice value); td::Result> get_inline_query_result(const Query *query); @@ -422,10 +424,10 @@ class Client final : public WebhookActor::Callback { struct BotCommandScope { object_ptr scope_; td::string chat_id_; - td::int64 user_id_ = 0; + int64 user_id_ = 0; explicit BotCommandScope(object_ptr scope, td::string chat_id = td::string(), - td::int64 user_id = 0) + int64 user_id = 0) : scope_(std::move(scope)), chat_id_(std::move(chat_id)), user_id_(user_id) { } }; @@ -446,7 +448,7 @@ class Client final : public WebhookActor::Callback { static td::Result> get_chat_administrator_rights(const Query *query); - static td::Result> get_mask_position(const Query *query, Slice field_name); + static td::Result> get_mask_position(const Query *query, td::Slice field_name); static td::Result> get_mask_position(td::JsonValue &&value); @@ -454,9 +456,22 @@ class Client final : public WebhookActor::Callback { static object_ptr mask_index_to_point(int32 index); - td::Result>> get_input_stickers(const Query *query) const; + static td::Result get_sticker_emojis(td::JsonValue &&value); - static td::Result get_passport_element_hash(Slice encoded_hash); + static td::Result get_sticker_emojis(td::MutableSlice emoji_list); + + static td::Result> get_sticker_format(td::Slice sticker_format); + + td::Result> get_input_sticker(const Query *query) const; + + td::Result> get_input_sticker(const Query *query, td::JsonValue &&value) const; + + td::Result>> get_input_stickers( + const Query *query, object_ptr &sticker_format) const; + + static td::Result> get_sticker_input_file(const Query *query); + + static td::Result get_passport_element_hash(td::Slice encoded_hash); static td::Result> get_passport_element_error_source( td::JsonObject &object); @@ -466,7 +481,7 @@ class Client final : public WebhookActor::Callback { static td::Result>> get_passport_element_errors( const Query *query); - static td::JsonValue get_input_entities(const Query *query, Slice field_name); + static td::JsonValue get_input_entities(const Query *query, td::Slice field_name); static td::Result> get_caption(const Query *query); @@ -492,10 +507,10 @@ class Client final : public WebhookActor::Callback { td::Result> get_input_media(const Query *query, td::JsonValue &&input_media, bool for_album) const; - td::Result> get_input_media(const Query *query, Slice field_name) const; + td::Result> get_input_media(const Query *query, td::Slice field_name) const; - td::Result>> get_input_message_contents(const Query *query, - Slice field_name) const; + td::Result>> get_input_message_contents( + const Query *query, td::Slice field_name) const; td::Result>> get_input_message_contents( const Query *query, td::JsonValue &&value) const; @@ -508,17 +523,18 @@ class Client final : public WebhookActor::Callback { static td::Result> get_poll_options(const Query *query); - static int32 get_integer_arg(const Query *query, Slice field_name, int32 default_value, + static int32 get_integer_arg(const Query *query, td::Slice field_name, int32 default_value, int32 min_value = std::numeric_limits::min(), int32 max_value = std::numeric_limits::max()); - static td::Result get_required_string_arg(const Query *query, Slice field_name); + static td::Result get_required_string_arg(const Query *query, td::Slice field_name); - static int64 get_message_id(const Query *query, Slice field_name = Slice("message_id")); + static int64 get_message_id(const Query *query, td::Slice field_name = td::Slice("message_id")); - static td::Result get_inline_message_id(const Query *query, Slice field_name = Slice("inline_message_id")); + static td::Result get_inline_message_id(const Query *query, + td::Slice field_name = td::Slice("inline_message_id")); - static td::Result get_user_id(const Query *query, Slice field_name = Slice("user_id")); + static td::Result 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); @@ -529,159 +545,168 @@ class Client final : public WebhookActor::Callback { static td::Result> get_message_scheduling_state(const Query *query); template - static td::Result> get_int_array_arg(const Query *query, Slice field_name, bool optional = false); + static td::Result> get_int_array_arg(const Query *query, td::Slice field_name, bool optional = false); - static int64 get_int64_arg(const Query *query, Slice field_name, int64 default_value, + static int64 get_int64_arg(const Query *query, td::Slice field_name, int64 default_value, int64 min_value = std::numeric_limits::min(), int64 max_value = std::numeric_limits::max()); static td::Result> get_report_reason(const Query *query, - Slice field_name = Slice("reason")); + td::Slice field_name = td::Slice("reason")); static td::Result> get_search_messages_filter( - const Query *query, Slice field_name = Slice("filter")); + const Query *query, td::Slice field_name = td::Slice("filter")); // end custom helper methods void on_message_send_succeeded(object_ptr &&message, int64 old_message_id); - void on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id, Status result); + void on_message_send_failed(int64 chat_id, int64 old_message_id, int64 new_message_id, td::Status result); static bool init_methods(); - static bool is_local_method(Slice method); + static bool is_local_method(td::Slice method); void on_cmd(PromisedQueryPtr query); - Status process_get_me_query(PromisedQueryPtr &query); - Status process_get_my_commands_query(PromisedQueryPtr &query); - Status process_set_my_commands_query(PromisedQueryPtr &query); - Status process_delete_my_commands_query(PromisedQueryPtr &query); - Status process_get_my_default_administrator_rights_query(PromisedQueryPtr &query); - Status process_set_my_default_administrator_rights_query(PromisedQueryPtr &query); - Status process_get_chat_menu_button_query(PromisedQueryPtr &query); - Status process_set_chat_menu_button_query(PromisedQueryPtr &query); - Status process_get_user_profile_photos_query(PromisedQueryPtr &query); - Status process_send_message_query(PromisedQueryPtr &query); - Status process_send_animation_query(PromisedQueryPtr &query); - Status process_send_audio_query(PromisedQueryPtr &query); - Status process_send_dice_query(PromisedQueryPtr &query); - Status process_send_document_query(PromisedQueryPtr &query); - Status process_send_photo_query(PromisedQueryPtr &query); - Status process_send_sticker_query(PromisedQueryPtr &query); - Status process_send_video_query(PromisedQueryPtr &query); - Status process_send_video_note_query(PromisedQueryPtr &query); - Status process_send_voice_query(PromisedQueryPtr &query); - Status process_send_game_query(PromisedQueryPtr &query); - Status process_send_invoice_query(PromisedQueryPtr &query); - Status process_send_location_query(PromisedQueryPtr &query); - Status process_send_venue_query(PromisedQueryPtr &query); - Status process_send_contact_query(PromisedQueryPtr &query); - Status process_send_poll_query(PromisedQueryPtr &query); - Status process_stop_poll_query(PromisedQueryPtr &query); - Status process_copy_message_query(PromisedQueryPtr &query); - Status process_forward_message_query(PromisedQueryPtr &query); - Status process_send_media_group_query(PromisedQueryPtr &query); - Status process_send_chat_action_query(PromisedQueryPtr &query); - Status process_edit_message_text_query(PromisedQueryPtr &query); - Status process_edit_message_live_location_query(PromisedQueryPtr &query); - Status process_edit_message_media_query(PromisedQueryPtr &query); - Status process_edit_message_caption_query(PromisedQueryPtr &query); - Status process_edit_message_reply_markup_query(PromisedQueryPtr &query); - Status process_delete_message_query(PromisedQueryPtr &query); - Status process_create_invoice_link_query(PromisedQueryPtr &query); - Status process_set_game_score_query(PromisedQueryPtr &query); - Status process_get_game_high_scores_query(PromisedQueryPtr &query); - Status process_answer_web_app_query_query(PromisedQueryPtr &query); - Status process_answer_inline_query_query(PromisedQueryPtr &query); - Status process_answer_callback_query_query(PromisedQueryPtr &query); - Status process_answer_shipping_query_query(PromisedQueryPtr &query); - Status process_answer_pre_checkout_query_query(PromisedQueryPtr &query); - Status process_export_chat_invite_link_query(PromisedQueryPtr &query); - Status process_create_chat_invite_link_query(PromisedQueryPtr &query); - Status process_edit_chat_invite_link_query(PromisedQueryPtr &query); - Status process_revoke_chat_invite_link_query(PromisedQueryPtr &query); - Status process_get_chat_query(PromisedQueryPtr &query); - Status process_set_chat_photo_query(PromisedQueryPtr &query); - Status process_delete_chat_photo_query(PromisedQueryPtr &query); - Status process_set_chat_title_query(PromisedQueryPtr &query); - Status process_set_chat_permissions_query(PromisedQueryPtr &query); - Status process_set_chat_description_query(PromisedQueryPtr &query); - Status process_pin_chat_message_query(PromisedQueryPtr &query); - Status process_unpin_chat_message_query(PromisedQueryPtr &query); - Status process_unpin_all_chat_messages_query(PromisedQueryPtr &query); - Status process_set_chat_sticker_set_query(PromisedQueryPtr &query); - Status process_delete_chat_sticker_set_query(PromisedQueryPtr &query); - Status process_get_forum_topic_icon_stickers_query(PromisedQueryPtr &query); - Status process_create_forum_topic_query(PromisedQueryPtr &query); - Status process_edit_forum_topic_query(PromisedQueryPtr &query); - Status process_close_forum_topic_query(PromisedQueryPtr &query); - Status process_reopen_forum_topic_query(PromisedQueryPtr &query); - Status process_delete_forum_topic_query(PromisedQueryPtr &query); - Status process_unpin_all_forum_topic_messages_query(PromisedQueryPtr &query); - Status process_edit_general_forum_topic_query(PromisedQueryPtr &query); - Status process_close_general_forum_topic_query(PromisedQueryPtr &query); - Status process_reopen_general_forum_topic_query(PromisedQueryPtr &query); - Status process_hide_general_forum_topic_query(PromisedQueryPtr &query); - Status process_unhide_general_forum_topic_query(PromisedQueryPtr &query); - Status process_get_chat_member_query(PromisedQueryPtr &query); - Status process_get_chat_administrators_query(PromisedQueryPtr &query); - Status process_get_chat_member_count_query(PromisedQueryPtr &query); - Status process_optimize_memory_query(PromisedQueryPtr &query); - Status process_leave_chat_query(PromisedQueryPtr &query); - Status process_promote_chat_member_query(PromisedQueryPtr &query); - Status process_set_chat_administrator_custom_title_query(PromisedQueryPtr &query); - Status process_ban_chat_member_query(PromisedQueryPtr &query); - Status process_restrict_chat_member_query(PromisedQueryPtr &query); - Status process_unban_chat_member_query(PromisedQueryPtr &query); - Status process_ban_chat_sender_chat_query(PromisedQueryPtr &query); - Status process_unban_chat_sender_chat_query(PromisedQueryPtr &query); - Status process_approve_chat_join_request_query(PromisedQueryPtr &query); - Status process_decline_chat_join_request_query(PromisedQueryPtr &query); - Status process_get_sticker_set_query(PromisedQueryPtr &query); - Status process_get_custom_emoji_stickers_query(PromisedQueryPtr &query); - Status process_upload_sticker_file_query(PromisedQueryPtr &query); - Status process_create_new_sticker_set_query(PromisedQueryPtr &query); - Status process_add_sticker_to_set_query(PromisedQueryPtr &query); - Status process_set_sticker_set_thumb_query(PromisedQueryPtr &query); - Status process_set_sticker_position_in_set_query(PromisedQueryPtr &query); - Status process_delete_sticker_from_set_query(PromisedQueryPtr &query); - Status process_set_passport_data_errors_query(PromisedQueryPtr &query); - Status process_send_custom_request_query(PromisedQueryPtr &query); - Status process_answer_custom_query_query(PromisedQueryPtr &query); - Status process_get_updates_query(PromisedQueryPtr &query); - Status process_set_webhook_query(PromisedQueryPtr &query); - Status process_get_webhook_info_query(PromisedQueryPtr &query); - Status process_get_file_query(PromisedQueryPtr &query); + 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_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_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_forward_message_query(PromisedQueryPtr &query); + td::Status process_send_media_group_query(PromisedQueryPtr &query); + td::Status process_send_chat_action_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_create_invoice_link_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_edit_chat_invite_link_query(PromisedQueryPtr &query); + td::Status process_revoke_chat_invite_link_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_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_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_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 - Status process_get_message_info_query(PromisedQueryPtr &query); - Status process_get_chat_members_query(PromisedQueryPtr &query); - Status process_delete_messages_query(PromisedQueryPtr &query); - Status process_toggle_group_invites_query(PromisedQueryPtr &query); - Status process_ping_query(PromisedQueryPtr &query); - Status process_get_memory_stats_query(PromisedQueryPtr &query); - Status process_get_proxies_query(PromisedQueryPtr &query); - Status process_add_proxy_query(PromisedQueryPtr &query); - Status process_delete_proxy_query(PromisedQueryPtr &query); - Status process_enable_proxy_query(PromisedQueryPtr &query); - Status process_disable_proxy_query(PromisedQueryPtr &query); + td::Status process_get_message_info_query(PromisedQueryPtr &query); + td::Status process_get_chat_members_query(PromisedQueryPtr &query); + td::Status process_delete_messages_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); //custom user methods - Status process_get_chats_query(PromisedQueryPtr &query); - Status process_get_common_chats_query(PromisedQueryPtr &query); - Status process_get_inactive_chats_query(PromisedQueryPtr &query); - Status process_get_nearby_chats_query(PromisedQueryPtr &query); - Status process_search_public_chats_query(PromisedQueryPtr &query); - Status process_set_poll_answer_query(PromisedQueryPtr &query); - Status process_join_chat_query(PromisedQueryPtr &query); - Status process_add_chat_member_query(PromisedQueryPtr &query); - Status process_report_chat_query(PromisedQueryPtr &query); - Status process_create_chat_query(PromisedQueryPtr &query); - Status process_search_messages_query(PromisedQueryPtr &query); - Status process_search_chat_messages_query(PromisedQueryPtr &query); - Status process_get_callback_query_answer_query(PromisedQueryPtr &query); - Status process_delete_chat_history_query(PromisedQueryPtr &query); - Status process_get_scheduled_messages_query(PromisedQueryPtr &query); - Status process_edit_message_scheduling_query(PromisedQueryPtr &query); + 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); @@ -692,19 +717,19 @@ class Client final : public WebhookActor::Callback { void webhook_verified(td::string cached_ip_address) final; void webhook_success() final; - void webhook_error(Status status) final; - void webhook_closed(Status status) 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(Status status); + 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(Status status); + void on_webhook_closed(td::Status status); void do_send_message(object_ptr input_message_content, PromisedQueryPtr query); @@ -729,22 +754,24 @@ class Client final : public WebhookActor::Callback { void fail_query_closing(PromisedQueryPtr &&query); - void fail_query_conflict(Slice message, 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; - Slice message; + td::Slice message; }; ClosingError get_closing_error(); - static int get_retry_after_time(Slice error_message); + static int get_retry_after_time(td::Slice error_message); - static void fail_query_with_error(PromisedQueryPtr query, int32 error_code, Slice error_message, - Slice default_message = Slice()); + 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 error, - Slice default_message = Slice()); + td::Slice default_message = td::Slice()); class JsonUpdates; void do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQueryPtr query); @@ -920,9 +947,9 @@ class Client final : public WebhookActor::Callback { void set_message_reply_to_message_id(MessageInfo *message_info, int64 reply_to_message_id); - static Slice get_sticker_type(const object_ptr &type); + static td::Slice get_sticker_type(const object_ptr &type); - static td::Result> get_sticker_type(Slice type); + static td::Result> get_sticker_type(td::Slice type); static td::CSlice get_callback_data(const object_ptr &type); @@ -982,8 +1009,7 @@ class Client final : public WebhookActor::Callback { struct FullMessageIdHash { td::uint32 operator()(FullMessageId full_message_id) const { - return td::Hash()(full_message_id.chat_id) * 2023654985u + - td::Hash()(full_message_id.message_id); + return td::Hash()(full_message_id.chat_id) * 2023654985u + td::Hash()(full_message_id.message_id); } }; @@ -1058,7 +1084,7 @@ class Client final : public WebhookActor::Callback { Size }; - static Slice get_update_type_name(UpdateType update_type); + static td::Slice get_update_type_name(UpdateType update_type); static td::uint32 get_allowed_update_types(td::MutableSlice allowed_updates, bool is_internal); @@ -1080,7 +1106,7 @@ class Client final : public WebhookActor::Callback { static td::string get_passport_element_type(int32 id); - static object_ptr get_passport_element_type(Slice type); + static object_ptr get_passport_element_type(td::Slice type); bool have_message_access(int64 chat_id) const; @@ -1117,7 +1143,7 @@ class Client final : public WebhookActor::Callback { int64 channel_bot_user_id_ = 0; int64 service_notifications_user_id_ = 0; - static td::FlatHashMap methods_; + static td::FlatHashMap methods_; td::WaitFreeHashMap, FullMessageIdHash> messages_; td::WaitFreeHashMap> users_; @@ -1226,7 +1252,7 @@ class Client final : public WebhookActor::Callback { bool webhook_fix_ip_address_ = false; td::string webhook_secret_token_; int32 last_webhook_error_date_ = 0; - Status last_webhook_error_; + 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; diff --git a/telegram-bot-api/HttpServer.h b/telegram-bot-api/HttpServer.h index d5f0008..8686a3f 100644 --- a/telegram-bot-api/HttpServer.h +++ b/telegram-bot-api/HttpServer.h @@ -12,6 +12,7 @@ #include "td/actor/actor.h" #include "td/utils/BufferedFd.h" +#include "td/utils/common.h" #include "td/utils/FloodControlFast.h" #include "td/utils/format.h" #include "td/utils/logging.h" @@ -47,7 +48,7 @@ class HttpServer final : public td::TcpListener::Callback { return; } flood_control_.add_event(now); - LOG(INFO) << "Create tcp listener " << td::tag("address", ip_address_) << td::tag("port", port_); + LOG(INFO) << "Create TCP listener " << td::tag("address", ip_address_) << td::tag("port", port_); listener_ = td::create_actor( PSLICE() << "TcpListener" << td::tag("address", ip_address_) << td::tag("port", port_), port_, actor_shared(this, 1), ip_address_); @@ -66,7 +67,7 @@ class HttpServer final : public td::TcpListener::Callback { scheduler_id--; } td::create_actor("HttpInboundConnection", td::BufferedFd(std::move(fd)), 0, - 20, 500, creator_(), scheduler_id) + 50, 500, creator_(), scheduler_id) .release(); } diff --git a/telegram-bot-api/Stats.cpp b/telegram-bot-api/Stats.cpp index 014568c..5dc08dd 100644 --- a/telegram-bot-api/Stats.cpp +++ b/telegram-bot-api/Stats.cpp @@ -187,13 +187,18 @@ td::vector BotStatActor::get_jsonable_description() const { double BotStatActor::get_score(double now) { auto minute_stat = stat_[2].stat_duration(now); - double result = minute_stat.first.request_count_ + minute_stat.first.update_count_; + double minute_score = minute_stat.first.request_count_ + minute_stat.first.update_count_; if (minute_stat.second != 0) { - result /= minute_stat.second; + minute_score /= minute_stat.second; } - result += td::max(static_cast(get_active_request_count() - 10), static_cast(0)); - result += static_cast(get_active_file_upload_bytes()) * 1e-8; - return result; + auto all_time_stat = stat_[0].stat_duration(now); + double all_time_score = 0.01 * (all_time_stat.first.request_count_ + all_time_stat.first.update_count_); + if (all_time_stat.second != 0) { + all_time_score /= all_time_stat.second; + } + auto active_request_score = static_cast(td::max(get_active_request_count() - 10, static_cast(0))); + auto active_file_upload_score = static_cast(get_active_file_upload_bytes()) * 1e-8; + return minute_score + all_time_score + active_request_score + active_file_upload_score; } double BotStatActor::get_minute_update_count(double now) { diff --git a/telegram-bot-api/WebhookActor.cpp b/telegram-bot-api/WebhookActor.cpp index af97634..630cb83 100644 --- a/telegram-bot-api/WebhookActor.cpp +++ b/telegram-bot-api/WebhookActor.cpp @@ -229,7 +229,7 @@ td::Status WebhookActor::create_connection(td::BufferedFd fd) { auto id = connections_.create(Connection()); auto *conn = connections_.get(id); conn->actor_id_ = td::create_actor( - PSLICE() << "Connect:" << id, std::move(fd), std::move(ssl_stream), 0, 20, 60, + PSLICE() << "Connect:" << id, std::move(fd), std::move(ssl_stream), 0, 50, 60, td::ActorShared(actor_id(this), id), slow_scheduler_id_); conn->ip_generation_ = ip_generation_; conn->event_id_ = {}; @@ -399,7 +399,7 @@ void WebhookActor::load_updates() { CHECK(update.id.is_valid()); auto &dest_ptr = update_map_[update.id]; if (dest_ptr != nullptr) { - LOG(ERROR) << "Receive duplicated event " << update.id << " from TQueue"; + LOG(ERROR) << "Receive duplicate event " << update.id << " from TQueue"; continue; } dest_ptr = td::make_unique(); diff --git a/telegram-bot-api/telegram-bot-api.cpp b/telegram-bot-api/telegram-bot-api.cpp index 363101f..6b3ef31 100644 --- a/telegram-bot-api/telegram-bot-api.cpp +++ b/telegram-bot-api/telegram-bot-api.cpp @@ -165,7 +165,7 @@ int main(int argc, char *argv[]) { auto start_time = td::Time::now(); auto shared_data = std::make_shared(); auto parameters = std::make_unique(); - parameters->version_ = "6.5"; + parameters->version_ = "6.6"; parameters->shared_data_ = shared_data; parameters->start_time_ = start_time; auto net_query_stats = td::create_net_query_stats();