19 Commits

Author SHA1 Message Date
Dmitri Shimanski
529378c0bb Create CONTRIBUTING.md 2025-03-29 17:18:13 +03:00
Dmitri Shimanski
2371180bd4 Merge pull request #5 from yawaflua/develop
pre-1.0.3
Fix error, when many commands with one base command(/start, /startapp, etc) not working properly.
Fix versions of dependencies for better compatability
2025-03-29 03:14:29 +03:00
Dmitri Shimanski
a691064881 Change version logic from ">=" to "(X,)" 2025-03-28 16:44:18 +03:00
Dmitri Shimanski
0a7e3d4b49 Fix warnings and change versions of dependencies for better compatability 2025-03-28 16:35:38 +03:00
Dmitri Shimanski
7b7b2effca Fix many StartWith handler 2025-03-28 16:15:07 +03:00
Dmitri Shimanski
9b0578092b Update README.md 2025-03-21 01:08:34 +02:00
Dmitri Shimanski
38df51f4b3 Merge pull request #4 from yawaflua/develop
pre-v1.0.2 fix
2025-03-21 01:07:42 +02:00
Dmitri Shimanski
55079122ac Merge remote-tracking branch 'origin/develop' into develop 2025-03-21 01:06:07 +02:00
Dmitri Shimanski
c2e04598f6 Fix error with providing attributes 2025-03-21 01:05:55 +02:00
Dmitri Shimanski
4da17d8bf0 Merge branch 'master' into develop 2025-03-21 00:51:37 +02:00
Dmitri Shimanski
cf9a5c14ef Change version 2025-03-21 00:51:00 +02:00
Dmitri Shimanski
3094fcbabe Fix error with broken dependencies. 2025-03-21 00:49:01 +02:00
Dmitri Shimanski
59a94c9f97 Update README.md 2025-03-21 00:10:16 +02:00
Dmitri Shimanski
4777fc3e73 Merge pull request #3 from yawaflua/develop
pre-v1.0.1 pr
2025-03-20 23:38:21 +02:00
Dmitri Shimanski
f82f5cd291 Add logger in error handler 2025-03-20 23:37:00 +02:00
Dmitri Shimanski
e442227c78 Merge remote-tracking branch 'origin/develop' into develop 2025-03-20 23:34:44 +02:00
Dmitri Shimanski
343ab4de7f Add logger 2025-03-20 23:34:34 +02:00
Dmitri Shimanski
779a69245f Fix name of package 2025-03-19 16:13:27 +02:00
Dmitri Shimanski
6f0d20964b Fix Telegram.Examples.csproj because thats been package 2025-03-19 16:08:37 +02:00
10 changed files with 329 additions and 156 deletions

67
CONTRIBUTING.md Normal file
View 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!

View File

@@ -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();

View File

@@ -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>

View File

@@ -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)
{

View File

@@ -0,0 +1,4 @@
{
"ExampleMessage": "Test!",
"telegram_test_token": "PROVIDE_TOKEN"
}

View File

@@ -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).

View File

@@ -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;
}
}

View File

@@ -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: ");
}
}
}

View File

@@ -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>

View File

@@ -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();
}