Tourmaline is built around the concept of
Handlers, each of which is modeled to handle a specific kind of input. For instance, the CommandHandler is specifically designed to handle bot commands. Each handler also has a corresponding annotation. For instance, Command.
There are currently 7 types of handler built in:
For the purposes of this document we'll be focusing on the CommandHandler, since it's the one you're most likely to use most often, but you can find specific documentation for each handler type on their API reference page.
The Command Handler#
Most, though not all, bots respond to commands. Commands are a form of message which start (unless otherwise specified) with a forward slash (
/). A simple example of a command is probably one of the most common.
/start is the universal bot initialization command in Telegram, because whenever someone goes to your bot for the first time this is the command that's going to be sent. In most cases you'll see this command being used to welcome a user to your bot, explain what the bot does, and maybe do some analytics in the backend.
A very basic start command might look like this:
@[Command("start")] def start_command(ctx) ctx.message.reply("Welcome to my bot") end
Commands have the ability to get very complex though. For instance, you could have the
/start command and the
/help command be the same thing. This is somewhat common for smaller bots with less commands.
@[Command(["start", "help"])] def start_command(ctx) # ... end
You can also set custom prefixes for your commands. For instance, it's also common to use
! as an additional prefix.
@[Command(["start", "help"], prefix: ["/", "!"])] def start_command(ctx) # ... end
You can even stack handlers if you so wish, just be sure to do some type checking.
@[Hears(/^how do i/)] @[Command(["start", "help"], prefix: ["/", "!"])] def start_command(ctx) # Both handlers have a `#message` property, so this is safe message = ctx.message # ... end
Handlers Without Annotations#
While annotations are the preferred way to invoke handlers, they aren't the only way. Sometimes you may wish to dynamically generate handlers, or you may be use to a library like Python-Telegram-Bot and prefer to add handlers to your bot instance using a more functional approach.
Here's an example of a
/start command added using this method:
# This makes things less verbose include Tourmaline bot = Client.new("YOUR_API_TOKEN") bot.add_handler CommandHandlers.new("start") do |ctx| ctx.message.reply("Welcome to my bot) end
And that's all there is to it! Which you prefer is, of course, your choice. In truth, as we'll see below, handlers are just syntactic sugar around this exact methodology.
All handlers have a property called
group which is normally set to
:default. Groups allow us to make sure that only one handler responds to any given update, unless otherwise specified. In most cases you'll want to just leave this property alone, but in the case that you do want multiple handlers to respond to incoming updates all you have to do is set
group to something unique. For example:
@[On(:update, group: :persist_users)] def persist_users(update) # ... end @[Command("help")] def help_command(ctx) # ... end
In the above example if we didn't have the
group set in the first handler the second handler would never get called.
You can also create custom handlers if you want. Let's create a simple
PhotoHandler as an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
For more advanced handler logic, be sure to check the source for each of the existing handlers.