Skip to content

Commit 4ad80dc

Browse files
committed
Refactor text handling: separate commands and queries
Updated `UpdateHandler` in `BotApp.cs` to distinguish between text commands and text messages. Introduced `TextCommandHandler` in `TextCommandHandler.cs` for processing commands starting with '/'. Updated `TextMessageHandler` in `TextMessageHandler.cs` to use `TextQueryAttribute` for handling text queries. Added `TextQueryAttribute` in `TextQueryAttribute.cs` to mark methods for text queries with optional regex matching. Refactored `TextMessageHandler` to focus solely on text queries.
1 parent 9319f1e commit 4ad80dc

4 files changed

Lines changed: 157 additions & 31 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Text.RegularExpressions;
3+
4+
namespace TelegramBot.Attributes
5+
{
6+
/// <summary>
7+
/// Text query attribute.
8+
/// </summary>
9+
[AttributeUsage(AttributeTargets.Method)]
10+
public class TextQueryAttribute : Attribute
11+
{
12+
/// <summary>
13+
/// Pattern.
14+
/// </summary>
15+
public Regex? Regex { get; }
16+
17+
/// <summary>
18+
/// Creates a new instance of <see cref="TextQueryAttribute"/>.
19+
/// </summary>
20+
/// <param name="pattern"><see cref="Regex"/> pattern.</param>
21+
public TextQueryAttribute(string? pattern = null)
22+
{
23+
if (pattern != null)
24+
{
25+
Regex = new Regex(pattern);
26+
}
27+
}
28+
}
29+
}

Sources/TelegramBot/BotApp.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,18 @@ private Task ErrorHandler(ITelegramBotClient client, Exception exception, Cancel
206206
private async Task UpdateHandler(ITelegramBotClient client, Update update, CancellationToken token)
207207
{
208208
CheckDisposed();
209-
if (update.Message != null && !string.IsNullOrWhiteSpace(update.Message.Text) && update.Message.Text.StartsWith('/'))
209+
if (update.Message != null && !string.IsNullOrWhiteSpace(update.Message.Text) && !update.Message.Text.StartsWith('/'))
210210
{
211211
_logger.LogInformation("Received text message: {Text}.", update.Message.Text);
212212
var handler = new TextMessageHandler(_controllerMethods, update);
213213
await HandleRequestAsync(handler, update);
214214
}
215+
else if (update.Message != null && !string.IsNullOrWhiteSpace(update.Message.Text) && update.Message.Text.StartsWith('/'))
216+
{
217+
_logger.LogInformation("Received text command: {Text}.", update.Message.Text);
218+
var handler = new TextCommandHandler(_controllerMethods, update);
219+
await HandleRequestAsync(handler, update);
220+
}
215221
else if (update.CallbackQuery != null && update.CallbackQuery.Data != null)
216222
{
217223
_logger.LogInformation("Received inline query: {Data}.", update.CallbackQuery.Data);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using System.Reflection;
2+
using Telegram.Bot.Types;
3+
using TelegramBot.Helpers;
4+
using TelegramBot.Attributes;
5+
using System.Collections.Generic;
6+
7+
namespace TelegramBot.Handlers
8+
{
9+
internal class TextCommandHandler : ITelegramUpdateHandler
10+
{
11+
private readonly List<object> _args;
12+
private readonly MethodInfo? _methodInfo;
13+
14+
public TextCommandHandler(IReadOnlyCollection<MethodInfo> controllerMethods, Update update)
15+
{
16+
_args = new List<object>();
17+
_methodInfo = GetMethodInfo(controllerMethods, update);
18+
}
19+
20+
private MethodInfo? GetMethodInfo(IReadOnlyCollection<MethodInfo> controllerMethods, Update update)
21+
{
22+
if (update.Type != Telegram.Bot.Types.Enums.UpdateType.Message
23+
|| update.Message == null
24+
|| string.IsNullOrWhiteSpace(update.Message.Text))
25+
{
26+
return null;
27+
}
28+
var message = update.Message;
29+
var parts = message.Text.Split(' ');
30+
string command = parts[0];
31+
if (!command.StartsWith('/'))
32+
{
33+
return null;
34+
}
35+
if (parts.Length > 1)
36+
{
37+
_args.AddRange(parts[1..]);
38+
}
39+
40+
List<MethodInfo> methods = new List<MethodInfo>();
41+
foreach (var method in controllerMethods)
42+
{
43+
var attributes = method.GetCustomAttributes(typeof(TextCommandAttribute), false);
44+
foreach (var attribute in attributes)
45+
{
46+
if (attribute is TextCommandAttribute botCommandAttribute)
47+
{
48+
if (botCommandAttribute.Command == command)
49+
{
50+
if (_args.Count == method.GetParameters().Length)
51+
{
52+
bool converted = ObjectHelpers.TryConvertParameters(method, _args.ToArray());
53+
if (converted)
54+
{
55+
methods.Add(method);
56+
}
57+
}
58+
}
59+
}
60+
}
61+
}
62+
if (methods.Count == 1)
63+
{
64+
var args = _args.ToArray();
65+
ObjectHelpers.TryConvertParameters(methods[0], args);
66+
_args.Clear();
67+
_args.AddRange(args);
68+
return methods[0];
69+
}
70+
else if (methods.Count > 1)
71+
{
72+
throw new AmbiguousMatchException("Multiple methods found with the same command and arguments: " + command);
73+
}
74+
return null;
75+
}
76+
77+
78+
public object[]? GetArguments()
79+
{
80+
return _args.Count > 0 ? _args.ToArray() : null;
81+
}
82+
83+
public MethodInfo? GetMethodInfo()
84+
{
85+
return _methodInfo;
86+
}
87+
}
88+
}
Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Reflection;
22
using Telegram.Bot.Types;
3-
using TelegramBot.Helpers;
43
using TelegramBot.Attributes;
54
using System.Collections.Generic;
65

@@ -19,60 +18,64 @@ public TextMessageHandler(IReadOnlyCollection<MethodInfo> controllerMethods, Upd
1918

2019
private MethodInfo? GetMethodInfo(IReadOnlyCollection<MethodInfo> controllerMethods, Update update)
2120
{
22-
if (update.Type != Telegram.Bot.Types.Enums.UpdateType.Message || update.Message == null)
21+
if (update.Type != Telegram.Bot.Types.Enums.UpdateType.Message
22+
|| update.Message == null
23+
|| string.IsNullOrWhiteSpace(update.Message.Text))
2324
{
2425
return null;
2526
}
26-
var message = update.Message;
27-
var parts = message.Text!.Split(' ');
28-
string command = parts[0];
29-
if (!command.StartsWith('/'))
30-
{
31-
return null;
32-
}
33-
if (parts.Length > 1)
34-
{
35-
_args.AddRange(parts[1..]);
36-
}
27+
string text = update.Message.Text;
3728

3829
List<MethodInfo> methods = new List<MethodInfo>();
3930
foreach (var method in controllerMethods)
4031
{
41-
var attributes = method.GetCustomAttributes(typeof(TextCommandAttribute), false);
32+
var attributes = method.GetCustomAttributes(typeof(TextQueryAttribute), false);
4233
foreach (var attribute in attributes)
4334
{
44-
if (attribute is TextCommandAttribute botCommandAttribute)
35+
if (attribute is TextQueryAttribute botTextAttribute)
4536
{
46-
if (botCommandAttribute.Command == command)
37+
if (method.GetParameters().Length > 1)
38+
{
39+
continue;
40+
}
41+
if (method.GetParameters().Length == 1)
4742
{
48-
if (_args.Count == method.GetParameters().Length)
43+
if (method.GetParameters()[0].ParameterType != typeof(string))
4944
{
50-
bool converted = ObjectHelpers.TryConvertParameters(method, _args.ToArray());
51-
if (converted)
52-
{
53-
methods.Add(method);
54-
}
45+
continue;
5546
}
5647
}
48+
if (botTextAttribute.Regex == null)
49+
{
50+
methods.Add(method);
51+
}
52+
else if (botTextAttribute.Regex.IsMatch(text))
53+
{
54+
methods.Add(method);
55+
}
56+
else
57+
{
58+
continue;
59+
}
5760
}
5861
}
5962
}
6063
if (methods.Count == 1)
6164
{
62-
var args = _args.ToArray();
63-
ObjectHelpers.TryConvertParameters(methods[0], args);
64-
_args.Clear();
65-
_args.AddRange(args);
66-
return methods[0];
65+
var method = methods[0];
66+
if (method.GetParameters().Length > 0)
67+
{
68+
_args.Add(text);
69+
}
70+
return method;
6771
}
6872
else if (methods.Count > 1)
6973
{
70-
throw new AmbiguousMatchException("Multiple methods found with the same command and arguments: " + command);
74+
throw new AmbiguousMatchException("Multiple methods found for text: " + text);
7175
}
7276
return null;
7377
}
7478

75-
7679
public object[]? GetArguments()
7780
{
7881
return _args.Count > 0 ? _args.ToArray() : null;
@@ -83,4 +86,4 @@ public TextMessageHandler(IReadOnlyCollection<MethodInfo> controllerMethods, Upd
8386
return _methodInfo;
8487
}
8588
}
86-
}
89+
}

0 commit comments

Comments
 (0)