Telegram Bot API in Kotlin Multiplatform
Full API documentation of Telegram Bot API
https://core.telegram.org/bots/api
Library API version 7.9
This library has 3 modules:
Published on Maven Central:
Kotlin/JVM
for Java/AndroidKotlin/JS
configuration used: IR, browserKotlin/Native
configuration used: linuxX64
Learn more about Kotlin Multiplatform benefits.
How to use dataclass
module
This module could be used for parse the Telegram requests, and for send back a response.
This module contains only 1 file: TelegramModels.kt
Setup dataclass
module
Add this in your build.gradle.ktx
file:
implementation("com.github.omarmiatello.telegram:dataclass:7.9")
Example 1 - Ktor 3.0 server
Please start from https://start.ktor.io/
See Application.kt
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
.start(wait = true)
}
fun Application.module() {
routing {
post("/") {
var request: Update? = null
try {
request = call.receiveText().parseTelegramRequest()
telegramRequest(request)
} catch (e: Exception) {
val text = e.stackTraceToString()
val message = request?.message
val chatId = message?.chat?.id?.toString()
if (chatId != null) {
call.respond(
SendMessageRequest(
chat_id = chatId,
text = "```\n$text\n```",
parse_mode = ParseMode.Markdown,
reply_parameters = ReplyParameters(
message_id = message.message_id
)
)
)
}
}
if (call.response.status() == null) call.respond(HttpStatusCode.NoContent)
}
}
}
suspend fun RoutingContext.telegramRequest(request: Update) {
call.respond(
TelegramRequest.SendMessageRequest(
chat_id = request.message!!.chat.id.toString(),
text = "Message: ${request.message}\n\n```\n$request\n```",
parse_mode = ParseMode.Markdown,
)
)
}
suspend inline fun RoutingCall.respond(response: TelegramRequest) {
respondText(text = response.toJsonForResponse(), contentType = ContentType.Application.Json)
}
Example 2 - GitHub Actions using Kotlin Script
See https://github.com/omarmiatello/github-actions-kotlin-script-template
#!/usr/bin/env kotlin
@file:Repository("https://repo.maven.apache.org/maven2")
@file:DependsOn("com.github.omarmiatello.kotlin-script-toolbox:zero-setup:0.0.3")
@file:DependsOn("com.github.omarmiatello.telegram:client-jvm:7.9")
@file:DependsOn("io.ktor:ktor-client-okhttp-jvm:3.0.0")
import com.github.omarmiatello.kotlinscripttoolbox.core.launchKotlinScriptToolbox
import com.github.omarmiatello.telegram.TelegramClient
import kotlin.system.exitProcess
launchKotlinScriptToolbox(scriptName = "Telegram example") {
val telegramClient = TelegramClient(apiKey = readSystemPropertyOrNull("TELEGRAM_BOT_APIKEY")!!)
val defaultChatId = readSystemPropertyOrNull("TELEGRAM_CHAT_ID")!!
suspend fun sendTelegramMessage(text: String, chatId: String = defaultChatId) {
println("💬 $text")
telegramClient.sendMessage(chat_id = chatId, text = text)
}
sendTelegramMessage("Hello world!")
}
Telegram Webhook: Parse the Telegram request
In the previous example we use this below, to parse the Telegram request.
val request: Update = call.receiveText().parseTelegramRequest()
The Update
object has some properties:
@Serializable
data class Update(
val update_id: Long,
val message: Message? = null,
val edited_message: Message? = null,
val channel_post: Message? = null,
val edited_channel_post: Message? = null,
val business_connection: BusinessConnection? = null,
val business_message: Message? = null,
val edited_business_message: Message? = null,
val deleted_business_messages: BusinessMessagesDeleted? = null,
val message_reaction: MessageReactionUpdated? = null,
val message_reaction_count: MessageReactionCountUpdated? = null,
val inline_query: InlineQuery? = null,
val chosen_inline_result: ChosenInlineResult? = null,
val callback_query: CallbackQuery? = null,
val shipping_query: ShippingQuery? = null,
val pre_checkout_query: PreCheckoutQuery? = null,
val poll: Poll? = null,
val poll_answer: PollAnswer? = null,
val my_chat_member: ChatMemberUpdated? = null,
val chat_member: ChatMemberUpdated? = null,
val chat_join_request: ChatJoinRequest? = null,
val chat_boost: ChatBoostUpdated? = null,
val removed_chat_boost: ChatBoostRemoved? = null,
) : TelegramModel() {
override fun toJson() = json.encodeToString(serializer(), this)
companion object {
fun fromJson(string: String) = json.decodeFromString(serializer(), string)
}
}
This object handle all possible Telegram update, not just message
.
NOTE: This library contains a useful Kotlin extension for parse Telegram request from a String
.
fun String.parseTelegramRequest() = Update.fromJson(this)
Reply to the user with a Message
To reply we could use the SendMessageRequest
class. This class has 2 mandatory fields: chat_id
and text
.
@Serializable
data class SendMessageRequest(
val chat_id: String,
val text: String,
val parse_mode: ParseMode? = null,
val disable_web_page_preview: Boolean? = null,
val disable_notification: Boolean? = null,
val reply_to_message_id: Int? = null,
val reply_markup: @ContextualSerialization KeyboardOption? = null
) : TelegramRequest() {
override fun toJsonForRequest() = json.stringify(serializer(), this)
override fun toJsonForResponse() = JsonObject(
json.toJson(serializer(), this).jsonObject.content + ("method" to JsonLiteral("sendMessage"))
).toString()
companion object {
fun fromJson(string: String) = json.parse(serializer(), string)
}
}
How to use client
module
This module contains only 2 file: TelegramModels.kt and TelegramClient.kt
Note: the client
module include dataclass
module
Setup client
module
Add this in your build.gradle.ktx
file:
implementation("com.github.omarmiatello.telegram:client:7.9")
Send a message to a user/group/channel
You could use a custom HttpClient
(example with logger)
val httpClient = HttpClient(OkHttp) {
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
}
Retrive a key from @BotFather
val apiKey = "1000000:aaaaaaaaaa"
val chatId = "10000_example"
val telegramApi = TelegramClient(apiKey, httpClient)
telegramApi.sendMessage(chatId, msg)
NOTE: sendMessage()
is a suspend function and return a Message
.
suspend fun sendMessage(
chat_id: String,
text: String,
parse_mode: ParseMode? = null,
disable_web_page_preview: Boolean? = null,
disable_notification: Boolean? = null,
reply_to_message_id: Int? = null,
reply_markup: KeyboardOption? = null
) = telegramPost(
"$basePath/sendMessage",
SendMessageRequest(chat_id, text, parse_mode, disable_web_page_preview, disable_notification, reply_to_message_id, reply_markup).toJsonForRequest(),
Message.serializer()
)
How to use dataclass-only
module
This module contains only 1 file: TelegramModelsOnly.kt
NOTE: Not for beginner. Guide here.
Recap: Setup
Add this in your build.gradle.ktx
file:
implementation("com.github.omarmiatello.telegram:client:7.9")
implementation("com.github.omarmiatello.telegram:dataclass:7.9")
implementation("com.github.omarmiatello.telegram:dataclass-only:7.9")
License
MIT License
Copyright (c) 2020 Omar Miatello
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.