mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-21 13:27:00 +08:00
Introduce information descriptors for contacts
This commit is contained in:
parent
b0d274dd1a
commit
51ee123a1e
@ -11,9 +11,7 @@ package net.mamoe.mirai.qqandroid
|
||||
|
||||
import kotlinx.coroutines.launch
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.FriendNameRemark
|
||||
import net.mamoe.mirai.data.PreviousNameList
|
||||
import net.mamoe.mirai.data.Profile
|
||||
import net.mamoe.mirai.data.*
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||
@ -24,6 +22,7 @@ import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.NotOnlineImageFromFile
|
||||
import net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
|
||||
import net.mamoe.mirai.qqandroid.network.highway.postImage
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.StTroopMemberInfo
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore
|
||||
@ -33,6 +32,7 @@ import net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.io.toUHexString
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.FriendInfo as JceFriendInfo
|
||||
|
||||
internal abstract class ContactImpl : Contact {
|
||||
override fun hashCode(): Int {
|
||||
@ -49,10 +49,22 @@ internal abstract class ContactImpl : Contact {
|
||||
}
|
||||
}
|
||||
|
||||
internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), QQ {
|
||||
override val bot: QQAndroidBot by bot.unsafeWeakRef()
|
||||
internal inline class FriendInfoImpl(
|
||||
private val jceFriendInfo: JceFriendInfo
|
||||
) : FriendInfo {
|
||||
override val nick: String get() = jceFriendInfo.nick ?: ""
|
||||
override val uin: Long get() = jceFriendInfo.friendUin
|
||||
}
|
||||
|
||||
override lateinit var nick: String
|
||||
internal class QQImpl(
|
||||
bot: QQAndroidBot,
|
||||
override val coroutineContext: CoroutineContext,
|
||||
override val id: Long,
|
||||
private val friendInfo: FriendInfo
|
||||
) : ContactImpl(), QQ {
|
||||
override val bot: QQAndroidBot by bot.unsafeWeakRef()
|
||||
override val nick: String
|
||||
get() = friendInfo.nick
|
||||
|
||||
override suspend fun sendMessage(message: MessageChain) {
|
||||
val event = FriendMessageSendEvent(this, message).broadcast()
|
||||
@ -135,14 +147,17 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
|
||||
image.input.close()
|
||||
}
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
override suspend fun queryProfile(): Profile {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
override suspend fun queryPreviousNameList(): PreviousNameList {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
override suspend fun queryRemark(): FriendNameRemark {
|
||||
TODO("not implemented")
|
||||
}
|
||||
@ -156,24 +171,27 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
|
||||
}
|
||||
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal class MemberImpl(
|
||||
qq: QQImpl,
|
||||
var _groupCard: String,
|
||||
var _specialTitle: String,
|
||||
group: GroupImpl,
|
||||
override val coroutineContext: CoroutineContext,
|
||||
override var permission: MemberPermission
|
||||
memberInfo: MemberInfo
|
||||
) : ContactImpl(), Member, QQ by qq {
|
||||
override val group: GroupImpl by group.unsafeWeakRef()
|
||||
val qq: QQImpl by qq.unsafeWeakRef()
|
||||
|
||||
override var permission: MemberPermission = memberInfo.permission
|
||||
internal var _nameCard: String = memberInfo.nameCard
|
||||
internal var _specialTitle: String = memberInfo.specialTitle
|
||||
|
||||
override var nameCard: String
|
||||
get() = _groupCard
|
||||
get() = _nameCard
|
||||
set(newValue) {
|
||||
group.checkBotPermissionOperator()
|
||||
if (_groupCard != newValue) {
|
||||
val oldValue = _groupCard
|
||||
_groupCard = newValue
|
||||
if (_nameCard != newValue) {
|
||||
val oldValue = _nameCard
|
||||
_nameCard = newValue
|
||||
launch {
|
||||
bot.network.run {
|
||||
TroopManagement.EditGroupNametag(
|
||||
@ -223,7 +241,8 @@ internal class MemberImpl(
|
||||
).sendAndExpect<TroopManagement.Mute.Response>()
|
||||
}
|
||||
|
||||
MemberMuteEvent(this@MemberImpl, durationSeconds, null).broadcast()
|
||||
@Suppress("RemoveRedundantQualifierName") // or unresolved reference
|
||||
net.mamoe.mirai.event.events.MemberMuteEvent(this@MemberImpl, durationSeconds, null).broadcast()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -241,7 +260,8 @@ internal class MemberImpl(
|
||||
).sendAndExpect<TroopManagement.Mute.Response>()
|
||||
}
|
||||
|
||||
MemberUnmuteEvent(this@MemberImpl, null).broadcast()
|
||||
@Suppress("RemoveRedundantQualifierName") // or unresolved reference
|
||||
net.mamoe.mirai.event.events.MemberUnmuteEvent(this@MemberImpl, null).broadcast()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -269,25 +289,60 @@ internal class MemberImpl(
|
||||
override fun hashCode(): Int = super.hashCode()
|
||||
}
|
||||
|
||||
internal class MemberInfoImpl(
|
||||
private val jceInfo: StTroopMemberInfo,
|
||||
private val groupOwnerId: Long
|
||||
) : MemberInfo {
|
||||
override val uin: Long get() = jceInfo.memberUin
|
||||
override val nameCard: String get() = jceInfo.sName ?: ""
|
||||
override val nick: String get() = jceInfo.nick
|
||||
override val permission: MemberPermission
|
||||
get() = when {
|
||||
jceInfo.memberUin == groupOwnerId -> MemberPermission.OWNER
|
||||
jceInfo.dwFlag == 1L -> MemberPermission.ADMINISTRATOR
|
||||
else -> MemberPermission.MEMBER
|
||||
}
|
||||
override val specialTitle: String get() = jceInfo.sSpecialTitle ?: ""
|
||||
}
|
||||
|
||||
/**
|
||||
* 对GroupImpl
|
||||
* 中name/announcement的更改会直接向服务器异步汇报
|
||||
*/
|
||||
@Suppress("PropertyName")
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal class GroupImpl(
|
||||
bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
|
||||
override val id: Long,
|
||||
val uin: Long,
|
||||
var _name: String,
|
||||
var _announcement: String,
|
||||
var _allowMemberInvite: Boolean,
|
||||
var _confessTalk: Boolean,
|
||||
var _muteAll: Boolean,
|
||||
var _autoApprove: Boolean,
|
||||
var _anonymousChat: Boolean,
|
||||
override val members: ContactList<Member>
|
||||
groupInfo: GroupInfo,
|
||||
members: Sequence<MemberInfo>
|
||||
) : ContactImpl(), Group {
|
||||
override val bot: QQAndroidBot by bot.unsafeWeakRef()
|
||||
val uin: Long = groupInfo.uin
|
||||
|
||||
override lateinit var owner: Member
|
||||
|
||||
@UseExperimental(MiraiExperimentalAPI::class)
|
||||
override lateinit var botPermission: MemberPermission
|
||||
|
||||
override val members: ContactList<Member> = ContactList(members.asSequence().mapNotNull {
|
||||
if (it.uin == bot.uin) {
|
||||
botPermission = it.permission
|
||||
null
|
||||
} else Member(it).also { member ->
|
||||
if (member.permission == MemberPermission.OWNER) {
|
||||
owner = member
|
||||
}
|
||||
}
|
||||
}.toLockFreeLinkedList())
|
||||
|
||||
internal var _name: String = groupInfo.name
|
||||
internal var _announcement: String = groupInfo.memo
|
||||
internal var _allowMemberInvite: Boolean = groupInfo.allowMemberInvite
|
||||
internal var _confessTalk: Boolean = groupInfo.confessTalk
|
||||
internal var _muteAll: Boolean = groupInfo.muteAll
|
||||
internal var _autoApprove: Boolean = groupInfo.autoApprove
|
||||
internal var _anonymousChat: Boolean = groupInfo.allowAnonymousChat
|
||||
|
||||
override var name: String
|
||||
get() = _name
|
||||
@ -304,7 +359,7 @@ internal class GroupImpl(
|
||||
newName = newValue
|
||||
).sendWithoutExpect()
|
||||
}
|
||||
GroupNameChangeEvent(oldValue, newValue, this@GroupImpl, null).broadcast()
|
||||
GroupNameChangeEvent(oldValue, newValue, this@GroupImpl, true).broadcast()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -377,7 +432,7 @@ internal class GroupImpl(
|
||||
switch = newValue
|
||||
).sendWithoutExpect()
|
||||
}
|
||||
GroupAllowConfessTalkEvent(oldValue, newValue, this@GroupImpl, null).broadcast()
|
||||
GroupAllowConfessTalkEvent(oldValue, newValue, this@GroupImpl, true).broadcast()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -403,16 +458,21 @@ internal class GroupImpl(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override lateinit var owner: Member
|
||||
@UseExperimental(MiraiExperimentalAPI::class)
|
||||
override var botPermission: MemberPermission = MemberPermission.MEMBER
|
||||
|
||||
override suspend fun quit(): Boolean {
|
||||
check(botPermission != MemberPermission.OWNER) { "An owner cannot quit from a owning group" }
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
@UseExperimental(MiraiExperimentalAPI::class)
|
||||
override fun Member(memberInfo: MemberInfo): Member {
|
||||
return MemberImpl(
|
||||
bot.QQ(memberInfo) as QQImpl,
|
||||
this,
|
||||
this.coroutineContext,
|
||||
memberInfo
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override operator fun get(id: Long): Member {
|
||||
return members.delegate.filteringGetOrNull { it.id == id } ?: throw NoSuchElementException("member $id not found in group $uin")
|
||||
@ -426,8 +486,6 @@ internal class GroupImpl(
|
||||
return members.delegate.filteringGetOrNull { it.id == id }
|
||||
}
|
||||
|
||||
override val bot: QQAndroidBot by bot.unsafeWeakRef()
|
||||
|
||||
override suspend fun sendMessage(message: MessageChain) {
|
||||
val event = GroupMessageSendEvent(this, message).broadcast()
|
||||
if (event.isCancelled) {
|
||||
|
@ -19,13 +19,13 @@ import kotlinx.io.core.IoBuffer
|
||||
import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.AddFriendResult
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.data.GroupInfo
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.WeakRef
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.io.transferTo
|
||||
import net.mamoe.mirai.utils.toList
|
||||
|
||||
/**
|
||||
* 机器人对象. 一个机器人实例登录一个 QQ 账号.
|
||||
@ -65,6 +65,13 @@ abstract class Bot : CoroutineScope {
|
||||
*/
|
||||
abstract val uin: Long
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
val nick: String
|
||||
get() = TODO("bot 昵称获取")
|
||||
|
||||
/**
|
||||
* 日志记录器
|
||||
*/
|
||||
@ -116,7 +123,7 @@ abstract class Bot : CoroutineScope {
|
||||
* [Bot] 无法管理这个对象, 但这个对象会以 [Bot] 的 [Job] 作为父 Job.
|
||||
* 因此, 当 [Bot] 被关闭后, 这个对象也会被关闭.
|
||||
*/
|
||||
abstract fun QQ(id: Long): QQ
|
||||
abstract fun QQ(friendInfo: FriendInfo): QQ
|
||||
|
||||
/**
|
||||
* 机器人加入的群列表.
|
||||
@ -131,6 +138,25 @@ abstract class Bot : CoroutineScope {
|
||||
?: throw NoSuchElementException("No such group $id for bot ${this.uin}")
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取群列表. 返回值前 32 bits 为 uin, 后 32 bits 为 groupCode
|
||||
*/
|
||||
abstract suspend fun queryGroupList(): Sequence<Long>
|
||||
|
||||
/**
|
||||
* 查询群资料. 获得的仅为当前时刻的资料.
|
||||
* 请优先使用 [getGroup] 然后查看群资料.
|
||||
*/
|
||||
abstract suspend fun queryGroupInfo(id: Long): GroupInfo
|
||||
|
||||
/**
|
||||
* 查询群成员列表.
|
||||
* 请优先使用 [getGroup], [Group.members] 查看群成员.
|
||||
*
|
||||
* 这个函数很慢. 请不要频繁使用.
|
||||
*/
|
||||
abstract suspend fun queryGroupMemberList(groupUin: Long, groupCode: Long, ownerId: Long): Sequence<MemberInfo>
|
||||
|
||||
// TODO 目前还不能构造群对象. 这将在以后支持
|
||||
|
||||
// endregion
|
||||
|
@ -12,8 +12,10 @@
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
/**
|
||||
* 群. 在 QQ Android 中叫做 "Troop"
|
||||
@ -117,6 +119,14 @@ interface Group : Contact, CoroutineScope {
|
||||
*/
|
||||
suspend fun quit(): Boolean
|
||||
|
||||
/**
|
||||
* 构造一个 [Member].
|
||||
* 非特殊情况请不要使用这个函数. 优先使用 [get].
|
||||
*/
|
||||
@MiraiExperimentalAPI("dangerous")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
@JvmName("newMember")
|
||||
fun Member(memberInfo: MemberInfo): Member
|
||||
|
||||
companion object {
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.data
|
||||
|
||||
interface FriendInfo {
|
||||
val uin: Long
|
||||
|
||||
val nick: String
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package net.mamoe.mirai.data
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
|
||||
/**
|
||||
* 群资料.
|
||||
*
|
||||
* 通过 [Bot.queryGroupInfo] 得到
|
||||
*/
|
||||
interface GroupInfo {
|
||||
/**
|
||||
* Uin
|
||||
*/
|
||||
val uin: Long
|
||||
|
||||
/**
|
||||
* 群号码
|
||||
*/ // 由 uin 计算得到
|
||||
val groupCode: Long
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
val name: String
|
||||
|
||||
/**
|
||||
* 群主
|
||||
*/
|
||||
val owner: Long
|
||||
|
||||
/**
|
||||
* 入群公告
|
||||
*/
|
||||
val memo: String
|
||||
|
||||
/**
|
||||
* 允许群员邀请其他人加入群
|
||||
*/
|
||||
val allowMemberInvite: Boolean
|
||||
|
||||
/**
|
||||
* 允许匿名聊天
|
||||
*/
|
||||
val allowAnonymousChat: Boolean
|
||||
|
||||
/**
|
||||
* 自动审批加群请求
|
||||
*/
|
||||
val autoApprove: Boolean
|
||||
|
||||
/**
|
||||
* 坦白说开启状态
|
||||
*/
|
||||
val confessTalk: Boolean
|
||||
|
||||
/**
|
||||
* 全员禁言
|
||||
*/
|
||||
val muteAll: Boolean
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.data
|
||||
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
|
||||
interface MemberInfo : FriendInfo {
|
||||
val nameCard: String
|
||||
|
||||
val permission: MemberPermission
|
||||
|
||||
val specialTitle: String
|
||||
}
|
Loading…
Reference in New Issue
Block a user