diff --git a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api index b30c5713b..b217dd6d0 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -2813,7 +2813,7 @@ public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : ne public fun toString ()Ljava/lang/String; } -public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent { +public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/internal/network/Packet { public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Lnet/mamoe/mirai/contact/NormalMember; diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index b96c341b3..903300c3f 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -2813,7 +2813,7 @@ public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : ne public fun toString ()Ljava/lang/String; } -public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent { +public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/internal/network/Packet { public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Lnet/mamoe/mirai/contact/NormalMember; diff --git a/docs/EventList.md b/docs/EventList.md index dcaf85192..e3053e459 100644 --- a/docs/EventList.md +++ b/docs/EventList.md @@ -85,7 +85,7 @@ ##### 名片和头衔 - 成员群名片改动: MemberCardChangeEvent -- 成员群头衔改动: MemberSpecialTitleChangeEvent +- 成员群特殊头衔改动: MemberSpecialTitleChangeEvent ##### 成员权限 - 成员权限改变: MemberPermissionChangeEvent diff --git a/mirai-core-api/src/commonMain/kotlin/contact/Member.kt b/mirai-core-api/src/commonMain/kotlin/contact/Member.kt index 200cae299..e8b5d0cab 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/Member.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/Member.kt @@ -57,7 +57,7 @@ public interface Member : User { public val nameCard: String /** - * 群头衔. + * 群特殊头衔. * * 为 [AnonymousMember] 时一定是 `"匿名"` * diff --git a/mirai-core-api/src/commonMain/kotlin/contact/NormalMember.kt b/mirai-core-api/src/commonMain/kotlin/contact/NormalMember.kt index 44583b038..a35a56cb0 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/NormalMember.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/NormalMember.kt @@ -49,13 +49,13 @@ public interface NormalMember : Member { public override var nameCard: String /** - * 群头衔. + * 群特殊头衔. * - * 仅群主可以修改群头衔. + * 仅群主可以修改群特殊头衔. * * 在修改时将会异步上传至服务器. * - * @see MemberSpecialTitleChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件. + * @see MemberSpecialTitleChangeEvent 群特殊头衔被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件. * @throws PermissionDeniedException 无权限修改时 */ public override var specialTitle: String diff --git a/mirai-core-api/src/commonMain/kotlin/data/GroupInfo.kt b/mirai-core-api/src/commonMain/kotlin/data/GroupInfo.kt index 164d1605c..348d74b8b 100644 --- a/mirai-core-api/src/commonMain/kotlin/data/GroupInfo.kt +++ b/mirai-core-api/src/commonMain/kotlin/data/GroupInfo.kt @@ -73,7 +73,7 @@ public interface GroupInfo { /* /** - * 机器人的头衔 + * 机器人的特殊头衔 */ val botSpecialTitle: String diff --git a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt index 29c423656..064a50051 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -492,7 +492,9 @@ public data class MemberCardChangeEvent @MiraiInternalApi constructor( ) : GroupMemberEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent /** - * 成员群头衔改动. 一定为群主操作 + * 成员群特殊头衔改动. 一定为群主操作 + * + * 由于服务器并不会告知特殊头衔的重置, 因此此事件在特殊头衔重置后只能由 mirai 在发现变动时才广播 */ public data class MemberSpecialTitleChangeEvent @MiraiInternalApi constructor( /** @@ -513,7 +515,7 @@ public data class MemberSpecialTitleChangeEvent @MiraiInternalApi constructor( * 为 null 时则是机器人操作. */ public override val operator: NormalMember? -) : GroupMemberEvent, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent +) : GroupMemberEvent, GroupOperableEvent, AbstractEvent(), Packet, GroupMemberInfoChangeEvent // endregion diff --git a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupMessageProcessor.kt b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupMessageProcessor.kt index c4d4cf9f9..a515416c1 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupMessageProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupMessageProcessor.kt @@ -16,6 +16,7 @@ import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.events.GroupMessageEvent import net.mamoe.mirai.event.events.GroupMessageSyncEvent import net.mamoe.mirai.event.events.MemberCardChangeEvent +import net.mamoe.mirai.event.events.MemberSpecialTitleChangeEvent import net.mamoe.mirai.internal.contact.GroupImpl import net.mamoe.mirai.internal.contact.NormalMemberImpl import net.mamoe.mirai.internal.contact.info @@ -124,6 +125,14 @@ internal class GroupMessageProcessor( sender.info?.castOrNull()?.run { lastSpeakTimestamp = currentTimeSeconds().toInt() } + sender.castOrNull()?.run { + val specialTitleNow = extraInfo?.senderTitle?.decodeToString().orEmpty() + if (specialTitle != specialTitleNow) { + //群特殊头衔 只有群主才能进行操作 + collect(MemberSpecialTitleChangeEvent(specialTitle, specialTitleNow, this, group.owner)) + _specialTitle = specialTitleNow + } + } if (isFromSelfAccount) { collect( @@ -137,7 +146,6 @@ internal class GroupMessageProcessor( ) return } else { - broadcastNameCardChangedEventIfNecessary(sender, nameCard) collect( diff --git a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt index 5d072acad..c8310886b 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -12,6 +12,7 @@ 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.contact.getMember import net.mamoe.mirai.data.GroupHonorType import net.mamoe.mirai.event.events.* import net.mamoe.mirai.internal.QQAndroidBot @@ -29,6 +30,7 @@ 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.internal.utils.parseToMessageDataList import net.mamoe.mirai.utils.* internal class GroupNotificationProcessor( @@ -158,8 +160,8 @@ internal class GroupNotificationProcessor( when (data.kind) { 0x0C -> processMute(data) 0x0E -> processAllowAnonymousChat(data) - 0x10 -> processAllowConfessTask(data) - 0x14 -> processGrayTip(data) + 0x10 -> processNormalGrayTip(data) + 0x14 -> processGeneralGrayTip(data) } } @@ -249,8 +251,10 @@ internal class GroupNotificationProcessor( /** * @see GroupAllowConfessTalkEvent + * @see MemberSpecialTitleChangeEvent */ - private fun NoticePipelineContext.processAllowConfessTask( + //gray tip: 聊天中的灰色小框系统提示信息(无通用模板,为混合xml代码的文本) + private fun NoticePipelineContext.processNormalGrayTip( data: MsgType0x2DC, ) = data.context { val proto = data.buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), offset = 1) @@ -260,10 +264,10 @@ internal class GroupNotificationProcessor( val tipsInfo = proto.optMsgGraytips ?: return val message = tipsInfo.optBytesContent.decodeToString() - // 机器人信息 when (tipsInfo.robotGroupOpt) { - // others + // 非机器人信息 0 -> { + //坦白说开关 if (message.endsWith("群聊坦白说")) { val new = when (message) { "管理员已关闭群聊坦白说" -> false @@ -274,6 +278,29 @@ internal class GroupNotificationProcessor( } } collect(GroupAllowConfessTalkEvent(new, !new, group, false)) + //群特殊头衔授予 + } else if (message.endsWith(">头衔")) { + message.parseToMessageDataList().let { seq -> + if (seq.count() == 2) { + val uin = seq.first().data.toLong() + val newTitle = seq.last().text + val member = group.getMember(uin) ?: return@let + member.checkIsMemberImpl() + collect( + MemberSpecialTitleChangeEvent( + member.specialTitle, + newTitle, + member, + group.owner + ) + ) + member._specialTitle = newTitle + } else { + logger.debug { "Unknown server special title messages $message" } + return + } + + } } } } @@ -286,8 +313,9 @@ internal class GroupNotificationProcessor( * @see NudgeEvent * @see MemberHonorChangeEvent * @see GroupTalkativeChangeEvent - */ // gray tip: 聊天中的灰色小框系统提示信息 - private fun NoticePipelineContext.processGrayTip( + */ + // general gray tip: 聊天中的灰色小框系统提示信息(有通用模板) + private fun NoticePipelineContext.processGeneralGrayTip( data: MsgType0x2DC, ) = data.context { val grayTip = buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), 1).optGeneralGrayTip @@ -323,6 +351,7 @@ internal class GroupNotificationProcessor( collect(MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE)) } } + // else -> { markNotConsumed() logger.debug { diff --git a/mirai-core/src/commonMain/kotlin/utils/string.kt b/mirai-core/src/commonMain/kotlin/utils/string.kt index e36aa5f1e..65a8a88a9 100644 --- a/mirai-core/src/commonMain/kotlin/utils/string.kt +++ b/mirai-core/src/commonMain/kotlin/utils/string.kt @@ -36,11 +36,12 @@ internal fun MessageData.toMemberInfo() = MemberInfoImpl( @Suppress("RegExpRedundantEscape") internal val extraJsonPattern = Regex("<(\\{.*?\\})>") +internal val jsonInstance = Json { ignoreUnknownKeys = true } @MiraiInternalApi internal fun String.parseToMessageDataList(): Sequence { return extraJsonPattern.findAll(this).filter { it.groups.size == 2 }.mapNotNull { result -> - Json.decodeFromString(MessageData.serializer(), result.groups[1]!!.value) + jsonInstance.decodeFromString(MessageData.serializer(), result.groups[1]!!.value) } }