Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2026. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email ForteScarlet@163.com
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program 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.
*
* This program 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
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.qguild.api.group

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import love.forte.simbot.qguild.api.PostQQGuildApi
import love.forte.simbot.qguild.api.SimplePostApiDescription
import love.forte.simbot.qguild.model.group.GroupMembersRemoveResult
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmOverloads

/**
* [群成员批量移除](https://bot.q.qq.com/wiki/develop/api-v2/autogen/api/v2_groups_group_openid_batch_remove_members.post.html)。
*
* 批量移除群成员,单次最多 20 个,可选择同时加入黑名单。
*
* @since 5.0
*/
public class BatchRemoveGroupMembersApi private constructor(
groupOpenid: String,
override val body: Any,
) : PostQQGuildApi<GroupMembersRemoveResult>() {
public companion object Factory : SimplePostApiDescription("/v2/groups/{group_openid}/batch_remove_members") {
/**
* 构建一次批量请求。
*
* 注意:不会校验 [memberOpenids] 的数量**上限**,这交给服务端处理。
*
* @throws IllegalArgumentException 群或成员 OpenID 为空或 [memberOpenids] 为空。

Check warning on line 52 in simbot-component-qq/simbot-component-qq-api/src/commonMain/kotlin/love/forte/simbot/qguild/api/group/BatchRemoveGroupMembersApi.kt

View workflow job for this annotation

GitHub Actions / qodana

Unresolved reference in KDoc

Cannot resolve symbol 'IllegalArgumentException'
*/
@JvmStatic
@JvmOverloads
public fun create(
groupOpenid: String,
memberOpenids: Iterable<String>,
addToMemberBlacklist: Boolean = false,
): BatchRemoveGroupMembersApi {
require(groupOpenid.isNotBlank()) { "groupOpenid must not be blank" }
val members = memberOpenids.toList()
require(members.isNotEmpty()) { "memberOpenids must not be empty" }
require(members.all { it.isNotBlank() }) { "memberOpenids must not contain blank IDs" }
return BatchRemoveGroupMembersApi(groupOpenid, Body(members, addToMemberBlacklist))
}
}

override val path: Array<String> = arrayOf("v2", "groups", groupOpenid, "batch_remove_members")

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

override fun createBody(): Any? = null

@Serializable
private class Body(
@SerialName("member_openids") val memberOpenids: List<String>,
@SerialName("add_to_member_blacklist") val addToMemberBlacklist: Boolean,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2026. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email ForteScarlet@163.com
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program 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.
*
* This program 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
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.qguild.api.group

import io.ktor.http.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.DeserializationStrategy
import love.forte.simbot.qguild.api.GetQQGuildApi
import love.forte.simbot.qguild.api.SimpleGetApiDescription
import love.forte.simbot.qguild.model.group.GroupBlacklistPage
import love.forte.simbot.qguild.model.group.GroupBlacklistUser
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic

/**
* [群黑名单查询](https://bot.q.qq.com/wiki/develop/api-v2/autogen/api/v2_groups_group_openid_member_blacklist.get.html)。
*
* 查询群黑名单列表,支持分页。
*
* @since 5.0
*/
public class GetGroupMemberBlacklistApi private constructor(
groupOpenid: String,
private val cursor: String?,
private val limit: Int?,
) : GetQQGuildApi<GroupBlacklistPage>() {
public companion object Factory : SimpleGetApiDescription("/v2/groups/{group_openid}/member_blacklist") {
/**
* 构建 [GetGroupMemberBlacklistApi]。
* @param cursor 分页游标
* @param limit 单页数量,默认 20,最大 100。注:数量不在本地校验,交给服务端。
*/
@JvmStatic
@JvmOverloads
public fun create(
groupOpenid: String,
cursor: String? = null,
limit: Int? = null,
): GetGroupMemberBlacklistApi = GetGroupMemberBlacklistApi(groupOpenid, cursor, limit)
}

override val path: Array<String> = arrayOf("v2", "groups", groupOpenid, "member_blacklist")

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

override fun URLBuilder.buildUrl() {
cursor?.also { parameters.append("cursor", it) }
limit?.also { parameters.append("limit", it.toString()) }
}
}

/**
* 按游标连续拉取群黑名单查询结果。返回冷流,收集时才请求。
*
* 返回冷流,收集时才请求。
* 游标的连续性由 [GroupBlacklistPage.nextCursor] 决定而不是当前页码内的数据列。
*
* @since 5.0
*/
public inline fun GetGroupMemberBlacklistApi.Factory.createFlow(
groupOpenid: String,
cursor: String? = null,
limit: Int? = null,
crossinline doRequest: suspend GetGroupMemberBlacklistApi.() -> GroupBlacklistPage,
): Flow<GroupBlacklistUser> = flow {
var currentCursor = cursor

while (true) {
val page = create(groupOpenid, currentCursor, limit).doRequest()
page.users.forEach { emit(it) }

val nextCursor = page.nextCursor
if (nextCursor.isEmpty()) break
currentCursor = nextCursor
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2026. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email ForteScarlet@163.com
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program 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.
*
* This program 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
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.qguild.api.group

import kotlinx.serialization.DeserializationStrategy
import love.forte.simbot.qguild.api.GetQQGuildApi
import love.forte.simbot.qguild.api.SimpleGetApiDescription
import love.forte.simbot.qguild.model.group.GroupMemberInfo
import kotlin.jvm.JvmStatic

/**
* [获取群成员信息](https://bot.q.qq.com/wiki/develop/api-v2/autogen/api/v2_groups_group_openid_members_member_openid.get.html)。
*
* @since 5.0
*/
public class GetGroupMemberInfoApi private constructor(
groupOpenid: String,
memberOpenid: String,
) : GetQQGuildApi<GroupMemberInfo>() {
public companion object Factory : SimpleGetApiDescription("/v2/groups/{group_openid}/members/{member_openid}") {
/**
* 构建指定群成员的资料查询请求。
* @param groupOpenid 群OpenID
* @param memberOpenid 成员OpenID
*/
@JvmStatic
public fun create(groupOpenid: String, memberOpenid: String): GetGroupMemberInfoApi =
GetGroupMemberInfoApi(groupOpenid, memberOpenid)
}

override val path: Array<String> = arrayOf("v2", "groups", groupOpenid, "members", memberOpenid)

override val resultDeserializationStrategy: DeserializationStrategy<GroupMemberInfo>
get() = GroupMemberInfo.serializer()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2026. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email ForteScarlet@163.com
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program 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.
*
* This program 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
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package love.forte.simbot.qguild.api.group

import io.ktor.http.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.DeserializationStrategy
import love.forte.simbot.qguild.api.GetQQGuildApi
import love.forte.simbot.qguild.api.SimpleGetApiDescription
import love.forte.simbot.qguild.model.group.GroupMemberPage
import love.forte.simbot.qguild.model.group.GroupMemberInfo
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic

/**
* [获取群成员列表](https://bot.q.qq.com/wiki/develop/api-v2/autogen/api/v2_groups_group_openid_members.get.html)。
*
* 每次最多返回 30 条,支持分页。
*
* @since 5.0
*/
public class GetGroupMemberListApi private constructor(
groupOpenid: String,
private val cursor: String?,
) : GetQQGuildApi<GroupMemberPage>() {
public companion object Factory : SimpleGetApiDescription("/v2/groups/{group_openid}/members") {
/**
* 构建 [GetGroupMemberListApi]。
*
* @param cursor 分页游标
* */
@JvmStatic
@JvmOverloads
public fun create(
groupOpenid: String,
cursor: String? = null,
): GetGroupMemberListApi = GetGroupMemberListApi(groupOpenid, cursor)
}

override val path: Array<String> = arrayOf("v2", "groups", groupOpenid, "members")

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

override fun URLBuilder.buildUrl() {
cursor?.also { parameters.append("cursor", it) }
}
}

/**
* 按游标连续拉取获取群成员列表结果。
*
* 返回冷流,收集时才请求。
* 游标的连续性由 [GroupMemberPage.nextCursor] 决定而不是当前页码内的数据列。
*
* @since 5.0
*/
public inline fun GetGroupMemberListApi.Factory.createFlow(
groupOpenid: String,
cursor: String? = null,
crossinline doRequest: suspend GetGroupMemberListApi.() -> GroupMemberPage,
): Flow<GroupMemberInfo> = flow {
var currentCursor = cursor

while (true) {
val page = create(groupOpenid, currentCursor).doRequest()
page.members.forEach { emit(it) }

val nextCursor = page.nextCursor
if (nextCursor.isEmpty()) break
currentCursor = nextCursor
}
}
Loading
Loading