From 99c84a566ac636dbd8501c136e8514c43adf2ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B0=D0=B9=D0=BA=D0=B8=D0=BD=20=D0=95=D0=B3=D0=BE?= =?UTF-8?q?=D1=80?= Date: Sun, 27 Oct 2024 11:42:43 +0300 Subject: [PATCH] =?UTF-8?q?new/=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=BE=D1=82=D0=B2=D0=B5=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BD=D0=B0=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20new/=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D1=80=D0=B8=D0=BA=D1=80=D0=B5?= =?UTF-8?q?=D0=BF=D0=BB=D1=8F=D1=82=D1=8C=20=D0=BA=D0=BB=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=B0=D1=82=D1=83=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Telegram bots/Chat.cs | 36 +++---- Telegram bots/Keyboards/IKeyboard.cs | 13 +++ Telegram bots/Keyboards/IKeyboardButton.cs | 19 ++++ Telegram bots/Keyboards/InlineKeyboard.cs | 23 ++++ .../Keyboards/InlineKeyboardButton.cs | 48 +++++++++ Telegram bots/Keyboards/KeyboardButton.cs | 21 ++++ Telegram bots/Keyboards/ReplyKeyboard.cs | 26 +++++ .../Keyboards/ReplyKeyboardRemove.cs | 25 +++++ Telegram bots/Message.cs | 65 ++++++++---- Telegram bots/ReplyParameters.cs | 100 ++++++++++++++++++ Telegram bots/Telegram bots.csproj | 2 +- Telegram bots/TelegramBot.cs | 87 +++++++++------ Telegram bots/Tst.cs | 24 +++-- Telegram bots/Update.cs | 21 ++-- Telegram bots/User.cs | 35 +++--- 15 files changed, 436 insertions(+), 109 deletions(-) create mode 100644 Telegram bots/Keyboards/IKeyboard.cs create mode 100644 Telegram bots/Keyboards/IKeyboardButton.cs create mode 100644 Telegram bots/Keyboards/InlineKeyboard.cs create mode 100644 Telegram bots/Keyboards/InlineKeyboardButton.cs create mode 100644 Telegram bots/Keyboards/KeyboardButton.cs create mode 100644 Telegram bots/Keyboards/ReplyKeyboard.cs create mode 100644 Telegram bots/Keyboards/ReplyKeyboardRemove.cs create mode 100644 Telegram bots/ReplyParameters.cs diff --git a/Telegram bots/Chat.cs b/Telegram bots/Chat.cs index b1e38ed..62d0440 100644 --- a/Telegram bots/Chat.cs +++ b/Telegram bots/Chat.cs @@ -1,4 +1,5 @@ -using System.Text.Json; +using System.Text; +using System.Text.Json; namespace Telegram_bots { @@ -118,38 +119,35 @@ public static Chat FromJSON(string jsonString) } #endregion - /// - /// Turns it into a string - /// - /// A string representing the chat + /// public override string ToString() { - string str = string.Empty; - str += "Id: "; - str += Id; - str += ", Type: "; - str += Type; + StringBuilder builder = new(); + builder.Append("Id: "); + builder.Append(Id); + builder.Append(", Type: "); + builder.Append(Type); if (Title != null) { - str += ", Title: "; - str += Title; + builder.Append(", Title: "); + builder.Append(Title); } if (FirstName != null) { - str += ", First name: "; - str += FirstName; + builder.Append(", First name: "); + builder.Append(FirstName); } if (LastName != null) { - str += ", Last name: "; - str += LastName; + builder.Append(", Last name: "); + builder.Append(LastName); } if (Username != null) { - str += ", Username: "; - str += Username; + builder.Append(", Username: "); + builder.Append(Username); } - return str; + return builder.ToString(); } } diff --git a/Telegram bots/Keyboards/IKeyboard.cs b/Telegram bots/Keyboards/IKeyboard.cs new file mode 100644 index 0000000..4c5a7f1 --- /dev/null +++ b/Telegram bots/Keyboards/IKeyboard.cs @@ -0,0 +1,13 @@ +namespace Telegram_bots.Keyboards +{ + /// + /// Keyboard + /// + public interface IKeyboard + { + /// + /// Keyboard's buttons + /// + IKeyboardButton[][] Keyboard { get; set; } + } +} \ No newline at end of file diff --git a/Telegram bots/Keyboards/IKeyboardButton.cs b/Telegram bots/Keyboards/IKeyboardButton.cs new file mode 100644 index 0000000..9d6a789 --- /dev/null +++ b/Telegram bots/Keyboards/IKeyboardButton.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; +using Telegram_bots.Keyboards; + +namespace Telegram_bots +{ + /// + /// Keyboard's button + /// + [JsonDerivedType(typeof(InlineKeyboardButton))] + [JsonDerivedType(typeof(KeyboardButton))] + public interface IKeyboardButton + { + /// + /// Button's text + /// + [JsonPropertyName("text")] + string Text { get; set; } + } +} \ No newline at end of file diff --git a/Telegram bots/Keyboards/InlineKeyboard.cs b/Telegram bots/Keyboards/InlineKeyboard.cs new file mode 100644 index 0000000..66024cb --- /dev/null +++ b/Telegram bots/Keyboards/InlineKeyboard.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Text.Json.Serialization; +using System.Xml.Serialization; + +namespace Telegram_bots.Keyboards +{ + /// + /// Inline keyboard + /// + /// + /// Create an inline keyboard + /// + /// Keyboard's buttons + [Serializable] + public class InlineKeyboard(InlineKeyboardButton[][] buttons) : IKeyboard + { + /// + /// + /// + [JsonPropertyName("inline_keyboard")] + public IKeyboardButton[][] Keyboard { get; set; } = buttons; + } +} diff --git a/Telegram bots/Keyboards/InlineKeyboardButton.cs b/Telegram bots/Keyboards/InlineKeyboardButton.cs new file mode 100644 index 0000000..8591603 --- /dev/null +++ b/Telegram bots/Keyboards/InlineKeyboardButton.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Telegram_bots +{ + /// + /// The inline keyboard button + /// + [Serializable] + public class InlineKeyboardButton : IKeyboardButton + { + /// + /// + /// + [JsonPropertyName("text")] + public string Text { get; set; } + /// + /// CallbackData of the inline keyboard buttons + /// + [JsonPropertyName("callback_data")] + public string CallbackData { get; set; } + + /// + /// Create an inline keyboard button + /// + /// Button's text + /// CallbackData of the inline keyboard buttons + public InlineKeyboardButton(string text, string callbackData) + { + Text = text; + CallbackData = callbackData; + } + + /// + /// Create an inline keyboard button + /// + /// Button's text + public InlineKeyboardButton(string text) + { + Text = text; + CallbackData = text; + } + } +} diff --git a/Telegram bots/Keyboards/KeyboardButton.cs b/Telegram bots/Keyboards/KeyboardButton.cs new file mode 100644 index 0000000..c45ad24 --- /dev/null +++ b/Telegram bots/Keyboards/KeyboardButton.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; + +namespace Telegram_bots.Keyboards +{ + /// + /// Keyboard button + /// + /// + /// Create a keyboard button + /// + /// Button's text + [Serializable] + public class KeyboardButton(string text) : IKeyboardButton + { + /// + /// + /// + [JsonPropertyName("text")] + public string Text { get; set; } = text; + } +} \ No newline at end of file diff --git a/Telegram bots/Keyboards/ReplyKeyboard.cs b/Telegram bots/Keyboards/ReplyKeyboard.cs new file mode 100644 index 0000000..f2886f0 --- /dev/null +++ b/Telegram bots/Keyboards/ReplyKeyboard.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Telegram_bots.Keyboards +{ + /// + /// Keyboard + /// + /// + /// Create a keyboard + /// + /// Keyboard's buttons + [Serializable] + public class ReplyKeyboard(KeyboardButton[][] buttons) : IKeyboard + { + /// + /// + /// + [JsonPropertyName("keyboard")] + public IKeyboardButton[][] Keyboard { get; set; } = buttons; + } +} diff --git a/Telegram bots/Keyboards/ReplyKeyboardRemove.cs b/Telegram bots/Keyboards/ReplyKeyboardRemove.cs new file mode 100644 index 0000000..98aed92 --- /dev/null +++ b/Telegram bots/Keyboards/ReplyKeyboardRemove.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Telegram_bots.Keyboards +{ + /// + /// Remove the keyboard + /// + [Serializable] + public class ReplyKeyboardRemove : IKeyboard + { + /// It's nothing + [JsonIgnore] + public IKeyboardButton[][] Keyboard { get; set; } = [[]]; + /// + /// Should I remove the keyboard or not? + /// + [JsonPropertyName("remove_keyboard")] + public bool RemoveKeyboard { get; set; } = true; + } +} diff --git a/Telegram bots/Message.cs b/Telegram bots/Message.cs index bf44fa3..e2e0bbe 100644 --- a/Telegram bots/Message.cs +++ b/Telegram bots/Message.cs @@ -1,4 +1,5 @@ -using System.Text.Json; +using System.Text; +using System.Text.Json; namespace Telegram_bots { @@ -21,13 +22,21 @@ public class Message public required Chat Chat { get; set; } /// - /// The text of the message + /// The Text of the message /// public string? Text { get; set; } /// /// The sender of the message /// public User? From { get; set; } + /// + /// Parameters for responding to a message + /// + public ReplyParameters? ReplyParameters { get; set; } + /// + /// The message that this message responds to + /// + public Message? ReplyMessage { get; set; } #region bool Equals(object? obj) /// @@ -72,6 +81,14 @@ public static Message FromJSON(JsonDocument jsonDocument) { message.From = User.FromJSON(from); } + if (json.TryGetProperty("reply_to_message", out JsonElement replyMessage)) + { + message.ReplyMessage = FromJSON(replyMessage); + } + if (json.TryGetProperty("reply_parameters", out JsonElement replyParameters)) + { + message.ReplyParameters = ReplyParameters.FromJSON(replyParameters); + } return message; } @@ -95,31 +112,41 @@ public static Message FromJSON(string jsonString) } #endregion - /// - /// Turns it into a string - /// - /// The string representing the message + /// public override string ToString() { - string str = "Id: "; - str += Id; - str += ", Date: "; - str += Datetime; - str += ", Chat: ("; - str += Chat; - str += ")"; + StringBuilder builder = new(); + builder.Append("Id: "); + builder.Append(Id); + builder.Append(", Date: "); + builder.Append(Datetime); + builder.Append(", Chat: ("); + builder.Append(Chat); + builder.Append(')'); if (Text != null) { - str += ", Text: "; - str += Text; + builder.Append(", Text: "); + builder.Append(Text); } if (From != null) { - str += ", From: ("; - str += From; - str += ")"; + builder.Append(", From: ("); + builder.Append(From); + builder.Append(')'); + } + if (ReplyParameters != null) + { + builder.Append(", Reply parameters: ("); + builder.Append(ReplyParameters); + builder.Append(')'); + } + if (ReplyMessage != null) + { + builder.Append(", Reply to message: ("); + builder.Append(ReplyMessage); + builder.Append(')'); } - return str; + return builder.ToString(); } /// diff --git a/Telegram bots/ReplyParameters.cs b/Telegram bots/ReplyParameters.cs new file mode 100644 index 0000000..7ca691d --- /dev/null +++ b/Telegram bots/ReplyParameters.cs @@ -0,0 +1,100 @@ +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Telegram_bots +{ + /// + /// Describes reply parameters for the message that is being sent. + /// + [Serializable] + public class ReplyParameters + { + /// + /// Id to reply to the message + /// + [JsonPropertyName("message_id")] + public long MessageId { get; init; } + + /// + /// The chat_id where the reply message is located + /// + [JsonPropertyName("chat_id")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public long? ChatId { get; set; } + + /// + /// Creates empty parameters for responding to a message + /// + public ReplyParameters() + { + MessageId = 0; + ChatId = null; + } + /// + /// Creates parameters for responding to a message + /// + /// The message that needs to be answered + public ReplyParameters(Message message) + { + MessageId = message.Id; + ChatId = message.Chat.Id; + } + + #region FromJSON + /// + /// Create a ReplyParameters from a JsonDocument + /// + /// JsonDocument + /// ReplyParameters + public static ReplyParameters FromJSON(JsonDocument jsonDocument) + { + JsonElement json = jsonDocument.RootElement; + + ReplyParameters replyParameters = new() + { + MessageId = json.GetProperty("message_id").GetInt64(), + }; + + if (json.TryGetProperty("chat_id", out JsonElement chatId)) + { + replyParameters.ChatId = chatId.GetInt64(); + } + + return replyParameters; + } + /// + /// Create a ReplyParameters from a JsonElement + /// + /// Root JsonElement + /// ReplyParameters + public static ReplyParameters FromJSON(JsonElement rootJsonElement) + { + return FromJSON(rootJsonElement.GetRawText()); + } + /// + /// Create a ReplyParameters from a json string + /// + /// Json string + /// ReplyParameters + public static ReplyParameters FromJSON(string jsonString) + { + return FromJSON(JsonDocument.Parse(jsonString)); + } + #endregion + + /// + public override string ToString() + { + StringBuilder builder = new(); + builder.Append("Message id: "); + builder.Append(MessageId); + if (ChatId != null) + { + builder.Append(", Chat id: "); + builder.Append(ChatId); + } + return builder.ToString(); + } + } +} diff --git a/Telegram bots/Telegram bots.csproj b/Telegram bots/Telegram bots.csproj index 2d54e88..deb2cd4 100644 --- a/Telegram bots/Telegram bots.csproj +++ b/Telegram bots/Telegram bots.csproj @@ -5,7 +5,7 @@ Telegram_bots enable enable - True + False False Exe MyTGBot.Tst diff --git a/Telegram bots/TelegramBot.cs b/Telegram bots/TelegramBot.cs index 2d8f1a3..d6be8ed 100644 --- a/Telegram bots/TelegramBot.cs +++ b/Telegram bots/TelegramBot.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text.Json; -using System.Threading.Tasks; +using System.Text.Json; namespace Telegram_bots { @@ -15,7 +11,7 @@ public class TelegramBot : IDisposable private bool disposedValue; /// - /// Token for the bot + /// token for the bot /// protected readonly string Token = string.Empty; @@ -39,7 +35,7 @@ public class TelegramBot : IDisposable /// /// A constructor for creating a bot /// - /// Token for the bot + /// token for the bot /// Called if you entered the wrong token /// /// @@ -49,12 +45,12 @@ public class TelegramBot : IDisposable /// } /// /// - public TelegramBot(string Token) + public TelegramBot(string token) { - this.Token = Token; + Token = token; httpClient = new() { - BaseAddress = new Uri("https://api.telegram.org/bot" + Token + "/") + BaseAddress = new Uri("https://api.telegram.org/bot" + token + "/") }; JsonDocument me = GetMe().Result; @@ -85,25 +81,35 @@ public async Task GetMe() /// /// Sends a message /// - /// The text of the message - /// The chat_id to which the message will be sent. Do not use if you want to use the chat_id from the latest update + /// The Text of the message + /// The chat_id to which the message will be sent. Do not use if you want to use the chat_id from the latest update + /// Parameters for responding to a message + /// Keyboard /// It is thrown if one of the arguments is null /// It is thrown if an incorrect request was made /// The message that was sent - public async Task SendMessage(string Text, long ChatId = 0) + public async Task SendMessage(object messageText, + long? chatId = null, + ReplyParameters? replyParameters = null, + Keyboards.IKeyboard? keyboard = null) { - ArgumentNullException.ThrowIfNull(Text); - ArgumentNullException.ThrowIfNull(ChatId); - - if (ChatId == 0) - { - ChatId = lastChatId; - } + string? text = messageText.ToString(); + ArgumentNullException.ThrowIfNull(text); + chatId ??= lastChatId; Dictionary contentData = []; - contentData["text"] = Text.ToString(); - contentData["chat_id"] = ChatId.ToString(); + contentData["text"] = text.ToString(); + contentData["chat_id"] = chatId.ToString(); + if (replyParameters != null) + { + contentData["reply_parameters"] = JsonSerializer.Serialize(replyParameters); + } + if (keyboard != null) + { + contentData["reply_markup"] = JsonSerializer.Serialize(keyboard, keyboard.GetType()); + Console.WriteLine(contentData["reply_markup"]); + } HttpContent content = new FormUrlEncodedContent(contentData); @@ -172,11 +178,34 @@ public async Task StartPolling() public event UpdateHandler? OnUpdate; #endregion - #region IDisposable implementation + #region +, - operators + /// + /// Add the event function + /// + /// Telegram bot + /// Function + /// Telegram bot + public static TelegramBot operator +(TelegramBot bot, UpdateHandler function) + { + bot.OnUpdate += function; + return bot; + } + /// - /// Release the resources occupied by the bot + /// Remove the event function /// - /// Release managed resources + /// Telegram bot + /// Function + /// Telegram bot + public static TelegramBot operator -(TelegramBot bot, UpdateHandler function) + { + bot.OnUpdate -= function; + return bot; + } + #endregion + + #region IDisposable implementation + /// protected virtual void Dispose(bool disposing) { if (!disposedValue) @@ -191,17 +220,13 @@ protected virtual void Dispose(bool disposing) } } - /// - /// Release unmanaged resources occupied by the bot - /// + /// ~TelegramBot() { Dispose(disposing: false); } - /// - /// Release the resources occupied by the bot - /// + /// public void Dispose() { Dispose(disposing: true); diff --git a/Telegram bots/Tst.cs b/Telegram bots/Tst.cs index e305c9f..7d44765 100644 --- a/Telegram bots/Tst.cs +++ b/Telegram bots/Tst.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Telegram_bots; +using Telegram_bots; +using Telegram_bots.Keyboards; namespace MyTGBot { @@ -11,19 +7,27 @@ class Tst { public static async Task Main(string[] args) { - using TelegramBot bot = new(args[0]); + TelegramBot bot = new(args[0]); - bot.OnUpdate += Update; + bot += Update; await bot.StartPolling(); + + Console.ReadLine(); } - public static async Task Update(Update update, TelegramBot bot) + private static async Task Update(Update update, TelegramBot bot) { if (update.Message != null) { if (update.Message.Text != null) { - await bot.SendMessage(update.Message.Text); + if (update.Message.ReplyMessage != null) + { + if (update.Message.ReplyMessage.Text != null) + { + + } + } } } } diff --git a/Telegram bots/Update.cs b/Telegram bots/Update.cs index 58d8355..b6bec6a 100644 --- a/Telegram bots/Update.cs +++ b/Telegram bots/Update.cs @@ -1,4 +1,5 @@ -using System.Text.Json; +using System.Text; +using System.Text.Json; namespace Telegram_bots { @@ -77,21 +78,19 @@ public static Update FromJSON(string jsonString) } #endregion - /// - /// Turns it into a string - /// - /// The line representing the update + /// public override string ToString() { - string str = "Update id: "; - str += UpdateId; + StringBuilder builder = new(); + builder.Append("Update id: "); + builder.Append(UpdateId); if (Message != null) { - str += ", Message: ("; - str += Message; - str += ")"; + builder.Append(", Message: ("); + builder.Append(Message); + builder.Append(')'); } - return str; + return builder.ToString(); } /// diff --git a/Telegram bots/User.cs b/Telegram bots/User.cs index 8da5bb0..96c231b 100644 --- a/Telegram bots/User.cs +++ b/Telegram bots/User.cs @@ -1,4 +1,5 @@ -using System.Text.Json; +using System.Text; +using System.Text.Json; namespace Telegram_bots { @@ -85,34 +86,32 @@ public static User FromJSON(string jsonString) } #endregion - /// - /// Turns it into a string - /// - /// The line representing the user + /// public override string ToString() { - string str = "Id: "; - str += Id; - str += ", Is bot: "; - str += IsBot; - str += ", First name: "; - str += FirstName; + StringBuilder builder = new(); + builder.Append("Id: "); + builder.Append(Id); + builder.Append(", Is bot: "); + builder.Append(IsBot); + builder.Append(", First name: "); + builder.Append(FirstName); if (LastName != null) { - str += ", Last name: "; - str += LastName; + builder.Append(", Last name: "); + builder.Append(LastName); } if (Username != null) { - str += ", Username: "; - str += Username; + builder.Append(", Username: "); + builder.Append(Username); } if (IsPremium != null) { - str += ", Is premium: "; - str += IsPremium; + builder.Append(", Is premium: "); + builder.Append(IsPremium); } - return str; + return builder.ToString(); } }