Awesome
telepooz
telepooz is a scala wrapper for Telegram Bot API.
Table of contents
Quick start
telepooz built for scala-2.12. To use it add following to build file:
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.nikdon" % "telepooz" % "0.5.6"
And configure telepooz via the reference.conf
or aplication.conf
or by, for ex., env variables:
telegram {
host = "api.telegram.org"
token = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
token = ${?telegram_token}
polling {
interval = 1000 // in milliseconds
interval = ${?telegram_update_interval}
limit = 100
limit = ${?telegram_update_limit}
parallelism = 2
parallelism = ${?telegram_polling_parallelism}
}
reactor {
parallelism = 2
parallelism = ${?telegram_reactor_parallelism}
}
}
Why?
The only one reason to write was curiosity. Telepooz written on top of Akka Streams with intention to maximize using of functional abstractions provided by cats. For example, API requests are composable:
import com.github.nikdon.telepooz.api._
import com.github.nikdon.telepooz.model.methods
import com.github.nikdon.telepooz.engine.ApiRequestExecutor
val apiRequestExecutor = new ApiRequestExecutor() {}
val req = for {
a ← methods.GetMe
b ← methods.SendMessage("abc", a.result.fold("empty")(_.first_name))
} yield b
val res = req.foldMap(apiRequestExecutor)
whenReady(res){ m ⇒
m shouldBe a [Response[_]]
m.ok shouldEqual true
m.result shouldBe defined
m.result.value shouldBe a [model.Message]
}
telepooz is far from completion, here is a list of some desired features to implemented in future:
- File uploading via multipart/form-data
Usage
In general, bot consists of three parts: ApiRequestExecutor
, Polling
or WebHook
and Reactor
.
ApiRequestExecutor
creates requests to the telegram bot API endpoint. Polling
asks telegram server about new
updates via ApiRequestExecutor
and send them to the Reactor
. WebHook
receives new updates via incoming requests
from telegram. Finally Reactor
reacts on an input stream of incoming updates from the Polling
or WebHook
.
Toplevel Telepooz
trait provides a method instance
that is a
ReaderT[Future, (ApiRequestExecutor, Polling, Reactor), Done]
. To start a bot provide a valid input
for instance.run(...)
with all three components described above.
Polling
/** Just an example of how the bot might look like */
import com.github.nikdon.telepooz.engine._
object NaiveBot extends Telepooz with App {
implicit val are = new ApiRequestExecutor {}
val poller = new Polling
val reactor = new Reactor {
val reactions = CommandBasedReactions()
.on("/start")(implicit message ⇒ args ⇒ reply("You are started!"))
.on("/test")(implicit message ⇒ args ⇒ reply("Hi there!"))
}
instance.run((are, poller, reactor))
}
Webhook
import akka.stream.ActorMaterializer
import com.github.nikdon.telepooz.engine._
object WebhookBot extends Telepooz with App {
implicit val asm = ActorMaterializer()
implicit val are = new MockApiRequestExecutor(1) {}
val poller = new Webhook(endpoint = "test", interface = "127.0.0.1")
val reactor = new Reactor {
val reactions = CommandBasedReactions()
.on("/start")(implicit message ⇒
args ⇒ {
println(s"You are started! $args")
reply("You are started!")
})
.on("/test")(implicit message ⇒
args ⇒ {
println(s"You are tested! $args")
reply("You are tested!")
})
}
webhook.run((poller, reactor))
}
Contributors and participation
telepooz support the Typelevel code of conduct, contributions are always welcome. Good ways to contribute include:
- Raising bugs and feature requests,
- Fixing bugs and developing new features (I will attempt to merge in pull requests ASAP),
- Improving the performance of telepooz,
- Provide examples of bots.
License
telepooz is licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.