Remove all deprecated APIs

This commit is contained in:
Him188 2020-05-02 16:56:18 +08:00
parent a7e0f63dc6
commit 2be325d781
44 changed files with 148 additions and 936 deletions

View File

@ -15,7 +15,6 @@ import io.ktor.client.HttpClient
import io.ktor.client.request.*
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData
import io.ktor.client.statement.HttpResponse
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.async
import kotlinx.coroutines.io.ByteReadChannel
@ -766,13 +765,6 @@ internal abstract class QQAndroidBotBase constructor(
}
}
@Suppress("DeprecatedCallableAddReplaceWith")
@PlannedRemoval("1.0.0")
@Deprecated("use your own Http clients, this is going to be removed in 1.0.0", level = DeprecationLevel.WARNING)
override suspend fun openChannel(image: Image): ByteReadChannel {
return MiraiPlatformUtils.Http.get<HttpResponse>(queryImageUrl(image)).content.toKotlinByteReadChannel()
}
/**
* 获取 获取群公告 所需的 bkn 参数
* */

View File

@ -97,13 +97,14 @@ internal class FriendImpl(
dstUin = id.toInt(),
fileId = 0,
fileMd5 = image.md5,
fileSize = image.inputSize.toInt(),
fileSize = @Suppress("INVISIBLE_MEMBER")
image.input.size.toInt(),
fileName = image.md5.toUHexString("") + "." + ExternalImage.defaultFormatName,
imgOriginal = 1
)
).sendAndExpect<LongConn.OffPicUp.Response>()
@Suppress("UNCHECKED_CAST", "DEPRECATION") // bug
@Suppress("UNCHECKED_CAST", "DEPRECATION", "INVISIBLE_MEMBER")
return when (response) {
is LongConn.OffPicUp.Response.FileExists -> net.mamoe.mirai.message.data.OfflineFriendImage(response.resourceId)
.also {
@ -111,7 +112,7 @@ internal class FriendImpl(
}
is LongConn.OffPicUp.Response.RequireUpload -> {
bot.network.logger.verbose {
"[Http] Uploading friend image, size=${image.inputSize.sizeToString()}"
"[Http] Uploading friend image, size=${image.input.size.sizeToString()}"
}
val time = measureTime {
@ -120,13 +121,12 @@ internal class FriendImpl(
bot.id,
null,
imageInput = image.input,
inputSize = image.inputSize,
uKeyHex = response.uKey.toUHexString("")
)
}
bot.network.logger.verbose {
"[Http] Uploading friend image: succeed at ${(image.inputSize.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s"
"[Http] Uploading friend image: succeed at ${(image.input.size.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s"
}
/*
@ -151,6 +151,7 @@ internal class FriendImpl(
}
}
} finally {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
(image.input as? Closeable)?.close()
}
}

View File

@ -412,7 +412,7 @@ internal class GroupImpl(
uin = bot.id,
groupCode = id,
md5 = image.md5,
size = image.inputSize
size = image.input.size.toInt()
).sendAndExpect()
@Suppress("UNCHECKED_CAST") // bug
@ -432,7 +432,7 @@ internal class GroupImpl(
bot,
response.uploadIpList.zip(response.uploadPortList),
response.uKey,
image,
image.input,
kind = "group image",
commandId = 2
)

View File

@ -118,7 +118,7 @@ internal class MemberImpl constructor(
newValue
).sendWithoutExpect()
}
MemberCardChangeEvent(oldValue, newValue, this@MemberImpl, null).broadcast()
MemberCardChangeEvent(oldValue, newValue, this@MemberImpl).broadcast()
}
}
}
@ -205,6 +205,7 @@ internal class MemberImpl constructor(
check(response.success) { "kick failed: ${response.ret}" }
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
group.members.delegate.removeIf { it.id == this@MemberImpl.id }
MemberLeaveEvent.Kick(this@MemberImpl, null).broadcast()
}

View File

@ -341,10 +341,10 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(groupIdOrZero: Long, bot: B
="" a_actionData="" url=""/></msg>
*/
/**
* [JsonMessage]
* json?
*/
1 -> @Suppress("DEPRECATION_ERROR")
list.add(JsonMessage(content))
list.add(ServiceMessage(1, content))
/**
* [LongMessage], [ForwardMessage]
*/
@ -364,7 +364,7 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(groupIdOrZero: Long, bot: B
else -> {
if (element.richMsg.serviceId == 60 || content.startsWith("<?")) {
@Suppress("DEPRECATION_ERROR") // bin comp
list.add(XmlMessage(element.richMsg.serviceId, content))
list.add(ServiceMessage(element.richMsg.serviceId, content))
} else list.add(ServiceMessage(element.richMsg.serviceId, content))
}
}

View File

@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package net.mamoe.mirai.qqandroid.network
import kotlinx.atomicfu.AtomicRef
@ -44,6 +46,7 @@ import net.mamoe.mirai.qqandroid.utils.io.useBytes
import net.mamoe.mirai.qqandroid.utils.retryCatching
import net.mamoe.mirai.utils.*
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmField
import kotlin.jvm.Volatile
import kotlin.time.ExperimentalTime
@ -204,6 +207,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
private val _pendingEnabled = atomic(true)
internal val pendingEnabled get() = _pendingEnabled.value
@JvmField
@Volatile
internal var pendingIncomingPackets: LockFreeLinkedList<KnownPacketFactories.IncomingPacket<*>>? =
LockFreeLinkedList()

View File

@ -42,13 +42,12 @@ import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
@OptIn(MiraiInternalAPI::class, InternalSerializationApi::class)
@Suppress("SpellCheckingInspection")
@Suppress("SpellCheckingInspection", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
internal suspend fun HttpClient.postImage(
htcmd: String,
uin: Long,
groupcode: Long?,
imageInput: Any, // Input from kotlinx.io, InputStream from kotlinx.io MPP, ByteReadChannel from ktor
inputSize: Long,
imageInput: ExternalImage.ReusableInput, // Input from kotlinx.io, InputStream from kotlinx.io MPP, ByteReadChannel from ktor
uKeyHex: String
): Boolean = post<HttpStatusCode> {
url {
@ -63,7 +62,7 @@ internal suspend fun HttpClient.postImage(
parameters["term"] = "pc"
parameters["ver"] = "5603"
parameters["filesize"] = inputSize.toString()
parameters["filesize"] = imageInput.size.toString()
parameters["range"] = 0.toString()
parameters["ukey"] = uKeyHex
@ -72,7 +71,7 @@ internal suspend fun HttpClient.postImage(
body = object : OutgoingContent.WriteChannelContent() {
override val contentType: ContentType = ContentType.Image.Any
override val contentLength: Long = inputSize
override val contentLength: Long = imageInput.size
@OptIn(MiraiExperimentalAPI::class)
override suspend fun writeTo(channel: ByteWriteChannel) {
@ -102,14 +101,15 @@ internal suspend fun HttpClient.postImage(
@OptIn(MiraiInternalAPI::class, InternalSerializationApi::class)
internal object HighwayHelper {
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
suspend fun uploadImageToServers(
bot: QQAndroidBot,
servers: List<Pair<Int, Int>>,
uKey: ByteArray,
image: ExternalImage,
image: ExternalImage.ReusableInput,
kind: String,
commandId: Int
) = uploadImageToServers(bot, servers, uKey, image.md5, image.input, image.inputSize, kind, commandId)
) = uploadImageToServers(bot, servers, uKey, image.md5, image.input(), image.size, kind, commandId)
@OptIn(ExperimentalTime::class)
suspend fun uploadImageToServers(
@ -137,7 +137,7 @@ internal object HighwayHelper {
serverIp = ip,
serverPort = port,
imageInput = input,
inputSize = inputSize.toInt(),
inputSize = inputSize,
fileMd5 = md5,
ticket = uKey,
commandId = commandId
@ -156,7 +156,7 @@ internal object HighwayHelper {
serverPort: Int,
ticket: ByteArray,
imageInput: Any,
inputSize: Int,
inputSize: Long,
fileMd5: ByteArray,
commandId: Int // group=2, friend=1
) {

View File

@ -41,14 +41,14 @@ internal fun createImageDataPacketSequence(
ticket: ByteArray,
data: Any,
dataSize: Int,
dataSize: Long,
fileMd5: ByteArray,
sizePerPacket: Int = ByteArrayPool.BUFFER_SIZE
): Flow<ByteReadPacket> {
ByteArrayPool.checkBufferSize(sizePerPacket)
require(data is Input || data is InputStream || data is ByteReadChannel) { "unsupported data: ${data::class.simpleName}" }
// require(ticket.size == 128) { "bad uKey. Required size=128, got ${ticket.size}" }
require(data !is ByteReadPacket || data.remaining.toInt() == dataSize) { "bad input. given dataSize=$dataSize, but actual readRemaining=${(data as ByteReadPacket).remaining}" }
require(data !is ByteReadPacket) { "bad input. given dataSize=$dataSize, but actual readRemaining=${(data as ByteReadPacket).remaining}" }
val flow = when (data) {
is ByteReadPacket -> data.chunkedFlow(sizePerPacket)
@ -82,7 +82,7 @@ internal fun createImageDataPacketSequence(
// cacheAddr = 812157193,
datalength = chunkedInput.bufferSize,
dataoffset = offset,
filesize = dataSize.toLong(),
filesize = dataSize,
serviceticket = ticket,
md5 = MiraiPlatformUtils.md5(chunkedInput.buffer, 0, chunkedInput.bufferSize),
fileMd5 = fileMd5,

View File

@ -219,6 +219,7 @@ internal object KnownPacketFactories {
it as IncomingPacket<T>
if (it.packetFactory is IncomingPacketFactory<T> && it.packetFactory.canBeCached && bot.network.pendingEnabled) {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
bot.network.pendingIncomingPackets?.addLast(it.also {
it.consumer = consumer
it.flag2 = flag2

View File

@ -17,6 +17,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x388
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.chat.toLongUnsigned
import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
import kotlin.random.Random
@ -27,9 +28,6 @@ internal fun getRandomString(length: Int): String =
private val defaultRanges: Array<CharRange> = arrayOf('a'..'z', 'A'..'Z', '0'..'9')
internal fun getRandomString(length: Int, charRange: CharRange): String =
String(CharArray(length) { charRange.random() })
internal fun getRandomString(length: Int, vararg charRanges: CharRange): String =
String(CharArray(length) { charRanges[Random.Default.nextInt(0..charRanges.lastIndex)].random() })
@ -41,7 +39,7 @@ internal class ImgStore {
uin: Long,
groupCode: Long,
md5: ByteArray,
size: Long,
size: Int,
picWidth: Int = 0, // not orthodox
picHeight: Int = 0, // not orthodox
picType: Int = 1000,
@ -63,7 +61,7 @@ internal class ImgStore {
groupCode = groupCode,
srcUin = uin,
fileMd5 = md5,
fileSize = size,
fileSize = size.toLongUnsigned(),
fileId = fileId,
fileName = filename,
picWidth = picWidth,

View File

@ -223,6 +223,7 @@ internal class MessageSvc {
// 新群
val newGroup = msg.getNewGroup(bot) ?: return@mapNotNull null
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
bot.groups.delegate.addLast(newGroup)
return@mapNotNull BotJoinGroupEvent(newGroup)
} else {
@ -232,6 +233,7 @@ internal class MessageSvc {
return@mapNotNull null
}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
return@mapNotNull MemberJoinEvent.Invite(group.newMember(msg.getNewMemberInfo())
.also { group.members.delegate.addLast(it) })
}
@ -245,6 +247,7 @@ internal class MessageSvc {
if (group.members.contains(msg.msgHead.authUin)) {
return@mapNotNull null
}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
return@mapNotNull MemberJoinEvent.Active(group.newMember(msg.getNewMemberInfo())
.also { group.members.delegate.addLast(it) })
}

View File

@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
@ -87,7 +87,8 @@ internal class OnlinePush {
}
}
val group = bot.getGroupOrNull(pbPushMsg.msg.msgHead.groupInfo!!.groupCode) as GroupImpl? ?: return null // 机器人还正在进群
val group =
bot.getGroupOrNull(pbPushMsg.msg.msgHead.groupInfo!!.groupCode) as GroupImpl? ?: return null // 机器人还正在进群
val sender = if (anonymous != null) {
group.newAnonymous(anonymous.anonNick.encodeToString())
} else {
@ -113,7 +114,7 @@ internal class OnlinePush {
if (it != sender.nameCard) {
val origin = sender._nameCard
sender._nameCard = name
MemberCardChangeEvent(origin, name, sender, sender).broadcast() // 不知道operator
MemberCardChangeEvent(origin, name, sender).broadcast()
}
},
sender = sender,
@ -562,7 +563,7 @@ internal class OnlinePush {
if (new == old) return@mapNotNull null
member._nameCard = new
return@mapNotNull MemberCardChangeEvent(old, new, member, null)
return@mapNotNull MemberCardChangeEvent(old, new, member)
}
2 -> {
if (info.value.singleOrNull()?.toInt() != 0) {

View File

@ -15,7 +15,6 @@ package net.mamoe.mirai
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.io.ByteReadChannel
import kotlinx.coroutines.launch
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult
@ -29,7 +28,6 @@ import net.mamoe.mirai.network.LoginFailedException
import net.mamoe.mirai.utils.*
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
@ -56,6 +54,7 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
/**
* 复制一份此时的 [Bot] 实例列表.
*/
@PlannedRemoval("1.2.0")
@Deprecated("use botInstances instead", replaceWith = ReplaceWith("botInstances"))
@JvmStatic
val instances: List<WeakRef<Bot>>
@ -72,7 +71,7 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
/**
* 遍历每一个 [Bot] 实例
*/
inline fun forEachInstance(block: (Bot) -> Unit) = BotImpl.forEachInstance(block)
fun forEachInstance(block: (Bot) -> Unit) = BotImpl.forEachInstance(block)
/**
* 获取一个 [Bot] 实例, 找不到则 [NoSuchElementException]
@ -89,10 +88,6 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
*/
abstract val context: Context
@PlannedRemoval("1.0.0")
@Deprecated("use id instead", replaceWith = ReplaceWith("id"))
abstract val uin: Long
/**
* QQ 号码. 实际类型为 uint
*/
@ -113,7 +108,7 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
// region contacts
/**
* [QQ.id] [Bot.uin] 相同的 [_lowLevelNewFriend] 实例
* [User.id] [Bot.id] 相同的 [_lowLevelNewFriend] 实例
*/
abstract val selfQQ: Friend
@ -201,18 +196,6 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
originalMessage: MessageChain
): OfflineMessageSource
/**
* 获取图片下载链接并开始下载.
*
* @see ByteReadChannel.copyAndClose
* @see ByteReadChannel.copyTo
*/
@PlannedRemoval("1.0.0")
@Deprecated("use your own Http clients, this is going to be removed in 1.0.0", level = DeprecationLevel.WARNING)
@MiraiExperimentalAPI
@JvmSynthetic
abstract suspend fun openChannel(image: Image): ByteReadChannel
/**
* 添加一个好友
*
@ -313,19 +296,6 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
*/
@MiraiInternalAPI
abstract val network: BotNetworkHandler
@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
@PlannedRemoval("1.0.0.")
@JvmName("getFriend")
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun getFriendDeprecated(id: Long): QQ = this.getFriend(id)
}
/**

View File

@ -46,10 +46,6 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
override val context: Context by context.unsafeWeakRef()
@Deprecated("use id instead", replaceWith = ReplaceWith("id"))
override val uin: Long
get() = this.id
final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) }
init {
@ -60,7 +56,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
@PublishedApi
internal val instances: LockFreeLinkedList<WeakRef<Bot>> = LockFreeLinkedList()
inline fun forEachInstance(block: (Bot) -> Unit) = instances.forEach {
fun forEachInstance(block: (Bot) -> Unit) = instances.forEach {
it.get()?.let(block)
}

View File

@ -11,8 +11,9 @@
package net.mamoe.mirai.contact
import net.mamoe.mirai.utils.*
import kotlin.jvm.JvmName
import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.asSequence
import kotlin.jvm.JvmField
/**
@ -20,9 +21,8 @@ import kotlin.jvm.JvmName
*
* @see ContactList.asSequence
*/
@OptIn(MiraiInternalAPI::class)
@Suppress("unused")
class ContactList<C : Contact>(@MiraiInternalAPI("Implementation may change in future release") val delegate: LockFreeLinkedList<C>) :
class ContactList<C : Contact> internal constructor(@JvmField internal val delegate: LockFreeLinkedList<C>) :
Iterable<C> {
operator fun get(id: Long): C =
delegate.asSequence().firstOrNull { it.id == id } ?: throw NoSuchElementException("Contact id $id")
@ -41,31 +41,6 @@ class ContactList<C : Contact>(@MiraiInternalAPI("Implementation may change in f
override fun iterator(): Iterator<C> {
return this.delegate.asSequence().iterator()
}
@PlannedRemoval("1.0.0")
@Suppress("PropertyName")
@get:JvmName("getIdContentString")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
val _idContentString: String
get() = this.idContentString
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
inline fun forEach(block: (C) -> Unit) = delegate.forEach(block)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun first(): C {
forEach { return it }
throw NoSuchElementException()
}
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun firstOrNull(): C? {
forEach { return it }
return null
}
}
/**
@ -76,64 +51,17 @@ class ContactList<C : Contact>(@MiraiInternalAPI("Implementation may change in f
* ```
*/
val ContactList<*>.idContentString: String
get() = "[" + @OptIn(MiraiInternalAPI::class) buildString { delegate.forEach { append(it.id).append(", ") } }.dropLast(
get() = "[" + buildString { delegate.forEach { append(it.id).append(", ") } }.dropLast(
2
) + "]"
@MiraiInternalAPI
operator fun <C : Contact> LockFreeLinkedList<C>.get(id: Long): C {
internal operator fun <C : Contact> LockFreeLinkedList<C>.get(id: Long): C {
forEach { if (it.id == id) return it }
throw NoSuchElementException("No such contact: $id")
}
@MiraiInternalAPI
fun <C : Contact> LockFreeLinkedList<C>.getOrNull(id: Long): C? {
internal fun <C : Contact> LockFreeLinkedList<C>.getOrNull(id: Long): C? {
forEach { if (it.id == id) return it }
return null
}
@OptIn(MiraiInternalAPI::class)
@PlannedRemoval("1.0.0")
@Deprecated(
"use firstOrNull from stdlib",
replaceWith = ReplaceWith("this.asSequence().firstOrNull(filter)"),
level = DeprecationLevel.ERROR
)
inline fun <C : Contact> LockFreeLinkedList<C>.firstOrNull(filter: (C) -> Boolean): C? {
forEach { if (filter(it)) return it }
return null
}
@OptIn(MiraiInternalAPI::class)
@PlannedRemoval("1.0.0")
@Deprecated(
"use firstOrNull from stdlib",
replaceWith = ReplaceWith("firstOrNull(filter)"),
level = DeprecationLevel.ERROR
)
inline fun <C : Contact> LockFreeLinkedList<C>.filteringGetOrNull(filter: (C) -> Boolean): C? =
this.asSequence().firstOrNull(filter)
@PlannedRemoval("1.0.0")
@Deprecated("use Iterator.toList from stdlib", level = DeprecationLevel.HIDDEN)
fun <E : Contact> ContactList<E>.toList(): List<E> = toMutableList()
@PlannedRemoval("1.0.0")
@Deprecated("use Iterator.toMutableList from stdlib", level = DeprecationLevel.HIDDEN)
@OptIn(MiraiInternalAPI::class)
fun <E : Contact> ContactList<E>.toMutableList(): MutableList<E> = this.delegate.toMutableList()
@PlannedRemoval("1.0.0")
@Deprecated("use Iterator.toSet from stdlib", level = DeprecationLevel.HIDDEN)
fun <E : Contact> ContactList<E>.toSet(): Set<E> = toMutableSet()
@PlannedRemoval("1.0.0")
@Deprecated("use Iterator.toMutableSet from stdlib", level = DeprecationLevel.HIDDEN)
@OptIn(MiraiInternalAPI::class)
fun <E : Contact> ContactList<E>.toMutableSet(): MutableSet<E> = this.delegate.toMutableSet()
@PlannedRemoval("1.0.0")
@Deprecated("use Iterator.asSequence from stdlib", level = DeprecationLevel.HIDDEN)
@OptIn(MiraiInternalAPI::class)
fun <E : Contact> ContactList<E>.asSequence(): Sequence<E> = this.delegate.asSequence()
}

View File

@ -30,7 +30,7 @@ import kotlin.jvm.JvmSynthetic
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
*/
@Suppress("DEPRECATION_ERROR")
abstract class Friend : QQ(), CoroutineScope {
abstract class Friend : User(), CoroutineScope {
/**
* 请求头像下载链接
*/

View File

@ -19,10 +19,8 @@ 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.PlannedRemoval
import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.WeakRefProperty
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@ -191,7 +189,7 @@ inline fun <R> Member.takeIfIsFriend(block: (Friend) -> R): R? {
/**
* 获取非空群名片或昵称.
*
* [群名片][Member.nameCard] 不为空则返回群名片, 为空则返回 [QQ.nick]
* [群名片][Member.nameCard] 不为空则返回群名片, 为空则返回 [User.nick]
*/
val Member.nameCardOrNick: String get() = this.nameCard.takeIf { it.isNotEmpty() } ?: this.nick
@ -209,16 +207,6 @@ val User.nameCardOrNick: String
else -> this.nick
}
/**
* 判断改成员是否处于禁言状态.
*/
@JvmName("isMuted2") // make compiler happy
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.InlineOnly // val Member.isMuted 编译在 JVM 也会产生 `public boolean isMuted(Member receive)`
@PlannedRemoval("1.0.0")
@Deprecated("use property instead", ReplaceWith("this.isMuted"))
inline fun Member.isMuted(): Boolean = this.isMuted
/**
* 判断群成员是否处于禁言状态.
*/

View File

@ -1,74 +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("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.utils.PlannedRemoval
import kotlin.jvm.JvmSynthetic
/**
* QQ 对象.
*
* 0.39.0 mirai 引入 [User] 作为 [Friend] [Member] 的父类,
* 以备将来支持仅 [Friend] 可用的 API, 如设置备注.
*
* 所有 API 均有二进制兼容.
*
* 请根据实际情况, 使用 [Friend] [User] 替代.
*/
@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 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<QQ>
}

View File

@ -27,4 +27,4 @@ expect abstract class ContactJavaFriendlyAPI internal constructor()
@Suppress("DEPRECATION_ERROR")
@MiraiInternalAPI
@JavaFriendlyAPI
expect abstract class MemberJavaFriendlyAPI internal constructor() : QQ // 将来会改为 User
expect abstract class MemberJavaFriendlyAPI internal constructor() : User

View File

@ -70,7 +70,7 @@ interface Event {
abstract class AbstractEvent : Event {
@Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "PropertyName")
@get:JvmSynthetic // so Java user won't see it
@Deprecated("", level = DeprecationLevel.HIDDEN)
@Deprecated("prohibit illegal overrides", level = DeprecationLevel.HIDDEN)
final override val DoNotImplementThisClassButExtendAbstractEvent: Nothing
get() = throw Error("Shouldn't be reached")

View File

@ -22,8 +22,6 @@ import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.message.GroupMessage
import net.mamoe.mirai.message.TempMessage
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.PlannedRemoval
import kotlin.js.JsName
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic
@ -440,79 +438,6 @@ open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
}
return stub
}
/**
* 不考虑空格, [消息内容][Message.contentToString] [this] 开始则执行 [replier] 并将其返回值回复给发信对象.
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他类型则 [Any.toString] 后回复
*/
@PlannedRemoval("1.0.0")
@Deprecated("use startsWith on your own", replaceWith = ReplaceWith("startsWith(this, true, true, replier)"))
open infix fun String.startsWithReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret {
val toCheck = this.trimStart()
return content({ it.trim().startsWith(toCheck) }, {
executeAndReply(this) { replier(this, it.trim().removePrefix(toCheck)) }
})
}
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun contains(message: Message, onEvent: MessageListener<M, R>): Ret {
return content({ this.message.any { it == message } }, onEvent)
}
@JvmName("case1")
@JsName("case1")
@PlannedRemoval("1.0.0")
@Deprecated("use String.invoke", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("this(block)"))
infix fun String.`->`(block: MessageListener<M, R>): Ret {
return this(block)
}
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun containsAll(
vararg sub: String,
ignoreCase: Boolean = false,
trim: Boolean = true,
onEvent: MessageListener<M, R>
): Ret = containsAllImpl(sub, ignoreCase = ignoreCase, trim = trim).invoke(onEvent)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun containsAny(
vararg sub: String,
ignoreCase: Boolean = false,
trim: Boolean = true,
onEvent: MessageListener<M, R>
): Ret = containsAnyImpl(*sub, ignoreCase = ignoreCase, trim = trim).invoke(onEvent)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun sentBy(name: String, onEvent: MessageListener<M, R>): Ret =
content({ (this as? GroupMessage)?.senderName == name }, onEvent)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun sentByOperator(onEvent: MessageListener<M, R>): Ret =
content({ this is GroupMessage && this.sender.isOperator() }, onEvent)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun sentByAdministrator(onEvent: MessageListener<M, R>): Ret =
content({ this is GroupMessage && this.sender.isAdministrator() }, onEvent)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun sentByOwner(onEvent: MessageListener<M, R>): Ret =
content({ this is GroupMessage && this.sender.isOwner() }, onEvent)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun sentFrom(groupId: Long, onEvent: MessageListener<GroupMessage, R>): Ret =
content({ this is GroupMessage && this.group.id == groupId }) { onEvent(this as GroupMessage, it) }
}
/**

View File

@ -25,7 +25,10 @@ import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.jvm.JvmField
import kotlin.jvm.JvmName
@ -148,7 +151,7 @@ sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
override val messageInternalId: Int,
override val messageTime: Int,
/**
* 撤回操作人, 可能为 [Bot.uin] 或好友的 [QQ.id]
* 撤回操作人, 可能为 [Bot.uin] 或好友的 [User.id]
*/
val operator: Long
) : MessageRecallEvent(), Packet {
@ -566,17 +569,8 @@ data class MemberCardChangeEvent(
*/
val new: String,
override val member: Member,
/**
* 此事件无法确定操作人, 将在未来版本删除
*/
@PlannedRemoval("1.0.0")
@Deprecated("operator is always unknown", level = DeprecationLevel.ERROR)
override val operator: Member?
) : GroupMemberEvent, Packet, AbstractEvent(),
@Deprecated("operator is always unknown", level = DeprecationLevel.ERROR)
GroupOperableEvent
override val member: Member
) : GroupMemberEvent, Packet, AbstractEvent()
/**
* 成员群头衔改动. 一定为群主操作
@ -660,16 +654,7 @@ data class FriendRemarkChangeEvent(
override val bot: Bot,
val friend: Friend,
val newName: String
) : BotEvent, Packet, AbstractEvent() {
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
@get:JvmSynthetic
@get:JvmName("getFriend")
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
val friendDeprecated: QQ
get() = friend
}
) : BotEvent, Packet, AbstractEvent()
/**
* 成功添加了一个新好友的事件
@ -682,14 +667,6 @@ data class FriendAddEvent(
val friend: Friend
) : BotEvent, Packet, AbstractEvent() {
override val bot: Bot get() = friend.bot
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
@get:JvmSynthetic
@get:JvmName("getFriend")
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
val friendDeprecated: QQ
get() = friend
}
/**
@ -700,14 +677,6 @@ data class FriendDeleteEvent(
val friend: Friend
) : BotEvent, Packet, AbstractEvent() {
override val bot: Bot get() = friend.bot
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
@get:JvmSynthetic
@get:JvmName("getFriend")
@Suppress("INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR")
val friendDeprecated: QQ
get() = friend
}
/**
@ -725,7 +694,7 @@ data class NewFriendRequestEvent(
*/
val message: String,
/**
* 请求人 [QQ.id]
* 请求人 [User.id]
*/
val fromId: Long,
/**

View File

@ -15,8 +15,6 @@ import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 有关一个 [Bot] 的事件
@ -90,11 +88,4 @@ interface FriendEvent : BotEvent {
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
}

View File

@ -185,9 +185,6 @@ abstract class MessageSelectBuilder<M : ContactMessage, R> @PublishedApi interna
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun Regex.findingReply(replier: suspend M.(MatchResult) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.startsWithReply(replier: suspend M.(String) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.endsWithReply(replier: suspend M.(String) -> Any?) = error("prohibited")

View File

@ -21,7 +21,6 @@ package net.mamoe.mirai.message
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.async
import kotlinx.coroutines.io.ByteReadChannel
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.*
@ -78,8 +77,9 @@ abstract class MessagePacketBase<out TSender : User, out TSubject : Contact> : P
/**
* 消息事件主体.
*
* 对于好友消息, 这个属性为 [QQ] 的实例, [sender] 引用相同;
* 对于群消息, 这个属性为 [Group] 的实例, [GroupMessage.group] 引用相同
* - 对于好友消息, 这个属性为 [Friend] 的实例, [sender] 引用相同;
* - 对于临时会话消息, 这个属性为 [Member] 的实例, [sender] 引用相同;
* - 对于群消息, 这个属性为 [Group] 的实例, [GroupMessage.group] 引用相同
*
* 在回复消息时, 可通过 [subject] 作为回复对象
*/
@ -89,7 +89,7 @@ abstract class MessagePacketBase<out TSender : User, out TSubject : Contact> : P
/**
* 发送人.
*
* 在好友消息时为 [QQ] 的实例, 在群消息时为 [Member] 的实例
* 在好友消息时为 [Friend] 的实例, 在群消息时为 [Member] 的实例
*/
@WeakRefProperty
abstract val sender: TSender
@ -178,53 +178,7 @@ abstract class MessagePacketBase<out TSender : User, out TSubject : Contact> : P
*/
suspend inline fun Image.url(): String = bot.queryImageUrl(this@url)
/**
* 获取图片下载链接并开始下载.
*
* @see ByteReadChannel.copyAndClose
* @see ByteReadChannel.copyTo
*/
@Suppress("DeprecatedCallableAddReplaceWith", "DEPRECATION")
@PlannedRemoval("1.0.0")
@Deprecated("use your own Http clients, this is going to be removed in 1.0.0", level = DeprecationLevel.WARNING)
suspend inline fun Image.channel(): ByteReadChannel = bot.openChannel(this)
// endregion
@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)
@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")
}
/**
@ -427,12 +381,4 @@ inline fun <reified M : Message> ContactMessage.nextMessageContainingOrNullAsync
.takeIf { this.message.anyIsInstance<M>() }
}?.message?.firstIsInstance<M>()
}
}
@PlannedRemoval("1.0.0")
@Suppress("DEPRECATION")
@Deprecated(level = DeprecationLevel.HIDDEN, message = "for binary compatibility")
fun MessagePacket<*, *>.isContextIdenticalWith(another: MessagePacket<*, *>): Boolean {
return (this as ContactMessage).isContextIdenticalWith(another as ContactMessage)
}
}

View File

@ -13,14 +13,11 @@ 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.currentTimeSeconds
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
@ -32,14 +29,6 @@ class FriendMessage constructor(
override val message: MessageChain,
override val time: Int
) : ContactMessage(), BroadcastControllable {
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
constructor(sender: QQ, message: MessageChain) : this(sender as Friend, message, currentTimeSeconds.toInt())
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
constructor(sender: Friend, message: MessageChain) : this(sender, message, currentTimeSeconds.toInt())
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" }

View File

@ -15,8 +15,6 @@ import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
@ -31,11 +29,6 @@ class GroupMessage(
override val message: MessageChain,
override val time: Int
) : ContactMessage(), Event {
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
constructor(senderName: String, permission: MemberPermission, sender: Member, message: MessageChain) :
this(senderName, permission, sender, message, currentTimeSeconds.toInt())
init {
val source = message.getOrNull(MessageSource) ?: error("Cannot find MessageSource from message")
check(source is OnlineMessageSource.Incoming.FromGroup) { "source provided to a GroupMessage must be an instance of OnlineMessageSource.Incoming.FromGroup" }

View File

@ -19,7 +19,6 @@ import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.recallIn
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@ -35,7 +34,7 @@ import kotlin.jvm.JvmSynthetic
* @param target 消息发送对象
*
* @see Group.sendMessage 发送群消息, 返回回执此对象
* @see QQ.sendMessage 发送群消息, 返回回执此对象
* @see User.sendMessage 发送群消息, 返回回执此对象
* @see Member.sendMessage 发送临时消息, 返回回执此对象
*
* @see MessageReceipt.sourceId id
@ -48,7 +47,7 @@ open class MessageReceipt<out C : Contact>(
*/
val source: OnlineMessageSource.Outgoing,
/**
* 发送目标, [Group] [QQ] [Member]
* 发送目标, [Group] [Friend] [Member]
*/
val target: C,
@ -89,16 +88,6 @@ open class MessageReceipt<out C : Contact>(
fun __quoteBlockingForJava__(): QuoteReply {
return this.quote()
}
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
@JavaFriendlyAPI
@JvmName("recall")
fun __recallInBlockingForJava__2(timeMillis: Long): Job {
return recallIn(timeMillis = timeMillis)
}
}
/**

View File

@ -9,7 +9,9 @@ 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.*
import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
/**
* 临时会话消息
@ -20,11 +22,6 @@ class TempMessage(
override val message: MessageChain,
override val time: Int
) : ContactMessage(), BroadcastControllable {
@PlannedRemoval("1.0.0")
@Deprecated("", level = DeprecationLevel.HIDDEN)
constructor(sender: Member, message: MessageChain) :
this(sender, message, currentTimeSeconds.toInt())
init {
val source = message.getOrNull(MessageSource) ?: error("Cannot find MessageSource from message")
check(source is OnlineMessageSource.Incoming.FromTemp) { "source provided to a TempMessage must be an instance of OnlineMessageSource.Incoming.FromTemp" }

View File

@ -17,7 +17,6 @@ package net.mamoe.mirai.message.data
import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.nameCardOrNick
import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
@ -73,15 +72,6 @@ private constructor(val target: Long, val display: String) :
return result
}
@OptIn(MiraiInternalAPI::class)
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("followedBy")
@JvmSynthetic
override fun followedBy1(tail: Message): CombinedMessage {
return followedByInternalForBinaryCompatibility(tail)
}
}
/**

View File

@ -94,6 +94,7 @@ expect interface Image : Message, MessageContent {
* @property imageId 形如 `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai` (后缀一定为 `".mirai"`)
* @see Image 查看更多说明
*/
@PlannedRemoval("1.2.0") // make internal
@Suppress("DEPRECATION_ERROR")
// CustomFace
@OptIn(MiraiInternalAPI::class)
@ -119,6 +120,7 @@ val Image.md5: ByteArray
*
* [imageId] 形如 `/f8f1ab55-bf8e-4236-b55e-955848d7069f` (37 长度) `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206` (54 长度)
*/ // NotOnlineImage
@PlannedRemoval("1.2.0") // make internal
@Suppress("DEPRECATION_ERROR")
@OptIn(MiraiInternalAPI::class)
sealed class FriendImage : AbstractImage() {
@ -157,17 +159,6 @@ val FRIEND_IMAGE_ID_REGEX_2 = Regex("""/[0-9]*-[0-9]*-[0-9a-fA-F]{32}""")
// Java: MessageUtils.GROUP_IMAGE_ID_REGEX
val GROUP_IMAGE_ID_REGEX = Regex("""\{[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\}\.mirai""")
/**
* `0.39.0` 前的图片的正则表示
*/
@Suppress("RegExpRedundantEscape") // This is required on Android
@Deprecated("Only for temporal use",
replaceWith = ReplaceWith("GROUP_IMAGE_ID_REGEX", "net.mamoe.mirai.message.data.GROUP_IMAGE_ID_REGEX"))
@SinceMirai("0.39.2")
@PlannedRemoval("1.0.0")
// Java: MessageUtils.GROUP_IMAGE_ID_REGEX_OLD
val GROUP_IMAGE_ID_REGEX_OLD = Regex("""\{[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\}\..*""")
/**
* 通过 [Image.imageId] 构造一个 [Image] 以便发送.
* 这个图片必须是服务器已经存在的图片.
@ -185,7 +176,6 @@ fun Image(imageId: String): OfflineImage = when {
imageId matches FRIEND_IMAGE_ID_REGEX_1 -> OfflineFriendImage(imageId)
imageId matches FRIEND_IMAGE_ID_REGEX_2 -> OfflineFriendImage(imageId)
imageId matches GROUP_IMAGE_ID_REGEX -> OfflineGroupImage(imageId)
imageId matches GROUP_IMAGE_ID_REGEX_OLD -> OfflineGroupImage(imageId)
else -> throw IllegalArgumentException("Illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE")
}
@ -279,7 +269,7 @@ data class OfflineGroupImage(
) : GroupImage(), OfflineImage {
init {
@Suppress("DEPRECATION")
require(imageId matches GROUP_IMAGE_ID_REGEX || imageId matches GROUP_IMAGE_ID_REGEX_OLD) {
require(imageId matches GROUP_IMAGE_ID_REGEX) {
"Illegal imageId. It must matches GROUP_IMAGE_ID_REGEX"
}
}
@ -329,18 +319,10 @@ abstract class OnlineFriendImage : FriendImage(), OnlineImage
// endregion
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@Suppress("FunctionName")
@JsName("newImage")
@JvmName("newImage")
fun Image2(imageId: String): Image = Image(imageId)
/**
* 所有 [Image] 实现的基类.
*/
@PlannedRemoval("1.2.0") // make internal
@Deprecated(
"This is internal API. Use Image instead",
level = DeprecationLevel.HIDDEN, // so that others can't see this class

View File

@ -195,76 +195,6 @@ interface Message { // must be interface. Don't consider any changes.
// `+ ""` will be resolved to `plus(String)` instead of `plus(CharSeq)`
operator fun plus(another: CharSequence): MessageChain = this.followedBy(another.toString().toMessage())
//////////////////////////////////////
// FOR BINARY COMPATIBILITY UNTIL 1.0.0
//////////////////////////////////////
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
ReplaceWith("this.contentToString() == other"),
DeprecationLevel.ERROR
)
infix fun eq(other: Message): Boolean = this.contentToString() == other.contentToString()
/**
* [contentToString] [other] 比较
*/
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
ReplaceWith("this.contentToString() == other"),
DeprecationLevel.ERROR
)
infix fun eq(other: String): Boolean = this.contentToString() == other
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
ReplaceWith("this.contentToString() == other"),
DeprecationLevel.ERROR
)
operator fun contains(sub: String): Boolean = false
@PlannedRemoval("1.0.0")
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@JvmName("followedBy")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
fun followedBy1(tail: Message): CombinedMessage = this.followedByInternalForBinaryCompatibility(tail)
@PlannedRemoval("1.0.0")
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@JvmName("plus")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
fun plus1(another: Message): CombinedMessage = this.followedByInternalForBinaryCompatibility(another)
@PlannedRemoval("1.0.0")
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@JvmName("plus")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
fun plus1(another: SingleMessage): CombinedMessage = this.followedByInternalForBinaryCompatibility(another)
@PlannedRemoval("1.0.0")
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@JvmName("plus")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
fun plus1(another: String): CombinedMessage = this.followedByInternalForBinaryCompatibility(another.toMessage())
@PlannedRemoval("1.0.0")
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@JvmName("plus")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
fun plus1(another: CharSequence): CombinedMessage =
this.followedByInternalForBinaryCompatibility(another.toString().toMessage())
}
@ -314,47 +244,19 @@ inline operator fun Message.times(count: Int): MessageChain = this.repeat(count)
@Suppress("OverridingDeprecatedMember")
interface SingleMessage : Message {
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
ReplaceWith("this.contentToString() == other"),
DeprecationLevel.ERROR
)
/* final */ override operator fun contains(sub: String): Boolean = sub in this.contentToString()
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
ReplaceWith("this.contentToString() == other"),
DeprecationLevel.ERROR
)
/* final */ override infix fun eq(other: Message): Boolean = this.contentToString() == other.contentToString()
@PlannedRemoval("1.0.0")
@JvmSynthetic
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
ReplaceWith("this.contentToString() == other"),
DeprecationLevel.ERROR
)
/* final */ override infix fun eq(other: String): Boolean = this.contentToString() == other
@PlannedRemoval("1.1.0")
@PlannedRemoval("1.2.0")
@JvmSynthetic
@SinceMirai("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun length(): Int = this.toString().length
@PlannedRemoval("1.1.0")
@PlannedRemoval("1.2.0")
@JvmSynthetic
@SinceMirai("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
fun charAt(index: Int): Char = this.toString()[index]
@PlannedRemoval("1.1.0")
@PlannedRemoval("1.2.0")
@JvmSynthetic
@SinceMirai("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)

View File

@ -15,7 +15,6 @@ package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.SinceMirai
import kotlin.js.JsName
import kotlin.jvm.JvmMultifileClass
@ -32,7 +31,7 @@ import kotlin.reflect.KProperty
* @see asMessageChain 将单个 [Message] 转换为 [MessageChain]
* @see asMessageChain [Iterable] [Sequence] 委托为 [MessageChain]
*
* @see foreachContent 遍历内容
* @see forEachContent 遍历内容
*
* @see orNull 属性委托扩展
* @see orElse 属性委托扩展
@ -40,14 +39,6 @@ import kotlin.reflect.KProperty
* @see flatten 扁平化
*/
interface MessageChain : Message, Iterable<SingleMessage> {
@PlannedRemoval("1.0.0")
@Deprecated(
"有歧义, 自行使用 contentToString() 比较",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("this.contentToString().contains(sub)")
)
/* final */ override operator fun contains(sub: String): Boolean = this.contentToString().contains(sub)
/**
* 元素数量. [EmptyMessageChain] 不参加计数.
*/
@ -96,20 +87,6 @@ interface MessageChain : Message, Iterable<SingleMessage> {
fun `__forEach for Java__`(block: (Message) -> Unit) {
this.forEach(block)
}
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
@Suppress("FunctionName", "INAPPLICABLE_JVM_NAME")
@JvmName("get")
fun <M : Message> get2(key: Message.Key<M>): M = first(key)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmSynthetic
@Suppress("FunctionName", "INAPPLICABLE_JVM_NAME")
@JvmName("getOrNull")
fun <M : Message> getOrNull2(key: Message.Key<M>): M? = getOrNull(key)
}
// region accessors
@ -128,12 +105,6 @@ inline fun MessageChain.forEachContent(block: (MessageContent) -> Unit) {
}
}
@Deprecated("typo, use forEachContent",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("forEachContent(block)"))
@JvmSynthetic
inline fun MessageChain.foreachContent(block: (MessageContent) -> Unit) = forEachContent(block)
/**
* 如果每一个 [消息内容][MessageContent] 都满足 [block], 返回 `true`
*/
@ -435,18 +406,4 @@ object EmptyMessageChain : MessageChain, Iterator<SingleMessage> {
override fun iterator(): Iterator<SingleMessage> = this
override fun hasNext(): Boolean = false
override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.")
}
/**
* Null [MessageChain].
* 它不包含任何元素, 也没有创建任何 list.
*/
@PlannedRemoval("1.0.0")
@Deprecated("ambiguous. use `null` or EmptyMessageChain instead", level = DeprecationLevel.ERROR)
object NullMessageChain : MessageChain {
override fun toString(): String = "NullMessageChain"
override fun contentToString(): String = ""
override val size: Int get() = 0
override fun equals(other: Any?): Boolean = other === this
override fun iterator(): MutableIterator<SingleMessage> = error("accessing NullMessageChain")
}
}

View File

@ -19,7 +19,10 @@ import net.mamoe.mirai.contact.*
import net.mamoe.mirai.message.ContactMessage
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.recallIn
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.LazyProperty
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.SinceMirai
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmMultifileClass
@ -279,34 +282,7 @@ sealed class OnlineMessageSource : MessageSource() {
final override val target: Group get() = group
inline val group: Group get() = sender.group
}
//////////////////////////////////
//// FOR BINARY COMPATIBILITY ////
//////////////////////////////////
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility until 1.0.0", level = DeprecationLevel.HIDDEN)
@get:JvmName("target")
@get:JvmSynthetic
final override val target2: Any
get() = target
}
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility until 1.0.0", level = DeprecationLevel.HIDDEN)
@get:JvmName("target")
@get:JvmSynthetic
open val target2: Any
get() = target
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility until 1.0.0", level = DeprecationLevel.HIDDEN)
@get:JvmName("sender")
@get:JvmSynthetic
open val sender2: Any
get() = sender
}
/**

View File

@ -29,7 +29,7 @@ data class PlainText(
val content: String
) : MessageContent {
@PlannedRemoval("1.1.0")
@PlannedRemoval("1.2.0")
@Deprecated(
"use content instead for clearer semantics",
level = DeprecationLevel.WARNING,

View File

@ -14,7 +14,6 @@
package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.SinceMirai
import kotlin.annotation.AnnotationTarget.*
import kotlin.jvm.JvmMultifileClass
@ -84,20 +83,6 @@ interface RichMessage : MessageContent {
}
}
@PlannedRemoval("1.0.0")
@JvmName("share")
@Deprecated(
"for binary compatibility", level = DeprecationLevel.HIDDEN
)
@Suppress("DEPRECATION_ERROR")
@MiraiExperimentalAPI
fun shareDeprecated(
url: String,
title: String? = null,
content: String? = null,
coverUrl: String? = null
): XmlMessage = share(url, title, content, coverUrl) as XmlMessage
override val typeName: String
get() = "RichMessage"
}
@ -154,59 +139,6 @@ open class ServiceMessage(val serviceId: Int, final override val content: String
}
/**
* Json 消息.
*
* 由于 [serviceId] 不准确, 请使用 [ServiceMessage] 并手动指定 `serviceId`
*
* @see LightApp 一些 json 消息实际上是 [LightApp]
*/
@PlannedRemoval("1.0.0")
@Deprecated("use ServiceMessage with serviceId 1",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("ServiceMessage"))
@Suppress("DEPRECATION_ERROR")
@MiraiExperimentalAPI
class JsonMessage
@Deprecated("use ServiceMessage with serviceId 1",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("ServiceMessage(1, content)"))
constructor(content: String) : ServiceMessage(1, content) {
@Suppress("DEPRECATION")
companion object Key : Message.Key<JsonMessage> {
override val typeName: String get() = "JsonMessage"
}
}
/**
* XML 消息, 如分享, 卡片等.
*
* 由于 [serviceId] 不准确, 请使用 [ServiceMessage] 并手动指定 `serviceId`
*
* @param serviceId 目前未知, 一般为 60
*
* @see buildXmlMessage 使用 DSL 构造一个 XML 消息
*/
@PlannedRemoval("1.0.0")
@Deprecated("use ServiceMessage with serviceId 1",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("ServiceMessage"))
@MiraiExperimentalAPI
@Suppress("DEPRECATION_ERROR")
@SinceMirai("0.27.0")
class XmlMessage @MiraiExperimentalAPI("Maybe replaced with an enum")
constructor(serviceId: Int = 60, content: String) : ServiceMessage(serviceId, content) {
@MiraiExperimentalAPI
@Deprecated("specify serviceId explicitly", replaceWith = ReplaceWith("XmlMessage(60, content)"))
constructor(content: String) : this(60, content)
companion object Key : Message.Key<XmlMessage> {
override val typeName: String get() = "XmlMessage"
}
}
/*
commonElem=CommonElem#750141174 {
businessType=0x00000001(1)
@ -224,7 +156,7 @@ commonElem=CommonElem#750141174 {
@SinceMirai("0.27.0")
@MiraiExperimentalAPI
inline fun buildXmlMessage(serviceId: Int, block: @XmlMessageDsl XmlMessageBuilder.() -> Unit): ServiceMessage =
XmlMessage(serviceId, XmlMessageBuilder().apply(block).text)
ServiceMessage(serviceId, XmlMessageBuilder().apply(block).text)
@MiraiExperimentalAPI
@Target(CLASS, FUNCTION, TYPE)
@ -299,14 +231,6 @@ class XmlMessageBuilder(
}
@JvmSynthetic
@SinceMirai("0.27.0")
@MiraiExperimentalAPI
@Deprecated("specify serviceId explicitly", ReplaceWith("buildXmlMessage(60, block)"))
inline fun buildXmlMessage(block: @XmlMessageDsl XmlMessageBuilder.() -> Unit): ServiceMessage =
buildXmlMessage(60, block)
@SinceMirai("0.31.0")
@MiraiExperimentalAPI
internal class LongMessage internal constructor(content: String, val resId: String) : ServiceMessage(35, content) {

View File

@ -1,43 +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:JvmName("HummerMessageKt")
@file:Suppress("NOTHING_TO_INLINE")
package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.SinceMirai
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/*
因为文件改名为做的兼容
*/
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("flash")
@SinceMirai("0.33.0")
inline fun Image.flash2(): FlashImage = FlashImage(this)
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("flash")
@JvmSynthetic
@SinceMirai("0.33.0")
inline fun GroupImage.flash2(): GroupFlashImage = FlashImage(this) as GroupFlashImage
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("flash")
@JvmSynthetic
@SinceMirai("0.33.0")
inline fun FriendImage.flash2(): FriendFlashImage = FlashImage(this) as FriendFlashImage

View File

@ -1,45 +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:JvmName("MessageKt")
@file:Suppress("NOTHING_TO_INLINE")
package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.PlannedRemoval
import kotlin.jvm.JvmName
/*
因为文件改名为做的兼容
*/
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("isPlain")
inline fun Message.isPlain2(): Boolean = this is PlainText
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("isNotPlain")
inline fun Message.isNotPlain2(): Boolean = this !is PlainText
@PlannedRemoval("1.0.0")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmName("repeat")
// inline: for future removal
inline fun Message.repeat2(count: Int): MessageChain {
if (this is ConstrainSingle<*>) {
// fast-path
return this.asMessageChain()
}
return buildMessageChain(count) {
add(this@repeat2)
}
}

View File

@ -37,13 +37,6 @@ private fun Message.hasDuplicationOfConstrain(key: Message.Key<*>): Boolean {
}
}
@OptIn(MiraiInternalAPI::class)
@JvmSynthetic
@Suppress("DEPRECATION_ERROR")
internal fun Message.followedByInternalForBinaryCompatibility(tail: Message): CombinedMessage {
return CombinedMessage(EmptyMessageChain, this.followedBy(tail))
}
@JvmSynthetic
internal fun Message.contentEqualsImpl(another: Message, ignoreCase: Boolean): Boolean {
if (!this.contentToString().equals(another.contentToString(), ignoreCase = ignoreCase)) return false
@ -220,9 +213,7 @@ internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M?
OnlineMessageSource.Incoming.FromGroup -> firstIsInstanceOrNull<OnlineMessageSource.Incoming.FromGroup>()
OnlineMessageSource.Incoming.FromFriend -> firstIsInstanceOrNull<OnlineMessageSource.Incoming.FromFriend>()
OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>()
XmlMessage -> firstIsInstanceOrNull<XmlMessage>()
LongMessage -> firstIsInstanceOrNull()
JsonMessage -> firstIsInstanceOrNull<JsonMessage>()
RichMessage -> firstIsInstanceOrNull<RichMessage>()
LightApp -> firstIsInstanceOrNull<LightApp>()
PokeMessage -> firstIsInstanceOrNull<PokeMessage>()
@ -364,7 +355,6 @@ internal fun calculateImageMd5ByImageId(imageId: String): ByteArray {
imageId matches FRIEND_IMAGE_ID_REGEX_2 -> imageId.imageIdToMd5(imageId.skipToSecondHyphen() + 1)
imageId matches FRIEND_IMAGE_ID_REGEX_1 -> imageId.imageIdToMd5(1)
imageId matches GROUP_IMAGE_ID_REGEX -> imageId.imageIdToMd5(1)
imageId matches GROUP_IMAGE_ID_REGEX_OLD -> imageId.imageIdToMd5(1)
else -> error(
"illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE"

View File

@ -22,8 +22,8 @@ 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.sendTo
import net.mamoe.mirai.message.data.toLongUnsigned
import net.mamoe.mirai.utils.internal.asReusableInput
import kotlin.jvm.JvmField
import kotlin.jvm.JvmSynthetic
/**
@ -37,43 +37,44 @@ import kotlin.jvm.JvmSynthetic
@OptIn(MiraiInternalAPI::class)
class ExternalImage internal constructor(
val md5: ByteArray,
@Suppress("EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR")
@MiraiInternalAPI("unstable API")
val input: ReusableInput, // Input from kotlinx.io, InputStream from kotlinx.io MPP, ByteReadChannel from ktor
@MiraiInternalAPI("unstable API")
val inputSize: Int // dont be greater than Int.MAX
@JvmField
internal val input: ReusableInput // Input from kotlinx.io, InputStream from kotlinx.io MPP, ByteReadChannel from ktor
) {
@SinceMirai("1.0.0")
internal interface ReusableInput {
val md5: ByteArray
val size: Long
/**
* Create a input for once usage
*/
fun input(): Input
}
constructor(
md5: ByteArray,
input: ByteReadChannel,
inputSize: Long // dont be greater than Int.MAX
) : this(md5, input.asReusableInput(), inputSize.coerceAtMost(Int.MAX_VALUE.toLongUnsigned()).toInt())
input: ByteReadChannel
) : this(md5, input.asReusableInput())
constructor(
md5: ByteArray,
input: Input,
inputSize: Long // dont be greater than Int.MAX
) : this(md5, input.asReusableInput(), inputSize.coerceAtMost(Int.MAX_VALUE.toLongUnsigned()).toInt())
input: Input
) : this(md5, input.asReusableInput())
constructor(
md5: ByteArray,
input: ByteReadPacket
) : this(md5, input.asReusableInput(), input.remaining.coerceAtMost(Int.MAX_VALUE.toLongUnsigned()).toInt())
) : this(md5, input.asReusableInput())
@OptIn(InternalSerializationApi::class)
constructor(
md5: ByteArray,
input: InputStream
) : this(md5, input.asReusableInput(), input.available())
) : this(md5, input.asReusableInput())
init {
require(inputSize < 30L * 1024 * 1024) { "file is too big. Maximum is about 20MB" }
require(input.size < 30L * 1024 * 1024) { "Image file is too big. Maximum is 30 MiB, but recommended to be 20 MiB" }
}
companion object {

View File

@ -19,14 +19,12 @@ import kotlin.jvm.JvmOverloads
/**
* Collect all the elements into a [MutableList] then cast it as a [List]
*/
@MiraiInternalAPI
fun <E> LockFreeLinkedList<E>.toList(): List<E> = toMutableList()
internal fun <E> LockFreeLinkedList<E>.toList(): List<E> = toMutableList()
/**
* Collect all the elements into a [MutableList].
*/
@MiraiInternalAPI
fun <E> LockFreeLinkedList<E>.toMutableList(): MutableList<E> {
internal fun <E> LockFreeLinkedList<E>.toMutableList(): MutableList<E> {
val list = mutableListOf<E>()
this.forEach { list.add(it) }
return list
@ -35,14 +33,12 @@ fun <E> LockFreeLinkedList<E>.toMutableList(): MutableList<E> {
/**
* Collect all the elements into a [MutableSet] then cast it as a [Set]
*/
@MiraiInternalAPI
fun <E> LockFreeLinkedList<E>.toSet(): Set<E> = toMutableSet()
internal fun <E> LockFreeLinkedList<E>.toSet(): Set<E> = toMutableSet()
/**
* Collect all the elements into a [MutableSet].
*/
@MiraiInternalAPI
fun <E> LockFreeLinkedList<E>.toMutableSet(): MutableSet<E> {
internal fun <E> LockFreeLinkedList<E>.toMutableSet(): MutableSet<E> {
val list = mutableSetOf<E>()
this.forEach { list.add(it) }
return list
@ -53,15 +49,13 @@ fun <E> LockFreeLinkedList<E>.toMutableSet(): MutableSet<E> {
*
* Note that the sequence is dynamic
*/
@MiraiInternalAPI
fun <E> LockFreeLinkedList<E>.asSequence(): Sequence<E> {
internal fun <E> LockFreeLinkedList<E>.asSequence(): Sequence<E> {
return generateSequence(head) { current: LockFreeLinkedListNode<E> ->
current.nextValidNode(until = tail).takeIf { it != tail }
}.drop(1) // drop head, should be dropped lazily
.map { it.nodeValue }
}
@OptIn(MiraiInternalAPI::class)
internal fun <E> LockFreeLinkedListNode<E>.nextValidNode(until: LockFreeLinkedListNode<E>): LockFreeLinkedListNode<E> {
var node: LockFreeLinkedListNode<E> = this.nextNode
while (node != until) {
@ -73,24 +67,21 @@ internal fun <E> LockFreeLinkedListNode<E>.nextValidNode(until: LockFreeLinkedLi
return node
}
@MiraiInternalAPI
operator fun <E> LockFreeLinkedList<E>.iterator(): Iterator<E> {
internal operator fun <E> LockFreeLinkedList<E>.iterator(): Iterator<E> {
return asSequence().iterator()
}
/**
* 构建链表结构然后转为 [LockFreeLinkedList]
*/
@MiraiInternalAPI
fun <E> Iterable<E>.toLockFreeLinkedList(): LockFreeLinkedList<E> {
internal fun <E> Iterable<E>.toLockFreeLinkedList(): LockFreeLinkedList<E> {
return LockFreeLinkedList<E>().apply { addAll(this@toLockFreeLinkedList) }
}
/**
* 构建链表结构然后转为 [LockFreeLinkedList]
*/
@MiraiInternalAPI
fun <E> Sequence<E>.toLockFreeLinkedList(): LockFreeLinkedList<E> {
internal fun <E> Sequence<E>.toLockFreeLinkedList(): LockFreeLinkedList<E> {
return LockFreeLinkedList<E>().apply { addAll(this@toLockFreeLinkedList) }
}
@ -100,9 +91,7 @@ fun <E> Sequence<E>.toLockFreeLinkedList(): LockFreeLinkedList<E> {
* Modifying can be performed concurrently.
* Iterating concurrency is guaranteed.
*/
@PlannedRemoval("1.0.0") // make internal
@MiraiInternalAPI("This is unstable API and is going to be internal in 1.0.0")
open class LockFreeLinkedList<E> {
internal open class LockFreeLinkedList<E> {
@PublishedApi
internal val tail: Tail<E> = Tail()

View File

@ -1,5 +1,11 @@
package net.mamoe.mirai
import io.ktor.utils.io.ByteReadChannel
import kotlinx.io.core.Input
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.internal.InputStream
/**
* Mirai 全局环境.
*/
@ -9,6 +15,31 @@ actual object Mirai {
set(value) {}
actual interface FileCacheStrategy {
@MiraiExperimentalAPI
actual fun newImageCache(input: Input): ExternalImage
@MiraiExperimentalAPI
actual fun newImageCache(input: ByteReadChannel): ExternalImage
@MiraiExperimentalAPI
actual fun newImageCache(input: InputStream): ExternalImage
actual companion object Default : FileCacheStrategy {
@MiraiExperimentalAPI
actual override fun newImageCache(input: Input): ExternalImage {
TODO("Not yet implemented")
}
@MiraiExperimentalAPI
actual override fun newImageCache(input: ByteReadChannel): ExternalImage {
TODO("Not yet implemented")
}
@MiraiExperimentalAPI
actual override fun newImageCache(input: InputStream): ExternalImage {
TODO("Not yet implemented")
}
}
}

View File

@ -208,7 +208,7 @@ actual abstract class ContactJavaFriendlyAPI {
@Suppress("INAPPLICABLE_JVM_NAME", "FunctionName", "unused", "unused", "DEPRECATION_ERROR")
@MiraiInternalAPI
@JavaFriendlyAPI
actual abstract class MemberJavaFriendlyAPI : QQ() {
actual abstract class MemberJavaFriendlyAPI : User() {
private inline fun <R> runBlocking(crossinline block: suspend Member.() -> R): R {
@Suppress("CAST_NEVER_SUCCEEDS")
return kotlinx.coroutines.runBlocking { block(this@MemberJavaFriendlyAPI as Member) }

View File

@ -93,51 +93,4 @@ actual abstract class MessagePacket<TSender : User, TSubject : Contact> actual c
@JvmSynthetic
suspend inline fun File.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
// endregion 发送图片 (扩展)
// region 下载图片 (扩展)
@JvmSynthetic
suspend inline fun Image.downloadTo(file: File) = file.outputStream().use { downloadTo(it) }
/**
* 下载图片到 [output] 但不关闭这个 [output]
*/
@JvmSynthetic
suspend inline fun Image.downloadTo(output: OutputStream) = channel().copyTo(output)
/**
* 下载图片到 [output] 并关闭这个 [output]
*/
@JvmSynthetic
suspend inline fun Image.downloadAndClose(output: OutputStream) = channel().copyAndClose(output)
/**
* 下载图片到 [output] 但不关闭这个 [output]
*/
@JvmSynthetic
suspend inline fun Image.downloadTo(output: Output) = channel().copyTo(output)
/**
* 下载图片到 [output] 并关闭这个 [output]
*/
@JvmSynthetic
suspend inline fun Image.downloadAndClose(output: Output) = channel().copyAndClose(output)
/**
* 下载图片到 [output] 但不关闭这个 [output]
*/
@JvmSynthetic
suspend inline fun Image.downloadTo(output: ByteWriteChannel) = channel().copyTo(output)
/**
* 下载图片到 [output] 并关闭这个 [output]
*/
@JvmSynthetic
suspend inline fun Image.downloadAndClose(output: ByteWriteChannel) = channel().copyAndClose(output)
/*
suspend inline fun Image.downloadAsStream(): InputStream = channel().asInputStream()
suspend inline fun Image.downloadAsExternalImage(): ExternalImage = withContext(Dispatchers.IO) { downloadAsStream().toExternalImage() }
suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(Dispatchers.IO) { ImageIO.read(downloadAsStream()) }
*/
// endregion
}