├── .gitignore ├── LICENSE ├── NetTelegramBotApi.Tests ├── InlineKeyboardButtonTest.cs └── NetTelegramBotApi.Tests.csproj ├── NetTelegramBotApi.sln ├── NetTelegramBotApi ├── BotRequestException.cs ├── BotResponse.cs ├── GlobalSuppressions.cs ├── IPostProcessingRequired.cs ├── ITelegramBot.cs ├── NetTelegramBotApi.csproj ├── Requests │ ├── AnswerCallbackQuery.cs │ ├── DeleteWebhook.cs │ ├── EditMessageCaption.cs │ ├── EditMessageReplyMarkup.cs │ ├── EditMessageText.cs │ ├── FileToSend.cs │ ├── ForwardMessage.cs │ ├── GetChat.cs │ ├── GetChatAdministrators.cs │ ├── GetChatMember.cs │ ├── GetChatMembersCount.cs │ ├── GetFile.cs │ ├── GetGameHighScores.cs │ ├── GetMe.cs │ ├── GetUpdates.cs │ ├── GetUserProfilePhotos.cs │ ├── GetWebhookInfo.cs │ ├── KickChatMember.cs │ ├── LeaveChat.cs │ ├── RequestBase.cs │ ├── SendAudio.cs │ ├── SendChatAction.cs │ ├── SendContact.cs │ ├── SendDocument.cs │ ├── SendFileRequestBase.cs │ ├── SendGame.cs │ ├── SendLocation.cs │ ├── SendMessage.cs │ ├── SendPhoto.cs │ ├── SendSticker.cs │ ├── SendVenue.cs │ ├── SendVideo.cs │ ├── SendVoice.cs │ ├── SetGameScore.cs │ ├── SetWebhook.cs │ ├── UnbanChatMember.cs │ └── _Classes.cd ├── StringExtensions.cs ├── TelegramBot.cs ├── Types │ ├── Animation.cs │ ├── Audio.cs │ ├── CallbackGame.cs │ ├── CallbackQuery.cs │ ├── Chat.cs │ ├── ChatMember.cs │ ├── ChatMemberStatus.cs │ ├── ChatType.cs │ ├── ChosenInlineResult.cs │ ├── Contact.cs │ ├── Document.cs │ ├── File.cs │ ├── ForceReply.cs │ ├── Game.cs │ ├── GameHighScore.cs │ ├── InlineKeyboardButton.cs │ ├── InlineKeyboardMarkup.cs │ ├── InlineQuery.cs │ ├── KeyboardButton.cs │ ├── Location.cs │ ├── Message.cs │ ├── MessageEntity.cs │ ├── MessageEntityType.cs │ ├── PhotoSize.cs │ ├── ReplyKeyboardMarkup.cs │ ├── ReplyKeyboardRemove.cs │ ├── ReplyMarkupBase.cs │ ├── ResponseParameters.cs │ ├── Sticker.cs │ ├── Update.cs │ ├── User.cs │ ├── UserProfilePhotos.cs │ ├── Venue.cs │ ├── Video.cs │ ├── Voice.cs │ ├── WebAppInfo.cs │ └── WebhookInfo.cs └── Util │ └── UnixdateTimeConverter.cs ├── README.md ├── Settings.StyleCop ├── TelegramBotDemo-vNext ├── Program.cs ├── Properties │ └── launchSettings.json ├── TelegramBotDemo-vNext.csproj ├── Telegram_Bot_API.htm ├── config.json ├── t_logo.png └── Пример_UTF8_filename.txt ├── appveyor.yml ├── package-icon.gif └── package-icon.png /.gitignore: -------------------------------------------------------------------------------- 1 | /packages 2 | /NetTelegramBotApi.v12.suo 3 | bin 4 | obj 5 | *.user 6 | StyleCop.Cache 7 | /*.nupkg 8 | /.vs 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Dmitry Popov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NetTelegramBotApi.Tests/InlineKeyboardButtonTest.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi 2 | { 3 | using System.Net; 4 | using System.Threading.Tasks; 5 | using NetTelegramBotApi.Requests; 6 | using NetTelegramBotApi.Types; 7 | using Xunit; 8 | 9 | public class InlineKeyboardButtonTest 10 | { 11 | /// 12 | /// Test for Issue #46 13 | /// 14 | [Fact] 15 | public async Task CallbackData_SerializedOk() 16 | { 17 | var keyb = new InlineKeyboardMarkup() 18 | { 19 | InlineKeyboard = [[new InlineKeyboardButton { Text = "test", CallbackData = "123" }]], 20 | }; 21 | var reqAction = new SendMessage(123, "Hello") { ReplyMarkup = keyb }; 22 | 23 | var submitText = await reqAction.CreateHttpContent().ReadAsStringAsync(); 24 | 25 | var encoded = WebUtility.UrlEncode("{\"inline_keyboard\":[[{\"text\":\"test\",\"callback_data\":\"123\"}]]}"); 26 | Assert.Equal($"chat_id=123&text=Hello&reply_markup={encoded}", submitText); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NetTelegramBotApi.Tests/NetTelegramBotApi.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | NetTelegramBotApi 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /NetTelegramBotApi.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.31313.79 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ABC2A4CB-9443-434E-B2EA-E739D288F330}" 6 | ProjectSection(SolutionItems) = preProject 7 | appveyor.yml = appveyor.yml 8 | LICENSE = LICENSE 9 | README.md = README.md 10 | EndProjectSection 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTelegramBotApi", "NetTelegramBotApi\NetTelegramBotApi.csproj", "{0CA802AD-0F85-4314-8D70-2C5F182C9F42}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotDemo-vNext", "TelegramBotDemo-vNext\TelegramBotDemo-vNext.csproj", "{0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTelegramBotApi.Tests", "NetTelegramBotApi.Tests\NetTelegramBotApi.Tests.csproj", "{82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Debug|x64 = Debug|x64 22 | Debug|x86 = Debug|x86 23 | Release|Any CPU = Release|Any CPU 24 | Release|x64 = Release|x64 25 | Release|x86 = Release|x86 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Debug|x64.ActiveCfg = Debug|Any CPU 31 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Debug|x64.Build.0 = Debug|Any CPU 32 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Debug|x86.ActiveCfg = Debug|Any CPU 33 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Debug|x86.Build.0 = Debug|Any CPU 34 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x64.ActiveCfg = Release|Any CPU 37 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x64.Build.0 = Release|Any CPU 38 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x86.ActiveCfg = Release|Any CPU 39 | {0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x86.Build.0 = Release|Any CPU 40 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|x64.ActiveCfg = Debug|Any CPU 43 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|x64.Build.0 = Debug|Any CPU 44 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|x86.ActiveCfg = Debug|Any CPU 45 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|x86.Build.0 = Debug|Any CPU 46 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Release|x64.ActiveCfg = Release|Any CPU 49 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Release|x64.Build.0 = Release|Any CPU 50 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Release|x86.ActiveCfg = Release|Any CPU 51 | {0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Release|x86.Build.0 = Release|Any CPU 52 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Debug|x64.ActiveCfg = Debug|Any CPU 55 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Debug|x64.Build.0 = Debug|Any CPU 56 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Debug|x86.ActiveCfg = Debug|Any CPU 57 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Debug|x86.Build.0 = Debug|Any CPU 58 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Release|x64.ActiveCfg = Release|Any CPU 61 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Release|x64.Build.0 = Release|Any CPU 62 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Release|x86.ActiveCfg = Release|Any CPU 63 | {82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}.Release|x86.Build.0 = Release|Any CPU 64 | EndGlobalSection 65 | GlobalSection(SolutionProperties) = preSolution 66 | HideSolutionNode = FALSE 67 | EndGlobalSection 68 | GlobalSection(ExtensibilityGlobals) = postSolution 69 | SolutionGuid = {1AE94356-8779-4DAE-A0A5-7F6DE8FC7E48} 70 | EndGlobalSection 71 | EndGlobal 72 | -------------------------------------------------------------------------------- /NetTelegramBotApi/BotRequestException.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi 2 | { 3 | using System; 4 | using System.Net; 5 | using NetTelegramBotApi.Types; 6 | 7 | public class BotRequestException : Exception 8 | { 9 | public BotRequestException() 10 | : base() 11 | { 12 | // Nothing 13 | } 14 | 15 | public BotRequestException(string message) 16 | : base(message) 17 | { 18 | // Nothing 19 | } 20 | 21 | public BotRequestException(string message, Exception inner) 22 | : base(message, inner) 23 | { 24 | // Nothing 25 | } 26 | 27 | /// 28 | /// HTTP Status Code retuned by server. 29 | /// 30 | public HttpStatusCode StatusCode { get; set; } 31 | 32 | /// 33 | /// Response body text. 34 | /// 35 | public string ResponseBody { get; set; } 36 | 37 | /// 38 | /// Optional. Human-readable description of the result (by Telegram). 39 | /// 40 | public string Description { get; set; } 41 | 42 | /// 43 | /// Contents are subject to change in the future (by Telegram). 44 | /// 45 | public long? ErrorCode { get; set; } 46 | 47 | /// 48 | /// Optional. Can help to automatically handle the error. 49 | /// 50 | public ResponseParameters Parameters { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NetTelegramBotApi/BotResponse.cs: -------------------------------------------------------------------------------- 1 | using NetTelegramBotApi.Types; 2 | 3 | namespace NetTelegramBotApi 4 | { 5 | public class BotResponse 6 | { 7 | public bool Ok { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public T Result { get; set; } 12 | 13 | public long? ErrorCode { get; set; } 14 | 15 | public ResponseParameters Parameters { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetTelegramBotApi/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | [assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "Sorry, no")] 9 | 10 | [assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "I'm lazy")] 11 | 12 | [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "I'm lazy")] 13 | [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1602:Enumeration items should be documented", Justification = "I'm lazy")] 14 | [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1615:Element return value should be documented", Justification = "I'm lazy")] 15 | [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "I'm lazy")] 16 | [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header", Justification = "I'm lazy")] 17 | -------------------------------------------------------------------------------- /NetTelegramBotApi/IPostProcessingRequired.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi 2 | { 3 | /// 4 | /// Implemented by Types, which require additional post-processing after receiving from server. 5 | /// 6 | public interface IPostProcessingRequired 7 | { 8 | void PostProcess(string accessToken); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetTelegramBotApi/ITelegramBot.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using NetTelegramBotApi.Requests; 3 | using NetTelegramBotApi.Types; 4 | 5 | namespace NetTelegramBotApi 6 | { 7 | public interface ITelegramBot 8 | { 9 | Task MakeRequestAsync(RequestBase request); 10 | 11 | Update DeserializeUpdate(string json); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetTelegramBotApi/NetTelegramBotApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Telegram Bot API library 5 | NetTelegramBotApi 6 | 6.0.1 7 | net8.0 8 | NetTelegramBotApi 9 | NetTelegramBotApi 10 | telegram;bot;api 11 | Some internal refacatoring and optimizations. 12 | package-icon.png 13 | https://github.com/justdmitry/NetTelegramBotApi 14 | git 15 | https://github.com/justdmitry/NetTelegramBotApi.git 16 | Dmitry Popov 17 | 18 | Copyright © Dmitry Popov, 2015-2024 19 | True 20 | MIT 21 | README.md 22 | 23 | 24 | 25 | 26 | all 27 | runtime; build; native; contentfiles; analyzers; buildtransitive 28 | 29 | 30 | 31 | 32 | 33 | 34 | True 35 | 36 | 37 | 38 | True 39 | \ 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/AnswerCallbackQuery.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Net.Http; 4 | 5 | namespace NetTelegramBotApi.Requests 6 | { 7 | /// 8 | /// Use this method to send answers to callback queries sent from inline keyboards. 9 | /// The answer will be displayed to the user as a notification at the top of the chat screen or as an alert. 10 | /// On success, True is returned. 11 | /// 12 | public class AnswerCallbackQuery : RequestBase 13 | { 14 | public AnswerCallbackQuery(string callbackQueryId) 15 | : base("answerCallbackQuery") 16 | { 17 | this.CallbackQueryId = callbackQueryId; 18 | } 19 | 20 | /// 21 | /// Unique identifier for the query to be answered. 22 | /// 23 | public string CallbackQueryId { get; protected set; } 24 | 25 | /// 26 | /// Optional. Text of the notification. If not specified, nothing will be shown to the user. 27 | /// 28 | public string Text { get; set; } 29 | 30 | /// 31 | /// Optional. If true, an alert will be shown by the client instead of a notification at the top of the chat screen. 32 | /// Defaults to false. 33 | /// 34 | public bool? ShowAlert { get; set; } 35 | 36 | /// 37 | /// Optional. URL that will be opened by the user's client. 38 | /// If you have created a Game and accepted the conditions via @Botfather, 39 | /// specify the URL that opens your game – note that this will only work if the query comes from a callback_game button. 40 | /// Otherwise, you may use links like telegram.me/your_bot?start=XXXX that open your bot with a parameter. 41 | /// 42 | public string Url { get; set; } 43 | 44 | /// 45 | /// The maximum amount of time in seconds that the result of the callback query may be cached client-side. 46 | /// Telegram apps will support caching starting in version 3.14. Defaults to 0. 47 | /// 48 | public long CacheTime { get; set; } 49 | 50 | public override HttpContent CreateHttpContent() 51 | { 52 | var dic = new Dictionary(); 53 | dic.Add("callback_query_id", CallbackQueryId); 54 | if (!string.IsNullOrEmpty(Text)) 55 | { 56 | dic.Add("text", Text); 57 | } 58 | 59 | if (ShowAlert.HasValue) 60 | { 61 | dic.Add("show_alert", ShowAlert.Value.ToString()); 62 | } 63 | 64 | if (!string.IsNullOrEmpty(Url)) 65 | { 66 | dic.Add("url", Url); 67 | } 68 | 69 | dic.Add("cache_time", CacheTime.ToString(CultureInfo.InvariantCulture)); 70 | 71 | return new FormUrlEncodedContent(dic); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/DeleteWebhook.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Requests 2 | { 3 | using System.Net.Http; 4 | 5 | public class DeleteWebhook : RequestBase 6 | { 7 | public DeleteWebhook() 8 | : base("deleteWebhook") 9 | { 10 | // Nothing 11 | } 12 | 13 | public override HttpContent CreateHttpContent() 14 | { 15 | return null; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/EditMessageCaption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to edit captions of messages sent by the bot or via the bot (for inline bots). 11 | /// On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. 12 | /// 13 | public class EditMessageCaption : RequestBase 14 | { 15 | public EditMessageCaption(long chatId, long messageId, string caption) 16 | : base("editMessageCaption") 17 | { 18 | this.ChatId = chatId; 19 | this.MessageId = messageId; 20 | this.Caption = caption; 21 | } 22 | 23 | public EditMessageCaption(string channelName, long messageId, string caption) 24 | : base("editMessageCaption") 25 | { 26 | this.ChannelName = channelName; 27 | this.MessageId = messageId; 28 | this.Caption = caption; 29 | } 30 | 31 | public EditMessageCaption(long inlineMessageId, string caption) 32 | : base("editMessageCaption") 33 | { 34 | this.InlineMessageId = inlineMessageId; 35 | this.Caption = caption; 36 | } 37 | 38 | /// 39 | /// Optional. Required if inline_message_id is not specified. Unique identifier for the target chat. 40 | /// 41 | public long? ChatId { get; protected set; } 42 | 43 | /// 44 | /// Optional. Required if inline_message_id is not specified. Username of the target channel. 45 | /// 46 | public string ChannelName { get; protected set; } 47 | 48 | /// 49 | /// Optional. Required if inline_message_id is not specified. Identifier of the sent message. 50 | /// 51 | public long? MessageId { get; protected set; } 52 | 53 | /// 54 | /// Optional. Required if chat_id and message_id are not specified. Identifier of the inline message. 55 | /// 56 | public long? InlineMessageId { get; protected set; } 57 | 58 | /// 59 | /// Optional. New caption of the message. 60 | /// 61 | public string Caption { get; set; } 62 | 63 | /// 64 | /// Optional. A JSON-serialized object for an inline keyboard. 65 | /// 66 | public InlineKeyboardMarkup ReplyMarkup { get; set; } 67 | 68 | public override HttpContent CreateHttpContent() 69 | { 70 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 71 | { 72 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 73 | } 74 | 75 | var dic = new Dictionary(); 76 | 77 | if (ChatId.HasValue) 78 | { 79 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 80 | } 81 | 82 | if (!string.IsNullOrEmpty(ChannelName)) 83 | { 84 | dic.Add("chat_id", ChannelName); 85 | } 86 | 87 | if (MessageId.HasValue) 88 | { 89 | dic.Add("message_id", MessageId.Value.ToString(CultureInfo.InvariantCulture)); 90 | } 91 | 92 | if (InlineMessageId.HasValue) 93 | { 94 | dic.Add("inline_message_id", InlineMessageId.Value.ToString(CultureInfo.InvariantCulture)); 95 | } 96 | 97 | dic.Add("caption", Caption); 98 | 99 | if (ReplyMarkup != null) 100 | { 101 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 102 | } 103 | 104 | return new FormUrlEncodedContent(dic); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/EditMessageReplyMarkup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to edit captions of messages sent by the bot or via the bot (for inline bots). 11 | /// On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. 12 | /// 13 | public class EditMessageReplyMarkup : RequestBase 14 | { 15 | public EditMessageReplyMarkup(long chatId, long messageId, InlineKeyboardMarkup replyMarkup) 16 | : base("editMessageReplyMarkup") 17 | { 18 | this.ChatId = chatId; 19 | this.MessageId = messageId; 20 | this.ReplyMarkup = replyMarkup; 21 | } 22 | 23 | public EditMessageReplyMarkup(string channelName, long messageId, InlineKeyboardMarkup replyMarkup) 24 | : base("editMessageReplyMarkup") 25 | { 26 | this.ChannelName = channelName; 27 | this.MessageId = messageId; 28 | this.ReplyMarkup = replyMarkup; 29 | } 30 | 31 | public EditMessageReplyMarkup(long inlineMessageId, InlineKeyboardMarkup replyMarkup) 32 | : base("editMessageReplyMarkup") 33 | { 34 | this.InlineMessageId = inlineMessageId; 35 | this.ReplyMarkup = replyMarkup; 36 | } 37 | 38 | /// 39 | /// Optional. Required if inline_message_id is not specified. Unique identifier for the target chat. 40 | /// 41 | public long? ChatId { get; protected set; } 42 | 43 | /// 44 | /// Optional. Required if inline_message_id is not specified. Username of the target channel. 45 | /// 46 | public string ChannelName { get; protected set; } 47 | 48 | /// 49 | /// Optional. Required if inline_message_id is not specified. Identifier of the sent message. 50 | /// 51 | public long? MessageId { get; protected set; } 52 | 53 | /// 54 | /// Optional. Required if chat_id and message_id are not specified. Identifier of the inline message. 55 | /// 56 | public long? InlineMessageId { get; protected set; } 57 | 58 | /// 59 | /// Optional. A JSON-serialized object for an inline keyboard. 60 | /// 61 | public InlineKeyboardMarkup ReplyMarkup { get; set; } 62 | 63 | public override HttpContent CreateHttpContent() 64 | { 65 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 66 | { 67 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 68 | } 69 | 70 | var dic = new Dictionary(); 71 | 72 | if (ChatId.HasValue) 73 | { 74 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 75 | } 76 | 77 | if (!string.IsNullOrEmpty(ChannelName)) 78 | { 79 | dic.Add("chat_id", ChannelName); 80 | } 81 | 82 | if (MessageId.HasValue) 83 | { 84 | dic.Add("message_id", MessageId.Value.ToString(CultureInfo.InvariantCulture)); 85 | } 86 | 87 | if (InlineMessageId.HasValue) 88 | { 89 | dic.Add("inline_message_id", InlineMessageId.Value.ToString(CultureInfo.InvariantCulture)); 90 | } 91 | 92 | if (ReplyMarkup != null) 93 | { 94 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 95 | } 96 | 97 | return new FormUrlEncodedContent(dic); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/EditMessageText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to edit text and game messages sent by the bot or via the bot (for inline bots). 11 | /// On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. 12 | /// 13 | public class EditMessageText : RequestBase 14 | { 15 | public EditMessageText(long chatId, long messageId, string text) 16 | : base("editMessageText") 17 | { 18 | this.ChatId = chatId; 19 | this.MessageId = messageId; 20 | this.Text = text; 21 | } 22 | 23 | public EditMessageText(string channelName, long messageId, string text) 24 | : base("editMessageText") 25 | { 26 | this.ChannelName = channelName; 27 | this.MessageId = messageId; 28 | this.Text = text; 29 | } 30 | 31 | public EditMessageText(long inlineMessageId, string text) 32 | : base("editMessageText") 33 | { 34 | this.InlineMessageId = inlineMessageId; 35 | this.Text = text; 36 | } 37 | 38 | /// 39 | /// Optional. Required if inline_message_id is not specified. Unique identifier for the target chat. 40 | /// 41 | public long? ChatId { get; protected set; } 42 | 43 | /// 44 | /// Optional. Required if inline_message_id is not specified. Username of the target channel. 45 | /// 46 | public string ChannelName { get; protected set; } 47 | 48 | /// 49 | /// Optional. Required if inline_message_id is not specified. Identifier of the sent message. 50 | /// 51 | public long? MessageId { get; protected set; } 52 | 53 | /// 54 | /// Optional. Required if chat_id and message_id are not specified. Identifier of the inline message. 55 | /// 56 | public long? InlineMessageId { get; protected set; } 57 | 58 | /// 59 | /// New text of the message. 60 | /// 61 | public string Text { get; set; } 62 | 63 | /// 64 | /// Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or 65 | /// inline URLs in your bot's message. 66 | /// 67 | public SendMessage.ParseModes ParseMode { get; set; } 68 | 69 | /// 70 | /// Optional. Disables link previews for links in this message. 71 | /// 72 | public bool? DisableWebPagePreview { get; set; } 73 | 74 | /// 75 | /// Optional. A JSON-serialized object for an inline keyboard. 76 | /// 77 | public InlineKeyboardMarkup ReplyMarkup { get; set; } 78 | 79 | public override HttpContent CreateHttpContent() 80 | { 81 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 82 | { 83 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 84 | } 85 | 86 | var dic = new Dictionary(); 87 | 88 | if (ChatId.HasValue) 89 | { 90 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 91 | } 92 | 93 | if (!string.IsNullOrEmpty(ChannelName)) 94 | { 95 | dic.Add("chat_id", ChannelName); 96 | } 97 | 98 | if (MessageId.HasValue) 99 | { 100 | dic.Add("message_id", MessageId.Value.ToString(CultureInfo.InvariantCulture)); 101 | } 102 | 103 | if (InlineMessageId.HasValue) 104 | { 105 | dic.Add("inline_message_id", InlineMessageId.Value.ToString(CultureInfo.InvariantCulture)); 106 | } 107 | 108 | dic.Add("text", Text); 109 | 110 | if (ParseMode == SendMessage.ParseModes.Markdown) 111 | { 112 | dic.Add("parse_mode", "Markdown"); 113 | } 114 | 115 | if (ParseMode == SendMessage.ParseModes.HTML) 116 | { 117 | dic.Add("parse_mode", "HTML"); 118 | } 119 | 120 | if (DisableWebPagePreview.HasValue) 121 | { 122 | dic.Add("disable_web_page_preview", DisableWebPagePreview.Value.ToString()); 123 | } 124 | 125 | if (ReplyMarkup != null) 126 | { 127 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 128 | } 129 | 130 | return new FormUrlEncodedContent(dic); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/FileToSend.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace NetTelegramBotApi.Requests 4 | { 5 | public class FileToSend 6 | { 7 | /// 8 | /// If the file is already stored somewhere on the Telegram servers, you don't need to reupload it: 9 | /// each file object has a file_id field, simply pass this file_id as a parameter instead of uploading. 10 | /// There are no limits for files sent this way. 11 | /// 12 | /// 13 | /// Since October 2016, provide Telegram with an HTTP URL for the file to be sent. 14 | /// Telegram will download and send the file. 5 MB max size for photos and 20 MB max for other types of content. 15 | /// 16 | public FileToSend(string existingFileId) 17 | { 18 | this.AlreadyUploaded = true; 19 | this.ExistingFileId = existingFileId; 20 | } 21 | 22 | /// 23 | /// Post the file using multipart/form-data in the usual way that files are uploaded via the browser. 24 | /// 10 MB max size for photos, 50 MB for other files. 25 | /// 26 | public FileToSend(Stream fileContent, string fileName) 27 | { 28 | this.AlreadyUploaded = false; 29 | this.NewFileContent = fileContent; 30 | this.NewFileName = fileName; 31 | } 32 | 33 | /// 34 | /// True, if file is already uploaded to server, only is used. 35 | /// Otherwise, and are used. 36 | /// 37 | public bool AlreadyUploaded { get; private set; } 38 | 39 | public string ExistingFileId { get; private set; } 40 | 41 | public Stream NewFileContent { get; private set; } 42 | 43 | public string NewFileName { get; private set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/ForwardMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to forward messages of any kind. On success, the sent Message is returned. 11 | /// 12 | public class ForwardMessage : RequestBase 13 | { 14 | public ForwardMessage(long chatId, long fromChatId, long messageId) 15 | : base("forwardMessage") 16 | { 17 | this.ChatId = chatId; 18 | this.FromChatId = fromChatId; 19 | this.MessageId = messageId; 20 | } 21 | 22 | public ForwardMessage(long chatId, string fromChannelName, long messageId) 23 | : base("forwardMessage") 24 | { 25 | this.ChatId = chatId; 26 | this.FromChannelName = fromChannelName; 27 | this.MessageId = messageId; 28 | } 29 | 30 | public ForwardMessage(string channelName, long fromChatId, long messageId) 31 | : base("forwardMessage") 32 | { 33 | this.ChannelName = channelName; 34 | this.FromChatId = fromChatId; 35 | this.MessageId = messageId; 36 | } 37 | 38 | public ForwardMessage(string channelName, string fromChannelName, long messageId) 39 | : base("forwardMessage") 40 | { 41 | this.ChannelName = channelName; 42 | this.FromChannelName = fromChannelName; 43 | this.MessageId = messageId; 44 | } 45 | 46 | /// 47 | /// Unique identifier for the target chat. 48 | /// 49 | public long? ChatId { get; set; } 50 | 51 | /// 52 | /// Unique identifier for target channel (in the format @channelusername). 53 | /// 54 | public string ChannelName { get; set; } 55 | 56 | /// 57 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 58 | /// 59 | public long? MessageThreadId { get; set; } 60 | 61 | /// 62 | /// Unique identifier for the chat where the original message was sent — User or GroupChat id. 63 | /// 64 | public long? FromChatId { get; set; } 65 | 66 | /// 67 | /// Unique identifier for the chat where the original message was sent - channel username in the format @channelusername). 68 | /// 69 | public string FromChannelName { get; set; } 70 | 71 | /// 72 | /// Sends the message silently. 73 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 74 | /// 75 | public bool? DisableNotification { get; set; } 76 | 77 | /// 78 | /// Unique message identifier. 79 | /// 80 | public long MessageId { get; set; } 81 | 82 | public override HttpContent CreateHttpContent() 83 | { 84 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 85 | { 86 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 87 | } 88 | 89 | if (FromChatId.HasValue && !string.IsNullOrEmpty(FromChannelName)) 90 | { 91 | throw new InvalidOperationException("Use FromChatId or FromChannelName, not both."); 92 | } 93 | 94 | var dic = new Dictionary(); 95 | 96 | if (ChatId.HasValue) 97 | { 98 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 99 | } 100 | 101 | if (!string.IsNullOrEmpty(ChannelName)) 102 | { 103 | dic.Add("chat_id", ChannelName); 104 | } 105 | 106 | if (MessageThreadId.HasValue) 107 | { 108 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 109 | } 110 | 111 | if (FromChatId.HasValue) 112 | { 113 | dic.Add("from_chat_id", FromChatId.Value.ToString(CultureInfo.InvariantCulture)); 114 | } 115 | 116 | if (!string.IsNullOrEmpty(FromChannelName)) 117 | { 118 | dic.Add("from_chat_id", FromChannelName); 119 | } 120 | 121 | if (DisableNotification.HasValue) 122 | { 123 | dic.Add("disable_notification", DisableNotification.Value.ToString()); 124 | } 125 | 126 | dic.Add("message_id", MessageId.ToString(CultureInfo.InvariantCulture)); 127 | 128 | return new FormUrlEncodedContent(dic); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetChat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to get up to date information about the chat 11 | /// (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). 12 | /// 13 | public class GetChat : RequestBase 14 | { 15 | public GetChat(long chatId) 16 | : base("getChat") 17 | { 18 | this.ChatId = chatId; 19 | } 20 | 21 | public GetChat(string channelName) 22 | : base("getChat") 23 | { 24 | this.ChannelName = channelName; 25 | } 26 | 27 | /// 28 | /// Unique identifier for the target chat. 29 | /// 30 | public long? ChatId { get; protected set; } 31 | 32 | /// 33 | /// Username of the target supergroup or channel (in the format @channelusername). 34 | /// 35 | public string ChannelName { get; set; } 36 | 37 | public override HttpContent CreateHttpContent() 38 | { 39 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 40 | { 41 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 42 | } 43 | 44 | var dic = new Dictionary(); 45 | 46 | if (ChatId.HasValue) 47 | { 48 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 49 | } 50 | 51 | if (!string.IsNullOrEmpty(ChannelName)) 52 | { 53 | dic.Add("chat_id", ChannelName); 54 | } 55 | 56 | return new FormUrlEncodedContent(dic); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetChatAdministrators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to get a list of administrators in a chat. 11 | /// On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. 12 | /// If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned. 13 | /// 14 | public class GetChatAdministrators : RequestBase 15 | { 16 | public GetChatAdministrators(long chatId) 17 | : base("getChatAdministrators") 18 | { 19 | this.ChatId = chatId; 20 | } 21 | 22 | public GetChatAdministrators(string channelName) 23 | : base("getChatAdministrators") 24 | { 25 | this.ChannelName = channelName; 26 | } 27 | 28 | /// 29 | /// Unique identifier for the target chat. 30 | /// 31 | public long? ChatId { get; protected set; } 32 | 33 | /// 34 | /// Username of the target supergroup or channel (in the format @channelusername). 35 | /// 36 | public string ChannelName { get; set; } 37 | 38 | public override HttpContent CreateHttpContent() 39 | { 40 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 41 | { 42 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 43 | } 44 | 45 | var dic = new Dictionary(); 46 | 47 | if (ChatId.HasValue) 48 | { 49 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 50 | } 51 | 52 | if (!string.IsNullOrEmpty(ChannelName)) 53 | { 54 | dic.Add("chat_id", ChannelName); 55 | } 56 | 57 | return new FormUrlEncodedContent(dic); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetChatMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to get information about a member of a chat. Returns a ChatMember object on success. 11 | /// 12 | public class GetChatMember : RequestBase 13 | { 14 | public GetChatMember(long chatId, long userId) 15 | : base("getChatMember") 16 | { 17 | this.ChatId = chatId; 18 | this.UserId = userId; 19 | } 20 | 21 | public GetChatMember(string channelName, long userId) 22 | : base("getChatMember") 23 | { 24 | this.ChannelName = channelName; 25 | this.UserId = userId; 26 | } 27 | 28 | /// 29 | /// Unique identifier for the target chat. 30 | /// 31 | public long? ChatId { get; protected set; } 32 | 33 | /// 34 | /// Username of the target channel (in the format @channelusername). 35 | /// 36 | public string ChannelName { get; set; } 37 | 38 | /// 39 | /// Unique identifier of the target user. 40 | /// 41 | public long UserId { get; set; } 42 | 43 | public override HttpContent CreateHttpContent() 44 | { 45 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 46 | { 47 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 48 | } 49 | 50 | var dic = new Dictionary(); 51 | 52 | if (ChatId.HasValue) 53 | { 54 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 55 | } 56 | 57 | if (!string.IsNullOrEmpty(ChannelName)) 58 | { 59 | dic.Add("chat_id", ChannelName); 60 | } 61 | 62 | dic.Add("user_id", UserId.ToString(CultureInfo.InvariantCulture)); 63 | 64 | return new FormUrlEncodedContent(dic); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetChatMembersCount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// Use this method to get the number of members in a chat. Returns Int on success. 10 | /// 11 | public class GetChatMembersCount : RequestBase 12 | { 13 | public GetChatMembersCount(long chatId) 14 | : base("getChatMembersCount") 15 | { 16 | this.ChatId = chatId; 17 | } 18 | 19 | public GetChatMembersCount(string channelName) 20 | : base("getChatMembersCount") 21 | { 22 | this.ChannelName = channelName; 23 | } 24 | 25 | /// 26 | /// Unique identifier for the target chat. 27 | /// 28 | public long? ChatId { get; protected set; } 29 | 30 | /// 31 | /// Username of the target supergroup or channel (in the format @channelusername). 32 | /// 33 | public string ChannelName { get; set; } 34 | 35 | public override HttpContent CreateHttpContent() 36 | { 37 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 38 | { 39 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 40 | } 41 | 42 | var dic = new Dictionary(); 43 | 44 | if (ChatId.HasValue) 45 | { 46 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 47 | } 48 | 49 | if (!string.IsNullOrEmpty(ChannelName)) 50 | { 51 | dic.Add("chat_id", ChannelName); 52 | } 53 | 54 | return new FormUrlEncodedContent(dic); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using NetTelegramBotApi.Types; 4 | 5 | namespace NetTelegramBotApi.Requests 6 | { 7 | /// 8 | /// Use this method to get basic info about a file and prepare it for downloading. 9 | /// For the moment, bots can download files of up to 20MB in size. 10 | /// On success, a object is returned. 11 | /// The file can then be downloaded via the link https://api.telegram.org/file/bot/, where is taken from the response. 12 | /// It is guaranteed that the link will be valid for at least 1 hour. 13 | /// When the link expires, a new one can be requested by calling getFile again. 14 | /// 15 | public class GetFile : RequestBase 16 | { 17 | public GetFile(string fileId) 18 | : base("getFile") 19 | { 20 | this.FileId = fileId; 21 | } 22 | 23 | /// 24 | /// File identifier to get info about 25 | /// 26 | public string FileId { get; set; } 27 | 28 | public override HttpContent CreateHttpContent() 29 | { 30 | var values = new[] 31 | { 32 | new KeyValuePair("file_id", FileId), 33 | }; 34 | return new FormUrlEncodedContent(values); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetGameHighScores.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to get data for high score tables. 11 | /// Will return the score of the specified user and several of his neighbors in a game. 12 | /// On success, returns an Array of GameHighScore objects. 13 | /// 14 | /// 15 | /// This method will currently return scores for the target user, plus two of his closest neighbors on each side. 16 | /// Will also return the top three users if the user and his neighbors are not among them. 17 | /// Please note that this behavior is subject to change. 18 | /// 19 | public class GetGameHighScores : RequestBase 20 | { 21 | public GetGameHighScores(long userId) 22 | : base("getGameHighScores") 23 | { 24 | this.UserId = userId; 25 | } 26 | 27 | /// 28 | /// Target user id. 29 | /// 30 | public long UserId { get; protected set; } 31 | 32 | /// 33 | /// Required if inline_message_id is not specified. Unique identifier for the target chat. 34 | /// 35 | public long? ChatId { get; protected set; } 36 | 37 | /// 38 | /// Required if inline_message_id is not specified. Unique identifier for the target chat. 39 | /// 40 | public string ChannelName { get; set; } 41 | 42 | /// 43 | /// Required if inline_message_id is not specified. Identifier of the sent message. 44 | /// 45 | public long? MessageId { get; set; } 46 | 47 | /// 48 | /// Required if chat_id and message_id are not specified. Identifier of the inline message. 49 | /// 50 | public string InlineMessageId { get; set; } 51 | 52 | public override HttpContent CreateHttpContent() 53 | { 54 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 55 | { 56 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 57 | } 58 | 59 | var dic = new Dictionary(); 60 | 61 | dic.Add("user_id", UserId.ToString(CultureInfo.InvariantCulture)); 62 | 63 | if (ChatId.HasValue) 64 | { 65 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 66 | } 67 | 68 | if (!string.IsNullOrEmpty(ChannelName)) 69 | { 70 | dic.Add("chat_id", ChannelName); 71 | } 72 | 73 | if (MessageId.HasValue) 74 | { 75 | dic.Add("message_id", MessageId.Value.ToString(CultureInfo.InvariantCulture)); 76 | } 77 | 78 | if (!string.IsNullOrEmpty(InlineMessageId)) 79 | { 80 | dic.Add("inline_message_id", InlineMessageId); 81 | } 82 | 83 | return new FormUrlEncodedContent(dic); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetMe.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using NetTelegramBotApi.Types; 3 | 4 | namespace NetTelegramBotApi.Requests 5 | { 6 | /// 7 | /// A simple method for testing your bot's auth token. Requires no parameters. 8 | /// Returns basic information about the bot in form of a User object. 9 | /// 10 | public class GetMe : RequestBase 11 | { 12 | public GetMe() 13 | : base("getMe") 14 | { 15 | // Nothing 16 | } 17 | 18 | public override HttpContent CreateHttpContent() 19 | { 20 | return null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetUpdates.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Net.Http; 4 | using NetTelegramBotApi.Types; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// Use this method to receive incoming updates using long polling (wiki). An Array of Update objects is returned. 10 | /// 11 | public class GetUpdates : RequestBase 12 | { 13 | public GetUpdates() 14 | : base("getUpdates") 15 | { 16 | // Nothing 17 | } 18 | 19 | /// 20 | /// Identifier of the first update to be returned. 21 | /// Must be greater by one than the highest among the identifiers of previously received updates. 22 | /// By default, updates starting with the earliest unconfirmed update are returned. 23 | /// An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. 24 | /// 25 | public long? Offset { get; set; } 26 | 27 | /// 28 | /// Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100. 29 | /// 30 | public int? Limit { get; set; } 31 | 32 | /// 33 | /// Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. 34 | /// 35 | public int? Timeout { get; set; } 36 | 37 | public override HttpContent CreateHttpContent() 38 | { 39 | if (!Offset.HasValue && !Limit.HasValue && !Timeout.HasValue) 40 | { 41 | return null; 42 | } 43 | 44 | var dic = new Dictionary(); 45 | 46 | if (Offset.HasValue) 47 | { 48 | dic.Add("offset", Offset.Value.ToString(CultureInfo.InvariantCulture)); 49 | } 50 | 51 | if (Limit.HasValue) 52 | { 53 | dic.Add("limit", Limit.Value.ToString(CultureInfo.InvariantCulture)); 54 | } 55 | 56 | if (Timeout.HasValue) 57 | { 58 | dic.Add("timeout", Timeout.Value.ToString(CultureInfo.InvariantCulture)); 59 | } 60 | 61 | return new FormUrlEncodedContent(dic); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetUserProfilePhotos.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Net.Http; 4 | using NetTelegramBotApi.Types; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos object. 10 | /// 11 | public class GetUserProfilePhotos : RequestBase 12 | { 13 | public GetUserProfilePhotos(long userId) 14 | : base("getUserProfilePhotos") 15 | { 16 | this.UserId = userId; 17 | } 18 | 19 | /// 20 | /// Unique identifier of the target user. 21 | /// 22 | public long UserId { get; set; } 23 | 24 | /// 25 | /// Sequential number of the first photo to be returned. By default, all photos are returned. 26 | /// 27 | public int? Offset { get; set; } 28 | 29 | /// 30 | /// Limits the number of photos to be retrieved. Values between 1—100 are accepted. Defaults to 100. 31 | /// 32 | public int? Limit { get; set; } 33 | 34 | public override HttpContent CreateHttpContent() 35 | { 36 | var dic = new Dictionary(); 37 | dic.Add("user_id", UserId.ToString(CultureInfo.InvariantCulture)); 38 | if (Offset.HasValue) 39 | { 40 | dic.Add("offset", Offset.Value.ToString(CultureInfo.InvariantCulture)); 41 | } 42 | 43 | if (Limit.HasValue) 44 | { 45 | dic.Add("limit", Limit.Value.ToString(CultureInfo.InvariantCulture)); 46 | } 47 | 48 | return new FormUrlEncodedContent(dic); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/GetWebhookInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using NetTelegramBotApi.Types; 3 | 4 | namespace NetTelegramBotApi.Requests 5 | { 6 | /// 7 | /// Use this method to get current webhook status. Requires no parameters. 8 | /// On success, returns a WebhookInfo object. 9 | /// If the bot is using getUpdates, will return an object with the url field empty. 10 | /// 11 | public class GetWebhookInfo : RequestBase 12 | { 13 | public GetWebhookInfo() 14 | : base("getWebhookInfo") 15 | { 16 | // Nothing 17 | } 18 | 19 | public override HttpContent CreateHttpContent() 20 | { 21 | return null; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/KickChatMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// Use this method to kick a user from a group or a supergroup. 10 | /// 11 | /// 12 | /// Note: This will method only work if the ‘All Members Are Admins’ setting is off in the target group. 13 | /// Otherwise members may only be removed by the group's creator or by the member that added them. 14 | /// 15 | /// In the case of supergroups, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. 16 | /// The bot must be an administrator in the group for this to work. 17 | /// Returns True on success. 18 | /// 19 | public class KickChatMember : RequestBase 20 | { 21 | public KickChatMember(long chatId, long userId) 22 | : base("kickChatMember") 23 | { 24 | this.ChatId = chatId; 25 | this.UserId = userId; 26 | } 27 | 28 | public KickChatMember(string channelName, long userId) 29 | : base("kickChatMember") 30 | { 31 | this.ChannelName = channelName; 32 | this.UserId = userId; 33 | } 34 | 35 | /// 36 | /// Unique identifier for the target chat. 37 | /// 38 | public long? ChatId { get; protected set; } 39 | 40 | /// 41 | /// Username of the target channel (in the format @channelusername). 42 | /// 43 | public string ChannelName { get; set; } 44 | 45 | /// 46 | /// Unique identifier of the target user. 47 | /// 48 | public long UserId { get; set; } 49 | 50 | public override HttpContent CreateHttpContent() 51 | { 52 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 53 | { 54 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 55 | } 56 | 57 | var dic = new Dictionary(); 58 | 59 | if (ChatId.HasValue) 60 | { 61 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 62 | } 63 | 64 | if (!string.IsNullOrEmpty(ChannelName)) 65 | { 66 | dic.Add("chat_id", ChannelName); 67 | } 68 | 69 | dic.Add("user_id", UserId.ToString(CultureInfo.InvariantCulture)); 70 | 71 | return new FormUrlEncodedContent(dic); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/LeaveChat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// Use this method for your bot to leave a group, supergroup or channel. Returns True on success. 10 | /// 11 | public class LeaveChat : RequestBase 12 | { 13 | public LeaveChat(long chatId) 14 | : base("leaveChat") 15 | { 16 | this.ChatId = chatId; 17 | } 18 | 19 | public LeaveChat(string channelName) 20 | : base("leaveChat") 21 | { 22 | this.ChannelName = channelName; 23 | } 24 | 25 | /// 26 | /// Unique identifier for the target chat. 27 | /// 28 | public long? ChatId { get; protected set; } 29 | 30 | /// 31 | /// Username of the target channel (in the format @channelusername). 32 | /// 33 | public string ChannelName { get; set; } 34 | 35 | public override HttpContent CreateHttpContent() 36 | { 37 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 38 | { 39 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 40 | } 41 | 42 | var dic = new Dictionary(); 43 | 44 | if (ChatId.HasValue) 45 | { 46 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 47 | } 48 | 49 | if (!string.IsNullOrEmpty(ChannelName)) 50 | { 51 | dic.Add("chat_id", ChannelName); 52 | } 53 | 54 | return new FormUrlEncodedContent(dic); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/RequestBase.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Text.Json; 3 | 4 | namespace NetTelegramBotApi.Requests 5 | { 6 | public abstract class RequestBase 7 | { 8 | protected RequestBase(string methodName) 9 | { 10 | this.MethodName = methodName; 11 | } 12 | 13 | public string MethodName { get; protected set; } 14 | 15 | public abstract HttpContent CreateHttpContent(); 16 | 17 | protected static string JsonSerialize(object value) 18 | { 19 | return JsonSerializer.Serialize(value, TelegramBot.JsonOptions); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendAudio.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using NetTelegramBotApi.Types; 4 | 5 | namespace NetTelegramBotApi.Requests 6 | { 7 | /// 8 | /// Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. 9 | /// For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Document). 10 | /// On success, the sent Message is returned. 11 | /// Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future. 12 | /// 13 | public class SendAudio : SendFileRequestBase 14 | { 15 | public SendAudio(long chatId, FileToSend audio) 16 | : base(chatId, "sendAudio", "audio") 17 | { 18 | this.File = audio; 19 | } 20 | 21 | public SendAudio(string channelName, FileToSend audio) 22 | : base(channelName, "sendAudio", "audio") 23 | { 24 | this.File = audio; 25 | } 26 | 27 | /// 28 | /// Audio caption, 0-200 characters. 29 | /// 30 | public string Caption { get; set; } 31 | 32 | /// 33 | /// Duration of sent audio in seconds. 34 | /// 35 | public int? Duration { get; set; } 36 | 37 | /// 38 | /// Performer of sent audio. 39 | /// 40 | public string Performer { get; set; } 41 | 42 | /// 43 | /// Title of sent audio. 44 | /// 45 | public string Title { get; set; } 46 | 47 | protected override void AppendParameters(Action appendCallback) 48 | { 49 | if (!string.IsNullOrEmpty(Caption)) 50 | { 51 | appendCallback("caption", Caption); 52 | } 53 | 54 | if (Duration.HasValue) 55 | { 56 | appendCallback("duration", Duration.Value.ToString(CultureInfo.InvariantCulture)); 57 | } 58 | 59 | if (!string.IsNullOrEmpty(Performer)) 60 | { 61 | appendCallback("performer", Performer); 62 | } 63 | 64 | if (!string.IsNullOrEmpty(Title)) 65 | { 66 | appendCallback("title", Title); 67 | } 68 | 69 | base.AppendParameters(appendCallback); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendChatAction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// Use this method when you need to tell the user that something is happening on the bot's side. 10 | /// The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). 11 | /// 12 | /// 13 | /// We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive. 14 | /// 15 | public class SendChatAction : RequestBase 16 | { 17 | public SendChatAction(long chatId, string action) 18 | : base("sendChatAction") 19 | { 20 | this.ChatId = chatId; 21 | this.Action = action; 22 | } 23 | 24 | public SendChatAction(string channelName, string action) 25 | : base("sendChatAction") 26 | { 27 | this.ChannelName = channelName; 28 | this.Action = action; 29 | } 30 | 31 | public SendChatAction(long chatId, ChatActions action) 32 | : this(chatId, ConvertChatAction(action)) 33 | { 34 | // Nothing 35 | } 36 | 37 | public SendChatAction(string channelName, ChatActions action) 38 | : this(channelName, ConvertChatAction(action)) 39 | { 40 | // Nothing 41 | } 42 | 43 | public enum ChatActions 44 | { 45 | Typing, 46 | UploadPhoto, 47 | RecordVideo, 48 | UploadVideo, 49 | RecordVoice, 50 | UploadVoice, 51 | UploadDocument, 52 | ChooseSticker, 53 | FindLocation, 54 | RecordVideoNote, 55 | UploadVideoNote, 56 | } 57 | 58 | /// 59 | /// Unique identifier for the target chat. 60 | /// 61 | public long? ChatId { get; protected set; } 62 | 63 | /// 64 | /// Username of the target channel (in the format @channelusername). 65 | /// 66 | public string ChannelName { get; set; } 67 | 68 | /// 69 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 70 | /// 71 | public long? MessageThreadId { get; set; } 72 | 73 | /// 74 | /// Type of action to broadcast. 75 | /// Choose one, depending on what the user is about to receive: 76 | /// typing for text messages, 77 | /// upload_photo for photos, 78 | /// record_video or upload_video for videos, 79 | /// record_audio or upload_audio for audio files, 80 | /// upload_document for general files, 81 | /// find_location for location data. 82 | /// 83 | public string Action { get; set; } 84 | 85 | public override HttpContent CreateHttpContent() 86 | { 87 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 88 | { 89 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 90 | } 91 | 92 | var dic = new Dictionary(); 93 | 94 | if (ChatId.HasValue) 95 | { 96 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 97 | } 98 | 99 | if (!string.IsNullOrEmpty(ChannelName)) 100 | { 101 | dic.Add("chat_id", ChannelName); 102 | } 103 | 104 | if (MessageThreadId.HasValue) 105 | { 106 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 107 | } 108 | 109 | dic.Add("action", Action); 110 | 111 | return new FormUrlEncodedContent(dic); 112 | } 113 | 114 | protected static string ConvertChatAction(ChatActions action) 115 | { 116 | return action switch 117 | { 118 | ChatActions.Typing => "typing", 119 | ChatActions.UploadPhoto => "upload_photo", 120 | ChatActions.RecordVideo => "record_video", 121 | ChatActions.UploadVideo => "upload_video", 122 | ChatActions.RecordVoice => "record_voice", 123 | ChatActions.UploadVoice => "upload_voice", 124 | ChatActions.UploadDocument => "upload_document", 125 | ChatActions.ChooseSticker => "choose_sticker", 126 | ChatActions.FindLocation => "find_location", 127 | ChatActions.RecordVideoNote => "record_video_note", 128 | ChatActions.UploadVideoNote => "upload_video_note", 129 | _ => string.Empty, 130 | }; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendContact.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to send phone contacts. On success, the sent Message is returned. 11 | /// 12 | public class SendContact : RequestBase 13 | { 14 | public SendContact(long chatId, string phoneNumber, string firstName) 15 | : base("sendContact") 16 | { 17 | this.ChatId = chatId; 18 | this.PhoneNumber = phoneNumber; 19 | this.FirstName = firstName; 20 | } 21 | 22 | public SendContact(string channelName, string phoneNumber, string firstName) 23 | : base("sendContact") 24 | { 25 | this.ChannelName = channelName; 26 | this.PhoneNumber = phoneNumber; 27 | this.FirstName = firstName; 28 | } 29 | 30 | /// 31 | /// Unique identifier for the target chat. 32 | /// 33 | public long? ChatId { get; protected set; } 34 | 35 | /// 36 | /// Username of the target channel (in the format @channelusername). 37 | /// 38 | public string ChannelName { get; set; } 39 | 40 | /// 41 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 42 | /// 43 | public long? MessageThreadId { get; set; } 44 | 45 | /// 46 | /// Contact's phone number. 47 | /// 48 | public string PhoneNumber { get; set; } 49 | 50 | /// 51 | /// Contact's first name. 52 | /// 53 | public string FirstName { get; set; } 54 | 55 | /// 56 | /// Optional. Contact's last name. 57 | /// 58 | public string LastName { get; set; } 59 | 60 | /// 61 | /// Sends the message silently. 62 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 63 | /// 64 | public bool? DisableNotification { get; set; } 65 | 66 | /// 67 | /// Optional. If the message is a reply, ID of the original message. 68 | /// 69 | public long? ReplyToMessageId { get; set; } 70 | 71 | /// 72 | /// Optional. Additional interface options. A JSON-serialized object for a custom reply keyboard, 73 | /// instructions to hide keyboard or to force a reply from the user. 74 | /// 75 | public ReplyMarkupBase ReplyMarkup { get; set; } 76 | 77 | public override HttpContent CreateHttpContent() 78 | { 79 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 80 | { 81 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 82 | } 83 | 84 | var dic = new Dictionary(); 85 | 86 | if (ChatId.HasValue) 87 | { 88 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 89 | } 90 | 91 | if (!string.IsNullOrEmpty(ChannelName)) 92 | { 93 | dic.Add("chat_id", ChannelName); 94 | } 95 | 96 | if (MessageThreadId.HasValue) 97 | { 98 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 99 | } 100 | 101 | dic.Add("phone_number", PhoneNumber); 102 | dic.Add("first_name", FirstName); 103 | if (!string.IsNullOrEmpty(LastName)) 104 | { 105 | dic.Add("last_name", LastName); 106 | } 107 | 108 | if (DisableNotification.HasValue) 109 | { 110 | dic.Add("disable_notification", DisableNotification.Value.ToString()); 111 | } 112 | 113 | if (ReplyToMessageId.HasValue) 114 | { 115 | dic.Add("reply_to_message_id", ReplyToMessageId.Value.ToString(CultureInfo.InvariantCulture)); 116 | } 117 | 118 | if (ReplyMarkup != null) 119 | { 120 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 121 | } 122 | 123 | return new FormUrlEncodedContent(dic); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendDocument.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NetTelegramBotApi.Types; 3 | 4 | namespace NetTelegramBotApi.Requests 5 | { 6 | /// 7 | /// Use this method to send general files. On success, the sent Message is returned. 8 | /// Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future. 9 | /// 10 | public class SendDocument : SendFileRequestBase 11 | { 12 | public SendDocument(long chatId, FileToSend document) 13 | : base(chatId, "sendDocument", "document") 14 | { 15 | this.File = document; 16 | } 17 | 18 | public SendDocument(string channelName, FileToSend document) 19 | : base(channelName, "sendDocument", "document") 20 | { 21 | this.File = document; 22 | } 23 | 24 | /// 25 | /// Document caption (may also be used when resending documents by file_id), 0-200 characters 26 | /// 27 | public string Caption { get; set; } 28 | 29 | protected override void AppendParameters(Action appendCallback) 30 | { 31 | if (!string.IsNullOrEmpty(Caption)) 32 | { 33 | appendCallback("caption", Caption); 34 | } 35 | 36 | base.AppendParameters(appendCallback); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendFileRequestBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Text; 7 | using NetTelegramBotApi.Types; 8 | 9 | namespace NetTelegramBotApi.Requests 10 | { 11 | /// 12 | /// Base class for all file-sending requests. 13 | /// 14 | public abstract class SendFileRequestBase : RequestBase 15 | { 16 | protected SendFileRequestBase(long chatId, string methodName, string fileParameterName) 17 | : base(methodName) 18 | { 19 | this.ChatId = chatId; 20 | this.FileParameterName = fileParameterName; 21 | } 22 | 23 | protected SendFileRequestBase(string channelName, string methodName, string fileParameterName) 24 | : base(methodName) 25 | { 26 | this.ChannelName = channelName; 27 | this.FileParameterName = fileParameterName; 28 | } 29 | 30 | /// 31 | /// Unique identifier for the target chat. 32 | /// 33 | public long? ChatId { get; protected set; } 34 | 35 | /// 36 | /// Username of the target channel (in the format @channelusername). 37 | /// 38 | public string ChannelName { get; set; } 39 | 40 | /// 41 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 42 | /// 43 | public long? MessageThreadId { get; set; } 44 | 45 | public FileToSend File { get; protected set; } 46 | 47 | /// 48 | /// Sends the message silently. 49 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 50 | /// 51 | public bool? DisableNotification { get; set; } 52 | 53 | /// 54 | /// Optional. If the message is a reply, ID of the original message. 55 | /// 56 | public long? ReplyToMessageId { get; set; } 57 | 58 | /// 59 | /// Optional. Additional interface options. A JSON-serialized object for a custom reply keyboard, 60 | /// instructions to hide keyboard or to force a reply from the user. 61 | /// 62 | public ReplyMarkupBase ReplyMarkup { get; set; } 63 | 64 | /// 65 | /// Name of parameter (when calling server) with file info (eg 'photo', 'video', 'document'). 66 | /// 67 | protected string FileParameterName { get; set; } 68 | 69 | public override HttpContent CreateHttpContent() 70 | { 71 | if (File == null || File.AlreadyUploaded) 72 | { 73 | var dic = new Dictionary(); 74 | if (File != null) 75 | { 76 | dic.Add(FileParameterName, File.ExistingFileId); 77 | } 78 | 79 | AppendParameters((string name, string value) => dic.Add(name, value)); 80 | return new FormUrlEncodedContent(dic); 81 | } 82 | else 83 | { 84 | var content = new MultipartFormDataContent(); 85 | AppendParameters((string name, string value) => content.Add(new StringContent(value), name)); 86 | 87 | // HACK, but utf-8 file names (issue #5) sent correctly now (in filename, not filename*), 88 | // thanks to http://stackoverflow.com/questions/21928982/how-to-disable-base64-encoded-filenames-in-httpclient-multipartformdatacontent 89 | var contentDispositionValue = string.Format( 90 | "form-data; name={0}; filename=\"{1}\"", 91 | FileParameterName, 92 | string.Concat(Encoding.UTF8.GetBytes(File.NewFileName).Select(x => (char)x).Where(x => x != '"'))); 93 | var fileContent = new StreamContent(File.NewFileContent); 94 | fileContent.Headers.Add("Content-Disposition", contentDispositionValue); 95 | content.Add(fileContent); 96 | 97 | return content; 98 | } 99 | } 100 | 101 | protected virtual void AppendParameters(Action appendCallback) 102 | { 103 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 104 | { 105 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 106 | } 107 | 108 | if (ChatId.HasValue) 109 | { 110 | appendCallback("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 111 | } 112 | 113 | if (!string.IsNullOrEmpty(ChannelName)) 114 | { 115 | appendCallback("chat_id", ChannelName); 116 | } 117 | 118 | if (MessageThreadId.HasValue) 119 | { 120 | appendCallback("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 121 | } 122 | 123 | if (ReplyToMessageId.HasValue) 124 | { 125 | appendCallback("reply_to_message_id", ReplyToMessageId.Value.ToString(CultureInfo.InvariantCulture)); 126 | } 127 | 128 | if (DisableNotification.HasValue) 129 | { 130 | appendCallback("disable_notification", DisableNotification.Value.ToString()); 131 | } 132 | 133 | if (ReplyMarkup != null) 134 | { 135 | appendCallback("reply_markup", JsonSerialize(ReplyMarkup)); 136 | } 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendGame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to send photos. On success, the sent Message is returned. 11 | /// 12 | /// 13 | public class SendGame : RequestBase 14 | { 15 | public SendGame(long chatId, string gameShortName) 16 | : base("sendGame") 17 | { 18 | this.ChatId = chatId; 19 | this.GameShortName = gameShortName; 20 | } 21 | 22 | public SendGame(string channelName, string gameShortName) 23 | : base("sendGame") 24 | { 25 | this.ChannelName = channelName; 26 | this.GameShortName = gameShortName; 27 | } 28 | 29 | /// 30 | /// Unique identifier for the target chat. 31 | /// 32 | public long? ChatId { get; protected set; } 33 | 34 | /// 35 | /// Username of the target channel (in the format @channelusername). 36 | /// 37 | public string ChannelName { get; set; } 38 | 39 | /// 40 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 41 | /// 42 | public long? MessageThreadId { get; set; } 43 | 44 | /// 45 | /// Short name of the game, serves as the unique identifier for the game. Set up your games via @Botfather. 46 | /// 47 | public string GameShortName { get; set; } 48 | 49 | /// 50 | /// Sends the message silently. 51 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 52 | /// 53 | public bool? DisableNotification { get; set; } 54 | 55 | /// 56 | /// Optional. If the message is a reply, ID of the original message. 57 | /// 58 | public long? ReplyToMessageId { get; set; } 59 | 60 | /// 61 | /// Optional. Additional interface options. A JSON-serialized object for a custom reply keyboard, 62 | /// instructions to hide keyboard or to force a reply from the user. 63 | /// 64 | public ReplyMarkupBase ReplyMarkup { get; set; } 65 | 66 | public override HttpContent CreateHttpContent() 67 | { 68 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 69 | { 70 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 71 | } 72 | 73 | var dic = new Dictionary(); 74 | 75 | if (ChatId.HasValue) 76 | { 77 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 78 | } 79 | 80 | if (!string.IsNullOrEmpty(ChannelName)) 81 | { 82 | dic.Add("chat_id", ChannelName); 83 | } 84 | 85 | if (MessageThreadId.HasValue) 86 | { 87 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 88 | } 89 | 90 | dic.Add("game_short_name", GameShortName); 91 | 92 | if (DisableNotification.HasValue) 93 | { 94 | dic.Add("disable_notification", DisableNotification.Value.ToString()); 95 | } 96 | 97 | if (ReplyToMessageId.HasValue) 98 | { 99 | dic.Add("reply_to_message_id", ReplyToMessageId.Value.ToString(CultureInfo.InvariantCulture)); 100 | } 101 | 102 | if (ReplyMarkup != null) 103 | { 104 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 105 | } 106 | 107 | return new FormUrlEncodedContent(dic); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendLocation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to send text messages. On success, the sent Message is returned. 11 | /// 12 | public class SendLocation : RequestBase 13 | { 14 | public SendLocation(long chatId, float latitude, float longitude) 15 | : base("sendLocation") 16 | { 17 | this.ChatId = chatId; 18 | this.Latitude = latitude; 19 | this.Longitude = longitude; 20 | } 21 | 22 | public SendLocation(string channelName, float latitude, float longitude) 23 | : base("sendLocation") 24 | { 25 | this.ChannelName = channelName; 26 | this.Latitude = latitude; 27 | this.Longitude = longitude; 28 | } 29 | 30 | /// 31 | /// Unique identifier for the target chat. 32 | /// 33 | public long? ChatId { get; protected set; } 34 | 35 | /// 36 | /// Username of the target channel (in the format @channelusername). 37 | /// 38 | public string ChannelName { get; set; } 39 | 40 | /// 41 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 42 | /// 43 | public long? MessageThreadId { get; set; } 44 | 45 | /// 46 | /// Latitude of location. 47 | /// 48 | public float Latitude { get; set; } 49 | 50 | /// 51 | /// Longitude of location. 52 | /// 53 | public float Longitude { get; set; } 54 | 55 | /// 56 | /// Sends the message silently. 57 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 58 | /// 59 | public bool? DisableNotification { get; set; } 60 | 61 | /// 62 | /// Optional. If the message is a reply, ID of the original message. 63 | /// 64 | public long? ReplyToMessageId { get; set; } 65 | 66 | /// 67 | /// Optional. Additional interface options. A JSON-serialized object for a custom reply keyboard, 68 | /// instructions to hide keyboard or to force a reply from the user. 69 | /// 70 | public ReplyMarkupBase ReplyMarkup { get; set; } 71 | 72 | public override HttpContent CreateHttpContent() 73 | { 74 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 75 | { 76 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 77 | } 78 | 79 | var dic = new Dictionary(); 80 | 81 | if (ChatId.HasValue) 82 | { 83 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 84 | } 85 | 86 | if (!string.IsNullOrEmpty(ChannelName)) 87 | { 88 | dic.Add("chat_id", ChannelName); 89 | } 90 | 91 | if (MessageThreadId.HasValue) 92 | { 93 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 94 | } 95 | 96 | dic.Add("latitude", Latitude.ToString(CultureInfo.InvariantCulture)); 97 | dic.Add("longitude", Longitude.ToString(CultureInfo.InvariantCulture)); 98 | 99 | if (DisableNotification.HasValue) 100 | { 101 | dic.Add("disable_notification", DisableNotification.Value.ToString()); 102 | } 103 | 104 | if (ReplyToMessageId.HasValue) 105 | { 106 | dic.Add("reply_to_message_id", ReplyToMessageId.Value.ToString(CultureInfo.InvariantCulture)); 107 | } 108 | 109 | if (ReplyMarkup != null) 110 | { 111 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 112 | } 113 | 114 | return new FormUrlEncodedContent(dic); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to send text messages. On success, the sent Message is returned. 11 | /// 12 | public class SendMessage : RequestBase 13 | { 14 | public SendMessage(long chatId, string text) 15 | : base("sendMessage") 16 | { 17 | this.ChatId = chatId; 18 | this.Text = text; 19 | } 20 | 21 | public SendMessage(string channelName, string text) 22 | : base("sendMessage") 23 | { 24 | this.ChannelName = channelName; 25 | this.Text = text; 26 | } 27 | 28 | public enum ParseModes 29 | { 30 | None, 31 | Markdown, 32 | MarkdownV2, 33 | HTML, 34 | } 35 | 36 | /// 37 | /// Unique identifier for the message recipient — User or GroupChat id. 38 | /// 39 | /// 40 | /// Use for sending to channels. 41 | /// 42 | public long? ChatId { get; set; } 43 | 44 | /// 45 | /// Target channel (in the format @channelusername). 46 | /// 47 | public string ChannelName { get; set; } 48 | 49 | /// 50 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 51 | /// 52 | public long? MessageThreadId { get; set; } 53 | 54 | /// 55 | /// Text of the message to be sent. 56 | /// 57 | public string Text { get; set; } 58 | 59 | /// 60 | /// Send "Markdown", if you want Telegram apps to show bold, italic and inline URLs in your bot's message. 61 | /// For the moment, only Telegram for Android supports this. 62 | /// 63 | public ParseModes ParseMode { get; set; } 64 | 65 | /// 66 | /// Optional. Disables link previews for links in this message. 67 | /// 68 | public bool? DisableWebPagePreview { get; set; } 69 | 70 | /// 71 | /// Sends the message silently. 72 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 73 | /// 74 | public bool? DisableNotification { get; set; } 75 | 76 | /// 77 | /// Optional. If the message is a reply, ID of the original message. 78 | /// 79 | public long? ReplyToMessageId { get; set; } 80 | 81 | /// 82 | /// Optional. Additional interface options. A JSON-serialized object for a custom reply keyboard, 83 | /// instructions to hide keyboard or to force a reply from the user. 84 | /// 85 | public ReplyMarkupBase ReplyMarkup { get; set; } 86 | 87 | public override HttpContent CreateHttpContent() 88 | { 89 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 90 | { 91 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 92 | } 93 | 94 | var dic = new Dictionary(); 95 | 96 | if (ChatId.HasValue) 97 | { 98 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 99 | } 100 | 101 | if (!string.IsNullOrEmpty(ChannelName)) 102 | { 103 | dic.Add("chat_id", ChannelName); 104 | } 105 | 106 | if (MessageThreadId.HasValue) 107 | { 108 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 109 | } 110 | 111 | dic.Add("text", Text); 112 | if (ParseMode == ParseModes.Markdown) 113 | { 114 | dic.Add("parse_mode", "Markdown"); 115 | } 116 | else if (ParseMode == ParseModes.MarkdownV2) 117 | { 118 | dic.Add("parse_mode", "MarkdownV2"); 119 | } 120 | else if (ParseMode == ParseModes.HTML) 121 | { 122 | dic.Add("parse_mode", "HTML"); 123 | } 124 | 125 | if (DisableWebPagePreview.HasValue) 126 | { 127 | dic.Add("disable_web_page_preview", DisableWebPagePreview.Value.ToString()); 128 | } 129 | 130 | if (DisableNotification.HasValue) 131 | { 132 | dic.Add("disable_notification", DisableNotification.Value.ToString()); 133 | } 134 | 135 | if (ReplyToMessageId.HasValue) 136 | { 137 | dic.Add("reply_to_message_id", ReplyToMessageId.Value.ToString(CultureInfo.InvariantCulture)); 138 | } 139 | 140 | if (ReplyMarkup != null) 141 | { 142 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 143 | } 144 | 145 | return new FormUrlEncodedContent(dic); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendPhoto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NetTelegramBotApi.Types; 3 | 4 | namespace NetTelegramBotApi.Requests 5 | { 6 | /// 7 | /// Use this method to send photos. On success, the sent Message is returned. 8 | /// 9 | public class SendPhoto : SendFileRequestBase 10 | { 11 | public SendPhoto(long chatId, FileToSend photo) 12 | : base(chatId, "sendPhoto", "photo") 13 | { 14 | this.File = photo; 15 | } 16 | 17 | public SendPhoto(string channelName, FileToSend photo) 18 | : base(channelName, "sendPhoto", "photo") 19 | { 20 | this.File = photo; 21 | } 22 | 23 | /// 24 | /// Photo caption (may also be used when resending photos by file_id). 25 | /// 26 | public string Caption { get; set; } 27 | 28 | protected override void AppendParameters(Action appendCallback) 29 | { 30 | if (!string.IsNullOrEmpty(Caption)) 31 | { 32 | appendCallback("caption", Caption); 33 | } 34 | 35 | base.AppendParameters(appendCallback); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendSticker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NetTelegramBotApi.Types; 3 | 4 | namespace NetTelegramBotApi.Requests 5 | { 6 | /// 7 | /// Use this method to send .webp stickers. On success, the sent Message is returned. 8 | /// 9 | public class SendSticker : SendFileRequestBase 10 | { 11 | public SendSticker(long chatId, FileToSend sticker) 12 | : base(chatId, "sendSticker", "sticker") 13 | { 14 | this.File = sticker; 15 | } 16 | 17 | public SendSticker(string channelName, FileToSend sticker) 18 | : base(channelName, "sendSticker", "sticker") 19 | { 20 | this.File = sticker; 21 | } 22 | 23 | protected override void AppendParameters(Action appendCallback) 24 | { 25 | base.AppendParameters(appendCallback); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendVenue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to send information about a venue. On success, the sent Message is returned. 11 | /// 12 | public class SendVenue : RequestBase 13 | { 14 | public SendVenue(long chatId, float latitude, float longitude) 15 | : base("sendLocation") 16 | { 17 | this.ChatId = chatId; 18 | this.Latitude = latitude; 19 | this.Longitude = longitude; 20 | } 21 | 22 | public SendVenue(string channelName, float latitude, float longitude) 23 | : base("sendLocation") 24 | { 25 | this.ChannelName = channelName; 26 | this.Latitude = latitude; 27 | this.Longitude = longitude; 28 | } 29 | 30 | /// 31 | /// Unique identifier for the target chat. 32 | /// 33 | public long? ChatId { get; protected set; } 34 | 35 | /// 36 | /// Username of the target channel (in the format @channelusername). 37 | /// 38 | public string ChannelName { get; set; } 39 | 40 | /// 41 | /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only. 42 | /// 43 | public long? MessageThreadId { get; set; } 44 | 45 | /// 46 | /// Latitude of the venue. 47 | /// 48 | public float Latitude { get; set; } 49 | 50 | /// 51 | /// Longitude of the venue. 52 | /// 53 | public float Longitude { get; set; } 54 | 55 | /// 56 | /// Name of the venue. 57 | /// 58 | public string Title { get; set; } 59 | 60 | /// 61 | /// Address of the venue. 62 | /// 63 | public string Address { get; set; } 64 | 65 | /// 66 | /// Optional. Foursquare identifier of the venue. 67 | /// 68 | public string FoursquareId { get; set; } 69 | 70 | /// 71 | /// Sends the message silently. 72 | /// iOS users will not receive a notification, Android users will receive a notification with no sound. 73 | /// 74 | public bool? DisableNotification { get; set; } 75 | 76 | /// 77 | /// Optional. If the message is a reply, ID of the original message. 78 | /// 79 | public long? ReplyToMessageId { get; set; } 80 | 81 | /// 82 | /// Optional. Additional interface options. A JSON-serialized object for a custom reply keyboard, 83 | /// instructions to hide keyboard or to force a reply from the user. 84 | /// 85 | public ReplyMarkupBase ReplyMarkup { get; set; } 86 | 87 | public override HttpContent CreateHttpContent() 88 | { 89 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 90 | { 91 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 92 | } 93 | 94 | var dic = new Dictionary(); 95 | 96 | if (ChatId.HasValue) 97 | { 98 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 99 | } 100 | 101 | if (!string.IsNullOrEmpty(ChannelName)) 102 | { 103 | dic.Add("chat_id", ChannelName); 104 | } 105 | 106 | if (MessageThreadId.HasValue) 107 | { 108 | dic.Add("message_thread_id", MessageThreadId.Value.ToString(CultureInfo.InvariantCulture)); 109 | } 110 | 111 | dic.Add("latitude", Latitude.ToString(CultureInfo.InvariantCulture)); 112 | dic.Add("longitude", Longitude.ToString(CultureInfo.InvariantCulture)); 113 | dic.Add("title", Title); 114 | dic.Add("address", Address); 115 | if (!string.IsNullOrEmpty(FoursquareId)) 116 | { 117 | dic.Add("foursquare_id", FoursquareId); 118 | } 119 | 120 | if (DisableNotification.HasValue) 121 | { 122 | dic.Add("disable_notification", DisableNotification.Value.ToString()); 123 | } 124 | 125 | if (ReplyToMessageId.HasValue) 126 | { 127 | dic.Add("reply_to_message_id", ReplyToMessageId.Value.ToString(CultureInfo.InvariantCulture)); 128 | } 129 | 130 | if (ReplyMarkup != null) 131 | { 132 | dic.Add("reply_markup", JsonSerialize(ReplyMarkup)); 133 | } 134 | 135 | return new FormUrlEncodedContent(dic); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendVideo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using NetTelegramBotApi.Types; 4 | 5 | namespace NetTelegramBotApi.Requests 6 | { 7 | /// 8 | /// Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). 9 | /// On success, the sent Message is returned. 10 | /// Bots can currently send video files of up to 50 MB in size, this limit may be changed in the future. 11 | /// 12 | public class SendVideo : SendFileRequestBase 13 | { 14 | public SendVideo(long chatId, FileToSend video) 15 | : base(chatId, "sendVideo", "video") 16 | { 17 | this.File = video; 18 | } 19 | 20 | public SendVideo(string channelName, FileToSend video) 21 | : base(channelName, "sendVideo", "video") 22 | { 23 | this.File = video; 24 | } 25 | 26 | /// 27 | /// Duration of sent video in seconds 28 | /// 29 | public int? Duration { get; set; } 30 | 31 | /// 32 | /// Video width 33 | /// 34 | public int? Width { get; set; } 35 | 36 | /// 37 | /// Video height 38 | /// 39 | public int? Height { get; set; } 40 | 41 | /// 42 | /// Video caption (may also be used when resending videos by file_id), 0-200 characters 43 | /// 44 | public string Caption { get; set; } 45 | 46 | protected override void AppendParameters(Action appendCallback) 47 | { 48 | if (Duration.HasValue) 49 | { 50 | appendCallback("duration", Duration.Value.ToString(CultureInfo.InvariantCulture)); 51 | } 52 | 53 | if (Width.HasValue) 54 | { 55 | appendCallback("width", Width.Value.ToString(CultureInfo.InvariantCulture)); 56 | } 57 | 58 | if (Height.HasValue) 59 | { 60 | appendCallback("height", Height.Value.ToString(CultureInfo.InvariantCulture)); 61 | } 62 | 63 | if (!string.IsNullOrEmpty(Caption)) 64 | { 65 | appendCallback("caption", Caption); 66 | } 67 | 68 | base.AppendParameters(appendCallback); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SendVoice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using NetTelegramBotApi.Types; 4 | 5 | namespace NetTelegramBotApi.Requests 6 | { 7 | /// 8 | /// Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. 9 | /// For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Audio or Document). 10 | /// On success, the sent Message is returned. 11 | /// Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. 12 | /// 13 | public class SendVoice : SendFileRequestBase 14 | { 15 | public SendVoice(long chatId, FileToSend voice) 16 | : base(chatId, "sendVoice", "voice") 17 | { 18 | this.File = voice; 19 | } 20 | 21 | public SendVoice(string channelName, FileToSend voice) 22 | : base(channelName, "sendVoice", "voice") 23 | { 24 | this.File = voice; 25 | } 26 | 27 | /// 28 | /// Voice message caption, 0-200 characters. 29 | /// 30 | public string Caption { get; set; } 31 | 32 | /// 33 | /// Duration of sent audio in seconds. 34 | /// 35 | public int? Duration { get; set; } 36 | 37 | protected override void AppendParameters(Action appendCallback) 38 | { 39 | if (!string.IsNullOrEmpty(Caption)) 40 | { 41 | appendCallback("caption", Caption); 42 | } 43 | 44 | if (Duration.HasValue) 45 | { 46 | appendCallback("duration", Duration.Value.ToString(CultureInfo.InvariantCulture)); 47 | } 48 | 49 | base.AppendParameters(appendCallback); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SetGameScore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | using NetTelegramBotApi.Types; 6 | 7 | namespace NetTelegramBotApi.Requests 8 | { 9 | /// 10 | /// Use this method to set the score of the specified user in a game. 11 | /// On success, if the message was sent by the bot, returns the edited Message, otherwise returns True. 12 | /// Returns an error, if the new score is not greater than the user's current score in the chat. 13 | /// 14 | public class SetGameScore : RequestBase 15 | { 16 | public SetGameScore(long userId, long score) 17 | : base("setGameScore") 18 | { 19 | this.UserId = userId; 20 | this.Score = score; 21 | } 22 | 23 | /// 24 | /// User identifier. 25 | /// 26 | public long UserId { get; protected set; } 27 | 28 | /// 29 | /// New score, must be positive. 30 | /// 31 | public long Score { get; protected set; } 32 | 33 | /// 34 | /// Pass True, if the high score is allowed to decrease. This can be useful when fixing mistakes or banning cheaters. 35 | /// 36 | public bool Force { get; set; } 37 | 38 | /// 39 | /// Pass True, if the game message should not be automatically edited to include the current scoreboard. 40 | /// 41 | public bool DisableEditMessage { get; set; } 42 | 43 | /// 44 | /// Required if inline_message_id is not specified. Unique identifier for the target chat. 45 | /// 46 | public long? ChatId { get; protected set; } 47 | 48 | /// 49 | /// Required if inline_message_id is not specified. Unique identifier for the target chat. 50 | /// 51 | public string ChannelName { get; set; } 52 | 53 | /// 54 | /// Required if inline_message_id is not specified. Identifier of the sent message. 55 | /// 56 | public long? MessageId { get; set; } 57 | 58 | /// 59 | /// Required if chat_id and message_id are not specified. Identifier of the inline message. 60 | /// 61 | public string InlineMessageId { get; set; } 62 | 63 | public override HttpContent CreateHttpContent() 64 | { 65 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 66 | { 67 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 68 | } 69 | 70 | var dic = new Dictionary(); 71 | 72 | dic.Add("user_id", UserId.ToString(CultureInfo.InvariantCulture)); 73 | dic.Add("score", Score.ToString(CultureInfo.InvariantCulture)); 74 | 75 | dic.Add("force", Force.ToString()); 76 | 77 | dic.Add("disable_edit_message", DisableEditMessage.ToString()); 78 | 79 | if (ChatId.HasValue) 80 | { 81 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 82 | } 83 | 84 | if (!string.IsNullOrEmpty(ChannelName)) 85 | { 86 | dic.Add("chat_id", ChannelName); 87 | } 88 | 89 | if (MessageId.HasValue) 90 | { 91 | dic.Add("message_id", MessageId.Value.ToString(CultureInfo.InvariantCulture)); 92 | } 93 | 94 | if (!string.IsNullOrEmpty(InlineMessageId)) 95 | { 96 | dic.Add("inline_message_id", InlineMessageId); 97 | } 98 | 99 | return new FormUrlEncodedContent(dic); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/SetWebhook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetTelegramBotApi.Requests 4 | { 5 | /// 6 | /// Use this method to specify a url and receive incoming updates via an outgoing webhook. 7 | /// Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url, 8 | /// containing a JSON-serialized Update. In case of an unsuccessful request, we will give up after 9 | /// a reasonable amount of attempts. 10 | /// 11 | /// 12 | /// If you'd like to make sure that the Webhook request comes from Telegram, 13 | /// we recommend using a secret path in the URL, e.g. www.example.com/secret_path. 14 | /// Since nobody else knows this secret_path, you can be pretty sure it’s us. 15 | /// 16 | public class SetWebhook : SendFileRequestBase 17 | { 18 | /// HTTPS url to send updates to. Use null or empty string to remove webhook integration. 19 | public SetWebhook(string url) 20 | : this(url, null) 21 | { 22 | // Nothing 23 | } 24 | 25 | /// HTTPS url to send updates to. Use null or empty string to remove webhook integration. 26 | /// Optional. Your public key certificate so that the root certificate in use can be checked. 27 | public SetWebhook(string url, FileToSend certificatePublicKey) 28 | : base((string)null, "setWebhook", "certificate") 29 | { 30 | this.Url = url; 31 | if (certificatePublicKey != null && certificatePublicKey.AlreadyUploaded) 32 | { 33 | throw new InvalidOperationException("You can't use preloaded (earlier) files as certificate. Please provide binary data."); 34 | } 35 | 36 | this.File = certificatePublicKey; 37 | } 38 | 39 | /// 40 | /// HTTPS url to send updates to. Use an empty string to remove webhook integration. 41 | /// 42 | public string Url { get; set; } 43 | 44 | /// 45 | /// Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. 46 | /// Defaults to 40. 47 | /// Use lower values to limit the load on your bot‘s server, and higher values to increase your bot’s throughput. 48 | /// 49 | public byte? MaxConnections { get; set; } 50 | 51 | protected override void AppendParameters(Action appendCallback) 52 | { 53 | appendCallback("url", Url); 54 | 55 | if (MaxConnections.HasValue) 56 | { 57 | appendCallback("max_connections", MaxConnections.Value.ToString()); 58 | } 59 | 60 | base.AppendParameters(appendCallback); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/UnbanChatMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net.Http; 5 | 6 | namespace NetTelegramBotApi.Requests 7 | { 8 | /// 9 | /// 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. 10 | /// The bot must be an administrator in the group for this to work. Returns True on success. 11 | /// 12 | public class UnbanChatMember : RequestBase 13 | { 14 | public UnbanChatMember(long chatId, long userId) 15 | : base("unbanChatMember") 16 | { 17 | this.ChatId = chatId; 18 | this.UserId = userId; 19 | } 20 | 21 | public UnbanChatMember(string channelName, long userId) 22 | : base("unbanChatMember") 23 | { 24 | this.ChannelName = channelName; 25 | this.UserId = userId; 26 | } 27 | 28 | /// 29 | /// Unique identifier for the target chat. 30 | /// 31 | public long? ChatId { get; protected set; } 32 | 33 | /// 34 | /// Username of the target channel (in the format @channelusername). 35 | /// 36 | public string ChannelName { get; set; } 37 | 38 | /// 39 | /// Unique identifier of the target user. 40 | /// 41 | public long UserId { get; set; } 42 | 43 | public override HttpContent CreateHttpContent() 44 | { 45 | if (ChatId.HasValue && !string.IsNullOrEmpty(ChannelName)) 46 | { 47 | throw new InvalidOperationException("Use ChatId or ChannelName, not both."); 48 | } 49 | 50 | var dic = new Dictionary(); 51 | 52 | if (ChatId.HasValue) 53 | { 54 | dic.Add("chat_id", ChatId.Value.ToString(CultureInfo.InvariantCulture)); 55 | } 56 | 57 | if (!string.IsNullOrEmpty(ChannelName)) 58 | { 59 | dic.Add("chat_id", ChannelName); 60 | } 61 | 62 | dic.Add("user_id", UserId.ToString(CultureInfo.InvariantCulture)); 63 | 64 | return new FormUrlEncodedContent(dic); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Requests/_Classes.cd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAAAAAAAIAQ= 7 | Requests\ForwardMessage.cs 8 | 9 | 10 | 11 | 12 | 13 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA= 14 | Requests\GetMe.cs 15 | 16 | 17 | 18 | 19 | 20 | AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAIACAAAAAAAgAA= 21 | Requests\GetUpdates.cs 22 | 23 | 24 | 25 | 26 | 27 | AAAAAAAAAAAAAAAAACAAAAAAAAAAAAAACAACAAAAAAA= 28 | Requests\RequestBase.cs 29 | 30 | 31 | 32 | 33 | 34 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAQ= 35 | Requests\SendChatAction.cs 36 | 37 | 38 | 39 | 40 | 41 | QAAAAAAAAAAAAAAAAIAAAAgAAAAAAAAIAAAAAAAAAAA= 42 | Requests\FileToSend.cs 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | AAAAAAAABAEAAAAAAAAAAACAAAAEBAAACAAAAAAAAAQ= 52 | Requests\SendFileRequestBase.cs 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | AAIAAAAABAAAAAAAAAAAAAAAAAAABAAACAAACAAAAAQ= 62 | Requests\SendMessage.cs 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | AAAAAAAAAAAAAAAAAAAAAACAAAAAAAAACAAAAAAAAAA= 76 | Requests\SendPhoto.cs 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | AAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA= 90 | Requests\SendAudio.cs 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | AAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA= 104 | Requests\SendDocument.cs 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | AAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA= 118 | Requests\SendSticker.cs 119 | 120 | 121 | 122 | 123 | 124 | AAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA= 125 | Requests\SendVideo.cs 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | AAAAAAAABEAAAAAAAAAIAAAAAAAABAAACAAAAAAAAAQ= 140 | Requests\SendLocation.cs 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /NetTelegramBotApi/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace System 2 | { 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | public static class StringExtensions 8 | { 9 | private static readonly char[] MarkdownV1Chars = ['\\', '_', '*', '`', '[']; 10 | 11 | private static readonly char[] MarkdownV2Chars = ['\\', '_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!']; 12 | 13 | [return: NotNullIfNotNull(nameof(value))] 14 | public static string MarkdownEncode(this string value) 15 | { 16 | return Escape(value, MarkdownV1Chars); 17 | } 18 | 19 | [return: NotNullIfNotNull(nameof(value))] 20 | public static string MarkdownV2Encode(this string value) 21 | { 22 | return Escape(value, MarkdownV2Chars); 23 | } 24 | 25 | [return: NotNullIfNotNull(nameof(source))] 26 | private static string Escape(string source, char[] characters) 27 | { 28 | if (string.IsNullOrWhiteSpace(source)) 29 | { 30 | return source; 31 | } 32 | 33 | if (source.IndexOfAny(characters) == -1) 34 | { 35 | return source; 36 | } 37 | 38 | var sb = new StringBuilder(source.Length + 50); 39 | foreach (var c in source) 40 | { 41 | if (characters.Contains(c)) 42 | { 43 | sb.Append('\\'); 44 | } 45 | 46 | sb.Append(c); 47 | } 48 | 49 | return sb.ToString(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NetTelegramBotApi/TelegramBot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using NetTelegramBotApi.Requests; 6 | using NetTelegramBotApi.Types; 7 | using NetTelegramBotApi.Util; 8 | 9 | namespace NetTelegramBotApi 10 | { 11 | public class TelegramBot : ITelegramBot 12 | { 13 | public static readonly JsonSerializerOptions JsonOptions = new() 14 | { 15 | PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, 16 | DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, 17 | }; 18 | 19 | private readonly string accessToken; 20 | private readonly HttpClient httpClient; 21 | 22 | static TelegramBot() 23 | { 24 | JsonOptions.Converters.Add(new UnixDateTimeConverter()); 25 | } 26 | 27 | public TelegramBot(string accessToken, HttpClient httpClient) 28 | { 29 | if (string.IsNullOrWhiteSpace(accessToken)) 30 | { 31 | throw new ArgumentNullException(nameof(accessToken)); 32 | } 33 | 34 | this.accessToken = accessToken; 35 | this.httpClient = httpClient ?? new HttpClient(); 36 | } 37 | 38 | /// When non-Ok response returned from server. 39 | public async Task MakeRequestAsync(RequestBase request) 40 | { 41 | var uri = new Uri($"https://api.telegram.org/bot{accessToken}/{request.MethodName}"); 42 | using var httpMessage = new HttpRequestMessage(HttpMethod.Get, uri); 43 | using var postContent = request.CreateHttpContent(); 44 | if (postContent != null) 45 | { 46 | httpMessage.Method = HttpMethod.Post; 47 | httpMessage.Content = postContent; 48 | } 49 | 50 | using var response = await httpClient.SendAsync(httpMessage).ConfigureAwait(false); 51 | if ((int)response.StatusCode >= 500) 52 | { 53 | // Let's throw exception. It's server fault 54 | response.EnsureSuccessStatusCode(); 55 | } 56 | 57 | var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); 58 | var result = DeserializeMessage>(responseText); 59 | if (!result.Ok || !response.IsSuccessStatusCode) 60 | { 61 | var exceptionMessage = $"Request failed (status code {(int)response.StatusCode}): {result.Description}"; 62 | throw new BotRequestException(exceptionMessage) 63 | { 64 | StatusCode = response.StatusCode, 65 | ResponseBody = responseText, 66 | Description = result.Description, 67 | ErrorCode = result.ErrorCode, 68 | Parameters = result.Parameters, 69 | }; 70 | } 71 | 72 | var retVal = result.Result; 73 | if (retVal is IPostProcessingRequired forPostProcessing) 74 | { 75 | forPostProcessing.PostProcess(accessToken); 76 | } 77 | 78 | return retVal; 79 | } 80 | 81 | /// 82 | /// Use this method to deserialize Update object, sent to your webhook by Telegram server. 83 | /// 84 | /// Json-string with Update (body of HTTP POST to your webhook). 85 | /// Deserialized message. 86 | public Update DeserializeUpdate(string json) 87 | { 88 | return DeserializeMessage(json); 89 | } 90 | 91 | protected static T DeserializeMessage(string json) 92 | { 93 | return JsonSerializer.Deserialize(json, JsonOptions); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Animation.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents an animation file to be displayed in the message containing a game. 5 | /// 6 | public class Animation 7 | { 8 | /// 9 | /// Unique file identifier. 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Optional. Animation thumbnail as defined by sender. 15 | /// 16 | public PhotoSize Thumb { get; set; } 17 | 18 | /// 19 | /// Optional. Original animation filename as defined by sender. 20 | /// 21 | public string FileName { get; set; } 22 | 23 | /// 24 | /// Optional. MIME type of the file as defined by sender. 25 | /// 26 | public string MimeType { get; set; } 27 | 28 | /// 29 | /// Optional. File size. 30 | /// 31 | public long? FileSize { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Audio.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents an audio file to be treated as music by the Telegram clients. 5 | /// 6 | public class Audio 7 | { 8 | /// 9 | /// Unique identifier for this file. 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Duration of the audio in seconds as defined by sender. 15 | /// 16 | public long Duration { get; set; } 17 | 18 | /// 19 | /// Optional. Performer of the audio as defined by sender or by audio tags. 20 | /// 21 | public string Performer { get; set; } 22 | 23 | /// 24 | /// Optional. Title of the audio as defined by sender or by audio tags. 25 | /// 26 | public string Title { get; set; } 27 | 28 | /// 29 | /// Optional. MIME type of the file as defined by sender. 30 | /// 31 | public string MimeType { get; set; } 32 | 33 | /// 34 | /// Optional. File size. 35 | /// 36 | public long? FileSize { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/CallbackGame.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// A placeholder, currently holds no information. Use BotFather to set up your game. 5 | /// 6 | public class CallbackGame 7 | { 8 | // Nothing 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/CallbackQuery.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents an incoming callback query from a callback button in an inline keyboard. 5 | /// If the button that originated the query was attached to a message sent by the bot, the field message will be presented. 6 | /// If the button was attached to a message sent via the bot (in inline mode), the field inline_message_id will be presented. 7 | /// 8 | public class CallbackQuery 9 | { 10 | /// 11 | /// Unique identifier for this query 12 | /// 13 | public string Id { get; set; } 14 | 15 | /// 16 | /// Sender 17 | /// 18 | public User From { get; set; } 19 | 20 | /// 21 | /// Optional. Message with the callback button that originated the query. 22 | /// Note that message content and message date will not be available if the message is too old 23 | /// 24 | public Message Message { get; set; } 25 | 26 | /// 27 | /// Optional. Identifier of the message sent via the bot in inline mode, that originated the query 28 | /// 29 | public string InlineMessageId { get; set; } 30 | 31 | /// 32 | /// Data associated with the callback button. Be aware that a bad client can send arbitrary data in this field 33 | /// 34 | public string Data { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Chat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetTelegramBotApi.Types 4 | { 5 | /// 6 | /// This object represents a chat. 7 | /// 8 | public class Chat 9 | { 10 | /// 11 | /// Unique identifier for this chat. 12 | /// 13 | public long Id { get; set; } 14 | 15 | /// 16 | /// Type of chat, can be either “private”, “group”, “supergroup” or “channel”. See also . 17 | /// 18 | public string Type { get; set; } 19 | 20 | /// 21 | /// Optional. Title, for supergroups, channels and group chats. 22 | /// 23 | public string Title { get; set; } 24 | 25 | /// 26 | /// Optional. Username, for private chats, supergroups and channels if available. 27 | /// 28 | public string Username { get; set; } 29 | 30 | /// 31 | /// Optional. First name of the other party in a private chat. 32 | /// 33 | public string FirstName { get; set; } 34 | 35 | /// 36 | /// Optional. Last name of the other party in a private chat. 37 | /// 38 | public string LastName { get; set; } 39 | 40 | /// 41 | /// Optional. True, if the supergroup chat is a forum (has topics enabled). 42 | /// 43 | public bool IsForum { get; set; } 44 | 45 | /// 46 | /// NOT IMPLEMENTED. Optional. Chat photo. Returned only in getChat. 47 | /// 48 | public object Photo { get; set; } 49 | 50 | /// 51 | /// Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. Returned only in getChat. 52 | /// 53 | public string[] ActiveUsernames { get; set; } 54 | 55 | /// 56 | /// Optional. Custom emoji identifier of emoji status of the other party in a private chat. Returned only in getChat. 57 | /// 58 | public string EmojiStatusCustomEmojiId { get; set; } 59 | 60 | /// 61 | /// Optional. Bio of the other party in a private chat. Returned only in getChat. 62 | /// 63 | public string Bio { get; set; } 64 | 65 | /// 66 | /// Optional. True, if privacy settings of the other party in the private chat allows to use tg://user?id=<user_id> links only in chats with the user. Returned only in getChat. 67 | /// 68 | public bool HasPrivateForwards { get; set; } 69 | 70 | /// 71 | /// Optional. True, if the privacy settings of the other party restrict sending voice and video note messages in the private chat. Returned only in getChat. 72 | /// 73 | public bool HasRestrictedVoiceAndVideoMessages { get; set; } 74 | 75 | /// 76 | /// Optional. True, if users need to join the supergroup before they can send messages. Returned only in getChat. 77 | /// 78 | public bool JoinToSendMessages { get; set; } 79 | 80 | /// 81 | /// Optional. True, if all users directly joining the supergroup need to be approved by supergroup administrators. Returned only in getChat. 82 | /// 83 | public bool JoinByRequest { get; set; } 84 | 85 | /// 86 | /// Optional. Description, for groups, supergroups and channel chats. Returned only in getChat. 87 | /// 88 | public string Description { get; set; } 89 | 90 | /// 91 | /// Optional. Primary invite link, for groups, supergroups and channel chats. Returned only in getChat. 92 | /// 93 | public string InviteLink { get; set; } 94 | 95 | /// 96 | /// Optional. The most recent pinned message (by sending date). Returned only in getChat. 97 | /// 98 | public Message PinnedMessage { get; set; } 99 | 100 | /// 101 | /// NOT IMPLEMENTED. Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. 102 | /// 103 | public object Permissions { get; set; } 104 | 105 | /// 106 | /// Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unpriviledged user; in seconds. Returned only in getChat. 107 | /// 108 | public int SlowModeDelay { get; set; } 109 | 110 | /// 111 | /// Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in getChat. 112 | /// 113 | public int MessageAutoDeleteTime { get; set; } 114 | 115 | /// 116 | /// Optional. True, if aggressive anti-spam checks are enabled in the supergroup. The field is only available to chat administrators. Returned only in getChat. 117 | /// 118 | public bool HasAggressiveAntiSpamEnabled { get; set; } 119 | 120 | /// 121 | /// Optional. True, if non-administrators can only get the list of bots and administrators in the chat. Returned only in getChat. 122 | /// 123 | public bool HasHiddenMembers { get; set; } 124 | 125 | /// 126 | /// Optional. True, if messages from the chat can't be forwarded to other chats. Returned only in getChat. 127 | /// 128 | public bool HasProtectedContent { get; set; } 129 | 130 | /// 131 | /// Optional. For supergroups, name of group sticker set. Returned only in getChat. 132 | /// 133 | public string StickerSetName { get; set; } 134 | 135 | /// 136 | /// Optional. True, if the bot can change the group sticker set. Returned only in getChat. 137 | /// 138 | public bool CanSetStickerSet { get; set; } 139 | 140 | /// 141 | /// Optional. Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; for supergroups and channel chats. Returned only in getChat. 142 | /// 143 | public long LinkedChatId { get; set; } 144 | 145 | /// 146 | /// NOT IMPLEMENTED. Optional. For supergroups, the location to which the supergroup is connected. Returned only in getChat. 147 | /// 148 | public object Location { get; set; } 149 | 150 | /// 151 | /// Returns one of 'ChatType' members, based on chat 'Type' value. 152 | /// 153 | public ChatType GetChatType() 154 | { 155 | return Type switch 156 | { 157 | "private" => ChatType.Private, 158 | "group" => ChatType.Group, 159 | "supergroup" => ChatType.Supergroup, 160 | "channel" => ChatType.Channel, 161 | _ => ChatType.Unknown, 162 | }; 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ChatMember.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object contains information about one member of the chat. 5 | /// 6 | public class ChatMember 7 | { 8 | /// 9 | /// Information about the user. 10 | /// 11 | public User User { get; set; } 12 | 13 | /// 14 | /// The member's status in the chat. Can be “creator”, “administrator”, “member”, “left” or “kicked”. 15 | /// 16 | public string Status { get; set; } 17 | 18 | public ChatMemberStatus GetStatus() 19 | { 20 | return Status switch 21 | { 22 | "creator" => ChatMemberStatus.Creator, 23 | "administrator" => ChatMemberStatus.Administrator, 24 | "member" => ChatMemberStatus.Member, 25 | "restricted" => ChatMemberStatus.Restricted, 26 | "left" => ChatMemberStatus.Left, 27 | "kicked" => ChatMemberStatus.Kicked, 28 | _ => ChatMemberStatus.Unknown, 29 | }; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ChatMemberStatus.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | public enum ChatMemberStatus : byte 4 | { 5 | Unknown, 6 | Creator, 7 | Administrator, 8 | Member, 9 | Restricted, 10 | Left, 11 | Kicked, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ChatType.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | public enum ChatType : byte 4 | { 5 | Unknown = 0, 6 | Private = 1, 7 | Group = 2, 8 | Supergroup = 3, 9 | Channel = 4, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ChosenInlineResult.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// Represents a result of an inline query that was chosen by the user and sent to their chat partner. 5 | /// 6 | public class ChosenInlineResult 7 | { 8 | /// 9 | /// The unique identifier for the result that was chosen 10 | /// 11 | public string ResultId { get; set; } 12 | 13 | /// 14 | /// The user that chose the result 15 | /// 16 | public User From { get; set; } 17 | 18 | /// 19 | /// Optional. Sender location, only for bots that require user location 20 | /// 21 | public Location Location { get; set; } 22 | 23 | /// 24 | /// Optional. Identifier of the sent inline message. 25 | /// Available only if there is an inline keyboard attached to the message. 26 | /// Will be also received in callback queries and can be used to edit the message. 27 | /// 28 | public string InlineMessageId { get; set; } 29 | 30 | /// 31 | /// The query that was used to obtain the result 32 | /// 33 | public string Query { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Contact.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a phone contact. 5 | /// 6 | public class Contact 7 | { 8 | /// 9 | /// Contact's phone number. 10 | /// 11 | public string PhoneNumber { get; set; } 12 | 13 | /// 14 | /// Contact's first name. 15 | /// 16 | public string FirstName { get; set; } 17 | 18 | /// 19 | /// Optional. Contact's last name. 20 | /// 21 | public string LastName { get; set; } 22 | 23 | /// 24 | /// Optional. Contact's user identifier in Telegram. 25 | /// 26 | public long UserId { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Document.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a general file (as opposed to photos, voice messages and audio files). 5 | /// 6 | public class Document 7 | { 8 | /// 9 | /// Unique file identifier 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Document thumbnail as defined by sender. 15 | /// 16 | public PhotoSize Thumb { get; set; } 17 | 18 | /// 19 | /// Optional. Original filename as defined by sender. 20 | /// 21 | public string FileName { get; set; } 22 | 23 | /// 24 | /// Optional. MIME type of the file as defined by sender. 25 | /// 26 | public string MimeType { get; set; } 27 | 28 | /// 29 | /// Optional. File size. 30 | /// 31 | public long? FileSize { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/File.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a file ready to be downloaded. 5 | /// The file can be downloaded via the link https://api.telegram.org/file/bot/. 6 | /// It is guaranteed that the link will be valid for at least 1 hour. 7 | /// When the link expires, a new one can be requested by calling getFile. 8 | /// 9 | public class File : IPostProcessingRequired 10 | { 11 | /// 12 | /// Unique identifier for this file 13 | /// 14 | public string FileId { get; set; } 15 | 16 | /// 17 | /// Optional. File size, if known 18 | /// 19 | public long FileSize { get; set; } 20 | 21 | /// 22 | /// Optional. File path. Use https://api.telegram.org/file/bot/ to get the file. 23 | /// 24 | public string FilePath { get; set; } 25 | 26 | /// 27 | /// Full Url, where file body/content must be downloaded from. 28 | /// 29 | /// Extension of Telegram type! 30 | public string FileDownloadUrl { get; private set; } 31 | 32 | public void PostProcess(string botAccessToken) 33 | { 34 | FileDownloadUrl = "https://api.telegram.org/file/bot" + botAccessToken + "/" + FilePath; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ForceReply.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace NetTelegramBotApi.Types 4 | { 5 | /// 6 | /// Upon receiving a message with this object, Telegram clients will display a reply interface to the user 7 | /// (act as if the user has selected the bot‘s message and tapped ’Reply'). 8 | /// This can be extremely useful if you want to create user-friendly step-by-step interfaces 9 | /// without having to sacrifice privacy mode. 10 | /// See more info on Telegram site. 11 | /// 12 | public class ForceReply : ReplyMarkupBase 13 | { 14 | /// 15 | /// Shows reply interface to the user, as if they manually selected the bot‘s message and tapped ’Reply'. 16 | /// 17 | /// 18 | /// In original Telegram API, member is called 'ForceReply', but in C# it's forbidden to have properties with same name as class. 19 | /// 20 | [JsonPropertyName("force_reply")] 21 | public bool Force { get; set; } 22 | 23 | /// 24 | /// Optional. Use this parameter if you want to force reply from specific users only. 25 | /// Targets: 26 | /// 1) users that are @mentioned in the text of the Message object; 27 | /// 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message. 28 | /// 29 | /// 30 | /// A poll bot for groups runs in privacy mode (only receives commands, replies to its messages and mentions). 31 | /// There could be two ways to create a new poll: 32 | /// 1) Explain the user how to send a command with parameters (e.g. /newpoll question answer1 answer2). 33 | /// May be appealing for hardcore users but lacks modern day polish. 34 | /// 2) Guide the user through a step-by-step process. ‘Please send me your question’, 35 | /// ‘Cool, now let’s add the first answer option‘, ’Great. 36 | /// Keep adding answer options, then send /done when you‘re ready’. 37 | /// The last option is definitely more attractive. And if you use ForceReply in your bot‘s questions, 38 | /// it will receive the user’s answers even if it only receives replies, commands and mentions — without any 39 | /// extra work for the user. 40 | /// 41 | public bool Selective { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Game.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a game. 5 | /// Use BotFather to create and edit games, their short names will act as unique identifiers. 6 | /// 7 | public class Game 8 | { 9 | /// 10 | /// Title of the game. 11 | /// 12 | public string Title { get; set; } 13 | 14 | /// 15 | /// Description of the game. 16 | /// 17 | public string Description { get; set; } 18 | 19 | /// 20 | /// Photo that will be displayed in the game message in chats. 21 | /// 22 | public PhotoSize[] Photo { get; set; } 23 | 24 | /// 25 | /// Optional. Brief description of the game or high scores included in the game message. 26 | /// Can be automatically edited to include current high scores for the game when the bot calls setGameScore, or manually edited using editMessageText. 27 | /// 0-4096 characters. 28 | /// 29 | public string Text { get; set; } 30 | 31 | /// 32 | /// Optional. Special entities that appear in text, such as usernames, URLs, bot commands, etc. 33 | /// 34 | public MessageEntity[] TextEntities { get; set; } 35 | 36 | /// 37 | /// Optional. Animation that will be displayed in the game message in chats. 38 | /// Upload via BotFather. 39 | /// 40 | public Animation Animation { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/GameHighScore.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents one row of the high scores table for a game. 5 | /// 6 | public class GameHighScore 7 | { 8 | /// 9 | /// Position in high score table for the game. 10 | /// 11 | public long Position { get; set; } 12 | 13 | /// 14 | /// User. 15 | /// 16 | public User User { get; set; } 17 | 18 | /// 19 | /// Score. 20 | /// 21 | public long Score { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/InlineKeyboardButton.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents one button of an inline keyboard. You must use exactly one of the optional fields. 5 | /// 6 | /// 7 | /// Note: This will only work in Telegram versions released after 9 April, 2016. Older clients will display unsupported message. 8 | /// 9 | public class InlineKeyboardButton 10 | { 11 | /// 12 | /// Label text on the button. 13 | /// 14 | public string Text { get; set; } 15 | 16 | /// 17 | /// Optional. HTTP url to be opened when button is pressed. 18 | /// 19 | public string Url { get; set; } 20 | 21 | /// 22 | /// Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes. 23 | /// 24 | public string CallbackData { get; set; } 25 | 26 | /// 27 | /// Optional. Description of the Web App that will be launched when the user presses the button. 28 | /// 29 | /// 30 | /// The Web App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. 31 | /// Available only in private chats between a user and the bot. Not supported for messages sent on behalf of a Telegram Business account. 32 | /// 33 | public WebAppInfo WebApp { get; set; } 34 | 35 | /// 36 | /// Optional. If set, pressing the button will prompt the user to select one of their chats, 37 | /// open that chat and insert the bot‘s username and the specified inline query in the input field. 38 | /// Can be empty, in which case just the bot’s username will be inserted. 39 | /// 40 | /// 41 | /// Note: This offers an easy way for users to start using your bot in inline mode when they are currently 42 | /// in a private chat with it. Especially useful when combined with switch_pm… actions – in this case the user 43 | /// will be automatically returned to the chat they switched from, skipping the chat selection screen. 44 | /// 45 | public string SwitchInlineQuery { get; set; } 46 | 47 | /// 48 | /// Optional. If set, pressing the button will insert the bot‘s username and the specified inline query in the current chat's input field. 49 | /// Can be empty, in which case only the bot’s username will be inserted. 50 | /// This offers a quick way for the user to open your bot in inline mode 51 | /// in the same chat – good for selecting something from multiple options. 52 | /// 53 | public string SwitchInlineQueryCurrentChat { get; set; } 54 | 55 | /// 56 | /// Optional. Description of the game that will be launched when the user presses the button. 57 | /// NOTE: This type of button must always be the first button in the first row. 58 | /// 59 | public CallbackGame CallbackGame { get; set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/InlineKeyboardMarkup.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents an inline keyboard that appears right next to the message it belongs to. 5 | /// 6 | /// 7 | /// Warning: Inline keyboards are currently being tested and are not available in channels yet. For now, feel free to use them in one-on-one chats or groups. 8 | /// Note: This will only work in Telegram versions released after 9 April, 2016. Older clients will display unsupported message. 9 | /// 10 | public class InlineKeyboardMarkup : ReplyMarkupBase 11 | { 12 | /// 13 | /// Array of button rows, each represented by an Array of InlineKeyboardButton objects. 14 | /// 15 | public InlineKeyboardButton[][] InlineKeyboard { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/InlineQuery.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents an incoming inline query. 5 | /// When the user sends an empty query, your bot could return some default or trending results. 6 | /// 7 | public class InlineQuery 8 | { 9 | /// 10 | /// Unique identifier for this query 11 | /// 12 | public string Id { get; set; } 13 | 14 | /// 15 | /// Sender 16 | /// 17 | public User From { get; set; } 18 | 19 | /// 20 | /// Optional. Sender location, only for bots that request user location 21 | /// 22 | public Location Location { get; set; } 23 | 24 | /// 25 | /// Text of the query (up to 512 characters) 26 | /// 27 | public string Query { get; set; } 28 | 29 | /// 30 | /// Offset of the results to be returned, can be controlled by the bot 31 | /// 32 | public string Offset { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/KeyboardButton.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | public class KeyboardButton 4 | { 5 | public KeyboardButton(string text) 6 | { 7 | this.Text = text; 8 | } 9 | 10 | /// 11 | /// Text of the button. 12 | /// If none of the optional fields are used, it will be sent to the bot as a message when the button is pressed. 13 | /// 14 | public string Text { get; set; } 15 | 16 | /// 17 | /// Optional. If True, the user's phone number will be sent as a contact when the button is pressed. 18 | /// Available in private chats only. 19 | /// 20 | public bool RequestContact { get; set; } 21 | 22 | /// 23 | /// Optional. If True, the user's current location will be sent when the button is pressed. 24 | /// Available in private chats only. 25 | /// 26 | public bool RequestLocation { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Location.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a point on the map. 5 | /// 6 | public class Location 7 | { 8 | /// 9 | /// Longitude as defined by sender. 10 | /// 11 | public float Longitude { get; set; } 12 | 13 | /// 14 | /// Latitude as defined by sender. 15 | /// 16 | public float Latitude { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetTelegramBotApi.Types 4 | { 5 | /// 6 | /// This object represents a message. 7 | /// 8 | public class Message 9 | { 10 | /// 11 | /// Unique message identifier. 12 | /// 13 | public long MessageId { get; set; } 14 | 15 | /// 16 | /// Optional. Unique identifier of a message thread to which the message belongs; for supergroups only. 17 | /// 18 | public long? MessageThreadId { get; set; } 19 | 20 | /// 21 | /// Optional. Sender, can be empty for messages sent to channels. 22 | /// 23 | public User From { get; set; } 24 | 25 | /// 26 | /// Date the message was sent in Unix time. 27 | /// 28 | public DateTimeOffset Date { get; set; } 29 | 30 | /// 31 | /// Conversation the message belongs to. 32 | /// 33 | public Chat Chat { get; set; } 34 | 35 | /// 36 | /// Optional. For forwarded messages, sender of the original message. 37 | /// 38 | public User ForwardFrom { get; set; } 39 | 40 | /// 41 | /// Optional. For messages forwarded from a channel, information about the original channel. 42 | /// 43 | public Chat ForwardFromChat { get; set; } 44 | 45 | /// 46 | /// Optional. For forwarded channel posts, identifier of the original message in the channel. 47 | /// 48 | public long? ForwardFromMessageId { get; set; } 49 | 50 | /// 51 | /// Optional. For forwarded messages, date the original message was sent in Unix time. 52 | /// 53 | public DateTimeOffset? ForwardDate { get; set; } 54 | 55 | /// 56 | /// Optional. For replies, the original message. 57 | /// Note that the Message object in this field will not contain further reply_to_message fields even if it itself is a reply. 58 | /// 59 | public Message ReplyToMessage { get; set; } 60 | 61 | /// 62 | /// Optional. Date the message was last edited in Unix time. 63 | /// 64 | public DateTimeOffset? EditDate { get; set; } 65 | 66 | /// 67 | /// Optional. For text messages, the actual UTF-8 text of the message, 0-4096 characters. 68 | /// 69 | public string Text { get; set; } 70 | 71 | /// 72 | /// Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text. 73 | /// 74 | public MessageEntity[] Entities { get; set; } 75 | 76 | /// 77 | /// Optional. Message is an audio file, information about the file. 78 | /// 79 | public Audio Audio { get; set; } 80 | 81 | /// 82 | /// Optional. Message is a general file, information about the file. 83 | /// 84 | public Document Document { get; set; } 85 | 86 | /// 87 | /// Optional. Message is a photo, available sizes of the photo. 88 | /// 89 | public PhotoSize[] Photo { get; set; } 90 | 91 | /// 92 | /// Optional. Message is a sticker, information about the sticker. 93 | /// 94 | public Sticker Sticker { get; set; } 95 | 96 | /// 97 | /// Optional. Message is a video, information about the video. 98 | /// 99 | public Video Video { get; set; } 100 | 101 | /// 102 | /// Optional. Message is a voice message, information about the file. 103 | /// 104 | public Voice Voice { get; set; } 105 | 106 | /// 107 | /// Optional. Caption for the document, photo or video, 0-200 characters. 108 | /// 109 | public string Caption { get; set; } 110 | 111 | /// 112 | /// Optional. Message is a shared contact, information about the contact. 113 | /// 114 | public Contact Contact { get; set; } 115 | 116 | /// 117 | /// Optional. Message is a shared location, information about the location. 118 | /// 119 | public Location Location { get; set; } 120 | 121 | /// 122 | /// Optional. Message is a venue, information about the venue. 123 | /// 124 | public Venue Venue { get; set; } 125 | 126 | /// 127 | /// Optional. A new member was added to the group, information about them (this member may be the bot itself). 128 | /// 129 | public User NewChatMember { get; set; } 130 | 131 | /// 132 | /// Optional. A member was removed from the group, information about them (this member may be the bot itself). 133 | /// 134 | public User LeftChatMember { get; set; } 135 | 136 | /// 137 | /// Optional. A group title was changed to this value. 138 | /// 139 | public string NewChatTitle { get; set; } 140 | 141 | /// 142 | /// Optional. A group photo was change to this value. 143 | /// 144 | public PhotoSize[] NewChatPhoto { get; set; } 145 | 146 | /// 147 | /// Optional. Service message: the chat photo was deleted. 148 | /// 149 | public bool DeleteChatPhoto { get; set; } 150 | 151 | /// 152 | /// Optional. Service message: the group has been created. 153 | /// 154 | public bool GroupChatCreated { get; set; } 155 | 156 | /// 157 | /// Optional. Service message: the supergroup has been created. 158 | /// 159 | /// 160 | /// This field can‘t be received in a message coming through updates, 161 | /// because bot can’t be a member of a supergroup when it is created. 162 | /// It can only be found in reply_to_message if someone replies to a very first message 163 | /// in a directly created supergroup. 164 | /// 165 | public bool SupergroupChatCreated { get; set; } 166 | 167 | /// 168 | /// Optional. Service message: the channel has been created. 169 | /// 170 | /// 171 | /// This field can‘t be received in a message coming through updates, 172 | /// because bot can’t be a member of a channel when it is created. 173 | /// It can only be found in reply_to_message if someone replies to a very first message in a channel. 174 | /// 175 | public bool ChannelChatCreated { get; set; } 176 | 177 | /// 178 | /// Optional. The group has been migrated to a supergroup with the specified identifier. 179 | /// 180 | public long MigrateToChatId { get; set; } 181 | 182 | /// 183 | /// Optional. The supergroup has been migrated from a group with the specified identifier. 184 | /// 185 | public long MigrateFromChatId { get; set; } 186 | 187 | /// 188 | /// Optional. Specified message was pinned. 189 | /// 190 | /// 191 | /// Note that the Message object in this field will not contain further reply_to_message fields 192 | /// even if it is itself a reply. 193 | /// 194 | public Message PinnedMessage { get; set; } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/MessageEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetTelegramBotApi.Types 4 | { 5 | /// 6 | /// This object represents one special entity in a text message. For example, hashtags, usernames, URLs, etc. 7 | /// 8 | public class MessageEntity 9 | { 10 | /// 11 | /// Type of the entity. 12 | /// Can be mention (@username), hashtag, bot_command, url, email, bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block), text_link (for clickable text URLs), text_mention (for users without usernames). 13 | /// 14 | public string Type { get; set; } 15 | 16 | /// 17 | /// Offset in UTF-16 code units to the start of the entity. 18 | /// 19 | public int Offset { get; set; } 20 | 21 | /// 22 | /// Length of the entity in UTF-16 code units. 23 | /// 24 | public int Length { get; set; } 25 | 26 | /// 27 | /// Optional. For “text_link” only, url that will be opened after user taps on the text. 28 | /// 29 | public string Url { get; set; } 30 | 31 | /// 32 | /// Optional. For “text_mention” only, the mentioned user. 33 | /// 34 | public User User { get; set; } 35 | 36 | /// 37 | /// Returns one of members, based on chat value. 38 | /// 39 | public MessageEntityType GetMessageEntityType() 40 | { 41 | // special case: mention(@username) 42 | if (Type.StartsWith("mention", StringComparison.OrdinalIgnoreCase)) 43 | { 44 | return MessageEntityType.Mention; 45 | } 46 | 47 | return Type.ToLowerInvariant() switch 48 | { 49 | "hashtag" => MessageEntityType.Hashtag, 50 | "bot_command" => MessageEntityType.BotCommand, 51 | "url" => MessageEntityType.Url, 52 | "email" => MessageEntityType.Email, 53 | "bold" => MessageEntityType.Bold, 54 | "italic" => MessageEntityType.Italic, 55 | "code" => MessageEntityType.Code, 56 | "pre" => MessageEntityType.Pre, 57 | "text_link" => MessageEntityType.TextLink, 58 | "text_mention" => MessageEntityType.TextMention, 59 | _ => MessageEntityType.Unknown, 60 | }; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/MessageEntityType.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | public enum MessageEntityType : byte 4 | { 5 | Unknown = 0, 6 | Mention = 1, 7 | Hashtag = 2, 8 | BotCommand = 3, 9 | Url = 4, 10 | Email = 5, 11 | Bold = 6, 12 | Italic = 7, 13 | Code = 8, 14 | Pre = 9, 15 | TextLink = 10, 16 | TextMention = 11, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/PhotoSize.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents one size of a photo or a file / sticker thumbnail. 5 | /// 6 | public class PhotoSize 7 | { 8 | /// 9 | /// Unique identifier for this file. 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Photo width. 15 | /// 16 | public long Width { get; set; } 17 | 18 | /// 19 | /// Photo height. 20 | /// 21 | public long Height { get; set; } 22 | 23 | /// 24 | /// Optional. File size. 25 | /// 26 | public long? FileSize { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ReplyKeyboardMarkup.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a custom keyboard with reply options (see Introduction to bots for details and examples). 5 | /// 6 | public class ReplyKeyboardMarkup : ReplyMarkupBase 7 | { 8 | /// 9 | /// Array of button rows, each represented by an Array of KeyboardButton objects 10 | /// 11 | public KeyboardButton[][] Keyboard { get; set; } 12 | 13 | /// 14 | /// Optional. Requests clients to resize the keyboard vertically for optimal fit 15 | /// (e.g., make the keyboard smaller if there are just two rows of buttons). 16 | /// Defaults to false, in which case the custom keyboard is always of the same height as the app's standard keyboard. 17 | /// 18 | public bool ResizeKeyboard { get; set; } 19 | 20 | /// 21 | /// Optional. Requests clients to hide the keyboard as soon as it's been used. Defaults to false. 22 | /// 23 | public bool OneTimeKeyboard { get; set; } 24 | 25 | /// 26 | /// Optional. Use this parameter if you want to show the keyboard to specific users only. 27 | /// Targets: 28 | /// 1) users that are @mentioned in the text of the Message object; 29 | /// 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message. 30 | /// 31 | /// 32 | /// A user requests to change the bot‘s language, bot replies to the request with a keyboard to select the new language. 33 | /// Other users in the group don’t see the keyboard. 34 | /// 35 | public bool Selective { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ReplyKeyboardRemove.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// Upon receiving a message with this object, Telegram clients will remove the current custom keyboard 5 | /// and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. 6 | /// An exception is made for one-time keyboards that are hidden immediately after the user presses a button 7 | /// (see ReplyKeyboardMarkup). 8 | /// 9 | public class ReplyKeyboardRemove : ReplyMarkupBase 10 | { 11 | /// 12 | /// Requests clients to remove the custom keyboard. 13 | /// 14 | /// 15 | /// User will not be able to summon this keyboard. 16 | /// If you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in ReplyKeyboardMarkup. 17 | /// 18 | public bool RemoveKeyboard { get; set; } 19 | 20 | /// 21 | /// Optional. Use this parameter if you want to hide keyboard for specific users only. 22 | /// Targets: 23 | /// 1) users that are @mentioned in the text of the Message object; 24 | /// 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message. 25 | /// 26 | /// 27 | /// A user votes in a poll, bot returns confirmation message in reply to the vote and hides keyboard for that user, 28 | /// while still showing the keyboard with poll options to users who haven't voted yet. 29 | /// 30 | public bool Selective { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ReplyMarkupBase.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | public abstract class ReplyMarkupBase 4 | { 5 | // Nothing 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/ResponseParameters.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// Contains information about why a request was unsuccessfull. 5 | /// 6 | public class ResponseParameters 7 | { 8 | /// 9 | /// Optional. The group has been migrated to a supergroup with the specified identifier. 10 | /// 11 | public long? MigrateToChatId { get; set; } 12 | 13 | /// 14 | /// Optional. In case of exceeding flood control, 15 | /// the number of seconds left to wait before the request can be repeated. 16 | /// 17 | public long? RetryAfter { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Sticker.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a sticker. 5 | /// 6 | public class Sticker 7 | { 8 | /// 9 | /// Unique identifier for this file. 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Sticker width. 15 | /// 16 | public long Width { get; set; } 17 | 18 | /// 19 | /// Sticker height. 20 | /// 21 | public long Height { get; set; } 22 | 23 | /// 24 | /// Sticker thumbnail in .webp or .jpg format. 25 | /// 26 | public PhotoSize Thumb { get; set; } 27 | 28 | /// 29 | /// Optional. Emoji associated with the sticker. 30 | /// 31 | public string Emoji { get; set; } 32 | 33 | /// 34 | /// Optional. File size. 35 | /// 36 | public long? FileSize { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Update.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents an incoming update. 5 | /// 6 | public class Update 7 | { 8 | /// 9 | /// The update‘s unique identifier. Update identifiers start from a certain positive number and increase sequentially. 10 | /// This ID becomes especially handy if you’re using Webhooks, since it allows you to ignore repeated updates 11 | /// or to restore the correct update sequence, should they get out of order. 12 | /// 13 | public long UpdateId { get; set; } 14 | 15 | /// 16 | /// Optional. New incoming message of any kind — text, photo, sticker, etc. 17 | /// 18 | public Message Message { get; set; } 19 | 20 | /// 21 | /// Optional. New version of a message that is known to the bot and was edited. 22 | /// 23 | public Message EditedMessage { get; set; } 24 | 25 | /// 26 | /// Optional. New incoming channel post of any kind — text, photo, sticker, etc. 27 | /// 28 | public Message ChannelPost { get; set; } 29 | 30 | /// 31 | /// Optional. New version of a channel post that is known to the bot and was edited. 32 | /// 33 | public Message EditedChannelPost { get; set; } 34 | 35 | /// 36 | /// Optional. New incoming inline query. 37 | /// 38 | public InlineQuery InlineQuery { get; set; } 39 | 40 | /// 41 | /// Optional. The result of an inline query that was chosen by a user and sent to their chat partner. 42 | /// 43 | public ChosenInlineResult ChosenInlineResult { get; set; } 44 | 45 | /// 46 | /// Optional. New incoming callback query. 47 | /// 48 | public CallbackQuery CallbackQuery { get; set; } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/User.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a Telegram user or bot. 5 | /// 6 | public class User 7 | { 8 | /// 9 | /// Unique identifier for this user, or bot, or group chat. 10 | /// 11 | public long Id { get; set; } 12 | 13 | /// 14 | /// True, if this user is a bot. 15 | /// 16 | public bool IsBot { get; set; } 17 | 18 | /// 19 | /// User's or bot's first name. 20 | /// 21 | public string FirstName { get; set; } 22 | 23 | /// 24 | /// Optional. User's or bot's last name. 25 | /// 26 | public string LastName { get; set; } 27 | 28 | /// 29 | /// Optional. User's or bot's username. 30 | /// 31 | public string Username { get; set; } 32 | 33 | /// 34 | /// Optional. IETF language tag of the user's language. 35 | /// 36 | public string LanguageCode { get; set; } 37 | 38 | /// 39 | /// Optional. True, if this user is a Telegram Premium user. 40 | /// 41 | public bool IsPremium { get; set; } 42 | 43 | /// 44 | /// Optional. True, if this user added the bot to the attachment menu. 45 | /// 46 | public bool AddedToAttachmentMenu { get; set; } 47 | 48 | /// 49 | /// Optional. True, if the bot can be invited to groups. Returned only in getMe. 50 | /// 51 | public bool CanJoinGroups { get; set; } 52 | 53 | /// 54 | /// Optional. True, if privacy mode is disabled for the bot. Returned only in getMe. 55 | /// 56 | public bool CanReadAllGroupMessages { get; set; } 57 | 58 | /// 59 | /// Optional. True, if the bot supports inline queries. Returned only in getMe. 60 | /// 61 | public bool SupportsInlineQueries { get; set; } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/UserProfilePhotos.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represent a user's profile pictures. 5 | /// 6 | public class UserProfilePhotos 7 | { 8 | /// 9 | /// Total number of profile pictures the target user has. 10 | /// 11 | public int TotalCount { get; set; } 12 | 13 | /// 14 | /// Requested profile pictures (in up to 4 sizes each). 15 | /// 16 | public PhotoSize[][] Photos { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Venue.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a venue. 5 | /// 6 | public class Venue 7 | { 8 | /// 9 | /// Venue location. 10 | /// 11 | public Location Location { get; set; } 12 | 13 | /// 14 | /// Name of the venue. 15 | /// 16 | public string Title { get; set; } 17 | 18 | /// 19 | /// Address of the venue. 20 | /// 21 | public string Address { get; set; } 22 | 23 | /// 24 | /// Optional. Foursquare identifier of the venue. 25 | /// 26 | public string FoursquareId { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Video.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a video file. 5 | /// 6 | public class Video 7 | { 8 | /// 9 | /// Unique identifier for this file 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Video width as defined by sender 15 | /// 16 | public long Width { get; set; } 17 | 18 | /// 19 | /// Video height as defined by sender 20 | /// 21 | public long Height { get; set; } 22 | 23 | /// 24 | /// Duration of the video in seconds as defined by sender 25 | /// 26 | public long Duration { get; set; } 27 | 28 | /// 29 | /// Video thumbnail 30 | /// 31 | public PhotoSize Thumb { get; set; } 32 | 33 | /// 34 | /// Optional. Mime type of a file as defined by sender 35 | /// 36 | public string MimeType { get; set; } 37 | 38 | /// 39 | /// Optional. File size 40 | /// 41 | public long? FileSize { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/Voice.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | /// 4 | /// This object represents a voice note. 5 | /// 6 | public class Voice 7 | { 8 | /// 9 | /// Unique identifier for this file 10 | /// 11 | public string FileId { get; set; } 12 | 13 | /// 14 | /// Duration of the audio in seconds as defined by sender 15 | /// 16 | public long Duration { get; set; } 17 | 18 | /// 19 | /// Optional. Mime type of a file as defined by sender 20 | /// 21 | public string MimeType { get; set; } 22 | 23 | /// 24 | /// Optional. File size 25 | /// 26 | public long? FileSize { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/WebAppInfo.cs: -------------------------------------------------------------------------------- 1 | namespace NetTelegramBotApi.Types 2 | { 3 | public class WebAppInfo 4 | { 5 | /// 6 | /// An HTTPS URL of a Web App to be opened with additional data as specified in Initializing Web Apps. 7 | /// 8 | public string Url { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Types/WebhookInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetTelegramBotApi.Types 4 | { 5 | /// 6 | /// Contains information about the current status of a webhook. 7 | /// 8 | public class WebhookInfo 9 | { 10 | /// 11 | /// Webhook URL, may be empty if webhook is not set up. 12 | /// 13 | public string Url { get; set; } 14 | 15 | /// 16 | /// True, if a custom certificate was provided for webhook certificate checks. 17 | /// 18 | public bool HasCustomCertificate { get; set; } 19 | 20 | /// 21 | /// Number of updates awaiting delivery. 22 | /// 23 | public long PendingUpdateCount { get; set; } 24 | 25 | /// 26 | /// Optional. Unix time for the most recent error that happened when trying to deliver an update via webhook. 27 | /// 28 | public DateTimeOffset? LastErrorDate { get; set; } 29 | 30 | /// 31 | /// Optional. Error message in human-readable format for the most recent error that happened when trying to deliver an update via webhook. 32 | /// 33 | public string LastErrorMessage { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /NetTelegramBotApi/Util/UnixdateTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace NetTelegramBotApi.Util 6 | { 7 | public class UnixDateTimeConverter : JsonConverter 8 | { 9 | public override bool CanConvert(Type typeToConvert) 10 | { 11 | return typeToConvert == typeof(DateTimeOffset); 12 | } 13 | 14 | public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 15 | { 16 | var t = reader.GetInt64(); 17 | return DateTimeOffset.UnixEpoch.AddSeconds(t).ToLocalTime(); 18 | } 19 | 20 | public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetTelegramBotApi 2 | C# client library for building Telegram bot (https://core.telegram.org/bots/api) 3 | 4 | Contains strongly-types request and response classes, and transport class for sending requests and receiving results. 5 | 6 | [![NuGet](https://img.shields.io/nuget/v/NetTelegramBotApi.svg?maxAge=86400&style=flat)](https://www.nuget.org/packages/NetTelegramBotApi/) 7 | 8 | ## Usage 9 | 10 | var bot = new TelegramBot(accessToken); 11 | var me = await bot.MakeRequestAsync(new GetMe()); 12 | if (me != null) 13 | { 14 | Console.WriteLine("Me: {0} (@{1})", me.FirstName, me.Username); 15 | } 16 | 17 | See `TelegramBotDemo` project for more samples. 18 | 19 | ## Version history 20 | 21 | ### 5.4 - net8.0 22 | 23 | * Target framworks changed: `net8.0` only 24 | 25 | ### 5.3 26 | 27 | * Add ParseMode.MarkdownV2 28 | * Add SendChatAction.ChatActionEnum 29 | * Add MessageThreadId 30 | 31 | ### 5.2 32 | 33 | * User and Chat updated to actual Bot API 34 | 35 | ### 5.1 - net6.0 36 | 37 | * Target framworks changed: `net6.0` only 38 | 39 | ### 5.0.0 - net5.0 40 | 41 | * Target framworks changed: `net5.0` only 42 | * `System.Text.Json` replaces `Newtosoft.Json` 43 | 44 | ### 4.0.0 - Big update 45 | 46 | Telegram API updated up to [v2.3 (November 21, 2016)](https://core.telegram.org/bots/api-changelog#november-21-2016). Message editing, games - everything should work **except inline mode** (see below). 47 | 48 | **Breaking changes** (compared to 3.8.1): 49 | 50 | 1. `MakeRequestAsync` now throws `BotRequestException` if non-Ok response is received from server. 51 | 2. Typo fixed on `Contact` type: `PhoneNumber` was `PhoneNumbet` 52 | 3. `ReplyKeyboardHide` renamed to `ReplyKeyboardRemove` (when it had been renamed in API???) 53 | 4. Breaking changes in API 2.3: 54 | * Parameter `EditMessage` replaced with `DisableEditMessage` in `SetGameScore` 55 | * In `ReplyKeyboardRemove`: `HideKeyboard` renamed to `RemoveKeyboard` 56 | 57 | **Inline mode** 58 | 59 | [Inline mode](https://core.telegram.org/bots/api#inline-mode) needs a lot of new classes to be created. Please make PR if you wish to help. 60 | 61 | ### 3.8.1 - .NET Core RTM, netstandard1.3 62 | 63 | * Upgraded to .NET Core 1.0.0 and `netstandard1.3` 64 | 65 | ### 3.7.50926 - API updates, proxy support 66 | 67 | * Changes in Telegram API defined as [August 29, 2015](https://core.telegram.org/bots/api-changelog#august-29-2015) implemented (issue #19): 68 | * Added support for uploading certificates in `SetWebhook` 69 | * Changes in Telegram API defined as [September 7, 2015](https://core.telegram.org/bots/api-changelog#september-7-2015) implemented (issue #20): 70 | * Added `ParseMode` field to `SendMessage` request for simple markdown markup (see [FAQ](https://core.telegram.org/bots/api#using-markdown) for details) 71 | * Changes in Telegram API defined as [September 18, 2015](https://core.telegram.org/bots/api-changelog#september-18-2015) implemented (issue #21): 72 | * Bots can now download files and media sent by users, use `GetFile` request and `File` object (run demo project and send him a picture!) 73 | * Proxy support added: 74 | * Use `WebProxy` property when creating bot (see [issue #22](https://github.com/justdmitry/NetTelegramBotApi/pull/22) for sample) 75 | 76 | ### 3.6.50925 - Upgrade to vNext 77 | 78 | Project converted to Visual Studio 2015 and new project type (`xproj`). 79 | 80 | NuGet package now targets multiple runtimes: `net45`, `dnx45`, `dnx50` and `dnxcore50`. 81 | 82 | New demo console app added (`TelegramBotDemo-vNext`) for testing under `dnx451` runtime. Old demo app ('classic' console project) also available, but **Attention! Now it grabs package from nuget!** (because old-style .csproj can't reference new .xproj assemblies directly). 83 | 84 | ### 3.5.50818 - API changes 'August 15, 2015' 85 | 86 | Changes in Telegram API defined as [August 15, 2015](https://core.telegram.org/bots/api-changelog#august-15-2015) implemented (issue #13). 87 | 88 | All real changes were already implemented in `3.5.50816`, only some documenation/comments are updated in this version. 89 | 90 | 91 | ### 3.5.50816 - API changes 92 | 93 | * Changes in Telegram API defined as [July 2015](https://core.telegram.org/bots/api-changelog#july-2015) implemented (issue #7): 94 | * The `Caption` field has been **removed** from the `Video` object and added to the `Message` object instead. 95 | * `Caption` and `Duration` optional fields have been added to the `SendVideo` request. 96 | * `UserId` type in the `Contact` object **changed** to Long (was String - typo in API docs) 97 | * Changes, not [yet?] announced in Telegram API changlog: 98 | * `Performer` and `Title` optional fields have been added to `Audio` object 99 | * `Duration`, `Performer` and `Title` optional fields have been added to the `SendAudio` request 100 | * Object `Voice` added (to `Message` class) 101 | * `SendVoice` request added 102 | 103 | ### 3.4.50815 - Webhooks support, bugfixes 104 | 105 | Improvements for working via webhooks: 106 | 107 | * `SetWebhook` request added (Issue #3) 108 | * `DeserializeUpdate` method added to convert webhook POST json value to `Update` object 109 | 110 | Fixed issue #6 with sending files with non-latin characters in name. 111 | 112 | ### 3.3.50701 - DateTimeOffset instead of long 113 | 114 | `Message` properties `Date` and `ForwardDate` are now DateTimeOffset (converted to local time). 115 | 116 | ### 3.2.50628 - With sending files 117 | 118 | Methods for sending files (`SendPhoto`, `SendVideo`, etc) implemented. 119 | 120 | ### 3.1.50627 - Using HttpClient 121 | 122 | Switched to HttpClient (instead of HttpRequest): 123 | 124 | * no more `System.Web` dependency; 125 | * `MakeRequest` method is now async only, use `.Result` or `.Wait()` for synchronous calls 126 | 127 | ### 2.1.50626 - Requests hierarchy 128 | 129 | Refactored to new request model - base `RequestBase` class and one (and one async) `MakeRequest` method. 130 | 131 | Major version increased to "2", patch version set to current date. 132 | 133 | ### 1.0.1 - Initial release 134 | 135 | Response class hierarchy (`Types`), first requests. It works! 136 | -------------------------------------------------------------------------------- /Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /TelegramBotDemo-vNext/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Net.Http; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | using Microsoft.Extensions.Configuration; 7 | using NetTelegramBotApi; 8 | using NetTelegramBotApi.Requests; 9 | using NetTelegramBotApi.Types; 10 | 11 | namespace TelegramBotDemo_vNext 12 | { 13 | public class Program 14 | { 15 | private static bool stopMe = false; 16 | 17 | public static void Main(string[] args) 18 | { 19 | var config = new ConfigurationBuilder() 20 | .SetBasePath(System.IO.Directory.GetCurrentDirectory()) 21 | .AddJsonFile("config.json") 22 | .Build(); 23 | var accessToken = config["AccessToken"]; 24 | 25 | Console.WriteLine("Starting your bot..."); 26 | Console.WriteLine(); 27 | 28 | var t = Task.Run(() => RunBot(accessToken)); 29 | t.ContinueWith(task => { Console.WriteLine(t.Exception?.GetBaseException()); }); 30 | 31 | Console.ReadLine(); 32 | 33 | stopMe = true; 34 | } 35 | 36 | public static void RunBot(string accessToken) 37 | { 38 | var bot = new TelegramBot(accessToken, new HttpClient()); 39 | 40 | var me = bot.MakeRequestAsync(new GetMe()).Result; 41 | if (me == null) 42 | { 43 | Console.WriteLine("GetMe() FAILED. Do you forget to add your AccessToken to config.json?"); 44 | Console.WriteLine("(Press ENTER to quit)"); 45 | Console.ReadLine(); 46 | return; 47 | } 48 | Console.OutputEncoding = System.Text.Encoding.UTF8; 49 | Console.WriteLine("{0} (@{1}) connected!", me.FirstName, me.Username); 50 | 51 | Console.WriteLine(); 52 | Console.WriteLine("Find @{0} in Telegram and send him a message - it will be displayed here", me.Username); 53 | Console.WriteLine("(Press ENTER to stop listening and quit)"); 54 | Console.WriteLine(); 55 | 56 | string uploadedPhotoId = null; 57 | string uploadedDocumentId = null; 58 | long offset = 0; 59 | while (!stopMe) 60 | { 61 | var updates = bot.MakeRequestAsync(new GetUpdates() { Offset = offset }).Result; 62 | if (updates != null) 63 | { 64 | foreach (var update in updates) 65 | { 66 | offset = update.UpdateId + 1; 67 | if (update.Message == null) 68 | { 69 | continue; 70 | } 71 | var from = update.Message.From; 72 | var text = update.Message.Text; 73 | var photos = update.Message.Photo; 74 | var contact = update.Message.Contact; 75 | var location = update.Message.Location; 76 | Console.WriteLine( 77 | "Msg from {0} {1} ({2}) at {4}: {3}", 78 | from.FirstName, 79 | from.LastName, 80 | from.Username, 81 | text, 82 | update.Message.Date); 83 | 84 | if (photos != null) 85 | { 86 | var webClient = new HttpClient(); 87 | foreach (var photo in photos) 88 | { 89 | Console.WriteLine(" New image arrived: size {1}x{2} px, {3} bytes, id: {0}", photo.FileId, photo.Height, photo.Width, photo.FileSize); 90 | var file = bot.MakeRequestAsync(new GetFile(photo.FileId)).Result; 91 | var tempFileName = System.IO.Path.GetTempFileName(); 92 | var bytes = webClient.GetByteArrayAsync(file.FileDownloadUrl).Result; 93 | System.IO.File.WriteAllBytes(tempFileName, bytes); 94 | Console.WriteLine(" Saved to {0}", tempFileName); 95 | } 96 | } 97 | if (contact != null) 98 | { 99 | var req = new SendContact(update.Message.Chat.Id, contact.PhoneNumber, contact.FirstName) 100 | { 101 | LastName = contact.LastName 102 | }; 103 | bot.MakeRequestAsync(req).Wait(); 104 | } 105 | if (location != null) 106 | { 107 | var req = new SendLocation(update.Message.Chat.Id, location.Latitude, location.Longitude); 108 | bot.MakeRequestAsync(req).Wait(); 109 | } 110 | 111 | if (string.IsNullOrEmpty(text)) 112 | { 113 | continue; 114 | } 115 | if (text == "/photo") 116 | { 117 | if (uploadedPhotoId == null) 118 | { 119 | var reqAction = new SendChatAction(update.Message.Chat.Id, "upload_photo"); 120 | bot.MakeRequestAsync(reqAction).Wait(); 121 | System.Threading.Thread.Sleep(500); 122 | using var photoData = typeof(Program).GetTypeInfo().Assembly.GetManifestResourceStream("TelegramBotDemo-vNext.t_logo.png"); 123 | var req = new SendPhoto(update.Message.Chat.Id, new FileToSend(photoData, "Telegram_logo.png")) 124 | { 125 | Caption = "Telegram_logo.png" 126 | }; 127 | var msg = bot.MakeRequestAsync(req).Result; 128 | uploadedPhotoId = msg.Photo.Last().FileId; 129 | } 130 | else 131 | { 132 | var req = new SendPhoto(update.Message.Chat.Id, new FileToSend(uploadedPhotoId)) 133 | { 134 | Caption = "Resending photo id=" + uploadedPhotoId 135 | }; 136 | bot.MakeRequestAsync(req).Wait(); 137 | } 138 | continue; 139 | } 140 | if (text == "/doc") 141 | { 142 | if (uploadedDocumentId == null) 143 | { 144 | var reqAction = new SendChatAction(update.Message.Chat.Id, "upload_document"); 145 | bot.MakeRequestAsync(reqAction).Wait(); 146 | System.Threading.Thread.Sleep(500); 147 | using var docData = typeof(Program).GetTypeInfo().Assembly.GetManifestResourceStream("TelegramBotDemo-vNext.Telegram_Bot_API.htm"); 148 | var req = new SendDocument(update.Message.Chat.Id, new FileToSend(docData, "Telegram_Bot_API.htm")); 149 | var msg = bot.MakeRequestAsync(req).Result; 150 | uploadedDocumentId = msg.Document.FileId; 151 | } 152 | else 153 | { 154 | var req = new SendDocument(update.Message.Chat.Id, new FileToSend(uploadedDocumentId)); 155 | bot.MakeRequestAsync(req).Wait(); 156 | } 157 | continue; 158 | } 159 | if (text == "/docutf8") 160 | { 161 | var reqAction = new SendChatAction(update.Message.Chat.Id, "upload_document"); 162 | bot.MakeRequestAsync(reqAction).Wait(); 163 | System.Threading.Thread.Sleep(500); 164 | using var docData = typeof(Program).GetTypeInfo().Assembly.GetManifestResourceStream("TelegramBotDemo-vNext.Пример_UTF8_filename.txt"); 165 | var req = new SendDocument(update.Message.Chat.Id, new FileToSend(docData, "Пример_UTF8_filename.txt")); 166 | var msg = bot.MakeRequestAsync(req).Result; 167 | uploadedDocumentId = msg.Document.FileId; 168 | continue; 169 | } 170 | if (text == "/help") 171 | { 172 | var keyb = new ReplyKeyboardMarkup() 173 | { 174 | Keyboard = new[] { 175 | new[] { new KeyboardButton("/photo"), new KeyboardButton("/doc"), new KeyboardButton("/docutf8") }, 176 | new[] { new KeyboardButton("/contact") { RequestContact = true }, new KeyboardButton("/location") { RequestLocation = true } }, 177 | new[] { new KeyboardButton("/help") } 178 | }, 179 | OneTimeKeyboard = true, 180 | ResizeKeyboard = true 181 | }; 182 | var reqAction = new SendMessage(update.Message.Chat.Id, "Here is all my commands") { ReplyMarkup = keyb }; 183 | bot.MakeRequestAsync(reqAction).Wait(); 184 | continue; 185 | } 186 | if (text == "/longmsg") 187 | { 188 | var msg = new string('X', 10240); 189 | bot.MakeRequestAsync(new SendMessage(update.Message.Chat.Id, msg)).Wait(); 190 | continue; 191 | } 192 | if (update.Message.Text.Length % 2 == 0) 193 | { 194 | bot.MakeRequestAsync(new SendMessage( 195 | update.Message.Chat.Id, 196 | "You wrote: \r\n" + update.Message.Text.MarkdownEncode()) 197 | { 198 | ParseMode = SendMessage.ParseModes.Markdown 199 | }).Wait(); 200 | } 201 | else 202 | { 203 | bot.MakeRequestAsync(new ForwardMessage(update.Message.Chat.Id, update.Message.Chat.Id, update.Message.MessageId)).Wait(); 204 | } 205 | } 206 | } 207 | } 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /TelegramBotDemo-vNext/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Default": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /TelegramBotDemo-vNext/TelegramBotDemo-vNext.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | TelegramBotDemo-vNext Console Application 5 | Dmitry 6 | net8.0 7 | TelegramBotDemo-vNext 8 | Exe 9 | TelegramBotDemo-vNext 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TelegramBotDemo-vNext/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "AccessToken": "12345:abcdef-bla-bla-bla" 3 | } 4 | -------------------------------------------------------------------------------- /TelegramBotDemo-vNext/t_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdmitry/NetTelegramBotApi/ae456458fa5d6c8ab89648230b032bc5e03ddeda/TelegramBotDemo-vNext/t_logo.png -------------------------------------------------------------------------------- /TelegramBotDemo-vNext/Пример_UTF8_filename.txt: -------------------------------------------------------------------------------- 1 | Eng: 2 | This is sample file with non-latin name (validating issue #5) 3 | 4 | Rus: 5 | Это пример файла с кириллицей в названии (проверяем issue #5) -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: N{build} 2 | image: Visual Studio 2019 3 | before_build: 4 | - cmd: dotnet restore 5 | build: 6 | verbosity: minimal 7 | test_script: 8 | - cmd: dotnet test NetTelegramBotApi.Tests/NetTelegramBotApi.Tests.csproj 9 | -------------------------------------------------------------------------------- /package-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdmitry/NetTelegramBotApi/ae456458fa5d6c8ab89648230b032bc5e03ddeda/package-icon.gif -------------------------------------------------------------------------------- /package-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdmitry/NetTelegramBotApi/ae456458fa5d6c8ab89648230b032bc5e03ddeda/package-icon.png --------------------------------------------------------------------------------