diff --git a/Examples/EFCoreBot/EFCoreBot.csproj b/Examples/EFCoreBot/EFCoreBot.csproj index 885fc87..1337c26 100644 --- a/Examples/EFCoreBot/EFCoreBot.csproj +++ b/Examples/EFCoreBot/EFCoreBot.csproj @@ -8,12 +8,12 @@ - - + + - + diff --git a/TelegramBotBase.Extensions.Images.IronSoftware/TelegramBotBase.Extensions.Images.IronSoftware.csproj b/TelegramBotBase.Extensions.Images.IronSoftware/TelegramBotBase.Extensions.Images.IronSoftware.csproj index df94a01..3f0707d 100644 --- a/TelegramBotBase.Extensions.Images.IronSoftware/TelegramBotBase.Extensions.Images.IronSoftware.csproj +++ b/TelegramBotBase.Extensions.Images.IronSoftware/TelegramBotBase.Extensions.Images.IronSoftware.csproj @@ -14,7 +14,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/TelegramBotBase.Extensions.Serializer.Database.MSSQL/TelegramBotBase.Extensions.Serializer.Database.MSSQL.csproj b/TelegramBotBase.Extensions.Serializer.Database.MSSQL/TelegramBotBase.Extensions.Serializer.Database.MSSQL.csproj index 7acb0e4..1243327 100644 --- a/TelegramBotBase.Extensions.Serializer.Database.MSSQL/TelegramBotBase.Extensions.Serializer.Database.MSSQL.csproj +++ b/TelegramBotBase.Extensions.Serializer.Database.MSSQL/TelegramBotBase.Extensions.Serializer.Database.MSSQL.csproj @@ -16,7 +16,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/TelegramBotBase.Extensions.Serializer.Database.PostgreSql/TelegramBotBase.Extensions.Serializer.Database.PostgreSql.csproj b/TelegramBotBase.Extensions.Serializer.Database.PostgreSql/TelegramBotBase.Extensions.Serializer.Database.PostgreSql.csproj index ce2b6ef..565075a 100644 --- a/TelegramBotBase.Extensions.Serializer.Database.PostgreSql/TelegramBotBase.Extensions.Serializer.Database.PostgreSql.csproj +++ b/TelegramBotBase.Extensions.Serializer.Database.PostgreSql/TelegramBotBase.Extensions.Serializer.Database.PostgreSql.csproj @@ -22,7 +22,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/TelegramBotBase/Base/MessageResult.cs b/TelegramBotBase/Base/MessageResult.cs index 11e33d7..0b86362 100644 --- a/TelegramBotBase/Base/MessageResult.cs +++ b/TelegramBotBase/Base/MessageResult.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; @@ -9,16 +10,33 @@ namespace TelegramBotBase.Base; public class MessageResult : ResultBase { - internal MessageResult() - { - } - public MessageResult(Update update) { UpdateData = update; + + init(); } - public Update UpdateData { get; set; } + void init() + { + IsAction = UpdateData.CallbackQuery != null; + + IsBotCommand = Message.Entities?.Any(a => a.Type == MessageEntityType.BotCommand) ?? false; + + if (!IsBotCommand) + return; + + BotCommand = MessageText.Split(' ')[0]; + + IsBotGroupCommand = BotCommand.Contains("@"); + + if (IsBotGroupCommand) + { + BotCommand = BotCommand.Substring(0, BotCommand.LastIndexOf('@')); + } + } + + public Update UpdateData { get; private set; } /// /// Returns the Device/ChatId @@ -55,12 +73,17 @@ public class MessageResult : ResultBase /// /// Is this an action ? (i.e. button click) /// - public bool IsAction => UpdateData.CallbackQuery != null; + public bool IsAction { get; private set; } /// /// Is this a command ? Starts with a slash '/' and a command /// - public bool IsBotCommand => MessageText.StartsWith("/"); + public bool IsBotCommand { get; private set; } + + /// + /// Is this a bot command sent from a group via @BotId ? + /// + public bool IsBotGroupCommand { get; private set; } /// /// Returns a List of all parameters which has been sent with the command itself (i.e. /start 123 456 789 => @@ -83,18 +106,7 @@ public class MessageResult : ResultBase /// /// Returns just the command (i.e. /start 1 2 3 => /start) /// - public string BotCommand - { - get - { - if (!IsBotCommand) - { - return null; - } - - return MessageText.Split(' ')[0]; - } - } + public string BotCommand { get; private set; } /// /// Returns if this message will be used on the first form or not. diff --git a/TelegramBotBase/BotBase.cs b/TelegramBotBase/BotBase.cs index a481d6d..5a50823 100644 --- a/TelegramBotBase/BotBase.cs +++ b/TelegramBotBase/BotBase.cs @@ -8,6 +8,7 @@ using Telegram.Bot.Types; using TelegramBotBase.Args; using TelegramBotBase.Base; using TelegramBotBase.Enums; +using TelegramBotBase.Exceptions; using TelegramBotBase.Interfaces; using TelegramBotBase.Sessions; using Console = TelegramBotBase.Tools.Console; @@ -139,6 +140,13 @@ public sealed class BotBase mr.IsFirstHandler = false; } while (ds.FormSwitched && i < GetSetting(ESettings.NavigationMaximum, 10)); } + catch (InvalidServiceProviderConfiguration ex) + { + var ds = Sessions.GetSession(e.DeviceId); + OnException(new SystemExceptionEventArgs(e.Message.Text, e.DeviceId, ds, ex)); + + throw; + } catch (Exception ex) { var ds = Sessions.GetSession(e.DeviceId); @@ -189,13 +197,10 @@ public sealed class BotBase /// Contains the device/chat id of the device to update. public async Task InvokeMessageLoop(long deviceId) { - var mr = new MessageResult + var mr = new MessageResult(new Update { - UpdateData = new Update - { - Message = new Message() - } - }; + Message = new Message() + }); await InvokeMessageLoop(deviceId, mr); } @@ -260,7 +265,7 @@ public sealed class BotBase { foreach (var scope in BotCommandScopes) { - if (scope.Value.Any(a => "/" + a.Command == command)) + if (scope.Value.Any(a => Constants.Telegram.BotCommandIndicator + a.Command == command)) { return true; } diff --git a/TelegramBotBase/Commands/Extensions.cs b/TelegramBotBase/Commands/Extensions.cs index 6a19ce1..e5b186d 100644 --- a/TelegramBotBase/Commands/Extensions.cs +++ b/TelegramBotBase/Commands/Extensions.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Telegram.Bot.Types; @@ -20,6 +21,16 @@ public static class Extensions scope = BotCommandScope.Default(); } + if (string.IsNullOrEmpty(command)) + { + throw new ArgumentNullException(nameof(command), $"{nameof(command)} parameter can not be null or empty"); + } + + if(command.StartsWith(Constants.Telegram.BotCommandIndicator)) + { + throw new ArgumentException($"{nameof(command)} parameter does not have to start with a slash, please remove.", $"{nameof(command)}"); + } + var item = cmds.FirstOrDefault(a => a.Key.Type == scope.Type); if (item.Value != null) diff --git a/TelegramBotBase/Constants/Telegram.cs b/TelegramBotBase/Constants/Telegram.cs index a2837d7..10b0eec 100644 --- a/TelegramBotBase/Constants/Telegram.cs +++ b/TelegramBotBase/Constants/Telegram.cs @@ -16,4 +16,15 @@ public static class Telegram public const int MaxReplyKeyboardCols = 12; public const int MessageDeletionsPerSecond = 30; + + /// + /// The maximum length of callback data. Will raise an exception of it exceeds it. + /// + public const int MaxCallBackDataBytes = 64; + + + /// + /// The slash constant which indicates a bot command. + /// + public const string BotCommandIndicator = "/"; } \ No newline at end of file diff --git a/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs b/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs index bc06b06..7b4dea8 100644 --- a/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs +++ b/TelegramBotBase/Controls/Hybrid/ButtonGrid.cs @@ -51,7 +51,24 @@ public class ButtonGrid : ControlBase DataSource = new ButtonFormDataSource(form); } - public string Title { get; set; } = Default.Language["ButtonGrid_Title"]; + string m_Title = Default.Language["ButtonGrid_Title"]; + + public string Title + { + get + { + return m_Title; + } + set + { + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException($"{nameof(Title)}", $"{nameof(Title)} property must have been a value unequal to null/empty"); + } + + m_Title = value; + } + } public string ConfirmationText { get; set; } = ""; @@ -340,14 +357,14 @@ public class ButtonGrid : ControlBase } - //var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText) - // ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText); + //var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText) + // ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText); - // bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText) + // bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText) - //var index = bf.FindRowByButton(button); + //var index = bf.FindRowByButton(button); - check: + check: //Remove button click message if (DeleteReplyMessage) @@ -449,15 +466,15 @@ public class ButtonGrid : ControlBase } - //var bf = DataSource.ButtonForm; + //var bf = DataSource.ButtonForm; - //var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) - // ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) - // ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData); + //var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) + // ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData) + // ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData); - //var index = bf.FindRowByButton(button); + //var index = bf.FindRowByButton(button); - check: + check: if (match != null) { await result.ConfirmAction(ConfirmationText ?? ""); @@ -506,13 +523,13 @@ public class ButtonGrid : ControlBase if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !EnablePaging) { throw new MaximumRowsReachedException - { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows }; + { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows }; } if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols) { throw new MaximumColsException - { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols }; + { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols }; } break; @@ -522,13 +539,13 @@ public class ButtonGrid : ControlBase if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !EnablePaging) { throw new MaximumRowsReachedException - { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows }; + { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows }; } if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols) { throw new MaximumColsException - { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols }; + { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols }; } break; @@ -693,7 +710,7 @@ public class ButtonGrid : ControlBase Updated(); } else - //Remove event handler + //Remove event handler { Device.MessageDeleted -= Device_MessageDeleted; } diff --git a/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs b/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs index ed44fc0..83cc657 100644 --- a/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs +++ b/TelegramBotBase/Controls/Hybrid/CheckedButtonList.cs @@ -13,6 +13,7 @@ using TelegramBotBase.Enums; using TelegramBotBase.Exceptions; using TelegramBotBase.Form; using TelegramBotBase.Localizations; +using static System.Net.Mime.MediaTypeNames; using static TelegramBotBase.Base.Async; namespace TelegramBotBase.Controls.Hybrid; @@ -51,7 +52,24 @@ public class CheckedButtonList : ControlBase DataSource = new ButtonFormDataSource(form); } - public string Title { get; set; } = Default.Language["ButtonGrid_Title"]; + string m_Title = Default.Language["ButtonGrid_Title"]; + + public string Title + { + get + { + return m_Title; + } + set + { + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException($"{nameof(Title)}", $"{nameof(Title)} property must have been a value unequal to null/empty"); + } + + m_Title = value; + } + } public string ConfirmationText { get; set; } = ""; diff --git a/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs b/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs index 94266b7..d7e1ee4 100644 --- a/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs +++ b/TelegramBotBase/Controls/Hybrid/TaggedButtonGrid.cs @@ -67,7 +67,24 @@ public class TaggedButtonGrid : MultiView DataSource = new ButtonFormDataSource(form); } - public string Title { get; set; } = Default.Language["ButtonGrid_Title"]; + string m_Title = Default.Language["ButtonGrid_Title"]; + + public string Title + { + get + { + return m_Title; + } + set + { + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException($"{nameof(Title)}", $"{nameof(Title)} property must have been a value unequal to null/empty"); + } + + m_Title = value; + } + } public string ConfirmationText { get; set; } diff --git a/TelegramBotBase/Controls/Inline/Label.cs b/TelegramBotBase/Controls/Inline/Label.cs index 429e505..b327f94 100644 --- a/TelegramBotBase/Controls/Inline/Label.cs +++ b/TelegramBotBase/Controls/Inline/Label.cs @@ -16,7 +16,7 @@ public class Label : ControlBase { private bool _renderNecessary = true; - private string _text = string.Empty; + private string _text = Default.Language["Label_Text"]; public String Text { @@ -29,6 +29,10 @@ public class Label : ControlBase if (_text == value) return; + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException($"{nameof(Text)}", $"{nameof(Text)} property must have been a value unequal to null/empty"); + } _text = value; _renderNecessary = true; @@ -36,6 +40,8 @@ public class Label : ControlBase } } + + private ParseMode _parseMode = ParseMode.Markdown; public ParseMode ParseMode diff --git a/TelegramBotBase/Controls/Inline/MultiToggleButton.cs b/TelegramBotBase/Controls/Inline/MultiToggleButton.cs index 488a5f1..61fb6a7 100644 --- a/TelegramBotBase/Controls/Inline/MultiToggleButton.cs +++ b/TelegramBotBase/Controls/Inline/MultiToggleButton.cs @@ -32,10 +32,32 @@ public class MultiToggleButton : ControlBase /// public string ChangedString { get; set; } = Default.Language["MultiToggleButton_Changed"]; + private string _title = Default.Language["MultiToggleButton_Title"]; + /// /// This holds the title of the control. /// - public string Title { get; set; } = Default.Language["MultiToggleButton_Title"]; + public String Title + { + get + { + return _title; + } + set + { + if (_title == value) + return; + + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException($"{nameof(Title)}", $"{nameof(Title)} must have been a value unequal to null/empty"); + } + + _title = value; + _renderNecessary = true; + + } + } public int? MessageId { get; set; } diff --git a/TelegramBotBase/Controls/Inline/ToggleButton.cs b/TelegramBotBase/Controls/Inline/ToggleButton.cs index 4c7811e..19c7cd2 100644 --- a/TelegramBotBase/Controls/Inline/ToggleButton.cs +++ b/TelegramBotBase/Controls/Inline/ToggleButton.cs @@ -36,7 +36,31 @@ public class ToggleButton : ControlBase public string ChangedString { get; set; } = Default.Language["ToggleButton_Changed"]; - public string Title { get; set; } = Default.Language["ToggleButton_Title"]; + private string _title = Default.Language["ToggleButton_Title"]; + + public String Title + { + get + { + return _title; + } + set + { + if (_title == value) + return; + + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException($"{nameof(Title)}", $"{nameof(Title)} property must have been a value unequal to null/empty"); + } + + _title = value; + _renderNecessary = true; + + } + } + + public int? MessageId { get; set; } diff --git a/TelegramBotBase/Exceptions/CallbackDataTooLongException.cs b/TelegramBotBase/Exceptions/CallbackDataTooLongException.cs new file mode 100644 index 0000000..354a7f0 --- /dev/null +++ b/TelegramBotBase/Exceptions/CallbackDataTooLongException.cs @@ -0,0 +1,35 @@ +using System; +using Telegram.Bot.Exceptions; + +namespace TelegramBotBase.Exceptions; + +public sealed class CallbackDataTooLongException : Exception +{ + static ApiRequestException _innerException = new Telegram.Bot.Exceptions.ApiRequestException("Bad Request: BUTTON_DATA_INVALID", 400); + + static String _message = $"You have exceeded the maximum {Constants.Telegram.MaxCallBackDataBytes} bytes of callback data.\r\nThis is a pre-sending message from the TelegramBotBase framework.\r\nread more: https://core.telegram.org/bots/api#inlinekeyboardbutton"; + + static String _message_with_bytes = $"You have exceeded the maximum {Constants.Telegram.MaxCallBackDataBytes} bytes of callback data with @current_callback_bytes@ bytes.\r\nThis is a pre-sending message from the TelegramBotBase framework.\r\nread more: https://core.telegram.org/bots/api#inlinekeyboardbutton"; + + public CallbackDataTooLongException() : base(_message, _innerException) + { + + } + + /// + /// + /// + /// The amount of callback bytes generated. + public CallbackDataTooLongException(int current_callback_bytes) : base(getMessage(current_callback_bytes), _innerException) + { + + } + + static String getMessage(int current_callback_bytes = -1) + { + if (current_callback_bytes == -1) + return _message; + + return _message_with_bytes.Replace("@current_callback_bytes@", current_callback_bytes.ToString()); + } +} \ No newline at end of file diff --git a/TelegramBotBase/Exceptions/InvalidServiceProviderConfiguration.cs b/TelegramBotBase/Exceptions/InvalidServiceProviderConfiguration.cs new file mode 100644 index 0000000..03135ad --- /dev/null +++ b/TelegramBotBase/Exceptions/InvalidServiceProviderConfiguration.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TelegramBotBase.Exceptions +{ + public sealed class InvalidServiceProviderConfiguration : Exception + { + public InvalidServiceProviderConfiguration(string message, Exception innerException) : base(message, innerException) { } + + } +} diff --git a/TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs b/TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs index 8bac651..f143604 100644 --- a/TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs +++ b/TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs @@ -1,6 +1,7 @@ using System; using Microsoft.Extensions.DependencyInjection; using TelegramBotBase.DependencyInjection; +using TelegramBotBase.Exceptions; using TelegramBotBase.Form; using TelegramBotBase.Interfaces; @@ -24,7 +25,16 @@ public class ServiceProviderStartFormFactory : IStartFormFactory public FormBase CreateForm() { - var fb = (FormBase)ActivatorUtilities.CreateInstance(_serviceProvider, _startFormClass); + FormBase fb = null; + + try + { + fb = (FormBase)ActivatorUtilities.CreateInstance(_serviceProvider, _startFormClass); + } + catch(InvalidOperationException ex) + { + throw new InvalidServiceProviderConfiguration(ex.Message, ex); + } //Sets an internal field for future ServiceProvider navigation fb.SetServiceProvider(_serviceProvider); diff --git a/TelegramBotBase/Form/CallbackData.cs b/TelegramBotBase/Form/CallbackData.cs index 8385551..13b701a 100644 --- a/TelegramBotBase/Form/CallbackData.cs +++ b/TelegramBotBase/Form/CallbackData.cs @@ -1,4 +1,6 @@ using Newtonsoft.Json; +using System.Text; +using TelegramBotBase.Exceptions; namespace TelegramBotBase.Form; @@ -23,22 +25,24 @@ public class CallbackData public static string Create(string method, string value) { - return new CallbackData(method, value).Serialize(); + return new CallbackData(method, value).Serialize(true); } /// /// Serializes data to json string /// /// - public string Serialize() + public string Serialize(bool throwExceptionOnOverflow = false) { - var s = ""; - try - { - s = JsonConvert.SerializeObject(this); - } - catch + var s = string.Empty; + + s = JsonConvert.SerializeObject(this); + + //Is data over 64 bytes ? + int byte_count = Encoding.UTF8.GetByteCount(s); + if (throwExceptionOnOverflow && byte_count > Constants.Telegram.MaxCallBackDataBytes) { + throw new CallbackDataTooLongException(byte_count); } return s; @@ -51,19 +55,8 @@ public class CallbackData /// public static CallbackData Deserialize(string data) { - CallbackData cd = null; - try - { - cd = JsonConvert.DeserializeObject(data); - - return cd; - } - catch - { - } - - return null; + return JsonConvert.DeserializeObject(data); } - public static implicit operator string(CallbackData callbackData) => callbackData.Serialize(); + public static implicit operator string(CallbackData callbackData) => callbackData.Serialize(true); } diff --git a/TelegramBotBase/Localizations/English.cs b/TelegramBotBase/Localizations/English.cs index 974143b..527b427 100644 --- a/TelegramBotBase/Localizations/English.cs +++ b/TelegramBotBase/Localizations/English.cs @@ -34,5 +34,6 @@ public sealed class English : Localization Values["ToggleButton_Changed"] = "Setting changed"; Values["ButtonGrid_SearchIcon"] = "🔍"; Values["TaggedButtonGrid_TagIcon"] = "📁"; + Values["Label_Text"] = "Default label text"; } } diff --git a/TelegramBotBase/Localizations/German.cs b/TelegramBotBase/Localizations/German.cs index ffe99c4..0d0f362 100644 --- a/TelegramBotBase/Localizations/German.cs +++ b/TelegramBotBase/Localizations/German.cs @@ -34,5 +34,6 @@ public sealed class German : Localization Values["ToggleButton_Changed"] = "Einstellung geändert"; Values["ButtonGrid_SearchIcon"] = "🔍"; Values["TaggedButtonGrid_TagIcon"] = "📁"; + Values["Label_Text"] = "Standard Label Text"; } } \ No newline at end of file diff --git a/TelegramBotBase/Localizations/Persian.cs b/TelegramBotBase/Localizations/Persian.cs index 72c6b40..add3088 100644 --- a/TelegramBotBase/Localizations/Persian.cs +++ b/TelegramBotBase/Localizations/Persian.cs @@ -34,6 +34,7 @@ public sealed class Persian : Localization Values["ToggleButton_Changed"] = "تنظیمات تغییر کرد"; Values["ButtonGrid_SearchIcon"] = "🔍"; Values["TaggedButtonGrid_TagIcon"] = "📁"; + Values["Label_Text"] = "متن برچسب پیش‌فرض"; } } diff --git a/TelegramBotBase/Localizations/Russian.cs b/TelegramBotBase/Localizations/Russian.cs index 08315e6..eff54d3 100644 --- a/TelegramBotBase/Localizations/Russian.cs +++ b/TelegramBotBase/Localizations/Russian.cs @@ -34,5 +34,6 @@ public sealed class Russian : Localization Values["ToggleButton_Changed"] = "Настройки изменены"; Values["ButtonGrid_SearchIcon"] = "🔍"; Values["TaggedButtonGrid_TagIcon"] = "📁"; + Values["Label_Text"] = "Текст метки по умолчанию"; } } \ No newline at end of file diff --git a/TelegramBotBase/MessageLoops/FormBaseMessageLoop.cs b/TelegramBotBase/MessageLoops/FormBaseMessageLoop.cs index 4bec2a0..bdc6374 100644 --- a/TelegramBotBase/MessageLoops/FormBaseMessageLoop.cs +++ b/TelegramBotBase/MessageLoops/FormBaseMessageLoop.cs @@ -79,13 +79,16 @@ public class FormBaseMessageLoop : IMessageLoopFactory } //Action Event - if (!session.FormSwitched && mr.IsAction) + if (!session.FormSwitched && mr.IsAction && !mr.Handled) { //Send Action event to controls await activeForm.ActionControls(mr); - //Send Action event to form itself - await activeForm.Action(mr); + if (!mr.Handled) + { + //Send Action event to form itself, if not already handled by a control + await activeForm.Action(mr); + } if (!mr.Handled) { diff --git a/TelegramBotBase/MessageLoops/FullMessageLoop.cs b/TelegramBotBase/MessageLoops/FullMessageLoop.cs index 1affd19..a0c1c51 100644 --- a/TelegramBotBase/MessageLoops/FullMessageLoop.cs +++ b/TelegramBotBase/MessageLoops/FullMessageLoop.cs @@ -72,13 +72,16 @@ public class FullMessageLoop : IMessageLoopFactory } //Action Event - if (!session.FormSwitched && mr.IsAction) + if (!session.FormSwitched && mr.IsAction && !mr.Handled) { //Send Action event to controls await activeForm.ActionControls(mr); - //Send Action event to form itself - await activeForm.Action(mr); + if (!mr.Handled) + { + //Send Action event to form itself, if not already handled by a control + await activeForm.Action(mr); + } if (!mr.Handled) { diff --git a/TelegramBotBase/Sessions/DeviceSession.cs b/TelegramBotBase/Sessions/DeviceSession.cs index 50ad65e..f2b49d2 100644 --- a/TelegramBotBase/Sessions/DeviceSession.cs +++ b/TelegramBotBase/Sessions/DeviceSession.cs @@ -131,13 +131,9 @@ public class DeviceSession : IDeviceSession public async Task ConfirmAction(string callbackQueryId, string message = "", bool showAlert = false, string urlToOpen = null) { - try - { - await Client.TelegramClient.AnswerCallbackQueryAsync(callbackQueryId, message, showAlert, urlToOpen); - } - catch - { - } + + await Client.TelegramClient.AnswerCallbackQueryAsync(callbackQueryId, message, showAlert, urlToOpen); + } /// @@ -157,17 +153,8 @@ public class DeviceSession : IDeviceSession throw new MessageTooLongException(text.Length); } - try - { - return await Api(a => - a.EditMessageTextAsync(DeviceId, messageId, text, parseMode, replyMarkup: markup)); - } - catch - { - } - - return null; + return await Api(a => a.EditMessageTextAsync(DeviceId, messageId, text, parseMode, replyMarkup: markup)); } /// @@ -185,17 +172,9 @@ public class DeviceSession : IDeviceSession throw new MessageTooLongException(text.Length); } - try - { - return await Api(a => - a.EditMessageTextAsync(DeviceId, messageId, text, parseMode, replyMarkup: markup)); - } - catch - { - } + return await Api(a => a.EditMessageTextAsync(DeviceId, messageId, text, parseMode, replyMarkup: markup)); - return null; } /// @@ -215,18 +194,8 @@ public class DeviceSession : IDeviceSession throw new MessageTooLongException(message.Text.Length); } - try - { - return await Api(a => - a.EditMessageTextAsync(DeviceId, message.MessageId, message.Text, parseMode, - replyMarkup: markup)); - } - catch - { - } - - - return null; + return await Api(a => a.EditMessageTextAsync(DeviceId, message.MessageId, message.Text, parseMode, + replyMarkup: markup)); } /// @@ -237,15 +206,8 @@ public class DeviceSession : IDeviceSession /// public async Task EditReplyMarkup(int messageId, ButtonForm bf) { - try - { - return await Api(a => a.EditMessageReplyMarkupAsync(DeviceId, messageId, bf)); - } - catch - { - } - return null; + return await Api(a => a.EditMessageReplyMarkupAsync(DeviceId, messageId, bf)); } /// @@ -277,21 +239,16 @@ public class DeviceSession : IDeviceSession text = text.MarkdownV2Escape(); } - try - { - var t = Api(a => a.SendTextMessageAsync(deviceId, text, null, parseMode, replyToMessageId: replyTo, - replyMarkup: markup, disableNotification: disableNotification)); - var o = GetOrigin(new StackTrace()); + var t = Api(a => a.SendTextMessageAsync(deviceId, text, null, parseMode, replyToMessageId: replyTo, + replyMarkup: markup, disableNotification: disableNotification)); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var o = GetOrigin(new StackTrace()); + + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -336,20 +293,15 @@ public class DeviceSession : IDeviceSession text = text.MarkdownV2Escape(); } - try - { - var t = Api(a => a.SendTextMessageAsync(DeviceId, text, null, parseMode, replyToMessageId: replyTo, - replyMarkup: markup, disableNotification: disableNotification)); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendTextMessageAsync(DeviceId, text, null, parseMode, replyToMessageId: replyTo, + replyMarkup: markup, disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -379,20 +331,15 @@ public class DeviceSession : IDeviceSession text = text.MarkdownV2Escape(); } - try - { - var t = Api(a => a.SendTextMessageAsync(DeviceId, text, null, parseMode, replyToMessageId: replyTo, - replyMarkup: markup, disableNotification: disableNotification)); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendTextMessageAsync(DeviceId, text, null, parseMode, replyToMessageId: replyTo, + replyMarkup: markup, disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -414,20 +361,15 @@ public class DeviceSession : IDeviceSession InlineKeyboardMarkup markup = buttons; - try - { - var t = Api(a => a.SendPhotoAsync(DeviceId, file, null, caption, parseMode, replyToMessageId: replyTo, - replyMarkup: markup, disableNotification: disableNotification)); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendPhotoAsync(DeviceId, file, null, caption, parseMode, replyToMessageId: replyTo, + replyMarkup: markup, disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -449,21 +391,16 @@ public class DeviceSession : IDeviceSession InlineKeyboardMarkup markup = buttons; - try - { - var t = Api(a => a.SendVideoAsync(DeviceId, file, caption: caption, parseMode: parseMode, - replyToMessageId: replyTo, replyMarkup: markup, - disableNotification: disableNotification)); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendVideoAsync(DeviceId, file, caption: caption, parseMode: parseMode, + replyToMessageId: replyTo, replyMarkup: markup, + disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -484,21 +421,16 @@ public class DeviceSession : IDeviceSession InlineKeyboardMarkup markup = buttons; - try - { - var t = Api(a => a.SendVideoAsync(DeviceId, InputFile.FromUri(url), parseMode: parseMode, - replyToMessageId: replyTo, replyMarkup: markup, - disableNotification: disableNotification)); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendVideoAsync(DeviceId, InputFile.FromUri(url), parseMode: parseMode, + replyToMessageId: replyTo, replyMarkup: markup, + disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -520,24 +452,19 @@ public class DeviceSession : IDeviceSession InlineKeyboardMarkup markup = buttons; - try - { - var ms = new MemoryStream(video); - var fts = InputFile.FromStream(ms, filename); + var ms = new MemoryStream(video); - var t = Api(a => a.SendVideoAsync(DeviceId, fts, parseMode: parseMode, replyToMessageId: replyTo, - replyMarkup: markup, disableNotification: disableNotification)); + var fts = InputFile.FromStream(ms, filename); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendVideoAsync(DeviceId, fts, parseMode: parseMode, replyToMessageId: replyTo, + replyMarkup: markup, disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -560,26 +487,21 @@ public class DeviceSession : IDeviceSession InlineKeyboardMarkup markup = buttons; - try - { - var fs = new FileStream(filepath, FileMode.Open); - var filename = Path.GetFileName(filepath); + var fs = new FileStream(filepath, FileMode.Open); - var fts = InputFile.FromStream(fs, filename); + var filename = Path.GetFileName(filepath); - var t = Api(a => a.SendVideoAsync(DeviceId, fts, parseMode: parseMode, replyToMessageId: replyTo, - replyMarkup: markup, disableNotification: disableNotification)); + var fts = InputFile.FromStream(fs, filename); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendVideoAsync(DeviceId, fts, parseMode: parseMode, replyToMessageId: replyTo, + replyMarkup: markup, disableNotification: disableNotification)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -650,20 +572,15 @@ public class DeviceSession : IDeviceSession markup = buttons; } - try - { - var t = Api(a => a.SendDocumentAsync(DeviceId, document, null, null, caption, replyMarkup: markup, - disableNotification: disableNotification, replyToMessageId: replyTo)); - var o = GetOrigin(new StackTrace()); - await OnMessageSent(new MessageSentEventArgs(await t, o)); + var t = Api(a => a.SendDocumentAsync(DeviceId, document, null, null, caption, replyMarkup: markup, + disableNotification: disableNotification, replyToMessageId: replyTo)); + + var o = GetOrigin(new StackTrace()); + await OnMessageSent(new MessageSentEventArgs(await t, o)); + + return await t; - return await t; - } - catch - { - return null; - } } /// @@ -714,22 +631,16 @@ public class DeviceSession : IDeviceSession public async Task HideReplyKeyboard(string closedMsg = "Closed", bool autoDeleteResponse = true) { - try - { - var m = await Send(closedMsg, new ReplyKeyboardRemove()); - if (autoDeleteResponse && m != null) - { - await DeleteMessage(m); - } + var m = await Send(closedMsg, new ReplyKeyboardRemove()); - return m; - } - catch + if (autoDeleteResponse && m != null) { + await DeleteMessage(m); } - return null; + return m; + } /// @@ -759,13 +670,9 @@ public class DeviceSession : IDeviceSession public virtual async Task ChangeChatPermissions(ChatPermissions permissions) { - try - { - await Api(a => a.SetChatPermissionsAsync(DeviceId, permissions)); - } - catch - { - } + + await Api(a => a.SetChatPermissionsAsync(DeviceId, permissions)); + } private Type GetOrigin(StackTrace stackTrace) @@ -878,49 +785,31 @@ public class DeviceSession : IDeviceSession public virtual async Task GetChatUser(long userId) { - try - { - return await Api(a => a.GetChatMemberAsync(DeviceId, userId)); - } - catch - { - } - return null; + return await Api(a => a.GetChatMemberAsync(DeviceId, userId)); + } [Obsolete("User BanUser instead.")] public virtual async Task KickUser(long userId, DateTime until = default) { - try - { - await Api(a => a.BanChatMemberAsync(DeviceId, userId, until)); - } - catch - { - } + + await Api(a => a.BanChatMemberAsync(DeviceId, userId, until)); + } public virtual async Task BanUser(long userId, DateTime until = default) { - try - { - await Api(a => a.BanChatMemberAsync(DeviceId, userId, until)); - } - catch - { - } + + await Api(a => a.BanChatMemberAsync(DeviceId, userId, until)); + } public virtual async Task UnbanUser(long userId) { - try - { - await Api(a => a.UnbanChatMemberAsync(DeviceId, userId)); - } - catch - { - } + + await Api(a => a.UnbanChatMemberAsync(DeviceId, userId)); + } #endregion