Skip to content

Commit f3562c9

Browse files
committed
support blocking InteractiveConversation (untested)
1 parent af7e699 commit f3562c9

2 files changed

Lines changed: 42 additions & 27 deletions

File tree

src/main/kotlin/stageguard/sctimetable/service/BotEventRouteService.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import stageguard.sctimetable.database.model.User
2424
import stageguard.sctimetable.database.model.Users
2525
import java.lang.management.ManagementFactory
2626
import com.sun.management.OperatingSystemMXBean
27-
import net.mamoe.mirai.console.command.CommandExecuteResult
2827
import net.mamoe.mirai.event.events.*
2928
import net.mamoe.mirai.message.data.*
3029
import net.mamoe.mirai.utils.MiraiExperimentalApi
@@ -67,7 +66,7 @@ object BotEventRouteService : AbstractPluginManagedService() {
6766
subject.sendMessage("太长时间未输入,请重新登录")
6867
} }
6968
}
70-
startsWith("修改时间表") { Database.query {
69+
startsWith("修改时间表") { Database.suspendQuery {
7170
val thisUser = User.find { Users.qq eq subject.id }
7271
val schoolTimetable = SchoolTimetable.find { SchoolTimetables.schoolId eq thisUser.first().schoolId }.first()
7372
interactiveConversation(this@BotEventRouteService, eachTimeLimit = 30000L, eachTryLimit = 5) {
@@ -142,7 +141,7 @@ object BotEventRouteService : AbstractPluginManagedService() {
142141
})
143142
} else subject.sendMessage("你还没有登录超级课表,无法查看今天课程")
144143
} }
145-
startsWith("删除账户") {
144+
finding(Regex("^删除(用户|账户|账号)")) {
146145
interactiveConversation(this@BotEventRouteService, eachTimeLimit = 10000L) {
147146
send("确认要删除你的所有信息吗,包括用户信息,你的课程信息?\n删除后将不再为你发送课程提醒。\n发送\"确认\"以删除。")
148147
select {

src/main/kotlin/stageguard/sctimetable/utils/InteractiveConversationHelper.kt

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import kotlin.contracts.contract
3636
*/
3737
class InteractiveConversationBuilder(
3838
private val eventContext: MessageEvent,
39-
private val coroutineScope: CoroutineScope,
39+
private val coroutineScope: CoroutineScope?,
4040
private val timeoutLimitation: Long,
4141
private val tryCountLimitation: Int
4242
) {
@@ -244,6 +244,7 @@ sealed class QuitConversationExceptions : Exception() {
244244
class TimeoutException : QuitConversationExceptions()
245245
}
246246

247+
typealias EIQ = Either<InteractiveConversationBuilder, QuitConversationExceptions>
247248
/**
248249
* 交互式对话的创建器
249250
*
@@ -257,8 +258,7 @@ sealed class QuitConversationExceptions : Exception() {
257258
*
258259
* ```
259260
*
260-
* @param scope 协程作用域,默认为全局作用域 [GlobalScope]。
261-
* 建议制定为*插件作用域*或自定义协程作用域。
261+
* @param scope 协程作用域,默认为 `null` 即阻塞当前协程。
262262
* @param eachTimeLimit 每一次捕获消息的最大等待时间,默认为 `-1L` 即无限等待。
263263
* 若超过了这个时间未捕获到适合的消息,则在 [exception] 中抛出 [QuitConversationExceptions.IllegalInputException]。
264264
* @param eachTryLimit 每一次捕获消息时允许尝试的最大次数。
@@ -271,29 +271,29 @@ sealed class QuitConversationExceptions : Exception() {
271271
* @see finish
272272
* @see exception
273273
*/
274-
inline fun <T : MessageEvent> T.interactiveConversation(
275-
scope: CoroutineScope = GlobalScope,
274+
suspend fun <T : MessageEvent> T.interactiveConversation(
275+
scope: CoroutineScope? = null,
276276
eachTimeLimit: Long = -1L,
277277
eachTryLimit: Int = -1,
278-
crossinline block: suspend InteractiveConversationBuilder.() -> Unit
279-
): Pair<CoroutineScope, Deferred<Either<InteractiveConversationBuilder, QuitConversationExceptions>>> = scope to scope.async (
280-
scope.coroutineContext
281-
) {
282-
try {
278+
block: suspend InteractiveConversationBuilder.() -> Unit
279+
): Pair<CoroutineScope?, Either<EIQ, Deferred<EIQ>>> {
280+
suspend fun executeICB() = try {
283281
InteractiveConversationBuilder(
284282
eventContext = this@interactiveConversation,
285283
coroutineScope = scope,
286284
tryCountLimitation = eachTryLimit,
287285
timeoutLimitation = eachTimeLimit
288286
).also { block(it) }.let { Either.Left(it) }
289-
} catch (ex: Exception) {
290-
when(ex) {
291-
is TimeoutCancellationException -> Either.Right(QuitConversationExceptions.TimeoutException())
292-
else -> Either.Right(ex as QuitConversationExceptions)
293-
}
287+
} catch (ex: Exception) { when(ex) {
288+
is TimeoutCancellationException -> Either.Right(QuitConversationExceptions.TimeoutException())
289+
else -> Either.Right(ex as QuitConversationExceptions)
290+
} }
291+
return if(scope == null) {
292+
null to Either.Left(executeICB())
293+
} else {
294+
scope to Either.Right(scope.async(scope.coroutineContext) { executeICB() })
294295
}
295296
}
296-
297297
/**
298298
* 会话非正常退出时调用这个函数
299299
* 处理方式:
@@ -306,11 +306,19 @@ inline fun <T : MessageEvent> T.interactiveConversation(
306306
* ```
307307
* 不必为 `when` 添加 `else` 分支,因为 [QuitConversationExceptions] 是一个 `sealed class`
308308
*/
309-
fun Pair<CoroutineScope, Deferred<Either<InteractiveConversationBuilder, QuitConversationExceptions>>>.exception(
309+
suspend fun Pair<CoroutineScope?, Either<EIQ, Deferred<EIQ>>>.exception(
310310
failed: suspend (QuitConversationExceptions) -> Unit = { }
311-
) : Pair<CoroutineScope, Deferred<Either<InteractiveConversationBuilder, QuitConversationExceptions>>> {
312-
first.launch(first.coroutineContext) {
313-
when(val icBuilder = this@exception.second.await()) { is Either.Right -> failed(icBuilder.value) }
311+
) : Pair<CoroutineScope?, Either<EIQ, Deferred<EIQ>>> {
312+
if(first != null) {
313+
first!!.launch(first!!.coroutineContext) {
314+
when(val icBuilder = (second as Either.Right).value.await()) {
315+
is Either.Right -> failed(icBuilder.value)
316+
}
317+
}
318+
} else {
319+
when(val icBuilder = (second as Either.Left).value) {
320+
is Either.Right -> failed(icBuilder.value)
321+
}
314322
}
315323
return this
316324
}
@@ -348,11 +356,19 @@ fun Pair<CoroutineScope, Deferred<Either<InteractiveConversationBuilder, QuitCon
348356
* 注意:[cast] 会忽略 `Map` 中的 `null` 检查!
349357
*
350358
*/
351-
fun Pair<CoroutineScope, Deferred<Either<InteractiveConversationBuilder, QuitConversationExceptions>>>.finish(
359+
suspend fun Pair<CoroutineScope?, Either<EIQ, Deferred<EIQ>>>.finish(
352360
success: suspend (Map<String, Any>) -> Unit = { }
353-
) : Pair<CoroutineScope, Deferred<Either<InteractiveConversationBuilder, QuitConversationExceptions>>> {
354-
first.launch(first.coroutineContext) {
355-
when(val icBuilder = this@finish.second.await()) { is Either.Left -> success(icBuilder.value.capturedList.toMap()) }
361+
) : Pair<CoroutineScope?, Either<EIQ, Deferred<EIQ>>> {
362+
if(first != null) {
363+
first!!.launch(first!!.coroutineContext) {
364+
when(val icBuilder = (second as Either.Right).value.await()) {
365+
is Either.Left -> success(icBuilder.value.capturedList)
366+
}
367+
}
368+
} else {
369+
when(val icBuilder = (second as Either.Left).value) {
370+
is Either.Left -> success(icBuilder.value.capturedList)
371+
}
356372
}
357373
return this
358374
}

0 commit comments

Comments
 (0)