-
Notifications
You must be signed in to change notification settings - Fork 0
Core Module Code Snippets
Please note: the entire project is carried out by one person. Some examples may be outdated. If you find outdated code, please create a new issue. Up-to-dated code is contained in the project.
To review the architecture of handlers (IUpdateHandlerBase<TUpdate>
), managers (LinearActionManager
), and updates, visit this link.
More info about BotBuilder
and available methods here.
static async Task Main(string[] args)
{
try
{
var privateCommandsManager = new LinearActionManager<SignedMessageTextUpdate>("commands.private");
var privateTextsHandler = new SignedMessageTextHandler(privateCommandsManager);
var privateMessagesHandler = new SignedMessageBaseHandler(privateTextsHandler);
var privateCallbacksManager = new LinearActionManager<SignedCallbackUpdate>("callbacks.private");
var privateCallbacksHandler = new CallbackHandler(privateCallbacks);
ChatDesigner privates = ChatDesigner.NewDesigner()
.UseMessageHandler(privateMessagesHandler)
.UseCallbackHandler(privateCallbacksHandler);
var bot = BotBuilder.NewBuilder("your_api_key")
.EnablePrivates(privates)
.Build();
BotBuilder.DebugSettings.LogExceptionTrace = true;
await bot.Listen();
}
catch (Exception e)
{
BotBuilder.DebugSettings.LocalLogger.Log(e);
return;
}
}
Last review: .Core v3.1.1 Back to contents
According to architecture IBotAction
serves as the endpoint for received updates. Here are examples of default actions available.
If you require passing any data via action data, please refer to the link (TODO: add refer ArgedInteractions).
public static DefaultCommand StartCommand { get; } = new("start", Do_StartAsync);
private static async Task Do_StartAsync(SignedMessageTextUpdate update)
{
// ...
}
public static DefaultCallback ClickMeCallback { get; } = new("ClickMeData", "Click Me Visible Text", Do_ClickMeAsync);
private static async Task Do_ClickMeAsync(SignedCallbackUpdate update)
{
// ...
}
Last review: .Core v3.1.1 Back to contents
When IBotAction
body defined, main question is: what can I do?
Through the received ICastedUpdated
you can access both: framework facilities and API methods.
BotManager
and ICastedUpdate
should cover all your needs, however if you need more fine-tuning or working with the API, you can access the Telegram.Bot
project's classes (Update
and ITelegramBotClient
).
private static async Task Do_StartAsync(SignedMessageTextUpdate update)
{
Update original = update.OriginalSource;
BotManager owner = update.Owner;
ITelegramBotClient bot = update.Owner.Bot;
}
Send a text message to the chat using its ID via bot instance or IDeliveryService
. Please note that this example based on the fact: Telegram users' IDs are equivalent to their chat IDs.
private static async Task Do_ActionAsync(SignedMessageTextUpdate update)
{
// Using ITelegramBotClient
await update.Owner.Bot.SendTextMessageAsync(update.Sender.TelegramId, "Hello World!");
// Using IDeliveryService
await update.Owner.DeliveryService.SendMessageToChatAsync(update.Sender.TelegramId, "Hello World!");
}
If you need to send a message to the same chat, then instead of explicitly declaring the ID (update.Sender.TelegramId
), you can use .AnswerSenderAsync(..., ISignedUpdate)
method.
Also, the basic functionality provides the ability to create a message class (TelegramTextMessage). This functionality is greatly expanded by the .AdvancedMessages module (WIP, temporarily refer to v3 Review (TODO)).
private static async Task Do_ActionAsync(SignedMessageTextUpdate update)
{
var message = new TelegramTextMessage("Hello World Message!")
{
AllowSendingWithoutReply = true,
ReplyToMessageId = update.TriggerMessageId,
};
await update.Owner.DeliveryService.AnswerSenderAsync(message, update);
}
If are developing multi-lingual bot interface you can use localizations.
private static async Task Do_ActionAsync(SignedMessageTextUpdate update)
{
var messageText = update.Owner.ResolveBotString("app.startUp");
var message = new TelegramTextMessage(messageText);
await update.Owner.DeliveryService.AnswerSenderAsync(message, update);
}
Ensuring you have declared "app.startUp" string in your localization pack:
{
"app.startUp": "..."
}
You can access the service provided it has been previously declared. More information on creating new services here.
private static async Task Do_ActionAsync(SignedMessageTextUpdate update)
{
var payments = await update.Owner.ResolveService<IPaymentsService>();
await payments.InitPayment(update.Sender, update);
}
Last review: .Core v3.1.1 Back to contents
IApplicant<T>
allows you to localize all bot actions in one class, which can be automatically applied to handlers/managers/other T
objects.
An example of the use of Applicant is the MenuService
class from the .PageNavs
module.
Here MenuService
as applicant, when applied to the appropriate manager, automatically declares the callbacks necessary for operation ('Back' and 'Open Page'). This adds development flexibility and allows you to divide code into logical parts.
public interface IMenuService : IBotService, IApplicant<IActionManager<SignedCallbackUpdate>>
{
// ...
}
public class MenuService : BotServiceBase, IMenuService
{
public void ApplyTo(IActionManager<SignedCallbackUpdate> callbackManager)
{
callbackManager.AddSafely(OpenPageCallback);
callbackManager.AddSafely(BackCallback);
}
}
An example of use can also be found in the project. Recommended system for using a complex Applicant - partial class using a C# nesting file.
Example Applicant (Applicant.cs
)
internal partial class MainApplicant : IApplicant<IActionManager<SignedMessageTextUpdate>>,
{
public void ApplyTo(IActionManager<SignedMessageTextUpdate> entity)
{
EnableCommands(entity);
}
private void EnableCommands(IActionManager<SignedMessageTextUpdate> entity)
{
entity.AddSafely(StartCommand);
}
internal static DefaultCommand StartCommand => new("start", Do_StartAsync);
private static async Task Do_StartAsync(SignedMessageTextUpdate update) { //... }
}
Example Applicant usage (Program.Main()
)
var privateCommandsManager = new LinearActionManager<SignedMessageTextUpdate>("commands.private");
applicant.ApplyTo(privateCommandsManager);
Example nesting file (.filenesting.json
)
{
"help": "https://go.microsoft.com/fwlink/?linkid=866610",
"root": true,
"dependentFileProviders": {
"add": {
"fileToFile": {
"add": {
"iCallbacks.cs": [ "MainApplicant.cs" ],
"iCommands.cs": [ "MainApplicant.cs" ],
"iInputs.cs": [ "MainApplicant.cs" ],
"iProcesses.cs": [ "MainApplicant.cs" ],
"iDataSets.cs": [ "MainApplicant.cs" ],
"iMenus.cs": [ "MainApplicant.cs" ]
}
}
}
}
}
Last review: .Core v3.1.1 Back to contents
Services require IBotService
implementation (IBotService : IDebugNamed, IOwnerCompilable
). Module provides OwnedObject
(see Owning) and BotServiceBase
classes.
public interface IPaymentsService : IBotService
{
public Task InitPayment(IBotUser payer, ISignedUpdate update);
}
public interface PaymentsService : BotServiceBase, IPaymentsService
{
public async Task InitPayment(IBotUser payer, ISignedUpdate update)
{
// You can access BotManager via inherited Owner property.
}
}
On bot creating add service or ServiceNotDefinedException
would be thrown on ResolveService<T>()
attempt.
var bot = BotBuilder.NewBuilder("your_api_key")
.EnablePrivates(privates)
.AddService<IPaymentsService>(new PaymentsService())
.Build();
Last review: .Core v3.1.1 Back to contents
To enable Users Manager in your project write custom UsersManager
class, implementing IUsersManager
. UM is used to collect and store user data during runtime (for ex. to save user state (TODO: add refer))
internal class UsersManager : IUsersManager
{
public UserDataChanged<IBotUser>? SignedUpdateHandled { get; set; }
private readonly List<DefaultBotUser> _users = [];
public async Task<bool> CheckIfRegisteredAsync(long telegramId) => await GetUserByIdAsync(telegramId) is not null;
public async Task<IBotUser?> GetUserByIdAsync(long telegramId) => await Task.FromResult(_users.Find(x => x.TelegramId == telegramId));
public async Task<IBotUser?> RegisterNewUserAsync(ICastedUpdate update)
{
var user = TelegramHelper.GetSender(update.OriginalSource, this)!;
var @new = new DefaultBotUser(user.Id, user.IsPremium.GetValueOrDefault(), user.LanguageCode ?? "en", user.FirstName);
_users.Add(@new);
return await Task.FromResult(@new);
}
}
ChatDesigner privates = ChatDesigner.NewDesigner()
.UseUsersManager(usersManager)
// ...
Last review: .Core v3.1.1 Back to contents
If you don't understand how this or that thing works, please share your problem in discussion.