Merge pull request #55 from MajMcCloud/development

Integrating development branch into master
This commit is contained in:
Florian Zevedei 2023-12-26 17:32:51 +01:00 committed by GitHub
commit d56b26a788
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 24 deletions

View File

@ -59,6 +59,7 @@ BitTorrent: `TYVZSykaVT1nKZnz9hjDgBRNB9VavU1bpW`
* [TaggedButtonGrid](#tagged-button-grid) * [TaggedButtonGrid](#tagged-button-grid)
* [CheckedButtonList](#checked-button-list) * [CheckedButtonList](#checked-button-list)
* [MultiToggleButton](#multi-toggle-button) * [MultiToggleButton](#multi-toggle-button)
- [Localizations](#localizations)
- [Groups](#groups) - [Groups](#groups)
* [SplitterForm](#splitter-form) * [SplitterForm](#splitter-form)
* [GroupForm](#group-form) * [GroupForm](#group-form)
@ -714,6 +715,19 @@ Check the example project [TelegramBotBase.Test/Tests/Controls/CheckedButtonList
Check the example project [TelegramBotBase.Test/Tests/Controls/MultiToggleButtonForm.cs](TelegramBotBase.Test/Tests/Controls/MultiToggleButtonForm.cs) Check the example project [TelegramBotBase.Test/Tests/Controls/MultiToggleButtonForm.cs](TelegramBotBase.Test/Tests/Controls/MultiToggleButtonForm.cs)
## Localizations
The current available languages for controls are:
- English
- German
- Persian
You can add other languages easily by creating a subclass of the [TelegramBotBase/Localizations/Localization.cs](TelegramBotBase/Localizations/Localization.cs) class.
To set the default language set the *Language* property on the static [TelegramBotBase/Localizations/Default.cs](TelegramBotBase/Localizations/Default.cs) instance.
## Groups ## Groups
For groups, there are multiple different tools which help to work with and allows bot also to manage For groups, there are multiple different tools which help to work with and allows bot also to manage

View File

@ -15,11 +15,14 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" /> <PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="TelegramBotBase" Version="6.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TelegramBotBase\TelegramBotBase.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,14 @@
using System;
namespace TelegramBotBase.Base
{
public class ErrorResult : EventArgs
{
public ErrorResult(Exception exception)
{
Exception = exception;
}
public Exception Exception { get; }
}
}

View File

@ -18,6 +18,7 @@ namespace TelegramBotBase.Base;
public class MessageClient public class MessageClient
{ {
private static readonly object EvOnMessageLoop = new(); private static readonly object EvOnMessageLoop = new();
private static readonly object EvOnReceiveError = new();
private static object __evOnMessage = new(); private static object __evOnMessage = new();
@ -27,6 +28,14 @@ public class MessageClient
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
/// <summary>
/// Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before
// start polling. If set to true Telegram.Bot.Polling.ReceiverOptions.AllowedUpdates
// should be set to not null, otherwise Telegram.Bot.Polling.ReceiverOptions.AllowedUpdates
// will effectively be set to receive all Telegram.Bot.Types.Updates.
/// </summary>
public bool ThrowPendingUpdates { get; set; }
public MessageClient(string apiKey) public MessageClient(string apiKey)
{ {
@ -113,6 +122,8 @@ public class MessageClient
var receiverOptions = new ReceiverOptions(); var receiverOptions = new ReceiverOptions();
receiverOptions.ThrowPendingUpdates = ThrowPendingUpdates;
TelegramClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, receiverOptions, TelegramClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, receiverOptions,
_cancellationTokenSource.Token); _cancellationTokenSource.Token);
} }
@ -128,22 +139,12 @@ public class MessageClient
await OnMessageLoop(new UpdateResult(update, null)); await OnMessageLoop(new UpdateResult(update, null));
} }
public Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, public async Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (exception is ApiRequestException exApi) await OnReceiveError(new ErrorResult(exception));
{
Console.WriteLine($"Telegram API Error:\n[{exApi.ErrorCode}]\n{exApi.Message}");
}
else
{
Console.WriteLine(exception.ToString());
}
return Task.CompletedTask;
} }
/// <summary> /// <summary>
/// This will return the current list of bot commands. /// This will return the current list of bot commands.
/// </summary> /// </summary>
@ -186,7 +187,41 @@ public class MessageClient
public async Task OnMessageLoop(UpdateResult update) public async Task OnMessageLoop(UpdateResult update)
{ {
await (Events[EvOnMessageLoop] as Async.AsyncEventHandler<UpdateResult>)?.Invoke(this, update); var eventHandlers = (Events[EvOnMessageLoop] as Async.AsyncEventHandler<UpdateResult>)?.Invoke(this, update);
if (eventHandlers != null)
{
await eventHandlers;
}
}
public event Async.AsyncEventHandler<ErrorResult> ReceiveError
{
add => Events.AddHandler(EvOnReceiveError, value);
remove => Events.RemoveHandler(EvOnReceiveError, value);
}
public async Task OnReceiveError(ErrorResult update)
{
var eventHandlers = (Events[EvOnReceiveError] as Async.AsyncEventHandler<ErrorResult>)?.Invoke(this, update);
if (eventHandlers != null)
{
await eventHandlers;
return;
}
//Fallback when no event handler is used.
if (update.Exception is ApiRequestException exApi)
{
Console.WriteLine($"Telegram API Error:\n[{exApi.ErrorCode}]\n{exApi.Message}");
}
else
{
Console.WriteLine(update.Exception.ToString());
}
} }
#endregion #endregion

View File

@ -207,7 +207,7 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
#region "Step 4 (Network Settings)" #region "Step 4 (Network Settings)"
public IBotCommandsStage WithProxy(string proxyAddress) public IBotCommandsStage WithProxy(string proxyAddress, bool throwPendingUpdates = false)
{ {
var url = new Uri(proxyAddress); var url = new Uri(proxyAddress);
_client = new MessageClient(_apiKey, url) _client = new MessageClient(_apiKey, url)
@ -217,11 +217,12 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
Timeout = new TimeSpan(0, 1, 0) Timeout = new TimeSpan(0, 1, 0)
}, },
}; };
_client.ThrowPendingUpdates = throwPendingUpdates;
return this; return this;
} }
public IBotCommandsStage NoProxy() public IBotCommandsStage NoProxy(bool throwPendingUpdates = false)
{ {
_client = new MessageClient(_apiKey) _client = new MessageClient(_apiKey)
{ {
@ -230,11 +231,12 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
Timeout = new TimeSpan(0, 1, 0) Timeout = new TimeSpan(0, 1, 0)
} }
}; };
_client.ThrowPendingUpdates = throwPendingUpdates;
return this; return this;
} }
public IBotCommandsStage WithBotClient(TelegramBotClient tgclient) public IBotCommandsStage WithBotClient(TelegramBotClient tgclient, bool throwPendingUpdates = false)
{ {
_client = new MessageClient(_apiKey, tgclient) _client = new MessageClient(_apiKey, tgclient)
{ {
@ -243,11 +245,12 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
Timeout = new TimeSpan(0, 1, 0) Timeout = new TimeSpan(0, 1, 0)
} }
}; };
_client.ThrowPendingUpdates = throwPendingUpdates;
return this; return this;
} }
public IBotCommandsStage WithHostAndPort(string proxyHost, int proxyPort) public IBotCommandsStage WithHostAndPort(string proxyHost, int proxyPort, bool throwPendingUpdates = false)
{ {
_client = new MessageClient(_apiKey, proxyHost, proxyPort) _client = new MessageClient(_apiKey, proxyHost, proxyPort)
{ {
@ -256,10 +259,11 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
Timeout = new TimeSpan(0, 1, 0) Timeout = new TimeSpan(0, 1, 0)
} }
}; };
_client.ThrowPendingUpdates = throwPendingUpdates;
return this; return this;
} }
public IBotCommandsStage WithHttpClient(HttpClient tgclient) public IBotCommandsStage WithHttpClient(HttpClient tgclient, bool throwPendingUpdates = false)
{ {
_client = new MessageClient(_apiKey, tgclient) _client = new MessageClient(_apiKey, tgclient)
{ {
@ -268,6 +272,7 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
Timeout = new TimeSpan(0, 1, 0) Timeout = new TimeSpan(0, 1, 0)
} }
}; };
_client.ThrowPendingUpdates = throwPendingUpdates;
return this; return this;
} }

View File

@ -9,22 +9,25 @@ public interface INetworkingSelectionStage
/// Chooses a proxy as network configuration. /// Chooses a proxy as network configuration.
/// </summary> /// </summary>
/// <param name="proxyAddress"></param> /// <param name="proxyAddress"></param>
/// <param name="throwPendingUpdates">Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before start polling.</param>
/// <returns></returns> /// <returns></returns>
IBotCommandsStage WithProxy(string proxyAddress); IBotCommandsStage WithProxy(string proxyAddress, bool throwPendingUpdates = false);
/// <summary> /// <summary>
/// Do not choose a proxy as network configuration. /// Do not choose a proxy as network configuration.
/// </summary> /// </summary>
/// <param name="throwPendingUpdates">Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before start polling.</param>
/// <returns></returns> /// <returns></returns>
IBotCommandsStage NoProxy(); IBotCommandsStage NoProxy(bool throwPendingUpdates = false);
/// <summary> /// <summary>
/// Chooses a custom instance of TelegramBotClient. /// Chooses a custom instance of TelegramBotClient.
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="throwPendingUpdates">Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before start polling.</param>
/// <returns></returns> /// <returns></returns>
IBotCommandsStage WithBotClient(TelegramBotClient client); IBotCommandsStage WithBotClient(TelegramBotClient client, bool throwPendingUpdates = false);
/// <summary> /// <summary>
@ -32,13 +35,15 @@ public interface INetworkingSelectionStage
/// </summary> /// </summary>
/// <param name="proxyHost"></param> /// <param name="proxyHost"></param>
/// <param name="Port"></param> /// <param name="Port"></param>
/// <param name="throwPendingUpdates">Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before start polling.</param>
/// <returns></returns> /// <returns></returns>
IBotCommandsStage WithHostAndPort(string proxyHost, int Port); IBotCommandsStage WithHostAndPort(string proxyHost, int Port, bool throwPendingUpdates = false);
/// <summary> /// <summary>
/// Uses a custom http client. /// Uses a custom http client.
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="throwPendingUpdates">Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before start polling.</param>
/// <returns></returns> /// <returns></returns>
IBotCommandsStage WithHttpClient(HttpClient client); IBotCommandsStage WithHttpClient(HttpClient client, bool throwPendingUpdates = false);
} }