Commit ab464388 authored by Him188's avatar Him188

Support BotJoinGroupEvent.Invite, close #344

parent e8345c38
......@@ -450,9 +450,10 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(groupIdOrZero: Long, bot: B
internal fun contextualBugReportException(
context: String,
forDebug: String,
e: Throwable? = null
e: Throwable? = null,
additional: String = ""
): IllegalStateException {
return IllegalStateException("在 $context 时遇到了意料之中的问题. 请完整复制此日志提交给 mirai. 调试信息: $forDebug", e)
return IllegalStateException("在 $context 时遇到了意料之中的问题. 请完整复制此日志提交给 mirai. $additional 调试信息: $forDebug", e)
}
@OptIn(ExperimentalContracts::class)
......
......@@ -14,10 +14,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent
import net.mamoe.mirai.event.events.BotLeaveEvent
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
import net.mamoe.mirai.event.events.NewFriendRequestEvent
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.message.contextualBugReportException
import net.mamoe.mirai.qqandroid.network.Packet
......@@ -25,6 +22,7 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Structmsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.getNewGroup
import net.mamoe.mirai.qqandroid.utils._miraiContentToString
import net.mamoe.mirai.qqandroid.utils.io.serialization.loadAs
import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
......@@ -169,10 +167,19 @@ internal class NewContact {
}
else -> throw contextualBugReportException(
"parse SystemMsgNewGroup, subType=1",
forDebug = this._miraiContentToString()
this._miraiContentToString(),
additional = "并尽量描述此时机器人是否正被邀请加入群, 或者是有有新群员加入此群"
)
}
}
2 -> {
// 被邀请入群, 自动同意
val group = bot.getNewGroup(groupCode) ?: return null
val invitor = group[actionUin]
BotJoinGroupEvent.Invite(reqUinNick, invitor)
}
5 -> {
val group = bot.getGroup(groupCode)
val operator = group[actionUin]
......@@ -180,7 +187,8 @@ internal class NewContact {
}
else -> throw contextualBugReportException(
"parse SystemMsgNewGroup",
forDebug = this._miraiContentToString()
forDebug = this._miraiContentToString(),
additional = "并尽量描述此时机器人是否正被邀请加入群, 或者是有有新群员加入此群"
)
}
} as Packet // 没有 as Packet 垃圾 kotlin 会把类型推断为Any
......
......@@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.atomicfu.loop
......@@ -105,42 +107,6 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
object EmptyResponse : GetMsgSuccess(emptyList())
private suspend fun MsgComm.Msg.getNewGroup(bot: QQAndroidBot): Group? {
val troopNum = bot.network.run {
FriendList.GetTroopListSimplify(bot.client)
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2)
}.groups.firstOrNull { it.groupUin == msgHead.fromUin } ?: return null
@Suppress("DuplicatedCode")
return GroupImpl(
bot = bot,
coroutineContext = bot.coroutineContext,
id = Group.calculateGroupCodeByGroupUin(msgHead.fromUin),
groupInfo = bot._lowLevelQueryGroupInfo(troopNum.groupCode).apply {
this as GroupInfoImpl
if (this.delegate.groupName == null) {
this.delegate.groupName = troopNum.groupName
}
if (this.delegate.groupMemo == null) {
this.delegate.groupMemo = troopNum.groupMemo
}
if (this.delegate.groupUin == null) {
this.delegate.groupUin = troopNum.groupUin
}
this.delegate.groupCode = troopNum.groupCode
},
members = bot._lowLevelQueryGroupMemberList(
troopNum.groupUin,
troopNum.groupCode,
troopNum.dwGroupOwnerUin
)
)
}
private fun MsgComm.Msg.getNewMemberInfo(): MemberInfo {
return object : MemberInfo {
override val nameCard: String get() = ""
......@@ -189,10 +155,10 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
}
// 新群
val newGroup = msg.getNewGroup(bot) ?: return@mapNotNull null
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
val newGroup = bot.getNewGroup(Group.calculateGroupCodeByGroupUin(msg.msgHead.fromUin))
?: return@mapNotNull null
bot.groups.delegate.addLast(newGroup)
return@mapNotNull BotJoinGroupEvent(newGroup)
return@mapNotNull BotJoinGroupEvent.Active(newGroup)
} else {
group ?: return@mapNotNull null
......@@ -212,12 +178,10 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
discardExact(9)
readByte().toInt().and(0xff)
} == 0x83) {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
return@mapNotNull MemberJoinEvent.Invite(group.newMember(msg.getNewMemberInfo())
.also { group.members.delegate.addLast(it) })
}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
return@mapNotNull MemberJoinEvent.Active(group.newMember(msg.getNewMemberInfo())
.also { group.members.delegate.addLast(it) })
}
......@@ -394,3 +358,39 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
}
}
internal suspend fun QQAndroidBot.getNewGroup(groupCode: Long): Group? {
val troopNum = network.run {
FriendList.GetTroopListSimplify(client)
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(timeoutMillis = 10_000, retry = 5)
}.groups.firstOrNull { it.groupCode == groupCode } ?: return null
@Suppress("DuplicatedCode")
return GroupImpl(
bot = this,
coroutineContext = coroutineContext,
id = groupCode,
groupInfo = _lowLevelQueryGroupInfo(troopNum.groupCode).apply {
this as GroupInfoImpl
if (this.delegate.groupName == null) {
this.delegate.groupName = troopNum.groupName
}
if (this.delegate.groupMemo == null) {
this.delegate.groupMemo = troopNum.groupMemo
}
if (this.delegate.groupUin == null) {
this.delegate.groupUin = troopNum.groupUin
}
this.delegate.groupCode = troopNum.groupCode
},
members = _lowLevelQueryGroupMemberList(
troopNum.groupUin,
troopNum.groupCode,
troopNum.dwGroupOwnerUin
)
)
}
......@@ -174,6 +174,7 @@ abstract class Group : Contact(), CoroutineScope {
companion object {
/**
* 使用 groupCode 计算 groupUin. 这两个值仅在 mirai 内部协议区分, 一般人使用时无需在意.
* @suppress internal api
*/
@JvmStatic
......@@ -181,6 +182,7 @@ abstract class Group : Contact(), CoroutineScope {
CommonGroupCalculations.calculateGroupUinByGroupCode(groupCode)
/**
* 使用 groupUin 计算 groupCode. 这两个值仅在 mirai 内部协议区分, 一般人使用时无需在意.
* @suppress internal api
*/
@JvmStatic
......
......@@ -9,7 +9,7 @@
@file:JvmMultifileClass
@file:JvmName("BotEventsKt")
@file:Suppress("unused", "FunctionName")
@file:Suppress("unused", "FunctionName", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package net.mamoe.mirai.event.events
......@@ -25,6 +25,7 @@ import net.mamoe.mirai.event.internal.MiraiAtomicBoolean
import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.internal.LowPriorityInOverloadResolution
import kotlin.jvm.*
/**
......@@ -91,10 +92,44 @@ data class BotUnmuteEvent internal constructor(
/**
* Bot 成功加入了一个新群
*/
@MiraiExperimentalAPI
data class BotJoinGroupEvent internal constructor(
override val group: Group
) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent()
sealed class BotJoinGroupEvent : GroupEvent, Packet, AbstractEvent() {
abstract override val group: Group
/**
* 不确定. 可能是主动加入
*/
@MiraiExperimentalAPI
data class Active internal constructor(
override val group: Group
) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent() {
override fun toString(): String {
return "BotJoinGroupEvent.Active(group=$group)"
}
}
/**
* Bot 被一个群内的成员直接邀请加入了群.
*
* 此时服务器基于 Bot 的 QQ 设置自动同意了请求.
*/
@MiraiExperimentalAPI
data class Invite internal constructor(
/**
* 邀请人昵称 (可能为备注或群名片)
*/
val invitorName: String,
/**
* 邀请人
*/
val invitor: Member
) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent() {
override val group: Group get() = invitor.group
override fun toString(): String {
return "BotJoinGroupEvent.Invite(invitorName='$invitorName', invitor=$invitor)"
}
}
}
// region 群设置
......@@ -121,6 +156,7 @@ data class GroupNameChangeEvent internal constructor(
*/
override val operator: Member?
) : GroupSettingChangeEvent<String>, Packet, GroupOperableEvent, AbstractEvent() {
@LowPriorityInOverloadResolution
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
val isByBot: Boolean
get() = operator == null
......@@ -202,7 +238,8 @@ data class GroupAllowMemberInviteEvent internal constructor(
/**
* 成员已经加入群的事件
*/
sealed class MemberJoinEvent(override val member: Member) : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent() {
sealed class MemberJoinEvent(override val member: Member) : GroupMemberEvent, BotPassiveEvent, Packet,
AbstractEvent() {
/**
* 被邀请加入群
*/
......
......@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION")
@file:Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package net.mamoe.mirai.event.events
......@@ -16,6 +16,7 @@ import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.event.Event
import kotlin.internal.HidesMembers
import kotlin.jvm.JvmSynthetic
/**
......@@ -69,6 +70,7 @@ interface GroupOperableEvent : GroupEvent {
/**
* 是否由 [Bot] 操作
*/
@HidesMembers
@get:JvmSynthetic // inline: planning to change to another file (1.2.0)
inline val GroupOperableEvent.isByBot: Boolean
get() = operator == null
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment