mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-05 23:50:08 +08:00
Migrate more transformers to NoticeProcessorPipeline
This commit is contained in:
parent
edf1bc9a2e
commit
9c272ebf1e
@ -22,22 +22,86 @@ public value class TypeKey<out T>(public val name: String) {
|
||||
public inline infix fun <T> to(value: T): TypeSafeMap = buildTypeSafeMap { set(this@TypeKey, value) }
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
public value class TypeSafeMap(
|
||||
private val map: MutableMap<TypeKey<*>, Any?> = ConcurrentHashMap()
|
||||
) {
|
||||
public operator fun <T> get(key: TypeKey<T>): T =
|
||||
public interface TypeSafeMap {
|
||||
public val size: Int
|
||||
|
||||
public operator fun <T> get(key: TypeKey<T>): T
|
||||
public operator fun <T> contains(key: TypeKey<T>): Boolean = get(key) != null
|
||||
|
||||
public fun toMap(): Map<TypeKey<*>, Any?>
|
||||
|
||||
public companion object {
|
||||
public val EMPTY: TypeSafeMap = TypeSafeMapImpl(emptyMap())
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun TypeSafeMap.plus(other: TypeSafeMap): TypeSafeMap {
|
||||
return when {
|
||||
other.size == 0 -> this
|
||||
this.size == 0 -> other
|
||||
else -> buildTypeSafeMap {
|
||||
setAll(this@plus)
|
||||
setAll(other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface MutableTypeSafeMap : TypeSafeMap {
|
||||
public operator fun <T> set(key: TypeKey<T>, value: T)
|
||||
public fun <T> remove(key: TypeKey<T>): T?
|
||||
public fun setAll(other: TypeSafeMap)
|
||||
}
|
||||
|
||||
|
||||
internal open class TypeSafeMapImpl(
|
||||
internal open val map: Map<TypeKey<*>, Any?> = ConcurrentHashMap()
|
||||
) : TypeSafeMap {
|
||||
override val size: Int get() = map.size
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is TypeSafeMapImpl && other.map == this.map
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return map.hashCode()
|
||||
}
|
||||
|
||||
override operator fun <T> get(key: TypeKey<T>): T =
|
||||
map[key]?.uncheckedCast() ?: throw NoSuchElementException(key.toString())
|
||||
|
||||
public operator fun <T> contains(key: TypeKey<T>): Boolean = get(key) != null
|
||||
public operator fun <T> set(key: TypeKey<T>, value: T) {
|
||||
override operator fun <T> contains(key: TypeKey<T>): Boolean = get(key) != null
|
||||
|
||||
override fun toMap(): Map<TypeKey<*>, Any?> = map
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal class MutableTypeSafeMapImpl(
|
||||
override val map: MutableMap<TypeKey<*>, Any?> = ConcurrentHashMap()
|
||||
) : TypeSafeMap, MutableTypeSafeMap, TypeSafeMapImpl(map) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is MutableTypeSafeMapImpl && other.map == this.map
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return map.hashCode()
|
||||
}
|
||||
|
||||
override operator fun <T> set(key: TypeKey<T>, value: T) {
|
||||
map[key] = value
|
||||
}
|
||||
|
||||
public fun <T> remove(key: TypeKey<T>): T? = map.remove(key)?.uncheckedCast()
|
||||
override fun setAll(other: TypeSafeMap) {
|
||||
if (other is TypeSafeMapImpl) {
|
||||
map.putAll(other.map)
|
||||
} else {
|
||||
map.putAll(other.toMap())
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> remove(key: TypeKey<T>): T? = map.remove(key)?.uncheckedCast()
|
||||
}
|
||||
|
||||
public inline fun buildTypeSafeMap(block: TypeSafeMap.() -> Unit): TypeSafeMap {
|
||||
public inline fun buildTypeSafeMap(block: MutableTypeSafeMap.() -> Unit): MutableTypeSafeMap {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return TypeSafeMap().apply(block)
|
||||
return MutableTypeSafeMapImpl().apply(block)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ import net.mamoe.mirai.internal.network.notice.group.GroupOrMemberListNoticeProc
|
||||
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.notice.priv.PrivateMessageProcessor
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.internal.utils.subLogger
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
@ -169,7 +169,7 @@ internal open class QQAndroidBot constructor(
|
||||
FriendNoticeProcessor(pipelineLogger.subLogger("FriendNoticeProcessor")),
|
||||
GroupOrMemberListNoticeProcessor(pipelineLogger.subLogger("GroupOrMemberListNoticeProcessor")),
|
||||
GroupMessageProcessor(pipelineLogger.subLogger("GroupMessageProcessor")),
|
||||
PrivateMessageNoticeProcessor(),
|
||||
PrivateMessageProcessor(),
|
||||
OtherClientNoticeProcessor(),
|
||||
UnconsumedNoticesAlerter(pipelineLogger.subLogger("UnconsumedNoticesAlerter")),
|
||||
GroupRecallProcessor()
|
||||
|
@ -15,8 +15,10 @@ import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.ParseErrorPacket
|
||||
import net.mamoe.mirai.internal.network.component.ComponentKey
|
||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||
import net.mamoe.mirai.internal.network.notice.BotAware
|
||||
import net.mamoe.mirai.internal.network.notice.decoders.DecodedNotifyMsgBody
|
||||
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
|
||||
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.proto.MsgComm
|
||||
@ -27,10 +29,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcP
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.OnlinePushPbPushTransMsg
|
||||
import net.mamoe.mirai.internal.network.toPacket
|
||||
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
|
||||
import net.mamoe.mirai.utils.TypeKey
|
||||
import net.mamoe.mirai.utils.TypeSafeMap
|
||||
import net.mamoe.mirai.utils.toDebugString
|
||||
import net.mamoe.mirai.utils.uncheckedCast
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import kotlin.reflect.KClass
|
||||
@ -46,7 +45,11 @@ internal interface NoticeProcessorPipeline {
|
||||
/**
|
||||
* Process [data] into [Packet]s. Exceptions are wrapped into [ParseErrorPacket]
|
||||
*/
|
||||
suspend fun process(bot: QQAndroidBot, data: ProtocolStruct, attributes: TypeSafeMap = TypeSafeMap()): ProcessResult
|
||||
suspend fun process(
|
||||
bot: QQAndroidBot,
|
||||
data: ProtocolStruct,
|
||||
attributes: TypeSafeMap = TypeSafeMap.EMPTY
|
||||
): ProcessResult
|
||||
|
||||
companion object : ComponentKey<NoticeProcessorPipeline> {
|
||||
val ComponentStorage.noticeProcessorPipeline get() = get(NoticeProcessorPipeline)
|
||||
@ -54,7 +57,7 @@ internal interface NoticeProcessorPipeline {
|
||||
@JvmStatic
|
||||
suspend inline fun QQAndroidBot.processPacketThroughPipeline(
|
||||
data: ProtocolStruct,
|
||||
attributes: TypeSafeMap = TypeSafeMap(),
|
||||
attributes: TypeSafeMap = TypeSafeMap.EMPTY,
|
||||
): Packet {
|
||||
return components.noticeProcessorPipeline.process(this, data, attributes).toPacket()
|
||||
}
|
||||
@ -66,8 +69,8 @@ internal value class MutableProcessResult(
|
||||
val data: MutableCollection<Packet>
|
||||
)
|
||||
|
||||
internal interface PipelineContext {
|
||||
val bot: QQAndroidBot
|
||||
internal interface PipelineContext : BotAware {
|
||||
override val bot: QQAndroidBot
|
||||
|
||||
val attributes: TypeSafeMap
|
||||
|
||||
@ -83,13 +86,13 @@ internal interface PipelineContext {
|
||||
* and throws a [contextualBugReportException] or logs something.
|
||||
*/
|
||||
@ConsumptionMarker
|
||||
fun NoticeProcessor.markAsConsumed()
|
||||
fun NoticeProcessor.markAsConsumed(marker: Any = this)
|
||||
|
||||
/**
|
||||
* Marks the input as not consumed, if it was marked by this [NoticeProcessor].
|
||||
*/
|
||||
@ConsumptionMarker
|
||||
fun NoticeProcessor.markNotConsumed()
|
||||
fun NoticeProcessor.markNotConsumed(marker: Any = this)
|
||||
|
||||
@DslMarker
|
||||
annotation class ConsumptionMarker // to give an explicit color.
|
||||
@ -116,13 +119,21 @@ internal interface PipelineContext {
|
||||
/**
|
||||
* Fire the [data] into the processor pipeline, and collect the results to current [collected].
|
||||
*
|
||||
* @param attributes extra attributes
|
||||
* @return result collected from processors. This would also have been collected to this context (where you call [processAlso]).
|
||||
*/
|
||||
suspend fun processAlso(data: ProtocolStruct): ProcessResult
|
||||
suspend fun processAlso(data: ProtocolStruct, attributes: TypeSafeMap = TypeSafeMap.EMPTY): ProcessResult
|
||||
|
||||
companion object {
|
||||
val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync")
|
||||
val KEY_MSG_INFO = TypeKey<MsgInfo>("msgInfo")
|
||||
|
||||
val PipelineContext.fromSync get() = attributes[KEY_FROM_SYNC]
|
||||
|
||||
/**
|
||||
* 来自 [MsgInfo] 的数据, 即 [MsgType0x210], [MsgType0x2DC] 的处理过程之中可以使用
|
||||
*/
|
||||
val PipelineContext.msgInfo get() = attributes[KEY_MSG_INFO]
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,15 +153,15 @@ internal open class NoticeProcessorPipelineImpl private constructor() : NoticePr
|
||||
inner class ContextImpl(
|
||||
override val bot: QQAndroidBot, override val attributes: TypeSafeMap,
|
||||
) : PipelineContext {
|
||||
private val consumers: Stack<NoticeProcessor> = Stack()
|
||||
private val consumers: Stack<Any> = Stack()
|
||||
|
||||
override val isConsumed: Boolean get() = consumers.isNotEmpty()
|
||||
override fun NoticeProcessor.markAsConsumed() {
|
||||
consumers.push(this)
|
||||
override fun NoticeProcessor.markAsConsumed(marker: Any) {
|
||||
consumers.push(marker)
|
||||
}
|
||||
|
||||
override fun NoticeProcessor.markNotConsumed() {
|
||||
if (consumers.peek() === this) {
|
||||
override fun NoticeProcessor.markNotConsumed(marker: Any) {
|
||||
if (consumers.peek() === marker) {
|
||||
consumers.pop()
|
||||
}
|
||||
}
|
||||
@ -165,8 +176,8 @@ internal open class NoticeProcessorPipelineImpl private constructor() : NoticePr
|
||||
this.collected.data.addAll(packets)
|
||||
}
|
||||
|
||||
override suspend fun processAlso(data: ProtocolStruct): ProcessResult {
|
||||
return process(bot, data, attributes)
|
||||
override suspend fun processAlso(data: ProtocolStruct, attributes: TypeSafeMap): ProcessResult {
|
||||
return process(bot, data, this.attributes + attributes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.GroupImpl
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Extension interfaces ---- should convert to context receivers in the future.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal interface BotAware : PrivateContactSupport {
|
||||
override val bot: QQAndroidBot
|
||||
}
|
||||
|
||||
internal interface GroupAware : GroupMemberSupport, BotAware {
|
||||
override val group: GroupImpl
|
||||
override val bot: QQAndroidBot get() = group.bot
|
||||
}
|
||||
|
||||
internal interface PrivateContactSupport {
|
||||
val bot: QQAndroidBot
|
||||
|
||||
fun Long.findFriend() = bot.friends[this]
|
||||
fun Long.findStranger() = bot.strangers[this]
|
||||
fun Long.findFriendOrStranger() = findFriend() ?: findStranger()
|
||||
fun String.findFriend() = this.toLongOrNull()?.findFriend()
|
||||
fun String.findStranger() = this.toLongOrNull()?.findStranger()
|
||||
fun String.findFriendOrStranger() = this.toLongOrNull()?.findFriendOrStranger()
|
||||
}
|
||||
|
||||
internal interface GroupMemberSupport {
|
||||
val group: GroupImpl
|
||||
|
||||
fun Long.findMember() = group[this]
|
||||
fun String.findMember() = this.toLongOrNull()?.findMember()
|
||||
}
|
@ -15,9 +15,11 @@ import kotlinx.io.core.readUInt
|
||||
import net.mamoe.mirai.internal.contact.GroupImpl
|
||||
import net.mamoe.mirai.internal.contact.checkIsGroupImpl
|
||||
import net.mamoe.mirai.internal.network.components.PipelineContext
|
||||
import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.KEY_MSG_INFO
|
||||
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.syncOnlinePush
|
||||
import net.mamoe.mirai.internal.network.notice.GroupAware
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack.SvcReqPushMsg
|
||||
@ -46,7 +48,7 @@ internal class MsgInfoDecoder(
|
||||
if (!bot.syncController.syncOnlinePush(data)) return
|
||||
when (data.shMsgType.toUShort().toInt()) {
|
||||
// 528
|
||||
0x210 -> processAlso(data.vMsg.loadAs(MsgType0x210.serializer()))
|
||||
0x210 -> processAlso(data.vMsg.loadAs(MsgType0x210.serializer()), KEY_MSG_INFO to data)
|
||||
|
||||
// 732
|
||||
0x2dc -> {
|
||||
@ -57,7 +59,7 @@ internal class MsgInfoDecoder(
|
||||
val kind = readByte().toInt()
|
||||
discardExact(1)
|
||||
|
||||
processAlso(MsgType0x2DC(kind, group, this.readBytes()))
|
||||
processAlso(MsgType0x2DC(kind, group, this.readBytes()), KEY_MSG_INFO to data)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@ -67,13 +69,12 @@ internal class MsgInfoDecoder(
|
||||
}
|
||||
}
|
||||
|
||||
internal interface BaseMsgType0x2DC<V> {
|
||||
internal interface BaseMsgType0x2DC<V> : GroupAware {
|
||||
val kind: Int
|
||||
val group: GroupImpl
|
||||
override val group: GroupImpl
|
||||
val buf: V
|
||||
|
||||
fun Long.findMember() = group[this]
|
||||
fun String.findMember() = this.toLongOrNull()?.let { group[it] }
|
||||
override val bot get() = group.bot
|
||||
}
|
||||
|
||||
internal data class MsgType0x2DC(
|
||||
|
@ -27,7 +27,7 @@ import net.mamoe.mirai.internal.network.components.PipelineContext
|
||||
import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
|
||||
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
|
||||
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.MemberNick.Companion.generateMemberNickFromMember
|
||||
import net.mamoe.mirai.internal.network.notice.priv.PrivateMessageNoticeProcessor
|
||||
import net.mamoe.mirai.internal.network.notice.priv.PrivateMessageProcessor
|
||||
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.MsgOnlinePush
|
||||
@ -37,7 +37,7 @@ import net.mamoe.mirai.message.data.MessageSourceKind
|
||||
import net.mamoe.mirai.utils.*
|
||||
|
||||
/**
|
||||
* Handles [GroupMessageEvent]. For private message events, see [PrivateMessageNoticeProcessor]
|
||||
* Handles [GroupMessageEvent]. For private message events, see [PrivateMessageProcessor]
|
||||
*/
|
||||
internal class GroupMessageProcessor(
|
||||
private val logger: MiraiLogger,
|
||||
|
@ -16,6 +16,7 @@ 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.checkIsGroupImpl
|
||||
import net.mamoe.mirai.internal.contact.checkIsMemberImpl
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
|
||||
@ -23,15 +24,135 @@ 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.jce.MsgType0x210
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x122
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27
|
||||
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
|
||||
import net.mamoe.mirai.utils.*
|
||||
|
||||
internal class GroupNotificationProcessor : MixedNoticeProcessor(), NewContactSupport {
|
||||
|
||||
override suspend fun PipelineContext.processImpl(data: MsgType0x210) = data.context {
|
||||
when (data.uSubMsgType) {
|
||||
0x27L -> {
|
||||
val body = vProtobuf.loadAs(Submsgtype0x27.SubMsgType0x27.SubMsgType0x27MsgBody.serializer())
|
||||
for (msgModInfo in body.msgModInfos) {
|
||||
markAsConsumed(msgModInfo)
|
||||
when {
|
||||
msgModInfo.msgModGroupProfile != null -> handleGroupProfileChanged(msgModInfo.msgModGroupProfile)
|
||||
msgModInfo.msgModGroupMemberProfile != null -> handleGroupMemberProfileChanged(msgModInfo.msgModGroupMemberProfile)
|
||||
else -> markNotConsumed(msgModInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GroupNameChangeEvent
|
||||
*/
|
||||
private fun PipelineContext.handleGroupProfileChanged(
|
||||
modGroupProfile: Submsgtype0x27.SubMsgType0x27.ModGroupProfile
|
||||
) {
|
||||
for (info in modGroupProfile.msgGroupProfileInfos) {
|
||||
when (info.field) {
|
||||
1 -> {
|
||||
// 群名
|
||||
val new = info.value.encodeToString()
|
||||
|
||||
val group = bot.getGroup(modGroupProfile.groupCode) ?: continue
|
||||
group.checkIsGroupImpl()
|
||||
val old = group.name
|
||||
|
||||
if (new == old) continue
|
||||
|
||||
if (modGroupProfile.cmdUin == bot.id) continue
|
||||
val operator = group[modGroupProfile.cmdUin] ?: continue
|
||||
|
||||
group.settings.nameField = new
|
||||
|
||||
collect(GroupNameChangeEvent(old, new, group, operator))
|
||||
}
|
||||
2 -> {
|
||||
// 头像
|
||||
// top_package/akkz.java:3446
|
||||
/*
|
||||
var4 = var82.byteAt(0);
|
||||
short var3 = (short) (var82.byteAt(1) | var4 << 8);
|
||||
var85 = var18.method_77927(var7 + "");
|
||||
var85.troopface = var3;
|
||||
var85.hasSetNewTroopHead = true;
|
||||
*/
|
||||
// bot.logger.debug(
|
||||
// contextualBugReportException(
|
||||
// "解析 Transformers528 0x27L ModGroupProfile 群头像修改",
|
||||
// forDebug = "this=${this._miraiContentToString()}"
|
||||
// )
|
||||
// )
|
||||
}
|
||||
3 -> { // troop.credit.data
|
||||
// top_package/akkz.java:3475
|
||||
// top_package/akkz.java:3498
|
||||
// bot.logger.debug(
|
||||
// contextualBugReportException(
|
||||
// "解析 Transformers528 0x27L ModGroupProfile 群 troop.credit.data",
|
||||
// forDebug = "this=${this._miraiContentToString()}"
|
||||
// )
|
||||
// )
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see MemberCardChangeEvent
|
||||
*/
|
||||
private fun PipelineContext.handleGroupMemberProfileChanged(
|
||||
modGroupMemberProfile: Submsgtype0x27.SubMsgType0x27.ModGroupMemberProfile
|
||||
) {
|
||||
for (info in modGroupMemberProfile.msgGroupMemberProfileInfos) {
|
||||
when (info.field) {
|
||||
1 -> { // name card
|
||||
val new = info.value
|
||||
val group = bot.getGroup(modGroupMemberProfile.groupCode) ?: continue
|
||||
group.checkIsGroupImpl()
|
||||
val member = group[modGroupMemberProfile.uin] ?: continue
|
||||
member.checkIsMemberImpl()
|
||||
|
||||
val old = member.nameCard
|
||||
|
||||
if (new == old) continue
|
||||
member._nameCard = new
|
||||
|
||||
collect(MemberCardChangeEvent(old, new, member))
|
||||
}
|
||||
2 -> {
|
||||
if (info.value.singleOrNull()?.code != 0) {
|
||||
bot.logger.debug {
|
||||
"Unknown Transformers528 0x27L ModGroupMemberProfile, field=${info.field}, value=${info.value}"
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
else -> {
|
||||
bot.logger.debug {
|
||||
"Unknown Transformers528 0x27L ModGroupMemberProfile, field=${info.field}, value=${info.value}"
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MsgType0x2DC
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {
|
||||
when (data.kind) {
|
||||
0x0C -> processMute(data)
|
||||
@ -164,16 +285,17 @@ internal class GroupNotificationProcessor : MixedNoticeProcessor(), NewContactSu
|
||||
* @see NudgeEvent
|
||||
* @see MemberHonorChangeEvent
|
||||
* @see GroupTalkativeChangeEvent
|
||||
*/
|
||||
*/ // gray tip: 聊天中的灰色小框系统提示信息
|
||||
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 -> {
|
||||
//预置数据,服务器将不会提供己方已知消息
|
||||
// group nudge
|
||||
// 预置数据,服务器将不会提供己方已知消息
|
||||
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
|
||||
@ -211,3 +333,7 @@ internal class GroupNotificationProcessor : MixedNoticeProcessor(), NewContactSu
|
||||
}
|
||||
|
||||
internal operator fun List<TroopTips0x857.TemplParam>.get(name: String) = this.findLast { it.name == name }?.value
|
||||
|
||||
@JvmName("get2")
|
||||
internal operator fun List<Submsgtype0x122.Submsgtype0x122.TemplParam>.get(name: String) =
|
||||
this.findLast { it.name == name }?.value
|
||||
|
@ -12,6 +12,9 @@ package net.mamoe.mirai.internal.network.notice.priv
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readUByte
|
||||
import kotlinx.io.core.readUShort
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.contact.impl
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
@ -19,17 +22,21 @@ import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.toMiraiFriendInfo
|
||||
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
|
||||
import net.mamoe.mirai.internal.network.components.PipelineContext
|
||||
import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.msgInfo
|
||||
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.Submsgtype0x115.SubMsgType0x115
|
||||
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.Submsgtype0x44.Submsgtype0x44
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0xb3.SubMsgType0xb3
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList.GetFriendGroupList
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
|
||||
import net.mamoe.mirai.internal.utils._miraiContentToString
|
||||
import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||
import net.mamoe.mirai.utils.*
|
||||
|
||||
@ -113,10 +120,67 @@ internal class FriendNoticeProcessor(
|
||||
val body = vProtobuf.loadAs(SubMsgType0x115.MsgBody.serializer())
|
||||
handleInputStatusChanged(body)
|
||||
}
|
||||
0x122L -> {
|
||||
val body = vProtobuf.loadAs(Submsgtype0x122.Submsgtype0x122.MsgBody.serializer())
|
||||
when (body.templId) {
|
||||
//戳一戳
|
||||
1132L, 1133L, 1134L, 1135L, 1136L, 10043L -> handlePrivateNudge(body)
|
||||
}
|
||||
}
|
||||
0x8AL -> {
|
||||
val body = vProtobuf.loadAs(Sub8A.serializer())
|
||||
processFriendRecall(body)
|
||||
}
|
||||
else -> markNotConsumed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Serializable
|
||||
private class Wording(
|
||||
@ProtoNumber(1) val itemID: Int = 0,
|
||||
@ProtoNumber(2) val itemName: String = "",
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
private class Sub8AMsgInfo(
|
||||
@ProtoNumber(1) val fromUin: Long,
|
||||
@ProtoNumber(2) val botUin: Long,
|
||||
@ProtoNumber(3) val srcId: Int,
|
||||
@ProtoNumber(4) val srcInternalId: Long,
|
||||
@ProtoNumber(5) val time: Long,
|
||||
@ProtoNumber(6) val random: Int,
|
||||
@ProtoNumber(7) val pkgNum: Int, // 1
|
||||
@ProtoNumber(8) val pkgIndex: Int, // 0
|
||||
@ProtoNumber(9) val devSeq: Int, // 0
|
||||
@ProtoNumber(12) val flag: Int, // 1
|
||||
@ProtoNumber(13) val wording: Wording,
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
private class Sub8A(
|
||||
@ProtoNumber(1) val msgInfo: List<Sub8AMsgInfo>,
|
||||
@ProtoNumber(2) val appId: Int, // 1
|
||||
@ProtoNumber(3) val instId: Int, // 1
|
||||
@ProtoNumber(4) val longMessageFlag: Int, // 0
|
||||
@ProtoNumber(5) val reserved: ByteArray? = null, // struct{ boolean(1), boolean(2) }
|
||||
) : ProtoBuf
|
||||
|
||||
private fun PipelineContext.processFriendRecall(body: Sub8A) {
|
||||
for (info in body.msgInfo) {
|
||||
if (info.botUin != bot.id) continue
|
||||
collected += MessageRecallEvent.FriendRecall(
|
||||
bot = bot,
|
||||
messageIds = intArrayOf(info.srcId),
|
||||
messageInternalIds = intArrayOf(info.srcInternalId.toInt()),
|
||||
messageTime = info.time.toInt(),
|
||||
operatorId = info.fromUin,
|
||||
operator = bot.getFriend(info.fromUin) ?: continue,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun PipelineContext.handleInputStatusChanged(body: SubMsgType0x115.MsgBody) {
|
||||
val friend = bot.getFriend(body.fromUin) ?: return
|
||||
val item = body.msgNotifyItem ?: return
|
||||
@ -203,4 +267,23 @@ internal class FriendNoticeProcessor(
|
||||
collect(FriendAddEvent(added))
|
||||
if (removed != null) collect(StrangerRelationChangeEvent.Friended(removed, added))
|
||||
}
|
||||
|
||||
private fun PipelineContext.handlePrivateNudge(body: Submsgtype0x122.Submsgtype0x122.MsgBody) {
|
||||
val action = body.msgTemplParam["action_str"].orEmpty()
|
||||
val from = body.msgTemplParam["uin_str1"]?.findFriendOrStranger() ?: bot.asFriend
|
||||
val target = body.msgTemplParam["uin_str2"]?.findFriendOrStranger() ?: bot.asFriend
|
||||
val suffix = body.msgTemplParam["suffix_str"].orEmpty()
|
||||
|
||||
val subject: User = bot.getFriend(msgInfo.lFromUin)
|
||||
?: bot.getStranger(msgInfo.lFromUin)
|
||||
?: return
|
||||
|
||||
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 = subject,
|
||||
)
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ import net.mamoe.mirai.utils.context
|
||||
* @see GroupTempMessageEvent
|
||||
* @see GroupTempMessageSyncEvent
|
||||
*/
|
||||
internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg>(type()) {
|
||||
internal class PrivateMessageProcessor : SimpleNoticeProcessor<MsgComm.Msg>(type()) {
|
||||
override suspend fun PipelineContext.processImpl(data: MsgComm.Msg) = data.context {
|
||||
markAsConsumed()
|
||||
if (msgHead.fromUin == bot.id && fromSync) {
|
@ -408,8 +408,8 @@ internal class Submsgtype0x122 {
|
||||
|
||||
@Serializable
|
||||
internal class TemplParam(
|
||||
@ProtoNumber(1) @JvmField val name: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoNumber(2) @JvmField val value: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoNumber(1) @JvmField val name: String = "",
|
||||
@ProtoNumber(2) @JvmField val value: String = "",
|
||||
) : ProtoBuf
|
||||
}
|
||||
}
|
||||
|
@ -10,36 +10,23 @@
|
||||
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.event.events.GroupNameChangeEvent
|
||||
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.contact.GroupImpl
|
||||
import net.mamoe.mirai.internal.contact.checkIsGroupImpl
|
||||
import net.mamoe.mirai.internal.contact.checkIsMemberImpl
|
||||
import net.mamoe.mirai.internal.network.MultiPacket
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
|
||||
import net.mamoe.mirai.internal.network.handler.logger
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
|
||||
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.proto.Submsgtype0x122
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27.SubMsgType0x27.*
|
||||
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.buildResponseUniPacket
|
||||
import net.mamoe.mirai.internal.utils._miraiContentToString
|
||||
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.readUniPacket
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.writeJceRequestPacket
|
||||
import net.mamoe.mirai.utils.debug
|
||||
import net.mamoe.mirai.utils.encodeToString
|
||||
|
||||
|
||||
//0C 01 B1 89 BE 09 5E 3D 72 A6 00 01 73 68 FC 06 00 00 00 3C
|
||||
@ -206,37 +193,6 @@ internal inline fun lambda528(crossinline block: suspend MsgType0x210.(QQAndroid
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
private class Wording(
|
||||
@ProtoNumber(1) val itemID: Int = 0,
|
||||
@ProtoNumber(2) val itemName: String = "",
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
private class Sub8AMsgInfo(
|
||||
@ProtoNumber(1) val fromUin: Long,
|
||||
@ProtoNumber(2) val botUin: Long,
|
||||
@ProtoNumber(3) val srcId: Int,
|
||||
@ProtoNumber(4) val srcInternalId: Long,
|
||||
@ProtoNumber(5) val time: Long,
|
||||
@ProtoNumber(6) val random: Int,
|
||||
@ProtoNumber(7) val pkgNum: Int, // 1
|
||||
@ProtoNumber(8) val pkgIndex: Int, // 0
|
||||
@ProtoNumber(9) val devSeq: Int, // 0
|
||||
@ProtoNumber(12) val flag: Int, // 1
|
||||
@ProtoNumber(13) val wording: Wording,
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
private class Sub8A(
|
||||
@ProtoNumber(1) val msgInfo: List<Sub8AMsgInfo>,
|
||||
@ProtoNumber(2) val appId: Int, // 1
|
||||
@ProtoNumber(3) val instId: Int, // 1
|
||||
@ProtoNumber(4) val longMessageFlag: Int, // 0
|
||||
@ProtoNumber(5) val reserved: ByteArray? = null, // struct{ boolean(1), boolean(2) }
|
||||
) : ProtoBuf
|
||||
|
||||
|
||||
// uSubMsgType to vProtobuf
|
||||
// 138 or 139: top_package/akln.java:1568
|
||||
// 66: top_package/nhz.java:269
|
||||
@ -247,18 +203,7 @@ private class Sub8A(
|
||||
internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
||||
|
||||
0x8AL to lambda528 { bot ->
|
||||
|
||||
return@lambda528 vProtobuf.loadAs(Sub8A.serializer()).msgInfo.asSequence()
|
||||
.filter { it.botUin == bot.id }.mapNotNull { info ->
|
||||
MessageRecallEvent.FriendRecall(
|
||||
bot = bot,
|
||||
messageIds = intArrayOf(info.srcId),
|
||||
messageInternalIds = intArrayOf(info.srcInternalId.toInt()),
|
||||
messageTime = info.time.toInt(),
|
||||
operatorId = info.fromUin,
|
||||
operator = bot.getFriend(info.fromUin) ?: return@mapNotNull null,
|
||||
)
|
||||
}
|
||||
TODO("removed")
|
||||
},
|
||||
|
||||
//戳一戳信息等
|
||||
@ -267,45 +212,7 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
||||
when (body.templId) {
|
||||
//戳一戳
|
||||
1132L, 1133L, 1134L, 1135L, 1136L, 10043L -> {
|
||||
//预置数据,服务器将不会提供己方已知消息
|
||||
var from: User? = null
|
||||
var action = ""
|
||||
var target: User? = null
|
||||
var suffix = ""
|
||||
body.msgTemplParam.asSequence().map { param ->
|
||||
param.name.decodeToString() to param.value.decodeToString()
|
||||
}.forEach { (key, value) ->
|
||||
when (key) {
|
||||
"action_str" -> action = value
|
||||
"uin_str1" -> from = bot.getFriend(value.toLong()) ?: bot.getStranger(value.toLong())
|
||||
?: return@lambda528 emptySequence()
|
||||
"uin_str2" -> target = bot.getFriend(value.toLong()) ?: bot.getStranger(value.toLong())
|
||||
?: return@lambda528 emptySequence()
|
||||
"suffix_str" -> suffix = value
|
||||
}
|
||||
}
|
||||
|
||||
val subject: User = bot.getFriend(msgInfo.lFromUin)
|
||||
?: bot.getStranger(msgInfo.lFromUin)
|
||||
?: return@lambda528 emptySequence()
|
||||
|
||||
sequenceOf(
|
||||
when {
|
||||
target == null && from == null || target?.id == from?.id && from?.id == bot.id -> {
|
||||
//机器人自己戳自己
|
||||
NudgeEvent(from = bot, target = bot, subject = subject, action, suffix)
|
||||
}
|
||||
target == null || target!!.id == bot.id -> {
|
||||
//机器人自身为目标
|
||||
NudgeEvent(from = subject, target = bot, subject = subject, action, suffix)
|
||||
}
|
||||
from == null || from!!.id == bot.id -> {
|
||||
//机器人自身为发起者
|
||||
NudgeEvent(from = bot, target = subject, subject = subject, action, suffix)
|
||||
}
|
||||
else -> NudgeEvent(from = subject, target = subject, subject = subject, action, suffix)
|
||||
},
|
||||
)
|
||||
TODO("removed")
|
||||
}
|
||||
else -> {
|
||||
bot.logger.debug {
|
||||
@ -317,113 +224,6 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
||||
},
|
||||
// 群相关, ModFriendRemark, DelFriend, ModGroupProfile
|
||||
0x27L to lambda528 { bot ->
|
||||
fun ModGroupProfile.transform(bot: QQAndroidBot): Sequence<Packet> {
|
||||
return this.msgGroupProfileInfos.asSequence().mapNotNull { info ->
|
||||
when (info.field) {
|
||||
1 -> {
|
||||
// 群名
|
||||
val new = info.value.encodeToString()
|
||||
|
||||
val group = bot.getGroup(this.groupCode) ?: return@mapNotNull null
|
||||
group.checkIsGroupImpl()
|
||||
val old = group.name
|
||||
|
||||
if (new == old) return@mapNotNull null
|
||||
|
||||
val operator = if (this.cmdUin == bot.id) null
|
||||
else group[this.cmdUin] ?: return@mapNotNull null
|
||||
|
||||
group.settings.nameField = new
|
||||
|
||||
return@mapNotNull GroupNameChangeEvent(old, new, group, operator)
|
||||
}
|
||||
2 -> {
|
||||
// 头像
|
||||
// top_package/akkz.java:3446
|
||||
/*
|
||||
var4 = var82.byteAt(0);
|
||||
short var3 = (short) (var82.byteAt(1) | var4 << 8);
|
||||
var85 = var18.method_77927(var7 + "");
|
||||
var85.troopface = var3;
|
||||
var85.hasSetNewTroopHead = true;
|
||||
*/
|
||||
// bot.logger.debug(
|
||||
// contextualBugReportException(
|
||||
// "解析 Transformers528 0x27L ModGroupProfile 群头像修改",
|
||||
// forDebug = "this=${this._miraiContentToString()}"
|
||||
// )
|
||||
// )
|
||||
null
|
||||
}
|
||||
3 -> { // troop.credit.data
|
||||
// top_package/akkz.java:3475
|
||||
// top_package/akkz.java:3498
|
||||
// bot.logger.debug(
|
||||
// contextualBugReportException(
|
||||
// "解析 Transformers528 0x27L ModGroupProfile 群 troop.credit.data",
|
||||
// forDebug = "this=${this._miraiContentToString()}"
|
||||
// )
|
||||
// )
|
||||
null
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ModGroupMemberProfile.transform(bot: QQAndroidBot): Sequence<Packet> {
|
||||
return this.msgGroupMemberProfileInfos.asSequence().mapNotNull { info ->
|
||||
when (info.field) {
|
||||
1 -> { // name card
|
||||
val new = info.value
|
||||
val group = bot.getGroup(this.groupCode) ?: return@mapNotNull null
|
||||
group.checkIsGroupImpl()
|
||||
val member = group[this.uin] ?: return@mapNotNull null
|
||||
member.checkIsMemberImpl()
|
||||
|
||||
val old = member.nameCard
|
||||
|
||||
if (new == old) return@mapNotNull null
|
||||
member._nameCard = new
|
||||
|
||||
return@mapNotNull MemberCardChangeEvent(old, new, member)
|
||||
}
|
||||
2 -> {
|
||||
if (info.value.singleOrNull()?.code != 0) {
|
||||
bot.logger.debug {
|
||||
"Unknown Transformers528 0x27L ModGroupMemberProfile, field=${info.field}, value=${info.value}"
|
||||
}
|
||||
}
|
||||
return@mapNotNull null
|
||||
}
|
||||
else -> {
|
||||
bot.logger.debug {
|
||||
"Unknown Transformers528 0x27L ModGroupMemberProfile, field=${info.field}, value=${info.value}"
|
||||
}
|
||||
return@mapNotNull null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return@lambda528 vProtobuf.loadAs(SubMsgType0x27MsgBody.serializer()).msgModInfos.asSequence()
|
||||
.flatMap {
|
||||
when {
|
||||
it.msgModFriendRemark != null -> TODO("removed")
|
||||
it.msgDelFriend != null -> TODO("removed")
|
||||
it.msgModGroupProfile != null -> it.msgModGroupProfile.transform(bot)
|
||||
it.msgModGroupMemberProfile != null -> it.msgModGroupMemberProfile.transform(bot)
|
||||
it.msgModCustomFace != null -> TODO("removed")
|
||||
it.msgModProfile != null -> TODO("removed")
|
||||
else -> {
|
||||
bot.network.logger.debug {
|
||||
"Transformers528 0x27L: new data: ${it._miraiContentToString()}"
|
||||
}
|
||||
emptySequence()
|
||||
}
|
||||
}
|
||||
}
|
||||
// 0A 1C 10 28 4A 18 0A 16 08 00 10 A2 FF 8C F0 03 1A 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B
|
||||
TODO("removed")
|
||||
},
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user