Idiomatic Scala wrapper for the Telegram Bot API
Simple, extensible, strongly-typed wrapper for the Telegram Bot API.
The current version is experimental, feel free to report bugs, for a stable (but a bit outdated) version, please check https://github.com/bot4s/telegram/tree/91f51fc9bddf6daaf21ee1e1629b0471723db591 .
- Quick start
- Leaking bot tokens
- Webhooks vs Polling
- Payments
- Games
- Deployment (or how to turn a spare phone into a Telegram Bot)
- Running the examples
- A note on implicits
- Examples
- Versioning
- Authors
- License
Add to your build.sbt
file:
// Core with minimal dependencies, enough to spawn your first bot.
libraryDependencies += "com.bot4s" %% "telegram-core" % "4.0.0-RC2"
// Extra goodies: Webhooks, support for games, bindings for actors.
libraryDependencies += "com.bot4s" %% "telegram-akka" % "4.0.0-RC2"
For mill add to your build.sc
file:
def ivyDeps = Seq(
ivy"com.bot4s::telegram-core:4.0.0-RC2", // core
ivy"com.bot4s::telegram-akka:4.0.0-RC2" // extra goodies
)
Don't ever expose your bot's token.
Hopefully GitGuardian got you covered and will warn you about exposed API keys.
Both methods are supported.
(Long) Polling is bundled in the core
artifact and it's by far the easiest method.
Webhook support comes in the extra
artifact based on akka-http; requires a server, it won't work on your laptop.
For a comprehensive reference check Marvin's Patent Pending Guide to All Things Webhook.
Payments are supported since version 3.0; refer to official payments documentation for details. I'll support developers willing to integrate and/or improve the payments API; please report issues here.
The Akka extensions include support for games in two flavors; self-hosted (served by the bot itself), and external, hosted on e.g. GitHub Pages. Check both the self-hosted and GitHub-hosted versions of the popular 2048 game.
I've managed to run bots on a Raspberry Pi 2, Heroku, Google App Engine
and most notably on an old Android (4.1.2) phone with a broken screen via the JDK for ARM.
Distribution/deployment is outside the scope of the library, but all platforms where Java is supported should be compatible. You may find sbt-assembly and sbt-docker very handy.
Scala.js is also supported, bots can run on the browser via the SttpClient. NodeJs is not supported yet.
bot4s.telegram
uses mill.
$ mill -i "examples[2.12.6].console"
[84/84] examples[2.12.6].console
Welcome to Scala 2.12.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_162).
Type in expressions for evaluation. Or try :help.
scala> new RandomBot("TOKEN").run()
Change RandomBot
to whatever bot you find interesting here.
A few implicits are provided to reduce boilerplate, but are discouraged because unexpected side-effects.
Think seamless T => Option[T]
conversion, Markdown string extensions (these are fine)...
Be aware that, for conciseness, most examples need the implicits to compile, be sure to include them.
import com.bot4s.telegram.Implicits._
Let me Google that for you! (full example)
import com.bot4s.telegram.api.declarative.Commands
import com.bot4s.telegram.api.Polling
/** Generates random values.
*/
class RandomBot(val token: String) extends TelegramBot
with Polling
with Commands {
val client = new ScalajHttpClient(token)
val rng = new scala.util.Random(System.currentTimeMillis())
onCommand("coin" or "flip") { implicit msg =>
reply(if (rng.nextBoolean()) "Head!" else "Tail!")
}
onCommand('real | 'double | 'float) { implicit msg =>
reply(rng.nextDouble().toString)
}
onCommand("/die") { implicit msg =>
reply((rng.nextInt(6) + 1).toString)
}
onCommand("random" or "rnd") { implicit msg =>
withArgs {
case Seq(Int(n)) if n > 0 =>
reply(rng.nextInt(n).toString)
case _ => reply("Invalid argumentヽ(ಠ_ಠ)ノ")
}
}
onCommand('choose | 'pick | 'select) { implicit msg =>
withArgs { args =>
replyMd(if (args.isEmpty) "No arguments provided." else args(rng.nextInt(args.size)))
}
}
/* Int(n) extractor */
object Int { def unapply(s: String): Option[Int] = Try(s.toInt).toOption }
}
val bot = new RandomBot("BOT_TOKEN")
val eol = bot.run()
println("Press [ENTER] to shutdown the bot, it may take a few seconds...")
scala.io.StdIn.readLine()
bot.shutdown() // initiate shutdown
// Wait for the bot end-of-life
Await.result(eol, Duration.Inf)
Google TTS (full example)
object TextToSpeechBot extends TelegramBot
with Polling
with Commands
with ChatActions {
override val client = new ScalajHttpClient("BOT_TOKEN")
def ttsUrl(text: String): String =
s"http://translate.google.com/translate_tts?client=tw-ob&tl=en-us&q=${URLEncoder.encode(text, "UTF-8")}"
onCommand("speak" | "say" | "talk") { implicit msg =>
withArgs { args =>
val text = args.mkString(" ")
for {
r <- Future { scalaj.http.Http(ttsUrl(text)).asBytes }
if r.isSuccess
bytes = r.body
} /* do */ {
uploadingAudio // hint the user
val voiceMp3 = InputFile("voice.mp3", bytes)
request(SendVoice(msg.source, voiceMp3))
}
}
}
}
val bot = TextToSpeechBot
val eol = bot.run()
println("Press [ENTER] to shutdown the bot, it may take a few seconds...")
scala.io.StdIn.readLine()
bot.shutdown() // initiate shutdown
// Wait for the bot end-of-life
Await.result(eol, Duration.Inf) // ScalaJs wont't let you do this
object LmgtfyBot extends AkkaTelegramBot
with Webhook
with Commands {
val client = new AkkaHttpClient(TOKEN)
override val port = 8443
override val webhookUrl = "https://1d1ceb07.ngrok.io"
onCommand("lmgtfy") { implicit msg =>
withArgs { args =>
reply(
"http://lmgtfy.com/?q=" + URLEncoder.encode(args.mkString(" "), "UTF-8"),
disableWebPagePreview = Some(true)
)
}
}
}
Check out the sample bots for more functionality.
This library uses Semantic Versioning. For the versions available, see the tags on this repository.
- Alfonso² Peterssen - Owner/maintainer -
mukel
Looking for maintainers!
See also the list of awesome contributors who participated in this project. Contributions are very welcome, documentation improvements/corrections, bug reports, even feature requests.
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.