{"id":18418093,"url":"https://github.com/bot4s/telegram","last_synced_at":"2026-01-11T16:54:43.518Z","repository":{"id":35761101,"uuid":"40040516","full_name":"bot4s/telegram","owner":"bot4s","description":"Telegram Bot API Wrapper for Scala","archived":false,"fork":false,"pushed_at":"2024-04-13T06:05:58.000Z","size":2271,"stargazers_count":401,"open_issues_count":10,"forks_count":96,"subscribers_count":19,"default_branch":"main","last_synced_at":"2024-04-14T02:42:17.373Z","etag":null,"topics":["polling","scala","telegram","telegram-api","telegram-bot","telegram-bot-api","telegram-bots","webhook"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bot4s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2015-08-01T08:31:47.000Z","updated_at":"2024-04-15T07:31:54.808Z","dependencies_parsed_at":"2023-11-08T04:24:56.925Z","dependency_job_id":"9f776893-baba-4888-873b-ee29ea0d622c","html_url":"https://github.com/bot4s/telegram","commit_stats":null,"previous_names":["mukel/telegrambot4s"],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bot4s%2Ftelegram","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bot4s%2Ftelegram/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bot4s%2Ftelegram/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bot4s%2Ftelegram/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bot4s","download_url":"https://codeload.github.com/bot4s/telegram/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247661597,"owners_count":20975083,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["polling","scala","telegram","telegram-api","telegram-bot","telegram-bot-api","telegram-bots","webhook"],"created_at":"2024-11-06T04:12:32.563Z","updated_at":"2026-01-11T16:54:43.510Z","avatar_url":"https://github.com/bot4s.png","language":"Scala","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" title=\"TelegramBot4s\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ci\u003e\n    Idiomatic Scala wrapper for the\n    \u003ca href=\"https://core.telegram.org/bots/api\" title=\"Telegram Bot API\"\u003e\n      Telegram Bot API\n    \u003c/a\u003e\n  \u003c/i\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://core.telegram.org/bots/api#recent-changes\" title=\"Telegram Bot API\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Bot%20API-6.9%20(September%2022,%202023)-00aced.svg\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://t.me/bot4s_updates\" title=\"Bot4s Telegram Channel\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/💬%20Channel-Bot4s-00aced.svg\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://t.me/bot4s\" title=\"Bot4s Telegram Group\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/💬%20Group-Bot4s-00aced.svg\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/bot4s/telegram/actions/workflows/build.yml\" title=\"Github Action Build Status\"\u003e\n    \u003cimg src=\"https://github.com/bot4s/telegram/actions/workflows/build.yml/badge.svg?branch=main\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://maven-badges.herokuapp.com/maven-central/com.bot4s/telegram-core_2.13\" title=\"Maven Central\"\u003e\n    \u003cimg src=\"https://maven-badges.sml.io/sonatype-central/com.bot4s/telegram-core_2.13/badge.svg\"/\u003e\n  \u003c/a\u003e\n\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"http://www.apache.org/licenses/LICENSE-2.0.html\" title=\"License\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-Apache%202-blue.svg\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# bot4s.telegram\n\nSimple, extensible, strongly-typed wrapper for the [Telegram Bot API](https://core.telegram.org/bots/api).\n\n# Table of contents\n\n- [Installation](#installation)\n- [Quickstart with scala-cli](#quickstart-with-scala-cli)\n- [Examples](#examples)\n- [Leaking bot tokens](#leaking-bot-tokens)\n- [Webhooks vs Polling](#webhooks-vs-polling)\n- [Payments](#payments)\n- [Games](#games)\n- [Deployment](#deployment)\n- [Running the examples](#running-the-examples)\n- [A note on implicits](#a-note-on-implicits)\n- [Versioning](#versioning)\n- [Authors](#authors)\n- [License](#license)\n\n## Installation\n\nSince version 6.0.0 `telegram-core` and `telegram-pekko` are published for Scala 2.12, 2.13 and 3.\n\nAdd to your `build.sbt` file:\n\n```scala\n// Core with minimal dependencies, enough to spawn your first bot.\nlibraryDependencies += \"com.bot4s\" %% \"telegram-core\" % \"7.0.0\"\n\n// Extra goodies: Webhooks, support for games, bindings for actors.\nlibraryDependencies += \"com.bot4s\" %% \"telegram-pekko\" % \"7.0.0\"\n```\n\nFor [mill](https://mill-build.org/mill/) add to your `build.sc` project deps:\n\n```scala\n// Core with minimal dependencies, enough to spawn your first bot.\nivy\"com.bot4s::telegram-core:7.0.0\",\n// Extra goodies: Webhooks, support for games, bindings for actors.\nivy\"com.bot4s::telegram-pekko:7.0.0\"\n```\n\n## Quickstart with scala-cli.\n\nReplace `BOT_TOKEN` with your [Telegram bot token](https://core.telegram.org/bots/tutorial#obtain-your-bot-token).\n\n```scala\n//\u003e using scala 3.3.7\n//\u003e using dep \"com.bot4s::telegram-core:7.0.0\"\n//\u003e using dep \"com.softwaremill.sttp.client3::okhttp-backend:3.11.0\"\n//\nimport cats.syntax.functor.*\nimport scala.concurrent.*\nimport scala.concurrent.duration.*\nimport com.bot4s.telegram.api.RequestHandler\nimport com.bot4s.telegram.clients.FutureSttpClient\nimport com.bot4s.telegram.future.*\nimport com.bot4s.telegram.methods.SendMessage\nimport com.bot4s.telegram.models.Message\nimport sttp.client4.Backend\nimport sttp.client4.okhttp.OkHttpFutureBackend\n\n/**\n * Echo bot.\n * Echo, ohcE\n */\nclass EchoBot(token: String) extends TelegramBot with Polling {\n  implicit val backend: Backend[Future] = OkHttpFutureBackend()\n  override val client: RequestHandler[Future]    = new FutureSttpClient(token)\n\n  override def receiveMessage(msg: Message): Future[Unit] =\n    msg.text.fold(Future.successful(())) { text =\u003e\n      request(SendMessage(msg.source, text.reverse)).void\n    }\n}\n\n@main def main() = {\n  // To run spawn the bot\n  val bot = new EchoBot(\"BOT_TOKEN\")\n  val eol: Future[Unit] = bot.run()\n  println(\"Press [ENTER] to shutdown the bot, it may take a few seconds...\")\n  scala.io.StdIn.readLine()\n  bot.shutdown() // initiate shutdown\n  // Wait for the bot end-of-life\n  Await.result(eol, Duration.Inf)\n}\n```\n\n## Examples\n\n#### Random bot [(full example)](https://github.com/bot4s/telegram/blob/main/examples/src/RandomBot.scala)\n\n```scala\nclass RandomBot(token: String) extends ExampleBot(token) with Polling with Commands[Future] {\n\n  val rng = new scala.util.Random(System.currentTimeMillis())\n  onCommand(\"coin\" or \"flip\") { implicit msg =\u003e\n    reply(if (rng.nextBoolean()) \"Head!\" else \"Tail!\").void\n  }\n  onCommand(\"real\" | \"double\" | \"float\") { implicit msg =\u003e\n    reply(rng.nextDouble().toString).void\n  }\n  onCommand(\"/die\" | \"roll\") { implicit msg =\u003e\n    reply(\"⚀⚁⚂⚃⚄⚅\" (rng.nextInt(6)).toString).void\n  }\n  onCommand(\"random\" or \"rnd\") { implicit msg =\u003e\n    withArgs {\n      case Seq(Int(n)) if n \u003e 0 =\u003e\n        reply(rng.nextInt(n).toString).void\n      case _ =\u003e reply(\"Invalid argumentヽ(ಠ_ಠ)ノ\").void\n    }\n  }\n  onCommand(\"choose\" | \"pick\" | \"select\") { implicit msg =\u003e\n    withArgs { args =\u003e\n      replyMd(if (args.isEmpty) \"No arguments provided.\" else args(rng.nextInt(args.size))).void\n    }\n  }\n\n  onCommand(\"auto\") { implicit msg =\u003e\n    request(SendDice(msg.chat.id)).void\n  }\n  // Extractor\n  object Int {\n    def unapply(s: String): Option[Int] = Try(s.toInt).toOption\n  }\n\n}\n```\n\n#### Text to speech bot [(full example)](https://github.com/bot4s/telegram/blob/main/examples/src-jvm-2/TextToSpeechBot.scala)\n\n```scala\n/**\n * Text-to-speech bot (using Google TTS API)\n *\n * Google will rightfully block your IP in case of abuse.\n * '''Usage:''' /speak Hello World\n * '''Inline mode:''' @YourBot This is awesome\n */\nclass TextToSpeechBot(token: String)\n    extends ExampleBot(token)\n    with Polling\n    with Commands[Future]\n    with InlineQueries[Future]\n    with ChatActions[Future] {\n\n  def ttsUrl(text: String): String =\n    s\"http://translate.google.com/translate_tts?client=tw-ob\u0026tl=en-us\u0026q=${URLEncoder.encode(text, \"UTF-8\")}\"\n\n  onCommand(\"speak\" | \"say\" | \"talk\") { implicit msg =\u003e\n    withArgs { args =\u003e\n      val text = args.mkString(\" \")\n      for {\n        r \u003c- Future(scalaj.http.Http(ttsUrl(text)).asBytes)\n        if r.isSuccess\n        bytes    = r.body\n        _       \u003c- uploadingAudio // hint the user\n        voiceMp3 = InputFile(\"voice.mp3\", bytes)\n        _       \u003c- request(SendVoice(msg.source, voiceMp3))\n      } yield ()\n    }\n  }\n\n  def nonEmptyQuery(iq: InlineQuery): Boolean = iq.query.nonEmpty\n\n  whenOrElse(onInlineQuery, nonEmptyQuery) { implicit iq =\u003e\n    answerInlineQuery(\n      Seq(\n        // Inline \"playable\" preview\n        InlineQueryResultVoice(\"inline: \" + iq.query, ttsUrl(iq.query), iq.query),\n        // Redirection to /speak command\n        InlineQueryResultArticle(\n          \"command: \" + iq.query,\n          iq.query,\n          inputMessageContent = InputTextMessageContent(\"/speak \" + iq.query),\n          description = \"/speak \" + iq.query\n        )\n      )\n    ).void\n  } /* empty query */ {\n    answerInlineQuery(Seq())(_).void\n  }\n}\n```\n\n#### Calculator bot (using Webhooks) [(full example)](https://github.com/bot4s/telegram/blob/main/examples/src-jvm-2/WebhookBot.scala)\n\n\n```scala\nclass WebhookBot(token: String) extends PekkoExampleBot(token) with Webhook {\n  val port       = 8080\n  val webhookUrl = \"https://88c444ab.ngrok.io\"\n\n  val baseUrl = \"http://api.mathjs.org/v1/?expr=\"\n\n  override def receiveMessage(msg: Message): Future[Unit] =\n    msg.text.fold(Future.successful(())) { text =\u003e\n      val url = baseUrl + URLEncoder.encode(text, \"UTF-8\")\n      for {\n        res \u003c- Http().singleRequest(HttpRequest(uri = Uri(url)))\n        if res.status.isSuccess()\n        result \u003c- Unmarshal(res).to[String]\n        _      \u003c- request(SendMessage(msg.source, result))\n      } yield ()\n    }\n}\n```\n\nCheck out the [sample bots](https://github.com/bot4s/telegram/tree/main/examples) for more functionality.\n\n## Leaking bot tokens\n\n**Don't ever expose your bot's token.**\n\nHopefully [GitGuardian](https://www.gitguardian.com/) got you covered and will warn you about exposed API keys.\n\n## Webhooks vs. Polling\n\nBoth methods are supported.\n(Long) Polling is bundled in the `core` artifact and it's by far the easiest method.\n\nWebhook support comes in the `extra` artifact based on [pekko-http](https://github.com/apache/pekko-http); requires a server, it won't work on your laptop.\nFor a comprehensive reference check [Marvin's Patent Pending Guide to All Things Webhook](https://core.telegram.org/bots/webhooks).\n\nSome webhook examples are available [here](https://github.com/bot4s/telegram/blob/main/examples/src-jvm-2/WebhookBot.scala) and [here](https://github.com/bot4s/telegram/blob/main/examples/src-jvm-2/WebhookSSLBot.scala) (with self signed SSL certificate setup).\n\n## Payments\n\nPayments are supported since version 3.0; refer to [official payments documentation](https://core.telegram.org/bots/payments) for details.\nI'll support developers willing to integrate and/or improve the payments API; please report issues [here](https://github.com/bot4s/telegram/issues/new).\n\n## Games\n\nThe Pekko extensions include support for games in two flavors; self-hosted (served by the bot itself),\nand external, hosted on e.g. GitHub Pages.\nCheck both the [self-hosted](https://github.com/bot4s/telegram/blob/main/examples/src-jvm-2/SelfHosted2048Bot.scala) and\n[GitHub-hosted](https://github.com/bot4s/telegram/blob/main/examples/src-jvm-2/GitHubHosted2048Bot.scala) versions of the\npopular [2048](https://gabrielecirulli.github.io/2048/) game.\n\n## Deployment\n\n`bot4s.telegram` runs on Raspberry Pi, Heroku, Google App Engine and most notably on an old Android (4.1.2) phone with a broken screen via the JDK for ARM.\nBots also runs flawlessly on top of my master thesis: \"A meta-circular Java bytecode interpreter for the GraalVM\".\n\nDistribution/deployment is outside the scope of the library, but all platforms where Java is\nsupported should be compatible. You may find [sbt-assembly](https://github.com/sbt/sbt-assembly) and [sbt-docker](https://github.com/marcuslonnberg/sbt-docker)\nvery handy.\n\nScala.js is also supported, bots can run on the browser via the SttpClient. NodeJs is not supported yet.\n\n## Running the examples\n\n`bot4s.telegram` uses [mill](https://mill-build.org/mill/).\n\n```\n./mill examples.jvm[2.13.10].console\n[79/79] examples.jvm[2.13.10].console\nWelcome to Scala 2.13.10 (OpenJDK 64-Bit Server VM, Java 11.0.10).\nType in expressions for evaluation. Or try :help.\n\nscala\u003e new RandomBot(\"BOT_TOKEN\").run()\n```\n\nChange `RandomBot` to whatever bot you find interesting [here](https://github.com/bot4s/telegram/tree/main/examples).\n\n## A note on implicits\n\nA few implicits are provided to reduce boilerplate, but are discouraged because unexpected side-effects.\n\nThink seamless `T =\u003e Option[T]` conversion, Markdown string extensions (these are fine)...\nBe aware that, for conciseness, most examples need the implicits to compile, be sure to include them.\n\n`import com.bot4s.telegram.Implicits._`\n\n## Versioning\n\nThis library uses [Semantic Versioning](http://semver.org/). For the versions available, see the [tags on this repository](https://github.com/bot4s/telegram/tags).\n\n## Authors\n\n- **Alfonso² Peterssen** - _Owner/maintainer_ - :octocat: [mukel](https://github.com/mukel)\n\n_Looking for maintainers!_\n\nSee also the list of [awesome contributors](https://github.com/bot4s/telegram/contributors) who participated in this project.\nContributions are very welcome, documentation improvements/corrections, bug reports, even feature requests.\n\n## License\n\nThis project is licensed under the Apache 2.0 License - see the [LICENSE](/LICENSE) file for details.\n\n## Buy Me A Coffee\n\n\u003ca href=\"https://www.buymeacoffee.com/bot4s.telegram\"\u003e\u003cimg src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: auto !important;width: auto !important;\" \u003e\u003c/a\u003e\n\nIf you like this library, please consider buying me a coffee. :relaxed:\n","funding_links":["https://www.buymeacoffee.com/bot4s.telegram"],"categories":["Telegram Libraries"],"sub_categories":["Scala"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbot4s%2Ftelegram","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbot4s%2Ftelegram","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbot4s%2Ftelegram/lists"}