Merge branch 'development' of https://github.com/MajMcCloud/TelegramBotFramework into development

This commit is contained in:
FlorianDahn 2022-02-08 17:01:40 +01:00
commit a0b87887f7
75 changed files with 1418 additions and 775 deletions

143
README.md
View File

@ -19,15 +19,17 @@ Download a release: [Releases](https://github.com/MajMcCloud/TelegramBotFramewor
Donations Donations
Bitcoin: 1NqyGWmZg8HLp9qQELbf6bChEoba3mxaFc Bitcoin: 1GoUJYMwAvBipQTfw2FKydAz12J8RDyeJs / bc1qqwlp0p5ley29lsu6jhe0qv7s7963kfc7d0m53d
ETH: 0x795B70CFC27C69603ce115F2b450cbAC5a5460D0 ETH: 0xAf3835104c2C3E5b3e721FA2c7365955e87DB931
Litecoin: LM5iCN6Nz22wAi8LSFnKgdGGWEtxWfJZXv Litecoin: LRhF1eB7kneFontcDRDU8YjJhEm2GoYHch
DASH: Xb2qyVefvbKTXusHoxZ4Soja2S6R4vLsSr DASH: XudiUwWtSmAJj1QDdVW7jocQumJFLsyoGZ
Paypal: https://paypal.me/majmccloud TRON: TYVZSykaVT1nKZnz9hjDgBRNB9VavU1bpW
BITTORRENT: TYVZSykaVT1nKZnz9hjDgBRNB9VavU1bpW
Thanks ! Thanks !
@ -37,6 +39,7 @@ Thanks !
## Index ## Index
- [Introduction](#introduction) - [Introduction](#introduction)
- [How to Start](#how-to-start) - [How to Start](#how-to-start)
- [Quick Start](#quick-start)
- [Message Handling](#message-handling) - [Message Handling](#message-handling)
* [Example #0 - System Calls](#add-some-system-calls-example-0---system-calls) * [Example #0 - System Calls](#add-some-system-calls-example-0---system-calls)
@ -143,11 +146,21 @@ It needs to be a subclass of "FormBase" you will find in Namespace TelegramBotBa
``` ```
//Prepare the System //Prepare the System (New in V5)
BotBase<StartForm> bb = new BotBase<StartForm>("{YOUR API KEY}"); var bb = BotBaseBuilder
.Create()
.WithAPIKey("{YOUR API KEY}")
.DefaultMessageLoop()
.WithStartForm<StartForm>()
.NoProxy()
.CustomCommands(a =>
{
a.Start("Starts the bot")
//Add Systemcommands if you like, you could catch them later })
bb.BotCommands.Add(new BotCommand() { Command = "start", Description = "Starts the bot" }); .NoSerialization()
.UseEnglish()
.Build();
//Update bot commands to botfather //Update bot commands to botfather
bb.UploadBotCommands().Wait(); bb.UploadBotCommands().Wait();
@ -169,11 +182,9 @@ public class StartForm : FormBase
} }
//Gets invoked during Navigation to this form //Gets invoked during Navigation to this form
public override async Task Init(params object[] param)
{ //Init() got replaced with event handler
}
//Opened() got replaced with event handler //Opened() got replaced with event handler
@ -231,6 +242,28 @@ var tf = new TestForm();
await this.NavigateTo(tf); await this.NavigateTo(tf);
``` ```
## Quick Start:
When migrating from a previous version or starting completely new, all these options can be a bit overwhelming.
For this I added a QuickStart option, directly after the Create call. It just need basic parameters like in earlier versions.
```
//Prepare the System (New in V5)
var bb = BotBaseBuilder
.Create()
.QuickStart<StartForm>("{YOUR API KEY}")
.Build();
//Start your Bot
bb.Start();
```
## Message Handling ## Message Handling
All examples are within the test project, so just try it out on your own. All examples are within the test project, so just try it out on your own.
@ -254,12 +287,24 @@ Below we have 4 options.
``` ```
BotBase<Start> bb = new BotBase<Start>("{YOUR API KEY}"); var bb = BotBaseBuilder
.Create()
.WithAPIKey("{YOUR API KEY}")
.DefaultMessageLoop()
.WithStartForm<Start>()
.NoProxy()
.CustomCommands(a =>
{
a.Start("Starts the bot");
a.Add("form1","Opens test form 1" );
a.Add("form2", "Opens test form 2" );
a.Add("params", "Returns all send parameters as a message." );
bb.BotCommands.Add(new BotCommand() { Command = "start", Description = "Starts the bot" });
bb.BotCommands.Add(new BotCommand() { Command = "form1", Description = "Opens test form 1" }); })
bb.BotCommands.Add(new BotCommand() { Command = "form2", Description = "Opens test form 2" }); .NoSerialization()
bb.BotCommands.Add(new BotCommand() { Command = "params", Description = "Returns all send parameters as a message." }); .UseEnglish()
.Build();
bb.BotCommand += async (s, en) => bb.BotCommand += async (s, en) =>
{ {
@ -965,13 +1010,19 @@ In general you didn't need to do more then, to keep the actual form:
``` ```
//Prepare the System //Prepare the System
BotBase<StartForm> bb = new BotBase<StartForm>("{YOUR API KEY}"); var bb = BotBaseBuilder
.Create()
//Add Systemcommands if you like, you could catch them later .WithAPIKey("{YOUR API KEY}")
bb.SystemCalls.Add("/start"); .DefaultMessageLoop()
.WithStartForm<StartForm>()
//Set the statemachine and enable it .NoProxy()
bb.StateMachine = new TelegramBotBase.States.SimpleJSONStateMachine(AppContext.BaseDirectory + "config\\states.json"); .CustomCommands(a =>
{
a.Start("Starts the bot");
})
.UseSimpleJSON(AppContext.BaseDirectory + "config\\states.json")
.UseEnglish()
.Build();
//Start your Bot //Start your Bot
bb.Start(); bb.Start();
@ -984,13 +1035,19 @@ In general you didn't need to do more then, to keep the actual form:
``` ```
//Prepare the System //Prepare the System
BotBase<StartForm> bb = new BotBase<StartForm>("{YOUR API KEY}"); var bb = BotBaseBuilder
.Create()
//Add Systemcommands if you like, you could catch them later .WithAPIKey("{YOUR API KEY}")
bb.SystemCalls.Add("/start"); .DefaultMessageLoop()
.WithStartForm<StartForm>()
//Set the statemachine and enable it .NoProxy()
bb.StateMachine = new TelegramBotBase.States.JSONStateMachine(AppContext.BaseDirectory + "config\\states.json"); .CustomCommands(a =>
{
a.Start("Starts the bot");
})
.UseJSON(AppContext.BaseDirectory + "config\\states.json")
.UseEnglish()
.Build();
//Start your Bot //Start your Bot
bb.Start(); bb.Start();
@ -1004,13 +1061,19 @@ In general you didn't need to do more then, to keep the actual form:
``` ```
//Prepare the System //Prepare the System
BotBase<StartForm> bb = new BotBase<StartForm>("{YOUR API KEY}"); var bb = BotBaseBuilder
.Create()
//Add Systemcommands if you like, you could catch them later .WithAPIKey("{YOUR API KEY}")
bb.SystemCalls.Add("/start"); .DefaultMessageLoop()
.WithStartForm<StartForm>()
//Set the statemachine and enable it .NoProxy()
bb.StateMachine = new TelegramBotBase.States.XMLStateMachine(AppContext.BaseDirectory + "config\\states.xml"); .CustomCommands(a =>
{
a.Start("Starts the bot");
})
.UseXML(AppContext.BaseDirectory + "config\\states.xml")
.UseEnglish()
.Build();
//Start your Bot //Start your Bot
bb.Start(); bb.Start();

View File

@ -0,0 +1,61 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading.Tasks;
using Telegram.Bot.Types.InputFiles;
using Telegram.Bot.Types;
using TelegramBotBase.Sessions;
using TelegramBotBase.Form;
namespace TelegramBotBase.Extensions.Images
{
public static class ImageExtensions
{
public static Stream ToStream(this Image image, ImageFormat format)
{
var stream = new System.IO.MemoryStream();
image.Save(stream, format);
stream.Position = 0;
return stream;
}
/// <summary>
/// Sends an image
/// </summary>
/// <param name="image"></param>
/// <param name="name"></param>
/// <param name="buttons"></param>
/// <param name="replyTo"></param>
/// <param name="disableNotification"></param>
/// <returns></returns>
public static async Task<Message> SendPhoto(this DeviceSession session, Image image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false)
{
using (var fileStream = ToStream(image, ImageFormat.Png))
{
InputOnlineFile fts = new InputOnlineFile(fileStream, name);
return await session.SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification);
}
}
/// <summary>
/// Sends an image
/// </summary>
/// <param name="image"></param>
/// <param name="name"></param>
/// <param name="buttons"></param>
/// <param name="replyTo"></param>
/// <param name="disableNotification"></param>
/// <returns></returns>
public static async Task<Message> SendPhoto(this DeviceSession session, Bitmap image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false)
{
using (var fileStream = ToStream(image, ImageFormat.Png))
{
InputOnlineFile fts = new InputOnlineFile(fileStream, name);
return await session.SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification);
}
}
}
}

View File

@ -0,0 +1,8 @@
# TelegramBotBase.Extensions.Images
[![NuGet version (TelegramBotBase)](https://img.shields.io/nuget/v/TelegramBotBase.Extensions.Images.svg?style=flat-square)](https://www.nuget.org/packages/TelegramBotBase.Extensions.Images/)
[![telegram chat](https://img.shields.io/badge/Support_Chat-Telegram-blue.svg?style=flat-square)](https://www.t.me/tgbotbase)
[![license](https://img.shields.io/github/license/MajMcCloud/telegrambotframework.svg?style=flat-square&maxAge=2592000&label=License)](https://raw.githubusercontent.com/MajMcCloud/TelegramBotFramework/master/LICENCE.md)
[![downloads](https://img.shields.io/nuget/dt/TelegramBotBase.Extensions.Images.svg?style=flat-square&label=Package%20Downloads)](https://www.nuget.org/packages/TelegramBotBase.Extensions.Images)

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net5;netcoreapp3.1;net6</TargetFrameworks>
<RepositoryUrl>https://github.com/MajMcCloud/TelegramBotFramework</RepositoryUrl>
<PackageProjectUrl>https://github.com/MajMcCloud/TelegramBotFramework</PackageProjectUrl>
<Copyright>MIT</Copyright>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="Telegram.Bot" Version="17.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TelegramBotBase\TelegramBotBase.csproj" />
</ItemGroup>
</Project>

View File

@ -8,6 +8,8 @@ using TelegramBotBase;
using TelegramBotBase.Form; using TelegramBotBase.Form;
using TelegramBotBaseTest.Tests; using TelegramBotBaseTest.Tests;
using TelegramBotBase.Commands; using TelegramBotBase.Commands;
using TelegramBotBase.Builder;
namespace TelegramBotBaseTest namespace TelegramBotBaseTest
{ {
class Program class Program
@ -15,14 +17,27 @@ namespace TelegramBotBaseTest
static void Main(string[] args) static void Main(string[] args)
{ {
BotBase<Start> bb = new BotBase<Start>(APIKey); String APIKey = "";
var bb = BotBaseBuilder
.Create()
.WithAPIKey(APIKey)
.DefaultMessageLoop()
.WithStartForm<Start>()
.NoProxy()
.CustomCommands(a =>
{
a.Start("Starts the bot");
a.Help("Should show you some help");
a.Settings("Should show you some settings");
a.Add("form1", "Opens test form 1");
a.Add("form2", "Opens test form 2");
a.Add("params", "Returns all send parameters as a message.");
})
.NoSerialization()
.UseEnglish()
.Build();
bb.BotCommands.AddStartCommand("Starts the bot");
bb.BotCommands.AddHelpCommand("Should show you some help");
bb.BotCommands.AddSettingsCommand("Should show you some settings");
bb.BotCommands.Add(new BotCommand() { Command = "form1", Description = "Opens test form 1" });
bb.BotCommands.Add(new BotCommand() { Command = "form2", Description = "Opens test form 2" });
bb.BotCommands.Add(new BotCommand() { Command = "params", Description = "Returns all send parameters as a message." });
bb.BotCommand += async (s, en) => bb.BotCommand += async (s, en) =>
{ {
@ -54,7 +69,7 @@ namespace TelegramBotBaseTest
case "/params": case "/params":
String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b); String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b);
await en.Device.Send("Your parameters are: " + m, replyTo: en.Device.LastMessageId); await en.Device.Send("Your parameters are: " + m, replyTo: en.Device.LastMessageId);
en.Handled = true; en.Handled = true;
@ -69,7 +84,7 @@ namespace TelegramBotBaseTest
bb.SetSetting(TelegramBotBase.Enums.eSettings.LogAllMessages, true); bb.SetSetting(TelegramBotBase.Enums.eSettings.LogAllMessages, true);
bb.Message += (s,en) => bb.Message += (s, en) =>
{ {
Console.WriteLine(en.DeviceId + " " + en.Message.MessageText + " " + (en.Message.RawData ?? "")); Console.WriteLine(en.DeviceId + " " + en.Message.MessageText + " " + (en.Message.RawData ?? ""));
}; };

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.1;net5</TargetFrameworks> <TargetFrameworks>netcoreapp3.1;net5;net6</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
</PropertyGroup> </PropertyGroup>
@ -27,6 +27,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\TelegramBotBase.Extensions.Images\TelegramBotBase.Extensions.Images.csproj" />
<ProjectReference Include="..\TelegramBotBase\TelegramBotBase.csproj" /> <ProjectReference Include="..\TelegramBotBase\TelegramBotBase.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -48,26 +48,6 @@ namespace TelegramBotBaseTest.Tests.Controls
} }
} }
public override async Task Load(MessageResult message)
{
}
public override async Task Action(MessageResult message)
{
}
public override async Task Render(MessageResult message)
{
}
} }
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles; using Telegram.Bot.Types.InputFiles;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;

View File

@ -49,17 +49,6 @@ namespace TelegramBotBaseTest.Tests.Datasources
} }
} }
public override async Task Load(MessageResult message)
{
}
public override async Task Render(MessageResult message)
{
}
} }
} }

View File

@ -16,16 +16,9 @@ namespace TelegramBotBaseTest.Tests.Navigation
public Start() public Start()
{ {
this.Closed += Start_Closed;
} }
private async Task Start_Closed(object sender, EventArgs e)
{
if (msg == null)
return;
await Device.DeleteMessage(msg);
}
public override async Task Load(MessageResult message) public override async Task Load(MessageResult message)
{ {
@ -49,12 +42,18 @@ namespace TelegramBotBaseTest.Tests.Navigation
//Create navigation controller and navigate to it, keep the current form as root form so we can get back to here later //Create navigation controller and navigate to it, keep the current form as root form so we can get back to here later
var nc = new CustomController(this); var nc = new CustomController(this);
nc.ForceCleanupOnLastPop = true;
var f1 = new Form1(); var f1 = new Form1();
await nc.PushAsync(f1);
await NavigateTo(nc); await NavigateTo(nc);
await nc.PushAsync(f1); if (msg == null)
return;
await Device.DeleteMessage(msg);
break; break;
@ -66,6 +65,10 @@ namespace TelegramBotBaseTest.Tests.Navigation
await NavigateTo(mn); await NavigateTo(mn);
if (msg == null)
return;
await Device.DeleteMessage(msg);
break; break;
} }

View File

@ -51,10 +51,10 @@ namespace TelegramBotBaseTest.Tests
default: default:
if (message.RawMessageData == null) if (message.UpdateData == null)
return; return;
this.LastMessage = message.RawMessageData.Message.Text; this.LastMessage = message.Message.Text;
break; break;
} }

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Extensions.Images;
using TelegramBotBase.Form; using TelegramBotBase.Form;
namespace TelegramBotBaseTest.Tests namespace TelegramBotBaseTest.Tests

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles; using Telegram.Bot.Types.InputFiles;
@ -14,7 +15,11 @@ namespace TelegramBotBase.Base
/// </summary> /// </summary>
public class DataResult : ResultBase public class DataResult : ResultBase
{ {
public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; }
//public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; }
public UpdateResult UpdateData { get; set; }
public Contact Contact public Contact Contact
{ {
@ -64,11 +69,20 @@ namespace TelegramBotBase.Base
} }
} }
public Telegram.Bot.Types.Enums.MessageType Type public Telegram.Bot.Types.Enums.MessageType Type
{ {
get get
{ {
return this.RawMessageData?.Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown; return this.Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown;
}
}
public override Message Message
{
get
{
return this.UpdateData?.Message;
} }
} }
@ -86,24 +100,15 @@ namespace TelegramBotBase.Base
} }
} }
public DataResult(UpdateResult update)
public DataResult(Telegram.Bot.Args.MessageEventArgs rawdata)
{ {
this.RawMessageData = rawdata; this.UpdateData = update;
this.Message = rawdata.Message;
} }
public DataResult(MessageResult message)
{
this.RawMessageData = message.RawMessageData;
this.Message = message.Message;
this.Client = message.Client;
}
public async Task<InputOnlineFile> DownloadDocument() public async Task<InputOnlineFile> DownloadDocument()
{ {
var encryptedContent = new System.IO.MemoryStream(this.Document.FileSize); var encryptedContent = new System.IO.MemoryStream(this.Document.FileSize.Value);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Document.FileId, encryptedContent); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Document.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, this.Document.FileName); return new InputOnlineFile(encryptedContent, this.Document.FileName);
@ -156,13 +161,13 @@ namespace TelegramBotBase.Base
ms.Position = 0; ms.Position = 0;
var sr = new StreamReader(ms, encoding); var sr = new StreamReader(ms, encoding);
return sr.ReadToEnd(); return sr.ReadToEnd();
} }
public async Task<InputOnlineFile> DownloadVideo() public async Task<InputOnlineFile> DownloadVideo()
{ {
var encryptedContent = new System.IO.MemoryStream(this.Video.FileSize); var encryptedContent = new System.IO.MemoryStream(this.Video.FileSize.Value);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Video.FileId, encryptedContent); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Video.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, ""); return new InputOnlineFile(encryptedContent, "");
@ -179,7 +184,7 @@ namespace TelegramBotBase.Base
public async Task<InputOnlineFile> DownloadAudio() public async Task<InputOnlineFile> DownloadAudio()
{ {
var encryptedContent = new System.IO.MemoryStream(this.Audio.FileSize); var encryptedContent = new System.IO.MemoryStream(this.Audio.FileSize.Value);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Audio.FileId, encryptedContent); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Audio.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, ""); return new InputOnlineFile(encryptedContent, "");
@ -197,7 +202,7 @@ namespace TelegramBotBase.Base
public async Task<InputOnlineFile> DownloadPhoto(int index) public async Task<InputOnlineFile> DownloadPhoto(int index)
{ {
var photo = this.Photos[index]; var photo = this.Photos[index];
var encryptedContent = new System.IO.MemoryStream(photo.FileSize); var encryptedContent = new System.IO.MemoryStream(photo.FileSize.Value);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(photo.FileId, encryptedContent); var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(photo.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, ""); return new InputOnlineFile(encryptedContent, "");

View File

@ -5,8 +5,13 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot.Exceptions;
using Telegram.Bot;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Extensions.Polling;
namespace TelegramBotBase.Base namespace TelegramBotBase.Base
{ {
@ -19,16 +24,20 @@ namespace TelegramBotBase.Base
public String APIKey { get; set; } public String APIKey { get; set; }
public Telegram.Bot.TelegramBotClient TelegramClient { get; set; } public ITelegramBotClient TelegramClient { get; set; }
private EventHandlerList __Events { get; set; } = new EventHandlerList(); private EventHandlerList __Events { get; set; } = new EventHandlerList();
private static object __evOnMessageLoop = new object();
private static object __evOnMessage = new object(); private static object __evOnMessage = new object();
private static object __evOnMessageEdit = new object(); private static object __evOnMessageEdit = new object();
private static object __evCallbackQuery = new object(); private static object __evCallbackQuery = new object();
CancellationTokenSource __cancellationTokenSource;
public MessageClient(String APIKey) public MessageClient(String APIKey)
{ {
@ -47,13 +56,22 @@ namespace TelegramBotBase.Base
Prepare(); Prepare();
} }
public MessageClient(String APIKey, Uri proxyUrl)
public MessageClient(String APIKey, Uri proxyUrl, NetworkCredential credential = null)
{ {
this.APIKey = APIKey; this.APIKey = APIKey;
var proxy = new WebProxy(proxyUrl); var proxy = new WebProxy(proxyUrl)
{
Credentials = credential
};
this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, proxy); var httpClient = new HttpClient(
new HttpClientHandler { Proxy = proxy, UseProxy = true }
);
this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, httpClient);
Prepare(); Prepare();
} }
@ -70,11 +88,17 @@ namespace TelegramBotBase.Base
var proxy = new WebProxy(proxyHost, proxyPort); var proxy = new WebProxy(proxyHost, proxyPort);
this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, proxy); var httpClient = new HttpClient(
new HttpClientHandler { Proxy = proxy, UseProxy = true }
);
this.TelegramClient = new Telegram.Bot.TelegramBotClient(APIKey, httpClient);
Prepare(); Prepare();
} }
public MessageClient(String APIKey, Telegram.Bot.TelegramBotClient Client) public MessageClient(String APIKey, Telegram.Bot.TelegramBotClient Client)
{ {
this.APIKey = APIKey; this.APIKey = APIKey;
@ -88,62 +112,49 @@ namespace TelegramBotBase.Base
{ {
this.TelegramClient.Timeout = new TimeSpan(0, 0, 30); this.TelegramClient.Timeout = new TimeSpan(0, 0, 30);
this.TelegramClient.OnMessage += TelegramClient_OnMessage;
this.TelegramClient.OnMessageEdited += TelegramClient_OnMessageEdited;
this.TelegramClient.OnCallbackQuery += TelegramClient_OnCallbackQuery;
} }
private async void TelegramClient_OnMessage(object sender, Telegram.Bot.Args.MessageEventArgs e)
public void StartReceiving()
{ {
//Skip empty messages by default __cancellationTokenSource = new CancellationTokenSource();
if (e.Message == null)
return;
try var receiverOptions = new ReceiverOptions
{
var mr = new MessageResult(e);
mr.Client = this;
OnMessage(mr);
}
catch
{ {
AllowedUpdates = { } // receive all update types
};
} this.TelegramClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, receiverOptions, __cancellationTokenSource.Token);
} }
public void StopReceiving()
private async void TelegramClient_OnMessageEdited(object sender, Telegram.Bot.Args.MessageEventArgs e)
{ {
//Skip empty messages by default __cancellationTokenSource.Cancel();
if (e.Message == null)
return;
try
{
var mr = new MessageResult(e);
mr.Client = this;
OnMessageEdit(mr);
}
catch
{
}
} }
private async void TelegramClient_OnCallbackQuery(object sender, Telegram.Bot.Args.CallbackQueryEventArgs e)
public Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{ {
try OnMessageLoop(new UpdateResult(update, null));
{
var ar = new MessageResult(e);
ar.Client = this;
OnAction(ar);
}
catch
{
} return Task.CompletedTask;
} }
public Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
{
if (exception is ApiRequestException exAPI)
{
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>
@ -168,55 +179,23 @@ namespace TelegramBotBase.Base
#region "Events" #region "Events"
public event EventHandler<MessageResult> Message
public event Async.AsyncEventHandler<UpdateResult> MessageLoop
{ {
add add
{ {
this.__Events.AddHandler(__evOnMessage, value); this.__Events.AddHandler(__evOnMessageLoop, value);
} }
remove remove
{ {
this.__Events.RemoveHandler(__evOnMessage, value); this.__Events.RemoveHandler(__evOnMessageLoop, value);
} }
} }
public void OnMessage(MessageResult result) public void OnMessageLoop(UpdateResult update)
{ {
(this.__Events[__evOnMessage] as EventHandler<MessageResult>)?.Invoke(this, result); (this.__Events[__evOnMessageLoop] as Async.AsyncEventHandler<UpdateResult>)?.Invoke(this, update);
}
public event EventHandler<MessageResult> MessageEdit
{
add
{
this.__Events.AddHandler(__evOnMessageEdit, value);
}
remove
{
this.__Events.RemoveHandler(__evOnMessageEdit, value);
}
}
public void OnMessageEdit(MessageResult result)
{
(this.__Events[__evOnMessageEdit] as EventHandler<MessageResult>)?.Invoke(this, result);
}
public event EventHandler<MessageResult> Action
{
add
{
this.__Events.AddHandler(__evCallbackQuery, value);
}
remove
{
this.__Events.RemoveHandler(__evCallbackQuery, value);
}
}
public void OnAction(MessageResult result)
{
(this.__Events[__evCallbackQuery] as EventHandler<MessageResult>)?.Invoke(this, result);
} }

View File

@ -3,15 +3,16 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types;
using TelegramBotBase.Sessions; using TelegramBotBase.Sessions;
namespace TelegramBotBase.Base namespace TelegramBotBase.Base
{ {
public class MessageResult : ResultBase public class MessageResult : ResultBase
{ {
public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; }
public Telegram.Bot.Args.CallbackQueryEventArgs RawCallbackData { get; set; } public Telegram.Bot.Types.Update UpdateData { get; set; }
/// <summary> /// <summary>
/// Returns the Device/ChatId /// Returns the Device/ChatId
@ -20,8 +21,9 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return this.RawMessageData?.Message?.Chat.Id return this.UpdateData?.Message?.Chat?.Id
?? this.RawCallbackData?.CallbackQuery.Message?.Chat.Id ?? this.UpdateData?.EditedMessage?.Chat.Id
?? this.UpdateData?.CallbackQuery.Message?.Chat.Id
?? Device?.DeviceId ?? Device?.DeviceId
?? 0; ?? 0;
} }
@ -40,8 +42,9 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return this.Message?.MessageId return this.UpdateData?.Message?.MessageId
?? this.RawCallbackData?.CallbackQuery?.Message?.MessageId ?? this.Message?.MessageId
?? this.UpdateData?.CallbackQuery?.Message?.MessageId
?? 0; ?? 0;
} }
} }
@ -50,7 +53,7 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return this.RawMessageData?.Message?.Text ?? ""; return this.UpdateData?.Message?.Text ?? "";
} }
} }
@ -58,7 +61,7 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return this.RawMessageData?.Message?.Text ?? ""; return this.UpdateData?.Message?.Text ?? "";
} }
} }
@ -66,8 +69,19 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return this.RawMessageData?.Message?.Type return Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown;
?? Telegram.Bot.Types.Enums.MessageType.Unknown; }
}
public Message Message
{
get
{
return this.UpdateData?.Message
?? this.UpdateData?.EditedMessage
?? this.UpdateData?.ChannelPost
?? this.UpdateData?.EditedChannelPost
?? this.UpdateData?.CallbackQuery?.Message;
} }
} }
@ -78,7 +92,7 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return (this.RawCallbackData != null); return (this.UpdateData.CallbackQuery != null);
} }
} }
@ -133,7 +147,7 @@ namespace TelegramBotBase.Base
{ {
get get
{ {
return this.RawCallbackData?.CallbackQuery?.Data; return this.UpdateData?.CallbackQuery?.Data;
} }
} }
@ -162,14 +176,7 @@ namespace TelegramBotBase.Base
/// <returns></returns> /// <returns></returns>
public async Task ConfirmAction(String message = "", bool showAlert = false, String urlToOpen = null) public async Task ConfirmAction(String message = "", bool showAlert = false, String urlToOpen = null)
{ {
try await this.Device.ConfirmAction(this.UpdateData.CallbackQuery.Id, message, showAlert, urlToOpen);
{
await this.Client.TelegramClient.AnswerCallbackQueryAsync(this.RawCallbackData.CallbackQuery.Id, message, showAlert, urlToOpen);
}
catch
{
}
} }
public override async Task DeleteMessage() public override async Task DeleteMessage()
@ -189,16 +196,10 @@ namespace TelegramBotBase.Base
} }
public MessageResult(Telegram.Bot.Args.MessageEventArgs rawdata) public MessageResult(Telegram.Bot.Types.Update update)
{ {
this.RawMessageData = rawdata; this.UpdateData = update;
this.Message = rawdata.Message;
}
public MessageResult(Telegram.Bot.Args.CallbackQueryEventArgs callback)
{
this.RawCallbackData = callback;
this.Message = callback.CallbackQuery.Message;
} }
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot;
namespace TelegramBotBase.Base namespace TelegramBotBase.Base
{ {
@ -20,7 +21,7 @@ namespace TelegramBotBase.Base
} }
} }
public Telegram.Bot.Types.Message Message { get; set; } public virtual Telegram.Bot.Types.Message Message { get; set; }
/// <summary> /// <summary>
/// Deletes the current message /// Deletes the current message

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Telegram.Bot.Types;
using TelegramBotBase.Sessions;
namespace TelegramBotBase.Base
{
public class UpdateResult : ResultBase
{
public UpdateResult(Update rawData, DeviceSession device)
{
RawData = rawData;
Device = device;
}
/// <summary>
/// Returns the Device/ChatId
/// </summary>
public override long DeviceId
{
get
{
return this.RawData?.Message?.Chat?.Id
?? this.RawData?.CallbackQuery?.Message?.Chat?.Id
?? Device?.DeviceId
?? 0;
}
}
public Update RawData { get; set; }
public override Message Message
{
get
{
return RawData?.Message
?? RawData?.EditedMessage
?? RawData?.ChannelPost
?? RawData?.EditedChannelPost
?? RawData?.CallbackQuery?.Message;
}
}
public DeviceSession Device
{
get;
set;
}
}
}

View File

@ -3,13 +3,17 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using TelegramBotBase.Args; using TelegramBotBase.Args;
using TelegramBotBase.Attributes; using TelegramBotBase.Attributes;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Enums; using TelegramBotBase.Enums;
using TelegramBotBase.Factories.MessageLoops;
using TelegramBotBase.Form; using TelegramBotBase.Form;
using TelegramBotBase.Interfaces; using TelegramBotBase.Interfaces;
using TelegramBotBase.Sessions; using TelegramBotBase.Sessions;
@ -20,8 +24,7 @@ namespace TelegramBotBase
/// Bot base class for full Device/Context and Messagehandling /// Bot base class for full Device/Context and Messagehandling
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public class BotBase<T> public class BotBase
where T : FormBase
{ {
public MessageClient Client { get; set; } public MessageClient Client { get; set; }
@ -33,7 +36,7 @@ namespace TelegramBotBase
/// <summary> /// <summary>
/// List of all running/active sessions /// List of all running/active sessions
/// </summary> /// </summary>
public SessionBase<T> Sessions { get; set; } public SessionBase Sessions { get; set; }
/// <summary> /// <summary>
/// Contains System commands which will be available at everytime and didnt get passed to forms, i.e. /start /// Contains System commands which will be available at everytime and didnt get passed to forms, i.e. /start
@ -65,10 +68,22 @@ namespace TelegramBotBase
/// </summary> /// </summary>
public IStateMachine StateMachine { get; set; } public IStateMachine StateMachine { get; set; }
/// <summary>
/// Offers functionality to manage the creation process of the start form.
/// </summary>
public IStartFormFactory StartFormFactory { get; set; }
/// <summary>
/// Contains the message loop factory, which cares about "message-management."
/// </summary>
public IMessageLoopFactory MessageLoopFactory { get; set; }
/// <summary>
/// All internal used settings.
/// </summary>
public Dictionary<eSettings, uint> SystemSettings { get; private set; } public Dictionary<eSettings, uint> SystemSettings { get; private set; }
private BotBase() public BotBase()
{ {
this.SystemSettings = new Dictionary<eSettings, uint>(); this.SystemSettings = new Dictionary<eSettings, uint>();
@ -80,77 +95,11 @@ namespace TelegramBotBase
this.BotCommands = new List<BotCommand>(); this.BotCommands = new List<BotCommand>();
this.Sessions = new SessionBase<T>(); this.Sessions = new SessionBase();
this.Sessions.BotBase = this; this.Sessions.BotBase = this;
} }
/// <summary>
/// Simple start of your Bot with the APIKey
/// </summary>
/// <param name="apiKey"></param>
public BotBase(String apiKey, bool initClient = true) : this()
{
this.APIKey = apiKey;
if (!initClient)
return;
this.Client = new Base.MessageClient(this.APIKey);
this.Client.TelegramClient.Timeout = new TimeSpan(0, 1, 0);
this.Sessions.Client = this.Client;
}
/// <summary>
/// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary>
/// <param name="apiKey"></param>
/// <param name="proxyBaseAddress">i.e. https://127.0.0.1:10000</param>
public BotBase(String apiKey, System.Net.Http.HttpClient proxy) : this(apiKey, false)
{
this.Client = new Base.MessageClient(this.APIKey, proxy);
this.Sessions.Client = this.Client;
}
/// <summary>
/// Simple start of your Bot with the APIKey and a TelegramBotClient instance.
/// </summary>
/// <param name="apiKey"></param>
/// <param name="client"></param>
public BotBase(String apiKey, TelegramBotClient client) : this(apiKey, false)
{
this.Client = new Base.MessageClient(this.APIKey, client);
this.Sessions.Client = this.Client;
}
/// <summary>
/// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary>
/// <param name="apiKey"></param>
/// <param name="proxyBaseAddress">i.e. https://127.0.0.1:10000</param>
public BotBase(String apiKey, String proxyBaseAddress) : this(apiKey, false)
{
var url = new Uri(proxyBaseAddress);
this.Client = new Base.MessageClient(this.APIKey, url);
this.Sessions.Client = this.Client;
}
/// <summary>
/// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary>
/// <param name="apiKey"></param>
/// <param name="proxyHost">i.e. 127.0.0.1</param>
/// <param name="proxyPort">i.e. 10000</param>
public BotBase(String apiKey, String proxyHost, int proxyPort) : this(apiKey, false)
{
this.Client = new Base.MessageClient(this.APIKey, proxyHost, proxyPort);
this.Sessions.Client = this.Client;
}
/// <summary> /// <summary>
/// Start your Bot /// Start your Bot
@ -160,9 +109,8 @@ namespace TelegramBotBase
if (this.Client == null) if (this.Client == null)
return; return;
this.Client.Message += Client_Message; this.Client.MessageLoop += Client_MessageLoop;
this.Client.MessageEdit += Client_MessageEdit;
this.Client.Action += Client_Action;
if (this.StateMachine != null) if (this.StateMachine != null)
{ {
@ -180,7 +128,39 @@ namespace TelegramBotBase
DeviceSession.MaxNumberOfRetries = this.GetSetting(eSettings.MaxNumberOfRetries, 5); DeviceSession.MaxNumberOfRetries = this.GetSetting(eSettings.MaxNumberOfRetries, 5);
this.Client.TelegramClient.StartReceiving(); this.Client.StartReceiving();
}
private async Task Client_MessageLoop(object sender, UpdateResult e)
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
if (ds == null)
{
ds = this.Sessions.StartSession(e.DeviceId).GetAwaiter().GetResult();
e.Device = ds;
ds.LastMessage = e.RawData.Message;
OnSessionBegins(new SessionBeginEventArgs(e.DeviceId, ds));
}
var mr = new MessageResult(e.RawData);
int i = 0;
//Should formulars get navigated (allow maximum of 10, to dont get loops)
do
{
i++;
//Reset navigation
ds.FormSwitched = false;
await MessageLoopFactory.MessageLoop(this, ds, e, mr);
mr.IsFirstHandler = false;
} while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10));
} }
@ -192,10 +172,10 @@ namespace TelegramBotBase
if (this.Client == null) if (this.Client == null)
return; return;
this.Client.Message -= Client_Message; this.Client.MessageLoop -= Client_MessageLoop;
this.Client.Action -= Client_Action;
this.Client.TelegramClient.StopReceiving();
this.Client.StopReceiving();
this.Sessions.SaveSessionStates(); this.Sessions.SaveSessionStates();
} }
@ -216,204 +196,7 @@ namespace TelegramBotBase
} }
} }
private async void Client_Message(object sender, MessageResult e)
{
if (this.GetSetting(eSettings.SkipAllMessages, false))
return;
try
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
e.Device = ds;
if (this.GetSetting(eSettings.LogAllMessages, false))
{
OnMessage(new MessageIncomeEventArgs(e.DeviceId, ds, e));
}
ds?.OnMessageReceived(new MessageReceivedEventArgs(e.Message));
await Client_Loop(sender, e);
}
catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{
}
catch (Exception ex)
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex));
}
}
//private async Task Client_TryMessage(object sender, MessageResult e)
//{
// DeviceSession ds = e.Device;
// if (ds == null)
// {
// ds = await this.Sessions.StartSession<T>(e.DeviceId);
// e.Device = ds;
// ds.LastMessage = e.Message;
// OnSessionBegins(new SessionBeginEventArgs(e.DeviceId, ds));
// }
// ds.LastAction = DateTime.Now;
// ds.LastMessage = e.Message;
// //Is this a bot command ?
// if (e.IsBotCommand && this.BotCommands.Count(a => "/" + a.Command == e.BotCommand) > 0)
// {
// var sce = new BotCommandEventArgs(e.BotCommand, e.BotCommandParameters, e.Message, ds.DeviceId, ds);
// await OnBotCommand(sce);
// if (sce.Handled)
// return;
// }
// FormBase activeForm = null;
// int i = 0;
// //Should formulars get navigated (allow maximum of 10, to dont get loops)
// do
// {
// i++;
// //Reset navigation
// ds.FormSwitched = false;
// activeForm = ds.ActiveForm;
// //Pre Loading Event
// await activeForm.PreLoad(e);
// //Send Load event to controls
// await activeForm.LoadControls(e);
// //Loading Event
// await activeForm.Load(e);
// //Is Attachment ? (Photo, Audio, Video, Contact, Location, Document)
// if (e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Contact | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Document | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Location |
// e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Photo | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Video | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Audio)
// {
// await activeForm.SentData(new DataResult(e));
// }
// //Render Event
// if (!ds.FormSwitched)
// {
// await activeForm.RenderControls(e);
// await activeForm.Render(e);
// }
// e.IsFirstHandler = false;
// } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10));
//}
private async Task Client_Loop(object sender, MessageResult e)
{
DeviceSession ds = e.Device;
if (ds == null)
{
ds = await this.Sessions.StartSession<T>(e.DeviceId);
e.Device = ds;
ds.LastMessage = e.Message;
OnSessionBegins(new SessionBeginEventArgs(e.DeviceId, ds));
}
ds.LastAction = DateTime.Now;
ds.LastMessage = e.Message;
//Is this a bot command ?
if (e.IsBotCommand && this.BotCommands.Count(a => "/" + a.Command == e.BotCommand) > 0)
{
var sce = new BotCommandEventArgs(e.BotCommand, e.BotCommandParameters, e.Message, ds.DeviceId, ds);
await OnBotCommand(sce);
if (sce.Handled)
return;
}
FormBase activeForm = null;
int i = 0;
//Should formulars get navigated (allow maximum of 10, to dont get loops)
do
{
i++;
//Reset navigation
ds.FormSwitched = false;
activeForm = ds.ActiveForm;
//Pre Loading Event
await activeForm.PreLoad(e);
//Send Load event to controls
await activeForm.LoadControls(e);
//Loading Event
await activeForm.Load(e);
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document)
if (e.MessageType == Telegram.Bot.Types.Enums.MessageType.Contact | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Document | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Location |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Video | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio)
{
await activeForm.SentData(new DataResult(e));
}
//Action Event
if (!ds.FormSwitched && e.IsAction)
{
//Send Action event to controls
await activeForm.ActionControls(e);
//Send Action event to form itself
await activeForm.Action(e);
if (!e.Handled)
{
var uhc = new UnhandledCallEventArgs(e.Message.Text, e.RawData, ds.DeviceId, e.MessageId, e.Message, ds);
OnUnhandledCall(uhc);
if (uhc.Handled)
{
e.Handled = true;
if (!ds.FormSwitched)
{
break;
}
}
}
}
if (!ds.FormSwitched)
{
//Render Event
await activeForm.RenderControls(e);
await activeForm.Render(e);
}
e.IsFirstHandler = false;
} while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10));
}
/// <summary> /// <summary>
/// This will invoke the full message loop for the device even when no "userevent" like message or action has been raised. /// This will invoke the full message loop for the device even when no "userevent" like message or action has been raised.
@ -438,7 +221,8 @@ namespace TelegramBotBase
DeviceSession ds = this.Sessions.GetSession(DeviceId); DeviceSession ds = this.Sessions.GetSession(DeviceId);
e.Device = ds; e.Device = ds;
await Client_Loop(this, e); await MessageLoopFactory.MessageLoop(this, ds, new UpdateResult(e.UpdateData, ds), e);
//await Client_Loop(this, e);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -447,156 +231,17 @@ namespace TelegramBotBase
} }
} }
private async void Client_MessageEdit(object sender, MessageResult e)
/// <summary>
/// Will get invoke on an unhandled call.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void MessageLoopFactory_UnhandledCall(object sender, UnhandledCallEventArgs e)
{ {
if (this.GetSetting(eSettings.SkipAllMessages, false)) OnUnhandledCall(e);
return;
try
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
e.Device = ds;
if (this.GetSetting(eSettings.LogAllMessages, false))
{
OnMessage(new MessageIncomeEventArgs(e.DeviceId, ds, e));
}
//Call same, to handle received liked edited
ds?.OnMessageReceived(new MessageReceivedEventArgs(e.Message));
await Client_TryMessageEdit(sender, e);
}
catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{
}
catch (Exception ex)
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex));
}
} }
private async Task Client_TryMessageEdit(object sender, MessageResult e)
{
DeviceSession ds = e.Device;
if (ds == null)
{
ds = await this.Sessions.StartSession<T>(e.DeviceId);
e.Device = ds;
}
ds.LastAction = DateTime.Now;
ds.LastMessage = e.Message;
//Pre Loading Event
await ds.ActiveForm.Edited(e);
//When form has been switched due navigation within the edit method, reopen Client_Message
if (ds.FormSwitched)
{
await Client_Loop(sender, e);
}
}
private async void Client_Action(object sender, MessageResult e)
{
try
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
e.Device = ds;
if (this.GetSetting(eSettings.LogAllMessages, false))
{
OnMessage(new MessageIncomeEventArgs(e.DeviceId, ds, e));
}
await Client_Loop(sender, e);
}
catch (Exception ex)
{
DeviceSession ds = this.Sessions.GetSession(e.DeviceId);
OnException(new SystemExceptionEventArgs(e.Message.Text, ds?.DeviceId ?? -1, ds, ex));
}
}
//private async void Client_TryAction(object sender, MessageResult e)
//{
// DeviceSession ds = e.Device;
// if (ds == null)
// {
// ds = await this.Sessions.StartSession<T>(e.DeviceId);
// e.Device = ds;
// }
// ds.LastAction = DateTime.Now;
// ds.LastMessage = e.Message;
// FormBase activeForm = null;
// int i = 0;
// //Should formulars get navigated (allow maximum of 10, to dont get loops)
// do
// {
// i++;
// //Reset navigation
// ds.FormSwitched = false;
// activeForm = ds.ActiveForm;
// //Pre Loading Event
// await activeForm.PreLoad(e);
// //Send Load event to controls
// await activeForm.LoadControls(e);
// //Loading Event
// await activeForm.Load(e);
// //Action Event
// if (!ds.FormSwitched)
// {
// //Send Action event to controls
// await activeForm.ActionControls(e);
// //Send Action event to form itself
// await activeForm.Action(e);
// if (!e.Handled)
// {
// var uhc = new UnhandledCallEventArgs(e.Message.Text, e.RawData, ds.DeviceId, e.MessageId, e.Message, ds);
// OnUnhandledCall(uhc);
// if (uhc.Handled)
// {
// e.Handled = true;
// if (!ds.FormSwitched)
// {
// break;
// }
// }
// }
// }
// //Render Event
// if (!ds.FormSwitched)
// {
// await activeForm.RenderControls(e);
// await activeForm.Render(e);
// }
// e.IsFirstHandler = false;
// } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10));
//}
/// <summary> /// <summary>
/// This method will update all local created bot commands to the botfather. /// This method will update all local created bot commands to the botfather.
/// </summary> /// </summary>

View File

@ -0,0 +1,324 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using Telegram.Bot;
using Telegram.Bot.Types;
using TelegramBotBase.Base;
using TelegramBotBase.Builder.Interfaces;
using TelegramBotBase.Commands;
using TelegramBotBase.Form;
using TelegramBotBase.Interfaces;
using TelegramBotBase.Localizations;
using TelegramBotBase.States;
namespace TelegramBotBase.Builder
{
public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage, IStartFormSelectionStage, IBuildingStage, INetworkingSelectionStage, IBotCommandsStage, ISessionSerializationStage, ILanguageSelectionStage
{
String _apiKey = null;
IStartFormFactory _factory = null;
MessageClient _client = null;
List<BotCommand> _botcommands = new List<BotCommand>();
IStateMachine _statemachine = null;
IMessageLoopFactory _messageloopfactory = null;
private BotBaseBuilder()
{
}
public static IAPIKeySelectionStage Create()
{
return new BotBaseBuilder();
}
#region "Step 1 (Basic Stuff)"
public IMessageLoopSelectionStage WithAPIKey(string apiKey)
{
this._apiKey = apiKey;
return this;
}
public IBuildingStage QuickStart(string apiKey, Type StartForm)
{
this._apiKey = apiKey;
this._factory = new Factories.DefaultStartFormFactory(StartForm);
DefaultMessageLoop();
NoProxy();
OnlyStart();
NoSerialization();
DefaultLanguage();
return this;
}
public IBuildingStage QuickStart<T>(string apiKey)
where T : FormBase
{
this._apiKey = apiKey;
this._factory = new Factories.DefaultStartFormFactory(typeof(T));
DefaultMessageLoop();
NoProxy();
OnlyStart();
NoSerialization();
DefaultLanguage();
return this;
}
public IBuildingStage QuickStart(string apiKey, IStartFormFactory StartFormFactory)
{
this._apiKey = apiKey;
this._factory = StartFormFactory;
DefaultMessageLoop();
NoProxy();
OnlyStart();
NoSerialization();
DefaultLanguage();
return this;
}
#endregion
#region "Step 2 (Message Loop)"
public IStartFormSelectionStage DefaultMessageLoop()
{
_messageloopfactory = new Factories.MessageLoops.FormBaseMessageLoop();
return this;
}
public IStartFormSelectionStage CustomMessageLoop(IMessageLoopFactory messageLoopClass)
{
_messageloopfactory = messageLoopClass;
return this;
}
public IStartFormSelectionStage CustomMessageLoop<T>()
where T : class, new()
{
_messageloopfactory = typeof(T).GetConstructor(new Type[] { })?.Invoke(new object[] { }) as IMessageLoopFactory;
return this;
}
#endregion
#region "Step 3 (Start Form/Factory)"
public INetworkingSelectionStage WithStartForm(Type startFormClass)
{
this._factory = new Factories.DefaultStartFormFactory(startFormClass);
return this;
}
public INetworkingSelectionStage WithStartForm<T>()
where T : FormBase, new()
{
this._factory = new Factories.DefaultStartFormFactory(typeof(T));
return this;
}
public INetworkingSelectionStage WithStartFormFactory(IStartFormFactory factory)
{
this._factory = factory;
return this;
}
#endregion
#region "Step 4 (Network Settings)"
public IBotCommandsStage WithProxy(string proxyAddress)
{
var url = new Uri(proxyAddress);
_client = new MessageClient(_apiKey, url);
_client.TelegramClient.Timeout = new TimeSpan(0, 1, 0);
return this;
}
public IBotCommandsStage NoProxy()
{
_client = new MessageClient(_apiKey);
_client.TelegramClient.Timeout = new TimeSpan(0, 1, 0);
return this;
}
public IBotCommandsStage WithBotClient(TelegramBotClient tgclient)
{
_client = new MessageClient(_apiKey, tgclient);
_client.TelegramClient.Timeout = new TimeSpan(0, 1, 0);
return this;
}
public IBotCommandsStage WithHostAndPort(string proxyHost, int proxyPort)
{
_client = new MessageClient(_apiKey, proxyHost, proxyPort);
_client.TelegramClient.Timeout = new TimeSpan(0, 1, 0);
return this;
}
public IBotCommandsStage WithHttpClient(HttpClient tgclient)
{
_client = new MessageClient(_apiKey, tgclient);
_client.TelegramClient.Timeout = new TimeSpan(0, 1, 0);
return this;
}
#endregion
#region "Step 5 (Bot Commands)"
public ISessionSerializationStage NoCommands()
{
return this;
}
public ISessionSerializationStage OnlyStart()
{
_botcommands.Start("Starts the bot");
return this;
}
public ISessionSerializationStage DefaultCommands()
{
_botcommands.Start("Starts the bot");
_botcommands.Help("Should show you some help");
_botcommands.Settings("Should show you some settings");
return this;
}
public ISessionSerializationStage CustomCommands(Action<List<BotCommand>> action)
{
action?.Invoke(_botcommands);
return this;
}
#endregion
#region "Step 6 (Serialization)"
public ILanguageSelectionStage NoSerialization()
{
return this;
}
public ILanguageSelectionStage UseSerialization(IStateMachine machine)
{
this._statemachine = machine;
return this;
}
public ILanguageSelectionStage UseJSON(string path)
{
this._statemachine = new JSONStateMachine(path);
return this;
}
public ILanguageSelectionStage UseSimpleJSON(string path)
{
this._statemachine = new SimpleJSONStateMachine(path);
return this;
}
public ILanguageSelectionStage UseXML(string path)
{
this._statemachine = new XMLStateMachine(path);
return this;
}
#endregion
#region "Step 7 (Language)"
public IBuildingStage DefaultLanguage()
{
return this;
}
public IBuildingStage UseEnglish()
{
Localizations.Default.Language = new Localizations.English();
return this;
}
public IBuildingStage UseGerman()
{
Localizations.Default.Language = new Localizations.German();
return this;
}
public IBuildingStage Custom(Localization language)
{
Localizations.Default.Language = language;
return this;
}
#endregion
public BotBase Build()
{
var bb = new BotBase();
bb.APIKey = _apiKey;
bb.StartFormFactory = _factory;
bb.Client = _client;
bb.Sessions.Client = bb.Client;
bb.BotCommands = _botcommands;
bb.StateMachine = _statemachine;
bb.MessageLoopFactory = _messageloopfactory;
bb.MessageLoopFactory.UnhandledCall += bb.MessageLoopFactory_UnhandledCall;
return bb;
}
}
}

View File

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Form;
using TelegramBotBase.Interfaces;
namespace TelegramBotBase.Builder.Interfaces
{
public interface IAPIKeySelectionStage
{
/// <summary>
/// Sets the API Key which will be used by the telegram bot client.
/// </summary>
/// <param name="apiKey"></param>
/// <returns></returns>
IMessageLoopSelectionStage WithAPIKey(String apiKey);
/// <summary>
/// Quick and easy way to create a BotBase instance.
/// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage
/// </summary>
/// <param name="apiKey"></param>
/// <param name="StartForm"></param>
/// <returns></returns>
IBuildingStage QuickStart(String apiKey, Type StartForm);
/// <summary>
/// Quick and easy way to create a BotBase instance.
/// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage
/// </summary>
/// <param name="apiKey"></param>
/// <returns></returns>
IBuildingStage QuickStart<T>(String apiKey) where T : FormBase;
/// <summary>
/// Quick and easy way to create a BotBase instance.
/// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage
/// </summary>
/// <param name="apiKey"></param>
/// <param name="StartFormFactory"></param>
/// <returns></returns>
IBuildingStage QuickStart(String apiKey, IStartFormFactory StartFormFactory);
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Text;
using Telegram.Bot.Types;
namespace TelegramBotBase.Builder.Interfaces
{
public interface IBotCommandsStage
{
/// <summary>
/// Does not create any commands.
/// </summary>
/// <returns></returns>
ISessionSerializationStage NoCommands();
/// <summary>
/// Creates default commands for start, help and settings.
/// </summary>
/// <returns></returns>
ISessionSerializationStage DefaultCommands();
/// <summary>
/// Only adds the start command.
/// </summary>
/// <returns></returns>
ISessionSerializationStage OnlyStart();
/// <summary>
/// Gives you the ability to add custom commands.
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
ISessionSerializationStage CustomCommands(Action<List<BotCommand>> action);
}
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace TelegramBotBase.Builder.Interfaces
{
public interface IBuildingStage
{
BotBase Build();
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Localizations;
namespace TelegramBotBase.Builder.Interfaces
{
public interface ILanguageSelectionStage
{
/// <summary>
/// Selects the default language for control usage. (English)
/// </summary>
/// <returns></returns>
IBuildingStage DefaultLanguage();
/// <summary>
/// Selects english as the default language for control labels.
/// </summary>
/// <returns></returns>
IBuildingStage UseEnglish();
/// <summary>
/// Selects german as the default language for control labels.
/// </summary>
/// <returns></returns>
IBuildingStage UseGerman();
/// <summary>
/// Selects a custom language as the default language for control labels.
/// </summary>
/// <returns></returns>
IBuildingStage Custom(Localization language);
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using Telegram.Bot;
namespace TelegramBotBase.Builder.Interfaces
{
public interface INetworkingSelectionStage
{
/// <summary>
/// Chooses a proxy as network configuration.
/// </summary>
/// <param name="proxyAddress"></param>
/// <returns></returns>
IBotCommandsStage WithProxy(String proxyAddress);
/// <summary>
/// Do not choose a proxy as network configuration.
/// </summary>
/// <returns></returns>
IBotCommandsStage NoProxy();
/// <summary>
/// Chooses a custom instance of TelegramBotClient.
/// </summary>
/// <param name="client"></param>
/// <returns></returns>
IBotCommandsStage WithBotClient(TelegramBotClient client);
/// <summary>
/// Sets the custom proxy host and port.
/// </summary>
/// <param name="proxyHost"></param>
/// <param name="Port"></param>
/// <returns></returns>
IBotCommandsStage WithHostAndPort(String proxyHost, int Port);
/// <summary>
/// Uses a custom http client.
/// </summary>
/// <param name="client"></param>
/// <returns></returns>
IBotCommandsStage WithHttpClient(HttpClient client);
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Interfaces;
namespace TelegramBotBase.Builder.Interfaces
{
public interface ISessionSerializationStage
{
/// <summary>
/// Do not uses serialization.
/// </summary>
/// <returns></returns>
ILanguageSelectionStage NoSerialization();
/// <summary>
/// Sets the state machine for serialization.
/// </summary>
/// <param name="machine"></param>
/// <returns></returns>
ILanguageSelectionStage UseSerialization(IStateMachine machine);
/// <summary>
/// Using the complex version of .Net JSON, which can serialize all objects.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
ILanguageSelectionStage UseJSON(String path);
/// <summary>
/// Use the easy version of .Net JSON, which can serialize basic types, but not generics and others.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
ILanguageSelectionStage UseSimpleJSON(String path);
/// <summary>
/// Uses the XML serializer for session serialization.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
ILanguageSelectionStage UseXML(String path);
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Form;
using TelegramBotBase.Interfaces;
namespace TelegramBotBase.Builder.Interfaces
{
public interface IStartFormSelectionStage
{
/// <summary>
/// Chooses a start form type which will be used for new sessions.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
INetworkingSelectionStage WithStartForm(Type startFormClass);
/// <summary>
/// Chooses a generic start form which will be used for new sessions.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
INetworkingSelectionStage WithStartForm<T>() where T : FormBase, new();
/// <summary>
/// Chooses a StartFormFactory which will be use for new sessions.
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
INetworkingSelectionStage WithStartFormFactory(IStartFormFactory factory);
}
}

View File

@ -12,7 +12,7 @@ namespace TelegramBotBase.Commands
/// </summary> /// </summary>
/// <param name="cmds"></param> /// <param name="cmds"></param>
/// <param name="description"></param> /// <param name="description"></param>
public static void AddStartCommand(this List<BotCommand> cmds, String description) public static void Start(this List<BotCommand> cmds, String description)
{ {
cmds.Add(new BotCommand() { Command = "start", Description = description }); cmds.Add(new BotCommand() { Command = "start", Description = description });
} }
@ -22,7 +22,7 @@ namespace TelegramBotBase.Commands
/// </summary> /// </summary>
/// <param name="cmds"></param> /// <param name="cmds"></param>
/// <param name="description"></param> /// <param name="description"></param>
public static void AddHelpCommand(this List<BotCommand> cmds, String description) public static void Help(this List<BotCommand> cmds, String description)
{ {
cmds.Add(new BotCommand() { Command = "help", Description = description }); cmds.Add(new BotCommand() { Command = "help", Description = description });
} }
@ -32,9 +32,20 @@ namespace TelegramBotBase.Commands
/// </summary> /// </summary>
/// <param name="cmds"></param> /// <param name="cmds"></param>
/// <param name="description"></param> /// <param name="description"></param>
public static void AddSettingsCommand(this List<BotCommand> cmds, String description) public static void Settings(this List<BotCommand> cmds, String description)
{ {
cmds.Add(new BotCommand() { Command = "settings", Description = description }); cmds.Add(new BotCommand() { Command = "settings", Description = description });
} }
/// <summary>
/// Adding the command with a description.
/// </summary>
/// <param name="cmds"></param>
/// <param name="command"></param>
/// <param name="description"></param>
public static void Add(this List<BotCommand> cmds, String command, String description)
{
cmds.Add(new BotCommand() { Command = command, Description = description });
}
} }
} }

View File

@ -75,7 +75,7 @@ namespace TelegramBotBase.Controls.Hybrid
/// <summary> /// <summary>
/// Parsemode of the message. /// Parsemode of the message.
/// </summary> /// </summary>
public ParseMode MessageParseMode { get; set; } = ParseMode.Default; public ParseMode MessageParseMode { get; set; } = ParseMode.Markdown;
/// <summary> /// <summary>
/// Enables automatic paging of buttons when the amount of rows is exceeding the limits. /// Enables automatic paging of buttons when the amount of rows is exceeding the limits.

View File

@ -76,7 +76,7 @@ namespace TelegramBotBase.Controls.Hybrid
/// <summary> /// <summary>
/// Parsemode of the message. /// Parsemode of the message.
/// </summary> /// </summary>
public ParseMode MessageParseMode { get; set; } = ParseMode.Default; public ParseMode MessageParseMode { get; set; } = ParseMode.Markdown;
/// <summary> /// <summary>
/// Enables automatic paging of buttons when the amount of rows is exceeding the limits. /// Enables automatic paging of buttons when the amount of rows is exceeding the limits.

View File

@ -73,7 +73,7 @@ namespace TelegramBotBase.Controls.Hybrid
/// <summary> /// <summary>
/// Parsemode of the message. /// Parsemode of the message.
/// </summary> /// </summary>
public ParseMode MessageParseMode { get; set; } = ParseMode.Default; public ParseMode MessageParseMode { get; set; } = ParseMode.Markdown;
/// <summary> /// <summary>
/// Enables automatic paging of buttons when the amount of rows is exceeding the limits. /// Enables automatic paging of buttons when the amount of rows is exceeding the limits.

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Form;
namespace TelegramBotBase.Factories
{
public class DefaultStartFormFactory : Interfaces.IStartFormFactory
{
private readonly Type _startFormClass;
public DefaultStartFormFactory(Type startFormClass)
{
if (!typeof(FormBase).IsAssignableFrom(startFormClass))
throw new ArgumentException("startFormClass argument must be a FormBase type");
_startFormClass = startFormClass;
}
public FormBase CreateForm()
{
return _startFormClass.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase;
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Form;
namespace TelegramBotBase.Factories
{
public class LambdaStartFormFactory : Interfaces.IStartFormFactory
{
public delegate FormBase CreateFormDelegate();
private readonly CreateFormDelegate _lambda;
public LambdaStartFormFactory(CreateFormDelegate lambda)
{
_lambda = lambda;
}
public FormBase CreateForm()
{
return _lambda();
}
}
}

View File

@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Args;
using TelegramBotBase.Base;
using TelegramBotBase.Enums;
using TelegramBotBase.Interfaces;
using TelegramBotBase.Sessions;
namespace TelegramBotBase.Factories.MessageLoops
{
public class FormBaseMessageLoop : IMessageLoopFactory
{
private static object __evUnhandledCall = new object();
private EventHandlerList __Events = new EventHandlerList();
public FormBaseMessageLoop()
{
}
public async Task MessageLoop(BotBase Bot, DeviceSession session, UpdateResult ur, MessageResult mr)
{
var update = ur.RawData;
if (update.Type != Telegram.Bot.Types.Enums.UpdateType.Message
&& update.Type != Telegram.Bot.Types.Enums.UpdateType.EditedMessage
&& update.Type != Telegram.Bot.Types.Enums.UpdateType.CallbackQuery)
{
return;
}
//Is this a bot command ?
if (mr.IsFirstHandler && mr.IsBotCommand && Bot.BotCommands.Count(a => "/" + a.Command == mr.BotCommand) > 0)
{
var sce = new BotCommandEventArgs(mr.BotCommand, mr.BotCommandParameters, mr.Message, session.DeviceId, session);
await Bot.OnBotCommand(sce);
if (sce.Handled)
return;
}
mr.Device = session;
var activeForm = session.ActiveForm;
//Pre Loading Event
await activeForm.PreLoad(mr);
//Send Load event to controls
await activeForm.LoadControls(mr);
//Loading Event
await activeForm.Load(mr);
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries)
if (update.Type == Telegram.Bot.Types.Enums.UpdateType.Message)
{
if (mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Contact
| mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Document
| mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Location
| mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo
| mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Video
| mr.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio)
{
await activeForm.SentData(new DataResult(ur));
}
}
//Action Event
if (!session.FormSwitched && mr.IsAction)
{
//Send Action event to controls
await activeForm.ActionControls(mr);
//Send Action event to form itself
await activeForm.Action(mr);
if (!mr.Handled)
{
var uhc = new UnhandledCallEventArgs(ur.Message.Text, mr.RawData, session.DeviceId, mr.MessageId, ur.Message, session);
OnUnhandledCall(uhc);
if (uhc.Handled)
{
mr.Handled = true;
if (!session.FormSwitched)
{
return;
}
}
}
}
if (!session.FormSwitched)
{
//Render Event
await activeForm.RenderControls(mr);
await activeForm.Render(mr);
}
}
/// <summary>
/// Will be called if no form handeled this call
/// </summary>
public event EventHandler<UnhandledCallEventArgs> UnhandledCall
{
add
{
this.__Events.AddHandler(__evUnhandledCall, value);
}
remove
{
this.__Events.RemoveHandler(__evUnhandledCall, value);
}
}
public void OnUnhandledCall(UnhandledCallEventArgs e)
{
(this.__Events[__evUnhandledCall] as EventHandler<UnhandledCallEventArgs>)?.Invoke(this, e);
}
}
}

View File

@ -138,7 +138,7 @@ namespace TelegramBotBase.Form
{ {
var oldMessages = OldMessages.AsEnumerable(); var oldMessages = OldMessages.AsEnumerable();
#if !NET472 #if !NETSTANDARD2_0
while (oldMessages.Any()) while (oldMessages.Any())
{ {
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
@ -150,8 +150,15 @@ namespace TelegramBotBase.Form
{ {
parallelQuery.ForAll(i => parallelQuery.ForAll(i =>
{ {
Device.DeleteMessage(i).GetAwaiter().GetResult(); try
deletedMessages.Add(i); {
Device.DeleteMessage(i).GetAwaiter().GetResult();
deletedMessages.Add(i);
}
catch (ApiRequestException req) when (req.ErrorCode == 400)
{
deletedMessages.Add(i);
}
}); });
} }
catch (AggregateException ex) catch (AggregateException ex)
@ -160,10 +167,10 @@ namespace TelegramBotBase.Form
var retryAfterSeconds = ex.InnerExceptions var retryAfterSeconds = ex.InnerExceptions
.Where(e => e is ApiRequestException apiEx && apiEx.ErrorCode == 429) .Where(e => e is ApiRequestException apiEx && apiEx.ErrorCode == 429)
.Max(e =>(int?) ((ApiRequestException)e).Parameters.RetryAfter) ?? 0; .Max(e => (int?)((ApiRequestException)e).Parameters.RetryAfter) ?? 0;
retryAfterTask = Task.Delay(retryAfterSeconds * 1000); retryAfterTask = Task.Delay(retryAfterSeconds * 1000);
} }
//deletedMessages.AsParallel().ForAll(i => Device.OnMessageDeleted(new MessageDeletedEventArgs(i))); //deletedMessages.AsParallel().ForAll(i => Device.OnMessageDeleted(new MessageDeletedEventArgs(i)));
oldMessages = oldMessages.Where(x => !deletedMessages.Contains(x)); oldMessages = oldMessages.Where(x => !deletedMessages.Contains(x));
@ -183,8 +190,15 @@ namespace TelegramBotBase.Form
{ {
parallelQuery.ForAll(i => parallelQuery.ForAll(i =>
{ {
Device.DeleteMessage(i).GetAwaiter().GetResult(); try
deletedMessages.Add(i); {
Device.DeleteMessage(i).GetAwaiter().GetResult();
deletedMessages.Add(i);
}
catch (ApiRequestException req) when (req.ErrorCode == 400)
{
deletedMessages.Add(i);
}
}); });
} }
catch (AggregateException ex) catch (AggregateException ex)

View File

@ -46,9 +46,9 @@ namespace TelegramBotBase.Form
return InlineKeyboardButton.WithCallbackData(this.Text, id + this.Value); return InlineKeyboardButton.WithCallbackData(this.Text, id + this.Value);
} }
var ikb = new InlineKeyboardButton(); var ikb = new InlineKeyboardButton(this.Text);
ikb.Text = this.Text; //ikb.Text = this.Text;
ikb.Url = this.Url; ikb.Url = this.Url;
return ikb; return ikb;

View File

@ -24,12 +24,12 @@ namespace TelegramBotBase.Form
{ {
case Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded: case Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded:
await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded, message, message.RawMessageData.Message.NewChatMembers)); await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMembersAdded, message, message.Message.NewChatMembers));
break; break;
case Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft: case Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft:
await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft, message, message.RawMessageData.Message.LeftChatMember)); await OnMemberChanges(new MemberChangeEventArgs(Telegram.Bot.Types.Enums.MessageType.ChatMemberLeft, message, message.Message.LeftChatMember));
break; break;

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Args;
using TelegramBotBase.Base;
using TelegramBotBase.Sessions;
namespace TelegramBotBase.Interfaces
{
public interface IMessageLoopFactory
{
Task MessageLoop(BotBase Bot, DeviceSession session, UpdateResult ur, MessageResult e);
event EventHandler<UnhandledCallEventArgs> UnhandledCall;
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using TelegramBotBase.Form;
namespace TelegramBotBase.Interfaces
{
public interface IStartFormFactory
{
FormBase CreateForm();
}
}

View File

@ -16,14 +16,23 @@ namespace TelegramBotBase
/// <summary> /// <summary>
/// Base class for managing all active sessions /// Base class for managing all active sessions
/// </summary> /// </summary>
public class SessionBase<T> public class SessionBase
where T : FormBase
{ {
/// <summary>
/// The Basic message client.
/// </summary>
public MessageClient Client { get; set; } public MessageClient Client { get; set; }
/// <summary>
/// A list of all active sessions.
/// </summary>
public Dictionary<long, DeviceSession> SessionList { get; set; } public Dictionary<long, DeviceSession> SessionList { get; set; }
public BotBase<T> BotBase { get; set; }
/// <summary>
/// Reference to the Main BotBase instance for later use.
/// </summary>
public BotBase BotBase { get; set; }
public SessionBase() public SessionBase()
@ -65,10 +74,10 @@ namespace TelegramBotBase
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="deviceId"></param> /// <param name="deviceId"></param>
/// <returns></returns> /// <returns></returns>
public async Task<DeviceSession> StartSession<T>(long deviceId) public async Task<DeviceSession> StartSession(long deviceId)
where T : FormBase
{ {
T start = typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }) as T; var start = BotBase.StartFormFactory.CreateForm();
//T start = typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }) as T;
start.Client = this.Client; start.Client = this.Client;
@ -239,7 +248,7 @@ namespace TelegramBotBase
} }
/// <summary> /// <summary>

View File

@ -2,12 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Exceptions; using Telegram.Bot.Exceptions;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.Enums;
@ -139,6 +138,23 @@ namespace TelegramBotBase.Sessions
} }
/// <summary>
/// Confirm incomming action (i.e. Button click)
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public async Task ConfirmAction(String CallbackQueryId, String message = "", bool showAlert = false, String urlToOpen = null)
{
try
{
await this.Client.TelegramClient.AnswerCallbackQueryAsync(CallbackQueryId, message, showAlert, urlToOpen);
}
catch
{
}
}
/// <summary> /// <summary>
/// Edits the text message /// Edits the text message
/// </summary> /// </summary>
@ -146,7 +162,7 @@ namespace TelegramBotBase.Sessions
/// <param name="text"></param> /// <param name="text"></param>
/// <param name="buttons"></param> /// <param name="buttons"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Edit(int messageId, String text, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Default) public async Task<Message> Edit(int messageId, String text, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Markdown)
{ {
InlineKeyboardMarkup markup = buttons; InlineKeyboardMarkup markup = buttons;
@ -175,7 +191,7 @@ namespace TelegramBotBase.Sessions
/// <param name="text"></param> /// <param name="text"></param>
/// <param name="buttons"></param> /// <param name="buttons"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Edit(int messageId, String text, InlineKeyboardMarkup markup, ParseMode parseMode = ParseMode.Default) public async Task<Message> Edit(int messageId, String text, InlineKeyboardMarkup markup, ParseMode parseMode = ParseMode.Markdown)
{ {
if (text.Length > Constants.Telegram.MaxMessageLength) if (text.Length > Constants.Telegram.MaxMessageLength)
{ {
@ -202,7 +218,7 @@ namespace TelegramBotBase.Sessions
/// <param name="text"></param> /// <param name="text"></param>
/// <param name="buttons"></param> /// <param name="buttons"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Edit(Message message, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Default) public async Task<Message> Edit(Message message, ButtonForm buttons = null, ParseMode parseMode = ParseMode.Markdown)
{ {
InlineKeyboardMarkup markup = buttons; InlineKeyboardMarkup markup = buttons;
@ -253,7 +269,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Send(long deviceId, String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) public async Task<Message> Send(long deviceId, String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true)
{ {
if (this.ActiveForm == null) if (this.ActiveForm == null)
return null; return null;
@ -293,7 +309,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Send(String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) public async Task<Message> Send(String text, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true)
{ {
return await Send(this.DeviceId, text, buttons, replyTo, disableNotification, parseMode, MarkdownV2AutoEscape); return await Send(this.DeviceId, text, buttons, replyTo, disableNotification, parseMode, MarkdownV2AutoEscape);
} }
@ -306,7 +322,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Send(String text, InlineKeyboardMarkup markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) public async Task<Message> Send(String text, InlineKeyboardMarkup markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true)
{ {
if (this.ActiveForm == null) if (this.ActiveForm == null)
return null; return null;
@ -344,7 +360,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> Send(String text, ReplyMarkupBase markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default, bool MarkdownV2AutoEscape = true) public async Task<Message> Send(String text, ReplyMarkupBase markup, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown, bool MarkdownV2AutoEscape = true)
{ {
if (this.ActiveForm == null) if (this.ActiveForm == null)
return null; return null;
@ -382,7 +398,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> SendPhoto(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default) public async Task<Message> SendPhoto(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown)
{ {
if (this.ActiveForm == null) if (this.ActiveForm == null)
return null; return null;
@ -404,44 +420,6 @@ namespace TelegramBotBase.Sessions
} }
} }
/// <summary>
/// Sends an image
/// </summary>
/// <param name="image"></param>
/// <param name="name"></param>
/// <param name="buttons"></param>
/// <param name="replyTo"></param>
/// <param name="disableNotification"></param>
/// <returns></returns>
public async Task<Message> SendPhoto(Image image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false)
{
using (var fileStream = Tools.Images.ToStream(image, ImageFormat.Png))
{
InputOnlineFile fts = new InputOnlineFile(fileStream, name);
return await SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification);
}
}
/// <summary>
/// Sends an image
/// </summary>
/// <param name="image"></param>
/// <param name="name"></param>
/// <param name="buttons"></param>
/// <param name="replyTo"></param>
/// <param name="disableNotification"></param>
/// <returns></returns>
public async Task<Message> SendPhoto(Bitmap image, String name, String caption, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false)
{
using (var fileStream = Tools.Images.ToStream(image, ImageFormat.Png))
{
InputOnlineFile fts = new InputOnlineFile(fileStream, name);
return await SendPhoto(fts, caption: caption, buttons, replyTo, disableNotification);
}
}
/// <summary> /// <summary>
/// Sends an video /// Sends an video
/// </summary> /// </summary>
@ -450,7 +428,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> SendVideo(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default) public async Task<Message> SendVideo(InputOnlineFile file, String caption = null, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown)
{ {
if (this.ActiveForm == null) if (this.ActiveForm == null)
return null; return null;
@ -480,7 +458,7 @@ namespace TelegramBotBase.Sessions
/// <param name="replyTo"></param> /// <param name="replyTo"></param>
/// <param name="disableNotification"></param> /// <param name="disableNotification"></param>
/// <returns></returns> /// <returns></returns>
public async Task<Message> SendVideo(String url, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Default) public async Task<Message> SendVideo(String url, ButtonForm buttons = null, int replyTo = 0, bool disableNotification = false, ParseMode parseMode = ParseMode.Markdown)
{ {
if (this.ActiveForm == null) if (this.ActiveForm == null)
return null; return null;
@ -719,11 +697,24 @@ namespace TelegramBotBase.Sessions
return null; return null;
} }
[Obsolete("User BanUser instead.")]
public virtual async Task KickUser(long userId, DateTime until = default(DateTime)) public virtual async Task KickUser(long userId, DateTime until = default(DateTime))
{ {
try try
{ {
await API(a => a.KickChatMemberAsync(this.DeviceId, userId, until)); await API(a => a.BanChatMemberAsync(this.DeviceId, userId, until));
}
catch
{
}
}
public virtual async Task BanUser(long userId, DateTime until = default(DateTime))
{
try
{
await API(a => a.BanChatMemberAsync(this.DeviceId, userId, until));
} }
catch catch
{ {
@ -751,7 +742,7 @@ namespace TelegramBotBase.Sessions
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="call"></param> /// <param name="call"></param>
/// <returns></returns> /// <returns></returns>
public T RAW<T>(Func<Telegram.Bot.TelegramBotClient, T> call) public T RAW<T>(Func<Telegram.Bot.ITelegramBotClient, T> call)
{ {
return call(this.Client.TelegramClient); return call(this.Client.TelegramClient);
} }
@ -762,7 +753,7 @@ namespace TelegramBotBase.Sessions
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="call"></param> /// <param name="call"></param>
/// <returns></returns> /// <returns></returns>
public async Task<T> API<T>(Func<Telegram.Bot.TelegramBotClient, Task<T>> call) public async Task<T> API<T>(Func<Telegram.Bot.ITelegramBotClient, Task<T>> call)
{ {
var numberOfTries = 0; var numberOfTries = 0;
while (numberOfTries < DeviceSession.MaxNumberOfRetries) while (numberOfTries < DeviceSession.MaxNumberOfRetries)
@ -776,8 +767,8 @@ namespace TelegramBotBase.Sessions
if (ex.ErrorCode != 429) if (ex.ErrorCode != 429)
throw; throw;
if (ex.Parameters != null) if (ex.Parameters != null && ex.Parameters.RetryAfter != null)
await Task.Delay(ex.Parameters.RetryAfter * 1000); await Task.Delay(ex.Parameters.RetryAfter.Value * 1000);
numberOfTries++; numberOfTries++;
} }
@ -790,7 +781,7 @@ namespace TelegramBotBase.Sessions
/// </summary> /// </summary>
/// <param name="call"></param> /// <param name="call"></param>
/// <returns></returns> /// <returns></returns>
public async Task API(Func<Telegram.Bot.TelegramBotClient, Task> call) public async Task API(Func<Telegram.Bot.ITelegramBotClient, Task> call)
{ {
var numberOfTries = 0; var numberOfTries = 0;
while (numberOfTries < DeviceSession.MaxNumberOfRetries) while (numberOfTries < DeviceSession.MaxNumberOfRetries)
@ -805,8 +796,8 @@ namespace TelegramBotBase.Sessions
if (ex.ErrorCode != 429) if (ex.ErrorCode != 429)
throw; throw;
if (ex.Parameters != null) if (ex.Parameters != null && ex.Parameters.RetryAfter != null)
await Task.Delay(ex.Parameters.RetryAfter * 1000); await Task.Delay(ex.Parameters.RetryAfter.Value * 1000);
numberOfTries++; numberOfTries++;
} }

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.1;net472;net5;netcoreapp3.1</TargetFrameworks> <TargetFrameworks>netstandard2.0;net5;netcoreapp3.1;net6</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> <GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageProjectUrl>https://github.com/MajMcCloud/TelegramBotFramework</PackageProjectUrl> <PackageProjectUrl>https://github.com/MajMcCloud/TelegramBotFramework</PackageProjectUrl>
<RepositoryUrl>https://github.com/MajMcCloud/TelegramBotFramework</RepositoryUrl> <RepositoryUrl>https://github.com/MajMcCloud/TelegramBotFramework</RepositoryUrl>
<PackageReleaseNotes>- moving from .Net Framework 4.7.2 to .Net Standard 2.1 for the Library and .Net Core 3.1 for the test project!</PackageReleaseNotes> <PackageReleaseNotes>- Dependency update. Removing .Net Framework target and replacing with .Net Standard 2.0</PackageReleaseNotes>
<Configurations>Debug;Release;</Configurations> <Configurations>Debug;Release;</Configurations>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild> <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
@ -16,10 +16,14 @@
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Version>$(VersionPrefix)</Version>
<AssemblyVersion></AssemblyVersion>
<FileVersion></FileVersion>
<DebugType>portable</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
@ -28,25 +32,14 @@
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>TRACE;DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\TelegramBotBase.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>portable</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
@ -64,10 +57,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Telegram.Bot" Version="17.0.0" />
<PackageReference Include="System.ComponentModel" Version="4.3.0" /> <PackageReference Include="Telegram.Bot.Extensions.Polling" Version="1.0.1" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="Telegram.Bot" Version="16.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TelegramBotBase.Tools
{
public static class Images
{
public static Stream ToStream(this Image image, ImageFormat format)
{
var stream = new System.IO.MemoryStream();
image.Save(stream, format);
stream.Position = 0;
return stream;
}
}
}

View File

@ -1,11 +1,11 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 17
VisualStudioVersion = 16.0.29324.140 VisualStudioVersion = 17.0.31912.275
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBase", "TelegramBotBase\TelegramBotBase.csproj", "{0BD16FB9-7ED4-4CCB-83EB-5CEE538E1B6C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBase", "TelegramBotBase\TelegramBotBase.csproj", "{0BD16FB9-7ED4-4CCB-83EB-5CEE538E1B6C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBaseTest", "TelegramBotBaseTest\TelegramBotBaseTest.csproj", "{88EC0E02-583D-4B9D-956C-81D63C8CFCFA}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBaseTest", "TelegramBotBase.Test\TelegramBotBaseTest.csproj", "{88EC0E02-583D-4B9D-956C-81D63C8CFCFA}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3856B3FB-63E3-444A-9FF0-34171BE7AC5D}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3856B3FB-63E3-444A-9FF0-34171BE7AC5D}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemCommandsBot", "Exampl
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JoinHiderBot", "Examples\JoinHiderBot\JoinHiderBot.csproj", "{E804B9E5-7ACC-49D3-9253-806766C1D9A5}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JoinHiderBot", "Examples\JoinHiderBot\JoinHiderBot.csproj", "{E804B9E5-7ACC-49D3-9253-806766C1D9A5}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramBotBase.Extensions.Images", "TelegramBotBase.Extensions.Images\TelegramBotBase.Extensions.Images.csproj", "{B5DDFA45-0E01-46A5-B67D-541300CDD606}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -40,6 +42,10 @@ Global
{E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Debug|Any CPU.Build.0 = Debug|Any CPU {E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Release|Any CPU.ActiveCfg = Release|Any CPU {E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Release|Any CPU.Build.0 = Release|Any CPU {E804B9E5-7ACC-49D3-9253-806766C1D9A5}.Release|Any CPU.Build.0 = Release|Any CPU
{B5DDFA45-0E01-46A5-B67D-541300CDD606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5DDFA45-0E01-46A5-B67D-541300CDD606}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5DDFA45-0E01-46A5-B67D-541300CDD606}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5DDFA45-0E01-46A5-B67D-541300CDD606}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE