Improve performance

This commit is contained in:
Him188 2020-02-03 01:59:41 +08:00
parent e38bfe30d8
commit d9e5805255
15 changed files with 129 additions and 109 deletions

View File

@ -7,9 +7,11 @@ import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
internal abstract class ContactImpl : Contact internal abstract class ContactImpl : Contact
@ -82,19 +84,20 @@ internal class GroupImpl(
) : ContactImpl(), Group { ) : ContactImpl(), Group {
override lateinit var owner: Member override lateinit var owner: Member
override fun getMember(id: Long): Member =
members.delegate.filterGetOrNull { it.id == id } ?: error("Failed to find Member${id} in group ${groupCode}")
override suspend fun updateGroupInfo(): net.mamoe.mirai.data.GroupInfo {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override suspend fun quit(): Boolean { override suspend fun quit(): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
operator fun get(key: Long): Member? { override operator fun get(id: Long): Member {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. return members.delegate.filteringGetOrNull { it.id == id } ?: throw NoSuchElementException("for group id $id")
}
override fun contains(id: Long): Boolean {
return members.delegate.filteringGetOrNull { it.id == id } != null
}
override fun getOrNull(id: Long): Member? {
return members.delegate.filteringGetOrNull { it.id == id }
} }
override val bot: QQAndroidBot by bot.unsafeWeakRef() override val bot: QQAndroidBot by bot.unsafeWeakRef()

View File

@ -12,7 +12,6 @@ import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.LockFreeLinkedList import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.getRandomByteArray
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
@ -32,10 +31,20 @@ internal abstract class QQAndroidBotBase constructor(
override val uin: Long get() = client.uin override val uin: Long get() = client.uin
override val qqs: ContactList<QQ> = ContactList(LockFreeLinkedList()) override val qqs: ContactList<QQ> = ContactList(LockFreeLinkedList())
val selfQQ: QQ by lazy { QQ(uin) }
override fun getQQ(id: Long): QQ { override fun getQQ(id: Long): QQ {
return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this as QQAndroidBot, coroutineContext, id) }) return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this as QQAndroidBot, coroutineContext, id) })
} }
fun getQQOrAdd(id: Long): QQ {
return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this as QQAndroidBot, coroutineContext, id) })
}
override fun QQ(id: Long): QQ {
return QQImpl(this as QQAndroidBot, coroutineContext, id)
}
override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler { override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler {
return QQAndroidBotNetworkHandler(this as QQAndroidBot) return QQAndroidBotNetworkHandler(this as QQAndroidBot)
} }
@ -47,7 +56,7 @@ internal abstract class QQAndroidBotBase constructor(
} }
override fun getGroupByGroupCode(groupCode: Long): Group { override fun getGroupByGroupCode(groupCode: Long): Group {
return groups.delegate.filterGetOrNull { it.groupCode == groupCode } return groups.delegate.filteringGetOrNull { it.groupCode == groupCode }
?: throw NoSuchElementException("Can not found group with GroupCode=${groupCode}") ?: throw NoSuchElementException("Can not found group with GroupCode=${groupCode}")
} }

View File

@ -10,7 +10,6 @@ import kotlinx.io.core.Input
import kotlinx.io.core.buildPacket import kotlinx.io.core.buildPacket
import kotlinx.io.core.use import kotlinx.io.core.use
import net.mamoe.mirai.contact.ContactList import net.mamoe.mirai.contact.ContactList
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.data.MultiPacket import net.mamoe.mirai.data.MultiPacket
@ -30,7 +29,6 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
@ -139,7 +137,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
totalFriendCount = data.totalFriendCount totalFriendCount = data.totalFriendCount
data.friendList.forEach { data.friendList.forEach {
// atomic add // atomic add
bot.qqs.delegate.addLast(QQImpl(bot, EmptyCoroutineContext, it.friendUin).also { bot.qqs.delegate.addLast(bot.getQQ(it.friendUin).also {
currentFriendCount++ currentFriendCount++
}) })
} }
@ -168,18 +166,18 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
val group = val group =
GroupImpl( GroupImpl(
bot, bot,
EmptyCoroutineContext, this.coroutineContext,
it.groupUin, it.groupUin,
it.groupCode, it.groupCode,
it.groupName!!, it.groupName,
it.groupMemo!!, it.groupMemo,
contactList contactList
) )
group.owner = group.owner =
MemberImpl( MemberImpl(
QQImpl(bot, EmptyCoroutineContext, it.dwGroupOwnerUin!!), bot.QQ(it.dwGroupOwnerUin) as QQImpl,
group, group,
EmptyCoroutineContext, group.coroutineContext,
MemberPermission.OWNER MemberPermission.OWNER
) )
toGet[group] = contactList toGet[group] = contactList
@ -240,7 +238,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
if (it.memberUin != bot.uin) { if (it.memberUin != bot.uin) {
list.delegate.addLast( list.delegate.addLast(
MemberImpl( MemberImpl(
QQImpl(bot, EmptyCoroutineContext, it.memberUin), bot.QQ(it.memberUin) as QQImpl,
group, group,
EmptyCoroutineContext, EmptyCoroutineContext,
when { when {

View File

@ -47,8 +47,8 @@ internal class stTroopNum(
@SerialId(1) val groupCode: Long, @SerialId(1) val groupCode: Long,
@SerialId(2) val flag: Byte? = null, @SerialId(2) val flag: Byte? = null,
@SerialId(3) val dwGroupInfoSeq: Long? = null, @SerialId(3) val dwGroupInfoSeq: Long? = null,
@SerialId(4) val groupName: String? = "", @SerialId(4) val groupName: String = "",
@SerialId(5) val groupMemo: String? = "", @SerialId(5) val groupMemo: String = "",
@SerialId(6) val dwGroupFlagExt: Long? = null, @SerialId(6) val dwGroupFlagExt: Long? = null,
@SerialId(7) val dwGroupRankSeq: Long? = null, @SerialId(7) val dwGroupRankSeq: Long? = null,
@SerialId(8) val dwCertificationType: Long? = null, @SerialId(8) val dwCertificationType: Long? = null,
@ -66,7 +66,7 @@ internal class stTroopNum(
@SerialId(20) val dwMemberNumSeq: Long? = null, @SerialId(20) val dwMemberNumSeq: Long? = null,
@SerialId(21) val dwMemberCardSeq: Long? = null, @SerialId(21) val dwMemberCardSeq: Long? = null,
@SerialId(22) val dwGroupFlagExt3: Long? = null, @SerialId(22) val dwGroupFlagExt3: Long? = null,
@SerialId(23) val dwGroupOwnerUin: Long? = null, @SerialId(23) val dwGroupOwnerUin: Long,
@SerialId(24) val isConfGroup: Byte? = null, @SerialId(24) val isConfGroup: Byte? = null,
@SerialId(25) val isModifyConfGroupFace: Byte? = null, @SerialId(25) val isModifyConfGroupFace: Byte? = null,
@SerialId(26) val isModifyConfGroupName: Byte? = null, @SerialId(26) val isModifyConfGroupName: Byte? = null,

View File

@ -135,6 +135,9 @@ internal class MessageSvc {
} }
}.toMutableList() }.toMutableList()
if (resp.syncFlag == MsgSvc.SyncFlag.STOP) { if (resp.syncFlag == MsgSvc.SyncFlag.STOP) {
messages.ifEmpty {
return GetMsgSuccess(messages)
}
return GetMsgSuccess(mutableListOf(messages.last())) return GetMsgSuccess(mutableListOf(messages.last()))
} }
return Response(resp.syncFlag, messages) return Response(resp.syncFlag, messages)

View File

@ -4,46 +4,68 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.message.GroupMessage import net.mamoe.mirai.message.GroupMessage
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgOnlinePush import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgOnlinePush
import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.utils.toMessageChain import net.mamoe.mirai.qqandroid.utils.toMessageChain
internal inline class GroupMessageOrNull(val delegate: GroupMessage?) : Packet {
override fun toString(): String {
return delegate?.toString() ?: "<Receipt>"
}
}
internal class OnlinePush { internal class OnlinePush {
/** /**
* 接受群消息 * 接受群消息
*/ */
internal object PbPushGroupMsg : IncomingPacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") { internal object PbPushGroupMsg : IncomingPacketFactory<GroupMessageOrNull>("OnlinePush.PbPushGroupMsg") {
@UseExperimental(ExperimentalStdlibApi::class) @UseExperimental(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): GroupMessage { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): GroupMessageOrNull {
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00 // 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
val pbPushMsg = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer()) val pbPushMsg = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer())
val extraInfo: ImMsgBody.ExtraInfo? = pbPushMsg.msg.msgBody.richText.elems.firstOrNull { it.extraInfo != null }?.extraInfo val extraInfo: ImMsgBody.ExtraInfo? = pbPushMsg.msg.msgBody.richText.elems.firstOrNull { it.extraInfo != null }?.extraInfo
if (pbPushMsg.msg.msgHead.fromUin == bot.uin) {
return GroupMessageOrNull(null)
}
val group = bot.getGroupByGroupCode(pbPushMsg.msg.msgHead.groupInfo!!.groupCode) val group = bot.getGroupByGroupCode(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
val flags = extraInfo?.flags ?: 0 val flags = extraInfo?.flags ?: 0
return GroupMessage( return GroupMessageOrNull(
bot = bot, GroupMessage(
group = group, bot = bot,
senderName = pbPushMsg.msg.msgHead.groupInfo.groupCard, group = group,
sender = group.getMember(pbPushMsg.msg.msgHead.fromUin), senderName = pbPushMsg.msg.msgHead.groupInfo.groupCard,
message = pbPushMsg.msg.msgBody.richText.toMessageChain(), sender = group[pbPushMsg.msg.msgHead.fromUin],
permission = when { message = pbPushMsg.msg.msgBody.richText.toMessageChain(),
flags and 16 != 0 -> MemberPermission.ADMINISTRATOR permission = when {
flags and 8 != 0 -> MemberPermission.OWNER flags and 16 != 0 -> MemberPermission.ADMINISTRATOR
flags == 0 -> MemberPermission.MEMBER flags and 8 != 0 -> MemberPermission.OWNER
else -> { flags == 0 -> MemberPermission.MEMBER
bot.logger.warning("判断群员权限失败") else -> {
MemberPermission.MEMBER bot.logger.warning("判断群员权限失败")
MemberPermission.MEMBER
}
} }
} )
) )
} }
override suspend fun QQAndroidBot.handle(packet: GroupMessageOrNull, sequenceId: Int): OutgoingPacket? {
if (packet.delegate != null) {
packet.delegate.broadcast()
}
return null
}
} }
} }

View File

@ -3,7 +3,6 @@ package net.mamoe.mirai.qqandroid.utils
import net.mamoe.mirai.data.ImageLink import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.utils.io.hexToBytes
internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage { internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage {
return ImMsgBody.NotOnlineImage( return ImMsgBody.NotOnlineImage(
@ -66,11 +65,11 @@ internal fun MessageChain.toRichTextElems(): MutableList<ImMsgBody.Elem> {
} }
is NotOnlineImageFromServer -> { is NotOnlineImageFromServer -> {
elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate)) elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes()))) // elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes())))
} }
is NotOnlineImageFromFile -> { is NotOnlineImageFromFile -> {
elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData())) elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData()))
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes()))) // elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes())))
} }
} }
} }

View File

@ -3,17 +3,21 @@
package net.mamoe.mirai package net.mamoe.mirai
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.io.OutputStream import kotlinx.io.OutputStream
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.use import kotlinx.io.core.use
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.ContactList
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.utils.GroupNotFoundException
import net.mamoe.mirai.utils.LoginFailedException import net.mamoe.mirai.utils.LoginFailedException
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.WeakRef
import net.mamoe.mirai.utils.io.transferTo import net.mamoe.mirai.utils.io.transferTo
/** /**
@ -49,32 +53,39 @@ abstract class Bot : CoroutineScope {
// region contacts // region contacts
/** /**
* 与这个机器人相关的 QQ 列表. 机器人与 QQ 不一定是好友 * 机器人的好友列表.
*/ */
abstract val qqs: ContactList<QQ> abstract val qqs: ContactList<QQ>
/** /**
* 获取缓存的 QQ 对象. 若没有对应的缓存, 则会线程安全地创建一个. * 获取一个好友对象. 若没有这个好友, 则会抛出异常[NoSuchElementException]
*/ */
abstract fun getQQ(id: Long): QQ abstract fun getQQ(id: Long): QQ
/** /**
* 与这个机器人相关的群列表. 机器人不一定是群成员. * 构造一个 [QQ] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
*
* [Bot] 无法管理这个对象, 但这个对象会以 [Bot] [Job] 作为父 Job.
* 因此, [Bot] 被关闭后, 这个对象也会被关闭.
*/
abstract fun QQ(id: Long): QQ
/**
* 机器人加入的群列表.
*/ */
abstract val groups: ContactList<Group> abstract val groups: ContactList<Group>
/** /**
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个. * 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException]
* [id] 无效, 将会抛出 [GroupNotFoundException]
*/ */
abstract fun getGroupByID(id: Long): Group abstract fun getGroupByID(id: Long): Group
/** /**
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个. * 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException]
* [internalId] 无效, 将会抛出 [GroupNotFoundException]
*/ */
abstract fun getGroupByGroupCode(groupCode: Long): Group abstract fun getGroupByGroupCode(groupCode: Long): Group
// 目前还不能构造群对象. 这将在以后支持
// endregion // endregion
@ -87,6 +98,7 @@ abstract class Bot : CoroutineScope {
/** /**
* 登录, 或重新登录. * 登录, 或重新登录.
* 不建议调用这个函数.
* *
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.login] * 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.login]
* *

View File

@ -45,7 +45,7 @@ fun <C : Contact> LockFreeLinkedList<C>.getOrNull(id: Long): C? {
return null return null
} }
inline fun <C : Contact> LockFreeLinkedList<C>.filterGetOrNull(filter: (C) -> Boolean): C? { inline fun <C : Contact> LockFreeLinkedList<C>.filteringGetOrNull(filter: (C) -> Boolean): C? {
forEach { if (filter(it)) return it } forEach { if (filter(it)) return it }
return null return null
} }

View File

@ -3,8 +3,6 @@
package net.mamoe.mirai.contact package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.utils.coerceAtLeastOrFail
/** /**
@ -47,16 +45,19 @@ interface Group : Contact, CoroutineScope {
/** /**
* 获取群成员. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException] * 获取群成员实例. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
*/ */
fun getMember(id: Long): Member operator fun get(id: Long): Member
/** /**
* 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新. * 获取群成员实例, 不存在则 null
*
* @return 这一时刻的群资料
*/ */
suspend fun updateGroupInfo(): GroupInfo fun getOrNull(id: Long): Member?
/**
* 检查此 id 的群成员是否存在
*/
operator fun contains(id: Long): Boolean
/** /**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败 * 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败

View File

@ -144,7 +144,7 @@ class MessageSubscribersBuilder<T : MessagePacket<*, *>>(
/** /**
* 监听的条件 * 监听的条件
*/ */
inner class ListeningFilter( open inner class ListeningFilter(
val filter: T.(String) -> Boolean val filter: T.(String) -> Boolean
) { ) {
/** /**
@ -345,6 +345,21 @@ class MessageSubscribersBuilder<T : MessagePacket<*, *>>(
inline fun sentBy(qq: Long, crossinline onEvent: MessageListener<T>): Listener<T> = inline fun sentBy(qq: Long, crossinline onEvent: MessageListener<T>): Listener<T> =
content({ this.sender.id == qq }, onEvent) content({ this.sender.id == qq }, onEvent)
/**
* 如果是好友发来的消息
*/
@MessageDsl
inline fun sentByFriend(crossinline onEvent: MessageListener<FriendMessage>): Listener<T> =
content({ this is FriendMessage }){
onEvent(this as FriendMessage, it)
}
/**
* 如果是好友发来的消息
*/
@MessageDsl
fun sentByFriend(): ListeningFilter = ListeningFilter { this is FriendMessage }
/** /**
* 如果是管理员或群主发的消息 * 如果是管理员或群主发的消息
*/ */
@ -399,7 +414,7 @@ class MessageSubscribersBuilder<T : MessagePacket<*, *>>(
*/ */
@MessageDsl @MessageDsl
inline fun sentFrom(groupId: Long, crossinline onEvent: MessageListener<GroupMessage>): Listener<T> = inline fun sentFrom(groupId: Long, crossinline onEvent: MessageListener<GroupMessage>): Listener<T> =
content({ this is GroupMessage && this.group.id == groupId }){ content({ this is GroupMessage && this.group.id == groupId }) {
onEvent(this as GroupMessage, it) onEvent(this as GroupMessage, it)
} }

View File

@ -30,8 +30,8 @@ class GroupMessage(
*/ */
override val subject: Group get() = group override val subject: Group get() = group
inline fun At.member(): Member = group.getMember(this.target) inline fun At.member(): Member = group[this.target]
inline fun Long.member(): Member = group.getMember(this) inline fun Long.member(): Member = group[this]
override fun toString(): String = override fun toString(): String =
"GroupMessage(group=${group.id}, senderName=$senderName, sender=${sender.id}, permission=${permission.name}, message=$message)" "GroupMessage(group=${group.id}, senderName=$senderName, sender=${sender.id}, permission=${permission.name}, message=$message)"

View File

@ -1,22 +0,0 @@
@file:Suppress("unused", "UNUSED_PARAMETER")
package net.mamoe.mirai.utils
import net.mamoe.mirai.contact.Group
/**
* 在获取 [Group] 对象等操作时可能出现的异常
*/
class GroupNotFoundException : Exception {
constructor()
constructor(message: String?)
constructor(message: String?, cause: Throwable?)
constructor(cause: Throwable?)
}
open class MiraiInternalException : Exception {
constructor()
constructor(message: String?)
constructor(message: String?, cause: Throwable?)
constructor(cause: Throwable?)
}

View File

@ -1,7 +1,6 @@
package net.mamoe.mirai.japt; package net.mamoe.mirai.japt;
import net.mamoe.mirai.contact.Group; import net.mamoe.mirai.contact.Group;
import net.mamoe.mirai.data.GroupInfo;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Map; import java.util.Map;
@ -9,28 +8,20 @@ import java.util.NoSuchElementException;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public interface BlockingGroup extends BlockingContact { public interface BlockingGroup extends BlockingContact {
/**
* 内部 ID
*/
long getInternalId();
/** /**
* 群主 (同步事件更新) * 群主 (同步事件更新)
* 进行 {@link #updateGroupInfo} 时将会更新这个值.
*/ */
@NotNull @NotNull
BlockingMember getOwner(); BlockingMember getOwner();
/** /**
* 群名称 (同步事件更新) * 群名称 (同步事件更新)
* 进行 {@link #updateGroupInfo} 时将会更新这个值.
*/ */
@NotNull @NotNull
String getName(); String getName();
/** /**
* 入群公告, 没有时为空字符串. (同步事件更新) * 入群公告, 没有时为空字符串. (同步事件更新)
* 进行 {@link #updateGroupInfo} 时将会更新这个值.
*/ */
@NotNull @NotNull
String getAnnouncement(); String getAnnouncement();
@ -49,14 +40,6 @@ public interface BlockingGroup extends BlockingContact {
@NotNull @NotNull
BlockingMember getMember(long id); BlockingMember getMember(long id);
/**
* 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新.
*
* @return 这一时刻的群资料
*/
@NotNull
GroupInfo updateGroupInfo();
/** /**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败 * 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
*/ */

View File

@ -8,7 +8,6 @@ import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.data.FriendNameRemark import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.data.PreviousNameList import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.data.Profile import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.japt.BlockingBot import net.mamoe.mirai.japt.BlockingBot
@ -41,16 +40,14 @@ internal class BlockingGroupImpl(private val delegate: Group) : BlockingGroup {
override fun getOwner(): BlockingMember = delegate.owner.blocking() override fun getOwner(): BlockingMember = delegate.owner.blocking()
override fun getName(): String = delegate.name override fun getName(): String = delegate.name
override fun getId(): Long = delegate.id override fun getId(): Long = delegate.id
override fun updateGroupInfo(): GroupInfo = runBlocking { delegate.updateGroupInfo() }
override fun toFullString(): String = delegate.toFullString() override fun toFullString(): String = delegate.toFullString()
override fun getMember(id: Long): BlockingMember = delegate.getMember(id).blocking() override fun getMember(id: Long): BlockingMember = delegate[id].blocking()
override fun getBot(): BlockingBot = delegate.bot.blocking() override fun getBot(): BlockingBot = delegate.bot.blocking()
override fun getAnnouncement(): String = delegate.announcement override fun getAnnouncement(): String = delegate.announcement
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
override fun getMembers(): Map<Long, BlockingMember> = override fun getMembers(): Map<Long, BlockingMember> =
delegate.members.delegate.toList().associateBy { it.id }.mapValues { it.value.blocking() } delegate.members.delegate.toList().associateBy { it.id }.mapValues { it.value.blocking() }
override fun getInternalId(): Long = delegate.internalId.value
override fun quit(): Boolean = runBlocking { delegate.quit() } override fun quit(): Boolean = runBlocking { delegate.quit() }
} }