mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-31 03:22:36 +08:00
Use groupCode as primary key
This commit is contained in:
parent
d9e5805255
commit
8c69eefcde
@ -77,7 +77,7 @@ internal class MemberImpl(
|
||||
internal class GroupImpl(
|
||||
bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
|
||||
override val id: Long,
|
||||
override val groupCode: Long,
|
||||
val uin: Long,
|
||||
override var name: String,
|
||||
override var announcement: String,
|
||||
override var members: ContactList<Member>
|
||||
|
@ -51,13 +51,13 @@ internal abstract class QQAndroidBotBase constructor(
|
||||
|
||||
override val groups: ContactList<Group> = ContactList(LockFreeLinkedList())
|
||||
|
||||
override fun getGroupByID(id: Long): Group {
|
||||
return groups.delegate.getOrNull(id) ?: throw NoSuchElementException("Can not found group with ID=${id}")
|
||||
fun getGroupByUin(uin: Long): Group {
|
||||
return groups.delegate.filteringGetOrNull { (it as GroupImpl).uin == uin } ?: throw NoSuchElementException("Can not found group with ID=${uin}")
|
||||
}
|
||||
|
||||
override fun getGroupByGroupCode(groupCode: Long): Group {
|
||||
return groups.delegate.filteringGetOrNull { it.groupCode == groupCode }
|
||||
?: throw NoSuchElementException("Can not found group with GroupCode=${groupCode}")
|
||||
override fun getGroup(id: Long): Group {
|
||||
return groups.delegate.getOrNull(id)
|
||||
?: throw NoSuchElementException("Can not found group with GroupCode=${id}")
|
||||
}
|
||||
|
||||
override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult {
|
||||
|
@ -31,7 +31,6 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.jvm.Volatile
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
@ -103,13 +102,11 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
}
|
||||
|
||||
// println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
|
||||
StatSvc.Register(bot.client).sendAndExpect<StatSvc.Register.Response>(6000)
|
||||
// println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
|
||||
StatSvc.Register(bot.client).sendAndExpect<StatSvc.Register.Response>(6000) // it's slow
|
||||
}
|
||||
|
||||
override suspend fun init() {
|
||||
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect()
|
||||
|
||||
this@QQAndroidBotNetworkHandler.subscribeAlways<ForceOfflineEvent> {
|
||||
if (this@QQAndroidBotNetworkHandler.bot == this.bot) {
|
||||
close()
|
||||
@ -159,26 +156,26 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
val troopData = FriendList.GetTroopListSimplify(
|
||||
bot.client
|
||||
).sendAndExpect<FriendList.GetTroopListSimplify.Response>(timeoutMillis = 1000)
|
||||
println("获取到群数量" + troopData.groups.size)
|
||||
// println("获取到群数量" + troopData.groups.size)
|
||||
val toGet: MutableMap<GroupImpl, ContactList<Member>> = mutableMapOf()
|
||||
troopData.groups.forEach {
|
||||
val contactList = ContactList(LockFreeLinkedList<Member>())
|
||||
val group =
|
||||
GroupImpl(
|
||||
bot,
|
||||
this.coroutineContext,
|
||||
it.groupUin,
|
||||
it.groupCode,
|
||||
it.groupName,
|
||||
it.groupMemo,
|
||||
contactList
|
||||
bot = bot,
|
||||
coroutineContext = this.coroutineContext,
|
||||
id = it.groupCode,
|
||||
uin = it.groupUin,
|
||||
name = it.groupName,
|
||||
announcement = it.groupMemo,
|
||||
members = contactList
|
||||
)
|
||||
group.owner =
|
||||
MemberImpl(
|
||||
bot.QQ(it.dwGroupOwnerUin) as QQImpl,
|
||||
group,
|
||||
group.coroutineContext,
|
||||
MemberPermission.OWNER
|
||||
qq = bot.QQ(it.dwGroupOwnerUin) as QQImpl,
|
||||
group = group,
|
||||
coroutineContext = group.coroutineContext,
|
||||
permission = MemberPermission.OWNER
|
||||
)
|
||||
toGet[group] = contactList
|
||||
bot.groups.delegate.addLast(group)
|
||||
@ -186,10 +183,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
toGet.forEach {
|
||||
try {
|
||||
getTroopMemberList(it.key, it.value, it.key.owner.id)
|
||||
groupInfo[it.key.groupCode] = it.value.size
|
||||
groupInfo[it.key.uin] = it.value.size
|
||||
} catch (e: Exception) {
|
||||
groupInfo[it.key.groupCode] = -1
|
||||
bot.logger.info("群${it.key.groupCode}的列表拉取失败, 将采用动态加入")
|
||||
groupInfo[it.key.uin] = -1
|
||||
bot.logger.info("群${it.key.uin}的列表拉取失败, 将采用动态加入")
|
||||
}
|
||||
//delay(200)
|
||||
}
|
||||
@ -221,36 +218,32 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
}
|
||||
bot.logger.info("====================Mirai Bot List初始化完毕====================")
|
||||
|
||||
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect()
|
||||
}
|
||||
|
||||
suspend fun getTroopMemberList(group: GroupImpl, list: ContactList<Member>, owner: Long): ContactList<Member> {
|
||||
bot.logger.info("开始获取群[${group.groupCode}]成员列表")
|
||||
bot.logger.info("开始获取群[${group.uin}]成员列表")
|
||||
var size = 0
|
||||
var nextUin = 0L
|
||||
while (true) {
|
||||
val data = FriendList.GetTroopMemberList(
|
||||
bot.client,
|
||||
group.id,
|
||||
group.groupCode,
|
||||
nextUin
|
||||
client = bot.client,
|
||||
targetGroupUin = group.uin,
|
||||
targetGroupCode = group.id,
|
||||
nextUin = nextUin
|
||||
).sendAndExpect<FriendList.GetTroopMemberList.Response>(timeoutMillis = 3000)
|
||||
data.members.forEach {
|
||||
if (it.memberUin != bot.uin) {
|
||||
list.delegate.addLast(
|
||||
MemberImpl(
|
||||
bot.QQ(it.memberUin) as QQImpl,
|
||||
group,
|
||||
EmptyCoroutineContext,
|
||||
when {
|
||||
it.memberUin == owner -> {
|
||||
MemberPermission.OWNER
|
||||
}
|
||||
it.dwFlag == 1L -> {
|
||||
MemberPermission.ADMINISTRATOR
|
||||
}
|
||||
else -> {
|
||||
MemberPermission.MEMBER
|
||||
}
|
||||
qq = bot.QQ(it.memberUin) as QQImpl,
|
||||
group = group,
|
||||
coroutineContext = group.coroutineContext,
|
||||
permission = when {
|
||||
it.memberUin == owner -> MemberPermission.OWNER
|
||||
it.dwFlag == 1L -> MemberPermission.ADMINISTRATOR
|
||||
else -> MemberPermission.MEMBER
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -261,9 +254,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
if (nextUin == 0L) {
|
||||
break
|
||||
}
|
||||
println("已获取群[${group.groupCode}]成员列表前" + size + "个成员")
|
||||
//println("已获取群[${group.uin}]成员列表前" + size + "个成员")
|
||||
}
|
||||
println("群[${group.groupCode}]成员全部获取完成, 共${list.size}个成员")
|
||||
//println("群[${group.uin}]成员全部获取完成, 共${list.size}个成员")
|
||||
return list
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ internal class MessageSvc {
|
||||
*/
|
||||
fun ToGroup(
|
||||
client: QQAndroidClient,
|
||||
groupId: Long,
|
||||
groupCode: Long,
|
||||
message: MessageChain
|
||||
): OutgoingPacket = buildOutgoingUniPacket(client) {
|
||||
|
||||
@ -224,7 +224,7 @@ internal class MessageSvc {
|
||||
///return@buildOutgoingUniPacket
|
||||
writeProtoBuf(
|
||||
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq(
|
||||
routingHead = MsgSvc.RoutingHead(grp = MsgSvc.Grp(groupCode = groupId)), // TODO: 2020/1/30 确认这里是 id 还是 internalId
|
||||
routingHead = MsgSvc.RoutingHead(grp = MsgSvc.Grp(groupCode = groupCode)), // TODO: 2020/1/30 确认这里是 id 还是 internalId
|
||||
contentHead = MsgComm.ContentHead(pkgNum = 1, divSeq = seq),
|
||||
msgBody = ImMsgBody.MsgBody(
|
||||
richText = ImMsgBody.RichText(
|
||||
|
@ -38,7 +38,7 @@ internal class OnlinePush {
|
||||
return GroupMessageOrNull(null)
|
||||
}
|
||||
|
||||
val group = bot.getGroupByGroupCode(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
|
||||
val group = bot.getGroup(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
|
||||
|
||||
val flags = extraInfo?.flags ?: 0
|
||||
return GroupMessageOrNull(
|
||||
|
@ -14,11 +14,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList.GetFriendGroupList.decode
|
||||
import net.mamoe.mirai.utils.io.debugIfFail
|
||||
import net.mamoe.mirai.utils.io.debugPrintThis
|
||||
import net.mamoe.mirai.utils.io.debugPrintln
|
||||
import net.mamoe.mirai.utils.io.discardExact
|
||||
|
||||
|
||||
internal class FriendList {
|
||||
@ -35,7 +31,7 @@ internal class FriendList {
|
||||
|
||||
operator fun invoke(
|
||||
client: QQAndroidClient,
|
||||
targetGroupId: Long,
|
||||
targetGroupUin: Long,
|
||||
targetGroupCode: Long,
|
||||
nextUin: Long = 0
|
||||
): OutgoingPacket {
|
||||
@ -53,7 +49,7 @@ internal class FriendList {
|
||||
GetTroopMemberListReq(
|
||||
uin = client.uin,
|
||||
groupCode = targetGroupCode,
|
||||
groupUin = targetGroupId,
|
||||
groupUin = targetGroupUin,
|
||||
nextUin = nextUin,
|
||||
reqType = 0,
|
||||
version = 2
|
||||
|
@ -21,7 +21,7 @@ import net.mamoe.mirai.utils.WeakRef
|
||||
import net.mamoe.mirai.utils.io.transferTo
|
||||
|
||||
/**
|
||||
* Mirai 的机器人. 一个机器人实例登录一个 QQ 账号.
|
||||
* 机器人对象. 一个机器人实例登录一个 QQ 账号.
|
||||
* Mirai 为多账号设计, 可同时维护多个机器人.
|
||||
*
|
||||
* @see Contact
|
||||
@ -78,12 +78,7 @@ abstract class Bot : CoroutineScope {
|
||||
/**
|
||||
* 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException]
|
||||
*/
|
||||
abstract fun getGroupByID(id: Long): Group
|
||||
|
||||
/**
|
||||
* 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException]
|
||||
*/
|
||||
abstract fun getGroupByGroupCode(groupCode: Long): Group
|
||||
abstract fun getGroup(id: Long): Group
|
||||
|
||||
// 目前还不能构造群对象. 这将在以后支持
|
||||
|
||||
@ -131,8 +126,10 @@ abstract class Bot : CoroutineScope {
|
||||
|
||||
/**
|
||||
* 关闭这个 [Bot], 停止一切相关活动. 不可重新登录.
|
||||
*
|
||||
* @param cause 原因. 为 null 时视为正常关闭, 非 null 时视为异常关闭
|
||||
*/
|
||||
abstract fun dispose(throwable: Throwable?)
|
||||
abstract fun close(cause: Throwable? = null)
|
||||
|
||||
// region extensions
|
||||
|
||||
|
@ -133,15 +133,15 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
// endregion
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
override fun dispose(throwable: Throwable?) {
|
||||
if (throwable == null) {
|
||||
override fun close(cause: Throwable?) {
|
||||
if (cause == null) {
|
||||
network.close()
|
||||
this.botJob.complete()
|
||||
groups.delegate.clear()
|
||||
qqs.delegate.clear()
|
||||
} else {
|
||||
network.close(throwable)
|
||||
this.botJob.completeExceptionally(throwable)
|
||||
network.close(cause)
|
||||
this.botJob.completeExceptionally(cause)
|
||||
groups.delegate.clear()
|
||||
qqs.delegate.clear()
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ interface Contact : CoroutineScope {
|
||||
val bot: Bot // weak ref
|
||||
|
||||
/**
|
||||
* 可以是 QQ 号码或者群号码 [GroupId].
|
||||
* 可以是 QQ 号码或者群号码.
|
||||
*/
|
||||
val id: Long
|
||||
|
||||
|
@ -7,32 +7,25 @@ import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
/**
|
||||
* 群. 在 QQ Android 中叫做 "Troop"
|
||||
*
|
||||
* Group UIN 与 Group Code 并不是同一个值.
|
||||
* Group Code是在客户端显示的code
|
||||
* Group Uin是QQ内部的群ID[在Mirai中则为 id]
|
||||
* 但是有的时候 两个是相同的value
|
||||
* 在网络调用层 Code与Uin会被混用
|
||||
* 但在开发层 你应该只关注Group Code
|
||||
*/
|
||||
interface Group : Contact, CoroutineScope {
|
||||
/**
|
||||
* 同为 groupCode, 用户看到的群号码.
|
||||
*/
|
||||
override val id: Long
|
||||
|
||||
val groupCode: Long
|
||||
/**
|
||||
* 群主 (同步事件更新)
|
||||
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||
*/
|
||||
val owner: Member
|
||||
|
||||
/**
|
||||
* 群名称 (同步事件更新)
|
||||
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||
*/
|
||||
val name: String
|
||||
|
||||
/**
|
||||
* 入群公告, 没有时为空字符串. (同步事件更新)
|
||||
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||
*/
|
||||
val announcement: String
|
||||
|
||||
@ -45,7 +38,7 @@ interface Group : Contact, CoroutineScope {
|
||||
|
||||
|
||||
/**
|
||||
* 获取群成员实例. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
|
||||
* 获取群成员实例. 若此 id 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
|
||||
*/
|
||||
operator fun get(id: Long): Member
|
||||
|
||||
|
@ -63,6 +63,8 @@ abstract class BotNetworkHandler : CoroutineScope {
|
||||
|
||||
/**
|
||||
* 关闭网络接口, 停止所有有关协程和任务
|
||||
*
|
||||
* @param cause 关闭的原因. null 时视为正常关闭, 非 null 时视为异常关闭.
|
||||
*/
|
||||
open fun close(cause: Throwable? = null) {
|
||||
if (supervisor.isActive) {
|
||||
@ -75,7 +77,7 @@ abstract class BotNetworkHandler : CoroutineScope {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun BotNetworkHandler.closeAndJoin(cause: Throwable? = null){
|
||||
suspend fun BotNetworkHandler.closeAndJoin(cause: Throwable? = null) {
|
||||
this.close(cause)
|
||||
this.supervisor.join()
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import net.mamoe.mirai.test.shouldBeEqualTo
|
||||
import org.junit.Test
|
||||
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
internal class GroupIdConversionsKtTest {
|
||||
@Test
|
||||
fun checkToInternalId() {
|
||||
GroupId(221056495).toInternalId().value shouldBeEqualTo 4111056495
|
||||
// 61 056495
|
||||
//4111 056495
|
||||
}
|
||||
}
|
@ -217,7 +217,9 @@ suspend fun directlySubscribe(bot: Bot) {
|
||||
|
||||
"复读" in message -> sender.sendMessage(message)
|
||||
|
||||
"发群消息" in message -> 580266363.group().sendMessage(message.toString().substringAfter("发群消息"))
|
||||
"发群消息" in message -> {
|
||||
bot.getGroup(580266363).sendMessage(message.toString().substringAfter("发群消息"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -50,10 +50,6 @@ suspend fun main() {
|
||||
|
||||
// 订阅来自这个 bot 的群消息事件
|
||||
bot.subscribeGroupMessages {
|
||||
"群资料" reply {
|
||||
group.updateGroupInfo().toString().reply()
|
||||
}
|
||||
|
||||
startsWith("mute") {
|
||||
val at: At by message
|
||||
at.member().mute(30)
|
||||
|
@ -5,7 +5,6 @@ import net.mamoe.mirai.BotAccount;
|
||||
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.MiraiInternalAPI;
|
||||
import net.mamoe.mirai.utils.MiraiLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -15,6 +14,9 @@ import java.util.List;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public interface BlockingBot {
|
||||
|
||||
// TODO: 2020/2/3 需要更新
|
||||
|
||||
/**
|
||||
* 账号信息
|
||||
*/
|
||||
@ -55,17 +57,11 @@ public interface BlockingBot {
|
||||
|
||||
/**
|
||||
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个.
|
||||
* 若 {@code id} 无效, 将会抛出 {@link GroupNotFoundException}
|
||||
* 若 {@code id} 无效, 将会抛出 {@link java.util.NoSuchElementException}
|
||||
*/
|
||||
@NotNull
|
||||
BlockingGroup getGroup(long id);
|
||||
|
||||
/**
|
||||
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个.
|
||||
* 若 {@code internalId} 无效, 将会抛出 {@link GroupNotFoundException}
|
||||
*/
|
||||
@NotNull
|
||||
BlockingGroup getGroupByInternalId(long internalId);
|
||||
|
||||
// endregion
|
||||
|
||||
|
@ -4,7 +4,6 @@ import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.BotAccount
|
||||
import net.mamoe.mirai.contact.GroupInternalId
|
||||
import net.mamoe.mirai.data.AddFriendResult
|
||||
import net.mamoe.mirai.japt.BlockingBot
|
||||
import net.mamoe.mirai.japt.BlockingGroup
|
||||
@ -29,12 +28,11 @@ internal class BlockingBotImpl(private val bot: Bot) : BlockingBot {
|
||||
override fun getGroups(): List<BlockingGroup> = bot.groups.delegate.toList().map { it.blocking() }
|
||||
|
||||
override fun getGroup(id: Long): BlockingGroup = runBlocking { bot.getGroup(id).blocking() }
|
||||
override fun getGroupByInternalId(internalId: Long): BlockingGroup = runBlocking { bot.getGroup(GroupInternalId(internalId)).blocking() }
|
||||
override fun getNetwork(): BotNetworkHandler = bot.network
|
||||
override fun login() = runBlocking { bot.login() }
|
||||
override fun downloadAsByteArray(image: Image): ByteArray = bot.run { runBlocking { image.downloadAsByteArray() } }
|
||||
override fun download(image: Image): ByteReadPacket = bot.run { runBlocking { image.download() } }
|
||||
override fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult = runBlocking { bot.addFriend(id, message, remark) }
|
||||
override fun approveFriendAddRequest(id: Long, remark: String?) = runBlocking { bot.approveFriendAddRequest(id, remark) }
|
||||
override fun dispose(throwable: Throwable?) = bot.dispose(throwable)
|
||||
override fun dispose(throwable: Throwable?) = bot.close(throwable)
|
||||
}
|
Loading…
Reference in New Issue
Block a user