From fb00e5c1ff33029bcf39f5e5d297172840465cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=B1=A0?= <98259561+whitechi73@users.noreply.github.com> Date: Sat, 3 Feb 2024 16:31:54 +0800 Subject: [PATCH] `Shamrock`: support `/create_guild_role` --- .../nativeinterface/GProRoleCreateInfo.java | 6 +-- .../IGProCreateRoleCallback.java | 5 ++ .../nativeinterface/IKernelGuildService.java | 3 ++ .../fuqiuluo/qqinterface/servlet/GProSvc.kt | 50 +++++++++++++++++++ .../remote/action/handlers/CreateGuildRole.kt | 42 ++++++++++++++++ .../remote/action/handlers/GetGuildRoles.kt | 4 +- .../remote/action/handlers/UpdateGuildRole.kt | 28 +++++++++++ .../shamrock/remote/api/GuildAction.kt | 18 +++++++ 8 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IGProCreateRoleCallback.java create mode 100644 xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/CreateGuildRole.kt create mode 100644 xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/UpdateGuildRole.kt diff --git a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/GProRoleCreateInfo.java b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/GProRoleCreateInfo.java index 399ecd96..931648ae 100644 --- a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/GProRoleCreateInfo.java +++ b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/GProRoleCreateInfo.java @@ -31,12 +31,8 @@ public String toString() { return "GProRoleCreateInfo{name=" + this.name + ",color=" + this.color + ",bHoist=" + this.bHoist + ",rolePermissions=" + this.rolePermissions + ",}"; } - public GProRoleCreateInfo(String str, long j2, boolean z, GProRolePermission gProRolePermission) { + public GProRoleCreateInfo(String name, long color, boolean hoist, GProRolePermission permissions) { this.name = ""; this.rolePermissions = new GProRolePermission(); - this.name = str; - this.color = j2; - this.bHoist = z; - this.rolePermissions = gProRolePermission; } } diff --git a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IGProCreateRoleCallback.java b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IGProCreateRoleCallback.java new file mode 100644 index 00000000..7f97cbb0 --- /dev/null +++ b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IGProCreateRoleCallback.java @@ -0,0 +1,5 @@ +package com.tencent.qqnt.kernel.nativeinterface; + +public interface IGProCreateRoleCallback { + void onCreateRoleResult(int code, String msg, GProSecurityResult result, GProGuildRole role); +} \ No newline at end of file diff --git a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IKernelGuildService.java b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IKernelGuildService.java index 3fbc69ef..785625ac 100644 --- a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IKernelGuildService.java +++ b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/IKernelGuildService.java @@ -70,4 +70,7 @@ public interface IKernelGuildService { void setMemberRoles(long guild, long u1, long u2, long tinyId, ArrayList addRoles, ArrayList removeRoles, IGProResultCallback cb); + void setRoleInfo(long guild, long role, GProRoleCreateInfo info, IGProResultCallback cb); + + void createRole(long guildId, GProRoleCreateInfo info, ArrayList initialUsers, IGProCreateRoleCallback cb); } diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GProSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GProSvc.kt index 51d45545..8072ef04 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GProSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GProSvc.kt @@ -4,7 +4,9 @@ package moe.fuqiuluo.qqinterface.servlet import com.tencent.mobileqq.qqguildsdk.api.IGPSService import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole +import com.tencent.qqnt.kernel.nativeinterface.GProRoleCreateInfo import com.tencent.qqnt.kernel.nativeinterface.GProRoleMemberList +import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.core.readBytes import kotlinx.coroutines.suspendCancellableCoroutine @@ -317,4 +319,52 @@ internal object GProSvc: BaseSvc() { } } } + + suspend fun getGuildRolePermission(guildId: ULong, roleId: ULong): Result { + val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService + val role:GProGuildRole = withTimeoutOrNull(5000) { + suspendCancellableCoroutine { + kernelGProService.fetchRoleWithPermission(guildId.toLong(), roleId.toLong(), 1) { code, msg, role, _, _, _ -> + if (code != 0) { + LogCenter.log("getGuildRolePermission failed: $code($msg)", Level.WARN) + it.resume(null) + } else it.resume(role) + } + } + } ?: return Result.failure(Exception("unable to fetch guild role permission")) + return Result.success(role) + } + + suspend fun updateGuildRole(guildId: ULong, roleId: ULong, name: String, color: Long): Result { + val oldInfo = getGuildRolePermission(guildId, roleId).onFailure { + return Result.failure(it) + }.getOrThrow() + val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService + val info = GProRoleCreateInfo( + name, color, oldInfo.bHoist, oldInfo.rolePermissions + ) + kernelGProService.setRoleInfo(guildId.toLong(), roleId.toLong(), info) { code, msg, result -> + if (code != 0) { + LogCenter.log("updateGuildRole failed: $code($msg) => $result", Level.WARN) + } + } + return Result.success(Unit) + } + + suspend fun createGuildRole(guildId: ULong, name: String, color: Long, initialUsers: ArrayList): Result { + val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService + val permission = GProRolePermission(false, arrayListOf()) + val info = GProRoleCreateInfo(name, color, false, permission) + val role: GProGuildRole = withTimeoutOrNull(5000) { + suspendCancellableCoroutine { + kernelGProService.createRole(guildId.toLong(), info, initialUsers) { code, msg, result, role -> + if (code != 0) { + LogCenter.log("createGuildRole failed: $code($msg) => $result", Level.WARN) + it.resume(null) + } else it.resume(role) + } + } + } ?: return Result.failure(Exception("unable to create guild role")) + return Result.success(role) + } } \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/CreateGuildRole.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/CreateGuildRole.kt new file mode 100644 index 00000000..981fe19e --- /dev/null +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/CreateGuildRole.kt @@ -0,0 +1,42 @@ +@file:Suppress("UNCHECKED_CAST") + +package moe.fuqiuluo.shamrock.remote.action.handlers + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement +import moe.fuqiuluo.qqinterface.servlet.GProSvc +import moe.fuqiuluo.shamrock.remote.action.ActionSession +import moe.fuqiuluo.shamrock.remote.action.IActionHandler +import moe.fuqiuluo.shamrock.tools.EmptyJsonString +import moe.fuqiuluo.shamrock.tools.asString +import moe.fuqiuluo.symbols.OneBotHandler + +@OneBotHandler("create_guild_role") +internal object CreateGuildRole: IActionHandler() { + override suspend fun internalHandle(session: ActionSession): String { + val guildId = session.getString("guild_id").toULong() + val name = session.getString("name") + val color = session.getLong("color") + val initialUsers = session.getArray("initial_users").map { + it.asString.toULong() + } + return invoke(guildId, color, name, initialUsers, session.echo) + } + + suspend operator fun invoke(guildId: ULong, color: Long, name: String, initialUsers: List, echo: JsonElement = EmptyJsonString): String { + val result = GProSvc.createGuildRole(guildId, name, color, initialUsers as ArrayList).onFailure { + return error(it.message ?: "Unknown error", echo) + }.getOrThrow() + return ok(data = CreateGuildRoleResult( + result.roleId.toULong() + ), echo = echo) + } + + override val requiredParams: Array = arrayOf("guild_id", "color", "name", "initial_users") + + @Serializable + data class CreateGuildRoleResult( + @SerialName("role_id") val roleId: ULong + ) +} \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetGuildRoles.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetGuildRoles.kt index 70d13b87..830fd0d1 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetGuildRoles.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetGuildRoles.kt @@ -24,11 +24,11 @@ internal object GetGuildRoles: IActionHandler() { return ok(GetGuildRolesResult(result.map { GuildRole( color = it.color, - disabled = it.count <= 0, + disabled = it.bHoist, independent = it.isChannelRole, maxCount = it.memberLimit, memberCount = it.count, - owned = it.bHoist, + owned = it.isNotSort, roleId = it.roleId, roleName = it.name, permission = it.rolePermissions.permissionList.map { diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/UpdateGuildRole.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/UpdateGuildRole.kt new file mode 100644 index 00000000..85940d30 --- /dev/null +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/UpdateGuildRole.kt @@ -0,0 +1,28 @@ +package moe.fuqiuluo.shamrock.remote.action.handlers + +import kotlinx.serialization.json.JsonElement +import moe.fuqiuluo.qqinterface.servlet.GProSvc +import moe.fuqiuluo.shamrock.remote.action.ActionSession +import moe.fuqiuluo.shamrock.remote.action.IActionHandler +import moe.fuqiuluo.shamrock.tools.EmptyJsonString +import moe.fuqiuluo.symbols.OneBotHandler + +@OneBotHandler("update_guild_role") +internal object UpdateGuildRole: IActionHandler() { + override suspend fun internalHandle(session: ActionSession): String { + val guildId = session.getString("guild_id").toULong() + val roleId = session.getString("role_id").toULong() + val name = session.getString("name") + val color = session.getLong("color") + return invoke(guildId, roleId, name, color, session.echo) + } + + suspend operator fun invoke(guildId: ULong, roleId: ULong, name: String, color: Long, echo: JsonElement = EmptyJsonString): String { + val result = GProSvc.updateGuildRole(guildId, roleId, name, color).onFailure { + return error(it.message ?: "Unknown error", echo) + } + return ok("success", echo = echo) + } + + override val requiredParams: Array = arrayOf("role_id", "guild_id", "name", "color") +} \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GuildAction.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GuildAction.kt index c49c201f..7140b658 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GuildAction.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GuildAction.kt @@ -8,6 +8,7 @@ import io.ktor.server.routing.get import io.ktor.server.routing.post import io.ktor.server.routing.route import moe.fuqiuluo.shamrock.helper.MessageHelper +import moe.fuqiuluo.shamrock.remote.action.handlers.CreateGuildRole import moe.fuqiuluo.shamrock.remote.action.handlers.DeleteGuildRole import moe.fuqiuluo.shamrock.remote.action.handlers.GetGProChannelList import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildFeeds @@ -20,6 +21,7 @@ import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildServiceProfile import moe.fuqiuluo.shamrock.remote.action.handlers.SendGuildMessage import moe.fuqiuluo.shamrock.remote.action.handlers.SendMessage import moe.fuqiuluo.shamrock.remote.action.handlers.SetGuildMemberRole +import moe.fuqiuluo.shamrock.remote.action.handlers.UpdateGuildRole import moe.fuqiuluo.shamrock.tools.fetchGetOrNull import moe.fuqiuluo.shamrock.tools.fetchGetOrThrow import moe.fuqiuluo.shamrock.tools.fetchOrNull @@ -150,4 +152,20 @@ fun Routing.guildAction() { ContentType.Application.Json ) } + + getOrPost("/update_guild_role") { + val guildId = fetchOrThrow("guild_id").toULong() + val roleId = fetchOrThrow("role_id").toULong() + val name = fetchOrThrow("name") + val color = fetchOrThrow("color").toLong() + call.respondText(UpdateGuildRole(guildId, roleId, name, color), ContentType.Application.Json) + } + + getOrPost("/create_guild_role") { + val guildId = fetchOrThrow("guild_id").toULong() + val name = fetchOrThrow("name") + val color = fetchOrThrow("color").toLong() + val initialUsers = fetchOrThrow("initial_users").split(",").map { it.toULong() } + call.respondText(CreateGuildRole(guildId, color, name, initialUsers), ContentType.Application.Json) + } } \ No newline at end of file