Skip to content
Alfonso² Peterssen edited this page Jul 25, 2017 · 1 revision

Design

The library is designed to express Bots as a composition of features.
An ideal bot should look something like this:

class MyAwesomeBot
  // Bot structure
  extends TelegramBot
  with Polling // Webhook
  with Declarative
  with Commands
  with RegexCommands

  // Custom extensions
  with DatabaseStuff
  with AwesomeCommands
  with MoreAwesomeCommands
  with AwesomeInlineQueries
  with PaymentsProcessor
  
  // Extras 
  with AccessControl
  with UpdateLogger
  with AsyncUpdates {
  
  lazy val token = Properties
    .envOrNone("BOT_TOKEN")
    .getOrElse(Source.fromFile("bot.token").getLines().mkString)
}

Core

The library core BotBase exposes methods to receive all kind of events from Telegram (messages, inline queries...).

receiveMessage
receiveEditedMessage
receiveChannelPost
receiveEditedChannelPost
receiveInlineQuery
receiveChosenInlineResult
receiveCallbackQuery
receiveShippingQuery
receivePreCheckoutQuery

and a method receiveUpdate which basically acts as a dispatcher to the specific method based on the update type.

The cake pattern provides an elegant way to compose different functionalities. e.g. AccessControl trait

trait AccessControl extends BotBase {
  override def receiveMessage(msg: Message) {
    if (isAuthenticated(msg.from))
      // Pass to the upper level
      super.receiveMessage(msg)
    else {
      request(SendMessage(msg.source,
        "401 Forbidden!"))
    }
  }
}

// Usage:
// Handle messages only from authenticated/white-listed users.
class MayAwesomeBot extends BotBase 
  with Polling 
  with Commands 
  with AccessControl {

  ...

}

Declarative Interface

On top of the stackable core TelegramBot4s offers a declarative interface.

All declarative action methods start with on* for actions. e.g onMessage, onUpdate ...

// For each message ...
onMessage { implicit msg =>
  reply("Hello")
}
when(onCommand('secret), isSenderAuthenticated) {
  implicit msg =>
    reply("42")
}

Or to provide an error message:

whenOrElse(onCommand('secret), isSenderAuthenticated) {
  implicit msg =>
    reply("42")
} /* or else */ {
  reply("You must /login first")(_)
}

Declarative interfaces are encapsulated, e.g. Messages, Callbacks, Payments, Updates, InlineQueries ... To mix them all just mix Declarative.

Clone this wiki locally