Merge 9b3e3de55df176ea66f953d92a330c4d2ce25ed7 into 26152ee348bafaf898583217217d60de0cb75c60
This commit is contained in:
commit
28ff3ed5ce
47
Examples/MiddlewareBaseBot/Forms/StartForm.cs
Normal file
47
Examples/MiddlewareBaseBot/Forms/StartForm.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
|
internal sealed class StartForm : FormBase
|
||||||
|
{
|
||||||
|
public override async Task PreLoad(MessageResult message)
|
||||||
|
{
|
||||||
|
await this.Device.Send("PreLoad");
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Load(MessageResult message)
|
||||||
|
{
|
||||||
|
await this.Device.Send("Load");
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Edited(MessageResult message)
|
||||||
|
{
|
||||||
|
await this.Device.Send("Edited");
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Action(MessageResult message)
|
||||||
|
{
|
||||||
|
await this.Device.Send("Action");
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task SentData(DataResult data)
|
||||||
|
{
|
||||||
|
await this.Device.Send("SentData");
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Render(MessageResult message)
|
||||||
|
{
|
||||||
|
await this.Device.Send("Render");
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Examples/MiddlewareBaseBot/MiddlewareBaseBot.csproj
Normal file
14
Examples/MiddlewareBaseBot/MiddlewareBaseBot.csproj
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\TelegramBotBase\TelegramBotBase.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
195
Examples/MiddlewareBaseBot/Program.cs
Normal file
195
Examples/MiddlewareBaseBot/Program.cs
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using TelegramBotBase;
|
||||||
|
using TelegramBotBase.Builder;
|
||||||
|
using TelegramBotBase.MessageLoops.Extensions;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
var bot = GetPhotoBot();
|
||||||
|
|
||||||
|
await bot.Start();
|
||||||
|
|
||||||
|
Console.WriteLine("Bot started :)");
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a bot with middleware message loop and authentication for admin user
|
||||||
|
/// </summary>
|
||||||
|
private static BotBase GetAdminBot()
|
||||||
|
{
|
||||||
|
var bot = BotBaseBuilder
|
||||||
|
.Create()
|
||||||
|
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set"))
|
||||||
|
.MiddlewareMessageLoop(
|
||||||
|
messageLoop =>
|
||||||
|
messageLoop
|
||||||
|
.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var updateResult = container.UpdateResult;
|
||||||
|
if (updateResult.Message is not null)
|
||||||
|
{
|
||||||
|
if (updateResult.Message.From is not null)
|
||||||
|
{
|
||||||
|
var fromId = updateResult.Message.From.Id;
|
||||||
|
|
||||||
|
if (fromId == 1)
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
})
|
||||||
|
.UseValidUpdateTypes(
|
||||||
|
UpdateType.Message,
|
||||||
|
UpdateType.EditedMessage,
|
||||||
|
UpdateType.CallbackQuery)
|
||||||
|
.UseBotCommands()
|
||||||
|
.UseForms())
|
||||||
|
.WithStartForm<StartForm>()
|
||||||
|
.NoProxy()
|
||||||
|
.DefaultCommands()
|
||||||
|
.NoSerialization()
|
||||||
|
.UsePersian()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a bot with middleware message loop for handle inline queries
|
||||||
|
/// </summary>
|
||||||
|
private static BotBase GetInlineQueryBot()
|
||||||
|
{
|
||||||
|
var bot = BotBaseBuilder
|
||||||
|
.Create()
|
||||||
|
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set"))
|
||||||
|
.MiddlewareMessageLoop(
|
||||||
|
messageLoop =>
|
||||||
|
messageLoop
|
||||||
|
.UseValidUpdateTypes(UpdateType.InlineQuery)
|
||||||
|
.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var query = container.UpdateResult.RawData.InlineQuery.Query;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(query))
|
||||||
|
{
|
||||||
|
// logic
|
||||||
|
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}))
|
||||||
|
.WithStartForm<StartForm>()
|
||||||
|
.NoProxy()
|
||||||
|
.DefaultCommands()
|
||||||
|
.NoSerialization()
|
||||||
|
.UsePersian()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a bot with middleware message loop like form base message loop
|
||||||
|
/// </summary>
|
||||||
|
private static BotBase GetFormBaseBot()
|
||||||
|
{
|
||||||
|
var bot = BotBaseBuilder
|
||||||
|
.Create()
|
||||||
|
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set"))
|
||||||
|
.MiddlewareMessageLoop(
|
||||||
|
messageLoop =>
|
||||||
|
messageLoop
|
||||||
|
.UseValidUpdateTypes(
|
||||||
|
UpdateType.Message,
|
||||||
|
UpdateType.EditedMessage,
|
||||||
|
UpdateType.CallbackQuery)
|
||||||
|
.UseBotCommands()
|
||||||
|
.UseForms())
|
||||||
|
// OR instead of UseForms
|
||||||
|
// .UsePreLoad()
|
||||||
|
// .UseLoad()
|
||||||
|
// .UseAllAttachments()
|
||||||
|
// .UseActions()
|
||||||
|
// .UseRender()
|
||||||
|
.WithStartForm<StartForm>()
|
||||||
|
.NoProxy()
|
||||||
|
.DefaultCommands()
|
||||||
|
.NoSerialization()
|
||||||
|
.UsePersian()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a bot with middleware message loop like form base message loop
|
||||||
|
/// </summary>
|
||||||
|
private static BotBase GetFullBot()
|
||||||
|
{
|
||||||
|
var bot = BotBaseBuilder
|
||||||
|
.Create()
|
||||||
|
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set"))
|
||||||
|
.MiddlewareMessageLoop(
|
||||||
|
messageLoop =>
|
||||||
|
messageLoop
|
||||||
|
.UseBotCommands()
|
||||||
|
.UseForms())
|
||||||
|
.WithStartForm<StartForm>()
|
||||||
|
.NoProxy()
|
||||||
|
.DefaultCommands()
|
||||||
|
.NoSerialization()
|
||||||
|
.UsePersian()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a bot with middleware message loop like minimal message loop
|
||||||
|
/// </summary>
|
||||||
|
private static BotBase GetMinimalBot()
|
||||||
|
{
|
||||||
|
var bot = BotBaseBuilder
|
||||||
|
.Create()
|
||||||
|
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set"))
|
||||||
|
.MiddlewareMessageLoop(
|
||||||
|
messageLoop =>
|
||||||
|
messageLoop
|
||||||
|
.UseLoad())
|
||||||
|
.WithStartForm<StartForm>()
|
||||||
|
.NoProxy()
|
||||||
|
.DefaultCommands()
|
||||||
|
.NoSerialization()
|
||||||
|
.UsePersian()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BotBase GetPhotoBot()
|
||||||
|
{
|
||||||
|
var bot = BotBaseBuilder
|
||||||
|
.Create()
|
||||||
|
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ?? throw new Exception("API_KEY is not set"))
|
||||||
|
.MiddlewareMessageLoop(
|
||||||
|
messageLoop =>
|
||||||
|
messageLoop
|
||||||
|
.UseAttachments(MessageType.Photo))
|
||||||
|
.WithStartForm<StartForm>()
|
||||||
|
.NoProxy()
|
||||||
|
.DefaultCommands()
|
||||||
|
.NoSerialization()
|
||||||
|
.UsePersian()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -146,6 +146,12 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage,
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IStartFormSelectionStage MiddlewareMessageLoop(Func<MiddlewareBaseMessageLoop, MiddlewareBaseMessageLoop> messageLoopConfiguration)
|
||||||
|
{
|
||||||
|
_messageLoopFactory = messageLoopConfiguration(new MiddlewareBaseMessageLoop());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public IStartFormSelectionStage MinimalMessageLoop()
|
public IStartFormSelectionStage MinimalMessageLoop()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
using TelegramBotBase.Interfaces;
|
using System;
|
||||||
|
using TelegramBotBase.Interfaces;
|
||||||
|
using TelegramBotBase.MessageLoops;
|
||||||
|
|
||||||
namespace TelegramBotBase.Builder.Interfaces;
|
namespace TelegramBotBase.Builder.Interfaces;
|
||||||
|
|
||||||
@ -12,6 +14,12 @@ public interface IMessageLoopSelectionStage
|
|||||||
IStartFormSelectionStage DefaultMessageLoop();
|
IStartFormSelectionStage DefaultMessageLoop();
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Choses a fully customizable middleware-based message loop.
|
||||||
|
/// </summary>
|
||||||
|
IStartFormSelectionStage MiddlewareMessageLoop(Func<MiddlewareBaseMessageLoop, MiddlewareBaseMessageLoop> messageLoopConfiguration);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Chooses a minimalistic message loop, which catches all update types and only calls the Load function.
|
/// Chooses a minimalistic message loop, which catches all update types and only calls the Load function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
namespace TelegramBotBase.Localizations
|
namespace TelegramBotBase.Localizations;
|
||||||
{
|
|
||||||
public sealed class Persian : Localization
|
public sealed class Persian : Localization
|
||||||
{
|
{
|
||||||
public Persian()
|
public Persian()
|
||||||
@ -34,4 +34,3 @@
|
|||||||
Values["ButtonGrid_TagIcon"] = "📁";
|
Values["ButtonGrid_TagIcon"] = "📁";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -0,0 +1,310 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using TelegramBotBase.Args;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using static System.Collections.Specialized.BitVector32;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.MessageLoops.Extensions;
|
||||||
|
|
||||||
|
public static class MiddlewareBaseMessageLoopExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds middleware to the message loop then returns the message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop Use(this MiddlewareBaseMessageLoop messageLoop, Func<MessageContainer, Func<Task>, Task> middleware)
|
||||||
|
{
|
||||||
|
messageLoop.AddMiddleware(middleware);
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds update type validator middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseValidUpdateTypes(this MiddlewareBaseMessageLoop messageLoop, params UpdateType[] updateTypes)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var updateType = container.UpdateResult.RawData.Type;
|
||||||
|
|
||||||
|
if (updateTypes.Contains(updateType))
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds bot commands handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseBotCommands(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var botBase = container.BotBase;
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
|
||||||
|
if (messageResult.IsFirstHandler &&
|
||||||
|
messageResult.IsBotCommand &&
|
||||||
|
botBase.IsKnownBotCommand(messageResult.BotCommand))
|
||||||
|
{
|
||||||
|
var deviceSession = container.DeviceSession;
|
||||||
|
|
||||||
|
var sce =
|
||||||
|
new BotCommandEventArgs(messageResult.BotCommand,
|
||||||
|
messageResult.BotCommandParameters,
|
||||||
|
messageResult.Message,
|
||||||
|
deviceSession.DeviceId,
|
||||||
|
deviceSession);
|
||||||
|
|
||||||
|
await botBase.OnBotCommand(sce);
|
||||||
|
|
||||||
|
if (sce.Handled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseForms(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var activeForm = container.DeviceSession.ActiveForm;
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
|
||||||
|
//Pre Loading Event
|
||||||
|
await activeForm.PreLoad(messageResult);
|
||||||
|
|
||||||
|
//Send Load event to controls
|
||||||
|
await activeForm.LoadControls(messageResult);
|
||||||
|
|
||||||
|
//Loading Event
|
||||||
|
await activeForm.Load(messageResult);
|
||||||
|
|
||||||
|
var updateType = container.UpdateResult.RawData.Type;
|
||||||
|
|
||||||
|
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries)
|
||||||
|
if (updateType == UpdateType.Message)
|
||||||
|
{
|
||||||
|
if ((messageResult.MessageType == MessageType.Contact)
|
||||||
|
| (messageResult.MessageType == MessageType.Document)
|
||||||
|
| (messageResult.MessageType == MessageType.Location)
|
||||||
|
| (messageResult.MessageType == MessageType.Photo)
|
||||||
|
| (messageResult.MessageType == MessageType.Video)
|
||||||
|
| (messageResult.MessageType == MessageType.Audio))
|
||||||
|
{
|
||||||
|
var updateResult = container.UpdateResult;
|
||||||
|
|
||||||
|
await activeForm.SentData(new DataResult(updateResult));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var deviceSession = container.DeviceSession;
|
||||||
|
|
||||||
|
//Action Event
|
||||||
|
if (!deviceSession.FormSwitched && messageResult.IsAction)
|
||||||
|
{
|
||||||
|
//Send Action event to controls
|
||||||
|
await activeForm.ActionControls(messageResult);
|
||||||
|
|
||||||
|
//Send Action event to form itself
|
||||||
|
await activeForm.Action(messageResult);
|
||||||
|
|
||||||
|
if (!messageResult.Handled)
|
||||||
|
{
|
||||||
|
messageResult.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deviceSession.FormSwitched)
|
||||||
|
{
|
||||||
|
//Render Event
|
||||||
|
await activeForm.RenderControls(messageResult);
|
||||||
|
|
||||||
|
await activeForm.Render(messageResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms pre loads handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UsePreLoad(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var activeForm = container.DeviceSession.ActiveForm;
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
|
||||||
|
await activeForm.PreLoad(messageResult);
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms loads handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseLoad(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var activeForm = container.DeviceSession.ActiveForm;
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
|
||||||
|
await activeForm.LoadControls(messageResult);
|
||||||
|
await activeForm.Load(messageResult);
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms custom attachments handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseAttachments(this MiddlewareBaseMessageLoop messageLoop, params MessageType[] validAttachments)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var activeForm = container.DeviceSession.ActiveForm;
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
var updateType = container.UpdateResult.RawData.Type;
|
||||||
|
|
||||||
|
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries)
|
||||||
|
if (updateType == UpdateType.Message)
|
||||||
|
{
|
||||||
|
if ((messageResult.MessageType == MessageType.Contact)
|
||||||
|
| (messageResult.MessageType == MessageType.Document)
|
||||||
|
| (messageResult.MessageType == MessageType.Location)
|
||||||
|
| (messageResult.MessageType == MessageType.Photo)
|
||||||
|
| (messageResult.MessageType == MessageType.Video)
|
||||||
|
| (messageResult.MessageType == MessageType.Audio))
|
||||||
|
{
|
||||||
|
if (validAttachments.Contains(messageResult.MessageType))
|
||||||
|
{
|
||||||
|
var updateResult = container.UpdateResult;
|
||||||
|
|
||||||
|
await activeForm.SentData(new DataResult(updateResult));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms all attachments handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseAllAttachments(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var activeForm = container.DeviceSession.ActiveForm;
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
var updateType = container.UpdateResult.RawData.Type;
|
||||||
|
|
||||||
|
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries)
|
||||||
|
if (updateType == UpdateType.Message)
|
||||||
|
{
|
||||||
|
if ((messageResult.MessageType == MessageType.Contact)
|
||||||
|
| (messageResult.MessageType == MessageType.Document)
|
||||||
|
| (messageResult.MessageType == MessageType.Location)
|
||||||
|
| (messageResult.MessageType == MessageType.Photo)
|
||||||
|
| (messageResult.MessageType == MessageType.Video)
|
||||||
|
| (messageResult.MessageType == MessageType.Audio))
|
||||||
|
{
|
||||||
|
var updateResult = container.UpdateResult;
|
||||||
|
|
||||||
|
await activeForm.SentData(new DataResult(updateResult));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms actions handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseActions(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
var deviceSession = container.DeviceSession;
|
||||||
|
var activeForm = deviceSession.ActiveForm;
|
||||||
|
|
||||||
|
//Action Event
|
||||||
|
if (!deviceSession.FormSwitched && messageResult.IsAction)
|
||||||
|
{
|
||||||
|
//Send Action event to controls
|
||||||
|
await activeForm.ActionControls(messageResult);
|
||||||
|
|
||||||
|
//Send Action event to form itself
|
||||||
|
await activeForm.Action(messageResult);
|
||||||
|
|
||||||
|
if (!messageResult.Handled)
|
||||||
|
{
|
||||||
|
messageResult.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds forms renders handler middleware to the message loop then returns message loop
|
||||||
|
/// </summary>
|
||||||
|
public static MiddlewareBaseMessageLoop UseRender(this MiddlewareBaseMessageLoop messageLoop)
|
||||||
|
{
|
||||||
|
messageLoop.Use(async (container, next) =>
|
||||||
|
{
|
||||||
|
var messageResult = container.MessageResult;
|
||||||
|
var deviceSession = container.DeviceSession;
|
||||||
|
var activeForm = deviceSession.ActiveForm;
|
||||||
|
|
||||||
|
if (!deviceSession.FormSwitched)
|
||||||
|
{
|
||||||
|
await activeForm.RenderControls(messageResult);
|
||||||
|
|
||||||
|
await activeForm.Render(messageResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
return messageLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ namespace TelegramBotBase.MessageLoops;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Thats the default message loop which reacts to Message, EditMessage and CallbackQuery.
|
/// Thats the default message loop which reacts to Message, EditMessage and CallbackQuery.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FormBaseMessageLoop : IMessageLoopFactory
|
public sealed class FormBaseMessageLoop : IMessageLoopFactory
|
||||||
{
|
{
|
||||||
private static readonly object EvUnhandledCall = new();
|
private static readonly object EvUnhandledCall = new();
|
||||||
|
|
||||||
@ -22,7 +22,6 @@ public class FormBaseMessageLoop : IMessageLoopFactory
|
|||||||
{
|
{
|
||||||
var update = ur.RawData;
|
var update = ur.RawData;
|
||||||
|
|
||||||
|
|
||||||
if (update.Type != UpdateType.Message
|
if (update.Type != UpdateType.Message
|
||||||
&& update.Type != UpdateType.EditedMessage
|
&& update.Type != UpdateType.EditedMessage
|
||||||
&& update.Type != UpdateType.CallbackQuery)
|
&& update.Type != UpdateType.CallbackQuery)
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace TelegramBotBase.MessageLoops;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This message loop reacts to all update types.
|
/// This message loop reacts to all update types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FullMessageLoop : IMessageLoopFactory
|
public sealed class FullMessageLoop : IMessageLoopFactory
|
||||||
{
|
{
|
||||||
private static readonly object EvUnhandledCall = new();
|
private static readonly object EvUnhandledCall = new();
|
||||||
|
|
||||||
@ -20,9 +20,6 @@ public class FullMessageLoop : IMessageLoopFactory
|
|||||||
|
|
||||||
public async Task MessageLoop(BotBase bot, DeviceSession session, UpdateResult ur, MessageResult mr)
|
public async Task MessageLoop(BotBase bot, DeviceSession session, UpdateResult ur, MessageResult mr)
|
||||||
{
|
{
|
||||||
var update = ur.RawData;
|
|
||||||
|
|
||||||
|
|
||||||
//Is this a bot command ?
|
//Is this a bot command ?
|
||||||
if (mr.IsFirstHandler && mr.IsBotCommand && bot.IsKnownBotCommand(mr.BotCommand))
|
if (mr.IsFirstHandler && mr.IsBotCommand && bot.IsKnownBotCommand(mr.BotCommand))
|
||||||
{
|
{
|
||||||
@ -50,6 +47,7 @@ public class FullMessageLoop : IMessageLoopFactory
|
|||||||
//Loading Event
|
//Loading Event
|
||||||
await activeForm.Load(mr);
|
await activeForm.Load(mr);
|
||||||
|
|
||||||
|
var update = ur.RawData;
|
||||||
|
|
||||||
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries)
|
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) (Ignore Callback Queries)
|
||||||
if (update.Type == UpdateType.Message)
|
if (update.Type == UpdateType.Message)
|
||||||
|
|||||||
77
TelegramBotBase/MessageLoops/MiddlewareBaseMessageLoop.cs
Normal file
77
TelegramBotBase/MessageLoops/MiddlewareBaseMessageLoop.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TelegramBotBase.Args;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Interfaces;
|
||||||
|
using TelegramBotBase.Sessions;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.MessageLoops;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This message loop based on middleware pattern
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MiddlewareBaseMessageLoop : IMessageLoopFactory
|
||||||
|
{
|
||||||
|
private List<Func<MessageContainer, Func<Task>, Task>> Middlewares = new();
|
||||||
|
|
||||||
|
public event EventHandler<UnhandledCallEventArgs> UnhandledCall;
|
||||||
|
|
||||||
|
public async Task MessageLoop(BotBase bot, DeviceSession session, UpdateResult ur, MessageResult mr)
|
||||||
|
{
|
||||||
|
ur.Device = session;
|
||||||
|
mr.Device = session;
|
||||||
|
|
||||||
|
var messageContainer = new MessageContainer(bot, session, ur, mr);
|
||||||
|
|
||||||
|
if (Middlewares.Any())
|
||||||
|
{
|
||||||
|
int middlewareIndex = 0;
|
||||||
|
|
||||||
|
await InvokeMiddleware(messageContainer, middlewareIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes middleware with index
|
||||||
|
/// </summary>
|
||||||
|
private async Task InvokeMiddleware(MessageContainer messageContainer, int middlewareIndex)
|
||||||
|
{
|
||||||
|
await Middlewares[middlewareIndex]
|
||||||
|
.Invoke(messageContainer, async () =>
|
||||||
|
{
|
||||||
|
int nextMiddlewareIndex = middlewareIndex + 1;
|
||||||
|
if (nextMiddlewareIndex < Middlewares.Count)
|
||||||
|
{
|
||||||
|
await InvokeMiddleware(messageContainer, nextMiddlewareIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new middleware
|
||||||
|
/// </summary>
|
||||||
|
public void AddMiddleware(Func<MessageContainer, Func<Task>, Task> middleware)
|
||||||
|
{
|
||||||
|
Middlewares.Add(middleware);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct MessageContainer
|
||||||
|
{
|
||||||
|
public BotBase BotBase { get; private set; }
|
||||||
|
public DeviceSession DeviceSession { get; private set; }
|
||||||
|
public UpdateResult UpdateResult { get; private set; }
|
||||||
|
public MessageResult MessageResult { get; private set; }
|
||||||
|
|
||||||
|
public MessageContainer(BotBase botBase, DeviceSession deviceSession, UpdateResult updateResult, MessageResult messageResult)
|
||||||
|
{
|
||||||
|
BotBase = botBase;
|
||||||
|
DeviceSession = deviceSession;
|
||||||
|
UpdateResult = updateResult;
|
||||||
|
MessageResult = messageResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,7 +11,7 @@ namespace TelegramBotBase.MessageLoops;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a minimal message loop which will react to all update types and just calling the Load method.
|
/// This is a minimal message loop which will react to all update types and just calling the Load method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MinimalMessageLoop : IMessageLoopFactory
|
public sealed class MinimalMessageLoop : IMessageLoopFactory
|
||||||
{
|
{
|
||||||
private static readonly object EvUnhandledCall = new();
|
private static readonly object EvUnhandledCall = new();
|
||||||
|
|
||||||
@ -19,9 +19,6 @@ public class MinimalMessageLoop : IMessageLoopFactory
|
|||||||
|
|
||||||
public async Task MessageLoop(BotBase bot, DeviceSession session, UpdateResult ur, MessageResult mr)
|
public async Task MessageLoop(BotBase bot, DeviceSession session, UpdateResult ur, MessageResult mr)
|
||||||
{
|
{
|
||||||
var update = ur.RawData;
|
|
||||||
|
|
||||||
|
|
||||||
mr.Device = session;
|
mr.Device = session;
|
||||||
|
|
||||||
var activeForm = session.ActiveForm;
|
var activeForm = session.ActiveForm;
|
||||||
|
|||||||
@ -32,6 +32,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotAndWebApplication", "Exa
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InlineAndReplyCombination", "Examples\InlineAndReplyCombination\InlineAndReplyCombination.csproj", "{067E8EBE-F90A-4AFF-A0FF-20578216486E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InlineAndReplyCombination", "Examples\InlineAndReplyCombination\InlineAndReplyCombination.csproj", "{067E8EBE-F90A-4AFF-A0FF-20578216486E}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiddlewareBaseBot", "Examples\MiddlewareBaseBot\MiddlewareBaseBot.csproj", "{8D053824-966C-4F82-B184-4840DB36D5F2}"
|
||||||
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyInjection", "Examples\DependencyInjection\DependencyInjection.csproj", "{689B16BC-200E-4C68-BB2E-8B209070849B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyInjection", "Examples\DependencyInjection\DependencyInjection.csproj", "{689B16BC-200E-4C68-BB2E-8B209070849B}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
@ -80,6 +82,10 @@ Global
|
|||||||
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8D053824-966C-4F82-B184-4840DB36D5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8D053824-966C-4F82-B184-4840DB36D5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8D053824-966C-4F82-B184-4840DB36D5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8D053824-966C-4F82-B184-4840DB36D5F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{689B16BC-200E-4C68-BB2E-8B209070849B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{689B16BC-200E-4C68-BB2E-8B209070849B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{689B16BC-200E-4C68-BB2E-8B209070849B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{689B16BC-200E-4C68-BB2E-8B209070849B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{689B16BC-200E-4C68-BB2E-8B209070849B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{689B16BC-200E-4C68-BB2E-8B209070849B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -97,6 +103,7 @@ Global
|
|||||||
{261BED47-0404-4A9A-86FC-047DE42A7D25} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
{261BED47-0404-4A9A-86FC-047DE42A7D25} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
||||||
{52EA3201-02E8-46F5-87C4-B4752C8A815C} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
{52EA3201-02E8-46F5-87C4-B4752C8A815C} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
||||||
{067E8EBE-F90A-4AFF-A0FF-20578216486E} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
{067E8EBE-F90A-4AFF-A0FF-20578216486E} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
||||||
|
{8D053824-966C-4F82-B184-4840DB36D5F2} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
||||||
{689B16BC-200E-4C68-BB2E-8B209070849B} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
{689B16BC-200E-4C68-BB2E-8B209070849B} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user