mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-24 14:30:09 +08:00
Deprecate QQ
Introduce `Friend` extending `User` Introduce `User` acting as the superclass of `Friend` and `Member` Add extensions `Member.asFriend`, etc. Remove specialized `Contact.hashCode` and `Contact.equals`, inherit from `kotlin.Any` Specify `toString` behavior in abstract `Contact` classes, instead of in implementation classes. Add virtual member `Contact.sendMessage(String)` Migrate the project from using `QQ` to `Friend` Remove multiplatform Contact class structure, keep them common. Remove extension `Long.at` in `GroupMessage`, `QQ.at` in `ContactMessage`. Add `At.asMember()` in `GroupMessage`. Make `calculateGroupUinByGroupCode`, `calculateGroupCodeByGroupUin` static on JVM.
This commit is contained in:
parent
3efeba1980
commit
a63af80668
@ -38,8 +38,8 @@ import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.network.LoginFailedException
|
||||
import net.mamoe.mirai.qqandroid.contact.FriendImpl
|
||||
import net.mamoe.mirai.qqandroid.contact.MemberInfoImpl
|
||||
import net.mamoe.mirai.qqandroid.contact.QQImpl
|
||||
import net.mamoe.mirai.qqandroid.contact.checkIsGroupImpl
|
||||
import net.mamoe.mirai.qqandroid.message.*
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
|
||||
@ -89,7 +89,7 @@ internal class QQAndroidBot constructor(
|
||||
event,
|
||||
accept = true
|
||||
).sendWithoutExpect()
|
||||
bot.friends.delegate.addLast(bot._lowLevelNewQQ(object : FriendInfo {
|
||||
bot.friends.delegate.addLast(bot._lowLevelNewFriend(object : FriendInfo {
|
||||
override val uin: Long get() = event.fromId
|
||||
override val nick: String get() = event.fromNick
|
||||
}))
|
||||
@ -150,7 +150,6 @@ internal class QQAndroidBot constructor(
|
||||
}
|
||||
|
||||
override suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean) {
|
||||
|
||||
check(event.responded.compareAndSet(false, true)) {
|
||||
"the request $this has already been responded"
|
||||
}
|
||||
@ -188,15 +187,15 @@ internal abstract class QQAndroidBotBase constructor(
|
||||
val json = Json(JsonConfiguration(ignoreUnknownKeys = true, encodeDefaults = true))
|
||||
}
|
||||
|
||||
override val friends: ContactList<QQ> = ContactList(LockFreeLinkedList())
|
||||
override val friends: ContactList<Friend> = ContactList(LockFreeLinkedList())
|
||||
|
||||
override val nick: String get() = selfInfo.nick
|
||||
|
||||
internal lateinit var selfInfo: JceFriendInfo
|
||||
|
||||
override val selfQQ: QQ by lazy {
|
||||
override val selfQQ: Friend by lazy {
|
||||
@OptIn(LowLevelAPI::class)
|
||||
_lowLevelNewQQ(object : FriendInfo {
|
||||
_lowLevelNewFriend(object : FriendInfo {
|
||||
override val uin: Long get() = this@QQAndroidBotBase.id
|
||||
override val nick: String get() = this@QQAndroidBotBase.nick
|
||||
})
|
||||
@ -214,10 +213,10 @@ internal abstract class QQAndroidBotBase constructor(
|
||||
}
|
||||
|
||||
@LowLevelAPI
|
||||
override fun _lowLevelNewQQ(friendInfo: FriendInfo): QQ {
|
||||
return QQImpl(
|
||||
override fun _lowLevelNewFriend(friendInfo: FriendInfo): Friend {
|
||||
return FriendImpl(
|
||||
this as QQAndroidBot,
|
||||
coroutineContext + CoroutineName("QQ(${friendInfo.uin}"),
|
||||
coroutineContext + CoroutineName("Friend(${friendInfo.uin}"),
|
||||
friendInfo.uin,
|
||||
friendInfo
|
||||
)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
@file:OptIn(MiraiInternalAPI::class, LowLevelAPI::class)
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR")
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR", "NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.qqandroid.contact
|
||||
|
||||
@ -16,12 +16,8 @@ import kotlinx.atomicfu.AtomicInt
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.io.core.Closeable
|
||||
import net.mamoe.mirai.LowLevelAPI
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.data.FriendNameRemark
|
||||
import net.mamoe.mirai.data.PreviousNameList
|
||||
import net.mamoe.mirai.data.Profile
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BeforeImageUploadEvent
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
@ -35,7 +31,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn
|
||||
import net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
|
||||
import net.mamoe.mirai.qqandroid.utils.toUHexString
|
||||
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.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@ -49,20 +48,20 @@ internal inline class FriendInfoImpl(
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal fun QQ.checkIsQQImpl(): QQImpl {
|
||||
internal inline fun Friend.checkIsFriendImpl(): FriendImpl {
|
||||
contract {
|
||||
returns() implies (this@checkIsQQImpl is QQImpl)
|
||||
returns() implies (this@checkIsFriendImpl is FriendImpl)
|
||||
}
|
||||
check(this is QQImpl) { "A QQ instance is not instance of QQImpl. Don't interlace two protocol implementations together!" }
|
||||
check(this is FriendImpl) { "A Friend instance is not instance of FriendImpl. Don't interlace two protocol implementations together!" }
|
||||
return this
|
||||
}
|
||||
|
||||
internal class QQImpl(
|
||||
internal class FriendImpl(
|
||||
bot: QQAndroidBot,
|
||||
override val coroutineContext: CoroutineContext,
|
||||
override val id: Long,
|
||||
private val friendInfo: FriendInfo
|
||||
) : QQ() {
|
||||
) : Friend() {
|
||||
@Suppress("unused") // bug
|
||||
val lastMessageSequence: AtomicInt = atomic(-1)
|
||||
|
||||
@ -72,7 +71,7 @@ internal class QQImpl(
|
||||
|
||||
@JvmSynthetic
|
||||
@Suppress("DuplicatedCode")
|
||||
override suspend fun sendMessage(message: Message): MessageReceipt<QQ> {
|
||||
override suspend fun sendMessage(message: Message): MessageReceipt<Friend> {
|
||||
return sendMessageImpl(message).also {
|
||||
logMessageSent(message)
|
||||
}
|
||||
@ -110,7 +109,7 @@ internal class QQImpl(
|
||||
width = response.imageInfo.fileWidth,
|
||||
resourceId = response.resourceId
|
||||
).also {
|
||||
ImageUploadEvent.Succeed(this@QQImpl, image, it).broadcast()
|
||||
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
|
||||
}
|
||||
is LongConn.OffPicUp.Response.RequireUpload -> {
|
||||
MiraiPlatformUtils.Http.postImage(
|
||||
@ -141,11 +140,11 @@ internal class QQImpl(
|
||||
width = image.width,
|
||||
resourceId = response.resourceId
|
||||
).also {
|
||||
ImageUploadEvent.Succeed(this@QQImpl, image, it).broadcast()
|
||||
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
|
||||
}
|
||||
}
|
||||
is LongConn.OffPicUp.Response.Failed -> {
|
||||
ImageUploadEvent.Failed(this@QQImpl, image, -1, response.message).broadcast()
|
||||
ImageUploadEvent.Failed(this@FriendImpl, image, -1, response.message).broadcast()
|
||||
error(response.message)
|
||||
}
|
||||
}
|
||||
@ -153,35 +152,4 @@ internal class QQImpl(
|
||||
} finally {
|
||||
(image.input as? Closeable)?.close()
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = bot.hashCode()
|
||||
result = 31 * result + id.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@Suppress("DuplicatedCode")
|
||||
if (this === other) return true
|
||||
if (other !is Contact) return false
|
||||
if (this::class != other::class) return false
|
||||
return this.id == other.id && this.bot == other.bot
|
||||
}
|
||||
|
||||
@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")
|
||||
}
|
||||
|
||||
override fun toString(): String = "QQ($id)"
|
||||
}
|
@ -250,7 +250,7 @@ internal class GroupImpl(
|
||||
override fun newMember(memberInfo: MemberInfo): Member {
|
||||
return MemberImpl(
|
||||
@OptIn(LowLevelAPI::class)
|
||||
bot._lowLevelNewQQ(memberInfo) as QQImpl,
|
||||
bot._lowLevelNewFriend(memberInfo) as FriendImpl,
|
||||
this,
|
||||
this.coroutineContext,
|
||||
memberInfo
|
||||
@ -476,23 +476,5 @@ internal class GroupImpl(
|
||||
(image.input as? Closeable)?.close()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Group($id)"
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = bot.hashCode()
|
||||
result = 31 * result + id.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@Suppress("DuplicatedCode", "DuplicatedCode")
|
||||
if (this === other) return true
|
||||
if (other !is Contact) return false
|
||||
if (this::class != other::class) return false
|
||||
return this.id == other.id && this.bot == other.bot
|
||||
}
|
||||
|
||||
|
||||
override fun toString(): String = "Group($id)"
|
||||
}
|
@ -16,10 +16,7 @@ import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.launch
|
||||
import net.mamoe.mirai.LowLevelAPI
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.FriendNameRemark
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.data.PreviousNameList
|
||||
import net.mamoe.mirai.data.Profile
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.MemberCardChangeEvent
|
||||
import net.mamoe.mirai.event.events.MemberLeaveEvent
|
||||
@ -42,7 +39,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
@OptIn(LowLevelAPI::class)
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal class MemberImpl constructor(
|
||||
val qq: QQImpl, // 不要 WeakRef
|
||||
val qq: FriendImpl, // 不要 WeakRef
|
||||
group: GroupImpl,
|
||||
override val coroutineContext: CoroutineContext,
|
||||
memberInfo: MemberInfo
|
||||
@ -52,22 +49,10 @@ internal class MemberImpl constructor(
|
||||
@Suppress("unused") // false positive
|
||||
val lastMessageSequence: AtomicInt = atomic(-1)
|
||||
|
||||
// region QQ delegate
|
||||
override val id: Long = qq.id
|
||||
override val nick: String = qq.nick
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
override suspend fun queryProfile(): Profile = qq.queryProfile()
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
override suspend fun queryPreviousNameList(): PreviousNameList = qq.queryPreviousNameList()
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
override suspend fun queryRemark(): FriendNameRemark = qq.queryRemark()
|
||||
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
@JvmSynthetic
|
||||
@Suppress("DuplicatedCode", "UNCHECKED_CAST")
|
||||
override suspend fun sendMessage(message: Message): MessageReceipt<Member> {
|
||||
return sendMessageImpl(message).also {
|
||||
logMessageSent(message)
|
||||
@ -92,7 +77,6 @@ internal class MemberImpl constructor(
|
||||
|
||||
@JvmSynthetic
|
||||
override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage = qq.uploadImage(image)
|
||||
// endregion
|
||||
|
||||
override var permission: MemberPermission = memberInfo.permission
|
||||
|
||||
@ -217,23 +201,6 @@ internal class MemberImpl constructor(
|
||||
MemberLeaveEvent.Kick(this@MemberImpl, null).broadcast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = bot.hashCode()
|
||||
result = 31 * result + id.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Contact) return false
|
||||
if (this::class != other::class) return false
|
||||
return this.id == other.id && this.bot == other.bot
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Member($id)"
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
|
@ -10,7 +10,7 @@
|
||||
package net.mamoe.mirai.qqandroid.contact
|
||||
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent
|
||||
@ -31,7 +31,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.verbose
|
||||
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
internal suspend fun QQ.sendMessageImpl(message: Message): MessageReceipt<QQ> {
|
||||
internal suspend fun Friend.sendMessageImpl(message: Message): MessageReceipt<Friend> {
|
||||
val event = MessageSendEvent.FriendMessageSendEvent(this, message.asMessageChain()).broadcast()
|
||||
if (event.isCancelled) {
|
||||
throw EventCancelledException("cancelled by FriendMessageSendEvent")
|
||||
|
@ -12,8 +12,8 @@
|
||||
package net.mamoe.mirai.qqandroid.message
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.event.internal.MiraiAtomicBoolean
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
@ -57,7 +57,7 @@ internal class MessageSourceFromFriendImpl(
|
||||
override val random: Int get() = msg.msgBody.richText.attr!!.random
|
||||
override val time: Int get() = msg.msgHead.msgTime
|
||||
override val originalMessage: MessageChain by lazy { msg.toMessageChain(bot, 0, false) }
|
||||
override val sender: QQ get() = bot.getFriend(msg.msgHead.fromUin)
|
||||
override val sender: Friend get() = bot.getFriend(msg.msgHead.fromUin)
|
||||
|
||||
private val jceData by lazy { msg.toJceDataFriendOrTemp(random) }
|
||||
|
||||
|
@ -14,9 +14,9 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.event.asyncFromEventOrNull
|
||||
import net.mamoe.mirai.event.internal.MiraiAtomicBoolean
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
@ -74,7 +74,7 @@ internal class MessageSourceToFriendImpl(
|
||||
override val time: Int,
|
||||
override val originalMessage: MessageChain,
|
||||
override val sender: Bot,
|
||||
override val target: QQ
|
||||
override val target: Friend
|
||||
) : OnlineMessageSource.Outgoing.ToFriend(), MessageSourceInternal {
|
||||
override val bot: Bot
|
||||
get() = sender
|
||||
|
@ -227,7 +227,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
data.friendList.forEach {
|
||||
// atomic
|
||||
bot.friends.delegate.addLast(
|
||||
QQImpl(bot, bot.coroutineContext, it.friendUin, FriendInfoImpl(it))
|
||||
FriendImpl(bot, bot.coroutineContext, it.friendUin, FriendInfoImpl(it))
|
||||
).also { currentFriendCount++ }
|
||||
}
|
||||
logger.verbose { "正在加载好友列表 ${currentFriendCount}/${totalFriendCount}" }
|
||||
|
@ -18,10 +18,10 @@ import kotlinx.coroutines.flow.*
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import net.mamoe.mirai.LowLevelAPI
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.events.BotJoinGroupEvent
|
||||
@ -33,8 +33,8 @@ import net.mamoe.mirai.message.TempMessage
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.contact.GroupImpl
|
||||
import net.mamoe.mirai.qqandroid.contact.checkIsFriendImpl
|
||||
import net.mamoe.mirai.qqandroid.contact.checkIsMemberImpl
|
||||
import net.mamoe.mirai.qqandroid.contact.checkIsQQImpl
|
||||
import net.mamoe.mirai.qqandroid.message.*
|
||||
import net.mamoe.mirai.qqandroid.network.MultiPacketByIterable
|
||||
import net.mamoe.mirai.qqandroid.network.Packet
|
||||
@ -53,10 +53,8 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
|
||||
import net.mamoe.mirai.qqandroid.utils.io.serialization.readUniPacket
|
||||
import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
|
||||
import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import net.mamoe.mirai.utils.debug
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.collections.firstOrNull
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.random.Random
|
||||
|
||||
@ -191,7 +189,7 @@ internal class MessageSvc {
|
||||
|
||||
if (resp.result != 0) {
|
||||
bot.network.logger
|
||||
.warning("MessageSvc.PushNotify: result != 0, result = ${resp.result}, errorMsg=${resp.errmsg}")
|
||||
.warning { "MessageSvc.PushNotify: result != 0, result = ${resp.result}, errorMsg=${resp.errmsg}" }
|
||||
return EmptyResponse
|
||||
}
|
||||
|
||||
@ -231,7 +229,7 @@ internal class MessageSvc {
|
||||
}
|
||||
166 -> {
|
||||
val friend = bot.getFriendOrNull(msg.msgHead.fromUin) ?: return@mapNotNull null
|
||||
friend.checkIsQQImpl()
|
||||
friend.checkIsFriendImpl()
|
||||
|
||||
if (msg.msgHead.fromUin == bot.id || !bot.firstLoginSucceed) {
|
||||
return@mapNotNull null
|
||||
@ -365,7 +363,7 @@ internal class MessageSvc {
|
||||
|
||||
inline fun createToFriend(
|
||||
client: QQAndroidClient,
|
||||
qq: QQ,
|
||||
qq: Friend,
|
||||
message: MessageChain,
|
||||
crossinline sourceCallback: (MessageSourceToFriendImpl) -> Unit
|
||||
): OutgoingPacket {
|
||||
|
@ -409,7 +409,7 @@ internal class OnlinePush {
|
||||
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 {
|
||||
val new = bot._lowLevelNewFriend(object : FriendInfo {
|
||||
override val uin: Long get() = body.msgAddFrdNotify.fuin
|
||||
override val nick: String get() = body.msgAddFrdNotify.fuinNick
|
||||
})
|
||||
|
@ -28,8 +28,6 @@ import net.mamoe.mirai.utils.OverFileSizeMaxException
|
||||
*
|
||||
* A QQ instance helps you to receive event from or sendPacket event to.
|
||||
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
|
||||
*
|
||||
* @author Him188moe
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
actual abstract class QQ : Contact(), CoroutineScope {
|
||||
|
@ -109,20 +109,21 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
|
||||
// region contacts
|
||||
|
||||
/**
|
||||
* [QQ.id] 与 [Bot.uin] 相同的 [_lowLevelNewQQ] 实例
|
||||
* [QQ.id] 与 [Bot.uin] 相同的 [_lowLevelNewFriend] 实例
|
||||
*/
|
||||
abstract val selfQQ: QQ
|
||||
abstract val selfQQ: Friend
|
||||
|
||||
|
||||
/**
|
||||
* 机器人的好友列表. 与服务器同步更新
|
||||
*/
|
||||
abstract val friends: ContactList<QQ>
|
||||
abstract val friends: ContactList<Friend>
|
||||
|
||||
/**
|
||||
* 获取一个好友对象.
|
||||
* @throws [NoSuchElementException] 当不存在这个好友时抛出
|
||||
*/
|
||||
fun getFriend(id: Long): QQ = friends.firstOrNull { it.id == id } ?: throw NoSuchElementException("friend $id")
|
||||
fun getFriend(id: Long): Friend = friends.firstOrNull { it.id == id } ?: throw NoSuchElementException("friend $id")
|
||||
|
||||
/**
|
||||
* 机器人加入的群列表. 与服务器同步更新
|
||||
@ -273,9 +274,17 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
|
||||
@MiraiInternalAPI
|
||||
abstract val network: BotNetworkHandler
|
||||
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated("for binary compatibility until 1.0.0", level = DeprecationLevel.HIDDEN)
|
||||
suspend inline fun Bot.join() = this.coroutineContext[Job]!!.join()
|
||||
@PlannedRemoval("1.0.0.")
|
||||
@get:JvmName("getSelfQQ")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
val selfQQDeprecated: QQ
|
||||
get() = selfQQ
|
||||
|
||||
@JvmName("getFriend")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
fun getFriendDeprecated(id: Long): QQ = this.getFriend(id)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,7 +360,7 @@ inline fun Bot.containsFriend(id: Long): Boolean = this.friends.contains(id)
|
||||
inline fun Bot.containsGroup(id: Long): Boolean = this.groups.contains(id)
|
||||
|
||||
@JvmSynthetic
|
||||
inline fun Bot.getFriendOrNull(id: Long): QQ? = this.friends.getOrNull(id)
|
||||
inline fun Bot.getFriendOrNull(id: Long): Friend? = this.friends.getOrNull(id)
|
||||
|
||||
@JvmSynthetic
|
||||
inline fun Bot.getGroupOrNull(id: Long): Group? = this.groups.getOrNull(id)
|
||||
|
@ -32,9 +32,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
|
||||
|
||||
/**
|
||||
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ], [群成员][Member] 和 [群][Group].
|
||||
*
|
||||
* @author Him188moe
|
||||
* 联系人. 虽然叫做联系人, 但他的子类有 [人][User], 和 [群][Group].
|
||||
*/
|
||||
abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI(), ContactOrBot {
|
||||
/**
|
||||
@ -85,23 +83,11 @@ abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI(), ContactOrBot
|
||||
@JvmSynthetic
|
||||
abstract suspend fun uploadImage(image: ExternalImage): OfflineImage
|
||||
|
||||
/**
|
||||
* 判断 `this` 和 [other] 是否是相同的类型, 并且 [id] 相同.
|
||||
*
|
||||
* 注:
|
||||
* [id] 相同的 [Member] 和 [QQ], 他们并不 [equals].
|
||||
* 因为, [Member] 含义为群员, 必属于一个群.
|
||||
* 而 [QQ] 含义为一个独立的人, 可以是好友, 也可以是陌生人.
|
||||
*/
|
||||
abstract override fun equals(other: Any?): Boolean
|
||||
final override fun equals(other: Any?): Boolean = super.equals(other)
|
||||
final override fun hashCode(): Int = super.hashCode()
|
||||
|
||||
/**
|
||||
* @return `bot.hashCode() * 31 + id.hashCode()`
|
||||
*/
|
||||
abstract override fun hashCode(): Int
|
||||
|
||||
/**
|
||||
* @return "QQ($id)" or "Group($id)" or "Member($id)"
|
||||
* @return "Friend($id)" or "Group($id)" or "Member($id)"
|
||||
*/
|
||||
abstract override fun toString(): String
|
||||
}
|
||||
|
@ -15,12 +15,11 @@ import net.mamoe.mirai.utils.SinceMirai
|
||||
/**
|
||||
* 拥有 [id] 的对象.
|
||||
* 此为 [Contact] 与 [Bot] 的唯一公共接口.
|
||||
* **注意:** 此接口为实验性接口, 将来可能会发生不兼容的更名.
|
||||
*
|
||||
* @see Contact
|
||||
* @see Bot
|
||||
*/
|
||||
@SinceMirai("0.37.2")
|
||||
@SinceMirai("0.39.0")
|
||||
interface ContactOrBot {
|
||||
/**
|
||||
* QQ 号或群号.
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
|
||||
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.toMessage
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* 好友 对象.
|
||||
* 注意: 一个 [Friend] 实例并不是独立的, 它属于一个 [Bot].
|
||||
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
|
||||
*
|
||||
* 对于同一个 [Bot] 任何一个人的 [Friend] 实例都是单一的.
|
||||
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
|
||||
*/
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class Friend : QQ(), CoroutineScope {
|
||||
/**
|
||||
* 请求头像下载链接
|
||||
*/
|
||||
// @MiraiExperimentalAPI
|
||||
//suspend fun queryAvatar(): AvatarLink
|
||||
/**
|
||||
* QQ 号码
|
||||
*/
|
||||
abstract override val id: Long
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
abstract override val nick: String
|
||||
|
||||
/**
|
||||
* 头像下载链接
|
||||
*/
|
||||
override val avatarUrl: String
|
||||
get() = "http://q1.qlogo.cn/g?b=qq&nk=$id&s=640"
|
||||
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
*
|
||||
* 单条消息最大可发送 4500 字符或 50 张图片.
|
||||
*
|
||||
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
|
||||
* @see GroupMessageSendEvent 发送群消息事件. cancellable
|
||||
*
|
||||
* @throws EventCancelledException 当发送消息事件被取消时抛出
|
||||
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
|
||||
* @throws MessageTooLargeException 当消息过长时抛出
|
||||
*
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<Friend>
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
|
||||
@kotlin.internal.InlineOnly // purely virtual
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendMessage(message: String): MessageReceipt<Friend> {
|
||||
return sendMessage(message.toMessage())
|
||||
}
|
||||
|
||||
final override fun toString(): String = "Friend($id)"
|
||||
}
|
@ -21,23 +21,25 @@ import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.OfflineGroupImage
|
||||
import net.mamoe.mirai.message.data.toMessage
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.OverFileSizeMaxException
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
import kotlin.jvm.JvmStatic
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* 群. 在 QQ Android 中叫做 "Troop"
|
||||
* 群.
|
||||
*/
|
||||
expect abstract class Group() : Contact, CoroutineScope {
|
||||
abstract class Group : Contact(), CoroutineScope {
|
||||
/**
|
||||
* 群名称.
|
||||
*
|
||||
* 在修改时将会异步上传至服务器.
|
||||
* 在修改时将会异步上传至服务器, 也会广播事件 [GroupNameChangeEvent].
|
||||
* 频繁修改可能会被服务器拒绝.
|
||||
*
|
||||
* @see MemberPermissionChangeEvent
|
||||
* @see GroupNameChangeEvent 群名片修改事件
|
||||
* @throws PermissionDeniedException 无权限修改时将会抛出异常
|
||||
*/
|
||||
abstract var name: String
|
||||
@ -88,6 +90,7 @@ expect abstract class Group() : Contact, CoroutineScope {
|
||||
* 群头像下载链接.
|
||||
*/
|
||||
val avatarUrl: String
|
||||
get() = "https://p.qlogo.cn/gh/$id/${id}_1/640"
|
||||
|
||||
/**
|
||||
* 群成员列表, 不含机器人自己, 含群主.
|
||||
@ -148,6 +151,16 @@ expect abstract class Group() : Contact, CoroutineScope {
|
||||
@JvmSynthetic
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<Group>
|
||||
|
||||
/**
|
||||
* @see sendMessage
|
||||
*/
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
|
||||
@kotlin.internal.InlineOnly // purely virtual
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendMessage(message: String): MessageReceipt<Group> {
|
||||
return sendMessage(message.toMessage())
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
*
|
||||
@ -161,14 +174,20 @@ expect abstract class Group() : Contact, CoroutineScope {
|
||||
abstract override suspend fun uploadImage(image: ExternalImage): OfflineGroupImage
|
||||
|
||||
companion object {
|
||||
// don't @JvmStatic: JDK 1.8 required
|
||||
fun calculateGroupUinByGroupCode(groupCode: Long): Long
|
||||
/**
|
||||
* @suppress internal api
|
||||
*/
|
||||
@JvmStatic
|
||||
fun calculateGroupUinByGroupCode(groupCode: Long): Long =
|
||||
CommonGroupCalculations.calculateGroupUinByGroupCode(groupCode)
|
||||
|
||||
fun calculateGroupCodeByGroupUin(groupUin: Long): Long
|
||||
/**
|
||||
* @suppress internal api
|
||||
*/
|
||||
@JvmStatic
|
||||
fun calculateGroupCodeByGroupUin(groupUin: Long): Long =
|
||||
CommonGroupCalculations.calculateGroupCodeByGroupUin(groupUin)
|
||||
}
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
fun toFullString(): String
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,8 +14,10 @@ package net.mamoe.mirai.contact
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.JavaFriendlyAPI
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.getFriendOrNull
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.toMessage
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.WeakRefProperty
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
@ -24,10 +26,13 @@ import kotlin.time.ExperimentalTime
|
||||
|
||||
/**
|
||||
* 群成员.
|
||||
*/ // 不要删除多平台结构, kotlin bug
|
||||
*
|
||||
* 群成员可能也是好友, 但他们在对象类型上不同.
|
||||
* 群成员可以通过 [asFriend] 得到相关好友对象.
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
@OptIn(MiraiInternalAPI::class, JavaFriendlyAPI::class)
|
||||
expect abstract class Member() : MemberJavaFriendlyAPI {
|
||||
abstract class Member : MemberJavaFriendlyAPI() {
|
||||
/**
|
||||
* 所在的群.
|
||||
*/
|
||||
@ -119,16 +124,6 @@ expect abstract class Member() : MemberJavaFriendlyAPI {
|
||||
@JvmSynthetic
|
||||
abstract suspend fun kick(message: String = "")
|
||||
|
||||
/**
|
||||
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
|
||||
*/
|
||||
abstract override fun equals(other: Any?): Boolean
|
||||
|
||||
/**
|
||||
* @return `bot.hashCode() * 31 + id.hashCode()`
|
||||
*/
|
||||
abstract override fun hashCode(): Int
|
||||
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
*
|
||||
@ -145,6 +140,43 @@ expect abstract class Member() : MemberJavaFriendlyAPI {
|
||||
*/
|
||||
@JvmSynthetic
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<Member>
|
||||
|
||||
/**
|
||||
* @see sendMessage
|
||||
*/
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
|
||||
@kotlin.internal.InlineOnly // purely virtual
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendMessage(message: String): MessageReceipt<Member> {
|
||||
return sendMessage(message.toMessage())
|
||||
}
|
||||
|
||||
final override fun toString(): String = "Member($id)"
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到此成员作为好友的对象.
|
||||
*/
|
||||
inline val Member.asFriend: Friend
|
||||
get() = this.bot.getFriendOrNull(this.id) ?: error("$this is not a friend")
|
||||
|
||||
/**
|
||||
* 得到此成员作为好友的对象.
|
||||
*/
|
||||
inline val Member.asFriendOrNull: Friend?
|
||||
get() = this.bot.getFriendOrNull(this.id)
|
||||
|
||||
/**
|
||||
* 判断此成员是否为好友
|
||||
*/
|
||||
inline val Member.isFriend: Boolean
|
||||
get() = this.bot.friends.contains(this.id)
|
||||
|
||||
/**
|
||||
* 如果此成员是好友, 则执行 [block] 并返回其返回值. 否则返回 `null`
|
||||
*/
|
||||
inline fun <R> Member.takeIfFriend(block: (Friend) -> R): R? {
|
||||
return this.asFriendOrNull?.let(block)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,6 +193,9 @@ fun Member.isMuted(): Boolean {
|
||||
return muteTimeRemaining != 0 && muteTimeRemaining != 0xFFFFFFFF.toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Member.mute
|
||||
*/
|
||||
@ExperimentalTime
|
||||
suspend inline fun Member.mute(duration: Duration) {
|
||||
require(duration.inDays <= 30) { "duration must be at most 1 month" }
|
||||
@ -168,4 +203,7 @@ suspend inline fun Member.mute(duration: Duration) {
|
||||
this.mute(duration.inSeconds.toInt())
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Member.mute
|
||||
*/
|
||||
suspend inline fun Member.mute(durationSeconds: Long) = this.mute(durationSeconds.toInt())
|
@ -12,10 +12,8 @@
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
|
||||
|
||||
/**
|
||||
* 群成员的权限.
|
||||
*
|
||||
@ -37,39 +35,42 @@ enum class MemberPermission : Comparable<MemberPermission> {
|
||||
*/
|
||||
OWNER; // ordinal = 2
|
||||
|
||||
/**
|
||||
* 权限等级. [OWNER] 为 2, [ADMINISTRATOR] 为 1, [MEMBER] 为 0
|
||||
*/
|
||||
@SinceMirai("0.32.0")
|
||||
val level: Int
|
||||
get() = ordinal
|
||||
}
|
||||
|
||||
/**
|
||||
* 是群主
|
||||
* 判断权限是否为群主
|
||||
*/
|
||||
inline fun MemberPermission.isOwner(): Boolean = this == MemberPermission.OWNER
|
||||
|
||||
/**
|
||||
* 是管理员
|
||||
* 判断权限是否为管理员
|
||||
*/
|
||||
inline fun MemberPermission.isAdministrator(): Boolean = this == MemberPermission.ADMINISTRATOR
|
||||
|
||||
/**
|
||||
* 是管理员或群主
|
||||
* 判断权限是否为管理员或群主
|
||||
*/
|
||||
inline fun MemberPermission.isOperator(): Boolean = isAdministrator() || isOwner()
|
||||
|
||||
|
||||
/**
|
||||
* 是群主
|
||||
* 判断权限是否为群主
|
||||
*/
|
||||
inline fun Member.isOwner(): Boolean = this.permission.isOwner()
|
||||
|
||||
/**
|
||||
* 是管理员
|
||||
* 判断权限是否为管理员
|
||||
*/
|
||||
inline fun Member.isAdministrator(): Boolean = this.permission.isAdministrator()
|
||||
|
||||
/**
|
||||
* 是管理员或群主
|
||||
* 判断权限是否为管理员或群主
|
||||
*/
|
||||
inline fun Member.isOperator(): Boolean = this.permission.isOperator()
|
||||
|
||||
@ -77,9 +78,10 @@ inline fun Member.isOperator(): Boolean = this.permission.isOperator()
|
||||
/**
|
||||
* 权限不足
|
||||
*/
|
||||
expect class PermissionDeniedException : IllegalStateException {
|
||||
constructor()
|
||||
constructor(message: String?)
|
||||
@Suppress("unused")
|
||||
class PermissionDeniedException : IllegalStateException {
|
||||
constructor() : super("Permission denied")
|
||||
constructor(message: String?) : super(message)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,10 +89,9 @@ expect class PermissionDeniedException : IllegalStateException {
|
||||
*
|
||||
* @throws PermissionDeniedException
|
||||
*/
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
inline fun Group.checkBotPermission(
|
||||
required: MemberPermission,
|
||||
lazyMessage: () -> String = {
|
||||
crossinline lazyMessage: () -> String = {
|
||||
"Permission denied: required $required, got actual $botPermission for $bot in group $id"
|
||||
}
|
||||
) {
|
||||
@ -104,9 +105,8 @@ inline fun Group.checkBotPermission(
|
||||
*
|
||||
* @throws PermissionDeniedException
|
||||
*/
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
inline fun Group.checkBotPermissionOperator(
|
||||
lazyMessage: () -> String = {
|
||||
crossinline lazyMessage: () -> String = {
|
||||
"Permission denied: required ${MemberPermission.ADMINISTRATOR} or ${MemberPermission.OWNER}, got actual $botPermission for $bot in group $id"
|
||||
}
|
||||
) {
|
||||
|
@ -13,76 +13,47 @@ package net.mamoe.mirai.contact
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.FriendNameRemark
|
||||
import net.mamoe.mirai.data.PreviousNameList
|
||||
import net.mamoe.mirai.data.Profile
|
||||
import net.mamoe.mirai.event.events.BeforeImageUploadEvent
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
import net.mamoe.mirai.event.events.ImageUploadEvent
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.OfflineFriendImage
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.OverFileSizeMaxException
|
||||
import net.mamoe.mirai.utils.PlannedRemoval
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* QQ 对象.
|
||||
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
|
||||
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
|
||||
*
|
||||
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
|
||||
* 自 0.39.0 起 mirai 引入 [User] 作为 [Friend] 和 [Member] 的父类,
|
||||
* 以备将来支持仅 [Friend] 可用的 API, 如设置备注.
|
||||
*
|
||||
* A QQ instance helps you to receive event from or sendPacket event to.
|
||||
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
|
||||
* 所有 API 均有二进制兼容.
|
||||
*
|
||||
* @author Him188moe
|
||||
* 请根据实际情况, 使用 [Friend] 或 [User] 替代.
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
expect abstract class QQ() : Contact, CoroutineScope {
|
||||
/**
|
||||
* 请求头像下载链接
|
||||
*/
|
||||
// @MiraiExperimentalAPI
|
||||
//suspend fun queryAvatar(): AvatarLink
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated(
|
||||
"use Friend or Person instead",
|
||||
replaceWith = ReplaceWith("Friend", "net.mamoe.mirai.contact.Friend"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class QQ : User(), CoroutineScope {
|
||||
/**
|
||||
* QQ 号码
|
||||
*/
|
||||
abstract override val id: Long
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
abstract val nick: String
|
||||
|
||||
/**
|
||||
* 查询用户资料
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
abstract suspend fun queryProfile(): Profile
|
||||
abstract override val nick: String
|
||||
|
||||
/**
|
||||
* 头像下载链接
|
||||
*/
|
||||
val avatarUrl: String
|
||||
|
||||
/**
|
||||
* 查询曾用名.
|
||||
*
|
||||
* 曾用名可能是:
|
||||
* - 昵称
|
||||
* - 共同群内的群名片
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
abstract suspend fun queryPreviousNameList(): PreviousNameList
|
||||
|
||||
/**
|
||||
* 查询机器人账号给这个人设置的备注
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
abstract suspend fun queryRemark(): FriendNameRemark
|
||||
override val avatarUrl: String
|
||||
get() = "http://q1.qlogo.cn/g?b=qq&nk=$id&s=640"
|
||||
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
@ -100,16 +71,4 @@ expect abstract class QQ() : Contact, CoroutineScope {
|
||||
*/
|
||||
@JvmSynthetic
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<QQ>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
*
|
||||
* @see BeforeImageUploadEvent 图片发送前事件, cancellable
|
||||
* @see ImageUploadEvent 图片发送完成事件
|
||||
*
|
||||
* @throws EventCancelledException 当发送消息事件被取消
|
||||
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
|
||||
*/
|
||||
@JvmSynthetic
|
||||
abstract override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage
|
||||
}
|
@ -1,12 +1,18 @@
|
||||
@file:Suppress("unused")
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
|
||||
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.FriendNameRemark
|
||||
import net.mamoe.mirai.data.PreviousNameList
|
||||
import net.mamoe.mirai.data.Profile
|
||||
import net.mamoe.mirai.event.events.BeforeImageUploadEvent
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
import net.mamoe.mirai.event.events.ImageUploadEvent
|
||||
@ -15,66 +21,38 @@ import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.OfflineFriendImage
|
||||
import net.mamoe.mirai.message.data.toMessage
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.OverFileSizeMaxException
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* QQ 对象.
|
||||
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
|
||||
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
|
||||
* 代表一个 **用户**.
|
||||
*
|
||||
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
|
||||
* 其子类有 [群成员][Member] 和 [好友][Friend].
|
||||
* 虽然群成员也可能是好友, 但他们仍是不同的两个类型.
|
||||
*
|
||||
* A QQ instance helps you to receive event from or sendPacket event to.
|
||||
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
|
||||
* 注意: 一个 [User] 实例并不是独立的, 它属于一个 [Bot].
|
||||
*
|
||||
* @author Him188moe
|
||||
* 对于同一个 [Bot] 任何一个人的 [User] 实例都是单一的.
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
actual abstract class QQ : Contact(), CoroutineScope {
|
||||
/**
|
||||
* 请求头像下载链接
|
||||
*/
|
||||
// @MiraiExperimentalAPI
|
||||
//suspend fun queryAvatar(): AvatarLink
|
||||
abstract class User : Contact(), CoroutineScope {
|
||||
/**
|
||||
* QQ 号码
|
||||
*/
|
||||
actual abstract override val id: Long
|
||||
abstract override val id: Long
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
actual abstract val nick: String
|
||||
|
||||
/**
|
||||
* 查询用户资料
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
actual abstract suspend fun queryProfile(): Profile
|
||||
abstract val nick: String
|
||||
|
||||
/**
|
||||
* 头像下载链接
|
||||
*/
|
||||
actual val avatarUrl: String
|
||||
open val avatarUrl: String
|
||||
get() = "http://q1.qlogo.cn/g?b=qq&nk=$id&s=640"
|
||||
|
||||
/**
|
||||
* 查询曾用名.
|
||||
*
|
||||
* 曾用名可能是:
|
||||
* - 昵称
|
||||
* - 共同群内的群名片
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
actual abstract suspend fun queryPreviousNameList(): PreviousNameList
|
||||
|
||||
/**
|
||||
* 查询机器人账号给这个人设置的备注
|
||||
*/
|
||||
@MiraiExperimentalAPI("还未支持")
|
||||
actual abstract suspend fun queryRemark(): FriendNameRemark
|
||||
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
*
|
||||
@ -90,7 +68,17 @@ actual abstract class QQ : Contact(), CoroutineScope {
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<QQ>
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<User>
|
||||
|
||||
/**
|
||||
* @see sendMessage
|
||||
*/
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
|
||||
@kotlin.internal.InlineOnly // purely virtual
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendMessage(message: String): MessageReceipt<User> {
|
||||
return sendMessage(message.toMessage())
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
@ -102,5 +90,7 @@ actual abstract class QQ : Contact(), CoroutineScope {
|
||||
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage
|
||||
abstract override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage
|
||||
|
||||
abstract override fun toString(): String
|
||||
}
|
@ -13,15 +13,18 @@ import net.mamoe.mirai.JavaFriendlyAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
|
||||
/**
|
||||
* [Contact] 中为了让 `Java` 更容易调用的 API
|
||||
* [Contact] 中为了让 `Java` 更容易调用的 API.
|
||||
* 不要用它作为一个类型, 只应使用其中的方法
|
||||
*/
|
||||
@MiraiInternalAPI
|
||||
@JavaFriendlyAPI
|
||||
expect abstract class ContactJavaFriendlyAPI()
|
||||
expect abstract class ContactJavaFriendlyAPI internal constructor()
|
||||
|
||||
/**
|
||||
* [Member] 中为了让 `Java` 更容易调用的 API
|
||||
* 不要用它作为一个类型, 只应使用其中的方法
|
||||
*/
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@MiraiInternalAPI
|
||||
@JavaFriendlyAPI
|
||||
expect abstract class MemberJavaFriendlyAPI : QQ
|
||||
expect abstract class MemberJavaFriendlyAPI internal constructor() : QQ // 将来会改为 User
|
@ -241,7 +241,7 @@ open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
|
||||
|
||||
/** 如果是这个人发的消息. 消息可以是好友消息也可以是群消息 */
|
||||
@MessageDsl
|
||||
fun sentBy(friend: QQ): ListeningFilter = content { sender.id == friend.id }
|
||||
fun sentBy(friend: User): ListeningFilter = content { sender.id == friend.id }
|
||||
|
||||
/** 如果是这个人发的消息. 消息可以是好友消息也可以是群消息 */
|
||||
@MessageDsl
|
||||
@ -294,7 +294,7 @@ open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
|
||||
|
||||
/** [消息内容][Message.contentToString]包含目标为 [target] 的 [At] */
|
||||
@MessageDsl
|
||||
fun at(target: QQ): ListeningFilter = content { message.firstIsInstanceOrNull<At>()?.target == target.id }
|
||||
fun at(target: User): ListeningFilter = content { message.firstIsInstanceOrNull<At>()?.target == target.id }
|
||||
|
||||
/** [消息内容][Message.contentToString]包含目标为 [Bot] 的 [At], 就执行 [onEvent] */
|
||||
@MessageDsl
|
||||
|
@ -102,7 +102,7 @@ sealed class MessageSendEvent : BotEvent, BotActiveEvent, AbstractCancellableEve
|
||||
) : MessageSendEvent(), CancellableEvent
|
||||
|
||||
data class FriendMessageSendEvent(
|
||||
override val target: QQ,
|
||||
override val target: Friend,
|
||||
var message: MessageChain
|
||||
) : MessageSendEvent(), CancellableEvent
|
||||
}
|
||||
@ -539,9 +539,17 @@ data class MemberUnmuteEvent(
|
||||
@SinceMirai("0.36.0")
|
||||
data class FriendRemarkChangeEvent(
|
||||
override val bot: Bot,
|
||||
val friend: QQ,
|
||||
val friend: Friend,
|
||||
val newName: String
|
||||
) : BotEvent, Packet
|
||||
) : BotEvent, Packet {
|
||||
|
||||
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmSynthetic
|
||||
@get:JvmName("getFriend")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
|
||||
val friendDeprecated: QQ
|
||||
get() = friend
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功添加了一个新好友的事件
|
||||
@ -551,9 +559,16 @@ data class FriendAddEvent(
|
||||
/**
|
||||
* 新好友. 已经添加到 [Bot.friends]
|
||||
*/
|
||||
val friend: QQ
|
||||
val friend: Friend
|
||||
) : BotEvent, Packet {
|
||||
override val bot: Bot get() = friend.bot
|
||||
|
||||
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmSynthetic
|
||||
@get:JvmName("getFriend")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
|
||||
val friendDeprecated: QQ
|
||||
get() = friend
|
||||
}
|
||||
|
||||
/**
|
||||
@ -561,9 +576,16 @@ data class FriendAddEvent(
|
||||
*/
|
||||
@SinceMirai("0.36.0")
|
||||
data class FriendDeleteEvent(
|
||||
val friend: QQ
|
||||
val friend: Friend
|
||||
) : BotEvent, Packet {
|
||||
override val bot: Bot get() = friend.bot
|
||||
|
||||
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmSynthetic
|
||||
@get:JvmName("getFriend")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
|
||||
val friendDeprecated: QQ
|
||||
get() = friend
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,11 +10,13 @@
|
||||
package net.mamoe.mirai.event.events
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* 有关一个 [Bot] 的事件
|
||||
@ -85,7 +87,14 @@ val GroupOperableEvent.operatorOrBot: Member
|
||||
* 有关好友的事件
|
||||
*/
|
||||
interface FriendEvent : BotEvent {
|
||||
val friend: QQ
|
||||
val friend: Friend
|
||||
override val bot: Bot
|
||||
get() = friend.bot
|
||||
|
||||
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmSynthetic
|
||||
@get:JvmName("getFriend")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
|
||||
val friendDeprecated: net.mamoe.mirai.contact.QQ
|
||||
get() = friend
|
||||
}
|
@ -10,8 +10,8 @@
|
||||
package net.mamoe.mirai
|
||||
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.data.*
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
@ -37,13 +37,13 @@ annotation class LowLevelAPI
|
||||
@LowLevelAPI
|
||||
interface LowLevelBotAPIAccessor {
|
||||
/**
|
||||
* 构造一个 [_lowLevelNewQQ] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
|
||||
* 构造一个 [Friend] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
|
||||
*
|
||||
* [Bot] 无法管理这个对象, 但这个对象会以 [Bot] 的 [Job] 作为父 Job.
|
||||
* 因此, 当 [Bot] 被关闭后, 这个对象也会被关闭.
|
||||
*/
|
||||
@LowLevelAPI
|
||||
fun _lowLevelNewQQ(friendInfo: FriendInfo): QQ
|
||||
fun _lowLevelNewFriend(friendInfo: FriendInfo): Friend
|
||||
|
||||
/**
|
||||
* 向服务器查询群列表. 返回值高 32 bits 为 uin, 低 32 bits 为 groupCode
|
||||
|
@ -23,10 +23,7 @@ import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.io.ByteReadChannel
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.event.selectMessages
|
||||
import net.mamoe.mirai.event.syncFromEvent
|
||||
@ -52,7 +49,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@SinceMirai("0.32.0")
|
||||
abstract class ContactMessage : MessagePacket<QQ, Contact>(), BotEvent
|
||||
abstract class ContactMessage : MessagePacket<User, Contact>(), BotEvent
|
||||
|
||||
/**
|
||||
* 一条从服务器接收到的消息事件.
|
||||
@ -63,7 +60,7 @@ abstract class ContactMessage : MessagePacket<QQ, Contact>(), BotEvent
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
expect abstract class MessagePacket<TSender : QQ, TSubject : Contact> constructor() :
|
||||
expect abstract class MessagePacket<TSender : User, TSubject : Contact> constructor() :
|
||||
MessagePacketBase<TSender, TSubject>
|
||||
|
||||
/**
|
||||
@ -74,7 +71,7 @@ expect abstract class MessagePacket<TSender : QQ, TSubject : Contact> constructo
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||
abstract class MessagePacketBase<out TSender : QQ, out TSubject : Contact> : Packet, BotEvent {
|
||||
abstract class MessagePacketBase<out TSender : User, out TSubject : Contact> : Packet, BotEvent {
|
||||
/**
|
||||
* 接受到这条消息的
|
||||
*/
|
||||
@ -105,6 +102,10 @@ abstract class MessagePacketBase<out TSender : QQ, out TSubject : Contact> : Pac
|
||||
*/
|
||||
abstract val message: MessageChain
|
||||
|
||||
/**
|
||||
* 消息源
|
||||
*/
|
||||
open val source: OnlineMessageSource.Incoming get() = message.source as OnlineMessageSource.Incoming
|
||||
|
||||
// region 发送 Message
|
||||
|
||||
@ -118,18 +119,11 @@ abstract class MessagePacketBase<out TSender : QQ, out TSubject : Contact> : Pac
|
||||
|
||||
suspend inline fun reply(plain: String): MessageReceipt<TSubject> =
|
||||
subject.sendMessage(plain.toMessage().asMessageChain()) as MessageReceipt<TSubject>
|
||||
|
||||
// endregion
|
||||
|
||||
// region 撤回
|
||||
|
||||
// endregion
|
||||
|
||||
// region 上传图片
|
||||
// region 图片
|
||||
suspend inline fun ExternalImage.upload(): Image = this.upload(subject)
|
||||
// endregion
|
||||
|
||||
// region 发送图片
|
||||
suspend inline fun ExternalImage.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
|
||||
suspend inline fun Image.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
@ -159,22 +153,12 @@ abstract class MessagePacketBase<out TSender : QQ, out TSubject : Contact> : Pac
|
||||
@JvmName("reply2")
|
||||
suspend inline fun MessageChain.quoteReply(): MessageReceipt<TSubject> = quoteReply(this)
|
||||
|
||||
open val source: OnlineMessageSource.Incoming get() = message.source as OnlineMessageSource.Incoming
|
||||
|
||||
// endregion
|
||||
|
||||
operator fun <M : Message> get(at: Message.Key<M>): M {
|
||||
inline operator fun <M : Message> get(at: Message.Key<M>): M {
|
||||
return this.message[at]
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 @ 这个账号的消息. 当且仅当消息为群消息时可用. 否则将会抛出 [IllegalArgumentException]
|
||||
*/
|
||||
fun QQ.at(): At = At(this as? Member ?: error("`QQ.at` can only be used in GroupMessage"))
|
||||
|
||||
fun At.member(): Member = (this@MessagePacketBase as? GroupMessage)?.group?.get(this.target)
|
||||
?: error("`At.member` can only be used in GroupMessage")
|
||||
|
||||
inline fun At.isBot(): Boolean = target == bot.id
|
||||
|
||||
// endregion
|
||||
@ -202,13 +186,40 @@ abstract class MessagePacketBase<out TSender : QQ, out TSubject : Contact> : Pac
|
||||
// endregion
|
||||
|
||||
|
||||
@Deprecated("use reply(String) for clear semantics", ReplaceWith("reply(this)"))
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated("use reply(String) for clear semantics", ReplaceWith("reply(this)"),
|
||||
DeprecationLevel.ERROR)
|
||||
@JvmName("reply1")
|
||||
suspend inline fun String.reply(): MessageReceipt<TSubject> = reply(this)
|
||||
|
||||
@Deprecated("use reply(String) for clear semantics", ReplaceWith("reply(this)"))
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated("use reply(String) for clear semantics", ReplaceWith("reply(this)"),
|
||||
level = DeprecationLevel.ERROR)
|
||||
@JvmName("reply1")
|
||||
suspend inline fun Message.reply(): MessageReceipt<TSubject> = reply(this)
|
||||
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmSynthetic
|
||||
@get:JvmName("getSender")
|
||||
@Suppress("DEPRECATION_ERROR", "INAPPLICABLE_JVM_NAME")
|
||||
val senderDeprecated: QQ
|
||||
get() = sender as QQ
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated("removed",
|
||||
level = DeprecationLevel.ERROR,
|
||||
replaceWith = ReplaceWith("At(this as? Member ?: error(\"`QQ.at` can only be used in GroupMessage\"))",
|
||||
"net.mamoe.mirai.message.data.At",
|
||||
"net.mamoe.mirai.contact.Member"))
|
||||
fun QQ.at(): At = At(this as? Member ?: error("`QQ.at` can only be used in GroupMessage"))
|
||||
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated("removed",
|
||||
level = DeprecationLevel.ERROR,
|
||||
replaceWith = ReplaceWith("(this@MessagePacketBase as? GroupMessage)?.group?.get(this.target) ?: error(\"`At.member` can only be used in GroupMessage\")"))
|
||||
fun At.member(): Member = (this@MessagePacketBase as? GroupMessage)?.group?.get(this.target)
|
||||
?: error("`At.member` can only be used in GroupMessage")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,15 +7,19 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION_ERROR")
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.event.BroadcastControllable
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.message.data.source
|
||||
import net.mamoe.mirai.utils.PlannedRemoval
|
||||
import net.mamoe.mirai.utils.getValue
|
||||
import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
|
||||
@ -23,17 +27,21 @@ import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
* 好友消息
|
||||
*/
|
||||
class FriendMessage(
|
||||
sender: QQ,
|
||||
sender: Friend,
|
||||
override val message: MessageChain
|
||||
) : ContactMessage(), BroadcastControllable {
|
||||
@PlannedRemoval("1.0.0")
|
||||
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||
constructor(sender: QQ, message: MessageChain) : this(sender as Friend, message)
|
||||
|
||||
init {
|
||||
val source = message.getOrNull(MessageSource) ?: error("Cannot find MessageSource from message")
|
||||
check(source is OnlineMessageSource.Incoming.FromFriend) { "source provided to a FriendMessage must be an instance of OnlineMessageSource.Incoming.FromFriend" }
|
||||
}
|
||||
|
||||
override val sender: QQ by sender.unsafeWeakRef()
|
||||
override val sender: Friend by sender.unsafeWeakRef()
|
||||
override val bot: Bot get() = sender.bot
|
||||
override val subject: QQ get() = sender
|
||||
override val subject: Friend get() = sender
|
||||
override val source: OnlineMessageSource.Incoming.FromFriend get() = message.source as OnlineMessageSource.Incoming.FromFriend
|
||||
|
||||
override fun toString(): String = "FriendMessage(sender=${sender.id}, message=$message)"
|
||||
|
@ -14,10 +14,7 @@ import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.message.data.source
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.utils.getValue
|
||||
import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
|
||||
@ -44,7 +41,7 @@ class GroupMessage(
|
||||
|
||||
override val source: OnlineMessageSource.Incoming.FromGroup get() = message.source as OnlineMessageSource.Incoming.FromGroup
|
||||
|
||||
inline fun Long.member(): Member = group[this]
|
||||
inline fun At.asMember(): Member = group[this.target]
|
||||
|
||||
override fun toString(): String =
|
||||
"GroupMessage(group=${group.id}, senderName=$senderName, sender=${sender.id}, permission=${permission.name}, message=$message)"
|
||||
|
@ -116,14 +116,12 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
* 消息发送人. 可能为 [机器人][Bot] 或 [好友][QQ] 或 [群员][Member].
|
||||
* 即类型必定为 [Bot], [QQ] 或 [Member]
|
||||
*/
|
||||
@ExperimentalIdentification
|
||||
abstract val sender: ContactOrBot
|
||||
|
||||
/**
|
||||
* 消息发送目标. 可能为 [机器人][Bot] 或 [好友][QQ] 或 [群][Group].
|
||||
* 即类型必定为 [Bot], [QQ] 或 [Group]
|
||||
*/
|
||||
@ExperimentalIdentification
|
||||
abstract val target: ContactOrBot
|
||||
|
||||
/**
|
||||
@ -135,7 +133,6 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
/**
|
||||
* 由 [机器人主动发送消息][Contact.sendMessage] 产生的 [MessageSource]
|
||||
*/
|
||||
@OptIn(ExperimentalIdentification::class)
|
||||
sealed class Outgoing : OnlineMessageSource() {
|
||||
companion object Key : Message.Key<Outgoing> {
|
||||
override val typeName: String get() = "OnlineMessageSource.Outgoing"
|
||||
@ -152,8 +149,8 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
override val typeName: String get() = "OnlineMessageSource.Outgoing.ToFriend"
|
||||
}
|
||||
|
||||
abstract override val target: QQ
|
||||
final override val subject: QQ get() = target
|
||||
abstract override val target: Friend
|
||||
final override val subject: Friend get() = target
|
||||
// final override fun toString(): String = "OnlineMessageSource.ToFriend(target=${target.id})"
|
||||
}
|
||||
|
||||
@ -181,13 +178,12 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
/**
|
||||
* 接收到的一条消息的 [MessageSource]
|
||||
*/
|
||||
@OptIn(ExperimentalIdentification::class)
|
||||
sealed class Incoming : OnlineMessageSource() {
|
||||
companion object Key : Message.Key<Incoming> {
|
||||
override val typeName: String get() = "OnlineMessageSource.Incoming"
|
||||
}
|
||||
|
||||
abstract override val sender: QQ // out QQ
|
||||
abstract override val sender: User
|
||||
|
||||
final override val fromId: Long get() = sender.id
|
||||
final override val targetId: Long get() = target.id
|
||||
@ -197,8 +193,8 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
override val typeName: String get() = "OnlineMessageSource.Incoming.FromFriend"
|
||||
}
|
||||
|
||||
abstract override val sender: QQ
|
||||
final override val subject: QQ get() = sender
|
||||
abstract override val sender: Friend
|
||||
final override val subject: Friend get() = sender
|
||||
final override val target: Bot get() = sender.bot
|
||||
// final override fun toString(): String = "OnlineMessageSource.FromFriend(from=${sender.id})"
|
||||
}
|
||||
@ -243,7 +239,6 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
@Deprecated("for binary compatibility until 1.0.0", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmName("target")
|
||||
@get:JvmSynthetic
|
||||
@OptIn(ExperimentalIdentification::class)
|
||||
open val target2: Any
|
||||
get() = target
|
||||
|
||||
@ -251,7 +246,6 @@ sealed class OnlineMessageSource : MessageSource() {
|
||||
@Deprecated("for binary compatibility until 1.0.0", level = DeprecationLevel.HIDDEN)
|
||||
@get:JvmName("sender")
|
||||
@get:JvmSynthetic
|
||||
@OptIn(ExperimentalIdentification::class)
|
||||
open val sender2: Any
|
||||
get() = sender
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
@ -18,7 +18,7 @@ import kotlinx.io.core.Input
|
||||
import kotlinx.serialization.InternalSerializationApi
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.OfflineImage
|
||||
@ -153,7 +153,7 @@ class ExternalImage private constructor(
|
||||
@JvmSynthetic
|
||||
suspend fun <C : Contact> ExternalImage.sendTo(contact: C): MessageReceipt<C> = when (contact) {
|
||||
is Group -> contact.uploadImage(this).sendTo(contact)
|
||||
is QQ -> contact.uploadImage(this).sendTo(contact)
|
||||
is User -> contact.uploadImage(this).sendTo(contact)
|
||||
else -> error("unreachable")
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ suspend fun <C : Contact> ExternalImage.sendTo(contact: C): MessageReceipt<C> =
|
||||
@JvmSynthetic
|
||||
suspend fun ExternalImage.upload(contact: Contact): OfflineImage = when (contact) {
|
||||
is Group -> contact.uploadImage(this)
|
||||
is QQ -> contact.uploadImage(this)
|
||||
is User -> contact.uploadImage(this)
|
||||
else -> error("unreachable")
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.mamoe.mirai
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.contact.PermissionDeniedException
|
||||
import net.mamoe.mirai.contact.recall
|
||||
import net.mamoe.mirai.data.AddFriendResult
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
|
@ -205,7 +205,7 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "FunctionName", "unused", "unused")
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "FunctionName", "unused", "unused", "DEPRECATION_ERROR")
|
||||
@MiraiInternalAPI
|
||||
@JavaFriendlyAPI
|
||||
actual abstract class MemberJavaFriendlyAPI : QQ() {
|
||||
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* 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.contact
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.LowLevelAPI
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.OfflineGroupImage
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.OverFileSizeMaxException
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
|
||||
/**
|
||||
* 群. 在 QQ Android 中叫做 "Troop"
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
actual abstract class Group : Contact(), CoroutineScope {
|
||||
/**
|
||||
* 群名称.
|
||||
*
|
||||
* 在修改时将会异步上传至服务器.
|
||||
* 频繁修改可能会被服务器拒绝.
|
||||
*
|
||||
* @see MemberPermissionChangeEvent
|
||||
* @throws PermissionDeniedException 无权限修改时将会抛出异常
|
||||
*/
|
||||
actual abstract var name: String
|
||||
|
||||
/**
|
||||
* 群设置
|
||||
*/
|
||||
@SinceMirai("0.30.0")
|
||||
actual abstract val settings: GroupSettings
|
||||
|
||||
/**
|
||||
* 同为 groupCode, 用户看到的群号码.
|
||||
*/
|
||||
actual abstract override val id: Long
|
||||
|
||||
/**
|
||||
* 群主.
|
||||
*
|
||||
* @return 若机器人是群主, 返回 [botAsMember]. 否则返回相应的成员
|
||||
*/
|
||||
actual abstract val owner: Member
|
||||
|
||||
/**
|
||||
* [Bot] 在群内的 [newMember] 实例
|
||||
*/
|
||||
@MiraiExperimentalAPI
|
||||
actual abstract val botAsMember: Member
|
||||
|
||||
/**
|
||||
* 机器人被禁言还剩余多少秒
|
||||
*
|
||||
* @see BotMuteEvent 机器人被禁言事件
|
||||
* @see isBotMuted 判断机器人是否正在被禁言
|
||||
*/
|
||||
actual abstract val botMuteRemaining: Int
|
||||
|
||||
/**
|
||||
* 机器人在这个群里的权限
|
||||
*
|
||||
* @see Group.checkBotPermission 检查 [Bot] 在这个群里的权限
|
||||
* @see Group.checkBotPermissionOperator 要求 [Bot] 在这个群里的权限为 [管理员或群主][MemberPermission.isOperator]
|
||||
*
|
||||
* @see BotGroupPermissionChangeEvent 机器人群员修改
|
||||
*/
|
||||
actual abstract val botPermission: MemberPermission
|
||||
|
||||
/**
|
||||
* 群头像下载链接.
|
||||
*/
|
||||
actual val avatarUrl: String
|
||||
get() = "https://p.qlogo.cn/gh/$id/${id}_1/640"
|
||||
|
||||
/**
|
||||
* 群成员列表, 不含机器人自己, 含群主.
|
||||
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
|
||||
*/
|
||||
actual abstract val members: ContactList<Member>
|
||||
|
||||
/**
|
||||
* 获取群成员实例. 不存在时抛出 [kotlin.NoSuchElementException]
|
||||
* 当 [id] 为 [Bot.id] 时返回 [botAsMember]
|
||||
*/
|
||||
actual abstract operator fun get(id: Long): Member
|
||||
|
||||
/**
|
||||
* 获取群成员实例, 不存在则 null
|
||||
* 当 [id] 为 [Bot.id] 时返回 [botAsMember]
|
||||
*/
|
||||
actual abstract fun getOrNull(id: Long): Member?
|
||||
|
||||
|
||||
/**
|
||||
* 检查此 id 的群成员是否存在
|
||||
* 当 [id] 为 [Bot.id] 时返回 `true`
|
||||
*/
|
||||
actual abstract operator fun contains(id: Long): Boolean
|
||||
|
||||
/**
|
||||
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
|
||||
*/
|
||||
@SinceMirai("0.37.0")
|
||||
actual abstract suspend fun quit(): Boolean
|
||||
|
||||
/**
|
||||
* 构造一个 [Member].
|
||||
* 非特殊情况请不要使用这个函数. 优先使用 [get].
|
||||
*/
|
||||
@LowLevelAPI
|
||||
@MiraiExperimentalAPI("dangerous")
|
||||
actual abstract fun newMember(memberInfo: MemberInfo): Member
|
||||
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
*
|
||||
* 单条消息最大可发送 4500 字符或 50 张图片.
|
||||
*
|
||||
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
|
||||
* @see GroupMessageSendEvent 发送群消息事件. cancellable
|
||||
*
|
||||
* @throws EventCancelledException 当发送消息事件被取消时抛出
|
||||
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
|
||||
* @throws MessageTooLargeException 当消息过长时抛出
|
||||
*
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<Group>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
*
|
||||
* @see BeforeImageUploadEvent 图片上传前事件, cancellable
|
||||
* @see ImageUploadEvent 图片上传完成事件
|
||||
*
|
||||
* @throws EventCancelledException 当发送消息事件被取消
|
||||
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun uploadImage(image: ExternalImage): OfflineGroupImage
|
||||
|
||||
actual companion object {
|
||||
actual fun calculateGroupUinByGroupCode(groupCode: Long): Long =
|
||||
CommonGroupCalculations.calculateGroupUinByGroupCode(groupCode)
|
||||
|
||||
actual fun calculateGroupCodeByGroupUin(groupUin: Long): Long =
|
||||
CommonGroupCalculations.calculateGroupCodeByGroupUin(groupUin)
|
||||
}
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
actual fun toFullString(): String {
|
||||
return "Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.JavaFriendlyAPI
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.WeakRefProperty
|
||||
|
||||
/**
|
||||
* 群成员.
|
||||
*/
|
||||
@OptIn(MiraiInternalAPI::class, JavaFriendlyAPI::class)
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
actual abstract class Member : MemberJavaFriendlyAPI() {
|
||||
/**
|
||||
* 所在的群.
|
||||
*/
|
||||
@WeakRefProperty
|
||||
actual abstract val group: Group
|
||||
|
||||
/**
|
||||
* 成员的权限, 动态更新.
|
||||
*
|
||||
* @see MemberPermissionChangeEvent 权限变更事件. 由群主或机器人的操作触发.
|
||||
*/
|
||||
actual abstract val permission: MemberPermission
|
||||
/**
|
||||
* 群名片. 可能为空.
|
||||
*
|
||||
* 管理员和群主都可修改任何人(包括群主)的群名片.
|
||||
*
|
||||
* 在修改时将会异步上传至服务器.
|
||||
*
|
||||
* @see [nameCardOrNick] 获取非空群名片或昵称
|
||||
*
|
||||
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
|
||||
* @throws PermissionDeniedException 无权限修改时
|
||||
*/
|
||||
actual abstract var nameCard: String
|
||||
/**
|
||||
* 群头衔.
|
||||
*
|
||||
* 仅群主可以修改群头衔.
|
||||
*
|
||||
* 在修改时将会异步上传至服务器.
|
||||
*
|
||||
* @see MemberSpecialTitleChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
|
||||
* @throws PermissionDeniedException 无权限修改时
|
||||
*/
|
||||
actual abstract var specialTitle: String
|
||||
/**
|
||||
* 被禁言剩余时长. 单位为秒.
|
||||
*
|
||||
* @see isMuted 判断改成员是否处于禁言状态
|
||||
* @see mute 设置禁言
|
||||
* @see unmute 取消禁言
|
||||
*/
|
||||
actual abstract val muteTimeRemaining: Int
|
||||
|
||||
/**
|
||||
* 禁言.
|
||||
*
|
||||
* QQ 中最小操作和显示的时间都是一分钟.
|
||||
* 机器人可以实现精确到秒, 会被客户端显示为 1 分钟但不影响实际禁言时间.
|
||||
*
|
||||
* 管理员可禁言成员, 群主可禁言管理员和群员.
|
||||
*
|
||||
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
|
||||
* @return 机器人无权限时返回 `false`
|
||||
*
|
||||
* @see Int.minutesToSeconds
|
||||
* @see Int.hoursToSeconds
|
||||
* @see Int.daysToSeconds
|
||||
*
|
||||
* @see MemberMuteEvent 成员被禁言事件
|
||||
* @throws PermissionDeniedException 无权限修改时
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract suspend fun mute(durationSeconds: Int)
|
||||
|
||||
/**
|
||||
* 解除禁言.
|
||||
*
|
||||
* 管理员可解除成员的禁言, 群主可解除管理员和群员的禁言.
|
||||
*
|
||||
* @see MemberUnmuteEvent 成员被取消禁言事件.
|
||||
* @throws PermissionDeniedException 无权限修改时
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract suspend fun unmute()
|
||||
|
||||
/**
|
||||
* 踢出该成员.
|
||||
*
|
||||
* 管理员可踢出成员, 群主可踢出管理员和群员.
|
||||
*
|
||||
* @see MemberLeaveEvent.Kick 成员被踢出事件.
|
||||
* @throws PermissionDeniedException 无权限修改时
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract suspend fun kick(message: String)
|
||||
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
*
|
||||
* 单条消息最大可发送 4500 字符或 50 张图片.
|
||||
*
|
||||
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
|
||||
* @see GroupMessageSendEvent 发送群消息事件. cancellable
|
||||
*
|
||||
* @throws EventCancelledException 当发送消息事件被取消时抛出
|
||||
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
|
||||
* @throws MessageTooLargeException 当消息过长时抛出
|
||||
*
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<Member>
|
||||
|
||||
/**
|
||||
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
|
||||
*/
|
||||
actual abstract override fun equals(other: Any?): Boolean
|
||||
|
||||
/**
|
||||
* @return `bot.hashCode() * 31 + id.hashCode()`
|
||||
*/
|
||||
actual abstract override fun hashCode(): Int
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
/**
|
||||
* 权限不足
|
||||
*/ // 不要删除多平台结构
|
||||
actual class PermissionDeniedException : IllegalStateException {
|
||||
actual constructor() : super("Permission denied")
|
||||
actual constructor(message: String?) : super(message)
|
||||
}
|
@ -16,7 +16,8 @@ import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.Output
|
||||
import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
@ -38,7 +39,7 @@ import java.net.URL
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
|
||||
actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor() :
|
||||
actual abstract class MessagePacket<TSender : User, TSubject : Contact> actual constructor() :
|
||||
MessagePacketBase<TSender, TSubject>() {
|
||||
// region 上传图片
|
||||
@JvmSynthetic
|
||||
|
Loading…
Reference in New Issue
Block a user