Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
f248ab389f Update Gradle to v9 2026-08-06 18:24:24 +00:00
13 changed files with 2 additions and 548 deletions

View File

@@ -1,12 +0,0 @@
# BotSubscriptionsBot
Demonstrates Bot Subscriptions (subscription updates) support introduced in Telegram Bot API 10.2.
The bot logs and reacts to `subscription` updates — when a user's recurring Telegram Stars subscription to
the bot becomes active, is canceled, or fails — handling the typed `BotSubscriptionUpdated.State`.
## Launch
```bash
../gradlew :BotSubscriptionsBot:run --args="BOT_TOKEN"
```

View File

@@ -1,21 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="BotSubscriptionsBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -1,93 +0,0 @@
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.LogLevel
import dev.inmo.kslog.common.defaultMessageFormatter
import dev.inmo.kslog.common.setDefaultKSLog
import dev.inmo.micro_utils.coroutines.runCatchingLogging
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitBotSubscriptionUpdated
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onBotSubscriptionUpdated
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.types.payments.BotSubscriptionUpdated
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
/**
* This bot demonstrates Bot Subscriptions (subscription updates) support introduced in Telegram Bot API 10.2.
*
* When a user starts, renews, cancels or fails to pay a subscription to the bot (a recurring Telegram Stars
* payment), the bot receives a `subscription` update carrying a [BotSubscriptionUpdated].
*
* Key concepts demonstrated:
* - [onBotSubscriptionUpdated] — trigger whose handler receives a [BotSubscriptionUpdated] (`user`,
* `invoicePayload`, `state`)
* - [BotSubscriptionUpdated.State] — the typed sealed state: [BotSubscriptionUpdated.State.Active],
* [BotSubscriptionUpdated.State.Canceled], [BotSubscriptionUpdated.State.Failed] (data objects) and the
* [BotSubscriptionUpdated.State.Unknown] value-class fallback for any future state
* - `botSubscriptionUpdatedUpdatesFlow` — the raw update flow of
* [dev.inmo.tgbotapi.types.update.BotSubscriptionUpdatedUpdate] (available directly because a
* BehaviourContext is a `FlowsUpdatesFilter`); each emission's payload is its `data`
* - [waitBotSubscriptionUpdated] — expectation returning a flow of [BotSubscriptionUpdated]
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.any { it == "debug" }
val isTestServer = args.any { it == "testServer" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(
botToken,
CoroutineScope(Dispatchers.IO),
testServer = isTestServer,
) {
val me = getMe()
println("Bot info: $me")
// subscription update: react to the typed BotSubscriptionUpdated.State
onBotSubscriptionUpdated { update ->
val user = update.user
val payload = update.invoicePayload
val stateText = when (val state = update.state) {
BotSubscriptionUpdated.State.Active -> "active ✅"
BotSubscriptionUpdated.State.Canceled -> "canceled ❌"
BotSubscriptionUpdated.State.Failed -> "payment failed ⚠️"
// Unknown is a value class carrying the raw state name — future-proof fallback
is BotSubscriptionUpdated.State.Unknown -> "unknown (${state.name})"
}
println("Subscription update from ${user.id}: payload=$payload, state=${update.state.name}")
// notify the subscriber (only works if they have an open chat with the bot)
runCatchingLogging {
send(user.id, "Your subscription (payload: $payload) is now: $stateText")
}
}
// Raw flow variant of the same updates. BehaviourContext : FlowsUpdatesFilter, so the flow is
// available directly; each emission is a BotSubscriptionUpdatedUpdate whose payload is `.data`.
botSubscriptionUpdatedUpdatesFlow.subscribeSafelyWithoutExceptions(this) { update ->
println("[flow] update ${update.updateId}: user=${update.data.user.id}, state=${update.data.state.name}")
}
// waitBotSubscriptionUpdated expectation: suspend until the next subscription update
onCommand("wait_subscription") {
reply(it, "Waiting for the next subscription update...")
val update = waitBotSubscriptionUpdated().first()
reply(it, "Subscription update: state=${update.state.name}, payload=${update.invoicePayload}")
}
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.second.join()
}

View File

@@ -1,12 +0,0 @@
# CommunitiesBot
Demonstrates Communities support introduced in Telegram Bot API 10.2.
Add the bot to a chat that belongs to a community. It reports when the chat is added to or removed from a
community, and `/community` prints the chat's current community (read from `getChat().community`).
## Launch
```bash
../gradlew :CommunitiesBot:run --args="BOT_TOKEN"
```

View File

@@ -1,21 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="CommunitiesBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -1,98 +0,0 @@
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.LogLevel
import dev.inmo.kslog.common.defaultMessageFormatter
import dev.inmo.kslog.common.setDefaultKSLog
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitCommunityChatAdded
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommunityChatAdded
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommunityChatRemoved
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
/**
* This bot demonstrates Communities support introduced in Telegram Bot API 10.2.
*
* A community groups several chats together. When a chat is added to (or removed from) a community, the bot
* receives a service event in that chat.
*
* Key concepts demonstrated:
* - [onCommunityChatAdded] — trigger for the `community_chat_added` service event. The handler receives a
* [dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage] carrying a
* [dev.inmo.tgbotapi.types.communities.CommunityChatAdded] whose `community` is the
* [dev.inmo.tgbotapi.types.communities.Community] (`id`: [dev.inmo.tgbotapi.types.communities.CommunityId],
* `name`) the chat was added to
* - [onCommunityChatRemoved] — trigger for the fieldless `community_chat_removed` service event
* - [waitCommunityChatAdded] — expectation returning a flow of [dev.inmo.tgbotapi.types.communities.CommunityChatAdded]
* - [dev.inmo.tgbotapi.types.chat.ExtendedChat.community] — the community a chat belongs to
* (`ChatFullInfo.community`), available directly from [getChat] without any cast
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.any { it == "debug" }
val isTestServer = args.any { it == "testServer" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(
botToken,
CoroutineScope(Dispatchers.IO),
testServer = isTestServer,
) {
val me = getMe()
println("Bot info: $me")
// community_chat_added: the chat was added to a community
onCommunityChatAdded { message ->
val community = message.chatEvent.community
println("Chat ${message.chat.id} was added to community '${community.name}' (id=${community.id.long})")
send(message.chat.id, "This chat has joined the community: ${community.name}")
// community is exposed on ExtendedChat itself (ChatFullInfo.community) — no cast needed
val extended = getChat(message.chat.id)
println("getChat().community = ${extended.community?.name} / ${extended.community?.id?.long}")
}
// community_chat_removed: a fieldless event — the chat left its community
onCommunityChatRemoved { message ->
println("Chat ${message.chat.id} was removed from its community")
send(message.chat.id, "This chat has left its community")
}
// Inspect the current chat's community on demand
onCommand("community") {
val community = getChat(it.chat.id).community
reply(
it,
if (community != null) {
"Community: ${community.name} (id=${community.id.long})"
} else {
"This chat is not part of any community"
}
)
}
// waitCommunityChatAdded expectation: suspend until this chat is added to a community
onCommand("wait_community") {
reply(it, "Waiting for this chat to be added to a community...")
val event = waitCommunityChatAdded().first()
reply(it, "Chat added to community: ${event.community.name} (id=${event.community.id.long})")
}
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.second.join()
}

View File

@@ -1,13 +0,0 @@
# EphemeralMessagesBot
Demonstrates Ephemeral Messages support introduced in Telegram Bot API 10.2.
Add the bot to a group and send `/ephemeral`. Tapping the button makes the bot send a message that only
you can see (an ephemeral message), then edit and delete it. The bot also detects incoming ephemeral
messages and replies to them ephemerally.
## Launch
```bash
../gradlew :EphemeralMessagesBot:run --args="BOT_TOKEN"
```

View File

@@ -1,21 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="EphemeralMessagesBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -1,138 +0,0 @@
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.LogLevel
import dev.inmo.kslog.common.defaultMessageFormatter
import dev.inmo.kslog.common.setDefaultKSLog
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.deleteEphemeralMessage
import dev.inmo.tgbotapi.extensions.api.edit.text.editEphemeralMessageText
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.replyToEphemeral
import dev.inmo.tgbotapi.extensions.api.send.sendTextMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyEphemeralMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
/**
* This bot demonstrates Ephemeral Messages support introduced in Telegram Bot API 10.2.
*
* An ephemeral message lives inside a group chat but is shown to exactly one user (its `receiver`).
* It is addressed not by a normal message id, but by a per-receiver [dev.inmo.tgbotapi.types.EphemeralMessageId]
* together with that receiver's [dev.inmo.tgbotapi.types.UserId]. Bots typically send ephemeral messages in
* response to a callback query (so a `callbackQueryId` is available) or reply ephemerally to an ephemeral
* message the bot itself received.
*
* Key concepts demonstrated:
* - [sendTextMessage] with `receiverUserId` + `callbackQueryId` — sends the outgoing message as ephemeral,
* visible only to `receiverUserId` in the group chat (one of the 13 ephemeral-capable send requests)
* - [PossiblyEphemeralMessage] — the marker interface (`receiverUser` / `ephemeralMessageId`) implemented by
* the group-family `Common*ContentMessage` types; the way to detect that a message is ephemeral
* - [editEphemeralMessageText] / [deleteEphemeralMessage] — edit / delete an ephemeral message addressed by
* `chatId` + `receiverUserId` + [dev.inmo.tgbotapi.types.EphemeralMessageId] ([deleteEphemeralMessage] also
* accepts a [PossiblyEphemeralMessage] directly)
* - [reply] smart-branch — replying to an ephemeral message automatically sends the reply ephemeral to the
* same receiver (see [dev.inmo.tgbotapi.types.ephemeralReplyParametersOrNull])
* - [replyToEphemeral] — the explicit form: reply to an ephemeral message by `chatId` + `receiverUserId` +
* `ephemeralMessageId` without needing the original [PossiblyEphemeralMessage] object
* - [BotCommand.isEphemeral] — the new command flag marking a command whose response is ephemeral
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.any { it == "debug" }
val isTestServer = args.any { it == "testServer" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(
botToken,
CoroutineScope(Dispatchers.IO),
testServer = isTestServer,
) {
val me = getMe()
println("Bot info: $me")
// Post (in a group) a message with an inline button. Tapping it triggers an ephemeral reply that is
// visible only to the user who tapped.
onCommand("ephemeral") {
reply(
it,
"Tap the button — the reply will be ephemeral (visible only to you).",
replyMarkup = flatInlineKeyboard {
dataButton("Reveal a secret", "reveal")
}
)
}
// Send an ephemeral message in response to a callback query. `receiverUserId` + `callbackQueryId`
// make the outgoing message ephemeral — Telegram shows it only to the querying user (and this also
// serves as the answer to the callback query).
onMessageDataCallbackQuery(Regex("reveal")) { query ->
val chatId = query.message.chat.id
val receiverUserId = query.from.id
val sent = sendTextMessage(
chatId,
"🔒 ${query.from.firstName}, here is your personal secret: 42",
receiverUserId = receiverUserId,
callbackQueryId = query.id,
)
// Only the group-family Common*ContentMessage types implement PossiblyEphemeralMessage, so the
// sent ephemeral message exposes its ephemeralMessageId through that interface.
val ephemeralMessageId = (sent as? PossiblyEphemeralMessage)?.ephemeralMessageId
if (ephemeralMessageId != null) {
delay(3000)
// editEphemeralMessageText: address the ephemeral message by chatId + receiverUserId + ephemeralMessageId
editEphemeralMessageText(chatId, receiverUserId, ephemeralMessageId, "🔓 Revealed: the answer is 42")
delay(3000)
// deleteEphemeralMessage: same addressing (there is also a PossiblyEphemeralMessage overload)
deleteEphemeralMessage(chatId, receiverUserId, ephemeralMessageId)
}
}
// Incoming ephemeral messages: detect them via PossiblyEphemeralMessage, then answer them.
onContentMessage { message ->
val ephemeral = (message as? PossiblyEphemeralMessage)?.takeIf { it.ephemeralMessageId != null }
?: return@onContentMessage
// reply smart-branch: because `message` is ephemeral, this reply is sent ephemeral to the same
// receiver automatically — no ephemeral parameters needed here.
reply(message, "Got your ephemeral message — I am replying ephemerally too.")
// The explicit equivalent, addressing the ephemeral message by hand:
val receiverUserId = ephemeral.receiverUser?.id
if (receiverUserId != null) {
replyToEphemeral(
message.chat.id,
receiverUserId,
ephemeral.ephemeralMessageId!!,
"Explicit ephemeral reply via replyToEphemeral",
)
}
}
setMyCommands(
// isEphemeral marks a command whose response is an ephemeral (personal) message
BotCommand("ephemeral", "Post a button that reveals an ephemeral (personal) message", isEphemeral = true),
)
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.second.join()
}

View File

@@ -13,7 +13,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAn
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onBaseInlineQuery
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onGuestRequestMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onPhoto
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onRichMessage
import dev.inmo.tgbotapi.extensions.utils.baseSentMessageUpdateOrNull
import dev.inmo.tgbotapi.extensions.utils.contentMessageOrNull
@@ -26,11 +25,8 @@ import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputRichMessag
import dev.inmo.tgbotapi.types.InlineQueryId
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
import dev.inmo.tgbotapi.types.media.TelegramMediaPhoto
import dev.inmo.tgbotapi.types.rich.InputRichMessageBlocks
import dev.inmo.tgbotapi.types.rich.InputRichMessageHTML
import dev.inmo.tgbotapi.types.rich.InputRichMessageMarkdown
import dev.inmo.tgbotapi.types.rich.InputRichMessageMedia
import dev.inmo.tgbotapi.types.toChatId
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -56,14 +52,6 @@ import kotlinx.coroutines.flow.mapNotNull
* - [waitRichMessage] — expectation for a rich message
* - [onlyRichMessageContentMessages] — flow filter keeping only rich message content
* - [InputRichMessageContent] — usable as InputMessageContent in inline query results
*
* Telegram Bot API 10.2 additions demonstrated below:
* - [InputRichMessageBlocks] — build a rich message from a typed [dev.inmo.tgbotapi.types.rich.InputRichBlock]
* tree via the InputRichBlocks DSL instead of an HTML/Markdown string (exactly one of html/markdown/blocks)
* - the draft-only `thinking()` block, streamed through [sendRichMessageDraft]
* - [InputRichMessageMedia] — media referenced from the rich message via `tg://photo?id=` / `tg://video?id=` /
* `tg://audio?id=`, plus first-class media blocks (photo/video/...) inside the blocks tree; new files are
* uploaded as `attach://` automatically by [dev.inmo.tgbotapi.requests.send.SendRichMessage]
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
@@ -456,103 +444,6 @@ suspend fun main(vararg args: String) {
)
}
// === Bots API 10.2 additions: InputRichBlocks DSL + rich message media ===
// InputRichMessageBlocks { } — build a rich message from a typed InputRichBlock tree instead
// of an HTML/Markdown string (exactly one of html/markdown/blocks may be used). The lambda is an
// InputRichBlocksBuilder; buildInputRichBlocks { } returns the raw List<InputRichBlock> the same way.
onCommand("rich_blocks") {
sendRichMessage(
it.chat.id,
InputRichMessageBlocks {
heading("Rich blocks (Bots API 10.2)", level = 1)
paragraph {
plain("This message is built from ")
bold("structured InputRichBlocks")
plain(" — no HTML or Markdown string is involved.")
}
heading("Lists", level = 2)
list {
item("A plain list item")
item(hasCheckbox = true, isChecked = true) { paragraph("A completed task item") }
item(hasCheckbox = true, isChecked = false) { paragraph("A pending task item") }
item(value = 7, labelType = "1") { paragraph("An ordered item explicitly starting at 7") }
}
divider()
heading("Code", level = 2)
preformatted("val answer = 42", language = "kotlin")
heading("Quotation", level = 2)
blockQuotation {
paragraph {
plain("Quotations are themselves made of nested blocks — ")
italic("including inline formatting")
plain(".")
}
}
}
)
}
// sendRichMessageDraft with blocks: the thinking() block is only valid inside a draft and is used
// to stream a model's reasoning before the finalized rich message is sent via sendRichMessage.
onCommand("rich_blocks_draft") {
val chatId = it.chat.id.toChatId()
val draftId = 2L
listOf("Analyzing your request", "Composing a structured answer").forEach { step ->
sendRichMessageDraft(
chatId,
draftId,
InputRichMessageBlocks { thinking(step) }
)
delay(1000)
}
// finalize the streamed draft with the real (non-thinking) blocks
sendRichMessage(
chatId,
InputRichMessageBlocks {
heading("Answer", level = 2)
paragraph("Here is the finalized, structured reply.")
}
)
}
// Rich message media: send me a photo and it gets embedded into a rich message two ways.
onPhoto { message ->
// reuse the received file by its fileId (no upload). To upload a brand-new file instead,
// build the TelegramMedia from file.asMultipartFile() — SendRichMessage collects any
// MultipartFile inside the rich message and uploads it as attach://<id> automatically.
val photoMedia = TelegramMediaPhoto(message.content.media.fileId)
// (1) referenced from HTML via tg://photo?id=<id>, resolved through InputRichMessage.media
sendRichMessage(
message.chat.id,
InputRichMessageHTML(
"""
<h2>Your photo, referenced from HTML</h2>
<p>Below is your photo, referenced via <code>tg://photo?id=userphoto</code>:</p>
<img src="tg://photo?id=userphoto"/>
""".trimIndent(),
media = listOf(
InputRichMessageMedia(id = "userphoto", media = photoMedia)
)
)
)
// (2) as a first-class media block inside an InputRichBlocks tree
sendRichMessage(
message.chat.id,
InputRichMessageBlocks {
heading("Your photo, as a media block", level = 2)
paragraph("The same photo, this time a photo() block inside the blocks tree:")
photo(photoMedia)
}
)
}
// waitRichMessage expectation: wait for the user to send a rich message
onCommand("wait_rich") {
reply(it, "Send me a rich message now")
@@ -637,9 +528,7 @@ suspend fun main(vararg args: String) {
setMyCommands(
BotCommand("rich_html", "Send a rich message described with HTML"),
BotCommand("rich_markdown", "Send a rich message described with Markdown"),
BotCommand("rich_blocks", "Send a rich message built from the InputRichBlocks DSL"),
BotCommand("rich_draft", "Stream a rich message draft, then finalize it"),
BotCommand("rich_blocks_draft", "Stream a blocks draft with thinking(), then finalize it"),
BotCommand("rich_edit", "Send a rich message and edit it with new rich content"),
BotCommand("wait_rich", "Wait for you to send a rich message"),
)

View File

@@ -6,7 +6,7 @@ kotlin.daemon.jvmargs=-Xmx3g -Xms500m
kotlin_version=2.3.20
telegram_bot_api_version=36.0.0
telegram_bot_api_version=35.0.0
micro_utils_version=0.29.1
serialization_version=1.10.0
ktor_version=3.4.1

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip

View File

@@ -81,9 +81,3 @@ include ":ChatManagementBot"
include ":RichMessagesBot"
include ":JoinRequestQueriesBot"
include ":EphemeralMessagesBot"
include ":CommunitiesBot"
include ":BotSubscriptionsBot"