TelegramBots / Telegram.Bot

.NET Client for Telegram Bot API
https://telegrambots.github.io/book
MIT License
3.11k stars 680 forks source link

Automatically generated request parameters classes #1015

Closed lentrodev closed 2 weeks ago

lentrodev commented 2 years ago

Automatically generated request parameters classes

I'd like to propose you to implement automatic generation of request parameters classes for each method available, using source generation.

For example, for the method SendTextMessageAsync will be created a new class named SendTextMessageParameters and interface ISendTextMessageParameters. Whole structure will look like this:


public interface ISendTextMessageParameters 
{
    ChatId ChatId { get; }

    string Text { get; }

    ISendTextMessageParameters WithChatId(ChatId chatId);

    SendTextMessageParameters WithText(string text);
}

public class SendTextMessageParameters : ISendTextMessageParameters 
{
    public ChatId ChatId { get; private set; }

    public string Text { get; private set; }

    public ISendTextMessageParameters WithChatId(ChatId chatId)
    {
        ChatId = chatId;

        return this;
    }

    public ISendTextMessageParameters WithText(string text)
    {
        Text = text;

        return this;
    }
}

And for make a request using this parameters, will be created overload for each method in the library.

In the TelegramBotClientParametersExtensions class:


public static Task SendTextMessageAsync(this ITelegramBotClient telegramBotClient, ISendTextMessageParameters sendTextMessageParameters)
{
    return telegramBotClient.SendTextMessageAsync(chatId: sendTextMessageParameters.ChatId, text: sendTextMessageParameters.Text, ...);
}

In your code:


public async Task DoSomethingAsync(ITelegramBotClient telegramBotClient)
{
    ISendTextMessageParameters sendTextMessageParameters = new SendTextMessageParameters()
        .WithChatId(128)
        .WithText("Hello Wold!");

    await telegramBotClient.SendTextMessageAsync(sendTextMessageParameters);
}

I think, this will will help users with building and reusing this parameters for future requests.

tuscen commented 2 years ago

I'd be glad to do that, but unfortunately the Bot API doesn't have any machine readable documentation. Current documentation is just an html page without any classes, it's just a bunch of divs and p so one would have to rely on hueristics to differentiate between types and methods, etc. I asked bot support for a machine readable docs and they answered they don't have plans for that in near future since the team have other priorities.

lentrodev commented 2 years ago

@tuscen I had successfull attempts with parsing official Telegram Bot API documentation, but it wasn't good for using it as scheme for implementing requests and API models, so I abandoned this project. My idea applies to already implemented methods, so source generator will take already defined extesion methods in TelegramBotClientExtensions class and just parse they signatures and will create classes and interfaces based on them.

tuscen commented 2 years ago

There's one disadvantage with using builders this way: builders are convenient when you use only their methods to set parameters. But about required parameters? If you set them in builder ctor it won't be as convenient. Otherwise you loose compile type safety.

lentrodev commented 2 years ago

@tuscen Anyway, if one of the required parameters is missing, Telegram will result an error when sending a request, so developer will see which parameter he forgot to specify. Or be can add some validation before sending a request, which will be a more correct solution, I think. I can test different solutions and propose a most correct one.

tuscen commented 2 years ago

We're trying to have as much compile time safety as we reasonably can though.

lentrodev commented 2 years ago

@tuscen Okay, I'll think about that, will propose a solution ASAP.

Vano4ok commented 1 year ago

To my mind, you can just use "required" when Telgram.Bot will be migrated to .NET 7. So problems with required parameters will be disappeared. And it looks no worse than the version with the builder.

public class SendTextMessageParameters 
{
    public required ChatId ChatId { get; init;} // or just set

    public required string Text { get; init;} // or just set

    public bool SomethingElse {get; init;}
}

In code

var param = new SendTextMessageParameters
{
    ChatId = 2,
    Text = "Vee"
}
wiz0u commented 2 weeks ago

We are now using required keyword and source generation (just not MS source generator) by parsing the official documentation.