From abff76e34d76f901ae95e77b14e12b82f5e8ee18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 20:04:33 +0200 Subject: [PATCH 01/55] chore(deps): bump junit-version from 5.9.3 to 5.10.0 (#551) * chore(deps): bump junit-version from 5.9.3 to 5.10.0 Bumps `junit-version` from 5.9.3 to 5.10.0. Updates `org.junit.jupiter:junit-jupiter-api` from 5.9.3 to 5.10.0 - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.10.0) Updates `org.junit.jupiter:junit-jupiter-params` from 5.9.3 to 5.10.0 - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.10.0) Updates `org.junit.jupiter:junit-jupiter-engine` from 5.9.3 to 5.10.0 - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.10.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.junit.jupiter:junit-jupiter-params dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.junit.jupiter:junit-jupiter-engine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Properly override junit version in spring --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Couchoud --- gradle/libs.versions.toml | 8 ++++---- viewer/build.gradle.kts | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8994921e..e9ef6e88 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ lang3-version = "3.12.0" commons-text-version = "1.10.0" jetbrains-annotations-version = "24.0.1" websocket-version = "1.5.4" -junit-version = "5.9.3" +junitVersion = "5.10.0" assertj-core-version = "3.24.2" assertj-db-version = "2.0.2" mockito-version = "5.2.0" @@ -67,9 +67,9 @@ flyway-mysql = { group = "org.flywaydb", name = "flyway-mysql", version.ref = "f selenide = { group = "com.codeborne", name = "selenide", version.ref = "selenide-version" } lombok = { group = "org.projectlombok", name = "lombok", version.ref = "lombok-version" } -junit-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit-version" } -junit-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit-version" } -junitEngine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit-version" } +junit-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junitVersion" } +junit-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junitVersion" } +junitEngine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junitVersion" } assertj-core = { group = "org.assertj", name = "assertj-core", version.ref = "assertj-core-version" } assertj-db = { group = "org.assertj", name = "assertj-db", version.ref = "assertj-db-version" } mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito-version" } diff --git a/viewer/build.gradle.kts b/viewer/build.gradle.kts index 1fcf7ea1..fbed1dda 100644 --- a/viewer/build.gradle.kts +++ b/viewer/build.gradle.kts @@ -12,13 +12,16 @@ configurations { } } +ext["junit-jupiter.version"] = libs.versions.junitVersion.get() + dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.springframework.boot:spring-boot-starter-web") - testImplementation(libs.bundles.junit) - testRuntimeOnly(libs.junitEngine) + testImplementation("org.junit.jupiter:junit-jupiter-api") + testImplementation("org.junit.jupiter:junit-jupiter-params") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") testImplementation(libs.bundles.assertj) testImplementation("org.mockito:mockito-core") From 0e89ec411d73916912a5e3e2ea4843c9e0105ea5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 20:22:37 +0200 Subject: [PATCH 02/55] chore(deps): bump org.apache.commons:commons-lang3 from 3.12.0 to 3.13.0 (#555) Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.13.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e9ef6e88..91b5a4fe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ picocli-version = "4.7.4" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" httpclient-version = "4.5.14" -lang3-version = "3.12.0" +lang3-version = "3.13.0" commons-text-version = "1.10.0" jetbrains-annotations-version = "24.0.1" websocket-version = "1.5.4" From c2e985ebeb4ce6586daf2c74719f296f14e22f14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 20:58:02 +0200 Subject: [PATCH 03/55] chore(deps): bump com.codeborne:selenide from 6.16.1 to 6.17.0 (#556) Bumps [com.codeborne:selenide](https://github.com/selenide/selenide) from 6.16.1 to 6.17.0. - [Release notes](https://github.com/selenide/selenide/releases) - [Changelog](https://github.com/selenide/selenide/blob/main/CHANGELOG.md) - [Commits](https://github.com/selenide/selenide/compare/v6.16.1...v6.17.0) --- updated-dependencies: - dependency-name: com.codeborne:selenide dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 91b5a4fe..494afc4d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ sqlite-version = "3.42.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.21.1" -selenide-version = "6.16.1" +selenide-version = "6.17.0" lombok-version = "1.18.28" jacocoVersion = "0.8.10" From 625f285d0597efc71abf2283b1927c5740c05027 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Aug 2023 20:56:42 +0200 Subject: [PATCH 04/55] chore(deps): bump unirest-version from 4.0.3 to 4.0.4 (#557) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 494afc4d..e8b00a15 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ slf4j-version = "2.0.7" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" -unirest-version = "4.0.3" +unirest-version = "4.0.4" picocli-version = "4.7.4" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" From 5b6c1b7bb2f2e00ede9db76f5eaeb3762676b3a7 Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Sat, 5 Aug 2023 17:39:36 +0200 Subject: [PATCH 05/55] CI --- .github/workflows/analyse.yml | 10 ------- .github/workflows/build-test-deploy.yml | 27 +++++++---------- .github/workflows/manual-docker.yml | 31 ++++++++----------- .github/workflows/pages.yml | 2 +- .github/workflows/release.yml | 40 ++++++++++++++----------- miner/build.gradle.kts | 6 ---- viewer/build.gradle.kts | 6 ---- 7 files changed, 48 insertions(+), 74 deletions(-) diff --git a/.github/workflows/analyse.yml b/.github/workflows/analyse.yml index d4ee6af4..d0c4f7a1 100644 --- a/.github/workflows/analyse.yml +++ b/.github/workflows/analyse.yml @@ -42,13 +42,3 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 -# qodana: -# name: Qodana -# runs-on: ubuntu-latest -# steps: -# - name: Checkout repository -# uses: actions/checkout@v3 -# with: -# fetch-depth: 0 -# - name: Run Qodana -# uses: JetBrains/qodana-action@v5.0.2 diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index ca0306e3..b3fa9f0a 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -12,11 +12,6 @@ on: - develop workflow_dispatch: -env: - APP_JAVA_VERSION: 17 - DOCKER_MINER_IMAGE_NAME: mrcraftcod/channel-points-miner - DOCKER_VIEWER_IMAGE_NAME: mrcraftcod/channel-points-miner-viewer - jobs: build: name: Build project @@ -30,7 +25,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} + java-version: ${{ vars.JAVA_VERSION }} - name: Build project uses: gradle/gradle-build-action@v2 @@ -69,7 +64,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} + java-version: ${{ vars.JAVA_VERSION }} - name: Run tests uses: gradle/gradle-build-action@v2 @@ -130,7 +125,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} + java-version: ${{ vars.JAVA_VERSION }} - name: Run tests uses: gradle/gradle-build-action@v2 @@ -193,18 +188,18 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} + java-version: ${{ vars.JAVA_VERSION }} - name: Calculate miner image name id: miner-image-name - run: echo "IMAGE_NAME=${DOCKER_MINER_IMAGE_NAME}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" + run: echo "IMAGE_NAME=${{ vars.DOCKER_IMAGE_MINER }}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" - name: Push branch/tag on Docker Hub uses: gradle/gradle-build-action@v2 with: arguments: | :miner:jib - -PdockerUsername=${{ secrets.DOCKER_USERNAME }} - -PdockerPassword=${{ secrets.DOCKER_TOKEN }} + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} -Djib.to.image=${{ steps.miner-image-name.outputs.IMAGE_NAME }} publish-viewer: @@ -222,16 +217,16 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} + java-version: ${{ vars.JAVA_VERSION }} - name: Calculate viewer image name id: viewer-image-name - run: echo "IMAGE_NAME=${DOCKER_VIEWER_IMAGE_NAME}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" + run: echo "IMAGE_NAME=${{ vars.DOCKER_IMAGE_VIEWER }}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" - name: Push branch/tag on Docker Hub uses: gradle/gradle-build-action@v2 with: arguments: | :viewer:jib - -PdockerUsername=${{ secrets.DOCKER_USERNAME }} - -PdockerPassword=${{ secrets.DOCKER_TOKEN }} + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} -Djib.to.image=${{ steps.viewer-image-name.outputs.IMAGE_NAME }} diff --git a/.github/workflows/manual-docker.yml b/.github/workflows/manual-docker.yml index ccb66901..3576a8b9 100644 --- a/.github/workflows/manual-docker.yml +++ b/.github/workflows/manual-docker.yml @@ -3,11 +3,6 @@ name: Manually deploy docker on: workflow_dispatch: -env: - APP_JAVA_VERSION: 17 - DOCKER_MINER_IMAGE_NAME: mrcraftcod/channel-points-miner - DOCKER_VIEWER_IMAGE_NAME: mrcraftcod/channel-points-miner-viewer - jobs: publish-miner: name: Publish Miner on DockerHub @@ -20,20 +15,20 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} + java-version: ${{ vars.JAVA_VERSION }} - name: Calculate miner image name id: miner-image-name run: | - echo "IMAGE_NAME=${DOCKER_MINER_IMAGE_NAME}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" - echo "IMAGE_NAME_LATEST=${DOCKER_MINER_IMAGE_NAME}:latest" >> "$GITHUB_OUTPUT" + echo "IMAGE_NAME=${{ vars.DOCKER_IMAGE_MINER }}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" + echo "IMAGE_NAME_LATEST=${{ vars.DOCKER_IMAGE_MINER }}:latest" >> "$GITHUB_OUTPUT" - name: Push branch/tag on Docker Hub uses: gradle/gradle-build-action@v2 with: arguments: | :miner:jib - -PdockerUsername=${{ secrets.DOCKER_USERNAME }} - -PdockerPassword=${{ secrets.DOCKER_TOKEN }} + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} -Djib.to.image=${{ steps.miner-image-name.outputs.IMAGE_NAME }} - name: Push latest on Docker Hub if: success() && github.ref == 'refs/heads/main' @@ -41,8 +36,8 @@ jobs: with: arguments: | :miner:jib - -PdockerUsername=${{ secrets.DOCKER_USERNAME }} - -PdockerPassword=${{ secrets.DOCKER_TOKEN }} + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} -Djib.to.image=${{ steps.miner-image-name.outputs.IMAGE_NAME_LATEST }} publish-viewer: @@ -61,15 +56,15 @@ jobs: - name: Calculate viewer image name id: viewer-image-name run: | - echo "IMAGE_NAME=${DOCKER_VIEWER_IMAGE_NAME}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" - echo "IMAGE_NAME_LATEST=${DOCKER_VIEWER_IMAGE_NAME}:latest" >> "$GITHUB_OUTPUT" + echo "IMAGE_NAME=${{ vars.DOCKER_IMAGE_VIEWER }}:${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT" + echo "IMAGE_NAME_LATEST=${{ vars.DOCKER_IMAGE_VIEWER }}:latest" >> "$GITHUB_OUTPUT" - name: Push branch/tag on Docker Hub uses: gradle/gradle-build-action@v2 with: arguments: | :viewer:jib - -PdockerUsername=${{ secrets.DOCKER_USERNAME }} - -PdockerPassword=${{ secrets.DOCKER_TOKEN }} + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} -Djib.to.image=${{ steps.viewer-image-name.outputs.IMAGE_NAME }} - name: Push latest on Docker Hub if: success() && github.ref == 'refs/heads/main' @@ -77,6 +72,6 @@ jobs: with: arguments: | :viewer:jib - -PdockerUsername=${{ secrets.DOCKER_USERNAME }} - -PdockerPassword=${{ secrets.DOCKER_TOKEN }} + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} -Djib.to.image=${{ steps.viewer-image-name.outputs.IMAGE_NAME_LATEST }} diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index c73631fa..3c084d0a 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -19,7 +19,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: '16' + node-version: '20' - name: Install Antora run: npm i antora asciidoctor-kroki diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 73f5c6c5..53bddbd2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,11 +5,6 @@ on: tags: - "*.*.*" -env: - APP_JAVA_VERSION: 17 - DOCKER_MINER_IMAGE_NAME: mrcraftcod/channel-points-miner - DOCKER_VIEWER_IMAGE_NAME: mrcraftcod/channel-points-miner-viewer - jobs: publish-docker-miner: name: Publish Miner on DockerHub @@ -22,11 +17,16 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} - - name: Set gradle permissions - run: chmod +x gradlew + java-version: ${{ vars.JAVA_VERSION }} + - name: Push latest on Docker Hub - run: ./gradlew :miner:jib -PdockerUsername=${{ secrets.DOCKER_USERNAME }} -PdockerPassword=${{ secrets.DOCKER_TOKEN }} -Djib.to.image="${DOCKER_MINER_IMAGE_NAME}:latest" + uses: gradle/gradle-build-action@v2 + with: + arguments: | + :miner:jib + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} + -Djib.to.image=${{ vars.DOCKER_IMAGE_MINER }}:latest publish-docker-viewer: name: Publish Viewer on DockerHub @@ -39,11 +39,16 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} - - name: Set gradle permissions - run: chmod +x gradlew + java-version: ${{ vars.JAVA_VERSION }} + - name: Push latest on Docker Hub - run: ./gradlew :viewer:jib -PdockerUsername=${{ secrets.DOCKER_USERNAME }} -PdockerPassword=${{ secrets.DOCKER_TOKEN }} -Djib.to.image="${DOCKER_VIEWER_IMAGE_NAME}:latest" + uses: gradle/gradle-build-action@v2 + with: + arguments: | + :viewer:jib + -Djib.to.auth.username=${{ secrets.DOCKER_USERNAME }} + -Djib.to.auth.password=${{ secrets.DOCKER_TOKEN }} + -Djib.to.image=${{ vars.DOCKER_IMAGE_VIEWER }}:latest publish-release: name: Publish Release @@ -57,13 +62,14 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: ${{ env.APP_JAVA_VERSION }} - - name: Set gradle permissions - run: chmod +x gradlew + java-version: ${{ vars.JAVA_VERSION }} + - name: Build project uses: gradle/gradle-build-action@v2 with: - arguments: assemble --scan + arguments: | + assemble + --scan - name: Release uses: softprops/action-gh-release@v1 with: diff --git a/miner/build.gradle.kts b/miner/build.gradle.kts index bd9f2947..1af0fe71 100644 --- a/miner/build.gradle.kts +++ b/miner/build.gradle.kts @@ -152,12 +152,6 @@ jib { } } } - to { - auth { - username = project.findProperty("dockerUsername").toString() - password = project.findProperty("dockerPassword").toString() - } - } container { creationTime.set("USE_CURRENT_TIMESTAMP") } diff --git a/viewer/build.gradle.kts b/viewer/build.gradle.kts index fbed1dda..0111d496 100644 --- a/viewer/build.gradle.kts +++ b/viewer/build.gradle.kts @@ -91,12 +91,6 @@ jib { } } } - to { - auth { - username = project.findProperty("dockerUsername").toString() - password = project.findProperty("dockerPassword").toString() - } - } container { creationTime.set("USE_CURRENT_TIMESTAMP") ports = listOf("8080") From b32e45ac7880423b4150f7324fc830e27c184d1e Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Sat, 5 Aug 2023 17:43:25 +0200 Subject: [PATCH 06/55] CI --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53bddbd2..afd6f9ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,7 +69,6 @@ jobs: with: arguments: | assemble - --scan - name: Release uses: softprops/action-gh-release@v1 with: From 1ef887b57a0d42d1bc950d3d978fc18692d743a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 21:40:57 +0200 Subject: [PATCH 07/55] chore(deps): bump io.spring.dependency-management from 1.1.2 to 1.1.3 (#558) Bumps [io.spring.dependency-management](https://github.com/spring-gradle-plugins/dependency-management-plugin) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/spring-gradle-plugins/dependency-management-plugin/releases) - [Commits](https://github.com/spring-gradle-plugins/dependency-management-plugin/compare/v1.1.2...v1.1.3) --- updated-dependencies: - dependency-name: io.spring.dependency-management dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e8b00a15..03895d06 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,7 +33,7 @@ names-version = "0.47.0" jib-version = "3.3.2" git-properties-version = "2.4.1" springboot-version = "3.1.2" -springboot-dependencies-version = "1.1.2" +springboot-dependencies-version = "1.1.3" test-logger-version = "3.2.0" git-version-plugin-version = "3.0.0" From b50d5d2ee6fa7380388ae2c6c961b35bad6cae1f Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Mon, 14 Aug 2023 22:13:16 +0200 Subject: [PATCH 08/55] Claim drop on event message received (#559) * feat: claim drop on message received * feat: use drop claim event * feat: event on drop progress * fix: use actual percentage * doc: fix doc link --- .../ROOT/pages/configuration/discord.adoc | 2 +- .../miner/api/ws/data/message/DropClaim.java | 25 ++++ .../api/ws/data/message/DropProgress.java | 25 ++++ .../api/ws/data/message/IPubSubMessage.java | 2 + .../data/message/dropclaim/DropClaimData.java | 28 ++++ .../dropprogress/DropProgressData.java | 29 ++++ .../api/ws/data/request/topic/TopicName.java | 3 +- .../miner/event/EventVariableKey.java | 1 + .../event/impl/DropClaimedChannelEvent.java | 41 ++++++ .../event/impl/DropProgressChannelEvent.java | 60 ++++++++ .../miner/factory/MinerFactory.java | 4 + .../factory/PubSubMessageHandlerFactory.java | 6 + .../miner/handler/ClaimDropHandler.java | 57 +++++++ .../handler/PubSubMessageHandlerAdapter.java | 6 + .../channelpointsminer/miner/miner/Miner.java | 16 +- ...witchPubSubWebSocketClientMessageTest.java | 50 +++++++ .../miner/factory/MinerFactoryTest.java | 44 ++++-- .../PubSubMessageHandlerFactoryTest.java | 6 + .../miner/handler/ClaimDropHandlerTest.java | 139 ++++++++++++++++++ .../DiscordMessageBuilderEmbedTest.java | 35 +++++ .../DiscordMessageBuilderMessageTest.java | 24 +++ .../miner/miner/MinerTest.java | 18 ++- .../src/test/resources/api/ws/dropClaim.json | 7 + .../test/resources/api/ws/dropProgress.json | 7 + 24 files changed, 606 insertions(+), 29 deletions(-) create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropClaim.java create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropProgress.java create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropclaim/DropClaimData.java create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropprogress/DropProgressData.java create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropClaimedChannelEvent.java create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropProgressChannelEvent.java create mode 100644 miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandler.java create mode 100644 miner/src/test/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandlerTest.java create mode 100644 miner/src/test/resources/api/ws/dropClaim.json create mode 100644 miner/src/test/resources/api/ws/dropProgress.json diff --git a/miner/docs/modules/ROOT/pages/configuration/discord.adoc b/miner/docs/modules/ROOT/pages/configuration/discord.adoc index f62b7c6d..06d02150 100644 --- a/miner/docs/modules/ROOT/pages/configuration/discord.adoc +++ b/miner/docs/modules/ROOT/pages/configuration/discord.adoc @@ -22,7 +22,7 @@ include::example$discord-filtering.json[] Format works the same way as <> except that additional parameters are provided. Placeholders are expected to be between braces, example: `\{placeholder_name}`. -Available values can be seen in link:https://github.com/Rakambda/ChannelPointsMiner/blob/filter/develop/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java[EventVariableKey]. +Available values can be seen in link:https://github.com/Rakambda/ChannelPointsMiner/blob/develop/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java[EventVariableKey]. NOTE: If you want to override the format of one event, you'll have to do the all as it'll also act as a filter. diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropClaim.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropClaim.java new file mode 100644 index 00000000..e38d03d1 --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropClaim.java @@ -0,0 +1,25 @@ +package fr.rakambda.channelpointsminer.miner.api.ws.data.message; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropclaim.DropClaimData; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.jetbrains.annotations.NotNull; + +@JsonTypeName("drop-claim") +@Getter +@EqualsAndHashCode(callSuper = true) +@ToString +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class DropClaim extends IPubSubMessage{ + @JsonProperty("data") + @NotNull + private DropClaimData data; +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropProgress.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropProgress.java new file mode 100644 index 00000000..2ea2e182 --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/DropProgress.java @@ -0,0 +1,25 @@ +package fr.rakambda.channelpointsminer.miner.api.ws.data.message; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropprogress.DropProgressData; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.jetbrains.annotations.NotNull; + +@JsonTypeName("drop-progress") +@Getter +@EqualsAndHashCode(callSuper = true) +@ToString +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class DropProgress extends IPubSubMessage{ + @JsonProperty("data") + @NotNull + private DropProgressData data; +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/IPubSubMessage.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/IPubSubMessage.java index 59d661c3..d1a4129a 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/IPubSubMessage.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/IPubSubMessage.java @@ -36,6 +36,8 @@ @JsonSubTypes.Type(value = CommunityMomentStart.class, name = "active"), @JsonSubTypes.Type(value = ActiveMultipliersUpdated.class, name = "active-multipliers-updated"), @JsonSubTypes.Type(value = ReadNotifications.class, name = "read-notifications"), + @JsonSubTypes.Type(value = DropProgress.class, name = "drop-progress"), + @JsonSubTypes.Type(value = DropClaim.class, name = "drop-claim"), }) @EqualsAndHashCode @ToString diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropclaim/DropClaimData.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropclaim/DropClaimData.java new file mode 100644 index 00000000..3c9ea50f --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropclaim/DropClaimData.java @@ -0,0 +1,28 @@ +package fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropclaim; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.jetbrains.annotations.NotNull; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@EqualsAndHashCode +@ToString +@Builder +public class DropClaimData{ + @JsonProperty("drop_id") + @NotNull + private String dropId; + @JsonProperty("drop_instance_id") + @NotNull + private String dropInstanceId; + @JsonProperty("channel_id") + @NotNull + private String channelId; +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropprogress/DropProgressData.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropprogress/DropProgressData.java new file mode 100644 index 00000000..058b75c2 --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/dropprogress/DropProgressData.java @@ -0,0 +1,29 @@ +package fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropprogress; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.jetbrains.annotations.NotNull; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@EqualsAndHashCode +@ToString +@Builder +public class DropProgressData{ + @JsonProperty("drop_id") + @NotNull + private String dropId; + @JsonProperty("channel_id") + @NotNull + private String channelId; + @JsonProperty("current_progress_min") + private int currentProgressMin; + @JsonProperty("required_progress_min") + private int requiredProgressMin; +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java index 09da20c5..63411152 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java @@ -15,7 +15,8 @@ public enum TopicName{ RAID("raid", false), PREDICTIONS_CHANNEL_V1("predictions-channel-v1", false), ONSITE_NOTIFICATIONS("onsite-notifications", true), - COMMUNITY_MOMENTS_CHANNEL_V1("community-moments-channel-v1", false); + COMMUNITY_MOMENTS_CHANNEL_V1("community-moments-channel-v1", false), + USER_DROP_EVENTS("user-drop-events", true); @Getter(onMethod_ = @JsonValue) private final String value; diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java index e8034441..e133e152 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java @@ -10,6 +10,7 @@ public class EventVariableKey{ public static final String COLOR = "color"; public static final String COMMIT = "commit"; public static final String DROP_NAME = "drop_name"; + public static final String DROP_PROGRESS = "drop_progress"; public static final String MESSAGE = "message"; public static final String EMOJI = "emoji"; public static final String POINTS = "points"; diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropClaimedChannelEvent.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropClaimedChannelEvent.java new file mode 100644 index 00000000..cda553ad --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropClaimedChannelEvent.java @@ -0,0 +1,41 @@ +package fr.rakambda.channelpointsminer.miner.event.impl; + +import fr.rakambda.channelpointsminer.miner.event.AbstractLoggableStreamerEvent; +import fr.rakambda.channelpointsminer.miner.streamer.Streamer; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.time.Instant; + +@EqualsAndHashCode(callSuper = true) +@ToString +public class DropClaimedChannelEvent extends AbstractLoggableStreamerEvent{ + public DropClaimedChannelEvent(@NotNull String streamerId, @Nullable String streamerUsername, @Nullable Streamer streamer, @NotNull Instant instant){ + super(streamerId, streamerUsername, streamer, instant); + } + + @Override + @NotNull + public String getConsoleLogFormat(){ + return "Drop claimed on channel {streamer}"; + } + + @Override + @NotNull + public String getDefaultFormat(){ + return "[{username}] {emoji} : Drop claimed on channel {streamer}"; + } + + @Override + @NotNull + protected String getColor(){ + return COLOR_INFO; + } + + @Override + @NotNull + protected String getEmoji(){ + return "🎁"; + } +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropProgressChannelEvent.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropProgressChannelEvent.java new file mode 100644 index 00000000..7af0ac5c --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl/DropProgressChannelEvent.java @@ -0,0 +1,60 @@ +package fr.rakambda.channelpointsminer.miner.event.impl; + +import fr.rakambda.channelpointsminer.miner.event.AbstractLoggableStreamerEvent; +import fr.rakambda.channelpointsminer.miner.event.EventVariableKey; +import fr.rakambda.channelpointsminer.miner.streamer.Streamer; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.time.Instant; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +public class DropProgressChannelEvent extends AbstractLoggableStreamerEvent{ + private final String progress; + + public DropProgressChannelEvent(@NotNull String streamerId, @Nullable String streamerUsername, @Nullable Streamer streamer, @NotNull Instant instant, int progress){ + super(streamerId, streamerUsername, streamer, instant); + this.progress = Integer.toString(progress); + } + + @Override + @NotNull + public String getConsoleLogFormat(){ + return "Drop progress on channel {streamer} : {drop_progress}%"; + } + + @Override + @NotNull + public String getDefaultFormat(){ + return "[{username}] {emoji} : Drop progress on channel {streamer} : {drop_progress}%"; + } + + @Override + public String lookup(String key){ + if(EventVariableKey.DROP_PROGRESS.equals(key)){ + return progress; + } + return super.lookup(key); + } + + @Override + @NotNull + public Map getEmbedFields(){ + return Map.of("Progress", EventVariableKey.DROP_PROGRESS); + } + + @Override + @NotNull + protected String getColor(){ + return COLOR_INFO; + } + + @Override + @NotNull + protected String getEmoji(){ + return "🎁"; + } +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactory.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactory.java index 395024c4..b137943a 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactory.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactory.java @@ -30,12 +30,16 @@ public static Miner create(@NotNull AccountConfiguration config, @NotNull IEvent database, eventManager); + var syncInventory = MinerRunnableFactory.createSyncInventory(miner, eventManager); + miner.setSyncInventory(syncInventory); + miner.addPubSubHandler(PubSubMessageHandlerFactory.createClaimAvailableHandler(miner, eventManager)); miner.addPubSubHandler(PubSubMessageHandlerFactory.createStreamStartEndHandler(miner, eventManager)); miner.addPubSubHandler(PubSubMessageHandlerFactory.createFollowRaidHandler(miner)); miner.addPubSubHandler(PubSubMessageHandlerFactory.createPredictionsHandler(miner, BetPlacerFactory.created(miner), eventManager)); miner.addPubSubHandler(PubSubMessageHandlerFactory.createPointsHandler(miner, eventManager)); miner.addPubSubHandler(PubSubMessageHandlerFactory.createClaimMomentHandler(miner, eventManager)); + miner.addPubSubHandler(PubSubMessageHandlerFactory.createClaimDropHandler(miner, eventManager)); eventManager.addEventHandler(LogEventListenerFactory.createLogger()); if(Objects.nonNull(config.getDiscord().getUrl())){ diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactory.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactory.java index 5d692e2a..dbba5f5d 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactory.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactory.java @@ -2,6 +2,7 @@ import fr.rakambda.channelpointsminer.miner.event.manager.IEventManager; import fr.rakambda.channelpointsminer.miner.handler.ClaimAvailableHandler; +import fr.rakambda.channelpointsminer.miner.handler.ClaimDropHandler; import fr.rakambda.channelpointsminer.miner.handler.ClaimMomentHandler; import fr.rakambda.channelpointsminer.miner.handler.FollowRaidHandler; import fr.rakambda.channelpointsminer.miner.handler.IPubSubMessageHandler; @@ -45,4 +46,9 @@ public static IPubSubMessageHandler createPointsHandler(@NotNull IMiner miner, @ public static IPubSubMessageHandler createClaimMomentHandler(@NotNull IMiner miner, @NotNull IEventManager eventManager){ return new ClaimMomentHandler(miner, eventManager); } + + @NotNull + public static IPubSubMessageHandler createClaimDropHandler(@NotNull IMiner miner, @NotNull IEventManager eventManager){ + return new ClaimDropHandler(miner, eventManager); + } } diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandler.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandler.java new file mode 100644 index 00000000..d74639bc --- /dev/null +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandler.java @@ -0,0 +1,57 @@ +package fr.rakambda.channelpointsminer.miner.handler; + +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropClaim; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropProgress; +import fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.Topic; +import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimedChannelEvent; +import fr.rakambda.channelpointsminer.miner.event.impl.DropProgressChannelEvent; +import fr.rakambda.channelpointsminer.miner.event.manager.IEventManager; +import fr.rakambda.channelpointsminer.miner.factory.TimeFactory; +import fr.rakambda.channelpointsminer.miner.log.LogContext; +import fr.rakambda.channelpointsminer.miner.miner.IMiner; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import java.util.Objects; + +@Slf4j +@RequiredArgsConstructor +public class ClaimDropHandler extends PubSubMessageHandlerAdapter{ + @NotNull + private IMiner miner; + @NotNull + private IEventManager eventManager; + + @Override + public void onDropProgress(@NotNull Topic topic, @NotNull DropProgress message){ + var channelId = message.getData().getChannelId(); + var streamer = miner.getStreamerById(channelId).orElse(null); + var username = Objects.isNull(streamer) ? null : streamer.getUsername(); + + try(var ignored = LogContext.with(miner).withStreamer(streamer)){ + var progress = 100 * message.getData().getCurrentProgressMin() / message.getData().getRequiredProgressMin(); + var event = new DropProgressChannelEvent(channelId, username, streamer, TimeFactory.now(), progress); + eventManager.onEvent(event); + } + } + + @Override + public void onDropClaim(@NotNull Topic topic, @NotNull DropClaim message){ + var channelId = message.getData().getChannelId(); + var streamer = miner.getStreamerById(channelId).orElse(null); + var username = Objects.isNull(streamer) ? null : streamer.getUsername(); + + try(var ignored = LogContext.with(miner).withStreamer(streamer)){ + miner.getGqlApi().dropsPageClaimDropRewards(message.getData().getDropInstanceId()) + .filter(r -> { + if(!r.isError()){ + return true; + } + log.error("Failed to claim drop due to `{}` | {}", r.getError(), r.getErrors()); + return false; + }) + .map(r -> new DropClaimedChannelEvent(channelId, username, streamer, TimeFactory.now())) + .ifPresent(eventManager::onEvent); + } + } +} diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/PubSubMessageHandlerAdapter.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/PubSubMessageHandlerAdapter.java index 98a1d326..c8c3fb53 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/PubSubMessageHandlerAdapter.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/handler/PubSubMessageHandlerAdapter.java @@ -7,6 +7,8 @@ import fr.rakambda.channelpointsminer.miner.api.ws.data.message.CommunityMomentStart; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.CreateNotification; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DeleteNotification; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropClaim; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropProgress; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.EventCreated; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.EventUpdated; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.GlobalLastViewedContentUpdated; @@ -85,6 +87,10 @@ public void onCommunityMomentStart(@NotNull Topic topic, @NotNull CommunityMomen public void onReadNotifications(@NotNull Topic topic, @NotNull ReadNotifications message){} + public void onDropProgress(@NotNull Topic topic, @NotNull DropProgress message){} + + public void onDropClaim(@NotNull Topic topic, @NotNull DropClaim message){} + @Override public void handle(@NotNull Topic topic, @NotNull IPubSubMessage message){ for(var clazz : ClassWalker.range(message.getClass(), IPubSubMessage.class)){ diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java index ed65e0d1..0ded2553 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java @@ -30,6 +30,7 @@ import fr.rakambda.channelpointsminer.miner.streamer.Streamer; import lombok.AccessLevel; import lombok.Getter; +import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.apache.logging.log4j.ThreadContext; import org.jetbrains.annotations.NotNull; @@ -51,6 +52,7 @@ import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_CHANNEL_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_USER_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.RAID; +import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.USER_DROP_EVENTS; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.VIDEO_PLAYBACK_BY_ID; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; @@ -78,6 +80,8 @@ public class Miner implements AutoCloseable, IMiner, ITwitchPubSubMessageListene private final MinerData minerData; private UpdateStreamInfo updateStreamInfo; + @Setter + @Getter(value = AccessLevel.PUBLIC, onMethod_ = {@TestOnly}) private SyncInventory syncInventory; @Getter @@ -126,7 +130,7 @@ public void start(){ scheduledExecutor.scheduleWithFixedDelay(getUpdateStreamInfo(), 0, 2, MINUTES); scheduledExecutor.scheduleWithFixedDelay(MinerRunnableFactory.createSendMinutesWatched(this), 0, 1, MINUTES); scheduledExecutor.scheduleAtFixedRate(MinerRunnableFactory.createWebSocketPing(this), 25, 25, SECONDS); - scheduledExecutor.scheduleAtFixedRate(getSyncInventory(), 1, 15, MINUTES); + scheduledExecutor.scheduleAtFixedRate(syncInventory, 1, 15, MINUTES); var streamerConfigurationReload = MinerRunnableFactory.createStreamerConfigurationReload(this, eventManager, streamerSettingsFactory, accountConfiguration.isLoadFollows()); if(accountConfiguration.getReloadEvery() > 0){ @@ -180,14 +184,6 @@ private UpdateStreamInfo getUpdateStreamInfo(){ return updateStreamInfo; } - @NotNull - private SyncInventory getSyncInventory(){ - if(Objects.isNull(syncInventory)){ - syncInventory = MinerRunnableFactory.createSyncInventory(this, eventManager); - } - return syncInventory; - } - private void listenTopic(@NotNull TopicName name, @NotNull String target){ pubSubWebSocketPool.listenTopic(Topics.buildFromName(name, target, twitchLogin.getAccessToken())); } @@ -223,6 +219,7 @@ public void updateStreamer(@NotNull Streamer streamer){ } listenTopic(VIDEO_PLAYBACK_BY_ID, streamer.getId()); + listenTopic(USER_DROP_EVENTS, streamer.getId()); if(streamer.getSettings().isMakePredictions()){ listenTopic(PREDICTIONS_USER_V1, getTwitchLogin().fetchUserId(gqlApi)); @@ -267,6 +264,7 @@ public boolean removeStreamer(@NotNull Streamer streamer){ removeTopic(PREDICTIONS_CHANNEL_V1, streamer.getId()); removeTopic(COMMUNITY_MOMENTS_CHANNEL_V1, streamer.getId()); removeTopic(RAID, streamer.getId()); + removeTopic(USER_DROP_EVENTS, streamer.getId()); chatClient.leave(streamer.getUsername()); eventManager.onEvent(new StreamerRemovedEvent(streamer, TimeFactory.now())); diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java index 090e287b..9319a01e 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java @@ -8,6 +8,8 @@ import fr.rakambda.channelpointsminer.miner.api.ws.data.message.CommunityMomentStart; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.CreateNotification; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DeleteNotification; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropClaim; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropProgress; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.PointsEarned; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.PointsSpent; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.PredictionMade; @@ -34,6 +36,8 @@ import fr.rakambda.channelpointsminer.miner.api.ws.data.message.createnotification.TextContent; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.createnotification.TextNotificationDataBlock; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.deletenotification.DeleteNotificationData; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropclaim.DropClaimData; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropprogress.DropProgressData; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.pointsearned.Balance; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.pointsearned.PointsEarnedData; import fr.rakambda.channelpointsminer.miner.api.ws.data.message.pointsspent.PointsSpentData; @@ -80,6 +84,7 @@ import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.ONSITE_NOTIFICATIONS; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_USER_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.RAID; +import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.USER_DROP_EVENTS; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.VIDEO_PLAYBACK_BY_ID; import static java.time.ZoneOffset.UTC; import static org.mockito.Mockito.timeout; @@ -812,6 +817,51 @@ void onReadNotifications(WebsocketMockServer server){ verify(listener, timeout(MESSAGE_TIMEOUT)).onWebSocketMessage(expected); } + @Test + void onDropProgress(WebsocketMockServer server){ + server.send(TestUtils.getAllResourceContent("api/ws/dropProgress.json")); + + var expected = MessageResponse.builder() + .data(MessageData.builder() + .topic(Topic.builder() + .name(USER_DROP_EVENTS) + .target("123456789") + .build()) + .message(DropProgress.builder() + .data(DropProgressData.builder() + .dropId("drop-id") + .channelId("123456789") + .currentProgressMin(1) + .requiredProgressMin(15) + .build()) + .build()) + .build()) + .build(); + verify(listener, timeout(MESSAGE_TIMEOUT)).onWebSocketMessage(expected); + } + + @Test + void onDropClaimEvent(WebsocketMockServer server){ + server.send(TestUtils.getAllResourceContent("api/ws/dropClaim.json")); + + var expected = MessageResponse.builder() + .data(MessageData.builder() + .topic(Topic.builder() + .name(USER_DROP_EVENTS) + .target("123456789") + .build()) + .message(DropClaim.builder() + .data(DropClaimData.builder() + .dropId("drop-id") + .channelId("123456789") + .dropInstanceId("drop-instance-id") + .build()) + .build()) + .build()) + .build(); + verify(listener, timeout(MESSAGE_TIMEOUT)).onWebSocketMessage(expected); + } + @BeforeEach void setUp(WebsocketMockServer server) throws InterruptedException{ var uri = URI.create("ws://127.0.0.1:" + server.getPort()); diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactoryTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactoryTest.java index cd62bbc1..caf17fd8 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactoryTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/MinerFactoryTest.java @@ -11,6 +11,7 @@ import fr.rakambda.channelpointsminer.miner.database.IDatabase; import fr.rakambda.channelpointsminer.miner.event.manager.IEventManager; import fr.rakambda.channelpointsminer.miner.handler.ClaimAvailableHandler; +import fr.rakambda.channelpointsminer.miner.handler.ClaimDropHandler; import fr.rakambda.channelpointsminer.miner.handler.ClaimMomentHandler; import fr.rakambda.channelpointsminer.miner.handler.FollowRaidHandler; import fr.rakambda.channelpointsminer.miner.handler.PointsHandler; @@ -18,8 +19,9 @@ import fr.rakambda.channelpointsminer.miner.handler.StreamStartEndHandler; import fr.rakambda.channelpointsminer.miner.log.LoggerEventListener; import fr.rakambda.channelpointsminer.miner.log.discord.DiscordEventListener; +import fr.rakambda.channelpointsminer.miner.miner.IMiner; +import fr.rakambda.channelpointsminer.miner.runnable.SyncInventory; import fr.rakambda.channelpointsminer.miner.tests.ParallelizableTest; -import org.assertj.core.api.Assertions; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.junit.jupiter.api.BeforeEach; @@ -28,8 +30,10 @@ import java.net.MalformedURLException; import java.net.URL; import java.sql.SQLException; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.verify; @@ -62,6 +66,8 @@ class MinerFactoryTest{ private ILoginMethod loginMethod; @Mock private IEventManager eventManager; + @Mock + private SyncInventory syncInventory; @BeforeEach void setUp(){ @@ -74,19 +80,23 @@ void setUp(){ @Test void nominal(){ - try(var apiFactory = mockStatic(ApiFactory.class)){ + try(var apiFactory = mockStatic(ApiFactory.class); + var minerRunnableFactory = mockStatic(MinerRunnableFactory.class)){ apiFactory.when(() -> ApiFactory.createLoginProvider(USERNAME, loginMethod, eventManager)).thenReturn(passportApi); + minerRunnableFactory.when(() -> MinerRunnableFactory.createSyncInventory(any(IMiner.class), eq(eventManager))).thenReturn(syncInventory); var miner = MinerFactory.create(accountConfiguration, eventManager); - Assertions.assertThat(miner.getPubSubMessageHandlers()) - .hasSize(6) + assertThat(miner.getSyncInventory()).isEqualTo(syncInventory); + assertThat(miner.getPubSubMessageHandlers()) + .hasSize(7) .hasAtLeastOneElementOfType(ClaimAvailableHandler.class) .hasAtLeastOneElementOfType(StreamStartEndHandler.class) .hasAtLeastOneElementOfType(FollowRaidHandler.class) .hasAtLeastOneElementOfType(PredictionsHandler.class) .hasAtLeastOneElementOfType(PointsHandler.class) - .hasAtLeastOneElementOfType(ClaimMomentHandler.class); + .hasAtLeastOneElementOfType(ClaimMomentHandler.class) + .hasAtLeastOneElementOfType(ClaimDropHandler.class); verify(eventManager).addEventHandler(any(LoggerEventListener.class)); verifyNoMoreInteractions(eventManager); @@ -97,24 +107,28 @@ void nominal(){ @Test void nominalWithDiscord() throws MalformedURLException{ - try(var apiFactory = mockStatic(ApiFactory.class)){ + try(var apiFactory = mockStatic(ApiFactory.class); + var minerRunnableFactory = mockStatic(MinerRunnableFactory.class)){ var discordWebhook = new URL("https://discord-webhook"); apiFactory.when(() -> ApiFactory.createLoginProvider(USERNAME, loginMethod, eventManager)).thenReturn(passportApi); apiFactory.when(() -> ApiFactory.createdDiscordApi(discordWebhook)).thenReturn(discordApi); + minerRunnableFactory.when(() -> MinerRunnableFactory.createSyncInventory(any(IMiner.class), eq(eventManager))).thenReturn(syncInventory); when(discordConfiguration.getUrl()).thenReturn(discordWebhook); var miner = MinerFactory.create(accountConfiguration, eventManager); - Assertions.assertThat(miner.getPubSubMessageHandlers()) - .hasSize(6) + assertThat(miner.getSyncInventory()).isEqualTo(syncInventory); + assertThat(miner.getPubSubMessageHandlers()) + .hasSize(7) .hasAtLeastOneElementOfType(ClaimAvailableHandler.class) .hasAtLeastOneElementOfType(StreamStartEndHandler.class) .hasAtLeastOneElementOfType(FollowRaidHandler.class) .hasAtLeastOneElementOfType(PredictionsHandler.class) .hasAtLeastOneElementOfType(PointsHandler.class) - .hasAtLeastOneElementOfType(ClaimMomentHandler.class); + .hasAtLeastOneElementOfType(ClaimMomentHandler.class) + .hasAtLeastOneElementOfType(ClaimDropHandler.class); verify(eventManager).addEventHandler(any(LoggerEventListener.class)); verify(eventManager).addEventHandler(any(DiscordEventListener.class)); @@ -127,24 +141,28 @@ void nominalWithDiscord() throws MalformedURLException{ @Test void nominalWithAnalytics() throws SQLException{ try(var apiFactory = mockStatic(ApiFactory.class); - var databaseFactory = mockStatic(DatabaseFactory.class)){ + var databaseFactory = mockStatic(DatabaseFactory.class); + var minerRunnableFactory = mockStatic(MinerRunnableFactory.class)){ apiFactory.when(() -> ApiFactory.createLoginProvider(USERNAME, loginMethod, eventManager)).thenReturn(passportApi); databaseFactory.when(() -> DatabaseFactory.createDatabase(databaseConfiguration)).thenReturn(database); databaseFactory.when(() -> DatabaseFactory.createDatabaseHandler(database, RECORD_USER_PREDICTIONS)).thenReturn(databaseEventHandler); + minerRunnableFactory.when(() -> MinerRunnableFactory.createSyncInventory(any(IMiner.class), eq(eventManager))).thenReturn(syncInventory); when(analyticsConfiguration.isEnabled()).thenReturn(true); when(analyticsConfiguration.getDatabase()).thenReturn(databaseConfiguration); var miner = MinerFactory.create(accountConfiguration, eventManager); - Assertions.assertThat(miner.getPubSubMessageHandlers()) - .hasSize(6) + assertThat(miner.getSyncInventory()).isEqualTo(syncInventory); + assertThat(miner.getPubSubMessageHandlers()) + .hasSize(7) .hasAtLeastOneElementOfType(ClaimAvailableHandler.class) .hasAtLeastOneElementOfType(StreamStartEndHandler.class) .hasAtLeastOneElementOfType(FollowRaidHandler.class) .hasAtLeastOneElementOfType(PredictionsHandler.class) .hasAtLeastOneElementOfType(PointsHandler.class) - .hasAtLeastOneElementOfType(ClaimMomentHandler.class); + .hasAtLeastOneElementOfType(ClaimMomentHandler.class) + .hasAtLeastOneElementOfType(ClaimDropHandler.class); verify(eventManager).addEventHandler(any(LoggerEventListener.class)); verify(eventManager).addEventHandler(any(DatabaseEventHandler.class)); diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactoryTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactoryTest.java index da7323da..074c25f6 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactoryTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/factory/PubSubMessageHandlerFactoryTest.java @@ -2,6 +2,7 @@ import fr.rakambda.channelpointsminer.miner.event.manager.IEventManager; import fr.rakambda.channelpointsminer.miner.handler.ClaimAvailableHandler; +import fr.rakambda.channelpointsminer.miner.handler.ClaimDropHandler; import fr.rakambda.channelpointsminer.miner.handler.ClaimMomentHandler; import fr.rakambda.channelpointsminer.miner.handler.FollowRaidHandler; import fr.rakambda.channelpointsminer.miner.handler.PointsHandler; @@ -55,4 +56,9 @@ void createPointsHandler(){ void createClaimMomentHandler(){ assertThat(PubSubMessageHandlerFactory.createClaimMomentHandler(miner, eventManager)).isNotNull().isInstanceOf(ClaimMomentHandler.class); } + + @Test + void createClaimDropHandler(){ + assertThat(PubSubMessageHandlerFactory.createClaimDropHandler(miner, eventManager)).isNotNull().isInstanceOf(ClaimDropHandler.class); + } } \ No newline at end of file diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandlerTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandlerTest.java new file mode 100644 index 00000000..2a84fefb --- /dev/null +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/handler/ClaimDropHandlerTest.java @@ -0,0 +1,139 @@ +package fr.rakambda.channelpointsminer.miner.handler; + +import fr.rakambda.channelpointsminer.miner.api.gql.gql.GQLApi; +import fr.rakambda.channelpointsminer.miner.api.gql.gql.data.GQLResponse; +import fr.rakambda.channelpointsminer.miner.api.gql.gql.data.dropspageclaimdroprewards.DropsPageClaimDropRewardsData; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropClaim; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.DropProgress; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropclaim.DropClaimData; +import fr.rakambda.channelpointsminer.miner.api.ws.data.message.dropprogress.DropProgressData; +import fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.Topic; +import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimedChannelEvent; +import fr.rakambda.channelpointsminer.miner.event.impl.DropProgressChannelEvent; +import fr.rakambda.channelpointsminer.miner.event.manager.IEventManager; +import fr.rakambda.channelpointsminer.miner.factory.TimeFactory; +import fr.rakambda.channelpointsminer.miner.miner.IMiner; +import fr.rakambda.channelpointsminer.miner.streamer.Streamer; +import fr.rakambda.channelpointsminer.miner.tests.ParallelizableTest; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import java.time.Instant; +import java.util.Optional; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ParallelizableTest +@ExtendWith(MockitoExtension.class) +class ClaimDropHandlerTest{ + private static final String DROP_INSTANCE_ID = "drop-instance-id"; + private static final String CHANNEL_ID = "channel-id"; + private static final String CHANNEL_USERNAME = "channel-username"; + private static final Instant NOW = Instant.parse("2022-05-15T12:02:14.000Z"); + private static final int CURRENT_PROGRESS = 1; + private static final int REQUIRED_PROGRESS = 4; + + @InjectMocks + private ClaimDropHandler tested; + + @Mock + private IMiner miner; + @Mock + private IEventManager eventManager; + @Mock + private GQLApi gqlApi; + @Mock + private Topic topic; + @Mock + private Streamer streamer; + @Mock + private DropClaim dropClaim; + @Mock + private DropClaimData dropClaimData; + @Mock + private DropProgress dropProgress; + @Mock + private DropProgressData dropProgressData; + + @Mock + private GQLResponse dropsPageClaimDropRewardsDataGQLResponse; + + @BeforeEach + void setUp(){ + lenient().when(dropClaim.getData()).thenReturn(dropClaimData); + lenient().when(dropClaimData.getChannelId()).thenReturn(CHANNEL_ID); + lenient().when(dropClaimData.getDropInstanceId()).thenReturn(DROP_INSTANCE_ID); + lenient().when(dropProgress.getData()).thenReturn(dropProgressData); + lenient().when(dropProgressData.getChannelId()).thenReturn(CHANNEL_ID); + lenient().when(dropProgressData.getCurrentProgressMin()).thenReturn(CURRENT_PROGRESS); + lenient().when(dropProgressData.getRequiredProgressMin()).thenReturn(REQUIRED_PROGRESS); + + lenient().when(miner.getGqlApi()).thenReturn(gqlApi); + lenient().when(miner.getStreamerById(CHANNEL_ID)).thenReturn(Optional.of(streamer)); + lenient().when(streamer.getUsername()).thenReturn(CHANNEL_USERNAME); + + lenient().when(dropsPageClaimDropRewardsDataGQLResponse.isError()).thenReturn(false); + lenient().when(gqlApi.dropsPageClaimDropRewards(DROP_INSTANCE_ID)).thenReturn(Optional.of(dropsPageClaimDropRewardsDataGQLResponse)); + } + + @Test + void dropClaim(){ + try(var timeFactory = mockStatic(TimeFactory.class)){ + timeFactory.when(TimeFactory::now).thenReturn(NOW); + tested.onDropClaim(topic, dropClaim); + + verify(eventManager).onEvent(new DropClaimedChannelEvent(CHANNEL_ID, CHANNEL_USERNAME, streamer, NOW)); + } + } + + @Test + void dropClaimUnknownStreamer(){ + try(var timeFactory = mockStatic(TimeFactory.class)){ + timeFactory.when(TimeFactory::now).thenReturn(NOW); + lenient().when(miner.getStreamerById(CHANNEL_ID)).thenReturn(Optional.empty()); + + tested.onDropClaim(topic, dropClaim); + + verify(eventManager).onEvent(new DropClaimedChannelEvent(CHANNEL_ID, null, null, NOW)); + } + } + + @Test + void dropClaimError(){ + when(dropsPageClaimDropRewardsDataGQLResponse.isError()).thenReturn(true); + + tested.onDropClaim(topic, dropClaim); + + verify(eventManager, never()).onEvent(any(DropClaimedChannelEvent.class)); + } + + @Test + void dropProgress(){ + try(var timeFactory = mockStatic(TimeFactory.class)){ + timeFactory.when(TimeFactory::now).thenReturn(NOW); + + tested.onDropProgress(topic, dropProgress); + + verify(eventManager).onEvent(new DropProgressChannelEvent(CHANNEL_ID, CHANNEL_USERNAME, streamer, NOW, 25)); + } + } + + @Test + void dropProgressUnknownStreamer(){ + try(var timeFactory = mockStatic(TimeFactory.class)){ + timeFactory.when(TimeFactory::now).thenReturn(NOW); + lenient().when(miner.getStreamerById(CHANNEL_ID)).thenReturn(Optional.empty()); + + tested.onDropProgress(topic, dropProgress); + + verify(eventManager).onEvent(new DropProgressChannelEvent(CHANNEL_ID, null, null, NOW, 25)); + } + } +} \ No newline at end of file diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderEmbedTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderEmbedTest.java index 15b6a68b..b46a5581 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderEmbedTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderEmbedTest.java @@ -24,7 +24,9 @@ import fr.rakambda.channelpointsminer.miner.event.impl.ClaimMomentEvent; import fr.rakambda.channelpointsminer.miner.event.impl.ClaimedMomentEvent; import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimEvent; +import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimedChannelEvent; import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimedEvent; +import fr.rakambda.channelpointsminer.miner.event.impl.DropProgressChannelEvent; import fr.rakambda.channelpointsminer.miner.event.impl.EventCreatedEvent; import fr.rakambda.channelpointsminer.miner.event.impl.LoginRequiredEvent; import fr.rakambda.channelpointsminer.miner.event.impl.MinerStartedEvent; @@ -630,6 +632,39 @@ void onDropClaimed(){ .build()); } + @Test + void onDropClaimedChannel(){ + var event = new DropClaimedChannelEvent(STREAMER_ID, STREAMER_USERNAME, streamer, NOW); + event.setMiner(miner); + var webhook = tested.createEmbedMessage(event, discordEventConfiguration); + + assertThat(webhook).isEqualTo(Webhook.builder() + .embeds(List.of(Embed.builder() + .author(author) + .footer(footer) + .color(CYAN.getRGB()) + .description("[username] \uD83C\uDF81 : Drop claimed on channel streamer-name") + .build())) + .build()); + } + + @Test + void onDropProgressChannel(){ + var event = new DropProgressChannelEvent(STREAMER_ID, STREAMER_USERNAME, streamer, NOW, 20); + event.setMiner(miner); + var webhook = tested.createEmbedMessage(event, discordEventConfiguration); + + assertThat(webhook).isEqualTo(Webhook.builder() + .embeds(List.of(Embed.builder() + .author(author) + .footer(footer) + .color(CYAN.getRGB()) + .description("[username] \uD83C\uDF81 : Drop progress on channel streamer-name : 20%") + .field(Field.builder().name("Progress").value("20").build()) + .build())) + .build()); + } + @Test void onLoginRequired(){ var event = new LoginRequiredEvent(NOW, "message"); diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderMessageTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderMessageTest.java index 0e826ec4..1f023828 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderMessageTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/log/discord/DiscordMessageBuilderMessageTest.java @@ -20,7 +20,9 @@ import fr.rakambda.channelpointsminer.miner.event.impl.ClaimMomentEvent; import fr.rakambda.channelpointsminer.miner.event.impl.ClaimedMomentEvent; import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimEvent; +import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimedChannelEvent; import fr.rakambda.channelpointsminer.miner.event.impl.DropClaimedEvent; +import fr.rakambda.channelpointsminer.miner.event.impl.DropProgressChannelEvent; import fr.rakambda.channelpointsminer.miner.event.impl.EventCreatedEvent; import fr.rakambda.channelpointsminer.miner.event.impl.LoginRequiredEvent; import fr.rakambda.channelpointsminer.miner.event.impl.MinerStartedEvent; @@ -462,6 +464,28 @@ void onDropClaimed(){ .build()); } + @Test + void onDropClaimedChannel(){ + var event = new DropClaimedChannelEvent(STREAMER_ID, STREAMER_USERNAME, streamer, NOW); + event.setMiner(miner); + var webhook = tested.createSimpleMessage(event, discordEventConfiguration); + + assertThat(webhook).isEqualTo(Webhook.builder() + .content("[%s] 🎁 : Drop claimed on channel %s".formatted(USERNAME, STREAMER_USERNAME)) + .build()); + } + + @Test + void onDropProgressChannel(){ + var event = new DropProgressChannelEvent(STREAMER_ID, STREAMER_USERNAME, streamer, NOW, 26); + event.setMiner(miner); + var webhook = tested.createSimpleMessage(event, discordEventConfiguration); + + assertThat(webhook).isEqualTo(Webhook.builder() + .content("[%s] 🎁 : Drop progress on channel %s : %s%%".formatted(USERNAME, STREAMER_USERNAME, "26")) + .build()); + } + @Test void onLoginRequired(){ var event = new LoginRequiredEvent(NOW, "message"); diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java index a9a09262..264943e5 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java @@ -51,6 +51,7 @@ import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_CHANNEL_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_USER_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.RAID; +import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.USER_DROP_EVENTS; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.VIDEO_PLAYBACK_BY_ID; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; @@ -130,6 +131,7 @@ class MinerTest{ @BeforeEach void setUp() throws LoginException, IOException{ tested = new Miner(accountConfiguration, passportApi, streamerSettingsFactory, webSocketPool, scheduledExecutorService, executorService, database, eventManager); + tested.setSyncInventory(syncInventory); lenient().when(accountConfiguration.getUsername()).thenReturn(USERNAME); lenient().when(accountConfiguration.getReloadEvery()).thenReturn(0); @@ -406,6 +408,7 @@ void addStreamerWithPredictions(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_USER_V1, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } @@ -442,6 +445,7 @@ void addStreamerWithMoments(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(COMMUNITY_MOMENTS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } @@ -478,6 +482,7 @@ void addStreamerWithRaid(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(RAID, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } @@ -515,6 +520,7 @@ void addStreamerWithIrcAndStreamerOffline(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); verify(twitchChatClient, never()).join(any()); } @@ -553,6 +559,7 @@ void addStreamerWithIrcAndStreamerOnline(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); verify(twitchChatClient).join(STREAMER_USERNAME); } @@ -588,6 +595,7 @@ void addDuplicateStreamer(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } } @@ -640,10 +648,8 @@ void getStreamerById(){ tested.addStreamer(streamer1); tested.addStreamer(streamer2); - assertThat(tested.getStreamerById(id1)).isPresent() - .get().isEqualTo(streamer1); - assertThat(tested.getStreamerById(id2)).isPresent() - .get().isEqualTo(streamer2); + assertThat(tested.getStreamerById(id1)).contains(streamer1); + assertThat(tested.getStreamerById(id2)).contains(streamer2); } } @@ -672,6 +678,7 @@ void removeStreamer(){ tested.removeStreamer(streamer); verify(webSocketPool).removeTopic(Topic.builder().name(VIDEO_PLAYBACK_BY_ID).target(STREAMER_ID).build()); + verify(webSocketPool).removeTopic(Topic.builder().name(USER_DROP_EVENTS).target(STREAMER_ID).build()); verify(webSocketPool).removeTopic(Topic.builder().name(PREDICTIONS_CHANNEL_V1).target(STREAMER_ID).build()); verify(webSocketPool).removeTopic(Topic.builder().name(COMMUNITY_MOMENTS_CHANNEL_V1).target(STREAMER_ID).build()); verify(webSocketPool).removeTopic(Topic.builder().name(RAID).target(STREAMER_ID).build()); @@ -748,6 +755,7 @@ void updateStreamerAllActivatedOnline(){ assertDoesNotThrow(() -> tested.updateStreamer(streamer)); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_USER_V1, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(RAID, STREAMER_ID, ACCESS_TOKEN)); @@ -785,6 +793,7 @@ void updateStreamerAllActivatedOffline(){ assertDoesNotThrow(() -> tested.updateStreamer(streamer)); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_USER_V1, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(RAID, STREAMER_ID, ACCESS_TOKEN)); @@ -882,7 +891,6 @@ void requestInventorySync(){ ircFactory.when(() -> TwitchChatFactory.createChat(tested, CHAT_MODE, false)).thenReturn(twitchChatClient); runnableFactory.when(() -> MinerRunnableFactory.createUpdateStreamInfo(tested)).thenReturn(updateStreamInfo); - runnableFactory.when(() -> MinerRunnableFactory.createSyncInventory(tested, eventManager)).thenReturn(syncInventory); assertDoesNotThrow(() -> tested.syncInventory()); diff --git a/miner/src/test/resources/api/ws/dropClaim.json b/miner/src/test/resources/api/ws/dropClaim.json new file mode 100644 index 00000000..6048379e --- /dev/null +++ b/miner/src/test/resources/api/ws/dropClaim.json @@ -0,0 +1,7 @@ +{ + "type" : "MESSAGE", + "data" : { + "topic" : "user-drop-events.123456789", + "message" : "{\"type\":\"drop-claim\",\"data\":{\"drop_instance_id\":\"drop-instance-id\",\"drop_id\":\"drop-id\",\"channel_id\":\"123456789\"}}" + } +} \ No newline at end of file diff --git a/miner/src/test/resources/api/ws/dropProgress.json b/miner/src/test/resources/api/ws/dropProgress.json new file mode 100644 index 00000000..29e3e9e4 --- /dev/null +++ b/miner/src/test/resources/api/ws/dropProgress.json @@ -0,0 +1,7 @@ +{ + "type" : "MESSAGE", + "data" : { + "topic" : "user-drop-events.123456789", + "message" : "{\"type\":\"drop-progress\",\"data\":{\"drop_id\":\"drop-id\",\"channel_id\":\"123456789\",\"current_progress_min\":1,\"required_progress_min\":15}}" + } +} \ No newline at end of file From 14fa5a485259bf02980a79a686078e13afcc9a4a Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Tue, 15 Aug 2023 09:42:02 +0200 Subject: [PATCH 09/55] User drops events only on non android-tv clients --- .../api/ws/TwitchPubSubWebSocketClient.java | 10 ++++- .../data/request/ITwitchWebSocketRequest.java | 2 + .../ws/data/request/ListenTopicRequest.java | 2 + .../api/ws/data/request/PingRequest.java | 2 + .../ws/data/request/UnlistenTopicRequest.java | 2 + .../channelpointsminer/miner/miner/Miner.java | 4 ++ .../miner/miner/MinerTest.java | 38 +++++++++++++++++++ 7 files changed, 59 insertions(+), 1 deletion(-) diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClient.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClient.java index 177af4b4..79d23485 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClient.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClient.java @@ -26,8 +26,11 @@ import java.net.URI; import java.time.Instant; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; @@ -40,6 +43,7 @@ public class TwitchPubSubWebSocketClient extends WebSocketClient{ private final Collection listeners; @Getter private final String uuid; + private final Map listenRequests; @Getter private Instant lastPong; @@ -47,6 +51,7 @@ public class TwitchPubSubWebSocketClient extends WebSocketClient{ public TwitchPubSubWebSocketClient(@NotNull URI uri){ super(uri); uuid = UUID.randomUUID().toString(); + listenRequests = new HashMap<>(); setConnectionLostTimeout(0); topics = new HashSet<>(); @@ -73,6 +78,7 @@ public void onMessage(String messageStr){ if(responseMessage.hasError()){ log.error("Received error response {}", responseMessage); if(Objects.equals("ERR_BADAUTH", responseMessage.getError())){ + Optional.ofNullable(listenRequests.get(responseMessage.getNonce())).ifPresent(req -> log.error("Request that had bad auth: {}", req)); close(GOING_AWAY, "Invalid credentials"); } } @@ -143,7 +149,9 @@ public boolean isTopicListened(@NotNull Topic topic){ public void listenTopic(@NotNull Topics topics){ try(var ignored = LogContext.empty().withSocketId(uuid)){ if(this.topics.add(topics)){ - send(new ListenTopicRequest(topics)); + var request = new ListenTopicRequest(topics); + listenRequests.put(request.getNonce(), request); + send(request); } } } diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ITwitchWebSocketRequest.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ITwitchWebSocketRequest.java index eed5be84..be8a1bbd 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ITwitchWebSocketRequest.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ITwitchWebSocketRequest.java @@ -2,7 +2,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; +import lombok.ToString; +@ToString @Getter public abstract class ITwitchWebSocketRequest{ @JsonProperty("type") diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ListenTopicRequest.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ListenTopicRequest.java index a9252297..c76011fc 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ListenTopicRequest.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/ListenTopicRequest.java @@ -4,8 +4,10 @@ import fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.Topics; import fr.rakambda.channelpointsminer.miner.util.CommonUtils; import lombok.Getter; +import lombok.ToString; import org.jetbrains.annotations.NotNull; +@ToString(callSuper = true) @Getter public class ListenTopicRequest extends ITwitchWebSocketRequest{ private static final int NONCE_LENGTH = 30; diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/PingRequest.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/PingRequest.java index c9b8a83e..509c927a 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/PingRequest.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/PingRequest.java @@ -1,7 +1,9 @@ package fr.rakambda.channelpointsminer.miner.api.ws.data.request; import lombok.Getter; +import lombok.ToString; +@ToString(callSuper = true) @Getter public class PingRequest extends ITwitchWebSocketRequest{ public PingRequest(){ diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/UnlistenTopicRequest.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/UnlistenTopicRequest.java index 72819826..c8fc12ba 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/UnlistenTopicRequest.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/UnlistenTopicRequest.java @@ -4,8 +4,10 @@ import fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.Topics; import fr.rakambda.channelpointsminer.miner.util.CommonUtils; import lombok.Getter; +import lombok.ToString; import org.jetbrains.annotations.NotNull; +@ToString(callSuper = true) @Getter public class UnlistenTopicRequest extends ITwitchWebSocketRequest{ private static final int NONCE_LENGTH = 30; diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java index 0ded2553..d981aa89 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java @@ -4,6 +4,7 @@ import fr.rakambda.channelpointsminer.miner.api.chat.TwitchChatEventProducer; import fr.rakambda.channelpointsminer.miner.api.gql.gql.GQLApi; import fr.rakambda.channelpointsminer.miner.api.passport.ILoginProvider; +import fr.rakambda.channelpointsminer.miner.api.passport.TwitchClient; import fr.rakambda.channelpointsminer.miner.api.passport.TwitchLogin; import fr.rakambda.channelpointsminer.miner.api.passport.exceptions.CaptchaSolveRequired; import fr.rakambda.channelpointsminer.miner.api.twitch.TwitchApi; @@ -185,6 +186,9 @@ private UpdateStreamInfo getUpdateStreamInfo(){ } private void listenTopic(@NotNull TopicName name, @NotNull String target){ + if(name == USER_DROP_EVENTS && twitchLogin.getTwitchClient() == TwitchClient.ANDROID_TV){ + return; + } pubSubWebSocketPool.listenTopic(Topics.buildFromName(name, target, twitchLogin.getAccessToken())); } diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java index 264943e5..8159fe1a 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java @@ -46,6 +46,8 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicBoolean; +import static fr.rakambda.channelpointsminer.miner.api.passport.TwitchClient.ANDROID_TV; +import static fr.rakambda.channelpointsminer.miner.api.passport.TwitchClient.WEB; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.COMMUNITY_MOMENTS_CHANNEL_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.COMMUNITY_POINTS_USER_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_CHANNEL_V1; @@ -150,6 +152,7 @@ void setUp() throws LoginException, IOException{ lenient().when(twitchLogin.getUsername()).thenReturn(USERNAME); lenient().when(twitchLogin.fetchUserId(gqlApi)).thenReturn(USER_ID); lenient().when(twitchLogin.getAccessToken()).thenReturn(ACCESS_TOKEN); + lenient().when(twitchLogin.getTwitchClient()).thenReturn(WEB); lenient().when(executorService.submit(any(Runnable.class))).thenAnswer(invocation -> { var runnable = invocation.getArgument(0, Runnable.class); @@ -600,6 +603,41 @@ void addDuplicateStreamer(){ } } + @Test + void addStreamerOnAndroid(){ + try(var apiFactory = mockStatic(ApiFactory.class); + var runnableFactory = mockStatic(MinerRunnableFactory.class); + var timeFactory = mockStatic(TimeFactory.class)){ + apiFactory.when(() -> ApiFactory.createTwitchApi(twitchLogin)).thenReturn(twitchApi); + apiFactory.when(() -> ApiFactory.createVersionProvider(VERSION_PROVIDER)).thenReturn(versionProvider); + apiFactory.when(() -> ApiFactory.createIntegrityProvider(twitchLogin, versionProvider, loginMethod, eventManager)).thenReturn(integrityProvider); + apiFactory.when(() -> ApiFactory.createGqlApi(twitchLogin, integrityProvider)).thenReturn(gqlApi); + + runnableFactory.when(() -> MinerRunnableFactory.createUpdateStreamInfo(tested)).thenReturn(updateStreamInfo); + + timeFactory.when(TimeFactory::now).thenReturn(NOW); + + when(twitchLogin.getTwitchClient()).thenReturn(ANDROID_TV); + + tested.start(); + + var streamer = mock(Streamer.class); + when(streamer.getId()).thenReturn(STREAMER_ID); + when(streamer.getUsername()).thenReturn(STREAMER_USERNAME); + when(streamer.getSettings()).thenReturn(streamerSettings); + when(streamer.isStreaming()).thenReturn(false); + + assertDoesNotThrow(() -> tested.addStreamer(streamer)); + + assertThat(tested.getStreamers()).hasSize(1) + .first().usingRecursiveComparison().isEqualTo(streamer); + + verify(updateStreamInfo).run(streamer); + verify(webSocketPool, never()).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); + verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); + } + } + @Test void getStreamerByIdUnknown(){ assertThat(tested.getStreamerById("unknown")).isEmpty(); From c54a96af566b2067faa3d6bfd5eb8717df634c9c Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Tue, 15 Aug 2023 10:10:59 +0200 Subject: [PATCH 10/55] fix: user_drop_event use own user id --- .../api/ws/data/request/topic/TopicName.java | 2 +- .../channelpointsminer/miner/miner/Miner.java | 7 +-- ...witchPubSubWebSocketClientMessageTest.java | 4 +- .../miner/miner/MinerTest.java | 50 ++----------------- .../src/test/resources/api/ws/dropClaim.json | 2 +- .../test/resources/api/ws/dropProgress.json | 2 +- 6 files changed, 9 insertions(+), 58 deletions(-) diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java index 63411152..397efbc7 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/request/topic/TopicName.java @@ -16,7 +16,7 @@ public enum TopicName{ PREDICTIONS_CHANNEL_V1("predictions-channel-v1", false), ONSITE_NOTIFICATIONS("onsite-notifications", true), COMMUNITY_MOMENTS_CHANNEL_V1("community-moments-channel-v1", false), - USER_DROP_EVENTS("user-drop-events", true); + USER_DROP_EVENTS("user-drop-events", false); @Getter(onMethod_ = @JsonValue) private final String value; diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java index d981aa89..3053ef07 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/miner/Miner.java @@ -4,7 +4,6 @@ import fr.rakambda.channelpointsminer.miner.api.chat.TwitchChatEventProducer; import fr.rakambda.channelpointsminer.miner.api.gql.gql.GQLApi; import fr.rakambda.channelpointsminer.miner.api.passport.ILoginProvider; -import fr.rakambda.channelpointsminer.miner.api.passport.TwitchClient; import fr.rakambda.channelpointsminer.miner.api.passport.TwitchLogin; import fr.rakambda.channelpointsminer.miner.api.passport.exceptions.CaptchaSolveRequired; import fr.rakambda.channelpointsminer.miner.api.twitch.TwitchApi; @@ -142,6 +141,7 @@ public void start(){ } listenTopic(COMMUNITY_POINTS_USER_V1, getTwitchLogin().fetchUserId(gqlApi)); + listenTopic(USER_DROP_EVENTS, getTwitchLogin().fetchUserId(gqlApi)); listenTopic(ONSITE_NOTIFICATIONS, getTwitchLogin().fetchUserId(gqlApi)); } } @@ -186,9 +186,6 @@ private UpdateStreamInfo getUpdateStreamInfo(){ } private void listenTopic(@NotNull TopicName name, @NotNull String target){ - if(name == USER_DROP_EVENTS && twitchLogin.getTwitchClient() == TwitchClient.ANDROID_TV){ - return; - } pubSubWebSocketPool.listenTopic(Topics.buildFromName(name, target, twitchLogin.getAccessToken())); } @@ -223,7 +220,6 @@ public void updateStreamer(@NotNull Streamer streamer){ } listenTopic(VIDEO_PLAYBACK_BY_ID, streamer.getId()); - listenTopic(USER_DROP_EVENTS, streamer.getId()); if(streamer.getSettings().isMakePredictions()){ listenTopic(PREDICTIONS_USER_V1, getTwitchLogin().fetchUserId(gqlApi)); @@ -268,7 +264,6 @@ public boolean removeStreamer(@NotNull Streamer streamer){ removeTopic(PREDICTIONS_CHANNEL_V1, streamer.getId()); removeTopic(COMMUNITY_MOMENTS_CHANNEL_V1, streamer.getId()); removeTopic(RAID, streamer.getId()); - removeTopic(USER_DROP_EVENTS, streamer.getId()); chatClient.leave(streamer.getUsername()); eventManager.onEvent(new StreamerRemovedEvent(streamer, TimeFactory.now())); diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java index 9319a01e..c5f92c6a 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java @@ -830,7 +830,7 @@ void onDropProgress(WebsocketMockServer server){ .message(DropProgress.builder() .data(DropProgressData.builder() .dropId("drop-id") - .channelId("123456789") + .channelId("987654321") .currentProgressMin(1) .requiredProgressMin(15) .build()) @@ -853,7 +853,7 @@ void onDropClaimEvent(WebsocketMockServer server){ .message(DropClaim.builder() .data(DropClaimData.builder() .dropId("drop-id") - .channelId("123456789") + .channelId("987654321") .dropInstanceId("drop-instance-id") .build()) .build()) diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java index 8159fe1a..a7d14f96 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/miner/MinerTest.java @@ -46,8 +46,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicBoolean; -import static fr.rakambda.channelpointsminer.miner.api.passport.TwitchClient.ANDROID_TV; -import static fr.rakambda.channelpointsminer.miner.api.passport.TwitchClient.WEB; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.COMMUNITY_MOMENTS_CHANNEL_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.COMMUNITY_POINTS_USER_V1; import static fr.rakambda.channelpointsminer.miner.api.ws.data.request.topic.TopicName.PREDICTIONS_CHANNEL_V1; @@ -152,7 +150,6 @@ void setUp() throws LoginException, IOException{ lenient().when(twitchLogin.getUsername()).thenReturn(USERNAME); lenient().when(twitchLogin.fetchUserId(gqlApi)).thenReturn(USER_ID); lenient().when(twitchLogin.getAccessToken()).thenReturn(ACCESS_TOKEN); - lenient().when(twitchLogin.getTwitchClient()).thenReturn(WEB); lenient().when(executorService.submit(any(Runnable.class))).thenAnswer(invocation -> { var runnable = invocation.getArgument(0, Runnable.class); @@ -411,7 +408,7 @@ void addStreamerWithPredictions(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_USER_V1, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } @@ -448,7 +445,6 @@ void addStreamerWithMoments(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(COMMUNITY_MOMENTS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } @@ -485,7 +481,6 @@ void addStreamerWithRaid(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(RAID, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } @@ -523,7 +518,6 @@ void addStreamerWithIrcAndStreamerOffline(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); verify(twitchChatClient, never()).join(any()); } @@ -562,7 +556,6 @@ void addStreamerWithIrcAndStreamerOnline(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); verify(twitchChatClient).join(STREAMER_USERNAME); } @@ -598,42 +591,6 @@ void addDuplicateStreamer(){ verify(updateStreamInfo).run(streamer); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); - verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); - } - } - - @Test - void addStreamerOnAndroid(){ - try(var apiFactory = mockStatic(ApiFactory.class); - var runnableFactory = mockStatic(MinerRunnableFactory.class); - var timeFactory = mockStatic(TimeFactory.class)){ - apiFactory.when(() -> ApiFactory.createTwitchApi(twitchLogin)).thenReturn(twitchApi); - apiFactory.when(() -> ApiFactory.createVersionProvider(VERSION_PROVIDER)).thenReturn(versionProvider); - apiFactory.when(() -> ApiFactory.createIntegrityProvider(twitchLogin, versionProvider, loginMethod, eventManager)).thenReturn(integrityProvider); - apiFactory.when(() -> ApiFactory.createGqlApi(twitchLogin, integrityProvider)).thenReturn(gqlApi); - - runnableFactory.when(() -> MinerRunnableFactory.createUpdateStreamInfo(tested)).thenReturn(updateStreamInfo); - - timeFactory.when(TimeFactory::now).thenReturn(NOW); - - when(twitchLogin.getTwitchClient()).thenReturn(ANDROID_TV); - - tested.start(); - - var streamer = mock(Streamer.class); - when(streamer.getId()).thenReturn(STREAMER_ID); - when(streamer.getUsername()).thenReturn(STREAMER_USERNAME); - when(streamer.getSettings()).thenReturn(streamerSettings); - when(streamer.isStreaming()).thenReturn(false); - - assertDoesNotThrow(() -> tested.addStreamer(streamer)); - - assertThat(tested.getStreamers()).hasSize(1) - .first().usingRecursiveComparison().isEqualTo(streamer); - - verify(updateStreamInfo).run(streamer); - verify(webSocketPool, never()).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); verify(eventManager).onEvent(new StreamerAddedEvent(streamer, NOW)); } } @@ -716,7 +673,6 @@ void removeStreamer(){ tested.removeStreamer(streamer); verify(webSocketPool).removeTopic(Topic.builder().name(VIDEO_PLAYBACK_BY_ID).target(STREAMER_ID).build()); - verify(webSocketPool).removeTopic(Topic.builder().name(USER_DROP_EVENTS).target(STREAMER_ID).build()); verify(webSocketPool).removeTopic(Topic.builder().name(PREDICTIONS_CHANNEL_V1).target(STREAMER_ID).build()); verify(webSocketPool).removeTopic(Topic.builder().name(COMMUNITY_MOMENTS_CHANNEL_V1).target(STREAMER_ID).build()); verify(webSocketPool).removeTopic(Topic.builder().name(RAID).target(STREAMER_ID).build()); @@ -793,7 +749,7 @@ void updateStreamerAllActivatedOnline(){ assertDoesNotThrow(() -> tested.updateStreamer(streamer)); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_USER_V1, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(RAID, STREAMER_ID, ACCESS_TOKEN)); @@ -831,7 +787,7 @@ void updateStreamerAllActivatedOffline(){ assertDoesNotThrow(() -> tested.updateStreamer(streamer)); verify(webSocketPool).listenTopic(Topics.buildFromName(VIDEO_PLAYBACK_BY_ID, STREAMER_ID, ACCESS_TOKEN)); - verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, STREAMER_ID, ACCESS_TOKEN)); + verify(webSocketPool).listenTopic(Topics.buildFromName(USER_DROP_EVENTS, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_USER_V1, USER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(PREDICTIONS_CHANNEL_V1, STREAMER_ID, ACCESS_TOKEN)); verify(webSocketPool).listenTopic(Topics.buildFromName(RAID, STREAMER_ID, ACCESS_TOKEN)); diff --git a/miner/src/test/resources/api/ws/dropClaim.json b/miner/src/test/resources/api/ws/dropClaim.json index 6048379e..c028c8df 100644 --- a/miner/src/test/resources/api/ws/dropClaim.json +++ b/miner/src/test/resources/api/ws/dropClaim.json @@ -2,6 +2,6 @@ "type" : "MESSAGE", "data" : { "topic" : "user-drop-events.123456789", - "message" : "{\"type\":\"drop-claim\",\"data\":{\"drop_instance_id\":\"drop-instance-id\",\"drop_id\":\"drop-id\",\"channel_id\":\"123456789\"}}" + "message" : "{\"type\":\"drop-claim\",\"data\":{\"drop_instance_id\":\"drop-instance-id\",\"drop_id\":\"drop-id\",\"channel_id\":\"987654321\"}}" } } \ No newline at end of file diff --git a/miner/src/test/resources/api/ws/dropProgress.json b/miner/src/test/resources/api/ws/dropProgress.json index 29e3e9e4..ffaa1c5b 100644 --- a/miner/src/test/resources/api/ws/dropProgress.json +++ b/miner/src/test/resources/api/ws/dropProgress.json @@ -2,6 +2,6 @@ "type" : "MESSAGE", "data" : { "topic" : "user-drop-events.123456789", - "message" : "{\"type\":\"drop-progress\",\"data\":{\"drop_id\":\"drop-id\",\"channel_id\":\"123456789\",\"current_progress_min\":1,\"required_progress_min\":15}}" + "message" : "{\"type\":\"drop-progress\",\"data\":{\"drop_id\":\"drop-id\",\"channel_id\":\"987654321\",\"current_progress_min\":1,\"required_progress_min\":15}}" } } \ No newline at end of file From 2ff3ee0dab422a78474fdf20314f12a7d5937a4c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 18:00:15 +0200 Subject: [PATCH 11/55] chore(deps): update dependency gradle to v8.3 (#560) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 28216 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f4197d5..ac72c34e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca1..0adc8e1a 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum From b131d9511810868d8ea6573d8068b01c48e038f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 19:32:21 +0200 Subject: [PATCH 12/55] chore(deps): bump com.codeborne:selenide from 6.17.0 to 6.17.1 (#561) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 03895d06..1c236462 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ sqlite-version = "3.42.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.21.1" -selenide-version = "6.17.0" +selenide-version = "6.17.1" lombok-version = "1.18.28" jacocoVersion = "0.8.10" From 7af62a5c381b004ff278ac916d8748690f31eb68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:47:56 +0000 Subject: [PATCH 13/55] chore(deps): bump flyway-version from 9.21.1 to 9.21.2 (#562) Bumps `flyway-version` from 9.21.1 to 9.21.2. Updates `org.flywaydb:flyway-core` from 9.21.1 to 9.21.2 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.21.1...flyway-9.21.2) Updates `org.flywaydb:flyway-mysql` from 9.21.1 to 9.21.2 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.21.1...flyway-9.21.2) --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.flywaydb:flyway-mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1c236462..335f12c2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ mariadb-version = "3.1.4" sqlite-version = "3.42.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" -flyway-version = "9.21.1" +flyway-version = "9.21.2" selenide-version = "6.17.1" lombok-version = "1.18.28" jacocoVersion = "0.8.10" From c7b93f3d9e7590ead7530a4f93610fbb6ca5529a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:49:22 +0200 Subject: [PATCH 14/55] chore(deps): update actions/checkout action to v3.6.0 (#563) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/auto-aprove-sync-files.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-aprove-sync-files.yml b/.github/workflows/auto-aprove-sync-files.yml index 8ec32031..0fe5df2a 100644 --- a/.github/workflows/auto-aprove-sync-files.yml +++ b/.github/workflows/auto-aprove-sync-files.yml @@ -8,7 +8,7 @@ jobs: if: contains(github.event.pull_request.title, 'Synced file(s)') && github.actor == 'couchoud-t' && github.event.pull_request.base.ref == github.event.repository.default_branch runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 - name: Pull Request approval uses: hmarr/auto-approve-action@v3.2.1 with: From df65450814923be42b3bae3d7457835aa7976acb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 19:51:31 +0200 Subject: [PATCH 15/55] chore(deps): bump org.springframework.boot from 3.1.2 to 3.1.3 (#564) Bumps [org.springframework.boot](https://github.com/spring-projects/spring-boot) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.2...v3.1.3) --- updated-dependencies: - dependency-name: org.springframework.boot dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 335f12c2..192419a5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ shadow-version = "8.1.1" names-version = "0.47.0" jib-version = "3.3.2" git-properties-version = "2.4.1" -springboot-version = "3.1.2" +springboot-version = "3.1.3" springboot-dependencies-version = "1.1.3" test-logger-version = "3.2.0" git-version-plugin-version = "3.0.0" From 57d104e9ae3db79ec476f8f18a762beabf303579 Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Fri, 25 Aug 2023 17:31:20 +0200 Subject: [PATCH 16/55] =?UTF-8?q?=F0=9F=94=84=20synced=20file(s)=20with=20?= =?UTF-8?q?Rakambda/rakambda-github-files=20(#565)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: undefined --- .github/workflows/auto-aprove-sync-files.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/auto-aprove-sync-files.yml b/.github/workflows/auto-aprove-sync-files.yml index 0fe5df2a..6a5d6aad 100644 --- a/.github/workflows/auto-aprove-sync-files.yml +++ b/.github/workflows/auto-aprove-sync-files.yml @@ -8,7 +8,6 @@ jobs: if: contains(github.event.pull_request.title, 'Synced file(s)') && github.actor == 'couchoud-t' && github.event.pull_request.base.ref == github.event.repository.default_branch runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.6.0 - name: Pull Request approval uses: hmarr/auto-approve-action@v3.2.1 with: From 89b49e1e1e2cd4e98692947f09dc595634004b8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 21:43:18 +0200 Subject: [PATCH 17/55] chore(deps): bump org.mariadb.jdbc:mariadb-java-client (#568) Bumps [org.mariadb.jdbc:mariadb-java-client](https://github.com/mariadb-corporation/mariadb-connector-j) from 3.1.4 to 3.2.0. - [Release notes](https://github.com/mariadb-corporation/mariadb-connector-j/releases) - [Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/CHANGELOG.md) - [Commits](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.4...3.2.0) --- updated-dependencies: - dependency-name: org.mariadb.jdbc:mariadb-java-client dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 192419a5..16f81558 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ awaitility-version = "4.2.0" json-unit-version = "3.0.0" kitteh-irc-version = "8.0.0" hikari-cp-version = "5.0.1" -mariadb-version = "3.1.4" +mariadb-version = "3.2.0" sqlite-version = "3.42.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" From c3abb033b4250f941946f67fc6b110b1a0ad6002 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 21:44:04 +0200 Subject: [PATCH 18/55] chore(deps): bump com.codeborne:selenide from 6.17.1 to 6.17.2 (#567) Bumps [com.codeborne:selenide](https://github.com/selenide/selenide) from 6.17.1 to 6.17.2. - [Release notes](https://github.com/selenide/selenide/releases) - [Changelog](https://github.com/selenide/selenide/blob/main/CHANGELOG.md) - [Commits](https://github.com/selenide/selenide/compare/v6.17.1...v6.17.2) --- updated-dependencies: - dependency-name: com.codeborne:selenide dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 16f81558..e4203fd0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ sqlite-version = "3.42.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.21.2" -selenide-version = "6.17.1" +selenide-version = "6.17.2" lombok-version = "1.18.28" jacocoVersion = "0.8.10" From 64960fe7883a6b252fe6b2abe88ca378b9374566 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Aug 2023 18:56:09 +0000 Subject: [PATCH 19/55] chore(deps): bump org.xerial:sqlite-jdbc from 3.42.0.0 to 3.42.0.1 (#566) Bumps [org.xerial:sqlite-jdbc](https://github.com/xerial/sqlite-jdbc) from 3.42.0.0 to 3.42.0.1. - [Release notes](https://github.com/xerial/sqlite-jdbc/releases) - [Changelog](https://github.com/xerial/sqlite-jdbc/blob/master/CHANGELOG) - [Commits](https://github.com/xerial/sqlite-jdbc/compare/3.42.0.0...3.42.0.1) --- updated-dependencies: - dependency-name: org.xerial:sqlite-jdbc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e4203fd0..051e22ce 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ json-unit-version = "3.0.0" kitteh-irc-version = "8.0.0" hikari-cp-version = "5.0.1" mariadb-version = "3.2.0" -sqlite-version = "3.42.0.0" +sqlite-version = "3.42.0.1" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.21.2" From 46c9d6e58cdb5f7f1a4bfcd75ee029d519dfd171 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 20:47:22 +0000 Subject: [PATCH 20/55] chore(deps): bump info.picocli:picocli from 4.7.4 to 4.7.5 (#569) Bumps [info.picocli:picocli](https://github.com/remkop/picocli) from 4.7.4 to 4.7.5. - [Release notes](https://github.com/remkop/picocli/releases) - [Changelog](https://github.com/remkop/picocli/blob/main/RELEASE-NOTES.md) - [Commits](https://github.com/remkop/picocli/compare/v4.7.4...v4.7.5) --- updated-dependencies: - dependency-name: info.picocli:picocli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 051e22ce..4e3b4629 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ slf4j-version = "2.0.7" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" unirest-version = "4.0.4" -picocli-version = "4.7.4" +picocli-version = "4.7.5" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" httpclient-version = "4.5.14" From 98f9db7bbbf93f778e0be4667976f2a59a074602 Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:50:27 +0200 Subject: [PATCH 21/55] Update Readme.adoc --- src/examples/loggers/Readme.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/loggers/Readme.adoc b/src/examples/loggers/Readme.adoc index ec13c427..1f306ca9 100644 --- a/src/examples/loggers/Readme.adoc +++ b/src/examples/loggers/Readme.adoc @@ -1,4 +1,4 @@ -rakambda= Loggers += Loggers == console_only.xml [[console_only]] From d31599cac980921b2b696419b2b15bd8e8b46b48 Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:52:45 +0200 Subject: [PATCH 22/55] Log into folder relative to PWD --- miner/src/main/resources/log4j2.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miner/src/main/resources/log4j2.xml b/miner/src/main/resources/log4j2.xml index cdd56c21..4d1004ff 100644 --- a/miner/src/main/resources/log4j2.xml +++ b/miner/src/main/resources/log4j2.xml @@ -6,8 +6,8 @@ %date{ISO8601} %level [%thread] %logger{1.} %X - %message%n From 345bd0a5cb29a12b2345822dbb1c12f5aef20596 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:08:02 +0200 Subject: [PATCH 23/55] chore(deps): bump flyway-version from 9.21.2 to 9.22.0 (#572) Bumps `flyway-version` from 9.21.2 to 9.22.0. Updates `org.flywaydb:flyway-core` from 9.21.2 to 9.22.0 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.21.2...flyway-9.22.0) Updates `org.flywaydb:flyway-mysql` from 9.21.2 to 9.22.0 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.21.2...flyway-9.22.0) --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.flywaydb:flyway-mysql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4e3b4629..15da3a3c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ mariadb-version = "3.2.0" sqlite-version = "3.42.0.1" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" -flyway-version = "9.21.2" +flyway-version = "9.22.0" selenide-version = "6.17.2" lombok-version = "1.18.28" jacocoVersion = "0.8.10" From 7bae1895007f2eeb22ef2fecef20cbaafe588a9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:07:58 +0000 Subject: [PATCH 24/55] chore(deps): bump org.xerial:sqlite-jdbc from 3.42.0.1 to 3.43.0.0 (#570) Bumps [org.xerial:sqlite-jdbc](https://github.com/xerial/sqlite-jdbc) from 3.42.0.1 to 3.43.0.0. - [Release notes](https://github.com/xerial/sqlite-jdbc/releases) - [Changelog](https://github.com/xerial/sqlite-jdbc/blob/master/CHANGELOG) - [Commits](https://github.com/xerial/sqlite-jdbc/compare/3.42.0.1...3.43.0.0) --- updated-dependencies: - dependency-name: org.xerial:sqlite-jdbc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- .../miner/database/BaseDatabase.java | 24 ++++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 15da3a3c..ab97cb14 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ json-unit-version = "3.0.0" kitteh-irc-version = "8.0.0" hikari-cp-version = "5.0.1" mariadb-version = "3.2.0" -sqlite-version = "3.42.0.1" +sqlite-version = "3.43.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.22.0" diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/database/BaseDatabase.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/database/BaseDatabase.java index a3b4a79a..91d0f6fd 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/database/BaseDatabase.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/database/BaseDatabase.java @@ -10,10 +10,10 @@ import org.flywaydb.core.Flyway; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.sql.Statement; import java.sql.Timestamp; import java.time.Instant; import java.time.ZonedDateTime; @@ -120,22 +120,18 @@ protected int getOrCreatePredictionUserId(@NotNull String username, @NotNull Str } try(var addUserStatement = conn.prepareStatement(""" - INSERT INTO `PredictionUser`(`Username`, `ChannelID`) VALUES (?, ?)""", Statement.RETURN_GENERATED_KEYS)){ + INSERT INTO `PredictionUser`(`Username`, `ChannelID`) VALUES (?, ?) RETURNING `ID`;""")) { addUserStatement.setString(1, username); addUserStatement.setString(2, channelId); - var insertResult = addUserStatement.executeUpdate(); - if(insertResult <= 0){ - throw new SQLException("Failed to create new prediction user"); - } - - var generatedKeys = addUserStatement.getGeneratedKeys(); - if(!generatedKeys.next()){ - throw new SQLException("Failed to get new prediction user id"); + try (var generatedKeys = addUserStatement.executeQuery()) { + if (!generatedKeys.next()) { + throw new SQLException("Failed to get new prediction user id"); + } + + var userId = generatedKeys.getInt(1); + log.debug("Added new prediction user '{}' for channel '{}' : {}", username, channelId, userId); + return userId; } - - var userId = generatedKeys.getInt(1); - log.debug("Added new prediction user '{}' for channel '{}' : {}", username, channelId, userId); - return userId; } } finally{ From e4cb32bbdd97523b5e8cc2d80b426535ce90bed2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 21:11:42 +0200 Subject: [PATCH 25/55] chore(deps): bump org.slf4j:slf4j-api from 2.0.7 to 2.0.9 (#574) Bumps org.slf4j:slf4j-api from 2.0.7 to 2.0.9. --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ab97cb14..cf9f71dc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -slf4j-version = "2.0.7" +slf4j-version = "2.0.9" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" unirest-version = "4.0.4" From af6fe6a46ec872eb87a6330c3f6de7a61c50bdb5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 21:12:05 +0200 Subject: [PATCH 26/55] chore(deps): update actions/checkout action to v4 (#573) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/analyse.yml | 2 +- .github/workflows/build-test-deploy.yml | 10 +++++----- .github/workflows/manual-docker.yml | 4 ++-- .github/workflows/pages.yml | 2 +- .github/workflows/release.yml | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/analyse.yml b/.github/workflows/analyse.yml index d0c4f7a1..487c3813 100644 --- a/.github/workflows/analyse.yml +++ b/.github/workflows/analyse.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Java JDK uses: actions/setup-java@v3 with: diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index b3fa9f0a..87558431 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 1 - name: Set up JDK @@ -57,7 +57,7 @@ jobs: needs: build steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 1 - name: Set up JDK @@ -118,7 +118,7 @@ jobs: needs: build steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 1 - name: Set up JDK @@ -183,7 +183,7 @@ jobs: concurrency: miner_docker steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: @@ -212,7 +212,7 @@ jobs: concurrency: viewer_docker steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: diff --git a/.github/workflows/manual-docker.yml b/.github/workflows/manual-docker.yml index 3576a8b9..6b1cdb78 100644 --- a/.github/workflows/manual-docker.yml +++ b/.github/workflows/manual-docker.yml @@ -10,7 +10,7 @@ jobs: concurrency: miner_docker steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: @@ -46,7 +46,7 @@ jobs: concurrency: viewer_docker steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 3c084d0a..6d68d975 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v3 - name: Install Node.js diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index afd6f9ac..06730346 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: concurrency: miner_docker steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: @@ -34,7 +34,7 @@ jobs: concurrency: viewer_docker steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: @@ -57,7 +57,7 @@ jobs: contents: write steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: From a0a597bf30acbf81c37cd217c7e85cdb47fbb7c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:46:11 +0200 Subject: [PATCH 27/55] chore(deps): update mikepenz/action-junit-report action to v4 (#575) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-test-deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index 87558431..4c0df7a9 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -79,7 +79,7 @@ jobs: with: arguments: :miner:jacocoTestReport - name: Publish Test Report - uses: mikepenz/action-junit-report@v3 + uses: mikepenz/action-junit-report@v4 if: always() with: report_paths: 'miner/build/test-results/test/*.xml' @@ -140,7 +140,7 @@ jobs: with: arguments: :viewer:jacocoTestReport - name: Publish Test Report - uses: mikepenz/action-junit-report@v3 + uses: mikepenz/action-junit-report@v4 if: always() with: report_paths: 'viewer/build/test-results/test/*.xml' From d1cb07ace14465e4f491b6405ca4122613c4379d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 17:47:53 +0000 Subject: [PATCH 28/55] chore(deps): bump com.codeborne:selenide from 6.17.2 to 6.18.0 (#576) * chore(deps): bump com.codeborne:selenide from 6.17.2 to 6.18.0 Bumps [com.codeborne:selenide](https://github.com/selenide/selenide) from 6.17.2 to 6.18.0. - [Release notes](https://github.com/selenide/selenide/releases) - [Changelog](https://github.com/selenide/selenide/blob/main/CHANGELOG.md) - [Commits](https://github.com/selenide/selenide/compare/v6.17.2...v6.18.0) --- updated-dependencies: - dependency-name: com.codeborne:selenide dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: imports --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Couchoud --- gradle/libs.versions.toml | 2 +- .../browser/BrowserIntegrityProvider.java | 2 +- .../miner/browser/Browser.java | 8 ++++---- .../browser/BrowserIntegrityProviderTest.java | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cf9f71dc..6674adfd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ sqlite-version = "3.43.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.22.0" -selenide-version = "6.17.2" +selenide-version = "6.18.0" lombok-version = "1.18.28" jacocoVersion = "0.8.10" diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProvider.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProvider.java index 44451b52..c05c2b8d 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProvider.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProvider.java @@ -16,7 +16,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.jetbrains.annotations.NotNull; -import org.openqa.selenium.devtools.v113.page.model.FrameId; +import org.openqa.selenium.devtools.v116.page.model.FrameId; import java.io.IOException; import java.time.Duration; import java.util.Comparator; diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/browser/Browser.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/browser/Browser.java index ebc46c34..8c08d6f3 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/browser/Browser.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/browser/Browser.java @@ -16,10 +16,10 @@ import org.openqa.selenium.devtools.Command; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.HasDevTools; -import org.openqa.selenium.devtools.v113.network.Network; -import org.openqa.selenium.devtools.v113.network.model.RequestId; -import org.openqa.selenium.devtools.v113.network.model.RequestWillBeSent; -import org.openqa.selenium.devtools.v113.network.model.ResponseReceived; +import org.openqa.selenium.devtools.v116.network.Network; +import org.openqa.selenium.devtools.v116.network.model.RequestId; +import org.openqa.selenium.devtools.v116.network.model.RequestWillBeSent; +import org.openqa.selenium.devtools.v116.network.model.ResponseReceived; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; import org.openqa.selenium.firefox.FirefoxProfile; diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProviderTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProviderTest.java index 3c4826dd..b8a76fd9 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProviderTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/gql/integrity/browser/BrowserIntegrityProviderTest.java @@ -14,14 +14,14 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.openqa.selenium.devtools.v113.network.model.Headers; -import org.openqa.selenium.devtools.v113.network.model.MonotonicTime; -import org.openqa.selenium.devtools.v113.network.model.Request; -import org.openqa.selenium.devtools.v113.network.model.RequestId; -import org.openqa.selenium.devtools.v113.network.model.RequestWillBeSent; -import org.openqa.selenium.devtools.v113.network.model.Response; -import org.openqa.selenium.devtools.v113.network.model.ResponseReceived; -import org.openqa.selenium.devtools.v113.page.model.FrameId; +import org.openqa.selenium.devtools.v116.network.model.Headers; +import org.openqa.selenium.devtools.v116.network.model.MonotonicTime; +import org.openqa.selenium.devtools.v116.network.model.Request; +import org.openqa.selenium.devtools.v116.network.model.RequestId; +import org.openqa.selenium.devtools.v116.network.model.RequestWillBeSent; +import org.openqa.selenium.devtools.v116.network.model.Response; +import org.openqa.selenium.devtools.v116.network.model.ResponseReceived; +import org.openqa.selenium.devtools.v116.page.model.FrameId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; From 07fde3c48e90a513730082609c55d09e2eb2f97b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 20:16:14 +0200 Subject: [PATCH 29/55] chore(deps): bump com.github.ben-manes.versions from 0.47.0 to 0.48.0 (#577) Bumps com.github.ben-manes.versions from 0.47.0 to 0.48.0. --- updated-dependencies: - dependency-name: com.github.ben-manes.versions dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6674adfd..4715ab85 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ lombok-version = "1.18.28" jacocoVersion = "0.8.10" shadow-version = "8.1.1" -names-version = "0.47.0" +names-version = "0.48.0" jib-version = "3.3.2" git-properties-version = "2.4.1" springboot-version = "3.1.3" From a3bdd934400c7eae1427ad92f4506f801cded2a6 Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Sat, 9 Sep 2023 16:20:23 +0200 Subject: [PATCH 30/55] Add new prediction result : RATE_LIMITED (#578) --- .../miner/api/gql/gql/data/types/MakePredictionErrorCode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/gql/data/types/MakePredictionErrorCode.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/gql/data/types/MakePredictionErrorCode.java index 1fe71c0d..2d909a6d 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/gql/data/types/MakePredictionErrorCode.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/gql/gql/data/types/MakePredictionErrorCode.java @@ -7,5 +7,6 @@ public enum MakePredictionErrorCode{ MULTIPLE_OUTCOMES, MUST_ACCEPT_TOS, NOT_ENOUGH_POINTS, + RATE_LIMITED, UNKNOWN } From 8f27f4cb49d796c262435157bb909a7b602129ea Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Sat, 9 Sep 2023 16:24:33 +0200 Subject: [PATCH 31/55] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d13ea101..88cb93fe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.2.6 +version=2.2.7 From 8e63d2cbac8e5421e3acb40caa98f9331ea0cf99 Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Mon, 11 Sep 2023 16:57:05 +0200 Subject: [PATCH 32/55] =?UTF-8?q?=F0=9F=94=84=20synced=20file(s)=20with=20?= =?UTF-8?q?Rakambda/rakambda-github-files=20(#580)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: undefined --- .github/dependabot.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 46eb209d..ecd7b2b6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,9 +1,19 @@ version: 2 +registries: + dockerhub: + type: docker-registry + url: https://registry.hub.docker.com + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + replaces-base: true + updates: - package-ecosystem: "gradle" directory: "/" schedule: interval: "daily" + time: "08:00" + timezone: "Europe/Paris" pull-request-branch-name: separator: "-" # Disable while paths can't be ignored as it'd update all 'auto-approve-sync-files.yml', Renovate will handle exclusion @@ -11,35 +21,49 @@ updates: # directory: "/" # schedule: # interval: "daily" +# time: "08:00" +# timezone: "Europe/Paris" # pull-request-branch-name: # separator: "-" - package-ecosystem: "docker" directory: "/" schedule: interval: "daily" + time: "08:00" + timezone: "Europe/Paris" pull-request-branch-name: separator: "-" + registries: + - dockerhub - package-ecosystem: "maven" directory: "/" schedule: interval: "daily" + time: "08:00" + timezone: "Europe/Paris" pull-request-branch-name: separator: "-" - package-ecosystem: "npm" directory: "/" schedule: interval: "daily" + time: "08:00" + timezone: "Europe/Paris" pull-request-branch-name: separator: "-" - package-ecosystem: "nuget" directory: "/" schedule: interval: "daily" + time: "08:00" + timezone: "Europe/Paris" pull-request-branch-name: separator: "-" - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" + time: "08:00" + timezone: "Europe/Paris" pull-request-branch-name: separator: "-" From af596d29e6b51b3a1634267e0d8356b051199407 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:16:40 +0200 Subject: [PATCH 33/55] chore(deps): bump flyway-version from 9.22.0 to 9.22.1 (#582) Bumps `flyway-version` from 9.22.0 to 9.22.1. Updates `org.flywaydb:flyway-core` from 9.22.0 to 9.22.1 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.22.0...flyway-9.22.1) Updates `org.flywaydb:flyway-mysql` from 9.22.0 to 9.22.1 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.22.0...flyway-9.22.1) --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.flywaydb:flyway-mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4715ab85..7dfbcc8b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ mariadb-version = "3.2.0" sqlite-version = "3.43.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" -flyway-version = "9.22.0" +flyway-version = "9.22.1" selenide-version = "6.18.0" lombok-version = "1.18.28" jacocoVersion = "0.8.10" From adc753155cc712e702cc3ad6c0dee76f6ed62498 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:18:20 +0200 Subject: [PATCH 34/55] chore(deps): bump json-unit-version from 3.0.0 to 3.1.0 (#581) Bumps `json-unit-version` from 3.0.0 to 3.1.0. Updates `net.javacrumbs.json-unit:json-unit` from 3.0.0 to 3.1.0 - [Commits](https://github.com/lukas-krecan/JsonUnit/compare/json-unit-parent-3.0.0...json-unit-parent-3.1.0) Updates `net.javacrumbs.json-unit:json-unit-assertj` from 3.0.0 to 3.1.0 - [Commits](https://github.com/lukas-krecan/JsonUnit/compare/json-unit-parent-3.0.0...json-unit-parent-3.1.0) --- updated-dependencies: - dependency-name: net.javacrumbs.json-unit:json-unit dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: net.javacrumbs.json-unit:json-unit-assertj dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7dfbcc8b..bd258175 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ assertj-core-version = "3.24.2" assertj-db-version = "2.0.2" mockito-version = "5.2.0" awaitility-version = "4.2.0" -json-unit-version = "3.0.0" +json-unit-version = "3.1.0" kitteh-irc-version = "8.0.0" hikari-cp-version = "5.0.1" mariadb-version = "3.2.0" From e38865fda576aea74785686c75c8b42f9ce03bbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 06:46:19 +0000 Subject: [PATCH 35/55] chore(deps): bump unirest-version from 4.0.4 to 4.0.5 (#583) Bumps `unirest-version` from 4.0.4 to 4.0.5. Updates `com.konghq:unirest-java-core` from 4.0.4 to 4.0.5 Updates `com.konghq:unirest-objectmapper-jackson` from 4.0.4 to 4.0.5 Updates `com.konghq:unirest-mocks` from 4.0.4 to 4.0.5 - [Release notes](https://github.com/Kong/unirest-java/releases) - [Changelog](https://github.com/Kong/unirest-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/Kong/unirest-java/compare/v4.0.4...v4.0.5) --- updated-dependencies: - dependency-name: com.konghq:unirest-java-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-objectmapper-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-mocks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd258175..929674e0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ slf4j-version = "2.0.9" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" -unirest-version = "4.0.4" +unirest-version = "4.0.5" picocli-version = "4.7.5" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" From 09eb4f468b0f573f597ad6c4e8bc503f9b0851b9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 16:15:45 +0000 Subject: [PATCH 36/55] chore(deps): update codecov/codecov-action action to v4 (#584) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-test-deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index 4c0df7a9..235658d5 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -84,7 +84,7 @@ jobs: with: report_paths: 'miner/build/test-results/test/*.xml' - name: Publish coverage on CodeCov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 if: always() with: token: ${{ secrets.CODECOV_TOKEN }} @@ -145,7 +145,7 @@ jobs: with: report_paths: 'viewer/build/test-results/test/*.xml' - name: Publish coverage on CodeCov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 if: always() with: token: ${{ secrets.CODECOV_TOKEN }} From 86a30b6e1729e82ba5bb71549dff0265f99eff70 Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Fri, 15 Sep 2023 21:20:11 +0200 Subject: [PATCH 37/55] Revert "chore(deps): update codecov/codecov-action action to v4 (#584)" (#587) This reverts commit 09eb4f468b0f573f597ad6c4e8bc503f9b0851b9. --- .github/workflows/build-test-deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index 235658d5..4c0df7a9 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -84,7 +84,7 @@ jobs: with: report_paths: 'miner/build/test-results/test/*.xml' - name: Publish coverage on CodeCov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v3 if: always() with: token: ${{ secrets.CODECOV_TOKEN }} @@ -145,7 +145,7 @@ jobs: with: report_paths: 'viewer/build/test-results/test/*.xml' - name: Publish coverage on CodeCov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v3 if: always() with: token: ${{ secrets.CODECOV_TOKEN }} From cbab77941f0326bc1a7b01eaec22e8aee48b5daa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 19:28:51 +0000 Subject: [PATCH 38/55] chore(deps): bump json-unit-version from 3.1.0 to 3.2.2 (#586) Bumps `json-unit-version` from 3.1.0 to 3.2.2. Updates `net.javacrumbs.json-unit:json-unit` from 3.1.0 to 3.2.2 - [Commits](https://github.com/lukas-krecan/JsonUnit/compare/json-unit-parent-3.1.0...json-unit-parent-3.2.2) Updates `net.javacrumbs.json-unit:json-unit-assertj` from 3.1.0 to 3.2.2 - [Commits](https://github.com/lukas-krecan/JsonUnit/compare/json-unit-parent-3.1.0...json-unit-parent-3.2.2) --- updated-dependencies: - dependency-name: net.javacrumbs.json-unit:json-unit dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: net.javacrumbs.json-unit:json-unit-assertj dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 929674e0..3892731c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ assertj-core-version = "3.24.2" assertj-db-version = "2.0.2" mockito-version = "5.2.0" awaitility-version = "4.2.0" -json-unit-version = "3.1.0" +json-unit-version = "3.2.2" kitteh-irc-version = "8.0.0" hikari-cp-version = "5.0.1" mariadb-version = "3.2.0" From 5b2cb529486d4a4a874ef605941a628b04043940 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 19:30:09 +0000 Subject: [PATCH 39/55] chore(deps): bump unirest-version from 4.0.5 to 4.0.7 (#585) Bumps `unirest-version` from 4.0.5 to 4.0.7. Updates `com.konghq:unirest-java-core` from 4.0.5 to 4.0.7 Updates `com.konghq:unirest-objectmapper-jackson` from 4.0.5 to 4.0.7 Updates `com.konghq:unirest-mocks` from 4.0.5 to 4.0.7 - [Release notes](https://github.com/Kong/unirest-java/releases) - [Changelog](https://github.com/Kong/unirest-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/Kong/unirest-java/compare/v4.0.5...v4.0.7) --- updated-dependencies: - dependency-name: com.konghq:unirest-java-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-objectmapper-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-mocks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3892731c..49f2729a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ slf4j-version = "2.0.9" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" -unirest-version = "4.0.5" +unirest-version = "4.0.7" picocli-version = "4.7.5" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" From 3f356d782f76504f78d5b42b5678f660ab17181b Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Mon, 18 Sep 2023 10:55:15 +0200 Subject: [PATCH 40/55] =?UTF-8?q?=F0=9F=94=84=20synced=20file(s)=20with=20?= =?UTF-8?q?Rakambda/rakambda-github-files=20(#588)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: undefined --- .github/dependabot.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ecd7b2b6..fe2d8f00 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,6 +10,8 @@ registries: updates: - package-ecosystem: "gradle" directory: "/" + assignees: + - "Rakambda" schedule: interval: "daily" time: "08:00" @@ -19,6 +21,8 @@ updates: # Disable while paths can't be ignored as it'd update all 'auto-approve-sync-files.yml', Renovate will handle exclusion # - package-ecosystem: "github-actions" # directory: "/" +# assignees: +# - "Rakambda" # schedule: # interval: "daily" # time: "08:00" @@ -27,6 +31,8 @@ updates: # separator: "-" - package-ecosystem: "docker" directory: "/" + assignees: + - "Rakambda" schedule: interval: "daily" time: "08:00" @@ -37,6 +43,8 @@ updates: - dockerhub - package-ecosystem: "maven" directory: "/" + assignees: + - "Rakambda" schedule: interval: "daily" time: "08:00" @@ -45,6 +53,8 @@ updates: separator: "-" - package-ecosystem: "npm" directory: "/" + assignees: + - "Rakambda" schedule: interval: "daily" time: "08:00" @@ -53,6 +63,8 @@ updates: separator: "-" - package-ecosystem: "nuget" directory: "/" + assignees: + - "Rakambda" schedule: interval: "daily" time: "08:00" @@ -61,6 +73,8 @@ updates: separator: "-" - package-ecosystem: "pip" directory: "/" + assignees: + - "Rakambda" schedule: interval: "daily" time: "08:00" From 9c22f073af0ecd794b1dd310fb81591fdaa9fb48 Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Tue, 19 Sep 2023 20:43:25 +0200 Subject: [PATCH 41/55] Use org name --- README.adoc | 4 ++-- miner/docs/modules/ROOT/pages/configuration/discord.adoc | 4 ++-- miner/docs/modules/ROOT/pages/configuration/global.adoc | 2 +- miner/docs/modules/ROOT/pages/configuration/streamer.adoc | 2 +- miner/docs/modules/ROOT/pages/installation/clone.adoc | 2 +- miner/docs/modules/ROOT/pages/installation/docker.adoc | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.adoc b/README.adoc index 16178aaf..88a26905 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,6 @@ = Channel Points Miner -image:https://codecov.io/gh/Rakambda/ChannelPointsMiner/branch/main/graph/badge.svg[link="https://codecov.io/gh/Rakambda/ChannelPointsMiner",window="_blank",align="center"] +image:https://codecov.io/gh/RakambdaOrg/ChannelPointsMiner/branch/main/graph/badge.svg[link="https://codecov.io/gh/RakambdaOrg/ChannelPointsMiner",window="_blank",align="center"] image:https://img.shields.io/docker/pulls/mrcraftcod/channel-points-miner.svg[link="https://hub.docker.com/r/mrcraftcod/channel-points-miner",window="_blank",align="center"] image:https://img.shields.io/discord/1007349372444491856.svg?label=Discord&logo=Discord&colorB=7289da[link="https://discord.gg/uXWsRftdy7",window="_blank",align="center"] @@ -8,7 +8,7 @@ include::miner/docs/modules/ROOT/partials/project-intro.adoc[] == Documentation -Doc is available on link:https://rakambda.github.io/ChannelPointsMiner/[pages]. +Doc is available on link:https://rakambdaorg.github.io/ChannelPointsMiner/[pages]. == Disclaimer diff --git a/miner/docs/modules/ROOT/pages/configuration/discord.adoc b/miner/docs/modules/ROOT/pages/configuration/discord.adoc index 06d02150..72c0794b 100644 --- a/miner/docs/modules/ROOT/pages/configuration/discord.adoc +++ b/miner/docs/modules/ROOT/pages/configuration/discord.adoc @@ -6,7 +6,7 @@ Discord settings can be customized to filter events and/or customize the format To filter messages, you need to provide a list of events you want to be sent, and set no customization. -The name of the events can be found in link:https://github.com/Rakambda/ChannelPointsMiner/tree/develop/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl[miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl] as the name of the classes (name of the file without `.java`). +The name of the events can be found in link:https://github.com/RakambdaOrg/ChannelPointsMiner/tree/develop/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl[miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/impl] as the name of the classes (name of the file without `.java`). .Example to sent only 3 type of events with default format [%collapsible] @@ -22,7 +22,7 @@ include::example$discord-filtering.json[] Format works the same way as <> except that additional parameters are provided. Placeholders are expected to be between braces, example: `\{placeholder_name}`. -Available values can be seen in link:https://github.com/Rakambda/ChannelPointsMiner/blob/develop/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java[EventVariableKey]. +Available values can be seen in link:https://github.com/RakambdaOrg/ChannelPointsMiner/blob/develop/miner/src/main/java/fr/rakambda/channelpointsminer/miner/event/EventVariableKey.java[EventVariableKey]. NOTE: If you want to override the format of one event, you'll have to do the all as it'll also act as a filter. diff --git a/miner/docs/modules/ROOT/pages/configuration/global.adoc b/miner/docs/modules/ROOT/pages/configuration/global.adoc index ec4c8bb5..460fbac6 100644 --- a/miner/docs/modules/ROOT/pages/configuration/global.adoc +++ b/miner/docs/modules/ROOT/pages/configuration/global.adoc @@ -4,7 +4,7 @@ The global settings, that you pass to the miner with the `--settings` argument, Schema of the file is available in the xref:configuration/index.adoc[Configuration] page. -Examples of this file can be found in link:https://github.com/Rakambda/ChannelPointsMiner/blob/main/src/examples/config[src/examples/config,window="_blank"]. +Examples of this file can be found in link:https://github.com/RakambdaOrg/ChannelPointsMiner/blob/main/src/examples/config[src/examples/config,window="_blank"]. == Login method diff --git a/miner/docs/modules/ROOT/pages/configuration/streamer.adoc b/miner/docs/modules/ROOT/pages/configuration/streamer.adoc index bbfc8d30..00943044 100644 --- a/miner/docs/modules/ROOT/pages/configuration/streamer.adoc +++ b/miner/docs/modules/ROOT/pages/configuration/streamer.adoc @@ -3,7 +3,7 @@ Streamer settings define settings for a particular streamer. Each streamer setting will be defined in a json file named with the username of the streamer (eg: `streamer_username.json`). -Examples can be found in link:https://github.com/Rakambda/ChannelPointsMiner/blob/main/miner/src/test/resources/factory[miner/src/test/resources/factory,window="_blank"]. +Examples can be found in link:https://github.com/RakambdaOrg/ChannelPointsMiner/blob/main/miner/src/test/resources/factory[miner/src/test/resources/factory,window="_blank"]. == Priorities [[priorities]] diff --git a/miner/docs/modules/ROOT/pages/installation/clone.adoc b/miner/docs/modules/ROOT/pages/installation/clone.adoc index 8a5d470e..fed8f6df 100644 --- a/miner/docs/modules/ROOT/pages/installation/clone.adoc +++ b/miner/docs/modules/ROOT/pages/installation/clone.adoc @@ -3,7 +3,7 @@ Running the project this way requires Java 17+ JDK to be installed. You can use the vendor of your choice (I personally use link:https://adoptium.net[Temurin]). -1. Clone this repository `git clone git@github.com:RakSrinaNa/ChannelPointsMiner.git`. +1. Clone this repository `git clone git@github.com:RakambdaOrg/ChannelPointsMiner.git`. 2. Get into the cloned directory `cd ChannelPointsMiner`. 3. Build the jar `./gradlew build -x test` 4. Run with `config.json` as the configuration diff --git a/miner/docs/modules/ROOT/pages/installation/docker.adoc b/miner/docs/modules/ROOT/pages/installation/docker.adoc index 45d74958..5f15754e 100644 --- a/miner/docs/modules/ROOT/pages/installation/docker.adoc +++ b/miner/docs/modules/ROOT/pages/installation/docker.adoc @@ -47,5 +47,5 @@ services: If you have 2FA enabled or using selenium, you'll have to enter information in the console for the first run in order to log in. As Docker doesn't give an interactive shell by default you'll have to run the container in interactive mode yourself the first time. -More can be read about it in link:https://github.com/Rakambda/ChannelPointsMiner/issues/87#issuecomment-988276214[#87]. +More can be read about it in link:https://github.com/RakambdaOrg/ChannelPointsMiner/issues/87#issuecomment-988276214[#87]. ==== \ No newline at end of file From d0182b118eaff256612c636531a3253b09482936 Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Tue, 19 Sep 2023 20:44:16 +0200 Subject: [PATCH 42/55] Use org name --- .github/antora-playbook.local.yml | 2 +- .github/antora-playbook.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/antora-playbook.local.yml b/.github/antora-playbook.local.yml index 7954f6bd..8f1d5b88 100644 --- a/.github/antora-playbook.local.yml +++ b/.github/antora-playbook.local.yml @@ -1,6 +1,6 @@ site: title: ChannelPointsMiner - url: https://rakambda.github.io/ChannelPointsMiner/ + url: https://rakambdaorg.github.io/ChannelPointsMiner/ start_page: miner::index.adoc content: sources: diff --git a/.github/antora-playbook.yml b/.github/antora-playbook.yml index 8537ceb1..84973bb0 100644 --- a/.github/antora-playbook.yml +++ b/.github/antora-playbook.yml @@ -1,10 +1,10 @@ site: title: ChannelPointsMiner - url: https://rakambda.github.io/ChannelPointsMiner/ + url: https://rakambdaorg.github.io/ChannelPointsMiner/ start_page: miner::index.adoc content: sources: - - url: https://github.com/Rakambda/ChannelPointsMiner.git + - url: https://github.com/RakambdaOrg/ChannelPointsMiner.git branches: [ main, develop ] start_paths: - miner/docs From f329aa6e1969b62d615ec1449d8f4cd21c0d556a Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Tue, 19 Sep 2023 23:00:14 +0200 Subject: [PATCH 43/55] =?UTF-8?q?=F0=9F=94=84=20synced=20file(s)=20with=20?= =?UTF-8?q?RakambdaOrg/rakambda-github-files=20(#589)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: undefined --- .github/workflows/auto-aprove-sync-files.yml | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/.github/workflows/auto-aprove-sync-files.yml b/.github/workflows/auto-aprove-sync-files.yml index 6a5d6aad..96cc9030 100644 --- a/.github/workflows/auto-aprove-sync-files.yml +++ b/.github/workflows/auto-aprove-sync-files.yml @@ -4,18 +4,6 @@ on: jobs: auto-approve-synced-files: - name: Auto approve synced files - if: contains(github.event.pull_request.title, 'Synced file(s)') && github.actor == 'couchoud-t' && github.event.pull_request.base.ref == github.event.repository.default_branch - runs-on: ubuntu-latest - steps: - - name: Pull Request approval - uses: hmarr/auto-approve-action@v3.2.1 - with: - github-token: "${{ secrets.SYNC_TOKEN }}" - - name: Pull Request merge - uses: KeisukeYamashita/auto-pull-request-merge@v1.0.6 - with: - token: "${{ secrets.SYNC_TOKEN }}" - strategy: squash - intervalSeconds: 60 - timeoutSeconds: 3600 + uses: RakambdaOrg/rakambda-github-workflows/.github/workflows/approve-sync-files.yml@main + secrets: + sync-token: ${{ secrets.SYNC_TOKEN }} From d536f9b329f2575f8483507530f0b6ed7f9e1239 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Sep 2023 09:04:22 +0200 Subject: [PATCH 44/55] chore(deps): bump org.projectlombok:lombok from 1.18.28 to 1.18.30 (#590) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.28 to 1.18.30. - [Release notes](https://github.com/projectlombok/lombok/releases) - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.28...v1.18.30) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 49f2729a..b5e494f9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.22.1" selenide-version = "6.18.0" -lombok-version = "1.18.28" +lombok-version = "1.18.30" jacocoVersion = "0.8.10" shadow-version = "8.1.1" From e18ff9a16bae117c37287ffe79200eeb97097888 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 09:32:15 +0200 Subject: [PATCH 45/55] chore(deps): bump unirest-version from 4.0.7 to 4.0.8 (#591) Bumps `unirest-version` from 4.0.7 to 4.0.8. Updates `com.konghq:unirest-java-core` from 4.0.7 to 4.0.8 Updates `com.konghq:unirest-objectmapper-jackson` from 4.0.7 to 4.0.8 Updates `com.konghq:unirest-mocks` from 4.0.7 to 4.0.8 - [Release notes](https://github.com/Kong/unirest-java/releases) - [Changelog](https://github.com/Kong/unirest-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/Kong/unirest-java/compare/v4.0.7...v4.0.8) --- updated-dependencies: - dependency-name: com.konghq:unirest-java-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-objectmapper-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-mocks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b5e494f9..1d443242 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ slf4j-version = "2.0.9" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" -unirest-version = "4.0.7" +unirest-version = "4.0.8" picocli-version = "4.7.5" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" From ded5ec95c99a30a25642dc78333939e0b2c29ca4 Mon Sep 17 00:00:00 2001 From: Thomas Couchoud Date: Fri, 22 Sep 2023 08:31:26 +0200 Subject: [PATCH 46/55] =?UTF-8?q?=F0=9F=94=84=20synced=20file(s)=20with=20?= =?UTF-8?q?RakambdaOrg/rakambda-github-files=20(#595)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: undefined --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b5eee899..f7239edf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @Rakambda +* @Rakambda @couchoud-t From 47e56b5632fa52560f8e38ac8d629ab15d4ec8ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 08:31:53 +0200 Subject: [PATCH 47/55] chore(deps): bump com.google.cloud.tools.jib from 3.3.2 to 3.4.0 (#594) Bumps com.google.cloud.tools.jib from 3.3.2 to 3.4.0. --- updated-dependencies: - dependency-name: com.google.cloud.tools.jib dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1d443242..c0319278 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,7 +30,7 @@ jacocoVersion = "0.8.10" shadow-version = "8.1.1" names-version = "0.48.0" -jib-version = "3.3.2" +jib-version = "3.4.0" git-properties-version = "2.4.1" springboot-version = "3.1.3" springboot-dependencies-version = "1.1.3" From 9564d88bad56b7888e10bb1659d5efeab089ad0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 08:32:21 +0200 Subject: [PATCH 48/55] chore(deps): bump flyway-version from 9.22.1 to 9.22.2 (#592) Bumps `flyway-version` from 9.22.1 to 9.22.2. Updates `org.flywaydb:flyway-core` from 9.22.1 to 9.22.2 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.22.1...flyway-9.22.2) Updates `org.flywaydb:flyway-mysql` from 9.22.1 to 9.22.2 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.22.1...flyway-9.22.2) --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.flywaydb:flyway-mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0319278..993c7cbc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ mariadb-version = "3.2.0" sqlite-version = "3.43.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" -flyway-version = "9.22.1" +flyway-version = "9.22.2" selenide-version = "6.18.0" lombok-version = "1.18.30" jacocoVersion = "0.8.10" From 7c1ec4d0ee10be73a0365c444c4544f7d13df38f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 08:32:38 +0200 Subject: [PATCH 49/55] chore(deps): bump org.springframework.boot from 3.1.3 to 3.1.4 (#593) Bumps [org.springframework.boot](https://github.com/spring-projects/spring-boot) from 3.1.3 to 3.1.4. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.3...v3.1.4) --- updated-dependencies: - dependency-name: org.springframework.boot dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 993c7cbc..7235fbf4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ shadow-version = "8.1.1" names-version = "0.48.0" jib-version = "3.4.0" git-properties-version = "2.4.1" -springboot-version = "3.1.3" +springboot-version = "3.1.4" springboot-dependencies-version = "1.1.3" test-logger-version = "3.2.0" git-version-plugin-version = "3.0.0" From 16f1fb3096e63a7208da59935e1466f148f19b4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:16:17 +0200 Subject: [PATCH 50/55] chore(deps): bump unirest-version from 4.0.8 to 4.0.9 (#596) Bumps `unirest-version` from 4.0.8 to 4.0.9. Updates `com.konghq:unirest-java-core` from 4.0.8 to 4.0.9 Updates `com.konghq:unirest-objectmapper-jackson` from 4.0.8 to 4.0.9 Updates `com.konghq:unirest-mocks` from 4.0.8 to 4.0.9 - [Release notes](https://github.com/Kong/unirest-java/releases) - [Changelog](https://github.com/Kong/unirest-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/Kong/unirest-java/compare/v4.0.8...v4.0.9) --- updated-dependencies: - dependency-name: com.konghq:unirest-java-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-objectmapper-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-mocks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7235fbf4..5c36f6ac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ slf4j-version = "2.0.9" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" -unirest-version = "4.0.8" +unirest-version = "4.0.9" picocli-version = "4.7.5" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" From 231f0b61bf67ac59cefc35f733b93fcdf1b37b41 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 26 Sep 2023 13:18:34 +0200 Subject: [PATCH 51/55] =?UTF-8?q?=F0=9F=94=84=20synced=20file(s)=20with=20?= =?UTF-8?q?RakambdaOrg/rakambda-github-files=20(#597)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: undefined --- .github/workflows/auto-aprove-sync-files.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/auto-aprove-sync-files.yml b/.github/workflows/auto-aprove-sync-files.yml index 96cc9030..b0de81a0 100644 --- a/.github/workflows/auto-aprove-sync-files.yml +++ b/.github/workflows/auto-aprove-sync-files.yml @@ -5,5 +5,7 @@ on: jobs: auto-approve-synced-files: uses: RakambdaOrg/rakambda-github-workflows/.github/workflows/approve-sync-files.yml@main + with: + runs-on: self-hosted secrets: sync-token: ${{ secrets.SYNC_TOKEN }} From fac066948d895f1caee45549c074bbd184a0ed3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:27:47 +0200 Subject: [PATCH 52/55] chore(deps): bump unirest-version from 4.0.9 to 4.0.10 (#598) Bumps `unirest-version` from 4.0.9 to 4.0.10. Updates `com.konghq:unirest-java-core` from 4.0.9 to 4.0.10 Updates `com.konghq:unirest-objectmapper-jackson` from 4.0.9 to 4.0.10 Updates `com.konghq:unirest-mocks` from 4.0.9 to 4.0.10 - [Release notes](https://github.com/Kong/unirest-java/releases) - [Changelog](https://github.com/Kong/unirest-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/Kong/unirest-java/compare/v4.0.9...v4.0.10) --- updated-dependencies: - dependency-name: com.konghq:unirest-java-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-objectmapper-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.konghq:unirest-mocks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c36f6ac..0e62c6cf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ slf4j-version = "2.0.9" log4j2-version = "2.20.0" log4j2-slf4j-version = "2.20.0" -unirest-version = "4.0.9" +unirest-version = "4.0.10" picocli-version = "4.7.5" jackson-version = "2.15.2" jsonschema-generator-version = "4.31.1" From 7c2c41f8022f9e65b06bd62f9a8ec380e0a51488 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 11:01:29 +0200 Subject: [PATCH 53/55] chore(deps): bump com.codeborne:selenide from 6.18.0 to 6.19.0 (#599) Bumps [com.codeborne:selenide](https://github.com/selenide/selenide) from 6.18.0 to 6.19.0. - [Release notes](https://github.com/selenide/selenide/releases) - [Changelog](https://github.com/selenide/selenide/blob/main/CHANGELOG.md) - [Commits](https://github.com/selenide/selenide/compare/v6.18.0...v6.19.0) --- updated-dependencies: - dependency-name: com.codeborne:selenide dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0e62c6cf..989d42af 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ sqlite-version = "3.43.0.0" mysql-version = "8.1.0" rerunner-jupiter-version = "2.1.6" flyway-version = "9.22.2" -selenide-version = "6.18.0" +selenide-version = "6.19.0" lombok-version = "1.18.30" jacocoVersion = "0.8.10" From a05c38b867a16265b22ae5d1b4d9fe5798e56928 Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Fri, 29 Sep 2023 18:44:28 +0200 Subject: [PATCH 54/55] Fix trying parsing an URL that isn't one during Raids (#601) * Use String instead of URL as it isn't a valid URL * Fix: tests --- .../miner/api/ws/data/message/subtype/Raid.java | 6 +----- .../channelpointsminer/miner/util/json/URLDeserializer.java | 2 +- .../api/ws/TwitchPubSubWebSocketClientMessageTest.java | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/subtype/Raid.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/subtype/Raid.java index e8b3c888..3067527a 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/subtype/Raid.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/api/ws/data/message/subtype/Raid.java @@ -1,8 +1,6 @@ package fr.rakambda.channelpointsminer.miner.api.ws.data.message.subtype; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import fr.rakambda.channelpointsminer.miner.util.json.URLDeserializer; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; @@ -10,7 +8,6 @@ import lombok.NoArgsConstructor; import lombok.ToString; import org.jetbrains.annotations.NotNull; -import java.net.URL; @Getter @NoArgsConstructor @@ -38,9 +35,8 @@ public class Raid{ @NotNull private String targetDisplayName; @JsonProperty("target_profile_image") - @JsonDeserialize(using = URLDeserializer.class) @NotNull - private URL targetProfileImage; + private String targetProfileImage; @JsonProperty("transition_jitter_seconds") private int transitionJitterSeconds; @JsonProperty("force_raid_now_seconds") diff --git a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/util/json/URLDeserializer.java b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/util/json/URLDeserializer.java index ac43045e..ea68659c 100644 --- a/miner/src/main/java/fr/rakambda/channelpointsminer/miner/util/json/URLDeserializer.java +++ b/miner/src/main/java/fr/rakambda/channelpointsminer/miner/util/json/URLDeserializer.java @@ -38,7 +38,7 @@ public URL deserialize(@NotNull JsonParser jsonParser, @NotNull DeserializationC } } catch(MalformedURLException | IllegalArgumentException e){ - log.warn("Failed to parse URL: {}", jsonParser.getValueAsString(), e); + log.warn("Failed to parse URL: {} at {} in {}", jsonParser.getValueAsString(), jsonParser.getCurrentName(), jsonParser.getCurrentLocation(), e); } return null; } diff --git a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java index c5f92c6a..937edacf 100644 --- a/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java +++ b/miner/src/test/java/fr/rakambda/channelpointsminer/miner/api/ws/TwitchPubSubWebSocketClientMessageTest.java @@ -203,7 +203,7 @@ void onRaidGoV2(WebsocketMockServer server) throws MalformedURLException{ .targetId("987654") .targetLogin("target-name") .targetDisplayName("target-display-name") - .targetProfileImage(new URL("https://google.com/target-image")) + .targetProfileImage("https://google.com/target-image") .transitionJitterSeconds(0) .forceRaidNowSeconds(90) .viewerCount(200) @@ -232,7 +232,7 @@ void onRaidUpdateV2(WebsocketMockServer server) throws MalformedURLException{ .targetId("987654") .targetLogin("target-name") .targetDisplayName("target-display-name") - .targetProfileImage(new URL("https://google.com/target-image")) + .targetProfileImage("https://google.com/target-image") .transitionJitterSeconds(0) .forceRaidNowSeconds(90) .viewerCount(200) @@ -261,7 +261,7 @@ void onRaidCancelV2(WebsocketMockServer server) throws MalformedURLException{ .targetId("987654") .targetLogin("target-name") .targetDisplayName("target-display-name") - .targetProfileImage(new URL("https://google.com/target-image")) + .targetProfileImage("https://google.com/target-image") .transitionJitterSeconds(0) .forceRaidNowSeconds(90) .viewerCount(200) From d07247700ed75599a62dcc1f4f7f3300b80ed55d Mon Sep 17 00:00:00 2001 From: Thomas <1688389+Rakambda@users.noreply.github.com> Date: Mon, 2 Oct 2023 09:20:01 +0200 Subject: [PATCH 55/55] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 88cb93fe..0f70e8ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.2.7 +version=2.2.8