mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-09 01:30:17 +08:00
Add FriendDeleteEvent
, FriendAddEvent
, also fix #216
This commit is contained in:
parent
6af75c02f7
commit
918ede1fa6
@ -56,6 +56,7 @@ internal fun Group.checkIsGroupImpl() {
|
||||
GroupImpl.checkIsInstance(this)
|
||||
}
|
||||
|
||||
@OptIn(MiraiExperimentalAPI::class, LowLevelAPI::class)
|
||||
@Suppress("PropertyName")
|
||||
internal class GroupImpl(
|
||||
bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
|
||||
@ -70,44 +71,20 @@ internal class GroupImpl(
|
||||
|
||||
override val bot: QQAndroidBot by bot.unsafeWeakRef()
|
||||
|
||||
@OptIn(LowLevelAPI::class)
|
||||
val uin: Long = groupInfo.uin
|
||||
|
||||
override lateinit var owner: Member
|
||||
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
override val botAsMember: Member by lazy {
|
||||
newMember(object : MemberInfo {
|
||||
override val nameCard: String
|
||||
get() = bot.nick // TODO: 2020/2/21 机器人在群内的昵称获取
|
||||
override val permission: MemberPermission
|
||||
get() = botPermission
|
||||
override val specialTitle: String
|
||||
get() = "" // TODO: 2020/2/21 获取机器人在群里的头衔
|
||||
override val muteTimestamp: Int
|
||||
get() = botMuteRemaining
|
||||
override val uin: Long
|
||||
get() = bot.id
|
||||
override val nick: String
|
||||
get() = bot.nick
|
||||
})
|
||||
}
|
||||
override lateinit var botAsMember: Member
|
||||
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
override lateinit var botPermission: MemberPermission
|
||||
|
||||
var _botMuteTimestamp: Int = groupInfo.botMuteTimestamp
|
||||
|
||||
override val botMuteRemaining: Int =
|
||||
if (_botMuteTimestamp == 0 || _botMuteTimestamp == 0xFFFFFFFF.toInt()) {
|
||||
0
|
||||
} else {
|
||||
_botMuteTimestamp - currentTimeSeconds.toInt() - bot.client.timeDifference.toInt()
|
||||
}
|
||||
// e.g. 600
|
||||
override val botMuteRemaining: Int get() = botAsMember.muteTimeRemaining
|
||||
|
||||
override val members: ContactList<Member> = ContactList(members.mapNotNull {
|
||||
if (it.uin == bot.id) {
|
||||
botPermission = it.permission
|
||||
botAsMember = newMember(it)
|
||||
if (it.permission == MemberPermission.OWNER) {
|
||||
owner = botAsMember
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ internal class MemberImpl constructor(
|
||||
if (_muteTimestamp == 0 || _muteTimestamp == 0xFFFFFFFF.toInt()) {
|
||||
0
|
||||
} else {
|
||||
_muteTimestamp - currentTimeSeconds.toInt() - bot.client.timeDifference.toInt()
|
||||
(_muteTimestamp - currentTimeSeconds.toInt()).coerceAtLeast(0)
|
||||
}
|
||||
|
||||
override var nameCard: String
|
||||
|
@ -255,10 +255,6 @@ internal class OfflineMessageSourceImplBySourceMsg( // from others' quotation
|
||||
override val bot: Bot,
|
||||
groupIdOrZero: Long
|
||||
) : OfflineMessageSource(), MessageSourceImpl {
|
||||
init {
|
||||
println(delegate._miraiContentToString())
|
||||
}
|
||||
|
||||
override val kind: Kind get() = if (delegate.srcMsg == null) Kind.GROUP else Kind.FRIEND
|
||||
|
||||
private val isRecalled: AtomicBoolean = atomic(false)
|
||||
|
@ -1,8 +1,9 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
|
||||
|
||||
import net.mamoe.mirai.qqandroid.utils.io.serialization.jce.JceId
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.qqandroid.utils.io.JceStruct
|
||||
import net.mamoe.mirai.qqandroid.utils.io.serialization.jce.JceId
|
||||
|
||||
@Serializable
|
||||
internal class AddGroup(
|
||||
@ -62,7 +63,7 @@ internal class MsgType0x210(
|
||||
@JceId(7) val stMsgInfo0x20: MsgType0x210SubMsgType0x20? = null,
|
||||
@JceId(8) val stMsgInfo0x1d: MsgType0x210SubMsgType0x1d? = null,
|
||||
@JceId(9) val stMsgInfo0x24: MsgType0x210SubMsgType0x24? = null,
|
||||
@JceId(10) val vProtobuf: ByteArray? = null
|
||||
@JceId(10) val vProtobuf: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : JceStruct
|
||||
|
||||
@Serializable
|
||||
|
@ -74,7 +74,7 @@ internal class Vec0xd6b : ProtoBuf {
|
||||
internal class MutualMarkData(
|
||||
@ProtoId(1) val frdUin: Long = 0L,
|
||||
@ProtoId(2) val result: Int = 0
|
||||
// @SerialId(11) val mutualmarkInfo: List<Mutualmark.MutualMark>? = null
|
||||
// @SerialId(11) val mutualmarkInfo: List<net.mamoe.mirai.qqandroid.network.protocol.data.proto.onlinePush0x210.Mutualmark.MutualMark>? = null
|
||||
) : ProtoBuf
|
||||
}
|
||||
|
||||
|
@ -1,394 +0,0 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
|
||||
|
||||
import kotlinx.serialization.protobuf.ProtoId
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.qqandroid.utils.io.ProtoBuf
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||
|
||||
@Serializable
|
||||
internal class SubMsgType0x27 : ProtoBuf {
|
||||
@Serializable
|
||||
internal class AddGroup(
|
||||
@ProtoId(1) val groupid: Int = 0,
|
||||
@ProtoId(2) val sortid: Int = 0,
|
||||
@ProtoId(3) val groupname: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class AppointmentNotify(
|
||||
@ProtoId(1) val fromUin: Long = 0L,
|
||||
@ProtoId(2) val appointId: String = "",
|
||||
@ProtoId(3) val notifytype: Int = 0,
|
||||
@ProtoId(4) val tipsContent: String = "",
|
||||
@ProtoId(5) val unreadCount: Int = 0,
|
||||
@ProtoId(6) val joinWording: String = "",
|
||||
@ProtoId(7) val viewWording: String = "",
|
||||
@ProtoId(8) val sig: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(9) val eventInfo: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(10) val nearbyEventInfo: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(11) val feedEventInfo: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class BinaryMsg(
|
||||
@ProtoId(1) val opType: Int = 0,
|
||||
@ProtoId(2) val opValue: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ChatMatchInfo(
|
||||
@ProtoId(1) val sig: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(2) val uin: Long = 0L,
|
||||
@ProtoId(3) val matchUin: Long = 0L,
|
||||
@ProtoId(4) val tipsWording: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(5) val leftChatTime: Int = 0,
|
||||
@ProtoId(6) val timeStamp: Long = 0L,
|
||||
@ProtoId(7) val matchExpiredTime: Int = 0,
|
||||
@ProtoId(8) val c2cExpiredTime: Int = 0,
|
||||
@ProtoId(9) val matchCount: Int = 0,
|
||||
@ProtoId(10) val nick: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ConfMsgRoamFlag(
|
||||
@ProtoId(1) val confid: Long = 0L,
|
||||
@ProtoId(2) val flag: Int = 0,
|
||||
@ProtoId(3) val timestamp: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class DaRenNotify(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val loginDays: Int = 0,
|
||||
@ProtoId(3) val days: Int = 0,
|
||||
@ProtoId(4) val isYestodayLogin: Int = 0,
|
||||
@ProtoId(5) val isTodayLogin: Int = 0
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class DelFriend(
|
||||
@ProtoId(1) val uint64Uins: List<Long>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class DelGroup(
|
||||
@ProtoId(1) val groupid: Int = 0
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class FanpaiziNotify(
|
||||
@ProtoId(1) val fromUin: Long = 0L,
|
||||
@ProtoId(2) val fromNick: String = "",
|
||||
@ProtoId(3) val tipsContent: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(4) val sig: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ForwardBody(
|
||||
@ProtoId(1) val notifyType: Int = 0,
|
||||
@ProtoId(2) val opType: Int = 0,
|
||||
@ProtoId(3) val msgAddGroup: AddGroup? = null,
|
||||
@ProtoId(4) val msgDelGroup: DelGroup? = null,
|
||||
@ProtoId(5) val msgModGroupName: ModGroupName? = null,
|
||||
@ProtoId(6) val msgModGroupSort: ModGroupSort? = null,
|
||||
@ProtoId(7) val msgModFriendGroup: ModFriendGroup? = null,
|
||||
@ProtoId(8) val msgModProfile: ModProfile? = null,
|
||||
@ProtoId(9) val msgModFriendRemark: ModFriendRemark? = null,
|
||||
@ProtoId(10) val msgModLongNick: ModLongNick? = null,
|
||||
@ProtoId(11) val msgModCustomFace: ModCustomFace? = null,
|
||||
@ProtoId(12) val msgModGroupProfile: ModGroupProfile? = null,
|
||||
@ProtoId(13) val msgModGroupMemberProfile: ModGroupMemberProfile? = null,
|
||||
@ProtoId(14) val msgDelFriend: DelFriend? = null,
|
||||
@ProtoId(15) val msgRoamPriv: ModFrdRoamPriv? = null,
|
||||
@ProtoId(16) val msgGrpMsgRoamFlag: GrpMsgRoamFlag? = null,
|
||||
@ProtoId(17) val msgConfMsgRoamFlag: ConfMsgRoamFlag? = null,
|
||||
@ProtoId(18) val msgModRichLongNick: ModLongNick? = null,
|
||||
@ProtoId(19) val msgBinPkg: BinaryMsg? = null,
|
||||
@ProtoId(20) val msgModFriendRings: ModSnsGeneralInfo? = null,
|
||||
@ProtoId(21) val msgModConfProfile: ModConfProfile? = null,
|
||||
@ProtoId(22) val msgModFriendFlag: SnsUpdateFlag? = null,
|
||||
@ProtoId(23) val msgAppointmentNotify: AppointmentNotify? = null,
|
||||
@ProtoId(25) val msgDarenNotify: DaRenNotify? = null,
|
||||
@ProtoId(26) val msgNewComeinUserNotify: NewComeinUserNotify? = null,
|
||||
@ProtoId(200) val msgPushSearchDev: PushSearchDev? = null,
|
||||
@ProtoId(201) val msgPushReportDev: PushReportDev? = null,
|
||||
@ProtoId(202) val msgQqPayPush: QQPayPush? = null,
|
||||
@ProtoId(203) val redpointInfo: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(204) val msgHotFriendNotify: HotFriendNotify? = null,
|
||||
@ProtoId(205) val msgPraiseRankNotify: PraiseRankNotify? = null,
|
||||
@ProtoId(210) val msgCampusNotify: MQQCampusNotify? = null,
|
||||
@ProtoId(211) val msgModRichLongNickEx: ModLongNick? = null,
|
||||
@ProtoId(212) val msgChatMatchInfo: ChatMatchInfo? = null,
|
||||
@ProtoId(214) val msgFrdCustomOnlineStatusChange: FrdCustomOnlineStatusChange? = null,
|
||||
@ProtoId(2000) val msgFanpanziNotify: FanpaiziNotify? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class FrdCustomOnlineStatusChange(
|
||||
@ProtoId(1) val uin: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class FriendGroup(
|
||||
@ProtoId(1) val fuin: Long = 0L,
|
||||
@ProtoId(2) val uint32OldGroupId: List<Int>? = null,
|
||||
@ProtoId(3) val uint32NewGroupId: List<Int>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class FriendRemark(
|
||||
@ProtoId(1) val type: Int = 0,
|
||||
@ProtoId(2) val fuin: Long = 0L,
|
||||
@ProtoId(3) val rmkName: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(4) val groupCode: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class GPS(
|
||||
@ProtoId(1) val int32Lat: Int = 900000000,
|
||||
@ProtoId(2) val int32Lon: Int = 900000000,
|
||||
@ProtoId(3) val int32Alt: Int = -10000000,
|
||||
@ProtoId(4) val int32Type: Int = 0
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class GroupMemberProfileInfo(
|
||||
@ProtoId(1) val field: Int = 0,
|
||||
@ProtoId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class GroupProfileInfo(
|
||||
@ProtoId(1) val field: Int = 0,
|
||||
@ProtoId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class GroupSort(
|
||||
@ProtoId(1) val groupid: Int = 0,
|
||||
@ProtoId(2) val sortid: Int = 0
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class GrpMsgRoamFlag(
|
||||
@ProtoId(1) val groupcode: Long = 0L,
|
||||
@ProtoId(2) val flag: Int = 0,
|
||||
@ProtoId(3) val timestamp: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class HotFriendNotify(
|
||||
@ProtoId(1) val dstUin: Long = 0L,
|
||||
@ProtoId(2) val praiseHotLevel: Int = 0,
|
||||
@ProtoId(3) val chatHotLevel: Int = 0,
|
||||
@ProtoId(4) val praiseHotDays: Int = 0,
|
||||
@ProtoId(5) val chatHotDays: Int = 0,
|
||||
@ProtoId(6) val closeLevel: Int = 0,
|
||||
@ProtoId(7) val closeDays: Int = 0,
|
||||
@ProtoId(8) val praiseFlag: Int = 0,
|
||||
@ProtoId(9) val chatFlag: Int = 0,
|
||||
@ProtoId(10) val closeFlag: Int = 0,
|
||||
@ProtoId(11) val notifyTime: Long = 0L,
|
||||
@ProtoId(12) val lastPraiseTime: Long = 0L,
|
||||
@ProtoId(13) val lastChatTime: Long = 0L,
|
||||
@ProtoId(14) val qzoneHotLevel: Int = 0,
|
||||
@ProtoId(15) val qzoneHotDays: Int = 0,
|
||||
@ProtoId(16) val qzoneFlag: Int = 0,
|
||||
@ProtoId(17) val lastQzoneTime: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModConfProfile(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val confUin: Int = 0,
|
||||
@ProtoId(3) val msgProfileInfos: List<ProfileInfo>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModCustomFace(
|
||||
@ProtoId(1) val type: Int = 0,
|
||||
@ProtoId(2) val uin: Long = 0L,
|
||||
@ProtoId(3) val groupCode: Long = 0L,
|
||||
@ProtoId(4) val cmdUin: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModFrdRoamPriv(
|
||||
@ProtoId(1) val msgRoamPriv: List<OneRoamPriv>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModFriendGroup(
|
||||
@ProtoId(1) val msgFrdGroup: List<FriendGroup>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModFriendRemark(
|
||||
@ProtoId(1) val msgFrdRmk: List<FriendRemark>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModGroupMemberProfile(
|
||||
@ProtoId(1) val groupUin: Long = 0L,
|
||||
@ProtoId(2) val uin: Long = 0L,
|
||||
@ProtoId(3) val msgGroupMemberProfileInfos: List<GroupMemberProfileInfo>? = null,
|
||||
@ProtoId(4) val groupCode: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModGroupName(
|
||||
@ProtoId(1) val groupid: Int = 0,
|
||||
@ProtoId(2) val groupname: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModGroupProfile(
|
||||
@ProtoId(1) val groupUin: Long = 0L,
|
||||
@ProtoId(2) val msgGroupProfileInfos: List<GroupProfileInfo>? = null,
|
||||
@ProtoId(3) val groupCode: Long = 0L,
|
||||
@ProtoId(4) val cmdUin: Long = 0L
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModGroupSort(
|
||||
@ProtoId(1) val msgGroupsort: List<GroupSort>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModLongNick(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModProfile(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val msgProfileInfos: List<ProfileInfo>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ModSnsGeneralInfo(
|
||||
@ProtoId(1) val msgSnsGeneralInfos: List<SnsUpateBuffer>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class MQQCampusNotify(
|
||||
@ProtoId(1) val fromUin: Long = 0L,
|
||||
@ProtoId(2) val wording: String = "",
|
||||
@ProtoId(3) val target: String = "",
|
||||
@ProtoId(4) val type: Int = 0,
|
||||
@ProtoId(5) val source: String = ""
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class MsgBody(
|
||||
@ProtoId(1) val msgModInfos: List<ForwardBody>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class NewComeinUser(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val isFrd: Int = 0,
|
||||
@ProtoId(3) val remark: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(4) val nick: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class NewComeinUserNotify(
|
||||
@ProtoId(1) val msgType: Int = 0,
|
||||
@ProtoId(2) val boolStrongNotify: Boolean = false,
|
||||
@ProtoId(3) val pushTime: Int = 0,
|
||||
@ProtoId(4) val msgNewComeinUser: NewComeinUser? = null,
|
||||
@ProtoId(5) val msgNewGroup: NewGroup? = null,
|
||||
@ProtoId(6) val msgNewGroupUser: NewGroupUser? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class NewGroup(
|
||||
@ProtoId(1) val groupCode: Long = 0L,
|
||||
@ProtoId(2) val groupName: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(3) val ownerUin: Long = 0L,
|
||||
@ProtoId(4) val ownerNick: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(5) val distance: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class NewGroupUser(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val int32Sex: Int = 0,
|
||||
@ProtoId(3) val int32Age: Int = 0,
|
||||
@ProtoId(4) val nick: String = "",
|
||||
@ProtoId(5) val distance: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class OneRoamPriv(
|
||||
@ProtoId(1) val fuin: Long = 0L,
|
||||
@ProtoId(2) val privTag: Int = 0,
|
||||
@ProtoId(3) val privValue: Int = 0
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class PraiseRankNotify(
|
||||
@ProtoId(11) val isChampion: Int = 0,
|
||||
@ProtoId(12) val rankNum: Int = 0,
|
||||
@ProtoId(13) val msg: String = ""
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class ProfileInfo(
|
||||
@ProtoId(1) val field: Int = 0,
|
||||
@ProtoId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class PushReportDev(
|
||||
@ProtoId(1) val msgType: Int = 0,
|
||||
@ProtoId(4) val cookie: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ProtoId(5) val reportMaxNum: Int = 200,
|
||||
@ProtoId(6) val sn: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class PushSearchDev(
|
||||
@ProtoId(1) val msgType: Int = 0,
|
||||
@ProtoId(2) val msgGpsInfo: GPS? = null,
|
||||
@ProtoId(3) val devTime: Int = 0,
|
||||
@ProtoId(4) val pushTime: Int = 0,
|
||||
@ProtoId(5) val din: Long = 0L,
|
||||
@ProtoId(6) val data: String = ""
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class QQPayPush(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val boolPayOk: Boolean = false
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class SnsUpateBuffer(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val code: Long = 0L,
|
||||
@ProtoId(3) val result: Int = 0,
|
||||
@ProtoId(400) val msgSnsUpdateItem: List<SnsUpdateItem>? = null,
|
||||
@ProtoId(401) val uint32Idlist: List<Int>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class SnsUpdateFlag(
|
||||
@ProtoId(1) val msgUpdateSnsFlag: List<SnsUpdateOneFlag>? = null
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class SnsUpdateItem(
|
||||
@ProtoId(1) val updateSnsType: Int = 0,
|
||||
@ProtoId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
|
||||
) : ProtoBuf
|
||||
|
||||
@Serializable
|
||||
internal class SnsUpdateOneFlag(
|
||||
@ProtoId(1) val uin: Long = 0L,
|
||||
@ProtoId(2) val id: Long = 0L,
|
||||
@ProtoId(3) val flag: Int = 0
|
||||
) : ProtoBuf
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,13 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.LowLevelAPI
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.getFriendOrNull
|
||||
import net.mamoe.mirai.message.GroupMessage
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.contact.GroupImpl
|
||||
@ -27,9 +30,13 @@ import net.mamoe.mirai.qqandroid.message.toMessageChain
|
||||
import net.mamoe.mirai.qqandroid.network.MultiPacketBySequence
|
||||
import net.mamoe.mirai.qqandroid.network.Packet
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.MsgInfo
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.MsgType0x210
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.OnlinePushPack
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.*
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.onlinePush0x210.Submsgtype0x27
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.onlinePush0x210.Submsgtype0x44
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.onlinePush0x210.Submsgtype0xb3
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildResponseUniPacket
|
||||
@ -42,6 +49,7 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.jce.JceId
|
||||
import net.mamoe.mirai.qqandroid.utils.read
|
||||
import net.mamoe.mirai.qqandroid.utils.toUHexString
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import net.mamoe.mirai.utils.debug
|
||||
|
||||
internal class OnlinePush {
|
||||
@ -220,18 +228,19 @@ internal class OnlinePush {
|
||||
return asSequence().flatMap { it.vMsg.read { mapper(it) } }
|
||||
}
|
||||
|
||||
private fun lambda(block: ByteReadPacket.(group: GroupImpl, bot: QQAndroidBot) -> Sequence<Packet>):
|
||||
private fun lambda732(block: ByteReadPacket.(group: GroupImpl, bot: QQAndroidBot) -> Sequence<Packet>):
|
||||
ByteReadPacket.(group: GroupImpl, bot: QQAndroidBot) -> Sequence<Packet> {
|
||||
return block
|
||||
}
|
||||
|
||||
object Transformers732 : Map<Int, ByteReadPacket.(GroupImpl, QQAndroidBot) -> Sequence<Packet>> by mapOf(
|
||||
0x0c to lambda { group: GroupImpl, bot: QQAndroidBot ->
|
||||
// mute
|
||||
0x0c to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
|
||||
val operatorUin = readUInt().toLong()
|
||||
if (operatorUin == bot.id) {
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
val operator = group.getOrNull(operatorUin) ?: return@lambda emptySequence()
|
||||
val operator = group.getOrNull(operatorUin) ?: return@lambda732 emptySequence()
|
||||
readUInt().toLong() // time
|
||||
this.discardExact(2)
|
||||
val target = readUInt().toLong()
|
||||
@ -240,51 +249,53 @@ internal class OnlinePush {
|
||||
if (target == 0L) {
|
||||
val new = time != 0
|
||||
if (group.settings.isMuteAll == new) {
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
group._muteAll = new
|
||||
return@lambda sequenceOf(GroupMuteAllEvent(!new, new, group, operator))
|
||||
return@lambda732 sequenceOf(GroupMuteAllEvent(!new, new, group, operator))
|
||||
}
|
||||
|
||||
if (target == bot.id) {
|
||||
return@lambda when {
|
||||
group._botMuteTimestamp == time -> emptySequence()
|
||||
return@lambda732 when {
|
||||
group.botMuteRemaining == time -> emptySequence()
|
||||
time == 0 -> {
|
||||
group._botMuteTimestamp = 0
|
||||
group.botAsMember.checkIsMemberImpl()._muteTimestamp = 0
|
||||
sequenceOf(BotUnmuteEvent(operator))
|
||||
}
|
||||
else -> {
|
||||
group._botMuteTimestamp = time
|
||||
group.botAsMember.checkIsMemberImpl()._muteTimestamp = currentTimeSeconds.toInt() + time
|
||||
sequenceOf(BotMuteEvent(time, operator))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val member = group.getOrNull(target) ?: return@lambda emptySequence()
|
||||
val member = group.getOrNull(target) ?: return@lambda732 emptySequence()
|
||||
member.checkIsMemberImpl()
|
||||
|
||||
if (member._muteTimestamp == time) {
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
|
||||
member._muteTimestamp = time
|
||||
return@lambda if (time == 0) sequenceOf(MemberUnmuteEvent(member, operator))
|
||||
return@lambda732 if (time == 0) sequenceOf(MemberUnmuteEvent(member, operator))
|
||||
else sequenceOf(MemberMuteEvent(member, time, operator))
|
||||
},
|
||||
|
||||
0x0e to lambda { group: GroupImpl, _: QQAndroidBot ->
|
||||
// anonymous
|
||||
0x0e to lambda732 { group: GroupImpl, _: QQAndroidBot ->
|
||||
// 匿名
|
||||
val operator = group.getOrNull(readUInt().toLong()) ?: return@lambda emptySequence()
|
||||
val operator = group.getOrNull(readUInt().toLong()) ?: return@lambda732 emptySequence()
|
||||
val new = readInt() == 0
|
||||
if (group.settings.isAnonymousChatEnabled == new) {
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
|
||||
group._anonymousChat = new
|
||||
return@lambda sequenceOf(GroupAllowAnonymousChatEvent(!new, new, group, operator))
|
||||
return@lambda732 sequenceOf(GroupAllowAnonymousChatEvent(!new, new, group, operator))
|
||||
},
|
||||
|
||||
0x10 to lambda { group: GroupImpl, bot: QQAndroidBot ->
|
||||
// confess
|
||||
0x10 to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
|
||||
val dataBytes = readBytes(26)
|
||||
val size = readByte().toInt() // orthodox, don't `readUByte`
|
||||
if (size < 0) {
|
||||
@ -305,15 +316,15 @@ internal class OnlinePush {
|
||||
"管理员已开启群聊坦白说" -> true
|
||||
else -> {
|
||||
bot.network.logger.debug { "Unknown server messages $message" }
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
}
|
||||
|
||||
if (group.settings.isConfessTalkEnabled == new) {
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
|
||||
return@lambda sequenceOf(
|
||||
return@lambda732 sequenceOf(
|
||||
GroupAllowConfessTalkEvent(
|
||||
new,
|
||||
false,
|
||||
@ -325,10 +336,10 @@ internal class OnlinePush {
|
||||
|
||||
else -> { // TODO SHOULD BE SPECIFIED TYPE
|
||||
if (group.name == message) {
|
||||
return@lambda emptySequence()
|
||||
return@lambda732 emptySequence()
|
||||
}
|
||||
|
||||
return@lambda sequenceOf(
|
||||
return@lambda732 sequenceOf(
|
||||
GroupNameChangeEvent(
|
||||
group.name.also { group._name = message },
|
||||
message, group, false
|
||||
@ -339,17 +350,17 @@ internal class OnlinePush {
|
||||
},
|
||||
|
||||
// recall
|
||||
0x11 to lambda { group: GroupImpl, bot: QQAndroidBot ->
|
||||
0x11 to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
|
||||
discardExact(1)
|
||||
val proto = readProtoBuf(TroopTips0x857.NotifyMsgBody.serializer())
|
||||
|
||||
val recallReminder = proto.optMsgRecall ?: return@lambda emptySequence()
|
||||
val recallReminder = proto.optMsgRecall ?: return@lambda732 emptySequence()
|
||||
|
||||
val operator =
|
||||
if (recallReminder.uin == bot.id) group.botAsMember
|
||||
else group.getOrNull(recallReminder.uin) ?: return@lambda emptySequence()
|
||||
else group.getOrNull(recallReminder.uin) ?: return@lambda732 emptySequence()
|
||||
|
||||
return@lambda recallReminder.recalledMsgList.asSequence().mapNotNull { pkg ->
|
||||
return@lambda732 recallReminder.recalledMsgList.asSequence().mapNotNull { pkg ->
|
||||
when {
|
||||
pkg.authorUin == bot.id && operator.id == bot.id -> null
|
||||
group.lastRecalledMessageRandoms.remove(pkg.msgRandom) -> null
|
||||
@ -362,11 +373,84 @@ internal class OnlinePush {
|
||||
}
|
||||
)
|
||||
|
||||
private fun lambda528(block: MsgType0x210.(bot: QQAndroidBot) -> Sequence<Packet>):
|
||||
MsgType0x210.(bot: QQAndroidBot) -> Sequence<Packet> {
|
||||
return block
|
||||
}
|
||||
|
||||
// uSubMsgType to vProtobuf
|
||||
// 138 or 139: top_package/akln.java:1568
|
||||
// 66: top_package/nhz.java:269
|
||||
/**
|
||||
* @see MsgType0x210
|
||||
*/
|
||||
@OptIn(LowLevelAPI::class, MiraiInternalAPI::class)
|
||||
object Transformers528 : Map<Long, MsgType0x210.(QQAndroidBot) -> Sequence<Packet>> by mapOf(
|
||||
0xB3L to lambda528 { bot ->
|
||||
// 08 01 12 52 08 A2 FF 8C F0 03 10 00 1D 15 3D 90 5E 22 2E E6 88 91 E4 BB AC E5 B7 B2 E7 BB 8F E6 98 AF E5 A5 BD E5 8F 8B E5 95 A6 EF BC 8C E4 B8 80 E8 B5 B7 E6 9D A5 E8 81 8A E5 A4 A9 E5 90 A7 21 2A 09 48 69 6D 31 38 38 6D 6F 65 30 07 38 03 48 DD F1 92 B7 07
|
||||
val body = vProtobuf.loadAs(Submsgtype0xb3.SubMsgType0xb3.MsgBody.serializer())
|
||||
val new = bot._lowLevelNewQQ(object : FriendInfo {
|
||||
override val uin: Long get() = body.msgAddFrdNotify.fuin
|
||||
override val nick: String get() = body.msgAddFrdNotify.fuinNick
|
||||
})
|
||||
bot.friends.delegate.addLast(new)
|
||||
return@lambda528 sequenceOf(FriendAddEvent(new))
|
||||
},
|
||||
0xE2L to lambda528 { bot ->
|
||||
// TODO: unknown. maybe messages.
|
||||
// 0A 35 08 00 10 A2 FF 8C F0 03 1A 1B E5 90 8C E6 84 8F E4 BD A0 E7 9A 84 E5 8A A0 E5 A5 BD E5 8F 8B E8 AF B7 E6 B1 82 22 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B 28 01
|
||||
// vProtobuf.loadAs(Msgtype0x210.serializer())
|
||||
|
||||
return@lambda528 emptySequence()
|
||||
},
|
||||
0x44L to lambda528 { bot ->
|
||||
val msg = vProtobuf.loadAs(Submsgtype0x44.Submsgtype0x44.MsgBody.serializer())
|
||||
when {
|
||||
msg.msgFriendMsgSync != null -> {
|
||||
|
||||
}
|
||||
}
|
||||
println(msg._miraiContentToString())
|
||||
return@lambda528 emptySequence()
|
||||
},
|
||||
0x27L to lambda528 { bot ->
|
||||
fun Submsgtype0x27.SubMsgType0x27.ModFriendRemark.transform(bot: QQAndroidBot): Sequence<Packet> {
|
||||
return this.msgFrdRmk?.asSequence()?.mapNotNull {
|
||||
val friend = bot.getFriendOrNull(it.fuin) ?: return@mapNotNull null
|
||||
FriendRemarkChangeEvent(bot, friend, it.rmkName)
|
||||
} ?: emptySequence()
|
||||
}
|
||||
|
||||
fun Submsgtype0x27.SubMsgType0x27.DelFriend.transform(bot: QQAndroidBot): Sequence<Packet> {
|
||||
return this.uint64Uins?.asSequence()?.mapNotNull {
|
||||
val friend = bot.getFriendOrNull(it) ?: return@mapNotNull null
|
||||
FriendDeleteEvent(friend)
|
||||
} ?: emptySequence()
|
||||
}
|
||||
|
||||
return@lambda528 vProtobuf.loadAs(Submsgtype0x27.SubMsgType0x27.MsgBody.serializer()).msgModInfos.asSequence()
|
||||
.flatMap {
|
||||
when {
|
||||
it.msgModFriendRemark != null -> it.msgModFriendRemark.transform(bot)
|
||||
it.msgDelFriend != null -> it.msgDelFriend.transform(bot)
|
||||
else -> {
|
||||
bot.network.logger.debug {
|
||||
"Transformers528 0x27L: new data: ${it._miraiContentToString()}"
|
||||
}
|
||||
emptySequence()
|
||||
}
|
||||
}
|
||||
}
|
||||
// 0A 1C 10 28 4A 18 0A 16 08 00 10 A2 FF 8C F0 03 1A 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B
|
||||
}
|
||||
)
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Response {
|
||||
val reqPushMsg = decodeUniPacket(OnlinePushPack.SvcReqPushMsg.serializer(), "req")
|
||||
|
||||
println(reqPushMsg._miraiContentToString())
|
||||
val packets: Sequence<Packet> = reqPushMsg.vMsgInfos.deco { msgInfo ->
|
||||
when (msgInfo.shMsgType.toInt()) {
|
||||
732 -> {
|
||||
@ -380,20 +464,28 @@ internal class OnlinePush {
|
||||
?.let { it(this@deco, group, bot) }
|
||||
?: kotlin.run {
|
||||
bot.network.logger.debug {
|
||||
"unknown group internal type $internalType , data: " + readBytes()
|
||||
.toUHexString() + " "
|
||||
"unknown group 732 type $internalType, data: " + readBytes().toUHexString()
|
||||
}
|
||||
return@deco emptySequence()
|
||||
}
|
||||
}
|
||||
|
||||
// 528 -> {
|
||||
// val notifyMsgBody = msgInfo.vMsg.loadAs(MsgType0x210.serializer())
|
||||
// OnlinePush0x210Factory.solve()
|
||||
// return@flatMap emptySequence()
|
||||
// }
|
||||
|
||||
// 00 27 1A 0C 1C 2C 3C 4C 5D 00 0C 6D 00 0C 7D 00 0C 8D 00 0C 9C AC BC CC DD 00 0C EC FC 0F 0B 2A 0C 1C 2C 3C 4C 5C 6C 0B 3A 0C 1C 2C 3C 4C 5C 6C 7C 8D 00 0C 9D 00 0C AC BD 00 0C CD 00 0C DC ED 00 0C FC 0F FC 10 0B 4A 0C 1C 2C 3C 4C 5C 6C 7C 8C 96 00 0B 5A 0C 1C 2C 3C 4C 5C 6C 7C 8C 9D 00 0C 0B 6A 0C 1A 0C 1C 26 00 0B 2A 0C 0B 3A 0C 16 00 0B 4A 09 0C 0B 5A 09 0C 0B 0B 7A 0C 1C 2C 36 00 0B 8A 0C 1C 2C 36 00 0B 9A 09 0C 0B AD 00 00 1E 0A 1C 10 28 4A 18 0A 16 08 00 10 A2 FF 8C F0 03 1A 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B
|
||||
528 -> {
|
||||
val notifyMsgBody = readJceStruct(MsgType0x210.serializer())
|
||||
Transformers528[notifyMsgBody.uSubMsgType]
|
||||
?.let { processor -> processor(notifyMsgBody, bot) }
|
||||
?: kotlin.run {
|
||||
bot.network.logger.debug {
|
||||
"unknown group 528 type ${notifyMsgBody.uSubMsgType}, data: " + notifyMsgBody.vProtobuf.toUHexString()
|
||||
}
|
||||
return@deco emptySequence()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
bot.network.logger.debug { "unknown sh type ${msgInfo.shMsgType.toInt()}" }
|
||||
bot.network.logger.debug { "data=${readBytes().toUHexString()}" }
|
||||
return@deco emptySequence()
|
||||
}
|
||||
}
|
||||
@ -402,8 +494,12 @@ internal class OnlinePush {
|
||||
}
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
internal class Response(val uin: Long, val svrip: Int, sequence: Sequence<Packet>) :
|
||||
MultiPacketBySequence<Packet>(sequence)
|
||||
internal data class Response(val uin: Long, val svrip: Int, val sequence: Sequence<Packet>) :
|
||||
MultiPacketBySequence<Packet>(sequence) {
|
||||
override fun toString(): String {
|
||||
return "OnlinePush.ReqPush.Response(sequence="
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
private class Resp(
|
||||
@ -416,13 +512,13 @@ internal class OnlinePush {
|
||||
writeJceStruct(
|
||||
RequestPacket.serializer(),
|
||||
RequestPacket(
|
||||
sServantName = "OnlinePush.RespPush",
|
||||
sServantName = "OnlinePush",
|
||||
sFuncName = "SvcRespPushMsg",
|
||||
iRequestId = 0,
|
||||
iRequestId = sequenceId,
|
||||
sBuffer = jceRequestSBuffer(
|
||||
"resp",
|
||||
Resp.serializer(),
|
||||
Resp(packet.uin, packet.svrip)
|
||||
OnlinePushPack.SvcRespPushMsg.serializer(),
|
||||
OnlinePushPack.SvcRespPushMsg(packet.uin, listOf(), packet.svrip)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -1,25 +0,0 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.onlinePush0x210
|
||||
|
||||
import kotlinx.io.core.String
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.event.events.MemberCardChangeEvent
|
||||
import net.mamoe.mirai.qqandroid.utils.io.serialization.loadAs
|
||||
|
||||
internal object OnlinePush0x210Factory {
|
||||
|
||||
// fun solve(msg: MsgType0x210, bot: Bot): Any? = when (msg.uSubMsgType) {
|
||||
// 0x27L -> {
|
||||
// val body = msg.vProtobuf?.loadAs(SubMsgType0x27.MsgBody.serializer())
|
||||
// if (body?.msgModInfos != null) {
|
||||
// body.msgModInfos.firstOrNull()?.msgModGroupMemberProfile?.run {
|
||||
// val member = bot.groups.getOrNull(groupUin)?.getOrNull(uin)
|
||||
// val new = msgGroupMemberProfileInfos?.firstOrNull()
|
||||
// if (member != null && new?.value != null) {
|
||||
// MemberCardChangeEvent(member.nameCard, String(new.value), member, member)
|
||||
// }
|
||||
// }
|
||||
// } else null
|
||||
// }
|
||||
// else -> null
|
||||
// }
|
||||
}
|
@ -484,6 +484,39 @@ data class MemberUnmuteEvent(
|
||||
|
||||
// region 好友、群认证
|
||||
|
||||
/**
|
||||
* 好友昵称改变事件. 目前仅支持解析 (来自 PC 端的修改).
|
||||
*/
|
||||
@SinceMirai("0.36.0")
|
||||
data class FriendRemarkChangeEvent(
|
||||
override val bot: Bot,
|
||||
val friend: QQ,
|
||||
val newName: String
|
||||
) : BotEvent, Packet
|
||||
|
||||
/**
|
||||
* 成功添加了一个新好友的事件
|
||||
*/
|
||||
@SinceMirai("0.36.0")
|
||||
data class FriendAddEvent(
|
||||
/**
|
||||
* 新好友. 已经添加到 [Bot.friends]
|
||||
*/
|
||||
val friend: QQ
|
||||
) : BotEvent, Packet {
|
||||
override val bot: Bot get() = friend.bot
|
||||
}
|
||||
|
||||
/**
|
||||
* 好友已被删除的事件.
|
||||
*/
|
||||
@SinceMirai("0.36.0")
|
||||
data class FriendDeleteEvent(
|
||||
val friend: QQ
|
||||
) : BotEvent, Packet {
|
||||
override val bot: Bot get() = friend.bot
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个账号请求添加机器人为好友的事件
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user