diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index d7a1e006e..ba4d48077 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -9,7 +9,7 @@ object Versions { object Mirai { - const val version = "0.34.0" + const val version = "0.35.0" } object Kotlin { diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt index 0c437b91c..ee5e156df 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt @@ -31,9 +31,9 @@ import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.* import net.mamoe.mirai.event.broadcast +import net.mamoe.mirai.event.events.MemberJoinRequestEvent import net.mamoe.mirai.event.events.MessageRecallEvent -import net.mamoe.mirai.event.events.NewFriendEvent -import net.mamoe.mirai.event.events.NewGroupEvent +import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.* import net.mamoe.mirai.qqandroid.contact.MemberInfoImpl @@ -70,6 +70,7 @@ internal fun Bot.asQQAndroidBot(): QQAndroidBot { return this as QQAndroidBot } +@Suppress("INVISIBLE_MEMBER") @OptIn(MiraiInternalAPI::class) internal class QQAndroidBot constructor( context: Context, @@ -77,7 +78,11 @@ internal class QQAndroidBot constructor( configuration: BotConfiguration ) : QQAndroidBotBase(context, account, configuration) { - override suspend fun acceptNewFriend(event: NewFriendEvent) { + override suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent) { + check(event.responded.compareAndSet(expect = false, update = true)) { + "the request $this has already been responded" + } + network.run { NewContact.SystemMsgNewFriend.Action( bot.client, @@ -87,7 +92,11 @@ internal class QQAndroidBot constructor( } } - override suspend fun rejectNewFriend(event: NewFriendEvent, blackList: Boolean) { + override suspend fun rejectNewFriendRequest(event: NewFriendRequestEvent, blackList: Boolean) { + check(event.responded.compareAndSet(expect = false, update = true)) { + "the request $this has already been responded" + } + network.run { NewContact.SystemMsgNewFriend.Action( bot.client, @@ -98,17 +107,30 @@ internal class QQAndroidBot constructor( } } - override suspend fun acceptNewGroup(event: NewGroupEvent) { + @OptIn(LowLevelAPI::class) + override suspend fun acceptMemberJoinRequest(event: MemberJoinRequestEvent) { + check(event.responded.compareAndSet(expect = false, update = true)) { + "the request $this has already been responded" + } + network.run { NewContact.SystemMsgNewGroup.Action( bot.client, event, accept = true ).sendWithoutExpect() + bot.friends.delegate.addLast(bot._lowLevelNewQQ(object : FriendInfo { + override val uin: Long get() = event.fromId + override val nick: String get() = event.fromNick + })) } } - override suspend fun rejectNewGroup(event: NewGroupEvent, blackList: Boolean) { + @OptIn(LowLevelAPI::class) + override suspend fun rejectMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) { + check(event.responded.compareAndSet(expect = false, update = true)) { + "the request $this has already been responded" + } network.run { NewContact.SystemMsgNewGroup.Action( bot.client, @@ -116,10 +138,22 @@ internal class QQAndroidBot constructor( accept = false, blackList = blackList ).sendWithoutExpect() + event.group.members.delegate.addLast(event.group.newMember(object : MemberInfo { + override val nameCard: String get() = "" + override val permission: MemberPermission get() = MemberPermission.MEMBER + override val specialTitle: String get() = "" + override val muteTimestamp: Int get() = 0 + override val uin: Long get() = event.fromId + override val nick: String get() = event.fromNick + })) } } - override suspend fun ignoreNewGroup(event: NewGroupEvent, blackList: Boolean) { + override suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) { + + check(event.responded.compareAndSet(expect = false, update = true)) { + "the request $this has already been responded" + } network.run { NewContact.SystemMsgNewGroup.Action( bot.client, diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/NewContact.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/NewContact.kt index 92563afd2..9e3f1e76d 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/NewContact.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/NewContact.kt @@ -2,8 +2,8 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.readBytes -import net.mamoe.mirai.event.events.NewFriendEvent -import net.mamoe.mirai.event.events.NewGroupEvent +import net.mamoe.mirai.event.events.MemberJoinRequestEvent +import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm @@ -17,7 +17,7 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf internal class NewContact { internal object SystemMsgNewFriend : - OutgoingPacketFactory<NewFriendEvent?>("ProfileService.Pb.ReqSystemMsgNew.Friend") { + OutgoingPacketFactory<NewFriendRequestEvent?>("ProfileService.Pb.ReqSystemMsgNew.Friend") { operator fun invoke(client: QQAndroidClient) = buildOutgoingUniPacket(client) { writeProtoBuf( @@ -41,17 +41,17 @@ internal class NewContact { } - override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): NewFriendEvent? { + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): NewFriendRequestEvent? { readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run { val struct = friendmsgs?.firstOrNull() return if (struct == null) null else { struct.msg?.run { - NewFriendEvent( + NewFriendRequestEvent( bot, struct.msgSeq, msgAdditional, struct.reqUin, - groupName, + groupCode, reqUinNick ) } @@ -63,7 +63,7 @@ internal class NewContact { operator fun invoke( client: QQAndroidClient, - event: NewFriendEvent, + event: NewFriendRequestEvent, accept: Boolean, blackList: Boolean = false ) = @@ -78,8 +78,8 @@ internal class NewContact { remark = "", blacklist = !accept && blackList ), - msgSeq = event.seq, - reqUin = event.id, + msgSeq = event.eventId, + reqUin = event.fromId, srcId = 6, subSrcId = 7, subType = 1 @@ -93,7 +93,7 @@ internal class NewContact { internal object SystemMsgNewGroup : - OutgoingPacketFactory<NewGroupEvent?>("ProfileService.Pb.ReqSystemMsgNew.Group") { + OutgoingPacketFactory<MemberJoinRequestEvent?>("ProfileService.Pb.ReqSystemMsgNew.Group") { operator fun invoke(client: QQAndroidClient) = buildOutgoingUniPacket(client) { writeProtoBuf( @@ -129,13 +129,13 @@ internal class NewContact { } - override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): NewGroupEvent? { + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): MemberJoinRequestEvent? { readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run { val struct = groupmsgs?.firstOrNull() return if (struct == null) null else { struct.msg?.run { - NewGroupEvent( + MemberJoinRequestEvent( bot, struct.msgSeq, msgAdditional, @@ -153,7 +153,7 @@ internal class NewContact { operator fun invoke( client: QQAndroidClient, - event: NewGroupEvent, + event: MemberJoinRequestEvent, accept: Boolean?, blackList: Boolean = false ) = @@ -174,8 +174,8 @@ internal class NewContact { ), groupMsgType = 1, language = 1000, - msgSeq = event.seq, - reqUin = event.id, + msgSeq = event.eventId, + reqUin = event.fromId, srcId = 3, subSrcId = 31, subType = 1 diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt index 37a5ed977..d007f69be 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/Bot.kt @@ -6,8 +6,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.io.ByteReadChannel import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.AddFriendResult -import net.mamoe.mirai.event.events.NewFriendEvent -import net.mamoe.mirai.event.events.NewGroupEvent +import net.mamoe.mirai.event.events.MemberJoinRequestEvent +import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.MessageChain @@ -208,7 +208,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param event 好友验证的事件对象 */ @JvmSynthetic - actual abstract suspend fun acceptNewFriend(event: NewFriendEvent) + actual abstract suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent) /** * 拒绝好友验证 @@ -217,7 +217,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param blackList 拒绝后是否拉入黑名单 */ @JvmSynthetic - actual abstract suspend fun rejectNewFriend(event: NewFriendEvent, blackList: Boolean) + actual abstract suspend fun rejectNewFriendRequest(event: NewFriendRequestEvent, blackList: Boolean) /** * 通过加群验证(需管理员权限) @@ -225,7 +225,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param event 加群验证的事件对象 */ @JvmSynthetic - actual abstract suspend fun acceptNewGroup(event: NewGroupEvent) + actual abstract suspend fun acceptMemberJoinRequest(event: MemberJoinRequestEvent) /** * 拒绝加群验证(需管理员权限) @@ -234,7 +234,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param blackList 拒绝后是否拉入黑名单 */ @JvmSynthetic - actual abstract suspend fun rejectNewGroup(event: NewGroupEvent, blackList: Boolean) + actual abstract suspend fun rejectMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) /** * 忽略加群验证(需管理员权限) @@ -243,5 +243,5 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param blackList 忽略后是否拉入黑名单 */ @JvmSynthetic - actual abstract suspend fun ignoreNewGroup(event: NewGroupEvent, blackList: Boolean) + actual abstract suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index c8f7cd9dc..5d5c490b8 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -18,8 +18,8 @@ import kotlinx.coroutines.io.ByteReadChannel import kotlinx.coroutines.launch import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.AddFriendResult -import net.mamoe.mirai.event.events.NewFriendEvent -import net.mamoe.mirai.event.events.NewGroupEvent +import net.mamoe.mirai.event.events.MemberJoinRequestEvent +import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.* import net.mamoe.mirai.network.BotNetworkHandler @@ -208,7 +208,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor { */ @SinceMirai("0.35.0") @JvmSynthetic - abstract suspend fun acceptNewFriend(event: NewFriendEvent) + abstract suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent) /** * 拒绝好友验证 @@ -218,7 +218,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor { */ @SinceMirai("0.35.0") @JvmSynthetic - abstract suspend fun rejectNewFriend(event: NewFriendEvent, blackList: Boolean = false) + abstract suspend fun rejectNewFriendRequest(event: NewFriendRequestEvent, blackList: Boolean = false) /** * 通过加群验证(需管理员权限) @@ -227,7 +227,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor { */ @SinceMirai("0.35.0") @JvmSynthetic - abstract suspend fun acceptNewGroup(event: NewGroupEvent) + abstract suspend fun acceptMemberJoinRequest(event: MemberJoinRequestEvent) /** * 拒绝加群验证(需管理员权限) @@ -237,7 +237,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor { */ @SinceMirai("0.35.0") @JvmSynthetic - abstract suspend fun rejectNewGroup(event: NewGroupEvent, blackList: Boolean = false) + abstract suspend fun rejectMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean = false) /** * 忽略加群验证(需管理员权限) @@ -247,7 +247,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor { */ @SinceMirai("0.35.0") @JvmSynthetic - abstract suspend fun ignoreNewGroup(event: NewGroupEvent, blackList: Boolean = false) + abstract suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean = false) // endregion diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt index 5206b352d..deafcc70f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt @@ -12,6 +12,8 @@ package net.mamoe.mirai.event.events +import kotlinx.atomicfu.AtomicBoolean +import kotlinx.atomicfu.atomic import net.mamoe.mirai.Bot import net.mamoe.mirai.JavaFriendlyAPI import net.mamoe.mirai.contact.* @@ -482,63 +484,112 @@ data class MemberUnmuteEvent( // region 好友、群认证 +/** + * 一个账号请求添加机器人为好友的事件 + */ @SinceMirai("0.35.0") -data class NewFriendEvent( +data class NewFriendRequestEvent( override val bot: Bot, - val seq: Long, // 事件唯一识别 - val additional: String, - val id: Long, - val groupName: String, + /** + * 事件唯一识别号 + */ + val eventId: Long, + /** + * 入群申请消息 + */ + val message: String, + /** + * 请求人 [QQ.id] + */ + val fromId: Long, + /** + * 来自群 [Group.id], 其他途径时为 0 + */ + val fromGroupId: Long, + /** + * 群名片或好友昵称 + */ val nick: String ) : BotEvent, Packet { - @JvmSynthetic - suspend fun accept() = bot.acceptNewFriend(this) + internal val responded: AtomicBoolean = atomic(false) + + /** + * @return 申请人来自的群. 当申请人来自其他途径申请时为 `null` + */ + val fromGroup: Group? = if (fromGroupId == 0L) null else bot.getGroup(fromGroupId) @JvmSynthetic - suspend fun reject(blackList: Boolean = false) = bot.rejectNewFriend(this, blackList) + suspend fun accept() = bot.acceptNewFriendRequest(this) + + @JvmSynthetic + suspend fun reject(blackList: Boolean = false) = bot.rejectNewFriendRequest(this, blackList) @JavaFriendlyAPI @JvmName("accept") - fun ` __ accept blocking for java __`() = runBlocking { bot.acceptNewFriend(this@NewFriendEvent) } + fun ` __ accept blocking for java __`() = runBlocking { accept() } @JavaFriendlyAPI @JvmOverloads @JvmName("reject") fun ` __ reject blocking for java __`(blackList: Boolean = false) = - runBlocking { bot.rejectNewFriend(this@NewFriendEvent, blackList) } + runBlocking { reject(blackList) } } +/** + * 机器人被邀请加入群 + */ @SinceMirai("0.35.0") -data class NewGroupEvent( +data class MemberJoinRequestEvent( override val bot: Bot, - val seq: Long, // 事件唯一识别 - val additional: String, - val id: Long, + /** + * 事件唯一识别号 + */ + val eventId: Long, + /** + * 入群申请消息 + */ + val message: String, + /** + * 申请入群的账号的 id + */ + val fromId: Long, val groupId: Long, val groupName: String, - val nick: String + /** + * 申请人昵称 + */ + val fromNick: String ) : BotEvent, Packet { - suspend fun accept() = bot.acceptNewGroup(this) - suspend fun reject(blackList: Boolean = false) = bot.rejectNewGroup(this, blackList) - suspend fun ignore(blackList: Boolean = false) = bot.ignoreNewGroup(this, blackList) + val group: Group = this.bot.getGroup(groupId) + + internal val responded: AtomicBoolean = atomic(false) + + @JvmSynthetic + suspend fun accept() = bot.acceptMemberJoinRequest(this) + + @JvmSynthetic + suspend fun reject(blackList: Boolean = false) = bot.rejectMemberJoinRequest(this, blackList) + + @JvmSynthetic + suspend fun ignore(blackList: Boolean = false) = bot.ignoreMemberJoinRequest(this, blackList) @JavaFriendlyAPI @JvmName("accept") - fun ` __ accept blocking for java __`() = runBlocking { bot.acceptNewGroup(this@NewGroupEvent) } + fun ` __ accept blocking for java __`() = runBlocking { bot.acceptMemberJoinRequest(this@MemberJoinRequestEvent) } @JavaFriendlyAPI @JvmOverloads @JvmName("reject") fun ` __ reject blocking for java __`(blackList: Boolean = false) = - runBlocking { bot.rejectNewGroup(this@NewGroupEvent, blackList) } + runBlocking { bot.rejectMemberJoinRequest(this@MemberJoinRequestEvent, blackList) } @JavaFriendlyAPI @JvmOverloads @JvmName("ignore") fun ` __ ignore blocking for java __`(blackList: Boolean = false) = - runBlocking { bot.ignoreNewGroup(this@NewGroupEvent, blackList) } + runBlocking { bot.ignoreMemberJoinRequest(this@MemberJoinRequestEvent, blackList) } } // endregion 好友、群认证 \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt index 012be785d..b74dec434 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/Bot.kt @@ -6,8 +6,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.io.ByteReadChannel import net.mamoe.mirai.contact.* import net.mamoe.mirai.data.AddFriendResult -import net.mamoe.mirai.event.events.NewFriendEvent -import net.mamoe.mirai.event.events.NewGroupEvent +import net.mamoe.mirai.event.events.NewFriendRequestEvent +import net.mamoe.mirai.event.events.MemberJoinRequestEvent import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.* import net.mamoe.mirai.network.BotNetworkHandler @@ -216,7 +216,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param event 好友验证的事件对象 */ @JvmSynthetic - actual abstract suspend fun acceptNewFriend(event: NewFriendEvent) + actual abstract suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent) /** * 拒绝好友验证 @@ -225,7 +225,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param blackList 拒绝后是否拉入黑名单 */ @JvmSynthetic - actual abstract suspend fun rejectNewFriend(event: NewFriendEvent, blackList: Boolean) + actual abstract suspend fun rejectNewFriendRequest(event: NewFriendRequestEvent, blackList: Boolean) /** * 通过加群验证(需管理员权限) @@ -233,7 +233,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param event 加群验证的事件对象 */ @JvmSynthetic - actual abstract suspend fun acceptNewGroup(event: NewGroupEvent) + actual abstract suspend fun acceptMemberJoinRequest(event: MemberJoinRequestEvent) /** * 拒绝加群验证(需管理员权限) @@ -242,7 +242,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param blackList 拒绝后是否拉入黑名单 */ @JvmSynthetic - actual abstract suspend fun rejectNewGroup(event: NewGroupEvent, blackList: Boolean) + actual abstract suspend fun rejectMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) /** * 忽略加群验证(需管理员权限) @@ -251,5 +251,5 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA * @param blackList 忽略后是否拉入黑名单 */ @JvmSynthetic - actual abstract suspend fun ignoreNewGroup(event: NewGroupEvent, blackList: Boolean) + actual abstract suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) } \ No newline at end of file