diff --git a/simbot-component-qq-guild-core-1/Module.md b/simbot-component-qq-guild-core-1/Module.md deleted file mode 100644 index fd864592..00000000 --- a/simbot-component-qq-guild-core-1/Module.md +++ /dev/null @@ -1,4 +0,0 @@ -# Module simbot-component-qq-guild-core - -基于core模块与 [simbot3核心库](https://github.com/simple-robot/simpler-robot/tree/v3-main) -对 [QQ频道API](https://bot.q.qq.com/wiki/develop/api/) 功能的完整性实现。 diff --git a/simbot-component-qq-guild-core-1/README.md b/simbot-component-qq-guild-core-1/README.md deleted file mode 100644 index 7565260f..00000000 --- a/simbot-component-qq-guild-core-1/README.md +++ /dev/null @@ -1,234 +0,0 @@ -# core组件模块 - -> **Note** -> 请先阅读 [**模块说明**](Module.md) . - -此模块是此仓库作为simbot组件库的主要 **"证据"** ,也是实际意义上的组件模块。 - -core模块尽可能大限度的以QQ频道的角度去实现simbot核心库中的API,是一个**较高封装程度**的模块。同样的,使用此模块可以使用绝大多数的simbot特性, -包括它的API风格以及Spring Boot Starter等特性。 - -有关simbot3的内容,可以前往其[**官方网站**](https://simbot.forte.love)或[**仓库首页**](https://github.com/simple-robot/simpler-robot/tree/v3-main)了解更多。 - - -## 使用 - -> 注:core模块中的 `ktor-client` 引擎默认使用 `ktor-client-cio-jvm`。如有需要可自行排除替换,例如在 `Java 11+` 的环境下替换使用 `ktor-client-java`。 - -**Gradle Kotlin DSL** - -```kotlin -implementation("love.forte.simbot:simbot-core:$SIMBOT_VERSION") // 必须显式指定simbot相关依赖比如此核心库或spring-boot-starter -implementation("love.forte.simbot.component:simbot-component-qq-guild-core:$VERSION") -``` - -**Gradle Groovy** - -```groovy -implementation 'love.forte.simbot:simbot-core:$SIMBOT_VERSION' // 必须显式指定simbot相关依赖,如此核心库或spring-boot-starter -implementation 'love.forte.simbot.component:simbot-component-qq-guild-core:$VERSION' -``` - -**Maven** - -```xml - - - love.forte.simbot - simbot-core - ${SIMBOT_VERSION} - - - love.forte.simbot.component - simbot-component-qq-guild-core - ${VERSION} - -``` - - -## 命名说明 - -在QQ频道组件中,所有相关的类型(包括但不限于事件、频道、子频道等相关对象)均会以 `QG` 为前缀命名 (例如 `QGGuild` 、`QGBot`),代表 `QQ-Guild`。 -其中除了 `Component` 的实现 `QQGuildComponent`。组件的实现使用全名 `QQGuild` 作为前缀。 - - -## 事件支持 - -目前,组件支持的事件有: - -| 事件 | 描述 | -|:----------------------------------|:----------------| -| `QGGuildEvent` | 频道服务器相关事件 | -| -> `QGGuildCreateEvent` | 频道服务器进入 | -| -> `QGGuildUpdateEvent` | 频道服务器信息更新 | -| -> `QGGuildDeleteEvent` | 频道服务器离开 | -| `QGChannelEvent` | 子频道相关事件 | -| -> `QGChannelCreateEvent` | 子频道新增 | -| -> `QGChannelUpdateEvent` | 子频道信息变更 | -| -> `QGChannelDeleteEvent` | 子频道删除 | -| -> `QGChannelCategoryCreateEvent` | 子频道分类新增 | -| -> `QGChannelCategoryUpdateEvent` | 子频道分类信息变更 | -| -> `QGChannelCategoryDeleteEvent` | 子频道分类删除 | -| `QGMemberEvent` | 成员相关事件 | -| -> `QGMemberAddEvent` | 新增频道成员 | -| -> `QGMemberUpdateEvent` | 频道成员信息更新 | -| -> `QGMemberRemoveEvent` | 频道成员离开/移除 | -| `QGMessageEvent` | 消息事件 | -| -> `QGAtMessageCreateEvent` | At消息(公域消息)事件 | - -以及一个用于兜底儿的 `QGUnsupportedEvent` 类型事件。 - -## 示例 - -### 直接使用 - -```kotlin -suspend fun main() { - val app = createSimpleApplication { - useQQGuild() - } - - // 注册事件 - app.eventListenerManager.listeners { - // 监听事件: 频道成员信息变更事件 - QGMemberUpdateEvent { event -> - println("UPDATE: $event") - println("member: ${event.member()}") - println("operator: ${event.operator()}") - println("guild: ${event.guild()}") - } - - // 公域消息事件 - // 也可以使用 ChannelMessageEvent -> 这是来自 simbot 标准API的事件类型,也是 QGAtMessageCreateEvent 的父类 - QGAtMessageCreateEvent { event -> - event.reply("纯文本消息,<会自动转义>") - event.reply(QGContentText("content文本消息,不会转义,会引发内嵌格式 <#123456>")) - - // 使用消息链 - event.reply(Face(1.ID) + "纯文本".toText() + QGContentText("content文本") + AtAll) - - // 也可以使用 send 发送消息 - event.channel().send("纯文本") - } - - } - - // 注册qq频道bot - app.qqGuildBots { - val bot = register( - "APP ID", - "SECRET", - "TOKEN" - ) { - // 标准库里的bot配置 - botConfig { - // 其他配置,例如使用沙箱环境 - useSandboxServerUrl() - } - } - - // 启动bot - bot.start() - - // 直接操作bot获取一些信息 - // 获取bot的频道服务器列表 - val list = bot.guilds.toList() - println(list) - println(list.size) - - // 找到一个频道(这里我找的是沙箱的灰度频道) - val home = list.first { "法欧莉" in it.name } - - // 获取所有的子频道 - home.channels.collect { - println("Channel: $it") - // 得到这个频道的所属分组 - val channelCategory = it.category.resolve() - } - - // 获取所有的分类频道 - home.categories.collect { - println("Category: $it") - } - - // 这个频道的一些其他信息 - println("Owner: ${home.owner()}") - println("Permissions: ${home.permissions()}") - - // ... - - } - - - app.join() - -} -``` - -
Java - -```java -SimpleApplication application = Applications.createSimbotApplication(Simple.INSTANCE, (c) -> {}, (builder, configuration) -> { - builder.install(QQGuildComponent.Factory, ($1, $2) -> Unit.INSTANCE); - builder.install(QGBotManager.Factory, ($1, $2) -> Unit.INSTANCE); -}); - -// 监听一个事件 -application.getEventListenerManager().register(SimpleListeners.listener(QGMemberUpdateEvent.Key, (context, event) -> { - System.out.println("event: " + event); - System.out.println("event.raw: " + event.getEventRaw()); - System.out.println("event.operator: " + event.getOperator()); - System.out.println("event.guild: " + event.getGuild()); -})); - -// 寻找并注册一个QQ频道Bot -for (BotManager botManager : application.getBotManagers()) { - if (botManager instanceof QGBotManager) { - QGBot bot = ((QGBotManager) botManager).register("101986850", "972f64f7c426096f9344b74ba85102fb", "g57N4WsHHRIx1udptqy7GBAEVsfLgynq", (config) -> { - config.botConfig((bc) -> { - bc.useSandboxServerUrl(); - return Unit.INSTANCE; - }); - - return Unit.INSTANCE; - }); - - bot.startBlocking(); - QGGuild forliy = null; - List guilds = bot.getGuilds().collectToList(); - for (QGGuild guild : guilds) { - System.out.println("Guild: " + guild); - if (guild.getName().contains("法欧莉")) { - forliy = guild; - } - } - assert forliy != null; - - System.out.println("================"); - - forliy.getChannels().collect((channel) -> { - System.out.println("Channel: " + channel); - //System.out.println("Channel.category: " + channel.getCategory().resolveBlocking()); - }); - - forliy.getCategories().collect((category) -> { - System.out.println("Category: " + category); - }); - - break; - } - - -} - -application.joinBlocking(); -``` - -
- -### Spring Boot - -如果希望使用 Spring Boot,参考 https://simbot.forte.love/docs/quick-start/spring-boot-starter 中的说明。 -QQ频道组件实现了 `simbot` 约定的 `service SPI`,支持自动加载。 - -## 注意事项 diff --git a/simbot-component-qq-guild-core-1/build.gradle.kts b/simbot-component-qq-guild-core-1/build.gradle.kts deleted file mode 100644 index a34d1c75..00000000 --- a/simbot-component-qq-guild-core-1/build.gradle.kts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2023-2024. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -plugins { - `simbot-tcg-suspend-transform-configure` - id("simbot-tencent-guild.module-conventions") - id("simbot-tencent-guild.maven-publish") - kotlin("plugin.serialization") - `qq-guild-dokka-partial-configure` -} - -kotlin { - sourceSets.configureEach { - languageSettings { - optIn("love.forte.simbot.InternalSimbotApi") - optIn("love.forte.simbot.qguild.QGInternalApi") - } - } -} - -dependencies { - api(project(":simbot-component-qq-guild-core-common")) - compileOnly(simbotCore) - - compileOnly(libs.kotlinx.serialization.properties) - compileOnly(libs.charleskorn.kaml) - - testImplementation(simbotCore) - testImplementation(libs.charleskorn.kaml) - testImplementation(simbotLoggerSlf4jImpl) - testImplementation("love.forte.simbot:simbot-logger-slf4j-impl:3.0.0-RC.3") - -} - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildBotManager.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildBotManager.kt deleted file mode 100644 index e49d390f..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildBotManager.kt +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild - -import love.forte.simbot.Component -import love.forte.simbot.NoSuchComponentException -import love.forte.simbot.application.ApplicationConfiguration -import love.forte.simbot.application.EventProviderAutoRegistrarFactory -import love.forte.simbot.component.qguild.config.QGBotComponentConfiguration -import love.forte.simbot.component.qguild.internal.QQGuildBotManagerImpl -import love.forte.simbot.event.EventProcessor -import love.forte.simbot.qguild.BotConfiguration -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext - -/** - * - * QQ频道BOT的bot管理器。 - * - * [QQGuildBotManager] 不允许注册相同 `appId` 的bot。 - * - * _Note: 仅由内部实现,对外不稳定_ - * - * @author ForteScarlet - */ -public abstract class QQGuildBotManager : BaseQQGuildBotManager() { - - /** - * [QQGuildBotManager] 的构建工厂。 - */ - public companion object Factory : BaseFactory() { - override suspend fun create( - eventProcessor: EventProcessor, - components: List, - applicationConfiguration: ApplicationConfiguration, - configurator: QQGuildBotManagerConfiguration.() -> Unit, - ): QQGuildBotManager { - val configuration = QQGuildBotManagerConfigurationImpl().also { - it.parentCoroutineContext = applicationConfiguration.coroutineContext - configurator(it) - } - - // find component - val component = components.find { it.id == QQGuildComponent.ID_VALUE } as? QQGuildComponent - ?: throw NoSuchComponentException("component id [${QQGuildComponent.ID_VALUE}], and type of QQGuildComponent.") - - return QQGuildBotManagerImpl(eventProcessor, configuration, component).also { - configuration.useBotManager(it) - } - } - } -} - - -/** - * [QQGuildBotManager] 的自动注册工厂。 - */ -public class QGBotManagerAutoRegistrarFactory : - EventProviderAutoRegistrarFactory { - override val registrar: QQGuildBotManager.Factory get() = QQGuildBotManager -} - - -/** - * [QQGuildBotManager] 使用的配置类。 - */ -@Suppress("MemberVisibilityCanBePrivate") -private class QQGuildBotManagerConfigurationImpl : QQGuildBotManagerConfiguration { - override var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext - - override var botConfigure: BotConfiguration.(appId: String, appKey: String, token: String) -> Unit = { _, _, _ -> } - - override fun botConfigure(configure: BotConfiguration.(appId: String, appKey: String, token: String) -> Unit) { - botConfigure.also { old -> - botConfigure = { appId, appKey, token -> - old(appId, appKey, token) - configure(appId, appKey, token) - } - } - } - - - private var botManagerConfig: suspend (QQGuildBotManager) -> Unit = {} - - private fun addBotManagerConfig(block: suspend (QQGuildBotManager) -> Unit) { - botManagerConfig.also { old -> - botManagerConfig = { - old(it) - block(it) - } - } - } - - override fun register( - appId: String, - appKey: String, - token: String, - botConfiguration: QGBotComponentConfiguration.() -> Unit, - onBot: suspend (QGBot) -> Unit, - ) { - addBotManagerConfig { manager -> - manager.register(appId, appKey, token, botConfiguration) - } - } - - suspend fun useBotManager(botManager: QQGuildBotManagerImpl) { - botManagerConfig(botManager) - } - -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildBotManagerUsage.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildBotManagerUsage.kt deleted file mode 100644 index 0386cad2..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildBotManagerUsage.kt +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2021-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild - -import love.forte.simbot.FragileSimbotApi -import love.forte.simbot.application.Application -import love.forte.simbot.application.ApplicationBuilder -import love.forte.simbot.application.BotRegistrar -import love.forte.simbot.application.EventProvider -import love.forte.simbot.bot.OriginBotManager - - -/** - * 在 [ApplicationBuilder.bots] 作用域中寻找并使用 [QQGuildBotManager]。 - * ```kotlin - * simpleApplication { - * qqGuildBots { - * val bot = register("app id", "app key", "token") { - * // config - * } - * bot.start() - * } - * } - * ``` - * - * 如果当前环境中不存在 [QQGuildBotManager], 则会抛出 [NoSuchElementException]. - * 此异常不会在准备阶段被抛出,而是在真正执行构建时。 - * - * @throws NoSuchElementException 不存在 [QQGuildBotManager] - * - */ -public inline fun ApplicationBuilder<*>.qqGuildBots( - crossinline block: suspend QQGuildBotManager.(BotRegistrar) -> Unit, -) { - bots { - val manager = providers.firstQQGuildBotManagerOrNull() - ?: throw NoSuchElementException("No event provider of type [BaseQGBotManager] in providers $providers") - manager.block(this) - } -} - -/** - * 在 [ApplicationBuilder.bots] 作用域中寻找并使用 [QQGuildBotManager]。 - * ```kotlin - * simpleApplication { - * qqGuildBotsIfSupport { - * val bot = register("app id", "app key", "token") { - * // config - * } - * bot.start() - * } - * } - * ``` - * - * 如果当前环境中不存在 [QQGuildBotManager], 则不会执行 [block]. - * - */ -public inline fun ApplicationBuilder<*>.qqGuildBotsIfSupport( - crossinline block: suspend QQGuildBotManager.(BotRegistrar) -> Unit, -) { - bots { - val manager = providers.firstQQGuildBotManagerOrNull() ?: return@bots - manager.block(this) - } -} - -/** - * 在 [ApplicationBuilder.bots] 作用域中寻找并使用 [QQGuildBotManager]。 - * ```kotlin - * simpleApplication { - * bots { - * qqGuild { - * val bot = register("app id", "app key", "token") { - * // config - * } - * bot.start() - * } - * } - * } - * ``` - * - * 如果当前环境中不存在 [QQGuildBotManager], 则会抛出 [NoSuchElementException]. - * 此异常不会准备阶段被抛出,而是在真正执行构建时。 - * - * @throws NoSuchElementException 当前环境中不存在 [QQGuildBotManager] - * - */ -public suspend inline fun BotRegistrar.qqGuild( - crossinline block: suspend QQGuildBotManager.() -> Unit, -) { - val manager = providers.firstQQGuildBotManagerOrNull() - ?: throw NoSuchElementException("No event provider of type [QQGuildBotManager] in providers $providers") - manager.block() -} - -/** - * 在 [ApplicationBuilder.bots] 作用域中寻找并使用 [QQGuildBotManager]。 - * ```kotlin - * simpleApplication { - * bots { - * qqGuildIfSupport { - * val bot = register("app id", "app key", "token") { - * // config - * } - * bot.start() - * } - * } - * } - * ``` - * - * 如果当前环境中不存在 [QQGuildBotManager], 则不会执行 [block]. - * - */ -public suspend inline fun BotRegistrar.qqGuildIfSupport( - crossinline block: suspend QQGuildBotManager.() -> Unit, -) { - val manager = providers.firstQQGuildBotManagerOrNull() ?: return - manager.block() -} - -/** - * 获取第一个 [QQGuildBotManager] 并使用 - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Application.qgGuildBots(block: QQGuildBotManager.() -> Unit) { - val manager = botManagers.first { it is QQGuildBotManager } as QQGuildBotManager - manager.block() -} - -/** - * 尝试寻找并使用 [QQGuildBotManager] - */ -public inline fun Application.qgGuildBotsIfSupport(block: QQGuildBotManager.() -> Unit) { - val manager = (botManagers.firstOrNull { it is QQGuildBotManager } ?: return) as QQGuildBotManager - manager.block() -} - -/** - * 从 [OriginBotManager] 中过滤取出所有 [QQGuildBotManager] 实例. - */ -@FragileSimbotApi -@Suppress("NOTHING_TO_INLINE") -public inline fun qqGuildBotManagers(): List = - OriginBotManager.filterIsInstance() - -/** - * 从 [OriginBotManager] 中取出第一个 [QQGuildBotManager] 实例。 - * - * @throws NoSuchElementException 如果元素不存在 - */ -@FragileSimbotApi -@Suppress("NOTHING_TO_INLINE") -public inline fun qqGuildBotManager(): QQGuildBotManager = - OriginBotManager.first { it is QQGuildBotManager } as QQGuildBotManager - -/** - * 从 [OriginBotManager] 中过滤取出所有 [QQGuildBotManager] 实例。 - * 如果元素不存在则得到null。 - */ -@FragileSimbotApi -@Suppress("NOTHING_TO_INLINE") -public inline fun qqGuildBotManagerOrNull(): QQGuildBotManager? = - OriginBotManager.firstOrNull { it is QQGuildBotManager } as QQGuildBotManager? - -/** - * 从中过滤取出所有 [QQGuildBotManager] 实例. - */ -@Suppress("NOTHING_TO_INLINE") -public inline fun Iterable.filterIsQQGuildBotManagers(): List = - filterIsInstance() - -/** - * 从序列中过滤出 [QQGuildBotManager] 实例. - */ -@Suppress("NOTHING_TO_INLINE") -public inline fun Sequence.filterIsQQGuildBotManagers(): Sequence = - filterIsInstance() - -/** - * 从中过滤取出所有 [QQGuildBotManager] 实例。 - * - * @throws NoSuchElementException 如果不存在 - */ -@Suppress("NOTHING_TO_INLINE") -public inline fun Iterable.firstQQGuildBotManager(): QQGuildBotManager = - first { it is QQGuildBotManager } as QQGuildBotManager - -/** - * 从序列中过滤出 [QQGuildBotManager] 实例。 - * - * @throws NoSuchElementException 如果不存在 - */ -@Suppress("NOTHING_TO_INLINE") -public inline fun Sequence.firstQQGuildBotManager(): QQGuildBotManager = - first { it is QQGuildBotManager } as QQGuildBotManager - -/** - * 从中过滤取出所有 [QQGuildBotManager] 实例。 - * 如果不存在则得到null。 - */ -@Suppress("NOTHING_TO_INLINE") -public inline fun Iterable.firstQQGuildBotManagerOrNull(): QQGuildBotManager? = - firstOrNull { it is QQGuildBotManager } as QQGuildBotManager? - -/** - * 从序列中过滤出 [QQGuildBotManager] 实例。 - * 如果不存在则得到null。 - */ -@Suppress("NOTHING_TO_INLINE") -public inline fun Sequence.firstQQGuildBotManagerOrNull(): QQGuildBotManager? = - firstOrNull { it is QQGuildBotManager } as QQGuildBotManager? diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildComponentUsage.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildComponentUsage.kt deleted file mode 100644 index c94b66d5..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/QQGuildComponentUsage.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild - -import love.forte.simbot.ability.CompletionPerceivable -import love.forte.simbot.application.* - - -/** - * 在 [ApplicationBuilder] 中安装使用 [QQGuildComponent]。 - * - * usage: - * ```kotlin - * simbotApplication(Foo) { - * useQQGuildComponent() - * // 或 - * useQQGuildComponent { ... } - * } - * ``` - * - * 相当于: - * ```kotlin - * simbotApplication(Foo) { - * install(QQGuildComponent) { ... } - * } - * ``` - * - * @see QQGuildComponent - * - */ -@ApplicationBuilderDsl -public fun ApplicationBuilder.useQQGuildComponent(configurator: QQGuildComponentConfiguration.(perceivable: CompletionPerceivable) -> Unit = {}) { - install(QQGuildComponent, configurator) -} - -/** - * 在 [ApplicationBuilder] 中 **尝试** 安装使用 [QQGuildBotManager]。 - * - * usage: - * ```kotlin - * simbotApplication(Foo) { - * useQQGuildBotManager() - * // 或 - * useQQGuildBotManager { ... } - * } - * ``` - * - * 相当于: - * ```kotlin - * simbotApplication(Foo) { - * install(QQGuildBotManager) { ... } - * } - * ``` - * @see QQGuildBotManager - * - */ -@Suppress("UNCHECKED_CAST") -@ApplicationBuilderDsl -@Throws(ClassNotFoundException::class) -public fun ApplicationBuilder.useQQGuildBotManager(configurator: QQGuildBotManagerConfiguration.(perceivable: CompletionPerceivable) -> Unit = {}) { - install(QQGuildBotManager, configurator) -} - -/** - * 同时安装使用 [QQGuildComponent] 和 [QQGuildBotManager]. - * - * usage: - * ```kotlin - * simbotApplication(Foo) { - * useQQGuild() - * // 或 - * useQQGuild { - * component { ... } - * botManager { ... } - * } - * } - * ``` - * - * 相当于: - * ```kotlin - * simbotApplication(Foo) { - * install(QQGuildComponent) { ... } - * install(QGBotManager) { ... } - * } - * ``` - * - * - */ -@ApplicationBuilderDsl -public fun ApplicationBuilder.useQQGuild(builder: QQGuildUsageBuilder.() -> Unit = {}) { - QQGuildUsageBuilderImpl().also(builder).build(this) -} - -/** - * 使用 [QQGuildBotManager] - * - * @throws NoSuchElementException 如果不存在 - */ -public inline fun A.qqGuildBots(block: QQGuildBotManager.() -> Unit) { - botManagers.firstQQGuildBotManager().also(block) -} - - -/** - * 为 [QQGuildUsageBuilder] 中的函数染色。 - */ -@DslMarker -@Target(AnnotationTarget.FUNCTION) -internal annotation class QQGuildUsageBuilderDsl - - -/** - * 使用在 [useQQGuild] 函数中,用于同时针对 [QQGuildComponent] 和 [QQGuildBotManager] - * 进行配置。 - * - * @see useQQGuild - */ -public interface QQGuildUsageBuilder { - - /** - * 追加一个安装 [QQGuildComponent] 时候使用的配置。 - */ - @QQGuildUsageBuilderDsl - public fun component(configurator: QQGuildComponentConfiguration.(perceivable: CompletionPerceivable) -> Unit) - - - /** - * 追加一个安装 [QQGuildBotManager] 时候使用的配置。 - */ - @QQGuildUsageBuilderDsl - public fun botManager(configurator: QQGuildBotManagerConfiguration.(perceivable: CompletionPerceivable) -> Unit) - -} - - -private class QQGuildUsageBuilderImpl : QQGuildUsageBuilder { - private var componentConfig: QQGuildComponentConfiguration.(perceivable: CompletionPerceivable) -> Unit = {} - private var botManagerConfig: QQGuildBotManagerConfiguration.(perceivable: CompletionPerceivable) -> Unit = - {} - - override fun component(configurator: QQGuildComponentConfiguration.(perceivable: CompletionPerceivable) -> Unit) { - componentConfig.also { old -> - componentConfig = { - old(it) - configurator(it) - } - } - } - - override fun botManager(configurator: QQGuildBotManagerConfiguration.(perceivable: CompletionPerceivable) -> Unit) { - botManagerConfig.also { old -> - botManagerConfig = { - old(it) - configurator(it) - } - } - } - - fun build(applicationBuilder: ApplicationBuilder) { - applicationBuilder.useQQGuildComponent(componentConfig) - applicationBuilder.useQQGuildBotManager(botManagerConfig) - } - - -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/InstantUtil.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/InstantUtil.kt deleted file mode 100644 index 10a9de6c..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/InstantUtil.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.Timestamp -import java.time.Instant -import java.time.OffsetDateTime -import java.time.format.DateTimeFormatter -import java.time.temporal.ChronoField - -/** - * Parse iso 8601 datetime string to [Timestamp] - */ -@ExperimentalSimbotApi -public fun String.toTimestamp(): Timestamp { - return DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(this) { temporal -> - when (temporal) { - is OffsetDateTime -> Timestamp.bySecond(temporal.toEpochSecond(), temporal.toLocalTime().nano) - is Instant -> Timestamp.byInstant(temporal) - else -> { - val instantSecs = temporal.getLong(ChronoField.INSTANT_SECONDS) - val nanoOfSecond = temporal[ChronoField.NANO_OF_SECOND] - - Timestamp.bySecond(instantSecs, nanoOfSecond) - } - } - } -} - - - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGBotImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGBotImpl.kt deleted file mode 100644 index 6d2a2ace..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGBotImpl.kt +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) 2021-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.* -import love.forte.simbot.component.qguild.config.QGBotComponentConfiguration -import love.forte.simbot.component.qguild.event.QGBotStartedEvent -import love.forte.simbot.component.qguild.internal.QGGuildImpl.Companion.qgGuild -import love.forte.simbot.component.qguild.internal.event.QGBotStartedEventImpl -import love.forte.simbot.component.qguild.internal.forum.QGForumChannelImpl -import love.forte.simbot.component.qguild.message.QGMessageReceipt -import love.forte.simbot.component.qguild.message.sendMessage -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.event.EventProcessor -import love.forte.simbot.literal -import love.forte.simbot.logger.LoggerFactory -import love.forte.simbot.message.Message -import love.forte.simbot.message.MessageContent -import love.forte.simbot.qguild.* -import love.forte.simbot.qguild.DisposableHandle -import love.forte.simbot.qguild.api.channel.GetChannelApi -import love.forte.simbot.qguild.api.channel.GetGuildChannelListApi -import love.forte.simbot.qguild.api.guild.GetGuildApi -import love.forte.simbot.qguild.api.member.GetMemberApi -import love.forte.simbot.qguild.api.user.GetBotGuildListApi -import love.forte.simbot.qguild.model.ChannelType -import love.forte.simbot.qguild.model.SimpleChannel -import love.forte.simbot.qguild.model.SimpleGuild -import love.forte.simbot.qguild.model.isCategory -import love.forte.simbot.utils.item.Items -import love.forte.simbot.utils.item.effectOn -import love.forte.simbot.utils.item.effectedItemsByFlow -import love.forte.simbot.utils.item.itemsByFlow -import java.util.concurrent.ConcurrentHashMap -import kotlin.coroutines.CoroutineContext -import love.forte.simbot.qguild.model.User as QGUser - -/** - * - * @author ForteScarlet - */ -internal class QGBotImpl( - override val source: Bot, - override val manager: QQGuildBotManager, - override val eventProcessor: EventProcessor, - override val component: QQGuildComponent, - configuration: QGBotComponentConfiguration -) : QGBot { - override val logger = - LoggerFactory.getLogger("love.forte.simbot.component.qguild.bot.${source.ticket.secret}") - - internal val job: CompletableJob - - @Suppress("RedundantModalityModifier") // warn - final override val coroutineContext: CoroutineContext - - private val cacheConfig = configuration.cacheConfig - private val cacheable = cacheConfig?.enable == true - - init { - val context = source.coroutineContext - val job = SupervisorJob(context[Job]) - this.job = job - this.coroutineContext = context + job - - // check config for warn log - if (configuration.cacheConfig?.dynamicCacheConfig?.enable == true) { - logger.warn("DynamicCacheConfig is not supported yet, but dynamicCacheConfig.enable == `true`. This will have no real effect.") - } - - } - - @Volatile - private lateinit var botSelf: QGUser - - override val userId: ID - get() { - if (!::botSelf.isInitialized) { - throw UninitializedPropertyAccessException("Information of bot has not been initialized. Please execute the `start()` method at least once first") - } - - return botSelf.id.ID - } - - - override fun isMe(id: ID): Boolean { - if (id == this.id) return true - return ::botSelf.isInitialized && botSelf.id == id.literal - } - - override val username: String - get() = if (!::botSelf.isInitialized) { - throw UninitializedPropertyAccessException("Information of bot has not been initialized. Please execute the `start()` method at least once first") - } else botSelf.username - - override val avatar: String - get() = if (!::botSelf.isInitialized) "" else botSelf.avatar - - - internal suspend fun queryGuild(id: String): QGGuildImpl? { - return try { - GetGuildApi.create(id).requestBy(bot) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNull() - }?.let { guild -> qgGuild(this, guild) } - } - - override suspend fun guild(id: ID): QGGuildImpl? = queryGuild(id.literal) - - @OptIn(ExperimentalCoroutinesApi::class) - override val guilds: Items - get() = itemsByFlow { props -> - props.effectOn(queryGuildList(props.batch).flatMapConcat { it.asFlow() }).map { qgGuild(this, it) } - } - - - internal fun channelFlow(guildId: String): Flow { - return flow { - GetGuildChannelListApi.create(guildId) - .requestBy(this@QGBotImpl) - .forEach { - emit(it) - } - } - } - - override suspend fun channel(channelId: ID): QGChannel? = channel(channelId.literal, null) - - override suspend fun category(channelId: ID): QGChannelCategory? { - val channel = channel(id) ?: return null - - return channel as? QGChannelCategory - ?: throw IllegalStateException("The type of channel(id=${channel.source.id}, name=${channel.source.name}) is not category (${ChannelType.CATEGORY}), but ${channel.source.type}") - } - - /** - * @throws QQGuildApiException - */ - internal suspend fun queryChannel(id: String): SimpleChannel? { - return try { - GetChannelApi.create(id).requestBy(this) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNull() - } - } - - @OptIn(InternalApi::class) - internal suspend fun channel(id: String, sourceGuild: QGGuildImpl?): QGChannel? { - val channelInfo = queryChannel(id) ?: return null - - return when (channelInfo.type) { - ChannelType.CATEGORY -> QGChannelCategoryImpl( - bot = sourceGuild?.bot ?: this.inGuild(channelInfo.guildId), - source = channelInfo, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - ) // throw IllegalStateException("The type of channel(id=${channelInfo.id}, name=${channelInfo.name}) is CATEGORY. Maybe you should use [guild.category(id)]?") - ChannelType.TEXT -> QGTextChannelImpl( - bot = sourceGuild?.bot ?: this.inGuild(channelInfo.guildId), - source = channelInfo, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - ) - - ChannelType.FORUM -> QGForumChannelImpl( - bot = sourceGuild?.bot ?: this.inGuild(channelInfo.guildId), - source = channelInfo, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - ) - - else -> QGNonTextChannelImpl( - bot = sourceGuild?.bot ?: this.inGuild(channelInfo.guildId), - source = channelInfo, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - ) - } - } - - internal data class ChannelInfoWithCategory(val info: SimpleChannel, val categoryId: QGChannelCategoryId) - - internal fun channelFlowWithCategoryId(guildId: String, sourceGuild: QGGuildImpl?): Flow { - val categoryMap = ConcurrentHashMap() - fun bot(info: SimpleChannel): QGGuildBotImpl = sourceGuild?.bot ?: inGuild(info.guildId) - - return channelFlow(guildId).filter { info -> - if (info.type.isCategory) { - categoryMap.computeIfAbsent(info.id) { - QGChannelCategoryImpl( - bot = bot(info), - source = info, - sourceGuild = checkIfTransmitCacheable(sourceGuild) - ) - } - - false - } else { - true - } - }.map { info -> - val category = categoryMap.computeIfAbsent(info.parentId) { cid -> - QGChannelCategoryIdImpl( - bot = bot(info), - guildId = info.guildId.ID, - id = cid.ID, - sourceGuild = sourceGuild - ) - } - - ChannelInfoWithCategory(info, category) - } - } - - - /** - * 通过API实时查询channels列表 - */ - @OptIn(InternalApi::class) - internal fun queryChannels(guildId: String, sourceGuild: QGGuildImpl?): Items = effectedItemsByFlow { - fun bot(info: SimpleChannel): QGGuildBotImpl = sourceGuild?.bot ?: inGuild(info.guildId) - channelFlowWithCategoryId(guildId, sourceGuild).map { (info, category) -> - when (info.type) { - ChannelType.TEXT -> QGTextChannelImpl( - bot = bot(info), - source = info, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - category = category, - ) - - ChannelType.FORUM -> QGForumChannelImpl( - bot = bot(info), - source = info, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - category = category, - ) - - else -> QGNonTextChannelImpl( - bot = bot(info), - source = info, - sourceGuild = checkIfTransmitCacheable(sourceGuild), - category = category - ) - } - - } - } - - override suspend fun sendTo(channelId: ID, text: String): QGMessageReceipt { - return try { - bot.sendMessage(channelId.literal, text) - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "Bot.sendTo" } - } - } - - override suspend fun sendTo(channelId: ID, message: Message): QGMessageReceipt { - return try { - bot.sendMessage(channelId.literal, message) - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "Bot.sendTo" } - } - } - - override suspend fun sendTo(channelId: ID, message: MessageContent): QGMessageReceipt { - return try { - bot.sendMessage(channelId.literal, message) - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "Bot.sendTo" } - } - } - - internal suspend fun member(guildId: String, userId: String, sourceGuild: QGGuildImpl?): QGMemberImpl? { - val member = try { - GetMemberApi.create(guildId, userId).requestBy(this) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNull() - } - - return member?.let { info -> - QGMemberImpl( - bot = this, - source = info, - guildId = guildId.ID, - sourceGuild = checkIfTransmitCacheable(sourceGuild) - ) - } - } - - private val startLock = Mutex() - - override suspend fun me(withCache: Boolean): QGUser { - if (withCache && ::botSelf.isInitialized) { - return botSelf - } - - return source.me().also { botSelf = it } - } - - - @Volatile - private var sourceListenerDisposableHandle: DisposableHandle? = null - - /** - * 启动当前bot。 - */ - override suspend fun start(): Boolean = startLock.withLock { - source.start().also { - // just set everytime. - botSelf = me().also { me -> - logger.debug("bot own information: {}", me) - } - - suspend fun pushStartedEvent() { - if (eventProcessor.isProcessable(QGBotStartedEvent)) { - launch { - eventProcessor.push(QGBotStartedEventImpl(this@QGBotImpl)) - } - } - } - - if (!it) { - pushStartedEvent() - return@also - } - - sourceListenerDisposableHandle?.also { handle -> - handle.dispose() - sourceListenerDisposableHandle = null - } - sourceListenerDisposableHandle = registerEventProcessor() - pushStartedEvent() - } - } - - - override suspend fun join() { - source.join() - } - - - override suspend fun cancel(reason: Throwable?): Boolean = source.cancel(reason) - - - override val isStarted: Boolean - get() = job.isCompleted || job.isActive - - - override val isCancelled: Boolean - get() = job.isCancelled - - - private fun queryGuildList(batch: Int): Flow> = flow { - val limit = batch.takeIf { it > 0 } ?: GetBotGuildListApi.DEFAULT_LIMIT - var lastId: String? = null - while (true) { - val list = GetBotGuildListApi.create(after = lastId, limit = limit).requestBy(source) - if (list.isEmpty()) break - lastId = list.last().id - emit(list) - } - } - - internal fun inGuild(guildId: String, sourceGuild: QGGuildImpl? = null): QGGuildBotImpl = - QGGuildBotImpl(bot = this, guildId = guildId, sourceGuild = checkIfTransmitCacheable(sourceGuild)) - - private val isTransmitCacheable = cacheable && cacheConfig?.transmitCacheConfig?.enable == true - - internal fun checkIfTransmitCacheable(target: T): T? = target.takeIf { isTransmitCacheable } - - override fun toString(): String { - // 还未初始化 - val uid = if (::botSelf.isInitialized) botSelf.id else "(Not initialized yet)" - return "QGBotImpl(appId=$id, userId=$uid, isActive=$isActive)" - } -} - - -/** - * 从 [QGBot] 中分配一个拥有新的 [SupervisorJob] 的 [CoroutineContext]. - */ -internal fun CoroutineScope.newSupervisorCoroutineContext(): CoroutineContext = - coroutineContext + SupervisorJob(coroutineContext[Job]) diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGChannelCategoryImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGChannelCategoryImpl.kt deleted file mode 100644 index 5854aad7..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGChannelCategoryImpl.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGChannelCategory -import love.forte.simbot.component.qguild.QGChannelCategoryId -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import kotlin.coroutines.CoroutineContext -import love.forte.simbot.qguild.model.Channel as QGuildChannel - - -internal class QGChannelCategoryIdImpl( - override val bot: QGGuildBotImpl, - private val guildId: ID, - override val id: ID, - private val sourceGuild: QGGuild? = null -) : QGChannelCategoryId { - - @Volatile - private lateinit var _category: QGChannelCategory - private val initLock = Mutex() - - override suspend fun resolve(): QGChannelCategory { - return if (::_category.isInitialized) _category else initLock.withLock { - if (::_category.isInitialized) _category else { - guild().category(id)?.also { - _category = it - } - ?: throw NoSuchElementException("category(id=$id)") - } - } - } - - override suspend fun guild(): QGGuild = - sourceGuild - ?: bot.guild(guildId) - ?: throw NoSuchElementException("guild(id=$guildId)") - - override fun toString(): String { - return "QGChannelCategoryIdImpl(id=$id, name=$name, guildId=$guildId)" - } -} - -internal class QGChannelCategoryImpl( - override val bot: QGGuildBotImpl, - override val source: QGuildChannel, - private val sourceGuild: QGGuild? = null -) : QGChannelCategory { - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - - override val category: QGChannelCategory get() = this - - override suspend fun resolve(): QGChannelCategory = this - - override val id: ID = source.id.ID - - override val ownerId: ID = source.ownerId.ID - override val guildId: ID = source.guildId.ID - - override suspend fun guild(): QGGuild = - sourceGuild - ?: bot.guild(guildId) - ?: throw NoSuchElementException("guild(id=$guildId)") - - override suspend fun owner(): QGMember = guild().member(ownerId) ?: throw NoSuchElementException("owner(id=$ownerId)") - - - override fun toString(): String { - return "QGChannelCategoryImpl(id=$id, name=$name, guildId=$guildId)" - } -} - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGEventProcess.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGEventProcess.kt deleted file mode 100644 index a8d79354..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGEventProcess.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import love.forte.simbot.FragileSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.event.* -import love.forte.simbot.component.qguild.internal.QGGuildImpl.Companion.qgGuild -import love.forte.simbot.component.qguild.internal.event.* -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.event.Event -import love.forte.simbot.qguild.DisposableHandle -import love.forte.simbot.qguild.api.channel.GetChannelApi -import love.forte.simbot.qguild.event.* -import love.forte.simbot.qguild.model.isCategory - -private fun QGBotImpl.guild0(eventGuild: EventGuild): QGGuildImpl = qgGuild(this, eventGuild) - -private suspend fun QGBotImpl.channel0(eventChannel: EventChannel): QGTextChannelImpl { - val channel = GetChannelApi.create(eventChannel.id).requestBy(this) - return QGTextChannelImpl(bot = this.inGuild(channel.guildId), source = channel) -} - -private fun QGBotImpl.member0(eventMember: EventMember): QGMemberImpl = - QGMemberImpl(this, eventMember, eventMember.guildId.ID) - -/** - * simbot针对QQ频道注册的时候只注册一个普通处理函数。 - */ -@OptIn(FragileSimbotApi::class) -internal fun QGBotImpl.registerEventProcessor(): DisposableHandle { - val bot = this - return source.registerProcessor { raw -> - when (val event = this) { - //region Guild相关 - is GuildCreate -> { - val guild = guild0(event.data) - pushEvent(QGGuildCreateEvent) { - QGGuildCreateEventImpl(raw, event.data, bot, guild) - } - } - - is GuildUpdate -> { - val guild = guild0(event.data) - pushEvent(QGGuildUpdateEvent) { - QGGuildUpdateEventImpl(raw, event.data, bot, guild) - } - } - - is GuildDelete -> { - val guild = guild0(event.data) - pushEvent(QGGuildDeleteEvent) { - QGGuildDeleteEventImpl(raw, event.data, bot, guild) - } - } - //endregion - - //region Channel相关 - is ChannelCreate -> { - if (event.data.type.isCategory) { - bot.logger.warn( - "Received category create event [raw={}]. report this log to issues https://github.com/simple-robot/simbot-component-qq-guild/issues/new/choose", - raw - ) - } - - val channel = channel0(event.data) - pushEvent(QGChannelCreateEvent) { - QGChannelCreateEventImpl(raw, event.data, bot, channel) - } - - } - - is ChannelUpdate -> { - if (event.data.type.isCategory) { - bot.logger.warn( - "Received category update event [raw={}]. report this log to issues https://github.com/simple-robot/simbot-component-qq-guild/issues/new/choose", - raw - ) - } - val channel = channel0(event.data) - pushEvent(QGChannelUpdateEvent) { - QGChannelUpdateEventImpl(raw, event.data, bot, channel) - } - } - - is ChannelDelete -> { - if (event.data.type.isCategory) { - bot.logger.warn( - "Received category delete event [raw={}]. report this log to issues https://github.com/simple-robot/simbot-component-qq-guild/issues/new/choose", - raw - ) - } - - val channel = channel0(event.data) - pushEvent(QGChannelDeleteEvent) { - QGChannelDeleteEventImpl(raw, event.data, bot, channel) - } - } - //endregion - - //region Member相关 - is GuildMemberAdd -> { - val member = member0(event.data) - pushEvent(QGMemberAddEvent) { - QGMemberAddEventImpl(bot, raw, event.data, member) - } - } - - is GuildMemberUpdate -> { - val member = member0(event.data) - pushEvent(QGMemberUpdateEvent) { - QGMemberUpdateEventImpl(bot, raw, event.data, member) - } - } - - is GuildMemberRemove -> { - val member = member0(event.data) - pushEvent(QGMemberRemoveEvent) { - QGMemberRemoveEventImpl(bot, raw, event.data, member) - } - } - //endregion - - - // 消息 - is AtMessageCreate -> { - pushEvent(QGAtMessageCreateEvent) { QGAtMessageCreateEventImpl(bot, raw, event.data) } - } - - // OpenForum - is OpenForumDispatch -> when (event) { - is OpenForumThreadCreate -> pushEvent(QGOpenForumThreadCreateEvent) { QGOpenForumThreadCreateEventImpl(bot, raw, event.data) } - is OpenForumThreadDelete -> pushEvent(QGOpenForumThreadDeleteEvent) { QGOpenForumThreadDeleteEventImpl(bot, raw, event.data) } - is OpenForumThreadUpdate -> pushEvent(QGOpenForumThreadUpdateEvent) { QGOpenForumThreadUpdateEventImpl(bot, raw, event.data) } - is OpenForumPostCreate -> pushEvent(QGOpenForumPostCreateEvent) { QGOpenForumPostCreateEventImpl(bot, raw, event.data) } - is OpenForumPostDelete -> pushEvent(QGOpenForumPostDeleteEvent) { QGOpenForumPostDeleteEventImpl(bot, raw, event.data) } - is OpenForumReplyCreate -> pushEvent(QGOpenForumReplyCreateEvent) { QGOpenForumReplyCreateEventImpl(bot, raw, event.data) } - is OpenForumReplyDelete -> pushEvent(QGOpenForumReplyDeleteEvent) { QGOpenForumReplyDeleteEventImpl(bot, raw, event.data) } - } - - // Forum - is ForumDispatch -> when (event) { - is ForumPostCreate -> pushEvent(QGForumPostCreateEvent) { QGForumPostCreateEventImpl(bot, raw, event.data) } - is ForumPostDelete -> pushEvent(QGForumPostDeleteEvent) { QGForumPostDeleteEventImpl(bot, raw, event.data) } - is ForumReplyCreate -> pushEvent(QGForumReplyCreateEvent) { QGForumReplyCreateEventImpl(bot, raw, event.data) } - is ForumReplyDelete -> pushEvent(QGForumReplyDeleteEvent) { QGForumReplyDeleteEventImpl(bot, raw, event.data) } - is ForumThreadCreate -> pushEvent(QGForumThreadCreateEvent) { QGForumThreadCreateEventImpl(bot, raw, event.data) } - is ForumThreadDelete -> pushEvent(QGForumThreadDeleteEvent) { QGForumThreadDeleteEventImpl(bot, raw, event.data) } - is ForumThreadUpdate -> pushEvent(QGForumThreadUpdateEvent) { QGForumThreadUpdateEventImpl(bot, raw, event.data) } - is ForumPublishAuditResult -> pushEvent(QGForumPublishAuditResultEvent) { QGForumPublishAuditResultEventImpl(bot, raw, event.data) } - } - - - // unsupported - else -> { - pushEvent(QGUnsupportedEvent) { QGUnsupportedEventImpl(bot, event, raw) } - } - } - } - - -} - - -private suspend inline fun QGBotImpl.pushEvent(eventKey: Event.Key<*>, crossinline block: () -> Event) { - if (eventProcessor.isProcessable(eventKey)) { - eventProcessor.push(block()) -// launch { -// eventProcessor.push(block()) -// } - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGGuildBotImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGGuildBotImpl.kt deleted file mode 100644 index 4577e61f..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGGuildBotImpl.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.* -import love.forte.simbot.component.qguild.message.QGMessageReceipt -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.event.EventProcessor -import love.forte.simbot.literal -import love.forte.simbot.message.Image -import love.forte.simbot.message.Message -import love.forte.simbot.message.MessageContent -import love.forte.simbot.qguild.Bot -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.member.GetMemberApi -import love.forte.simbot.qguild.isNotFound -import love.forte.simbot.qguild.model.User -import love.forte.simbot.utils.item.Items -import org.slf4j.Logger -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -internal class QGGuildBotImpl( - override val bot: QGBotImpl, - private val guildId: String, - private val sourceGuild: QGGuildImpl? = null, -) : QGGuildBot, QGBot { - override suspend fun asMember(): QGMemberImpl { - val member = try { - GetMemberApi.create(guildId, bot.userId.literal).requestBy(bot) - } catch (apiEx: QQGuildApiException) { - if (apiEx.isNotFound) throw NoSuchElementException("bot member(id=${bot.userId})") else throw apiEx - } - return QGMemberImpl(bot, member, guildId.ID, sourceGuild) - } - - override val userId: ID get() = bot.userId - override val username: String get() = bot.username - override val avatar: String get() = bot.avatar - - override suspend fun guild(id: ID): QGGuildImpl? = bot.guild(id) - - override suspend fun resolveImage(id: ID): Image<*> = bot.resolveImage(id) - - override val coroutineContext: CoroutineContext get() = bot.coroutineContext - override val isCancelled: Boolean get() = bot.isCancelled - override val isStarted: Boolean get() = bot.isStarted - override val logger: Logger get() = bot.logger - - override suspend fun cancel(reason: Throwable?): Boolean = bot.cancel(reason) - - override suspend fun join() = bot.join() - - override val component: QQGuildComponent get() = bot.component - override val source: Bot get() = bot.source - - override fun isMe(id: ID): Boolean = bot.isMe(id) - - override suspend fun start(): Boolean = bot.start() - - override val manager: QQGuildBotManager - get() = bot.manager - - override val eventProcessor: EventProcessor - get() = bot.eventProcessor - - override val guilds: Items - get() = bot.guilds - - override suspend fun me(withCache: Boolean): User = bot.me(withCache) - override suspend fun me(): User = bot.me() - - override suspend fun channel(channelId: ID): QGChannel? = bot.channel(channelId) - - override suspend fun category(channelId: ID): QGChannelCategory? = bot.category(channelId) - - override suspend fun sendTo(channelId: ID, text: String): QGMessageReceipt = bot.sendTo(channelId, text) - - override suspend fun sendTo(channelId: ID, message: Message): QGMessageReceipt = bot.sendTo(channelId, message) - - override suspend fun sendTo(channelId: ID, message: MessageContent): QGMessageReceipt = bot.sendTo(channelId, message) - - override fun toString(): String { - return "QGGuildBotImpl(bot=$bot, guildId=$guildId)" - } -} - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGGuildImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGGuildImpl.kt deleted file mode 100644 index b5938afd..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGGuildImpl.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import kotlinx.coroutines.CompletableJob -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.flow.emitAll -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.map -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGChannel -import love.forte.simbot.component.qguild.QGChannelCategory -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.forum.QGForums -import love.forte.simbot.component.qguild.internal.forum.QGForumsImpl -import love.forte.simbot.component.qguild.internal.role.QGGuildRoleImpl -import love.forte.simbot.component.qguild.internal.role.QGRoleCreatorImpl -import love.forte.simbot.component.qguild.role.QGRoleCreator -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.qguild.api.apipermission.ApiPermissions -import love.forte.simbot.qguild.api.apipermission.GetApiPermissionListApi -import love.forte.simbot.qguild.api.member.GetGuildMemberListApi -import love.forte.simbot.qguild.api.member.createFlow -import love.forte.simbot.qguild.api.role.GetGuildRoleListApi -import love.forte.simbot.qguild.model.ChannelType -import love.forte.simbot.qguild.model.Guild -import love.forte.simbot.qguild.model.isCategory -import love.forte.simbot.utils.item.* -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -internal class QGGuildImpl private constructor( - internal val baseBot: QGBotImpl, - override val source: Guild, - override val coroutineContext: CoroutineContext -) : QGGuild { - - override val id: ID = source.id.ID - override val ownerId: ID = source.ownerId.ID - - @OptIn(ExperimentalSimbotApi::class) - override val joinTime: Timestamp get() = source.joinedAt.toTimestamp() - override val currentMember: Int get() = source.memberCount - override val description: String get() = source.description - override val icon: String get() = source.icon - override val maximumMember: Int get() = source.maxMembers - override val name: String get() = source.name - - override fun toString(): String { - return "QGGuildImpl(id=$id, name=$name)" - } - - override suspend fun permissions(): ApiPermissions = GetApiPermissionListApi.create(source.id).requestBy(baseBot) - - override val bot: QGGuildBotImpl = baseBot.inGuild(source.id, this) - - override suspend fun owner(): QGMemberImpl { - return member(ownerId) ?: throw NoSuchElementException("owner(id=$ownerId)") - } - - override val members: Items - get() = queryMembers() - - private fun queryMembers(): Items = flowItems { prop -> - // 批次 - val batchLimit = prop.batch.takeIf { it > 0 } ?: GetGuildMemberListApi.MAX_LIMIT - val flow = - GetGuildMemberListApi.createFlow(guildId = source.id, batch = batchLimit) { requestBy(baseBot) } - .let(prop::effectOn) - - emitAll(flow.map { m -> - QGMemberImpl( - bot = baseBot, - source = m, - guildId = this@QGGuildImpl.id, - sourceGuild = baseBot.checkIfTransmitCacheable(this@QGGuildImpl) - ) - }) - } - - override suspend fun member(id: ID): QGMemberImpl? = member(id.literal) - - internal suspend fun member(id: String): QGMemberImpl? = baseBot.member(source.id, id, this) - - @ExperimentalSimbotApi - override val roles: Items - get() = bot.effectedFlowItems { - GetGuildRoleListApi.create(source.id).requestBy(baseBot).roles.forEach { info -> - val roleImpl = QGGuildRoleImpl( - bot = baseBot, - guildId = id, - source = info, - sourceGuild = baseBot.checkIfTransmitCacheable(this@QGGuildImpl) - ) - - emit(roleImpl) - } - } - - - @ExperimentalSimbotApi - override fun roleCreator(): QGRoleCreator = QGRoleCreatorImpl(this) - - override val channels: Items - get() = baseBot.queryChannels(source.id, baseBot.checkIfTransmitCacheable(this)) - - - override suspend fun channel(id: ID): QGChannel? = - baseBot.channel(id.literal, this) - - override val categories: Items - get() = queryCategories() - - private fun queryCategories(): Items = effectedItemsByFlow { - baseBot.channelFlow(source.id) - .filter { it.type.isCategory } - .map { info -> - QGChannelCategoryImpl( - bot = bot, - source = info, - sourceGuild = this - ) - } - } - - override suspend fun category(id: ID): QGChannelCategory? { - val channel = channel(id) ?: return null - - return channel as? QGChannelCategory - ?: throw IllegalStateException("The type of channel(id=${channel.source.id}, name=${channel.source.name}) in guild(id=${source.id}, name=$name) is not category (${ChannelType.CATEGORY}), but ${channel.source.type}") - } - - @Volatile - private lateinit var _forums: QGForums - - override val forums: QGForums - get() { - if (::_forums.isInitialized) { - return _forums - } - - synchronized(this) { - if (::_forums.isInitialized) { - return _forums - } - - return initForums().also { - _forums = it - } - } - - } - - private fun initForums(): QGForums = QGForumsImpl(this) - - companion object { - internal fun qgGuild(bot: QGBotImpl, guild: Guild): QGGuildImpl { - val job: CompletableJob = SupervisorJob(bot.coroutineContext[Job]) - val coroutineContext: CoroutineContext = bot.coroutineContext + job - - return QGGuildImpl(bot, guild, coroutineContext) - } - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGMemberImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGMemberImpl.kt deleted file mode 100644 index 64a03292..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGMemberImpl.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.internal.message.asReceipt -import love.forte.simbot.component.qguild.internal.role.QGMemberRoleImpl -import love.forte.simbot.component.qguild.message.MessageParsers -import love.forte.simbot.component.qguild.message.QGMessageReceipt -import love.forte.simbot.component.qguild.message.QGReceiveMessageContent -import love.forte.simbot.component.qguild.message.sendMessage -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.message.Message -import love.forte.simbot.message.MessageContent -import love.forte.simbot.qguild.InternalApi -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.addStackTrace -import love.forte.simbot.qguild.api.message.MessageSendApi -import love.forte.simbot.qguild.api.message.direct.CreateDmsApi -import love.forte.simbot.qguild.api.message.direct.DmsSendApi -import love.forte.simbot.qguild.model.DirectMessageSession -import love.forte.simbot.utils.item.Items -import love.forte.simbot.utils.item.effectedFlowItems -import kotlin.coroutines.CoroutineContext -import love.forte.simbot.qguild.model.Member as QGSourceMember - -/** - * - * @author ForteScarlet - */ -internal class QGMemberImpl( - override val bot: QGBotImpl, - override val source: QGSourceMember, - private val guildId: ID, - private val sourceGuild: QGGuildImpl? = null -) : QGMember { - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - - private val user get() = source.user - - override val id: ID = user.id.ID - - @OptIn(ExperimentalSimbotApi::class) - override val joinTime: Timestamp - get() = source.joinedAt.toTimestamp() - - - override suspend fun guild(): QGGuildImpl = - sourceGuild ?: bot.guild(guildId) ?: throw NoSuchElementException("guild(id=$guildId)") - - private val roleIdSet = source.roles.toSet() - - private val dmsInitLock = Mutex() - - @Volatile - private lateinit var dms: DirectMessageSession - - private suspend fun getDms(): DirectMessageSession { - if (::dms.isInitialized) { - return dms - } else { - dmsInitLock.withLock { - if (::dms.isInitialized) { - return dms - } - return CreateDmsApi.create(user.id, guildId.literal).requestBy(bot).also { - dms = it - } - } - } - } - - @ExperimentalSimbotApi - override val roles: Items - get() { - return effectedFlowItems { - guild().roles.collect { - if (it.id.literal in roleIdSet) { - emit( - QGMemberRoleImpl( - guildRole = it, - memberId = this@QGMemberImpl.id, - sourceMember = bot.checkIfTransmitCacheable(this@QGMemberImpl) - ) - ) - } - } - } - } - - - @JvmSynthetic - override suspend fun send(message: Message): QGMessageReceipt { - val builder = MessageParsers.parse(message) - return send0(builder) - } - - override suspend fun send(text: String): QGMessageReceipt { - return bot.sendMessage(dms.guildId, text) - } - - - override suspend fun send(message: MessageContent): QGMessageReceipt { - if (message is QGReceiveMessageContent) { - val body = MessageSendApi.Body { - fromMessage(message.sourceMessage) - } - return send0(body) - } - - return send(message.messages) - } - - private suspend fun send0(body: MessageSendApi.Body): QGMessageReceipt { - val dms = getDms() - return DmsSendApi.create(dms.guildId, body).requestBy(bot).asReceipt() - } - - @OptIn(InternalApi::class) - private suspend fun send0(bodyList: List): QGMessageReceipt { - val dms = getDms() - - if (bodyList.size == 1) { - val body = bodyList[0].build() - return DmsSendApi.create(dms.guildId, body).requestBy(bot).asReceipt() - } - - return try { - bodyList.map { - DmsSendApi.create(dms.guildId, it.build()).requestBy(bot) - }.asReceipt() - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "member.send" } - } - } - - override fun toString(): String { - return "QGMemberImpl(id=$id, username=$username, nickname=$nickname, guildId=$guildId)" - } -} - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGNonTextChannelImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGNonTextChannelImpl.kt deleted file mode 100644 index 837e3603..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGNonTextChannelImpl.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGChannelCategoryId -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.QGNonTextChannel -import love.forte.simbot.qguild.InternalApi -import love.forte.simbot.qguild.model.Channel -import kotlin.coroutines.CoroutineContext - - -/** - * [QGNonTextChannel] 基本实现,用于包装那些非特殊实现的非文字子频道类型。 - * - * [QGNonTextChannelImpl] 类型作为 [QGNonTextChannel] 实现的默认替补,且不对外公开。 - * - * @author ForteScarlet - */ -@InternalApi -internal class QGNonTextChannelImpl( - override val bot: QGGuildBotImpl, - override val source: Channel, - private val sourceGuild: QGGuild? = null, - override val category: QGChannelCategoryId = QGChannelCategoryIdImpl( - bot = bot, - guildId = source.guildId.ID, - id = source.parentId.ID, - sourceGuild = sourceGuild, - ), -) : QGNonTextChannel { - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - override val id: ID = source.id.ID - override val guildId: ID = source.guildId.ID - override val ownerId: ID = source.ownerId.ID - - override suspend fun owner(): QGMember = guild().member(ownerId) ?: throw NoSuchElementException("owner(id=$ownerId)") - - override suspend fun guild(): QGGuild = - sourceGuild - ?: bot.guild(guildId) - ?: throw NoSuchElementException("guild(id=$guildId)") - - override fun toString(): String { - return "QGNonTextChannelImpl(id=$id, name=$name, category=$category)" - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGTextChannelImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGTextChannelImpl.kt deleted file mode 100644 index bc663569..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QGTextChannelImpl.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGChannelCategoryId -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.QGTextChannel -import love.forte.simbot.component.qguild.message.QGMessageReceipt -import love.forte.simbot.component.qguild.message.sendMessage -import love.forte.simbot.message.Message -import love.forte.simbot.message.MessageContent -import love.forte.simbot.qguild.InternalApi -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.addStackTrace -import kotlin.coroutines.CoroutineContext -import love.forte.simbot.qguild.model.Channel as QGSourceChannel - -/** - * - * @author ForteScarlet - */ -internal class QGTextChannelImpl internal constructor( - override val bot: QGGuildBotImpl, - override val source: QGSourceChannel, - private val sourceGuild: QGGuild? = null, - override val category: QGChannelCategoryId = QGChannelCategoryIdImpl( - bot = bot, - guildId = source.guildId.ID, - id = source.parentId.ID, - sourceGuild = sourceGuild, - ), - /** - * 如果是从一个事件而来,提供可用于消息回复的 msgId 来避免 event.channel().send(...) 出现问题 - */ - private val currentMsgId: String? = null, -) : QGTextChannel { - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - override val id: ID = source.id.ID - override val guildId: ID = source.guildId.ID - override val ownerId: ID = source.ownerId.ID - - override suspend fun guild(): QGGuild = - sourceGuild - ?: bot.guild(guildId) - ?: throw NoSuchElementException("guild(id=$guildId)") - - override suspend fun owner(): QGMember = - guild().member(ownerId) ?: throw NoSuchElementException("owner(id=$ownerId)") - - @OptIn(InternalApi::class) - override suspend fun send(message: Message): QGMessageReceipt { - return try { - bot.sendMessage(source.id, message) { - if (msgId == null) { - msgId = currentMsgId - } - } - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "channel.send" } - } - } - - @OptIn(InternalApi::class) - override suspend fun send(message: MessageContent): QGMessageReceipt { - return try { - bot.sendMessage(source.id, message) { - if (msgId == null) { - msgId = currentMsgId - } - } - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "channel.send" } - } - } - - @OptIn(InternalApi::class) - override suspend fun send(text: String): QGMessageReceipt { - return try { - bot.sendMessage(source.id, text) { - if (msgId == null) { - msgId = currentMsgId - } - } - } catch (e: QQGuildApiException) { - throw e.addStackTrace { "channel.send" } - } - } - - override fun toString(): String { - return "QGTextChannelImpl(id=$id, name=$name, category=$category)" - } -} - - - - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QQGuildBotManagerImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QQGuildBotManagerImpl.kt deleted file mode 100644 index 3d46d17a..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/QQGuildBotManagerImpl.kt +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2021-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal - -import kotlinx.coroutines.* -import love.forte.simbot.ID -import love.forte.simbot.bot.BotAlreadyRegisteredException -import love.forte.simbot.component.qguild.QGBot -import love.forte.simbot.component.qguild.QQGuildBotManager -import love.forte.simbot.component.qguild.QQGuildBotManagerConfiguration -import love.forte.simbot.component.qguild.QQGuildComponent -import love.forte.simbot.component.qguild.config.QGBotComponentConfiguration -import love.forte.simbot.component.qguild.event.QGBotRegisteredEvent -import love.forte.simbot.component.qguild.internal.event.QGBotRegisteredEventImpl -import love.forte.simbot.component.qguild.util.registerRootJob -import love.forte.simbot.event.EventProcessor -import love.forte.simbot.event.pushIfProcessable -import love.forte.simbot.logger.LoggerFactory -import love.forte.simbot.qguild.BotFactory -import org.slf4j.Logger -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.locks.ReentrantReadWriteLock -import kotlin.concurrent.read -import kotlin.concurrent.write -import kotlin.coroutines.CoroutineContext - -/** - * - * @author ForteScarlet - */ -internal class QQGuildBotManagerImpl( - override val eventProcessor: EventProcessor, - override val configuration: QQGuildBotManagerConfiguration, - override val component: QQGuildComponent, -) : QQGuildBotManager() { - companion object { - private val LOGGER = LoggerFactory.getLogger(QQGuildBotManagerImpl::class) - } - - private val job: CompletableJob - override val coroutineContext: CoroutineContext - - init { - val parentContext = configuration.parentCoroutineContext - val parentJob = parentContext[Job] - job = SupervisorJob(parentJob) - coroutineContext = parentContext + job - } - - override val logger: Logger - get() = LOGGER - - private val lock = ReentrantReadWriteLock() - - override val isActive: Boolean - get() = job.isActive - - override val isCancelled: Boolean - get() = job.isCompleted - - override val isStarted: Boolean - get() = job.isActive || job.isCompleted - - override fun invokeOnCompletion(handler: CompletionHandler) { - job.invokeOnCompletion(handler) - } - - override suspend fun join() { - job.join() - } - - // nothing to start - override suspend fun start(): Boolean { - return !job.isCompleted - } - - private var botMap = ConcurrentHashMap() - - - override suspend fun doCancel(reason: Throwable?): Boolean { - lock.write { - val cancelled = job.isCancelled - for (bot in botMap.values.toList()) { - bot.cancel(reason) - } - if (cancelled) { - return false - } - - if (reason != null) { - job.cancel(reason.localizedMessage, reason) - } else { - job.cancel() - } - job.join() - return true - } - } - - override fun get(id: ID): QGBot? { - lock.read { - if (job.isCancelled) throw IllegalStateException("This manager has already cancelled.") - - return botMap[id.toString()] - } - } - - override fun all(): List { - return botMap.values.toList() - } - - - override fun register( - appId: String, - appKey: String, - token: String, - block: QGBotComponentConfiguration.() -> Unit, - ): QGBot { - val configure = configuration.botConfigure - lock.write { - val config = QGBotComponentConfiguration().also(block) - val sourceBot = BotFactory.create(appId, appKey, token) { - configure(appId, appKey, token) - config.botConfigure.invoke(this) - - val customJob = coroutineContext[Job] - if (customJob == null) { - coroutineContext += job - } else { - customJob.registerRootJob(job) - } - } - // check botInfo - logger.info("Registered bot appId: {}", sourceBot.ticket.appId) - return botMap.compute(appId) { key, old -> - if (old != null) throw BotAlreadyRegisteredException(key) - - QGBotImpl(sourceBot, this, eventProcessor, component, config).apply { - job.invokeOnCompletion { - // remove self on completion - botMap.remove(key, this) - } - } - }!!.also { bot -> - bot.launch { - eventProcessor.pushIfProcessable(QGBotRegisteredEvent) { - QGBotRegisteredEventImpl(bot) - } - } - } - // return guildBot - } - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGAtMessageCreateEventImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGAtMessageCreateEventImpl.kt deleted file mode 100644 index e677d4c9..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGAtMessageCreateEventImpl.kt +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.event.QGAtMessageCreateEvent -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGMemberImpl -import love.forte.simbot.component.qguild.internal.QGTextChannelImpl -import love.forte.simbot.component.qguild.internal.message.QGReceiveMessageContentImpl -import love.forte.simbot.component.qguild.internal.toTimestamp -import love.forte.simbot.component.qguild.message.QGMessageReceipt -import love.forte.simbot.component.qguild.message.sendMessage -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.message.MessageContent -import love.forte.simbot.message.MessageReceipt -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.channel.GetChannelApi -import love.forte.simbot.qguild.api.member.GetMemberApi -import love.forte.simbot.qguild.ifNotFoundThenNoSuch -import love.forte.simbot.qguild.model.Message -import java.util.* - - -/** - * - * @author ForteScarlet - */ -internal class QGAtMessageCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Message -) : QGAtMessageCreateEvent() { - - @OptIn(ExperimentalSimbotApi::class) - override val timestamp: Timestamp get() = sourceEventEntity.timestamp.toTimestamp() - - override val id: ID get() = "${sourceEventEntity.guildId}.${sourceEventEntity.channelId}.${sourceEventEntity.id}.${Base64.getEncoder().encodeToString(sourceEventEntity.timestamp.toByteArray())}".ID - - override val messageContent: QGReceiveMessageContentImpl = QGReceiveMessageContentImpl(sourceEventEntity) - - - override suspend fun reply(message: love.forte.simbot.message.Message): QGMessageReceipt { - var ref: Message.Reference? = null - return bot.sendMessage(sourceEventEntity.channelId, message) { - if (msgId == null) { - msgId = sourceEventEntity.id - } - if (messageReference == null) { - messageReference = ref ?: Message.Reference(sourceEventEntity.id).also { ref = it } - } - } - } - - override suspend fun reply(message: MessageContent): MessageReceipt { - var ref: Message.Reference? = null - return bot.sendMessage(sourceEventEntity.channelId, message) { - if (msgId == null) { - msgId = sourceEventEntity.id - } - if (messageReference == null) { - messageReference = ref ?: Message.Reference(sourceEventEntity.id).also { ref = it } - } - } - } - - override suspend fun reply(text: String): MessageReceipt { - var ref: Message.Reference? = null - return bot.sendMessage(sourceEventEntity.channelId, text) { - if (msgId == null) { - msgId = sourceEventEntity.id - } - if (messageReference == null) { - messageReference = ref ?: Message.Reference(sourceEventEntity.id).also { ref = it } - } - } - } - - override suspend fun author(): QGMemberImpl { - val member = - try { - GetMemberApi.create(sourceEventEntity.guildId, sourceEventEntity.author.id).requestBy(bot) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNoSuch { "member(id=${sourceEventEntity.author.id})" } - } - - return QGMemberImpl(bot, member, sourceEventEntity.guildId.ID) - } - - override suspend fun channel(): QGTextChannelImpl { - val channel = - try { - GetChannelApi.create(sourceEventEntity.channelId).requestBy(bot) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNoSuch { "channel(id=${sourceEventEntity.channelId})" } - } - - return QGTextChannelImpl( - bot = bot.inGuild(sourceEventEntity.guildId), - source = channel, - currentMsgId = sourceEventEntity.id - ) - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGChannelEventImpls.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGChannelEventImpls.kt deleted file mode 100644 index 93504c36..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGChannelEventImpls.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGTextChannel -import love.forte.simbot.component.qguild.event.QGChannelCreateEvent -import love.forte.simbot.component.qguild.event.QGChannelDeleteEvent -import love.forte.simbot.component.qguild.event.QGChannelUpdateEvent -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGTextChannelImpl -import love.forte.simbot.qguild.event.EventChannel - - -internal class QGChannelCreateEventImpl( - override val eventRaw: String, - override val sourceEventEntity: EventChannel, - override val bot: QGBotImpl, - private val _channel: QGTextChannelImpl, -) : QGChannelCreateEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = tcgChannelModifyId(0, bot.id, sourceEventEntity.id, currentTimeMillis, this.hashCode()) - override suspend fun channel(): QGTextChannel = _channel - override suspend fun source(): QGGuild = _channel.guild() -} - - -internal class QGChannelUpdateEventImpl( - override val eventRaw: String, - override val sourceEventEntity: EventChannel, - override val bot: QGBotImpl, - private val _channel: QGTextChannelImpl, -) : QGChannelUpdateEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = tcgChannelModifyId(1, bot.id, sourceEventEntity.id, currentTimeMillis, this.hashCode()) - override suspend fun channel(): QGTextChannel = _channel - override suspend fun source(): QGGuild = _channel.guild() -} - - -internal class QGChannelDeleteEventImpl( - override val eventRaw: String, - override val sourceEventEntity: EventChannel, - override val bot: QGBotImpl, - private val _channel: QGTextChannelImpl -) : QGChannelDeleteEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = tcgChannelModifyId(2, bot.id, sourceEventEntity.id, currentTimeMillis, this.hashCode()) - override suspend fun channel(): QGTextChannel = _channel - override suspend fun source(): QGGuild = _channel.guild() -} - -//internal class QGChannelCategoryCreateEventImpl( -// override val eventRaw: String, -// override val sourceEventEntity: EventChannel, -// override val bot: QGBotImpl, -// private val _category: QGChannelCategoryImpl, -// private val _guild: QGGuildImpl, -//) : QGChannelCategoryCreateEvent() { -// override val id: ID = tcgChannelModifyId(3, bot.id, sourceEventEntity.id, changedTime) -// override val operatorId: ID = sourceEventEntity.opUserId.ID -// override suspend fun category(): QGChannelCategory = _category -// override suspend fun guild(): QGGuild = _guild -//} -// -// -//internal class QGChannelCategoryUpdateEventImpl( -// override val eventRaw: String, -// override val sourceEventEntity: EventChannel, -// override val bot: QGBotImpl, -// private val _category: QGChannelCategoryImpl, -// private val _guild: QGGuildImpl, -//) : QGChannelCategoryUpdateEvent() { -// override val id: ID = tcgChannelModifyId(4, bot.id, sourceEventEntity.id, changedTime) -// override val operatorId: ID = sourceEventEntity.opUserId.ID -// override suspend fun category(): QGChannelCategory = _category -// override suspend fun guild(): QGGuild = _guild -//} -// -// -//internal class QGChannelCategoryDeleteEventImpl( -// override val eventRaw: String, -// override val sourceEventEntity: EventChannel, -// override val bot: QGBotImpl, -// private val _guild: QGGuildImpl, -//) : QGChannelCategoryDeleteEvent() { -// override val id: ID = tcgChannelModifyId(5, bot.id, sourceEventEntity.id, changedTime) -// override val operatorId: ID = sourceEventEntity.opUserId.ID -// override suspend fun guild(): QGGuildImpl = _guild -// -//} - - -private fun tcgChannelModifyId(t: Int, sourceBot: ID, sourceChannel: String, timestamp: Long, hash: Int): ID = - "$t$sourceBot.$timestamp.$sourceChannel.$hash".ID diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGForumEventImpls.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGForumEventImpls.kt deleted file mode 100644 index dd40e4dc..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGForumEventImpls.kt +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.event.* -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.forum.QGPost -import love.forte.simbot.component.qguild.forum.QGReply -import love.forte.simbot.component.qguild.forum.QGThread -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.forum.QGPostImpl -import love.forte.simbot.component.qguild.internal.forum.QGReplyImpl -import love.forte.simbot.component.qguild.internal.forum.QGThreadImpl -import love.forte.simbot.delegate.getValue -import love.forte.simbot.delegate.stringID -import love.forte.simbot.delegate.timestamp -import love.forte.simbot.qguild.model.forum.AuditResult -import love.forte.simbot.qguild.model.forum.Post -import love.forte.simbot.qguild.model.forum.Reply -import love.forte.simbot.qguild.model.forum.Thread - -internal class QGForumThreadCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Thread -) : QGForumThreadCreateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val thread: QGThread = QGThreadImpl(bot, sourceEventEntity, null) -} - - -internal class QGForumThreadUpdateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Thread -) : QGForumThreadUpdateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val thread: QGThread = QGThreadImpl(bot, sourceEventEntity, null) -} - - -internal class QGForumThreadDeleteEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Thread -) : QGForumThreadDeleteEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val thread: QGThread = QGThreadImpl(bot, sourceEventEntity, null) -} - - -internal class QGForumPostCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Post -) : QGForumPostCreateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val post: QGPost = QGPostImpl(bot, sourceEventEntity, null) -} - -internal class QGForumPostDeleteEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Post -) : QGForumPostDeleteEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val post: QGPost = QGPostImpl(bot, sourceEventEntity, null) -} - -internal class QGForumReplyCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Reply -) : QGForumReplyCreateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val post: QGReply = QGReplyImpl(bot, sourceEventEntity, null) -} - -internal class QGForumReplyDeleteEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: Reply -) : QGForumReplyDeleteEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) - - override val post: QGReply = QGReplyImpl(bot, sourceEventEntity, null) -} - -internal class QGForumPublishAuditResultEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: AuditResult, -) : QGForumPublishAuditResultEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = - bot.forumChannel(sourceEventEntity) - - override suspend fun author(): QGMember = - bot.author(sourceEventEntity) -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGGuildEventImpls.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGGuildEventImpls.kt deleted file mode 100644 index 6a436bd6..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGGuildEventImpls.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.FragileSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.event.QGGuildCreateEvent -import love.forte.simbot.component.qguild.event.QGGuildDeleteEvent -import love.forte.simbot.component.qguild.event.QGGuildUpdateEvent -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.qguild.event.EventGuild - -internal class QGGuildCreateEventImpl( - override val eventRaw: String, - override val sourceEventEntity: EventGuild, - override val bot: QGBotImpl, - private val _guild: QGGuildImpl, -) : QGGuildCreateEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = tcgGuildModifyId(0, bot.id, sourceEventEntity.id, currentTimeMillis, hashCode()) - override suspend fun guild(): QGGuild = _guild -} - - -internal class QGGuildUpdateEventImpl( - override val eventRaw: String, - override val sourceEventEntity: EventGuild, - override val bot: QGBotImpl, - private val _guild: QGGuildImpl, -) : QGGuildUpdateEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = tcgGuildModifyId(1, bot.id, sourceEventEntity.id, currentTimeMillis, hashCode()) - override suspend fun guild(): QGGuild = _guild -} - - -internal class QGGuildDeleteEventImpl( - override val eventRaw: String, - override val sourceEventEntity: EventGuild, - override val bot: QGBotImpl, - private val _guild: QGGuildImpl?, -) : QGGuildDeleteEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = tcgGuildModifyId(2, bot.id, sourceEventEntity.id, currentTimeMillis, hashCode()) - @FragileSimbotApi - override val guild: QGGuild? get() = _guild -} - - -private fun tcgGuildModifyId(t: Int, sourceBot: ID, sourceGuild: String, timestamp: Long, hash: Int): ID = - "$t$sourceBot.$timestamp.$sourceGuild.$hash".ID diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGInternalBotEventImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGInternalBotEventImpl.kt deleted file mode 100644 index f0a32e7e..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGInternalBotEventImpl.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.event.QGBotRegisteredEvent -import love.forte.simbot.component.qguild.event.QGBotStartedEvent -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.delegate.getValue -import love.forte.simbot.delegate.stringID -import love.forte.simbot.delegate.timestamp - - -internal class QGBotRegisteredEventImpl(override val bot: QGBotImpl) : QGBotRegisteredEvent() { - override val timestamp: Timestamp by timestamp { now } - override val id: ID by stringID { random } -} - -internal class QGBotStartedEventImpl(override val bot: QGBotImpl) : QGBotStartedEvent() { - override val timestamp: Timestamp by timestamp { now } - override val id: ID by stringID { random } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGMemberEventImpls.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGMemberEventImpls.kt deleted file mode 100644 index e9e7fcb2..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGMemberEventImpls.kt +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.action.ActionType -import love.forte.simbot.component.qguild.QGBot -import love.forte.simbot.component.qguild.event.QGMemberAddEvent -import love.forte.simbot.component.qguild.event.QGMemberRemoveEvent -import love.forte.simbot.component.qguild.event.QGMemberUpdateEvent -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.internal.QGMemberImpl -import love.forte.simbot.qguild.InternalApi -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.addStackTrace -import love.forte.simbot.qguild.event.EventMember -import love.forte.simbot.qguild.isUnauthorized - - -internal class QGMemberAddEventImpl( - override val bot: QGBot, - override val eventRaw: String, - override val sourceEventEntity: EventMember, - private val _member: QGMemberImpl, -) : QGMemberAddEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val actionType: ActionType - get() = if (sourceEventEntity.opUserId == sourceEventEntity.user.id) ActionType.PROACTIVE else ActionType.PASSIVE - - override val id: ID get() = memberEventId(0, bot.id, sourceEventEntity.user.id, currentTimeMillis, hashCode()) - override suspend fun member(): QGMemberImpl = _member - @OptIn(InternalApi::class) - override suspend fun operator(): QGMemberImpl? { - return try { - guild().member(sourceEventEntity.opUserId) - } catch (apiEx: QQGuildApiException) { - // process no auth - if (apiEx.isUnauthorized) null else throw apiEx.addStackTrace() - } - } - - override suspend fun guild(): QGGuildImpl = _member.guild() -} - -internal class QGMemberUpdateEventImpl( - override val bot: QGBot, - override val eventRaw: String, - override val sourceEventEntity: EventMember, - private val _member: QGMemberImpl, -) : QGMemberUpdateEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val id: ID get() = memberEventId(1, bot.id, sourceEventEntity.user.id, currentTimeMillis, hashCode()) - override suspend fun member(): QGMemberImpl = _member - @OptIn(InternalApi::class) - override suspend fun operator(): QGMemberImpl? { - return try { - guild().member(sourceEventEntity.opUserId) - } catch (apiEx: QQGuildApiException) { - // process no auth - if (apiEx.isUnauthorized) null else throw apiEx.addStackTrace() - } - } - - override suspend fun guild(): QGGuildImpl = _member.guild() -} - -internal class QGMemberRemoveEventImpl( - override val bot: QGBot, - override val eventRaw: String, - override val sourceEventEntity: EventMember, - private val _member: QGMemberImpl, -) : QGMemberRemoveEvent() { - private val currentTimeMillis = System.currentTimeMillis() - override val changedTime: Timestamp get() = Timestamp.byMillisecond(currentTimeMillis) - override val actionType: ActionType - get() = if (sourceEventEntity.opUserId == sourceEventEntity.user.id) ActionType.PROACTIVE else ActionType.PASSIVE - - override val id: ID get() = memberEventId(2, bot.id, sourceEventEntity.user.id, currentTimeMillis, hashCode()) - override suspend fun member(): QGMemberImpl = _member - @OptIn(InternalApi::class) - override suspend fun operator(): QGMemberImpl? { - return try { - guild().member(sourceEventEntity.opUserId) - } catch (apiEx: QQGuildApiException) { - // process no auth - if (apiEx.isUnauthorized) null else throw apiEx.addStackTrace() - } - } - - override suspend fun guild(): QGGuildImpl = _member.guild() -} - -private fun memberEventId(t: Int, sourceBot: ID, sourceUserId: String, timestamp: Long, hash: Int): ID = - "$t$sourceBot.$timestamp.$sourceUserId.$hash".ID diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGOpenForumEventImpls.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGOpenForumEventImpls.kt deleted file mode 100644 index 8399f046..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGOpenForumEventImpls.kt +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.ID -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.event.* -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.forum.asForumChannel -import love.forte.simbot.delegate.getValue -import love.forte.simbot.delegate.stringID -import love.forte.simbot.delegate.timestamp -import love.forte.simbot.qguild.event.OpenForumPostData -import love.forte.simbot.qguild.event.OpenForumReplyData -import love.forte.simbot.qguild.event.OpenForumThreadData -import love.forte.simbot.qguild.model.forum.ForumSourceInfo - - -internal suspend fun QGBotImpl.forumChannel(data: ForumSourceInfo): QGForumChannel { - val channel = channel(data.channelId, null) - ?: throw NoSuchElementException("channel(id=${data.channelId})") - - return channel.asForumChannel(channel.source) -} - -internal suspend fun QGBotImpl.author(data: ForumSourceInfo): QGMember = - member(data.guildId, data.authorId, null) - ?: throw NoSuchElementException("member(id=${data.authorId})") - -internal class QGOpenForumThreadCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumThreadData, -) : QGOpenForumThreadCreateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} - -internal class QGOpenForumThreadUpdateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumThreadData, -) : QGOpenForumThreadUpdateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} - -internal class QGOpenForumThreadDeleteEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumThreadData, -) : QGOpenForumThreadDeleteEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} - - -internal class QGOpenForumPostCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumPostData, -) : QGOpenForumPostCreateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} - -internal class QGOpenForumPostDeleteEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumPostData, -) : QGOpenForumPostDeleteEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} - -internal class QGOpenForumReplyCreateEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumReplyData, -) : QGOpenForumReplyCreateEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} - -internal class QGOpenForumReplyDeleteEventImpl( - override val bot: QGBotImpl, - override val eventRaw: String, - override val sourceEventEntity: OpenForumReplyData, -) : QGOpenForumReplyDeleteEvent() { - override val id: ID by stringID { random } - override val timestamp: Timestamp by timestamp { now } - - override suspend fun channel(): QGForumChannel = bot.forumChannel(sourceEventEntity) - override suspend fun author(): QGMember = bot.author(sourceEventEntity) -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGUnsupportedEventImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGUnsupportedEventImpl.kt deleted file mode 100644 index b5531704..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/event/QGUnsupportedEventImpl.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.event - -import love.forte.simbot.FragileSimbotApi -import love.forte.simbot.component.qguild.QGBot -import love.forte.simbot.component.qguild.event.QGUnsupportedEvent -import love.forte.simbot.qguild.event.Signal - - -/** - * - * @author ForteScarlet - */ -@OptIn(FragileSimbotApi::class) -internal data class QGUnsupportedEventImpl( - override val bot: QGBot, - override val sourceEventEntity: Signal.Dispatch, - override val eventRaw: String -) : QGUnsupportedEvent() diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGForumChannelImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGForumChannelImpl.kt deleted file mode 100644 index 438a8e99..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGForumChannelImpl.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.forum - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGChannel -import love.forte.simbot.component.qguild.QGChannelCategoryId -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.forum.QGThread -import love.forte.simbot.component.qguild.forum.QGThreadCreator -import love.forte.simbot.component.qguild.internal.QGChannelCategoryIdImpl -import love.forte.simbot.component.qguild.internal.QGGuildBotImpl -import love.forte.simbot.component.qguild.internal.newSupervisorCoroutineContext -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.forum.GetThreadApi -import love.forte.simbot.qguild.api.forum.GetThreadListApi -import love.forte.simbot.qguild.ifNotFoundThenNull -import love.forte.simbot.qguild.model.Channel -import love.forte.simbot.qguild.model.ChannelType -import love.forte.simbot.qguild.model.forum.Thread -import love.forte.simbot.utils.item.Items -import love.forte.simbot.utils.item.effectedItemsByFlow -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -internal class QGForumChannelImpl( - override val bot: QGGuildBotImpl, - override val source: Channel, - internal val sourceGuild: QGGuild?, - override val category: QGChannelCategoryId = QGChannelCategoryIdImpl( - bot = bot, - guildId = source.guildId.ID, - id = source.parentId.ID, - sourceGuild = sourceGuild, - ), -) : QGForumChannel { - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - override val id: ID = source.id.ID - override val guildId: ID = source.guildId.ID - override val ownerId: ID = source.ownerId.ID - - override suspend fun owner(): QGMember = - guild().member(ownerId) ?: throw NoSuchElementException("owner(id=$ownerId)") - - override suspend fun guild(): QGGuild = - sourceGuild ?: bot.guild(guildId) ?: throw NoSuchElementException("guild(id=$guildId)") - - private fun threadFlow(): Flow = flow { - GetThreadListApi.create(source.id).requestBy(bot).threads.forEach { - emit(it) - } - } - - override val threads: Items - get() = effectedItemsByFlow { - threadFlow().map { it.toQGThread() } - } - - override suspend fun thread(id: ID): QGThread? { - return try { - GetThreadApi.create(source.id, id.literal).requestBy(bot).thread.toQGThread() - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNull() - } - } - - private fun Thread.toQGThread(): QGThread = QGThreadImpl(bot.bot, this, this@QGForumChannelImpl) - - override fun threadCreator(): QGThreadCreator = QGThreadCreatorImpl(this) - - override fun toString(): String { - return "QGForumChannelImpl(id=$id, name=$name, category=$category)" - } -} - -/** - * @throws IllegalStateException Can't as [QGForumChannel] - */ -internal fun QGChannel.asForumChannel(source: Channel = this.source): QGForumChannel = - this as? QGForumChannel - ?: throw IllegalStateException("The type of channel(id=${source.id}, name=${source.name}) in guild(id=${source.guildId}) is not category (${ChannelType.CATEGORY}), but ${source.type}") - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGForumsImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGForumsImpl.kt deleted file mode 100644 index 77a93b9c..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGForumsImpl.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.forum - -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.map -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGBot -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.forum.QGForums -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.internal.newSupervisorCoroutineContext -import love.forte.simbot.qguild.model.ChannelType -import love.forte.simbot.utils.item.Items -import love.forte.simbot.utils.item.effectedItemsByFlow -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -internal class QGForumsImpl( - private val sourceGuild: QGGuildImpl, -) : QGForums { - override val coroutineContext: CoroutineContext = sourceGuild.newSupervisorCoroutineContext() - override val bot: QGBot get() = sourceGuild.baseBot - - override suspend fun guild(): QGGuild = sourceGuild - - override val forumChannels: Items - get() = effectedItemsByFlow { - sourceGuild.baseBot.channelFlowWithCategoryId(sourceGuild.source.id, sourceGuild) - .filter { (info, _) -> - info.type == ChannelType.FORUM - }.map { (info, category) -> - QGForumChannelImpl( - bot = sourceGuild.bot, - source = info, - sourceGuild = sourceGuild.baseBot.checkIfTransmitCacheable(sourceGuild), - category = category - ) - } - } - - override suspend fun forumChannel(id: ID): QGForumChannel? { - val channel = sourceGuild.channel(id) ?: return null - - return channel.asForumChannel(channel.source) - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGPostImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGPostImpl.kt deleted file mode 100644 index 6c0617b5..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGPostImpl.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.forum - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.forum.QGPost -import love.forte.simbot.component.qguild.forum.QGThread -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.internal.toTimestamp -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.forum.GetThreadApi -import love.forte.simbot.qguild.ifNotFoundThenNoSuch -import love.forte.simbot.qguild.model.forum.Post - -/** - * - * @author ForteScarlet - */ -internal class QGPostImpl( - override val bot: QGBotImpl, - override val source: Post, - private val sourceChannel: QGForumChannelImpl? -) : QGPost { - - @OptIn(ExperimentalSimbotApi::class) - override val datetime: Timestamp = source.postInfo.dateTime.toTimestamp() - - override suspend fun guild(): QGGuild = - sourceChannel?.guild() - ?: bot.queryGuild(source.guildId) - ?: throw NoSuchElementException("guild(id=${source.guildId})") - - - override suspend fun channel(): QGForumChannel = - sourceChannel - ?: (bot.channel(source.channelId, null) - ?: throw NoSuchElementException("channel(id=${source.channelId})")).asForumChannel() - - override suspend fun author(): QGMember = - bot.member(source.guildId, source.authorId, sourceChannel?.sourceGuild as? QGGuildImpl) ?: throw NoSuchElementException("author(id=$authorId)") - - override suspend fun thread(): QGThread { - val (thread) = try { - GetThreadApi.create(source.channelId, source.postInfo.threadId).requestBy(bot) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNoSuch { "thread(id=${source.postInfo.threadId}) by post(id=${source.postInfo.postId})" } - } - - return QGThreadImpl(bot, thread, sourceChannel) - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGReplyImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGReplyImpl.kt deleted file mode 100644 index 1dc84b04..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGReplyImpl.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.forum - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.forum.QGReply -import love.forte.simbot.component.qguild.forum.QGThread -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.internal.toTimestamp -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.forum.GetThreadApi -import love.forte.simbot.qguild.ifNotFoundThenNoSuch -import love.forte.simbot.qguild.model.forum.Reply - -/** - * - * @author ForteScarlet - */ -internal class QGReplyImpl( - override val bot: QGBotImpl, - override val source: Reply, - private val sourceChannel: QGForumChannelImpl? -) : QGReply { - @OptIn(ExperimentalSimbotApi::class) - override val datetime: Timestamp = source.replyInfo.dateTime.toTimestamp() - - override suspend fun guild(): QGGuild = - sourceChannel?.guild() - ?: bot.queryGuild(source.guildId) - ?: throw NoSuchElementException("guild(id=${source.guildId})") - - - override suspend fun channel(): QGForumChannel = - sourceChannel - ?: (bot.channel(source.channelId, null) - ?: throw NoSuchElementException("channel(id=${source.channelId})")).asForumChannel() - - - override suspend fun author(): QGMember = - bot.member(source.guildId, source.authorId, sourceChannel?.sourceGuild as? QGGuildImpl) ?: throw NoSuchElementException("author(id=$authorId)") - - override suspend fun thread(): QGThread { - val (thread) = try { - GetThreadApi.create(source.channelId, source.replyInfo.threadId).requestBy(bot) - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThenNoSuch { "thread(id=${source.replyInfo.threadId}) by reply(id=${source.replyInfo.replyId})" } - } - - return QGThreadImpl(bot, thread, sourceChannel) - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGThreadCreatorImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGThreadCreatorImpl.kt deleted file mode 100644 index f0eea50f..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGThreadCreatorImpl.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.forum - -import love.forte.simbot.component.qguild.forum.QGThreadCreator -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.qguild.api.forum.PublishThreadApi -import love.forte.simbot.qguild.api.forum.ThreadPublishFormat -import love.forte.simbot.qguild.api.forum.ThreadPublishResult - - -/** - * - * @author ForteScarlet - */ -internal class QGThreadCreatorImpl(private val channel: QGForumChannelImpl) : QGThreadCreator { - override var title: String? = null - override var content: String? = null - override var format: Int? = null - override var formatType: ThreadPublishFormat? - get() = format?.let { ThreadPublishFormat.values().find { f -> f.value == it } } - set(value) { - format = value?.value - } - - override suspend fun publish(): ThreadPublishResult { - return PublishThreadApi.create( - channelId = channel.source.id, - title = title ?: throw IllegalArgumentException("Required property 'title' is null"), - content = content ?: throw IllegalArgumentException("Required property 'content' is null"), - format = format ?: throw IllegalArgumentException("Required property 'format' is null"), - ).requestBy(channel.bot) - } - - override fun toString(): String { - return "QGThreadCreatorImpl(title=$title, content=$content, format=$format, formatType=$formatType)" - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGThreadImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGThreadImpl.kt deleted file mode 100644 index 6ab720f2..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/forum/QGThreadImpl.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.forum - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.Timestamp -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.forum.QGForumChannel -import love.forte.simbot.component.qguild.forum.QGThread -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.internal.newSupervisorCoroutineContext -import love.forte.simbot.component.qguild.internal.toTimestamp -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.forum.DeleteThreadApi -import love.forte.simbot.qguild.ifNotFoundThen -import love.forte.simbot.qguild.model.forum.Thread -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -internal class QGThreadImpl( - override val bot: QGBotImpl, - override val source: Thread, - private val sourceChannel: QGForumChannelImpl?, -) : QGThread { - - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - - override suspend fun guild(): QGGuild = - sourceChannel?.guild() - ?: bot.queryGuild(source.guildId) - ?: throw NoSuchElementException("guild(id=${source.guildId})") - - override suspend fun author(): QGMember = - bot.member(source.guildId, source.authorId, sourceChannel?.sourceGuild as? QGGuildImpl) ?: throw NoSuchElementException("author(id=$authorId)") - - @OptIn(ExperimentalSimbotApi::class) - override val dateTime: Timestamp - get() = source.threadInfo.dateTime.toTimestamp() - - override suspend fun channel(): QGForumChannel { - if (sourceChannel != null) { - return sourceChannel - } - - val channel = bot.channel(source.channelId, null) - ?: throw NoSuchElementException("channel(id=${source.channelId})") - - return channel.asForumChannel() - } - - override suspend fun delete(): Boolean { - return try { - DeleteThreadApi.create(source.channelId, source.threadInfo.threadId).requestBy(bot) - true - } catch (apiEx: QQGuildApiException) { - apiEx.ifNotFoundThen { false } - } - } - - override fun toString(): String { - return "QGThreadImpl(id=${source.threadInfo.threadId}, title=$title, channelId=${source.channelId})" - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/message/QGReceiveMessageContentImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/message/QGReceiveMessageContentImpl.kt deleted file mode 100644 index a67dc610..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/message/QGReceiveMessageContentImpl.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.message - -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.message.MessageParsers -import love.forte.simbot.component.qguild.message.QGReceiveMessageContent -import love.forte.simbot.message.Messages -import love.forte.simbot.qguild.model.Message - -/** - * - * @author ForteScarlet - */ -internal class QGReceiveMessageContentImpl(override val sourceMessage: Message) : QGReceiveMessageContent() { - - override val messageId: ID get() = sourceMessage.id.ID - - private val parseContext by lazy(LazyThreadSafetyMode.PUBLICATION) { MessageParsers.parse(sourceMessage) } - - override val messages: Messages get() = parseContext.messages - - override val plainText: String by lazy(LazyThreadSafetyMode.PUBLICATION) { - parseContext.plainTextBuilder.toString() - } - - override fun toString(): String { - return "QGReceiveMessageContentImpl(messageId=${sourceMessage.id}, sourceMessage=$sourceMessage)" - } - - - override fun equals(other: Any?): Boolean { - if (other !is QGReceiveMessageContent) return false - if (other === this) return true - return sourceMessage.id == other.sourceMessage.id - } - - override fun hashCode(): Int = sourceMessage.id.hashCode() -} - diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/message/QGSingleMessageReceiptImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/message/QGSingleMessageReceiptImpl.kt deleted file mode 100644 index cf21e397..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/message/QGSingleMessageReceiptImpl.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.message - -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.message.QGAggregatedMessageReceipt -import love.forte.simbot.component.qguild.message.QGSingleMessageReceipt -import love.forte.simbot.qguild.model.Message - - -private class QGSingleMessageReceiptImpl(override val messageResult: Message) : QGSingleMessageReceipt() { - override val id: ID = messageResult.id.ID -} - -@PublishedApi -internal fun Message.asReceipt(): QGSingleMessageReceipt = QGSingleMessageReceiptImpl(this) - - -private class QGAggregatedMessageReceiptImpl(private val messages: List) : QGAggregatedMessageReceipt() { - override val size: Int get() = messages.size - - override fun get(index: Int): QGSingleMessageReceipt = messages[index] - - override fun iterator(): Iterator = messages.iterator() -} - -internal fun Iterable.asReceipt(): QGAggregatedMessageReceipt = QGAggregatedMessageReceiptImpl(this.map { QGSingleMessageReceiptImpl(it) }) diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/BaseQGRole.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/BaseQGRole.kt deleted file mode 100644 index fbe56485..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/BaseQGRole.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.role - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.component.qguild.QGBot -import love.forte.simbot.component.qguild.QGRole -import love.forte.simbot.qguild.model.Role - - -/** - * - * @author ForteScarlet - */ -@ExperimentalSimbotApi -internal abstract class BaseQGRole : QGRole { - abstract val bot: QGBot - abstract override var source: Role -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGGuildRoleImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGGuildRoleImpl.kt deleted file mode 100644 index 04e4ff84..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGGuildRoleImpl.kt +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.role - -import kotlinx.coroutines.flow.map -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.internal.QGMemberImpl -import love.forte.simbot.component.qguild.internal.newSupervisorCoroutineContext -import love.forte.simbot.component.qguild.role.QGGuildRole -import love.forte.simbot.component.qguild.role.QGRoleUpdater -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.qguild.api.member.GetGuildRoleMemberListApi -import love.forte.simbot.qguild.api.member.createFlow -import love.forte.simbot.qguild.api.role.AddMemberRoleApi -import love.forte.simbot.qguild.api.role.DeleteGuildRoleApi -import love.forte.simbot.qguild.model.Role -import love.forte.simbot.utils.item.Items -import love.forte.simbot.utils.item.effectOn -import love.forte.simbot.utils.item.itemsByFlow -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -@OptIn(ExperimentalSimbotApi::class) -internal class QGGuildRoleImpl( - override val bot: QGBotImpl, - override val guildId: ID, - @Volatile override var source: Role, - private val sourceGuild: QGGuildImpl? = null -) : BaseQGRole(), QGGuildRole { - override val coroutineContext: CoroutineContext = bot.newSupervisorCoroutineContext() - override val id: ID = source.id.ID - - override suspend fun guild(): QGGuild = - sourceGuild - ?: bot.guild(guildId) - ?: throw NoSuchElementException("Guild($guildId)") - - override fun updater(): QGRoleUpdater = QGRoleUpdaterImpl(this) - - override suspend fun grantTo(memberId: ID): QGMemberRoleImpl = grantTo0(memberId, null) - - override suspend fun grantTo(member: QGMember): QGMemberRoleImpl = grantTo0(member, null) - - override suspend fun grantTo(memberId: ID, channelId: ID): QGMemberRoleImpl = grantTo0(memberId, channelId.literal) - - override suspend fun grantTo(member: QGMember, channelId: ID): QGMemberRoleImpl = - grantTo0(member, channelId.literal) - - private suspend fun grantTo0(memberId: ID, channelId: String?): QGMemberRoleImpl { - AddMemberRoleApi.create(guildId.literal, memberId.literal, id.literal, channelId).requestBy(bot) - return QGMemberRoleImpl(this, memberId, null) - } - - private suspend fun grantTo0(member: QGMember, channelId: String?): QGMemberRoleImpl { - AddMemberRoleApi.create(guildId.literal, member.id.literal, id.literal, channelId).requestBy(bot) - return QGMemberRoleImpl(this, member.id, member) - } - - override suspend fun delete(): Boolean { - DeleteGuildRoleApi.create(guildId.literal, source.id).requestBy(bot) - return true - } - - override val members: Items - get() { - val guildId = guildId - val guildIdLiteral = guildId.literal - val roleId = source.id - - return itemsByFlow { prop -> - GetGuildRoleMemberListApi.createFlow( - guildIdLiteral, - roleId, - prop.batch.takeIf { it < 1 } ?: GetGuildRoleMemberListApi.MAX_LIMIT - ) { requestBy(bot) } - .let(prop::effectOn) - .map { - QGMemberImpl( - bot = bot, - source = it, - guildId = guildId, - sourceGuild = this.sourceGuild - ) - } - } - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGMemberRoleImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGMemberRoleImpl.kt deleted file mode 100644 index b3a33d96..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGMemberRoleImpl.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.role - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.ID -import love.forte.simbot.component.qguild.QGGuild -import love.forte.simbot.component.qguild.QGMember -import love.forte.simbot.component.qguild.internal.QGBotImpl -import love.forte.simbot.component.qguild.internal.QGMemberImpl -import love.forte.simbot.component.qguild.internal.newSupervisorCoroutineContext -import love.forte.simbot.component.qguild.role.QGMemberRole -import love.forte.simbot.component.qguild.role.QGRoleUpdater -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.qguild.api.member.GetMemberApi -import love.forte.simbot.qguild.api.role.RemoveMemberRoleApi -import love.forte.simbot.qguild.model.Role -import kotlin.coroutines.CoroutineContext - - -/** - * - * @author ForteScarlet - */ -@OptIn(ExperimentalSimbotApi::class) -internal class QGMemberRoleImpl( - override val guildRole: QGGuildRoleImpl, - override val memberId: ID, - private val sourceMember: QGMember?, -) : BaseQGRole(), QGMemberRole { - override val coroutineContext: CoroutineContext = guildRole.bot.newSupervisorCoroutineContext() - - override val id: ID get() = guildRole.id - - override val guildId: ID - get() = guildRole.guildId - - override val bot: QGBotImpl - get() = guildRole.bot - - override var source: Role - get() = guildRole.source - set(value) { - guildRole.source = value - } - - override suspend fun guild(): QGGuild = guildRole.guild() - override fun updater(): QGRoleUpdater = guildRole.updater() - override suspend fun member(): QGMember { - return sourceMember ?: GetMemberApi.create(guildId.literal, memberId.literal).requestBy(bot) - .let { QGMemberImpl(bot, it, guildId) } - } - - override suspend fun delete(): Boolean = delete0(null) - override suspend fun delete(channelId: ID): Boolean = delete0(channelId.literal) - - private suspend fun delete0(channelId: String?): Boolean { - RemoveMemberRoleApi.create(guildId.literal, memberId.literal, id.literal, channelId).requestBy(bot) - return true - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGRoleCreatorImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGRoleCreatorImpl.kt deleted file mode 100644 index 4eb0748a..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGRoleCreatorImpl.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.role - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.component.qguild.internal.QGGuildImpl -import love.forte.simbot.component.qguild.role.QGGuildRole -import love.forte.simbot.component.qguild.role.QGRoleCreator -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.qguild.api.role.CreateGuildRoleApi -import love.forte.simbot.qguild.api.role.ModifyGuildRoleApi - - -/** - * - * @author ForteScarlet - */ -@OptIn(ExperimentalSimbotApi::class) -internal class QGRoleCreatorImpl(private val guild: QGGuildImpl) : QGRoleCreator { - override var name: String? = null - override var color: Int? = null - override var isHoist: Boolean? = null - - override suspend fun create(): QGGuildRole { - if (name == null && color == null && isHoist == null) { - throw IllegalArgumentException("No Parameters are set") - } - - val hoist = isHoist?.let { if (it) 1 else 0 } - val created = CreateGuildRoleApi.create(guild.id.literal, name, color, hoist) - .requestBy(guild.baseBot) - - val role = created.role ?: ModifyGuildRoleApi.create(guild.id.literal, created.roleId, name, color, hoist) - .requestBy(guild.baseBot).role -// ?: GetGuildRoleListApi.create(guild.id.literal).requestBy(guild.baseBot) -// .roles.find { it.id == created.roleId }!! - - - return QGGuildRoleImpl( - bot = guild.baseBot, - guildId = guild.id, - source = role, - sourceGuild = guild.baseBot.checkIfTransmitCacheable(guild) - ) - } -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGRoleUpdaterImpl.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGRoleUpdaterImpl.kt deleted file mode 100644 index 5dc5cba2..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/role/QGRoleUpdaterImpl.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.role - -import love.forte.simbot.ExperimentalSimbotApi -import love.forte.simbot.component.qguild.role.QGRoleUpdater -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.literal -import love.forte.simbot.qguild.api.role.ModifyGuildRoleApi - - -/** - * - * @author ForteScarlet - */ -@OptIn(ExperimentalSimbotApi::class) -internal class QGRoleUpdaterImpl(private val role: BaseQGRole) : QGRoleUpdater { - override var name: String? = null - override var color: Int? = null - - // 0-否, 1-是 - override var isHoist: Boolean? = null - - override suspend fun update() { - if (name == null && color == null && isHoist == null) { - throw IllegalArgumentException("No parameters are set") - } - val modified = ModifyGuildRoleApi.create(role.guildId.literal, role.source.id, name, color, isHoist?.let { if (it) 1 else 0 }) - .requestBy(role.bot) - - // update value - role.source = modified.role - } - -} diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/utils/TimestampDelegate.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/utils/TimestampDelegate.kt deleted file mode 100644 index 80a51454..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/internal/utils/TimestampDelegate.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.internal.utils - -///** -// * 使用一个毫秒时间戳代理为 [Timestamp]. 可用于减少 [Timestamp] 对象的快速急迫产生, -// * 但是会使其每次获取都得到新的实例。 -// * -// */ -//@Suppress("NOTHING_TO_INLINE") -//internal inline operator fun Long.getValue(thisRef: Any?, property: KProperty<*>): Timestamp = -// Timestamp.byMillisecond(this) - -///** -// * 当前系统毫秒时间戳 -// */ -//internal inline val nowTimeMillis: Long get() = System.currentTimeMillis() diff --git a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/message/MessageSender.kt b/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/message/MessageSender.kt deleted file mode 100644 index 88ba75b3..00000000 --- a/simbot-component-qq-guild-core-1/src/main/kotlin/love/forte/simbot/component/qguild/message/MessageSender.kt +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2023. ForteScarlet. - * - * This file is part of simbot-component-qq-guild. - * - * simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild. - * If not, see . - */ - -package love.forte.simbot.component.qguild.message - -import love.forte.simbot.InternalSimbotApi -import love.forte.simbot.component.qguild.QGBot -import love.forte.simbot.component.qguild.internal.message.asReceipt -import love.forte.simbot.component.qguild.util.requestBy -import love.forte.simbot.message.Message -import love.forte.simbot.message.MessageContent -import love.forte.simbot.qguild.QQGuildApiException -import love.forte.simbot.qguild.api.MessageAuditedException -import love.forte.simbot.qguild.api.message.MessageSendApi -import love.forte.simbot.qguild.api.message.direct.DmsSendApi -import love.forte.simbot.qguild.message.ContentTextEncoder - -/** - * 使用当前 [QGBot] 向 [channelId] 通过 [MessageSendApi] 发送一个消息, - * 消息内容为 [message] 的解析结果。 - * - * [message] 会通过 [MessageParsers.parse] 解析为一个或多个 [MessageSendApi.Body.Builder]。 - * 当解析结果数量为1时,[sendMessage] 的结果为 [QGSingleMessageReceipt] 类型的回执。 - * 相反如果结果大于1,则 [sendMessage] 会得到实际为 [QGAggregatedMessageReceipt] 类型的结果。 - * - * 需要注意如果 [message] 的解析结果最终没有任何可用元素(例如元素为空)则可能会引发API请求异常。 - * - * @param channelId 目标频道ID - * @param message 解析消息 - * @param onEachPre 对于每个 [MessageSendApi.Body.Builder] 被构造后的初始化行为 - * @param onEachPost 对于每个 [MessageSendApi.Body.Builder] 最终执行的收尾行为 - * - * @see MessageParsers.parse - * - * @throws QQGuildApiException 请求得到了异常的结果 - * @throws MessageAuditedException 当响应状态为表示消息审核的 `304023`、`304024` 时 - * - * @return 发送后的回执 - */ -@InternalSimbotApi -public suspend inline fun QGBot.sendMessage( - channelId: String, - message: Message, - crossinline onEachPre: MessageSendApi.Body.Builder.() -> Unit = {}, - onEachPost: MessageSendApi.Body.Builder.() -> Unit = {}, -): QGMessageReceipt { - val parsed = MessageParsers.parse(message = message, onEachPre = onEachPre, onEachPost = onEachPost) - - if (parsed.size == 1) { - val body = parsed[0].build() - return sendMessage(channelId, body) - } - - return sendMessage(channelId, parsed) -} - -/** - * 使用当前 [QGBot] 向 [channelId] 通过 [MessageSendApi] 发送一个消息, - * 消息内容为 [messageContent] 的解析结果。 - * - * 如果 [messageContent] 是其他QQ频道事件收到的消息(即为 [QGReceiveMessageContent] 类型), - * 则会直接通过 [MessageSendApi.Body.Builder.fromMessage] 转义内部信息而不会尝试解析 [MessageContent.messages]。 - * - * **注意:** 在转化的过程中会丢失不支持发送的消息(例如附件、图片等)。 - * - * 如果类型不是上述情况,则行为与使用 [MessageContent.messages] 一致。 - * - * @param channelId 目标频道ID - * @param messageContent 解析消息本体 - * @param onEachPre 对于每个 [MessageSendApi.Body.Builder] 被构造后的初始化行为 - * @param onEachPost 对于每个 [MessageSendApi.Body.Builder] 最终执行的收尾行为 - * - * @see MessageParsers.parse - * - * @throws QQGuildApiException 请求得到了异常的结果 - * @throws MessageAuditedException 当响应状态为表示消息审核的 `304023`、`304024` 时 - * - * @return 发送后的回执 - */ -@InternalSimbotApi -public suspend inline fun QGBot.sendMessage( - channelId: String, - messageContent: MessageContent, - crossinline onEachPre: MessageSendApi.Body.Builder.() -> Unit = {}, - onEachPost: MessageSendApi.Body.Builder.() -> Unit = {}, -): QGMessageReceipt { - if (messageContent is QGReceiveMessageContent) { - val body = MessageSendApi.Body { - onEachPre() - fromMessage(messageContent.sourceMessage) - onEachPost() - } - - return sendMessage(channelId, body) - } - - return sendMessage(channelId, messageContent.messages, onEachPre, onEachPost) -} - -/** - * 使用当前 [QGBot] 向 [channelId] 通过 [MessageSendApi] 发送一个消息, - * 消息内容为通过 [ContentTextEncoder.encode] 转义后的无特殊含义 [text] 文本。 - * - * [text] 会通过 [ContentTextEncoder.encode] 进行转义来消除其中可能存在的[内嵌格式](https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html)文本。 - * 如果你希望保留内嵌格式,参考使用 [QGContentText] 而不是纯文本内容。 - * - * - * @param channelId 目标频道ID - * @param text 纯文本消息 - * @param onEachPre 对于每个 [MessageSendApi.Body.Builder] 被构造后的初始化行为 - * @param onEachPost 对于每个 [MessageSendApi.Body.Builder] 最终执行的收尾行为 - * - * @see MessageParsers.parse - * @see QGContentText - * - * @throws QQGuildApiException 请求得到了异常的结果 - * @throws MessageAuditedException 当响应状态为表示消息审核的 `304023`、`304024` 时 - * - * @return 发送后的回执 - */ -@InternalSimbotApi -public suspend inline fun QGBot.sendMessage( - channelId: String, - text: String, - onEachPre: MessageSendApi.Body.Builder.() -> Unit = {}, - onEachPost: MessageSendApi.Body.Builder.() -> Unit = {}, -): QGMessageReceipt { - val body = MessageSendApi.Body { - onEachPre() - // 转移后的纯文本字符串 - content = ContentTextEncoder.encode(text) - onEachPost() - } - - return sendMessage(channelId, body) -} - - -@PublishedApi -@InternalSimbotApi -internal suspend fun QGBot.sendMessage(channelId: String, body: MessageSendApi.Body): QGMessageReceipt = - MessageSendApi.create(channelId, body).requestBy(this).asReceipt() - -@PublishedApi -@InternalSimbotApi -internal suspend fun QGBot.sendMessage( - channelId: String, bodyBuilderList: List -): QGMessageReceipt = bodyBuilderList.mapTo(ArrayList(bodyBuilderList.size)) { - MessageSendApi.create(channelId, it.build()).requestBy(this) -}.asReceipt() - - -@PublishedApi -@InternalSimbotApi -internal suspend fun QGBot.sendDmsMessage(guildId: String, body: MessageSendApi.Body): QGMessageReceipt = - DmsSendApi.create(guildId, body).requestBy(this).asReceipt() diff --git a/simbot-component-qq-guild-core-1/src/main/resources/META-INF/services/love.forte.simbot.application.EventProviderAutoRegistrarFactory b/simbot-component-qq-guild-core-1/src/main/resources/META-INF/services/love.forte.simbot.application.EventProviderAutoRegistrarFactory deleted file mode 100644 index 9afb9057..00000000 --- a/simbot-component-qq-guild-core-1/src/main/resources/META-INF/services/love.forte.simbot.application.EventProviderAutoRegistrarFactory +++ /dev/null @@ -1 +0,0 @@ -love.forte.simbot.component.qguild.QGBotManagerAutoRegistrarFactory diff --git a/simbot-component-qq-guild-core-1/src/test/resources/simbot-logger-slf4j.properties b/simbot-component-qq-guild-core-1/src/test/resources/simbot-logger-slf4j.properties deleted file mode 100644 index cc04762f..00000000 --- a/simbot-component-qq-guild-core-1/src/test/resources/simbot-logger-slf4j.properties +++ /dev/null @@ -1 +0,0 @@ -level.love.forte.simbot=DEBUG