From be28f7ae7eb1037ecb6ff8e44a5ab12b00df9ae8 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 21 Nov 2024 08:58:36 +0100 Subject: [PATCH 01/93] try a different approach on loading stuff --- .idea/compiler.xml | 2 +- .idea/misc.xml | 2 +- src/main/kotlin/dev/jansel/feixiao/App.kt | 27 ++----------- .../kotlin/dev/jansel/feixiao/utils/Twitch.kt | 40 +++++++++++++++++++ .../kotlin/dev/jansel/feixiao/utils/_Utils.kt | 20 ++++++++++ 5 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt diff --git a/.idea/compiler.xml b/.idea/compiler.xml index ed2ab47..f4f3637 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,7 +1,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index c6d38c5..a4abeb1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/src/main/kotlin/dev/jansel/feixiao/App.kt b/src/main/kotlin/dev/jansel/feixiao/App.kt index f97e1dd..a2495b1 100644 --- a/src/main/kotlin/dev/jansel/feixiao/App.kt +++ b/src/main/kotlin/dev/jansel/feixiao/App.kt @@ -19,39 +19,20 @@ import kotlinx.coroutines.runBlocking var twitchClient: TwitchClient? = null val logger = KotlinLogging.logger { } +var botRef : ExtensibleBot? = null suspend fun main() { - val bot = ExtensibleBot(token) { + botRef = ExtensibleBot(token) { database(true) + twitch(true) dataCollectionMode = DataCollection.None extensions { add(::EventHooks) add(::StreamerCommand) } } - twitchClient = TwitchClientBuilder.builder() - .withEnableHelix(true) - .withClientId(twitchcid) - .withClientSecret(twitchcs) - .build() - twitchClient!!.eventManager.onEvent(ChannelGoLiveEvent::class.java) { - logger.info { "${it.channel.name} went live!" } - runBlocking { - launch { - val streamer = StreamerCollection().getData(it.channel.name) - val channel = bot.kordRef.getChannelOf(streamer!!.servers.first().channelId) - val role = streamer.servers.first().roleId - if (role != null) { - channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") - } else { - channel?.createMessage("${it.channel.name} went live: ${it.stream.title}") - } - } - } - } - - bot.start() + botRef!!.start() } diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt new file mode 100644 index 0000000..6327551 --- /dev/null +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -0,0 +1,40 @@ +package dev.jansel.feixiao.utils + +import com.github.twitch4j.TwitchClientBuilder +import com.github.twitch4j.events.ChannelGoLiveEvent +import dev.jansel.feixiao.botRef +import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.twitchClient +import dev.kord.core.entity.channel.GuildMessageChannel +import dev.kordex.core.koin.KordExKoinComponent +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking + +class Twitch : KordExKoinComponent { + suspend fun init() { + twitchClient = TwitchClientBuilder.builder() + .withEnableHelix(true) + .withClientId(twitchcid) + .withClientSecret(twitchcs) + .build() + + twitchClient!!.eventManager.onEvent(ChannelGoLiveEvent::class.java) { + dev.jansel.feixiao.logger.info { "${it.channel.name} went live!" } + runBlocking { + launch { + val streamer = StreamerCollection().getData(it.channel.name) + val channel = botRef!!.kordRef.getChannelOf(streamer!!.servers.first().channelId) + val role = streamer.servers.first().roleId + if (role != null) { + channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } else { + channel?.createMessage("${it.channel.name} went live: ${it.stream.title}") + } + } + } + } + } + + + +} diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt index ca0dc30..a7c9ec5 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt @@ -1,12 +1,17 @@ package dev.jansel.feixiao.utils +import com.github.twitch4j.TwitchClientBuilder +import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.database.Database import dev.jansel.feixiao.database.collections.MetaCollection import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Snowflake +import dev.kord.core.entity.channel.GuildMessageChannel import dev.kordex.core.builders.ExtensibleBotBuilder import dev.kordex.core.utils.env import dev.kordex.core.utils.loadModule +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.koin.dsl.bind @@ -37,3 +42,18 @@ suspend inline fun ExtensibleBotBuilder.database(migrate: Boolean) { } } } + +suspend inline fun ExtensibleBotBuilder.twitch(active: Boolean) { + hooks { + beforeKoinSetup { + loadModule { + single { Twitch() } bind Twitch::class + } + + if (active) { + Twitch().init() + } + } + } + +} From 84086034760d11fe8ad8e816646e55f7f79e2f01 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 25 Nov 2024 03:32:56 +0100 Subject: [PATCH 02/93] print online message in a seperate text channel --- .idea/Feixiao.iml | 9 +++++++++ .idea/compiler.xml | 2 +- .idea/misc.xml | 2 +- .idea/modules.xml | 8 ++++++++ .idea/modules/feixiao.iml | 8 ++++++++ .../kotlin/dev/jansel/feixiao/extensions/EventHooks.kt | 7 +++++++ 6 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 .idea/Feixiao.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/modules/feixiao.iml diff --git a/.idea/Feixiao.iml b/.idea/Feixiao.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/Feixiao.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index ed2ab47..f4f3637 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,7 +1,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index c6d38c5..a4abeb1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4787ae5 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/feixiao.iml b/.idea/modules/feixiao.iml new file mode 100644 index 0000000..4ad6139 --- /dev/null +++ b/.idea/modules/feixiao.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt index 246afb1..24b7641 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt @@ -4,6 +4,10 @@ import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.database.entities.StreamerData import dev.jansel.feixiao.logger import dev.jansel.feixiao.twitchClient +import dev.jansel.feixiao.utils.tchannelid +import dev.jansel.feixiao.utils.tserverid +import dev.kord.core.behavior.getChannelOf +import dev.kord.core.entity.channel.GuildMessageChannel import dev.kord.core.event.gateway.ReadyEvent import dev.kordex.core.extensions.Extension import dev.kordex.core.extensions.event @@ -17,6 +21,9 @@ class EventHooks : Extension() { event { action { logger.info { "Bot is ready!" } + val onlineLog = + kord.getGuildOrNull(tserverid)?.getChannelOf(tchannelid) + onlineLog?.createMessage("Bot Online!") kord.editPresence { listening("the database") } // check every entry in the database and enable the stream event listener if a server is listening to the streamer StreamerCollection().collection.find().toList().forEach { From 2dd0211353275b670313caed48b59fe0f76395e1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 02:41:13 +0000 Subject: [PATCH 03/93] Add renovate.json --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..2b42fb1 --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} From 7ef5f34ee67e81243fc329fd6de3a6905089ac43 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 03:50:56 +0100 Subject: [PATCH 04/93] Update and rename renovate.json to .github/renovate.json --- renovate.json => .github/renovate.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename renovate.json => .github/renovate.json (59%) diff --git a/renovate.json b/.github/renovate.json similarity index 59% rename from renovate.json rename to .github/renovate.json index 2b42fb1..6bda63c 100644 --- a/renovate.json +++ b/.github/renovate.json @@ -2,5 +2,7 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended" - ] + ], + "commitBody": "[skip ci]", + "baseBranches": ["refactor/depUpdates"] } From 2d5fa8708b1926fe5532edf81d1e50a279af8fb7 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 03:56:56 +0100 Subject: [PATCH 05/93] Update renovate.json [skip ci] --- .github/renovate.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index 6bda63c..ba1d693 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -4,5 +4,12 @@ "config:recommended" ], "commitBody": "[skip ci]", - "baseBranches": ["refactor/depUpdates"] + "baseBranches": ["refactor/depUpdates"], + "prHourlyLimit": 0, + "packageRules": [ + { + "matchUpdateTypes": ["patch", "pin", "digest"], + "automerge": true + } + ] } From 9b6c2455c5f4047b928be5b6d68a5aecb935a9b6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 02:58:49 +0000 Subject: [PATCH 06/93] Update dependency com.github.twitch4j:twitch4j to v1.23.0 [skip ci] --- 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 9329a3e..2e3de5f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kx-ser = "1.7.3" logback = "1.5.12" logback-groovy = "1.14.5" logging = "7.0.0" -twitch4j = "1.22.0" +twitch4j = "1.23.0" events4j = "0.12.2" kx-coroutines = "1.9.0" kmongo = "4.9.0" From 9b0a21131ec4e9a12ca4995a8c890ceb47631d03 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:00:35 +0000 Subject: [PATCH 07/93] Update dependency gradle to v8.11.1 [skip ci] --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..e2847c8 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.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 352591ac1ae056e2d39c99749f95c81b92f55238 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:00:48 +0000 Subject: [PATCH 08/93] Update actions/upload-artifact action to v4 [skip ci] --- .github/workflows/ci.yml | 2 +- .github/workflows/develop.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b2d159..d7a094d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: run: "./gradlew build" - name: Upload build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Build and Deploy Artifacts diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index f2c1dbc..eb0ab25 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -26,7 +26,7 @@ jobs: run: "./gradlew build" - name: Upload build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Build and Deploy Artifacts From 7736b99eea7c6777de913907d8b92ba7a7277b39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:00:51 +0000 Subject: [PATCH 09/93] Update dependency org.litote.kmongo:kmongo-coroutine-serialization to v5 [skip ci] --- 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 9329a3e..f0935c2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ logging = "7.0.0" twitch4j = "1.22.0" events4j = "0.12.2" kx-coroutines = "1.9.0" -kmongo = "4.9.0" +kmongo = "5.1.0" [libraries] groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" } From 2243329faeb58df1f1a568b31ded4dc5f747fc27 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:00:54 +0000 Subject: [PATCH 10/93] Update docker/build-push-action action to v6 [skip ci] --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 9943979..92fc109 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -39,7 +39,7 @@ jobs: password: ${{ secrets.CR_PAT }} - name: Build and push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . platforms: linux/arm64 From 6f0276fc95cefdb914b9be3618037a60b5aa2edd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:00:57 +0000 Subject: [PATCH 11/93] Update docker/login-action action to v3 [skip ci] --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 9943979..d1c9341 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -31,7 +31,7 @@ jobs: run: "./gradlew build" - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io From e283d68edb01b7b6e9abf15d3406643569e85df2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 03:02:52 +0000 Subject: [PATCH 12/93] Update dependency org.codehaus.groovy:groovy to v3.0.23 [skip ci] --- 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 2e3de5f..349681e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.0.21" # Note: Plugin versions must be updated in the settings.gradle.kts too -groovy = "3.0.22" +groovy = "3.0.23" jansi = "2.4.1" kx-ser = "1.7.3" logback = "1.5.12" From f5270e3eb70fe8c816c4ef6542cbf6f56e4fbe6c Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 04:26:40 +0100 Subject: [PATCH 13/93] revert gradle version to 8.10.2 --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 802ad4c..e53343b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.11.1" + gradleVersion = "8.10.2" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2847c8..df97d72 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.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index bc1be29..fc0b921 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,8 +13,8 @@ pluginManagement { gradlePluginPortal() mavenCentral() - maven("https://snapshots-repo.kordex.dev") maven("https://releases-repo.kordex.dev") + maven("https://snapshots-repo.kordex.dev") } } From accd4d19758ef0b5b62db32f3d05b4b2a88c333f Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 09:01:24 +0100 Subject: [PATCH 14/93] better loading system should work, will see it later during prod --- src/main/kotlin/dev/jansel/feixiao/App.kt | 10 +--------- src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt | 2 ++ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/dev/jansel/feixiao/App.kt b/src/main/kotlin/dev/jansel/feixiao/App.kt index 16167c9..afdfc21 100644 --- a/src/main/kotlin/dev/jansel/feixiao/App.kt +++ b/src/main/kotlin/dev/jansel/feixiao/App.kt @@ -3,23 +3,15 @@ */ package dev.jansel.feixiao -import com.github.philippheuer.events4j.reactor.ReactorEventHandler import com.github.twitch4j.TwitchClient -import com.github.twitch4j.TwitchClientBuilder -import com.github.twitch4j.events.ChannelGoLiveEvent -import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.extensions.EventHooks import dev.jansel.feixiao.extensions.StreamerCommand import dev.jansel.feixiao.utils.database import dev.jansel.feixiao.utils.token -import dev.jansel.feixiao.utils.twitchcid -import dev.jansel.feixiao.utils.twitchcs -import dev.kord.core.entity.channel.GuildMessageChannel import dev.kordex.core.ExtensibleBot import dev.kordex.core.i18n.SupportedLocales import io.github.oshai.kotlinlogging.KotlinLogging -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking +import dev.jansel.feixiao.utils.twitch var twitchClient: TwitchClient? = null val logger = KotlinLogging.logger { } diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt index 6327551..07b3d2e 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -1,5 +1,6 @@ package dev.jansel.feixiao.utils +import com.github.philippheuer.events4j.reactor.ReactorEventHandler import com.github.twitch4j.TwitchClientBuilder import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.botRef @@ -14,6 +15,7 @@ class Twitch : KordExKoinComponent { suspend fun init() { twitchClient = TwitchClientBuilder.builder() .withEnableHelix(true) + .withDefaultEventHandler(ReactorEventHandler::class.java) .withClientId(twitchcid) .withClientSecret(twitchcs) .build() From 45da7ed2daf50bfe1aa8d1c038b650cff6deb8e0 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 09:06:11 +0100 Subject: [PATCH 15/93] MAYBE ALSO IMPLEMENT CHANGES THAT WERE MADE SINCE THIS BRANCH WAS MADE --- .../kotlin/dev/jansel/feixiao/utils/Twitch.kt | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt index 07b3d2e..1f45103 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -25,12 +25,37 @@ class Twitch : KordExKoinComponent { runBlocking { launch { val streamer = StreamerCollection().getData(it.channel.name) - val channel = botRef!!.kordRef.getChannelOf(streamer!!.servers.first().channelId) - val role = streamer.servers.first().roleId - if (role != null) { - channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") - } else { - channel?.createMessage("${it.channel.name} went live: ${it.stream.title}") + for (server in streamer!!.servers) { + val channel = botRef!!.kordRef.getChannelOf(server.channelId) + val role = server.roleId + val livemessage = server.liveMessage + + if (role != null) { + if (livemessage != null) { + channel?.createMessage( + livemessage + .replace("{name}", it.channel.name) + .replace("{category}", it.stream.gameName) + .replace("{title}", it.stream.title) + .replace("{url}", "https://twitch.tv/${it.channel.name}") + .replace("{role}", "<@&$role>") + ) + } else { + channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } + } else { + if (livemessage != null) { + channel?.createMessage( + livemessage + .replace("{name}", it.channel.name) + .replace("{category}", it.stream.gameName) + .replace("{title}", it.stream.title) + .replace("{url}", "https://twitch.tv/${it.channel.name}") + ) + } else { + channel?.createMessage("https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } + } } } } From 5a2b1ec4387338f40c1084f9b1d9fcd3577baaea Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 09:45:03 +0100 Subject: [PATCH 16/93] finally i'm able to update gradle to 8.11.1 --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e53343b..802ad4c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.10.2" + gradleVersion = "8.11.1" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..e2847c8 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.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index fc0b921..84e3ff8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,8 +6,8 @@ pluginManagement { id("com.github.johnrengelman.shadow") version "8.1.1" - id("dev.kordex.gradle.docker") version "1.5.8" - id("dev.kordex.gradle.kordex") version "1.5.8" + id("dev.kordex.gradle.docker") version "1.6.0" + id("dev.kordex.gradle.kordex") version "1.6.0" } repositories { gradlePluginPortal() From e05bd9fe9c2c6be9dddf3498b2258bc7eedd01dd Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 21 Nov 2024 08:58:36 +0100 Subject: [PATCH 17/93] rebasing --- src/main/kotlin/dev/jansel/feixiao/App.kt | 61 ++----------------- .../kotlin/dev/jansel/feixiao/utils/Twitch.kt | 40 ++++++++++++ .../kotlin/dev/jansel/feixiao/utils/_Utils.kt | 20 ++++++ 3 files changed, 66 insertions(+), 55 deletions(-) create mode 100644 src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt diff --git a/src/main/kotlin/dev/jansel/feixiao/App.kt b/src/main/kotlin/dev/jansel/feixiao/App.kt index 299c7a5..3bf0d24 100644 --- a/src/main/kotlin/dev/jansel/feixiao/App.kt +++ b/src/main/kotlin/dev/jansel/feixiao/App.kt @@ -3,17 +3,13 @@ */ package dev.jansel.feixiao -import com.github.philippheuer.events4j.reactor.ReactorEventHandler import com.github.twitch4j.TwitchClient import com.github.twitch4j.TwitchClientBuilder import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.extensions.EventHooks import dev.jansel.feixiao.extensions.StreamerCommand -import dev.jansel.feixiao.utils.database -import dev.jansel.feixiao.utils.token -import dev.jansel.feixiao.utils.twitchcid -import dev.jansel.feixiao.utils.twitchcs +import dev.jansel.feixiao.utils.* import dev.kord.core.entity.channel.GuildMessageChannel import dev.kordex.core.ExtensibleBot import dev.kordex.core.i18n.SupportedLocales @@ -22,11 +18,13 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking var twitchClient: TwitchClient? = null -val logger = KotlinLogging.logger { } +val logger = KotlinLogging.logger { } +var botRef : ExtensibleBot? = null suspend fun main() { - val bot = ExtensibleBot(token) { + botRef = ExtensibleBot(token) { database(true) + twitch(true) extensions { add(::EventHooks) add(::StreamerCommand) @@ -35,55 +33,8 @@ suspend fun main() { applicationCommandLocale(SupportedLocales.ENGLISH, SupportedLocales.GERMAN) } } - twitchClient = TwitchClientBuilder.builder() - .withEnableHelix(true) - .withClientId(twitchcid) - .withClientSecret(twitchcs) - .withDefaultEventHandler(ReactorEventHandler::class.java) - .build() - twitchClient!!.eventManager.onEvent(ChannelGoLiveEvent::class.java) { - logger.info { "${it.channel.name} went live!" } - runBlocking { - launch { - val streamer = StreamerCollection().getData(it.channel.name) - for (server in streamer!!.servers) { - val channel = bot.kordRef.getChannelOf(server.channelId) - val role = server.roleId - val livemessage = server.liveMessage - - if (role != null) { - if (livemessage != null) { - channel?.createMessage( - livemessage - .replace("{name}", it.channel.name) - .replace("{category}", it.stream.gameName) - .replace("{title}", it.stream.title) - .replace("{url}", "https://twitch.tv/${it.channel.name}") - .replace("{role}", "<@&$role>") - ) - } else { - channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") - } - } else { - if (livemessage != null) { - channel?.createMessage( - livemessage - .replace("{name}", it.channel.name) - .replace("{category}", it.stream.gameName) - .replace("{title}", it.stream.title) - .replace("{url}", "https://twitch.tv/${it.channel.name}") - ) - } else { - channel?.createMessage("https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") - } - } - } - } - } - } - - bot.start() + botRef!!.start() } diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt new file mode 100644 index 0000000..6327551 --- /dev/null +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -0,0 +1,40 @@ +package dev.jansel.feixiao.utils + +import com.github.twitch4j.TwitchClientBuilder +import com.github.twitch4j.events.ChannelGoLiveEvent +import dev.jansel.feixiao.botRef +import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.twitchClient +import dev.kord.core.entity.channel.GuildMessageChannel +import dev.kordex.core.koin.KordExKoinComponent +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking + +class Twitch : KordExKoinComponent { + suspend fun init() { + twitchClient = TwitchClientBuilder.builder() + .withEnableHelix(true) + .withClientId(twitchcid) + .withClientSecret(twitchcs) + .build() + + twitchClient!!.eventManager.onEvent(ChannelGoLiveEvent::class.java) { + dev.jansel.feixiao.logger.info { "${it.channel.name} went live!" } + runBlocking { + launch { + val streamer = StreamerCollection().getData(it.channel.name) + val channel = botRef!!.kordRef.getChannelOf(streamer!!.servers.first().channelId) + val role = streamer.servers.first().roleId + if (role != null) { + channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } else { + channel?.createMessage("${it.channel.name} went live: ${it.stream.title}") + } + } + } + } + } + + + +} diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt index ca0dc30..a7c9ec5 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt @@ -1,12 +1,17 @@ package dev.jansel.feixiao.utils +import com.github.twitch4j.TwitchClientBuilder +import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.database.Database import dev.jansel.feixiao.database.collections.MetaCollection import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Snowflake +import dev.kord.core.entity.channel.GuildMessageChannel import dev.kordex.core.builders.ExtensibleBotBuilder import dev.kordex.core.utils.env import dev.kordex.core.utils.loadModule +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.koin.dsl.bind @@ -37,3 +42,18 @@ suspend inline fun ExtensibleBotBuilder.database(migrate: Boolean) { } } } + +suspend inline fun ExtensibleBotBuilder.twitch(active: Boolean) { + hooks { + beforeKoinSetup { + loadModule { + single { Twitch() } bind Twitch::class + } + + if (active) { + Twitch().init() + } + } + } + +} From f0d9a037c1898daa8d11fa9b4d87c63a64e47968 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 09:01:24 +0100 Subject: [PATCH 18/93] more rebasing --- src/main/kotlin/dev/jansel/feixiao/App.kt | 8 ++++---- src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/dev/jansel/feixiao/App.kt b/src/main/kotlin/dev/jansel/feixiao/App.kt index 3bf0d24..79d73fe 100644 --- a/src/main/kotlin/dev/jansel/feixiao/App.kt +++ b/src/main/kotlin/dev/jansel/feixiao/App.kt @@ -3,19 +3,19 @@ */ package dev.jansel.feixiao +import com.github.philippheuer.events4j.reactor.ReactorEventHandler import com.github.twitch4j.TwitchClient import com.github.twitch4j.TwitchClientBuilder import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.extensions.EventHooks import dev.jansel.feixiao.extensions.StreamerCommand -import dev.jansel.feixiao.utils.* -import dev.kord.core.entity.channel.GuildMessageChannel +import dev.jansel.feixiao.utils.database +import dev.jansel.feixiao.utils.token import dev.kordex.core.ExtensibleBot import dev.kordex.core.i18n.SupportedLocales import io.github.oshai.kotlinlogging.KotlinLogging -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking +import dev.jansel.feixiao.utils.twitch var twitchClient: TwitchClient? = null val logger = KotlinLogging.logger { } diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt index 6327551..07b3d2e 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -1,5 +1,6 @@ package dev.jansel.feixiao.utils +import com.github.philippheuer.events4j.reactor.ReactorEventHandler import com.github.twitch4j.TwitchClientBuilder import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.botRef @@ -14,6 +15,7 @@ class Twitch : KordExKoinComponent { suspend fun init() { twitchClient = TwitchClientBuilder.builder() .withEnableHelix(true) + .withDefaultEventHandler(ReactorEventHandler::class.java) .withClientId(twitchcid) .withClientSecret(twitchcs) .build() From e78864ae8bfdf80750f732fc376306a6e8fde4e2 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 09:06:11 +0100 Subject: [PATCH 19/93] MAYBE ALSO IMPLEMENT CHANGES THAT WERE MADE SINCE THIS BRANCH WAS MADE --- .../kotlin/dev/jansel/feixiao/utils/Twitch.kt | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt index 07b3d2e..1f45103 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -25,12 +25,37 @@ class Twitch : KordExKoinComponent { runBlocking { launch { val streamer = StreamerCollection().getData(it.channel.name) - val channel = botRef!!.kordRef.getChannelOf(streamer!!.servers.first().channelId) - val role = streamer.servers.first().roleId - if (role != null) { - channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") - } else { - channel?.createMessage("${it.channel.name} went live: ${it.stream.title}") + for (server in streamer!!.servers) { + val channel = botRef!!.kordRef.getChannelOf(server.channelId) + val role = server.roleId + val livemessage = server.liveMessage + + if (role != null) { + if (livemessage != null) { + channel?.createMessage( + livemessage + .replace("{name}", it.channel.name) + .replace("{category}", it.stream.gameName) + .replace("{title}", it.stream.title) + .replace("{url}", "https://twitch.tv/${it.channel.name}") + .replace("{role}", "<@&$role>") + ) + } else { + channel?.createMessage("<@&$role> https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } + } else { + if (livemessage != null) { + channel?.createMessage( + livemessage + .replace("{name}", it.channel.name) + .replace("{category}", it.stream.gameName) + .replace("{title}", it.stream.title) + .replace("{url}", "https://twitch.tv/${it.channel.name}") + ) + } else { + channel?.createMessage("https://twitch.tv/${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } + } } } } From b9f8def37552560d5baa4c9d9690212a07ebb9ca Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 28 Nov 2024 09:45:03 +0100 Subject: [PATCH 20/93] finally i'm able to update gradle to 8.11.1 --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e53343b..802ad4c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.10.2" + gradleVersion = "8.11.1" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..e2847c8 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.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index fc0b921..84e3ff8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,8 +6,8 @@ pluginManagement { id("com.github.johnrengelman.shadow") version "8.1.1" - id("dev.kordex.gradle.docker") version "1.5.8" - id("dev.kordex.gradle.kordex") version "1.5.8" + id("dev.kordex.gradle.docker") version "1.6.0" + id("dev.kordex.gradle.kordex") version "1.6.0" } repositories { gradlePluginPortal() From 6fb1e794bd087976cacfa6c0f119be33f48918b5 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Tue, 3 Dec 2024 21:12:44 +0100 Subject: [PATCH 21/93] how tf did this never work (it does now tho --- gradle/libs.versions.toml | 2 +- .../kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b20ea0c..13e95fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ jansi = "2.4.1" kx-ser = "1.7.3" logback = "1.5.12" logback-groovy = "1.14.5" -logging = "7.0.0" +logging = "7.0.3" twitch4j = "1.23.0" events4j = "0.12.2" kx-coroutines = "1.9.0" diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt index efafbac..3a2541f 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt @@ -1,6 +1,7 @@ package dev.jansel.feixiao.extensions import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.database.entities.StreamerData import dev.jansel.feixiao.i18n.Translations import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Permission @@ -14,6 +15,7 @@ import dev.kordex.core.commands.converters.impl.optionalString import dev.kordex.core.commands.converters.impl.string import dev.kordex.core.extensions.Extension import dev.kordex.core.extensions.publicSlashCommand +import org.litote.kmongo.eq class StreamerCommand : Extension() { override val name = "streaming" @@ -54,7 +56,9 @@ class StreamerCommand : Extension() { } action { val streamer = arguments.streamer - StreamerCollection().removeData(guild!!.id, channel.id, streamer, null, null) + StreamerCollection().collection.findOne(StreamerData::name eq streamer)?.servers?.forEach { + StreamerCollection().removeData(it.guildId, it.channelId, streamer, it.roleId, it.liveMessage) + } respond { content = "Removed streamer $streamer" } From 5728ac716c1e1fd992df61b4699cb022cb6d0045 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Tue, 3 Dec 2024 22:20:15 +0100 Subject: [PATCH 22/93] done a lot of shit that will be too much to explain, especially because for once I had to comment my code which I don't like. --- .../collections/StreamerCollection.kt | 81 ++++++++++++++++++- .../feixiao/extensions/StreamerCommand.kt | 74 ++++++++++++++++- .../translations/feixiao/strings.properties | 18 +++++ 3 files changed, 171 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt index 651df09..3928d93 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt @@ -6,6 +6,7 @@ import dev.jansel.feixiao.database.entities.StreamerData import dev.kord.common.entity.Snowflake import dev.kordex.core.koin.KordExKoinComponent import org.koin.core.component.inject +import org.litote.kmongo.elemMatch import org.litote.kmongo.eq import org.litote.kmongo.setValue @@ -20,7 +21,7 @@ class StreamerCollection : KordExKoinComponent { suspend fun getData(channelName: String): StreamerData? = collection.findOne(StreamerData::name eq channelName) - suspend fun updateData( + suspend fun addData( guildId: Snowflake, channelId: Snowflake, streamerName: String, @@ -40,6 +41,84 @@ class StreamerCollection : KordExKoinComponent { } } + /** + * Update the roleId + * @param streamerName: The name of the streamer + * @param roleId: The roleId to update + * @param guildId: The guildId to update + * @param noOverload: This is needed to avoid a conflict with the other updateData function, set to true or false, doesn't matter + * @return 0 = success, 1 = no Server associated with the guildId, 2 = no StreamerData associated with the streamerName + */ + + suspend fun updateData( + streamerName: String, + roleId: Snowflake, + guildId: Snowflake, + noOverload : Boolean = false // this is needed to avoid a conflict with the other updateData function + ): Int { + val coll = collection.findOne(StreamerData::name eq streamerName) + if (coll != null) { + val temp = coll.servers.find { server -> server.guildId == guildId } + if (temp == null) return 1 + collection.updateMany( + StreamerData::name eq streamerName, + setValue(StreamerData::servers, coll.servers - temp + Server(guildId, temp.channelId, roleId, temp.liveMessage)) + ) + return 0 + } + return 2 + } + + /** + * Update the liveMessage + * @param streamerName: The name of the streamer + * @param liveMessage: The liveMessage to update + * @param guildId: The guildId to update + * @return 0 = success, 1 = no Server associated with the guildId, 2 = no StreamerData associated with the streamerName + */ + suspend fun updateData( + streamerName: String, + liveMessage: String?, + guildId: Snowflake + ): Int { + val coll = collection.findOne(StreamerData::name eq streamerName) + if (coll != null) { + val temp = coll.servers.find { server -> server.guildId == guildId } + if (temp == null) return 1 + collection.updateMany( + StreamerData::name eq streamerName, + setValue(StreamerData::servers, coll.servers - temp + Server(guildId, temp.channelId, temp.roleId, liveMessage)) + ) + return 0 + } + return 2 + } + + /** + * Update the channelId + * @param streamerName: The name of the streamer + * @param channelId: The channelId to update + * @param guildId: The guildId to update + * @return 0 = success, 1 = no Server associated with the guildId, 2 = no StreamerData associated with the streamerName + */ + suspend fun updateData( + streamerName: String, + channelId: Snowflake, + guildId: Snowflake + ): Int { + val coll = collection.findOne(StreamerData::name eq streamerName) + if (coll != null) { + val temp = coll.servers.find { server -> server.guildId == guildId } + if (temp == null) return 1 + collection.updateMany( + StreamerData::name eq streamerName, + setValue(StreamerData::servers, coll.servers - temp + Server(guildId, channelId, temp.roleId, temp.liveMessage)) + ) + return 0 + } + return 2 + } + suspend fun removeData( guildId: Snowflake, channelId: Snowflake, diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt index 3a2541f..ddef6a6 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt @@ -2,6 +2,7 @@ package dev.jansel.feixiao.extensions import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.database.entities.StreamerData +import dev.jansel.feixiao.extensions.StreamerCommand.UpdateStreamerArgs import dev.jansel.feixiao.i18n.Translations import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Permission @@ -10,6 +11,7 @@ import dev.kordex.core.checks.hasPermission import dev.kordex.core.commands.Arguments import dev.kordex.core.commands.application.slash.publicSubCommand import dev.kordex.core.commands.converters.impl.channel +import dev.kordex.core.commands.converters.impl.optionalChannel import dev.kordex.core.commands.converters.impl.optionalRole import dev.kordex.core.commands.converters.impl.optionalString import dev.kordex.core.commands.converters.impl.string @@ -33,7 +35,15 @@ class StreamerCommand : Extension() { } action { val streamer = arguments.streamer - StreamerCollection().updateData( + StreamerCollection().getData(streamer)?.servers?.forEach { + if (it.guildId == guild!!.id) { + respond { + content = "Streamer already exists in this server" + } + return@action + } + } + StreamerCollection().addData( guild!!.id, arguments.channel.id, streamer, @@ -64,6 +74,49 @@ class StreamerCommand : Extension() { } } } + + publicSubCommand(::UpdateStreamerArgs) { + name = Translations.Streamer.Command.Update.name + description = Translations.Streamer.Command.Update.description + check { + anyGuild() + hasPermission(Permission.ManageGuild) + } + action { + val streamer = arguments.streamer + val data = StreamerCollection().collection.findOne(StreamerData::name eq streamer) + if (data != null) { + val servers = data.servers + val guildId = guild!!.id + val roleId = arguments.role + val channelId = arguments.channel + val message = arguments.message + val temp = servers.find { it.guildId == guildId } + if (temp != null) { + if (channelId != null) { + StreamerCollection().updateData(streamer, channelId.id, guildId) + } + if (roleId != null) { + StreamerCollection().updateData(streamer, roleId.id, guildId, false) + } + if (message != null) { + StreamerCollection().updateData(streamer, message, guildId) + } + respond { + content = "Updated streamer $streamer" + } + } else { + respond { + content = "No server associated with the guildId" + } + } + } else { + respond { + content = "No StreamerData associated with the streamerName" + } + } + } + } } } @@ -95,4 +148,23 @@ class StreamerCommand : Extension() { require(true) } } + + inner class UpdateStreamerArgs : Arguments() { + val streamer by string { + name = Translations.Streamer.Command.Arguments.Update.Streamer.name + description = Translations.Streamer.Command.Arguments.Update.Streamer.description + } + val channel by optionalChannel { + name = Translations.Streamer.Command.Arguments.Update.Channel.name + description = Translations.Streamer.Command.Arguments.Update.Channel.description + } + val role by optionalRole { + name = Translations.Streamer.Command.Arguments.Update.Role.name + description = Translations.Streamer.Command.Arguments.Update.Role.description + } + val message by optionalString { + name = Translations.Streamer.Command.Arguments.Update.Message.name + description = Translations.Streamer.Command.Arguments.Update.Message.description + } + } } diff --git a/src/main/resources/translations/feixiao/strings.properties b/src/main/resources/translations/feixiao/strings.properties index 95535d7..81c90c9 100644 --- a/src/main/resources/translations/feixiao/strings.properties +++ b/src/main/resources/translations/feixiao/strings.properties @@ -2,10 +2,16 @@ streamer.command.name=streamer streamer.command.description=A bundle of Streamer commands + streamer.command.add.name=add streamer.command.add.description=Add a new streamer to the listener + streamer.command.remove.name=remove streamer.command.remove.description=Remove a streamer from the listener + +streamer.command.update.name=update +streamer.command.update.description=Update a streamer listener's settings for this guild + streamer.command.arguments.add.streamer.name=streamer streamer.command.arguments.add.streamer.description=The streamer to add streamer.command.arguments.add.channel.name=channel @@ -14,7 +20,19 @@ streamer.command.arguments.add.role.name=role streamer.command.arguments.add.role.description=The role to assign to the streamer streamer.command.arguments.add.message.name=message streamer.command.arguments.add.message.description=Custom Announce message. Placeholders (in curly braces): url, name, title, category, role (if set) + streamer.command.arguments.remove.name=streamer streamer.command.arguments.remove.description=The streamer to remove +streamer.command.arguments.update.streamer.name=streamer +streamer.command.arguments.update.streamer.description=The streamer to edit +streamer.command.arguments.update.channel.name=channel +streamer.command.arguments.update.channel.description=The channel to add the streamer to +streamer.command.arguments.update.role.name=role +streamer.command.arguments.update.role.description=The role to assign to the streamer +streamer.command.arguments.update.message.name=message +streamer.command.arguments.update.message.description=Custom Announce message. Placeholders (in curly braces): url, name, title, category, role (if set) + + + # more to come... From 76f775d292046ae5544119a7199b6e42f5b3a59e Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 5 Dec 2024 18:31:48 +0100 Subject: [PATCH 23/93] optimize code and imports --- .idea/material_theme_project_new.xml | 10 ++++++++++ src/main/kotlin/dev/jansel/feixiao/App.kt | 9 +++------ .../database/collections/StreamerCollection.kt | 18 +++++++++++++----- .../feixiao/extensions/StreamerCommand.kt | 7 +------ .../kotlin/dev/jansel/feixiao/utils/Twitch.kt | 1 - .../kotlin/dev/jansel/feixiao/utils/_Utils.kt | 5 ----- 6 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 .idea/material_theme_project_new.xml diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..fea3e03 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/src/main/kotlin/dev/jansel/feixiao/App.kt b/src/main/kotlin/dev/jansel/feixiao/App.kt index afdfc21..eabdacc 100644 --- a/src/main/kotlin/dev/jansel/feixiao/App.kt +++ b/src/main/kotlin/dev/jansel/feixiao/App.kt @@ -1,6 +1,3 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ package dev.jansel.feixiao import com.github.twitch4j.TwitchClient @@ -8,14 +5,14 @@ import dev.jansel.feixiao.extensions.EventHooks import dev.jansel.feixiao.extensions.StreamerCommand import dev.jansel.feixiao.utils.database import dev.jansel.feixiao.utils.token +import dev.jansel.feixiao.utils.twitch import dev.kordex.core.ExtensibleBot import dev.kordex.core.i18n.SupportedLocales import io.github.oshai.kotlinlogging.KotlinLogging -import dev.jansel.feixiao.utils.twitch var twitchClient: TwitchClient? = null -val logger = KotlinLogging.logger { } -var botRef : ExtensibleBot? = null +val logger = KotlinLogging.logger { } +var botRef: ExtensibleBot? = null suspend fun main() { botRef = ExtensibleBot(token) { diff --git a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt index 3928d93..1954f78 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt @@ -6,7 +6,6 @@ import dev.jansel.feixiao.database.entities.StreamerData import dev.kord.common.entity.Snowflake import dev.kordex.core.koin.KordExKoinComponent import org.koin.core.component.inject -import org.litote.kmongo.elemMatch import org.litote.kmongo.eq import org.litote.kmongo.setValue @@ -54,7 +53,7 @@ class StreamerCollection : KordExKoinComponent { streamerName: String, roleId: Snowflake, guildId: Snowflake, - noOverload : Boolean = false // this is needed to avoid a conflict with the other updateData function + noOverload: Boolean = false // this is needed to avoid a conflict with the other updateData function ): Int { val coll = collection.findOne(StreamerData::name eq streamerName) if (coll != null) { @@ -62,7 +61,10 @@ class StreamerCollection : KordExKoinComponent { if (temp == null) return 1 collection.updateMany( StreamerData::name eq streamerName, - setValue(StreamerData::servers, coll.servers - temp + Server(guildId, temp.channelId, roleId, temp.liveMessage)) + setValue( + StreamerData::servers, + coll.servers - temp + Server(guildId, temp.channelId, roleId, temp.liveMessage) + ) ) return 0 } @@ -87,7 +89,10 @@ class StreamerCollection : KordExKoinComponent { if (temp == null) return 1 collection.updateMany( StreamerData::name eq streamerName, - setValue(StreamerData::servers, coll.servers - temp + Server(guildId, temp.channelId, temp.roleId, liveMessage)) + setValue( + StreamerData::servers, + coll.servers - temp + Server(guildId, temp.channelId, temp.roleId, liveMessage) + ) ) return 0 } @@ -112,7 +117,10 @@ class StreamerCollection : KordExKoinComponent { if (temp == null) return 1 collection.updateMany( StreamerData::name eq streamerName, - setValue(StreamerData::servers, coll.servers - temp + Server(guildId, channelId, temp.roleId, temp.liveMessage)) + setValue( + StreamerData::servers, + coll.servers - temp + Server(guildId, channelId, temp.roleId, temp.liveMessage) + ) ) return 0 } diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt index ddef6a6..0e1818c 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt @@ -2,7 +2,6 @@ package dev.jansel.feixiao.extensions import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.database.entities.StreamerData -import dev.jansel.feixiao.extensions.StreamerCommand.UpdateStreamerArgs import dev.jansel.feixiao.i18n.Translations import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Permission @@ -10,11 +9,7 @@ import dev.kordex.core.checks.anyGuild import dev.kordex.core.checks.hasPermission import dev.kordex.core.commands.Arguments import dev.kordex.core.commands.application.slash.publicSubCommand -import dev.kordex.core.commands.converters.impl.channel -import dev.kordex.core.commands.converters.impl.optionalChannel -import dev.kordex.core.commands.converters.impl.optionalRole -import dev.kordex.core.commands.converters.impl.optionalString -import dev.kordex.core.commands.converters.impl.string +import dev.kordex.core.commands.converters.impl.* import dev.kordex.core.extensions.Extension import dev.kordex.core.extensions.publicSlashCommand import org.litote.kmongo.eq diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt index 1f45103..0aa7ca8 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/Twitch.kt @@ -63,5 +63,4 @@ class Twitch : KordExKoinComponent { } - } diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt index a7c9ec5..c1b55da 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt @@ -1,17 +1,12 @@ package dev.jansel.feixiao.utils -import com.github.twitch4j.TwitchClientBuilder -import com.github.twitch4j.events.ChannelGoLiveEvent import dev.jansel.feixiao.database.Database import dev.jansel.feixiao.database.collections.MetaCollection import dev.jansel.feixiao.database.collections.StreamerCollection -import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Snowflake -import dev.kord.core.entity.channel.GuildMessageChannel import dev.kordex.core.builders.ExtensibleBotBuilder import dev.kordex.core.utils.env import dev.kordex.core.utils.loadModule -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.koin.dsl.bind From 891c544ad8f9647cc2070a209e0d5df4257801b6 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 5 Dec 2024 18:34:17 +0100 Subject: [PATCH 24/93] [skip ci] edit renovate.json --- .github/renovate.json | 3 ++- .idea/material_theme_project_new.xml | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index ba1d693..804df73 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -11,5 +11,6 @@ "matchUpdateTypes": ["patch", "pin", "digest"], "automerge": true } - ] + ], + "assignees": ["NotJansel"] } diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml index fea3e03..8d28a9e 100644 --- a/.idea/material_theme_project_new.xml +++ b/.idea/material_theme_project_new.xml @@ -3,7 +3,9 @@ From d4f750ba6834bf308cace9948f6c866851501a09 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Fri, 6 Dec 2024 13:46:42 +0100 Subject: [PATCH 25/93] maybe this is more clear regarding everyone pings (I have no clue if the described workaround works, too lazy) --- .idea/misc.xml | 4 ++-- .idea/modules.xml | 8 -------- gradle/libs.versions.toml | 2 +- .../dev/jansel/feixiao/extensions/StreamerCommand.kt | 12 ++++++++++++ 4 files changed, 15 insertions(+), 11 deletions(-) delete mode 100644 .idea/modules.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index a4abeb1..0b1ec52 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + - \ No newline at end of file + diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 4787ae5..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 13e95fa..51def88 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,4 +23,4 @@ logback-groovy = { module = "io.github.virtualdogbert:logback-groovy-config", ve logging = { module = "io.github.oshai:kotlin-logging", version.ref = "logging" } twitch4j = { module = "com.github.twitch4j:twitch4j", version.ref = "twitch4j" } events4j = { module = "com.github.philippheuer.events4j:events4j-handler-reactor", version.ref = "events4j" } -kmongo = { module="org.litote.kmongo:kmongo-coroutine-serialization", version.ref = "kmongo"} +kmongo = { module="org.litote.kmongo:kmongo-coroutine-serialization", version.ref = "kmongo" } diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt index 0e1818c..495d306 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt @@ -38,6 +38,12 @@ class StreamerCommand : Extension() { return@action } } + if (arguments.role?.id == guild!!.id) { + respond { + content = "This action would implement a everyone ping. to properly use it please make a ping without role and insert the everyone ping manually." + } + return@action + } StreamerCollection().addData( guild!!.id, arguments.channel.id, @@ -87,6 +93,12 @@ class StreamerCommand : Extension() { val channelId = arguments.channel val message = arguments.message val temp = servers.find { it.guildId == guildId } + if (roleId?.id== guildId) { + respond { + content = "This action would implement a everyone ping. to properly use it please make a ping without role and insert the everyone ping manually." + } + return@action + } if (temp != null) { if (channelId != null) { StreamerCollection().updateData(streamer, channelId.id, guildId) From 789d58f99aef689958c20c4ff10c1833e5c19ee0 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 9 Dec 2024 17:56:03 +0100 Subject: [PATCH 26/93] rewrite the response better when an attempt is made to ping everyone as a role ping --- .../kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt index 495d306..4f014d1 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt @@ -40,7 +40,7 @@ class StreamerCommand : Extension() { } if (arguments.role?.id == guild!!.id) { respond { - content = "This action would implement a everyone ping. to properly use it please make a ping without role and insert the everyone ping manually." + content = "This action would implement a everyone ping, which is due to how role pings are implemented right now not possible. If you want to make an everyone ping regardless, make a role-less ping and write the everyone ping manually." } return@action } @@ -95,7 +95,7 @@ class StreamerCommand : Extension() { val temp = servers.find { it.guildId == guildId } if (roleId?.id== guildId) { respond { - content = "This action would implement a everyone ping. to properly use it please make a ping without role and insert the everyone ping manually." + content = "This action would implement a everyone ping, which is due to how role pings are implemented right now not possible. If you want to make an everyone ping regardless, make a role-less ping and write the everyone ping manually." } return@action } From 3093900cebb55b8427b3a8a771d5468240a2c246 Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 02:19:26 +0000 Subject: [PATCH 27/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index a59dafc..a37dba7 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -34,9 +34,9 @@ jobs: uses: docker/login-action@v3 with: - registry: ghcr.io + registry: pi5:8125 username: ${{ github.repository_owner }} - password: ${{ secrets.CR_PAT }} + password: ${{ secrets.PW }} - name: Build and push uses: docker/build-push-action@v6 @@ -44,4 +44,4 @@ jobs: context: . platforms: linux/arm64 push: true - tags: ghcr.io/notjansel/feixiao:latest + tags: jansel/feixiao:latest From 5f07b1b61d89c3957167f7f5bacb15a589f613aa Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 12:39:04 +0000 Subject: [PATCH 28/93] Update .github/workflows/ci.yml --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7a094d..ec9eff1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ jobs: runs-on: ubuntu-latest steps: + - name: Disable SSL verify (Temporary Fix) + run: git config --global http.sslVerify false + - uses: actions/checkout@v4 - name: Set up Java From 6ceb20aee601ce9c168e3f2a708621c0962cb476 Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 12:40:03 +0000 Subject: [PATCH 29/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index a37dba7..bb95fe5 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -9,6 +9,9 @@ jobs: build: runs-on: ubuntu-latest steps: + - name: Disable SSL verify (Temporary Fix) + run: git config --global http.sslVerify false + - uses: actions/checkout@v4 - name: Set up QEMU From f9f62ae9c612d0561c9297ecba9e3084667065ed Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 12:45:42 +0000 Subject: [PATCH 30/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index bb95fe5..8e6da64 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -47,4 +47,4 @@ jobs: context: . platforms: linux/arm64 push: true - tags: jansel/feixiao:latest + tags: pi5:8125/jansel/feixiao:latest From dd7f3504ba08dfd71c032138bc54c640feaa2bab Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 20:58:45 +0000 Subject: [PATCH 31/93] let this work? --- .github/workflows/root.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 8e6da64..cc58af1 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -41,10 +41,5 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.PW }} - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/arm64 - push: true - tags: pi5:8125/jansel/feixiao:latest + - name: Push to Gitea Registry + run: docker buildx build --output type=registry,registry.insecure=true,name=pi5:8125/jansel/feixiao From 49e1d4149f6888458a709c3541d20b6b7b44a806 Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:03:53 +0000 Subject: [PATCH 32/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index cc58af1..7ad061b 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -33,7 +33,7 @@ jobs: - name: Gradle (Build) run: "./gradlew build" - - name: Login to GitHub Container Registry + - name: Login to Gitea Registry uses: docker/login-action@v3 with: @@ -42,4 +42,4 @@ jobs: password: ${{ secrets.PW }} - name: Push to Gitea Registry - run: docker buildx build --output type=registry,registry.insecure=true,name=pi5:8125/jansel/feixiao + run: docker build pi5:8125/jansel/feixiao . From 834d3578550484a358a2048ee6dfa41c0702f1cc Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:06:04 +0000 Subject: [PATCH 33/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 7ad061b..964d20c 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -27,11 +27,31 @@ jobs: java-version: 17 distribution: temurin + - name: Gradle Cache + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Gradle (Build) run: "./gradlew build" + + - name: Gradle Cache + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- - name: Login to Gitea Registry uses: docker/login-action@v3 From 2d0f156f458f1d8c022d729145e61e013d69e964 Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:12:43 +0000 Subject: [PATCH 34/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 964d20c..158fa07 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -61,5 +61,8 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.PW }} - - name: Push to Gitea Registry - run: docker build pi5:8125/jansel/feixiao . + - name: Build the Docker image + run: docker build -t pi5:8125/jansel/feixiao . + + - name: Push the Docker image + run: docker push pi5:8125/jansel/feixiao From 0548bf56bd444a95e1d78a9af70c09d2045291d0 Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:24:21 +0000 Subject: [PATCH 35/93] pls let the caching work --- .github/workflows/root.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 158fa07..4df8a38 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -28,7 +28,7 @@ jobs: distribution: temurin - name: Gradle Cache - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | ~/.gradle/caches @@ -44,14 +44,12 @@ jobs: run: "./gradlew build" - name: Gradle Cache - uses: actions/cache@v4 + uses: actions/cache/save@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - name: Login to Gitea Registry uses: docker/login-action@v3 From 2270f3d72592bf1b479ddc7f68d43f250693264b Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:34:08 +0000 Subject: [PATCH 36/93] update java to 21 --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 4df8a38..b745558 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -24,7 +24,7 @@ jobs: uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: temurin - name: Gradle Cache From ae8b09c405765c83ea6e9ed69ebd41cd27aef0db Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:39:11 +0000 Subject: [PATCH 37/93] [skip ci] delete unused workflow Signed-off-by: jansel --- .github/workflows/develop.yml | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 .github/workflows/develop.yml diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml deleted file mode 100644 index eb0ab25..0000000 --- a/.github/workflows/develop.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Build & Publish - -on: - push: - branches: - - develop - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Set up Java - uses: actions/setup-java@v4 - - with: - java-version: 17 - distribution: temurin - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Gradle (Build) - run: "./gradlew build" - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - - with: - name: Build and Deploy Artifacts - path: build/libs/*.jar From 47f281ed5b3098e1490c062671ed55ca11f7606a Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 11 Dec 2024 21:39:31 +0000 Subject: [PATCH 38/93] [skip ci] delete unused workflow --- .github/workflows/ci.yml | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index ec9eff1..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Build (CI) - -on: - push: - branches-ignore: - - root - - develop - - pull_request: - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Disable SSL verify (Temporary Fix) - run: git config --global http.sslVerify false - - - uses: actions/checkout@v4 - - - name: Set up Java - uses: actions/setup-java@v4 - - with: - java-version: 17 - distribution: temurin - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Gradle (Build) - run: "./gradlew build" - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - - with: - name: Build and Deploy Artifacts - path: build/libs/*.jar From 19daee52120bc2f6728b1fce1dceb16c5e6367b1 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 13 Dec 2024 02:49:10 +0000 Subject: [PATCH 39/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index b745558..ed6825e 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -60,7 +60,7 @@ jobs: password: ${{ secrets.PW }} - name: Build the Docker image - run: docker build -t pi5:8125/jansel/feixiao . + run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ gitea.run_number }} . - name: Push the Docker image run: docker push pi5:8125/jansel/feixiao From c689e4c9a0a87cbef58b17910cd4d4a7ebe759d3 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 13 Dec 2024 02:59:46 +0000 Subject: [PATCH 40/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index ed6825e..01ef38c 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -63,4 +63,4 @@ jobs: run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ gitea.run_number }} . - name: Push the Docker image - run: docker push pi5:8125/jansel/feixiao + run: docker push -a pi5:8125/jansel/feixiao From d3c2f54fc63223ecf3553034cc16829bf6d2a94d Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 13 Dec 2024 03:04:23 +0000 Subject: [PATCH 41/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 01ef38c..7e50421 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -62,5 +62,8 @@ jobs: - name: Build the Docker image run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ gitea.run_number }} . - - name: Push the Docker image - run: docker push -a pi5:8125/jansel/feixiao + - name: Push the latest Docker image + run: docker push pi5:8125/jansel/feixiao:latest + + - name: Push the Docker image related to this workflow + run: docker push pi5:8125/jansel/feixiao:${{ gitea.run_number }} \ No newline at end of file From 72180525a4d1b897d68e62d7df7ba97136254bbf Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 13 Dec 2024 03:10:16 +0000 Subject: [PATCH 42/93] reverse order --- .github/workflows/root.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 7e50421..3735f00 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -62,8 +62,8 @@ jobs: - name: Build the Docker image run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ gitea.run_number }} . - - name: Push the latest Docker image - run: docker push pi5:8125/jansel/feixiao:latest - - name: Push the Docker image related to this workflow - run: docker push pi5:8125/jansel/feixiao:${{ gitea.run_number }} \ No newline at end of file + run: docker push pi5:8125/jansel/feixiao:${{ gitea.run_number }} + + - name: Push the latest Docker image + run: docker push pi5:8125/jansel/feixiao:latest \ No newline at end of file From 7e72fdcb79c7561b0b5bc50dd15e7990d5555fe7 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 13 Dec 2024 03:39:57 +0000 Subject: [PATCH 43/93] Delete .github/renovate.json --- .github/renovate.json | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .github/renovate.json diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index 804df73..0000000 --- a/.github/renovate.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended" - ], - "commitBody": "[skip ci]", - "baseBranches": ["refactor/depUpdates"], - "prHourlyLimit": 0, - "packageRules": [ - { - "matchUpdateTypes": ["patch", "pin", "digest"], - "automerge": true - } - ], - "assignees": ["NotJansel"] -} From afc7f29e871d9a3985cc61acb73e7cfc8af568b6 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 13 Dec 2024 03:56:10 +0000 Subject: [PATCH 44/93] [skip ci] edit readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index afc06e6..80fee11 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,5 @@ Blanketbot is a Discord bot, coded to notify you when your favorite twitch streamer goes live. To simply set it up, add the Bot to your server through the Invite link above and use the `/streamer add` command to add your favorite streamer. The bot will then notify you when the streamer goes live. If issues arise, please don't hesitate to create an issue here on GitHub. + +Info if you're looking at this from GitHub and not the Gitea Instance: This repo now is used as a mirror, Issues will still be looked at here on GitHub. For PR's, I will create a patchfile from that pr and apply it manually on the [origin repo](https://git.jansel.dev/jansel/feixiao) \ No newline at end of file From cd7389e34704f98cc79b80c783d4847e8ac78df6 Mon Sep 17 00:00:00 2001 From: jansel Date: Sat, 14 Dec 2024 18:53:03 +0000 Subject: [PATCH 45/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 3735f00..d96266a 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -8,10 +8,7 @@ on: jobs: build: runs-on: ubuntu-latest - steps: - - name: Disable SSL verify (Temporary Fix) - run: git config --global http.sslVerify false - + steps: - uses: actions/checkout@v4 - name: Set up QEMU From 6bb57cd591af150fb97bdedb874ed5fa3e23c1b1 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 27 Dec 2024 03:27:41 +0100 Subject: [PATCH 46/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index d96266a..7f72ea9 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -4,6 +4,8 @@ on: push: branches: - root + schedule: + - cron: "0 0 * * *" jobs: build: @@ -24,6 +26,10 @@ jobs: java-version: 21 distribution: temurin + - name: Get current date + id: date + run: echo "::set-output name=date::$(date +'%Y-%m-%d')" + - name: Gradle Cache uses: actions/cache/restore@v4 with: @@ -57,10 +63,10 @@ jobs: password: ${{ secrets.PW }} - name: Build the Docker image - run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ gitea.run_number }} . + run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} . - name: Push the Docker image related to this workflow - run: docker push pi5:8125/jansel/feixiao:${{ gitea.run_number }} + run: docker push pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} - name: Push the latest Docker image run: docker push pi5:8125/jansel/feixiao:latest \ No newline at end of file From 1dda6129170208f50b094cb1486eeb60de58ae8a Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 27 Dec 2024 03:28:23 +0100 Subject: [PATCH 47/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 7f72ea9..00c7ae8 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -5,7 +5,7 @@ on: branches: - root schedule: - - cron: "0 0 * * *" + - cron: "0 6 * * *" jobs: build: From d89a881499a174c8aff65e7aa5dcec6ff41d3f3a Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 27 Dec 2024 03:35:00 +0100 Subject: [PATCH 48/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 00c7ae8..5902021 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -10,7 +10,10 @@ on: jobs: build: runs-on: ubuntu-latest - steps: + steps: + - name: Disable SSL verify (Temporary Fix) + run: git config --global http.sslVerify false + - uses: actions/checkout@v4 - name: Set up QEMU From 2c36e0c3b55238e1e433a31f00db374e19bc4048 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 27 Dec 2024 03:53:10 +0100 Subject: [PATCH 49/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 5902021..be87cbd 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -39,7 +39,7 @@ jobs: path: | ~/.gradle/caches ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + key: ${{ runner.os }}-gradle-Feixiao restore-keys: | ${{ runner.os }}-gradle- @@ -55,7 +55,7 @@ jobs: path: | ~/.gradle/caches ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + key: ${{ runner.os }}-gradle-Feixiao - name: Login to Gitea Registry uses: docker/login-action@v3 From 9228529f189061fa2f7fe25d80871003efbed968 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Sun, 5 Jan 2025 21:14:59 +0100 Subject: [PATCH 50/93] fuck the cache, it didnt wanna work properly anyways --- .github/workflows/root.yml | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index be87cbd..bea574a 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Disable SSL verify (Temporary Fix) run: git config --global http.sslVerify false - + - uses: actions/checkout@v4 - name: Set up QEMU @@ -33,29 +33,11 @@ jobs: id: date run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - name: Gradle Cache - uses: actions/cache/restore@v4 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-Feixiao - restore-keys: | - ${{ runner.os }}-gradle- - - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Gradle (Build) run: "./gradlew build" - - - name: Gradle Cache - uses: actions/cache/save@v4 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-Feixiao - name: Login to Gitea Registry uses: docker/login-action@v3 @@ -67,9 +49,15 @@ jobs: - name: Build the Docker image run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} . - + - name: Push the Docker image related to this workflow run: docker push pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} - + - name: Push the latest Docker image - run: docker push pi5:8125/jansel/feixiao:latest \ No newline at end of file + run: docker push pi5:8125/jansel/feixiao:latest + + - name: Remove the Docker image + run: docker rmi pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} + + - name: Force remove the latest Docker image + run: docker rmi pi5:8125/jansel/feixiao:latest --force From 7d4d0fda3ff76d74dcc6d693d6b1293a1d55bdf6 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Wed, 8 Jan 2025 18:45:17 +0100 Subject: [PATCH 51/93] upgrade various versions, including gradle to 8.12 --- build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 3 +-- settings.gradle.kts | 4 ++-- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 802ad4c..2d557ec 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.11.1" + gradleVersion = "8.12" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 51def88..37b60c6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.0.21" # Note: Plugin versions must be updated in the settings.gradle.kts too +kotlin = "2.1.0" # Note: Plugin versions must be updated in the settings.gradle.kts too groovy = "3.0.23" jansi = "2.4.1" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2847c8..cea7a79 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.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6..f3b75f3 100755 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/settings.gradle.kts b/settings.gradle.kts index 84e3ff8..cbdaaef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,8 @@ pluginManagement { plugins { // Update this in libs.version.toml when you change it here. - kotlin("jvm") version "2.0.21" - kotlin("plugin.serialization") version "2.0.21" + kotlin("jvm") version "2.1.0" + kotlin("plugin.serialization") version "2.1.0" id("com.github.johnrengelman.shadow") version "8.1.1" From 5dc0c64e0e1cc7d1a971bf7ec2d3499a5f167bff Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 17 Jan 2025 00:31:24 +0100 Subject: [PATCH 52/93] [skip ci] change scheduled builds to just monday midnight --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index bea574a..ade5488 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -5,7 +5,7 @@ on: branches: - root schedule: - - cron: "0 6 * * *" + - cron: "0 0 * * 1" jobs: build: From 7969b988d7f11edb1d691278f09ce45ce3133a06 Mon Sep 17 00:00:00 2001 From: jansel Date: Fri, 17 Jan 2025 00:35:53 +0100 Subject: [PATCH 53/93] [skip ci] change run name so it doesnt just take the last commit name --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index ade5488..4b074ac 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -1,5 +1,5 @@ name: Build & Publish - +run-name: Feixiao weekly deploy on: push: branches: From 3a04c4d6ed4f8646a84fd55ca92e437b3af4b64c Mon Sep 17 00:00:00 2001 From: jansel Date: Wed, 22 Jan 2025 11:38:34 +0100 Subject: [PATCH 54/93] Upgrade Version to 1.1-SNAPSHOT Signed-off-by: jansel --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2d557ec..25a2b6c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { } group = "dev.jansel" -version = "1.0-SNAPSHOT" +version = "1.1-SNAPSHOT" dependencies { From 8ce36de89ace7d780b8f18251a67a492d8bdf3f3 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Sat, 25 Jan 2025 02:39:18 +0100 Subject: [PATCH 55/93] gradle 8.12.1 --- .idea/kotlinc.xml | 2 +- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index c224ad5..bb44937 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 25a2b6c..3d1a220 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.12" + gradleVersion = "8.12.1" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a79..e18bc25 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.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From c5ef4b0b56898bd2cd4ab0347d6f8c6c4b1ceafd Mon Sep 17 00:00:00 2001 From: jansel Date: Sun, 9 Feb 2025 19:39:25 +0100 Subject: [PATCH 56/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 4b074ac..6bedbb5 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -5,7 +5,7 @@ on: branches: - root schedule: - - cron: "0 0 * * 1" + - cron: "0 0 * * 0" jobs: build: From 63102a7ba2aa00a0950cd31ac2e9b400f73e3abb Mon Sep 17 00:00:00 2001 From: jansel Date: Sat, 15 Feb 2025 03:32:32 +0100 Subject: [PATCH 57/93] change registry to DigitalOcean --- .github/workflows/root.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 6bedbb5..d4e06c8 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -43,21 +43,21 @@ jobs: uses: docker/login-action@v3 with: - registry: pi5:8125 - username: ${{ github.repository_owner }} - password: ${{ secrets.PW }} + registry: registry.digitalocean.com + username: ${{ secrets.DOMAIL }} + password: ${{ secrets.DOKEY }} - name: Build the Docker image - run: docker build -t pi5:8125/jansel/feixiao:latest -t pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} . + run: docker build -t registry.digitalocean.com/jansel/feixiao:latest -t registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} . - name: Push the Docker image related to this workflow - run: docker push pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} + run: docker push registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} - name: Push the latest Docker image - run: docker push pi5:8125/jansel/feixiao:latest + run: docker push registry.digitalocean.com/jansel/feixiao:latest - name: Remove the Docker image - run: docker rmi pi5:8125/jansel/feixiao:${{ steps.date.outputs.date }} + run: docker rmi registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} - name: Force remove the latest Docker image - run: docker rmi pi5:8125/jansel/feixiao:latest --force + run: docker rmi registry.digitalocean.com/jansel/feixiao:latest --force From b680ce4ef45b42dbd724750d126973fa4792da8c Mon Sep 17 00:00:00 2001 From: jansel Date: Sat, 15 Feb 2025 03:38:42 +0100 Subject: [PATCH 58/93] [skip ci] yep should change this lol --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index d4e06c8..779319c 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -39,7 +39,7 @@ jobs: - name: Gradle (Build) run: "./gradlew build" - - name: Login to Gitea Registry + - name: Login to DigitalOcean Registry uses: docker/login-action@v3 with: From 836e938dcef34253fef0b680e04324e04c56342a Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Sat, 15 Feb 2025 11:10:51 +0100 Subject: [PATCH 59/93] Streamers are now saved by both name and id, and on startup updates to the new name if there is one. --- .../dev/jansel/feixiao/database/Migrator.kt | 2 ++ .../collections/StreamerCollection.kt | 3 ++- .../feixiao/database/entities/StreamerData.kt | 1 + .../jansel/feixiao/database/migrations/v2.kt | 16 ++++++++++++++ .../jansel/feixiao/extensions/EventHooks.kt | 9 ++++++-- .../kotlin/dev/jansel/feixiao/utils/_Utils.kt | 21 +++++++++++++++++++ 6 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/dev/jansel/feixiao/database/migrations/v2.kt diff --git a/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt b/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt index 2043779..f8f08e7 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt @@ -3,6 +3,7 @@ package dev.jansel.feixiao.database import dev.jansel.feixiao.database.collections.MetaCollection import dev.jansel.feixiao.database.entities.MetaData import dev.jansel.feixiao.database.migrations.v1 +import dev.jansel.feixiao.database.migrations.v2 import dev.kordex.core.koin.KordExKoinComponent import io.github.oshai.kotlinlogging.KotlinLogging import org.koin.core.component.inject @@ -35,6 +36,7 @@ object Migrator : KordExKoinComponent { try { when (nextVersion) { 1 -> ::v1 + 2 -> ::v2 else -> break }(db.mongo) diff --git a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt index 1954f78..3471e94 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt @@ -3,6 +3,7 @@ package dev.jansel.feixiao.database.collections import dev.jansel.feixiao.database.Database import dev.jansel.feixiao.database.entities.Server import dev.jansel.feixiao.database.entities.StreamerData +import dev.jansel.feixiao.utils.getTwitchIdByName import dev.kord.common.entity.Snowflake import dev.kordex.core.koin.KordExKoinComponent import org.koin.core.component.inject @@ -35,7 +36,7 @@ class StreamerCollection : KordExKoinComponent { ) } else { collection.insertOne( - StreamerData(streamerName, listOf(Server(guildId, channelId, roleId, liveMessage))) + StreamerData(streamerName, getTwitchIdByName(streamerName), listOf(Server(guildId, channelId, roleId, liveMessage))) ) } } diff --git a/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt b/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt index 3425532..9e79d75 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt @@ -6,6 +6,7 @@ import kotlinx.serialization.Serializable @Serializable data class StreamerData( val name: String, + val id: String?, val servers: List ) diff --git a/src/main/kotlin/dev/jansel/feixiao/database/migrations/v2.kt b/src/main/kotlin/dev/jansel/feixiao/database/migrations/v2.kt new file mode 100644 index 0000000..df0f783 --- /dev/null +++ b/src/main/kotlin/dev/jansel/feixiao/database/migrations/v2.kt @@ -0,0 +1,16 @@ +package dev.jansel.feixiao.database.migrations + +import dev.jansel.feixiao.database.entities.StreamerData +import dev.jansel.feixiao.utils.getTwitchIdByName +import org.litote.kmongo.coroutine.CoroutineDatabase +import org.litote.kmongo.eq +import org.litote.kmongo.setValue + +suspend fun v2(db: CoroutineDatabase) { + db.getCollection("streamerData").findOne(StreamerData::id eq null)?.let { + db.getCollection("streamerData").updateOne( + StreamerData::name eq it.name, + setValue(StreamerData::id, getTwitchIdByName(it.name)) + ) + } +} diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt index 5fb0e0d..c9a4ca6 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt @@ -4,6 +4,8 @@ import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.database.entities.StreamerData import dev.jansel.feixiao.logger import dev.jansel.feixiao.twitchClient +import dev.jansel.feixiao.utils.getTwitchIdByName +import dev.jansel.feixiao.utils.getTwitchNameById import dev.jansel.feixiao.utils.tchannelid import dev.jansel.feixiao.utils.tserverid import dev.kord.core.behavior.getChannelOf @@ -12,6 +14,7 @@ import dev.kord.core.event.gateway.ReadyEvent import dev.kordex.core.extensions.Extension import dev.kordex.core.extensions.event import org.litote.kmongo.eq +import org.litote.kmongo.setValue class EventHooks : Extension() { override val name = "eventhooks" @@ -27,8 +30,10 @@ class EventHooks : Extension() { // check every entry in the database and enable the stream event listener if a server is listening to the streamer StreamerCollection().collection.find().toList().forEach { if (it.servers.isNotEmpty()) { - twitchClient!!.clientHelper.enableStreamEventListener(it.name) - logger.info { "Enabled stream event listener for ${it.name}" } + val currentName = getTwitchNameById(it.id!!) + twitchClient!!.clientHelper.enableStreamEventListener(currentName) + logger.info { "Enabled stream event listener for $currentName" } + StreamerCollection().collection.updateOne(StreamerData::name eq it.name, setValue(StreamerData::name, currentName)) } else { logger.info { "No servers are listening to ${it.name}, deleting from the database..." } StreamerCollection().collection.deleteMany(StreamerData::name eq it.name) diff --git a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt index c1b55da..97ece69 100644 --- a/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt +++ b/src/main/kotlin/dev/jansel/feixiao/utils/_Utils.kt @@ -3,6 +3,7 @@ package dev.jansel.feixiao.utils import dev.jansel.feixiao.database.Database import dev.jansel.feixiao.database.collections.MetaCollection import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.twitchClient import dev.kord.common.entity.Snowflake import dev.kordex.core.builders.ExtensibleBotBuilder import dev.kordex.core.utils.env @@ -52,3 +53,23 @@ suspend inline fun ExtensibleBotBuilder.twitch(active: Boolean) { } } + +fun getTwitchNameById(id: String): String? { + val resultList = twitchClient!!.helix?.getUsers(null, listOf(id), null)?.execute() + resultList?.users?.forEach { user -> + if (user.id == id) { + return user.displayName + } + } + return null +} + +fun getTwitchIdByName(name: String): String? { + val resultList = twitchClient!!.helix?.getUsers(null, null, listOf(name))?.execute() + resultList?.users?.forEach { user -> + if (user.displayName == name) { + return user.id + } + } + return null +} From c6cf204f44f4e4a456c9d2c4282f522bdeb37b55 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Sat, 15 Feb 2025 11:34:17 +0100 Subject: [PATCH 60/93] MAYBE INIT A TWITCH CLIENT WHEN MIGRATING AAAAAAAAA --- .../kotlin/dev/jansel/feixiao/database/Migrator.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt b/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt index f8f08e7..5e539eb 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt @@ -1,9 +1,14 @@ package dev.jansel.feixiao.database +import com.github.philippheuer.events4j.reactor.ReactorEventHandler +import com.github.twitch4j.TwitchClientBuilder import dev.jansel.feixiao.database.collections.MetaCollection import dev.jansel.feixiao.database.entities.MetaData import dev.jansel.feixiao.database.migrations.v1 import dev.jansel.feixiao.database.migrations.v2 +import dev.jansel.feixiao.twitchClient +import dev.jansel.feixiao.utils.twitchcid +import dev.jansel.feixiao.utils.twitchcs import dev.kordex.core.koin.KordExKoinComponent import io.github.oshai.kotlinlogging.KotlinLogging import org.koin.core.component.inject @@ -16,6 +21,13 @@ object Migrator : KordExKoinComponent { suspend fun migrate() { logger.info { "Starting main database migration" } + logger.info { "Initializing Twitch client just in case" } + twitchClient = TwitchClientBuilder.builder() + .withEnableHelix(true) + .withDefaultEventHandler(ReactorEventHandler::class.java) + .withClientId(twitchcid) + .withClientSecret(twitchcs) + .build() var meta = mainMetaCollection.get() From 58275f226247abe9c9f1bda892401647351bc6d6 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 10 Mar 2025 14:30:31 +0100 Subject: [PATCH 61/93] update some dependencies --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43705 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- settings.gradle.kts | 4 ++-- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3d1a220..4596f7f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.12.1" + gradleVersion = "8.13" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..9bbc975c742b298b441bfb90dbc124400a3751b9 100644 GIT binary patch delta 34744 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 delta 34727 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�{ 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 a%EQ2*fnt2> Date: Wed, 12 Mar 2025 20:18:49 +0100 Subject: [PATCH 62/93] update twitch4j --- 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 37b60c6..f34741c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kx-ser = "1.7.3" logback = "1.5.12" logback-groovy = "1.14.5" logging = "7.0.3" -twitch4j = "1.23.0" +twitch4j = "1.24.0" events4j = "0.12.2" kx-coroutines = "1.9.0" kmongo = "5.1.0" From da4c983d8945720d1452f0a39614b91df1080e83 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Tue, 18 Mar 2025 11:08:05 +0100 Subject: [PATCH 63/93] remove minimum allocation, but keep max allocation --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4596f7f..a2ead66 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -82,7 +82,7 @@ docker { emptyLine() entryPointExec( - "java", "-Xms2G", "-Xmx2G", + "java", "-Xmx2G", "-jar", "/bot/bot.jar" ) } From e8250b2e3a7b32aadcb6f150794798f4acac4ac8 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Thu, 3 Apr 2025 17:06:03 +0200 Subject: [PATCH 64/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 779319c..a61c8bf 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -16,12 +16,6 @@ jobs: - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Set up Java uses: actions/setup-java@v4 From 8788c0100def6858b39afea3608f61f7fdbd083a Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Tue, 15 Apr 2025 00:12:16 +0200 Subject: [PATCH 65/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index a61c8bf..6832d82 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -1,11 +1,8 @@ name: Build & Publish -run-name: Feixiao weekly deploy on: push: branches: - root - schedule: - - cron: "0 0 * * 0" jobs: build: From 550912020ea74e04c53e7ec15c424b4fec149d15 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Tue, 20 May 2025 10:25:17 +0200 Subject: [PATCH 66/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 45 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 6832d82..12c3c01 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -1,17 +1,21 @@ name: Build & Publish + on: + workflow_dispatch: push: - branches: - - root jobs: build: runs-on: ubuntu-latest - steps: - - name: Disable SSL verify (Temporary Fix) - run: git config --global http.sslVerify false + steps: - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Set up Java uses: actions/setup-java@v4 @@ -20,13 +24,17 @@ jobs: java-version: 21 distribution: temurin + - name: Gradle (Setup) + uses: gradle/actions/setup-gradle@v4 + + with: + dependency-graph: generate-and-submit + cache-disabled: true + - name: Get current date id: date run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Gradle (Build) run: "./gradlew build" @@ -38,17 +46,10 @@ jobs: username: ${{ secrets.DOMAIL }} password: ${{ secrets.DOKEY }} - - name: Build the Docker image - run: docker build -t registry.digitalocean.com/jansel/feixiao:latest -t registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} . - - - name: Push the Docker image related to this workflow - run: docker push registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} - - - name: Push the latest Docker image - run: docker push registry.digitalocean.com/jansel/feixiao:latest - - - name: Remove the Docker image - run: docker rmi registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} - - - name: Force remove the latest Docker image - run: docker rmi registry.digitalocean.com/jansel/feixiao:latest --force + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: registry.digitalocean.com/jansel/feixiao:latest,registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} From a1b3587af4f70332e75b68b28fa79c8d4bb8b8be Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Tue, 20 May 2025 10:33:45 +0200 Subject: [PATCH 67/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 12c3c01..8667e10 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -24,8 +24,8 @@ jobs: java-version: 21 distribution: temurin - - name: Gradle (Setup) - uses: gradle/actions/setup-gradle@v4 + - name: Grant execute permission for gradlew + run: chmod +x gradlew with: dependency-graph: generate-and-submit From 806cfe8f4636f58bda151ee8f410a3fcafb9b54f Mon Sep 17 00:00:00 2001 From: jansel Date: Sat, 14 Jun 2025 23:42:55 +0200 Subject: [PATCH 68/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 8667e10..6c7ee3a 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -9,16 +9,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: https://github.com/actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: https://github.com/docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: https://github.com/docker/setup-buildx-action@v3 - name: Set up Java - uses: actions/setup-java@v4 + uses: https://github.com/actions/setup-java@v4 with: java-version: 21 @@ -39,7 +39,7 @@ jobs: run: "./gradlew build" - name: Login to DigitalOcean Registry - uses: docker/login-action@v3 + uses: https://github.com/docker/login-action@v3 with: registry: registry.digitalocean.com @@ -47,7 +47,7 @@ jobs: password: ${{ secrets.DOKEY }} - name: Build and push - uses: docker/build-push-action@v5 + uses: https://github.com/docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64 From f162ef0d7ead56b625cf568369b6f3fc563fd498 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 21:05:59 +0000 Subject: [PATCH 69/93] Add renovate.json --- renovate.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..344c613 --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json" +} From 62ccfcd8bf082323f5f76ead2e1be581317cd0ba Mon Sep 17 00:00:00 2001 From: jansel Date: Sun, 15 Jun 2025 23:08:06 +0200 Subject: [PATCH 70/93] Update .github/workflows/root.yml --- .github/workflows/root.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 6c7ee3a..1db3a29 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -3,6 +3,8 @@ name: Build & Publish on: workflow_dispatch: push: + branches: + - root jobs: build: From 8b6f60c1ea2d145c58165bf238a843e7a846e992 Mon Sep 17 00:00:00 2001 From: jansel Date: Sun, 15 Jun 2025 23:13:01 +0200 Subject: [PATCH 71/93] Update renovate.json --- renovate.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/renovate.json b/renovate.json index 344c613..5fecc42 100644 --- a/renovate.json +++ b/renovate.json @@ -1,3 +1,11 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json" -} + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ], + "packageRules": [ + { + "matchUpdateTypes": ["minor", "patch"] + } + ] +} \ No newline at end of file From e2651e17f2b79e2288eb78f225cf33989eb8c8b0 Mon Sep 17 00:00:00 2001 From: jansel Date: Sun, 15 Jun 2025 23:19:20 +0200 Subject: [PATCH 72/93] [skip ci] update --- renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 5fecc42..d822bf8 100644 --- a/renovate.json +++ b/renovate.json @@ -7,5 +7,6 @@ { "matchUpdateTypes": ["minor", "patch"] } - ] + ], + "prHourlyLimit": 0 } \ No newline at end of file From 089f09031ea0196402984c83dfcf58e6fe778e23 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 21:39:06 +0000 Subject: [PATCH 73/93] Update dependency org.jetbrains.kotlinx:kotlinx-serialization-core to v1.8.1 --- 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 f34741c..635e4f7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.1.0" # Note: Plugin versions must be updated in the settings.gradle groovy = "3.0.23" jansi = "2.4.1" -kx-ser = "1.7.3" +kx-ser = "1.8.1" logback = "1.5.12" logback-groovy = "1.14.5" logging = "7.0.3" From b6f0209529a1333c554a40fb53f1366fdf61560f Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 21:38:46 +0000 Subject: [PATCH 74/93] Update dependency gradle to v8.14.2 --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43705 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- gradlew.bat | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a2ead66..56d7e6a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,6 @@ docker { } tasks.wrapper { - gradleVersion = "8.13" + gradleVersion = "8.14.2" distributionType = Wrapper.DistributionType.BIN } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 9bbc975c742b298b441bfb90dbc124400a3751b9..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 642 zcmdmamFde>rVZJA^}0Q$xegf!xPEW^+5YDM%iT2bEgct9o+jH~+sJas#HZ=szO|** z=Pj=X_vx?W&DSwKck|WWn~hffsvnQ+42*W$b7b0$SCcOoZ`{W{^$^pk;4>8-A*-)$ z?n(Po`1$6Jn_u?t-L+tsPyZ2#X}8T6OS8pAU;kdgd+_Hw4z4TW0p9E!T+=f7-c&O% zFic^X{7^$?^Ho04eona9n#mGMxKhA=~8B%JN`M zMhm5wc-2v)$``sY$!Q`9xiU@DhI73ZxiGEKg>yIPs)NmWwMdF-ngLXpZSqV5ez36n zVkxF2rjrjWR+_xr6e6@_u@s~2uv{9vi*1pj2)BjFD+-%@&pRVP1f{O1glxTOp2-62Ph;v z`N1+vCd)9ea)af*Ol1*JCfnp$%Uu}%OuoN7g2}3C@`L5FlP#(sA=|h@iixuZC?qp^ z=L$=v$ZoI}|87Wh=&h7udff{aieKr*l+zDp?pf)_bbRvUf>kn;HCDMXNlgbbo!QRK I1x7am0No)LiU0rr delta 584 zcmexzm1*ZyrVZJAexH5Moc8h7)w{^+t*dqJ%=yhh23L$9JpFV=_k`zJ-?Q4DI*eSe z+ES)HSrVnWLtJ&)lO%hRkV9zl5qqWRt0e;bb zPPo`)y?HTAyZI&u&X<|2$FDHCf4;!v8}p=?Tm`^F0`u(|1ttf~&t$qP3KUSD>@TJQ zRwJ}Pim6NzEc8KA6)e;S6gs8=7IIL8sQL*MYEuRYO;Uj<%3UbMbV&^&!Zvx+LKmjT z8Zch6rYP7Tw?$Hn(UTJwWiS=$f{lB(C=e*%usDV})0AQIK~sat=ND@+Gg*Pyij!rR z*fa02W|%BsV++>4W{DKDGSIUEHd2$P+8ct!RF+CHDowUuTEZOZ%rJSQv*qOXOSPDN zT|sP-$p*_3ncsWB*qoD7JQcyZ9xan%cJP6Tb4-?AZpr*F6v98hoNaPJm@HV`yya5N z))6pqFXn@}P(3T0nEzM8*c_9KtE9o|_pFd&K35GBXP^9Kg(b6GH-z8S4GDzIl~T+b zdLd#meKKHu$5u))8cu$=GKINkGDPOUD)!0$C(BH(U!}!-e;Q0ok8Sc?V1zRO04>ts AA^-pY diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37f853b..ff23a68 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.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index faf9300..23d15a9 100755 --- a/gradlew +++ b/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..db3a6ac 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From ec202e631b5de4e411b688ca10efb2d1a7e926cc Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 21:39:14 +0000 Subject: [PATCH 75/93] Update dependency org.litote.kmongo:kmongo-coroutine-serialization to v5.2.1 --- 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 635e4f7..91d26e0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ logging = "7.0.3" twitch4j = "1.24.0" events4j = "0.12.2" kx-coroutines = "1.9.0" -kmongo = "5.1.0" +kmongo = "5.2.1" [libraries] groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" } From 080234fa0a578b5c38f1d5e5963999141009c2cf Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 21:21:35 +0000 Subject: [PATCH 76/93] Update kotlin monorepo to v2.1.21 --- settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index a461b7e..34e8233 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,8 @@ pluginManagement { plugins { // Update this in libs.version.toml when you change it here. - kotlin("jvm") version "2.1.0" - kotlin("plugin.serialization") version "2.1.0" + kotlin("jvm") version "2.1.21" + kotlin("plugin.serialization") version "2.1.21" id("com.github.johnrengelman.shadow") version "8.1.1" From b6016939053f00ab53ae3d5872d3eb2edfa0f55d Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 21:37:43 +0000 Subject: [PATCH 77/93] Update dependency com.github.twitch4j:twitch4j to v1.25.0 --- 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 91d26e0..c5c68e2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kx-ser = "1.8.1" logback = "1.5.12" logback-groovy = "1.14.5" logging = "7.0.3" -twitch4j = "1.24.0" +twitch4j = "1.25.0" events4j = "0.12.2" kx-coroutines = "1.9.0" kmongo = "5.2.1" From 91cf4d260834084b6dec021ec26da266b2ccd06a Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 22:02:09 +0000 Subject: [PATCH 78/93] Update dependency ch.qos.logback:logback-classic to v1.5.18 --- 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 c5c68e2..467a72e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ kotlin = "2.1.0" # Note: Plugin versions must be updated in the settings.gradle groovy = "3.0.23" jansi = "2.4.1" kx-ser = "1.8.1" -logback = "1.5.12" +logback = "1.5.18" logback-groovy = "1.14.5" logging = "7.0.3" twitch4j = "1.25.0" From add22d993c90b5b23a626149908cc4cedec87881 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 22:02:25 +0000 Subject: [PATCH 79/93] Update dependency io.github.oshai:kotlin-logging to v7.0.7 --- 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 c5c68e2..4e9a855 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ jansi = "2.4.1" kx-ser = "1.8.1" logback = "1.5.12" logback-groovy = "1.14.5" -logging = "7.0.3" +logging = "7.0.7" twitch4j = "1.25.0" events4j = "0.12.2" kx-coroutines = "1.9.0" From b2db4cdfc333f194d34959e02d09ccadb49d3661 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 22:02:45 +0000 Subject: [PATCH 80/93] Update dependency org.fusesource.jansi:jansi to v2.4.2 --- 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 c5c68e2..3b26729 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.1.0" # Note: Plugin versions must be updated in the settings.gradle.kts too groovy = "3.0.23" -jansi = "2.4.1" +jansi = "2.4.2" kx-ser = "1.8.1" logback = "1.5.12" logback-groovy = "1.14.5" From 700a2410ef2f30b1f4d8f4407b055850f3b69409 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 22:02:50 +0000 Subject: [PATCH 81/93] Update dependency org.jetbrains.kotlinx:kotlinx-coroutines-core to v1.10.2 --- 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 c5c68e2..ef60613 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ logback-groovy = "1.14.5" logging = "7.0.3" twitch4j = "1.25.0" events4j = "0.12.2" -kx-coroutines = "1.9.0" +kx-coroutines = "1.10.2" kmongo = "5.2.1" [libraries] From 881298dd15c634ca57f3665fdfbb0966b730e0b8 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 22:02:56 +0000 Subject: [PATCH 82/93] Update plugin dev.kordex.gradle.docker to v1.7.1 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 34e8233..a883090 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,7 +6,7 @@ pluginManagement { id("com.github.johnrengelman.shadow") version "8.1.1" - id("dev.kordex.gradle.docker") version "1.6.2" + id("dev.kordex.gradle.docker") version "1.7.1" id("dev.kordex.gradle.kordex") version "1.6.2" } repositories { From b19242fc8a5d6242f3ad20ac5e63d208a271dda9 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 15 Jun 2025 22:03:09 +0000 Subject: [PATCH 83/93] Update https://github.com/docker/build-push-action action to v6 --- .github/workflows/root.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 1db3a29..dcfceb0 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -49,7 +49,7 @@ jobs: password: ${{ secrets.DOKEY }} - name: Build and push - uses: https://github.com/docker/build-push-action@v5 + uses: https://github.com/docker/build-push-action@v6 with: context: . platforms: linux/amd64,linux/arm64 From f67b01601412e9007108ffc4d092754888762abd Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 16 Jun 2025 00:01:02 +0000 Subject: [PATCH 84/93] Update dependency org.codehaus.groovy:groovy to v3.0.25 --- 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 3215992..ecd302d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.1.0" # Note: Plugin versions must be updated in the settings.gradle.kts too -groovy = "3.0.23" +groovy = "3.0.25" jansi = "2.4.2" kx-ser = "1.8.1" logback = "1.5.18" From adb69e1f1f1835a22c6b54f230cd2b543003dd6f Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 16 Jun 2025 00:01:10 +0000 Subject: [PATCH 85/93] Update plugin dev.kordex.gradle.kordex to v1.7.1 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index a883090..9eba578 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { id("com.github.johnrengelman.shadow") version "8.1.1" id("dev.kordex.gradle.docker") version "1.7.1" - id("dev.kordex.gradle.kordex") version "1.6.2" + id("dev.kordex.gradle.kordex") version "1.7.1" } repositories { gradlePluginPortal() From 32208e049673831c785da767bb6724abdb5b68b9 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 16 Jun 2025 00:01:13 +0000 Subject: [PATCH 86/93] Migrate config renovate.json --- renovate.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/renovate.json b/renovate.json index d822bf8..e655623 100644 --- a/renovate.json +++ b/renovate.json @@ -1,12 +1,15 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base" + "config:recommended" ], "packageRules": [ { - "matchUpdateTypes": ["minor", "patch"] + "matchUpdateTypes": [ + "minor", + "patch" + ] } ], "prHourlyLimit": 0 -} \ No newline at end of file +} From bf93c329b7b296b79c51633094697cdd52be967e Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 02:20:25 +0200 Subject: [PATCH 87/93] finish dependency update, also use the newer docker file template haha --- .idea/kotlinc.xml | 2 +- build.gradle.kts | 71 ++++++++++++++++++++++++++++----------- gradle/libs.versions.toml | 11 +++++- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index bb44937..1e16934 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 56d7e6a..1dff957 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,17 +2,17 @@ import dev.kordex.gradle.plugins.docker.file.* import dev.kordex.gradle.plugins.kordex.DataCollection plugins { - kotlin("jvm") - kotlin("plugin.serialization") + distribution - id("com.github.johnrengelman.shadow") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.serialization) - id("dev.kordex.gradle.docker") - id("dev.kordex.gradle.kordex") + alias(libs.plugins.kordex.plugin) + alias(libs.plugins.kordex.docker) } group = "dev.jansel" -version = "1.1-SNAPSHOT" +version = "1.2-SNAPSHOT" dependencies { @@ -31,9 +31,26 @@ dependencies { implementation(libs.logging) } +// Configure distributions plugin +distributions { + main { + distributionBaseName = project.name + + contents { + // Copy the LICENSE file into the distribution + from("LICENSE") + + // Exclude src/main/dist/README.md + exclude("README.md") + } + } +} + + kordEx { kordExVersion = "2.3.1-SNAPSHOT" jvmTarget = 21 + ignoreIncompatibleKotlinVersion = true bot { // See https://docs.kordex.dev/data-collection.html @@ -58,37 +75,51 @@ docker { // Each function (aside from comment/emptyLine) corresponds to a Dockerfile instruction. // See: https://docs.docker.com/reference/dockerfile/ - from("azul/zulu-openjdk-alpine:21-jre-headless-latest") + from("openjdk:21-jdk-slim") emptyLine() + comment("Create required directories") runShell("mkdir -p /bot/plugins") runShell("mkdir -p /bot/data") - - emptyLine() - - copy("build/libs/$name-*-all.jar", "/bot/bot.jar") + runShell("mkdir -p /dist/out") emptyLine() // Add volumes for locations that you need to persist. This is important! + comment("Declare required volumes") volume("/bot/data") // Storage for data files volume("/bot/plugins") // Plugin ZIP/JAR location emptyLine() + comment("Copy the distribution files into the container") + copy("build/distributions/${project.name}-${project.version}.tar", "/dist") + + emptyLine() + + comment("Extract the distribution files, and prepare them for use") + runShell("tar -xf /dist/${project.name}-${project.version}.tar -C /dist/out") + + if (file("src/main/dist/plugins").isDirectory) { + runShell("mv /dist/out/${project.name}-${project.version}/plugins/* /bot/plugins") + } + + runShell("chmod +x /dist/out/${project.name}-${project.version}/bin/$name") + + emptyLine() + + comment("Clean up unnecessary files") + runShell("rm /dist/${project.name}-${project.version}.tar") + + emptyLine() + + comment("Set the correct working directory") workdir("/bot") emptyLine() - entryPointExec( - "java", "-Xmx2G", - "-jar", "/bot/bot.jar" - ) + comment("Run the distribution start script") + entryPointExec("/dist/out/${project.name}-${project.version}/bin/$name") } } - -tasks.wrapper { - gradleVersion = "8.14.2" - distributionType = Wrapper.DistributionType.BIN -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ecd302d..4766e0d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.1.0" # Note: Plugin versions must be updated in the settings.gradle.kts too +kotlin = "2.1.21" # Note: Plugin versions must be updated in the settings.gradle.kts too groovy = "3.0.25" jansi = "2.4.2" @@ -11,6 +11,7 @@ twitch4j = "1.25.0" events4j = "0.12.2" kx-coroutines = "1.10.2" kmongo = "5.2.1" +kordex-gradle = "1.7.1" [libraries] groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" } @@ -24,3 +25,11 @@ logging = { module = "io.github.oshai:kotlin-logging", version.ref = "logging" } twitch4j = { module = "com.github.twitch4j:twitch4j", version.ref = "twitch4j" } events4j = { module = "com.github.philippheuer.events4j:events4j-handler-reactor", version.ref = "events4j" } kmongo = { module="org.litote.kmongo:kmongo-coroutine-serialization", version.ref = "kmongo" } + + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } + +kordex-docker = { id = "dev.kordex.gradle.docker", version.ref = "kordex-gradle" } +kordex-plugin = { id = "dev.kordex.gradle.kordex", version.ref = "kordex-gradle" } From 4d5ba6754a0f5c1c95c5e2fe0698cd01adc31496 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 12:40:46 +0200 Subject: [PATCH 88/93] [skip ci] remove plugins from settings.gradle.kts --- settings.gradle.kts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 9eba578..ebc20a7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,14 +1,4 @@ pluginManagement { - plugins { - // Update this in libs.version.toml when you change it here. - kotlin("jvm") version "2.1.21" - kotlin("plugin.serialization") version "2.1.21" - - id("com.github.johnrengelman.shadow") version "8.1.1" - - id("dev.kordex.gradle.docker") version "1.7.1" - id("dev.kordex.gradle.kordex") version "1.7.1" - } repositories { gradlePluginPortal() mavenCentral() From 3b292d6ddde5902d47f30f8249c4b1d4815e9bd2 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 12:43:35 +0200 Subject: [PATCH 89/93] [skip ci] move privacy-policy.md and terms-of-service.md into the root --- docs/privacy-policy.md => privacy-policy.md | 0 docs/terms-of-service.md => terms-of-service.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename docs/privacy-policy.md => privacy-policy.md (100%) rename docs/terms-of-service.md => terms-of-service.md (100%) diff --git a/docs/privacy-policy.md b/privacy-policy.md similarity index 100% rename from docs/privacy-policy.md rename to privacy-policy.md diff --git a/docs/terms-of-service.md b/terms-of-service.md similarity index 100% rename from docs/terms-of-service.md rename to terms-of-service.md From 8b49b19b1a8f27cabb55cb900fb9c2fc50dec5f6 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 17:46:48 +0200 Subject: [PATCH 90/93] test caching --- .github/workflows/root.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index dcfceb0..fe74e10 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: https://github.com/actions/checkout@v4 - + - name: Set up QEMU uses: https://github.com/docker/setup-qemu-action@v3 @@ -26,6 +26,14 @@ jobs: java-version: 21 distribution: temurin + - name: "Restore Cache" + id: restore-cache + uses: https://data.forgejo.org/actions/cache/restore@v4 + + with: + path: "~/.gradle/caches,~/.gradle/wrapper,~/.m2/repository" + key: gradle-store + - name: Grant execute permission for gradlew run: chmod +x gradlew @@ -55,3 +63,10 @@ jobs: platforms: linux/amd64,linux/arm64 push: true tags: registry.digitalocean.com/jansel/feixiao:latest,registry.digitalocean.com/jansel/feixiao:${{ steps.date.outputs.date }} + + - name: "Save Cache" + uses: https://data.forgejo.org/actions/cache/save@v4 + + with: + path: ~/.gradle/caches,~/.gradle/wrapper,~/.m2/repository + key: ${{ steps.restore-cache.outputs.cache-primary-key }} From fa8dd0ab140759584c230dc2f00fb719b0f36c38 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 17:50:30 +0200 Subject: [PATCH 91/93] remove cache from qemu action --- .github/workflows/root.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index fe74e10..e796d97 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -15,6 +15,8 @@ jobs: - name: Set up QEMU uses: https://github.com/docker/setup-qemu-action@v3 + with: + cache-image: false - name: Set up Docker Buildx uses: https://github.com/docker/setup-buildx-action@v3 From 95dc9bffdc8d0f61f78f8d474d90e0ac8df8d53e Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 18:03:27 +0200 Subject: [PATCH 92/93] test again --- .github/workflows/root.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index e796d97..872e5fc 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -33,7 +33,10 @@ jobs: uses: https://data.forgejo.org/actions/cache/restore@v4 with: - path: "~/.gradle/caches,~/.gradle/wrapper,~/.m2/repository" + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.m2/repository key: gradle-store - name: Grant execute permission for gradlew @@ -70,5 +73,8 @@ jobs: uses: https://data.forgejo.org/actions/cache/save@v4 with: - path: ~/.gradle/caches,~/.gradle/wrapper,~/.m2/repository + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.m2/repository key: ${{ steps.restore-cache.outputs.cache-primary-key }} From fd2eafac95d3b80db8fb54640c76f52338442ea8 Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Mon, 16 Jun 2025 18:28:37 +0200 Subject: [PATCH 93/93] test again --- .github/workflows/root.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 872e5fc..2ebd1de 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -11,7 +11,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: https://github.com/actions/checkout@v4 + - name: Checkout code + uses: https://github.com/actions/checkout@v4 - name: Set up QEMU uses: https://github.com/docker/setup-qemu-action@v3