Skip to content

Determining Your Bot Design Plan

Nill edited this page Dec 29, 2021 · 1 revision

There are three main design patterns that Telefrag accomodates; feel free to use whichever pattern works the best for you.

Bot as a Service/Component

The most intuitive way to use Bot is simply to instantiate one, set its Options, and start using it.

From your own code, you can call API methods using the Bot.Methods object, and you can subscribe to events located on the Bot.Events object.

This paradigm treats Bot as a closed component (just as you would an InputBox or HttpClient) and uses the event-driven model that most C# developers grew up on.

Example:

 var b = new Bot("myBot", api_key);
 
 // Test our connection
 var me = await b.Methods.GetMe();
 Console.WriteLine($"My bot is connected and its username is @{me.username}");

// Hook up an event handler for chat messages
 b.Events.ChatMessage.Subscribe(async (context, e) =>
 {
     var text = e.Message?.text;
     if (text == "omg")
         await context.SendReply("bbq wtf");
 });

Advantages

  • Simple and intuitive
  • Consistent with other .NET client components

Disadvantages

  • All of the Bot's business logic is in another class
  • Business logic is not easily sharable/reusable between bots, platforms, or bot owners

Bot as a Base Class

In this model, the primary difference is that you subclass Bot and instantiate your specialization of Bot instead.

Example:

public class TestBot : Bot
{
    public TestBot(string id) : base(id)
    {
        Options.ApiKey = GetThisFromSomeplaceSecure();
        Events.ChatMessage.Subscribe(onChatMessage, this);
    }

    private async Task onChatMessage(Context c, MessageEventArgs e)
    {
        var text = e.Message?.text;
        if (text == "omg")
            await c.SendReply("bbq wtf");
    }
}

...
var b = new TestBot();
// Api key already populated and event handler
// already hooked up at this point

// Can still easily invoke methods or optionally subscribe to event handlers from outside the bot's class
var me = await b.Methods.GetMe();
Console.WriteLine($"My bot is connected and its username is @{me.username}");

Advantages

  • The bot's business logic is inside the bot's derived class
  • You can use private/protected fields/properties to track internal state as required
  • You can access protected virtual methods (e.g. OnUpdateReceived) which are more performant for high volume processing than handling events
  • Most rapid development model

Disadvantages

  • No code re-use/sharing between bots, developers, or bot owners, aside from the entire bot as a whole

BotLayer as a Base Class

In this model, all bot functionality is broken down into one or more layers, which can be added or removed as needed, shared among several bots, as well as packaged up as a NuGet package and leveraged by other bot owners for unrelated bots.

Functionality in layers should be modular so that consumers can mix and match features and personalities as desired. For example, a bot that helps manage chat administration might implement these example discrete layers in a single bot:

  • Greeter layer -- Greets users joining a chat and makes them aware of the rules
  • Bouncer layer -- Monitors users joining a chat and kicks/bans them if certain criteria are met
  • Gatekeeper layer -- In charge of rotating and disclosing the chat's invite link
  • Gamemaster layer -- Handles rolling dice, RNG, and other tasks

See Layers for more information about layers.

Example:

public class TestLayer : BotLayer
{
    // Business logic is packaged up in the layer
    // by the layer developer

    public TestLayer(Bot bot) : base(bot)
    {
        Events.ChatMessage.Subscribe(onChatMessage, this);
    }

    private async Task onChatMessage(Context c, MessageEventArgs e)
    {
        var text = e.Message?.text;
        if (text == "omg")
            await c.SendReply("bbq wtf");
    }
}

public class TestBot : Bot
{
    // Bot configuration is left to the bot owner

    public TestBot(string id) : base(id)
    {
        Options.ApiKey = GetThisFromSomeplaceSecure();
        Layers.Add<TestLayer>();
    }
}

Advantages

  • The bot's business logic is broken into unique duties that can be shared among bots and with other developers and bot owners.
  • The business logic can be removed, replaced, or re-ordered at any time without impacting the other functions of the bot (in other added layers or at the base layer)
  • Layers are lifetime sources, so constructs such as event handlers can be scoped to the layer's lifetime and so are automatically unsubscribed/removed if the layer that owns them is unloaded.
  • Layers can filter updates from receiving layers above them; giving the bot owner control over the order that various features on their bot take precedence

Disadvantages

  • Least rapid development model
  • Requires more code

Clone this wiki locally