1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-24 20:43:33 +08:00
This commit is contained in:
StageGuard 2024-09-23 12:26:06 +01:00 committed by GitHub
commit 73006fdf88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 426 additions and 70 deletions
mirai-core-api
compatibility-validation
android/api
jvm/api
src/commonMain/kotlin
mirai-core-mock/src/internal
mirai-core/src

View File

@ -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;

View File

@ -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;

View File

@ -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] 相关的所有有协程联系的任务.

View File

@ -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>
}

View File

@ -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?) {

View File

@ -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
}
}

View File

@ -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) =

View File

@ -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) {}
}

View File

@ -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)
}
}

View File

@ -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(

View File

@ -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

View File

@ -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")
}
}

View File

@ -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")
}

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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)
}
}
}