diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e365cd46c..70e881e1f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,9 +9,15 @@ jobs: steps: - uses: actions/checkout@v1 - - name: setup-android - uses: msfjarvis/setup-android@0.2 + - name: Setup Java JDK + uses: actions/setup-java@v1.3.0 with: - # Gradle tasks to run - If you want to run ./gradlew assemble, specify assemble here. - gradleTasks: build -x mirai-core:jvmTest - + # The Java version to make available on the path. Takes a whole or semver Java version, or 1.x syntax (e.g. 1.8 => Java 8.x) + java-version: 11 + # The package type (jre, jdk, jdk+fx) + java-package: jdk+fx + - name: Gradle Command + uses: eskatos/gradle-command-action@v1 + with: + # Gradle command line arguments, see gradle --help + arguments: build -x mirai-core:jvmTest diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index 5671f2088..6670eed35 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -43,7 +43,7 @@ internal abstract class QQAndroidBotBase constructor( context: Context, account: BotAccount, configuration: BotConfiguration -) : BotImpl(account, configuration) { +) : BotImpl(context, account, configuration) { val client: QQAndroidClient = QQAndroidClient( context, @@ -88,10 +88,10 @@ internal abstract class QQAndroidBotBase constructor( }.groups.asSequence().map { it.groupUin.shl(32) and it.groupCode } } - override suspend fun queryGroupInfo(id: Long): GroupInfo = network.run { + override suspend fun queryGroupInfo(groupCode: Long): GroupInfo = network.run { TroopManagement.GetGroupInfo( client = bot.client, - groupCode = id + groupCode = groupCode ).sendAndExpect(retry = 2) } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index 3cd073c91..9ac70b87e 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -547,5 +547,5 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler super.close(cause) } - override suspend fun awaitDisconnection() = supervisor.join() + override suspend fun join() = supervisor.join() } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index 4430c4514..a8dea8551 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -33,7 +33,7 @@ import kotlin.jvm.JvmStatic * 机器人对象. 一个机器人实例登录一个 QQ 账号. * Mirai 为多账号设计, 可同时维护多个机器人. * - * 注: Bot 为全协程实现, 没有其他任务时若不使用 [awaitDisconnection], 主线程将会退出. + * 注: Bot 为全协程实现, 没有其他任务时若不使用 [join], 主线程将会退出. * * @see Contact */ @@ -44,7 +44,8 @@ abstract class Bot : CoroutineScope { * 复制一份此时的 [Bot] 实例列表. */ @JvmStatic - val instances: List> get() = BotImpl.instances.toList() + val instances: List> + get() = BotImpl.instances.toList() /** * 遍历每一个 [Bot] 实例 @@ -58,6 +59,14 @@ abstract class Bot : CoroutineScope { fun instanceWhose(qq: Long): Bot = BotImpl.instanceWhose(qq = qq) } + /** + * [Bot] 运行的 [Context]. + * + * 在 JVM 的默认实现为 `class ContextImpl : Context` + * 在 Android 实现为 `android.content.Context` + */ + abstract val context: Context + /** * 账号信息 */ @@ -135,7 +144,9 @@ abstract class Bot : CoroutineScope { abstract val groups: ContactList /** - * 获取一个机器人加入的群. 若没有这个群, 则会抛出异常 [NoSuchElementException] + * 获取一个机器人加入的群. + * + * @throws NoSuchElementException 当不存在这个群时 */ fun getGroup(id: Long): Group { return groups.delegate.getOrNull(id) @@ -143,21 +154,23 @@ abstract class Bot : CoroutineScope { } /** - * 获取群列表. 返回值前 32 bits 为 uin, 后 32 bits 为 groupCode + * 向服务器查询群列表. 返回值前 32 bits 为 uin, 后 32 bits 为 groupCode */ abstract suspend fun queryGroupList(): Sequence /** - * 查询群资料. 获得的仅为当前时刻的资料. + * 向服务器查询群资料. 获得的仅为当前时刻的资料. * 请优先使用 [getGroup] 然后查看群资料. */ - abstract suspend fun queryGroupInfo(id: Long): GroupInfo + abstract suspend fun queryGroupInfo(groupCode: Long): GroupInfo /** - * 查询群成员列表. + * 向服务器查询群成员列表. * 请优先使用 [getGroup], [Group.members] 查看群成员. * * 这个函数很慢. 请不要频繁使用. + * + * @see Group.calculateGroupUinByGroupCode 使用 groupCode 计算 groupUin */ abstract suspend fun queryGroupMemberList(groupUin: Long, groupCode: Long, ownerId: Long): Sequence @@ -175,7 +188,10 @@ abstract class Bot : CoroutineScope { /** * 挂起直到 [Bot] 下线. */ - suspend inline fun awaitDisconnection() = network.awaitDisconnection() + suspend inline fun join() = network.join() + + @Deprecated("使用 join()", ReplaceWith("this.join()"), level = DeprecationLevel.HIDDEN) + suspend inline fun awaitDisconnection() = join() /** * 登录, 或重新登录. @@ -220,6 +236,8 @@ abstract class Bot : CoroutineScope { * 注: 不可重新登录. 必须重新实例化一个 [Bot]. * * @param cause 原因. 为 null 时视为正常关闭, 非 null 时视为异常关闭 + * + * @see closeAndJoin */ abstract fun close(cause: Throwable? = null) @@ -244,6 +262,18 @@ abstract class Bot : CoroutineScope { // endregion } +/** + * 关闭这个 [Bot], 停止一切相关活动. 所有引用都会被释放. + * + * 注: 不可重新登录. 必须重新实例化一个 [Bot]. + * + * @param cause 原因. 为 null 时视为正常关闭, 非 null 时视为异常关闭 + */ +suspend inline fun Bot.closeAndJoin(cause: Throwable? = null) { + close(cause) + coroutineContext[Job]?.join() +} + inline fun Bot.containsFriend(id: Long): Boolean = this.qqs.contains(id) inline fun Bot.containsGroup(id: Long): Boolean = this.groups.contains(id) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt index 23a913e50..a8686f90f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt @@ -32,6 +32,7 @@ import kotlin.coroutines.CoroutineContext @UseExperimental(MiraiExperimentalAPI::class) @MiraiInternalAPI abstract class BotImpl constructor( + context: Context, account: BotAccount, val configuration: BotConfiguration ) : Bot(), CoroutineScope { @@ -39,6 +40,7 @@ abstract class BotImpl constructor( override val coroutineContext: CoroutineContext = configuration.parentCoroutineContext + botJob + (configuration.parentCoroutineContext[CoroutineExceptionHandler] ?: CoroutineExceptionHandler { _, e -> logger.error("An exception was thrown under a coroutine of Bot", e) }) + override val context: Context by context.unsafeWeakRef() @Suppress("CanBePrimaryConstructorProperty") // for logger final override val account: BotAccount = account diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt index 76ffb50d1..66e4a544e 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt @@ -80,9 +80,10 @@ abstract class BotNetworkHandler : CoroutineScope { } /** - * 等待直到与服务器断开连接. 若未连接则立即返回 + * 当 [Bot] 正常运作时, 这个函数将一直挂起协程到 [Bot] 被 [Bot.close] + * 当 [Bot] 离线时, 这个函数立即返回. */ - abstract suspend fun awaitDisconnection() + abstract suspend fun join() /** * 关闭网络接口, 停止所有有关协程和任务