Full API documentation of Telegram Bot API https://core.telegram.org/bots/api
Library API version 7.9
This library has 3 modules:
- Module :dataclass:
- 198
data class
with Kotlinx/Serialization - Contains only 1 file: TelegramModels.kt
- See example: Example with Ktor server
- See example: Telegram Webhook: Parse the Telegram request
- See example: Reply to the user with a Message
- 198
- Module :client: (TelegramModels.kt + TelegramClient.kt)
- 198
data class
with Kotlinx/Serialization + Ktor client with 122 methods for Telegram bot API - See example: Send a message to a user/group/channel
- 198
- Module :dataclass-only: (not recommended)
- 198
data class
only (serializer not included) - Contains only 1 file: TelegramModelsOnly.kt
- Could be used with Gson or plain Java / Kotlin project.
- 198
This project use Kotlin Multiplatform
Published on Maven Central:
-
Kotlin/JVM
for Java/Android -
Kotlin/JS
configuration used: IR, browser -
Kotlin/Native
configuration used: linuxX64
Learn more about Kotlin Multiplatform benefits.
This module could be used for parse the Telegram requests, and for send back a response.
This module contains only 1 file: TelegramModels.kt
Add this in your build.gradle.ktx
file:
// `data class` with Kotlinx/Serialization
implementation("com.github.omarmiatello.telegram:dataclass:7.9")
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 {
// Endpoint for Telegram webhook. Parse the Telegram request
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(
// Send a message back to the user
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)
}
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") // required for com.github.omarmiatello.telegram:client
import com.github.omarmiatello.kotlinscripttoolbox.core.launchKotlinScriptToolbox
import com.github.omarmiatello.telegram.TelegramClient
import kotlin.system.exitProcess
launchKotlinScriptToolbox(scriptName = "Telegram example") {
// Set up: Telegram notification
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)
}
// Send notification
sendTelegramMessage("Hello world!")
}
In the previous example we use this below, to parse the Telegram request.
// Endpoint for Telegram webhook. Parse the Telegram request
val request: Update = call.receiveText().parseTelegramRequest()
The Update
object has some properties:
/**
* <p>This <a href="#available-types">object</a> represents an incoming update.<br>At most <strong>one</strong> of the optional parameters can be present in any given update.</p>
*
* @property update_id The update's unique identifier. Update identifiers start from a certain positive number and increase sequentially. This identifier becomes especially handy if you're using <a href="#setwebhook">webhooks</a>, since it allows you to ignore repeated updates or to restore the correct update sequence, should they get out of order. If there are no new updates for at least a week, then identifier of the next update will be chosen randomly instead of sequentially.
* @property message <em>Optional</em>. New incoming message of any kind - text, photo, sticker, etc.
* @property edited_message <em>Optional</em>. New version of a message that is known to the bot and was edited. This update may at times be triggered by changes to message fields that are either unavailable or not actively used by your bot.
* @property channel_post <em>Optional</em>. New incoming channel post of any kind - text, photo, sticker, etc.
* @property edited_channel_post <em>Optional</em>. New version of a channel post that is known to the bot and was edited. This update may at times be triggered by changes to message fields that are either unavailable or not actively used by your bot.
* @property business_connection <em>Optional</em>. The bot was connected to or disconnected from a business account, or a user edited an existing connection with the bot
* @property business_message <em>Optional</em>. New non-service message from a connected business account
* @property edited_business_message <em>Optional</em>. New version of a message from a connected business account
* @property deleted_business_messages <em>Optional</em>. Messages were deleted from a connected business account
* @property message_reaction <em>Optional</em>. A reaction to a message was changed by a user. The bot must be an administrator in the chat and must explicitly specify <code>"message_reaction"</code> in the list of <em>allowed_updates</em> to receive these updates. The update isn't received for reactions set by bots.
* @property message_reaction_count <em>Optional</em>. Reactions to a message with anonymous reactions were changed. The bot must be an administrator in the chat and must explicitly specify <code>"message_reaction_count"</code> in the list of <em>allowed_updates</em> to receive these updates. The updates are grouped and can be sent with delay up to a few minutes.
* @property inline_query <em>Optional</em>. New incoming <a href="#inline-mode">inline</a> query
* @property chosen_inline_result <em>Optional</em>. The result of an <a href="#inline-mode">inline</a> query that was chosen by a user and sent to their chat partner. Please see our documentation on the <a href="/bots/inline#collecting-feedback">feedback collecting</a> for details on how to enable these updates for your bot.
* @property callback_query <em>Optional</em>. New incoming callback query
* @property shipping_query <em>Optional</em>. New incoming shipping query. Only for invoices with flexible price
* @property pre_checkout_query <em>Optional</em>. New incoming pre-checkout query. Contains full information about checkout
* @property poll <em>Optional</em>. New poll state. Bots receive only updates about manually stopped polls and polls, which are sent by the bot
* @property poll_answer <em>Optional</em>. A user changed their answer in a non-anonymous poll. Bots receive new votes only in polls that were sent by the bot itself.
* @property my_chat_member <em>Optional</em>. The bot's chat member status was updated in a chat. For private chats, this update is received only when the bot is blocked or unblocked by the user.
* @property chat_member <em>Optional</em>. A chat member's status was updated in a chat. The bot must be an administrator in the chat and must explicitly specify <code>"chat_member"</code> in the list of <em>allowed_updates</em> to receive these updates.
* @property chat_join_request <em>Optional</em>. A request to join the chat has been sent. The bot must have the <em>can_invite_users</em> administrator right in the chat to receive these updates.
* @property chat_boost <em>Optional</em>. A chat boost was added or changed. The bot must be an administrator in the chat to receive these updates.
* @property removed_chat_boost <em>Optional</em>. A boost was removed from a chat. The bot must be an administrator in the chat to receive these updates.
*
* @constructor Creates a [Update].
* */
@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)
To reply we could use the SendMessageRequest
class. This class has 2 mandatory fields: chat_id
and text
.
/**
* <p>Use this method to send text messages. On success, the sent <a href="#message">Message</a> is returned.</p>
*
* @property chat_id Unique identifier for the target chat or username of the target channel (in the format <code>@channelusername</code>)
* @property text Text of the message to be sent, 1-4096 characters after entities parsing
* @property parse_mode Mode for parsing entities in the message text. See <a href="#formatting-options">formatting options</a> for more details.
* @property disable_web_page_preview Disables link previews for links in this message
* @property disable_notification Sends the message <a href="https://telegram.org/blog/channels-2-0#silent-messages">silently</a>. Users will receive a notification with no sound.
* @property reply_to_message_id If the message is a reply, ID of the original message
* @property reply_markup Additional interface options. A JSON-serialized object for an <a href="https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating">inline keyboard</a>, <a href="https://core.telegram.org/bots#keyboards">custom reply keyboard</a>, instructions to remove reply keyboard or to force a reply from the user.
* */
@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)
}
}
This module contains only 2 file: TelegramModels.kt and TelegramClient.kt
Note: the
client
module includedataclass
module
Add this in your build.gradle.ktx
file:
// `data class` with Kotlinx/Serialization + Ktor client
implementation("com.github.omarmiatello.telegram:client:7.9")
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" // Retrieve a key from @BotFather
val chatId = "10000_example" // Choose a destination for your message
val telegramApi = TelegramClient(apiKey, httpClient) // NOTE httpClient is an optional parameter
telegramApi.sendMessage(chatId, msg)
NOTE: sendMessage()
is a suspend function and return a Message
.
/**
* <p>Use this method to send text messages. On success, the sent <a href="#message">Message</a> is returned.</p>
*
* @property chat_id Unique identifier for the target chat or username of the target channel (in the format <code>@channelusername</code>)
* @property text Text of the message to be sent, 1-4096 characters after entities parsing
* @property parse_mode Mode for parsing entities in the message text. See <a href="#formatting-options">formatting options</a> for more details.
* @property disable_web_page_preview Disables link previews for links in this message
* @property disable_notification Sends the message <a href="https://telegram.org/blog/channels-2-0#silent-messages">silently</a>. Users will receive a notification with no sound.
* @property reply_to_message_id If the message is a reply, ID of the original message
* @property reply_markup Additional interface options. A JSON-serialized object for an <a href="https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating">inline keyboard</a>, <a href="https://core.telegram.org/bots#keyboards">custom reply keyboard</a>, instructions to remove reply keyboard or to force a reply from the user.
*
* @return [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()
)
This module contains only 1 file: TelegramModelsOnly.kt
NOTE: Not for beginner. Guide here.
Add this in your build.gradle.ktx
file:
// alternative, contains: `data class` with Kotlinx/Serialization + Ktor client
implementation("com.github.omarmiatello.telegram:client:7.9")
// alternative, contains only: `data class` with Kotlinx/Serialization
implementation("com.github.omarmiatello.telegram:dataclass:7.9")
// alternative, contains only: `data class` (for plain Java/Kotlin project)
implementation("com.github.omarmiatello.telegram:dataclass-only:7.9")
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.