mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-29 01:01:19 +08:00
Make Profile data class
This commit is contained in:
parent
cc2343e220
commit
c655c0fe33
@ -65,7 +65,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
|
|||||||
|
|
||||||
val contacts = ContactSystem()
|
val contacts = ContactSystem()
|
||||||
|
|
||||||
var network: BotNetworkHandler<*> = TIMBotNetworkHandler(this)
|
var network: BotNetworkHandler<*> = TIMBotNetworkHandler(this.coroutineContext, this)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
launch {
|
launch {
|
||||||
@ -90,7 +90,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
network = TIMBotNetworkHandler(this)
|
network = TIMBotNetworkHandler(this.coroutineContext, this)
|
||||||
return network.login(configuration)
|
return network.login(configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package net.mamoe.mirai.contact
|
package net.mamoe.mirai.contact
|
||||||
|
|
||||||
import com.soywiz.klock.Date
|
import com.soywiz.klock.Date
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.message.Message
|
import net.mamoe.mirai.message.Message
|
||||||
@ -17,6 +18,7 @@ import net.mamoe.mirai.network.sessionKey
|
|||||||
import net.mamoe.mirai.qqAccount
|
import net.mamoe.mirai.qqAccount
|
||||||
import net.mamoe.mirai.sendPacket
|
import net.mamoe.mirai.sendPacket
|
||||||
import net.mamoe.mirai.utils.SuspendLazy
|
import net.mamoe.mirai.utils.SuspendLazy
|
||||||
|
import net.mamoe.mirai.utils.internal.PositiveNumbers
|
||||||
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
||||||
import net.mamoe.mirai.withSession
|
import net.mamoe.mirai.withSession
|
||||||
|
|
||||||
@ -33,7 +35,9 @@ class ContactList<C : Contact> : MutableMap<UInt, C> by mutableMapOf()
|
|||||||
sealed class Contact(val bot: Bot, val id: UInt) {
|
sealed class Contact(val bot: Bot, val id: UInt) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向这个对象发送消息. 速度太快会被服务器拒绝(无响应)
|
* 向这个对象发送消息.
|
||||||
|
*
|
||||||
|
* 速度太快会被服务器拒绝(无响应). 在测试中不延迟地发送 6 条消息就会被屏蔽之后的数据包 1 秒左右.
|
||||||
*/
|
*/
|
||||||
abstract suspend fun sendMessage(message: MessageChain)
|
abstract suspend fun sendMessage(message: MessageChain)
|
||||||
|
|
||||||
@ -65,7 +69,7 @@ fun UInt.groupId(): GroupId = GroupId(this)
|
|||||||
*
|
*
|
||||||
* 注: 在 Java 中常用 [Long] 来表示 [UInt]
|
* 注: 在 Java 中常用 [Long] 来表示 [UInt]
|
||||||
*/
|
*/
|
||||||
fun Long.groupId(): GroupId = GroupId(this.coerceAtLeastOrFail(0).toUInt())
|
fun @receiver:PositiveNumbers Long.groupId(): GroupId = GroupId(this.coerceAtLeastOrFail(0).toUInt())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一些群 API 使用的 ID. 在使用时会特别注明
|
* 一些群 API 使用的 ID. 在使用时会特别注明
|
||||||
@ -95,9 +99,7 @@ class Group internal constructor(bot: Bot, val groupId: GroupId) : Contact(bot,
|
|||||||
bot.sendPacket(SendGroupMessagePacket(bot.qqAccount, internalId, bot.sessionKey, message))
|
bot.sendPacket(SendGroupMessagePacket(bot.qqAccount, internalId, bot.sessionKey, message))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = "Group(${this.id})"
|
||||||
return "Group(${this.id})"
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
@ -111,6 +113,9 @@ inline fun <R> Contact.withSession(block: BotSession.() -> R): R = bot.withSessi
|
|||||||
/**
|
/**
|
||||||
* QQ 对象.
|
* QQ 对象.
|
||||||
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
|
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
|
||||||
|
* 它不能被直接构造. 任何时候都应从 [Bot.qq], [Bot.ContactSystem.getQQ], [BotSession.qq] 或事件中获取.
|
||||||
|
*
|
||||||
|
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
|
||||||
*
|
*
|
||||||
* A QQ instance helps you to receive event from or sendPacket event to.
|
* 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.
|
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
|
||||||
@ -118,12 +123,17 @@ inline fun <R> Contact.withSession(block: BotSession.() -> R): R = bot.withSessi
|
|||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
open class QQ internal constructor(bot: Bot, id: UInt) : Contact(bot, id) {
|
open class QQ internal constructor(bot: Bot, id: UInt) : Contact(bot, id) {
|
||||||
// TODO: 2019/11/8 should be suspend val if kotlin supports
|
private var _profile: Profile? = null
|
||||||
val profile: Deferred<Profile> by bot.network.SuspendLazy { updateProfile() }
|
private val _initialProfile by bot.network.SuspendLazy { updateProfile() }
|
||||||
|
|
||||||
override suspend fun sendMessage(message: MessageChain) {
|
/**
|
||||||
|
* 用户资料.
|
||||||
|
*/
|
||||||
|
val profile: Deferred<Profile>
|
||||||
|
get() = if (_profile == null) _initialProfile else CompletableDeferred(_profile!!)
|
||||||
|
|
||||||
|
override suspend fun sendMessage(message: MessageChain) =
|
||||||
bot.sendPacket(SendFriendMessagePacket(bot.qqAccount, id, bot.sessionKey, message))
|
bot.sendPacket(SendFriendMessagePacket(bot.qqAccount, id, bot.sessionKey, message))
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新个人资料.
|
* 更新个人资料.
|
||||||
@ -137,19 +147,13 @@ open class QQ internal constructor(bot: Bot, id: UInt) : Contact(bot, id) {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
suspend fun updateProfile(): Profile = bot.withSession {
|
suspend fun updateProfile(): Profile = bot.withSession {
|
||||||
RequestProfileDetailsPacket(bot.qqAccount, id, sessionKey)
|
_profile = RequestProfileDetailsPacket(bot.qqAccount, id, sessionKey)
|
||||||
.sendAndExpectAsync<RequestProfileDetailsResponse, Profile> { it.profile }
|
.sendAndExpect<RequestProfileDetailsResponse, Profile> { it.profile }
|
||||||
.await().let {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
return _profile!!
|
||||||
if ((::profile as SuspendLazy<Profile>).isInitialized()) {
|
|
||||||
profile.await().apply { copyFrom(it) }
|
|
||||||
} else it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = "QQ(${this.id})"
|
||||||
return "QQ(${this.id})"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -161,9 +165,7 @@ class Member internal constructor(bot: Bot, id: UInt, val group: Group) : QQ(bot
|
|||||||
TODO("Group member implementation")
|
TODO("Group member implementation")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = "Member(${this.id})"
|
||||||
return "Member(${this.id})"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,61 +189,20 @@ enum class MemberPermission {
|
|||||||
/**
|
/**
|
||||||
* 个人资料
|
* 个人资料
|
||||||
*/
|
*/
|
||||||
// FIXME: 2019/11/8 should be `data class Profile`
|
|
||||||
@Suppress("PropertyName")
|
@Suppress("PropertyName")
|
||||||
class Profile(
|
data class Profile(
|
||||||
internal var _qq: UInt,
|
val qq: UInt,
|
||||||
internal var _nickname: String,
|
val nickname: String,
|
||||||
internal var _zipCode: String?,
|
val zipCode: String?,
|
||||||
internal var _phone: String?,
|
val phone: String?,
|
||||||
internal var _gender: Gender,
|
val gender: Gender,
|
||||||
internal var _birthday: Date?,
|
val birthday: Date?,
|
||||||
internal var _personalStatus: String?,
|
val personalStatus: String?,
|
||||||
internal var _school: String?,
|
val school: String?,
|
||||||
internal var _homepage: String?,
|
val homepage: String?,
|
||||||
internal var _email: String?,
|
val email: String?,
|
||||||
internal var _company: String?
|
val company: String?
|
||||||
) {
|
)
|
||||||
|
|
||||||
val qq: UInt get() = _qq
|
|
||||||
val nickname: String get() = _nickname
|
|
||||||
val zipCode: String? get() = _zipCode
|
|
||||||
val phone: String? get() = _phone
|
|
||||||
val gender: Gender get() = _gender
|
|
||||||
/**
|
|
||||||
* 个性签名
|
|
||||||
*/
|
|
||||||
val personalStatus: String? get() = _personalStatus
|
|
||||||
val school: String? get() = _school
|
|
||||||
val company: String? get() = _company
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 主页
|
|
||||||
*/
|
|
||||||
val homepage: String? get() = _homepage
|
|
||||||
val email: String? get() = _email
|
|
||||||
val birthday: Date? get() = _birthday
|
|
||||||
|
|
||||||
override fun toString(): String = "Profile(" +
|
|
||||||
"qq=$qq, nickname=$nickname, zipCode=$zipCode, phone=$phone, " +
|
|
||||||
"gender=$gender, birthday=$birthday, personalStatus=$personalStatus, school=$school, " +
|
|
||||||
"homepage=$homepage, email=$email, company=$company" +
|
|
||||||
")"
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Profile.copyFrom(another: Profile) {
|
|
||||||
this._qq = another.qq
|
|
||||||
this._nickname = another.nickname
|
|
||||||
this._zipCode = another.zipCode
|
|
||||||
this._phone = another.phone
|
|
||||||
this._gender = another.gender
|
|
||||||
this._birthday = another.birthday
|
|
||||||
this._personalStatus = another.personalStatus
|
|
||||||
this._school = another.school
|
|
||||||
this._homepage = another.homepage
|
|
||||||
this._email = another.email
|
|
||||||
this._company = another.company
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 性别
|
* 性别
|
||||||
|
@ -8,10 +8,16 @@ enum class MessageType(val value: UByte) {
|
|||||||
PLAIN_TEXT(0x01u),
|
PLAIN_TEXT(0x01u),
|
||||||
AT(0x06u),
|
AT(0x06u),
|
||||||
FACE(0x02u),
|
FACE(0x02u),
|
||||||
GROUP_IMAGE(0x03u),
|
/**
|
||||||
FRIEND_IMAGE(0x06u),
|
* [ImageId.value] 长度为 42 的图片
|
||||||
|
*/
|
||||||
|
IMAGE_42(0x03u),
|
||||||
|
/**
|
||||||
|
* [ImageId.value] 长度为 37 的图片
|
||||||
|
*/
|
||||||
|
IMAGE_37(0x06u),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
val intValue: Int = this.value.toInt()
|
inline val intValue: Int get() = this.value.toInt()
|
||||||
}
|
}
|
@ -145,7 +145,7 @@ fun ByteReadPacket.readMessageChain(): MessageChain {
|
|||||||
return chain
|
return chain
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MessageChain.toPacket(forGroup: Boolean): ByteReadPacket = buildPacket {
|
fun MessageChain.toPacket(): ByteReadPacket = buildPacket {
|
||||||
this@toPacket.forEach { message ->
|
this@toPacket.forEach { message ->
|
||||||
writePacket(with(message) {
|
writePacket(with(message) {
|
||||||
when (this) {
|
when (this) {
|
||||||
@ -170,7 +170,7 @@ fun MessageChain.toPacket(forGroup: Boolean): ByteReadPacket = buildPacket {
|
|||||||
when (id.value.length) {
|
when (id.value.length) {
|
||||||
// "{F61593B5-5B98-1798-3F47-2A91D32ED2FC}.jpg"
|
// "{F61593B5-5B98-1798-3F47-2A91D32ED2FC}.jpg"
|
||||||
42 -> {
|
42 -> {
|
||||||
writeUByte(MessageType.GROUP_IMAGE.value)
|
writeUByte(MessageType.IMAGE_42.value)
|
||||||
|
|
||||||
//00 00 03 00 CB 02 00 2A 7B 46 36 31 35 39 33 42 35 2D 35 42 39 38 2D 31 37 39 38 2D 33 46 34 37 2D 32 41 39 31 44 33 32 45 44 32 46 43 7D 2E 6A 70 67
|
//00 00 03 00 CB 02 00 2A 7B 46 36 31 35 39 33 42 35 2D 35 42 39 38 2D 31 37 39 38 2D 33 46 34 37 2D 32 41 39 31 44 33 32 45 44 32 46 43 7D 2E 6A 70 67
|
||||||
// 04 00 04 87 E5 09 3B 05 00 04 D2 C4 C0 B7 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 01 ED 16 00 04 00 00 02 17 18 00 04 00 00 EB 34 FF 00 5C 15 36 20 39 32 6B 41 31 43 38 37 65 35 30 39 33 62 64 32 63 34 63 30 62 37 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
|
// 04 00 04 87 E5 09 3B 05 00 04 D2 C4 C0 B7 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 01 ED 16 00 04 00 00 02 17 18 00 04 00 00 EB 34 FF 00 5C 15 36 20 39 32 6B 41 31 43 38 37 65 35 30 39 33 62 64 32 63 34 63 30 62 37 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
|
||||||
@ -191,7 +191,7 @@ fun MessageChain.toPacket(forGroup: Boolean): ByteReadPacket = buildPacket {
|
|||||||
|
|
||||||
// "/01ee6426-5ff1-4cf0-8278-e8634d2909ef"
|
// "/01ee6426-5ff1-4cf0-8278-e8634d2909ef"
|
||||||
37 -> {
|
37 -> {
|
||||||
writeUByte(MessageType.FRIEND_IMAGE.value)
|
writeUByte(MessageType.IMAGE_37.value)
|
||||||
|
|
||||||
// 00 00 06 00 F3 02
|
// 00 00 06 00 F3 02
|
||||||
// 00 1B 24 5B 56 54 4A 38 60 4C 5A 4E 46 7D 53 39 4F 52 36 25 45 60 42 55 53 2E 6A 70 67
|
// 00 1B 24 5B 56 54 4A 38 60 4C 5A 4E 46 7D 53 39 4F 52 36 25 45 60 42 55 53 2E 6A 70 67
|
||||||
|
@ -25,7 +25,6 @@ import net.mamoe.mirai.utils.getGTK
|
|||||||
import net.mamoe.mirai.utils.internal.PositiveNumbers
|
import net.mamoe.mirai.utils.internal.PositiveNumbers
|
||||||
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
||||||
import kotlin.coroutines.coroutineContext
|
import kotlin.coroutines.coroutineContext
|
||||||
import kotlin.jvm.JvmField
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造 [BotSession] 的捷径
|
* 构造 [BotSession] 的捷径
|
||||||
@ -60,7 +59,6 @@ class BotSession(
|
|||||||
*/
|
*/
|
||||||
val sKey: String get() = _sKey
|
val sKey: String get() = _sKey
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Suppress("PropertyName")
|
@Suppress("PropertyName")
|
||||||
internal var _sKey: String = ""
|
internal var _sKey: String = ""
|
||||||
set(value) {
|
set(value) {
|
||||||
@ -73,7 +71,6 @@ class BotSession(
|
|||||||
*/
|
*/
|
||||||
val gtk: Int get() = _gtk
|
val gtk: Int get() = _gtk
|
||||||
|
|
||||||
@JvmField
|
|
||||||
private var _gtk: Int = 0
|
private var _gtk: Int = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,6 +136,9 @@ class BotSession(
|
|||||||
* ```
|
* ```
|
||||||
* @sample Bot.addFriend 添加好友
|
* @sample Bot.addFriend 添加好友
|
||||||
*/
|
*/
|
||||||
|
suspend inline fun <reified P : Packet, R> OutgoingPacket.sendAndExpect(checkSequence: Boolean = true, crossinline block: (P) -> R): R =
|
||||||
|
sendAndExpectAsync<P, R>(checkSequence) { block(it) }.await()
|
||||||
|
|
||||||
suspend inline fun <reified P : Packet> OutgoingPacket.sendAndExpect(checkSequence: Boolean = true): P =
|
suspend inline fun <reified P : Packet> OutgoingPacket.sendAndExpect(checkSequence: Boolean = true): P =
|
||||||
sendAndExpectAsync<P, P>(checkSequence) { it }.await()
|
sendAndExpectAsync<P, P>(checkSequence) { it }.await()
|
||||||
|
|
||||||
|
@ -38,11 +38,11 @@ internal expect val NetworkDispatcher: CoroutineDispatcher
|
|||||||
*
|
*
|
||||||
* @see BotNetworkHandler
|
* @see BotNetworkHandler
|
||||||
*/
|
*/
|
||||||
internal class TIMBotNetworkHandler internal constructor(override inline val bot: Bot) :
|
internal class TIMBotNetworkHandler internal constructor(coroutineContext: CoroutineContext, override inline val bot: Bot) :
|
||||||
BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() {
|
BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() {
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext =
|
override val coroutineContext: CoroutineContext =
|
||||||
NetworkDispatcher + CoroutineExceptionHandler { _, e ->
|
coroutineContext + NetworkDispatcher + CoroutineExceptionHandler { _, e ->
|
||||||
bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e)
|
bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e)
|
||||||
} + SupervisorJob()
|
} + SupervisorJob()
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class TemporaryPacketHandler<P : Packet, R>(
|
|||||||
private val fromSession: BotSession,
|
private val fromSession: BotSession,
|
||||||
private val checkSequence: Boolean,
|
private val checkSequence: Boolean,
|
||||||
/**
|
/**
|
||||||
* 调用者的 [CoroutineContext]
|
* 调用者的 [CoroutineContext]. 包处理过程将会在这个 context 下运行
|
||||||
*/
|
*/
|
||||||
private val callerContext: CoroutineContext
|
private val callerContext: CoroutineContext
|
||||||
) {
|
) {
|
||||||
|
@ -61,23 +61,23 @@ object RequestProfileDetailsPacket : SessionPacketFactory<RequestProfileDetailsR
|
|||||||
discardExact(6)
|
discardExact(6)
|
||||||
val map = readTLVMap(tagSize = 2, expectingEOF = true)
|
val map = readTLVMap(tagSize = 2, expectingEOF = true)
|
||||||
val profile = Profile(
|
val profile = Profile(
|
||||||
_qq = qq,
|
qq = qq,
|
||||||
_nickname = map[0x4E22u]?.stringOfWitch() ?: "",//error("Cannot determine nickname")
|
nickname = map[0x4E22u]?.stringOfWitch() ?: "",//error("Cannot determine nickname")
|
||||||
_zipCode = map[0x4E25u]?.stringOfWitch(),
|
zipCode = map[0x4E25u]?.stringOfWitch(),
|
||||||
_phone = map[0x4E27u]?.stringOfWitch(),
|
phone = map[0x4E27u]?.stringOfWitch(),
|
||||||
_gender = when (map[0x4E29u]?.let { it[0] }?.toUInt()) {
|
gender = when (map[0x4E29u]?.let { it[0] }?.toUInt()) {
|
||||||
null -> Gender.SECRET //error("Cannot determine gender, entry 0x4E29u not found")
|
null -> Gender.SECRET //error("Cannot determine gender, entry 0x4E29u not found")
|
||||||
0x02u -> Gender.FEMALE
|
0x02u -> Gender.FEMALE
|
||||||
0x01u -> Gender.MALE
|
0x01u -> Gender.MALE
|
||||||
else -> Gender.SECRET // 猜的
|
else -> Gender.SECRET // 猜的
|
||||||
//else -> error("Cannot determine gender, bad value of 0x4E29u: ${map[0x4729u]!![0].toUHexString()}")
|
//else -> error("Cannot determine gender, bad value of 0x4E29u: ${map[0x4729u]!![0].toUHexString()}")
|
||||||
},
|
},
|
||||||
_birthday = map[0x4E3Fu]?.let { Date(it.toUInt().toInt()) },
|
birthday = map[0x4E3Fu]?.let { Date(it.toUInt().toInt()) },
|
||||||
_personalStatus = map[0x4E33u]?.stringOfWitch(),
|
personalStatus = map[0x4E33u]?.stringOfWitch(),
|
||||||
_homepage = map[0x4E2Du]?.stringOfWitch(),
|
homepage = map[0x4E2Du]?.stringOfWitch(),
|
||||||
_company = map[0x5DC8u]?.stringOfWitch(),
|
company = map[0x5DC8u]?.stringOfWitch(),
|
||||||
_school = map[0x4E35u]?.stringOfWitch(),
|
school = map[0x4E35u]?.stringOfWitch(),
|
||||||
_email = map[0x4E2Bu]?.stringOfWitch()
|
email = map[0x4E2Bu]?.stringOfWitch()
|
||||||
)
|
)
|
||||||
map.clear()
|
map.clear()
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ object SendFriendMessagePacket : SessionPacketFactory<SendFriendMessagePacket.Re
|
|||||||
writeHex(TIMProtocol.messageConstNewest)
|
writeHex(TIMProtocol.messageConstNewest)
|
||||||
writeZero(2)
|
writeZero(2)
|
||||||
|
|
||||||
writePacket(message.toPacket(false))
|
writePacket(message.toPacket())
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//Plain text
|
//Plain text
|
||||||
|
@ -35,7 +35,7 @@ object SendGroupMessagePacket : SessionPacketFactory<SendGroupMessagePacket.Resp
|
|||||||
writeHex(TIMProtocol.messageConst1)
|
writeHex(TIMProtocol.messageConst1)
|
||||||
writeZero(2)
|
writeZero(2)
|
||||||
|
|
||||||
writePacket(message.toPacket(true))
|
writePacket(message.toPacket())
|
||||||
}
|
}
|
||||||
/*it.writeByte(0x01)
|
/*it.writeByte(0x01)
|
||||||
it.writeShort(bytes.size + 3)
|
it.writeShort(bytes.size + 3)
|
||||||
|
@ -27,7 +27,7 @@ fun <R> CoroutineScope.SuspendLazy(initializer: suspend () -> R): Lazy<Deferred<
|
|||||||
* @sample QQ.profile
|
* @sample QQ.profile
|
||||||
*/
|
*/
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal class SuspendLazy<R>(scope: CoroutineScope, val initializer: suspend () -> R) : Lazy<Deferred<R>> {
|
internal class SuspendLazy<R>(scope: CoroutineScope, initializer: suspend () -> R) : Lazy<Deferred<R>> {
|
||||||
private val valueUpdater: Deferred<R> by lazy { scope.async { initializer() } }
|
private val valueUpdater: Deferred<R> by lazy { scope.async { initializer() } }
|
||||||
|
|
||||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
|
@ -1,30 +1,39 @@
|
|||||||
package net.mamoe.mirai.utils.internal
|
package net.mamoe.mirai.utils.internal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要求 [this] 最小为 [min].
|
||||||
|
*/
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun Int.coerceAtLeastOrFail(value: Int): Int {
|
internal fun Int.coerceAtLeastOrFail(min: Int): Int {
|
||||||
require(this > value)
|
require(this >= min)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要求 [this] 最小为 [min].
|
||||||
|
*/
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun Long.coerceAtLeastOrFail(value: Long): Long {
|
internal fun Long.coerceAtLeastOrFail(min: Long): Long {
|
||||||
require(this > value)
|
require(this >= min)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要求 [this] 最大为 [max].
|
||||||
|
*/
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun Int.coerceAtMostOrFail(maximumValue: Int): Int =
|
internal fun Int.coerceAtMostOrFail(max: Int): Int =
|
||||||
if (this > maximumValue) error("value is greater than its expected maximum value $maximumValue")
|
if (this >= max) error("value is greater than its expected maximum value $max")
|
||||||
else this
|
else this
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun Long.coerceAtMostOrFail(maximumValue: Long): Long =
|
internal fun Long.coerceAtMostOrFail(max: Long): Long =
|
||||||
if (this > maximumValue) error("value is greater than its expected maximum value $maximumValue")
|
if (this >= max) error("value is greater than its expected maximum value $max")
|
||||||
else this
|
else this
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示这个参数必须为正数
|
* 表示这个参数必须为正数. 仅用于警示
|
||||||
*/
|
*/
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
|
||||||
internal annotation class PositiveNumbers
|
internal annotation class PositiveNumbers
|
Loading…
Reference in New Issue
Block a user