diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt index 8426a2963..8aab9c5e8 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt @@ -7,9 +7,11 @@ import net.mamoe.mirai.data.Profile import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.MessageChain 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.EmptyCoroutineContext internal abstract class ContactImpl : Contact @@ -82,19 +84,20 @@ internal class GroupImpl( ) : ContactImpl(), Group { 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 { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - operator fun get(key: Long): Member? { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + override operator fun get(id: Long): Member { + 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() diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index 71c823dad..7a941c706 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -12,7 +12,6 @@ import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.Context import net.mamoe.mirai.utils.LockFreeLinkedList import net.mamoe.mirai.utils.MiraiInternalAPI -import net.mamoe.mirai.utils.io.getRandomByteArray import kotlin.coroutines.CoroutineContext @UseExperimental(MiraiInternalAPI::class) @@ -32,10 +31,20 @@ internal abstract class QQAndroidBotBase constructor( override val uin: Long get() = client.uin override val qqs: ContactList = ContactList(LockFreeLinkedList()) + val selfQQ: QQ by lazy { QQ(uin) } + override fun getQQ(id: Long): QQ { 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 { return QQAndroidBotNetworkHandler(this as QQAndroidBot) } @@ -47,7 +56,7 @@ internal abstract class QQAndroidBotBase constructor( } 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}") } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index 7b348d689..230b9206a 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -10,7 +10,6 @@ import kotlinx.io.core.Input import kotlinx.io.core.buildPacket import kotlinx.io.core.use import net.mamoe.mirai.contact.ContactList -import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.MemberPermission 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.StatSvc import net.mamoe.mirai.utils.* -import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.io.* import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @@ -139,7 +137,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler totalFriendCount = data.totalFriendCount data.friendList.forEach { // atomic add - bot.qqs.delegate.addLast(QQImpl(bot, EmptyCoroutineContext, it.friendUin).also { + bot.qqs.delegate.addLast(bot.getQQ(it.friendUin).also { currentFriendCount++ }) } @@ -168,18 +166,18 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler val group = GroupImpl( bot, - EmptyCoroutineContext, + this.coroutineContext, it.groupUin, it.groupCode, - it.groupName!!, - it.groupMemo!!, + it.groupName, + it.groupMemo, contactList ) group.owner = MemberImpl( - QQImpl(bot, EmptyCoroutineContext, it.dwGroupOwnerUin!!), + bot.QQ(it.dwGroupOwnerUin) as QQImpl, group, - EmptyCoroutineContext, + group.coroutineContext, MemberPermission.OWNER ) toGet[group] = contactList @@ -240,7 +238,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler if (it.memberUin != bot.uin) { list.delegate.addLast( MemberImpl( - QQImpl(bot, EmptyCoroutineContext, it.memberUin), + bot.QQ(it.memberUin) as QQImpl, group, EmptyCoroutineContext, when { diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/TroopList.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/TroopList.kt index 266cd0920..c195bdbb1 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/TroopList.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/TroopList.kt @@ -47,8 +47,8 @@ internal class stTroopNum( @SerialId(1) val groupCode: Long, @SerialId(2) val flag: Byte? = null, @SerialId(3) val dwGroupInfoSeq: Long? = null, - @SerialId(4) val groupName: String? = "", - @SerialId(5) val groupMemo: String? = "", + @SerialId(4) val groupName: String = "", + @SerialId(5) val groupMemo: String = "", @SerialId(6) val dwGroupFlagExt: Long? = null, @SerialId(7) val dwGroupRankSeq: Long? = null, @SerialId(8) val dwCertificationType: Long? = null, @@ -66,7 +66,7 @@ internal class stTroopNum( @SerialId(20) val dwMemberNumSeq: Long? = null, @SerialId(21) val dwMemberCardSeq: 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(25) val isModifyConfGroupFace: Byte? = null, @SerialId(26) val isModifyConfGroupName: Byte? = null, diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt index 98a54f1b3..34c37fd6c 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt @@ -135,6 +135,9 @@ internal class MessageSvc { } }.toMutableList() if (resp.syncFlag == MsgSvc.SyncFlag.STOP) { + messages.ifEmpty { + return GetMsgSuccess(messages) + } return GetMsgSuccess(mutableListOf(messages.last())) } return Response(resp.syncFlag, messages) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt index b304e304d..2f2b5db3a 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.PbPushGroupMsg.kt @@ -4,46 +4,68 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive import kotlinx.io.core.ByteReadPacket 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.qqandroid.QQAndroidBot 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.MsgOnlinePush 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 +internal inline class GroupMessageOrNull(val delegate: GroupMessage?) : Packet { + override fun toString(): String { + return delegate?.toString() ?: "" + } +} internal class OnlinePush { + /** * 接受群消息 */ - internal object PbPushGroupMsg : IncomingPacketFactory("OnlinePush.PbPushGroupMsg") { + internal object PbPushGroupMsg : IncomingPacketFactory("OnlinePush.PbPushGroupMsg") { @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 val pbPushMsg = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer()) 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 flags = extraInfo?.flags ?: 0 - return GroupMessage( - bot = bot, - group = group, - senderName = pbPushMsg.msg.msgHead.groupInfo.groupCard, - sender = group.getMember(pbPushMsg.msg.msgHead.fromUin), - message = pbPushMsg.msg.msgBody.richText.toMessageChain(), - permission = when { - flags and 16 != 0 -> MemberPermission.ADMINISTRATOR - flags and 8 != 0 -> MemberPermission.OWNER - flags == 0 -> MemberPermission.MEMBER - else -> { - bot.logger.warning("判断群员权限失败") - MemberPermission.MEMBER + return GroupMessageOrNull( + GroupMessage( + bot = bot, + group = group, + senderName = pbPushMsg.msg.msgHead.groupInfo.groupCard, + sender = group[pbPushMsg.msg.msgHead.fromUin], + message = pbPushMsg.msg.msgBody.richText.toMessageChain(), + permission = when { + flags and 16 != 0 -> MemberPermission.ADMINISTRATOR + flags and 8 != 0 -> MemberPermission.OWNER + flags == 0 -> MemberPermission.MEMBER + else -> { + bot.logger.warning("判断群员权限失败") + MemberPermission.MEMBER + } } - } + ) ) } + + override suspend fun QQAndroidBot.handle(packet: GroupMessageOrNull, sequenceId: Int): OutgoingPacket? { + if (packet.delegate != null) { + packet.delegate.broadcast() + } + return null + } } } \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/MessageQQA.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/MessageQQA.kt index b9f842dd3..f6d5ff9fc 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/MessageQQA.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/MessageQQA.kt @@ -3,7 +3,6 @@ package net.mamoe.mirai.qqandroid.utils import net.mamoe.mirai.data.ImageLink import net.mamoe.mirai.message.data.* import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody -import net.mamoe.mirai.utils.io.hexToBytes internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage { return ImMsgBody.NotOnlineImage( @@ -66,11 +65,11 @@ internal fun MessageChain.toRichTextElems(): MutableList { } is NotOnlineImageFromServer -> { 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 -> { 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()))) } } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index 409512892..5736a424c 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -3,17 +3,21 @@ package net.mamoe.mirai import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.io.OutputStream import kotlinx.io.core.ByteReadPacket 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.message.data.Image import net.mamoe.mirai.network.BotNetworkHandler -import net.mamoe.mirai.utils.GroupNotFoundException import net.mamoe.mirai.utils.LoginFailedException import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.utils.WeakRef import net.mamoe.mirai.utils.io.transferTo /** @@ -49,32 +53,39 @@ abstract class Bot : CoroutineScope { // region contacts /** - * 与这个机器人相关的 QQ 列表. 机器人与 QQ 不一定是好友 + * 机器人的好友列表. */ abstract val qqs: ContactList /** - * 获取缓存的 QQ 对象. 若没有对应的缓存, 则会线程安全地创建一个. + * 获取一个好友对象. 若没有这个好友, 则会抛出异常[NoSuchElementException] */ abstract fun getQQ(id: Long): QQ /** - * 与这个机器人相关的群列表. 机器人不一定是群成员. + * 构造一个 [QQ] 对象. 它持有对 [Bot] 的弱引用([WeakRef]). + * + * [Bot] 无法管理这个对象, 但这个对象会以 [Bot] 的 [Job] 作为父 Job. + * 因此, 当 [Bot] 被关闭后, 这个对象也会被关闭. + */ + abstract fun QQ(id: Long): QQ + + /** + * 机器人加入的群列表. */ abstract val groups: ContactList /** - * 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个. - * 若 [id] 无效, 将会抛出 [GroupNotFoundException] + * 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException] */ abstract fun getGroupByID(id: Long): Group /** - * 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个. - * 若 [internalId] 无效, 将会抛出 [GroupNotFoundException] + * 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException] */ abstract fun getGroupByGroupCode(groupCode: Long): Group + // 目前还不能构造群对象. 这将在以后支持 // endregion @@ -87,6 +98,7 @@ abstract class Bot : CoroutineScope { /** * 登录, 或重新登录. + * 不建议调用这个函数. * * 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.login] * diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/ContactList.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/ContactList.kt index 4156953ff..3e96f57eb 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/ContactList.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/ContactList.kt @@ -45,7 +45,7 @@ fun LockFreeLinkedList.getOrNull(id: Long): C? { return null } -inline fun LockFreeLinkedList.filterGetOrNull(filter: (C) -> Boolean): C? { +inline fun LockFreeLinkedList.filteringGetOrNull(filter: (C) -> Boolean): C? { forEach { if (filter(it)) return it } return null } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt index 9120fd5ca..450672bfb 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt @@ -3,8 +3,6 @@ package net.mamoe.mirai.contact 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 /** - * 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新. - * - * @return 这一时刻的群资料 + * 获取群成员实例, 不存在则 null */ - suspend fun updateGroupInfo(): GroupInfo + fun getOrNull(id: Long): Member? + + /** + * 检查此 id 的群成员是否存在 + */ + operator fun contains(id: Long): Boolean /** * 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败 diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt index 087274c0c..8d8222d0f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt @@ -144,7 +144,7 @@ class MessageSubscribersBuilder>( /** * 监听的条件 */ - inner class ListeningFilter( + open inner class ListeningFilter( val filter: T.(String) -> Boolean ) { /** @@ -345,6 +345,21 @@ class MessageSubscribersBuilder>( inline fun sentBy(qq: Long, crossinline onEvent: MessageListener): Listener = content({ this.sender.id == qq }, onEvent) + /** + * 如果是好友发来的消息 + */ + @MessageDsl + inline fun sentByFriend(crossinline onEvent: MessageListener): Listener = + content({ this is FriendMessage }){ + onEvent(this as FriendMessage, it) + } + + /** + * 如果是好友发来的消息 + */ + @MessageDsl + fun sentByFriend(): ListeningFilter = ListeningFilter { this is FriendMessage } + /** * 如果是管理员或群主发的消息 */ @@ -399,7 +414,7 @@ class MessageSubscribersBuilder>( */ @MessageDsl inline fun sentFrom(groupId: Long, crossinline onEvent: MessageListener): Listener = - content({ this is GroupMessage && this.group.id == groupId }){ + content({ this is GroupMessage && this.group.id == groupId }) { onEvent(this as GroupMessage, it) } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/GroupMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/GroupMessage.kt index a87465c55..f265fdc63 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/GroupMessage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/GroupMessage.kt @@ -30,8 +30,8 @@ class GroupMessage( */ override val subject: Group get() = group - inline fun At.member(): Member = group.getMember(this.target) - inline fun Long.member(): Member = group.getMember(this) + inline fun At.member(): Member = group[this.target] + inline fun Long.member(): Member = group[this] override fun toString(): String = "GroupMessage(group=${group.id}, senderName=$senderName, sender=${sender.id}, permission=${permission.name}, message=$message)" diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Exceptions.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Exceptions.kt deleted file mode 100644 index b42004faa..000000000 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Exceptions.kt +++ /dev/null @@ -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?) -} \ No newline at end of file diff --git a/mirai-japt/src/main/java/net/mamoe/mirai/japt/BlockingGroup.java b/mirai-japt/src/main/java/net/mamoe/mirai/japt/BlockingGroup.java index e40d96de3..54f50e0f5 100644 --- a/mirai-japt/src/main/java/net/mamoe/mirai/japt/BlockingGroup.java +++ b/mirai-japt/src/main/java/net/mamoe/mirai/japt/BlockingGroup.java @@ -1,7 +1,6 @@ package net.mamoe.mirai.japt; import net.mamoe.mirai.contact.Group; -import net.mamoe.mirai.data.GroupInfo; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -9,28 +8,20 @@ import java.util.NoSuchElementException; @SuppressWarnings("unused") public interface BlockingGroup extends BlockingContact { - /** - * 内部 ID - */ - long getInternalId(); - /** * 群主 (同步事件更新) - * 进行 {@link #updateGroupInfo} 时将会更新这个值. */ @NotNull BlockingMember getOwner(); /** * 群名称 (同步事件更新) - * 进行 {@link #updateGroupInfo} 时将会更新这个值. */ @NotNull String getName(); /** * 入群公告, 没有时为空字符串. (同步事件更新) - * 进行 {@link #updateGroupInfo} 时将会更新这个值. */ @NotNull String getAnnouncement(); @@ -49,14 +40,6 @@ public interface BlockingGroup extends BlockingContact { @NotNull BlockingMember getMember(long id); - /** - * 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新. - * - * @return 这一时刻的群资料 - */ - @NotNull - GroupInfo updateGroupInfo(); - /** * 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败 */ diff --git a/mirai-japt/src/main/kotlin/net/mamoe/mirai/japt/internal/BlockingContactsImpl.kt b/mirai-japt/src/main/kotlin/net/mamoe/mirai/japt/internal/BlockingContactsImpl.kt index 295d9fffe..f13cae01c 100644 --- a/mirai-japt/src/main/kotlin/net/mamoe/mirai/japt/internal/BlockingContactsImpl.kt +++ b/mirai-japt/src/main/kotlin/net/mamoe/mirai/japt/internal/BlockingContactsImpl.kt @@ -8,7 +8,6 @@ import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.data.FriendNameRemark -import net.mamoe.mirai.data.GroupInfo import net.mamoe.mirai.data.PreviousNameList import net.mamoe.mirai.data.Profile 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 getName(): String = delegate.name override fun getId(): Long = delegate.id - override fun updateGroupInfo(): GroupInfo = runBlocking { delegate.updateGroupInfo() } 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 getAnnouncement(): String = delegate.announcement @UseExperimental(MiraiInternalAPI::class) override fun getMembers(): Map = 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() } }