Add contracts

This commit is contained in:
Him188 2019-11-16 13:27:29 +08:00
parent 2697ac8fdb
commit a9a0e62130
4 changed files with 78 additions and 21 deletions

View File

@ -19,6 +19,9 @@ import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.DefaultLogger
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmOverloads
@ -228,7 +231,13 @@ Mirai 22:04:48 : Packet received: UnknownEventPacket(id=00 D6, identity=(2092749
* @param lazyMessage 若需要验证请求时的验证消息.
* @param lazyRemark 好友备注
*/
suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }, lazyRemark: () -> String = { "" }): AddFriendResult = bot.withSession {
@UseExperimental(ExperimentalContracts::class)
suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }, lazyRemark: () -> String = { "" }): AddFriendResult {
contract {
callsInPlace(lazyMessage, InvocationKind.AT_MOST_ONCE)
callsInPlace(lazyRemark, InvocationKind.AT_MOST_ONCE)
}
return bot.withSession {
when (CanAddFriendPacket(bot.qqAccount, id, bot.sessionKey).sendAndExpect<CanAddFriendResponse>()) {
is CanAddFriendResponse.AlreadyAdded -> AddFriendResult.ALREADY_ADDED
is CanAddFriendResponse.Rejected -> AddFriendResult.REJECTED
@ -253,6 +262,7 @@ suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }
}*/
}
}
}
/*
1494695429 同意好友请求后收到以下包:

View File

@ -7,10 +7,14 @@ import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.BotSession
import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import net.mamoe.mirai.network.protocol.tim.packet.login.requireSuccess
import net.mamoe.mirai.network.session
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.internal.PositiveNumbers
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmOverloads
/*
@ -43,7 +47,13 @@ inline val Bot.qqs: ContactList<QQ>
* [BotSession] 作为接收器 (receiver) 并调用 [block], 返回 [block] 的返回值.
* 这个方法将能帮助使用在 [BotSession] 中定义的一些扩展方法, [BotSession.sendAndExpectAsync]
*/
inline fun <R> Bot.withSession(block: BotSession.() -> R): R = with(this.network.session) { block() }
@UseExperimental(ExperimentalContracts::class)
inline fun <R> Bot.withSession(block: BotSession.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return with(this.network.session) { block() }
}
/**
* 发送数据包
@ -54,18 +64,43 @@ suspend inline fun Bot.sendPacket(packet: OutgoingPacket) = this.network.sendPac
/**
* 使用在默认配置基础上修改的配置进行登录
*/
suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit): LoginResult = this.network.login(BotConfiguration().apply(configuration))
@UseExperimental(ExperimentalContracts::class)
suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit): LoginResult {
contract {
callsInPlace(configuration, InvocationKind.EXACTLY_ONCE)
}
return this.network.login(BotConfiguration().apply(configuration))
}
/**
* 使用默认的配置 ([BotConfiguration.Default]) 登录
*/
suspend inline fun Bot.login(): LoginResult = this.network.login(BotConfiguration.Default)
/**
* 使用默认的配置 ([BotConfiguration.Default]) 登录
*/
@UseExperimental(ExperimentalContracts::class)
suspend inline fun Bot.alsoLogin(lazyMessageWhenLoginFailed: (LoginResult) -> String): Bot {
contract {
callsInPlace(lazyMessageWhenLoginFailed, InvocationKind.AT_MOST_ONCE)
}
return this.apply {
login().requireSuccess(lazyMessageWhenLoginFailed)
}
}
/**
* 添加好友
*/
@UseExperimental(ExperimentalContracts::class)
@JvmOverloads
suspend inline fun Bot.addFriend(id: UInt, noinline lazyMessage: () -> String = { "" }): AddFriendResult = this.contacts.addFriend(id, lazyMessage)
suspend inline fun Bot.addFriend(id: UInt, noinline lazyMessage: () -> String = { "" }, noinline lazyRemark: () -> String = { "" }): AddFriendResult {
contract {
callsInPlace(lazyMessage, InvocationKind.AT_MOST_ONCE)
}
return this.contacts.addFriend(id, lazyMessage, lazyRemark)
}
/**
* 取得机器人的 QQ

View File

@ -1,6 +1,9 @@
package net.mamoe.mirai.network.protocol.tim.packet.login
import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult.SUCCESS
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
/**
* 登录结果. [SUCCESS] 外均为失败.
@ -56,7 +59,11 @@ enum class LoginResult {
/**
* 如果 [this] 不为 [LoginResult.SUCCESS] 就抛出消息为 [lazyMessage] [IllegalStateException]
*/
fun LoginResult.requireSuccess(lazyMessage: (LoginResult) -> String) {
@UseExperimental(ExperimentalContracts::class)
inline fun LoginResult.requireSuccess(lazyMessage: (LoginResult) -> String) {
contract {
callsInPlace(lazyMessage, InvocationKind.AT_MOST_ONCE)
}
if (this != SUCCESS) error(lazyMessage(this))
}
@ -86,5 +93,10 @@ fun LoginResult.requireSuccessOrNull(): Unit? =
*
* @return 成功时 [Unit], 失败时 `null`
*/
inline fun <R> LoginResult.ifFail(block: (LoginResult) -> R): R? =
if (this != SUCCESS) block(this) else null
@UseExperimental(ExperimentalContracts::class)
inline fun <R> LoginResult.ifFail(block: (LoginResult) -> R): R? {
contract {
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
return if (this != SUCCESS) block(this) else null
}

View File

@ -16,7 +16,7 @@ fun <R> CoroutineScope.SuspendLazy(initializer: suspend () -> R): Lazy<Deferred<
/**
* 挂起初始化的 [lazy], 是属性不能 `suspend` 的替代品.
*
* 本对象代表值初始化时将会通过 [CoroutineScope.async] 运行 [initializer]
* 本对象代表值初始化时将会通过 [CoroutineScope.async] 运行 [valueUpdater]
*
* [SuspendLazy] :
* - 线程安全