Migrate more transformers to NoticeProcessorPipeline

This commit is contained in:
Him188 2021-08-13 18:53:51 +08:00
parent e097c5ab9d
commit edf1bc9a2e
21 changed files with 427 additions and 272 deletions

View File

@ -12,9 +12,9 @@
import org.gradle.api.JavaVersion import org.gradle.api.JavaVersion
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.testing.Test import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
@ -144,7 +144,9 @@ val experimentalAnnotations = arrayOf(
"net.mamoe.mirai.message.data.ExperimentalMessageKey", "net.mamoe.mirai.message.data.ExperimentalMessageKey",
"net.mamoe.mirai.console.ConsoleFrontEndImplementation", "net.mamoe.mirai.console.ConsoleFrontEndImplementation",
"net.mamoe.mirai.console.util.ConsoleInternalApi", "net.mamoe.mirai.console.util.ConsoleInternalApi",
"net.mamoe.mirai.console.util.ConsoleExperimentalApi" "net.mamoe.mirai.console.util.ConsoleExperimentalApi",
"kotlinx.io.core.internal.DangerousInternalIoApi",
) )
fun Project.configureKotlinExperimentalUsages() { fun Project.configureKotlinExperimentalUsages() {

View File

@ -109,4 +109,7 @@ public fun String.truncated(length: Int, truncated: String = "..."): String {
public inline fun <T> T.context(block: T.() -> Unit) { public inline fun <T> T.context(block: T.() -> Unit) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return block() return block()
} }
public fun assertUnreachable(hint: String? = null): Nothing =
error("This clause should not be reached. " + hint.orEmpty())

View File

@ -37,8 +37,15 @@ import net.mamoe.mirai.internal.network.handler.state.StateObserver
import net.mamoe.mirai.internal.network.handler.state.safe import net.mamoe.mirai.internal.network.handler.state.safe
import net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException import net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException
import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandlerFactory import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandlerFactory
import net.mamoe.mirai.internal.network.notice.* import net.mamoe.mirai.internal.network.notice.UnconsumedNoticesAlerter
import net.mamoe.mirai.internal.network.notice.decoders.GroupNotificationDecoder
import net.mamoe.mirai.internal.network.notice.decoders.MsgInfoDecoder import net.mamoe.mirai.internal.network.notice.decoders.MsgInfoDecoder
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor
import net.mamoe.mirai.internal.network.notice.group.GroupOrMemberListNoticeProcessor
import net.mamoe.mirai.internal.network.notice.group.GroupRecallProcessor
import net.mamoe.mirai.internal.network.notice.priv.FriendNoticeProcessor
import net.mamoe.mirai.internal.network.notice.priv.OtherClientNoticeProcessor
import net.mamoe.mirai.internal.network.notice.priv.PrivateMessageNoticeProcessor
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.internal.utils.subLogger import net.mamoe.mirai.internal.utils.subLogger
import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.BotConfiguration
@ -156,13 +163,16 @@ internal open class QQAndroidBot constructor(
set( set(
NoticeProcessorPipeline, NoticeProcessorPipeline,
NoticeProcessorPipelineImpl.create( NoticeProcessorPipelineImpl.create(
MsgInfoDecoder(pipelineLogger), MsgInfoDecoder(pipelineLogger.subLogger("MsgInfoDecoder")),
FriendNoticeProcessor(pipelineLogger), GroupNotificationDecoder(),
GroupListNoticeProcessor(pipelineLogger),
GroupMessageProcessor(), FriendNoticeProcessor(pipelineLogger.subLogger("FriendNoticeProcessor")),
GroupOrMemberListNoticeProcessor(pipelineLogger.subLogger("GroupOrMemberListNoticeProcessor")),
GroupMessageProcessor(pipelineLogger.subLogger("GroupMessageProcessor")),
PrivateMessageNoticeProcessor(), PrivateMessageNoticeProcessor(),
OtherClientNoticeProcessor(), OtherClientNoticeProcessor(),
UnconsumedNoticesAlerter(pipelineLogger), UnconsumedNoticesAlerter(pipelineLogger.subLogger("UnconsumedNoticesAlerter")),
GroupRecallProcessor()
) )
) )

View File

@ -16,7 +16,7 @@ import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
import net.mamoe.mirai.utils.cast import net.mamoe.mirai.utils.cast
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
internal abstract class AbstractMember( internal sealed class AbstractMember(
final override val group: GroupImpl, final override val group: GroupImpl,
parentCoroutineContext: CoroutineContext, parentCoroutineContext: CoroutineContext,
memberInfo: MemberInfo, memberInfo: MemberInfo,

View File

@ -57,7 +57,7 @@ internal val User.correspondingMessageSourceKind
else -> error("Unknown user: ${this::class.qualifiedName}") else -> error("Unknown user: ${this::class.qualifiedName}")
} }
internal abstract class AbstractUser( internal sealed class AbstractUser(
bot: QQAndroidBot, bot: QQAndroidBot,
parentCoroutineContext: CoroutineContext, parentCoroutineContext: CoroutineContext,
userInfo: UserInfo, userInfo: UserInfo,

View File

@ -14,16 +14,14 @@ import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async import kotlinx.coroutines.async
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.nextEventOrNull import net.mamoe.mirai.event.nextEventOrNull
import net.mamoe.mirai.internal.MiraiImpl
import net.mamoe.mirai.internal.asQQAndroidBot import net.mamoe.mirai.internal.asQQAndroidBot
import net.mamoe.mirai.internal.getMiraiImpl import net.mamoe.mirai.internal.getMiraiImpl
import net.mamoe.mirai.internal.message.* import net.mamoe.mirai.internal.message.*
import net.mamoe.mirai.internal.message.LightMessageRefiner.refineLight
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.components.MessageSvcSyncer import net.mamoe.mirai.internal.network.components.MessageSvcSyncer
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.notice.GroupMessageProcessor.SendGroupMessageReceipt import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.SendGroupMessageReceipt
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement

View File

@ -28,6 +28,10 @@ import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.asQQAndroidBot import net.mamoe.mirai.internal.asQQAndroidBot
import net.mamoe.mirai.internal.contact.GroupImpl import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.contact.OnlineAnnouncementImpl import net.mamoe.mirai.internal.contact.OnlineAnnouncementImpl
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.deleteGroupAnnouncement
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.getGroupAnnouncement
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.getRawGroupAnnouncements
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.sendGroupAnnouncement
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.toAnnouncement import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.toAnnouncement
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.toGroupAnnouncement import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.toGroupAnnouncement
import net.mamoe.mirai.internal.network.highway.ChannelKind import net.mamoe.mirai.internal.network.highway.ChannelKind
@ -37,6 +41,8 @@ import net.mamoe.mirai.internal.network.psKey
import net.mamoe.mirai.internal.network.sKey import net.mamoe.mirai.internal.network.sKey
import net.mamoe.mirai.internal.utils.io.writeResource import net.mamoe.mirai.internal.utils.io.writeResource
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.Either.Companion.onLeft
import net.mamoe.mirai.utils.Either.Companion.rightOrNull
import java.util.stream.Stream import java.util.stream.Stream
internal class AnnouncementsImpl( internal class AnnouncementsImpl(

View File

@ -20,7 +20,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.Mirai import net.mamoe.mirai.Mirai
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.asyncFromEventOrNull import net.mamoe.mirai.event.asyncFromEventOrNull
import net.mamoe.mirai.internal.network.notice.GroupMessageProcessor.SendGroupMessageReceipt import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.SendGroupMessageReceipt
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg

View File

@ -15,6 +15,7 @@ import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.ParseErrorPacket import net.mamoe.mirai.internal.network.ParseErrorPacket
import net.mamoe.mirai.internal.network.component.ComponentKey import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.component.ComponentStorage import net.mamoe.mirai.internal.network.component.ComponentStorage
import net.mamoe.mirai.internal.network.notice.decoders.DecodedNotifyMsgBody
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210 import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus
@ -32,7 +33,6 @@ import net.mamoe.mirai.utils.toDebugString
import net.mamoe.mirai.utils.uncheckedCast import net.mamoe.mirai.utils.uncheckedCast
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.CopyOnWriteArrayList
import kotlin.reflect.KClass import kotlin.reflect.KClass
internal typealias ProcessResult = Collection<Packet> internal typealias ProcessResult = Collection<Packet>
@ -98,8 +98,8 @@ internal interface PipelineContext {
val collected: MutableProcessResult val collected: MutableProcessResult
// DSL to simplify some expressions // DSL to simplify some expressions
operator fun MutableProcessResult.plusAssign(packet: Packet) { operator fun MutableProcessResult.plusAssign(packet: Packet?) {
collect(packet) if (packet != null) collect(packet)
} }
@ -114,11 +114,11 @@ internal interface PipelineContext {
fun collect(packets: Iterable<Packet>) fun collect(packets: Iterable<Packet>)
/** /**
* Fire the [data] into the processor pipeline. * Fire the [data] into the processor pipeline, and collect the results to current [collected].
* *
* @return result collected from processors. This would also have been collected to this context (where you call [fire]). * @return result collected from processors. This would also have been collected to this context (where you call [processAlso]).
*/ */
suspend fun fire(data: ProtocolStruct): ProcessResult suspend fun processAlso(data: ProtocolStruct): ProcessResult
companion object { companion object {
val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync") val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync")
@ -129,7 +129,10 @@ internal interface PipelineContext {
internal inline val PipelineContext.context get() = this internal inline val PipelineContext.context get() = this
internal open class NoticeProcessorPipelineImpl private constructor() : NoticeProcessorPipeline { internal open class NoticeProcessorPipelineImpl private constructor() : NoticeProcessorPipeline {
private val processors = CopyOnWriteArrayList<NoticeProcessor>() /**
* Must be ordered
*/
private val processors = ConcurrentLinkedQueue<NoticeProcessor>()
override fun registerProcessor(processor: NoticeProcessor) { override fun registerProcessor(processor: NoticeProcessor) {
processors.add(processor) processors.add(processor)
@ -141,7 +144,7 @@ internal open class NoticeProcessorPipelineImpl private constructor() : NoticePr
) : PipelineContext { ) : PipelineContext {
private val consumers: Stack<NoticeProcessor> = Stack() private val consumers: Stack<NoticeProcessor> = Stack()
override val isConsumed: Boolean = consumers.isNotEmpty() override val isConsumed: Boolean get() = consumers.isNotEmpty()
override fun NoticeProcessor.markAsConsumed() { override fun NoticeProcessor.markAsConsumed() {
consumers.push(this) consumers.push(this)
} }
@ -162,7 +165,7 @@ internal open class NoticeProcessorPipelineImpl private constructor() : NoticePr
this.collected.data.addAll(packets) this.collected.data.addAll(packets)
} }
override suspend fun fire(data: ProtocolStruct): ProcessResult { override suspend fun processAlso(data: ProtocolStruct): ProcessResult {
return process(bot, data, attributes) return process(bot, data, attributes)
} }
} }
@ -193,7 +196,6 @@ internal open class NoticeProcessorPipelineImpl private constructor() : NoticePr
companion object { companion object {
fun createEmpty(): NoticeProcessorPipelineImpl = NoticeProcessorPipelineImpl()
fun create(vararg processors: NoticeProcessor): NoticeProcessorPipelineImpl = fun create(vararg processors: NoticeProcessor): NoticeProcessorPipelineImpl =
NoticeProcessorPipelineImpl().apply { NoticeProcessorPipelineImpl().apply {
for (processor in processors) { for (processor in processors) {
@ -214,9 +216,9 @@ internal interface NoticeProcessor {
suspend fun process(context: PipelineContext, data: Any?) suspend fun process(context: PipelineContext, data: Any?)
} }
internal abstract class AnyNoticeProcessor : SimpleNoticeProcessor<Any>(type()) internal abstract class AnyNoticeProcessor : SimpleNoticeProcessor<ProtocolStruct>(type())
internal abstract class SimpleNoticeProcessor<T : Any>( internal abstract class SimpleNoticeProcessor<in T : ProtocolStruct>(
private val type: KClass<T>, private val type: KClass<T>,
) : NoticeProcessor { ) : NoticeProcessor {
@ -239,7 +241,7 @@ internal abstract class MsgCommonMsgProcessor : SimpleNoticeProcessor<MsgComm.Ms
} }
internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() { internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
final override suspend fun PipelineContext.processImpl(data: Any) { final override suspend fun PipelineContext.processImpl(data: ProtocolStruct) {
when (data) { when (data) {
is PbMsgInfo -> processImpl(data) is PbMsgInfo -> processImpl(data)
is MsgOnlinePush.PbPushMsg -> processImpl(data) is MsgOnlinePush.PbPushMsg -> processImpl(data)
@ -248,6 +250,7 @@ internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
is MsgType0x2DC -> processImpl(data) is MsgType0x2DC -> processImpl(data)
is Structmsg.StructMsg -> processImpl(data) is Structmsg.StructMsg -> processImpl(data)
is RequestPushStatus -> processImpl(data) is RequestPushStatus -> processImpl(data)
is DecodedNotifyMsgBody -> processImpl(data)
} }
} }
@ -258,4 +261,6 @@ internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
protected open suspend fun PipelineContext.processImpl(data: MsgComm.Msg) {} protected open suspend fun PipelineContext.processImpl(data: MsgComm.Msg) {}
protected open suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) {} protected open suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) {}
protected open suspend fun PipelineContext.processImpl(data: RequestPushStatus) {} protected open suspend fun PipelineContext.processImpl(data: RequestPushStatus) {}
protected open suspend fun PipelineContext.processImpl(data: DecodedNotifyMsgBody) {}
} }

View File

@ -27,7 +27,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
internal interface NewContactSupport { internal interface NewContactSupport { // can be a marker interface when context receivers are available.
fun MsgComm.Msg.getNewMemberInfo(): MemberInfoImpl { fun MsgComm.Msg.getNewMemberInfo(): MemberInfoImpl {
return MemberInfoImpl( return MemberInfoImpl(

View File

@ -0,0 +1,34 @@
/*
* Copyright 2019-2021 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.network.notice.decoders
import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.protocol.data.proto.TroopTips0x857
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
internal class GroupNotificationDecoder : MixedNoticeProcessor() {
override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {
when (data.kind) {
0x10 -> {
val proto = data.buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), offset = 1)
processAlso(DecodedNotifyMsgBody(data.kind, data.group, proto))
}
}
}
}
internal data class DecodedNotifyMsgBody(
override val kind: Int,
override val group: GroupImpl,
override val buf: TroopTips0x857.NotifyMsgBody,
) : BaseMsgType0x2DC<TroopTips0x857.NotifyMsgBody>, ProtocolStruct

View File

@ -46,7 +46,7 @@ internal class MsgInfoDecoder(
if (!bot.syncController.syncOnlinePush(data)) return if (!bot.syncController.syncOnlinePush(data)) return
when (data.shMsgType.toUShort().toInt()) { when (data.shMsgType.toUShort().toInt()) {
// 528 // 528
0x210 -> fire(data.vMsg.loadAs(MsgType0x210.serializer())) 0x210 -> processAlso(data.vMsg.loadAs(MsgType0x210.serializer()))
// 732 // 732
0x2dc -> { 0x2dc -> {
@ -57,7 +57,7 @@ internal class MsgInfoDecoder(
val kind = readByte().toInt() val kind = readByte().toInt()
discardExact(1) discardExact(1)
fire(MsgType0x2DC(kind, group, this.readBytes())) processAlso(MsgType0x2DC(kind, group, this.readBytes()))
} }
} }
else -> { else -> {
@ -67,8 +67,37 @@ internal class MsgInfoDecoder(
} }
} }
internal class MsgType0x2DC( internal interface BaseMsgType0x2DC<V> {
val kind: Int, // inner kind, read from vMsg val kind: Int
val group: GroupImpl, val group: GroupImpl
val buf: ByteArray, val buf: V
) : ProtocolStruct
fun Long.findMember() = group[this]
fun String.findMember() = this.toLongOrNull()?.let { group[it] }
}
internal data class MsgType0x2DC(
override val kind: Int, // inner kind, read from vMsg
override val group: GroupImpl,
override val buf: ByteArray,
) : ProtocolStruct, BaseMsgType0x2DC<ByteArray> {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MsgType0x2DC
if (kind != other.kind) return false
if (group != other.group) return false
if (!buf.contentEquals(other.buf)) return false
return true
}
override fun hashCode(): Int {
var result = kind
result = 31 * result + group.hashCode()
result = 31 * result + buf.contentHashCode()
return result
}
}

View File

@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
package net.mamoe.mirai.internal.network.notice package net.mamoe.mirai.internal.network.notice.group
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.event.AbstractEvent import net.mamoe.mirai.event.AbstractEvent
@ -26,8 +26,8 @@ import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.PipelineContext import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.MemberNick.Companion.generateMemberNickFromMember
import net.mamoe.mirai.internal.network.notice.GroupMessageProcessor.MemberNick.Companion.generateMemberNickFromMember import net.mamoe.mirai.internal.network.notice.priv.PrivateMessageNoticeProcessor
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
@ -39,7 +39,9 @@ import net.mamoe.mirai.utils.*
/** /**
* Handles [GroupMessageEvent]. For private message events, see [PrivateMessageNoticeProcessor] * Handles [GroupMessageEvent]. For private message events, see [PrivateMessageNoticeProcessor]
*/ */
internal class GroupMessageProcessor : SimpleNoticeProcessor<MsgOnlinePush.PbPushMsg>(type()) { internal class GroupMessageProcessor(
private val logger: MiraiLogger,
) : SimpleNoticeProcessor<MsgOnlinePush.PbPushMsg>(type()) {
internal data class SendGroupMessageReceipt( internal data class SendGroupMessageReceipt(
val messageRandom: Int, val messageRandom: Int,
val sequenceId: Int, val sequenceId: Int,
@ -113,7 +115,7 @@ internal class GroupMessageProcessor : SimpleNoticeProcessor<MsgOnlinePush.PbPus
nameCard = sender.generateMemberNickFromMember() nameCard = sender.generateMemberNickFromMember()
} else { // normal member chat } else { // normal member chat
sender = group[msgHead.fromUin] ?: kotlin.run { sender = group[msgHead.fromUin] ?: kotlin.run {
bot.network.logger.warning { "Failed to find member ${msgHead.fromUin} in group ${group.id}" } logger.warning { "Failed to find member ${msgHead.fromUin} in group ${group.id}" }
return return
} }
nameCard = findSenderName(extraInfo, msgHead.groupInfo) ?: sender.generateMemberNickFromMember() nameCard = findSenderName(extraInfo, msgHead.groupInfo) ?: sender.generateMemberNickFromMember()

View File

@ -0,0 +1,213 @@
/*
* Copyright 2019-2021 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.network.notice.group
import kotlinx.io.core.readUInt
import kotlinx.io.core.readUShort
import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.data.GroupHonorType
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.contact.checkIsMemberImpl
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.notice.NewContactSupport
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC
import net.mamoe.mirai.internal.network.protocol.data.proto.TroopTips0x857
import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.utils.context
import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.read
internal class GroupNotificationProcessor : MixedNoticeProcessor(), NewContactSupport {
override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {
when (data.kind) {
0x0C -> processMute(data)
0x0E -> processAllowAnonymousChat(data)
0x10 -> processAllowConfessTask(data)
0x14 -> processGrayTip(data)
}
}
/**
* @see MemberMuteEvent
* @see MemberUnmuteEvent
* @see GroupMuteAllEvent
* @see BotMuteEvent
* @see BotUnmuteEvent
*/
private fun PipelineContext.processMute(
data: MsgType0x2DC,
) = data.context {
fun handleMuteMemberPacket(
bot: QQAndroidBot,
group: GroupImpl,
operator: NormalMember,
target: Long,
timeSeconds: Int,
): Packet? {
if (target == 0L) {
val new = timeSeconds != 0
if (group.settings.isMuteAllField == new) {
return null
}
group.settings.isMuteAllField = new
return GroupMuteAllEvent(!new, new, group, operator)
}
if (target == bot.id) {
return when {
group.botMuteRemaining == timeSeconds -> null
timeSeconds == 0 || timeSeconds == 0xFFFF_FFFF.toInt() -> {
group.botAsMember.checkIsMemberImpl()._muteTimestamp = 0
BotUnmuteEvent(operator)
}
else -> {
group.botAsMember.checkIsMemberImpl()._muteTimestamp =
currentTimeSeconds().toInt() + timeSeconds
BotMuteEvent(timeSeconds, operator)
}
}
}
val member = group[target] ?: return null
member.checkIsMemberImpl()
if (member.muteTimeRemaining == timeSeconds) return null
member._muteTimestamp = currentTimeSeconds().toInt() + timeSeconds
return if (timeSeconds == 0) MemberUnmuteEvent(member, operator)
else MemberMuteEvent(member, timeSeconds, operator)
}
markAsConsumed()
buf.read {
val operatorUin = readUInt().toLong()
if (operatorUin == bot.id) return
val operator = group[operatorUin] ?: return
readUInt().toLong() // time
val length = readUShort().toInt()
repeat(length) {
val target = readUInt().toLong()
val timeSeconds = readUInt()
collected += handleMuteMemberPacket(bot, group, operator, target, timeSeconds.toInt())
}
}
}
/**
* @see GroupAllowAnonymousChatEvent
*/
private fun PipelineContext.processAllowAnonymousChat(
data: MsgType0x2DC,
) = data.context {
markAsConsumed()
buf.read {
val operator = group[readUInt().toLong()] ?: return
val new = readInt() == 0
if (group.settings.isAnonymousChatEnabledField == new) return
group.settings.isAnonymousChatEnabledField = new
collect(GroupAllowAnonymousChatEvent(!new, new, group, operator))
}
}
/**
* @see GroupAllowConfessTalkEvent
*/
private fun PipelineContext.processAllowConfessTask(
data: MsgType0x2DC,
) = data.context {
val proto = data.buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), offset = 1)
markAsConsumed()
when (proto.optEnumType) {
1 -> {
val tipsInfo = proto.optMsgGraytips ?: return
val message = tipsInfo.optBytesContent.decodeToString()
// 机器人信息
when (tipsInfo.robotGroupOpt) {
// others
0 -> {
if (message.endsWith("群聊坦白说")) {
val new = when (message) {
"管理员已关闭群聊坦白说" -> false
"管理员已开启群聊坦白说" -> true
else -> {
bot.network.logger.debug { "Unknown server confess talk messages $message" }
return
}
}
collect(GroupAllowConfessTalkEvent(new, !new, group, false))
}
}
}
}
else -> markNotConsumed()
}
}
/**
* @see NudgeEvent
* @see MemberHonorChangeEvent
* @see GroupTalkativeChangeEvent
*/
private fun PipelineContext.processGrayTip(
data: MsgType0x2DC,
) = data.context {
val grayTip = buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), 1).optGeneralGrayTip
markAsConsumed()
when (grayTip?.templId) {
// 戳一戳
10043L, 1133L, 1132L, 1134L, 1135L, 1136L -> {
//预置数据,服务器将不会提供己方已知消息
val action = grayTip.msgTemplParam["action_str"].orEmpty()
val from = grayTip.msgTemplParam["uin_str1"]?.findMember() ?: group.botAsMember
val target = grayTip.msgTemplParam["uin_str2"]?.findMember() ?: group.botAsMember
val suffix = grayTip.msgTemplParam["suffix_str"].orEmpty()
collected += NudgeEvent(
from = if (from.id == bot.id) bot else from,
target = if (target.id == bot.id) bot else target,
action = action,
suffix = suffix,
subject = group,
)
}
// 龙王
10093L, 1053L, 1054L -> {
val now: NormalMember = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember
val previous: NormalMember? = grayTip.msgTemplParam["uin_last"]?.findMember()
if (previous == null) {
collect(MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE))
} else {
collect(GroupTalkativeChangeEvent(group, now, previous))
collect(MemberHonorChangeEvent.Lose(previous, GroupHonorType.TALKATIVE))
collect(MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE))
}
}
else -> {
markNotConsumed()
bot.network.logger.debug {
"Unknown Transformers528 0x14 template\ntemplId=${grayTip?.templId}\nPermList=${grayTip?.msgTemplParam?._miraiContentToString()}"
}
}
}
}
}
internal operator fun List<TroopTips0x857.TemplParam>.get(name: String) = this.findLast { it.name == name }?.value

View File

@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
package net.mamoe.mirai.internal.network.notice package net.mamoe.mirai.internal.network.notice.group
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@ -25,16 +25,19 @@ import net.mamoe.mirai.internal.message.contextualBugReportException
import net.mamoe.mirai.internal.network.components.ContactUpdater import net.mamoe.mirai.internal.network.components.ContactUpdater
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
import net.mamoe.mirai.internal.network.components.PipelineContext import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC import net.mamoe.mirai.internal.network.notice.NewContactSupport
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.jce.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.proto.* 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.utils._miraiContentToString import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.parseToMessageDataList import net.mamoe.mirai.internal.utils.parseToMessageDataList
import net.mamoe.mirai.internal.utils.toMemberInfo import net.mamoe.mirai.internal.utils.toMemberInfo
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.context import net.mamoe.mirai.utils.context
import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.read import net.mamoe.mirai.utils.read
@ -54,7 +57,7 @@ import net.mamoe.mirai.utils.read
* @see BotInvitedJoinGroupRequestEvent * @see BotInvitedJoinGroupRequestEvent
* @see MemberJoinRequestEvent * @see MemberJoinRequestEvent
*/ */
internal class GroupListNoticeProcessor( internal class GroupOrMemberListNoticeProcessor(
private val logger: MiraiLogger, private val logger: MiraiLogger,
) : MixedNoticeProcessor(), NewContactSupport { ) : MixedNoticeProcessor(), NewContactSupport {
@ -79,14 +82,14 @@ internal class GroupListNoticeProcessor(
* @see MemberJoinEvent.Invite * @see MemberJoinEvent.Invite
* @see MemberLeaveEvent.Quit * @see MemberLeaveEvent.Quit
*/ */
override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) = data.context { override suspend fun PipelineContext.processImpl(data: DecodedNotifyMsgBody) = data.context {
if (data.kind != 0x10) return val proto = data.buf
val proto = data.buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), offset = 1)
if (proto.optEnumType != 1) return if (proto.optEnumType != 1) return
val tipsInfo = proto.optMsgGraytips ?: return val tipsInfo = proto.optMsgGraytips ?: return
val message = tipsInfo.optBytesContent.decodeToString() val message = tipsInfo.optBytesContent.decodeToString()
// 机器人信息 // 机器人信息
markAsConsumed()
when (tipsInfo.robotGroupOpt) { when (tipsInfo.robotGroupOpt) {
// 添加 // 添加
1 -> { 1 -> {
@ -107,13 +110,8 @@ internal class GroupListNoticeProcessor(
collect(MemberLeaveEvent.Quit(member)) collect(MemberLeaveEvent.Quit(member))
} }
} }
else -> markNotConsumed()
else -> {
logger.debug { "Unknown robotGroupOpt ${tipsInfo.robotGroupOpt}, message=$message" }
}
} }
return markAsConsumed()
} }
/** /**

View File

@ -0,0 +1,45 @@
/*
* Copyright 2019-2021 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.network.notice.group
import net.mamoe.mirai.event.events.MessageRecallEvent
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC
import net.mamoe.mirai.internal.network.protocol.data.proto.TroopTips0x857
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.utils.mapToIntArray
internal class GroupRecallProcessor : MixedNoticeProcessor() {
override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {
val (_, group, buf) = data
val proto = buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), 1)
val recallReminder = proto.optMsgRecall ?: return
val operator = group[recallReminder.uin] ?: return
markAsConsumed()
for (firstPkg in recallReminder.recalledMsgList) {
if (firstPkg.authorUin == bot.id && operator.id == bot.id) continue // already broadcast
val author = group[firstPkg.authorUin] ?: continue
collected += MessageRecallEvent.GroupRecall(
bot = bot,
authorId = firstPkg.authorUin,
messageIds = recallReminder.recalledMsgList.mapToIntArray { it.seq },
messageInternalIds = recallReminder.recalledMsgList.mapToIntArray { it.msgRandom },
messageTime = firstPkg.time,
operator = operator,
group = group,
author = author,
)
}
}
}

View File

@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
package net.mamoe.mirai.internal.network.notice package net.mamoe.mirai.internal.network.notice.priv
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.io.core.readUByte import kotlinx.io.core.readUByte
@ -19,6 +19,7 @@ import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
import net.mamoe.mirai.internal.contact.toMiraiFriendInfo import net.mamoe.mirai.internal.contact.toMiraiFriendInfo
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
import net.mamoe.mirai.internal.network.components.PipelineContext import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.notice.NewContactSupport
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210 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.FrdSysMsg
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm

View File

@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
package net.mamoe.mirai.internal.network.notice package net.mamoe.mirai.internal.network.notice.priv
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel

View File

@ -7,9 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
package net.mamoe.mirai.internal.network.notice package net.mamoe.mirai.internal.network.notice.priv
import net.mamoe.mirai.contact.User
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.internal.contact.* import net.mamoe.mirai.internal.contact.*
import net.mamoe.mirai.internal.getGroupByUin import net.mamoe.mirai.internal.getGroupByUin
@ -18,7 +17,9 @@ import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.fromSync import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.fromSync
import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
import net.mamoe.mirai.internal.network.components.SsoProcessor import net.mamoe.mirai.internal.network.components.SsoProcessor
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.utils.assertUnreachable
import net.mamoe.mirai.utils.context import net.mamoe.mirai.utils.context
/** /**
@ -47,7 +48,12 @@ internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg
166, 167, // 单向好友 166, 167, // 单向好友
208, // friend ptt, maybe also support stranger 208, // friend ptt, maybe also support stranger
-> { -> {
handlePrivateMessage(data, bot.getFriend(senderUin) ?: bot.getStranger(senderUin) ?: return) handlePrivateMessage(
data,
bot.getFriend(senderUin)?.impl()
?: bot.getStranger(senderUin)?.impl()
?: return
)
} }
141, // group temp 141, // group temp
@ -63,9 +69,8 @@ internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg
private suspend fun PipelineContext.handlePrivateMessage( private suspend fun PipelineContext.handlePrivateMessage(
data: MsgComm.Msg, data: MsgComm.Msg,
user: User, user: AbstractUser,
) = data.context { ) = data.context {
user.impl()
if (!user.messageSeq.updateIfDifferentWith(msgHead.msgSeq)) return if (!user.messageSeq.updateIfDifferentWith(msgHead.msgSeq)) return
if (contentHead?.autoReply == 1) return if (contentHead?.autoReply == 1) return
@ -80,15 +85,15 @@ internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg
is FriendImpl -> FriendMessageSyncEvent(user, chain, time) is FriendImpl -> FriendMessageSyncEvent(user, chain, time)
is StrangerImpl -> StrangerMessageSyncEvent(user, chain, time) is StrangerImpl -> StrangerMessageSyncEvent(user, chain, time)
is NormalMemberImpl -> GroupTempMessageSyncEvent(user, chain, time) is NormalMemberImpl -> GroupTempMessageSyncEvent(user, chain, time)
else -> null is AnonymousMemberImpl -> assertUnreachable()
} }
} else { } else {
when (user) { when (user) {
is FriendImpl -> FriendMessageEvent(user, chain, time) is FriendImpl -> FriendMessageEvent(user, chain, time)
is StrangerImpl -> StrangerMessageEvent(user, chain, time) is StrangerImpl -> StrangerMessageEvent(user, chain, time)
is NormalMemberImpl -> GroupTempMessageEvent(user, chain, time) is NormalMemberImpl -> GroupTempMessageEvent(user, chain, time)
else -> null is AnonymousMemberImpl -> assertUnreachable()
} }
} ?: error("unreachable") }
} }
} }

View File

@ -320,8 +320,8 @@ internal class TroopTips0x857 : ProtoBuf {
@Serializable @Serializable
internal class TemplParam( internal class TemplParam(
@ProtoNumber(1) @JvmField val name: ByteArray = EMPTY_BYTE_ARRAY, @ProtoNumber(1) @JvmField val name: String = "",
@ProtoNumber(2) @JvmField val value: ByteArray = EMPTY_BYTE_ARRAY, @ProtoNumber(2) @JvmField val value: String = "",
) : ProtoBuf ) : ProtoBuf
@Serializable @Serializable

View File

@ -10,16 +10,13 @@
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.readUInt
import kotlinx.io.core.readUShort
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.contact.User import net.mamoe.mirai.contact.User
import net.mamoe.mirai.data.GroupHonorType import net.mamoe.mirai.event.events.GroupNameChangeEvent
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.MemberCardChangeEvent
import net.mamoe.mirai.event.events.MessageRecallEvent
import net.mamoe.mirai.event.events.NudgeEvent
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.contact.GroupImpl import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.contact.checkIsGroupImpl import net.mamoe.mirai.internal.contact.checkIsGroupImpl
@ -33,20 +30,16 @@ import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x122 import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x122
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27.SubMsgType0x27.* import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27.SubMsgType0x27.*
import net.mamoe.mirai.internal.network.protocol.data.proto.TroopTips0x857
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.internal.network.protocol.packet.buildResponseUniPacket import net.mamoe.mirai.internal.network.protocol.packet.buildResponseUniPacket
import net.mamoe.mirai.internal.utils._miraiContentToString import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.ProtoBuf import net.mamoe.mirai.internal.utils.io.ProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.loadAs 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.readUniPacket import net.mamoe.mirai.internal.utils.io.serialization.readUniPacket
import net.mamoe.mirai.internal.utils.io.serialization.writeJceRequestPacket import net.mamoe.mirai.internal.utils.io.serialization.writeJceRequestPacket
import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.debug import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.encodeToString import net.mamoe.mirai.utils.encodeToString
import net.mamoe.mirai.utils.mapToIntArray
//0C 01 B1 89 BE 09 5E 3D 72 A6 00 01 73 68 FC 06 00 00 00 3C //0C 01 B1 89 BE 09 5E 3D 72 A6 00 01 73 68 FC 06 00 00 00 3C
@ -100,189 +93,24 @@ internal inline fun lambda732(crossinline block: ByteReadPacket.(GroupImpl, QQAn
} }
} }
private fun handleMuteMemberPacket(
bot: QQAndroidBot,
group: GroupImpl,
operator: NormalMember,
target: Long,
timeSeconds: Int,
): Packet? {
if (target == 0L) {
val new = timeSeconds != 0
if (group.settings.isMuteAllField == new) {
return null
}
group.settings.isMuteAllField = new
return GroupMuteAllEvent(!new, new, group, operator)
}
if (target == bot.id) {
return when {
group.botMuteRemaining == timeSeconds -> null
timeSeconds == 0 || timeSeconds == 0xFFFF_FFFF.toInt() -> {
group.botAsMember.checkIsMemberImpl()._muteTimestamp = 0
BotUnmuteEvent(operator)
}
else -> {
group.botAsMember.checkIsMemberImpl()._muteTimestamp =
currentTimeSeconds().toInt() + timeSeconds
BotMuteEvent(timeSeconds, operator)
}
}
}
val member = group[target] ?: return null
member.checkIsMemberImpl()
if (member.muteTimeRemaining == timeSeconds) {
return null
}
member._muteTimestamp = currentTimeSeconds().toInt() + timeSeconds
return if (timeSeconds == 0) MemberUnmuteEvent(member, operator)
else MemberMuteEvent(member, timeSeconds, operator)
}
internal object Transformers732 : Map<Int, Lambda732> by mapOf( internal object Transformers732 : Map<Int, Lambda732> by mapOf(
// mute // mute
0x0c to lambda732 { group: GroupImpl, bot: QQAndroidBot -> 0x0c to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
val operatorUin = readUInt().toLong() TODO("removed")
if (operatorUin == bot.id) {
return@lambda732 emptySequence()
}
val operator = group[operatorUin] ?: return@lambda732 emptySequence()
readUInt().toLong() // time
val length = readUShort().toInt()
val packetList: MutableList<Packet> = mutableListOf()
repeat(length) {
val target = readUInt().toLong()
val timeSeconds = readUInt()
handleMuteMemberPacket(bot, group, operator, target, timeSeconds.toInt())?.let {
packetList.add(it)
}
}
return@lambda732 packetList.asSequence()
}, },
// anonymous // anonymous
0x0e to lambda732 { group: GroupImpl, _: QQAndroidBot -> 0x0e to lambda732 { group: GroupImpl, _: QQAndroidBot ->
// 匿名 TODO("removed")
val operator = group[readUInt().toLong()] ?: return@lambda732 emptySequence()
val new = readInt() == 0
if (group.settings.isAnonymousChatEnabledField == new) {
return@lambda732 emptySequence()
}
group.settings.isAnonymousChatEnabledField = new
return@lambda732 sequenceOf(GroupAllowAnonymousChatEvent(!new, new, group, operator))
}, },
//系统提示 //系统提示
0x14 to lambda732 { group: GroupImpl, bot: QQAndroidBot -> 0x14 to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
TODO("removed")
discardExact(1)
val grayTip = readProtoBuf(TroopTips0x857.NotifyMsgBody.serializer()).optGeneralGrayTip
when (grayTip?.templId) {
//戳一戳
10043L, 1133L, 1132L, 1134L, 1135L, 1136L -> {
//预置数据,服务器将不会提供己方已知消息
var action = ""
var from: Member = group.botAsMember
var target: Member = group.botAsMember
var suffix = ""
grayTip.msgTemplParam.map {
Pair(it.name.decodeToString(), it.value.decodeToString())
}.asSequence().forEach { (key, value) ->
run {
when (key) {
"action_str" -> action = value
"uin_str1" -> from = group[value.toLong()] ?: return@lambda732 emptySequence()
"uin_str2" -> target = group[value.toLong()] ?: return@lambda732 emptySequence()
"suffix_str" -> suffix = value
}
}
}
return@lambda732 sequenceOf(
NudgeEvent(
from = if (from.id == bot.id) bot else from,
target = if (target.id == bot.id) bot else target,
action = action,
suffix = suffix,
subject = group,
),
)
}
//龙王
10093L, 1053L, 1054L -> {
var now: NormalMember = group.botAsMember
var previous: NormalMember? = null
grayTip.msgTemplParam.asSequence().map {
it.name.decodeToString() to it.value.decodeToString()
}.forEach { (key, value) ->
when (key) {
"uin" -> now = group[value.toLong()] ?: return@lambda732 emptySequence()
"uin_last" -> previous = group[value.toLong()] ?: return@lambda732 emptySequence()
}
}
return@lambda732 previous?.let {
sequenceOf(
GroupTalkativeChangeEvent(group, now, it),
MemberHonorChangeEvent.Lose(it, GroupHonorType.TALKATIVE),
MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE),
)
} ?: sequenceOf(MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE))
}
else -> {
bot.network.logger.debug {
"Unknown Transformers528 0x14 template\ntemplId=${grayTip?.templId}\nPermList=${grayTip?.msgTemplParam?._miraiContentToString()}"
}
return@lambda732 emptySequence()
}
}
}, },
// 传字符串信息 // 传字符串信息
0x10 to lambda732 { group: GroupImpl, bot: QQAndroidBot -> 0x10 to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
discardExact(1) TODO("removed")
readProtoBuf(TroopTips0x857.NotifyMsgBody.serializer()).let { body ->
when (body.optEnumType) {
1 -> body.optMsgGraytips?.let { tipsInfo ->
val message = tipsInfo.optBytesContent.decodeToString()
//机器人信息
if (tipsInfo.robotGroupOpt != 0) {
TODO("removed")
} else when {
message.endsWith("群聊坦白说") -> {
val new = when (message) {
"管理员已关闭群聊坦白说" -> false
"管理员已开启群聊坦白说" -> true
else -> {
bot.network.logger.debug { "Unknown server confess talk messages $message" }
return@lambda732 emptySequence()
}
}
return@lambda732 sequenceOf(
GroupAllowConfessTalkEvent(
new,
!new,
group,
false,
),
)
}
else -> {
bot.network.logger.debug { "Unknown server messages $message" }
return@lambda732 emptySequence()
}
}
}
else -> {
bot.network.logger.debug {
"Unknown Transformers732 0x10 optEnumType\noptEnumType=${body.optEnumType}\ncontent=${body._miraiContentToString()}"
}
return@lambda732 emptySequence()
}
} ?: return@lambda732 emptySequence()
}
/* /*
val dataBytes = readBytes(26) val dataBytes = readBytes(26)
@ -352,31 +180,7 @@ internal object Transformers732 : Map<Int, Lambda732> by mapOf(
// recall // recall
0x11 to lambda732 { group: GroupImpl, bot: QQAndroidBot -> 0x11 to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
discardExact(1) TODO("removed")
val proto = readProtoBuf(TroopTips0x857.NotifyMsgBody.serializer())
val recallReminder = proto.optMsgRecall ?: return@lambda732 emptySequence()
val operator =
if (recallReminder.uin == bot.id) group.botAsMember
else group[recallReminder.uin] ?: return@lambda732 emptySequence()
val firstPkg = recallReminder.recalledMsgList.firstOrNull() ?: return@lambda732 emptySequence()
return@lambda732 when {
firstPkg.authorUin == bot.id && operator.id == bot.id -> emptySequence()
else -> sequenceOf(
MessageRecallEvent.GroupRecall(
bot,
firstPkg.authorUin,
recallReminder.recalledMsgList.mapToIntArray { it.seq },
recallReminder.recalledMsgList.mapToIntArray { it.msgRandom },
firstPkg.time,
operator,
group,
group[firstPkg.authorUin] ?: return@lambda732 emptySequence(),
),
)
}
}, },
) )