diff --git a/Delphinus.Info.json b/Delphinus.Info.json index ae39c22..2a771f4 100644 --- a/Delphinus.Info.json +++ b/Delphinus.Info.json @@ -12,7 +12,7 @@ "dependencies": [], "author": "M.E.Sysoev", "description": "Telegram Bot API for Delphi", - "version": "3.5.0", + "version": "3.5.1", "first_version": "2.3.1", "project_url": "https://github.com/ms301/TelegAPI", "homepage_url": "https://t.me/telegaPiBotTest", diff --git a/Demo/Console/ConsoleBot.dproj b/Demo/Console/ConsoleBot.dproj index 9c7c9bb..559b537 100644 --- a/Demo/Console/ConsoleBot.dproj +++ b/Demo/Console/ConsoleBot.dproj @@ -37,7 +37,7 @@ ..\..\dcu\$(Platform)-$(Config) false - ..\..\Bin\$(Platform)-$(Config) + ..\..\..\Bin\$(Platform)-$(Config) false false false diff --git a/Demo/EchoBot/EchoBot.Main.fmx b/Demo/EchoBot/EchoBot.Main.fmx index 487a3d9..acd1742 100644 --- a/Demo/EchoBot/EchoBot.Main.fmx +++ b/Demo/EchoBot/EchoBot.Main.fmx @@ -44,7 +44,6 @@ object Main: TMain Touch.InteractiveGestures = [LongTap, DoubleTap] Align = Client TabOrder = 1 - Text = '283107814:AAF9VZC6TRv6qKmOMCsLFoI8SBlV_xFMI80' Margins.Right = 5.000000000000000000 Size.Width = 346.000000000000000000 Size.Height = 23.000000000000000000 diff --git a/Demo/EchoBot/EchoBot.Main.pas b/Demo/EchoBot/EchoBot.Main.pas index 17e8499..2652ed9 100644 --- a/Demo/EchoBot/EchoBot.Main.pas +++ b/Demo/EchoBot/EchoBot.Main.pas @@ -56,6 +56,7 @@ TMain = class(TForm) procedure ParseTextMessage(Msg: ITgMessage); procedure ParsePhotoMessage(Msg: ITgMessage); procedure ParseLocationMessage(Msg: ITgMessage); + procedure ParseContactMessage(Msg: ITgMessage); public { Public declarations } end; @@ -79,6 +80,11 @@ procedure TMain.FormClose(Sender: TObject; var Action: TCloseAction); tgReceiverUI1.IsActive := False; end; +procedure TMain.ParseContactMessage(Msg: ITgMessage); +begin + WriteLine('Contact: ' + Msg.Contact.LastName + ' ' + Msg.Contact.FirstName + ' ' + Msg.Contact.PhoneNumber); +end; + procedure TMain.ParseLocationMessage(Msg: ITgMessage); begin WriteLine('Location: ' + Msg.Location.Longitude.ToString + ' ' + Msg.Location.Latitude.ToString); @@ -150,9 +156,7 @@ procedure TMain.swtchTokenSwitch(Sender: TObject); procedure TMain.SendPhoto(Msg: ITgMessage); const - PATH_PHOTO = 'C:\Users\Public\Pictures\Sample Pictures\Tulips.jpg'; -var - LFile: TtgFileToSend; + PATH_PHOTO = 'Photo.png'; begin tgBot.SendChatAction(Msg.Chat.Id, TtgSendChatAction.UploadPhoto); if not TFile.Exists(PATH_PHOTO) then @@ -160,12 +164,7 @@ procedure TMain.SendPhoto(Msg: ITgMessage); WriteLine('Change path to photo in metod: TMain.SendPhoto'); Exit; end; - LFile := TtgFileToSend.Create(PATH_PHOTO); - try - tgBot.SendPhoto(Msg.Chat.Id, LFile, 'Nice Picture'); - finally - LFile.Free; - end; + tgBot.SendPhoto(Msg.Chat.Id, TtgFileToSend.FromFile(PATH_PHOTO), 'Nice Picture'); end; procedure TMain.SendInline; @@ -264,6 +263,8 @@ procedure TMain.tgReceiverUI1Message(ASender: TObject; AMessage: ITgMessage); ParsePhotoMessage(AMessage); TtgMessageType.LocationMessage: ParseLocationMessage(AMessage); + TtgMessageType.ContactMessage: + ParseContactMessage(AMessage); end; end; diff --git a/Demo/EchoBot/EchoBot.dproj b/Demo/EchoBot/EchoBot.dproj index 5110a64..bde90b4 100644 --- a/Demo/EchoBot/EchoBot.dproj +++ b/Demo/EchoBot/EchoBot.dproj @@ -70,7 +70,7 @@ true ..\..\DCU\$(Platform)-$(Config) false - ..\..\Bin\$(Platform)-$(Config) + ..\..\..\Bin\$(Platform)-$(Config) false false false @@ -101,7 +101,6 @@ Debug - ..\bin\$(Platform)-$(Config) Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;svnui;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;TelegaPiBot;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) $(BDS)\bin\default_app.manifest @@ -175,8 +174,6 @@ Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components - Component Tray - (untitled) diff --git a/Install/TelegaPi.dpk b/Install/TelegaPi.dpk index dab6d72..fa359db 100644 --- a/Install/TelegaPi.dpk +++ b/Install/TelegaPi.dpk @@ -31,7 +31,8 @@ package TelegaPi; requires rtl, - RESTComponents; + RESTComponents, + fmx; contains TelegAPI.Base in '..\Source\TelegAPI.Base.pas', @@ -50,8 +51,11 @@ contains TelegAPi.Types in '..\Source\TelegAPi.Types.pas', TelegaPi.Types.ReplyMarkups in '..\Source\TelegaPi.Types.ReplyMarkups.pas', TelegAPI.Utils.Json in '..\Source\TelegAPI.Utils.Json.pas', - TelegAPI.Utils.Params in '..\Source\TelegAPI.Utils.Params.pas', + TelegAPI.CoreAPI.ParameterConverter in '..\Source\TelegAPI.CoreAPI.ParameterConverter.pas', TelegAPI.Receiver.UI in '..\Source\TelegAPI.Receiver.UI.pas', - TelegaPi.Factory in '..\Source\TelegaPi.Factory.pas'; + TelegaPi.Factory in '..\Source\TelegaPi.Factory.pas', + TelegAPi.CoreAPI.Request in '..\Source\TelegAPi.CoreAPI.Request.pas', + TelegAPi.CoreAPI.Parameter in '..\Source\TelegAPi.CoreAPI.Parameter.pas', + TelegaPi.Ext.Sessions in '..\Source\TelegaPi.Ext.Sessions.pas'; end. diff --git a/Install/TelegaPi.dproj b/Install/TelegaPi.dproj index 0a16b75..d6edbff 100644 --- a/Install/TelegaPi.dproj +++ b/Install/TelegaPi.dproj @@ -69,23 +69,33 @@ $(PreBuildEvent)]]> None rtl;fmx;RESTComponents;$(DCC_UsePackage) android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar + true + 1 package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= Debug Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) rtl;fmx;RESTComponents;$(DCC_UsePackage) + true true - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + CompanyName=Maxim Sysoev;FileDescription=$(MSBuildProjectName);FileVersion=3.5.1.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 1033 + 3 + 5 + 1 Debug Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) rtl;fmx;RESTComponents;$(DCC_UsePackage) + true true - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + CompanyName=Maxim Sysoev;FileDescription=$(MSBuildProjectName);FileVersion=3.5.1.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 1033 + 3 + 5 + 1 true @@ -113,6 +123,7 @@ $(PreBuildEvent)]]> + @@ -123,15 +134,18 @@ $(PreBuildEvent)]]> - + - + + + + Base @@ -155,7 +169,6 @@ $(PreBuildEvent)]]> Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components - (untitled) diff --git a/README.md b/README.md index 0484c9e..ee8641b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Telega π - Library for working with Telegram Bot API in Delphi -Version Bot API: *3.5.0* +Version Bot API: *3.5.1* ## Support project @@ -50,7 +50,7 @@ as well as many others who ask / suggest features / points bugs. Telega π - Библиотека для работы с Telegram Bot API в Delphi -Версия Bot API: *3.5.0* +Версия Bot API: *3.5.1* ## Помощь проекту diff --git a/Source/TelegAPI.Base.pas b/Source/TelegAPI.Base.pas index 81adddb..c24d44a 100644 --- a/Source/TelegAPI.Base.pas +++ b/Source/TelegAPI.Base.pas @@ -28,7 +28,7 @@ constructor TtgAbstractComponent.Create(AOwner: TComponent); begin inherited; FAutor := 'Maxim Sysoev'; - FVersion := '3.5.0'; + FVersion := '3.5.1'; end; end. diff --git a/Source/TelegAPI.Bot.Impl.pas b/Source/TelegAPI.Bot.Impl.pas index 3fe7561..4606a61 100644 --- a/Source/TelegAPI.Bot.Impl.pas +++ b/Source/TelegAPI.Bot.Impl.pas @@ -12,6 +12,7 @@ interface System.Net.HttpClient, System.Generics.Collections, TelegAPI.Base, + TelegAPI.CoreAPI.Parameter, TelegAPI.Bot, TelegAPI.Types, TelegAPI.Types.Impl, @@ -19,7 +20,6 @@ interface TelegAPI.Types.ReplyMarkups, TelegAPI.Types.InlineQueryResults, TelegAPI.Exceptions, - TelegAPI.Utils.Params, TelegAPI.Utils.Json, System.Json; @@ -31,221 +31,41 @@ TTelegramBot = class(TtgAbstractComponent, ITelegramBot) FToken: string; FProxySettings: TProxySettings; FOnRawData: TtgOnReceiveRawData; - FParamLoader: TtgParamLoader; FExceptionManager: ItgExceptionHandler; function GetToken: string; procedure SetToken(const Value: string); // Returns TJSONValue as method request result - function GetJSONFromMethod(const Method: string; const Parameters: TDictionary): TJSONValue; + function GetJSONFromMethod(const AValue: string): TJSONValue; // Returns TJSONArray as method request result - function GetJSONArrayFromMethod(const Method: string; const Parameters: TDictionary): TJSONArray; + function GetJSONArrayFromMethod(const AValue: string): TJSONArray; // Returns true when given Method executed successfully - function ExecuteMethod(const Method: string; const Parameters: TDictionary): Boolean; + function ExtractBool(const AValue: string): Boolean; // Returns response JSON from server as result of request - function GetArrayFromMethod(const TgClass: TBaseJsonClass; const Method: string; const Parameters: TDictionary): TArray; - function GetValueFromMethod(const Method: string; const Parameters: TDictionary): string; + function GetArrayFromMethod(const TgClass: TBaseJsonClass; const AValue: string): TArray; + function GetValueFromMethod(const AValue: string): string; function GetExceptionManager: ItgExceptionHandler; procedure SetExceptionManager(const Value: ItgExceptionHandler); protected - /// - /// Мастер-функция для запросов на сервак - /// - function RequestAPI(const Method: string; const Parameters: TDictionary): string; - function SendDataToServer(const Method: string; const Parameters: TDictionary): string; - function ParamsToFormData(const Parameters: TDictionary): TMultipartFormData; + function RequestAPI(const Method: string; const Parameters: TArray): string; + function ApiTest(const ARequest: string; const Parameters: TArray = nil): string; public - function ApiTest(const ARequest: string; const Parameters: TDictionary = nil): string; - constructor Create(AOwner: TComponent); overload; override; - destructor Destroy; override; - {$REGION 'Getting updates'} - /// - /// - /// Используйте этот метод для получения обновлений используя long - /// polling. - /// - /// - /// Use this method to receive incoming updates using long polling. - /// - /// - /// - /// Identifier of the first update to be returned. Must be greater by one - /// than the highest among the identifiers of previously received - /// updates. By default, updates starting with the earliest unconfirmed - /// update are returned. An update is considered confirmed as soon as - /// getUpdates is called with an offset higher than its update_id. - /// The negative offset can be specified to retrieve updates starting - /// from -offset update from the end of the updates queue. All previous - /// updates will forgotten. - /// - /// - /// Количество обновлений которые могут прийти в одном запросе. - /// Допустимое значение от 1 до 100. По умолчанию - 100.Limits the number - /// of updates to be retrieved. Values between 1—100 are accepted. - /// Defaults to 100. - /// - /// - /// Timeout in seconds for long polling. Defaults to 0, i.e. usual short - /// polling - /// - /// - /// List the types of updates you want your bot to receive. For example, - /// specify [“message”, “edited_channel_post”, “callback_query”] to only - /// receive updates of these types. See Update for a complete list of - /// available update types. Specify an empty list to receive all updates - /// regardless of type (default). If not specified, the previous setting - /// will be used.

Please note that this parameter doesn't - /// affect updates created before the call to the getUpdates, so unwanted - /// updates may be received for a short period of time. - /// - /// - /// An Array of Update objects is returned. - /// - /// - /// 1. This method will not work if an outgoing webhook is set up. 2. In - /// order to avoid getting duplicate updates, recalculate offset after - /// each server response. - /// +{$REGION 'Getting updates'} function GetUpdates(// const Offset: Int64 = 0; // const Limit: Int64 = 100; // const Timeout: Int64 = 0; // const AllowedUpdates: TAllowedUpdates = UPDATES_ALLOWED_ALL): TArray; - /// - /// Use this method to specify a url and receive incoming updates via an - /// outgoing webhook. Whenever there is an update for the bot, we will - /// send an HTTPS POST request to the specified url, containing a - /// JSON-serialized Update. In case of an unsuccessful request, we will - /// give up after a reasonable amount of attempts. - /// - /// - /// HTTPS url to send updates to. Use an empty string to remove webhook - /// integration - /// - /// - /// Upload your public key certificate so that the root certificate in - /// use can be checked. See our self-signed guide for details. - /// - /// - /// Maximum allowed number of simultaneous HTTPS connections to the - /// webhook for update delivery, 1-100. Defaults to 40. Use lower values - /// to limit the load on your bot‘s server, and higher values to increase - /// your bot’s throughput. - /// - /// - /// List the types of updates you want your bot to receive. For example, - /// specify [“message”, “edited_channel_post”, “callback_query”] to only - /// receive updates of these types. See Update for a complete list of - /// available update types. Specify an empty list to receive all updates - /// regardless of type (default). If not specified, the previous setting - /// will be used.

Please note that this parameter doesn't - /// affect updates created before the call to the setWebhook, so unwanted - /// updates may be received for a short period of time. - /// - /// - /// - /// Notes - /// - /// - /// 1. You will not be able to receive updates using - /// getUpdates for as long as an outgoing webhook is set up. - /// - /// - /// 2. To use a self-signed certificate, you need to upload your - /// public key certificate using certificate parameter. - /// Please upload as InputFile, sending a String will not work. - /// - /// - /// 3. Ports currently supported for Webhooks: 443, 80, 88, 8443 - /// . - /// - /// - /// NEW! If you're having any trouble setting up webhooks, - /// please check out this - /// amazing guide to Webhooks. - /// - /// function SetWebhook(// const Url: string; // const Certificate: TtgFileToSend = nil; // const MaxConnections: Int64 = 40; // const AllowedUpdates: TAllowedUpdates = UPDATES_ALLOWED_ALL): Boolean; - /// - /// Use this method to remove webhook integration if you decide to switch - /// back to - /// getUpdates. - /// - /// - /// Returns True on success. - /// function DeleteWebhook: Boolean; - - /// - /// Use this method to get current webhook status. - /// - /// - /// On success, returns a - /// WebhookInfo object - /// - /// - /// If the bot is using - /// getUpdates, will return an object with the url field empty - /// function GetWebhookInfo: ItgWebhookInfo; {$ENDREGION} + {$REGION 'Basic methods'} - /// - /// - /// Простой метод для проверки токена вашего бота - /// - /// - /// A simple method for testing your bot's auth token. - /// - /// - /// - /// - /// Возвращает основную информацию о боте - /// - /// - /// Returns basic information about the bot in form of a - /// User object. - /// - /// function GetMe: ItgUser; - /// - /// Use this method to send text messages. - /// - /// - /// Int64 or String. Unique identifier for the target chat or username of - /// the target channel (in the format @channelusername ). - /// - /// - /// Text of the message to be sent - /// - /// - /// Send Markdown or HTML, if you want Telegram apps to show bold, - /// italic, fixed-width text or inline URLs in your bot's message. - /// - /// - /// Disables link previews for links in this message - /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound. - /// - /// - /// If the message is a reply, ID of the original message - /// - /// - /// InlineKeyboardMarkup or ReplyKeyboardMarkup or ReplyKeyboardHide or - /// ForceReply. Additional interface options. A JSON-serialized object - /// for an inline keyboard, custom reply keyboard, instructions to hide - /// reply keyboard or to force a reply from the user. - /// - /// - /// On success, the sent Message - /// is returned. - /// function SendMessage(// const ChatId: TValue; // const Text: string; // @@ -253,652 +73,101 @@ TTelegramBot = class(TtgAbstractComponent, ITelegramBot) const DisableWebPagePreview: Boolean = False; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to forward messages of any kind. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Unique identifier for the chat where the original message was sent - /// (or channel username in the format @channelusername)
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// Unique message identifier
- /// - /// - /// On success, the sent Message is returned. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function ForwardMessage(// const ChatId, FromChatId: TValue; // const MessageId: Int64; // const DisableNotification: Boolean = False): ITgMessage; - /// - /// Use this method to send photos. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Photo to send. You can either pass a file_id as String to resend a - /// photo that is already on the Telegram servers, or upload a new photo - /// using multipart/form-data.
- /// - /// - /// Photo caption (may also be used when resending photos by file_id), - /// 0-200 characters
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to remove reply - /// keyboard or to force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned. - /// - /// - /// var - /// LMessage: TtgMessage; - /// Begin - /// //Если не известен ИД файла - /// LMessage := sendPhoto(chatId, TtgFileToSend.Create('Путь к файлу'), nil); - /// //Если известен ИД файла - /// LMessage := sendPhoto(chatId, 'ИД Файла'); - /// ... - /// LMessage.Free; - /// End; - /// function SendPhoto(// - const ChatId, Photo: TValue; // + const ChatId: TValue; // + const Photo: TtgFileToSend; // const Caption: string = ''; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to send audio files, if you want Telegram clients to - /// display them in the music player. Your audio must be in the .mp3 - /// format. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Audio file to send. You can either pass a file_id as String to resend - /// an audio that is already on the Telegram servers, or upload a new - /// audio file using multipart/form-data.
- /// - /// - /// Duration of the audio in seconds
- /// - /// - /// Performer
- /// - /// - /// Track name
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned. - /// - /// - /// Bots can currently send audio files of up to 50 MB in size, this - /// limit may be changed in the future. For sending voice messages, use - /// the - /// sendVoice method instead. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendAudio(// - const ChatId, Audio: TValue; // + const ChatId: TValue; // + const Audio: TtgFileToSend; // const Caption: string = ''; // const Duration: Int64 = 0; // const Performer: string = ''; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to send general files. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// File to send. You can either pass a file_id as String to resend a - /// file that is already on the Telegram servers, or upload a new file - /// using multipart/form-data.
- /// - /// - /// Document caption (may also be used when resending documents by - /// file_id), 0-200 characters
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned. - /// - /// - /// Bots can currently send files of any type of up to 50 MB in size, - /// this limit may be changed in the future. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendDocument(// - const ChatId, Document: TValue; // + const ChatId: TValue; // + const Document: TtgFileToSend; // const Caption: string = ''; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to send video files, Telegram clients support mp4 - /// videos (other formats may be sent as Document). - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Video to send. You can either pass a file_id as String to resend a - /// video that is already on the Telegram servers, or upload a new video - /// file using multipart/form-data.
- /// - /// - /// Duration of sent video in seconds
- /// - /// - /// Video width
- /// - /// - /// Video height
- /// - /// - /// Video caption (may also be used when resending videos by file_id), - /// 0-200 characters
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// On success, the sent Message is returned. - /// - /// - /// Bots can currently send video files of up to 50 MB in size, this - /// limit may be changed in the future. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendVideo(// - const ChatId, Video: TValue; // + const ChatId: TValue; // + const Video: TtgFileToSend; // const Caption: string = ''; // const Duration: Int64 = 0; // const Width: Int64 = 0; // const Height: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - - /// - /// Use this method to send audio files, if you want Telegram clients to - /// display the file as a playable voice message. For this to work, your - /// audio must be in an .ogg file encoded with OPUS (other formats may be - /// sent as Audio or Document). - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Audio file to send. You can either pass a file_id as String to resend - /// an audio that is already on the Telegram servers, or upload a new - /// audio file using multipart/form-data.
- /// - /// - /// Duration of sent audio in seconds
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned - /// - /// - /// Bots can currently send voice messages of up to 50 MB in size, this - /// limit may be changed in the future. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendVoice(// - const ChatId, Voice: TValue; // + const ChatId: TValue; // + const Voice: TtgFileToSend; // const Caption: string = ''; // const Duration: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// As of - /// v.4.0, Telegram clients support rounded square mp4 videos of up - /// to 1 minute long. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Video note to send. Pass a file_id as String to send a video note - /// that exists on the Telegram servers (recommended) or upload a new - /// video using multipart/form-data. More info on Sending Files ». - /// Sending video notes by a URL is currently unsupported
- /// - /// - /// Duration of sent video in seconds
- /// - /// - /// Video width and height
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to remove reply - /// keyboard or to force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned. - /// - /// - /// Use this method to send video messages. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendVideoNote(// const ChatId: TValue; // - const VideoNote: TValue; // + const VideoNote: TtgFileToSend; // const Duration: Int64 = 0; // const Length: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - - /// - /// Use this method to send point on the map. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Latitude and Longitude of location - /// - /// - /// Sends the message - /// silently. iOS users will not receive a notification, Android - /// users will receive a notification with no sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendLocation(// const ChatId: TValue; // const Location: TtgLocation; // const LivePeriod: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to send information about a venue. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Latitude and Longitude of the venue
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.

- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// Name of the venue - /// - /// - /// Address of the venue - /// - /// - /// Foursquare identifier of the venue - /// - /// - /// On success, the sent Message is returned. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendVenue(// const ChatId: TValue; // const Venue: TtgVenue; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to send phone contacts. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Contact's phone number, first name, last name - /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound. - /// - /// - /// If the message is a reply, ID of the original message - /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide keyboard or to - /// force a reply from the user.
- /// - /// - /// On success, the sent Message - /// is returned. - /// - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendContact(// const ChatId: TValue; // const Contact: TtgContact; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method when you need to tell the user that something is - /// happening on the bot's side. The status is set for 5 seconds or less - /// (when a message arrives from your bot, Telegram clients clear its - /// typing status). - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Type of action to broadcast. Choose one, depending on what the user - /// is about to receive: typing for text messages, upload_photo for - /// photos, record_video or upload_video for videos, record_audio or - /// upload_audio for audio files, upload_document for general files, - /// find_location for location data
- /// - /// - /// We only recommend using this method when a response from the bot will - /// take a noticeable amount of time to arrive. - /// - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SendChatAction(// const ChatId: TValue; // const Action: TtgSendChatAction): Boolean; - /// - /// Use this method to get a list of profile pictures for a user. - /// - /// - /// Unique identifier of the target user
- /// - /// - /// Sequential number of the first photo to be returned. By default, all - /// photos are returned.
- /// - /// - /// Limits the number of photos to be retrieved. Values between 1—100 are - /// accepted. Defaults to 100.
- /// - /// - /// Returns a - /// UserProfilePhotos object. - /// - /// function GetUserProfilePhotos(// const ChatId: TValue; // const Offset: Int64; // const Limit: Int64 = 100): ItgUserProfilePhotos; - /// - /// Use this method to get basic info about a file and prepare it for - /// downloading. For the moment, bots can download files of up to 20MB in - /// size. - /// - /// - /// File identifier to get info about
- /// - /// - /// On success, a File object is - /// returned. - /// - /// function GetFile(const FileId: string): ItgFile; - /// - /// Use this method to kick a user from a group, a supergroup or a - /// channel. In the case of supergroups and channels, the user will not - /// be able to return to the group on their own using invite links, etc., - /// unless unbanned first. The bot must be an administrator in the chat - /// for this to work and must have the appropriate admin rights. - /// - /// - /// Unique identifier for the target group or username of the target - /// supergroup (in the format @supergroupusername)
- /// - /// - /// Unique identifier of the target user
- /// - /// - /// Date when the user will be unbanned, unix time. If user is banned for - /// more than 366 days or less than 30 seconds from the current time they - /// are considered to be banned forever
unbanChatMember - /// - /// - /// Returns True on success. - /// - /// - /// Note: In regular groups (non-supergroups), this method will only work - /// if the ‘All Members Are Admins’ setting is off in the target group. - /// Otherwise members may only be removed by the group's creator or by - /// the member that added them. - /// - /// function KickChatMember(// const ChatId: TValue; // const UserId: Int64; // - const UntilDate: Int64 = 0): Boolean; - /// - /// Use this method to unban a previously kicked user in a supergroup. - /// The user will not return to the group automatically, but will be able - /// to join via link, etc. - /// - /// - /// Unique identifier for the target group or username of the target - /// supergroup (in the format @supergroupusername)
- /// - /// - /// Unique identifier of the target user
- /// - /// - /// Returns True on success. - /// - /// - /// The bot must be an administrator in the group for this to work. - /// - /// + const UntilDate: TDateTime = 0): Boolean; function UnbanChatMember(// const ChatId: TValue; // const UserId: Int64): Boolean; - /// - /// Use this method for your bot to leave a group, supergroup or channel. - /// - /// - /// Unique identifier for the target group or username of the target - /// supergroup (in the format @supergroupusername)
- /// - /// - /// Returns True on success. - /// - /// function LeaveChat(const ChatId: TValue): Boolean; - /// - /// Use this method to get up to date information about the chat (current - /// name of the user for one-on-one conversations, current username of a - /// user, group or channel, etc.) - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format @channelusername)
- /// - /// - /// Returns a Chat object on - /// success. - /// - /// function GetChat(const ChatId: TValue): ItgChat; - /// - /// Use this method to get a list of administrators in a chat - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format @channelusername)
- /// - /// - /// On success, returns an Array of - /// ChatMember objects that contains information about all chat - /// administrators except other bots. If the chat is a group or a - /// supergroup and no administrators were appointed, only the creator - /// will be returned. - /// - /// function GetChatAdministrators(const ChatId: TValue): TArray; - /// - /// Use this method to get the number of members in a chat. - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format @channelusername)
- /// - /// - /// Returns Int64 on success. - /// - /// function GetChatMembersCount(const ChatId: TValue): Int64; - /// - /// Use this method to get information about a member of a chat. - /// - /// - /// Unique identifier for the target group or username of the target - /// supergroup (in the format @supergroupusername)
- /// - /// - /// Unique identifier of the target user
- /// - /// - /// Returns a ChatMember - /// object on success. - /// - /// function GetChatMember(// const ChatId: TValue; // const UserId: Int64): ItgChatMember; - /// - /// Use this method to send answers to callback queries sent from inline - /// keyboards. The answer will be displayed to the user as a notification - /// at the top of the chat screen or as an alert. - /// - /// - /// Unique identifier for the query to be answered
- /// - /// - /// Text of the notification. If not specified, nothing will be shown to - /// the user
- /// - /// - /// If true, an alert will be shown by the client instead of a - /// notification at the top of the chat screen. Defaults to false.
- /// - /// - /// On success, True is returned. - /// - /// function AnswerCallbackQuery(// const CallbackQueryId: string; // const Text: string = ''; // @@ -906,311 +175,59 @@ TTelegramBot = class(TtgAbstractComponent, ITelegramBot) const Url: string = ''; // const CacheTime: Int64 = 0): Boolean; {$ENDREGION} + {$REGION 'Updating messages'} - /// - /// Use this method to edit text messages sent by the bot or via the bot - /// (for inline bots). - /// - /// - /// Required if inline_message_id is not specified. Unique identifier for - /// the target chat or username of the target channel (in the format - /// @channelusername)
- /// - /// - /// Required if inline_message_id is not specified. Unique identifier of - /// the sent message
- /// - /// - /// Required if chat_id and message_id are not specified. Identifier of - /// the inline message
- /// - /// - /// New text of the message
- /// - /// - /// Send Markdown or HTML, if you want Telegram apps to show bold, - /// italic, fixed-width text or inline URLs in your bot's message.
- /// - /// - /// Disables link previews for links in this message
- /// - /// - /// A JSON-serialized object for an inline keyboard.
- /// - /// - /// On success, if edited message is sent by the bot, the edited Message - /// is returned, otherwise True is returned. - /// - /// function EditMessageText(// const ChatId: TValue; // const MessageId: Int64; // const Text: string; // const ParseMode: TtgParseMode = TtgParseMode.Default; // const DisableWebPagePreview: Boolean = False; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; function EditMessageText(// const InlineMessageId: string; // const Text: string; // const ParseMode: TtgParseMode = TtgParseMode.Default; // const DisableWebPagePreview: Boolean = False; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; - /// - /// Use this method to edit captions of messages sent by the bot or via - /// the bot (for inline bots). - /// - /// - /// Required if InlineMessageId is not specified. Unique identifier for - /// the target chat or username of the target channel (in the format - /// @channelusername)
- /// - /// - /// Required if InlineMessageId is not specified. Unique identifier of
- /// the sent message
- /// - /// - /// Required if ChatId and MessageId are not specified. Identifier of the - /// inline message
- /// - /// - /// New caption of the message
- /// - /// - /// A JSON-serialized object for an inline keyboard.
- /// - /// - /// On success, if edited message is sent by the bot, the edited Message - /// is returned, otherwise True is returned. - /// - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; function EditMessageCaption(// const ChatId: TValue; // const MessageId: Int64; // const Caption: string; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; - { TODO -oM.E.Sysoev -cGeneral : Create Documentatiom } + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; function EditMessageCaption(// const InlineMessageId: string; // const Caption: string; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; - - /// - /// Use this method to edit live location messages sent by the bot or via - /// the bot (for inline bots). A location can be edited until its - /// live_period expires or editing is explicitly disabled by a call to - /// stopMessageLiveLocation. - /// - /// - /// Required if inline_message_id is not specified. Unique identifier for - /// the target chat or username of the target channel (in the format - /// @channelusername) - /// - /// - /// Required if inline_message_id is not specified. Identifier of the - /// sent message - /// - /// - /// new location - /// - /// - /// A JSON-serialized object for a new inline keyboard. - /// - /// - /// On success, if the edited message was sent by the bot, the edited - /// Message is returned, otherwise True is returned. - /// + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; function editMessageLiveLocation(// const ChatId: TValue; // const MessageId: Int64; // const Location: TtgLocation; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; - /// - /// Use this method to edit live location messages sent by the bot or via - /// the bot (for inline bots). A location can be edited until its - /// live_period expires or editing is explicitly disabled by a call to - /// stopMessageLiveLocation. - /// - /// - /// Required if chat_id and message_id are not specified. Identifier of - /// the inline message - /// - /// - /// new location - /// - /// - /// A JSON-serialized object for a new inline keyboard. - /// - /// - /// Required if inline_message_id is not specified. Unique identifier for - /// the target chat or username of the target channel (in the format - /// @channelusername) - /// - /// - /// Required if inline_message_id is not specified. Identifier of the - /// sent message - /// - /// - /// On success, if the edited message was sent by the bot, the edited - /// Message is returned, otherwise True is returned. - /// + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; function editMessageLiveLocation(// const InlineMessageId: string; // const Location: TtgLocation; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; - - /// - /// Use this method to stop updating a live location message sent by the - /// bot or via the bot (for inline bots) before live_period expires. - /// - /// - /// equired if inline_message_id is not specified. Unique identifier for - /// the target chat or username of the target channel (in the format - /// @channelusername) - /// - /// - /// Required if inline_message_id is not specified. Identifier of the - /// sent message - /// - /// - /// A JSON-serialized object for a new inline keyboard. - /// - /// - /// On success, if the message was sent by the bot, the sent Message is - /// returned, otherwise True is returned. - /// + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; function stopMessageLiveLocation(// const ChatId: TValue; // const MessageId: Int64; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; - /// - /// Use this method to stop updating a live location message sent by the - /// bot or via the bot (for inline bots) before live_period expires. - /// - /// - /// Required if chat_id and message_id are not specified. Identifier of - /// the inline message - /// - /// - /// A JSON-serialized object for a new inline keyboard. - /// - /// - /// On success, if the message was sent by the bot, the sent Message is - /// returned, otherwise True is returned. - /// + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; function stopMessageLiveLocation(// const InlineMessageId: string; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; - /// - /// Use this method to edit only the reply markup of messages sent by the - /// bot or via the bot (for inline bots). - /// - /// - /// Required if InlineMessageId is not specified. Unique identifier for
- /// the target chat or username of the target channel (in the format
- /// @channelusername)
- /// - /// - /// Required if InlineMessageId is not specified. Unique identifier of
- /// the sent message
- /// - /// - /// A JSON-serialized object for an inline keyboard.
- /// - /// - /// On success, if edited message is sent by the bot, the edited Message - /// is returned, otherwise True is returned. - /// + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; function EditMessageReplyMarkup(// const ChatId: TValue; // const MessageId: Int64; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; - /// - /// Use this method to edit only the reply markup of messages sent by the - /// bot or via the bot (for inline bots). - /// - /// - /// Required if ChatId and MessageId are not specified. Identifier of
- /// the inline message
- /// - /// - /// A JSON-serialized object for an inline keyboard.
- /// - /// - /// On success, if edited message is sent by the bot, the edited Message - /// is returned, otherwise True is returned. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; function EditMessageReplyMarkup(// const InlineMessageId: string; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; - /// - /// Use this method to delete a message. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Identifier of the message to delete
- /// - /// - /// Returns True on success. - /// - /// - /// A message can only be deleted if it was sent less than 48 hours ago. - /// Any such recently sent outgoing message may be deleted. Additionally, - /// if the bot is an administrator in a group chat, it can delete any - /// message. If the bot is an administrator in a supergroup, it can - /// delete messages from any other user and service messages about people - /// joining or leaving the group (other types of service messages may - /// only be removed by the group creator). In channels, bots can only - /// remove their own messages. - /// - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; function DeleteMessage(// const ChatId: TValue; // const MessageId: Int64): Boolean; - {$ENDREGION} +{$ENDREGION} + {$REGION 'Inline mode'} - /// - /// Use this method to send answers to an inline query. - /// - /// - /// Unique identifier for the answered query
- /// - /// - /// A JSON-serialized array of results for the inline query
- /// - /// - /// The maximum amount of time in seconds that the result of the inline - /// query may be cached on the server. Defaults to 300.
- /// - /// - /// Pass True, if results may be cached on the server side only for the - /// user that sent the query. By default, results may be returned to any - /// user who sends the same query
- /// - /// - /// Pass the offset that a client should send in the next query with the - /// same text to receive more results. Pass an empty string if there are - /// no more results or if you don‘t support pagination. Offset length - /// can’t exceed 64 bytes.
- /// - /// - /// If passed, clients will display a button with specified text that - /// switches the user to a private chat with the bot and sends the bot a - /// start message with the parameter switch_pm_parameter
- /// - /// - /// Parameter for the start message sent to the bot when user presses the - /// switch button
- /// - /// - /// On success, True is returned. - /// - /// - /// No more than 50 results per query are allowed. - /// - /// function AnswerInlineQuery(// const InlineQueryId: string; // const Results: TArray; // @@ -1220,88 +237,11 @@ TTelegramBot = class(TtgAbstractComponent, ITelegramBot) const SwitchPmText: string = ''; // const SwitchPmParameter: string = ''): Boolean; {$ENDREGION} + {$REGION 'Payments'} - /// - /// Use this method to send invoices. - /// - /// - /// Unique identifier for the target private chat
- /// - /// - /// Product name - /// - /// - /// Product description - /// - /// - /// Bot-defined invoice payload, 1-128 bytes. This will not be displayed - /// to the user, use for your internal processes. - /// - /// - /// Payments provider token, obtained via Botfather - /// - /// - /// Unique deep-linking parameter that can be used to generate this - /// invoice when used as a start parameter - /// - /// - /// Three-letter ISO 4217 currency code, see more on currencies - /// - /// - /// Price breakdown, a list of components (e.g. product price, tax, - /// discount, delivery cost, delivery tax, bonus, etc.) - /// - /// - /// URL of the product photo for the invoice. Can be a photo of the goods - /// or a marketing image for a service. - /// - /// - /// Photo size - /// - /// - /// Photo width - /// - /// - /// Photo height - /// - /// - /// Pass True, if you require the user's full name to complete the order - /// - /// - /// Pass True, if you require the user's phone number to complete the - /// order - /// - /// - /// Pass True, if you require the user's email to complete the order - /// - /// - /// Pass True, if you require the user's shipping address to complete the - /// order - /// - /// - /// Pass True, if the final price depends on the shipping method - /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound. - /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for a custom - /// reply keyboard, instructions to hide keyboard or to force a reply - /// from the user.
- /// - /// - /// On success, the sent is - /// returned. - /// - /// function SendInvoice(// const ChatId: Int64; // - const title: string; // + const Title: string; // const Description: string; // const Payload: string; // const ProviderToken: string; // @@ -1320,406 +260,71 @@ TTelegramBot = class(TtgAbstractComponent, ITelegramBot) const IsFlexible: Boolean = False; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// If you sent an invoice requesting a shipping address and the - /// parameter is_flexible was specified, the Bot API will send an Update - /// with a shipping_query field to the bot. Use this method to reply to - /// shipping queries. On success, True is returned. - /// - /// - /// Unique identifier for the query to be answered - /// - /// - /// Specify True if delivery to the specified address is possible and - /// False if there are any problems (for example, if delivery to the - /// specified address is not possible) - /// - /// - /// Required if ok is True. A JSON-serialized array of - /// available shipping options. - /// - /// - /// Required if ok is False. Error message in human - /// readable form that explains why it is impossible to complete the - /// order (e.g. "Sorry, delivery to your desired address is - /// unavailable'). Telegram will display this message to the user. - /// - /// - function AnswerShippingQuery(// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; + function AnswerShippingQueryGood(// + const ShippingQueryId: string; // + const ShippingOptions: TArray): Boolean; + function AnswerShippingQueryBad(// const ShippingQueryId: string; // - const Ok: Boolean; // - const ShippingOptions: TArray; // const ErrorMessage: string): Boolean; - /// - /// Once the user has confirmed their payment and shipping details, the - /// Bot API sends the final confirmation in the form of an - /// Update with the field PreCheckoutQueryId. Use this method to - /// respond to such pre-checkout queries. - /// - /// - /// Unique identifier for the query to be answered - /// - /// - /// Specify True if everything is alright (goods are available, - /// etc.) and the bot is ready to proceed with the order. Use False if - /// there are any problems. - /// - /// - /// Required if ok is False. Error message in human - /// readable form that explains the reason for failure to proceed with - /// the checkout (e.g. "Sorry, somebody just bought the last of our - /// amazing black T-shirts while you were busy filling out your payment - /// details. Please choose a different color or garment!"). Telegram will - /// display this message to the user. - /// - /// - /// On success, True is returned. - /// - /// - /// Note: The Bot API must receive an answer within 10 seconds - /// after the pre-checkout query was sent. - /// - /// - function AnswerPreCheckoutQuery(// + function AnswerPreCheckoutQueryGood(// + const PreCheckoutQueryId: string): Boolean; + function AnswerPreCheckoutQueryBad(// const PreCheckoutQueryId: string; // - const Ok: Boolean; // - const ErrorMessage: string = ''): Boolean; + const ErrorMessage: string): Boolean; {$ENDREGION} + {$REGION 'Games'} - /// - /// Use this method to send a game. - /// - /// - /// Unique identifier for the target chat
- /// - /// - /// Short name of the game, serves as the unique identifier for the game. - /// Set up your games via Botfather.
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// A JSON-serialized object for an inline keyboard. If empty, one ‘Play - /// game_title’ button will be shown. If not empty, the first button must - /// launch the game.
- /// - /// - /// On success, the sent Message is returned. - /// - /// function SendGame(// const ChatId: Int64; // const GameShortName: string; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to set the score of the specified user in a game. - /// - /// - /// User identifier
- /// - /// - /// New score, must be non-negative
- /// - /// - /// Pass True, if the high score is allowed to decrease. This can be - /// useful when fixing mistakes or banning cheaters
- /// - /// - /// Pass True, if the game message should not be automatically edited to - /// include the current scoreboard
- /// - /// - /// Required if InlineMessageId is not specified. Unique identifier for
- /// the target chat
- /// - /// - /// Required if InlineMessageId is not specified. Identifier of the
- /// sent message
- /// - /// - /// Required if ChatId and MessageId are not specified. Identifier of the - /// inline message
- /// - /// - /// On success, if the message was sent by the bot, returns the edited - /// Message, otherwise returns True. Returns an error, if the new score - /// is not greater than the user's current score in the chat and force is - /// False. - /// - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function SetGameScore(// const UserId: Int64; // const Score: Int64; // + const InlineMessageId: string; // const Force: Boolean = False; // - const DisableEditMessage: Boolean = False; // - const ChatId: Int64 = 0; // - const MessageId: Int64 = 0; // - const InlineMessageId: string = ''): ITgMessage; - /// - /// Use this method to get data for high score tables. Will return the - /// score of the specified user and several of his neighbors in a game. - /// - /// - /// Target user id
- /// - /// - /// Required if InlineMessageId is not specified. Unique identifier for
- /// the target chat
- /// - /// - /// Required if InlineMessageId is not specified. Identifier of the
- /// sent message
- /// - /// - /// Required if ChatId and MessageId are not specified. Identifier of
- /// the inline message
- /// - /// - /// On success, returns an Array of - /// GameHighScore objects. - /// - /// - /// This method will currently return scores for the target user, plus - /// two of his closest neighbors on each side. Will also return the top - /// three users if the user and his neighbors are not among them. Please - /// note that this behavior is subject to change. - /// - /// - /// Official API - /// + const DisableEditMessage: Boolean = False): ITgMessage; overload; + function SetGameScore(// + const UserId: Int64; // + const Score: Int64; // + const ChatId: Int64; // + const MessageId: Int64; // + const Force: Boolean = False; // + const DisableEditMessage: Boolean = False): ITgMessage; overload; + function GetGameHighScores(// + const UserId: Int64; // + const InlineMessageId: string = ''): TArray; overload; function GetGameHighScores(// const UserId: Int64; // const ChatId: Int64 = 0; // - const MessageId: Int64 = 0; // - const InlineMessageId: string = ''): TArray; + const MessageId: Int64 = 0): TArray; overload; {$ENDREGION} + {$REGION 'Manage groups and channels'} - /// - /// Use this method to delete a chat photo. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername) - /// - /// - /// Returns True on success. - /// - /// - /// Photos can't be changed for private chats. The bot must be an - /// administrator in the chat for this to work and must have the - /// appropriate admin rights. - /// function DeleteChatPhoto(const ChatId: TValue): Boolean; - /// - /// Use this method to export an invite link to a supergroup or a - /// channel. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername) - /// - /// - /// Returns exported invite link as String on success. - /// - /// - /// The bot must be an administrator in the chat for this to work and - /// must have the appropriate admin rights. - /// function ExportChatInviteLink(const ChatId: TValue): string; - /// - /// Use this method to pin a message in a supergroup. The bot must be an - /// administrator in the chat for this to work and must have the - /// appropriate admin rights. - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format @supergroupusername) - /// - /// - /// Identifier of a message to pin
- /// - /// - /// Pass True, if it is not necessary to send a notification to all group - /// members about the new pinned message - /// - /// - /// Returns True on success. - /// function PinChatMessage(// const ChatId: TValue; // const MessageId: Int64; // const DisableNotification: Boolean = False): Boolean; - /// - /// Use this method to change the description of a supergroup or a - /// channel. The bot must be an administrator in the chat for this to - /// work and must have the appropriate admin rights. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername) - /// - /// - /// New chat description, 0-255 characters - /// - /// - /// Returns True on success. - /// function SetChatDescription(const ChatId: TValue; const Description: string): Boolean; - /// - /// Use this method to set a new profile photo for the chat. Photos can't - /// be changed for private chats. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername) - /// - /// - /// New chat photo, uploaded using multipart/form-data - /// - /// - /// Returns True on success. - /// - /// - /// The bot must be an administrator in the chat for this to work and - /// must have the appropriate admin rights. - /// function SetChatPhoto(const ChatId: TValue; const Photo: TtgFileToSend): Boolean; - /// - /// Use this method to change the title of a chat. Titles can't be - /// changed for private chats. The bot must be an administrator in the - /// chat for this to work and must have the appropriate admin rights. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername) - /// - /// - /// New chat title, 1-255 characters - /// - /// - /// Returns True on success. - /// - /// - /// Note: In regular groups (non-supergroups), this method will only work - /// if the ‘All Members Are Admins’ setting is off in the target group. - /// function SetChatTitle(const ChatId: TValue; const Title: string): Boolean; - /// - /// Use this method to unpin a message in a supergroup chat. The bot must - /// be an administrator in the chat for this to work and must have the - /// appropriate admin rights. - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format @supergroupusername) - /// - /// - /// Returns True on success. - /// function UnpinChatMessage(const ChatId: TValue): Boolean; {$ENDREGION} + {$REGION 'Manage users and admins'} - /// - /// Use this method to restrict a user in a supergroup. The bot must be - /// an administrator in the supergroup for this to work and must have the - /// appropriate admin rights. Pass True for all boolean parameters to - /// lift restrictions from a user. - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format @supergroupusername) - /// - /// - /// Unique identifier of the target user - /// - /// - /// Date when restrictions will be lifted for the user, unix time. If - /// user is restricted for more than 366 days or less than 30 seconds - /// from the current time, they are considered to be restricted forever - /// - /// - /// Pass True, if the user can send text messages, contacts, locations - /// and venues - /// - /// - /// Pass True, if the user can send audios, documents, photos, videos, - /// video notes and voice notes, implies CanSendMessages
- /// - /// - /// Pass True, if the user can send animations, games, stickers and use - /// inline bots, implies CanSendMediaMessages
- /// - /// - /// Pass True, if the user may add web page previews to their messages, - /// implies CanSendMediaMessages
- /// - /// - /// Returns True on success. - /// function RestrictChatMember(// const ChatId: TValue; // const UserId: Int64; // - const UntilDate: Int64 = 0; // + const UntilDate: TDateTime = 0; // const CanSendMessages: Boolean = False; // const CanSendMediaMessages: Boolean = False; // const CanSendOtherMessages: Boolean = False; // const CanAddWebPagePreviews: Boolean = False): Boolean; - /// - /// Use this method to restrict a user in a supergroup. The bot must be - /// an administrator in the supergroup for this to work and must have the - /// appropriate admin rights. Pass True for all boolean parameters to - /// lift restrictions from a user. - /// - /// - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format @supergroupusername) - /// - /// - /// Unique identifier of the target user - /// - /// - /// Pass True, if the administrator can change chat title, photo and - /// other settings - /// - /// - /// Pass True, if the administrator can create channel posts, channels - /// only - /// - /// - /// Pass True, if the administrator can edit messages of other users, - /// channels only - /// - /// - /// Pass True, if the administrator can delete messages of other users - /// - /// - /// Pass True, if the administrator can invite new users to the chat - /// - /// - /// Pass True, if the administrator can restrict, ban or unban chat - /// members - /// - /// - /// Pass True, if the administrator can pin messages, supergroups only - /// - /// - /// Pass True, if the administrator can add new administrators with a - /// subset of his own privileges or demote administrators that he has - /// promoted, directly or indirectly (promoted by administrators that - /// were appointed by him) - /// - /// - /// Returns True on success. - /// function PromoteChatMember(// const ChatId: TValue; // const UserId: Int64; // @@ -1732,177 +337,32 @@ TTelegramBot = class(TtgAbstractComponent, ITelegramBot) const CanPinMessages: Boolean = False; // const CanPromoteMembers: Boolean = False): Boolean; {$ENDREGION} + {$REGION 'Strickers'} - /// - /// Use this method to send .webp stickers. - /// - /// - /// Unique identifier for the target chat or username of the target - /// channel (in the format @channelusername)
- /// - /// - /// Sticker to send. You can either pass a file_id as String to resend a - /// sticker that is already on the Telegram servers, or upload a new - /// sticker using multipart/form-data.
- /// - /// - /// Sends the message silently. iOS users will not receive a - /// notification, Android users will receive a notification with no - /// sound.
- /// - /// - /// If the message is a reply, ID of the original message
- /// - /// - /// Additional interface options. A JSON-serialized object for an inline - /// keyboard, custom reply keyboard, instructions to hide reply keyboard - /// or to force a reply from the user.
- /// - /// - /// On success, the sent Message is returned. - /// function SendSticker(// const ChatId: TValue; // const Sticker: TValue; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; - /// - /// Use this method to get a sticker set. - /// - /// - /// Name of the sticker set - /// - /// - /// On success, a StickerSet - /// object is returned. - /// + ReplyMarkup: IReplyMarkup = nil): ITgMessage; function getStickerSet(const Name: string): TtgStickerSet; - /// - /// Use this method to upload a .png file with a sticker for later use in - /// - /// createNewStickerSet and - /// addStickerToSet methods (can be used multiple times).
- ///
- /// - /// User identifier of sticker file owner
- /// - /// - /// Png image with the sticker, must be up to 512 kilobytes in size, - /// dimensions must not exceed 512px, and either width or height must be - /// exactly 512px.
- /// - /// - /// Returns the uploaded File on - /// success. - /// function uploadStickerFile(const UserId: Int64; const PngSticker: TtgFileToSend): ItgFile; - /// - /// Use this method to create new sticker set owned by a user. The bot - /// will be able to edit the created sticker set. - /// - /// - /// User identifier of created sticker set owner
- /// - /// - /// Short name of sticker set, to be used in t.me/addstickers/ URLs - /// (e.g., animals). Can contain only english letters, digits and - /// underscores. Must begin with a letter, can't contain consecutive - /// underscores and must end in by “__<bot username>”. - /// <bot_username> is case insensitive. 1-64 characters.
- /// - /// - /// Sticker set title, 1-64 characters
- /// - /// - /// Png image with the sticker, must be up to 512 kilobytes in size, - /// dimensions must not exceed 512px, and either width or height must be - /// exactly 512px. Pass a file_id as a String to send a file that already - /// exists on the Telegram servers, pass an HTTP URL as a String for - /// Telegram to get a file from the Internet, or upload a new one using - /// multipart/form-data. More info on Sending Files »
- /// - /// - /// One or more emoji corresponding to the sticker
- /// - /// - /// Pass True, if a set of mask stickers should be created
- /// - /// - /// A JSON-serialized object for position where the mask should be placed - /// on faces
- /// - /// - /// Returns True on success. - /// function createNewStickerSet(// const UserId: Int64; // - const Name, title: string; // + const Name, Title: string; // const PngSticker: TValue; // const Emojis: string; // const ContainsMasks: Boolean = False; // const MaskPosition: TtgMaskPosition = nil): Boolean; - /// - /// Use this method to add a new sticker to a set created by the bot. - /// - /// - /// Returns True on success. - /// function addStickerToSet(// const UserId: Int64; // const Name: string; // const PngSticker: TValue; // const Emojis: string; // const MaskPosition: TtgMaskPosition = nil): Boolean; - /// - /// Use this method to move a sticker in a set created by the bot to a - /// specific position. - /// - /// - /// File identifier of the sticker - /// - /// - /// New sticker position in the set, zero-based - /// - /// - /// Returns True on success. - /// function setStickerPositionInSet(const Sticker: string; const Position: Int64): Boolean; - /// - /// Use this method to delete a sticker from a set created by the bot. - /// - /// - /// File identifier of the sticker - /// - /// - /// Returns True on success. - /// function deleteStickerFromSet(const Sticker: string): Boolean; - /// - /// Use this method to set a new group sticker set for a supergroup. - /// - /// - /// Returns True on success. - /// - /// - /// The bot must be an administrator in the chat for this to work and - /// must have the appropriate admin rights. Use the field - /// CanSetStickerSet optionally returned in - /// getChat requests to check if the bot can use this method. - /// function setChatStickerSet(const ChatId: TValue; const StickerSetName: string): Boolean; - /// - /// Use this method to delete a group sticker set from a supergroup. - /// - /// - /// Returns True on success. - /// - /// - /// The bot must be an administrator in the chat for this to work and - /// must have the appropriate admin rights. Use the field - /// CanSetStickerSet optionally returned in - /// getChat requests to check if the bot can use this method. - /// function deleteChatStickerSet(const ChatId: TValue): Boolean; function sendMediaGroup(// const ChatId: TValue; // @@ -1925,172 +385,81 @@ implementation uses REST.Json, - TelegAPI.Helpers; + FMX.Types, + TelegAPI.Helpers, + TelegAPI.CoreAPI.Request; { TTelegramBot } {$REGION 'Core'} -constructor TTelegramBot.Create(AOwner: TComponent); -begin - inherited Create(AOwner); - FParamLoader := TtgParamLoader.Create; -end; - -destructor TTelegramBot.Destroy; -begin - FParamLoader.Free; - inherited; -end; - -function TTelegramBot.RequestAPI(const Method: string; const Parameters: TDictionary): string; -var - LTextResponse: string; -begin - LTextResponse := SendDataToServer(Method, Parameters); - if Assigned(OnReceiveRawData) then - OnReceiveRawData(Self, LTextResponse); - if LTextResponse.IsEmpty then - ExceptionManager.HaveGlobalExeption('RequestAPI', ETelegramUnknownData.Create('Can''t parse response')) - else - Result := ApiTest(LTextResponse, Parameters); -end; - -function TTelegramBot.ApiTest(const ARequest: string; const Parameters: TDictionary): string; +function TTelegramBot.RequestAPI(const Method: string; const Parameters: TArray): string; var - FJSON: TJSONObject; + LTgRequest: TtgApiRequest; begin - Result := ''; - if ARequest.IsEmpty then - Exit; - FJSON := TJSONObject.ParseJSONValue(ARequest) as TJSONObject; + LTgRequest := TtgApiRequest.Create(Self, Method); try - if FJSON.GetValue('ok') is TJSONFalse then - if ExceptionManager <> nil then + LTgRequest.OnSend := + procedure(Url, Data: string) begin - ExceptionManager.HaveApiExeption('TTelegramBot.ApiTest', EApiRequestException.Create(ARequest, 0, Parameters)); - Exit; + Log.d('%s - %s', [Url, Data]); end; - Result := FJSON.GetValue('result').ToJSON; - finally - FJSON.Free; - end; -end; - -function TTelegramBot.ParamsToFormData(const Parameters: TDictionary): TMultipartFormData; -var - LParameter: TPair; - LAddProc: TtgParamLoader.TLoader; - LTest: string; -begin - Result := TMultipartFormData.Create; - for LParameter in Parameters do - begin - // skip all empty params - if LParameter.Value.IsEmpty then - Continue; - // look for the given parameter type - if FParamLoader.ParamLoaders.TryGetValue(LParameter.Value.TypeInfo, LAddProc) then - begin - LAddProc(Result, LParameter.Value.TypeInfo, LParameter.Key, LParameter.Value); - end - else if LParameter.Value.Kind = tkClass then - // last variant to search - begin - { TODO -oOwner -cGeneral : Проверить че за херня тут твориться } - if not LParameter.Value.IsEmpty then + LTgRequest.OnReceive := + procedure(Data: string) begin - if LParameter.Value.IsTypethen - begin - LTest := TJson.ObjectToJsonString(LParameter.Value.AsObject); - Result.AddField(LParameter.Key, LTest); - end - else if Assigned(ExceptionManager) then - ExceptionManager.HaveGlobalExeption('TTelegramBot.ParamsToFormData', Exception.Create('Unknown object')) - else - raise Exception.Create('Error Message'); - end - end - else if Assigned(ExceptionManager) then - ExceptionManager.HaveGlobalExeption('ParamsToFormData', ETelegramDataConvert.Create('Check parameter type ' + LParameter.Value.ToString)) - else - raise ETelegramDataConvert.Create('Check parameter type ' + LParameter.Value.ToString); - end; -end; - -function TTelegramBot.SendDataToServer(const Method: string; const Parameters: TDictionary): string; -var - LHttp: THTTPClient; - LHttpResponse: IHTTPResponse; - LFullUrl: string; - LParamToDate: TMultipartFormData; -begin - LHttp := THTTPClient.Create; - LParamToDate := nil; - Result := string.Empty; - try - LHttp.ProxySettings := FProxySettings; - LFullUrl := 'https://api.telegram.org/bot' + FToken + '/' + Method; - try - if Assigned(Parameters) then - begin - LParamToDate := ParamsToFormData(Parameters); - LHttpResponse := LHttp.Post(LFullUrl, LParamToDate); - end - else - LHttpResponse := LHttp.Get(LFullUrl); - if LHttpResponse.StatusCode = 200 then - Result := LHttpResponse.ContentAsString(TEncoding.UTF8) - else - ExceptionManager.HaveGlobalExeption('SendDataToServer', EApiRequestException.Create(LHttpResponse.StatusText, LHttpResponse.StatusCode, Parameters)) - except - on E: Exception do + Log.d('%s', [Data]); + if Assigned(OnReceiveRawData) then + OnReceiveRawData(Self, Data); + end; + LTgRequest.OnError := + procedure(E: Exception) begin - ExceptionManager.HaveGlobalExeption('SendDataToServer', E); + ExceptionManager.HaveGlobalExeption('RequestAPI', E) end; - end; + LTgRequest.Parameters.AddRange(Parameters); + if LTgRequest.Execute(Result) then + begin + if Result.IsEmpty then + ExceptionManager.HaveGlobalExeption('RequestAPI', ETelegramUnknownData.Create('Can''t parse response')) + else + Result := ApiTest(Result, Parameters); + end finally - FreeAndNil(LParamToDate); - FreeAndNil(LHttp); + LTgRequest.Free; end; end; -procedure TTelegramBot.SetToken(const Value: string); -begin - FToken := Value; -end; -{$ENDREGION} -{$REGION 'Getting updates'} - -function TTelegramBot.SetWebhook(const Url: string; const Certificate: TtgFileToSend; const MaxConnections: Int64; const AllowedUpdates: TAllowedUpdates): Boolean; +function TTelegramBot.ApiTest(const ARequest: string; const Parameters: TArray): string; var - Parameters: TDictionary; + FJSON: TJSONObject; begin - Parameters := TDictionary.Create; + Result := ''; + if ARequest.IsEmpty then + Exit; + FJSON := TJSONObject.ParseJSONValue(ARequest) as TJSONObject; try - Parameters.Add('url', Url); - Parameters.Add('certificate', Certificate); - Parameters.Add('max_connections', MaxConnections); - Parameters.Add('allowed_updates', AllowedUpdates.ToString); - Result := ExecuteMethod('setWebhook', Parameters); + if FJSON.GetValue('ok') is TJSONFalse then + ExceptionManager.HaveApiExeption('TTelegramBot.ApiTest', EApiRequestException.Create(ARequest, 0)) + else + Result := FJSON.GetValue('result').ToJSON; finally - Parameters.Free; + FJSON.Free; end; end; -function TTelegramBot.GetJSONFromMethod(const Method: string; const Parameters: TDictionary): TJSONValue; +function TTelegramBot.GetJSONFromMethod(const AValue: string): TJSONValue; begin - Result := TJSONObject.ParseJSONValue(RequestAPI(Method, Parameters)); + Result := TJSONObject.ParseJSONValue(AValue); end; -function TTelegramBot.GetJSONArrayFromMethod(const Method: string; const Parameters: TDictionary): TJSONArray; +function TTelegramBot.GetJSONArrayFromMethod(const AValue: string): TJSONArray; begin - Result := TJSONObject.ParseJSONValue(RequestAPI(Method, Parameters)) as TJSONArray; + Result := TJSONObject.ParseJSONValue(AValue) as TJSONArray; end; -function TTelegramBot.ExecuteMethod(const Method: string; const Parameters: TDictionary): Boolean; +function TTelegramBot.ExtractBool(const AValue: string): Boolean; var LJson: TJSONValue; begin - LJson := GetJSONFromMethod(Method, Parameters); + LJson := TJSONObject.ParseJSONValue(AValue); try Result := LJson is TJSONTrue; finally @@ -2098,11 +467,11 @@ function TTelegramBot.ExecuteMethod(const Method: string; const Parameters: TDic end; end; -function TTelegramBot.GetValueFromMethod(const Method: string; const Parameters: TDictionary): string; +function TTelegramBot.GetValueFromMethod(const AValue: string): string; var LJson: TJSONValue; begin - LJson := GetJSONFromMethod(Method, Parameters); + LJson := GetJSONFromMethod(AValue); try Result := LJson.Value; finally @@ -2110,7 +479,7 @@ function TTelegramBot.GetValueFromMethod(const Method: string; const Parameters: end; end; -function TTelegramBot.GetArrayFromMethod(const TgClass: TBaseJsonClass; const Method: string; const Parameters: TDictionary): TArray; +function TTelegramBot.GetArrayFromMethod(const TgClass: TBaseJsonClass; const AValue: string): TArray; var LJsonArr: TJSONArray; I: Integer; @@ -2123,372 +492,274 @@ function TTelegramBot.GetArrayFromMethod(const TgClass: TBaseJsonClass; cons if TgClass.GetInterfaceEntry(GUID) = nil then raise Exception.Create('GetArrayFromMethod: unsupported interface for ' + TgClass.ClassName); // stage 2: proceed data - LJsonArr := GetJSONArrayFromMethod(Method, Parameters); + LJsonArr := GetJSONArrayFromMethod(AValue); if (not Assigned(LJsonArr)) or LJsonArr.Null then Exit(nil); try SetLength(Result, LJsonArr.Count); for I := 0 to High(Result) do - begin TgClass.GetTgClass.Create(LJsonArr.Items[I].ToJSON).GetInterface(GUID, Result[I]); - end; finally LJsonArr.Free; end; end; -function TTelegramBot.stopMessageLiveLocation(const ChatId: TValue; const MessageId: Int64; const ReplyMarkup: IReplyMarkup): Boolean; -var - Parameters: TDictionary; -begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := ExecuteMethod('stopMessageLiveLocation', Parameters); - finally - Parameters.Free; - end; -end; - -function TTelegramBot.stopMessageLiveLocation(const InlineMessageId: string; const ReplyMarkup: IReplyMarkup): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.GetToken: string; begin - Parameters := TDictionary.Create; - try - Parameters.Add('inline_message_id', InlineMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := ExecuteMethod('stopMessageLiveLocation', Parameters); - finally - Parameters.Free; - end; + Result := FToken; end; -function TTelegramBot.GetWebhookInfo: ItgWebhookInfo; +procedure TTelegramBot.SetToken(const Value: string); begin - Result := TtgWebhookInfo.Create(GetJSONFromMethod('getWebhookInfo', nil).ToJSON); + FToken := Value; end; -function TTelegramBot.GetUpdates(const Offset, Limit, Timeout: Int64; const AllowedUpdates: TAllowedUpdates): TArray; -var - Parameters: TDictionary; +function TTelegramBot.GetExceptionManager: ItgExceptionHandler; begin - Parameters := TDictionary.Create; - try - Parameters.Add('offset', Offset); - Parameters.Add('limit', Limit); - Parameters.Add('timeout', Timeout); - Parameters.Add('allowed_updates', AllowedUpdates.ToString); - Result := GetArrayFromMethod(TtgUpdate, 'getUpdates', Parameters); - finally - Parameters.Free; - end; + if FExceptionManager = nil then + FExceptionManager := TtgExceptionManagerConsole.Create; + Result := FExceptionManager; end; -function TTelegramBot.DeleteWebhook: Boolean; +procedure TTelegramBot.SetExceptionManager(const Value: ItgExceptionHandler); begin - Result := ExecuteMethod('deleteWebhook', nil); + FExceptionManager := Value; end; -{$ENDREGION} -{$REGION 'Basic methods'} -function TTelegramBot.UnbanChatMember(const ChatId: TValue; const UserId: Int64): Boolean; -var - Parameters: TDictionary; -begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('user_id', UserId); - Result := ExecuteMethod('unbanChatMember', Parameters); - finally - Parameters.Free; - end; -end; -function TTelegramBot.SendLocation(const ChatId: TValue; const Location: TtgLocation; const LivePeriod: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; -begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('latitude', Location.Latitude); - Parameters.Add('longitude', Location.Longitude); - Parameters.Add('live_period', LivePeriod); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendLocation', Parameters)); - finally - Parameters.Free; - end; -end; +{$ENDREGION} +{$REGION 'Getting updates'} -function TTelegramBot.sendMediaGroup(const ChatId: TValue; const AMedia: TArray; const ADisableNotification: Boolean; const ReplyToMessageId: Int64): TArray; -var - Parameters: TDictionary; +function TTelegramBot.SetWebhook(const Url: string; const Certificate: TtgFileToSend; const MaxConnections: Int64; const AllowedUpdates: TAllowedUpdates): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('media', TJsonUtils.ArrayToJString(AMedia)); - Parameters.Add('disable_notification', ADisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Result := GetArrayFromMethod(TTgMessage, 'sendMediaGroup', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('setWebhook', [// + TtgApiParameter.Create('url', Url, '', True), // + TtgApiParameter.Create('certificate', Certificate, nil, False), // + TtgApiParameter.Create('max_connections', MaxConnections, 0, False), // + TtgApiParameter.Create('allowed_updates', AllowedUpdates.ToString, '[]', False) // + ])); end; -function TTelegramBot.SendPhoto(const ChatId, Photo: TValue; const Caption: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.GetWebhookInfo: ItgWebhookInfo; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('photo', Photo); - Parameters.Add('caption', Caption); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendPhoto', Parameters)); - finally - Parameters.Free; - end; + Result := TtgWebhookInfo.Create(RequestAPI('getWebhookInfo', nil)); end; -function TTelegramBot.SendSticker(const ChatId, Sticker: TValue; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.GetUpdates(const Offset, Limit, Timeout: Int64; const AllowedUpdates: TAllowedUpdates): TArray; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('sticker', Sticker); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendSticker', Parameters)); - finally - Parameters.Free; - end; + Result := GetArrayFromMethod(TtgUpdate, RequestAPI('getUpdates', [// + TtgApiParameter.Create('offset', Offset, 0, False), // + TtgApiParameter.Create('limit', Limit, 100, False), // + TtgApiParameter.Create('timeout', Timeout, 0, False), // + TtgApiParameter.Create('allowed_updates', AllowedUpdates.ToString, '[]', False) // + ])); end; -function TTelegramBot.SendMessage(const ChatId: TValue; const Text: string; const ParseMode: TtgParseMode; const DisableWebPagePreview, DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.DeleteWebhook: Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('text', Text); - Parameters.Add('parse_mode', ParseMode.ToString); - Parameters.Add('disable_web_page_preview', DisableWebPagePreview); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendMessage', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('deleteWebhook', nil)); end; +{$ENDREGION} +{$REGION 'Basic methods'} -function TTelegramBot.SendVenue(const ChatId: TValue; const Venue: TtgVenue; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.stopMessageLiveLocation(const ChatId: TValue; const MessageId: Int64; ReplyMarkup: IReplyMarkup): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('latitude', Venue.Location.Latitude); - Parameters.Add('longitude', Venue.Location.Longitude); - Parameters.Add('title', Venue.title); - Parameters.Add('address', Venue.Address); - Parameters.Add('foursquare_id', Venue.FoursquareId); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendVenue', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('stopMessageLiveLocation', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, 0, True), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.SendVideo(const ChatId, Video: TValue; const Caption: string; const Duration, Width, Height: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.stopMessageLiveLocation(const InlineMessageId: string; ReplyMarkup: IReplyMarkup): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('video', Video); - Parameters.Add('duration', Duration); - Parameters.Add('width', Width); - Parameters.Add('height', Height); - Parameters.Add('caption', Caption); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendVideo', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('stopMessageLiveLocation', [// + TtgApiParameter.Create('inline_message_id', InlineMessageId, '', True), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.SendVideoNote(const ChatId, VideoNote: TValue; const Duration, Length: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - LParameters: TDictionary; +function TTelegramBot.UnbanChatMember(const ChatId: TValue; const UserId: Int64): Boolean; begin - LParameters := TDictionary.Create; - try - LParameters.Add('chat_id', ChatId); - LParameters.Add('video_note', VideoNote); - LParameters.Add('duration', Duration); - LParameters.Add('length', Length); - LParameters.Add('disable_notification', DisableNotification); - LParameters.Add('reply_to_message_id', ReplyToMessageId); - LParameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendVoice', LParameters)); - finally - LParameters.Free; - end; + Result := ExtractBool(RequestAPI('unbanChatMember', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('user_id', UserId, 0, True) // + ])); end; -function TTelegramBot.SendVoice(const ChatId, Voice: TValue; const Caption: string; const Duration: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.SendLocation(const ChatId: TValue; const Location: TtgLocation; const LivePeriod: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('voice', Voice); - Parameters.Add('caption', Caption); - Parameters.Add('duration', Duration); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendVoice', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('sendLocation', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('latitude', Location.Latitude, 0.0, True), // + TtgApiParameter.Create('longitude', Location.Longitude, 0.0, True), // + TtgApiParameter.Create('live_period', LivePeriod, 0, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.SendAudio(const ChatId, Audio: TValue; const Caption: string; const Duration: Int64; const Performer: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.sendMediaGroup(const ChatId: TValue; const AMedia: TArray; const ADisableNotification: Boolean; const ReplyToMessageId: Int64): TArray; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('audio', Audio); - Parameters.Add('duration', Duration); - Parameters.Add('performer', Performer); - Parameters.Add('caption', Caption); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendAudio', Parameters)); - finally - Parameters.Free; - end; + Result := GetArrayFromMethod(TTgMessage, RequestAPI('sendMediaGroup', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('media', TJsonUtils.ArrayToJString(AMedia), '[]', True), // + TtgApiParameter.Create('disable_notification', ADisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False) // + ])); +end; + +function TTelegramBot.SendPhoto(const ChatId: TValue; const Photo: TtgFileToSend; const Caption: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendPhoto', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('photo', Photo, nil, True), // + TtgApiParameter.Create('caption', Caption, '', False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); +end; + +function TTelegramBot.SendMessage(const ChatId: TValue; const Text: string; const ParseMode: TtgParseMode; const DisableWebPagePreview, DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendMessage', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('text', Text, '', True), // + TtgApiParameter.Create('parse_mode', ParseMode.ToString, '', False), // + TtgApiParameter.Create('disable_web_page_preview', DisableWebPagePreview, False, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); +end; + +function TTelegramBot.SendVenue(const ChatId: TValue; const Venue: TtgVenue; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendVenue', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('latitude', Venue.Location.Latitude, '', True), // + TtgApiParameter.Create('longitude', Venue.Location.Longitude, '', True), // + TtgApiParameter.Create('title', Venue.Title, '', True), // + TtgApiParameter.Create('address', Venue.Address, '', True), // + TtgApiParameter.Create('foursquare_id', Venue.FoursquareId, False, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); +end; + +function TTelegramBot.SendVideo(const ChatId: TValue; const Video: TtgFileToSend; const Caption: string; const Duration, Width, Height: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendVideo', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('video', Video, '', True), // + TtgApiParameter.Create('duration', Duration, 0, False), // + TtgApiParameter.Create('width', Width, 0, False), // + TtgApiParameter.Create('height', Height, 0, False), // + TtgApiParameter.Create('caption', Caption, '', False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); +end; + +function TTelegramBot.SendVideoNote(const ChatId: TValue; const VideoNote: TtgFileToSend; const Duration, Length: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendVideoNote', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('video_note', VideoNote, '', True), // + TtgApiParameter.Create('duration', Duration, 0, False), // + TtgApiParameter.Create('length', Length, 0, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); +end; + +function TTelegramBot.SendVoice(const ChatId: TValue; const Voice: TtgFileToSend; const Caption: string; const Duration: Int64; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendVoice', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('voice', Voice, '', True), // + TtgApiParameter.Create('caption', Caption, '', False), // + TtgApiParameter.Create('duration', Duration, 0, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); +end; + +function TTelegramBot.SendAudio(const ChatId: TValue; const Audio: TtgFileToSend; const Caption: string; const Duration: Int64; const Performer: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendAudio', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('audio', Audio, nil, True), // + TtgApiParameter.Create('duration', Duration, 0, False), // + TtgApiParameter.Create('performer', Performer, '', False), // + TtgApiParameter.Create('caption', Caption, 0, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; function TTelegramBot.SendChatAction(const ChatId: TValue; const Action: TtgSendChatAction): Boolean; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('action', Action.ToString); - Result := ExecuteMethod('sendChatAction', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('sendChatAction', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('action', Action.ToString, '', True)// + ])); end; -function TTelegramBot.SendContact(const ChatId: TValue; const Contact: TtgContact; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.SendContact(const ChatId: TValue; const Contact: TtgContact; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('phone_number', Contact.PhoneNumber); - Parameters.Add('first_name', Contact.FirstName); - Parameters.Add('last_name', Contact.LastName); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendContact', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('sendContact', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('phone_number', Contact.PhoneNumber, '', True), // + TtgApiParameter.Create('first_name', Contact.FirstName, '', True), // + TtgApiParameter.Create('last_name', Contact.LastName, '', False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.SendDocument(const ChatId, Document: TValue; const Caption: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.SendDocument(const ChatId: TValue; const Document: TtgFileToSend; const Caption: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('document', Document); - Parameters.Add('caption', Caption); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendDocument', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('sendDocument', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('document', Document, nil, True), // + TtgApiParameter.Create('caption', Caption, '', False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.KickChatMember(const ChatId: TValue; const UserId, UntilDate: Int64): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.KickChatMember(const ChatId: TValue; const UserId: Int64; const UntilDate: TDateTime): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('user_id', UserId); - Parameters.Add('until_date', UntilDate); - Result := ExecuteMethod('kickChatMember', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('kickChatMember', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('until_date', UntilDate, 0, False)// + ])); end; function TTelegramBot.LeaveChat(const ChatId: TValue): Boolean; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := ExecuteMethod('leaveChat', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('leaveChat', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; function TTelegramBot.GetUserProfilePhotos(const ChatId: TValue; const Offset, Limit: Int64): ItgUserProfilePhotos; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('offset', Offset); - Parameters.Add('limit', Limit); - Result := TtgUserProfilePhotos.Create(RequestAPI('getUserProfilePhotos', Parameters)); - finally - Parameters.Free; - end; + Result := TtgUserProfilePhotos.Create(RequestAPI('getUserProfilePhotos', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('offset', Offset, 0, True), // + TtgApiParameter.Create('limit', Limit, 100, False) // + ])); end; function TTelegramBot.GetMe: ItgUser; @@ -2496,679 +767,437 @@ function TTelegramBot.GetMe: ItgUser; Result := TtgUser.Create(RequestAPI('getMe', nil)); end; -function TTelegramBot.GetToken: string; -begin - Result := FToken; -end; - -function TTelegramBot.getStickerSet(const Name: string): TtgStickerSet; -var - Parameters: TDictionary; -begin - Parameters := TDictionary.Create; - try - Parameters.Add('name', Name); - Result := TtgStickerSet.Create(RequestAPI('getStickerSet', Parameters)); - finally - Parameters.Free; - end; -end; - function TTelegramBot.ForwardMessage(const ChatId, FromChatId: TValue; const MessageId: Int64; const DisableNotification: Boolean): ITgMessage; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('from_chat_id', FromChatId); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('message_id', MessageId); - Result := TTgMessage.Create(RequestAPI('forwardMessage', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('forwardMessage', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('from_chat_id', FromChatId, 0, True), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('message_id', MessageId, 0, False)])); end; function TTelegramBot.GetChat(const ChatId: TValue): ItgChat; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := TtgChat.Create(RequestAPI('getChat', Parameters)); - finally - Parameters.Free; - end; + Result := TtgChat.Create(RequestAPI('getChat', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; function TTelegramBot.GetChatAdministrators(const ChatId: TValue): TArray; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := GetArrayFromMethod(TtgChatMember, 'getChatAdministrators', Parameters); - finally - Parameters.Free; - end; + Result := GetArrayFromMethod(TtgChatMember, // + RequestAPI('getChatAdministrators', // + [TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; function TTelegramBot.GetChatMember(const ChatId: TValue; const UserId: Int64): ItgChatMember; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('user_id', UserId); - Result := TtgChatMember.Create(RequestAPI('getChatMember', Parameters)); - finally - Parameters.Free; - end; + Result := TtgChatMember.Create(RequestAPI('getChatMember', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('user_id', UserId, 0, True)])); end; function TTelegramBot.GetChatMembersCount(const ChatId: TValue): Int64; var - Parameters: TDictionary; LJson: TJSONValue; begin - Parameters := TDictionary.Create; + LJson := TJSONObject.ParseJSONValue(RequestAPI('getChatMembersCount', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); try - Parameters.Add('chat_id', ChatId); - LJson := TJSONObject.ParseJSONValue(RequestAPI('getChatMembersCount', Parameters)); - try - if not LJson.TryGetValue(Result) then - Result := 0; - finally - LJson.Free; - end; + if not LJson.TryGetValue(Result) then + Result := 0; finally - Parameters.Free; + LJson.Free; end; end; -function TTelegramBot.GetExceptionManager: ItgExceptionHandler; -begin - if FExceptionManager = nil then - FExceptionManager := TtgExceptionManagerConsole.Create; - Result := FExceptionManager; -end; - function TTelegramBot.GetFile(const FileId: string): ItgFile; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('file_id', FileId); - Result := TtgFile.Create(RequestAPI('getFile', Parameters)); - finally - Parameters.Free; - end; -end; - -function TTelegramBot.addStickerToSet(const UserId: Int64; const Name: string; const PngSticker: TValue; const Emojis: string; const MaskPosition: TtgMaskPosition): Boolean; -var - Parameters: TDictionary; -begin - Parameters := TDictionary.Create; - try - Parameters.Add('user_id', UserId); - Parameters.Add('name', Name); - Parameters.Add('png_sticker', PngSticker); - Parameters.Add('emojis', Emojis); - Parameters.Add('mask_position', MaskPosition); - Result := ExecuteMethod('addStickerToSet', Parameters); - finally - Parameters.Free; - end; + Result := TtgFile.Create(RequestAPI('getFile', [// + TtgApiParameter.Create('file_id', FileId, '', True)])); end; function TTelegramBot.AnswerCallbackQuery(const CallbackQueryId, Text: string; const ShowAlert: Boolean; const Url: string; const CacheTime: Int64): Boolean; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('callback_query_id', CallbackQueryId); - Parameters.Add('text', Text); - Parameters.Add('show_alert', ShowAlert); - Parameters.Add('url', Url); - Parameters.Add('cache_time', CacheTime); - Result := ExecuteMethod('answerCallbackQuery', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('answerCallbackQuery', [// + TtgApiParameter.Create('callback_query_id', CallbackQueryId, '', True), // + TtgApiParameter.Create('text', Text, '', True), // + TtgApiParameter.Create('show_alert', ShowAlert, False, False), // + TtgApiParameter.Create('url', Url, '', False), // + TtgApiParameter.Create('cache_time', CacheTime, 0, False)])); end; {$ENDREGION} {$REGION 'Updating messages'} -function TTelegramBot.EditMessageText(const InlineMessageId, Text: string; const ParseMode: TtgParseMode; const DisableWebPagePreview: Boolean; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.EditMessageText(const InlineMessageId, Text: string; const ParseMode: TtgParseMode; const DisableWebPagePreview: Boolean; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('inline_message_id', InlineMessageId); - Parameters.Add('text', Text); - Parameters.Add('parse_mode', ParseMode.ToString); - Parameters.Add('disable_web_page_preview', DisableWebPagePreview); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('editMessageText', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage(RequestAPI('editMessageText', [// + TtgApiParameter.Create('inline_message_id', InlineMessageId, 0, True), // + TtgApiParameter.Create('text', Text, 0, True), // + TtgApiParameter.Create('parse_mode', ParseMode.ToString, False, False), // + TtgApiParameter.Create('disable_web_page_preview', DisableWebPagePreview, False, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), 0, False)])); end; -function TTelegramBot.EditMessageText(const ChatId: TValue; const MessageId: Int64; const Text: string; const ParseMode: TtgParseMode; const DisableWebPagePreview: Boolean; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.EditMessageText(const ChatId: TValue; const MessageId: Int64; const Text: string; const ParseMode: TtgParseMode; const DisableWebPagePreview: Boolean; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('text', Text); - Parameters.Add('parse_mode', ParseMode.ToString); - Parameters.Add('disable_web_page_preview', DisableWebPagePreview); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('editMessageText', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('editMessageText', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, nil, True), // + TtgApiParameter.Create('text', Text, '', False), // + TtgApiParameter.Create('parse_mode', ParseMode.ToString, False, False), // + TtgApiParameter.Create('disable_web_page_preview', DisableWebPagePreview, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; function TTelegramBot.DeleteMessage(const ChatId: TValue; const MessageId: Int64): Boolean; -var - Parameters: TDictionary; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Result := ExecuteMethod('deleteMessage', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('deleteMessage', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, nil, True) // + ])); end; -function TTelegramBot.deleteStickerFromSet(const Sticker: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.EditMessageCaption(const ChatId: TValue; const MessageId: Int64; const Caption: string; ReplyMarkup: IReplyMarkup): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('sticker', Sticker); - Result := ExecuteMethod('deleteStickerFromSet', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('editMessageCaption', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, nil, True), // + TtgApiParameter.Create('caption', Caption, '', False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.EditMessageCaption(const ChatId: TValue; const MessageId: Int64; const Caption: string; const ReplyMarkup: IReplyMarkup): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.EditMessageCaption(const InlineMessageId, Caption: string; ReplyMarkup: IReplyMarkup): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('caption', Caption); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := ExecuteMethod('editMessageCaption', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('editMessageCaption', [// + TtgApiParameter.Create('inline_message_id', InlineMessageId, nil, True), // + TtgApiParameter.Create('caption', Caption, '', False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.EditMessageCaption(const InlineMessageId, Caption: string; const ReplyMarkup: IReplyMarkup): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.editMessageLiveLocation(const ChatId: TValue; const MessageId: Int64; const Location: TtgLocation; ReplyMarkup: IReplyMarkup): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('caption', Caption); - Parameters.Add('inline_message_id', InlineMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := ExecuteMethod('editMessageCaption', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('editMessageLiveLocation', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, 0, True), // + TtgApiParameter.Create('latitude', Location.Latitude, '', False), // + TtgApiParameter.Create('longitude', Location.Longitude, False, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.editMessageLiveLocation(const ChatId: TValue; const MessageId: Int64; const Location: TtgLocation; const ReplyMarkup: IReplyMarkup): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.editMessageLiveLocation(const InlineMessageId: string; const Location: TtgLocation; ReplyMarkup: IReplyMarkup): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('latitude', Location.Latitude); - Parameters.Add('longitude', Location.Longitude); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := ExecuteMethod('editMessageLiveLocation', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('editMessageLiveLocation', [// + TtgApiParameter.Create('inline_message_id', InlineMessageId, 0, True), // + TtgApiParameter.Create('latitude', Location.Latitude, '', False), // + TtgApiParameter.Create('longitude', Location.Longitude, False, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.editMessageLiveLocation(const InlineMessageId: string; const Location: TtgLocation; const ReplyMarkup: IReplyMarkup): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.EditMessageReplyMarkup(const ChatId: TValue; const MessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('inline_message_id', InlineMessageId); - Parameters.Add('latitude', Location.Latitude); - Parameters.Add('longitude', Location.Longitude); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := ExecuteMethod('editMessageLiveLocation', Parameters); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('editMessageReplyMarkup', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, '', False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.EditMessageReplyMarkup(const ChatId: TValue; const MessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.EditMessageReplyMarkup(const InlineMessageId: string; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('editMessageReplyMarkup', Parameters)); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('editMessageReplyMarkup', [// + TtgApiParameter.Create('inline_message_id', InlineMessageId, 0, True), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; +{$ENDREGION} -function TTelegramBot.EditMessageReplyMarkup(const InlineMessageId: string; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; + + +{$REGION 'Manage groups and channels'} + +function TTelegramBot.DeleteChatPhoto(const ChatId: TValue): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('inline_message_id', InlineMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('editMessageReplyMarkup', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('deleteChatPhoto', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; -{$ENDREGION} -{$REGION 'Inline mode'} -function TTelegramBot.AnswerInlineQuery(const InlineQueryId: string; const Results: TArray; const CacheTime: Int64; const IsPersonal: Boolean; const NextOffset, SwitchPmText, SwitchPmParameter: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.deleteChatStickerSet(const ChatId: TValue): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('inline_query_id', InlineQueryId); - Parameters.Add('results', TJsonUtils.ArrayToJString(Results)); - Parameters.Add('cache_time', CacheTime); - Parameters.Add('is_personal', IsPersonal); - Parameters.Add('next_offset', NextOffset); - Parameters.Add('switch_pm_text', SwitchPmText); - Parameters.Add('switch_pm_parameter', SwitchPmParameter); - Result := ExecuteMethod('answerInlineQuery', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('deleteChatStickerSet', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; -{$ENDREGION} -{$REGION 'Payments'} -function TTelegramBot.SendInvoice(const ChatId: Int64; const title: string; const Description: string; const Payload: string; const ProviderToken: string; const StartParameter: string; const Currency: string; const Prices: TArray; const ProviderData: string; const PhotoUrl: string; const PhotoSize: Int64; const PhotoWidth: Int64; const PhotoHeight: Int64; const NeedName: Boolean; const NeedPhoneNumber: Boolean; const NeedEmail: Boolean; const NeedShippingAddress: Boolean; const IsFlexible: Boolean; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - LParameters: TDictionary; +function TTelegramBot.ExportChatInviteLink(const ChatId: TValue): string; begin - LParameters := TDictionary.Create; - try - LParameters.Add('chat_id', ChatId); - LParameters.Add('title', title); - LParameters.Add('description', Description); - LParameters.Add('payload', Payload); - LParameters.Add('provider_token', ProviderToken); - LParameters.Add('start_parameter', StartParameter); - LParameters.Add('currency', Currency); - LParameters.Add('prices', TJsonUtils.ArrayToJString(Prices)); - LParameters.Add('provider_data', ProviderData); - LParameters.Add('photo_url', PhotoUrl); - LParameters.Add('photo_size', PhotoSize); - LParameters.Add('photo_width', PhotoWidth); - LParameters.Add('photo_height', PhotoHeight); - LParameters.Add('need_name', NeedName); - LParameters.Add('need_phone_number', NeedPhoneNumber); - LParameters.Add('need_email', NeedEmail); - LParameters.Add('need_shipping_address', NeedShippingAddress); - LParameters.Add('is_flexible', IsFlexible); - LParameters.Add('disable_notification', DisableNotification); - LParameters.Add('reply_to_message_id', ReplyToMessageId); - LParameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendInvoice', LParameters)); - finally - LParameters.Free; - end; + Result := GetValueFromMethod(RequestAPI('exportChatInviteLink', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; -function TTelegramBot.AnswerPreCheckoutQuery(const PreCheckoutQueryId: string; const Ok: Boolean; const ErrorMessage: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.PinChatMessage(const ChatId: TValue; const MessageId: Int64; const DisableNotification: Boolean): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('Pre_checkout_query_id', PreCheckoutQueryId); - Parameters.Add('Ok', Ok); - Parameters.Add('Error_message', ErrorMessage); - Result := ExecuteMethod('AnswerPreCheckoutQuery', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('pinChatMessage', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, 0, True), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False)])); end; -function TTelegramBot.AnswerShippingQuery(const ShippingQueryId: string; const Ok: Boolean; const ShippingOptions: TArray; const ErrorMessage: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.SetChatDescription(const ChatId: TValue; const Description: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('Shipping_query_id', ShippingQueryId); - Parameters.Add('Ok', Ok); - Parameters.Add('Shipping_options', TJsonUtils.ArrayToJString(ShippingOptions)); - Parameters.Add('Error_message', ErrorMessage); - Result := ExecuteMethod('answerShippingQuery', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('setChatDescription', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('description', Description, '', True)])); end; -function TTelegramBot.createNewStickerSet(const UserId: Int64; const Name, Title: string; const PngSticker: TValue; const Emojis: string; const ContainsMasks: Boolean; const MaskPosition: TtgMaskPosition): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.SetChatPhoto(const ChatId: TValue; const Photo: TtgFileToSend): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('user_id', UserId); - Parameters.Add('name', Name); - Parameters.Add('title', Title); - Parameters.Add('png_sticker', PngSticker); - Parameters.Add('emojis', Emojis); - Parameters.Add('contains_masks', ContainsMasks); - Parameters.Add('mask_position', MaskPosition); - Result := ExecuteMethod('createNewStickerSet', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('setChatPhoto', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('photo', Photo, nil, True)])); end; -{$ENDREGION} -{$REGION 'Games'} -function TTelegramBot.SetGameScore(const UserId, Score: Int64; const Force, DisableEditMessage: Boolean; const ChatId, MessageId: Int64; const InlineMessageId: string): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.setChatStickerSet(const ChatId: TValue; const StickerSetName: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('user_id', UserId); - Parameters.Add('score', Score); - Parameters.Add('force', Force); - Parameters.Add('disable_edit_message', DisableEditMessage); - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('inline_message_id', InlineMessageId); - Result := TTgMessage.Create(RequestAPI('setGameScore', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('setChatStickerSet', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('sticker_set_name', StickerSetName, '', True)])); end; -function TTelegramBot.setStickerPositionInSet(const Sticker: string; const Position: Int64): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.SetChatTitle(const ChatId: TValue; const Title: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('sticker', Sticker); - Parameters.Add('position', Position); - Result := ExecuteMethod('setStickerPositionInSet', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('setChatTitle', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('title', Title, '', True)])); end; -function TTelegramBot.SendGame(const ChatId: Int64; const GameShortName: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; const ReplyMarkup: IReplyMarkup): ITgMessage; -var - Parameters: TDictionary; +function TTelegramBot.UnpinChatMessage(const ChatId: TValue): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('game_short_name', GameShortName); - Parameters.Add('disable_notification', DisableNotification); - Parameters.Add('reply_to_message_id', ReplyToMessageId); - Parameters.Add('reply_markup', TInterfacedObject(ReplyMarkup)); - Result := TTgMessage.Create(RequestAPI('sendGame', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('unpinChatMessage', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True)])); end; -function TTelegramBot.GetGameHighScores(const UserId, ChatId, MessageId: Int64; const InlineMessageId: string): TArray; -var - Parameters: TDictionary; - LJson: TJSONArray; - I: Integer; + +{$ENDREGION} +{$REGION 'Manage users and admins'} + +function TTelegramBot.PromoteChatMember(const ChatId: TValue; const UserId: Int64; const CanChangeInfo, CanPostMessages, CanEditMessages, CanDeleteMessages, CanInviteUsers, CanRestrictMembers, CanPinMessages, CanPromoteMembers: Boolean): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('user_id', UserId); - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('inline_message_id', InlineMessageId); - LJson := TJSONObject.ParseJSONValue(RequestAPI('getGameHighScores', Parameters)) as TJSONArray; - try - SetLength(Result, LJson.Count); - for I := 0 to High(Result) do - Result[I] := TtgGameHighScore.Create(LJson.Items[I].ToJSON); - finally - LJson.Free; - end; - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('promoteChatMember', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('can_change_info', CanChangeInfo, False, False), // + TtgApiParameter.Create('can_post_messages', CanPostMessages, False, False), // + TtgApiParameter.Create('can_edit_messages', CanEditMessages, False, False), // + TtgApiParameter.Create('can_delete_messages', CanDeleteMessages, False, False), // + TtgApiParameter.Create('can_invite_users', CanInviteUsers, False, False), // + TtgApiParameter.Create('can_restrict_members', CanRestrictMembers, False, False), // + TtgApiParameter.Create('can_pin_messages', CanPinMessages, False, False), // + TtgApiParameter.Create('can_promote_members', CanPromoteMembers, False, False)])); +end; + +function TTelegramBot.RestrictChatMember(const ChatId: TValue; const UserId: Int64; const UntilDate: TDateTime; const CanSendMessages, CanSendMediaMessages, CanSendOtherMessages, CanAddWebPagePreviews: Boolean): Boolean; +begin + Result := ExtractBool(RequestAPI('restrictChatMember', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('until_date', UntilDate, 0, False), // + TtgApiParameter.Create('can_send_messages', CanSendMessages, False, False), // + TtgApiParameter.Create('can_send_media_messages', CanSendMediaMessages, False, False), // + TtgApiParameter.Create('can_send_other_messages', CanSendOtherMessages, False, False), // + TtgApiParameter.Create('can_add_web_page_previews', CanAddWebPagePreviews, False, False)])); end; {$ENDREGION} -{$REGION 'Manage groups and channels'} +{$REGION 'Stickers'} -function TTelegramBot.DeleteChatPhoto(const ChatId: TValue): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.addStickerToSet(const UserId: Int64; const Name: string; const PngSticker: TValue; const Emojis: string; const MaskPosition: TtgMaskPosition): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := ExecuteMethod('deleteChatPhoto', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('addStickerToSet', [// + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('name', Name, 0, True), // + TtgApiParameter.Create('png_sticker', PngSticker, False, False), // + TtgApiParameter.Create('emojis', Emojis, False, False), // + TtgApiParameter.Create('mask_position', MaskPosition, 0, False)])); end; -function TTelegramBot.deleteChatStickerSet(const ChatId: TValue): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.createNewStickerSet(const UserId: Int64; const Name, Title: string; const PngSticker: TValue; const Emojis: string; const ContainsMasks: Boolean; const MaskPosition: TtgMaskPosition): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := ExecuteMethod('deleteChatStickerSet', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('createNewStickerSet', [// + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('name', Name, nil, True), // + TtgApiParameter.Create('title', Title, 0, True), // + TtgApiParameter.Create('png_sticker', PngSticker, 0, True), // + TtgApiParameter.Create('emojis', Emojis, nil, True), // + TtgApiParameter.Create('contains_masks', ContainsMasks, 0, True), // + TtgApiParameter.Create('mask_position', MaskPosition, '', False)])); end; -function TTelegramBot.ExportChatInviteLink(const ChatId: TValue): string; -var - Parameters: TDictionary; +function TTelegramBot.deleteStickerFromSet(const Sticker: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := GetValueFromMethod('exportChatInviteLink', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('deleteStickerFromSet', [// + TtgApiParameter.Create('sticker', Sticker, 0, True)])); end; -function TTelegramBot.PinChatMessage(const ChatId: TValue; const MessageId: Int64; const DisableNotification: Boolean): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.getStickerSet(const Name: string): TtgStickerSet; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('message_id', MessageId); - Parameters.Add('disable_notification', DisableNotification); - Result := ExecuteMethod('pinChatMessage', Parameters); - finally - Parameters.Free; - end; + Result := TtgStickerSet.Create(RequestAPI('getStickerSet', [// + TtgApiParameter.Create('name', Name, 0, True)])); end; -function TTelegramBot.SetChatDescription(const ChatId: TValue; const Description: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.SendSticker(const ChatId, Sticker: TValue; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('description', Description); - Result := ExecuteMethod('setChatDescription', Parameters); - finally - Parameters.Free; - end; + Result := TTgMessage.Create(RequestAPI('sendSticker', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('sticker', Sticker, '', True), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, 0, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.SetChatPhoto(const ChatId: TValue; const Photo: TtgFileToSend): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.setStickerPositionInSet(const Sticker: string; const Position: Int64): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('photo', Photo); - Result := ExecuteMethod('setChatPhoto', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('setStickerPositionInSet', [// + TtgApiParameter.Create('sticker', Sticker, 0, True), // + TtgApiParameter.Create('position', Position, nil, True)])); end; -function TTelegramBot.setChatStickerSet(const ChatId: TValue; const StickerSetName: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.uploadStickerFile(const UserId: Int64; const PngSticker: TtgFileToSend): ItgFile; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('sticker_set_name', StickerSetName); - Result := ExecuteMethod('setChatStickerSet', Parameters); - finally - Parameters.Free; - end; + Result := TtgFile.Create(RequestAPI('uploadStickerFile', [// + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('png_sticker', PngSticker, nil, True)])); end; +{$ENDREGION} +{$REGION 'Inline mode'} -function TTelegramBot.SetChatTitle(const ChatId: TValue; const Title: string): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.AnswerInlineQuery(const InlineQueryId: string; const Results: TArray; const CacheTime: Int64; const IsPersonal: Boolean; const NextOffset, SwitchPmText, SwitchPmParameter: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('title', Title); - Result := ExecuteMethod('setChatTitle', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('answerInlineQuery', [// + TtgApiParameter.Create('inline_query_id', InlineQueryId, '', True), // + TtgApiParameter.Create('results', TJsonUtils.ArrayToJString(Results), nil, True), // + TtgApiParameter.Create('cache_time', CacheTime, 0, False), // + TtgApiParameter.Create('is_personal', IsPersonal, False, False), // + TtgApiParameter.Create('next_offset', NextOffset, '', False), // + TtgApiParameter.Create('switch_pm_text', SwitchPmText, '', False), // + TtgApiParameter.Create('switch_pm_parameter', SwitchPmParameter, '', False) // + ])); end; -procedure TTelegramBot.SetExceptionManager(const Value: ItgExceptionHandler); + +{$ENDREGION} +{$REGION 'Payments'} + +function TTelegramBot.SendInvoice(const ChatId: Int64; const title: string; const Description: string; const Payload: string; const ProviderToken: string; const StartParameter: string; const Currency: string; const Prices: TArray; const ProviderData: string; const PhotoUrl: string; const PhotoSize: Int64; const PhotoWidth: Int64; const PhotoHeight: Int64; const NeedName: Boolean; const NeedPhoneNumber: Boolean; const NeedEmail: Boolean; const NeedShippingAddress: Boolean; const IsFlexible: Boolean; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; begin - FExceptionManager := Value; + Result := TTgMessage.Create(RequestAPI('sendInvoice', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('title', title, '', True), // + TtgApiParameter.Create('description', Description, '', True), // + TtgApiParameter.Create('payload', Payload, '', True), // + TtgApiParameter.Create('provider_token', ProviderToken, '', True), // + TtgApiParameter.Create('start_parameter', StartParameter, '', True), // + TtgApiParameter.Create('currency', Currency, '', True), // + TtgApiParameter.Create('prices', TJsonUtils.ArrayToJString(Prices), nil, True), // + TtgApiParameter.Create('provider_data', ProviderData, '', False), // + TtgApiParameter.Create('photo_url', PhotoUrl, '', False), // + TtgApiParameter.Create('photo_size', PhotoSize, 0, False), // + TtgApiParameter.Create('photo_width', PhotoWidth, 0, False), // + TtgApiParameter.Create('photo_height', PhotoHeight, 0, False), // + TtgApiParameter.Create('need_name', NeedName, False, False), // + TtgApiParameter.Create('need_phone_number', NeedPhoneNumber, False, False), // + TtgApiParameter.Create('need_email', NeedEmail, False, False), // + TtgApiParameter.Create('need_shipping_address', NeedShippingAddress, False, False), // + TtgApiParameter.Create('is_flexible', IsFlexible, False, False), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, False, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False) // + ])); end; -function TTelegramBot.UnpinChatMessage(const ChatId: TValue): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.AnswerPreCheckoutQueryBad(const PreCheckoutQueryId, ErrorMessage: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Result := ExecuteMethod('unpinChatMessage', Parameters); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('AnswerPreCheckoutQuery', [// + TtgApiParameter.Create('Pre_checkout_query_id', PreCheckoutQueryId, 0, True), // + TtgApiParameter.Create('Ok', False, True, False), // + TtgApiParameter.Create('Error_message', ErrorMessage, '', True)])); end; -function TTelegramBot.uploadStickerFile(const UserId: Int64; const PngSticker: TtgFileToSend): ItgFile; -var - Parameters: TDictionary; +function TTelegramBot.AnswerPreCheckoutQueryGood(const PreCheckoutQueryId: string): Boolean; begin - Parameters := TDictionary.Create; - try - Parameters.Add('user_id', UserId); - Parameters.Add('png_sticker', PngSticker); - Result := TtgFile.Create(RequestAPI('uploadStickerFile', Parameters)); - finally - Parameters.Free; - end; + Result := ExtractBool(RequestAPI('AnswerPreCheckoutQuery', [// + TtgApiParameter.Create('Pre_checkout_query_id', PreCheckoutQueryId, 0, True), // + TtgApiParameter.Create('Ok', True, False, False)])); end; + +function TTelegramBot.AnswerShippingQueryBad(const ShippingQueryId, ErrorMessage: string): Boolean; +begin + Result := ExtractBool(RequestAPI('answerShippingQuery', [// + TtgApiParameter.Create('Shipping_query_id', ShippingQueryId, 0, True), // + TtgApiParameter.Create('Ok', False, False, False), // + TtgApiParameter.Create('Error_message', ErrorMessage, '', False) // + ])); +end; + +function TTelegramBot.AnswerShippingQueryGood(const ShippingQueryId: string; const ShippingOptions: TArray): Boolean; +begin + Result := ExtractBool(RequestAPI('answerShippingQuery', [// + TtgApiParameter.Create('Shipping_query_id', ShippingQueryId, 0, True), // + TtgApiParameter.Create('Ok', True, False, False), // + TtgApiParameter.Create('Shipping_options', TJsonUtils.ArrayToJString(ShippingOptions), nil, True)])); +end; + {$ENDREGION} -{$REGION 'Manage users and admins'} -function TTelegramBot.PromoteChatMember(const ChatId: TValue; const UserId: Int64; const CanChangeInfo, CanPostMessages, CanEditMessages, CanDeleteMessages, CanInviteUsers, CanRestrictMembers, CanPinMessages, CanPromoteMembers: Boolean): Boolean; -var - Parameters: TDictionary; +{$REGION 'Games'} + +function TTelegramBot.GetGameHighScores(const UserId: Int64; const InlineMessageId: string): TArray; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('user_id', UserId); - Parameters.Add('can_change_info', CanChangeInfo); - Parameters.Add('can_post_messages', CanPostMessages); - Parameters.Add('can_edit_messages', CanEditMessages); - Parameters.Add('can_delete_messages', CanDeleteMessages); - Parameters.Add('can_invite_users', CanInviteUsers); - Parameters.Add('can_restrict_members', CanRestrictMembers); - Parameters.Add('can_pin_messages', CanPinMessages); - Parameters.Add('can_promote_members', CanPromoteMembers); - Result := ExecuteMethod('promoteChatMember', Parameters); - finally - Parameters.Free; - end; + Result := GetArrayFromMethod(TtgGameHighScore, RequestAPI('getGameHighScores', [// + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('inline_message_id', InlineMessageId, 0, True)])) end; -function TTelegramBot.RestrictChatMember(const ChatId: TValue; const UserId, UntilDate: Int64; const CanSendMessages, CanSendMediaMessages, CanSendOtherMessages, CanAddWebPagePreviews: Boolean): Boolean; -var - Parameters: TDictionary; +function TTelegramBot.GetGameHighScores(const UserId, ChatId, MessageId: Int64): TArray; begin - Parameters := TDictionary.Create; - try - Parameters.Add('chat_id', ChatId); - Parameters.Add('user_id', UserId); - Parameters.Add('until_date', UntilDate); - Parameters.Add('can_send_messages', CanSendMessages); - Parameters.Add('can_send_media_messages', CanSendMediaMessages); - Parameters.Add('can_send_other_messages', CanSendOtherMessages); - Parameters.Add('can_add_web_page_previews', CanAddWebPagePreviews); - Result := ExecuteMethod('restrictChatMember', Parameters); - finally - Parameters.Free; - end; + Result := GetArrayFromMethod(TtgGameHighScore, RequestAPI('getGameHighScores', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, 0, True)])) +end; + +function TTelegramBot.SendGame(const ChatId: Int64; const GameShortName: string; const DisableNotification: Boolean; const ReplyToMessageId: Int64; ReplyMarkup: IReplyMarkup): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('sendGame', [// + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('game_short_name', GameShortName, '', True), // + TtgApiParameter.Create('disable_notification', DisableNotification, False, False), // + TtgApiParameter.Create('reply_to_message_id', ReplyToMessageId, False, False), // + TtgApiParameter.Create('reply_markup', TInterfacedObject(ReplyMarkup), nil, False)])); +end; + +function TTelegramBot.SetGameScore(const UserId, Score: Int64; const InlineMessageId: string; const Force, DisableEditMessage: Boolean): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('setGameScore', [// + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('score', Score, 0, True), // + TtgApiParameter.Create('force', Force, False, False), // + TtgApiParameter.Create('disable_edit_message', DisableEditMessage, False, False), // + TtgApiParameter.Create('inline_message_id', InlineMessageId, 0, True)])); +end; + +function TTelegramBot.SetGameScore(const UserId, Score, ChatId, MessageId: Int64; const Force, DisableEditMessage: Boolean): ITgMessage; +begin + Result := TTgMessage.Create(RequestAPI('setGameScore', [// + TtgApiParameter.Create('user_id', UserId, 0, True), // + TtgApiParameter.Create('score', Score, nil, True), // + TtgApiParameter.Create('force', Force, False, False), // + TtgApiParameter.Create('disable_edit_message', DisableEditMessage, False, False), // + TtgApiParameter.Create('chat_id', ChatId, 0, True), // + TtgApiParameter.Create('message_id', MessageId, 0, True)])); end; {$ENDREGION} diff --git a/Source/TelegAPI.Bot.pas b/Source/TelegAPI.Bot.pas index a922070..e0c246e 100644 --- a/Source/TelegAPI.Bot.pas +++ b/Source/TelegAPI.Bot.pas @@ -216,7 +216,7 @@ interface const DisableWebPagePreview: Boolean = False; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to forward messages of any kind. /// @@ -289,11 +289,12 @@ interface /// End; /// function SendPhoto(// - const ChatId, Photo: TValue; // + const ChatId: TValue; // + const Photo: TtgFileToSend; // const Caption: string = ''; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send audio files, if you want Telegram clients to /// display them in the music player. Your audio must be in the .mp3 @@ -341,13 +342,14 @@ interface /// sendVoice method instead. /// function SendAudio(// - const ChatId, Audio: TValue; // + const ChatId: TValue; // + const Audio: TtgFileToSend; // const Caption: string = ''; // const Duration: Int64 = 0; // const Performer: string = ''; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send general files. /// @@ -386,11 +388,12 @@ interface /// this limit may be changed in the future. /// function SendDocument(// - const ChatId, Document: TValue; // + const ChatId: TValue; // + const Document: TtgFileToSend; // const Caption: string = ''; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send video files, Telegram clients support mp4 /// videos (other formats may be sent as Document). @@ -438,14 +441,15 @@ interface /// limit may be changed in the future. /// function SendVideo(// - const ChatId, Video: TValue; // + const ChatId: TValue; // + const Video: TtgFileToSend; // const Caption: string = ''; // const Duration: Int64 = 0; // const Width: Int64 = 0; // const Height: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send audio files, if you want Telegram clients to @@ -487,12 +491,13 @@ interface /// limit may be changed in the future. /// function SendVoice(// - const ChatId, Voice: TValue; // + const ChatId: TValue; // + const Voice: TtgFileToSend; // const Caption: string = ''; // const Duration: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// As of /// v.4.0, Telegram clients support rounded square mp4 videos of up @@ -536,12 +541,12 @@ interface /// function SendVideoNote(// const ChatId: TValue; // - const VideoNote: TValue; // + const VideoNote: TtgFileToSend; // const Duration: Int64 = 0; // const Length: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send point on the map. @@ -576,7 +581,7 @@ interface const LivePeriod: Int64 = 0; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send information about a venue. /// @@ -617,7 +622,7 @@ interface const Venue: TtgVenue; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to send phone contacts. /// @@ -651,7 +656,7 @@ interface const Contact: TtgContact; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method when you need to tell the user that something is /// happening on the bot's side. The status is set for 5 seconds or less @@ -746,7 +751,7 @@ interface function KickChatMember(// const ChatId: TValue; // const UserId: Int64; // - const UntilDate: Int64 = 0): Boolean; + const UntilDate: TDateTime = 0): Boolean; /// /// Use this method to unban a previously kicked user in a supergroup. /// The user will not return to the group automatically, but will be able @@ -911,13 +916,13 @@ interface const Text: string; // const ParseMode: TtgParseMode = TtgParseMode.Default; // const DisableWebPagePreview: Boolean = False; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; function EditMessageText(// const InlineMessageId: string; // const Text: string; // const ParseMode: TtgParseMode = TtgParseMode.Default; // const DisableWebPagePreview: Boolean = False; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; /// /// Use this method to edit captions of messages sent by the bot or via /// the bot (for inline bots). @@ -950,12 +955,12 @@ interface const ChatId: TValue; // const MessageId: Int64; // const Caption: string; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; { TODO -oM.E.Sysoev -cGeneral : Create Documentatiom } function EditMessageCaption(// const InlineMessageId: string; // const Caption: string; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; /// /// Use this method to edit live location messages sent by the bot or via @@ -986,7 +991,7 @@ interface const ChatId: TValue; // const MessageId: Int64; // const Location: TtgLocation; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; /// /// Use this method to edit live location messages sent by the bot or via /// the bot (for inline bots). A location can be edited until its @@ -1019,7 +1024,7 @@ interface function editMessageLiveLocation(// const InlineMessageId: string; // const Location: TtgLocation; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; /// /// Use this method to stop updating a live location message sent by the @@ -1044,7 +1049,7 @@ interface function stopMessageLiveLocation(// const ChatId: TValue; // const MessageId: Int64; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; /// /// Use this method to stop updating a live location message sent by the /// bot or via the bot (for inline bots) before live_period expires. @@ -1062,7 +1067,7 @@ interface /// function stopMessageLiveLocation(// const InlineMessageId: string; // - const ReplyMarkup: IReplyMarkup = nil): Boolean; overload; + ReplyMarkup: IReplyMarkup = nil): Boolean; overload; /// /// Use this method to edit only the reply markup of messages sent by the /// bot or via the bot (for inline bots). @@ -1086,7 +1091,7 @@ interface function EditMessageReplyMarkup(// const ChatId: TValue; // const MessageId: Int64; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; /// /// Use this method to edit only the reply markup of messages sent by the /// bot or via the bot (for inline bots). @@ -1104,7 +1109,7 @@ interface /// function EditMessageReplyMarkup(// const InlineMessageId: string; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; overload; /// /// Use this method to delete a message. /// @@ -1283,7 +1288,7 @@ interface const IsFlexible: Boolean = False; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// If you sent an invoice requesting a shipping address and the /// parameter is_flexible was specified, the Bot API will send an Update @@ -1309,10 +1314,11 @@ interface /// unavailable'). Telegram will display this message to the user. /// /// - function AnswerShippingQuery(// + function AnswerShippingQueryGood(// + const ShippingQueryId: string; // + const ShippingOptions: TArray): Boolean; + function AnswerShippingQueryBad(// const ShippingQueryId: string; // - const Ok: Boolean; // - const ShippingOptions: TArray; // const ErrorMessage: string): Boolean; /// /// Once the user has confirmed their payment and shipping details, the @@ -1344,10 +1350,11 @@ interface /// after the pre-checkout query was sent. /// /// - function AnswerPreCheckoutQuery(// + function AnswerPreCheckoutQueryGood(// + const PreCheckoutQueryId: string): Boolean; + function AnswerPreCheckoutQueryBad(// const PreCheckoutQueryId: string; // - const Ok: Boolean; // - const ErrorMessage: string = ''): Boolean; + const ErrorMessage: string): Boolean; {$ENDREGION} {$REGION 'Games'} /// @@ -1382,7 +1389,7 @@ interface const GameShortName: string; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to set the score of the specified user in a game. /// @@ -1422,11 +1429,16 @@ interface function SetGameScore(// const UserId: Int64; // const Score: Int64; // + const InlineMessageId: string; // const Force: Boolean = False; // - const DisableEditMessage: Boolean = False; // - const ChatId: Int64 = 0; // - const MessageId: Int64 = 0; // - const InlineMessageId: string = ''): ITgMessage; + const DisableEditMessage: Boolean = False): ITgMessage; overload; + function SetGameScore(// + const UserId: Int64; // + const Score: Int64; // + const ChatId: Int64; // + const MessageId: Int64; // + const Force: Boolean = False; // + const DisableEditMessage: Boolean = False): ITgMessage; overload; /// /// Use this method to get data for high score tables. Will return the /// score of the specified user and several of his neighbors in a game. @@ -1459,11 +1471,13 @@ interface /// /// Official API /// + function GetGameHighScores(// + const UserId: Int64; // + const InlineMessageId: string = ''): TArray; overload; function GetGameHighScores(// const UserId: Int64; // const ChatId: Int64 = 0; // - const MessageId: Int64 = 0; // - const InlineMessageId: string = ''): TArray; + const MessageId: Int64 = 0): TArray; overload; {$ENDREGION} {$REGION 'Manage groups and channels'} /// @@ -1631,7 +1645,7 @@ interface function RestrictChatMember(// const ChatId: TValue; // const UserId: Int64; // - const UntilDate: Int64 = 0; // + const UntilDate: TDateTime = 0; // const CanSendMessages: Boolean = False; // const CanSendMediaMessages: Boolean = False; // const CanSendOtherMessages: Boolean = False; // @@ -1729,7 +1743,7 @@ interface const Sticker: TValue; // const DisableNotification: Boolean = False; // const ReplyToMessageId: Int64 = 0; // - const ReplyMarkup: IReplyMarkup = nil): ITgMessage; + ReplyMarkup: IReplyMarkup = nil): ITgMessage; /// /// Use this method to get a sticker set. /// diff --git a/Source/TelegAPI.CoreAPI.ParameterConverter.pas b/Source/TelegAPI.CoreAPI.ParameterConverter.pas new file mode 100644 index 0000000..a80c4bf --- /dev/null +++ b/Source/TelegAPI.CoreAPI.ParameterConverter.pas @@ -0,0 +1,124 @@ +unit TelegAPI.CoreAPI.ParameterConverter; + +interface + +uses + System.Generics.Collections, + System.Net.Mime, + System.Rtti, + System.SysUtils, + System.TypInfo, + TelegAPI.Types, + TelegAPI.CoreAPI.Parameter; + +type + /// + /// This class is used by func. TTelegramBotCore.ParamsToFormData to locate + /// suitable param loader for API request parameters preparation. + /// + TtgParamConverter = class + public + type + //parameter loader method + TLoader = procedure(var AFormData: TMultipartFormData; AParam: TtgApiParameter) of object; + protected + procedure AddInteger(var AFormData: TMultipartFormData; AParam: TtgApiParameter); + procedure AddTDateTime(var AFormData: TMultipartFormData; AParam: TtgApiParameter); + procedure AddString(var AFormData: TMultipartFormData; AParam: TtgApiParameter); + procedure AddInt64(var AFormData: TMultipartFormData; AParam: TtgApiParameter); + procedure AddBoolean(var AFormData: TMultipartFormData; AParam: TtgApiParameter); + procedure AddClass_TtgFileToSend(var AFormData: TMultipartFormData; AParam: TtgApiParameter); + public + ParamLoaders: TDictionary; + constructor Create; + destructor Destroy; override; + function IsSupported(Param: TtgApiParameter): Boolean; + function ApplyParamToFormData(const AParam: TtgApiParameter; var Form: TMultipartFormData): Boolean; + end; + +implementation + +uses + System.DateUtils, + TelegAPI.Helpers; + +procedure TtgParamConverter.AddInteger(var AFormData: TMultipartFormData; AParam: TtgApiParameter); +begin + AFormData.AddField(AParam.Key, AParam.Value.AsInteger.ToString); +end; + +procedure TtgParamConverter.AddString(var AFormData: TMultipartFormData; AParam: TtgApiParameter); +begin + AFormData.AddField(AParam.Key, AParam.Value.AsString); +end; + +procedure TtgParamConverter.AddTDateTime(var AFormData: TMultipartFormData; + AParam: TtgApiParameter); +begin + AFormData.AddField(AParam.Key, DateTimeToUnix(AParam.Value.AsType, False).ToString); +end; + +function TtgParamConverter.ApplyParamToFormData(const AParam: TtgApiParameter; var Form: TMultipartFormData): Boolean; +begin + Result := ParamLoaders.ContainsKey(AParam.Value.TypeInfo); + if not Result then + Exit; + ParamLoaders[AParam.Value.TypeInfo](Form, AParam); +end; + +constructor TtgParamConverter.Create; +begin + //init type-lookup dictionary + ParamLoaders := TDictionary.Create; + //primitive types + ParamLoaders.Add(PTypeInfo(TypeInfo(Integer)), AddInteger); + ParamLoaders.Add(PTypeInfo(TypeInfo(string)), AddString); + ParamLoaders.Add(PTypeInfo(TypeInfo(Int64)), AddInt64); + ParamLoaders.Add(PTypeInfo(TypeInfo(Boolean)), AddBoolean); + ParamLoaders.Add(PTypeInfo(TypeInfo(TDateTime)), AddTDateTime); + //class types + ParamLoaders.Add(PTypeInfo(TypeInfo(TtgFileToSend)), AddClass_TtgFileToSend); +end; + +destructor TtgParamConverter.Destroy; +begin + ParamLoaders.Free; + inherited; +end; + +function TtgParamConverter.IsSupported(Param: TtgApiParameter): Boolean; +begin + Result := ParamLoaders.ContainsKey(Param.Value.TypeInfo); +end; + +procedure TtgParamConverter.AddInt64(var AFormData: TMultipartFormData; AParam: TtgApiParameter); +begin + AFormData.AddField(AParam.Key, AParam.Value.AsInt64.ToString); +end; + +procedure TtgParamConverter.AddBoolean(var AFormData: TMultipartFormData; AParam: TtgApiParameter); +begin + AFormData.AddField(AParam.Key, AParam.Value.AsBoolean.ToString(TUseBoolStrs.True)); +end; + +procedure TtgParamConverter.AddClass_TtgFileToSend(var AFormData: TMultipartFormData; AParam: TtgApiParameter); +var + LFileToSent: TtgFileToSend; +begin + LFileToSent := AParam.Value.AsType; + try + case LFileToSent.Tag of + TtgFileToSend.FILE_TO_SEND_STREAM: AFormData.AddStream(AParam.Key, LFileToSent.Content, LFileToSent.Data); + TtgFileToSend.FILE_TO_SEND_FILE: AFormData.AddFile(AParam.Key, LFileToSent.Data); + TtgFileToSend.FILE_TO_SEND_ID, + TtgFileToSend.FILE_TO_SEND_URL: AFormData.AddField(AParam.Key, LFileToSent.Data); + else + raise Exception.Create('Cant convert TTgFileToSend: Unknown prototype tag'); + end; + finally + LFileToSent.Free; + end; +end; + +end. + diff --git a/Source/TelegAPI.Utils.Json.pas b/Source/TelegAPI.Utils.Json.pas index 2ce190c..b3b3e7b 100644 --- a/Source/TelegAPI.Utils.Json.pas +++ b/Source/TelegAPI.Utils.Json.pas @@ -1,4 +1,4 @@ -unit TelegAPI.Utils.Json; +unit TelegAPI.Utils.Json; interface @@ -51,6 +51,7 @@ class function TJsonUtils.ArrayToJString(LArray: TArray): string; Result := Result + ','; end; Result := Result + ']'; + Result := Result.Replace('"inline_keyboard":null', '', [rfReplaceAll]);// какашечка end; { TBaseJson } diff --git a/Source/TelegAPI.Utils.Params.pas b/Source/TelegAPI.Utils.Params.pas deleted file mode 100644 index ce20a7c..0000000 --- a/Source/TelegAPI.Utils.Params.pas +++ /dev/null @@ -1,96 +0,0 @@ -unit TelegAPI.Utils.Params; - -interface - -uses - System.Generics.Collections, - System.Net.Mime, - System.rtti, - System.SysUtils, - System.TypInfo, - TelegAPI.Types; - -type - /// - /// This class is used by func. TTelegramBotCore.ParamsToFormData to locate - /// suitable param loader for API request parameters preparation. - /// - TtgParamLoader = class - public - type - //parameter loader method - TLoader = procedure(var AFormData: TMultipartFormData; TypeInfo: PTypeInfo; const AKey: string; AValue: TValue) of object; - public - ParamLoaders: TDictionary; - protected - procedure AddInteger(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); - procedure AddString(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); - procedure AddInt64(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); - procedure AddBoolean(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); - procedure AddClass_TtgFileToSend(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); - public - constructor Create; - destructor Destroy; override; - end; - -implementation - -uses - TelegAPI.Helpers; - -procedure TtgParamLoader.AddInteger(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); -begin - if AValue.AsInteger <> 0 then - AFormData.AddField(AKey, AValue.AsInteger.ToString); -end; - -procedure TtgParamLoader.AddString(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); -begin - if not AValue.AsString.IsEmpty then - AFormData.AddField(AKey, AValue.AsString); -end; - -constructor TtgParamLoader.Create; -begin - //init type-lookup dictionary - ParamLoaders := TDictionary.Create; - //primitive types - ParamLoaders.Add(PTypeInfo(TypeInfo(Integer)), AddInteger); - ParamLoaders.Add(PTypeInfo(TypeInfo(string)), AddString); - ParamLoaders.Add(PTypeInfo(TypeInfo(Int64)), AddInt64); - ParamLoaders.Add(PTypeInfo(TypeInfo(Boolean)), AddBoolean); - //class types - ParamLoaders.Add(PTypeInfo(TypeInfo(TtgFileToSend)), AddClass_TtgFileToSend); -end; - -destructor TtgParamLoader.Destroy; -begin - ParamLoaders.Free; - inherited; -end; - -procedure TtgParamLoader.AddInt64(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); -begin - if AValue.AsInt64 <> 0 then - AFormData.AddField(AKey, AValue.AsInt64.ToString); -end; - -procedure TtgParamLoader.AddBoolean(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); -begin - if AValue.AsBoolean then - AFormData.AddField(AKey, AValue.AsBoolean.ToString(TUseBoolStrs.True)); -end; - -procedure TtgParamLoader.AddClass_TtgFileToSend(var AFormData: TMultipartFormData; ATypeInfo: PTypeInfo; const AKey: string; AValue: TValue); -var - LFileToSent: TtgFileToSend; -begin - LFileToSent := AValue.AsType; - if Assigned(LFileToSent.Content) then - AFormData.AddStream(AKey, LFileToSent.Content, LFileToSent.FileName) - else - AFormData.AddFile(AKey, LFileToSent.FileName); -end; - -end. - diff --git a/Source/TelegAPi.CoreAPI.Parameter.pas b/Source/TelegAPi.CoreAPI.Parameter.pas new file mode 100644 index 0000000..f1ffeaa --- /dev/null +++ b/Source/TelegAPi.CoreAPI.Parameter.pas @@ -0,0 +1,44 @@ +unit TelegAPi.CoreAPI.Parameter; + +interface + +uses + System.Rtti; + +type + TtgApiParameter = class + Key: string; + Value: TValue; + DefaultValue: TValue; + Required: Boolean; + function IsDefaultValue: Boolean; + function Skip: Boolean; + constructor Create(const AKey: string; AValue, ADefaultValue: TValue; ARequired: Boolean = False); + end; + +implementation + +uses + System.SysUtils; +{ TtgApiParameter } + +constructor TtgApiParameter.Create(const AKey: string; AValue, ADefaultValue: TValue; ARequired: Boolean); +begin + Key := AKey; + Value := AValue; + DefaultValue := ADefaultValue; + Required := ARequired; +end; + +function TtgApiParameter.IsDefaultValue: Boolean; +begin + Result := Value.AsVariant = DefaultValue.AsVariant; // <-- DANGER +end; + +function TtgApiParameter.Skip: Boolean; +begin + Result := (not Required) and (IsDefaultValue or Value.IsEmpty); +end; + +end. + diff --git a/Source/TelegAPi.CoreAPI.Request.pas b/Source/TelegAPi.CoreAPI.Request.pas new file mode 100644 index 0000000..5515a08 --- /dev/null +++ b/Source/TelegAPi.CoreAPI.Request.pas @@ -0,0 +1,182 @@ +unit TelegAPi.CoreAPI.Request; + +interface + +uses + System.Rtti, + System.Net.HttpClient, + System.Generics.Collections, + System.Net.URLClient, + System.Net.Mime, + System.SysUtils, + TelegAPi.CoreAPI.Parameter, + TelegAPi.Bot.Impl, + System.Classes; + +type + TtgApiRequest = class + private + const + SERVER_URL = 'https://api.telegram.org/bot'; + private + FMethod: string; + FParams: TObjectList; + FHttp: THTTPClient; + FOnReceive: TProc; + FTelega: TTelegramBot; + FOnSend: TProc; + FOnError: TProc; + protected + function DoPost: IHTTPResponse; + function DoGet: IHTTPResponse; + procedure FillFormData(var AForm: TMultipartFormData); + function StreamToString(Stream: TMemoryStream): string; + public + constructor Create(Sender: TTelegramBot; const AMethod: string); + function Execute(out Return: IHTTPResponse): Boolean; overload; + function Execute(out Return: string): Boolean; overload; + function GetUrl: string; + destructor Destroy; override; + property Parameters: TObjectList read FParams write FParams; + property OnReceive: TProc read FOnReceive write FOnReceive; + property OnSend: TProc read FOnSend write FOnSend; + property OnError: TProc read FOnError write FOnError; + end; + +implementation + +uses + TelegAPi.Types, + TelegAPi.Types.ReplyMarkups, + REST.Json, + TelegAPi.Exceptions, + TelegAPi.CoreAPI.ParameterConverter; + +{ TtgApiRequest } + +constructor TtgApiRequest.Create(Sender: TTelegramBot; const AMethod: string); +begin + FMethod := AMethod; + FTelega := Sender; + FParams := TObjectList.Create; + FHttp := THTTPClient.Create; +end; + +destructor TtgApiRequest.Destroy; +begin + FHttp.Free; + FParams.Free; + inherited; +end; + +function TtgApiRequest.DoGet: IHTTPResponse; +begin + Result := FHttp.Get(GetUrl); + if Assigned(OnSend) then + OnSend(GetUrl, ''); +end; + +function TtgApiRequest.DoPost: IHTTPResponse; +var + PostData: TMultipartFormData; +begin + PostData := TMultipartFormData.Create; + try + FillFormData(PostData); + Result := FHttp.Post(GetUrl, PostData); + if Assigned(OnSend) then + OnSend(GetUrl, StreamToString(PostData.Stream)); + finally + PostData.Free; + end; +end; + +function TtgApiRequest.Execute(out Return: IHTTPResponse): Boolean; +begin + Result := False; + FHttp.ProxySettings := FTelega.ProxySettings; + try + if Parameters.Count > 0 then + Return := DoPost + else + Return := DoGet; + if Return = nil then + Exit; + Result := True; + if Assigned(OnReceive) then + OnReceive(Return.ContentAsString); + except + on E: Exception do + begin + Result := False; + if Assigned(OnError) then + OnError(E); + end; + end; +end; + +function TtgApiRequest.Execute(out Return: string): Boolean; +var + LResponse: IHTTPResponse; +begin + Result := Execute(LResponse); + if Result then + Return := LResponse.ContentAsString(TEncoding.UTF8); +end; + +procedure TtgApiRequest.FillFormData(var AForm: TMultipartFormData); +var + LParam: TtgApiParameter; + ParamConverter: TtgParamConverter; +begin + ParamConverter := TtgParamConverter.Create; + try + for LParam in Parameters do + begin + // skip all empty params + if LParam.Skip then + Continue; + if LParam.Required and (LParam.IsDefaultValue or LParam.Value.IsEmpty) then + FTelega.ExceptionManager.HaveGlobalExeption('TtgApiRequest.FillFormData', ETelegramException.Create('Not assigned required data')); + if ParamConverter.IsSupported(LParam) then + ParamConverter.ApplyParamToFormData(LParam, AForm) + else if LParam.Value.Kind = tkClass then // last variant to search + begin + { TODO -oOwner -cGeneral : } + if not LParam.Value.IsEmpty then + begin + if LParam.Value.IsTypethen + AForm.AddField(LParam.Key, TJson.ObjectToJsonString(LParam.Value.AsObject)) + else + FTelega.ExceptionManager.HaveGlobalExeption('TTelegramBot.ParamsToFormData', Exception.Create('Unknown object')); + end; + end + else + FTelega.ExceptionManager.HaveGlobalExeption('ParamsToFormData', ETelegramDataConvert.Create('Check parameter type ' + LParam.Value.ToString)) + end; + finally + ParamConverter.Free; + end; +end; + +function TtgApiRequest.GetUrl: string; +begin + Result := SERVER_URL + FTelega.Token + '/' + FMethod; +end; + +function TtgApiRequest.StreamToString(Stream: TMemoryStream): string; +var + LStrings: TStringList; +begin + LStrings := TStringList.Create; + try + Stream.Position := 0; + LStrings.LoadFromStream(Stream); + Result := LStrings.Text; + finally + LStrings.Free; + end; +end; + +end. + diff --git a/Source/TelegAPi.Types.Impl.pas b/Source/TelegAPi.Types.Impl.pas index 93b66f8..42e8511 100644 --- a/Source/TelegAPi.Types.Impl.pas +++ b/Source/TelegAPi.Types.Impl.pas @@ -23,7 +23,7 @@ TtgUser = class(TBaseJson, ItgUser) TtgChatMember = class(TBaseJson, ItgChatMember) public function User: ItgUser; - function Status: string; + function Status: TtgChatMemberStatus; function UntilDate: TDateTime; function CanBeEdited: Boolean; function CanChangeInfo: Boolean; @@ -624,6 +624,7 @@ function TTgMessage.NewChatMembers: TArray; LJsonArray: TJSONArray; I: Integer; begin + Result := nil; if FJSON.TryGetValue('new_chat_members', LValue) then begin LJsonArray := TJSONObject.ParseJSONValue(LValue) as TJSONArray; @@ -643,6 +644,7 @@ function TTgMessage.NewChatPhoto: TArray; LJsonArray: TJSONArray; I: Integer; begin + Result := nil; if FJSON.TryGetValue('new_chat_photo', LValue) then begin LJsonArray := TJSONObject.ParseJSONValue(LValue) as TJSONArray; @@ -1195,9 +1197,26 @@ function TtgChatMember.CanSendOtherMessages: Boolean; Result := ReadToSimpleType('can_send_other_messages'); end; -function TtgChatMember.Status: string; -begin - Result := ReadToSimpleType('status'); +function TtgChatMember.Status: TtgChatMemberStatus; +var + LStatus: string; +begin + Result := TtgChatMemberStatus.Member; + LStatus := ReadToSimpleType('status'); + if LStatus = 'creator' then + Result := TtgChatMemberStatus.Creator + else if LStatus = 'administrator' then + Result := TtgChatMemberStatus.Administrator + else if LStatus = 'member' then + Result := TtgChatMemberStatus.Member + else if LStatus = 'restricted' then + Result := TtgChatMemberStatus.Restricted + else if LStatus = 'left' then + Result := TtgChatMemberStatus.Left + else if LStatus = 'kicked' then + Result := TtgChatMemberStatus.Kicked + else + TBaseJson.UnSupported; end; function TtgChatMember.UntilDate: TDateTime; diff --git a/Source/TelegAPi.Types.pas b/Source/TelegAPi.Types.pas index 0d94f00..f65ef6c 100644 --- a/Source/TelegAPi.Types.pas +++ b/Source/TelegAPi.Types.pas @@ -21,7 +21,7 @@ interface ItgChatMember = interface ['{BE073F97-DA34-43E6-A15E-14A2B90CAB7E}'] function User: ItgUser; - function Status: string; + function Status: TtgChatMemberStatus; function UntilDate: TDateTime; function CanBeEdited: Boolean; function CanChangeInfo: Boolean; @@ -205,6 +205,7 @@ interface end; ItgInvoice = interface + ['{1D8923E1-068C-4747-84DE-A1B3B4674FD3}'] function Title: string; function Description: string; function StartParameter: string; @@ -213,6 +214,7 @@ interface end; ItgSuccessfulPayment = interface + ['{B2BE36C2-61F9-4D4B-AB9D-75BB524661AB}'] function Currency: string; function TotalAmount: Int64; end; @@ -379,19 +381,6 @@ interface function AllowedUpdates: TArray; end; - ItgFileToSend = interface - ['{91FF9D95-7BF3-49B3-B7CB-6C836305FEC2}'] - function getContent: TStream; - end; - - TtgFileToSend = class - public - FileName: string; - Content: TStream; - constructor Create(const AFileName: string); overload; - constructor Create(AContent: TStream; const AFileName: string); overload; - end; - TtgInputMedia = class private FType: string; @@ -414,35 +403,30 @@ TtgInputMediaVideo = class(TtgInputMedia) constructor Create(AMedia: TValue; const ACaption: string = ''; AWidth: Integer = 0; AHeight: Integer = 0; ADuration: Integer = 0); reintroduce; end; + TtgFileToSend = class + public + const + FILE_TO_SEND_ERROR = 254; + FILE_TO_SEND_ID = 0; + FILE_TO_SEND_URL = 1; + FILE_TO_SEND_FILE = 2; + FILE_TO_SEND_STREAM = 3; + public + Data: string; + Content: TStream; + Tag: Byte; + constructor Create(const ATag: Byte = FILE_TO_SEND_ERROR; const AData: string = ''; AContent: TStream = nil); + class function FromFile(const AFileName: string): TtgFileToSend; + class function FromID(const AID: string): TtgFileToSend; + class function FromURL(const AURL: string): TtgFileToSend; + class function FromStream(const AContent: TStream; const AFileName: string): TtgFileToSend; + end; + implementation uses System.SysUtils; -{ TtgFileToSend } -constructor TtgFileToSend.Create(const AFileName: string); -begin - Content := nil; - FileName := AFileName; - if not FileExists(AFileName) then - raise EFileNotFoundException.CreateFmt('File %S not found!', [AFileName]); -end; - -constructor TtgFileToSend.Create(AContent: TStream; const AFileName: string); -begin - FileName := AFileName; - Content := AContent; - // I guess, in most cases, AFilename param should contain a non-empty string. - // It is odd to receive a file with filename and - // extension which both are not connected with its content. - if AFileName.IsEmpty then - raise Exception.Create('TtgFileToSend: Filename is empty!'); - if not Assigned(AContent) then - raise EStreamError.Create('Stream not assigned!'); - FileName := AFileName; - Content := AContent; -end; - { TtgInputMedia } constructor TtgInputMedia.Create(AMedia: TValue; const ACaption: string); @@ -470,5 +454,43 @@ constructor TtgInputMediaVideo.Create(AMedia: TValue; const ACaption: string; AW Duration := ADuration; end; +{ TtgFileToSend } + +constructor TtgFileToSend.Create(const ATag: Byte; const AData: string; AContent: TStream); +begin + Tag := ATag; + Data := AData; + Content := AContent; +end; + +class function TtgFileToSend.FromFile(const AFileName: string): TtgFileToSend; +begin + if not FileExists(AFileName) then + raise EFileNotFoundException.CreateFmt('File %S not found!', [AFileName]); + Result := TtgFileToSend.Create(FILE_TO_SEND_FILE, AFileName, nil); +end; + +class function TtgFileToSend.FromID(const AID: string): TtgFileToSend; +begin + Result := TtgFileToSend.Create(FILE_TO_SEND_ID, AID, nil); +end; + +class function TtgFileToSend.FromStream(const AContent: TStream; const AFileName: string): TtgFileToSend; +begin + // I guess, in most cases, AFilename param should contain a non-empty string. + // It is odd to receive a file with filename and + // extension which both are not connected with its content. + if AFileName.IsEmpty then + raise Exception.Create('TtgFileToSend: Filename is empty!'); + if not Assigned(AContent) then + raise EStreamError.Create('Stream not assigned!'); + Result := TtgFileToSend.Create(FILE_TO_SEND_STREAM, AFileName, AContent); +end; + +class function TtgFileToSend.FromURL(const AURL: string): TtgFileToSend; +begin + Result := TtgFileToSend.Create(FILE_TO_SEND_URL, AURL, nil); +end; + end. diff --git a/Source/TelegaPi.Ext.Sessions.pas b/Source/TelegaPi.Ext.Sessions.pas new file mode 100644 index 0000000..d7b6f7e --- /dev/null +++ b/Source/TelegaPi.Ext.Sessions.pas @@ -0,0 +1,144 @@ +unit TelegaPi.Ext.Sessions; + +interface + +uses + System.Rtti, + System.Generics.Collections; + +type + ItgSession = interface + ['{D581A266-7AC0-496A-8784-9DCEDC6849C9}'] + function GetItem(const AKey: string): TValue; + procedure SetItem(const AKey: string; const Value: TValue); + function GetCreatedAt: TDateTime; + procedure SetCreatedAt(const Value: TDateTime); + // + procedure Clear; + property Items[const AKey: string]: TValue read GetItem write SetItem; Default; + property CreatedAt: TDateTime read GetCreatedAt write SetCreatedAt; + end; + + TtgSession = class(TInterfacedObject, ItgSession) + private + FItems: TDictionary; + FCreatedAt: TDateTime; + function GetItem(const AKey: string): TValue; + procedure SetItem(const AKey: string; const Value: TValue); + function GetCreatedAt: TDateTime; + procedure SetCreatedAt(const Value: TDateTime); + public + constructor Create; + destructor Destroy; override; + procedure Clear; + property CreatedAt: TDateTime read GetCreatedAt write SetCreatedAt; + property Items[const AKey: string]: TValue read GetItem write SetItem; Default; + end; + + ItgSessionManager = interface + ['{52E3CD5C-C096-4C3D-BC70-D284233C0250}'] + function GetItem(const AID: Int64): ItgSession; + procedure SetItem(const AID: Int64; const Value: ItgSession); + procedure Clear; + property Items[const AID: Int64]: ItgSession read GetItem write SetItem; Default; + end; + + TtgSessionManager = class(TInterfacedObject, ItgSessionManager) + private + class var + FInstance: TtgSessionManager; + private + FItems: TDictionary; + function GetItem(const AID: Int64): ItgSession; + procedure SetItem(const AID: Int64; const Value: ItgSession); + public + class function NewInstance: TObject; override; + constructor Create; + destructor Destroy; override; + procedure Clear; + property Items[const AID: Int64]: ItgSession read GetItem write SetItem; Default; + end; + +implementation + +uses + System.SysUtils; + +procedure TtgSession.Clear; +begin + FItems.Clear; +end; + +constructor TtgSession.Create; +begin + FItems := TDictionary.Create; +end; + +destructor TtgSession.Destroy; +begin + FItems.Free; + inherited; +end; + +function TtgSession.GetCreatedAt: TDateTime; +begin + Result := FCreatedAt; +end; + +function TtgSession.GetItem(const AKey: string): TValue; +begin + if not FItems.ContainsKey(AKey) then + FItems.Add(AKey, TValue.Empty); + Result := FItems.Items[AKey] +end; + +procedure TtgSession.SetCreatedAt(const Value: TDateTime); +begin + FCreatedAt := Value; +end; + +procedure TtgSession.SetItem(const AKey: string; const Value: TValue); +begin + FItems.AddOrSetValue(AKey, Value); +end; + +{ TtgSesionManager } + +procedure TtgSessionManager.Clear; +begin + FItems.Clear; +end; + +constructor TtgSessionManager.Create; +begin + FItems := TDictionary.Create; +end; + +destructor TtgSessionManager.Destroy; +begin + FItems.Free; + inherited; +end; + +function TtgSessionManager.GetItem(const AID: Int64): ItgSession; +begin + if not FItems.ContainsKey(AID) then + FItems.Add(AID, TtgSession.Create); + Result := FItems.Items[AID] +end; + +class function TtgSessionManager.NewInstance: TObject; +begin + if FInstance = nil then + FInstance := TtgSessionManager(inherited NewInstance); + Result := FInstance; +end; + +procedure TtgSessionManager.SetItem(const AID: Int64; const Value: ItgSession); +begin + FItems.AddOrSetValue(AID, Value); + FItems.Items[AID].CreatedAt := Now; +end; + +end. + diff --git a/Source/TelegaPi.Types.Enums.pas b/Source/TelegaPi.Types.Enums.pas index ce91305..4670a59 100644 --- a/Source/TelegaPi.Types.Enums.pas +++ b/Source/TelegaPi.Types.Enums.pas @@ -79,6 +79,7 @@ interface /// Normal member of the /// Member, + Restricted, /// /// A who left the