Skip to content
Alexey Alekhin edited this page Jul 26, 2017 · 3 revisions

Commands

Commands can be defined in a declarative way by mixing the declarative.Commands trait.
The follow declarations are all equivalent:

onCommand("/hello") { implicit msg => ... }
// '/' prefix is optional
onCommand("hello") { implicit msg => ... }
// Symbol command
onCommand('hello) { implicit msg => ... }

Note that the message is passed implicitly, this greatly reduces boilerplate on methods like reply or typing.

Several variants can be linked together:

// '/' prefix is optional
onCommand("/hello", "hi", "hey") { implicit msg => ... }  
  
// Also with symbol commands
onCommand('beer, 'beers, 'bier) { implicit msg => ... }

Replying

reply is a simple wrapper around SendMessage. Other wrappers can be added in a similar way. e.g. replyWithPhoto:

def replyWithPhoto(photo               : InputFile,
                   caption             : Option[String] = None,
                   disableNotification : Option[Boolean] = None,
                   replyToMessageId    : Option[Long] = None,
                   replyMarkup         : Option[ReplyMarkup] = None)
  (implicit msg: message): Future[Message] = {
  request(SendPhoto(msg.source, photo, caption, disableNotitication, replytoMessageId, replyMarkup))
}

// Usage
onCommand('pic) { implicit msg => 
  replyWithPhoto(InputFile(Paths.get("cat.jpg")), "!!")
}

Extractors

Getting certain information from messages can be done using extractors.

type Extractor[T, R] = T => Option[R]

using provides a simple way to extract fields or other information.

onCommand('hello) { implicit msg =>
  using(_.from) { user =>
    reply(s"Hello ${user.firstName}")
  }
}

Arguments

onCommand('echo) { implicit msg =>
  withArgs { args => 
    reply(args.mkString(" ").reverse)
  }
}

Or using pattern matching:

onCommand('random) { implicit msg =>
  withArgs {
    case Seq(Extractors.Int(n)) if n > 0 =>
      reply(rng.nextInt(n).toString)
    case _ =>
      reply("Invalid argumentヽ(ಠ_ಠ)ノ")
  }
}

There are some additional helpers:

def fromAuthenticatedUser(msg: Message): Boolean =
  msg.from.map(isAuthenticated).getOrElse(false)

// Command enabled for authenticated users only
when(onCommand('secret), fromAuthenticatedUser) {
  implicit msg =>
    reply("The answer to life the universe and everything: 42")
}

// Or
// Also warn non-autenticated users
whenOrElse(onCommand('secret), fromAuthenticatedUser) {
  implicit msg =>
    reply("The answer to life the universe and everything: 42")
} /* else */ {
  reply("Please /login first")(_)
}
Clone this wiki locally