From 1bb46e3a718f146ac094b85c57c6db82fbd47419 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:10:51 +0100 Subject: [PATCH] Got 3rd party dependencies working in development mode --- .gitignore | 1 + build.gradle.kts | 4 -- gameyfin/build.gradle.kts | 26 ------------- .../core/plugins/PluginManagerConfig.kt | 4 +- .../gameyfin/logs/util/AsyncFileTailer.kt | 4 +- plugin-api/build.gradle.kts | 4 +- .../gameyfin/pluginapi/core/GameyfinPlugin.kt | 5 +++ .../pluginapi/core/PluginConfigError.kt | 3 ++ .../gameyfin/pluginapi/core/PluginContext.kt | 9 +++++ .../gamemetadata/GameMetadataFetcher.kt | 2 - plugins/build.gradle.kts | 38 +++++++------------ plugins/igdb/build.gradle.kts | 24 ++++++++++++ .../gameyfin/plugins/igdb/IgdbPlugin.kt | 38 ++++++++++++++----- .../gameyfin/plugins/igdb/IgdbPluginConfig.kt | 6 +++ .../plugins/igdb/dto/TwitchOAuthTokenDto.kt | 7 ++++ 15 files changed, 104 insertions(+), 71 deletions(-) create mode 100644 plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/GameyfinPlugin.kt create mode 100644 plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginConfigError.kt create mode 100644 plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginContext.kt create mode 100644 plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPluginConfig.kt create mode 100644 plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/dto/TwitchOAuthTokenDto.kt diff --git a/.gitignore b/.gitignore index 7933b50..1a1f636 100644 --- a/.gitignore +++ b/.gitignore @@ -45,5 +45,6 @@ docker-compose.yml generated db data +packaged_plugins logs templates diff --git a/build.gradle.kts b/build.gradle.kts index a9bf26e..0190f5d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,8 +32,4 @@ subprojects { } } -tasks.named("build") { - dependsOn(":gameyfin:uberJar") -} - extra.set("pluginDir", rootProject.layout.buildDirectory.get().asFile.resolve("plugins")) \ No newline at end of file diff --git a/gameyfin/build.gradle.kts b/gameyfin/build.gradle.kts index 0679649..d3fe842 100644 --- a/gameyfin/build.gradle.kts +++ b/gameyfin/build.gradle.kts @@ -1,5 +1,4 @@ group = "de.grimsi" -val pluginDir: File by rootProject.extra val appMainClass = "de.grimsi.gameyfin.GameyfinApplication" plugins { @@ -86,31 +85,6 @@ dependencyManagement { } } -tasks.named("run") { - systemProperty("pf4j.pluginsDir", pluginDir.absolutePath) -} - -tasks.register("uberJar") { - dependsOn(tasks.named("compileKotlin")) - archiveClassifier.set("uber") - - from(sourceSets.main.get().output) - - dependsOn(configurations.runtimeClasspath) - from({ - configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) } - }) - - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - isZip64 = true - - manifest { - attributes["Main-Class"] = appMainClass - } - - archiveBaseName.set(project.name) -} - tasks.withType { useJUnitPlatform() } \ No newline at end of file diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginManagerConfig.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginManagerConfig.kt index f9932b4..5e919d2 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginManagerConfig.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginManagerConfig.kt @@ -10,10 +10,10 @@ import java.nio.file.Path @Configuration class PluginManagerConfig { private val log = KotlinLogging.logger {} - private val pluginPath = Path.of("plugins") + private val pluginPath = System.getProperty("pf4j.pluginsDir", "plugins") @Bean - fun pluginManager() = SpringDevtoolsPluginManager(pluginPath) + fun pluginManager() = SpringDevtoolsPluginManager(Path.of(pluginPath)) @EventListener(ApplicationReadyEvent::class) fun loadedPlugins() { diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/logs/util/AsyncFileTailer.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/logs/util/AsyncFileTailer.kt index 4a3c342..77018ec 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/logs/util/AsyncFileTailer.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/logs/util/AsyncFileTailer.kt @@ -48,7 +48,7 @@ class AsyncFileTailer( tailer.run() } - log.info { "Started tailing the file: ${file.name}" } + log.debug { "Started tailing the file: ${file.name}" } } else { log.error { "File tailing for file ${file.name} is already running!" } } @@ -58,7 +58,7 @@ class AsyncFileTailer( tailerJob?.let { it.cancel() tailerJob = null - log.info { "Stopped tailing the file: ${file.name}" } + log.debug { "Stopped tailing the file: ${file.name}" } } } } \ No newline at end of file diff --git a/plugin-api/build.gradle.kts b/plugin-api/build.gradle.kts index 48a1835..96f562a 100644 --- a/plugin-api/build.gradle.kts +++ b/plugin-api/build.gradle.kts @@ -10,7 +10,9 @@ repositories { dependencies { // PF4J (shared) - api("org.pf4j:pf4j:${rootProject.extra["pf4jVersion"]}") + api("org.pf4j:pf4j:${rootProject.extra["pf4jVersion"]}") { + exclude(group = "org.slf4j") + } implementation(kotlin("stdlib")) diff --git a/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/GameyfinPlugin.kt b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/GameyfinPlugin.kt new file mode 100644 index 0000000..3496eac --- /dev/null +++ b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/GameyfinPlugin.kt @@ -0,0 +1,5 @@ +package de.grimsi.gameyfin.pluginapi.core + +import org.pf4j.Plugin + +abstract class GameyfinPlugin(protected val context: PluginContext) : Plugin() \ No newline at end of file diff --git a/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginConfigError.kt b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginConfigError.kt new file mode 100644 index 0000000..c461e7c --- /dev/null +++ b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginConfigError.kt @@ -0,0 +1,3 @@ +package de.grimsi.gameyfin.pluginapi.core + +class PluginConfigError(message: String) : RuntimeException(message) \ No newline at end of file diff --git a/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginContext.kt b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginContext.kt new file mode 100644 index 0000000..bf96ba6 --- /dev/null +++ b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/core/PluginContext.kt @@ -0,0 +1,9 @@ +package de.grimsi.gameyfin.pluginapi.core + +import org.pf4j.RuntimeMode + +class PluginContext(private val runtimeMode: RuntimeMode) { + fun getRuntimeMode(): RuntimeMode { + return runtimeMode + } +} \ No newline at end of file diff --git a/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/gamemetadata/GameMetadataFetcher.kt b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/gamemetadata/GameMetadataFetcher.kt index 8d55f32..e699202 100644 --- a/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/gamemetadata/GameMetadataFetcher.kt +++ b/plugin-api/src/main/kotlin/de/grimsi/gameyfin/pluginapi/gamemetadata/GameMetadataFetcher.kt @@ -3,7 +3,5 @@ package de.grimsi.gameyfin.pluginapi.gamemetadata import org.pf4j.ExtensionPoint interface GameMetadataFetcher : ExtensionPoint { - fun getConfig(): Map - fun setConfig(config: Map) fun fetchMetadata(gameId: String): GameMetadata } \ No newline at end of file diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts index 0135936..12af4f6 100644 --- a/plugins/build.gradle.kts +++ b/plugins/build.gradle.kts @@ -11,36 +11,26 @@ subprojects { implementation(project(":plugin-api")) } - tasks.register("plugin") { - archiveBaseName.set("plugin-${project.name}") - - // first taking the classes generated by the jar task - into("classes") { - with(tasks.named("jar").get()) - } - // and then we also need to include any libraries that are needed by the plugin - dependsOn(configurations.runtimeClasspath) - into("lib") { - from({ - configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") } - }) - } - archiveExtension.set("jar") - } - - tasks.register("assemblePlugin") { - from(project.tasks.named("plugin")) - into(pluginDir) - } - tasks.jar { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + isZip64 = true + archiveBaseName.set("plugin-${project.name}") manifest { from("./src/main/resources/MANIFEST.MF") } + + from(configurations.runtimeClasspath.get().map { project.zipTree(it) }) { + exclude("META-INF/*.SF") + exclude("META-INF/*.DSA") + exclude("META-INF/*.RSA") + } + from(sourceSets["main"].output.classesDirs) + from(sourceSets["main"].resources) } - tasks.named("build") { - dependsOn(tasks.named("plugin")) + tasks.register("assemblePlugin") { + from(project.tasks.jar) + into(pluginDir) } } diff --git a/plugins/igdb/build.gradle.kts b/plugins/igdb/build.gradle.kts index 6f15a8b..9533046 100644 --- a/plugins/igdb/build.gradle.kts +++ b/plugins/igdb/build.gradle.kts @@ -3,5 +3,29 @@ plugins { } dependencies { + // Kotlin annotation processor ksp("care.better.pf4j:pf4j-kotlin-symbol-processing:2.0.20-1.0.1") + + // IGDB API client + implementation("io.github.husnjak:igdb-api-jvm:1.2.0") + + compileOnly("org.slf4j:slf4j-api:2.0.16") +} + +tasks.register("copyDependencyClasses") { + dependsOn(tasks.jar) + + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + from(configurations.runtimeClasspath.get().map { project.zipTree(it) }) { + include("**/*.class") + } + from("src/main/resources/MANIFEST.MF") { + into("META-INF") + } + into(layout.buildDirectory.get().asFile.resolve("classes/kotlin/main")) +} + +tasks.build { + dependsOn("copyDependencyClasses") } \ No newline at end of file diff --git a/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPlugin.kt b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPlugin.kt index 78dd4bd..513efff 100644 --- a/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPlugin.kt +++ b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPlugin.kt @@ -1,5 +1,8 @@ package de.grimsi.gameyfin.plugins.igdb +import com.api.igdb.request.IGDBWrapper +import com.api.igdb.request.TwitchAuthenticator +import de.grimsi.gameyfin.pluginapi.core.PluginConfigError import de.grimsi.gameyfin.pluginapi.gamemetadata.GameMetadata import de.grimsi.gameyfin.pluginapi.gamemetadata.GameMetadataFetcher import org.pf4j.Extension @@ -9,24 +12,39 @@ import java.time.Instant class IgdbPlugin(wrapper: PluginWrapper) : Plugin(wrapper) { + companion object { + val config: IgdbPluginConfig = IgdbPluginConfig(null, null) + } + override fun start() { - println("IgdbPlugin.start()") + authenticate() } override fun stop() { - println("IgdbPlugin.stop()") + log.debug("IgdbPlugin.stop()") + } + + private fun authenticate() { + log.debug("Authenticating on Twitch API...") + + // FIXME: This should be read from the config + val clientId = "8nrnjn74x1oa7of2g8sg4voy2lapml" + // FIXME: This should be read from the config + val clientSecret = "pyrvg3sdduxjg4qxidra9237xj17yn" + + // val clientId: String = config.clientId ?: throw PluginConfigError("Twitch Client ID not set") + // val clientSecret: String = config.clientSecret ?: throw PluginConfigError("Twitch Client Secret not set") + + val token = TwitchAuthenticator.requestTwitchToken(clientId, clientSecret) + ?: throw PluginConfigError("Failed to authenticate on Twitch API") + + IGDBWrapper.setCredentials(clientId, token.access_token) + + log.debug("Authentication successful") } @Extension class IgdbMetadataFetcher : GameMetadataFetcher { - override fun getConfig(): Map { - TODO("Not yet implemented") - } - - override fun setConfig(config: Map) { - TODO("Not yet implemented") - } - override fun fetchMetadata(gameId: String): GameMetadata { return GameMetadata( title = "Test Game", diff --git a/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPluginConfig.kt b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPluginConfig.kt new file mode 100644 index 0000000..29957d7 --- /dev/null +++ b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/IgdbPluginConfig.kt @@ -0,0 +1,6 @@ +package de.grimsi.gameyfin.plugins.igdb + +data class IgdbPluginConfig( + val clientId: String?, + val clientSecret: String? +) \ No newline at end of file diff --git a/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/dto/TwitchOAuthTokenDto.kt b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/dto/TwitchOAuthTokenDto.kt new file mode 100644 index 0000000..bc7bf3e --- /dev/null +++ b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/dto/TwitchOAuthTokenDto.kt @@ -0,0 +1,7 @@ +package de.grimsi.gameyfin.plugins.igdb.dto + +data class TwitchOAuthTokenDto( + val accessToken: String, + val expiresIn: Int, + val tokenType: String +) \ No newline at end of file