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