From 3b779b58b067171800de5dbda0336e03e3461c46 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Wed, 5 Jul 2023 20:00:12 +0800 Subject: [PATCH 01/20] fix: honor event --- .../kotlin/network/notice/group/GroupNotificationProcessor.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 b59a4bb047f..7b058e69dc5 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -376,14 +376,14 @@ internal class GroupNotificationProcessor( } } // 群聊之火 - 1052L, 1129L -> { + 1052L, 1129L, 10095L -> { val now = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember now.info.honors += GroupHonorType.PERFORMER collect(MemberHonorChangeEvent.Achieve(now, GroupHonorType.PERFORMER)) } // 群聊炽焰 - 1055L -> { + 1055L, 10096L -> { val now = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember now.info.honors -= GroupHonorType.PERFORMER From 77ec3ebea8e6ef7a878cce7e703fbe3431d2156f Mon Sep 17 00:00:00 2001 From: cssxsh Date: Wed, 5 Jul 2023 20:26:10 +0800 Subject: [PATCH 02/20] fix: honor event --- mirai-core-api/src/commonMain/kotlin/event/events/group.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0d642caef03..909e1b7ae86 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -570,7 +570,7 @@ public data class MemberUnmuteEvent @MiraiInternalApi constructor( // region 群荣誉 /** - * [Member] 荣誉改变时的事件, 目前只支持龙王 + * [Member] 荣誉改变时的事件 */ @MiraiExperimentalApi public sealed class MemberHonorChangeEvent : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent() { From 16d3233890c1e27d20d1399742654467dcb88452 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Wed, 5 Jul 2023 20:27:12 +0800 Subject: [PATCH 03/20] feat: MemberTemperatureTitleChangeEvent --- .../commonMain/kotlin/event/events/group.kt | 22 +++++++++++++++++++ .../group/GroupNotificationProcessor.kt | 14 +++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) 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 909e1b7ae86..43ea1f273b1 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -631,6 +631,28 @@ public data class GroupTalkativeChangeEvent( public val previous: NormalMember ) : Packet, GroupEvent, BotPassiveEvent, AbstractEvent() +/** + * [Member] 活跃度头衔改变时的事件,目前只有 Bot 自身会触发 + */ +public class MemberTemperatureTitleChangeEvent( + /** + * 改变活跃度头衔的群成员 + */ + public override val member: NormalMember, + /** + * 活跃度 + */ + public val temperature: Int, + /** + * 当前头衔 + */ + public val title: String +) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { + override fun toString(): String { + return "MemberTemperatureTitleChangeEvent(group=${group.id}, member=${member.id}, temperature=${temperature}, title=${title})" + } +} + // endregion // endregion 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 7b058e69dc5..1c50a6385bb 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -411,7 +411,19 @@ internal class GroupNotificationProcessor( collect(MemberHonorChangeEvent.Achieve(now, GroupHonorType.RED_PACKET)) } } - // + // 等级头衔 + 10097L -> { + // XXX: 目前只有机器人本身会触发 + val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember + val level = grayTip.msgTemplParam["level"]?.removePrefix("LV")?.toInt() ?: 1 + val title = grayTip.msgTemplParam["title"] ?: grayTip.msgTemplParam["level"] ?: "" + + collected += MemberTemperatureTitleChangeEvent( + member = user, + temperature = level, + title = title + ) + } else -> { markNotConsumed() logger.debug { From f467df45027a1a27f25f9d0443bb12631c50a37f Mon Sep 17 00:00:00 2001 From: cssxsh Date: Wed, 5 Jul 2023 20:38:38 +0800 Subject: [PATCH 04/20] feat: MemberReceivedEvent --- .../commonMain/kotlin/event/events/group.kt | 44 ++++++++++++++----- .../group/GroupNotificationProcessor.kt | 6 +++ 2 files changed, 38 insertions(+), 12 deletions(-) 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 43ea1f273b1..bee6fb7b398 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -520,6 +520,29 @@ public data class MemberSpecialTitleChangeEvent @MiraiInternalApi constructor( public override val operator: NormalMember? ) : GroupMemberEvent, GroupOperableEvent, AbstractEvent(), Packet, GroupMemberInfoChangeEvent +/** + * [Member] 活跃度头衔改变时的事件,目前只有 Bot 自身会触发 + */ +@MiraiExperimentalApi +public class MemberTemperatureTitleChangeEvent( + /** + * 改变活跃度头衔的群成员 + */ + public override val member: NormalMember, + /** + * 活跃度 + */ + public val temperature: Int, + /** + * 当前头衔 + */ + public val title: String +) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { + override fun toString(): String { + return "MemberTemperatureTitleChangeEvent(group=${group.id}, member=${member.id}, temperature=${temperature}, title=${title})" + } +} + // endregion @@ -631,25 +654,22 @@ public data class GroupTalkativeChangeEvent( public val previous: NormalMember ) : Packet, GroupEvent, BotPassiveEvent, AbstractEvent() +// endregion + +// region 群待办 + /** - * [Member] 活跃度头衔改变时的事件,目前只有 Bot 自身会触发 + * [Member] 完成群待办事件,可能会在成员阅读完群公告(待办)时触发 */ -public class MemberTemperatureTitleChangeEvent( +@MiraiExperimentalApi +public class MemberReceivedEvent( /** - * 改变活跃度头衔的群成员 + * 完成群待办的群成员 */ public override val member: NormalMember, - /** - * 活跃度 - */ - public val temperature: Int, - /** - * 当前头衔 - */ - public val title: String ) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { override fun toString(): String { - return "MemberTemperatureTitleChangeEvent(group=${group.id}, member=${member.id}, temperature=${temperature}, title=${title})" + return "MemberReceivedEvent(group=${group.id}, member=${member.id})" } } 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 1c50a6385bb..f040d74c299 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -358,6 +358,12 @@ internal class GroupNotificationProcessor( rank = rank ) } + // 群待办 + 10134L, 10135L -> { + // 阅读群公告可能会触发 + val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember + collected += MemberReceivedEvent(member = user) + } // 龙王 10093L, 10094L, 1053L, 1054L, 1103L -> { val now = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember From f2d09c7cfe275e8a74c2e11b3a3435ea36f75408 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Fri, 14 Jul 2023 09:25:37 +0800 Subject: [PATCH 05/20] fix: style --- .../src/commonMain/kotlin/event/events/group.kt | 11 +++-------- .../notice/group/GroupNotificationProcessor.kt | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) 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 bee6fb7b398..87925eb1316 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -523,7 +523,6 @@ public data class MemberSpecialTitleChangeEvent @MiraiInternalApi constructor( /** * [Member] 活跃度头衔改变时的事件,目前只有 Bot 自身会触发 */ -@MiraiExperimentalApi public class MemberTemperatureTitleChangeEvent( /** * 改变活跃度头衔的群成员 @@ -534,7 +533,7 @@ public class MemberTemperatureTitleChangeEvent( */ public val temperature: Int, /** - * 当前头衔 + * 获得头衔 */ public val title: String ) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { @@ -545,7 +544,6 @@ public class MemberTemperatureTitleChangeEvent( // endregion - // region 成员权限 /** @@ -559,7 +557,6 @@ public data class MemberPermissionChangeEvent @MiraiInternalApi constructor( // endregion - // region 禁言 /** @@ -595,7 +592,6 @@ public data class MemberUnmuteEvent @MiraiInternalApi constructor( /** * [Member] 荣誉改变时的事件 */ -@MiraiExperimentalApi public sealed class MemberHonorChangeEvent : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent() { /** * 改变荣誉的群成员 @@ -661,15 +657,14 @@ public data class GroupTalkativeChangeEvent( /** * [Member] 完成群待办事件,可能会在成员阅读完群公告(待办)时触发 */ -@MiraiExperimentalApi -public class MemberReceivedEvent( +public class MemberCompleteTodoEvent( /** * 完成群待办的群成员 */ public override val member: NormalMember, ) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { override fun toString(): String { - return "MemberReceivedEvent(group=${group.id}, member=${member.id})" + return "MemberCompleteTodoEvent(group=${group.id}, member=${member.id})" } } 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 f040d74c299..ace094f7ec0 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -362,7 +362,7 @@ internal class GroupNotificationProcessor( 10134L, 10135L -> { // 阅读群公告可能会触发 val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember - collected += MemberReceivedEvent(member = user) + collected += MemberCompleteTodoEvent(member = user) } // 龙王 10093L, 10094L, 1053L, 1054L, 1103L -> { @@ -421,7 +421,7 @@ internal class GroupNotificationProcessor( 10097L -> { // XXX: 目前只有机器人本身会触发 val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember - val level = grayTip.msgTemplParam["level"]?.removePrefix("LV")?.toInt() ?: 1 + val level = grayTip.msgTemplParam["level"]?.removePrefix("LV")?.toIntOrNull() ?: 1 val title = grayTip.msgTemplParam["title"] ?: grayTip.msgTemplParam["level"] ?: "" collected += MemberTemperatureTitleChangeEvent( From b755f3ddeb48c968d21837058b26c223741b47b5 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Fri, 14 Jul 2023 09:54:34 +0800 Subject: [PATCH 06/20] add: api dump --- .../android/api/android.api | 21 +++++++++++++++++++ .../compatibility-validation/jvm/api/jvm.api | 21 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index c3e8c889ae8..3d7530acfa3 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/mirai-core-api/compatibility-validation/android/api/android.api @@ -2570,6 +2570,18 @@ public final class net/mamoe/mirai/event/events/MemberCardChangeEvent : net/mamo public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberCompleteTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public fun toString ()Ljava/lang/String; +} + +public abstract class net/mamoe/mirai/event/events/MemberHonorChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public abstract fun getHonorType ()I + public abstract fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; +} + public final class net/mamoe/mirai/event/events/MemberHonorChangeEvent$Achieve : net/mamoe/mirai/event/events/MemberHonorChangeEvent { public synthetic fun (Lnet/mamoe/mirai/contact/NormalMember;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Lnet/mamoe/mirai/contact/NormalMember; @@ -2761,6 +2773,15 @@ public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent : public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberTemperatureTitleChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;ILjava/lang/String;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public final fun getTemperature ()I + public final fun getTitle ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + public final class net/mamoe/mirai/event/events/MemberUnmuteEvent : 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 ()Lnet/mamoe/mirai/contact/Member; public final fun component2 ()Lnet/mamoe/mirai/contact/Member; diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 202bfe61fb5..6e74c091c90 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/mirai-core-api/compatibility-validation/jvm/api/jvm.api @@ -2570,6 +2570,18 @@ public final class net/mamoe/mirai/event/events/MemberCardChangeEvent : net/mamo public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberCompleteTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public fun toString ()Ljava/lang/String; +} + +public abstract class net/mamoe/mirai/event/events/MemberHonorChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public abstract fun getHonorType ()I + public abstract fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; +} + public final class net/mamoe/mirai/event/events/MemberHonorChangeEvent$Achieve : net/mamoe/mirai/event/events/MemberHonorChangeEvent { public synthetic fun (Lnet/mamoe/mirai/contact/NormalMember;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Lnet/mamoe/mirai/contact/NormalMember; @@ -2761,6 +2773,15 @@ public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent : public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberTemperatureTitleChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;ILjava/lang/String;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public final fun getTemperature ()I + public final fun getTitle ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + public final class net/mamoe/mirai/event/events/MemberUnmuteEvent : 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 ()Lnet/mamoe/mirai/contact/Member; public final fun component2 ()Lnet/mamoe/mirai/contact/Member; From fd16f729fb369084fbd69d878bb12ee86fcbb5ef Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 22 Jul 2023 07:21:30 +0800 Subject: [PATCH 07/20] fix: docs --- mirai-core-api/src/commonMain/kotlin/event/events/group.kt | 2 +- .../kotlin/network/notice/group/GroupNotificationProcessor.kt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) 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 87925eb1316..ce3fea4c567 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -655,7 +655,7 @@ public data class GroupTalkativeChangeEvent( // region 群待办 /** - * [Member] 完成群待办事件,可能会在成员阅读完群公告(待办)时触发 + * [Member] 完成群待办事件,可能会在成员阅读完群待办(公告)时触发 */ public class MemberCompleteTodoEvent( /** 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 ace094f7ec0..68c767013d2 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -360,7 +360,6 @@ internal class GroupNotificationProcessor( } // 群待办 10134L, 10135L -> { - // 阅读群公告可能会触发 val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember collected += MemberCompleteTodoEvent(member = user) } From 2b40cb5a35b7260a0e5df09f865f7ec9671c5384 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 22 Jul 2023 07:31:37 +0800 Subject: [PATCH 08/20] feat: MemberLuckyWordEvent --- .../android/api/android.api | 8 +++++++ .../compatibility-validation/jvm/api/jvm.api | 8 +++++++ .../commonMain/kotlin/event/events/group.kt | 22 +++++++++++++++++++ .../group/GroupNotificationProcessor.kt | 14 ++++++++++++ 4 files changed, 52 insertions(+) diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index 3d7530acfa3..ae5ec2e62cd 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/mirai-core-api/compatibility-validation/android/api/android.api @@ -2726,6 +2726,14 @@ public final class net/mamoe/mirai/event/events/MemberLeaveEvent$Quit : net/mamo public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberLuckyWordEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;Ljava/util/List;)V + public final fun getImages ()Ljava/util/List; + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public fun toString ()Ljava/lang/String; +} + public final class net/mamoe/mirai/event/events/MemberMuteEvent : 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 ()Lnet/mamoe/mirai/contact/Member; public final fun component2 ()I diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 6e74c091c90..5d9790165c2 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/mirai-core-api/compatibility-validation/jvm/api/jvm.api @@ -2726,6 +2726,14 @@ public final class net/mamoe/mirai/event/events/MemberLeaveEvent$Quit : net/mamo public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberLuckyWordEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;Ljava/util/List;)V + public final fun getImages ()Ljava/util/List; + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public fun toString ()Ljava/lang/String; +} + public final class net/mamoe/mirai/event/events/MemberMuteEvent : 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 ()Lnet/mamoe/mirai/contact/Member; public final fun component2 ()I 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 ce3fea4c567..d71a9859213 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -652,6 +652,28 @@ public data class GroupTalkativeChangeEvent( // endregion +// region 群幸运词 + +/** + * [Member] 触发群幸运词事件 + */ +public class MemberLuckyWordEvent( + /** + * 触发群幸运词的群成员 + */ + public override val member: NormalMember, + /** + * 群幸运词的图片链接 + */ + public val images: List +) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { + override fun toString(): String { + return "MemberLuckyWordEvent(group=${group.id}, member=${member.id})" + } +} + +// endregion + // region 群待办 /** 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 68c767013d2..5eae9209aea 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -327,6 +327,20 @@ internal class GroupNotificationProcessor( val grayTip = buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), 1).optGeneralGrayTip markAsConsumed() when (grayTip?.templId) { + // 群幸运词 + 10047L, 10048L -> { + val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember + val images = listOfNotNull( + grayTip.msgTemplParam["img_url"], + grayTip.msgTemplParam["img_url_1"], + grayTip.msgTemplParam["img_url_2"] + ) + + collected += MemberLuckyWordEvent( + member = user, + images = images + ) + } // 群戳一戳 10043L, 1133L, 1132L, 1134L, 1135L, 1136L -> { // group nudge From db214e8e715052f35bb74f6bd5cf465fd3d99575 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 22 Jul 2023 08:21:25 +0800 Subject: [PATCH 09/20] fix: null handle --- .../network/notice/group/GroupNotificationProcessor.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 5eae9209aea..7406bb888f7 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -325,8 +325,9 @@ internal class GroupNotificationProcessor( data: MsgType0x2DC, ) = data.context { val grayTip = buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), 1).optGeneralGrayTip + ?: return@context markAsConsumed() - when (grayTip?.templId) { + when (grayTip.templId) { // 群幸运词 10047L, 10048L -> { val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember @@ -446,7 +447,7 @@ internal class GroupNotificationProcessor( else -> { markNotConsumed() logger.debug { - "Unknown Transformers528 0x14 template\ntemplId=${grayTip?.templId}\nPermList=${grayTip?.msgTemplParam?.structureToString()}" + "Unknown Transformers528 0x14 template\ntemplId=${grayTip.templId}\nPermList=${grayTip.msgTemplParam.structureToString()}" } } } From 24036690f0d941f0b88308655636d1c8abc4d090 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 22 Jul 2023 08:27:21 +0800 Subject: [PATCH 10/20] fix: null handle --- .../kotlin/network/notice/group/GroupNotificationProcessor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7406bb888f7..9c5112d925f 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -325,7 +325,7 @@ internal class GroupNotificationProcessor( data: MsgType0x2DC, ) = data.context { val grayTip = buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), 1).optGeneralGrayTip - ?: return@context + ?: return@context markNotConsumed() markAsConsumed() when (grayTip.templId) { // 群幸运词 From 0babe209693d8688b66aeae08c5586c630a9dca6 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 22 Jul 2023 08:43:08 +0800 Subject: [PATCH 11/20] feat: MemberSetTodoEvent --- .../android/api/android.api | 7 +++++++ .../compatibility-validation/jvm/api/jvm.api | 7 +++++++ .../src/commonMain/kotlin/event/events/group.kt | 14 ++++++++++++++ .../notice/group/GroupNotificationProcessor.kt | 5 ++++- 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index ae5ec2e62cd..5c1560a5ca2 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/mirai-core-api/compatibility-validation/android/api/android.api @@ -2763,6 +2763,13 @@ public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : ne public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberSetTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + 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, net/mamoe/mirai/internal/network/Packet { public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 5d9790165c2..675bdccb2a8 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/mirai-core-api/compatibility-validation/jvm/api/jvm.api @@ -2763,6 +2763,13 @@ public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : ne public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberSetTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + 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, net/mamoe/mirai/internal/network/Packet { public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/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 d71a9859213..993d3793a15 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -676,6 +676,20 @@ public class MemberLuckyWordEvent( // region 群待办 +/** + * [Member] 设置群待办事件 + */ +public class MemberSetTodoEvent( + /** + * 设置群待办的群成员 + */ + public override val member: NormalMember, +) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { + override fun toString(): String { + return "MemberSetTodoEvent(group=${group.id}, member=${member.id})" + } +} + /** * [Member] 完成群待办事件,可能会在成员阅读完群待办(公告)时触发 */ 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 9c5112d925f..8643de340fd 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -376,7 +376,10 @@ internal class GroupNotificationProcessor( // 群待办 10134L, 10135L -> { val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember - collected += MemberCompleteTodoEvent(member = user) + when (grayTip.templId) { + 10134L -> collected += MemberSetTodoEvent(member = user) + 10135L -> collected += MemberCompleteTodoEvent(member = user) + } } // 龙王 10093L, 10094L, 1053L, 1054L, 1103L -> { From 1203a4c24dfedb6d0849ea5f881febf4fa1e8cb1 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Fri, 28 Jul 2023 12:39:12 +0800 Subject: [PATCH 12/20] fix: docs --- mirai-core-api/src/commonMain/kotlin/event/events/group.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 993d3793a15..216e5d9fa91 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -678,6 +678,8 @@ public class MemberLuckyWordEvent( /** * [Member] 设置群待办事件 + * + * 因 QQ 自身限制,无法获取到待办内容 */ public class MemberSetTodoEvent( /** @@ -691,7 +693,9 @@ public class MemberSetTodoEvent( } /** - * [Member] 完成群待办事件,可能会在成员阅读完群待办(公告)时触发 + * [Member] 完成群待办事件,可能会在成员完成群待办时触发 + * + * 因 QQ 自身限制,无法获取到待办内容 */ public class MemberCompleteTodoEvent( /** From 8078c005c536f539a1104698e3a771a3912a04fa Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 5 Aug 2023 17:22:44 +0800 Subject: [PATCH 13/20] feat: MemberRecallTodoEvent --- .../src/commonMain/kotlin/event/events/group.kt | 16 ++++++++++++++++ .../notice/group/GroupNotificationProcessor.kt | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) 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 216e5d9fa91..353c31cd332 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -692,6 +692,22 @@ public class MemberSetTodoEvent( } } +/** + * [Member] 撤回群待办事件 + * + * 因 QQ 自身限制,无法获取到待办内容 + */ +public class MemberRecallTodoEvent( + /** + * 完成群待办的群成员 + */ + public override val member: NormalMember, +) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { + override fun toString(): String { + return "MemberCompleteTodoEvent(group=${group.id}, member=${member.id})" + } +} + /** * [Member] 完成群待办事件,可能会在成员完成群待办时触发 * 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 8643de340fd..fbab306fa51 100644 --- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupNotificationProcessor.kt @@ -374,11 +374,12 @@ internal class GroupNotificationProcessor( ) } // 群待办 - 10134L, 10135L -> { + 10134L, 10135L, 10136L -> { val user = grayTip.msgTemplParam["uin"]?.findMember() ?: group.botAsMember when (grayTip.templId) { 10134L -> collected += MemberSetTodoEvent(member = user) 10135L -> collected += MemberCompleteTodoEvent(member = user) + 10136L -> collected += MemberRecallTodoEvent(member = user) } } // 龙王 From 5dd6c17a2191a0eb91045aed59903e3ccdf070af Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 5 Aug 2023 17:28:12 +0800 Subject: [PATCH 14/20] feat: GroupTodo --- .../src/commonMain/kotlin/contact/Group.kt | 8 + .../kotlin/contact/todo/GroupTodo.kt | 60 +++++ .../kotlin/contact/todo/GroupTodoRecord.kt | 29 +++ .../kotlin/contact/todo/GroupTodoStatus.kt | 14 ++ .../src/contact/todo/MockGroupTodo.kt | 16 ++ .../src/internal/contact/MockGroupImpl.kt | 6 +- .../contact/todo/MockGroupTodoImpl.kt | 57 +++++ .../commonMain/kotlin/contact/GroupImpl.kt | 9 + .../kotlin/contact/todo/GroupTodoImpl.kt | 171 ++++++++++++++ .../network/protocol/data/proto/Oidb0xf8e.kt | 53 +++++ .../network/protocol/data/proto/Oidb0xf90.kt | 47 ++++ .../network/protocol/packet/PacketFactory.kt | 6 + .../protocol/packet/chat/TroopTodoManager.kt | 209 ++++++++++++++++++ 13 files changed, 684 insertions(+), 1 deletion(-) create mode 100644 mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt create mode 100644 mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoRecord.kt create mode 100644 mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoStatus.kt create mode 100644 mirai-core-mock/src/contact/todo/MockGroupTodo.kt create mode 100644 mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt create mode 100644 mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt create mode 100644 mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf8e.kt create mode 100644 mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf90.kt create mode 100644 mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/TroopTodoManager.kt diff --git a/mirai-core-api/src/commonMain/kotlin/contact/Group.kt b/mirai-core-api/src/commonMain/kotlin/contact/Group.kt index fb7826d8ea0..a5d598babee 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/Group.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/Group.kt @@ -20,6 +20,7 @@ import net.mamoe.mirai.contact.announcement.Announcements import net.mamoe.mirai.contact.essence.Essences import net.mamoe.mirai.contact.file.RemoteFiles import net.mamoe.mirai.contact.roaming.RoamingSupported +import net.mamoe.mirai.contact.todo.GroupTodo import net.mamoe.mirai.event.events.* import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.* @@ -237,6 +238,13 @@ public interface Group : Contact, CoroutineScope, FileSupported, AudioSupported, */ public val essences: Essences + /** + * 群待办相关功能接口 + * + * @since 2.16 + */ + public val todo: GroupTodo + public companion object { /** * 将一条消息设置为群精华消息, 需要管理员或群主权限. diff --git a/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt new file mode 100644 index 00000000000..0361ea5b39b --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.contact.todo + +import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge +import net.mamoe.mirai.event.events.MemberCompleteTodoEvent +import net.mamoe.mirai.event.events.MemberRecallTodoEvent +import net.mamoe.mirai.event.events.MemberSetTodoEvent +import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.utils.NotStableForInheritance + +/** + * 表示一个群待办管理. + * + * @since 2.16 + */ +@NotStableForInheritance +@JvmBlockingBridge +public interface GroupTodo { + + public suspend fun status(): GroupTodoStatus + + public suspend fun current(): GroupTodoRecord? + + /** + * @see MemberSetTodoEvent + */ + public suspend fun set(source: MessageSource): GroupTodoRecord + + /** + * @see MemberRecallTodoEvent + */ + public suspend fun recall(source: MessageSource) + + /** + * @see MemberRecallTodoEvent + */ + public suspend fun recall(record: GroupTodoRecord) + + /** + * @see MemberCompleteTodoEvent + */ + public suspend fun complete(source: MessageSource) + + /** + * @see MemberCompleteTodoEvent + */ + public suspend fun complete(record: GroupTodoRecord) + + public suspend fun close(source: MessageSource) + + public suspend fun close(record: GroupTodoRecord) +} \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoRecord.kt b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoRecord.kt new file mode 100644 index 00000000000..ef5831fb376 --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoRecord.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.contact.todo + +import net.mamoe.mirai.contact.Group +import net.mamoe.mirai.contact.NormalMember +import net.mamoe.mirai.utils.MiraiInternalApi + +public class GroupTodoRecord @MiraiInternalApi constructor( + public val group: Group, + public val title: String, + public val operator: NormalMember?, + public val operatorId: Long, + public val operatorNick: String, + public val operatorTime: Int, + @MiraiInternalApi public val msgSeq: Long, + @MiraiInternalApi public val msgRandom: Long +) { + override fun toString(): String { + return "GroupTodoRecord(title=${title}, operator=${operatorId}, group=${group.id}, time=${operatorTime})" + } +} \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoStatus.kt b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoStatus.kt new file mode 100644 index 00000000000..3074628b6a2 --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodoStatus.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.contact.todo + +public enum class GroupTodoStatus { + NONE, COMPLETED, CLOSED +} \ No newline at end of file diff --git a/mirai-core-mock/src/contact/todo/MockGroupTodo.kt b/mirai-core-mock/src/contact/todo/MockGroupTodo.kt new file mode 100644 index 00000000000..21212fc1c1a --- /dev/null +++ b/mirai-core-mock/src/contact/todo/MockGroupTodo.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.mock.contact.todo + +import net.mamoe.mirai.contact.todo.GroupTodo + +public interface MockGroupTodo : GroupTodo { + +} \ No newline at end of file diff --git a/mirai-core-mock/src/internal/contact/MockGroupImpl.kt b/mirai-core-mock/src/internal/contact/MockGroupImpl.kt index b0be49d219d..e777301a66e 100644 --- a/mirai-core-mock/src/internal/contact/MockGroupImpl.kt +++ b/mirai-core-mock/src/internal/contact/MockGroupImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 Mamoe Technologies and contributors. * * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. @@ -32,9 +32,11 @@ import net.mamoe.mirai.mock.contact.MockGroupControlPane import net.mamoe.mirai.mock.contact.MockNormalMember import net.mamoe.mirai.mock.contact.active.MockGroupActive import net.mamoe.mirai.mock.contact.essence.MockEssences +import net.mamoe.mirai.mock.contact.todo.MockGroupTodo import net.mamoe.mirai.mock.internal.contact.active.MockGroupActiveImpl import net.mamoe.mirai.mock.internal.contact.essence.MockEssencesImpl import net.mamoe.mirai.mock.internal.contact.roaming.MockRoamingMessages +import net.mamoe.mirai.mock.internal.contact.todo.MockGroupTodoImpl import net.mamoe.mirai.mock.internal.msgsrc.OnlineMsgSrcToGroup import net.mamoe.mirai.mock.internal.msgsrc.newMsgSrc import net.mamoe.mirai.mock.utils.broadcastBlocking @@ -340,6 +342,8 @@ internal class MockGroupImpl( override val essences: MockEssences = MockEssencesImpl(this) + override val todo: MockGroupTodo = MockGroupTodoImpl(this) + @Deprecated("Please use files instead.", replaceWith = ReplaceWith("files.root")) @Suppress("OverridingDeprecatedMember", "DEPRECATION", "DEPRECATION_ERROR") override val filesRoot: RemoteFile by lazy { diff --git a/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt b/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt new file mode 100644 index 00000000000..a65c29db677 --- /dev/null +++ b/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.mock.internal.contact.todo + +import net.mamoe.mirai.contact.todo.GroupTodoRecord +import net.mamoe.mirai.contact.todo.GroupTodoStatus +import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.mock.contact.todo.MockGroupTodo +import net.mamoe.mirai.mock.internal.contact.MockGroupImpl + +internal class MockGroupTodoImpl( + private val group: MockGroupImpl +) : MockGroupTodo { + + override suspend fun status(): GroupTodoStatus { + TODO("Not yet implemented") + } + + override suspend fun current(): GroupTodoRecord? { + TODO("Not yet implemented") + } + + override suspend fun set(source: MessageSource): GroupTodoRecord { + TODO("Not yet implemented") + } + + override suspend fun recall(source: MessageSource) { + TODO("Not yet implemented") + } + + override suspend fun recall(record: GroupTodoRecord) { + TODO("Not yet implemented") + } + + override suspend fun complete(source: MessageSource) { + TODO("Not yet implemented") + } + + override suspend fun complete(record: GroupTodoRecord) { + TODO("Not yet implemented") + } + + override suspend fun close(source: MessageSource) { + TODO("Not yet implemented") + } + + override suspend fun close(record: GroupTodoRecord) { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt b/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt index 92e7c3b6c0d..9188125a0a5 100644 --- a/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt @@ -22,6 +22,7 @@ import net.mamoe.mirai.contact.announcement.Announcements import net.mamoe.mirai.contact.essence.Essences import net.mamoe.mirai.contact.file.RemoteFiles import net.mamoe.mirai.contact.roaming.RoamingMessages +import net.mamoe.mirai.contact.todo.GroupTodo import net.mamoe.mirai.data.GroupHonorType import net.mamoe.mirai.data.GroupInfo import net.mamoe.mirai.data.MemberInfo @@ -34,6 +35,7 @@ import net.mamoe.mirai.internal.contact.essence.EssencesImpl import net.mamoe.mirai.internal.contact.file.RemoteFilesImpl import net.mamoe.mirai.internal.contact.info.MemberInfoImpl import net.mamoe.mirai.internal.contact.roaming.RoamingMessagesImplGroup +import net.mamoe.mirai.internal.contact.todo.GroupTodoImpl import net.mamoe.mirai.internal.message.contextualBugReportException import net.mamoe.mirai.internal.message.data.OfflineAudioImpl import net.mamoe.mirai.internal.message.image.OfflineGroupImage @@ -416,6 +418,13 @@ internal abstract class CommonGroupImpl constructor( ) } + override val todo: GroupTodo by lazy { + GroupTodoImpl( + this as GroupImpl, + bot.network.logger.subLogger("Group $id"), + ) + } + override fun toString(): String = "Group($id)" } diff --git a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt new file mode 100644 index 00000000000..06ee02a80a6 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt @@ -0,0 +1,171 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.internal.contact.todo + +import net.mamoe.mirai.contact.todo.GroupTodo +import net.mamoe.mirai.contact.todo.GroupTodoRecord +import net.mamoe.mirai.contact.todo.GroupTodoStatus +import net.mamoe.mirai.internal.contact.GroupImpl +import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0xf8e +import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0xf90 +import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopTodoManager +import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.utils.structureToString +import net.mamoe.mirai.utils.toLongUnsigned + +internal class GroupTodoImpl( + internal val group: GroupImpl, + internal val logger: MiraiLogger, +) : GroupTodo { + + private fun Oidb0xf8e.RspBody.toGroupTodoRecord(): GroupTodoRecord? { + val info = info ?: return null + return GroupTodoRecord( + group = group, + title = info.title, + operator = group[info.uin], + operatorId = info.uin, + operatorNick = info.nickname, + operatorTime = info.createTime, + msgSeq = info.seq, + msgRandom = info.random.toLongUnsigned() + ) + } + + private fun Oidb0xf90.TodoInfo.toGroupTodoRecord(): GroupTodoRecord { + return GroupTodoRecord( + group = group, + title = title, + operator = group[uin], + operatorId = uin, + operatorNick = nickname, + operatorTime = createTime, + msgSeq = seq, + msgRandom = random.toLongUnsigned() + ) + } + + override suspend fun status(): GroupTodoStatus { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.Status( + group.bot.client, + group.uin, + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + + return when (val code = result.body.rptGroupList?.single()?.status) { + null, 0 -> GroupTodoStatus.NONE + 1 -> GroupTodoStatus.COMPLETED + 2 -> GroupTodoStatus.CLOSED + else -> throw IllegalStateException("status: $code") + } + } + + override suspend fun current(): GroupTodoRecord? { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.Current( + group.bot.client, + group.uin, + ), 30000, 2 + ) + + return result.body.toGroupTodoRecord() + } + + override suspend fun set(source: MessageSource): GroupTodoRecord { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.SetTodo( + group.bot.client, + group.uin, + source.internalIds.first().toLongUnsigned(), + source.ids.first().toLongUnsigned() + ), 30000, 2 + ) + println(result.info.structureToString()) + check(result.pkg.result == 0) { result.pkg.errorMsg } + val info = result.info!! + + return info.toGroupTodoRecord() + } + + override suspend fun recall(source: MessageSource) { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.RecallTodo( + group.bot.client, + group.uin, + source.internalIds.first().toLongUnsigned(), + source.ids.first().toLongUnsigned() + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + } + + override suspend fun recall(record: GroupTodoRecord) { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.RecallTodo( + group.bot.client, + group.uin, + record.msgRandom, + record.msgSeq + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + } + + override suspend fun complete(source: MessageSource) { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.CompleteTodo( + group.bot.client, + group.uin, + source.internalIds.first().toLongUnsigned(), + source.ids.first().toLongUnsigned() + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + } + + override suspend fun complete(record: GroupTodoRecord) { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.CompleteTodo( + group.bot.client, + group.uin, + record.msgRandom, + record.msgSeq + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + } + + override suspend fun close(source: MessageSource) { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.CloseTodo( + group.bot.client, + group.uin, + source.internalIds.first().toLongUnsigned(), + source.ids.first().toLongUnsigned() + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + } + + override suspend fun close(record: GroupTodoRecord) { + val result = group.bot.network.sendAndExpect( + TroopTodoManager.CloseTodo( + group.bot.client, + group.uin, + record.msgRandom, + record.msgSeq + ), 30000, 2 + ) + check(result.pkg.result == 0) { result.pkg.errorMsg } + } +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf8e.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf8e.kt new file mode 100644 index 00000000000..3b0c127f373 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf8e.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.internal.network.protocol.data.proto + +import kotlinx.serialization.Serializable +import kotlinx.serialization.protobuf.ProtoNumber +import net.mamoe.mirai.internal.utils.io.ProtoBuf + +@Serializable +internal class Oidb0xf8e : ProtoBuf { + @Serializable + internal class InfoValue( + @JvmField @ProtoNumber(1) val groupCode: Long = 0, + @JvmField @ProtoNumber(2) val seq: Long = 0, + @JvmField @ProtoNumber(3) val random: Int = 0, + @JvmField @ProtoNumber(4) val uin: Long = 0, + @JvmField @ProtoNumber(5) val nickname: String = "", + @JvmField @ProtoNumber(6) val title: String = "", + @JvmField @ProtoNumber(7) val jumpUrl: String = "", + @JvmField @ProtoNumber(8) val iconUrl: String = "", + @JvmField @ProtoNumber(9) val createTime: Int = 0, + @JvmField @ProtoNumber(10) val appName: String = "", + @JvmField @ProtoNumber(11) val appId: Long = 0, + @JvmField @ProtoNumber(12) val msgType: Int = 0, + ) : ProtoBuf + + @Serializable + internal class ReqBody( + @JvmField @ProtoNumber(1) val groupCode: Long = 0, + ) : ProtoBuf + + @Serializable + internal class RspBody( + @JvmField @ProtoNumber(1) val info: InfoValue? = null, + @JvmField @ProtoNumber(2) val rptGroupList: List? = null, + @JvmField @ProtoNumber(3) val expTime: Int = 0, + ) : ProtoBuf + + @Serializable + internal class UserNode( + @JvmField @ProtoNumber(1) val groupCode: Long = 0, + @JvmField @ProtoNumber(2) val seq: Long = 0, + @JvmField @ProtoNumber(3) val status: Int = 0, + ) : ProtoBuf + +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf90.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf90.kt new file mode 100644 index 00000000000..842790b35ba --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Oidb0xf90.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.internal.network.protocol.data.proto + +import kotlinx.serialization.Serializable +import kotlinx.serialization.protobuf.ProtoNumber +import net.mamoe.mirai.internal.utils.io.ProtoBuf + +@Serializable +internal class Oidb0xf90 : ProtoBuf { + @Serializable + internal class ReqBody( + @JvmField @ProtoNumber(1) val groupCode: Long = 0, + @JvmField @ProtoNumber(2) val seq: Long = 0, + @JvmField @ProtoNumber(3) val random: Long = 0, + @JvmField @ProtoNumber(4) val appId: Long = 0 + ) : ProtoBuf + + @Serializable + internal class RspBody( + @JvmField @ProtoNumber(1) val info: TodoInfo? = null, + ) : ProtoBuf + + @Serializable + internal class TodoInfo( + @JvmField @ProtoNumber(1) val groupCode: Long = 0, + @JvmField @ProtoNumber(2) val seq: Long = 0, + @JvmField @ProtoNumber(3) val random: Int = 0, + @JvmField @ProtoNumber(4) val uin: Long = 0, + @JvmField @ProtoNumber(5) val nickname: String = "", + @JvmField @ProtoNumber(6) val title: String = "", + @JvmField @ProtoNumber(7) val jumpUrl: String = "", + @JvmField @ProtoNumber(8) val iconUrl: String = "", + @JvmField @ProtoNumber(9) val createTime: Int = 0, + @JvmField @ProtoNumber(10) val appName: String = "", + @JvmField @ProtoNumber(11) val appId: Long = 0, + @JvmField @ProtoNumber(12) val msgType: Int = 0, + ) : ProtoBuf + +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt index e0219ced6b2..408ffbf3851 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt @@ -165,6 +165,12 @@ internal object KnownPacketFactories { TroopManagement.SwitchAnonymousChat, TroopEssenceMsgManager.SetEssence, TroopEssenceMsgManager.RemoveEssence, + TroopTodoManager.Current, + TroopTodoManager.Status, + TroopTodoManager.SetTodo, + TroopTodoManager.RecallTodo, + TroopTodoManager.CompleteTodo, + TroopTodoManager.CloseTodo, NudgePacket, Heartbeat.Alive, PbMessageSvc.PbMsgWithDraw, diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/TroopTodoManager.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/TroopTodoManager.kt new file mode 100644 index 00000000000..dcc922cdcf7 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/TroopTodoManager.kt @@ -0,0 +1,209 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.internal.network.protocol.packet.chat + +import io.ktor.utils.io.core.* +import net.mamoe.mirai.internal.QQAndroidBot +import net.mamoe.mirai.internal.network.Packet +import net.mamoe.mirai.internal.network.QQAndroidClient +import net.mamoe.mirai.internal.network.protocol.data.proto.OidbSso +import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0xf90 +import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0xf8e +import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory +import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket +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.toByteArray +import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf + +/** + * 群待办管理 + * + * */ +internal class TroopTodoManager { + + // region OidbSvcTrpcTcp.0xf8e + + class Fetch( + val pkg: OidbSso.OIDBSSOPkg, + ) : Packet { + val body by lazy { + pkg.bodybuffer.loadAs(Oidb0xf8e.RspBody.serializer()) + } + + override fun toString(): String = + "TroopTodoManager.Fetch(success=${pkg.result == 0}, error=${pkg.errorMsg})" + } + + internal object Current : OutgoingPacketFactory("OidbSvcTrpcTcp.0xf8e_1") { + + operator fun invoke( + client: QQAndroidClient, + groupCode: Long + ) = buildOutgoingUniPacket(client) { + writeProtoBuf( + OidbSso.OIDBSSOPkg.serializer(), OidbSso.OIDBSSOPkg( + command = 3982, + serviceType = 1, + bodybuffer = Oidb0xf8e.ReqBody( + groupCode = groupCode + ).toByteArray(Oidb0xf8e.ReqBody.serializer()), + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Fetch { + return Fetch(readProtoBuf(OidbSso.OIDBSSOPkg.serializer())) + } + } + + internal object Status : OutgoingPacketFactory("OidbSvcTrpcTcp.0xf8e_2") { + + operator fun invoke( + client: QQAndroidClient, + groupCode: Long + ) = buildOutgoingUniPacket(client) { + writeProtoBuf( + OidbSso.OIDBSSOPkg.serializer(), OidbSso.OIDBSSOPkg( + command = 3982, + serviceType = 2, + bodybuffer = Oidb0xf8e.ReqBody( + groupCode = groupCode + ).toByteArray(Oidb0xf8e.ReqBody.serializer()), + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Fetch { + return Fetch(readProtoBuf(OidbSso.OIDBSSOPkg.serializer())) + } + } + + // endregion + + // region OidbSvcTrpcTcp.0xf90 + + class Response( + val pkg: OidbSso.OIDBSSOPkg, + ) : Packet { + val info by lazy { + pkg.bodybuffer.loadAs(Oidb0xf90.RspBody.serializer()).info + } + + override fun toString(): String = + "TroopTodoManager.Response(success=${pkg.result == 0}, error=${pkg.errorMsg})" + } + + internal object SetTodo : OutgoingPacketFactory("OidbSvcTrpcTcp.0xf90_1") { + + operator fun invoke( + client: QQAndroidClient, + groupCode: Long, + msgRandom: Long, + msgSeq: Long + ) = buildOutgoingUniPacket(client) { + writeProtoBuf( + OidbSso.OIDBSSOPkg.serializer(), OidbSso.OIDBSSOPkg( + command = 3984, + serviceType = 1, + bodybuffer = Oidb0xf90.ReqBody( + groupCode = groupCode, + seq = msgSeq, + random = msgRandom, + ).toByteArray(Oidb0xf90.ReqBody.serializer()), + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { + return Response(readProtoBuf(OidbSso.OIDBSSOPkg.serializer())) + } + } + + internal object CompleteTodo : OutgoingPacketFactory("OidbSvcTrpcTcp.0xf90_2") { + + operator fun invoke( + client: QQAndroidClient, + groupCode: Long, + msgRandom: Long, + msgSeq: Long + ) = buildOutgoingUniPacket(client) { + writeProtoBuf( + OidbSso.OIDBSSOPkg.serializer(), OidbSso.OIDBSSOPkg( + command = 3984, + serviceType = 2, + bodybuffer = Oidb0xf90.ReqBody( + groupCode = groupCode, + seq = msgSeq, + random = msgRandom, + ).toByteArray(Oidb0xf90.ReqBody.serializer()), + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { + return Response(readProtoBuf(OidbSso.OIDBSSOPkg.serializer())) + } + } + + internal object RecallTodo : OutgoingPacketFactory("OidbSvcTrpcTcp.0xf90_3") { + + operator fun invoke( + client: QQAndroidClient, + groupCode: Long, + msgRandom: Long, + msgSeq: Long + ) = buildOutgoingUniPacket(client) { + writeProtoBuf( + OidbSso.OIDBSSOPkg.serializer(), OidbSso.OIDBSSOPkg( + command = 3984, + serviceType = 3, + bodybuffer = Oidb0xf90.ReqBody( + groupCode = groupCode, + seq = msgSeq, + random = msgRandom, + ).toByteArray(Oidb0xf90.ReqBody.serializer()), + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { + return Response(readProtoBuf(OidbSso.OIDBSSOPkg.serializer())) + } + } + + internal object CloseTodo : OutgoingPacketFactory("OidbSvcTrpcTcp.0xf90_4") { + + operator fun invoke( + client: QQAndroidClient, + groupCode: Long, + msgRandom: Long, + msgSeq: Long + ) = buildOutgoingUniPacket(client) { + writeProtoBuf( + OidbSso.OIDBSSOPkg.serializer(), OidbSso.OIDBSSOPkg( + command = 3984, + serviceType = 4, + bodybuffer = Oidb0xf90.ReqBody( + groupCode = groupCode, + seq = msgSeq, + random = msgRandom, + ).toByteArray(Oidb0xf90.ReqBody.serializer()), + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { + return Response(readProtoBuf(OidbSso.OIDBSSOPkg.serializer())) + } + } + + // endregion +} \ No newline at end of file From 0a75c04197d3105928ad8ee7206020ae77df7dab Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 5 Aug 2023 17:33:29 +0800 Subject: [PATCH 15/20] add: api dump --- .../android/api/android.api | 49 +++++++++++++++++++ .../compatibility-validation/jvm/api/jvm.api | 49 +++++++++++++++++++ .../commonMain/kotlin/event/events/group.kt | 2 +- 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index 5c1560a5ca2..35b71b53084 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/mirai-core-api/compatibility-validation/android/api/android.api @@ -484,6 +484,7 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin public fun getOrFail (J)Lnet/mamoe/mirai/contact/NormalMember; public abstract fun getOwner ()Lnet/mamoe/mirai/contact/NormalMember; public abstract fun getSettings ()Lnet/mamoe/mirai/contact/GroupSettings; + public abstract fun getTodo ()Lnet/mamoe/mirai/contact/todo/GroupTodo; public fun quit ()Z public abstract fun quit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt; @@ -1210,6 +1211,47 @@ public abstract interface class net/mamoe/mirai/contact/roaming/RoamingSupported public abstract fun getRoamingMessages ()Lnet/mamoe/mirai/contact/roaming/RoamingMessages; } +public abstract interface class net/mamoe/mirai/contact/todo/GroupTodo { + public fun close (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;)V + public abstract fun close (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun close (Lnet/mamoe/mirai/message/data/MessageSource;)V + public abstract fun close (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun complete (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;)V + public abstract fun complete (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun complete (Lnet/mamoe/mirai/message/data/MessageSource;)V + public abstract fun complete (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun current ()Lnet/mamoe/mirai/contact/todo/GroupTodoRecord; + public abstract fun current (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun recall (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;)V + public abstract fun recall (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun recall (Lnet/mamoe/mirai/message/data/MessageSource;)V + public abstract fun recall (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun set (Lnet/mamoe/mirai/message/data/MessageSource;)Lnet/mamoe/mirai/contact/todo/GroupTodoRecord; + public abstract fun set (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun status ()Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public abstract fun status (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class net/mamoe/mirai/contact/todo/GroupTodoRecord { + public final fun getGroup ()Lnet/mamoe/mirai/contact/Group; + public final fun getMsgRandom ()J + public final fun getMsgSeq ()J + public final fun getOperator ()Lnet/mamoe/mirai/contact/NormalMember; + public final fun getOperatorId ()J + public final fun getOperatorNick ()Ljava/lang/String; + public final fun getOperatorTime ()I + public final fun getTitle ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public final class net/mamoe/mirai/contact/todo/GroupTodoStatus : java/lang/Enum { + public static final field CLOSED Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static final field COMPLETED Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static final field NONE Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static fun valueOf (Ljava/lang/String;)Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static fun values ()[Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; +} + public abstract interface class net/mamoe/mirai/data/FriendInfo : net/mamoe/mirai/data/UserInfo { public abstract fun getFriendGroupId ()I public abstract fun getNick ()Ljava/lang/String; @@ -2763,6 +2805,13 @@ public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : ne public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberRecallTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public fun toString ()Ljava/lang/String; +} + public final class net/mamoe/mirai/event/events/MemberSetTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { public fun (Lnet/mamoe/mirai/contact/NormalMember;)V public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 675bdccb2a8..65ad4ced785 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/mirai-core-api/compatibility-validation/jvm/api/jvm.api @@ -484,6 +484,7 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin public fun getOrFail (J)Lnet/mamoe/mirai/contact/NormalMember; public abstract fun getOwner ()Lnet/mamoe/mirai/contact/NormalMember; public abstract fun getSettings ()Lnet/mamoe/mirai/contact/GroupSettings; + public abstract fun getTodo ()Lnet/mamoe/mirai/contact/todo/GroupTodo; public fun quit ()Z public abstract fun quit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt; @@ -1210,6 +1211,47 @@ public abstract interface class net/mamoe/mirai/contact/roaming/RoamingSupported public abstract fun getRoamingMessages ()Lnet/mamoe/mirai/contact/roaming/RoamingMessages; } +public abstract interface class net/mamoe/mirai/contact/todo/GroupTodo { + public fun close (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;)V + public abstract fun close (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun close (Lnet/mamoe/mirai/message/data/MessageSource;)V + public abstract fun close (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun complete (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;)V + public abstract fun complete (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun complete (Lnet/mamoe/mirai/message/data/MessageSource;)V + public abstract fun complete (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun current ()Lnet/mamoe/mirai/contact/todo/GroupTodoRecord; + public abstract fun current (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun recall (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;)V + public abstract fun recall (Lnet/mamoe/mirai/contact/todo/GroupTodoRecord;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun recall (Lnet/mamoe/mirai/message/data/MessageSource;)V + public abstract fun recall (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun set (Lnet/mamoe/mirai/message/data/MessageSource;)Lnet/mamoe/mirai/contact/todo/GroupTodoRecord; + public abstract fun set (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun status ()Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public abstract fun status (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class net/mamoe/mirai/contact/todo/GroupTodoRecord { + public final fun getGroup ()Lnet/mamoe/mirai/contact/Group; + public final fun getMsgRandom ()J + public final fun getMsgSeq ()J + public final fun getOperator ()Lnet/mamoe/mirai/contact/NormalMember; + public final fun getOperatorId ()J + public final fun getOperatorNick ()Ljava/lang/String; + public final fun getOperatorTime ()I + public final fun getTitle ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public final class net/mamoe/mirai/contact/todo/GroupTodoStatus : java/lang/Enum { + public static final field CLOSED Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static final field COMPLETED Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static final field NONE Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static fun valueOf (Ljava/lang/String;)Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; + public static fun values ()[Lnet/mamoe/mirai/contact/todo/GroupTodoStatus; +} + public abstract interface class net/mamoe/mirai/data/FriendInfo : net/mamoe/mirai/data/UserInfo { public abstract fun getFriendGroupId ()I public abstract fun getNick ()Ljava/lang/String; @@ -2763,6 +2805,13 @@ public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : ne public fun toString ()Ljava/lang/String; } +public final class net/mamoe/mirai/event/events/MemberRecallTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { + public fun (Lnet/mamoe/mirai/contact/NormalMember;)V + public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; + public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember; + public fun toString ()Ljava/lang/String; +} + public final class net/mamoe/mirai/event/events/MemberSetTodoEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet { public fun (Lnet/mamoe/mirai/contact/NormalMember;)V public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member; 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 353c31cd332..a26e771e4e5 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/group.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/events/group.kt @@ -704,7 +704,7 @@ public class MemberRecallTodoEvent( public override val member: NormalMember, ) : Packet, GroupMemberEvent, BotPassiveEvent, AbstractEvent() { override fun toString(): String { - return "MemberCompleteTodoEvent(group=${group.id}, member=${member.id})" + return "MemberRecallTodoEvent(group=${group.id}, member=${member.id})" } } From b7e2ddf4899f231311383560b7a7a4ed8b4cfeb2 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 12 Aug 2023 14:37:32 +0800 Subject: [PATCH 16/20] remove: println --- mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt index 06ee02a80a6..9ff655fb8e7 100644 --- a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt @@ -18,7 +18,6 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0xf90 import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopTodoManager import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.utils.MiraiLogger -import net.mamoe.mirai.utils.structureToString import net.mamoe.mirai.utils.toLongUnsigned internal class GroupTodoImpl( @@ -90,7 +89,6 @@ internal class GroupTodoImpl( source.ids.first().toLongUnsigned() ), 30000, 2 ) - println(result.info.structureToString()) check(result.pkg.result == 0) { result.pkg.errorMsg } val info = result.info!! From c38cdc285cfcd5adeca71f7a938a1e56ab012a03 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 12 Aug 2023 14:38:17 +0800 Subject: [PATCH 17/20] add: check bot permission --- .../src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt index 9ff655fb8e7..458c32be14e 100644 --- a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt @@ -9,6 +9,8 @@ package net.mamoe.mirai.internal.contact.todo +import net.mamoe.mirai.contact.MemberPermission +import net.mamoe.mirai.contact.checkBotPermission import net.mamoe.mirai.contact.todo.GroupTodo import net.mamoe.mirai.contact.todo.GroupTodoRecord import net.mamoe.mirai.contact.todo.GroupTodoStatus @@ -81,6 +83,7 @@ internal class GroupTodoImpl( } override suspend fun set(source: MessageSource): GroupTodoRecord { + group.checkBotPermission(MemberPermission.ADMINISTRATOR) val result = group.bot.network.sendAndExpect( TroopTodoManager.SetTodo( group.bot.client, @@ -96,6 +99,7 @@ internal class GroupTodoImpl( } override suspend fun recall(source: MessageSource) { + group.checkBotPermission(MemberPermission.ADMINISTRATOR) val result = group.bot.network.sendAndExpect( TroopTodoManager.RecallTodo( group.bot.client, @@ -108,6 +112,7 @@ internal class GroupTodoImpl( } override suspend fun recall(record: GroupTodoRecord) { + group.checkBotPermission(MemberPermission.ADMINISTRATOR) val result = group.bot.network.sendAndExpect( TroopTodoManager.RecallTodo( group.bot.client, @@ -144,6 +149,7 @@ internal class GroupTodoImpl( } override suspend fun close(source: MessageSource) { + group.checkBotPermission(MemberPermission.ADMINISTRATOR) val result = group.bot.network.sendAndExpect( TroopTodoManager.CloseTodo( group.bot.client, @@ -156,6 +162,7 @@ internal class GroupTodoImpl( } override suspend fun close(record: GroupTodoRecord) { + group.checkBotPermission(MemberPermission.ADMINISTRATOR) val result = group.bot.network.sendAndExpect( TroopTodoManager.CloseTodo( group.bot.client, From 60ecbe6a8f4122d63a6e69daab513a741360c0f1 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 12 Aug 2023 14:43:49 +0800 Subject: [PATCH 18/20] use: default timeout --- .../kotlin/contact/todo/GroupTodoImpl.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt index 458c32be14e..28e50827af0 100644 --- a/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/todo/GroupTodoImpl.kt @@ -59,7 +59,7 @@ internal class GroupTodoImpl( TroopTodoManager.Status( group.bot.client, group.uin, - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } @@ -76,7 +76,7 @@ internal class GroupTodoImpl( TroopTodoManager.Current( group.bot.client, group.uin, - ), 30000, 2 + ) ) return result.body.toGroupTodoRecord() @@ -90,7 +90,7 @@ internal class GroupTodoImpl( group.uin, source.internalIds.first().toLongUnsigned(), source.ids.first().toLongUnsigned() - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } val info = result.info!! @@ -106,7 +106,7 @@ internal class GroupTodoImpl( group.uin, source.internalIds.first().toLongUnsigned(), source.ids.first().toLongUnsigned() - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } } @@ -119,7 +119,7 @@ internal class GroupTodoImpl( group.uin, record.msgRandom, record.msgSeq - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } } @@ -131,7 +131,7 @@ internal class GroupTodoImpl( group.uin, source.internalIds.first().toLongUnsigned(), source.ids.first().toLongUnsigned() - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } } @@ -143,7 +143,7 @@ internal class GroupTodoImpl( group.uin, record.msgRandom, record.msgSeq - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } } @@ -156,7 +156,7 @@ internal class GroupTodoImpl( group.uin, source.internalIds.first().toLongUnsigned(), source.ids.first().toLongUnsigned() - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } } @@ -169,7 +169,7 @@ internal class GroupTodoImpl( group.uin, record.msgRandom, record.msgSeq - ), 30000, 2 + ) ) check(result.pkg.result == 0) { result.pkg.errorMsg } } From 315ee52ef3258a5cf50234753a14fc44f7b82b9a Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 12 Aug 2023 14:44:49 +0800 Subject: [PATCH 19/20] add: docs --- .../kotlin/contact/todo/GroupTodo.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt index 0361ea5b39b..7e0d6da804a 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/todo/GroupTodo.kt @@ -14,11 +14,34 @@ import net.mamoe.mirai.event.events.MemberCompleteTodoEvent import net.mamoe.mirai.event.events.MemberRecallTodoEvent import net.mamoe.mirai.event.events.MemberSetTodoEvent import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.contact.Group import net.mamoe.mirai.utils.NotStableForInheritance /** * 表示一个群待办管理. * + * ## 获取 [GroupTodo] 实例 + * + * 只可以通过 [Group.todo] 获取一个群的精华消息管理, 即 [GroupTodo] 实例. + * + * ### 获取当前群待办内容 + * + * 通过 [current] 可以获得当前群待办内容 + * + * ### 获取当前群待办状态 + * + * 通过 [status] 可以获得当前群待办内容 + * + * ### 操作群待办 + * + * 通过 [set] 可以设置新的群待办 + * + * 通过 [close] 可以关闭群待办 + * + * 通过 [complete] 可以完成群待办 + * + * 通过 [recall] 可以撤销群待办 + * * @since 2.16 */ @NotStableForInheritance @@ -54,7 +77,13 @@ public interface GroupTodo { */ public suspend fun complete(record: GroupTodoRecord) + /** + * @see MemberSetTodoEvent + */ public suspend fun close(source: MessageSource) + /** + * @see MemberSetTodoEvent + */ public suspend fun close(record: GroupTodoRecord) } \ No newline at end of file From 58337b42219460e2ef65b18598f64ce4f863fb36 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Sat, 12 Aug 2023 16:49:45 +0800 Subject: [PATCH 20/20] add: MockGroupTodoImpl --- .../contact/todo/MockGroupTodoImpl.kt | 86 +++++++++++++++++-- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt b/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt index a65c29db677..c3b1bab8656 100644 --- a/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt +++ b/mirai-core-mock/src/internal/contact/todo/MockGroupTodoImpl.kt @@ -9,49 +9,117 @@ package net.mamoe.mirai.mock.internal.contact.todo +import kotlinx.coroutines.launch +import net.mamoe.mirai.contact.MemberPermission +import net.mamoe.mirai.contact.checkBotPermission import net.mamoe.mirai.contact.todo.GroupTodoRecord import net.mamoe.mirai.contact.todo.GroupTodoStatus +import net.mamoe.mirai.event.broadcast +import net.mamoe.mirai.event.events.MemberCompleteTodoEvent +import net.mamoe.mirai.event.events.MemberRecallTodoEvent +import net.mamoe.mirai.event.events.MemberSetTodoEvent import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.mock.contact.todo.MockGroupTodo import net.mamoe.mirai.mock.internal.contact.MockGroupImpl +import net.mamoe.mirai.utils.currentTimeSeconds +import net.mamoe.mirai.utils.toLongUnsigned +import java.util.concurrent.atomic.AtomicReference internal class MockGroupTodoImpl( private val group: MockGroupImpl ) : MockGroupTodo { + private val status: AtomicReference = AtomicReference() + + private val current: AtomicReference = AtomicReference() + override suspend fun status(): GroupTodoStatus { - TODO("Not yet implemented") + return status.get() ?: GroupTodoStatus.NONE } override suspend fun current(): GroupTodoRecord? { - TODO("Not yet implemented") + return current.get() } override suspend fun set(source: MessageSource): GroupTodoRecord { - TODO("Not yet implemented") + group.checkBotPermission(MemberPermission.ADMINISTRATOR) + val record = GroupTodoRecord( + group = group, + title = source.originalMessage.contentToString(), + operator = group.botAsMember, + operatorId = group.bot.id, + operatorNick = group.botAsMember.nick, + operatorTime = currentTimeSeconds().toInt(), + msgSeq = source.ids.first().toLongUnsigned(), + msgRandom = source.internalIds.first().toLongUnsigned() + ) + current.set(record) + status.set(GroupTodoStatus.NONE) + group.launch { + MemberSetTodoEvent(member = group.botAsMember).broadcast() + } + return record } override suspend fun recall(source: MessageSource) { - TODO("Not yet implemented") + val current = checkNotNull(current.get()) { "current no todo" } + val id = source.ids.first().toLongUnsigned() + val internalId = source.internalIds.first().toLongUnsigned() + check(id == current.msgSeq && internalId == current.msgRandom) { "todo no match" } + status.set(GroupTodoStatus.NONE) + group.launch { + MemberRecallTodoEvent(member = group.botAsMember).broadcast() + } } override suspend fun recall(record: GroupTodoRecord) { - TODO("Not yet implemented") + val current = checkNotNull(current.get()) { "current no todo" } + check(record.msgSeq == current.msgSeq && record.msgRandom == current.msgRandom) { "todo no match" } + status.set(GroupTodoStatus.NONE) + group.launch { + MemberRecallTodoEvent(member = group.botAsMember).broadcast() + } } override suspend fun complete(source: MessageSource) { - TODO("Not yet implemented") + val current = checkNotNull(current.get()) { "current no todo" } + val id = source.ids.first().toLongUnsigned() + val internalId = source.internalIds.first().toLongUnsigned() + check(id == current.msgSeq && internalId == current.msgRandom) { "todo no match" } + status.set(GroupTodoStatus.COMPLETED) + group.launch { + MemberCompleteTodoEvent(member = group.botAsMember).broadcast() + } } override suspend fun complete(record: GroupTodoRecord) { - TODO("Not yet implemented") + val current = checkNotNull(current.get()) { "current no todo" } + check(record.msgSeq == current.msgSeq && record.msgRandom == current.msgRandom) { "todo no match" } + status.set(GroupTodoStatus.COMPLETED) + group.launch { + MemberCompleteTodoEvent(member = group.botAsMember).broadcast() + } } override suspend fun close(source: MessageSource) { - TODO("Not yet implemented") + group.checkBotPermission(MemberPermission.ADMINISTRATOR) + val current = checkNotNull(current.get()) { "current no todo" } + val id = source.ids.first().toLongUnsigned() + val internalId = source.internalIds.first().toLongUnsigned() + check(id == current.msgSeq && internalId == current.msgRandom) { "todo no match" } + status.set(GroupTodoStatus.CLOSED) + group.launch { + MemberSetTodoEvent(member = group.botAsMember).broadcast() + } } override suspend fun close(record: GroupTodoRecord) { - TODO("Not yet implemented") + group.checkBotPermission(MemberPermission.ADMINISTRATOR) + val current = checkNotNull(current.get()) { "current no todo" } + check(record.msgSeq == current.msgSeq && record.msgRandom == current.msgRandom) { "todo no match" } + status.set(GroupTodoStatus.CLOSED) + group.launch { + MemberSetTodoEvent(member = group.botAsMember).broadcast() + } } } \ No newline at end of file