Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3e52a3c
feat(api): 支持 ChannelKickoutApi (/channel/kickout)
ForteScarlet Aug 18, 2025
f72c588
feat(api): making ChannelKickoutApi constructor parameters inaccessib…
ForteScarlet Aug 18, 2025
b169131
Merge pull request #284 from simple-robot/dev/channel-kickout
ForteScarlet Aug 18, 2025
9980b36
feat(api): Support /channel/user-list
ForteScarlet Aug 19, 2025
c187965
Update simbot-component-kook-api/src/commonMain/kotlin/love/forte/sim…
ForteScarlet Aug 19, 2025
065d36f
Merge pull request #286 from simple-robot/dev/support-channel-user-li…
ForteScarlet Aug 19, 2025
b805c12
test(api): 改进 ChannelKickoutApi 的部分相关测试
ForteScarlet Aug 19, 2025
5b5cf10
improve(api): 改进 identifyNum 的默认值获取
ForteScarlet Aug 19, 2025
9c85658
build: next version to 4.2.0
ForteScarlet Aug 19, 2025
2c65d80
Update simbot-component-kook-api/src/commonTest/kotlin/love/forte/sim…
ForteScarlet Aug 19, 2025
9eeeade
Update simbot-component-kook-api/src/commonTest/kotlin/love/forte/sim…
ForteScarlet Aug 19, 2025
7bc1540
Update simbot-component-kook-api/src/commonTest/kotlin/love/forte/sim…
ForteScarlet Aug 19, 2025
5afc99d
Merge pull request #287 from simple-robot/dev/support-channel-kickout…
ForteScarlet Aug 19, 2025
6263997
feat(api): add support for ChannelMoveUserApi with tests
ForteScarlet Aug 19, 2025
9ebbe47
Update simbot-component-kook-api/src/commonMain/kotlin/love/forte/sim…
ForteScarlet Aug 19, 2025
5d36e13
Merge pull request #288 from simple-robot/dev/support-channel-move-us…
ForteScarlet Aug 20, 2025
996dd52
feat(api): add voice channel APIs (join, list, leave) supported
ForteScarlet Aug 20, 2025
765fba9
Merge pull request #289 from simple-robot/dev/support-voice-APIs
ForteScarlet Aug 20, 2025
632dace
feat(core): 增加新的 KookVoiceChannel 来描述一个语音频道的信息
ForteScarlet Aug 20, 2025
38a3e40
feat(core): 实现 KookVoiceChannel, KookVoiceMember 并支持语音频道的相关操作
ForteScarlet Aug 22, 2025
74bf089
build: api dump
ForteScarlet Aug 22, 2025
4311397
build(core): 补充桥接函数注解
ForteScarlet Aug 22, 2025
a005757
test: Fix compilation failed
ForteScarlet Aug 22, 2025
192aedc
Merge pull request #291 from simple-robot/dev/support-kook-voice-channel
ForteScarlet Aug 22, 2025
16274fb
release: v4.2.0
ForteScarlet Aug 22, 2025
c2016ff
release: v4.2.0, fix logger msg
ForteScarlet Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/P.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ object P : ProjectDetail() {
override val homepage: String
get() = HOMEPAGE

const val VERSION = "4.1.7"
const val NEXT_VERSION = "4.1.8"
const val VERSION = "4.2.0"
const val NEXT_VERSION = "4.2.1"

override val snapshotVersion = "$NEXT_VERSION-SNAPSHOT"
override val version = if (isSnapshot()) snapshotVersion else VERSION
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref =
ktor-client-java = { group = "io.ktor", name = "ktor-client-java", version.ref = "ktor" }
ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" }
ktor-client-ws = { group = "io.ktor", name = "ktor-client-websockets", version.ref = "ktor" }
ktor-client-mock = { group = "io.ktor", name = "ktor-client-mock", version.ref = "ktor" }

ktor-client-js = { group = "io.ktor", name = "ktor-client-js", version.ref = "ktor" }

Expand Down
268 changes: 268 additions & 0 deletions simbot-component-kook-api/api/simbot-component-kook-api.api

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions simbot-component-kook-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ kotlin {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test)
implementation(libs.ktor.client.mock)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import love.forte.simbot.kook.InternalKookApi
import love.forte.simbot.kook.api.KookApiResults.SUCCESS_CODE
import love.forte.simbot.kook.api.RateLimit.Companion.DEFAULT_LIMIT
import love.forte.simbot.kook.api.RateLimit.Companion.DEFAULT_REMAINING
import love.forte.simbot.kook.api.RateLimit.Companion.DEFAULT_RESET
Expand Down Expand Up @@ -207,7 +208,7 @@
/**
* 此接口的响应码是否为成功的响应码.
*/
public val isSuccess: Boolean get() = isHttpSuccess && code == KookApiResults.SUCCESS_CODE
public val isSuccess: Boolean get() = isHttpSuccess && code == SUCCESS_CODE

/**
* 判断 [httpStatus] 是否 [成功][HttpStatusCode.isSuccess]。
Expand Down Expand Up @@ -241,7 +242,7 @@
* @param json 用于解析 [data] 的json反序列化器
* @param deserializationStrategy 解析目标的反序列化策略,参考 [KookApi.resultDeserializationStrategy]
* @throws ApiResultException 如果 [code] 不为成功
* @throws SerializationException see [Json.decodeFromJsonElement].

Check warning on line 245 in simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/api/ApiResult.kt

View workflow job for this annotation

GitHub Actions / qodana

Unresolved reference in KDoc

Cannot resolve symbol 'Json'
*/
@JvmOverloads
public fun <T> parseDataOrThrow(
Expand All @@ -256,8 +257,22 @@


override fun toString(): String =
"ApiResult(code=$code, message=$message, data=$data, httpStatus=$httpStatus, rateLimit=$rateLimit, raw=$raw)"

"ApiResult(" +
"code=$code, " +
"message=$message, " +
"data=$data, " +
Copy link
Preview

Copilot AI Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The toString() method improvement adds null checks for uninitialized properties, but the data field is not checked like the others (httpStatus, rateLimit, raw). Consider adding a similar null check for data if it can also be uninitialized.

Suggested change
"data=$data, " +
"data=${dataOrNull ?: "<Not Initialized>"}, " +

Copilot uses AI. Check for mistakes.

"httpStatus=${httpStatusOrNull ?: "<Not Initialized>"}, " +
"rateLimit=${rateLimitOrNull ?: "<Not Initialized>"}, " +
"raw=${rawOrNull ?: "<Not Initialized>"})"

private val httpStatusOrNull
get() = if (::httpStatus.isInitialized) httpStatus else null

private val rateLimitOrNull
get() = if (::rateLimit.isInitialized) rateLimit else null

private val rawOrNull
get() = if (::raw.isInitialized) raw else null

override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2023-2025. ForteScarlet.
*
* This file is part of simbot-component-kook.
*
* simbot-component-kook 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-kook 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-kook,
* If not, see <https://www.gnu.org/licenses/>.
*/

package love.forte.simbot.kook.api.channel

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import love.forte.simbot.kook.api.KookPostApi
import kotlin.jvm.JvmStatic

/**
* [踢出语音频道中的用户](https://developer.kookapp.cn/doc/http/channel#踢出语音频道中的用户)
*
* 踢出语音频道中的用户,只能踢出在语音频道中的用户
*
* @author ForteScarlet
* @since 4.2.0
*/
public class ChannelKickoutApi private constructor(
channelId: String,
userId: String
) : KookPostApi<Unit>() {
public companion object Factory {
private val PATH = ApiPath.create("channel", "kickout")

/**
* 构造 [ChannelKickoutApi].
*
* @param channelId 目标频道 id,需要是语音频道
* @param userId 用户 id
*/
@JvmStatic
public fun create(channelId: String, userId: String): ChannelKickoutApi =
ChannelKickoutApi(channelId, userId)
}

override val resultDeserializationStrategy: DeserializationStrategy<Unit>
get() = Unit.serializer()

override val apiPath: ApiPath
get() = PATH

override val body: Any = Body(channelId, userId)

@Serializable
private data class Body(
@SerialName("channel_id")
val channelId: String,
@SerialName("user_id")
val userId: String
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2023-2025. ForteScarlet.
*
* This file is part of simbot-component-kook.
*
* simbot-component-kook 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-kook 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-kook,
* If not, see <https://www.gnu.org/licenses/>.
*/

package love.forte.simbot.kook.api.channel

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import love.forte.simbot.kook.api.KookPostApi
import kotlin.jvm.JvmStatic

/**
* [语音频道之间移动用户](https://developer.kookapp.cn/doc/http/channel#语音频道之间移动用户)
*
* 语音频道之间移动用户,只能在语音频道之间移动,用户也必须在其他语音频道在线才能够移动到目标频道。
*
*
* @author ForteScarlet
* @since 4.2.0
*/
public class ChannelMoveUserApi private constructor(
targetId: String,
userIds: List<String>
) : KookPostApi<Unit>() {

public companion object Factory {
private val PATH = ApiPath.create("channel", "move-user")

/**
* 构造 [ChannelMoveUserApi].
*
* @param targetId 目标频道 id,需要是语音频道
* @param userIds 用户 id 的数组
*/
@JvmStatic
public fun create(targetId: String, userIds: List<String>): ChannelMoveUserApi =
ChannelMoveUserApi(targetId, userIds)

/**
* 构造 [ChannelMoveUserApi].
*
* @param targetId 目标频道 id,需要是语音频道
* @param userIds 用户 id 的数组
*/
@JvmStatic
public fun create(targetId: String, vararg userIds: String): ChannelMoveUserApi =
ChannelMoveUserApi(targetId, userIds.asList())
}

override val resultDeserializationStrategy: DeserializationStrategy<Unit>
get() = Unit.serializer()

override val apiPath: ApiPath
get() = PATH

override val body: Any = Body(targetId, userIds)

@Serializable
private data class Body(
@SerialName("target_id")
val targetId: String,
@SerialName("user_ids")
val userIds: List<String>
)
}
Loading
Loading