diff --git a/.changelog/v4.0.0-beta5.md b/.changelog/v4.0.0-beta5.md new file mode 100644 index 00000000..a18f9fde --- /dev/null +++ b/.changelog/v4.0.0-beta5.md @@ -0,0 +1,7 @@ +> 对应核心版本: [**v4.5.0**](https://github.com/simple-robot/simpler-robot/releases/tag/v4.5.0) + +> [!warning] +> 目前版本尚处于 **`beta`** 阶段,代表仍然可能存在部分已知问题或未知问题, +> 以及尚未完善的内容和落后于官方更新的内容。 + +我们欢迎并期望着您的 [反馈](https://github.com/simple-robot/simbot-component-kook/issues) 或 [协助](https://github.com/simple-robot/simbot-component-kook/pulls),感谢您的贡献与支持! diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index db5047f9..c6486840 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,9 +1,9 @@ blank_issues_enabled: true contact_links: - - name: 问题反馈 + - name: 统一反馈处 url: https://github.com/simple-robot/simpler-robot/issues/new/choose - about: 通过simbot核心库issues统一反馈组件问题 + about: 通过simbot核心仓库统一反馈问题 - name: 社区 url: https://github.com/orgs/simple-robot/discussions diff --git a/.github/ISSUE_TEMPLATE/report.yml b/.github/ISSUE_TEMPLATE/report.yml index 375eaac7..dcdcaa24 100644 --- a/.github/ISSUE_TEMPLATE/report.yml +++ b/.github/ISSUE_TEMPLATE/report.yml @@ -1,6 +1,5 @@ name: "🔥问题反馈" -description: "反馈遇到的BUG或问题" -labels: [ "bug?" ] +description: "直接向本仓库反馈问题或提出一个贡献申请" assignees: [ "ForteScarlet" ] # https://docs.github.com/cn/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema body: @@ -14,11 +13,34 @@ body:
+ - type: dropdown + id: will-contribute + attributes: + label: 是否会提供贡献? + description: 如果此条议题是你打算提供代码贡献作为前提,那么标记它,来告诉我们与其他开发者,以避免产生可能的重复劳动 + options: + - 否 + - 是 + - 不确定 + default: 0 + validations: + required: true + + - type: textarea + id: version + attributes: + label: 版本信息 + description: 核心库、组件库、以及其他可能涉及到的依赖库的版本信息。 + placeholder: | + 例如: + simbot-component-kook: va.b.c + simbot-core: v999 - type: dropdown id: language attributes: - label: 使用的语言 + label: 涉及的编程语言 + description: 如果没有或无对应选项则选择'其他'后在后续描述中补充说明 options: - Java - Kotlin @@ -29,7 +51,8 @@ body: - type: dropdown id: build-tool attributes: - label: 使用的构建工具 + label: 项目构建工具 + description: 如果没有或无对应选项则选择'其他'后在后续描述中补充说明 options: - Maven - Gradle @@ -41,6 +64,6 @@ body: id: description attributes: label: 内容描述 - description: 描述你的反馈内容 + description: 描述你的反馈内容。(注意日志、代码等特殊内容格式,确保易于阅读) validations: required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ea7718bd..11ec9866 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,3 +7,6 @@ updates: interval: weekly labels: - dependencies + assignees: + - ForteScarlet + open-pull-requests-limit: 10 diff --git a/.github/workflows/deploy-website-v4.yml b/.github/workflows/deploy-website-v4.yml index f91a77db..7a9bc675 100644 --- a/.github/workflows/deploy-website-v4.yml +++ b/.github/workflows/deploy-website-v4.yml @@ -121,33 +121,3 @@ jobs: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v1 - - # https://www.jetbrains.com/help/writerside/configure-search.html - publish-indexes: - # Requires the build-job results - needs: [build, test] - runs-on: ubuntu-latest - container: - image: registry.jetbrains.team/p/writerside/builder/algolia-publisher:2.0.32-2 - - env: - - CONFIG_JSON_VERSION: ${{ fromJSON(needs.build.outputs.config_json).productVersion }} - - steps: - - name: Download artifact - uses: actions/download-artifact@v3 - with: - name: algolia-indexes - - - name: Unzip artifact - run: | - unzip -O UTF-8 -qq ${{ env.ALGOLIA_ARTIFACT }} -d algolia-indexes - env "algolia-key=${{secrets.ALGOLIA_KEY}}" java -jar /opt/builder/help-publication-agent.jar \ - update-index \ - --application-name ${{env.ALGOLIA_APP_NAME}} \ - --index-name ${{env.ALGOLIA_INDEX_NAME}} \ - --product ${{env.INSTANCE_NAME}} \ - --version ${{env.CONFIG_JSON_VERSION}} \ - --index-directory algolia-indexes/ \ - 2>&1 | tee algolia-update-index-log.txt diff --git a/.github/workflows/deploy-website.yml.bk b/.github/workflows/deploy-website.yml.bk deleted file mode 100644 index 4d0b8142..00000000 --- a/.github/workflows/deploy-website.yml.bk +++ /dev/null @@ -1,38 +0,0 @@ -name: Deploy Website -on: - workflow_dispatch: - push: - branches: - - main - - dev/ver/** - - dev/main - paths: - - 'website/**' - tags-ignore: - - 'v**' - -jobs: - deploy-website: - name: Deploy Website - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 - with: - node-version: 16.x - cache: npm - cache-dependency-path: ./website/package-lock.json - - - run: | - npm ci - npm run build - working-directory: ./website - - # https://github.com/marketplace/actions/github-pages-action - - name: Push to doc repository - uses: peaceiris/actions-gh-pages@v3 - with: - personal_token: ${{ secrets.PUSH_TOKEN }} - publish_branch: gh-pages - publish_dir: ./website/build - diff --git a/.github/workflows/doc-test-branch.yml.bk b/.github/workflows/doc-test-branch.yml.bk deleted file mode 100644 index bec2070e..00000000 --- a/.github/workflows/doc-test-branch.yml.bk +++ /dev/null @@ -1,28 +0,0 @@ -name: Test Doc Branch -on: - pull_request: - branches: - - 'dev/**' - paths: - - 'website/**' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - deploy-website: - name: Build Website - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 - with: - node-version: 16.x - cache: npm - cache-dependency-path: ./website/package-lock.json - - - run: | - npm ci - npm run build - working-directory: ./website diff --git a/.github/workflows/publish-kdoc.yml b/.github/workflows/publish-kdoc.yml new file mode 100644 index 00000000..e854b445 --- /dev/null +++ b/.github/workflows/publish-kdoc.yml @@ -0,0 +1,59 @@ +name: Publish KDoc +on: + workflow_dispatch: + + +env: + JAVA_VERSION: 21 + JAVA_DISTRIBUTION: zulu + GRADLE_VERSION: 8.5 + IS_CI: true + GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} + GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }} + GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + GRADLE_OPTS: "-XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8" + +jobs: + deploy-doc: + name: Deploy-doc + runs-on: ubuntu-latest + steps: + # 检出仓库代码 + - name: Check out repo + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + # setup Java + - name: Setup java + uses: actions/setup-java@v4 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + + # setup Gradle + - name: Gradle generate documentation + uses: gradle/actions/setup-gradle@v3 + with: + gradle-version: ${{ env.GRADLE_VERSION }} + arguments: | + -Porg.gradle.jvmargs="-Xmx4g -Xms4g -XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8" + -Porg.gradle.daemon=false + --info + --warning-mode all + -x test + --build-cache + dokkaHtmlMultiModule + + - name: Push to doc repository + uses: peaceiris/actions-gh-pages@v3 + with: + personal_token: ${{ secrets.PUSH_TOKEN }} + external_repository: simple-robot-library/simbot3-api-docs + publish_branch: kdoc-deploy/component-kook + publish_dir: ./build/dokka/html + # deploy to sub dir + destination_dir: components/kook + diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index c1c02dad..87095493 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -9,6 +9,9 @@ concurrency: group: publish-release-${{ github.ref_name }} env: + JAVA_VERSION: 21 + JAVA_DISTRIBUTION: zulu + GRADLE_VERSION: 8.5 IS_CI: true GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }} @@ -18,45 +21,55 @@ env: GRADLE_OPTS: "-Xmx8g -Xms2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" jobs: - run-test-and-publish: - name: Run test and publish + run-test: + name: Run all tests for publish strategy: matrix: os: [ macos-latest, windows-latest, ubuntu-latest ] runs-on: ${{ matrix.os }} steps: - # 检出仓库代码 - - name: Check Out Repo - uses: actions/checkout@v4 - - # setup Java - - name: Setup Java - uses: actions/setup-java@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - distribution: 'zulu' - java-version: 21 + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} cache: 'gradle' + # setup Gradle - name: Gradle Run Test uses: gradle/actions/setup-gradle@v3 with: - gradle-version: 8.5 -# arguments: clean assemble test - arguments: assemble test -Porg.gradle.daemon=false + gradle-version: ${{ env.GRADLE_VERSION }} + + - name: Run all tests + run: gradle assemble allTests --stacktrace --warning-mode all - - name: Gradle Publish Release + + publish-releases: + name: Publish releases + needs: run-test + # 交叉编译 support + # see https://kotlinlang.org/docs/multiplatform-publish-lib.html#host-requirements + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: 'gradle' + - name: Publish releases uses: gradle/actions/setup-gradle@v3 with: - gradle-version: 8.5 + gradle-version: ${{ env.GRADLE_VERSION }} arguments: | publishToSonatype closeAndReleaseStagingRepositories - --info + --info --warning-mode all -x test --build-cache - -Porg.gradle.jvmargs="-Xmx8g -Xms2g -XX:MaxPermSize=1g -Dfile.encoding=UTF-8" - -Porg.gradle.daemon=false + -Porg.gradle.jvmargs="-Xmx8g -Xms2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" env: SIMBOT_IS_SNAPSHOT: false @@ -65,7 +78,7 @@ jobs: create-release: name: Create release runs-on: ubuntu-latest - needs: run-test-and-publish + needs: publish-releases permissions: contents: write steps: @@ -82,41 +95,10 @@ jobs: generate_release_notes: true prerelease: ${{ contains(github.ref_name, 'preview') || contains(github.ref_name, 'alpha') || contains(github.ref_name, 'dev') }} -# || contains(github.ref_name, 'beta') - - publish-snapshot: - name: Publish snapshot - strategy: - matrix: - os: [ macos-latest, windows-latest, ubuntu-latest ] - runs-on: ${{ matrix.os }} - needs: run-test-and-publish - steps: - # 检出仓库代码 - - name: Check out repo - uses: actions/checkout@v4 - - # setup Java - - name: Setup java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: 21 - - # setup Gradle - - name: Gradle publish snapshot - uses: gradle/actions/setup-gradle@v3 - with: - gradle-version: 8.5 - arguments: clean test publishToSonatype closeAndReleaseStagingRepositories - env: - SIMBOT_IS_SNAPSHOT: true - SIMBOT_SNAPSHOT_ONLY: true - deploy-doc: name: Deploy-doc runs-on: ubuntu-latest - needs: run-test-and-publish + needs: publish-releases steps: # 检出仓库代码 - name: Check out repo diff --git a/.github/workflows/publish-snapshot.yml b/.github/workflows/publish-snapshot.yml index 6812c8c7..f2709b91 100644 --- a/.github/workflows/publish-snapshot.yml +++ b/.github/workflows/publish-snapshot.yml @@ -3,24 +3,26 @@ on: push: branches: - main - - dev-snapshot** - - v*.*.** - - dev/main - dev/ver/** - + - dev/main paths: - - '**src/main/kotlin/**.kt' - - '**src/main/java/**.java' - - 'buildSrc/**' - - '**.kts' - - tags-ignore: - - 'v4**' + - 'buildSrc' + - '**src/**/kotlin/**.kt' + - '**src/**/java/**.java' + - '**/src/**/kotlin/**.kt' + - '**/src/**/java/**.java' + - '**/build.gradle.kts' + - 'build.gradle.kts' + - 'settings.gradle.kts' + - 'gradle.properties' # 手动触发工作流 workflow_dispatch: env: + JAVA_VERSION: 21 + JAVA_DISTRIBUTION: zulu + GRADLE_VERSION: 8.5 IS_CI: true GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }} @@ -32,42 +34,59 @@ env: GRADLE_OPTS: "-Dfile.encoding=UTF-8" jobs: - publish-snapshot: - name: Publish snapshot + run-test: + name: Run all tests strategy: matrix: os: [ macos-latest, windows-latest, ubuntu-latest ] runs-on: ${{ matrix.os }} steps: - # 检出仓库代码 - - name: Check out repo - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: 'gradle' - # setup Java - - name: Setup java - uses: actions/setup-java@v4 + # setup Gradle + - name: Gradle test and publish snapshot + uses: gradle/actions/setup-gradle@v3 with: - distribution: 'zulu' - java-version: 21 + gradle-version: ${{ env.GRADLE_VERSION }} + + - name: Gradle run all tests + run: gradle assemble allTests --stacktrace --warning-mode all + + publish-snapshots: + name: Publish snapshots + needs: run-test + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: 'gradle' # setup Gradle - - name: Gradle publish snapshot + - name: Publish snapshots uses: gradle/actions/setup-gradle@v3 with: - gradle-version: 8.5 + gradle-version: ${{ env.GRADLE_VERSION }} arguments: | - test publishToSonatype closeAndReleaseStagingRepositories - --info - --warning-mode all - -Porg.gradle.jvmargs="-Xmx8g -Xms2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" - -Porg.gradle.daemon=false + --info + --warning-mode all + -Porg.gradle.jvmargs="-Xmx8g -Xms2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + env: + SIMBOT_IS_SNAPSHOT: true deploy-doc: name: Deploy snapshot doc runs-on: ubuntu-latest - needs: publish-snapshot + needs: publish-snapshots steps: # 检出仓库代码 - name: Check out repo diff --git a/.github/workflows/publish-v4-release.yml.bk b/.github/workflows/publish-v4-release.yml.bk deleted file mode 100644 index 1edf441e..00000000 --- a/.github/workflows/publish-v4-release.yml.bk +++ /dev/null @@ -1,172 +0,0 @@ -name: Publish V4 Release -on: - push: - tags: - - 'v4**' - -env: - IS_CI: true - GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} - GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }} - GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - GRADLE_OPTS: "-Xmx8g -Xms2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" - -jobs: - run-test-and-publish-v4: - name: Run test and publish V4 - strategy: - matrix: - os: [ macos-latest, windows-latest, ubuntu-latest ] - runs-on: ${{ matrix.os }} - steps: - # 检出仓库代码 - - name: Check Out Repo - uses: actions/checkout@v4 - - # setup Java - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: 21 - cache: 'gradle' - - - name: Gradle Run Test - uses: gradle/gradle-build-action@v3 - with: - gradle-version: 8.5 -# arguments: clean assemble test - arguments: assemble test -Porg.gradle.daemon=false - - - name: Gradle Publish Release - uses: gradle/gradle-build-action@v3 - with: - gradle-version: 8.5 - arguments: | - publishToSonatype - closeAndReleaseStagingRepositories - --info - --warning-mode all - -x test - --build-cache - -Porg.gradle.jvmargs="-Xmx8g -Xms2g -XX:MaxPermSize=1g -Dfile.encoding=UTF-8" - -Porg.gradle.daemon=false - - env: - SIMBOT_IS_SNAPSHOT: false - SIMBOT_RELEASES_ONLY: true - - create-release-v4: - name: Create V4 release - runs-on: ubuntu-latest - needs: run-test-and-publish-v4 - permissions: - contents: write - steps: - # 检出仓库代码 - - name: Check Out Repo - uses: actions/checkout@v4 - - # Create gitHub release - - name: Create Github Release - uses: softprops/action-gh-release@v0.1.14 - with: - token: ${{ secrets.PUSH_TOKEN }} - body_path: .changelog/${{ github.ref_name }}.md - generate_release_notes: true - prerelease: ${{ contains(github.ref_name, 'preview') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') || contains(github.ref_name, 'dev') }} - - publish-snapshot-v4: - name: Publish V4 snapshot - runs-on: ubuntu-latest - needs: run-test-and-publish-v4 - steps: - # 检出仓库代码 - - name: Check out repo - uses: actions/checkout@v4 - - # setup Java - - name: Setup java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: 21 - - # setup Gradle - - name: Gradle publish snapshot - uses: gradle/gradle-build-action@v3 - with: - gradle-version: 8.5 - arguments: clean test publishToSonatype closeAndReleaseStagingRepositories - env: - SIMBOT_IS_SNAPSHOT: true - SIMBOT_SNAPSHOT_ONLY: true - - deploy-v4-doc: - name: Deploy-doc - runs-on: ubuntu-latest - needs: run-test-and-publish - steps: - # 检出仓库代码 - - name: Check out repo - uses: actions/checkout@v4 - with: - persist-credentials: false - fetch-depth: 0 - # setup Java - - name: Setup java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: 21 - - # setup Gradle - - name: Gradle generate documentation - uses: gradle/gradle-build-action@v3 - with: - gradle-version: 8.5 - arguments: | - -Porg.gradle.jvmargs="-Xmx4g -Xms4g -XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8" - -Porg.gradle.daemon=false - --info - --warning-mode all - -x test - --build-cache - dokkaHtmlMultiModule - - - name: Push to doc repository - uses: peaceiris/actions-gh-pages@v3 - with: - personal_token: ${{ secrets.PUSH_TOKEN }} - external_repository: simple-robot-library/simbot3-api-docs - publish_branch: kdoc-deploy/component-kook-v4 - publish_dir: ./build/dokka/html - # deploy to sub dir - destination_dir: components/kook-v4 - -# deploy-website: -# name: Deploy Website -# runs-on: ubuntu-latest -# needs: run-test-and-publish -# steps: -# - uses: actions/checkout@v4 -# - uses: actions/setup-node@v3 -# with: -# node-version: 16.x -# cache: npm -# cache-dependency-path: ./website/package-lock.json -# -# - run: | -# npm ci -# npm run build -# working-directory: ./website -# -# # https://github.com/marketplace/actions/github-pages-action -# - name: Push to doc repository -# uses: peaceiris/actions-gh-pages@v3 -# with: -# personal_token: ${{ secrets.PUSH_TOKEN }} -# publish_branch: gh-pages -# publish_dir: ./website/build diff --git a/.github/workflows/publish-v4-snapshot.yml.bk b/.github/workflows/publish-v4-snapshot.yml.bk deleted file mode 100644 index f3b4ab82..00000000 --- a/.github/workflows/publish-v4-snapshot.yml.bk +++ /dev/null @@ -1,107 +0,0 @@ -name: Publish Snapshot -on: - push: - branches: - - main - - dev-snapshot** - - v*.*.** - - dev/main - - dev/ver/** - - paths: - - '**src/main/kotlin/**.kt' - - '**src/main/java/**.java' - - 'buildSrc/**' - - '**.kts' - - tags-ignore: - - 'v4**' - - # 手动触发工作流 - workflow_dispatch: - -env: - IS_CI: true - GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} - GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }} - GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SIMBOT_IS_SNAPSHOT: true - SIMBOT_SNAPSHOT_ONLY: true - GRADLE_OPTS: "-Dfile.encoding=UTF-8" - -jobs: - publish-snapshot: - name: Publish snapshot - strategy: - matrix: - os: [ macos-latest, windows-latest, ubuntu-latest ] - runs-on: ${{ matrix.os }} - steps: - # 检出仓库代码 - - name: Check out repo - uses: actions/checkout@v4 - - # setup Java - - name: Setup java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: 21 - - # setup Gradle - - name: Gradle publish snapshot - uses: gradle/gradle-build-action@v3 - with: - gradle-version: 8.5 - arguments: | - test - publishToSonatype - closeAndReleaseStagingRepositories - --info - --warning-mode all - -Porg.gradle.jvmargs="-Xmx8g -Xms2g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" - -Porg.gradle.daemon=false - - deploy-doc: - name: Deploy snapshot doc - runs-on: ubuntu-latest - needs: publish-snapshot - steps: - # 检出仓库代码 - - name: Check out repo - uses: actions/checkout@v4 - with: - persist-credentials: false - fetch-depth: 0 - # setup Java - - name: Setup java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: 21 - - # setup Gradle - - name: Gradle generate documentation - uses: gradle/gradle-build-action@v3 - with: - gradle-version: 8.5 - arguments: | - -Porg.gradle.jvmargs="-Xmx4g -Xms4g -XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8" - -Porg.gradle.daemon=false - --info - --warning-mode all - -x test - --build-cache - dokkaHtmlMultiModule - - - name: Push to doc repository - uses: peaceiris/actions-gh-pages@v3 - with: - personal_token: ${{ secrets.PUSH_TOKEN }} - external_repository: simple-robot-library/simbot3-api-docs - publish_branch: kdoc-deploy/snapshots/component-kook - publish_dir: ./build/dokka/html - # deploy to sub dir - destination_dir: snapshots/components/kook diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index 0a9096b0..a70cd6ab 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -2,6 +2,9 @@ name: Qodana on: workflow_dispatch: pull_request: + branches: + - dev/main + - main push: branches: - dev/main @@ -9,12 +12,22 @@ on: jobs: qodana: + if: ${{ !startsWith(github.head_ref, 'dependabot/') }} runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + checks: write steps: - uses: actions/checkout@v4 with: - fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit + fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2023.2 + uses: JetBrains/qodana-action@main + with: + upload-result: true + github-token: ${{ secrets.FORLIY_ACCESS_TOKEN }} env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} # read the steps about it below + GITHUB_TOKEN: ${{ secrets.FORLIY_ACCESS_TOKEN }} diff --git a/.simbot/dokka-assets/css/kdoc-style.css b/.simbot/dokka-assets/css/kdoc-style.css index 83a1461d..f06f72cc 100644 --- a/.simbot/dokka-assets/css/kdoc-style.css +++ b/.simbot/dokka-assets/css/kdoc-style.css @@ -1,8 +1,26 @@ -.library-name a::before { - background: url("../images/logo-icon.svg") center no-repeat; - background-size: contain; - width: 40px; - height: 40px; - top: -12px; - left: -50px; +/* + * Copyright (c) 2024. ForteScarlet. + * + * Project https://github.com/simple-robot/simpler-robot + * Email ForteScarlet@163.com + * + * This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.). + * + * This program 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. + * + * This program 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 + * Lesser GNU General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program. If not, see . + * + */ + +:root { + --dokka-logo-image-url: url('../images/logo-icon-light.svg'); } diff --git a/.simbot/dokka-assets/logo-icon-light.svg b/.simbot/dokka-assets/logo-icon-light.svg new file mode 100644 index 00000000..4cb36253 --- /dev/null +++ b/.simbot/dokka-assets/logo-icon-light.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.simbot/dokka-assets/logo-icon.svg b/.simbot/dokka-assets/logo-icon.svg index 4cb36253..a1d8512f 100644 --- a/.simbot/dokka-assets/logo-icon.svg +++ b/.simbot/dokka-assets/logo-icon.svg @@ -22,57 +22,57 @@ - --> - + - + - - - + + + - + - + - - + + - + - - + + diff --git a/.simbot/dokka-templates/includes/page_metadata.ftl b/.simbot/dokka-templates/includes/page_metadata.ftl new file mode 100644 index 00000000..2f6156ce --- /dev/null +++ b/.simbot/dokka-templates/includes/page_metadata.ftl @@ -0,0 +1,26 @@ +<#macro display> + ${pageName} + <@template_cmd name="pathToRoot"> + diff --git a/Writerside/kook.tree b/Writerside/kook.tree index 160f7d3f..a5e4fa73 100644 --- a/Writerside/kook.tree +++ b/Writerside/kook.tree @@ -35,7 +35,6 @@ - @@ -50,4 +49,6 @@ + + diff --git a/Writerside/topics/KookChannel.md b/Writerside/topics/KookChannel.md index 659c31c0..cbba079d 100644 --- a/Writerside/topics/KookChannel.md +++ b/Writerside/topics/KookChannel.md @@ -1,4 +1,6 @@ # 子频道 KookChannel + + diff --git a/Writerside/topics/KookGuild.md b/Writerside/topics/KookGuild.md index 3664b968..4d37b6b0 100644 --- a/Writerside/topics/KookGuild.md +++ b/Writerside/topics/KookGuild.md @@ -1,4 +1,6 @@ # 频道 KookGuild + + diff --git a/Writerside/topics/KookMember.md b/Writerside/topics/KookMember.md index 95e5c5ac..7298a1d2 100644 --- a/Writerside/topics/KookMember.md +++ b/Writerside/topics/KookMember.md @@ -1,4 +1,6 @@ # 频道成员 KookMember + + diff --git a/Writerside/topics/KookUserChat.md b/Writerside/topics/KookUserChat.md index 52826c7b..cf387128 100644 --- a/Writerside/topics/KookUserChat.md +++ b/Writerside/topics/KookUserChat.md @@ -1,4 +1,6 @@ # 私聊会话 KookUserChat + + diff --git a/Writerside/topics/actors.md b/Writerside/topics/actors.md index e13ff16c..9490560b 100644 --- a/Writerside/topics/actors.md +++ b/Writerside/topics/actors.md @@ -1,5 +1,7 @@ # 行为对象 + + KOOK的**行为对象**(例如 `KookGuild`、`KookMember` 等) 都是对 simbot 标准库中的行为对象进行的实现与延伸扩展。 diff --git a/Writerside/topics/api-list.md b/Writerside/topics/api-list.md index 8c00b16f..2cbbcac7 100644 --- a/Writerside/topics/api-list.md +++ b/Writerside/topics/api-list.md @@ -1,5 +1,7 @@ # API定义列表 + + 此处会列举 `API 模块` 中、`love.forte.simbot.kook.api` 包下定义的所有 `KookApi` 实现。 > 对于一个具体的API的详细说明,我们建议你前往 [API 文档](https://docs.simbot.forte.love/) 或源码注释查阅, diff --git a/Writerside/topics/bot-config.md b/Writerside/topics/bot-config.md index f63dd17b..34b0f932 100644 --- a/Writerside/topics/bot-config.md +++ b/Writerside/topics/bot-config.md @@ -1,5 +1,7 @@ # Bot配置文件 + +

在使用 Spring Boot 时自动注册 bot 所需的配置文件。

diff --git a/Writerside/topics/event.md b/Writerside/topics/event.md index 8a420cfb..239ea7b5 100644 --- a/Writerside/topics/event.md +++ b/Writerside/topics/event.md @@ -1,5 +1,7 @@ # 事件定义列表 + + KOOK组件中的**事件类型**包含两个层面: 1. **API 模块** 中,对 KOOK API 中官方定义的事件结构的基本封装与实现。 diff --git a/Writerside/topics/kookbot.md b/Writerside/topics/kookbot.md index 157ec582..6d9073b3 100644 --- a/Writerside/topics/kookbot.md +++ b/Writerside/topics/kookbot.md @@ -1,3 +1,5 @@ # KookBot + + diff --git a/Writerside/topics/logger.md b/Writerside/topics/logger.md index cf1d3923..2aa830eb 100644 --- a/Writerside/topics/logger.md +++ b/Writerside/topics/logger.md @@ -1,5 +1,7 @@ # 日志 + + ## API 日志 开启 `love.forte.simbot.kook.api` 的 `DEBUG` 级别日志, diff --git a/Writerside/topics/message-element.md b/Writerside/topics/message-element.md index 8cb41fe5..ad1afe25 100644 --- a/Writerside/topics/message-element.md +++ b/Writerside/topics/message-element.md @@ -3,6 +3,8 @@ switcher-label: Java API 风格 --- # 消息元素 + + 本章节介绍 KOOK 组件中针对 simbot 标准库中 **消息元素(`Message.Element`)** 的实现类型。 diff --git a/Writerside/topics/message-send.md b/Writerside/topics/message-send.md index be1d946e..75e62ece 100644 --- a/Writerside/topics/message-send.md +++ b/Writerside/topics/message-send.md @@ -3,6 +3,8 @@ switcher-label: Java API 风格 --- # 消息发送 + + 在 KOOK 组件中,主要有两种发送消息的方式。 diff --git a/Writerside/topics/object-KMarkdown.md b/Writerside/topics/object-KMarkdown.md index 3715c21e..c352f6c3 100644 --- a/Writerside/topics/object-KMarkdown.md +++ b/Writerside/topics/object-KMarkdown.md @@ -1,5 +1,7 @@ # KMarkdown + + > 官方文档: [KMarkdown](https://developer.kookapp.cn/doc/kmarkdown) diff --git a/Writerside/topics/objects-Attachments.md b/Writerside/topics/objects-Attachments.md index 30838c87..291da615 100644 --- a/Writerside/topics/objects-Attachments.md +++ b/Writerside/topics/objects-Attachments.md @@ -1,5 +1,7 @@ # Attachments + + > 官方文档: [附加的多媒体数据 Attachments](https://developer.kookapp.cn/doc/objects#附加的多媒体数据%20Attachments) diff --git a/Writerside/topics/objects-Card.md b/Writerside/topics/objects-Card.md index a8ec4492..5f21702f 100644 --- a/Writerside/topics/objects-Card.md +++ b/Writerside/topics/objects-Card.md @@ -1,5 +1,7 @@ # Card + + > 官方文档: [卡片消息](https://developer.kookapp.cn/doc/cardmessage) diff --git a/Writerside/topics/objects.md b/Writerside/topics/objects.md index a0d98cd3..50d99deb 100644 --- a/Writerside/topics/objects.md +++ b/Writerside/topics/objects.md @@ -1,5 +1,7 @@ # Objects + + KOOK API 中提供了一些 [Objects](https://developer.kookapp.cn/doc/objects) 的定义, 在KOOK组件库的 **API模块** 针对这其中的大部分类型提供了对应的封装。 diff --git a/Writerside/topics/role-api.md b/Writerside/topics/role-api.md index def240f3..dceff7f4 100644 --- a/Writerside/topics/role-api.md +++ b/Writerside/topics/role-api.md @@ -1,3 +1,5 @@ # 角色 KookRole + + diff --git a/Writerside/topics/snippets.md b/Writerside/topics/snippets.md index f9ce33a2..df26598d 100644 --- a/Writerside/topics/snippets.md +++ b/Writerside/topics/snippets.md @@ -214,3 +214,27 @@ implementation 'io.ktor:ktor-client-darwin:$ktor_version' + + + +

站点迁移啦~!

+ + + +KOOK组件的文档内容已经迁移合并到了[**核心库手册**](https://simbot.forte.love/component-kook.html)中! +本站点将不再更新,直接前往核心库手册的[**KOOK组件**](https://simbot.forte.love/component-kook.html)部分吧~! + + + + + +作为由我们官方维护的组件库,分散在各自的文档站点中的确有好处:它们可以各自维护自己所需的东西、互不干扰。 + +但是缺点也很明显:**太过分散。** + +组件库与核心库之间的关系是比较**紧密**的, +我们希望你能够在一个站点内就可以查阅或搜索到所有你想要得知的信息。 + + + +
diff --git a/Writerside/topics/unsupported-event.md b/Writerside/topics/unsupported-event.md index 6070b967..1f61f45a 100644 --- a/Writerside/topics/unsupported-event.md +++ b/Writerside/topics/unsupported-event.md @@ -1,3 +1,5 @@ # 未知事件与未支持事件 + + diff --git a/Writerside/topics/use-api.md b/Writerside/topics/use-api.md index 7298c084..6613e91c 100644 --- a/Writerside/topics/use-api.md +++ b/Writerside/topics/use-api.md @@ -4,6 +4,8 @@ switcher-label: Java API 风格 + + # 使用 API @@ -44,7 +46,7 @@ API 模块无法直接作为 Simple Robot 组件使用。 ```Kotlin -implementation("love.forte.simbot.component:simbot-component-kook-api:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-api:%kook-version%") ``` @@ -53,7 +55,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-api:%version%" 那么你需要指定依赖的后缀为 `-jvm`。 ```Kotlin -implementation("love.forte.simbot.component:simbot-component-kook-api-jvm:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-api-jvm:%kook-version%") ``` @@ -62,7 +64,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-api-jvm:%versi ```Groovy -implementation 'love.forte.simbot.component:simbot-component-kook-api:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-api:%kook-version%' ``` @@ -71,7 +73,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-api:%version%' 那么你需要指定依赖的后缀为 `-jvm`。 ```Groovy -implementation 'love.forte.simbot.component:simbot-component-kook-api-jvm:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-api-jvm:%kook-version%' ``` @@ -84,7 +86,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-api-jvm:%versi love.forte.simbot.component simbot-component-kook-api-jvm - %version% + %kook-version% ``` diff --git a/Writerside/topics/use-core.md b/Writerside/topics/use-core.md index a08b66bf..85aec8d8 100644 --- a/Writerside/topics/use-core.md +++ b/Writerside/topics/use-core.md @@ -2,6 +2,8 @@ switcher-label: Java API 风格 --- + + # 使用核心库 @@ -35,7 +37,7 @@ simbot 核心库的版本尽量不要低于 `v%minimum-core-version%`,可前 // simbot4核心库 implementation("love.forte.simbot:simbot-core:%minimum-core-version%") // KOOK组件库 -implementation("love.forte.simbot.component:simbot-component-kook-core:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-core:%kook-version%") ``` @@ -47,7 +49,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-core:%version% // simbot4核心库 implementation("love.forte.simbot:simbot-core-jvm:%minimum-core-version%") // KOOK组件库 -implementation("love.forte.simbot.component:simbot-component-kook-core-jvm:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-core-jvm:%kook-version%") ``` @@ -59,7 +61,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-core-jvm:%vers // simbot4核心库 implementation 'love.forte.simbot:simbot-core:%minimum-core-version%' // KOOK组件库 -implementation 'love.forte.simbot.component:simbot-component-kook-core:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-core:%kook-version%' ``` @@ -71,7 +73,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-core:%version% // simbot4核心库 implementation 'love.forte.simbot:simbot-core-jvm:%minimum-core-version%' // KOOK组件库 -implementation 'love.forte.simbot.component:simbot-component-kook-core-jvm:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-core-jvm:%kook-version%' ``` @@ -90,7 +92,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-core-jvm:%vers love.forte.simbot.component simbot-component-kook-core-jvm - %version% + %kook-version% ``` diff --git a/Writerside/topics/use-spring-boot.md b/Writerside/topics/use-spring-boot.md index 50af5c13..5f447661 100644 --- a/Writerside/topics/use-spring-boot.md +++ b/Writerside/topics/use-spring-boot.md @@ -4,6 +4,8 @@ switcher-label: Java API 风格 + + # 使用 Spring Boot @@ -50,7 +52,7 @@ simbot 核心库的版本尽量不要低于 `v%minimum-core-version%`,可前 // simbot4核心库 implementation("love.forte.simbot:simbot-core-spring-boot-starter:%minimum-core-version%") // KOOK组件库 -implementation("love.forte.simbot.component:simbot-component-kook-core:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-core:%kook-version%") ``` @@ -62,7 +64,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-core:%version% // simbot4核心库 implementation("love.forte.simbot:simbot-core-spring-boot-starter:%minimum-core-version%") // KOOK组件库 -implementation("love.forte.simbot.component:simbot-component-kook-core-jvm:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-core-jvm:%kook-version%") ``` @@ -74,7 +76,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-core-jvm:%vers // simbot4核心库 implementation 'love.forte.simbot:simbot-core-spring-boot-starter:%minimum-core-version%' // KOOK组件库 -implementation 'love.forte.simbot.component:simbot-component-kook-core:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-core:%kook-version%' ``` @@ -86,7 +88,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-core:%version% // simbot4核心库 implementation 'love.forte.simbot:simbot-core-spring-boot-starter:%minimum-core-version%' // KOOK组件库 -implementation 'love.forte.simbot.component:simbot-component-kook-core-jvm:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-core-jvm:%kook-version%' ``` @@ -105,7 +107,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-core-jvm:%vers love.forte.simbot.component simbot-component-kook-core-jvm - %version% + %kook-version% ``` diff --git a/Writerside/topics/use-stdlib.md b/Writerside/topics/use-stdlib.md index 68f4a898..0546bbe1 100644 --- a/Writerside/topics/use-stdlib.md +++ b/Writerside/topics/use-stdlib.md @@ -4,6 +4,8 @@ switcher-label: Java API 风格 # 使用标准库 + +

本章节介绍如何使用 标准库(stdlib模块) 来构建 Bot 实例、订阅并处理事件。

@@ -47,7 +49,7 @@ switcher-label: Java API 风格 ```Kotlin -implementation("love.forte.simbot.component:simbot-component-kook-stdlib:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-stdlib:%kook-version%") ``` @@ -56,7 +58,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-stdlib:%versio 那么你需要指定依赖的后缀为 `-jvm`。 ```Kotlin -implementation("love.forte.simbot.component:simbot-component-kook-stdlib-jvm:%version%") +implementation("love.forte.simbot.component:simbot-component-kook-stdlib-jvm:%kook-version%") ``` @@ -65,7 +67,7 @@ implementation("love.forte.simbot.component:simbot-component-kook-stdlib-jvm:%ve ```Groovy -implementation 'love.forte.simbot.component:simbot-component-kook-stdlib:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-stdlib:%kook-version%' ``` @@ -74,7 +76,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-stdlib:%versio 那么你需要指定依赖的后缀为 `-jvm`。 ```Groovy -implementation 'love.forte.simbot.component:simbot-component-kook-stdlib-jvm:%version%' +implementation 'love.forte.simbot.component:simbot-component-kook-stdlib-jvm:%kook-version%' ``` @@ -87,7 +89,7 @@ implementation 'love.forte.simbot.component:simbot-component-kook-stdlib-jvm:%ve love.forte.simbot.component simbot-component-kook-stdlib-jvm - %version% + %kook-version% ``` diff --git a/Writerside/topics/welcome.md b/Writerside/topics/welcome.md index 680a4bc2..7e60551d 100644 --- a/Writerside/topics/welcome.md +++ b/Writerside/topics/welcome.md @@ -1,5 +1,7 @@ # 欢迎! + + 这里是 [**Simple Robot v4**](https://github.com/simple-robot/simpler-robot/tree/v4-dev) 的 diff --git a/Writerside/v.list b/Writerside/v.list index bef20f63..2636a134 100644 --- a/Writerside/v.list +++ b/Writerside/v.list @@ -3,6 +3,6 @@ - + diff --git a/Writerside/writerside.cfg b/Writerside/writerside.cfg index ca051825..2dcc6a9e 100644 --- a/Writerside/writerside.cfg +++ b/Writerside/writerside.cfg @@ -4,5 +4,5 @@ - + diff --git a/buildSrc/src/main/kotlin/P.kt b/buildSrc/src/main/kotlin/P.kt index 36ba4ba6..3eda9e1e 100644 --- a/buildSrc/src/main/kotlin/P.kt +++ b/buildSrc/src/main/kotlin/P.kt @@ -21,10 +21,7 @@ @file:Suppress("MemberVisibilityCanBePrivate", "unused") import love.forte.gradle.common.core.project.ProjectDetail -import love.forte.gradle.common.core.project.Version -import love.forte.gradle.common.core.project.minus import love.forte.gradle.common.core.property.systemProp -import love.forte.gradle.common.core.project.version as v /* * Copyright (c) 2022-2022 ForteScarlet @@ -52,10 +49,11 @@ object P : ProjectDetail() { override val homepage: String get() = HOMEPAGE - private val baseVersion = v(4, 0, 0) - v("beta4") + const val VERSION = "4.0.0-beta5" + const val NEXT_VERSION = "4.0.0-beta6" - val snapshotVersion = baseVersion - Version.SNAPSHOT - override val version = if (isSnapshot()) snapshotVersion else baseVersion + override val snapshotVersion = "$NEXT_VERSION-SNAPSHOT" + override val version = if (isSnapshot()) snapshotVersion else VERSION override val group: String get() = GROUP override val description: String get() = DESCRIPTION diff --git a/buildSrc/src/main/kotlin/changelog/GenerateChangelog.kt b/buildSrc/src/main/kotlin/changelog/GenerateChangelog.kt index 02f95b4d..e7bb7dc4 100644 --- a/buildSrc/src/main/kotlin/changelog/GenerateChangelog.kt +++ b/buildSrc/src/main/kotlin/changelog/GenerateChangelog.kt @@ -33,7 +33,7 @@ import java.util.* data class CommitLog(val message: String, val hash: MutableList, val pre: String?) fun Project.generateChangelog(tag: String) { - println("Generate change log for $tag ...") + logger.lifecycle("Generate change log for {} ...", tag) // configurations.runtimeClasspath val changelogDir = rootProject.file(".changelog").also { it.mkdirs() diff --git a/buildSrc/src/main/kotlin/kook-dokka-partial-configure.gradle.kts b/buildSrc/src/main/kotlin/kook-dokka-partial-configure.gradle.kts index 9927a136..71118d2e 100644 --- a/buildSrc/src/main/kotlin/kook-dokka-partial-configure.gradle.kts +++ b/buildSrc/src/main/kotlin/kook-dokka-partial-configure.gradle.kts @@ -1,23 +1,29 @@ /* - * Copyright (c) 2023. ForteScarlet. + * Copyright (c) 2023-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.base.DokkaBaseConfiguration import org.jetbrains.dokka.gradle.DokkaTaskPartial import java.net.URI +import java.time.Year plugins { id("org.jetbrains.dokka") @@ -26,8 +32,23 @@ plugins { // dokka config tasks.withType().configureEach { + pluginConfiguration { + customAssets = listOf( + rootProject.file(".simbot/dokka-assets/logo-icon.svg"), + rootProject.file(".simbot/dokka-assets/logo-icon-light.svg"), + ) + customStyleSheets = listOf(rootProject.file(".simbot/dokka-assets/css/kdoc-style.css")) + if (!isSimbotLocal()) { + templatesDir = rootProject.file(".simbot/dokka-templates") + } + footerMessage = "© 2021-${Year.now().value} Simple Robot. All rights reserved." + separateInheritedMembers = true + mergeImplicitExpectActualDeclarations = true + homepageLink = P.HOMEPAGE + } + dokkaSourceSets.configureEach { - version = P.version.toString() + version = P.version documentedVisibilities.set( listOf( DokkaConfiguration.Visibility.PUBLIC, @@ -62,6 +83,9 @@ tasks.withType().configureEach { sourceLink { localDirectory.set(projectDir.resolve("src")) val relativeTo = projectDir.relativeTo(rootProject.projectDir) + .path + .replace('\\', '/') + remoteUrl.set(URI.create("${P.HOMEPAGE}/tree/main/$relativeTo/src/").toURL()) remoteLineSuffix.set("#L") } @@ -90,7 +114,7 @@ tasks.withType().configureEach { externalDocumentation(URI.create("https://api.ktor.io/")) // simbot doc - externalDocumentation(URI.create("https://docs.simbot.forte.love/main/")) + externalDocumentation(URI.create("https://docs.simbot.forte.love/main-v4/")) } } diff --git a/buildSrc/src/main/kotlin/kook-multiplatform-maven-publish.gradle.kts b/buildSrc/src/main/kotlin/kook-multiplatform-maven-publish.gradle.kts index 6eb3acc0..adcb126f 100644 --- a/buildSrc/src/main/kotlin/kook-multiplatform-maven-publish.gradle.kts +++ b/buildSrc/src/main/kotlin/kook-multiplatform-maven-publish.gradle.kts @@ -1,24 +1,29 @@ /* - * Copyright (c) 2023. ForteScarlet. + * Copyright (c) 2023-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ import love.forte.gradle.common.core.Gpg import love.forte.gradle.common.core.project.setup import love.forte.gradle.common.core.property.systemProp -import love.forte.gradle.common.publication.configure.multiplatformConfigPublishing +import love.forte.gradle.common.publication.configure.configPublishMaven +import love.forte.gradle.common.publication.configure.publishingExtension +import love.forte.gradle.common.publication.configure.setupPom plugins { kotlin("multiplatform") @@ -30,30 +35,43 @@ plugins { setup(P) val p = project -multiplatformConfigPublishing { - project = P - isSnapshot = project.version.toString().contains("SNAPSHOT", true) - - val jarJavadoc by tasks.registering(Jar::class) { - group = "documentation" - archiveClassifier.set("javadoc") - if (!(isSnapshot || isSnapshot() || isSimbotLocal())) { - archiveClassifier.set("javadoc") - from(tasks.findByName("dokkaHtml")) +val isSnapshot = project.version.toString().contains("SNAPSHOT", true) + +val jarJavadoc by tasks.registering(Jar::class) { + group = "documentation" + archiveClassifier.set("javadoc") + if (!(isSnapshot || isSnapshot() || isSimbotLocal())) { + dependsOn(tasks.dokkaHtml) + from(tasks.dokkaHtml.flatMap { it.outputDirectory }) + } +} + +publishing { + repositories { + mavenLocal() + if (isSnapshot) { + configPublishMaven(SnapshotRepository) + } else { + configPublishMaven(ReleaseRepository) } } - artifact(jarJavadoc) - releasesRepository = ReleaseRepository - snapshotRepository = SnapshotRepository - gpg = Gpg.ofSystemPropOrNull() + publications { + withType { + artifacts { + artifact(jarJavadoc) + } - if (isSimbotLocal()) { - mainHost = null + setupPom(project.name, P) + } } +} - publicationsFromMainHost += listOf("wasm", "wasm32", "wasm_js") - mainHostSupportedTargets += listOf("wasm", "wasm32", "wasm_js") +signing { + val gpg = Gpg.ofSystemPropOrNull() ?: return@signing + val (keyId, secretKey, password) = gpg + useInMemoryPgpKeys(keyId, secretKey, password) + sign(publishingExtension.publications) } // TODO see https://github.com/gradle-nexus/publish-plugin/issues/208#issuecomment-1465029831 diff --git a/buildSrc/src/main/kotlin/simbot-kook-changelog-generator.gradle.kts b/buildSrc/src/main/kotlin/simbot-kook-changelog-generator.gradle.kts index dacc7c03..e7745e6f 100644 --- a/buildSrc/src/main/kotlin/simbot-kook-changelog-generator.gradle.kts +++ b/buildSrc/src/main/kotlin/simbot-kook-changelog-generator.gradle.kts @@ -1,18 +1,21 @@ /* - * Copyright (c) 2022-2023. ForteScarlet. + * Copyright (c) 2022-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ import changelog.generateChangelog @@ -52,30 +55,3 @@ tasks.create("createChangelog") { } } -tasks.create("updateWebsiteVersionJson") { - group = "documentation" - doFirst { - val version = P.version.toString() - - val websiteVersionJsonDir = rootProject.file("website/static") - if (!websiteVersionJsonDir.exists()) { - websiteVersionJsonDir.mkdirs() - } - val websiteVersionJsonFile = File(websiteVersionJsonDir, "version.json") - if (!websiteVersionJsonFile.exists()) { - websiteVersionJsonFile.createNewFile() - } - - websiteVersionJsonFile.writeText( - """ - { - "version": "$version" - } - """.trimIndent() - ) - } -} - -//fun repoRow(moduleName: String, group: String, id: String, version: String): String { -// return "| $moduleName | [$moduleName: v$version](https://repo1.maven.org/maven2/${group.replace(".", "/")}/${id.replace(".", "/")}/$version) | [$moduleName: v$version](https://search.maven.org/artifact/$group/$id/$version/jar) |" -//} diff --git a/buildSrc/src/main/kotlin/simbot-kook-dokka-multi-module.gradle.kts b/buildSrc/src/main/kotlin/simbot-kook-dokka-multi-module.gradle.kts index c29e39d4..fa93334b 100644 --- a/buildSrc/src/main/kotlin/simbot-kook-dokka-multi-module.gradle.kts +++ b/buildSrc/src/main/kotlin/simbot-kook-dokka-multi-module.gradle.kts @@ -1,18 +1,21 @@ /* - * Copyright (c) 2022-2023. ForteScarlet. + * Copyright (c) 2022-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ import org.jetbrains.dokka.base.DokkaBase @@ -40,15 +43,19 @@ fun org.jetbrains.dokka.gradle.AbstractDokkaTask.configOutput(format: String) { tasks.named("dokkaHtmlMultiModule") { configOutput("html") - rootProject.file("README.md").takeIf { it.exists() }?.also { - includes.from(it) - } - pluginConfiguration { - customAssets = listOf(rootProject.file(".simbot/dokka-assets/logo-icon.svg")) + customAssets = listOf( + rootProject.file(".simbot/dokka-assets/logo-icon.svg"), + rootProject.file(".simbot/dokka-assets/logo-icon-light.svg"), + ) customStyleSheets = listOf(rootProject.file(".simbot/dokka-assets/css/kdoc-style.css")) - footerMessage = "© 2021-${Year.now().value} Simple Robot, ForteScarlet. All rights reserved." + if (!isSimbotLocal()) { + templatesDir = rootProject.file(".simbot/dokka-templates") + } + footerMessage = "© 2021-${Year.now().value} Simple Robot. All rights reserved." separateInheritedMembers = true + mergeImplicitExpectActualDeclarations = true + homepageLink = P.HOMEPAGE } } diff --git a/buildSrc/src/main/kotlin/simbot-kook-maven-publish.gradle.kts b/buildSrc/src/main/kotlin/simbot-kook-maven-publish.gradle.kts deleted file mode 100644 index 2719882e..00000000 --- a/buildSrc/src/main/kotlin/simbot-kook-maven-publish.gradle.kts +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2022-2023. ForteScarlet. - * - * This file is part of simbot-component-kook. - * - * simbot-component-kook 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-kook 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-kook, - * If not, see . - */ - -import love.forte.gradle.common.core.Gpg -import love.forte.gradle.common.publication.configure.jvmConfigPublishing -import util.checkPublishConfigurable -import util.isCi -import util.isLinux - -/* - * Copyright (c) 2022 ForteScarlet - * - * 本文件是 simbot-component-kaiheila 的一部分。 - * - * simbot-component-kaiheila 是自由软件:你可以再分发之和/或依照由自由软件基金会发布的 GNU 通用公共许可证修改之,无论是版本 3 许可证,还是(按你的决定)任何以后版都可以。 - * - * 发布 simbot-component-kaiheila 是希望它能有用,但是并无保障;甚至连可销售和符合某个特定的目的都不保证。请参看 GNU 通用公共许可证,了解详情。 - * - * 你应该随程序获得一份 GNU 通用公共许可证的复本。如果没有,请看: - * https://www.gnu.org/licenses - * https://www.gnu.org/licenses/gpl-3.0-standalone.html - * https://www.gnu.org/licenses/lgpl-3.0-standalone.html - * - * - */ - -plugins { - id("signing") - id("maven-publish") -} - -val (isSnapshotOnly, isReleaseOnly, isPublishConfigurable) = checkPublishConfigurable() - - -logger.info("isSnapshotOnly: {}", isSnapshotOnly) -logger.info("isReleaseOnly: {}", isReleaseOnly) -logger.info("isPublishConfigurable: {}", isPublishConfigurable) - -if (!isCi || isLinux) { - checkPublishConfigurable { - jvmConfigPublishing { - project = P - publicationName = "kookDist" - isSnapshot = isSnapshot().also { - logger.info("jvmConfigPublishing.isSnapshot: {}", it) - } - val jarSources by tasks.registering(Jar::class) { - archiveClassifier.set("sources") - from(sourceSets["main"].allSource) - } - - val jarJavadoc by tasks.registering(Jar::class) { - if (!(isSnapshot || isSnapshot())) { - dependsOn(tasks.dokkaHtml) - from(tasks.dokkaHtml.flatMap { it.outputDirectory }) - } - archiveClassifier.set("javadoc") - } - - artifact(jarSources) - artifact(jarJavadoc) - - releasesRepository = ReleaseRepository - snapshotRepository = SnapshotRepository - gpg = if (isSnapshot()) null else Gpg.ofSystemPropOrNull() - } - - publishing { - publications.withType { - show() - } - } - - - } -} - -// TODO see https://github.com/gradle-nexus/publish-plugin/issues/208#issuecomment-1465029831 -val signingTasks: TaskCollection = tasks.withType() -tasks.withType().configureEach { - mustRunAfter(signingTasks) -} - -fun MavenPublication.show() { - //// show project info - println("========================================================") - println("== MavenPublication for ${project.name}") - println("== maven.pub.group: $group") - println("== maven.pub.name: $name") - println("== project.version: ${project.version}") - println("== maven.pub.version: $version") - println("== maven.pub.description: $description") - println("========================================================") -} - - -inline val Project.sourceSets: SourceSetContainer - get() = extensions.getByName("sourceSets") as SourceSetContainer - -internal val TaskContainer.dokkaHtml: TaskProvider - get() = named("dokkaHtml") diff --git a/buildSrc/src/main/kotlin/simbot-kook-module-conventions.gradle.kts b/buildSrc/src/main/kotlin/simbot-kook-module-conventions.gradle.kts index 89592872..22fe81e5 100644 --- a/buildSrc/src/main/kotlin/simbot-kook-module-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/simbot-kook-module-conventions.gradle.kts @@ -49,7 +49,7 @@ plugins { setup(P) if (isSnapshot()) { - version = P.snapshotVersion.toString() + version = P.snapshotVersion } repositories { @@ -95,14 +95,6 @@ configurations.all { resolutionStrategy.cacheChangingModulesFor(0, "seconds") } - -//// show project info -logger.info("========================================================") -logger.info("== project.group: ${group}") -logger.info("== project.name: ${name}") -logger.info("== project.version: ${version}") -logger.info("========================================================") - idea { module { isDownloadSources = true diff --git a/buildSrc/src/main/kotlin/simbot-kook-nexus-publish.gradle.kts b/buildSrc/src/main/kotlin/simbot-kook-nexus-publish.gradle.kts index 86034901..7a4e6d44 100644 --- a/buildSrc/src/main/kotlin/simbot-kook-nexus-publish.gradle.kts +++ b/buildSrc/src/main/kotlin/simbot-kook-nexus-publish.gradle.kts @@ -1,23 +1,26 @@ /* - * Copyright (c) 2022-2023. ForteScarlet. + * Copyright (c) 2022-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ import love.forte.gradle.common.core.project.setup import love.forte.gradle.common.core.repository.Repositories -import love.forte.gradle.common.publication.configure.nexusPublishConfig +import java.time.Duration /* * Copyright (c) 2022 ForteScarlet @@ -48,17 +51,22 @@ if (userInfo == null) { logger.warn("sonatype.username or sonatype.password is null, cannot config nexus publishing.") } -nexusPublishConfig { - projectDetail = P +nexusPublishing { + packageGroup.set(P.GROUP) useStaging = project.provider { !project.version.toString().endsWith("SNAPSHOT", ignoreCase = true) } - repositoriesConfig = { + + transitionCheckOptions { + maxRetries = 114514 + delayBetween = Duration.ofSeconds(2) + } + + repositories { sonatype { snapshotRepositoryUrl.set(uri(Repositories.Snapshot.URL)) username.set(userInfo?.username) password.set(userInfo?.password) } } - } diff --git a/buildSrc/src/main/kotlin/simbot-kook-suspend-transform.gradle.kts b/buildSrc/src/main/kotlin/simbot-kook-suspend-transform.gradle.kts index 5a7f265c..fefd987e 100644 --- a/buildSrc/src/main/kotlin/simbot-kook-suspend-transform.gradle.kts +++ b/buildSrc/src/main/kotlin/simbot-kook-suspend-transform.gradle.kts @@ -1,20 +1,23 @@ /* - * Copyright (c) 2023. ForteScarlet. + * Copyright (c) 2023-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ -import love.forte.simbot.gradle.suspendtransforms.SuspendTransforms +import love.forte.simbot.gradle.suspendtransforms.addSimbotJvmTransformers plugins { id("love.forte.plugin.suspend-transform") @@ -24,25 +27,6 @@ suspendTransform { includeRuntime = false includeAnnotation = false - addJvmTransformers( - // @JvmBlocking - SuspendTransforms.jvmBlockingTransformer, - // @JvmAsync - SuspendTransforms.jvmAsyncTransformer, - - // @ST - SuspendTransforms.suspendTransTransformerForJvmBlocking, - SuspendTransforms.suspendTransTransformerForJvmAsync, - SuspendTransforms.suspendTransTransformerForJvmReserve, - - // @STP - SuspendTransforms.jvmSuspendTransPropTransformerForBlocking, - SuspendTransforms.jvmSuspendTransPropTransformerForAsync, - SuspendTransforms.jvmSuspendTransPropTransformerForReserve, - ) - - // addJsTransformers( - // SuspendTransforms.suspendTransTransformerForJsPromise, - // ) + addSimbotJvmTransformers() } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 449fe3f7..f849ed0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,19 +1,19 @@ [versions] kotlin = "2.0.0" kotlinx-coroutines = "1.8.1" -kotlinx-serialization = "1.6.3" +kotlinx-serialization = "1.7.1" dokka = "1.9.20" openjdk-jmh = "1.37" -ktor = "2.3.8" +ktor = "2.3.12" log4j = "2.23.0" # simbot -simbot = "4.0.0" +simbot = "4.5.0" suspendTransform = "0.9.0" -gradleCommon = "0.4.0" +gradleCommon = "0.6.0" # ksp -ksp = "2.0.0-1.0.22" +ksp = "2.0.0-1.0.24" # https://square.github.io/kotlinpoet/ -kotlinPoet = "1.17.0" +kotlinPoet = "1.18.1" [libraries] # simbot @@ -55,7 +55,6 @@ kotlinx-serialization-hocon = { group = "org.jetbrains.kotlinx", name = "kotlinx kotlinx-serialization-protobuf = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-protobuf", version.ref = "kotlinx-serialization" } kotlinx-serialization-cbor = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-cbor", version.ref = "kotlinx-serialization" } kotlinx-serialization-properties = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-properties", version.ref = "kotlinx-serialization" } -charleskorn-kaml = "com.charleskorn.kaml:kaml:0.57.0" # ktor ## serialization diff --git a/internal-processors/message-element-processor/build.gradle.kts b/internal-processors/message-element-processor/build.gradle.kts new file mode 100644 index 00000000..be27cc4d --- /dev/null +++ b/internal-processors/message-element-processor/build.gradle.kts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-kook. + * + * simbot-component-kook 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-kook 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-kook, + * If not, see . + */ + +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + kotlin("jvm") +} + +repositories { + mavenCentral() +} + +kotlin { + jvmToolchain(11) + compilerOptions { + javaParameters = true + jvmTarget.set(JvmTarget.JVM_11) + } +} + +configJavaCompileWithModule() + +dependencies { + api(libs.ksp) + api(libs.kotlinPoet.ksp) + testImplementation(kotlin("test-junit5")) +} + +tasks.getByName("test") { + useJUnitPlatform() +} + diff --git a/internal-processors/message-element-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessor.kt b/internal-processors/message-element-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessor.kt new file mode 100644 index 00000000..6007900b --- /dev/null +++ b/internal-processors/message-element-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessor.kt @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-kook. + * + * simbot-component-kook 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-kook 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-kook, + * If not, see . + */ + +package kook.internal.processors.msgelement + +import com.google.devtools.ksp.getClassDeclarationByName +import com.google.devtools.ksp.isAbstract +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.Modifier +import com.squareup.kotlinpoet.* +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.ksp.toClassName +import com.squareup.kotlinpoet.ksp.writeTo +import java.time.Instant +import java.time.ZoneOffset + + +private const val BASE_ELEMENT_CLASS_PACKAGE = "love.forte.simbot.component.kook.message" +private const val BASE_ELEMENT_CLASS_SIMPLE_NAME = "KookMessageElement" + +private const val BASE_ELEMENT_CLASS_NAME = + "$BASE_ELEMENT_CLASS_PACKAGE.$BASE_ELEMENT_CLASS_SIMPLE_NAME" + +private val BaseElementClassName = + ClassName(BASE_ELEMENT_CLASS_PACKAGE, BASE_ELEMENT_CLASS_SIMPLE_NAME) + +private const val KTX_SERIALIZABLE_ANNOTATION_PACKAGE = "kotlinx.serialization" +private const val KTX_SERIALIZABLE_ANNOTATION_SIMPLE_NAME = "Serializable" +private const val KTX_SERIALIZABLE_ANNOTATION_NAME = + "$KTX_SERIALIZABLE_ANNOTATION_PACKAGE.$KTX_SERIALIZABLE_ANNOTATION_SIMPLE_NAME" + +private val PolymorphicModuleBuilderClassName = + ClassName("kotlinx.serialization.modules", "PolymorphicModuleBuilder") + +private const val OUTPUT_PACKAGE = "love.forte.simbot.component.kook.message" +private const val OUTPUT_FILE = "IncludeKookMessageElements.generated" +private const val OUTPUT_FUN_NAME = "includeKookMessageElements" + +/** + * + * @author ForteScarlet + */ +class MessageElementProcessor(environment: SymbolProcessorEnvironment) : SymbolProcessor { + private val codeGenerator = environment.codeGenerator + private val elementDeclarations = mutableListOf() + + override fun finish() { + val newFun = resolve(elementDeclarations) + + val fileSpec = FileSpec.Companion.builder( + OUTPUT_PACKAGE, OUTPUT_FILE + ) + .addFunction(newFun) + .addFileComment("\nAuto-Generated at ${Instant.now().atOffset(ZoneOffset.ofHours(8))}\n") + .build() + + fileSpec.writeTo( + codeGenerator = codeGenerator, + aggregating = true, + originatingKSFiles = buildList { + for (impl in elementDeclarations) { + impl.containingFile?.also { add(it) } + } + } + ) + } + + override fun process(resolver: Resolver): List { + val baseClass = resolver.getClassDeclarationByName( + BASE_ELEMENT_CLASS_NAME + ) ?: error("Base class $BASE_ELEMENT_CLASS_NAME not found") + + val baseClassStarType = baseClass.asStarProjectedType() + + resolver + .getSymbolsWithAnnotation(KTX_SERIALIZABLE_ANNOTATION_NAME) + .filterIsInstance() + .filter { declaration -> + // 是 base class 的子类 + baseClassStarType.isAssignableFrom(declaration.asStarProjectedType()) + } + .filter { declaration -> + // 不是抽象的、不是sealed的可序列化类 + !declaration.isAbstract() && !declaration.modifiers.contains(Modifier.SEALED) + } + .toCollection(elementDeclarations) + + return emptyList() + } + + /** + * 生成函数: + * + * ```kotlin + * internal fun PolymorphicModuleBuilder.includeKookMessageElements() { + * subclass(KookAsset::class, KookAsset.serializer()) + * // ... + * } + * ``` + */ + private fun resolve(declarations: List): FunSpec { + val receiverType = PolymorphicModuleBuilderClassName.parameterizedBy(BaseElementClassName) +// val optAnnotation = + val optAnnotation = AnnotationSpec.builder(ClassName("kotlin", "OptIn")) + .addMember( + "%T::class, %T::class", + ClassName("love.forte.simbot.annotations", "ExperimentalSimbotAPI"), + ClassName("love.forte.simbot.kook", "ExperimentalKookApi") + ) + .build() + + val internalAPIAnnotation = ClassName("love.forte.simbot.kook", "InternalKookApi") + + return FunSpec.builder(OUTPUT_FUN_NAME).apply { + modifiers.add(KModifier.INTERNAL) + receiver(receiverType) + addAnnotation(optAnnotation) + addAnnotation(internalAPIAnnotation) + + for (declaration in declarations) { + val className = declaration.toClassName() + addCode("subclass(%T::class, %T.serializer())\n", className, className) + } + }.build() + } +} + diff --git a/internal-processors/message-element-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessorProvider.kt b/internal-processors/message-element-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessorProvider.kt new file mode 100644 index 00000000..972199da --- /dev/null +++ b/internal-processors/message-element-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessorProvider.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-kook. + * + * simbot-component-kook 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-kook 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-kook, + * If not, see . + */ + +package kook.internal.processors.msgelement + +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.processing.SymbolProcessorProvider + +/** + * + * @author ForteScarlet + */ +class MessageElementProcessorProvider : SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor = + MessageElementProcessor(environment) +} + diff --git a/internal-processors/message-element-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/internal-processors/message-element-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider new file mode 100644 index 00000000..6bb0a159 --- /dev/null +++ b/internal-processors/message-element-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -0,0 +1 @@ +kook.internal.processors.msgelement.MessageElementProcessorProvider diff --git a/settings.gradle.kts b/settings.gradle.kts index edc33e40..a61f8bac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,24 +1,28 @@ /* - * Copyright (c) 2022-2023. ForteScarlet. + * Copyright (c) 2022-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ rootProject.name = "simbot-component-kook" // internals include(":internal-processors:api-reader") +include(":internal-processors:message-element-processor") include("simbot-component-kook-api") include("simbot-component-kook-stdlib") diff --git a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/Kook.kt b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/Kook.kt index d94bab92..e97af2f9 100644 --- a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/Kook.kt +++ b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/Kook.kt @@ -1,18 +1,21 @@ /* - * Copyright (c) 2023. ForteScarlet. + * Copyright (c) 2023-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ package love.forte.simbot.kook @@ -82,6 +85,7 @@ public object Kook { useArrayPolymorphism = false // see https://github.com/kaiheila/api-docs/issues/174 explicitNulls = false + coerceInputValues = true } } diff --git a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/messages/MessageDetails.kt b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/messages/MessageDetails.kt index d5d7a609..fbd75151 100644 --- a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/messages/MessageDetails.kt +++ b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/messages/MessageDetails.kt @@ -1,24 +1,30 @@ /* - * Copyright (c) 2021-2023. ForteScarlet. + * Copyright (c) 2021-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ package love.forte.simbot.kook.messages import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import love.forte.simbot.kook.Kook import love.forte.simbot.kook.api.ApiResultType import love.forte.simbot.kook.objects.* @@ -168,16 +174,33 @@ public data class ChannelMessageDetails( */ @Serializable public data class DirectMessageDetails( - override val id: String, - override val type: Int, - @SerialName("author_id") override val authorId: String, - override val content: String, - override val embeds: List> = emptyList(), - override val attachments: Attachments? = null, - override val reactions: List = emptyList(), - override val quote: Quote? = null, + public val id: String, + public val type: Int, + @SerialName("author_id") public val authorId: String, + public val content: String, + public val embeds: List> = emptyList(), + // 2024/8/6 + // 事件中,客户端发送的附件都被转成了card消息,attachments 永远为 null,看不出结构; + // 私聊事件查询详情时会得到空数组 `"attachments":[]`, 进而导致报错 + // 暂时不知道到底是两边都是数组,还是只有私聊变成了数组,因此暂且仅处理私聊。 + @SerialName("attachments") + public val attachmentsList: List? = null, + public val reactions: List = emptyList(), + // 如果没有引用,会冒出来一个空字符串。 + // 我真服了。 + @SerialName("quote") + private val sourceQuote: JsonElement? = null, @SerialName("read_status") public val readStatus: Boolean = false, -) : MessageDetails +) { + val quote: Quote? + get() { + val obj = (sourceQuote as? JsonObject?) ?: return null + return Kook.DEFAULT_JSON.decodeFromJsonElement(Quote.serializer(), obj) + } + + public val attachments: Attachments? + get() = attachmentsList?.firstOrNull() +} /** diff --git a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/Attachments.kt b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/Attachments.kt index 843f7858..72c75ec0 100644 --- a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/Attachments.kt +++ b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/Attachments.kt @@ -1,18 +1,21 @@ /* - * Copyright (c) 2023. ForteScarlet. + * Copyright (c) 2023-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see . + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see . */ package love.forte.simbot.kook.objects @@ -59,9 +62,9 @@ public interface Attachments { */ @Serializable public data class SimpleAttachments( - override val type: String, - override val url: String, - override val name: String, + override val type: String = "", + override val url: String = "", + override val name: String = "", override val size: Long = -1 ) : Attachments diff --git a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/card/Card.kt b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/card/Card.kt index ea268fb0..a5b00b9f 100644 --- a/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/card/Card.kt +++ b/simbot-component-kook-api/src/commonMain/kotlin/love/forte/simbot/kook/objects/card/Card.kt @@ -119,6 +119,7 @@ public data class CardMessage(private val cards: List) : List by car isLenient = true ignoreUnknownKeys = true encodeDefaults = true + coerceInputValues = true } /** diff --git a/simbot-component-kook-core/build.gradle.kts b/simbot-component-kook-core/build.gradle.kts index cadc3654..d4353203 100644 --- a/simbot-component-kook-core/build.gradle.kts +++ b/simbot-component-kook-core/build.gradle.kts @@ -18,6 +18,7 @@ * If not, see . */ +import com.google.devtools.ksp.gradle.KspTaskMetadata import love.forte.gradle.common.core.project.setup import love.forte.gradle.common.kotlin.multiplatform.applyTier1 import love.forte.gradle.common.kotlin.multiplatform.applyTier2 @@ -82,13 +83,11 @@ kotlin { } jvmTest.dependencies { - runtimeOnly(libs.ktor.client.cio) -// runtimeOnly(libs.kotlinx.coroutines.reactor) -// implementation(libs.reactor.core) + implementation(libs.ktor.client.java) - implementation(libs.log4j.api) - implementation(libs.log4j.core) - implementation(libs.log4j.slf4j2Impl) + implementation(libs.simbot.logger.slf4jimpl) +// implementation(libs.log4j.core) +// implementation(libs.log4j.slf4j2Impl) } jsMain.dependencies { @@ -109,6 +108,7 @@ kotlin { dependencies { add("kspJvm", project(":internal-processors:api-reader")) + add("kspCommonMainMetadata", project(":internal-processors:message-element-processor")) } ksp { @@ -117,3 +117,11 @@ ksp { arg("kook.api.finder.event.output", rootDir.resolve("generated-docs/core-event-list.md").absolutePath) arg("kook.api.finder.event.class", "love.forte.simbot.component.kook.event.KookEvent") } + + kotlin.sourceSets.commonMain { + // solves all implicit dependency trouble and IDEs source code detection + // see https://github.com/google/ksp/issues/963#issuecomment-1894144639 + tasks.withType { + kotlin.srcDir(destinationDirectory.file("kotlin")) + } + } diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/KookComponent.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/KookComponent.kt index ec07bd10..bf6984d8 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/KookComponent.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/KookComponent.kt @@ -21,11 +21,9 @@ package love.forte.simbot.component.kook -import kotlinx.serialization.modules.PolymorphicModuleBuilder import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.polymorphic import kotlinx.serialization.modules.subclass -import love.forte.simbot.annotations.ExperimentalSimbotAPI import love.forte.simbot.bot.serializableBotConfigurationPolymorphic import love.forte.simbot.common.function.ConfigurerFunction import love.forte.simbot.common.function.invokeBy @@ -34,11 +32,12 @@ import love.forte.simbot.component.ComponentConfigureContext import love.forte.simbot.component.ComponentFactory import love.forte.simbot.component.ComponentFactoryProvider import love.forte.simbot.component.kook.bot.KookBotVerifyInfoConfiguration -import love.forte.simbot.component.kook.message.* +import love.forte.simbot.component.kook.message.KookMessageElement +import love.forte.simbot.component.kook.message.includeKookMessageElements import love.forte.simbot.kook.ExperimentalKookApi import love.forte.simbot.kook.objects.kmd.KMarkdown import love.forte.simbot.kook.objects.kmd.RawValueKMarkdown -import love.forte.simbot.message.Message +import love.forte.simbot.message.messageElementPolymorphic import kotlin.jvm.JvmStatic /** @@ -104,36 +103,19 @@ public class KookComponent : Component { /** * [KookComponent] 组件所使用的消息序列化信息。 */ - @OptIn(ExperimentalSimbotAPI::class, ExperimentalKookApi::class) + @OptIn(ExperimentalKookApi::class) @get:JvmStatic public val messageSerializersModule: SerializersModule = SerializersModule { - fun PolymorphicModuleBuilder.include() { - subclass(KookAsset::class, KookAsset.serializer()) - subclass(KookAssetImage::class, KookAssetImage.serializer()) - subclass(KookAtAllHere::class, KookAtAllHere.serializer()) - // KookAttachmentMessage - subclass(KookAttachment::class, KookAttachment.serializer()) - subclass(KookAttachmentImage::class, KookAttachmentImage.serializer()) - subclass(KookAttachmentFile::class, KookAttachmentFile.serializer()) - subclass(KookAttachmentVideo::class, KookAttachmentVideo.serializer()) - - subclass(KookCardMessage::class, KookCardMessage.serializer()) - subclass(KookKMarkdownMessage::class, KookKMarkdownMessage.serializer()) - - subclass(KookTempTarget.Current::class, KookTempTarget.Current.serializer()) - subclass(KookTempTarget.Target::class, KookTempTarget.Target.serializer()) - } - - polymorphic(KMarkdown::class) { - subclass(RawValueKMarkdown::class, RawValueKMarkdown.serializer()) + polymorphic(KookMessageElement::class) { + includeKookMessageElements() } - polymorphic(KookMessageElement::class) { - include() + messageElementPolymorphic { + includeKookMessageElements() } - polymorphic(Message.Element::class) { - include() + polymorphic(KMarkdown::class) { + subclass(RawValueKMarkdown::class, RawValueKMarkdown.serializer()) } serializableBotConfigurationPolymorphic { diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotRegisteredEvent.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotRegisteredEvent.kt index 73b97240..baa7429a 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotRegisteredEvent.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotRegisteredEvent.kt @@ -26,14 +26,14 @@ import love.forte.simbot.common.id.UUID import love.forte.simbot.common.time.Timestamp import love.forte.simbot.component.kook.bot.KookBot import love.forte.simbot.component.kook.bot.KookBotManager -import love.forte.simbot.event.BotEvent +import love.forte.simbot.event.BotRegisteredEvent /** * 当一个 [KookBot] 在 [KookBotManager] 中被_注册_时。 * * @author ForteScarlet */ -public abstract class KookBotRegisteredEvent : KookEvent(), BotEvent { +public abstract class KookBotRegisteredEvent : KookEvent(), BotRegisteredEvent { override val id: ID = UUID.random() @OptIn(ExperimentalSimbotAPI::class) diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotStartedEvent.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotStartedEvent.kt index 5c437d98..1d5ab273 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotStartedEvent.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookBotStartedEvent.kt @@ -25,14 +25,14 @@ import love.forte.simbot.common.id.ID import love.forte.simbot.common.id.UUID import love.forte.simbot.common.time.Timestamp import love.forte.simbot.component.kook.bot.KookBot -import love.forte.simbot.event.BotEvent +import love.forte.simbot.event.BotStartedEvent /** * [KookBot] 执行 [start][KookBot.start] 之后推送的事件。 * * @author ForteScarlet */ -public abstract class KookBotStartedEvent : KookEvent(), BotEvent { +public abstract class KookBotStartedEvent : KookEvent(), BotStartedEvent { override val id: ID = UUID.random() @OptIn(ExperimentalSimbotAPI::class) diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookUpdatedMessageEvent.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookUpdatedMessageEvent.kt index 4c77b20c..7b9e1540 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookUpdatedMessageEvent.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/event/KookUpdatedMessageEvent.kt @@ -111,6 +111,7 @@ public abstract class KookUpdatedChannelMessageEvent : KookUpdatedMessageEvent() KookUpdatedMessageContent( bot = bot, isDirect = false, + chatCode = null, rawContent = sourceBody.content, msgId = sourceBody.msgId, mention = sourceBody.mention, @@ -178,6 +179,7 @@ public abstract class KookUpdatedPrivateMessageEvent : KookUpdatedMessageEvent() KookUpdatedMessageContent( bot = bot, isDirect = true, + chatCode = sourceBody.chatCode, rawContent = sourceBody.content, msgId = sourceBody.msgId, mention = emptyList(), diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookChannelMessageDetailsContent.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookChannelMessageDetailsContent.kt index 3c87c744..348b7ac7 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookChannelMessageDetailsContent.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookChannelMessageDetailsContent.kt @@ -31,6 +31,8 @@ import love.forte.simbot.common.id.ID import love.forte.simbot.common.id.StringID.Companion.ID import love.forte.simbot.component.kook.bot.KookBot import love.forte.simbot.component.kook.message.KookAttachmentMessage.Companion.asMessage +import love.forte.simbot.component.kook.message.KookQuote.Companion.asMessage +import love.forte.simbot.component.kook.util.requestDataBy import love.forte.simbot.component.kook.util.requestResultBy import love.forte.simbot.kook.api.ApiResponseException import love.forte.simbot.kook.api.message.DeleteChannelMessageApi @@ -43,6 +45,7 @@ import love.forte.simbot.message.Messages import love.forte.simbot.message.PlainText import love.forte.simbot.message.toText import kotlin.jvm.JvmStatic +import kotlin.jvm.JvmSynthetic /** * 将 [ChannelMessageDetails] 作为消息正文实现。 @@ -51,7 +54,7 @@ import kotlin.jvm.JvmStatic * @see GetChannelMessageViewApi * @author ForteScarlet */ -public data class KookChannelMessageDetailsContent( +public data class KookChannelMessageDetailsContent internal constructor( internal val details: ChannelMessageDetails, private val bot: KookBot, ) : KookMessageContent { @@ -91,6 +94,12 @@ public data class KookChannelMessageDetailsContent( messages.filterIsInstance().joinToString("") { it.text } } + @JvmSynthetic + override suspend fun reference(): KookQuote? { + val details = GetChannelMessageViewApi.create(details.id).requestDataBy(bot) + return details.quote?.asMessage() + } + /** * 删除当前的频道消息。 * diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookMessagesTransformer.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookMessagesTransformer.kt index 781ba2f8..3b751a6a 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookMessagesTransformer.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookMessagesTransformer.kt @@ -48,23 +48,17 @@ import love.forte.simbot.resource.ByteArrayResource import love.forte.simbot.resource.Resource -private fun createRequest( - type: Int, - content: String, - targetId: String, - quote: String?, - nonce: String?, - tempTargetId: String?, -): KookApi<*> { - return SendChannelMessageApi.create( - type = type, - targetId = targetId, - content = content, - quote = quote, - nonce = nonce, - tempTargetId = tempTargetId, - ) +private data class QuoteRef(var quote: String?) { + // 是否要让只有第一个消息有引用效果? +// fun take(): String? { +// val q = quote +// if (q != null) { +// quote = null +// } +// return q +// } } +private data class TempTargetIdRef(var tempTargetId: String?) private const val NOT_DIRECT = 0 private const val DIRECT_TYPE_BY_TARGET = 1 @@ -75,10 +69,13 @@ private const val DIRECT_TYPE_BY_CODE = 2 * 届时将会返回 [KookAggregatedMessageReceipt]. * * 消息的发送会更**倾向于**整合为一条或较少条消息,如果出现多条消息, - * 则 [quote] 会只被**第一条**消息所使用,而 [nonce] 和 [tempTargetId] 则会重复使用。 + * [quote]、[nonce] 和 [tempTargetId] 会被 **所有** 可能产生的消息重复使用。 * + * 其中,部分消息元素可能会覆盖默认值: + * - [MessageReference] 会覆盖 [quote] + * - [KookTempTarget] 会覆盖 [tempTargetId] * - * @return 消息最终的发送结果回执。如果为 null 则代表没有有效消息发送。 + * @return 消息最终地发送结果回执。如果为 `null` 则代表没有有效消息发送。 */ public suspend fun Message.sendToChannel( bot: KookBot, @@ -95,10 +92,13 @@ public suspend fun Message.sendToChannel( * 届时将会返回 [KookAggregatedMessageReceipt]. * * 消息的发送会更**倾向于**整合为一条或较少条消息,如果出现多条消息, - * 则 [quote] 会只被**第一条**消息所使用,而 [nonce] 和 [tempTargetId] 则会重复使用。 + * [quote]、[nonce] 和 [tempTargetId] 会被 **所有** 可能产生的消息重复使用。 * + * 其中,部分消息元素可能会覆盖默认值: + * - [MessageReference] 会覆盖 [quote] + * - [KookTempTarget] 会覆盖 [tempTargetId] * - * @return 消息最终的发送结果回执。如果为 null 则代表没有有效消息发送。 + * @return 消息最终地发送结果回执。如果为 `null` 则代表没有有效消息发送。 */ public suspend fun Message.sendToDirectByTargetId( bot: KookBot, @@ -113,10 +113,13 @@ public suspend fun Message.sendToDirectByTargetId( * 届时将会返回 [KookAggregatedMessageReceipt]. * * 消息的发送会更**倾向于**整合为一条或较少条消息,如果出现多条消息, - * 则 [quote] 会只被**第一条**消息所使用,而 [nonce] 和 [tempTargetId] 则会重复使用。 + * [quote]、[nonce] 和 [tempTargetId] 会被 **所有** 可能产生的消息重复使用。 * * + * 其中,部分消息元素可能会覆盖默认值: + * - [MessageReference] 会覆盖 [quote] + * - [KookTempTarget] 会覆盖 [tempTargetId] * - * @return 消息最终的发送结果回执。如果为 null 则代表没有有效消息发送。 + * @return 消息最终地发送结果回执。如果为 `null` 则代表没有有效消息发送。 */ public suspend fun Message.sendToDirectByChatCode( bot: KookBot, @@ -132,11 +135,15 @@ public suspend fun Message.sendToDirectByChatCode( * 届时将会返回 [KookAggregatedMessageReceipt]. * * 消息的发送会更**倾向于**整合为一条或较少条消息,如果出现多条消息, - * 则 [quote] 会只被**第一条**消息所使用,而 [nonce] 和 [tempTargetId] 则会重复使用。 + * [quote]、[nonce] 和 [tempTargetId] 会被 **所有** 可能产生的消息重复使用。 + * + * 其中,部分消息元素可能会覆盖默认值: + * - [MessageReference] 会覆盖 [quote] + * - [KookTempTarget] 会覆盖 [tempTargetId] * * @param defaultTempTargetId 如果存在 [KookTempTarget] * - * @return 消息最终的发送结果回执。如果为 null 则代表没有有效消息发送。 + * @return 消息最终地发送结果回执。如果为 `null` 则代表没有有效消息发送。 */ @OptIn(ExperimentalSimbotAPI::class) private suspend fun Message.send0( @@ -148,10 +155,6 @@ private suspend fun Message.send0( tempTargetId: String? = null, defaultTempTargetId: String? = null, ): KookMessageReceipt? { - data class TempTargetIdWrapper(var tempTargetId: String?) - -// var quote0 = quote - fun doRequest(type: Int, content: String, nonce: String?, quote: String?, tempTargetId: String?): KookApi<*> { return when (directType) { NOT_DIRECT -> SendChannelMessageApi.create( @@ -171,8 +174,8 @@ private suspend fun Message.send0( val message = this var kMarkdownBuilder: KMarkdownBuilder? = null - var quote0 = quote - val tempWrapper = TempTargetIdWrapper(tempTargetId) + val quoteRef = QuoteRef(quote) + val tempRef = TempTargetIdRef(tempTargetId) // val requests: List<KookApiRequest<*>> = buildList(if (this is Message.Element<*>) 1 else (this as Messages).size) { val requests: List<() -> KookApi<*>> = @@ -180,15 +183,13 @@ private suspend fun Message.send0( // 清算 kmd fun liquidationKmd() { kMarkdownBuilder?.let { kmb -> - val currentQuote = quote0 - quote0 = null add { doRequest( MessageType.KMARKDOWN.type, kmb.buildRaw(), nonce, - currentQuote, - tempWrapper.tempTargetId + quoteRef.quote, + tempRef.tempTargetId ) } kMarkdownBuilder = null @@ -203,14 +204,19 @@ private suspend fun Message.send0( } is KookTempTarget -> when (message) { - is KookTempTarget.Target -> tempWrapper.tempTargetId = message.id.literal - is KookTempTarget.Current -> tempWrapper.tempTargetId = defaultTempTargetId + is KookTempTarget.Target -> tempRef.tempTargetId = message.id.literal + is KookTempTarget.Current -> tempRef.tempTargetId = defaultTempTargetId + } + // 任意的 MessageReference 类型元素 + // 覆盖当前消息元素 + is MessageReference -> { + quoteRef.quote = message.id.literal } else -> { message.elementToRequest(bot, isSingle, { type, content -> liquidationKmd() - add { doRequest(type, content, nonce, null, tempWrapper.tempTargetId) } + add { doRequest(type, content, nonce, quoteRef.quote, tempRef.tempTargetId) } }) { block -> block(kMarkdownBuilder ?: KMarkdownBuilder().also { kMarkdownBuilder = it }) } @@ -320,10 +326,6 @@ private suspend inline fun Message.Element.elementToRequest( // card message is KookCardMessage -> doRequest(MessageType.CARD.type, message.cards.encode()) - // is KookRequestMessage -> { - // this.request - // } - is KookAtAllHere -> { withinKmd { at(AtTarget.Here) @@ -344,8 +346,8 @@ private suspend inline fun Message.Element.elementToRequest( is KookAttachmentVideo -> MessageType.VIDEO } - // TODO just re-upload and send, waiting for fix. - // see https://github.com/simple-robot/simbot-component-kook/issues/75 + // Just re-upload and send, waiting for fix. + // See https://github.com/simple-robot/simbot-component-kook/issues/75 val createRequest = createReUploadAssetApi(bot, message.attachment) val asset = createRequest.requestDataBy(bot) diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookQuote.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookQuote.kt new file mode 100644 index 00000000..0ed785ea --- /dev/null +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookQuote.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-kook. + * + * simbot-component-kook 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-kook 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-kook, + * If not, see <https://www.gnu.org/licenses/>. + */ + +package love.forte.simbot.component.kook.message + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import love.forte.simbot.common.id.ID +import love.forte.simbot.common.id.StringID.Companion.ID +import love.forte.simbot.kook.objects.Quote +import love.forte.simbot.message.MessageIdReference +import love.forte.simbot.message.MessageReference +import kotlin.jvm.JvmName +import kotlin.jvm.JvmStatic + + +/** + * 一个通过 [KookMessageContent.reference] + * 查询得到的消息引用信息。 + * + * 也可用于发送,效果等同于使用 [MessageIdReference]。 + * + * @author ForteScarlet + */ +@SerialName("kook.quote") +@Serializable +public data class KookQuote internal constructor(public val quote: Quote) : + MessageReference { + override val id: ID + get() = quote.id.ID + + public companion object { + /** + * 将 [Quote] 作为 [KookQuote]。 + */ + @JvmStatic + @JvmName("create") + public fun Quote.asMessage(): KookQuote = KookQuote(this) + } + +} diff --git a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookReceiveMessageContent.kt b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookReceiveMessageContent.kt index a0e6db1e..2bc369c1 100644 --- a/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookReceiveMessageContent.kt +++ b/simbot-component-kook-core/src/commonMain/kotlin/love/forte/simbot/component/kook/message/KookReceiveMessageContent.kt @@ -1,22 +1,26 @@ /* - * Copyright (c) 2022-2023. ForteScarlet. + * Copyright (c) 2022-2024. ForteScarlet. * - * This file is part of simbot-component-kook. + * This file is part of simbot-component-kook. * - * simbot-component-kook 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-kook 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-kook 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. + * simbot-component-kook 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-kook, - * If not, see <https://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public License + * along with simbot-component-kook, + * If not, see <https://www.gnu.org/licenses/>. */ package love.forte.simbot.component.kook.message +import kotlinx.serialization.SerializationException import love.forte.simbot.ability.DeleteOption import love.forte.simbot.ability.DeleteSupport import love.forte.simbot.annotations.ExperimentalSimbotAPI @@ -28,16 +32,25 @@ import love.forte.simbot.component.kook.bot.KookBot import love.forte.simbot.component.kook.message.KookAttachmentMessage.Companion.asMessage import love.forte.simbot.component.kook.message.KookMessages.AT_TYPE_ROLE import love.forte.simbot.component.kook.message.KookMessages.AT_TYPE_USER +import love.forte.simbot.component.kook.message.KookQuote.Companion.asMessage +import love.forte.simbot.component.kook.util.requestData +import love.forte.simbot.component.kook.util.requestDataBy import love.forte.simbot.component.kook.util.requestResultBy import love.forte.simbot.component.kook.util.walk import love.forte.simbot.kook.api.ApiResponseException +import love.forte.simbot.kook.api.ApiResult +import love.forte.simbot.kook.api.ApiResultException import love.forte.simbot.kook.api.message.DeleteChannelMessageApi import love.forte.simbot.kook.api.message.DeleteDirectMessageApi +import love.forte.simbot.kook.api.message.GetChannelMessageViewApi +import love.forte.simbot.kook.api.message.GetDirectMessageViewApi +import love.forte.simbot.kook.api.userchat.CreateUserChatApi import love.forte.simbot.kook.event.* import love.forte.simbot.kook.objects.card.CardMessage import love.forte.simbot.logger.Logger import love.forte.simbot.logger.LoggerFactory import love.forte.simbot.message.* +import love.forte.simbot.suspendrunner.STP import kotlin.experimental.and import kotlin.experimental.or import kotlin.jvm.JvmSynthetic @@ -113,9 +126,39 @@ public interface KookMessageContent : MessageContent, DeleteSupport { * 将消息转化为一个消息链(尤其是转化kmarkdown类型的消息)的过程中有可能会丢失一部分原有的格式。 * 因此当你直接通过 [messages] 重复发送消息时有可能会产生与收到的消息不一致的效果。 * + * ## 消息引用 + * 有关消息引用的信息需要通过 [reference] API 查询获取,不会被包含在 [messages] 中。 + * */ override val messages: Messages + /** + * 获取消息中的引用信息。 + * 会通过 API [GetChannelMessageViewApi] + * 或 [GetDirectMessageViewApi] 发起请求并得到结果, + * 因此 [reference] 会产生挂起。 + * + * [reference] 的结果不会包含在 [messages] 中。 + * + * 如果是私聊会话,会先查询会话code,然后查询消息引用。 + * + * 查询结果不会被缓存,每次调用都会产生API请求。 + * + * @throws SerializationException 由于服务端响应值类型不规范导致的异常。 + * 2024/8/6: 经测试,在私聊会话情况下,如果发送的消息内无引用,则响应的 `quote` 值为 **空字符串**, + * 例如: + * ```json + * {"quote":""} + * ``` + * 这会引发 [SerializationException]。而如果消息包含引用,则响应为 `Quote` 对象结构。 + * 虽然在内部做了写兼容性的处理,但是不能保证未来服务端的行为不会发生变化。 + * + * @throws ApiResponseException 请求结果的状态码不是 200..300 之间 + * @throws ApiResultException 请求结果的 [ApiResult.code] 校验失败 + */ + @STP + override suspend fun reference(): KookQuote? + /** * 尝试根据当前消息ID删除目标。 * @@ -133,6 +176,22 @@ public interface KookMessageContent : MessageContent, DeleteSupport { public abstract class BaseKookReceiveMessageContent : KookMessageContent +private suspend fun referenceFromChannel(bot: KookBot, msgId: String): KookQuote? { + val api = GetChannelMessageViewApi.create(msgId) + val details = bot.requestData(api) + return details.quote?.asMessage() +} + +private suspend fun referenceFromDirect(bot: KookBot, msgId: String, authorId: String): KookQuote? { + val chat = CreateUserChatApi.create(authorId).requestDataBy(bot) + return referenceFromDirectWithChatCode(bot, msgId, chat.code) +} + +private suspend fun referenceFromDirectWithChatCode(bot: KookBot, msgId: String, chatCode: String): KookQuote? { + val details = GetDirectMessageViewApi.create(chatCode, msgId).requestDataBy(bot) + return details.quote?.asMessage() +} + /** * KOOK 消息事件所收到的消息正文类型。 * @@ -142,7 +201,7 @@ public abstract class BaseKookReceiveMessageContent : KookMessageContent * * @author ForteScarlet */ -public class KookReceiveMessageContent( +public class KookReceiveMessageContent internal constructor( private val isDirect: Boolean, internal val source: Event<TextExtra>, private val bot: KookBot, @@ -171,6 +230,15 @@ public class KookReceiveMessageContent( messages.filterIsInstance<PlainText>().joinToString("") { it.text } } + @JvmSynthetic + override suspend fun reference(): KookQuote? { + return if (isDirect) { + referenceFromDirect(bot, source.msgId, source.authorId) + } else { + referenceFromChannel(bot, source.msgId) + } + } + @JvmSynthetic override suspend fun delete(vararg options: DeleteOption) { // TODO options @@ -196,9 +264,10 @@ public class KookReceiveMessageContent( * * @see KookMessageContent */ -public class KookUpdatedMessageContent( +public class KookUpdatedMessageContent internal constructor( private val bot: KookBot, private val isDirect: Boolean, + private val chatCode: String? = null, override val rawContent: String, private val msgId: String, private val mention: List<String>, @@ -206,8 +275,13 @@ public class KookUpdatedMessageContent( private val isMentionAll: Boolean, private val isMentionHere: Boolean, ) : BaseKookReceiveMessageContent() { - override val id: ID get() = msgId.ID + init { + check(!isDirect || chatCode != null) { + "If is direct, chatCode can not be null" + } + } + override val id: ID get() = msgId.ID override val messages: Messages by lazy(LazyThreadSafetyMode.PUBLICATION) { toMessagesByKMarkdown(rawContent, mention, mentionRoles, isMentionAll, isMentionHere) @@ -217,6 +291,15 @@ public class KookUpdatedMessageContent( messages.filterIsInstance<PlainText>().joinToString("") { it.text } } + @JvmSynthetic + override suspend fun reference(): KookQuote? { + return if (isDirect) { + referenceFromDirectWithChatCode(bot, msgId, chatCode!!) + } else { + referenceFromChannel(bot, msgId) + } + } + @JvmSynthetic override suspend fun delete(vararg options: DeleteOption) { // TODO options