diff --git a/.changelog/v0.0.8.md b/.changelog/v0.0.8.md
new file mode 100644
index 0000000..163b1a0
--- /dev/null
+++ b/.changelog/v0.0.8.md
@@ -0,0 +1,7 @@
+> 对应核心版本: [**v4.1.0**](https://github.com/simple-robot/simpler-robot/releases/tag/v4.1.0)
+
+
+我们欢迎并期望着您的的[反馈](https://github.com/simple-robot/simbot-component-telegram/issues)或[协助](https://github.com/simple-robot/simbot-component-telegram/pulls),
+感谢您的贡献与支持!
+
+也欢迎您为我们献上一颗 `star`,这是对我们最大的鼓励与认可!
diff --git a/README_CN.md b/README_CN.md
index f721688..bfb95b8 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -33,144 +33,26 @@ _中文_ | [English](README.md)
> 或
> [加入社群](https://simbot.forte.love/communities.html)~
-这是一个基于 [Kotlin coroutines](https://github.com/Kotlin/kotlinx.coroutines)
-的 [**Telegram Bot**][telegram bot doc] API/SDK
-Kotlin 多平台库,异步高效、Java友好。
+**Telegram组件**
+是一个 [Kotlin 多平台](https://kotlinlang.org/docs/multiplatform.html) 的 [**Telegram Bot API**][telegram bot doc] SDK实现库,
+也是 Simple Robot 标准API下实现的组件库,异步高效、Java友好!
-它同样是一个 [Simple Robot v4][simbot4 gh] (下文简称 simbot)
-的组件库,是 simbot 的子项目之一。
-借助 simbot 核心库提供的能力,它可以支持更多高级功能和封装,比如组件协同、Spring支持等。
+> 序列化和网络请求相关分别基于 [Kotlin serialization](https://github.com/Kotlin/kotlinx.serialization)
+> 和 [Ktor](https://ktor.io/).
-它可以作为一个低级别的 API/SDK 辅助依赖库,
-也可在 simbot 核心库的支持下用作为一个轻量级的快速开发框架!
-
-序列化和网络请求相关分别基于 [Kotlin serialization](https://github.com/Kotlin/kotlinx.serialization)
-和 [Ktor](https://ktor.io/).
+> 序列化和网络请求相关分别基于 [Kotlin serialization](https://github.com/Kotlin/kotlinx.serialization)
+> 和 [Ktor](https://ktor.io/).
+
## 文档
-- **Telegram组件**手册:(待建设)
-- 了解simbot: [**Simple Robot 应用手册**](https://simbot.forte.love)
+- 手册: [**Simple Robot 应用手册**](https://simbot.forte.love) 及其中的 [**Telegram组件**](https://simbot.forte.love/component-telegram.html) 部分。
- **API文档**: [**文档引导站点**](https://docs.simbot.forte.love) 中 Telegram 的 [**KDoc站点**](https://docs.simbot.forte.love/components/telegram)
- [**社群**](https://simbot.forte.love/communities.html): 与我们和其他开发者愉快地交流!
-
## 安装
-To use the simbot component library, you first need to add the core implementation of simbot
-(such as the core library (`simbot-core`) or Spring Boot starter (`simbot-core-spring-boot-starter`)),
-and then add the component library dependencies of the Telegram (`simbot-component-telegram-core`).
-
-> [!note]
-> The version of the simbot core implementation library (`SIMBOT_VERSION` below)
-> goes [here](https://github.com/simple-robot/simpler-robot/releases) for reference;
->
-> Telegram Component library versions (`VERSION` below) go to the [release](https://github.com/simple-robot/simbot-component-telegram/releases) reference.
-
-**With simbot core**
-
-### Gradle
-
-`build.gradle.kts`
-
-```kotlin
-plugins {
- kotlin("...") version "..."
-}
-
-dependencies {
- implementation("love.forte.simbot:simbot-core:${SIMBOT_VERSION}")
- implementation("love.forte.simbot.component:simbot-component-telegram-core:$VERSION")
-}
-```
-
-### Maven
-
-`pom.xml`
-
-```xml
-
-
- love.forte.simbot
- simbot-core-jvm
- ${SIMBOT_VERSION}
-
-
- love.forte.simbot.component
- simbot-component-telegram-core-jvm
- ${VERSION}
-
-
-```
-
-**With simbot spring boot starter**
-
-### Gradle
-
-`build.gradle.kts`
-
-```kotlin
-plugins {
- kotlin("jvm") version "..."
-}
-
-dependencies {
- implementation("love.forte.simbot:simbot-core-spring-boot-starter:${SIMBOT_VERSION}")
- implementation("love.forte.simbot.component:simbot-component-telegram-core:$VERSION")
-}
-```
-
-### Maven
-
-`pom.xml`
-
-```xml
-
-
- love.forte.simbot
- simbot-core-spring-boot-starter
- ${SIMBOT_VERSION}
-
-
- love.forte.simbot.component
- simbot-component-telegram-core-jvm
- ${VERSION}
-
-
-```
-
-### Ktor client engine
-
-The Telegram component uses Ktor as the HTTP client implementation,
-but does not rely on any specific engine by default.
-
-Therefore, you need to choose and use a Ktor Client engine implementation.
-
-You can go to the [Ktor documentation](https://ktor.io/docs/client-engines.html)
-to select a suitable Client Engine for your platform.
-
-Take the JVM platform as an example:
-
-Gradle
-
-```kotlin
-runtimeOnly("io.ktor:ktor-client-java:$ktor_version")
-```
-
-
-
-Maven
-
-```xml
-
- io.ktor
- ktor-client-java-jvm
- ${ktor_version}
- runtime
-
-```
-
-
+参考手册的 [**Telegram组件**](https://simbot.forte.love/component-telegram.html) 部分。
## Examples
diff --git a/buildSrc/src/main/kotlin/P.kt b/buildSrc/src/main/kotlin/P.kt
index 72b4481..87e828b 100644
--- a/buildSrc/src/main/kotlin/P.kt
+++ b/buildSrc/src/main/kotlin/P.kt
@@ -40,8 +40,8 @@ object P {
override val description: String get() = DESCRIPTION
override val homepage: String get() = HOMEPAGE
- const val VERSION = "0.0.7"
- const val NEXT_VERSION = "0.0.8"
+ const val VERSION = "0.0.8"
+ const val NEXT_VERSION = "0.0.9"
override val snapshotVersion = "$NEXT_VERSION-SNAPSHOT"
override val version = if (isSnapshot()) snapshotVersion else VERSION
diff --git a/simbot-component-telegram-api/src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/DeleteMyCommandsApi.kt b/simbot-component-telegram-api/src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/DeleteMyCommandsApi.kt
new file mode 100644
index 0000000..4665532
--- /dev/null
+++ b/simbot-component-telegram-api/src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/DeleteMyCommandsApi.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2024. ForteScarlet.
+ *
+ * This file is part of simbot-component-telegram.
+ *
+ * simbot-component-telegram is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * simbot-component-telegram is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with simbot-component-telegram.
+ * If not, see .
+ */
+
+package love.forte.simbot.telegram.api.bot.command
+
+import kotlinx.serialization.DeserializationStrategy
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.builtins.serializer
+import love.forte.simbot.telegram.api.SimpleBodyTelegramApi
+import love.forte.simbot.telegram.api.TelegramApiResult
+import love.forte.simbot.telegram.type.BotCommandScope
+import kotlin.jvm.JvmOverloads
+import kotlin.jvm.JvmStatic
+
+
+/**
+ * [deleteMyCommands](https://core.telegram.org/bots/api#deletemycommands)
+ *
+ * Use this method to delete the list of the bot's commands for the given scope and user language.
+ * After deletion, higher level commands will be shown to affected users. Returns True on success.
+ *
+ * @author ForteScarlet
+ */
+public class DeleteMyCommandsApi
+private constructor(body: Body) : SimpleBodyTelegramApi() {
+ public companion object Factory {
+ private const val NAME = "deleteMyCommands"
+ private val EMPTY = DeleteMyCommandsApi(Body())
+
+ /**
+ * Create an instance of [DeleteMyCommandsApi].
+ *
+ * @param scope A JSON-serialized object, describing scope of users for which the commands are relevant.
+ * Defaults to BotCommandScopeDefault.
+ * @param languageCode A two-letter ISO 639-1 language code.
+ * If empty, commands will be applied to all users from the given scope,
+ * for whose language there are no dedicated commands
+ */
+ @JvmStatic
+ @JvmOverloads
+ public fun create(
+ scope: BotCommandScope? = null,
+ languageCode: String? = null,
+ ): DeleteMyCommandsApi {
+ return if (scope == null && languageCode == null) {
+ EMPTY
+ } else {
+ DeleteMyCommandsApi(
+ Body(
+ scope = scope,
+ languageCode = languageCode
+ )
+ )
+ }
+ }
+ }
+
+ /**
+ * Request body for [DeleteMyCommandsApi]
+ * @property scope A JSON-serialized object, describing scope of users for which the commands are relevant.
+ * Defaults to BotCommandScopeDefault.
+ * @property languageCode A two-letter ISO 639-1 language code.
+ * If empty, commands will be applied to all users from the given scope,
+ * for whose language there are no dedicated commands
+ */
+ @Serializable
+ public data class Body(
+ val scope: BotCommandScope? = null,
+ @SerialName("language_code")
+ val languageCode: String? = null,
+ )
+
+ override val name: String
+ get() = NAME
+
+ override val body: Any = body
+
+ override val responseDeserializer: DeserializationStrategy
+ get() = Boolean.serializer()
+
+ override val resultDeserializer: DeserializationStrategy>
+ get() = TelegramApiResult.BooleanSerializer
+}
+
+/*
+Parameter Type Required Description
+ */
diff --git a/simbot-component-telegram-api/src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/SetMyCommandsApi.kt b/simbot-component-telegram-api/src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/SetMyCommandsApi.kt
new file mode 100644
index 0000000..7f67184
--- /dev/null
+++ b/simbot-component-telegram-api/src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/SetMyCommandsApi.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2024. ForteScarlet.
+ *
+ * This file is part of simbot-component-telegram.
+ *
+ * simbot-component-telegram is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * simbot-component-telegram is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with simbot-component-telegram.
+ * If not, see .
+ */
+
+package love.forte.simbot.telegram.api.bot.command
+
+import kotlinx.serialization.DeserializationStrategy
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.builtins.serializer
+import love.forte.simbot.telegram.api.SimpleBodyTelegramApi
+import love.forte.simbot.telegram.api.TelegramApiResult
+import love.forte.simbot.telegram.type.BotCommand
+import love.forte.simbot.telegram.type.BotCommandScope
+import kotlin.jvm.JvmOverloads
+import kotlin.jvm.JvmStatic
+
+
+/**
+ * [setMyCommands](https://core.telegram.org/bots/api#setmycommands)
+ * Use this method to change the list of the bot's commands.
+ * See this manual for more details about bot commands. Returns True on success.
+ *
+ * @author ForteScarlet
+ */
+public class SetMyCommandsApi
+private constructor(body: Body) : SimpleBodyTelegramApi() {
+ public companion object Factory {
+ private const val NAME = "setMyCommands"
+
+ /**
+ * Create an instance of [SetMyCommandsApi].
+ *
+ * @param commands A JSON-serialized list of bot commands to be set as the list of the bot's commands.
+ * At most 100 commands can be specified.
+ * @param scope A JSON-serialized object, describing scope of users for which the commands are relevant.
+ * Defaults to BotCommandScopeDefault.
+ * @param languageCode A two-letter ISO 639-1 language code.
+ * If empty, commands will be applied to all users from the given scope,
+ * for whose language there are no dedicated commands
+ */
+ @JvmStatic
+ @JvmOverloads
+ public fun create(
+ commands: List,
+ scope: BotCommandScope? = null,
+ languageCode: String? = null,
+ ): SetMyCommandsApi = SetMyCommandsApi(
+ Body(
+ commands = commands,
+ scope = scope,
+ languageCode = languageCode
+ )
+ )
+ }
+
+ /**
+ * Request body for [SetMyCommandsApi]
+ * @property commands A JSON-serialized list of bot commands to be set as the list of the bot's commands.
+ * At most 100 commands can be specified.
+ * @property scope A JSON-serialized object, describing scope of users for which the commands are relevant.
+ * Defaults to BotCommandScopeDefault.
+ * @property languageCode A two-letter ISO 639-1 language code.
+ * If empty, commands will be applied to all users from the given scope,
+ * for whose language there are no dedicated commands
+ */
+ @Serializable
+ public data class Body(
+ val commands: List = emptyList(),
+ val scope: BotCommandScope? = null,
+ @SerialName("language_code")
+ val languageCode: String? = null,
+ )
+
+ override val name: String
+ get() = NAME
+
+ override val body: Any = body
+
+ override val responseDeserializer: DeserializationStrategy
+ get() = Boolean.serializer()
+
+ override val resultDeserializer: DeserializationStrategy>
+ get() = TelegramApiResult.BooleanSerializer
+}
+
+/*
+Parameter Type Required Description
+ */
diff --git a/simbot-component-telegram-api/supports.md b/simbot-component-telegram-api/supports.md
index fbca720..bb5ea7f 100644
--- a/simbot-component-telegram-api/supports.md
+++ b/simbot-component-telegram-api/supports.md
@@ -3,7 +3,9 @@
- [bot](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot)
- [x] [CloseApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/CloseApi.kt)
- [command](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command)
+ - [x] [DeleteMyCommandsApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/DeleteMyCommandsApi.kt)
- [x] [GetMyCommandsApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/GetMyCommandsApi.kt)
+ - [x] [SetMyCommandsApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/command/SetMyCommandsApi.kt)
- [x] [GetChatMenuButtonApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/GetChatMenuButtonApi.kt)
- [x] [GetMeApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/GetMeApi.kt)
- [x] [GetMyDefaultAdministratorRightsApi](src/commonMain/kotlin/love/forte/simbot/telegram/api/bot/GetMyDefaultAdministratorRightsApi.kt)
diff --git a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/TelegramBot.kt b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/TelegramBot.kt
index ab5fcb8..fd7fd8b 100644
--- a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/TelegramBot.kt
+++ b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/TelegramBot.kt
@@ -23,9 +23,12 @@ import love.forte.simbot.bot.GroupRelation
import love.forte.simbot.bot.GuildRelation
import love.forte.simbot.common.id.ID
import love.forte.simbot.common.id.LongID.Companion.ID
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommands
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommandsUpdater
import love.forte.simbot.component.telegram.core.component.TelegramComponent
import love.forte.simbot.suspendrunner.ST
import love.forte.simbot.telegram.api.update.Update
+import love.forte.simbot.telegram.type.BotCommandScope
import love.forte.simbot.telegram.type.User
import kotlin.coroutines.CoroutineContext
@@ -98,14 +101,45 @@ public interface TelegramBot : Bot {
source.pushUpdate(update, raw)
}
+ /**
+ * Fetches a [TelegramBotCommands] with [scope] and [languageCode].
+ *
+ * @param scope Scope of bot commands.
+ * @param languageCode A two-letter ISO 639-1 language code of commands.
+ */
+ @ST
+ public suspend fun commands(scope: BotCommandScope?, languageCode: String?): TelegramBotCommands
+
+ /**
+ * Fetches a [TelegramBotCommands].
+ */
+ @ST
+ public suspend fun commands(): TelegramBotCommands =
+ commands(scope = null, languageCode = null)
+
+ /**
+ * An updater for set commands.
+ *
+ * @see TelegramBotCommandsUpdater
+ */
+ public val commandsUpdater: TelegramBotCommandsUpdater
override val groupRelation: GroupRelation?
- get() = null // TODO?
+ get() = null
override val guildRelation: GuildRelation?
- get() = null // TODO?
+ get() = null
override val contactRelation: ContactRelation?
- get() = null // TODO?
+ get() = null
}
+
+/**
+ * Update bot commands by [TelegramBot.commandsUpdater]
+ *
+ * @see TelegramBot.commandsUpdater
+ */
+public suspend inline fun TelegramBot.updateCommands(
+ block: TelegramBotCommandsUpdater.() -> Unit
+): TelegramBotCommands = commandsUpdater.also(block).update()
diff --git a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/command/TelegramBotCommands.kt b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/command/TelegramBotCommands.kt
new file mode 100644
index 0000000..7328e57
--- /dev/null
+++ b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/command/TelegramBotCommands.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024. ForteScarlet.
+ *
+ * This file is part of simbot-component-telegram.
+ *
+ * simbot-component-telegram is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * simbot-component-telegram is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with simbot-component-telegram.
+ * If not, see .
+ */
+
+package love.forte.simbot.component.telegram.core.bot.command
+
+import love.forte.simbot.ability.DeleteOption
+import love.forte.simbot.ability.DeleteSupport
+import love.forte.simbot.component.telegram.core.bot.TelegramBot
+import love.forte.simbot.telegram.type.BotCommand
+import love.forte.simbot.telegram.type.BotCommandScope
+import kotlin.jvm.JvmSynthetic
+
+
+/**
+ * A set of Telegram's [BotCommand]s
+ *
+ * @author ForteScarlet
+ */
+public interface TelegramBotCommands : DeleteSupport, Iterable {
+ /**
+ * The list of [TelegramBotCommand]
+ */
+ public val values: List
+
+ /**
+ * Iterator of [values].
+ */
+ override fun iterator(): Iterator =
+ values.iterator()
+
+ /**
+ * A command scope used in the query.
+ */
+ public val scope: BotCommandScope?
+
+ /**
+ * A two-letter ISO 639-1 language code used in the query.
+ */
+ public val languageCode: String?
+
+ /**
+ * Delete this set of commands with [scope] and [languageCode].
+ */
+ @JvmSynthetic
+ override suspend fun delete(vararg options: DeleteOption)
+
+ /**
+ * Get a [TelegramBotCommandsUpdater] with [scope] and [languageCode]
+ * for update commands.
+ *
+ * @see TelegramBotCommandsUpdater
+ */
+ public val updater: TelegramBotCommandsUpdater
+}
+
+/**
+ * Update bot commands by [TelegramBotCommands.updater]
+ *
+ * @see TelegramBotCommands.updater
+ */
+public suspend inline fun TelegramBotCommands.update(
+ block: TelegramBotCommandsUpdater.() -> Unit
+): TelegramBotCommands = updater.also(block).update()
+
+/**
+ * A [BotCommand] of [TelegramBotCommands] from [TelegramBot.commands].
+ *
+ * @see TelegramBotCommands
+ * @see BotCommand
+ */
+public interface TelegramBotCommand {
+ /**
+ * The source type [BotCommand]
+ */
+ public val source: BotCommand
+
+ /**
+ * Text of the command.
+ *
+ * @see BotCommand.command
+ */
+ public val command: String
+ get() = source.command
+
+ /**
+ * Description of the command.
+ *
+ * @see BotCommand.description
+ */
+ public val description: String
+ get() = source.description
+}
+
+
diff --git a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/command/TelegramBotCommandsUpdater.kt b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/command/TelegramBotCommandsUpdater.kt
new file mode 100644
index 0000000..9a040eb
--- /dev/null
+++ b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/command/TelegramBotCommandsUpdater.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024. ForteScarlet.
+ *
+ * This file is part of simbot-component-telegram.
+ *
+ * simbot-component-telegram is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * simbot-component-telegram is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with simbot-component-telegram.
+ * If not, see .
+ */
+
+package love.forte.simbot.component.telegram.core.bot.command
+
+import love.forte.simbot.suspendrunner.ST
+import love.forte.simbot.telegram.type.BotCommand
+import love.forte.simbot.telegram.type.BotCommandScope
+
+
+/**
+ * An updater for set bot commands.
+ *
+ * @author ForteScarlet
+ */
+public interface TelegramBotCommandsUpdater {
+ /**
+ * the [BotCommandScope]
+ */
+ public var scope: BotCommandScope?
+
+ /**
+ * the [languageCode]
+ */
+ public var languageCode: String?
+
+ /**
+ * Commands for update.
+ */
+ public var commands: MutableList
+
+ /**
+ * @see scope
+ */
+ public fun scope(scope: BotCommandScope?): TelegramBotCommandsUpdater = apply {
+ this.scope = scope
+ }
+
+ /**
+ * @see languageCode
+ */
+ public fun languageCode(languageCode: String?): TelegramBotCommandsUpdater = apply {
+ this.languageCode = languageCode
+ }
+
+ /**
+ * Add a command into [commands]
+ * @see commands
+ */
+ public fun addCommand(command: BotCommand): TelegramBotCommandsUpdater = apply {
+ commands.add(command)
+ }
+
+ /**
+ * Add a command into [commands]
+ * @see commands
+ */
+ public fun addCommand(command: String, description: String): TelegramBotCommandsUpdater =
+ addCommand(BotCommand(command, description))
+
+ /**
+ * Execute setting and a new [TelegramBotCommands] that
+ * values **directly** based on new commands is returned.
+ *
+ */
+ @ST
+ public suspend fun update(): TelegramBotCommands
+}
diff --git a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/TelegramBotImpl.kt b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/TelegramBotImpl.kt
index 2285037..fbdf92f 100644
--- a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/TelegramBotImpl.kt
+++ b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/TelegramBotImpl.kt
@@ -31,6 +31,10 @@ import love.forte.simbot.common.id.toLongOrNull
import love.forte.simbot.component.telegram.core.bot.StdlibBot
import love.forte.simbot.component.telegram.core.bot.TelegramBot
import love.forte.simbot.component.telegram.core.bot.TelegramBotConfiguration
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommands
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommandsUpdater
+import love.forte.simbot.component.telegram.core.bot.internal.command.TelegramBotCommandsUpdaterImpl
+import love.forte.simbot.component.telegram.core.bot.internal.command.toTGCommands
import love.forte.simbot.component.telegram.core.component.TelegramComponent
import love.forte.simbot.component.telegram.core.event.TelegramUnsupportedEvent
import love.forte.simbot.component.telegram.core.event.internal.TelegramChannelMessageEventImpl
@@ -42,6 +46,7 @@ import love.forte.simbot.event.EventDispatcher
import love.forte.simbot.event.onEachError
import love.forte.simbot.logger.LoggerFactory
import love.forte.simbot.telegram.api.bot.GetMeApi
+import love.forte.simbot.telegram.api.bot.command.GetMyCommandsApi
import love.forte.simbot.telegram.api.update.SuspendableUpdateDivider
import love.forte.simbot.telegram.api.update.Update
import love.forte.simbot.telegram.stdlib.bot.SubscribeSequence
@@ -111,9 +116,32 @@ internal class TelegramBotImpl(
isStarted = true
}
}
+
+ override suspend fun commands(scope: BotCommandScope?, languageCode: String?): TelegramBotCommands {
+ val commands = GetMyCommandsApi.create(
+ scope = scope,
+ languageCode = languageCode
+ ).requestDataBy(source)
+
+ return commands.toTGCommands(
+ bot = this,
+ scope = scope,
+ languageCode = languageCode
+ )
+ }
+
+ override val commandsUpdater: TelegramBotCommandsUpdater
+ get() = TelegramBotCommandsUpdaterImpl(
+ bot = this,
+ scope = null,
+ languageCode = null
+ )
}
+
+
+
@OptIn(FragileSimbotAPI::class)
internal fun subscribeInternalProcessor(
bot: TelegramBotImpl,
diff --git a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/command/TelegramBotCommandsImpl.kt b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/command/TelegramBotCommandsImpl.kt
new file mode 100644
index 0000000..d680ae7
--- /dev/null
+++ b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/command/TelegramBotCommandsImpl.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024. ForteScarlet.
+ *
+ * This file is part of simbot-component-telegram.
+ *
+ * simbot-component-telegram is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * simbot-component-telegram is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with simbot-component-telegram.
+ * If not, see .
+ */
+
+package love.forte.simbot.component.telegram.core.bot.internal.command
+
+import love.forte.simbot.ability.DeleteFailureException
+import love.forte.simbot.ability.DeleteOption
+import love.forte.simbot.ability.StandardDeleteOption
+import love.forte.simbot.component.telegram.core.bot.TelegramBot
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommand
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommands
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommandsUpdater
+import love.forte.simbot.telegram.api.bot.command.DeleteMyCommandsApi
+import love.forte.simbot.telegram.stdlib.bot.requestDataBy
+import love.forte.simbot.telegram.type.BotCommand
+import love.forte.simbot.telegram.type.BotCommandScope
+
+internal class TelegramBotCommandsImpl(
+ private val bot: TelegramBot,
+ override val values: List,
+ override val scope: BotCommandScope?,
+ override val languageCode: String?,
+) : TelegramBotCommands {
+ override suspend fun delete(vararg options: DeleteOption) {
+ runCatching {
+ DeleteMyCommandsApi.create(
+ scope = scope,
+ languageCode = languageCode
+ ).requestDataBy(bot.source)
+ }.onFailure { err ->
+ if (StandardDeleteOption.IGNORE_ON_FAILURE !in options) {
+ throw DeleteFailureException(err.message, err)
+ }
+ }
+ }
+
+ override val updater: TelegramBotCommandsUpdater
+ get() = TelegramBotCommandsUpdaterImpl(
+ bot = bot,
+ scope = scope,
+ languageCode = languageCode
+ )
+
+ override fun toString(): String =
+ "TelegramBotCommands(scope=$scope, languageCode=$languageCode, values=$values)"
+}
+
+internal fun Iterable.toTGCommands(
+ bot: TelegramBot,
+ scope: BotCommandScope?,
+ languageCode: String?,
+): TelegramBotCommandsImpl =
+ TelegramBotCommandsImpl(
+ bot,
+ this.map { it.toTGCommand() },
+ scope,
+ languageCode
+ )
+
+/**
+ *
+ * @author ForteScarlet
+ */
+internal class TelegramBotCommandImpl(
+ override val source: BotCommand
+) : TelegramBotCommand {
+ override fun toString(): String {
+ return "TelegramBotCommand(source=$source)"
+ }
+}
+
+internal fun BotCommand.toTGCommand(): TelegramBotCommandImpl =
+ TelegramBotCommandImpl(this)
diff --git a/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/command/TelegramBotCommandsUpdaterImpl.kt b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/command/TelegramBotCommandsUpdaterImpl.kt
new file mode 100644
index 0000000..26d71ac
--- /dev/null
+++ b/simbot-component-telegram-core/src/commonMain/kotlin/love/forte/simbot/component/telegram/core/bot/internal/command/TelegramBotCommandsUpdaterImpl.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024. ForteScarlet.
+ *
+ * This file is part of simbot-component-telegram.
+ *
+ * simbot-component-telegram is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * simbot-component-telegram is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with simbot-component-telegram.
+ * If not, see .
+ */
+
+package love.forte.simbot.component.telegram.core.bot.internal.command
+
+import love.forte.simbot.component.telegram.core.bot.TelegramBot
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommands
+import love.forte.simbot.component.telegram.core.bot.command.TelegramBotCommandsUpdater
+import love.forte.simbot.telegram.api.bot.command.SetMyCommandsApi
+import love.forte.simbot.telegram.stdlib.bot.requestDataBy
+import love.forte.simbot.telegram.type.BotCommand
+import love.forte.simbot.telegram.type.BotCommandScope
+
+
+/**
+ *
+ * @author ForteScarlet
+ */
+internal class TelegramBotCommandsUpdaterImpl(
+ private val bot: TelegramBot,
+ override var scope: BotCommandScope?,
+ override var languageCode: String?,
+ override var commands: MutableList = mutableListOf(),
+) : TelegramBotCommandsUpdater {
+ override suspend fun update(): TelegramBotCommands {
+ val commands = commands.toList()
+ val scope = scope
+ val languageCode = languageCode
+
+ val updated = SetMyCommandsApi.create(
+ commands,
+ scope,
+ languageCode
+ ).requestDataBy(bot.source)
+
+ check(updated) {
+ "The SetMyCommandsApi request returned `false`"
+ }
+
+ return commands.toTGCommands(
+ bot = bot,
+ scope = scope,
+ languageCode = languageCode
+ )
+ }
+}