mirror of
https://github.com/yawaflua/Telegram.Net.git
synced 2025-12-09 20:19:28 +02:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
529378c0bb | ||
|
|
2371180bd4 | ||
|
|
a691064881 | ||
|
|
0a7e3d4b49 | ||
|
|
7b7b2effca | ||
|
|
9b0578092b | ||
|
|
38df51f4b3 | ||
|
|
55079122ac | ||
|
|
c2e04598f6 | ||
|
|
4da17d8bf0 | ||
|
|
cf9a5c14ef | ||
|
|
3094fcbabe | ||
|
|
59a94c9f97 | ||
|
|
4777fc3e73 | ||
|
|
f82f5cd291 | ||
|
|
e442227c78 | ||
|
|
343ab4de7f | ||
|
|
779a69245f | ||
|
|
6f0d20964b |
67
CONTRIBUTING.md
Normal file
67
CONTRIBUTING.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Contributing to Telegram.Net
|
||||
|
||||
Thank you for your interest in contributing to Telegram.Net! We welcome contributions from anyone in the community, regardless of experience level.
|
||||
|
||||
## How to Contribute
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. Fork the repository at [https://github.com/yawaflua/Telegram.Net](https://github.com/yawaflua/Telegram.Net)
|
||||
2. Clone your fork to your local machine
|
||||
3. Set up the development environment with the required .NET SDK
|
||||
|
||||
### Making Changes
|
||||
|
||||
1. Create a new branch for your feature or bug fix:
|
||||
```
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
2. Make your changes
|
||||
3. Write or update tests for the changes you made using appropriate testing frameworks (e.g., MSTest, NUnit, or xUnit)
|
||||
4. Ensure your code passes all tests and meets C# coding conventions
|
||||
|
||||
## Code Quality Requirements
|
||||
|
||||
### Test Coverage
|
||||
|
||||
- **All pull requests must include tests with at least 50% code coverage**
|
||||
- Before submitting your PR, verify coverage using tools like:
|
||||
```
|
||||
# Example using Coverlet and ReportGenerator
|
||||
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
|
||||
dotnet tool run reportgenerator -reports:"**/coverage.opencover.xml" -targetdir:"coveragereport" -reporttypes:Html
|
||||
```
|
||||
|
||||
### Coding Standards
|
||||
|
||||
- Follow C# coding conventions and the existing style in the project
|
||||
- Use meaningful names for classes, methods, and variables
|
||||
- Include XML documentation comments for public APIs
|
||||
- Keep methods focused and reasonably sized
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Update documentation if you're changing or adding functionality
|
||||
2. Ensure your code has adequate test coverage (minimum 50%)
|
||||
3. Submit your pull request with a clear title and description
|
||||
4. Reference any relevant issues in your PR description
|
||||
|
||||
## Review Process
|
||||
|
||||
- All submissions require review before being merged
|
||||
- Maintainers may request changes or suggest improvements
|
||||
- Be responsive to feedback on your pull request
|
||||
|
||||
## C# Specific Guidelines
|
||||
|
||||
- Target the same .NET version as the project
|
||||
- Avoid excessive dependencies unless absolutely necessary
|
||||
- Follow SOLID principles when applicable
|
||||
- Use async/await patterns appropriately for asynchronous operations
|
||||
- Be mindful of performance implications, especially for a networking library
|
||||
|
||||
## Questions?
|
||||
|
||||
If you have any questions about contributing to Telegram.Net, feel free to open an issue for discussion.
|
||||
|
||||
Thank you for helping improve Telegram.Net!
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Telegram.Net;
|
||||
@@ -7,12 +8,11 @@ var webHost = Host.CreateDefaultBuilder()
|
||||
.ConfigureLogging(l => l.ClearProviders().AddConsole())
|
||||
.ConfigureServices(k =>
|
||||
{
|
||||
k.ConnectTelegram(new("TOKEN")
|
||||
{
|
||||
errorHandler = async (client, exception, ctx) =>
|
||||
{
|
||||
Console.WriteLine(exception);
|
||||
}
|
||||
});
|
||||
var _conf = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
k.AddSingleton(_conf);
|
||||
k.ConnectTelegram(new(_conf.GetValue<string>("telegram_test_token")));
|
||||
});
|
||||
webHost.Build().Run();
|
||||
@@ -6,11 +6,15 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.3" />
|
||||
<ProjectReference Include="..\..\Telegram.Net\Telegram.Net.csproj" />
|
||||
|
||||
<None CopyToOutputDirectory="Always" Include="appsettings.json"></None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Telegram.Bot;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Net.Attributes;
|
||||
using Telegram.Net.Interfaces;
|
||||
@@ -7,6 +8,11 @@ namespace Telegram.Examples.UpdatePolling;
|
||||
|
||||
public class Update : IUpdatePollingService
|
||||
{
|
||||
private static IConfiguration _conf;
|
||||
public Update(IConfiguration conf)
|
||||
{
|
||||
_conf = conf;
|
||||
}
|
||||
[Update]
|
||||
public async Task UpdateExample(ITelegramBotClient client, Bot.Types.Update update, CancellationToken ctx)
|
||||
{
|
||||
@@ -31,6 +37,12 @@ public class Update : IUpdatePollingService
|
||||
await client.SendMessage(message.From!.Id, "Hello, I`m example bot.", cancellationToken: ctx);
|
||||
}
|
||||
|
||||
[Command("/test_conf")]
|
||||
public async Task TestConfigurationBuilder(ITelegramBotClient client, Message message, CancellationToken cts)
|
||||
{
|
||||
await client.SendMessage(message.Chat.Id, _conf.GetValue<string>("ExampleMessage") ?? throw new Exception("Not found"));
|
||||
}
|
||||
|
||||
[EditMessage]
|
||||
public async Task EditMessageExmaple(ITelegramBotClient client, Message message, CancellationToken ctx)
|
||||
{
|
||||
|
||||
4
Examples/Telegram.Examples/appsettings.json
Normal file
4
Examples/Telegram.Examples/appsettings.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"ExampleMessage": "Test!",
|
||||
"telegram_test_token": "PROVIDE_TOKEN"
|
||||
}
|
||||
23
README.md
23
README.md
@@ -15,11 +15,25 @@ This project provides a set of C# attributes to facilitate the handling of diffe
|
||||
Ensure you have the required dependencies installed:
|
||||
|
||||
```sh
|
||||
dotnet add package Telegram.Bot
|
||||
dotnet add package yawaflua.Telegram.Net
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Provide dependencies in class
|
||||
You can provide dependencies in class from constructor, and after it use it like `static`.
|
||||
```csharp
|
||||
public class Example : IUpdatePollingService
|
||||
{
|
||||
private static MyCoolService _service; // It should to be static!
|
||||
|
||||
public Example(MyCoolService service)
|
||||
{
|
||||
_service = service;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Inline Query Handling
|
||||
Use the `InlineAttribute` to register a method as an inline query handler.
|
||||
|
||||
@@ -86,5 +100,10 @@ public static async Task HandleUpdate(ITelegramBotClient bot, Update update, Can
|
||||
}
|
||||
```
|
||||
|
||||
### We know about this bugs:
|
||||
- [ X ] Not working providing dependencies in class constructor and this gives an error.
|
||||
~~Try to not use provided dependencies in class. We are should to fix it in v1.0.2.~~
|
||||
Now just use static variables
|
||||
|
||||
## License
|
||||
This project is open-source and available under the MIT License.
|
||||
This project is open-source and available under the [Apache 2.0 License](LICENSE).
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Telegram.Net.Models;
|
||||
using Telegram.Net.Services;
|
||||
|
||||
@@ -8,7 +10,8 @@ public static class ServiceBindings
|
||||
{
|
||||
public static IServiceCollection ConnectTelegram(this IServiceCollection isc, TelegramBotConfig config)
|
||||
{
|
||||
isc.AddHostedService<TelegramHostedService>(k => new(config, isc));
|
||||
var logger = isc.BuildServiceProvider().GetRequiredService<ILogger<TelegramHostedService>>();
|
||||
isc.AddHostedService<TelegramHostedService>(k => new(config, isc, logger));
|
||||
return isc;
|
||||
}
|
||||
}
|
||||
@@ -2,143 +2,161 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Payments;
|
||||
using Telegram.Net.Attributes;
|
||||
using Telegram.Net.Interfaces;
|
||||
using static System.Reflection.BindingFlags;
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
||||
namespace Telegram.Net.Services;
|
||||
|
||||
[SuppressMessage("ReSharper", "ReturnValueOfPureMethodIsNotUsed")]
|
||||
public class TelegramHostedService : IHostedService
|
||||
{
|
||||
private IServiceCollection isc { get; }
|
||||
internal TelegramBotClient Client { get; set; }
|
||||
private ITelegramBotConfig Config { get; }
|
||||
internal Dictionary<string, Func<ITelegramBotClient, Message, CancellationToken, Task>> CommandHandler { get; } = new();
|
||||
internal List<Func<ITelegramBotClient, Message, CancellationToken, Task>> EditedMessageHandler { get; } = new();
|
||||
internal Dictionary<string, Func<ITelegramBotClient, CallbackQuery,CancellationToken, Task>> CallbackQueryHandler { get; } = new();
|
||||
internal Dictionary<string, Func<ITelegramBotClient, InlineQuery ,CancellationToken, Task>> InlineHandler { get; } = new();
|
||||
private IServiceCollection ServiceCollection { get; } = null!;
|
||||
internal TelegramBotClient Client { get; set; } = null!;
|
||||
private ITelegramBotConfig Config { get; } = null!;
|
||||
internal Dictionary<string, Func<ITelegramBotClient, Message, CancellationToken, Task>?> CommandHandler { get; set; } = new();
|
||||
internal List<Func<ITelegramBotClient, Message, CancellationToken, Task>?> EditedMessageHandler { get; set; } = new();
|
||||
internal Dictionary<string, Func<ITelegramBotClient, CallbackQuery, CancellationToken, Task>?> CallbackQueryHandler { get; set; } = new();
|
||||
internal Dictionary<string, Func<ITelegramBotClient, InlineQuery, CancellationToken, Task>?> InlineHandler { get; set; } = new();
|
||||
internal Func<ITelegramBotClient, PreCheckoutQuery,CancellationToken, Task>? PreCheckoutHandler { get; set; }
|
||||
internal List<Func<ITelegramBotClient, Update, CancellationToken, Task>> DefaultUpdateHandler { get; } = new();
|
||||
|
||||
public TelegramHostedService(ITelegramBotConfig config, IServiceCollection isc)
|
||||
internal List<Func<ITelegramBotClient, Update, CancellationToken, Task>?> DefaultUpdateHandler { get; set; } = new();
|
||||
internal static ILogger<TelegramHostedService> Logger = null!;
|
||||
|
||||
public TelegramHostedService(ITelegramBotConfig config, IServiceCollection serviceCollection, ILogger<TelegramHostedService> logger)
|
||||
{
|
||||
Client = new TelegramBotClient(config.Token);
|
||||
Config = config;
|
||||
this.isc = isc;
|
||||
try
|
||||
{
|
||||
Logger = logger;
|
||||
Client = new TelegramBotClient(config.Token);
|
||||
Config = config;
|
||||
this.ServiceCollection = serviceCollection;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(LogLevel.Critical, new EventId(), ex, "Catched exception when creating TelegramHostedService: ");
|
||||
}
|
||||
}
|
||||
internal static bool IsValidHandlerMethod(MethodInfo method, Type parameterType)
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
return method.ReturnType == typeof(Task) &&
|
||||
parameters.Length == 3 &&
|
||||
parameters[0].ParameterType == typeof(ITelegramBotClient) &&
|
||||
parameters[1].ParameterType == parameterType &&
|
||||
parameters[2].ParameterType == typeof(CancellationToken);
|
||||
try
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
return method.ReturnType == typeof(Task) &&
|
||||
parameters.Length == 3 &&
|
||||
parameters[0].ParameterType == typeof(ITelegramBotClient) &&
|
||||
parameters[1].ParameterType == parameterType &&
|
||||
parameters[2].ParameterType == typeof(CancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Catched exception in parsing and checking params.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Func<ITelegramBotClient, T, CancellationToken, Task> CreateDelegate<T>(MethodInfo method)
|
||||
internal static Func<ITelegramBotClient, T, CancellationToken, Task>? CreateDelegate<T>(MethodInfo method)
|
||||
{
|
||||
var delegateType = typeof(Func<ITelegramBotClient, T, CancellationToken, Task>);
|
||||
return (Delegate.CreateDelegate(delegateType, null, method) as Func<ITelegramBotClient, T, CancellationToken, Task>)!;
|
||||
}
|
||||
try
|
||||
{
|
||||
var delegateType = typeof(Func<ITelegramBotClient, T, CancellationToken, Task>);
|
||||
return (Delegate.CreateDelegate(delegateType, null, method) as
|
||||
Func<ITelegramBotClient, T, CancellationToken, Task>)!;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(LogLevel.Critical, new EventId(), ex, "Catched exception in CreateDelegate function: ");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal async Task AddAttributes(CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
var implementations = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes())
|
||||
.Where(t => typeof(IUpdatePollingService).IsAssignableFrom(t) && !t.IsInterface);
|
||||
|
||||
foreach (var implementation in implementations)
|
||||
try
|
||||
{
|
||||
isc.AddSingleton(implementation);
|
||||
var attributeTypes = new HashSet<Type>
|
||||
{
|
||||
typeof(CommandAttribute),
|
||||
typeof(CallbackAttribute),
|
||||
typeof(EditMessageAttribute),
|
||||
typeof(InlineAttribute),
|
||||
typeof(PreCheckoutAttribute),
|
||||
typeof(UpdateAttribute)
|
||||
};
|
||||
|
||||
var methods = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes())
|
||||
.Where(t => typeof(IUpdatePollingService).IsAssignableFrom(t) && !t.IsInterface)
|
||||
.SelectMany(t => t.GetMethods(Instance |
|
||||
Public |
|
||||
NonPublic |
|
||||
DeclaredOnly))
|
||||
.Where(m => m.GetCustomAttributes().Any(a => attributeTypes.Contains(a.GetType())))
|
||||
.ToList();
|
||||
|
||||
if (methods.Count == 0)
|
||||
{
|
||||
Logger.LogWarning("No methods found with required attributes");
|
||||
}
|
||||
|
||||
var isp = ServiceCollection.BuildServiceProvider();
|
||||
foreach (var method in methods)
|
||||
{
|
||||
var declaringType = method.DeclaringType!;
|
||||
var constructor = declaringType.GetConstructors()[0];
|
||||
var parameters = constructor.GetParameters()
|
||||
.Select(param => isp.GetRequiredService(param.ParameterType))
|
||||
.ToArray();
|
||||
|
||||
constructor.Invoke(parameters);
|
||||
|
||||
switch (method.GetCustomAttributes().First(t => attributeTypes.Contains(t.GetType())))
|
||||
{
|
||||
case CommandAttribute command when IsValidHandlerMethod(method, typeof(Message)):
|
||||
var commandHandler = CreateDelegate<Message>(method);
|
||||
if (!CommandHandler.TryAdd(command.Command, commandHandler))
|
||||
throw new Exception($"Failed to add command: {command.Command}");
|
||||
break;
|
||||
|
||||
case CallbackAttribute callback when IsValidHandlerMethod(method, typeof(CallbackQuery)):
|
||||
var callbackHandler = CreateDelegate<CallbackQuery>(method);
|
||||
if (!CallbackQueryHandler.TryAdd(callback.QueryId, callbackHandler))
|
||||
throw new Exception($"Failed to add callback: {callback.QueryId}");
|
||||
break;
|
||||
|
||||
case EditMessageAttribute _ when IsValidHandlerMethod(method, typeof(Message)):
|
||||
EditedMessageHandler.Add(CreateDelegate<Message>(method));
|
||||
break;
|
||||
|
||||
case InlineAttribute inline when IsValidHandlerMethod(method, typeof(InlineQuery)):
|
||||
var inlineHandler = CreateDelegate<InlineQuery>(method);
|
||||
if (!InlineHandler.TryAdd(inline.InlineId, inlineHandler))
|
||||
throw new Exception($"Failed to add inline: {inline.InlineId}");
|
||||
break;
|
||||
|
||||
case PreCheckoutAttribute _ when IsValidHandlerMethod(method, typeof(PreCheckoutQuery)):
|
||||
PreCheckoutHandler = CreateDelegate<PreCheckoutQuery>(method);
|
||||
break;
|
||||
|
||||
case UpdateAttribute _ when IsValidHandlerMethod(method, typeof(Update)):
|
||||
DefaultUpdateHandler.Add(CreateDelegate<Update>(method));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var methods = implementations
|
||||
.SelectMany(t => t.GetMethods(
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Public | BindingFlags.NonPublic |
|
||||
BindingFlags.DeclaredOnly))
|
||||
.Where(m =>
|
||||
m.GetCustomAttribute<CommandAttribute>() != null ||
|
||||
m.GetCustomAttribute<CallbackAttribute>() != null ||
|
||||
m.GetCustomAttribute<EditMessageAttribute>() != null ||
|
||||
m.GetCustomAttribute<InlineAttribute>() != null ||
|
||||
m.GetCustomAttribute<PreCheckoutAttribute>() != null ||
|
||||
m.GetCustomAttribute<UpdateAttribute>() != null);
|
||||
|
||||
foreach (var method in methods)
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
|
||||
var commandAttr = method.GetCustomAttribute<CommandAttribute>();
|
||||
if (commandAttr != null)
|
||||
{
|
||||
if (IsValidHandlerMethod(method, typeof(Message)))
|
||||
{
|
||||
var handler = CreateDelegate<Message>(method);
|
||||
CommandHandler.TryAdd(commandAttr.Command, handler);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var callbackAttr = method.GetCustomAttribute<CallbackAttribute>();
|
||||
if (callbackAttr != null)
|
||||
{
|
||||
if (IsValidHandlerMethod(method, typeof(CallbackQuery)))
|
||||
{
|
||||
var handler = CreateDelegate<CallbackQuery>(method);
|
||||
CallbackQueryHandler.TryAdd(callbackAttr.QueryId, handler);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var editMessageAttr = method.GetCustomAttribute<EditMessageAttribute>();
|
||||
if (editMessageAttr != null)
|
||||
{
|
||||
if (IsValidHandlerMethod(method, typeof(Message)))
|
||||
{
|
||||
var handler = CreateDelegate<Message>(method);
|
||||
EditedMessageHandler.Add(handler);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var inlineAttr = method.GetCustomAttribute<InlineAttribute>();
|
||||
if (inlineAttr != null)
|
||||
{
|
||||
if (IsValidHandlerMethod(method, typeof(InlineQuery)))
|
||||
{
|
||||
var handler = CreateDelegate<InlineQuery>(method);
|
||||
InlineHandler.TryAdd(inlineAttr.InlineId, handler);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var preCheckoutAttr = method.GetCustomAttribute<PreCheckoutAttribute>();
|
||||
if (preCheckoutAttr != null)
|
||||
{
|
||||
if (IsValidHandlerMethod(method, typeof(PreCheckoutQuery)))
|
||||
{
|
||||
var handler = CreateDelegate<PreCheckoutQuery>(method);
|
||||
PreCheckoutHandler = handler;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var updateAttr = method.GetCustomAttribute<UpdateAttribute>();
|
||||
if (updateAttr != null)
|
||||
{
|
||||
if (IsValidHandlerMethod(method, typeof(Update)))
|
||||
{
|
||||
var handler = CreateDelegate<Update>(method);
|
||||
DefaultUpdateHandler.Add(handler);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Logger.Log(LogLevel.Critical, new EventId(), ex, "Catched new exception when added methods: ");
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
@@ -146,45 +164,88 @@ public class TelegramHostedService : IHostedService
|
||||
|
||||
internal async Task UpdateHandler(ITelegramBotClient client, Update update, CancellationToken ctx)
|
||||
{
|
||||
switch (update)
|
||||
try
|
||||
{
|
||||
case { Message: { } message }:
|
||||
await CommandHandler.FirstOrDefault(k => message.Text!.StartsWith(k.Key)).Value(client, message, ctx);
|
||||
break;
|
||||
case { EditedMessage: { } message }:
|
||||
EditedMessageHandler.ForEach(async k => await k(client, message, ctx));
|
||||
break;
|
||||
case { CallbackQuery: { } callbackQuery }:
|
||||
await CallbackQueryHandler.FirstOrDefault(k => callbackQuery.Data!.StartsWith(k.Key)).Value(client, callbackQuery, ctx);
|
||||
break;
|
||||
case { InlineQuery: { } inlineQuery }:
|
||||
await InlineHandler.FirstOrDefault(k => inlineQuery.Id.StartsWith(k.Key)).Value(client, inlineQuery, ctx);
|
||||
break;
|
||||
case { PreCheckoutQuery: { } preCheckoutQuery }:
|
||||
if (PreCheckoutHandler != null) await PreCheckoutHandler(client, preCheckoutQuery, ctx);
|
||||
break;
|
||||
default:
|
||||
DefaultUpdateHandler.ForEach(async k => await k(client, update, ctx));
|
||||
break;
|
||||
switch (update)
|
||||
{
|
||||
case { Message: { } message }:
|
||||
CommandHandler.Where(k => message.Text!.StartsWith(k.Key)).Select(async k =>
|
||||
{
|
||||
await k.Value!(client, message, ctx);
|
||||
return k;
|
||||
});
|
||||
break;
|
||||
case { EditedMessage: { } message }:
|
||||
// ReSharper disable once AsyncVoidLambda
|
||||
EditedMessageHandler.ForEach(async k => await k!(client, message, ctx));
|
||||
break;
|
||||
case { CallbackQuery: { } callbackQuery }:
|
||||
CallbackQueryHandler.Where(k => callbackQuery.Data!.StartsWith(k.Key))
|
||||
.Select(async k =>
|
||||
{
|
||||
await k.Value!(client, callbackQuery, ctx);
|
||||
return k;
|
||||
});
|
||||
break;
|
||||
case { InlineQuery: { } inlineQuery }:
|
||||
InlineHandler.Where(k => inlineQuery.Id.StartsWith(k.Key)).Select(async k =>
|
||||
{
|
||||
await k.Value!(client, inlineQuery, ctx);
|
||||
return k;
|
||||
});
|
||||
break;
|
||||
case { PreCheckoutQuery: { } preCheckoutQuery }:
|
||||
if (PreCheckoutHandler != null) await PreCheckoutHandler(client, preCheckoutQuery, ctx);
|
||||
break;
|
||||
default:
|
||||
// ReSharper disable once AsyncVoidLambda
|
||||
DefaultUpdateHandler.ForEach(async k => await k!(client, update, ctx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is KeyNotFoundException)
|
||||
Logger.Log(LogLevel.Warning, new EventId(), ex, "Key not found: ");
|
||||
else
|
||||
Logger.Log(LogLevel.Error, new EventId(), ex, "Caught exception in UpdateHandler: ");
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "AsyncVoidLambda")]
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await AddAttributes(cancellationToken);
|
||||
try
|
||||
{
|
||||
await AddAttributes(cancellationToken);
|
||||
|
||||
|
||||
|
||||
Client.StartReceiving(
|
||||
UpdateHandler,
|
||||
Config.errorHandler ?? ((_, _, _) => Task.CompletedTask),
|
||||
Config.ReceiverOptions,
|
||||
cancellationToken);
|
||||
Client.StartReceiving(
|
||||
UpdateHandler,
|
||||
Config.errorHandler ?? ((_, ex, _) =>
|
||||
{
|
||||
Logger.LogError(ex, "Catched error in telegram bot working: ");
|
||||
return Task.CompletedTask;
|
||||
}),
|
||||
Config.ReceiverOptions,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(LogLevel.Critical, new EventId(), ex, "Failed to start. Catched exception: ");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await Client.DropPendingUpdates(cancellationToken);
|
||||
try
|
||||
{
|
||||
await Client.DropPendingUpdates(cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogCritical(ex, "Failed to stop. Exception: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>1.0.0</Version>
|
||||
<Version>1.0.3</Version>
|
||||
<Authors>yawaflua</Authors>
|
||||
<Title>yawaflua.Telegram.Net</Title>
|
||||
<Description>Telegram.Bots extender pack, what provides to user attributes, which can used with services</Description>
|
||||
@@ -19,8 +19,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.3" />
|
||||
<PackageReference Include="Telegram.Bot" Version="22.4.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="(6.0.0,)" />
|
||||
<PackageReference Include="Telegram.Bot" Version="22.4.*" />
|
||||
<None Include="..\README.md" Pack="true" PackagePath="\"/>
|
||||
<None Include="..\LICENSE" Pack="true" PackagePath=""/>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -10,6 +10,7 @@ using Telegram.Net.Services;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
@@ -22,6 +23,7 @@ namespace Telegram.Tests
|
||||
{
|
||||
private TelegramBotConfig _configMock;
|
||||
private ServiceCollection _services;
|
||||
private ILogger<TelegramHostedService> logger;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@@ -31,7 +33,8 @@ namespace Telegram.Tests
|
||||
.AddJsonFile("appsettings.json", false)
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var loggerFactory = new LoggerFactory();
|
||||
logger = loggerFactory.CreateLogger<TelegramHostedService>();
|
||||
_configMock = new TelegramBotConfig(conf.GetValue<string>("telegram_test_token") ?? throw new Exception("Provide telegram token first"));
|
||||
_services = new ServiceCollection();
|
||||
}
|
||||
@@ -67,7 +70,7 @@ namespace Telegram.Tests
|
||||
public void AddAttributes_RegistersCommandHandlersCorrectly()
|
||||
{
|
||||
_services.AddSingleton<TestHandler>();
|
||||
var service = new TelegramHostedService(_configMock, _services);
|
||||
var service = new TelegramHostedService(_configMock, _services, logger);
|
||||
|
||||
service.AddAttributes(CancellationToken.None).Wait();
|
||||
|
||||
@@ -132,8 +135,8 @@ namespace Telegram.Tests
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<TelegramHostedServiceTests.TestHandler>();
|
||||
_botClientMock = new Mock<ITelegramBotClient>();
|
||||
|
||||
_hostedService = new TelegramHostedService(_configMock.Object, services);
|
||||
var logger = new LoggerFactory().CreateLogger<TelegramHostedService>();
|
||||
_hostedService = new TelegramHostedService(_configMock.Object, services, logger);
|
||||
_hostedService.AddAttributes(CancellationToken.None).Wait();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user