mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-24 20:43:33 +08:00
Merge 6682782168
into 283f8840d4
This commit is contained in:
commit
73006fdf88
mirai-core-api
compatibility-validation
src/commonMain/kotlin
mirai-core-mock/src/internal
mirai-core/src
commonMain/kotlin
commonTest/kotlin/notice/processors
@ -26,6 +26,8 @@ public abstract interface class net/mamoe/mirai/Bot : kotlinx/coroutines/Corouti
|
||||
public static fun getInstances ()Ljava/util/List;
|
||||
public static fun getInstancesSequence ()Lkotlin/sequences/Sequence;
|
||||
public abstract fun getLogger ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun getNewFriendRequestList ()Ljava/util/List;
|
||||
public abstract fun getNewFriendRequestList (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun getOtherClients ()Lnet/mamoe/mirai/contact/ContactList;
|
||||
public fun getStranger (J)Lnet/mamoe/mirai/contact/Stranger;
|
||||
public fun getStrangerOrFail (J)Lnet/mamoe/mirai/contact/Stranger;
|
||||
@ -137,6 +139,8 @@ public abstract interface annotation class net/mamoe/mirai/LowLevelApi : java/la
|
||||
public abstract interface class net/mamoe/mirai/LowLevelApiAccessor {
|
||||
public fun getGroupVoiceDownloadUrl (Lnet/mamoe/mirai/Bot;[BJJ)Ljava/lang/String;
|
||||
public abstract fun getGroupVoiceDownloadUrl (Lnet/mamoe/mirai/Bot;[BJJLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getNewFriendRequestList (Lnet/mamoe/mirai/Bot;)Ljava/util/List;
|
||||
public abstract fun getNewFriendRequestList (Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getRawGroupList (Lnet/mamoe/mirai/Bot;)Lkotlin/sequences/Sequence;
|
||||
public abstract fun getRawGroupList (Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getRawGroupMemberList (Lnet/mamoe/mirai/Bot;JJJ)Lkotlin/sequences/Sequence;
|
||||
|
@ -26,6 +26,8 @@ public abstract interface class net/mamoe/mirai/Bot : kotlinx/coroutines/Corouti
|
||||
public static fun getInstances ()Ljava/util/List;
|
||||
public static fun getInstancesSequence ()Lkotlin/sequences/Sequence;
|
||||
public abstract fun getLogger ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun getNewFriendRequestList ()Ljava/util/List;
|
||||
public abstract fun getNewFriendRequestList (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun getOtherClients ()Lnet/mamoe/mirai/contact/ContactList;
|
||||
public fun getStranger (J)Lnet/mamoe/mirai/contact/Stranger;
|
||||
public fun getStrangerOrFail (J)Lnet/mamoe/mirai/contact/Stranger;
|
||||
@ -137,6 +139,8 @@ public abstract interface annotation class net/mamoe/mirai/LowLevelApi : java/la
|
||||
public abstract interface class net/mamoe/mirai/LowLevelApiAccessor {
|
||||
public fun getGroupVoiceDownloadUrl (Lnet/mamoe/mirai/Bot;[BJJ)Ljava/lang/String;
|
||||
public abstract fun getGroupVoiceDownloadUrl (Lnet/mamoe/mirai/Bot;[BJJLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getNewFriendRequestList (Lnet/mamoe/mirai/Bot;)Ljava/util/List;
|
||||
public abstract fun getNewFriendRequestList (Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getRawGroupList (Lnet/mamoe/mirai/Bot;)Lkotlin/sequences/Sequence;
|
||||
public abstract fun getRawGroupList (Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getRawGroupMemberList (Lnet/mamoe/mirai/Bot;JJJ)Lkotlin/sequences/Sequence;
|
||||
|
@ -16,6 +16,7 @@ import kotlinx.coroutines.*
|
||||
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.contact.friendgroup.FriendGroups
|
||||
import net.mamoe.mirai.data.RequestEventData
|
||||
import net.mamoe.mirai.event.EventChannel
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.message.action.BotNudge
|
||||
@ -170,6 +171,13 @@ public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
|
||||
*/
|
||||
public override fun nudge(): BotNudge = BotNudge(this)
|
||||
|
||||
/**
|
||||
* 获取未处理的好友请求
|
||||
*
|
||||
* @see RequestEventData.NewFriendRequest
|
||||
* @since 2.17
|
||||
*/
|
||||
public suspend fun getNewFriendRequestList(): List<RequestEventData.NewFriendRequest>
|
||||
|
||||
/**
|
||||
* 关闭这个 [Bot], 立即取消 [Bot] 的 [SupervisorJob], 取消与这个 [Bot] 相关的所有有协程联系的任务.
|
||||
|
@ -16,6 +16,7 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.data.RequestEventData
|
||||
import net.mamoe.mirai.data.StrangerInfo
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalApi
|
||||
import net.mamoe.mirai.utils.NotStableForInheritance
|
||||
@ -196,4 +197,10 @@ public interface LowLevelApiAccessor {
|
||||
groupId: Long,
|
||||
seconds: Int,
|
||||
)
|
||||
|
||||
/**
|
||||
* 获取新好友请求列表
|
||||
*/
|
||||
@LowLevelApi
|
||||
public suspend fun getNewFriendRequestList(bot: Bot): List<RequestEventData.NewFriendRequest>
|
||||
}
|
||||
|
@ -20,12 +20,14 @@ import net.mamoe.mirai.contact.ContactList
|
||||
import net.mamoe.mirai.contact.ContactOrBot
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.contact.friendgroup.FriendGroups
|
||||
import net.mamoe.mirai.data.RequestEventData
|
||||
import net.mamoe.mirai.event.EventChannel
|
||||
import net.mamoe.mirai.event.GlobalEventChannel
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
import net.mamoe.mirai.event.events.BotReloginEvent
|
||||
import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
import net.mamoe.mirai.internal.network.components.EventDispatcher
|
||||
@ -119,6 +121,10 @@ internal class MockBotImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getNewFriendRequestList(): List<RequestEventData.NewFriendRequest> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
override fun close(cause: Throwable?) {
|
||||
|
@ -803,4 +803,11 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getNewFriendRequestList(bot: Bot): List<RequestEventData.NewFriendRequest>{
|
||||
bot.asQQAndroidBot()
|
||||
val resp = bot.network.sendAndExpect(NewContact.SystemMsgNewFriend(bot.client))
|
||||
|
||||
return resp.list
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,14 @@ package net.mamoe.mirai.internal
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.auth.AuthReason
|
||||
import net.mamoe.mirai.data.RequestEventData
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
import net.mamoe.mirai.event.events.BotReloginEvent
|
||||
import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
import net.mamoe.mirai.internal.contact.friendgroup.FriendGroupsImpl
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorageDelegate
|
||||
@ -318,6 +321,10 @@ internal open class QQAndroidBot constructor(
|
||||
},
|
||||
) // We can move the factory to configuration but this is not necessary for now.
|
||||
}
|
||||
|
||||
override suspend fun getNewFriendRequestList(): List<RequestEventData.NewFriendRequest> {
|
||||
return Mirai.getNewFriendRequestList(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun QQAndroidBot.getGroupByUinOrFail(uin: Long) =
|
||||
|
@ -171,6 +171,7 @@ internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
|
||||
is Structmsg.StructMsg -> processImpl(data)
|
||||
is RequestPushStatus -> processImpl(data)
|
||||
is DecodedNotifyMsgBody -> processImpl(data)
|
||||
is Structmsg.RspSystemMsgNew -> processImpl(data)
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,4 +184,5 @@ internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
|
||||
protected open suspend fun NoticePipelineContext.processImpl(data: RequestPushStatus) {}
|
||||
|
||||
protected open suspend fun NoticePipelineContext.processImpl(data: DecodedNotifyMsgBody) {}
|
||||
protected open suspend fun NoticePipelineContext.processImpl(data: Structmsg.RspSystemMsgNew) {}
|
||||
}
|
@ -25,12 +25,14 @@ import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
import net.mamoe.mirai.internal.network.components.ContactUpdater
|
||||
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext
|
||||
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
|
||||
import net.mamoe.mirai.internal.network.notice.decoders.DecodedNotifyMsgBody
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x44
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||
import net.mamoe.mirai.internal.utils.parseToMessageDataList
|
||||
import net.mamoe.mirai.internal.utils.toMemberInfo
|
||||
@ -38,6 +40,7 @@ import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.context
|
||||
import net.mamoe.mirai.utils.read
|
||||
import net.mamoe.mirai.utils.structureToString
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
/**
|
||||
@ -197,19 +200,26 @@ internal class GroupOrMemberListNoticeProcessor(
|
||||
// Structmsg.StructMsg
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override suspend fun NoticePipelineContext.processImpl(data: Structmsg.StructMsg) = data.msg.context {
|
||||
if (this == null) return
|
||||
override suspend fun NoticePipelineContext.processImpl(data: Structmsg.StructMsg) {
|
||||
val systemMsg = data.msg ?: return
|
||||
if (attributes[NewContact.SYSTEM_MSG_TYPE] != 1) return
|
||||
|
||||
if (data.msgTime <= bot.syncController.latestMsgNewGroupTime) return
|
||||
if (!bot.syncController.syncNewGroup(data.msgSeq, data.msgTime)) return // duplicate
|
||||
|
||||
markAsConsumed()
|
||||
when (subType) {
|
||||
var consumed = true
|
||||
|
||||
when (systemMsg.subType) {
|
||||
0 -> {
|
||||
if (groupMsgType == 8) {
|
||||
if (systemMsg.groupMsgType == 8) {
|
||||
// #1388: 使用手机TIM邀请入群,我为管理员,成功邀请 bot 入群
|
||||
|
||||
// 能正常解析 BotInvitedJoinGroupRequestEvent 和 BotJoinGroupEvent.Active, 因此忽略该通知
|
||||
return
|
||||
} else {
|
||||
throw contextualBugReportException(
|
||||
"解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=$groupMsgType",
|
||||
"解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=${systemMsg.groupMsgType}",
|
||||
data.structureToString(),
|
||||
null,
|
||||
"并描述此时机器人是否被邀请加入群等其他",
|
||||
@ -218,26 +228,27 @@ internal class GroupOrMemberListNoticeProcessor(
|
||||
}
|
||||
|
||||
// 处理被邀请入群 或 处理成员入群申请
|
||||
1 -> when (groupMsgType) {
|
||||
1 -> when (systemMsg.groupMsgType) {
|
||||
1 -> {
|
||||
// 成员申请入群
|
||||
collected += MemberJoinRequestEvent(
|
||||
bot, data.msgSeq, msgAdditional,
|
||||
data.reqUin, groupCode, groupName, reqUinNick
|
||||
bot, data.msgSeq, systemMsg.msgAdditional,
|
||||
data.reqUin, systemMsg.groupCode, systemMsg.groupName, systemMsg.reqUinNick
|
||||
)
|
||||
}
|
||||
2 -> {
|
||||
// Bot 被邀请入群
|
||||
collected += BotInvitedJoinGroupRequestEvent(
|
||||
bot, data.msgSeq, actionUin,
|
||||
groupCode, groupName, actionUinNick
|
||||
bot, data.msgSeq, systemMsg.actionUin,
|
||||
systemMsg.groupCode, systemMsg.groupName, systemMsg.actionUinNick
|
||||
)
|
||||
}
|
||||
22 -> {
|
||||
// 成员邀请入群
|
||||
collected += MemberJoinRequestEvent(
|
||||
bot, data.msgSeq, msgAdditional,
|
||||
data.reqUin, groupCode, groupName, reqUinNick, actionUin
|
||||
bot, data.msgSeq, systemMsg.msgAdditional,
|
||||
data.reqUin, systemMsg.groupCode, systemMsg.groupName,
|
||||
systemMsg.reqUinNick, systemMsg.actionUin
|
||||
)
|
||||
}
|
||||
else -> throw contextualBugReportException(
|
||||
@ -256,8 +267,8 @@ internal class GroupOrMemberListNoticeProcessor(
|
||||
3 -> { // 已被请他管理员处理
|
||||
}
|
||||
5 -> {
|
||||
val group = bot.getGroup(groupCode) ?: return
|
||||
when (groupMsgType) {
|
||||
val group = bot.getGroup(systemMsg.groupCode) ?: return
|
||||
when (systemMsg.groupMsgType) {
|
||||
3 -> {
|
||||
// https://github.com/mamoe/mirai/issues/651
|
||||
// msgDescribe=将你设置为管理员
|
||||
@ -268,7 +279,7 @@ internal class GroupOrMemberListNoticeProcessor(
|
||||
// 但无法获取是哪个成员.
|
||||
}
|
||||
7 -> { // 机器人被踢
|
||||
val operator = group[actionUin] ?: return
|
||||
val operator = group[systemMsg.actionUin] ?: return
|
||||
collected += BotLeaveEvent.Kick(operator)
|
||||
}
|
||||
6 -> {
|
||||
@ -284,7 +295,7 @@ internal class GroupOrMemberListNoticeProcessor(
|
||||
}
|
||||
else -> {
|
||||
throw contextualBugReportException(
|
||||
"解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=$groupMsgType",
|
||||
"解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=${systemMsg.groupMsgType}",
|
||||
this.structureToString(),
|
||||
null,
|
||||
"并描述此时机器人是否被踢出群等",
|
||||
@ -292,7 +303,15 @@ internal class GroupOrMemberListNoticeProcessor(
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> markNotConsumed()
|
||||
else -> {
|
||||
consumed = false
|
||||
markNotConsumed()
|
||||
}
|
||||
}
|
||||
|
||||
if (consumed) {
|
||||
val latestTime = bot.syncController.latestMsgNewGroupTime
|
||||
bot.syncController.latestMsgNewGroupTime = max(latestTime, data.msgTime)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,11 +21,13 @@ import net.mamoe.mirai.internal.contact.toMiraiFriendInfo
|
||||
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext.Companion.msgInfo
|
||||
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
|
||||
import net.mamoe.mirai.internal.network.notice.NewContactSupport
|
||||
import net.mamoe.mirai.internal.network.notice.group.get
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.FrdSysMsg
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x115.SubMsgType0x115
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x122
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27.SubMsgType0x27.*
|
||||
@ -36,10 +38,12 @@ import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList.GetFrien
|
||||
import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* All [FriendEvent] except [FriendMessageEvent]
|
||||
* All [FriendEvent] except [FriendMessageEvent], plus [NewFriendRequestEvent]
|
||||
*
|
||||
* @see NewFriendRequestEvent
|
||||
* @see FriendInputStatusChangedEvent
|
||||
* @see FriendAddEvent
|
||||
* @see StrangerRelationChangeEvent.Friended
|
||||
@ -142,6 +146,27 @@ internal class FriendNoticeProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun NoticePipelineContext.processImpl(data: Structmsg.StructMsg) {
|
||||
val systemMsg = data.msg ?: return
|
||||
if (attributes[NewContact.SYSTEM_MSG_TYPE] != 0) return
|
||||
markAsConsumed()
|
||||
|
||||
if (data.msgTime <= bot.syncController.latestMsgNewFriendTime) return
|
||||
if (!bot.syncController.syncNewFriend(data.msgSeq, data.msgTime)) return // duplicate
|
||||
|
||||
collected += NewFriendRequestEvent(
|
||||
bot,
|
||||
data.msgSeq,
|
||||
systemMsg.msgAdditional,
|
||||
data.reqUin,
|
||||
systemMsg.groupCode,
|
||||
systemMsg.reqUinNick,
|
||||
)
|
||||
|
||||
val latestTime = bot.syncController.latestMsgNewFriendTime
|
||||
bot.syncController.latestMsgNewFriendTime = max(latestTime, data.msgTime)
|
||||
}
|
||||
|
||||
|
||||
@Serializable
|
||||
private class Wording(
|
||||
|
@ -137,6 +137,7 @@ internal class Structmsg : ProtoBuf {
|
||||
@ProtoNumber(8) @JvmField val isGetFrdRibbon: Boolean = true,
|
||||
@ProtoNumber(9) @JvmField val isGetGrpRibbon: Boolean = true,
|
||||
@ProtoNumber(10) @JvmField val friendMsgTypeFlag: Long = 0L,
|
||||
@ProtoNumber(11) @JvmField val reqMsgType: Int = 0
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
|
@ -12,12 +12,11 @@
|
||||
package net.mamoe.mirai.internal.network.protocol.packet.chat
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
import net.mamoe.mirai.data.RequestEventData
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
|
||||
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
|
||||
@ -25,12 +24,13 @@ import net.mamoe.mirai.internal.network.toPacket
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
||||
import kotlin.math.max
|
||||
import net.mamoe.mirai.utils.TypeKey
|
||||
import net.mamoe.mirai.utils.buildTypeSafeMap
|
||||
|
||||
internal class NewContact {
|
||||
|
||||
internal object SystemMsgNewFriend :
|
||||
OutgoingPacketFactory<Packet>("ProfileService.Pb.ReqSystemMsgNew.Friend") {
|
||||
OutgoingPacketFactory<SystemMsgNewFriend.Response>("ProfileService.Pb.ReqSystemMsgNew.Friend") {
|
||||
|
||||
operator fun invoke(client: QQAndroidClient) = buildOutgoingUniPacket(client) {
|
||||
writeProtoBuf(
|
||||
@ -49,35 +49,30 @@ internal class NewContact {
|
||||
isGetGrpRibbon = false,
|
||||
msgNum = 20,
|
||||
version = 1000,
|
||||
reqMsgType = 2,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
internal class Response(val list: List<RequestEventData.NewFriendRequest>) : Packet
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet {
|
||||
readProtoBuf(Structmsg.RspSystemMsgNew.serializer()).run {
|
||||
return friendmsgs.filter {
|
||||
it.msgTime >= bot.syncController.latestMsgNewFriendTime
|
||||
}.mapNotNull { struct ->
|
||||
if (!bot.syncController.syncNewFriend(struct.msgSeq, struct.msgTime)) { // duplicate
|
||||
return@mapNotNull null
|
||||
}
|
||||
struct.msg?.run {
|
||||
NewFriendRequestEvent(
|
||||
bot,
|
||||
struct.msgSeq,
|
||||
msgAdditional,
|
||||
struct.reqUin,
|
||||
groupCode,
|
||||
reqUinNick,
|
||||
)
|
||||
}
|
||||
}.toPacket().also {
|
||||
bot.syncController.run {
|
||||
latestMsgNewFriendTime = max(latestMsgNewFriendTime, friendmsgs.maxOfOrNull { it.msgTime } ?: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||
val resp = readProtoBuf(Structmsg.RspSystemMsgNew.serializer())
|
||||
|
||||
return resp.friendmsgs.map { struct ->
|
||||
bot.processPacketThroughPipeline(struct, buildTypeSafeMap { set(SYSTEM_MSG_TYPE, 0) })
|
||||
|
||||
val systemMsg = struct.msg ?: return@map null
|
||||
if (systemMsg.actions.size < 2) return@map null // 只返回可以操作的(同意或拒绝好友请求)
|
||||
|
||||
RequestEventData.NewFriendRequest(
|
||||
struct.msgSeq,
|
||||
struct.reqUin,
|
||||
systemMsg.reqUinNick,
|
||||
systemMsg.groupCode,
|
||||
systemMsg.msgAdditional,
|
||||
)
|
||||
}.filterNotNull().let { Response(it) }
|
||||
}
|
||||
|
||||
internal object Action : OutgoingPacketFactory<Nothing?>("ProfileService.Pb.ReqSystemMsgAction.Friend") {
|
||||
@ -152,20 +147,11 @@ internal class NewContact {
|
||||
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet {
|
||||
return readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run {
|
||||
groupmsgs.filter {
|
||||
it.msgTime >= bot.syncController.latestMsgNewGroupTime
|
||||
}.mapNotNull { struct ->
|
||||
if (!bot.syncController.syncNewGroup(struct.msgSeq, struct.msgTime)) { // duplicate
|
||||
return@mapNotNull null
|
||||
}
|
||||
bot.processPacketThroughPipeline(struct)
|
||||
}.toPacket().also {
|
||||
bot.syncController.run {
|
||||
latestMsgNewGroupTime = max(latestMsgNewGroupTime, groupmsgs.maxOfOrNull { it.msgTime } ?: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
val resp = readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer())
|
||||
|
||||
return resp.groupmsgs.map { struct ->
|
||||
bot.processPacketThroughPipeline(struct, buildTypeSafeMap { set(SYSTEM_MSG_TYPE, 1) })
|
||||
}.toPacket()
|
||||
}
|
||||
|
||||
internal object Action : OutgoingPacketFactory<Nothing?>("ProfileService.Pb.ReqSystemMsgAction.Group") {
|
||||
@ -179,8 +165,7 @@ internal class NewContact {
|
||||
accept: Boolean?,
|
||||
blackList: Boolean = false,
|
||||
message: String = "",
|
||||
) =
|
||||
buildOutgoingUniPacket(client) {
|
||||
) = buildOutgoingUniPacket(client) {
|
||||
writeProtoBuf(
|
||||
Structmsg.ReqSystemMsgAction.serializer(),
|
||||
Structmsg.ReqSystemMsgAction(
|
||||
@ -209,4 +194,11 @@ internal class NewContact {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot) = null
|
||||
}
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
/**
|
||||
* friend = 0, group = 1
|
||||
*/
|
||||
internal val SYSTEM_MSG_TYPE = TypeKey<Int>("SystemMsgType")
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ import net.mamoe.mirai.utils.*
|
||||
* To add breakpoint, see [NoticeProcessorPipelineImpl.process]
|
||||
*/
|
||||
internal abstract class AbstractNoticeProcessorTest : AbstractCommonNHTest(), GroupExtensions {
|
||||
var mockTime = currentTimeSeconds()
|
||||
|
||||
init {
|
||||
setSystemProp("mirai.network.notice.pipeline.log.full", "true")
|
||||
}
|
||||
|
@ -16,7 +16,10 @@ import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.GroupImpl
|
||||
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipelineImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.buildTypeSafeMap
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
@ -24,13 +27,15 @@ import kotlin.test.assertIs
|
||||
internal class BotInvitedJoinTest : AbstractNoticeProcessorTest() {
|
||||
@Test
|
||||
fun `invited join`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
|
||||
suspend fun runTest() = use(
|
||||
attributes = buildTypeSafeMap { set(NewContact.SYSTEM_MSG_TYPE, 1) }
|
||||
) {
|
||||
mockTime += 1000
|
||||
Structmsg.StructMsg(
|
||||
version = 1,
|
||||
msgType = 2,
|
||||
msgSeq = 1630,
|
||||
msgTime = 1630,
|
||||
msgSeq = mockTime * 1000,
|
||||
msgTime = mockTime,
|
||||
reqUin = 1230,
|
||||
msg = Structmsg.SystemMsg(
|
||||
subType = 1,
|
||||
@ -81,6 +86,7 @@ internal class BotInvitedJoinTest : AbstractNoticeProcessorTest() {
|
||||
c2cInviteJoinGroupFlag = 1,
|
||||
),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
setBot(1230003)
|
||||
@ -93,7 +99,7 @@ internal class BotInvitedJoinTest : AbstractNoticeProcessorTest() {
|
||||
assertEquals("user1", invitorNick)
|
||||
assertEquals(2230203, groupId)
|
||||
assertEquals("testtest", groupName)
|
||||
assertEquals(1630, eventId)
|
||||
assertEquals(mockTime * 1000, eventId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,19 +13,25 @@ import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.MemberJoinEvent
|
||||
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.buildTypeSafeMap
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import kotlin.test.*
|
||||
|
||||
internal class MemberJoinTest : AbstractNoticeProcessorTest() {
|
||||
|
||||
@Test
|
||||
fun `member actively request join`() = runBlockingUnit {
|
||||
suspend fun runTest() = use {
|
||||
suspend fun runTest() = use(
|
||||
attributes = buildTypeSafeMap { set(NewContact.SYSTEM_MSG_TYPE, 1) }
|
||||
) {
|
||||
mockTime += 1000
|
||||
Structmsg.StructMsg(
|
||||
version = 1,
|
||||
msgType = 2,
|
||||
msgSeq = 16300,
|
||||
msgTime = 1630,
|
||||
msgSeq = mockTime * 1000,
|
||||
msgTime = mockTime,
|
||||
reqUin = 1230001,
|
||||
msg = Structmsg.SystemMsg(
|
||||
subType = 1,
|
||||
|
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright 2019-2023 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.notice.processors
|
||||
|
||||
import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
|
||||
import net.mamoe.mirai.internal.test.runBlockingUnit
|
||||
import net.mamoe.mirai.utils.buildTypeSafeMap
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
|
||||
internal class NewFriendRequestTest : AbstractNoticeProcessorTest() {
|
||||
@Test
|
||||
fun `new friend request from search test`() = runBlockingUnit {
|
||||
|
||||
setBot(114514)
|
||||
|
||||
use(attributes = buildTypeSafeMap { set(NewContact.SYSTEM_MSG_TYPE, 0) }) {
|
||||
mockTime += 1000
|
||||
Structmsg.StructMsg(
|
||||
version = 1,
|
||||
msgType = 2,
|
||||
msgSeq = mockTime * 1000,
|
||||
msgTime = mockTime,
|
||||
reqUin = 123456,
|
||||
unreadFlag = 0,
|
||||
msg = Structmsg.SystemMsg(
|
||||
subType = 1,
|
||||
msgTitle = "好友申请",
|
||||
msgDescribe = "请求加为好友",
|
||||
msgAdditional = "我是颠佬",
|
||||
msgSource = "QQ群",
|
||||
msgDecided = "",
|
||||
srcId = 3004,
|
||||
subSrcId = 2,
|
||||
groupCode = 1,
|
||||
actionUin = 0,
|
||||
groupMsgType = 0,
|
||||
groupInviterRole = 0,
|
||||
friendInfo = Structmsg.FriendInfo(
|
||||
msgJointFriend = "1 个共同好友",
|
||||
msgBlacklist = "设为黑名单后你将拒绝对方,并不再接收此人请求。"
|
||||
),
|
||||
groupInfo = null,
|
||||
actorUin = 0,
|
||||
msgActorDescribe = "",
|
||||
msgAdditionalList = "",
|
||||
relation = 0,
|
||||
reqsubtype = 0,
|
||||
cloneUin = 0,
|
||||
discussUin = 0,
|
||||
eimGroupId = 0,
|
||||
msgInviteExtinfo = null,
|
||||
msgPayGroupExtinfo = null,
|
||||
sourceFlag = 1,
|
||||
gameNick = byteArrayOf(),
|
||||
gameMsg = byteArrayOf(),
|
||||
groupFlagext3 = 0,
|
||||
groupOwnerUin = 0,
|
||||
doubtFlag = 0,
|
||||
warningTips = byteArrayOf(),
|
||||
nameMore = byteArrayOf(),
|
||||
reqUinFaceid = 21762,
|
||||
reqUinNick = "颠佬",
|
||||
groupName = "",
|
||||
actionUinNick = "",
|
||||
msgQna = "",
|
||||
msgDetail = "",
|
||||
groupExtFlag = 0,
|
||||
actorUinNick = "",
|
||||
picUrl = "",
|
||||
cloneUinNick = "",
|
||||
reqUinBusinessCard = "",
|
||||
eimGroupIdName = "",
|
||||
reqUinPreRemark = "",
|
||||
actionUinQqNick = "",
|
||||
actionUinRemark = "",
|
||||
reqUinGender = 255,
|
||||
reqUinAge = 0,
|
||||
c2cInviteJoinGroupFlag = 0,
|
||||
cardSwitch = 0,
|
||||
actions = listOf(
|
||||
Structmsg.SystemMsgAction(
|
||||
name = "同意",
|
||||
result = "已同意",
|
||||
action = 1,
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 2,
|
||||
groupCode = 0,
|
||||
sig = byteArrayOf(),
|
||||
msg = "",
|
||||
groupId = 0,
|
||||
remark = "",
|
||||
blacklist = false,
|
||||
addFrdSNInfo = null
|
||||
),
|
||||
detailName = "同意"
|
||||
),
|
||||
Structmsg.SystemMsgAction(
|
||||
name = "拒绝",
|
||||
result = "已拒绝",
|
||||
action = 1,
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 3,
|
||||
groupCode = 0,
|
||||
sig = byteArrayOf(),
|
||||
msg = "",
|
||||
groupId = 0,
|
||||
remark = "",
|
||||
blacklist = false,
|
||||
addFrdSNInfo = null
|
||||
),
|
||||
detailName = "拒绝"
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
}.run {
|
||||
assertEquals(1, size, toString())
|
||||
val event = single()
|
||||
assertIs<NewFriendRequestEvent>(event)
|
||||
|
||||
assertEquals(123456, event.fromId)
|
||||
assertEquals("颠佬", event.fromNick)
|
||||
}
|
||||
}@Test
|
||||
fun `new friend request test`() = runBlockingUnit {
|
||||
|
||||
setBot(114514)
|
||||
|
||||
use(attributes = buildTypeSafeMap { set(NewContact.SYSTEM_MSG_TYPE, 0) }) {
|
||||
mockTime += 1000
|
||||
Structmsg.StructMsg(
|
||||
version = 1,
|
||||
msgType = 1,
|
||||
msgSeq = mockTime * 1000,
|
||||
msgTime = mockTime,
|
||||
reqUin = 654321,
|
||||
unreadFlag = 0,
|
||||
msg = Structmsg.SystemMsg(
|
||||
subType = 1,
|
||||
msgTitle = "好友申请",
|
||||
msgDescribe = "请求加为好友1",
|
||||
msgAdditional = "",
|
||||
msgSource = "QQ群-%group_name%",
|
||||
msgDecided = "",
|
||||
srcId = 6,
|
||||
subSrcId = 2,
|
||||
groupCode = 111111,
|
||||
actionUin = 0,
|
||||
groupMsgType = 0,
|
||||
groupInviterRole = 0,
|
||||
friendInfo = Structmsg.FriendInfo(
|
||||
msgJointFriend = "2 个共同好友",
|
||||
msgBlacklist = "设为黑名单后你将拒绝对方,并不再接收此人请求。"
|
||||
),
|
||||
groupInfo = Structmsg.GroupInfo(
|
||||
groupAuthType = 0,
|
||||
displayAction = 0,
|
||||
msgAlert = "",
|
||||
msgDetailAlert = "",
|
||||
msgOtherAdminDone = "",
|
||||
appPrivilegeFlag = 67633344
|
||||
),
|
||||
actorUin = 0,
|
||||
msgActorDescribe = "",
|
||||
msgAdditionalList = "",
|
||||
relation = 0,
|
||||
reqsubtype = 0,
|
||||
cloneUin = 0,
|
||||
discussUin = 0,
|
||||
eimGroupId = 0,
|
||||
msgInviteExtinfo = null,
|
||||
msgPayGroupExtinfo = null,
|
||||
sourceFlag = 1,
|
||||
gameNick = byteArrayOf(),
|
||||
gameMsg = byteArrayOf(),
|
||||
groupFlagext3 = 0,
|
||||
groupOwnerUin = 0,
|
||||
doubtFlag = 0,
|
||||
warningTips = byteArrayOf(),
|
||||
nameMore = byteArrayOf(),
|
||||
reqUinFaceid = 0,
|
||||
reqUinNick = "颠佬2",
|
||||
groupName = "%group_name%",
|
||||
actionUinNick = "",
|
||||
msgQna = "",
|
||||
msgDetail = "",
|
||||
groupExtFlag = 1076036672,
|
||||
actorUinNick = "",
|
||||
picUrl = "",
|
||||
cloneUinNick = "",
|
||||
reqUinBusinessCard = "",
|
||||
eimGroupIdName = "",
|
||||
reqUinPreRemark = "",
|
||||
actionUinQqNick = "",
|
||||
actionUinRemark = "",
|
||||
reqUinGender = 0,
|
||||
reqUinAge = 0,
|
||||
c2cInviteJoinGroupFlag = 0,
|
||||
cardSwitch = 0,
|
||||
actions = listOf(
|
||||
Structmsg.SystemMsgAction(
|
||||
name = "同意",
|
||||
result = "已同意",
|
||||
action = 1,
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 2,
|
||||
groupCode = 0,
|
||||
sig = byteArrayOf(),
|
||||
msg = "",
|
||||
groupId = 0,
|
||||
remark = "",
|
||||
blacklist = false,
|
||||
addFrdSNInfo = null
|
||||
),
|
||||
detailName = "同意"
|
||||
),
|
||||
Structmsg.SystemMsgAction(
|
||||
name = "拒绝",
|
||||
result = "已拒绝",
|
||||
action = 1,
|
||||
actionInfo = Structmsg.SystemMsgActionInfo(
|
||||
type = 3,
|
||||
groupCode = 0,
|
||||
sig = byteArrayOf(),
|
||||
msg = "",
|
||||
groupId = 0,
|
||||
remark = "",
|
||||
blacklist = false,
|
||||
addFrdSNInfo = null
|
||||
),
|
||||
detailName = "拒绝"
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
}.run {
|
||||
assertEquals(1, size, toString())
|
||||
val event = single()
|
||||
assertIs<NewFriendRequestEvent>(event)
|
||||
|
||||
assertEquals(654321, event.fromId)
|
||||
assertEquals("颠佬2", event.fromNick)
|
||||
assertEquals(111111, event.fromGroupId)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user