mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-02 04:30:25 +08:00
Merge remote-tracking branch 'mirai/dev' into dev
This commit is contained in:
commit
c4c0bce381
@ -623,6 +623,7 @@ public abstract interface class net/mamoe/mirai/data/FriendInfo : net/mamoe/mira
|
||||
public abstract fun getNick ()Ljava/lang/String;
|
||||
public abstract fun getRemark ()Ljava/lang/String;
|
||||
public abstract fun getUin ()J
|
||||
public abstract fun setRemark (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public class net/mamoe/mirai/data/FriendInfoImpl : net/mamoe/mirai/data/FriendInfo {
|
||||
@ -1914,7 +1915,7 @@ public final class net/mamoe/mirai/event/events/BotEventsKt {
|
||||
public static final synthetic fun isSuccess (Lnet/mamoe/mirai/event/events/MessagePostSendEvent;)Z
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotGroupPermissionChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/BotGroupPermissionChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/MemberPermission;Lnet/mamoe/mirai/contact/MemberPermission;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Group;
|
||||
public final fun component2 ()Lnet/mamoe/mirai/contact/MemberPermission;
|
||||
@ -1929,7 +1930,7 @@ public final class net/mamoe/mirai/event/events/BotGroupPermissionChangeEvent :
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotInvitedJoinGroupRequestEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/BotInvitedJoinGroupRequestEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BaseGroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;JJJLjava/lang/String;Ljava/lang/String;)V
|
||||
public final synthetic fun accept ()Lkotlin/Unit;
|
||||
public final fun accept ()V
|
||||
@ -1945,7 +1946,7 @@ public final class net/mamoe/mirai/event/events/BotInvitedJoinGroupRequestEvent
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun getEventId ()J
|
||||
public final fun getGroupId ()J
|
||||
public fun getGroupId ()J
|
||||
public final fun getGroupName ()Ljava/lang/String;
|
||||
public final fun getInvitor ()Lnet/mamoe/mirai/contact/Friend;
|
||||
public final fun getInvitorId ()J
|
||||
@ -1957,7 +1958,7 @@ public final class net/mamoe/mirai/event/events/BotInvitedJoinGroupRequestEvent
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/event/events/BotJoinGroupEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public abstract class net/mamoe/mirai/event/events/BotJoinGroupEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public abstract fun getGroup ()Lnet/mamoe/mirai/contact/Group;
|
||||
}
|
||||
|
||||
@ -1995,7 +1996,7 @@ public final class net/mamoe/mirai/event/events/BotJoinGroupEvent$Retrieve : net
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/event/events/BotLeaveEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public abstract class net/mamoe/mirai/event/events/BotLeaveEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public abstract fun getGroup ()Lnet/mamoe/mirai/contact/Group;
|
||||
}
|
||||
@ -2025,7 +2026,7 @@ public final class net/mamoe/mirai/event/events/BotLeaveEvent$Kick : net/mamoe/m
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotMuteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/BotMuteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (ILnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()I
|
||||
public final fun component2 ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
@ -2077,6 +2078,7 @@ public abstract interface class net/mamoe/mirai/event/events/BotOfflineEvent$Cau
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotOfflineEvent$Dropped : net/mamoe/mirai/event/events/BotOfflineEvent, net/mamoe/mirai/event/events/BotOfflineEvent$CauseAware, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun component2 ()Ljava/lang/Throwable;
|
||||
public final fun copy (Lnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)Lnet/mamoe/mirai/event/events/BotOfflineEvent$Dropped;
|
||||
@ -2091,6 +2093,7 @@ public final class net/mamoe/mirai/event/events/BotOfflineEvent$Dropped : net/ma
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotOfflineEvent$Force : net/mamoe/mirai/event/events/BotOfflineEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
@ -2107,6 +2110,7 @@ public final class net/mamoe/mirai/event/events/BotOfflineEvent$Force : net/mamo
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotOfflineEvent$MsfOffline : net/mamoe/mirai/event/events/BotOfflineEvent, net/mamoe/mirai/event/events/BotOfflineEvent$CauseAware, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun component2 ()Ljava/lang/Throwable;
|
||||
public final fun copy (Lnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)Lnet/mamoe/mirai/event/events/BotOfflineEvent$MsfOffline;
|
||||
@ -2121,6 +2125,7 @@ public final class net/mamoe/mirai/event/events/BotOfflineEvent$MsfOffline : net
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotOfflineEvent$PacketFactoryErrorCode : net/mamoe/mirai/event/events/BotOfflineEvent, net/mamoe/mirai/event/events/BotOfflineEvent$CauseAware, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (ILnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)V
|
||||
public final fun component1 ()I
|
||||
public final fun component2 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun component3 ()Ljava/lang/Throwable;
|
||||
@ -2137,6 +2142,7 @@ public final class net/mamoe/mirai/event/events/BotOfflineEvent$PacketFactoryErr
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotOfflineEvent$RequireReconnect : net/mamoe/mirai/event/events/BotOfflineEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun copy (Lnet/mamoe/mirai/Bot;)Lnet/mamoe/mirai/event/events/BotOfflineEvent$RequireReconnect;
|
||||
public static synthetic fun copy$default (Lnet/mamoe/mirai/event/events/BotOfflineEvent$RequireReconnect;Lnet/mamoe/mirai/Bot;ILjava/lang/Object;)Lnet/mamoe/mirai/event/events/BotOfflineEvent$RequireReconnect;
|
||||
@ -2149,6 +2155,7 @@ public final class net/mamoe/mirai/event/events/BotOfflineEvent$RequireReconnect
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotOnlineEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotActiveEvent {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun copy (Lnet/mamoe/mirai/Bot;)Lnet/mamoe/mirai/event/events/BotOnlineEvent;
|
||||
public static synthetic fun copy$default (Lnet/mamoe/mirai/event/events/BotOnlineEvent;Lnet/mamoe/mirai/Bot;ILjava/lang/Object;)Lnet/mamoe/mirai/event/events/BotOnlineEvent;
|
||||
@ -2162,6 +2169,7 @@ public abstract interface class net/mamoe/mirai/event/events/BotPassiveEvent : n
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotReloginEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotActiveEvent, net/mamoe/mirai/event/events/BotEvent {
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/Bot;
|
||||
public final fun component2 ()Ljava/lang/Throwable;
|
||||
public final fun copy (Lnet/mamoe/mirai/Bot;Ljava/lang/Throwable;)Lnet/mamoe/mirai/event/events/BotReloginEvent;
|
||||
@ -2173,7 +2181,7 @@ public final class net/mamoe/mirai/event/events/BotReloginEvent : net/mamoe/mira
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/BotUnmuteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/BotUnmuteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
public final fun copy (Lnet/mamoe/mirai/contact/NormalMember;)Lnet/mamoe/mirai/event/events/BotUnmuteEvent;
|
||||
@ -2192,7 +2200,7 @@ public final class net/mamoe/mirai/event/events/EventCancelledException : java/l
|
||||
public fun <init> (Ljava/lang/Throwable;)V
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/FriendAddEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/FriendAddEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/event/events/FriendInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/contact/Friend;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Friend;
|
||||
public final fun copy (Lnet/mamoe/mirai/contact/Friend;)Lnet/mamoe/mirai/event/events/FriendAddEvent;
|
||||
@ -2213,7 +2221,7 @@ public final class net/mamoe/mirai/event/events/FriendAvatarChangedEvent : net/m
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/FriendDeleteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/FriendDeleteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/event/events/FriendInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Friend;
|
||||
public final fun copy (Lnet/mamoe/mirai/contact/Friend;)Lnet/mamoe/mirai/event/events/FriendDeleteEvent;
|
||||
public static synthetic fun copy$default (Lnet/mamoe/mirai/event/events/FriendDeleteEvent;Lnet/mamoe/mirai/contact/Friend;ILjava/lang/Object;)Lnet/mamoe/mirai/event/events/FriendDeleteEvent;
|
||||
@ -2308,7 +2316,7 @@ public final class net/mamoe/mirai/event/events/FriendMessageSyncEvent : net/mam
|
||||
public fun getTime ()I
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/FriendNickChangedEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/FriendNickChangedEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/event/events/FriendInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Friend;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
@ -2322,7 +2330,7 @@ public final class net/mamoe/mirai/event/events/FriendNickChangedEvent : net/mam
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/FriendRemarkChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/FriendRemarkChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/FriendEvent, net/mamoe/mirai/event/events/FriendInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Friend;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
public final fun component3 ()Ljava/lang/String;
|
||||
@ -2336,7 +2344,7 @@ public final class net/mamoe/mirai/event/events/FriendRemarkChangeEvent : net/ma
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/GroupAllowAnonymousChatEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/GroupAllowAnonymousChatEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (ZZLnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Z
|
||||
public final fun component2 ()Z
|
||||
@ -2356,7 +2364,7 @@ public final class net/mamoe/mirai/event/events/GroupAllowAnonymousChatEvent : n
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/GroupAllowConfessTalkEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/GroupAllowConfessTalkEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (ZZLnet/mamoe/mirai/contact/Group;Z)V
|
||||
public final fun component1 ()Z
|
||||
public final fun component2 ()Z
|
||||
@ -2375,7 +2383,7 @@ public final class net/mamoe/mirai/event/events/GroupAllowConfessTalkEvent : net
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/GroupAllowMemberInviteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/GroupAllowMemberInviteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (ZZLnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Z
|
||||
public final fun component2 ()Z
|
||||
@ -2399,7 +2407,7 @@ public abstract interface class net/mamoe/mirai/event/events/GroupAwareMessageEv
|
||||
public abstract fun getGroup ()Lnet/mamoe/mirai/contact/Group;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/GroupEntranceAnnouncementChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/GroupEntranceAnnouncementChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
@ -2497,7 +2505,7 @@ public final class net/mamoe/mirai/event/events/GroupMessageSyncEvent : net/mamo
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/GroupMuteAllEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/GroupMuteAllEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (ZZLnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Z
|
||||
public final fun component2 ()Z
|
||||
@ -2517,7 +2525,7 @@ public final class net/mamoe/mirai/event/events/GroupMuteAllEvent : net/mamoe/mi
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/GroupNameChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/GroupNameChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/event/events/GroupSettingChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
@ -2670,7 +2678,7 @@ public final class net/mamoe/mirai/event/events/ImageUploadEvent$Succeed : net/m
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/MemberCardChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/MemberCardChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
@ -2719,7 +2727,7 @@ public final class net/mamoe/mirai/event/events/MemberHonorChangeEvent$Lose : ne
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/event/events/MemberJoinEvent : 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 class net/mamoe/mirai/event/events/MemberJoinEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public synthetic fun <init> (Lnet/mamoe/mirai/contact/NormalMember;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public synthetic fun getMember ()Lnet/mamoe/mirai/contact/Member;
|
||||
public fun getMember ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
@ -2763,7 +2771,7 @@ public final class net/mamoe/mirai/event/events/MemberJoinEvent$Retrieve : net/m
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/MemberJoinRequestEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/MemberJoinRequestEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BaseGroupMemberInfoChangeEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public static final field Companion Lnet/mamoe/mirai/event/events/MemberJoinRequestEvent$Companion;
|
||||
public synthetic fun <init> (Lnet/mamoe/mirai/Bot;JLjava/lang/String;JJLjava/lang/String;Ljava/lang/String;)V
|
||||
public fun <init> (Lnet/mamoe/mirai/Bot;JLjava/lang/String;JJLjava/lang/String;Ljava/lang/String;Ljava/lang/Long;)V
|
||||
@ -2789,7 +2797,7 @@ public final class net/mamoe/mirai/event/events/MemberJoinRequestEvent : net/mam
|
||||
public final fun getFromId ()J
|
||||
public final fun getFromNick ()Ljava/lang/String;
|
||||
public final fun getGroup ()Lnet/mamoe/mirai/contact/Group;
|
||||
public final fun getGroupId ()J
|
||||
public fun getGroupId ()J
|
||||
public final fun getGroupName ()Ljava/lang/String;
|
||||
public final fun getInvitor ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
public final fun getInvitorId ()Ljava/lang/Long;
|
||||
@ -2812,7 +2820,7 @@ public final class net/mamoe/mirai/event/events/MemberJoinRequestEvent : net/mam
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/event/events/MemberLeaveEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent {
|
||||
public abstract class net/mamoe/mirai/event/events/MemberLeaveEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent {
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/MemberLeaveEvent$Kick : net/mamoe/mirai/event/events/MemberLeaveEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
@ -2842,7 +2850,7 @@ 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/MemberMuteEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupOperableEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
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 fun <init> (Lnet/mamoe/mirai/contact/Member;ILnet/mamoe/mirai/contact/Member;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Member;
|
||||
public final fun component2 ()I
|
||||
@ -2857,7 +2865,7 @@ public final class net/mamoe/mirai/event/events/MemberMuteEvent : net/mamoe/mira
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/MemberPermissionChangeEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotPassiveEvent, net/mamoe/mirai/event/events/GroupMemberEvent, net/mamoe/mirai/event/events/GroupMemberInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public fun <init> (Lnet/mamoe/mirai/contact/NormalMember;Lnet/mamoe/mirai/contact/MemberPermission;Lnet/mamoe/mirai/contact/MemberPermission;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
public final fun component2 ()Lnet/mamoe/mirai/contact/MemberPermission;
|
||||
@ -2873,7 +2881,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/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 {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/contact/NormalMember;Lnet/mamoe/mirai/contact/NormalMember;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()Ljava/lang/String;
|
||||
@ -2892,7 +2900,7 @@ public final class net/mamoe/mirai/event/events/MemberSpecialTitleChangeEvent :
|
||||
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/GroupOperableEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
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 fun <init> (Lnet/mamoe/mirai/contact/Member;Lnet/mamoe/mirai/contact/Member;)V
|
||||
public final fun component1 ()Lnet/mamoe/mirai/contact/Member;
|
||||
public final fun component2 ()Lnet/mamoe/mirai/contact/Member;
|
||||
@ -2991,7 +2999,7 @@ public final class net/mamoe/mirai/event/events/MessageRecallEvent$GroupRecall :
|
||||
public abstract interface class net/mamoe/mirai/event/events/MessageSyncEvent : net/mamoe/mirai/event/events/MessageEvent {
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/event/events/NewFriendRequestEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final class net/mamoe/mirai/event/events/NewFriendRequestEvent : net/mamoe/mirai/event/AbstractEvent, net/mamoe/mirai/event/events/BotEvent, net/mamoe/mirai/event/events/FriendInfoChangeEvent, net/mamoe/mirai/internal/network/Packet {
|
||||
public final synthetic fun accept ()Lkotlin/Unit;
|
||||
public final fun accept ()V
|
||||
public final fun accept (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
@ -5385,6 +5393,9 @@ public class net/mamoe/mirai/utils/BotConfiguration {
|
||||
public fun <init> ()V
|
||||
public final fun autoReconnectOnForceOffline ()V
|
||||
public final fun copy ()Lnet/mamoe/mirai/utils/BotConfiguration;
|
||||
public final fun disableContactCaches ()V
|
||||
public final fun disableFriendListCache ()V
|
||||
public final fun disableGroupMemberListCache ()V
|
||||
public final fun fileBasedDeviceInfo ()V
|
||||
public final fun fileBasedDeviceInfo (Ljava/lang/String;)V
|
||||
public static synthetic fun fileBasedDeviceInfo$default (Lnet/mamoe/mirai/utils/BotConfiguration;Ljava/lang/String;ILjava/lang/Object;)V
|
||||
@ -5393,6 +5404,8 @@ public class net/mamoe/mirai/utils/BotConfiguration {
|
||||
public static final fun getDefault ()Lnet/mamoe/mirai/utils/BotConfiguration;
|
||||
public final fun getDeviceInfo ()Lkotlin/jvm/functions/Function1;
|
||||
public final fun getFirstReconnectDelayMillis ()J
|
||||
public final fun getFriendListCache ()Lnet/mamoe/mirai/utils/BotConfiguration$FriendListCache;
|
||||
public final fun getGroupMemberListCache ()Lnet/mamoe/mirai/utils/BotConfiguration$GroupMemberListCache;
|
||||
public final fun getHeartbeatPeriodMillis ()J
|
||||
public final fun getHeartbeatTimeoutMillis ()J
|
||||
public final fun getHighwayUploadCoroutineCount ()I
|
||||
@ -5431,6 +5444,8 @@ public class net/mamoe/mirai/utils/BotConfiguration {
|
||||
public final fun setBotLoggerSupplier (Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun setDeviceInfo (Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun setFirstReconnectDelayMillis (J)V
|
||||
public final fun setFriendListCache (Lnet/mamoe/mirai/utils/BotConfiguration$FriendListCache;)V
|
||||
public final fun setGroupMemberListCache (Lnet/mamoe/mirai/utils/BotConfiguration$GroupMemberListCache;)V
|
||||
public final fun setHeartbeatPeriodMillis (J)V
|
||||
public final fun setHeartbeatTimeoutMillis (J)V
|
||||
public final fun setHighwayUploadCoroutineCount (I)V
|
||||
@ -5451,6 +5466,24 @@ public final class net/mamoe/mirai/utils/BotConfiguration$Companion {
|
||||
public abstract interface annotation class net/mamoe/mirai/utils/BotConfiguration$ConfigurationDsl : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/utils/BotConfiguration$FriendListCache {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/io/File;)V
|
||||
public fun <init> (Ljava/io/File;J)V
|
||||
public synthetic fun <init> (Ljava/io/File;JILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getCacheFile ()Ljava/io/File;
|
||||
public final fun getSaveIntervalMillis ()J
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/utils/BotConfiguration$GroupMemberListCache {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/io/File;)V
|
||||
public fun <init> (Ljava/io/File;J)V
|
||||
public synthetic fun <init> (Ljava/io/File;JILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getCacheDir ()Ljava/io/File;
|
||||
public final fun getSaveIntervalMillis ()J
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/utils/BotConfiguration$MiraiProtocol : java/lang/Enum {
|
||||
public static final field ANDROID_PAD Lnet/mamoe/mirai/utils/BotConfiguration$MiraiProtocol;
|
||||
public static final field ANDROID_PHONE Lnet/mamoe/mirai/utils/BotConfiguration$MiraiProtocol;
|
||||
|
0
gradlew.bat
vendored
Normal file → Executable file
0
gradlew.bat
vendored
Normal file → Executable file
@ -11,6 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.Bot
|
||||
import kotlin.internal.InlineOnly
|
||||
|
||||
|
@ -17,9 +17,16 @@ public interface FriendInfo : UserInfo {
|
||||
|
||||
public override val nick: String
|
||||
|
||||
public override val remark: String
|
||||
public override var remark: String
|
||||
}
|
||||
|
||||
|
||||
@Deprecated(
|
||||
"Moved to net.mamoe.mirai.internal.contact.FriendInfoImpl. Kept for binary compatibility.",
|
||||
ReplaceWith("FriendInfoImpl", "net.mamoe.mirai.internal.contact.FriendInfoImpl"),
|
||||
level = DeprecationLevel.HIDDEN
|
||||
)
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@LowLevelApi
|
||||
public open class FriendInfoImpl(
|
||||
override val uin: Long,
|
||||
|
@ -25,7 +25,7 @@ import net.mamoe.mirai.utils.MiraiInternalApi
|
||||
/**
|
||||
* [Bot] 登录完成, 好友列表, 群组列表初始化完成
|
||||
*/
|
||||
public data class BotOnlineEvent internal constructor(
|
||||
public data class BotOnlineEvent @MiraiInternalApi public constructor(
|
||||
public override val bot: Bot
|
||||
) : BotActiveEvent, AbstractEvent()
|
||||
|
||||
@ -55,7 +55,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||
/**
|
||||
* 被挤下线. 默认不会自动重连. 可将 [reconnect] 改为 `true` 以重连.
|
||||
*/
|
||||
public data class Force internal constructor(
|
||||
public data class Force @MiraiInternalApi public constructor(
|
||||
public override val bot: Bot,
|
||||
public val title: String,
|
||||
public val message: String,
|
||||
@ -67,7 +67,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||
* 被服务器断开
|
||||
*/
|
||||
@MiraiInternalApi("This is very experimental and might be changed")
|
||||
public data class MsfOffline internal constructor(
|
||||
public data class MsfOffline @MiraiInternalApi public constructor(
|
||||
public override val bot: Bot,
|
||||
public override val cause: Throwable?
|
||||
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware {
|
||||
@ -77,7 +77,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||
/**
|
||||
* 因网络问题而掉线
|
||||
*/
|
||||
public data class Dropped internal constructor(
|
||||
public data class Dropped @MiraiInternalApi public constructor(
|
||||
public override val bot: Bot,
|
||||
public override val cause: Throwable?
|
||||
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware {
|
||||
@ -88,7 +88,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||
* 因 returnCode = -10008 等原因掉线
|
||||
*/
|
||||
@MiraiInternalApi("This is very experimental and might be changed")
|
||||
public data class PacketFactoryErrorCode internal constructor(
|
||||
public data class PacketFactoryErrorCode @MiraiInternalApi public constructor(
|
||||
val returnCode: Int,
|
||||
public override val bot: Bot,
|
||||
public override val cause: Throwable
|
||||
@ -100,7 +100,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||
* 服务器主动要求更换另一个服务器
|
||||
*/
|
||||
@MiraiInternalApi
|
||||
public data class RequireReconnect internal constructor(
|
||||
public data class RequireReconnect @MiraiInternalApi public constructor(
|
||||
public override val bot: Bot
|
||||
) : BotOfflineEvent(), Packet, BotPassiveEvent {
|
||||
override var reconnect: Boolean = true
|
||||
@ -115,7 +115,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
|
||||
/**
|
||||
* [Bot] 主动或被动重新登录. 在此事件广播前就已经登录完毕.
|
||||
*/
|
||||
public data class BotReloginEvent internal constructor(
|
||||
public data class BotReloginEvent @MiraiInternalApi public constructor(
|
||||
public override val bot: Bot,
|
||||
public val cause: Throwable?
|
||||
) : BotEvent, BotActiveEvent, AbstractEvent()
|
||||
|
@ -32,7 +32,7 @@ public data class FriendRemarkChangeEvent internal constructor(
|
||||
public override val friend: Friend,
|
||||
public val oldRemark: String,
|
||||
public val newRemark: String
|
||||
) : FriendEvent, Packet, AbstractEvent()
|
||||
) : FriendEvent, Packet, AbstractEvent(), FriendInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 成功添加了一个新好友的事件
|
||||
@ -42,14 +42,14 @@ public data class FriendAddEvent @MiraiInternalApi constructor(
|
||||
* 新好友. 已经添加到 [Bot.friends]
|
||||
*/
|
||||
public override val friend: Friend
|
||||
) : FriendEvent, Packet, AbstractEvent()
|
||||
) : FriendEvent, Packet, AbstractEvent(), FriendInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 好友已被删除或主动删除的事件.
|
||||
*/
|
||||
public data class FriendDeleteEvent internal constructor(
|
||||
public override val friend: Friend
|
||||
) : FriendEvent, Packet, AbstractEvent()
|
||||
) : FriendEvent, Packet, AbstractEvent(), FriendInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 一个账号请求添加机器人为好友的事件
|
||||
@ -77,7 +77,7 @@ public data class NewFriendRequestEvent internal constructor(
|
||||
* 群名片或好友昵称
|
||||
*/
|
||||
public val fromNick: String
|
||||
) : BotEvent, Packet, AbstractEvent() {
|
||||
) : BotEvent, Packet, AbstractEvent(), FriendInfoChangeEvent {
|
||||
@JvmField
|
||||
internal val responded: AtomicBoolean = AtomicBoolean(false)
|
||||
|
||||
@ -109,7 +109,7 @@ public data class FriendNickChangedEvent internal constructor(
|
||||
public override val friend: Friend,
|
||||
public val from: String,
|
||||
public val to: String
|
||||
) : FriendEvent, Packet, AbstractEvent()
|
||||
) : FriendEvent, Packet, AbstractEvent(), FriendInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 好友输入状态改变的事件,当开始输入文字、退出聊天窗口或清空输入框时会触发此事件
|
||||
|
@ -9,7 +9,9 @@
|
||||
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("BotEventsKt")
|
||||
@file:Suppress("unused", "FunctionName", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "DEPRECATION_ERROR")
|
||||
@file:Suppress("unused", "FunctionName", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "DEPRECATION_ERROR",
|
||||
"MemberVisibilityCanBePrivate"
|
||||
)
|
||||
|
||||
package net.mamoe.mirai.event.events
|
||||
|
||||
@ -28,8 +30,8 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
/**
|
||||
* 机器人被踢出群或在其他客户端主动退出一个群. 在事件广播前 [Bot.groups] 就已删除这个群.
|
||||
*/
|
||||
public sealed class BotLeaveEvent : BotEvent, Packet, AbstractEvent() {
|
||||
public abstract val group: Group
|
||||
public sealed class BotLeaveEvent : BotEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent {
|
||||
public abstract override val group: Group
|
||||
|
||||
/**
|
||||
* 机器人主动退出一个群.
|
||||
@ -64,7 +66,7 @@ public data class BotGroupPermissionChangeEvent @MiraiInternalApi constructor(
|
||||
public override val group: Group,
|
||||
public val origin: MemberPermission,
|
||||
public val new: MemberPermission
|
||||
) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent()
|
||||
) : BotPassiveEvent, GroupEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
/**
|
||||
* Bot 被禁言
|
||||
@ -75,7 +77,7 @@ public data class BotMuteEvent @MiraiInternalApi constructor(
|
||||
* 操作人.
|
||||
*/
|
||||
public val operator: NormalMember
|
||||
) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent() {
|
||||
) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent(), GroupMemberInfoChangeEvent {
|
||||
public override val group: Group
|
||||
get() = operator.group
|
||||
}
|
||||
@ -88,7 +90,7 @@ public data class BotUnmuteEvent @MiraiInternalApi constructor(
|
||||
* 操作人.
|
||||
*/
|
||||
public val operator: NormalMember
|
||||
) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent() {
|
||||
) : GroupEvent, Packet, BotPassiveEvent, AbstractEvent(), GroupMemberInfoChangeEvent {
|
||||
public override val group: Group
|
||||
get() = operator.group
|
||||
}
|
||||
@ -96,7 +98,7 @@ public data class BotUnmuteEvent @MiraiInternalApi constructor(
|
||||
/**
|
||||
* Bot 成功加入了一个新群
|
||||
*/
|
||||
public sealed class BotJoinGroupEvent : GroupEvent, BotPassiveEvent, Packet, AbstractEvent() {
|
||||
public sealed class BotJoinGroupEvent : GroupEvent, BotPassiveEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent {
|
||||
public abstract override val group: Group
|
||||
|
||||
/**
|
||||
@ -164,7 +166,7 @@ public data class GroupNameChangeEvent @MiraiInternalApi constructor(
|
||||
* 操作人. 为 null 时则是机器人操作
|
||||
*/
|
||||
public override val operator: NormalMember?
|
||||
) : GroupSettingChangeEvent<String>, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupSettingChangeEvent<String>, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 入群公告改变. 此事件广播前修改就已经完成.
|
||||
@ -177,7 +179,7 @@ public data class GroupEntranceAnnouncementChangeEvent @MiraiInternalApi constru
|
||||
* 操作人. 为 null 时则是机器人操作
|
||||
*/
|
||||
public override val operator: NormalMember?
|
||||
) : GroupSettingChangeEvent<String>, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupSettingChangeEvent<String>, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
|
||||
/**
|
||||
@ -191,7 +193,7 @@ public data class GroupMuteAllEvent @MiraiInternalApi constructor(
|
||||
* 操作人. 为 null 时则是机器人操作
|
||||
*/
|
||||
public override val operator: NormalMember?
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
|
||||
/**
|
||||
@ -205,7 +207,7 @@ public data class GroupAllowAnonymousChatEvent @MiraiInternalApi constructor(
|
||||
* 操作人. 为 null 时则是机器人操作
|
||||
*/
|
||||
public override val operator: NormalMember?
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
|
||||
/**
|
||||
@ -216,7 +218,7 @@ public data class GroupAllowConfessTalkEvent @MiraiInternalApi constructor(
|
||||
public override val new: Boolean,
|
||||
public override val group: Group,
|
||||
public val isByBot: Boolean // 无法获取操作人
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, AbstractEvent()
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 群 "允许群员邀请好友加群" 功能状态改变. 此事件广播前修改就已经完成.
|
||||
@ -229,7 +231,7 @@ public data class GroupAllowMemberInviteEvent @MiraiInternalApi constructor(
|
||||
* 操作人. 为 null 时则是机器人操作
|
||||
*/
|
||||
public override val operator: NormalMember?
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupSettingChangeEvent<Boolean>, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
|
||||
// endregion
|
||||
@ -245,7 +247,7 @@ public data class GroupAllowMemberInviteEvent @MiraiInternalApi constructor(
|
||||
public sealed class MemberJoinEvent(
|
||||
public override val member: NormalMember
|
||||
) : GroupMemberEvent, BotPassiveEvent, Packet,
|
||||
AbstractEvent() {
|
||||
AbstractEvent(), GroupMemberInfoChangeEvent {
|
||||
/**
|
||||
* 被邀请加入群
|
||||
*/
|
||||
@ -282,7 +284,7 @@ public sealed class MemberJoinEvent(
|
||||
/**
|
||||
* 成员已经离开群的事件. 在事件广播前成员就已经从 [Group.members] 中删除
|
||||
*/
|
||||
public sealed class MemberLeaveEvent : GroupMemberEvent, AbstractEvent() {
|
||||
public sealed class MemberLeaveEvent : GroupMemberEvent, AbstractEvent(), GroupMemberInfoChangeEvent {
|
||||
/**
|
||||
* 成员被踢出群. 成员不可能是机器人自己.
|
||||
*/
|
||||
@ -320,13 +322,13 @@ public data class BotInvitedJoinGroupRequestEvent @MiraiInternalApi constructor(
|
||||
* 邀请入群的账号的 id
|
||||
*/
|
||||
public val invitorId: Long,
|
||||
public val groupId: Long,
|
||||
public override val groupId: Long,
|
||||
public val groupName: String,
|
||||
/**
|
||||
* 邀请人昵称
|
||||
*/
|
||||
public val invitorNick: String
|
||||
) : BotEvent, Packet, AbstractEvent() {
|
||||
) : BotEvent, Packet, AbstractEvent(), BaseGroupMemberInfoChangeEvent {
|
||||
/**
|
||||
* 邀请人. 若在事件发生后邀请人已经被删除好友, [invitor] 为 `null`.
|
||||
*/
|
||||
@ -360,7 +362,7 @@ public data class MemberJoinRequestEvent @MiraiInternalApi constructor(
|
||||
* 申请入群的账号的 id
|
||||
*/
|
||||
val fromId: Long,
|
||||
val groupId: Long,
|
||||
override val groupId: Long,
|
||||
val groupName: String,
|
||||
/**
|
||||
* 申请人昵称
|
||||
@ -370,7 +372,7 @@ public data class MemberJoinRequestEvent @MiraiInternalApi constructor(
|
||||
* 邀请人 id(如果是邀请入群)
|
||||
*/
|
||||
val invitorId: Long? = null
|
||||
) : BotEvent, Packet, AbstractEvent() {
|
||||
) : BotEvent, Packet, AbstractEvent(), BaseGroupMemberInfoChangeEvent {
|
||||
/**
|
||||
* 相关群. 若在事件发生后机器人退出这个群, [group] 为 `null`.
|
||||
*/
|
||||
@ -471,7 +473,7 @@ public data class MemberCardChangeEvent @MiraiInternalApi constructor(
|
||||
public val new: String,
|
||||
|
||||
public override val member: NormalMember
|
||||
) : GroupMemberEvent, Packet, AbstractEvent()
|
||||
) : GroupMemberEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 成员群头衔改动. 一定为群主操作
|
||||
@ -495,7 +497,7 @@ public data class MemberSpecialTitleChangeEvent @MiraiInternalApi constructor(
|
||||
* 为 null 时则是机器人操作.
|
||||
*/
|
||||
public override val operator: NormalMember?
|
||||
) : GroupMemberEvent, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupMemberEvent, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
// endregion
|
||||
|
||||
@ -509,7 +511,7 @@ public data class MemberPermissionChangeEvent @MiraiInternalApi constructor(
|
||||
public override val member: NormalMember,
|
||||
public val origin: MemberPermission,
|
||||
public val new: MemberPermission
|
||||
) : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent()
|
||||
) : GroupMemberEvent, BotPassiveEvent, Packet, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
// endregion
|
||||
|
||||
@ -528,7 +530,7 @@ public data class MemberMuteEvent @MiraiInternalApi constructor(
|
||||
* 操作人. 为 null 则为机器人操作
|
||||
*/
|
||||
public override val operator: Member?
|
||||
) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
/**
|
||||
* 群成员被取消禁言事件. 被禁言的成员都不可能是机器人本人
|
||||
@ -541,7 +543,7 @@ public data class MemberUnmuteEvent @MiraiInternalApi constructor(
|
||||
* 操作人. 为 null 则为机器人操作
|
||||
*/
|
||||
public override val operator: Member?
|
||||
) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent()
|
||||
) : GroupMemberEvent, Packet, GroupOperableEvent, AbstractEvent(), GroupMemberInfoChangeEvent
|
||||
|
||||
// endregion
|
||||
|
||||
|
@ -16,6 +16,7 @@ import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.utils.MiraiInternalApi
|
||||
|
||||
/**
|
||||
* 有关一个 [Bot] 的事件
|
||||
@ -90,6 +91,8 @@ public interface FriendEvent : BotEvent, UserEvent {
|
||||
override val user: Friend get() = friend
|
||||
}
|
||||
|
||||
internal interface FriendInfoChangeEvent : BotEvent // for cache
|
||||
|
||||
/**
|
||||
* 有关陌生人的事件
|
||||
*/
|
||||
@ -108,6 +111,19 @@ public interface GroupMemberEvent : GroupEvent, UserEvent {
|
||||
override val user: Member get() = member
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于更新缓存, 请勿使用.
|
||||
*/
|
||||
@MiraiInternalApi
|
||||
internal interface BaseGroupMemberInfoChangeEvent : BotEvent {
|
||||
val groupId: Long
|
||||
} // for cache
|
||||
|
||||
@MiraiInternalApi
|
||||
internal interface GroupMemberInfoChangeEvent : BotEvent, GroupEvent, BaseGroupMemberInfoChangeEvent {
|
||||
override val groupId: Long get() = group.id
|
||||
} // for cache
|
||||
|
||||
public interface OtherClientEvent : BotEvent, Packet {
|
||||
public val client: OtherClient
|
||||
override val bot: Bot get() = client.bot
|
||||
|
@ -57,32 +57,87 @@ public open class BotConfiguration { // open for Java
|
||||
public var workingDir: File = File(".")
|
||||
|
||||
/**
|
||||
* 日志记录器
|
||||
*
|
||||
* - 默认打印到标准输出, 通过 [MiraiLogger.create]
|
||||
* - 忽略所有日志: [noBotLog]
|
||||
* - 重定向到一个目录: `networkLoggerSupplier = { DirectoryLogger("Net ${it.id}") }`
|
||||
* - 重定向到一个文件: `networkLoggerSupplier = { SingleFileLogger("Net ${it.id}") }`
|
||||
*
|
||||
* @see MiraiLogger
|
||||
* Json 序列化器, 使用 'kotlinx.serialization'
|
||||
*/
|
||||
public var botLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Bot ${it.id}") }
|
||||
@MiraiExperimentalApi
|
||||
public var json: Json = kotlin.runCatching {
|
||||
Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
prettyPrint = true
|
||||
}
|
||||
}.getOrElse { Json {} }
|
||||
|
||||
/**
|
||||
* 网络层日志构造器
|
||||
*
|
||||
* - 默认打印到标准输出, 通过 [MiraiLogger.create]
|
||||
* - 忽略所有日志: [noNetworkLog]
|
||||
* - 重定向到一个目录: `networkLoggerSupplier = { DirectoryLogger("Net ${it.id}") }`
|
||||
* - 重定向到一个文件: `networkLoggerSupplier = { SingleFileLogger("Net ${it.id}") }`
|
||||
*
|
||||
* @see MiraiLogger
|
||||
*/
|
||||
public var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Net ${it.id}") }
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Coroutines
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** 父 [CoroutineContext]. [Bot] 创建后会使用 [SupervisorJob] 覆盖其 [Job], 但会将这个 [Job] 作为父 [Job] */
|
||||
public var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* 使用当前协程的 [coroutineContext] 作为 [parentCoroutineContext].
|
||||
*
|
||||
* Bot 将会使用一个 [SupervisorJob] 覆盖 [coroutineContext] 当前协程的 [Job], 并使用当前协程的 [Job] 作为父 [Job]
|
||||
*
|
||||
* 用例:
|
||||
* ```
|
||||
* coroutineScope {
|
||||
* val bot = Bot(...) {
|
||||
* inheritCoroutineContext()
|
||||
* }
|
||||
* bot.login()
|
||||
* } // coroutineScope 会等待 Bot 退出
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* **注意**: `bot.cancel` 时将会让父 [Job] 也被 cancel.
|
||||
* ```
|
||||
* coroutineScope { // this: CoroutineScope
|
||||
* launch {
|
||||
* while(isActive) {
|
||||
* delay(500)
|
||||
* println("I'm alive")
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* val bot = Bot(...) {
|
||||
* inheritCoroutineContext() // 使用 `coroutineScope` 的 Job 作为父 Job
|
||||
* }
|
||||
* bot.login()
|
||||
* bot.cancel() // 取消了整个 `coroutineScope`, 因此上文不断打印 `"I'm alive"` 的协程也会被取消.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 因此, 此函数尤为适合在 `suspend fun main()` 中使用, 它能阻止主线程退出:
|
||||
* ```
|
||||
* suspend fun main() {
|
||||
* val bot = Bot() {
|
||||
* inheritCoroutineContext()
|
||||
* }
|
||||
* bot.subscribe { ... }
|
||||
*
|
||||
* // 主线程不会退出, 直到 Bot 离线.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 简言之,
|
||||
* - 若想让 [Bot] 作为 '守护进程' 运行, 则无需调用 [inheritCoroutineContext].
|
||||
* - 若想让 [Bot] 依赖于当前协程, 让当前协程等待 [Bot] 运行, 则使用 [inheritCoroutineContext]
|
||||
*
|
||||
* @see parentCoroutineContext
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@ConfigurationDsl
|
||||
public suspend inline fun inheritCoroutineContext() {
|
||||
parentCoroutineContext = coroutineContext
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Connection
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** 心跳周期. 过长会导致被服务器断开连接. */
|
||||
public var heartbeatPeriodMillis: Long = 60.secondsToMillis
|
||||
|
||||
@ -125,6 +180,26 @@ public open class BotConfiguration { // open for Java
|
||||
/** 使用协议类型 */
|
||||
public var protocol: MiraiProtocol = MiraiProtocol.ANDROID_PHONE
|
||||
|
||||
public enum class MiraiProtocol {
|
||||
/**
|
||||
* Android 手机. 所有功能都支持.
|
||||
*/
|
||||
ANDROID_PHONE,
|
||||
|
||||
/**
|
||||
* Android 平板.
|
||||
*
|
||||
* 注意: 不支持戳一戳事件解析
|
||||
*/
|
||||
ANDROID_PAD,
|
||||
|
||||
/**
|
||||
* Android 手表.
|
||||
*/
|
||||
ANDROID_WATCH,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Highway 通道上传图片, 语音, 文件等资源时的协程数量.
|
||||
*
|
||||
@ -135,25 +210,6 @@ public open class BotConfiguration { // open for Java
|
||||
*/
|
||||
public var highwayUploadCoroutineCount: Int = Runtime.getRuntime().availableProcessors()
|
||||
|
||||
/**
|
||||
* 设备信息覆盖. 在没有手动指定时将会通过日志警告, 并使用随机设备信息.
|
||||
* @see fileBasedDeviceInfo 使用指定文件存储设备信息
|
||||
* @see randomDeviceInfo 使用随机设备信息
|
||||
*/
|
||||
public var deviceInfo: ((Bot) -> DeviceInfo)? = deviceInfoStub // allows user to set `null` manually.
|
||||
|
||||
/**
|
||||
* Json 序列化器, 使用 'kotlinx.serialization'
|
||||
*/
|
||||
@MiraiExperimentalApi
|
||||
public var json: Json = kotlin.runCatching {
|
||||
Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
prettyPrint = true
|
||||
}
|
||||
}.getOrElse { Json {} }
|
||||
|
||||
/**
|
||||
* 设置 [autoReconnectOnForceOffline] 为 `true`, 即在被挤下线时自动重连.
|
||||
* @since 2.1
|
||||
@ -163,6 +219,17 @@ public open class BotConfiguration { // open for Java
|
||||
autoReconnectOnForceOffline = true
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Device
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 设备信息覆盖. 在没有手动指定时将会通过日志警告, 并使用随机设备信息.
|
||||
* @see fileBasedDeviceInfo 使用指定文件存储设备信息
|
||||
* @see randomDeviceInfo 使用随机设备信息
|
||||
*/
|
||||
public var deviceInfo: ((Bot) -> DeviceInfo)? = deviceInfoStub // allows user to set `null` manually.
|
||||
|
||||
/**
|
||||
* 使用随机设备信息.
|
||||
*
|
||||
@ -198,6 +265,34 @@ public open class BotConfiguration { // open for Java
|
||||
deviceInfo = getFileBasedDeviceInfoSupplier { workingDir.resolve(filepath) }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Logging
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 日志记录器
|
||||
*
|
||||
* - 默认打印到标准输出, 通过 [MiraiLogger.create]
|
||||
* - 忽略所有日志: [noBotLog]
|
||||
* - 重定向到一个目录: `networkLoggerSupplier = { DirectoryLogger("Net ${it.id}") }`
|
||||
* - 重定向到一个文件: `networkLoggerSupplier = { SingleFileLogger("Net ${it.id}") }`
|
||||
*
|
||||
* @see MiraiLogger
|
||||
*/
|
||||
public var botLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Bot ${it.id}") }
|
||||
|
||||
/**
|
||||
* 网络层日志构造器
|
||||
*
|
||||
* - 默认打印到标准输出, 通过 [MiraiLogger.create]
|
||||
* - 忽略所有日志: [noNetworkLog]
|
||||
* - 重定向到一个目录: `networkLoggerSupplier = { DirectoryLogger("Net ${it.id}") }`
|
||||
* - 重定向到一个文件: `networkLoggerSupplier = { SingleFileLogger("Net ${it.id}") }`
|
||||
*
|
||||
* @see MiraiLogger
|
||||
*/
|
||||
public var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Net ${it.id}") }
|
||||
|
||||
|
||||
/**
|
||||
* 重定向 [网络日志][networkLoggerSupplier] 到指定目录. 若目录不存在将会自动创建 ([File.mkdirs])
|
||||
@ -265,33 +360,6 @@ public open class BotConfiguration { // open for Java
|
||||
botLoggerSupplier = { DirectoryLogger(identity(it), workingDir.resolve(dir), retain) }
|
||||
}
|
||||
|
||||
public enum class MiraiProtocol {
|
||||
/**
|
||||
* Android 手机. 所有功能都支持.
|
||||
*/
|
||||
ANDROID_PHONE,
|
||||
|
||||
/**
|
||||
* Android 平板.
|
||||
*
|
||||
* 注意: 不支持戳一戳事件解析
|
||||
*/
|
||||
ANDROID_PAD,
|
||||
|
||||
/**
|
||||
* Android 手表.
|
||||
*/
|
||||
ANDROID_WATCH,
|
||||
|
||||
}
|
||||
|
||||
public companion object {
|
||||
/** 默认的配置实例. 可以进行修改 */
|
||||
@JvmStatic
|
||||
public val Default: BotConfiguration = BotConfiguration()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 不显示网络日志. 不推荐.
|
||||
* @see networkLoggerSupplier 更多日志处理方式
|
||||
@ -310,86 +378,127 @@ public open class BotConfiguration { // open for Java
|
||||
botLoggerSupplier = { _ -> SilentLogger }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Cache
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 使用当前协程的 [coroutineContext] 作为 [parentCoroutineContext].
|
||||
*
|
||||
* Bot 将会使用一个 [SupervisorJob] 覆盖 [coroutineContext] 当前协程的 [Job], 并使用当前协程的 [Job] 作为父 [Job]
|
||||
*
|
||||
* 用例:
|
||||
* ```
|
||||
* coroutineScope {
|
||||
* val bot = Bot(...) {
|
||||
* inheritCoroutineContext()
|
||||
* }
|
||||
* bot.login()
|
||||
* } // coroutineScope 会等待 Bot 退出
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* **注意**: `bot.cancel` 时将会让父 [Job] 也被 cancel.
|
||||
* ```
|
||||
* coroutineScope { // this: CoroutineScope
|
||||
* launch {
|
||||
* while(isActive) {
|
||||
* delay(500)
|
||||
* println("I'm alive")
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* val bot = Bot(...) {
|
||||
* inheritCoroutineContext() // 使用 `coroutineScope` 的 Job 作为父 Job
|
||||
* }
|
||||
* bot.login()
|
||||
* bot.cancel() // 取消了整个 `coroutineScope`, 因此上文不断打印 `"I'm alive"` 的协程也会被取消.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 因此, 此函数尤为适合在 `suspend fun main()` 中使用, 它能阻止主线程退出:
|
||||
* ```
|
||||
* suspend fun main() {
|
||||
* val bot = Bot() {
|
||||
* inheritCoroutineContext()
|
||||
* }
|
||||
* bot.subscribe { ... }
|
||||
*
|
||||
* // 主线程不会退出, 直到 Bot 离线.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 简言之,
|
||||
* - 若想让 [Bot] 作为 '守护进程' 运行, 则无需调用 [inheritCoroutineContext].
|
||||
* - 若想让 [Bot] 依赖于当前协程, 让当前协程等待 [Bot] 运行, 则使用 [inheritCoroutineContext]
|
||||
*
|
||||
* @see parentCoroutineContext
|
||||
* 非 `null` 时启用好友列表缓存, 加快初始化速度. 在启用后将会在下载好友列表后保存到文件, 并在修改时自动保存.
|
||||
* @since 2.4
|
||||
* @see disableFriendListCache
|
||||
*/
|
||||
public var friendListCache: FriendListCache? = FriendListCache()
|
||||
|
||||
/**
|
||||
* 好友列表缓存设置.
|
||||
* @since 2.4
|
||||
* @see friendListCache
|
||||
*/
|
||||
public class FriendListCache @JvmOverloads constructor(
|
||||
/**
|
||||
* 缓存文件位置, 相对于 [workingDir] 的路径.
|
||||
*
|
||||
* 注意: 保存的文件仅供内部使用, 将来可能会变化.
|
||||
*/
|
||||
public val cacheFile: File = File("cache/friends.json"),
|
||||
/**
|
||||
* 在有好友列表修改时自动保存间隔
|
||||
*/
|
||||
public val saveIntervalMillis: Long = 60_000,
|
||||
)
|
||||
|
||||
/**
|
||||
* 禁用好友列表缓存.
|
||||
* @since 2.4
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@ConfigurationDsl
|
||||
public suspend inline fun inheritCoroutineContext() {
|
||||
parentCoroutineContext = coroutineContext
|
||||
public fun disableFriendListCache() {
|
||||
friendListCache = null
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 非 `null` 时启用群成员列表缓存, 加快初始化速度. 在启用后将会在下载群成员列表后保存到文件, 并在修改时自动保存.
|
||||
* @since 2.4
|
||||
* @see disableGroupMemberListCache
|
||||
*/
|
||||
public var groupMemberListCache: GroupMemberListCache? = GroupMemberListCache()
|
||||
|
||||
/**
|
||||
* 群成员列表缓存设置.
|
||||
* @since 2.4
|
||||
* @see groupMemberListCache
|
||||
*/
|
||||
public class GroupMemberListCache @JvmOverloads constructor(
|
||||
/**
|
||||
* 缓存目录位置, 相对于 [workingDir] 的路径.
|
||||
*
|
||||
* 注意: 保存的文件仅供内部使用, 将来可能会变化.
|
||||
*/
|
||||
public val cacheDir: File = File("cache/groups"),
|
||||
/**
|
||||
* 在有成员列表修改时自动保存间隔
|
||||
*/
|
||||
public val saveIntervalMillis: Long = 60_000,
|
||||
)
|
||||
|
||||
/**
|
||||
* 禁用群成员列表缓存.
|
||||
* @since 2.4
|
||||
*/
|
||||
@ConfigurationDsl
|
||||
public fun disableGroupMemberListCache() {
|
||||
groupMemberListCache = null
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用好友列表, 群成员列表, 陌生人列表的缓存.
|
||||
* @since 2.4
|
||||
*/
|
||||
@ConfigurationDsl
|
||||
public fun disableContactCaches() {
|
||||
disableFriendListCache()
|
||||
disableGroupMemberListCache()
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Misc
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public fun copy(): BotConfiguration {
|
||||
return BotConfiguration().also { new ->
|
||||
new.botLoggerSupplier = botLoggerSupplier
|
||||
new.networkLoggerSupplier = networkLoggerSupplier
|
||||
new.deviceInfo = deviceInfo
|
||||
// To structural order
|
||||
new.workingDir = workingDir
|
||||
new.json = json
|
||||
new.parentCoroutineContext = parentCoroutineContext
|
||||
new.heartbeatPeriodMillis = heartbeatPeriodMillis
|
||||
new.heartbeatTimeoutMillis = heartbeatTimeoutMillis
|
||||
new.firstReconnectDelayMillis = firstReconnectDelayMillis
|
||||
new.reconnectPeriodMillis = reconnectPeriodMillis
|
||||
new.reconnectionRetryTimes = reconnectionRetryTimes
|
||||
new.autoReconnectOnForceOffline = autoReconnectOnForceOffline
|
||||
new.loginSolver = loginSolver
|
||||
new.protocol = protocol
|
||||
new.highwayUploadCoroutineCount = highwayUploadCoroutineCount
|
||||
new.deviceInfo = deviceInfo
|
||||
new.botLoggerSupplier = botLoggerSupplier
|
||||
new.networkLoggerSupplier = networkLoggerSupplier
|
||||
new.friendListCache = friendListCache
|
||||
new.groupMemberListCache = groupMemberListCache
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 标注一个配置 DSL 函数 */
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@DslMarker
|
||||
public annotation class ConfigurationDsl
|
||||
|
||||
public companion object {
|
||||
/** 默认的配置实例. 可以进行修改 */
|
||||
@JvmStatic
|
||||
public val Default: BotConfiguration = BotConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@ package net.mamoe.mirai.utils
|
||||
|
||||
import io.ktor.utils.io.charsets.*
|
||||
import kotlinx.io.core.*
|
||||
import java.io.File
|
||||
import kotlin.text.Charsets
|
||||
|
||||
|
||||
@ -123,4 +124,11 @@ public inline fun Input.readString(length: UShort, charset: Charset = Charsets.U
|
||||
String(this.readBytes(length.toInt()), charset = charset)
|
||||
|
||||
public inline fun Input.readString(length: Byte, charset: Charset = Charsets.UTF_8): String =
|
||||
String(this.readBytes(length.toInt()), charset = charset)
|
||||
String(this.readBytes(length.toInt()), charset = charset)
|
||||
|
||||
public fun File.createFileIfNotExists() {
|
||||
if (!this.exists()) {
|
||||
this.parentFile.mkdirs()
|
||||
this.createNewFile()
|
||||
}
|
||||
}
|
24
mirai-core-utils/src/commonMain/kotlin/Serialization.kt
Normal file
24
mirai-core-utils/src/commonMain/kotlin/Serialization.kt
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2020 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/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.StringFormat
|
||||
import java.io.File
|
||||
|
||||
public fun <T> File.loadAs(
|
||||
serializer: DeserializationStrategy<T>,
|
||||
stringFormat: StringFormat,
|
||||
): T? {
|
||||
if (!this.exists() || this.length() == 0L) {
|
||||
return null
|
||||
}
|
||||
return stringFormat.decodeFromString(serializer, this.readText())
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal
|
||||
|
||||
import contact.StrangerImpl
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.okhttp.*
|
||||
import io.ktor.client.features.*
|
||||
@ -19,12 +20,15 @@ import kotlinx.coroutines.withContext
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readBytes
|
||||
import kotlinx.serialization.json.*
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.*
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.*
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.message.*
|
||||
import net.mamoe.mirai.internal.network.highway.*
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo
|
||||
|
@ -19,24 +19,24 @@ import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.*
|
||||
import net.mamoe.mirai.internal.contact.OtherClientImpl
|
||||
import net.mamoe.mirai.internal.contact.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.checkIsGroupImpl
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.uin
|
||||
import net.mamoe.mirai.internal.message.*
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.*
|
||||
import net.mamoe.mirai.internal.network.handler.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketWithRespType
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.*
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.internal.network.useNextServers
|
||||
import net.mamoe.mirai.internal.utils.ScheduledJob
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.network.LoginFailedException
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.FriendInfo as JceFriendInfo
|
||||
import kotlin.time.milliseconds
|
||||
|
||||
internal fun Bot.asQQAndroidBot(): QQAndroidBot {
|
||||
contract {
|
||||
@ -58,7 +58,7 @@ internal class QQAndroidBot constructor(
|
||||
configuration: BotConfiguration
|
||||
) : AbstractBot<QQAndroidBotNetworkHandler>(configuration, account.id) {
|
||||
var client: QQAndroidClient = initClient()
|
||||
private set
|
||||
private set
|
||||
|
||||
fun initClient(): QQAndroidClient {
|
||||
client = QQAndroidClient(
|
||||
@ -77,15 +77,45 @@ internal class QQAndroidBot constructor(
|
||||
|
||||
override val friends: ContactList<Friend> = ContactList()
|
||||
|
||||
override lateinit var nick: String
|
||||
val friendListCache: FriendListCache? by lazy {
|
||||
configuration.friendListCache?.cacheFile?.let { cacheFile ->
|
||||
val ret = configuration.workingDir.resolve(cacheFile).loadAs(FriendListCache.serializer(), JsonForCache) ?: FriendListCache()
|
||||
|
||||
internal var selfInfo: JceFriendInfo? = null
|
||||
get() = field ?: error("selfInfo is not yet initialized")
|
||||
set(it) {
|
||||
checkNotNull(it)
|
||||
field = it
|
||||
nick = it.nick
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
bot.eventChannel.parentScope(this@QQAndroidBot)
|
||||
.subscribeAlways<net.mamoe.mirai.event.events.FriendInfoChangeEvent> {
|
||||
friendListSaver?.notice()
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
val groupMemberListCaches: GroupMemberListCaches? by lazy {
|
||||
if (configuration.groupMemberListCache!= null) {
|
||||
GroupMemberListCaches(this)
|
||||
} else null
|
||||
}
|
||||
|
||||
private val friendListSaver by lazy {
|
||||
configuration.friendListCache?.let { friendListCache: BotConfiguration.FriendListCache ->
|
||||
|
||||
ScheduledJob(coroutineContext, friendListCache.saveIntervalMillis.milliseconds) {
|
||||
runBIO { saveFriendCache() }
|
||||
}
|
||||
}
|
||||
}
|
||||
fun saveFriendCache() {
|
||||
val friendListCache = friendListCache
|
||||
if (friendListCache != null) {
|
||||
configuration.friendListCache?.cacheFile?.let { configuration.workingDir.resolve(it) }?.run {
|
||||
createFileIfNotExists()
|
||||
writeText(JsonForCache.encodeToString(FriendListCache.serializer(), friendListCache))
|
||||
bot.network.logger.info { "Saved ${friendListCache.list.size} friends to local cache." }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override lateinit var nick: String
|
||||
|
||||
override val asFriend: Friend by lazy {
|
||||
@OptIn(LowLevelApi::class)
|
||||
@ -107,7 +137,7 @@ internal class QQAndroidBot constructor(
|
||||
|
||||
override suspend fun sendLogout() {
|
||||
network.run {
|
||||
StatSvc.Register.offline(client). sendWithoutExpect()
|
||||
StatSvc.Register.offline(client).sendWithoutExpect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ package net.mamoe.mirai.internal.contact
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.utils.cast
|
||||
import net.mamoe.mirai.utils.getValue
|
||||
import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
|
@ -40,9 +40,6 @@ import kotlin.coroutines.CoroutineContext
|
||||
|
||||
internal val User.info: UserInfo? get() = this.castOrNull<AbstractUser>()?.info
|
||||
|
||||
internal open class UserInfoImpl(override val uin: Long, override val nick: String, override val remark: String = "") :
|
||||
UserInfo
|
||||
|
||||
internal abstract class AbstractUser(
|
||||
bot: Bot,
|
||||
coroutineContext: CoroutineContext,
|
||||
|
@ -23,10 +23,10 @@ import kotlinx.atomicfu.atomic
|
||||
import net.mamoe.mirai.LowLevelApi
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.data.FriendInfoImpl
|
||||
import net.mamoe.mirai.event.events.FriendMessagePostSendEvent
|
||||
import net.mamoe.mirai.event.events.FriendMessagePreSendEvent
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
|
||||
import net.mamoe.mirai.internal.utils.C2CPkgMsgParsingCache
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
@ -42,15 +42,6 @@ internal fun net.mamoe.mirai.internal.network.protocol.data.jce.FriendInfo.toMir
|
||||
remark
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal inline fun FriendInfo.checkIsInfoImpl(): FriendInfoImpl {
|
||||
contract {
|
||||
returns() implies (this@checkIsInfoImpl is FriendInfoImpl)
|
||||
}
|
||||
check(this is FriendInfoImpl) { "A FriendInfo instance is not instance of checkIsInfoImpl. Your instance: ${this::class.qualifiedName}" }
|
||||
return this
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal inline fun Friend.checkIsFriendImpl(): FriendImpl {
|
||||
contract {
|
||||
|
@ -20,9 +20,10 @@ import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.message.*
|
||||
import net.mamoe.mirai.internal.network.BdhSession
|
||||
import net.mamoe.mirai.internal.network.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.highway.*
|
||||
import net.mamoe.mirai.internal.network.highway.ResourceKind.GROUP_IMAGE
|
||||
import net.mamoe.mirai.internal.network.highway.ResourceKind.GROUP_VOICE
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.contact
|
||||
|
||||
import contact.StrangerImpl
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.nextEventOrNull
|
||||
import net.mamoe.mirai.internal.MiraiImpl
|
||||
|
@ -15,17 +15,19 @@
|
||||
"INVISIBLE_REFERENCE"
|
||||
)
|
||||
|
||||
package net.mamoe.mirai.internal.contact
|
||||
package contact
|
||||
|
||||
import kotlinx.atomicfu.AtomicInt
|
||||
import kotlinx.atomicfu.atomic
|
||||
import net.mamoe.mirai.LowLevelApi
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.FriendInfoImpl
|
||||
import net.mamoe.mirai.data.StrangerInfo
|
||||
import net.mamoe.mirai.event.events.StrangerMessagePostSendEvent
|
||||
import net.mamoe.mirai.event.events.StrangerMessagePreSendEvent
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.AbstractUser
|
||||
import net.mamoe.mirai.internal.contact.StrangerSendMessageHandler
|
||||
import net.mamoe.mirai.internal.contact.sendMessageImpl
|
||||
import net.mamoe.mirai.internal.message.OnlineMessageSourceToStrangerImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.StrangerList
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
@ -36,20 +38,6 @@ import kotlin.contracts.contract
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
|
||||
internal class StrangerInfoImpl(
|
||||
override val uin: Long, override val nick: String, override val fromGroup: Long = 0,
|
||||
override val remark: String = ""
|
||||
) : StrangerInfo
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal inline fun StrangerInfo.checkIsInfoImpl(): FriendInfoImpl {
|
||||
contract {
|
||||
returns() implies (this@checkIsInfoImpl is StrangerInfoImpl)
|
||||
}
|
||||
check(this is FriendInfoImpl) { "A StrangerInfo instance is not instance of StrangerInfoImpl. Your instance: ${this::class.qualifiedName}" }
|
||||
return this
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal inline fun Stranger.checkIsImpl(): StrangerImpl {
|
||||
contract {
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2020 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/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.contact.info
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
|
||||
// since 2.4, for serialization
|
||||
@Serializable
|
||||
internal data class FriendInfoImpl(
|
||||
override val uin: Long,
|
||||
override var nick: String,
|
||||
override var remark: String,
|
||||
) : FriendInfo
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.contact.info
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.data.GroupInfo
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum
|
||||
|
||||
@Serializable
|
||||
internal data class GroupInfoImpl(
|
||||
override val uin: Long,
|
||||
override val owner: Long,
|
||||
override val groupCode: Long,
|
||||
override val memo: String,
|
||||
override val name: String,
|
||||
override val allowMemberInvite: Boolean,
|
||||
override val allowAnonymousChat: Boolean,
|
||||
override val autoApprove: Boolean,
|
||||
override val confessTalk: Boolean,
|
||||
override val muteAll: Boolean,
|
||||
override val botMuteTimestamp: Int,
|
||||
) : GroupInfo, Packet, Packet.NoLog {
|
||||
constructor(stTroopNum: StTroopNum) : this(
|
||||
uin = stTroopNum.groupUin,
|
||||
owner = stTroopNum.dwGroupOwnerUin,
|
||||
groupCode = stTroopNum.groupCode,
|
||||
memo = stTroopNum.groupMemo,
|
||||
name = stTroopNum.groupName,
|
||||
allowMemberInvite = stTroopNum.dwGroupFlagExt?.and(0x000000c0) != 0L,
|
||||
allowAnonymousChat = stTroopNum.dwGroupFlagExt?.and(0x40000000) == 0L,
|
||||
autoApprove = stTroopNum.dwGroupFlagExt3?.and(0x00100000) == 0L,
|
||||
confessTalk = stTroopNum.dwGroupFlagExt3?.and(0x00002000) == 0L,
|
||||
muteAll = stTroopNum.dwShutUpTimestamp != 0L,
|
||||
botMuteTimestamp = stTroopNum.dwMyShutUpTimestamp?.toInt() ?: 0,
|
||||
)
|
||||
}
|
@ -7,15 +7,17 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.contact
|
||||
package net.mamoe.mirai.internal.contact.info
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopMemberInfo
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
|
||||
internal class MemberInfoImpl(
|
||||
@Serializable
|
||||
internal data class MemberInfoImpl(
|
||||
override val uin: Long,
|
||||
override var nick: String,
|
||||
override var permission: MemberPermission,
|
||||
@ -27,7 +29,7 @@ internal class MemberInfoImpl(
|
||||
override val joinTimestamp: Int = currentTimeSeconds().toInt(),
|
||||
override var lastSpeakTimestamp: Int = 0,
|
||||
override val isOfficialBot: Boolean = false
|
||||
) : MemberInfo, UserInfoImpl(uin, nick, remark) {
|
||||
) : MemberInfo {
|
||||
constructor(
|
||||
client: QQAndroidClient,
|
||||
jceInfo: StTroopMemberInfo,
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.contact.info
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.data.StrangerInfo
|
||||
|
||||
@SerialName("StrangerInfo")
|
||||
@Serializable
|
||||
internal class StrangerInfoImpl(
|
||||
override val uin: Long,
|
||||
override val nick: String,
|
||||
override val fromGroup: Long = 0,
|
||||
override val remark: String = ""
|
||||
) : StrangerInfo
|
@ -18,6 +18,7 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.utils.MiraiInternalApi
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.WeakRefProperty
|
||||
@ -46,7 +47,7 @@ internal abstract class BotNetworkHandler : CoroutineScope {
|
||||
* 所属 [Bot]. 为弱引用
|
||||
*/
|
||||
@WeakRefProperty
|
||||
abstract val bot: Bot
|
||||
abstract val bot: QQAndroidBot
|
||||
|
||||
/**
|
||||
* 监管 child [Job]s
|
||||
|
126
mirai-core/src/commonMain/kotlin/network/ContactListCache.kt
Normal file
126
mirai-core/src/commonMain/kotlin/network/ContactListCache.kt
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum
|
||||
import net.mamoe.mirai.internal.utils.ScheduledJob
|
||||
import net.mamoe.mirai.utils.createFileIfNotExists
|
||||
import net.mamoe.mirai.utils.info
|
||||
import net.mamoe.mirai.utils.runBIO
|
||||
import java.io.File
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import kotlin.time.milliseconds
|
||||
|
||||
internal val JsonForCache = Json {
|
||||
encodeDefaults = true
|
||||
ignoreUnknownKeys = true
|
||||
isLenient = true
|
||||
}
|
||||
|
||||
@Serializable
|
||||
internal data class FriendListCache(
|
||||
var friendListSeq: Long = 0,
|
||||
/**
|
||||
* 实际上是个序列号, 不是时间
|
||||
*/
|
||||
var timeStamp: Long = 0,
|
||||
var list: List<FriendInfoImpl> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
internal data class GroupMemberListCache(
|
||||
var troopMemberNumSeq: Long,
|
||||
var list: List<MemberInfoImpl> = emptyList(),
|
||||
)
|
||||
|
||||
internal fun GroupMemberListCache.isValid(stTroopNum: StTroopNum): Boolean {
|
||||
return this.list.size == stTroopNum.dwMemberNum?.toInt() && this.troopMemberNumSeq == stTroopNum.dwMemberNumSeq
|
||||
}
|
||||
|
||||
internal class GroupMemberListCaches(
|
||||
private val bot: QQAndroidBot,
|
||||
) {
|
||||
init {
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
bot.eventChannel.parentScope(bot)
|
||||
.subscribeAlways<net.mamoe.mirai.event.events.BaseGroupMemberInfoChangeEvent> {
|
||||
groupListSaver.notice()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val changedGroups: MutableCollection<Long> = ConcurrentLinkedQueue()
|
||||
private val groupListSaver by lazy {
|
||||
ScheduledJob(bot.coroutineContext, bot.configuration.groupMemberListCache!!.saveIntervalMillis.milliseconds) {
|
||||
runBIO { saveGroupCaches() }
|
||||
}
|
||||
}
|
||||
|
||||
fun reportChanged(groupCode: Long) {
|
||||
changedGroups.add(groupCode)
|
||||
groupListSaver.notice()
|
||||
}
|
||||
|
||||
private fun takeCurrentChangedGroups(): Map<Long, GroupMemberListCache> {
|
||||
val ret = HashMap<Long, GroupMemberListCache>()
|
||||
changedGroups.removeIf {
|
||||
ret[it] = get(it)
|
||||
true
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
private val cacheDir by lazy {
|
||||
bot.configuration.groupMemberListCache!!.cacheDir.let { bot.configuration.workingDir.resolve(it) }
|
||||
}
|
||||
|
||||
private fun resolveCacheFile(groupCode: Long): File {
|
||||
cacheDir.mkdirs()
|
||||
return cacheDir.resolve("$groupCode.json")
|
||||
}
|
||||
|
||||
fun saveGroupCaches() {
|
||||
val currentChanged = takeCurrentChangedGroups()
|
||||
if (currentChanged.isNotEmpty()) {
|
||||
for ((id, cache) in currentChanged) {
|
||||
val file = resolveCacheFile(id)
|
||||
file.createFileIfNotExists()
|
||||
file.writeText(JsonForCache.encodeToString(GroupMemberListCache.serializer(), cache))
|
||||
}
|
||||
bot.network.logger.info { "Saved ${currentChanged.size} groups to local cache." }
|
||||
}
|
||||
}
|
||||
|
||||
val map: MutableMap<Long, GroupMemberListCache> = ConcurrentHashMap()
|
||||
|
||||
fun retainAll(list: Collection<Long>) {
|
||||
this.map.keys.retainAll(list)
|
||||
}
|
||||
|
||||
operator fun get(id: Long): GroupMemberListCache {
|
||||
return map.getOrPut(id) {
|
||||
val file = resolveCacheFile(id)
|
||||
if (file.exists() && file.isFile) {
|
||||
val text = file.readText()
|
||||
if (text.isNotBlank()) {
|
||||
return JsonForCache.decodeFromString(GroupMemberListCache.serializer(), text)
|
||||
}
|
||||
}
|
||||
|
||||
GroupMemberListCache(0, emptyList())
|
||||
}
|
||||
}
|
||||
}
|
232
mirai-core/src/commonMain/kotlin/network/ContactUpdater.kt
Normal file
232
mirai-core/src/commonMain/kotlin/network/ContactUpdater.kt
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright 2020 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/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network
|
||||
|
||||
import contact.StrangerImpl
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.FriendImpl
|
||||
import net.mamoe.mirai.internal.contact.GroupImpl
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.GroupInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.toMiraiFriendInfo
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcRespRegister
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.isValid
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopManagement
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.StrangerList
|
||||
import net.mamoe.mirai.utils.info
|
||||
import net.mamoe.mirai.utils.retryCatching
|
||||
import net.mamoe.mirai.utils.verbose
|
||||
|
||||
internal interface ContactUpdater {
|
||||
suspend fun loadAll(registerResp: SvcRespRegister)
|
||||
|
||||
fun closeAllContacts(e: CancellationException)
|
||||
}
|
||||
|
||||
internal class ContactUpdaterImpl(
|
||||
val bot: QQAndroidBot,
|
||||
) : ContactUpdater {
|
||||
@Synchronized
|
||||
override suspend fun loadAll(registerResp: SvcRespRegister) {
|
||||
coroutineScope {
|
||||
launch { reloadFriendList(registerResp) }
|
||||
launch { reloadGroupList() }
|
||||
launch { reloadStrangerList() }
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun closeAllContacts(e: CancellationException) {
|
||||
if (!initFriendOk) {
|
||||
bot.friends.delegate.removeAll { it.cancel(e); true }
|
||||
}
|
||||
if (!initGroupOk) {
|
||||
bot.groups.delegate.removeAll { it.cancel(e); true }
|
||||
}
|
||||
if (!initStrangerOk) {
|
||||
bot.strangers.delegate.removeAll { it.cancel(e); true }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Volatile
|
||||
private var initFriendOk = false
|
||||
|
||||
@Volatile
|
||||
private var initGroupOk = false
|
||||
|
||||
@Volatile
|
||||
private var initStrangerOk = false
|
||||
|
||||
/**
|
||||
* Don't use concurrently
|
||||
*/
|
||||
private suspend fun reloadFriendList(registerResp: SvcRespRegister) = bot.network.run {
|
||||
if (initFriendOk) {
|
||||
return
|
||||
}
|
||||
|
||||
val friendListCache = bot.friendListCache
|
||||
|
||||
fun updateCacheSeq(list: List<FriendInfoImpl>) {
|
||||
bot.friendListCache?.apply {
|
||||
friendListSeq = registerResp.iLargeSeq
|
||||
timeStamp = registerResp.timeStamp
|
||||
this.list = list
|
||||
bot.saveFriendCache()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun refreshFriendList(): List<FriendInfoImpl> {
|
||||
logger.info { "Start loading friend list..." }
|
||||
val friendInfos = mutableListOf<FriendInfoImpl>()
|
||||
|
||||
var count = 0
|
||||
var total: Short
|
||||
while (true) {
|
||||
val data = FriendList.GetFriendGroupList(
|
||||
bot.client, count, 150, 0, 0
|
||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 5000, retry = 2)
|
||||
|
||||
total = data.totalFriendCount
|
||||
|
||||
for (jceInfo in data.friendList) {
|
||||
friendInfos.add(jceInfo.toMiraiFriendInfo())
|
||||
}
|
||||
|
||||
count += data.friendList.size
|
||||
logger.verbose { "Loading friend list: ${count}/${total}" }
|
||||
if (count >= total) break
|
||||
}
|
||||
logger.info { "Successfully loaded friend list: $count in total" }
|
||||
return friendInfos
|
||||
}
|
||||
|
||||
val list = if (friendListCache?.isValid(registerResp) == true) {
|
||||
val list = friendListCache.list
|
||||
bot.network.logger.info { "Loaded ${list.size} friends from local cache." }
|
||||
list
|
||||
} else {
|
||||
refreshFriendList().also {
|
||||
updateCacheSeq(it)
|
||||
}
|
||||
}
|
||||
|
||||
for (friendInfoImpl in list) {
|
||||
addFriendToBot(friendInfoImpl)
|
||||
}
|
||||
|
||||
|
||||
initFriendOk = true
|
||||
}
|
||||
|
||||
private fun addFriendToBot(it: FriendInfo) =
|
||||
bot.friends.delegate.add(FriendImpl(bot, bot.coroutineContext, it))
|
||||
|
||||
private suspend fun addGroupToBot(stTroopNum: StTroopNum) = stTroopNum.run {
|
||||
suspend fun refreshGroupMemberList(): Sequence<MemberInfo> {
|
||||
return Mirai.getRawGroupMemberList(
|
||||
bot,
|
||||
groupUin,
|
||||
groupCode,
|
||||
dwGroupOwnerUin
|
||||
)
|
||||
}
|
||||
|
||||
val cache = bot.groupMemberListCaches?.get(groupCode)
|
||||
val members = if (cache != null) {
|
||||
if (cache.isValid(stTroopNum)) {
|
||||
cache.list.asSequence().also {
|
||||
bot.network.logger.info { "Loaded ${cache.list.size} members from local cache for group ${groupName} (${groupCode})" }
|
||||
}
|
||||
} else refreshGroupMemberList().also { sequence ->
|
||||
cache.troopMemberNumSeq = dwMemberNumSeq ?: 0
|
||||
cache.list = sequence.mapTo(ArrayList()) { it as MemberInfoImpl }
|
||||
bot.groupMemberListCaches!!.reportChanged(groupCode)
|
||||
}
|
||||
} else {
|
||||
refreshGroupMemberList()
|
||||
}
|
||||
|
||||
bot.groups.delegate.add(
|
||||
GroupImpl(
|
||||
bot = bot,
|
||||
coroutineContext = bot.coroutineContext,
|
||||
id = groupCode,
|
||||
groupInfo = GroupInfoImpl(stTroopNum),
|
||||
members = members
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun reloadStrangerList() = bot.network.run {
|
||||
if (initStrangerOk) {
|
||||
return
|
||||
}
|
||||
var currentCount = 0
|
||||
logger.info { "Start loading stranger list..." }
|
||||
val response = StrangerList.GetStrangerList(bot.client)
|
||||
.sendAndExpect<StrangerList.GetStrangerList.Response>(timeoutMillis = 5000, retry = 2)
|
||||
|
||||
if (response.result == 0) {
|
||||
response.strangerList.forEach {
|
||||
// atomic
|
||||
bot.strangers.delegate.add(
|
||||
StrangerImpl(bot, bot.coroutineContext, StrangerInfoImpl(it.uin, it.nick.decodeToString()))
|
||||
).also { currentCount++ }
|
||||
}
|
||||
}
|
||||
logger.info { "Successfully loaded stranger list: $currentCount in total" }
|
||||
initStrangerOk = true
|
||||
|
||||
}
|
||||
|
||||
private suspend fun reloadGroupList() = bot.network.run {
|
||||
if (initGroupOk) {
|
||||
return
|
||||
}
|
||||
TroopManagement.GetTroopConfig(bot.client).sendAndExpect<TroopManagement.GetTroopConfig.Response>()
|
||||
|
||||
logger.info { "Start loading group list..." }
|
||||
val troopListData = FriendList.GetTroopListSimplify(bot.client)
|
||||
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 5)
|
||||
|
||||
val semaphore = Semaphore(30)
|
||||
|
||||
coroutineScope {
|
||||
troopListData.groups.forEach { group ->
|
||||
launch {
|
||||
semaphore.withPermit {
|
||||
retryCatching(5) { addGroupToBot(group) }.getOrThrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info { "Successfully loaded group list: ${troopListData.groups.size} in total." }
|
||||
bot.groupMemberListCaches?.saveGroupCaches()
|
||||
initGroupOk = true
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,17 +7,14 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
package net.mamoe.mirai.internal.network
|
||||
package net.mamoe.mirai.internal.network.handler
|
||||
|
||||
import kotlinx.atomicfu.AtomicRef
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
@ -29,15 +26,11 @@ import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.createOtherClient
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum
|
||||
import net.mamoe.mirai.internal.network.*
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgSvc
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.*
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.KnownPacketFactories.PacketFactoryIllegalStateException
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.GroupInfoImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopManagement
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetMsg
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.StrangerList
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.ConfigPushSvc
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.Heartbeat
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
@ -272,13 +265,8 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
||||
|
||||
// println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
|
||||
registerClientOnline()
|
||||
|
||||
startHeartbeatJobOrKill()
|
||||
|
||||
bot.otherClientsLock.withLock {
|
||||
updateOtherClientsList()
|
||||
}
|
||||
|
||||
launch {
|
||||
while (isActive) {
|
||||
bot.client.wLoginSigInfo.sKey.run {
|
||||
@ -299,17 +287,17 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
||||
WtLogin15(bot.client).sendAndExpect()
|
||||
}
|
||||
|
||||
private suspend fun registerClientOnline() {
|
||||
private suspend fun registerClientOnline(): StatSvc.Register.Response {
|
||||
// object : OutgoingPacketFactory<Packet?>("push.proxyUnRegister") {
|
||||
// override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet? {
|
||||
// return null
|
||||
// }
|
||||
// }.buildOutgoingUniPacket(bot.client) {}.sendWithoutExpect()
|
||||
kotlin.runCatching {
|
||||
StatSvc.Register.offline(bot.client).sendAndExpect()
|
||||
}.getOrElse { logger.warning(it) }
|
||||
// kotlin.runCatching {
|
||||
// StatSvc.Register.offline(bot.client).sendAndExpect()
|
||||
// }.getOrElse { logger.warning(it) }
|
||||
|
||||
StatSvc.Register.online(bot.client).sendAndExpect()
|
||||
return StatSvc.Register.online(bot.client).sendAndExpect()
|
||||
}
|
||||
|
||||
private suspend fun updateOtherClientsList() {
|
||||
@ -333,177 +321,67 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
||||
internal var pendingIncomingPackets: ConcurrentLinkedQueue<KnownPacketFactories.IncomingPacket<*>>? =
|
||||
ConcurrentLinkedQueue()
|
||||
|
||||
private var initFriendOk = false
|
||||
private var initGroupOk = false
|
||||
private var initStrangerOk = false
|
||||
|
||||
/**
|
||||
* Don't use concurrently
|
||||
*/
|
||||
suspend fun reloadFriendList() {
|
||||
if (initFriendOk) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.info { "Start loading friend list..." }
|
||||
var currentFriendCount = 0
|
||||
var totalFriendCount: Short
|
||||
while (true) {
|
||||
val data = FriendList.GetFriendGroupList(
|
||||
bot.client, currentFriendCount, 150, 0, 0
|
||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 5000, retry = 2)
|
||||
|
||||
// self info
|
||||
data.selfInfo?.run {
|
||||
bot.selfInfo = this
|
||||
// bot.remark = remark ?: ""
|
||||
// bot.sex = sex
|
||||
}
|
||||
|
||||
totalFriendCount = data.totalFriendCount
|
||||
data.friendList.forEach {
|
||||
// atomic
|
||||
bot.friends.delegate.add(
|
||||
FriendImpl(bot, bot.coroutineContext, it.toMiraiFriendInfo())
|
||||
).also { currentFriendCount++ }
|
||||
}
|
||||
logger.verbose { "Loading friend list: ${currentFriendCount}/${totalFriendCount}" }
|
||||
if (currentFriendCount >= totalFriendCount) {
|
||||
break
|
||||
}
|
||||
// delay(200)
|
||||
}
|
||||
logger.info { "Successfully loaded friend list: $currentFriendCount in total" }
|
||||
initFriendOk = true
|
||||
}
|
||||
|
||||
suspend fun StTroopNum.reloadGroup() {
|
||||
bot.groups.delegate.add(
|
||||
GroupImpl(
|
||||
bot = bot,
|
||||
coroutineContext = bot.coroutineContext,
|
||||
id = groupCode,
|
||||
groupInfo = GroupInfoImpl(this),
|
||||
members = Mirai.getRawGroupMemberList(
|
||||
bot,
|
||||
groupUin,
|
||||
groupCode,
|
||||
dwGroupOwnerUin
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun reloadStrangerList() {
|
||||
if (initStrangerOk) {
|
||||
return
|
||||
}
|
||||
var currentCount = 0
|
||||
logger.info { "Start loading stranger list..." }
|
||||
val response = StrangerList.GetStrangerList(bot.client)
|
||||
.sendAndExpect<StrangerList.GetStrangerList.Response>(timeoutMillis = 5000, retry = 2)
|
||||
|
||||
if (response.result == 0) {
|
||||
response.strangerList.forEach {
|
||||
// atomic
|
||||
bot.strangers.delegate.add(
|
||||
StrangerImpl(bot, bot.coroutineContext, StrangerInfoImpl(it.uin, it.nick.decodeToString()))
|
||||
).also { currentCount++ }
|
||||
}
|
||||
}
|
||||
logger.info { "Successfully loaded stranger list: $currentCount in total" }
|
||||
initStrangerOk = true
|
||||
|
||||
}
|
||||
|
||||
suspend fun reloadGroupList() {
|
||||
if (initGroupOk) {
|
||||
return
|
||||
}
|
||||
logger.info { "Start syncing group config..." }
|
||||
TroopManagement.GetTroopConfig(bot.client).sendAndExpect<TroopManagement.GetTroopConfig.Response>()
|
||||
logger.info { "Successfully synced group config." }
|
||||
|
||||
logger.info { "Start loading group list..." }
|
||||
val troopListData = FriendList.GetTroopListSimplify(bot.client)
|
||||
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 5)
|
||||
|
||||
val semaphore = Semaphore(30)
|
||||
|
||||
coroutineScope {
|
||||
troopListData.groups.forEach { group ->
|
||||
launch {
|
||||
semaphore.withPermit {
|
||||
retryCatching(5) { group.reloadGroup() }.getOrThrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info { "Successfully loaded group list: ${troopListData.groups.size} in total." }
|
||||
initGroupOk = true
|
||||
}
|
||||
|
||||
private val contactUpdater: ContactUpdater by lazy { ContactUpdaterImpl(bot) }
|
||||
|
||||
override suspend fun init(): Unit = coroutineScope {
|
||||
check(bot.isActive) { "bot is dead therefore network can't init." }
|
||||
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't init." }
|
||||
|
||||
CancellationException("re-init").let { reInitCancellationException ->
|
||||
if (!initFriendOk) {
|
||||
bot.friends.delegate.removeAll { it.cancel(reInitCancellationException); true }
|
||||
}
|
||||
if (!initGroupOk) {
|
||||
bot.groups.delegate.removeAll { it.cancel(reInitCancellationException); true }
|
||||
}
|
||||
if (!initStrangerOk) {
|
||||
bot.strangers.delegate.removeAll { it.cancel(reInitCancellationException); true }
|
||||
}
|
||||
}
|
||||
contactUpdater.closeAllContacts(CancellationException("re-init"))
|
||||
|
||||
if (!pendingEnabled) {
|
||||
pendingIncomingPackets = ConcurrentLinkedQueue()
|
||||
_pendingEnabled.value = true
|
||||
}
|
||||
|
||||
coroutineScope {
|
||||
launch { reloadFriendList() }
|
||||
launch { reloadGroupList() }
|
||||
launch { reloadStrangerList() }
|
||||
val registerResp = registerClientOnline()
|
||||
|
||||
this@QQAndroidBotNetworkHandler.launch(CoroutineName("Awaiting ConfigPushSvc.PushReq"), block= ConfigPushSyncer())
|
||||
|
||||
launch {
|
||||
syncMessageSvc()
|
||||
}
|
||||
|
||||
this@QQAndroidBotNetworkHandler.launch(CoroutineName("Awaiting ConfigPushSvc.PushReq")) {
|
||||
logger.info { "Awaiting ConfigPushSvc.PushReq." }
|
||||
when (val resp: ConfigPushSvc.PushReq.PushReqResponse? = nextEventOrNull(20_000)) {
|
||||
null -> {
|
||||
kotlin.runCatching { bot.client.bdhSession.completeExceptionally(TimeoutCancellationException("Timeout waiting for ConfigPushSvc.PushReq")) }
|
||||
logger.warning { "Missing ConfigPushSvc.PushReq. File uploading may be affected." }
|
||||
}
|
||||
is ConfigPushSvc.PushReq.PushReqResponse.Success -> {
|
||||
logger.info { "ConfigPushSvc.PushReq: Success." }
|
||||
}
|
||||
is ConfigPushSvc.PushReq.PushReqResponse.ChangeServer -> {
|
||||
bot.logger.info { "Server requires reconnect." }
|
||||
bot.logger.info { "Server list: ${resp.serverList.joinToString()}." }
|
||||
|
||||
if (resp.serverList.isNotEmpty()) {
|
||||
bot.serverList.clear()
|
||||
resp.serverList.shuffled().forEach {
|
||||
bot.serverList.add(it.host to it.port)
|
||||
}
|
||||
}
|
||||
|
||||
bot.launch { BotOfflineEvent.RequireReconnect(bot).broadcast() }
|
||||
return@launch
|
||||
}
|
||||
launch {
|
||||
bot.otherClientsLock.withLock {
|
||||
updateOtherClientsList()
|
||||
}
|
||||
}
|
||||
|
||||
syncMessageSvc()
|
||||
contactUpdater.loadAll(registerResp.origin)
|
||||
|
||||
bot.firstLoginSucceed = true
|
||||
postInitActions()
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
private fun BotNetworkHandler.ConfigPushSyncer(): suspend CoroutineScope.() -> Unit = launch@{
|
||||
logger.info { "Awaiting ConfigPushSvc.PushReq." }
|
||||
when (val resp: ConfigPushSvc.PushReq.PushReqResponse? = nextEventOrNull(20_000)) {
|
||||
null -> {
|
||||
kotlin.runCatching { bot.client.bdhSession.completeExceptionally(CancellationException("Timeout waiting for ConfigPushSvc.PushReq")) }
|
||||
logger.warning { "Missing ConfigPushSvc.PushReq. File uploading may be affected." }
|
||||
}
|
||||
is ConfigPushSvc.PushReq.PushReqResponse.Success -> {
|
||||
logger.info { "ConfigPushSvc.PushReq: Success." }
|
||||
}
|
||||
is ConfigPushSvc.PushReq.PushReqResponse.ChangeServer -> {
|
||||
bot.logger.info { "Server requires reconnect." }
|
||||
bot.logger.info { "Server list: ${resp.serverList.joinToString()}." }
|
||||
|
||||
if (resp.serverList.isNotEmpty()) {
|
||||
bot.serverList.clear()
|
||||
resp.serverList.shuffled().forEach {
|
||||
bot.serverList.add(it.host to it.port)
|
||||
}
|
||||
}
|
||||
|
||||
bot.launch { BotOfflineEvent.RequireReconnect(bot).broadcast() }
|
||||
return@launch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun postInitActions() {
|
||||
_pendingEnabled.value = false
|
||||
pendingIncomingPackets?.forEach {
|
@ -15,41 +15,41 @@ import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
|
||||
|
||||
@Serializable
|
||||
internal class SvcReqRegister(
|
||||
@TarsId(0) @JvmField val lUin: Long = 0L,
|
||||
@TarsId(1) @JvmField val lBid: Long = 0L,
|
||||
@TarsId(2) @JvmField val cConnType: Byte = 0,
|
||||
@TarsId(3) @JvmField val sOther: String = "",
|
||||
@TarsId(4) @JvmField val iStatus: Int = 11,
|
||||
@TarsId(5) @JvmField val bOnlinePush: Byte = 0,
|
||||
@TarsId(6) @JvmField val bIsOnline: Byte = 0,
|
||||
@TarsId(7) @JvmField val bIsShowOnline: Byte = 0,
|
||||
@TarsId(8) @JvmField val bKikPC: Byte = 0,
|
||||
@TarsId(9) @JvmField val bKikWeak: Byte = 0,
|
||||
@TarsId(10) @JvmField val timeStamp: Long = 0L,
|
||||
@TarsId(11) @JvmField val iOSVersion: Long = 0L,
|
||||
@TarsId(12) @JvmField val cNetType: Byte = 0,
|
||||
@TarsId(13) @JvmField val sBuildVer: String? = "",
|
||||
@TarsId(14) @JvmField val bRegType: Byte = 0,
|
||||
@TarsId(15) @JvmField val vecDevParam: ByteArray? = null,
|
||||
@TarsId(16) @JvmField val vecGuid: ByteArray? = null,
|
||||
@TarsId(17) @JvmField val iLocaleID: Int = 2052,
|
||||
@TarsId(18) @JvmField val bSlientPush: Byte = 0,
|
||||
@TarsId(19) @JvmField val strDevName: String? = null,
|
||||
@TarsId(20) @JvmField val strDevType: String? = null,
|
||||
@TarsId(21) @JvmField val strOSVer: String? = null,
|
||||
@TarsId(22) @JvmField val bOpenPush: Byte = 1,
|
||||
@TarsId(23) @JvmField val iLargeSeq: Long = 0L,
|
||||
@TarsId(24) @JvmField val iLastWatchStartTime: Long = 0L,
|
||||
@TarsId(26) @JvmField val uOldSSOIp: Long = 0L,
|
||||
@TarsId(27) @JvmField val uNewSSOIp: Long = 0L,
|
||||
@TarsId(28) @JvmField val sChannelNo: String? = null,
|
||||
@TarsId(29) @JvmField val lCpId: Long = 0L,
|
||||
@TarsId(30) @JvmField val strVendorName: String? = null,
|
||||
@TarsId(31) @JvmField val strVendorOSName: String? = null,
|
||||
@TarsId(32) @JvmField val strIOSIdfa: String? = null,
|
||||
@TarsId(33) @JvmField val bytes_0x769_reqbody: ByteArray? = null,
|
||||
@TarsId(34) @JvmField val bIsSetStatus: Byte = 0,
|
||||
@TarsId(35) @JvmField val vecServerBuf: ByteArray? = null,
|
||||
@TarsId(36) @JvmField val bSetMute: Byte = 0
|
||||
@TarsId(0) @JvmField var lUin: Long = 0L,
|
||||
@TarsId(1) @JvmField var lBid: Long = 0L,
|
||||
@TarsId(2) @JvmField var cConnType: Byte = 0,
|
||||
@TarsId(3) @JvmField var sOther: String = "",
|
||||
@TarsId(4) @JvmField var iStatus: Int = 11,
|
||||
@TarsId(5) @JvmField var bOnlinePush: Byte = 0,
|
||||
@TarsId(6) @JvmField var bIsOnline: Byte = 0,
|
||||
@TarsId(7) @JvmField var bIsShowOnline: Byte = 0,
|
||||
@TarsId(8) @JvmField var bKikPC: Byte = 0,
|
||||
@TarsId(9) @JvmField var bKikWeak: Byte = 0,
|
||||
@TarsId(10) @JvmField var timeStamp: Long = 0L,
|
||||
@TarsId(11) @JvmField var iOSVersion: Long = 0L,
|
||||
@TarsId(12) @JvmField var cNetType: Byte = 0,
|
||||
@TarsId(13) @JvmField var sBuildVer: String? = "",
|
||||
@TarsId(14) @JvmField var bRegType: Byte = 0,
|
||||
@TarsId(15) @JvmField var vecDevParam: ByteArray? = null,
|
||||
@TarsId(16) @JvmField var vecGuid: ByteArray? = null,
|
||||
@TarsId(17) @JvmField var iLocaleID: Int = 2052,
|
||||
@TarsId(18) @JvmField var bSlientPush: Byte = 0,
|
||||
@TarsId(19) @JvmField var strDevName: String? = null,
|
||||
@TarsId(20) @JvmField var strDevType: String? = null,
|
||||
@TarsId(21) @JvmField var strOSVer: String? = null,
|
||||
@TarsId(22) @JvmField var bOpenPush: Byte,
|
||||
@TarsId(23) @JvmField var iLargeSeq: Long,
|
||||
@TarsId(24) @JvmField var iLastWatchStartTime: Long = 0L,
|
||||
@TarsId(26) @JvmField var uOldSSOIp: Long = 0L,
|
||||
@TarsId(27) @JvmField var uNewSSOIp: Long = 0L,
|
||||
@TarsId(28) @JvmField var sChannelNo: String? = null,
|
||||
@TarsId(29) @JvmField var lCpId: Long = 0L,
|
||||
@TarsId(30) @JvmField var strVendorName: String? = null,
|
||||
@TarsId(31) @JvmField var strVendorOSName: String? = null,
|
||||
@TarsId(32) @JvmField var strIOSIdfa: String? = null,
|
||||
@TarsId(33) @JvmField var bytes_0x769_reqbody: ByteArray? = null,
|
||||
@TarsId(34) @JvmField var bIsSetStatus: Byte = 0,
|
||||
@TarsId(35) @JvmField var vecServerBuf: ByteArray? = null,
|
||||
@TarsId(36) @JvmField var bSetMute: Byte = 0
|
||||
// @SerialId(25) var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
|
||||
) : JceStruct
|
@ -10,6 +10,7 @@
|
||||
package net.mamoe.mirai.internal.network.protocol.data.jce
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.internal.network.FriendListCache
|
||||
import net.mamoe.mirai.internal.utils.io.JceStruct
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
|
||||
|
||||
@ -30,7 +31,15 @@ internal class SvcRespRegister(
|
||||
@JvmField @TarsId(11) val iClientPort: Int = 0,
|
||||
@JvmField @TarsId(12) val iHelloInterval: Int = 300,
|
||||
@JvmField @TarsId(13) val iLargeSeq: Long = 0L,
|
||||
/**
|
||||
* =1 好友列表更新
|
||||
*/
|
||||
@JvmField @TarsId(14) val largeSeqUpdate: Byte = 0,
|
||||
@JvmField @TarsId(15) val bytes_0x769_rspBody: ByteArray? = null,
|
||||
@JvmField @TarsId(16) val iStatus: Int? = 0
|
||||
) : JceStruct
|
||||
|
||||
internal fun FriendListCache.isValid(svcRespRegister: SvcRespRegister): Boolean {
|
||||
return svcRespRegister.iLargeSeq == friendListSeq && svcRespRegister.timeStamp == timeStamp
|
||||
// return this.largeSeqUpdate != 0.toByte()
|
||||
}
|
@ -16,7 +16,7 @@ import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.utils.io.encryptAndWrite
|
||||
import net.mamoe.mirai.internal.utils.io.writeHex
|
||||
|
@ -13,14 +13,13 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
import kotlinx.io.core.toByteArray
|
||||
import net.mamoe.mirai.LowLevelApi
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.info.GroupInfoImpl
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.ModifyGroupCardReq
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.stUinInfo
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.*
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
@ -28,24 +27,6 @@ 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.*
|
||||
import net.mamoe.mirai.utils.daysToSeconds
|
||||
import net.mamoe.mirai.data.GroupInfo as MiraiGroupInfo
|
||||
|
||||
@OptIn(LowLevelApi::class)
|
||||
internal class GroupInfoImpl(
|
||||
private val stTroopNum: StTroopNum
|
||||
) : MiraiGroupInfo, Packet, Packet.NoLog {
|
||||
override val uin: Long get() = stTroopNum.groupUin
|
||||
override val owner: Long get() = stTroopNum.dwGroupOwnerUin
|
||||
override val groupCode: Long get() = stTroopNum.groupCode
|
||||
override val memo: String get() = stTroopNum.groupMemo
|
||||
override val name: String get() = stTroopNum.groupName
|
||||
override val allowMemberInvite get() = stTroopNum.dwGroupFlagExt?.and(0x000000c0) != 0L
|
||||
override val allowAnonymousChat get() = stTroopNum.dwGroupFlagExt?.and(0x40000000) == 0L
|
||||
override val autoApprove get() = stTroopNum.dwGroupFlagExt3?.and(0x00100000) == 0L
|
||||
override val confessTalk get() = stTroopNum.dwGroupFlagExt3?.and(0x00002000) == 0L
|
||||
override val muteAll: Boolean get() = stTroopNum.dwShutUpTimestamp != 0L
|
||||
override val botMuteTimestamp: Int get() = stTroopNum.dwMyShutUpTimestamp?.toInt() ?: 0
|
||||
}
|
||||
|
||||
internal class TroopManagement {
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
|
||||
|
||||
import contact.checkIsImpl
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.delay
|
||||
@ -29,6 +30,8 @@ import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.message.OnlineMessageSourceFromFriendImpl
|
||||
import net.mamoe.mirai.internal.message.refine
|
||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
||||
@ -42,7 +45,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.SubMsgType0x7
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.GroupInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.GroupInfoImpl
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
|
||||
import net.mamoe.mirai.internal.utils.*
|
||||
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.event.events.GroupMessageSyncEvent
|
||||
import net.mamoe.mirai.event.events.MemberCardChangeEvent
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.message.refine
|
||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.contact.NormalMember
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
import net.mamoe.mirai.internal.network.MultiPacketByIterable
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
|
@ -21,12 +21,13 @@ import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.FriendInfoImpl
|
||||
import net.mamoe.mirai.data.GroupHonorType
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.network.MultiPacketBySequence
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
@ -708,7 +709,7 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
||||
return this.msgFrdRmk.asSequence().mapNotNull {
|
||||
val friend = bot.getFriend(it.fuin) ?: return@mapNotNull null
|
||||
val old: String
|
||||
friend.checkIsFriendImpl().friendInfo.checkIsInfoImpl()
|
||||
friend.checkIsFriendImpl().friendInfo
|
||||
.also { info -> old = info.remark }
|
||||
.remark = it.rmkName
|
||||
// TODO: 2020/4/10 ADD REMARK QUERY
|
||||
|
@ -30,7 +30,7 @@ import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
||||
internal class StrangerList {
|
||||
object GetStrangerList : OutgoingPacketFactory<GetStrangerList.Response>("OidbSvc.0x5d2_0") {
|
||||
|
||||
class Response(val result: Int, val strangerList: List<Oidb0x5d2.FriendEntry>) : Packet {
|
||||
class Response(val result: Int, val strangerList: List<Oidb0x5d2.FriendEntry>, val origin: Oidb0x5d2.RspGetList?) : Packet {
|
||||
override fun toString(): String {
|
||||
return "StrangerList.GetStrangerList.Response(result=$result)"
|
||||
}
|
||||
@ -61,10 +61,10 @@ internal class StrangerList {
|
||||
if (pkg.result == 0) {
|
||||
pkg.bodybuffer.loadAs(Oidb0x5d2.RspBody.serializer()).rspGetList!!.let {
|
||||
bot.client.strangerSeq = it.seq
|
||||
return Response(pkg.result, it.list)
|
||||
return Response(pkg.result, it.list, it)
|
||||
}
|
||||
}
|
||||
return Response(pkg.result, emptyList())
|
||||
return Response(pkg.result, emptyList(), null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.appId
|
||||
import net.mamoe.mirai.internal.createOtherClient
|
||||
import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
import net.mamoe.mirai.internal.network.FriendListCache
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.getRandomByteArray
|
||||
@ -94,29 +95,30 @@ internal class StatSvc {
|
||||
|
||||
internal object Register : OutgoingPacketFactory<Register.Response>("StatSvc.register") {
|
||||
|
||||
internal object Response : Packet {
|
||||
internal class Response(
|
||||
val origin: SvcRespRegister
|
||||
) : Packet {
|
||||
override fun toString(): String = "Response(StatSvc.register)"
|
||||
}
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||
val packet = readUniPacket(SvcRespRegister.serializer())
|
||||
if (packet.updateFlag.toInt() == 1) {
|
||||
//TODO 加载好友列表
|
||||
}
|
||||
if (packet.largeSeqUpdate.toInt() == 1) {
|
||||
//TODO 刷新好友列表
|
||||
}
|
||||
packet.iHelloInterval.let {
|
||||
bot.configuration.heartbeatPeriodMillis = it.times(1000).toLong()
|
||||
}
|
||||
|
||||
return Response
|
||||
return Response(packet)
|
||||
}
|
||||
|
||||
fun online(
|
||||
client: QQAndroidClient,
|
||||
regPushReason: RegPushReason = RegPushReason.appRegister
|
||||
) = impl(client, 1 or 2 or 4, client.onlineStatus, regPushReason)
|
||||
) = impl(client, 1 or 2 or 4, client.onlineStatus, regPushReason) {
|
||||
client.bot.friendListCache?.let { friendListCache: FriendListCache ->
|
||||
iLargeSeq = friendListCache.friendListSeq
|
||||
// timeStamp = friendListCache.timeStamp
|
||||
}
|
||||
}
|
||||
|
||||
fun offline(
|
||||
client: QQAndroidClient,
|
||||
@ -127,7 +129,8 @@ internal class StatSvc {
|
||||
client: QQAndroidClient,
|
||||
bid: Long,
|
||||
status: OnlineStatus,
|
||||
regPushReason: RegPushReason = RegPushReason.appRegister
|
||||
regPushReason: RegPushReason = RegPushReason.appRegister,
|
||||
applyAction: SvcReqRegister.() -> Unit = {}
|
||||
) = buildLoginOutgoingPacket(
|
||||
client,
|
||||
bodyType = 1,
|
||||
@ -198,7 +201,7 @@ internal class StatSvc {
|
||||
)
|
||||
),
|
||||
bSetMute = 0
|
||||
)
|
||||
).apply(applyAction)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
71
mirai-core/src/commonMain/kotlin/utils/ScheduledJob.kt
Normal file
71
mirai-core/src/commonMain/kotlin/utils/ScheduledJob.kt
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2020 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/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.utils
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.time.Duration
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
internal class ScheduledJob(
|
||||
coroutineContext: CoroutineContext,
|
||||
val interval: Duration,
|
||||
private val task: suspend () -> Unit
|
||||
) : CoroutineScope by CoroutineScope(coroutineContext + SupervisorJob(coroutineContext[Job])) {
|
||||
private val coroutineExceptionHandler =
|
||||
coroutineContext[CoroutineExceptionHandler].also {
|
||||
requireNotNull(it) {
|
||||
"Could not init ScheduledJob, coroutineExceptionHandler == null"
|
||||
}
|
||||
}
|
||||
|
||||
private val channel = Channel<Unit>(Channel.CONFLATED)
|
||||
|
||||
fun notice() {
|
||||
if (interval == Duration.ZERO) {
|
||||
launch { task() }
|
||||
} else channel.offer(Unit)
|
||||
}
|
||||
|
||||
private suspend fun doTask() {
|
||||
runCatching {
|
||||
task()
|
||||
}.onFailure {
|
||||
coroutineExceptionHandler!!.handleException(currentCoroutineContext(), it)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
if (interval != Duration.ZERO) {
|
||||
launch {
|
||||
channel.receiveAsFlow()
|
||||
.runCatching {
|
||||
sample(interval.toLongMilliseconds())
|
||||
}
|
||||
.fold(
|
||||
onSuccess = { flow ->
|
||||
flow.collect { doTask() }
|
||||
},
|
||||
onFailure = {
|
||||
// binary change
|
||||
while (isActive) {
|
||||
delay(interval)
|
||||
task()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
mirai-core/src/commonTest/kotlin/ScheduledJobTest.kt
Normal file
38
mirai-core/src/commonTest/kotlin/ScheduledJobTest.kt
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
package net.mamoe.mirai.internal.utils
|
||||
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.time.seconds
|
||||
|
||||
internal class ScheduledJobTest {
|
||||
@Test
|
||||
fun testScheduledJob() {
|
||||
runBlocking {
|
||||
val scope = CoroutineScope(CoroutineExceptionHandler { _, throwable ->
|
||||
throwable.printStackTrace()
|
||||
})
|
||||
val invoked = AtomicInteger(0)
|
||||
val job = ScheduledJob(scope.coroutineContext, 1.seconds) {
|
||||
invoked.incrementAndGet()
|
||||
}
|
||||
delay(100)
|
||||
assertEquals(0, invoked.get())
|
||||
job.notice()
|
||||
job.notice()
|
||||
job.notice()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user