diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/OneBotStranger.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/OneBotStranger.kt new file mode 100644 index 0000000..3456c28 --- /dev/null +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/OneBotStranger.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-onebot. + * + * simbot-component-onebot 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-onebot 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-onebot. + * If not, see . + */ + +package love.forte.simbot.component.onebot.v11.core.actor + +import love.forte.simbot.common.id.ID +import love.forte.simbot.common.id.literal +import love.forte.simbot.component.onebot.v11.common.utils.qqAvatar640 +import love.forte.simbot.component.onebot.v11.core.api.GetStrangerInfoApi +import love.forte.simbot.definition.User + + +/** + * 一个陌生人。 + * 通常是通过 [GetStrangerInfoApi] + * 得到的信息。 + * + * @author ForteScarlet + */ +public interface OneBotStranger : User { + override val id: ID + override val name: String + + override val avatar: String + get() = qqAvatar640(id.literal) + + /** + * 年龄。 + * 如果无法获取则有可能会被填充一个默认值。 + */ + public val age: Int + + /** + * 性别。`male` 或 `female` 或 `unknown` + */ + public val sex: String +} diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/internal/OneBotStrangerImpl.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/internal/OneBotStrangerImpl.kt new file mode 100644 index 0000000..6ab5e74 --- /dev/null +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/internal/OneBotStrangerImpl.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-onebot. + * + * simbot-component-onebot 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-onebot 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-onebot. + * If not, see . + */ + +package love.forte.simbot.component.onebot.v11.core.actor.internal + +import love.forte.simbot.common.id.ID +import love.forte.simbot.component.onebot.v11.core.actor.OneBotStranger +import love.forte.simbot.component.onebot.v11.core.api.GetStrangerInfoResult +import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl +import kotlin.coroutines.CoroutineContext + + +/** + * + * @author ForteScarlet + */ +internal class OneBotStrangerImpl( + override val coroutineContext: CoroutineContext, + private val source: GetStrangerInfoResult +) : OneBotStranger { + + override val id: ID + get() = source.userId + + override val name: String + get() = source.nickname + + override val age: Int + get() = source.age + + override val sex: String + get() = source.sex + + override fun toString(): String = + "OneBotStranger(source=$source)" +} + +internal fun GetStrangerInfoResult.toStranger( + bot: OneBotBotImpl, + coroutineContext: CoroutineContext = bot.subContext, +): OneBotStrangerImpl = + OneBotStrangerImpl(coroutineContext, this) diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt index c11c68c..55de34d 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt @@ -87,6 +87,8 @@ import love.forte.simbot.component.onebot.v11.core.event.internal.message.OneBot import love.forte.simbot.component.onebot.v11.core.event.internal.meta.OneBotDefaultMetaEventImpl import love.forte.simbot.component.onebot.v11.core.event.internal.meta.OneBotHeartbeatEventImpl import love.forte.simbot.component.onebot.v11.core.event.internal.meta.OneBotLifecycleEventImpl +import love.forte.simbot.component.onebot.v11.core.event.internal.request.OneBotFriendRequestEventImpl +import love.forte.simbot.component.onebot.v11.core.event.internal.request.OneBotGroupRequestEventImpl import love.forte.simbot.component.onebot.v11.core.event.internal.stage.OneBotBotStartedEventImpl import love.forte.simbot.component.onebot.v11.core.utils.onEachErrorLog import love.forte.simbot.component.onebot.v11.event.UnknownEvent @@ -95,6 +97,8 @@ import love.forte.simbot.component.onebot.v11.event.message.PrivateMessageEvent import love.forte.simbot.component.onebot.v11.event.meta.HeartbeatEvent import love.forte.simbot.component.onebot.v11.event.meta.LifecycleEvent import love.forte.simbot.component.onebot.v11.event.meta.MetaEvent +import love.forte.simbot.component.onebot.v11.event.request.FriendRequestEvent +import love.forte.simbot.component.onebot.v11.event.request.GroupRequestEvent import love.forte.simbot.component.onebot.v11.event.resolveEventSerializer import love.forte.simbot.component.onebot.v11.event.resolveEventSubTypeFieldName import love.forte.simbot.event.Event @@ -455,7 +459,7 @@ internal class OneBotBotImpl( resolveRawEvent(eventRaw) }.getOrElse { e -> val exMsg = "Failed to resolve raw event $eventRaw, " + - "session and bot will be closed exceptionally" + "session and bot will be closed exceptionally" val ex = IllegalStateException( exMsg, @@ -575,6 +579,20 @@ internal class OneBotBotImpl( } //endregion + //region 申请事件 + is FriendRequestEvent -> OneBotFriendRequestEventImpl( + raw, + event, + bot + ) + is GroupRequestEvent -> OneBotGroupRequestEventImpl( + raw, + event, + bot + ) + // 其余未知的申请事件扔到 unsupported + //endregion + // TODO notice events is UnknownEvent -> OneBotUnknownEvent(raw, event) diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/internal/request/OneBotRequestEventImpl.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/internal/request/OneBotRequestEventImpl.kt new file mode 100644 index 0000000..e57fdfd --- /dev/null +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/internal/request/OneBotRequestEventImpl.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-onebot. + * + * simbot-component-onebot 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-onebot 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-onebot. + * If not, see . + */ + +package love.forte.simbot.component.onebot.v11.core.event.internal.request + +import love.forte.simbot.common.id.ID +import love.forte.simbot.common.id.UUID +import love.forte.simbot.common.time.Timestamp +import love.forte.simbot.component.onebot.v11.core.actor.OneBotGroup +import love.forte.simbot.component.onebot.v11.core.actor.OneBotStranger +import love.forte.simbot.component.onebot.v11.core.actor.internal.toStranger +import love.forte.simbot.component.onebot.v11.core.api.GetStrangerInfoApi +import love.forte.simbot.component.onebot.v11.core.api.SetFriendAddRequestApi +import love.forte.simbot.component.onebot.v11.core.api.SetGroupAddRequestApi +import love.forte.simbot.component.onebot.v11.core.bot.OneBotBot +import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl +import love.forte.simbot.component.onebot.v11.core.bot.requestDataBy +import love.forte.simbot.component.onebot.v11.core.event.internal.eventToString +import love.forte.simbot.component.onebot.v11.core.event.request.OneBotFriendRequestEvent +import love.forte.simbot.component.onebot.v11.core.event.request.OneBotGroupRequestEvent +import love.forte.simbot.component.onebot.v11.core.event.request.OneBotRequestEvent +import love.forte.simbot.component.onebot.v11.core.utils.timestamp +import love.forte.simbot.component.onebot.v11.event.request.FriendRequestEvent +import love.forte.simbot.component.onebot.v11.event.request.GroupRequestEvent + + +internal abstract class OneBotRequestEventImpl : OneBotRequestEvent { + override val id: ID = UUID.random() + + override val time: Timestamp + get() = sourceEvent.timestamp() + + override suspend fun accept() { + doSetRequest(true) + } + + override suspend fun reject() { + doSetRequest(false) + } + + protected abstract suspend fun doSetRequest(approve: Boolean) +} + +internal class OneBotFriendRequestEventImpl( + override val sourceEventRaw: String?, + override val sourceEvent: FriendRequestEvent, + override val bot: OneBotBot, +) : OneBotRequestEventImpl(), OneBotFriendRequestEvent { + override suspend fun doSetRequest(approve: Boolean) { + SetFriendAddRequestApi.create( + flag = sourceEvent.flag, + approve = approve, + ).requestDataBy(bot) + } + + override fun toString(): String = + eventToString("OneBotFriendRequestEvent") +} + +internal class OneBotGroupRequestEventImpl( + override val sourceEventRaw: String?, + override val sourceEvent: GroupRequestEvent, + override val bot: OneBotBotImpl, +) : OneBotRequestEventImpl(), OneBotGroupRequestEvent { + override suspend fun doSetRequest(approve: Boolean) { + SetGroupAddRequestApi.create( + flag = sourceEvent.flag, + subType = sourceEvent.subType, + approve = approve + ).requestDataBy(bot) + } + + override suspend fun content(): OneBotGroup { + return bot.groupRelation.group(sourceEvent.groupId) + ?: error("Group with id ${sourceEvent.groupId} not found") + } + + override suspend fun requester(): OneBotStranger { + return GetStrangerInfoApi + .create(sourceEvent.userId) + .requestDataBy(bot) + .toStranger(bot) + } + + override fun toString(): String = + eventToString("OneBotGroupRequestEvent") +} + diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/request/OneBotRequestEvent.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/request/OneBotRequestEvent.kt index 35fb67a..cd74d9f 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/request/OneBotRequestEvent.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/event/request/OneBotRequestEvent.kt @@ -17,8 +17,15 @@ package love.forte.simbot.component.onebot.v11.core.event.request +import love.forte.simbot.common.id.LongID +import love.forte.simbot.component.onebot.v11.core.actor.OneBotGroup +import love.forte.simbot.component.onebot.v11.core.actor.OneBotStranger import love.forte.simbot.component.onebot.v11.core.event.OneBotBotEvent +import love.forte.simbot.component.onebot.v11.event.request.FriendRequestEvent +import love.forte.simbot.component.onebot.v11.event.request.GroupRequestEvent +import love.forte.simbot.event.OrganizationJoinRequestEvent import love.forte.simbot.event.RequestEvent +import love.forte.simbot.suspendrunner.STP public typealias OBSourceRequestEvent = love.forte.simbot.component.onebot.v11.event.request.RequestEvent @@ -31,3 +38,97 @@ public typealias OBSourceRequestEvent = love.forte.simbot.component.onebot.v11.e public interface OneBotRequestEvent : OneBotBotEvent, RequestEvent { override val sourceEvent: OBSourceRequestEvent } + +/** + * 好友添加申请事件 + * @see FriendRequestEvent + */ +public interface OneBotFriendRequestEvent : OneBotRequestEvent { + override val sourceEvent: FriendRequestEvent + + /** + * 好友添加申请始终是 [主动地][RequestEvent.Type.PROACTIVE] + */ + override val type: RequestEvent.Type + get() = RequestEvent.Type.PROACTIVE + + /** + * 验证信息。 + * + * @see FriendRequestEvent.comment + */ + override val message: String + get() = sourceEvent.comment + + /** + * 请求 flag,在调用处理请求的 API 时需要传入 + * + * @see FriendRequestEvent.flag + */ + public val flag: String + get() = sourceEvent.flag + + /** + * 发送请求的 QQ 号 + * + * @see FriendRequestEvent.userId + */ + public val requesterId: LongID + get() = sourceEvent.userId +} + +/** + * 群添加申请事件 + * @see GroupRequestEvent + */ +public interface OneBotGroupRequestEvent : OneBotRequestEvent, OrganizationJoinRequestEvent { + override val sourceEvent: GroupRequestEvent + + /** + * 申请加入的群。 + */ + @STP + override suspend fun content(): OneBotGroup + + /** + * 根据 [GroupRequestEvent.subType] 的值区分类型。 + * 如果是 `invite` 则为被动,否则(包括 `add`)均视为主动。 + * + */ + override val type: RequestEvent.Type + get() = when (sourceEvent.subType) { + GroupRequestEvent.SUB_TYPE_INVITE -> RequestEvent.Type.PASSIVE + GroupRequestEvent.SUB_TYPE_ADD -> RequestEvent.Type.PROACTIVE + else -> RequestEvent.Type.PROACTIVE + } + + /** + * 验证信息。 + * + * @see GroupRequestEvent.comment + */ + override val message: String + get() = sourceEvent.comment + + /** + * 请求 flag,在调用处理请求的 API 时需要传入 + * + * @see GroupRequestEvent.flag + */ + public val flag: String + get() = sourceEvent.flag + + /** + * 发送请求的 QQ 号 + * + * @see GroupRequestEvent.userId + */ + override val requesterId: LongID + get() = sourceEvent.userId + + /** + * 申请者的部分信息。 + */ + @STP + override suspend fun requester(): OneBotStranger +} diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/request/GroupRequestEvent.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/request/GroupRequestEvent.kt index a22ddef..032e7b9 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/request/GroupRequestEvent.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/request/GroupRequestEvent.kt @@ -53,4 +53,17 @@ public data class GroupRequestEvent( public val userId: LongID, public val comment: String = "", public val flag: String, -) : RequestEvent +) : RequestEvent { + + public companion object { + /** + * @see GroupRequestEvent.subType + */ + public const val SUB_TYPE_ADD: String = "add" + + /** + * @see GroupRequestEvent.subType + */ + public const val SUB_TYPE_INVITE: String = "invite" + } +}