From 34f00c091f2534aab9e79ded193d2344d6c0e9f2 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:33:35 +0100 Subject: [PATCH] Finish plugin support implementation Small refactoring --- .../administration/PluginManagement.tsx | 76 +++++-------------- .../components/general/AssignRolesModal.tsx | 6 +- .../general/ConfirmUserDeletionModal.tsx | 6 +- .../components/general/InviteUserModal.tsx | 5 +- .../general/PasswortResetTokenModal.tsx | 6 +- .../general/PluginConfigurationModal.tsx | 75 ++++++++++++++++++ .../general/PluginManagementCard.tsx | 50 ++++++++++++ .../{ => config}/PluginConfigEndpoint.kt | 2 +- .../plugins/{ => config}/PluginConfigEntry.kt | 2 +- .../{ => config}/PluginConfigRepository.kt | 2 +- .../{ => config}/PluginConfigService.kt | 10 ++- .../{ => management}/GameyfinPluginLoader.kt | 2 +- .../{ => management}/GameyfinPluginManager.kt | 3 +- .../core/plugins/management/PluginDto.kt | 11 +++ .../management/PluginManagementEndpoint.kt | 19 +++++ .../management/PluginManagementService.kt | 32 ++++++++ .../{ => management}/PluginManagerConfig.kt | 3 +- .../gameyfin/plugins/igdb/IgdbPlugin.kt | 72 +----------------- .../de/grimsi/gameyfin/plugins/igdb/Mapper.kt | 74 ++++++++++++++++++ .../plugins/igdb/dto/TwitchOAuthTokenDto.kt | 7 -- plugins/igdb/src/main/resources/MANIFEST.MF | 5 +- 21 files changed, 305 insertions(+), 163 deletions(-) create mode 100644 gameyfin/src/main/frontend/components/general/PluginConfigurationModal.tsx create mode 100644 gameyfin/src/main/frontend/components/general/PluginManagementCard.tsx rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => config}/PluginConfigEndpoint.kt (94%) rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => config}/PluginConfigEntry.kt (94%) rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => config}/PluginConfigRepository.kt (86%) rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => config}/PluginConfigService.kt (71%) rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => management}/GameyfinPluginLoader.kt (92%) rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => management}/GameyfinPluginManager.kt (95%) create mode 100644 gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginDto.kt create mode 100644 gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementEndpoint.kt create mode 100644 gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementService.kt rename gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/{ => management}/PluginManagerConfig.kt (88%) create mode 100644 plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/Mapper.kt delete mode 100644 plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/dto/TwitchOAuthTokenDto.kt diff --git a/gameyfin/src/main/frontend/components/administration/PluginManagement.tsx b/gameyfin/src/main/frontend/components/administration/PluginManagement.tsx index 338e47d..ce78a5c 100644 --- a/gameyfin/src/main/frontend/components/administration/PluginManagement.tsx +++ b/gameyfin/src/main/frontend/components/administration/PluginManagement.tsx @@ -1,69 +1,29 @@ import React, {useEffect, useState} from "react"; -import Section from "Frontend/components/general/Section"; -import {PluginConfigEndpoint} from "Frontend/generated/endpoints"; -import {Form, Formik} from "formik"; -import {Check} from "@phosphor-icons/react"; -import {Button} from "@nextui-org/react"; -import Input from "Frontend/components/general/Input"; +import {PluginManagementEndpoint} from "Frontend/generated/endpoints"; +import PluginDto from "Frontend/generated/de/grimsi/gameyfin/core/plugins/management/PluginDto"; +import {PluginManagementCard} from "Frontend/components/general/PluginManagementCard"; +import {Divider} from "@nextui-org/react"; export default function PluginManagement() { - const [configSaved, setConfigSaved] = useState(false); - const [igdbConfigMeta, setIgdbConfigMeta] = useState(); - const [igdbConfig, setIgdbConfig] = useState(); + const [plugins, setPlugins] = useState([]); useEffect(() => { - PluginConfigEndpoint.getConfigMetadata("igdb").then(setIgdbConfigMeta); - PluginConfigEndpoint.getConfig("igdb").then(setIgdbConfig); + PluginManagementEndpoint.getPlugins().then((response) => { + if (response === undefined) return; + setPlugins(response as PluginDto[]); + }); }, []); - useEffect(() => { - if (configSaved) { - setTimeout(() => setConfigSaved(false), 2000); - } - }, [configSaved]) - - async function handleSubmit(values: any) { - await PluginConfigEndpoint.setConfigEntries("igdb", values); - setConfigSaved(true); - } - return ( - <> - - {(formik: { values: any; isSubmitting: any; }) => ( -
-
-

Plugins

-
- -
-
+
+
+

Plugins

+
-
-
-
- {igdbConfigMeta && igdbConfigMeta.map((entry: any) => ( - - ))} -
-
- - )} - - + +
+ {plugins.map((plugin) => )} +
+
); } \ No newline at end of file diff --git a/gameyfin/src/main/frontend/components/general/AssignRolesModal.tsx b/gameyfin/src/main/frontend/components/general/AssignRolesModal.tsx index 04dd619..c95e495 100644 --- a/gameyfin/src/main/frontend/components/general/AssignRolesModal.tsx +++ b/gameyfin/src/main/frontend/components/general/AssignRolesModal.tsx @@ -26,11 +26,7 @@ interface Role { id: string; } -export default function AssignRolesModal({ - isOpen, - onOpenChange, - user - }: AssignRolesModalProps) { +export default function AssignRolesModal({isOpen, onOpenChange, user}: AssignRolesModalProps) { const [availableRoles, setAvailableRoles] = useState([]); const [selectedRole, setSelectedRole] = useState(); const [error, setError] = useState(); diff --git a/gameyfin/src/main/frontend/components/general/ConfirmUserDeletionModal.tsx b/gameyfin/src/main/frontend/components/general/ConfirmUserDeletionModal.tsx index 207f24a..bb3579c 100644 --- a/gameyfin/src/main/frontend/components/general/ConfirmUserDeletionModal.tsx +++ b/gameyfin/src/main/frontend/components/general/ConfirmUserDeletionModal.tsx @@ -9,11 +9,7 @@ interface ConfirmUserDeletionModalProps { user: UserInfoDto; } -export default function ConfirmUserDeletionModal({ - isOpen, - onOpenChange, - user - }: ConfirmUserDeletionModalProps) { +export default function ConfirmUserDeletionModal({isOpen, onOpenChange, user}: ConfirmUserDeletionModalProps) { const [confirmUsername, setConfirmUsername] = useState(""); useEffect(() => { diff --git a/gameyfin/src/main/frontend/components/general/InviteUserModal.tsx b/gameyfin/src/main/frontend/components/general/InviteUserModal.tsx index 04f4b84..abced0b 100644 --- a/gameyfin/src/main/frontend/components/general/InviteUserModal.tsx +++ b/gameyfin/src/main/frontend/components/general/InviteUserModal.tsx @@ -8,10 +8,7 @@ interface InviteUserModalProps { onOpenChange: () => void; } -export default function InviteUserModal({ - isOpen, - onOpenChange - }: InviteUserModalProps) { +export default function InviteUserModal({isOpen, onOpenChange}: InviteUserModalProps) { const [email, setEmail] = useState(); const [error, setError] = useState(); diff --git a/gameyfin/src/main/frontend/components/general/PasswortResetTokenModal.tsx b/gameyfin/src/main/frontend/components/general/PasswortResetTokenModal.tsx index 1f7e929..295c14b 100644 --- a/gameyfin/src/main/frontend/components/general/PasswortResetTokenModal.tsx +++ b/gameyfin/src/main/frontend/components/general/PasswortResetTokenModal.tsx @@ -9,11 +9,7 @@ interface PasswordResetTokenModalProps { token: TokenDto; } -export default function PasswordResetTokenModal({ - isOpen, - onOpenChange, - token - }: PasswordResetTokenModalProps) { +export default function PasswordResetTokenModal({isOpen, onOpenChange, token}: PasswordResetTokenModalProps) { const [timeUntilExpiry, setTimeUntilExpiry] = useState(""); const timeoutRefresh = setInterval(updateTimeUntilExpiry, 1000); diff --git a/gameyfin/src/main/frontend/components/general/PluginConfigurationModal.tsx b/gameyfin/src/main/frontend/components/general/PluginConfigurationModal.tsx new file mode 100644 index 0000000..ffc8855 --- /dev/null +++ b/gameyfin/src/main/frontend/components/general/PluginConfigurationModal.tsx @@ -0,0 +1,75 @@ +import React, {useEffect, useState} from "react"; +import {Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader} from "@nextui-org/react"; +import {toast} from "sonner"; +import {Form, Formik} from "formik"; +import {PluginConfigEndpoint} from "Frontend/generated/endpoints"; +import PluginDto from "Frontend/generated/de/grimsi/gameyfin/core/plugins/management/PluginDto"; +import PluginConfigElement from "Frontend/generated/de/grimsi/gameyfin/pluginapi/core/PluginConfigElement"; +import Input from "Frontend/components/general/Input"; + +interface PluginConfigurationModalProps { + plugin: PluginDto; + isOpen: boolean; + onOpenChange: () => void; +} + +export default function PluginConfigurationModal({plugin, isOpen, onOpenChange}: PluginConfigurationModalProps) { + const [pluginConfigMeta, setPluginConfigMeta] = useState<(PluginConfigElement)[]>(); + const [pluginConfig, setPluginConfig] = useState>(); + + useEffect(() => { + PluginConfigEndpoint.getConfigMetadata(plugin.id).then(response => { + if (response === undefined) return; + setPluginConfigMeta(response as PluginConfigElement[]); + }); + PluginConfigEndpoint.getConfig(plugin.id).then(response => { + if (response === undefined) return; + setPluginConfig(response as Record); + }); + }, []); + + async function saveConfig(values: Record) { + await PluginConfigEndpoint.setConfigEntries(plugin.id, values); + toast.success(`Configuration for ${plugin.name} saved!`); + } + + return ( + + + {(onClose) => ( + { + await saveConfig(values); + onClose(); + }} + > + {(formik: { isSubmitting: any; }) => ( +
+ {plugin.name} configuration + + {pluginConfigMeta && pluginConfigMeta.map((entry: any) => ( + + ))} + + + + + +
+ )} +
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/gameyfin/src/main/frontend/components/general/PluginManagementCard.tsx b/gameyfin/src/main/frontend/components/general/PluginManagementCard.tsx new file mode 100644 index 0000000..2ad5825 --- /dev/null +++ b/gameyfin/src/main/frontend/components/general/PluginManagementCard.tsx @@ -0,0 +1,50 @@ +import {Card, Chip, Tooltip, useDisclosure} from "@nextui-org/react"; +import {PuzzlePiece} from "@phosphor-icons/react"; +import PluginDto from "Frontend/generated/de/grimsi/gameyfin/core/plugins/management/PluginDto"; +import PluginState from "Frontend/generated/org/pf4j/PluginState"; +import React from "react"; +import PluginConfigurationModal from "Frontend/components/general/PluginConfigurationModal"; + +export function PluginManagementCard({plugin}: { plugin: PluginDto }) { + const pluginConfigurationModal = useDisclosure(); + + function stateToColor(state: PluginState | undefined): string { + switch (state) { + case PluginState.STARTED: + return "success"; + case PluginState.DISABLED: + return "warning"; + case PluginState.STOPPED: + return "danger"; + default: + return ""; + } + } + + return ( + <> + +
+ + + +
+
+

{plugin.name}

+
+ {plugin.version} +
+
+

Author: {plugin.author}

+
+
+
+ + + + ) +} \ No newline at end of file diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigEndpoint.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigEndpoint.kt similarity index 94% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigEndpoint.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigEndpoint.kt index 97094fd..52cf1ca 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigEndpoint.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigEndpoint.kt @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.config import com.vaadin.hilla.Endpoint import de.grimsi.gameyfin.core.Role diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigEntry.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigEntry.kt similarity index 94% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigEntry.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigEntry.kt index dca5aab..a48dea6 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigEntry.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigEntry.kt @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.config import de.grimsi.gameyfin.core.security.EncryptionConverter import jakarta.persistence.Column diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigRepository.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigRepository.kt similarity index 86% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigRepository.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigRepository.kt index 1dc4eea..a6e6aeb 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigRepository.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigRepository.kt @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.config import org.springframework.data.jpa.repository.JpaRepository diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigService.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigService.kt similarity index 71% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigService.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigService.kt index 36a8a2d..4082b0a 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginConfigService.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/config/PluginConfigService.kt @@ -1,7 +1,9 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.config +import de.grimsi.gameyfin.core.plugins.management.GameyfinPluginManager import de.grimsi.gameyfin.pluginapi.core.GameyfinPlugin import de.grimsi.gameyfin.pluginapi.core.PluginConfigElement +import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Service @Service @@ -10,22 +12,28 @@ class PluginConfigService( private val pluginManager: GameyfinPluginManager ) { + private val log = KotlinLogging.logger {} + fun getConfigMetadata(pluginId: String): List { + log.info { "Getting config metadata for plugin $pluginId" } val plugin = pluginManager.getPlugin(pluginId).plugin as GameyfinPlugin return plugin.configMetadata } fun getConfig(pluginId: String): Map { + log.info { "Getting config for plugin $pluginId" } return pluginConfigRepository.findAllById_PluginId(pluginId).associate { it.id.key to it.value } } fun setConfigEntries(pluginId: String, config: Map) { + log.info { "Setting config entries for plugin $pluginId" } val entries = config.map { PluginConfigEntry(PluginConfigEntryKey(pluginId, it.key), it.value) } pluginConfigRepository.saveAll(entries) pluginManager.restart(pluginId) } fun setConfigEntry(pluginId: String, key: String, value: String) { + log.info { "Setting config entry $key for plugin $pluginId" } val entry = PluginConfigEntry(PluginConfigEntryKey(pluginId, key), value) pluginConfigRepository.save(entry) pluginManager.restart(pluginId) diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/GameyfinPluginLoader.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/GameyfinPluginLoader.kt similarity index 92% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/GameyfinPluginLoader.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/GameyfinPluginLoader.kt index bb56d85..2a5caf9 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/GameyfinPluginLoader.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/GameyfinPluginLoader.kt @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.management import org.pf4j.DevelopmentPluginLoader import org.pf4j.PluginClassLoader diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/GameyfinPluginManager.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/GameyfinPluginManager.kt similarity index 95% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/GameyfinPluginManager.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/GameyfinPluginManager.kt index a882610..bbebf1d 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/GameyfinPluginManager.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/GameyfinPluginManager.kt @@ -1,5 +1,6 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.management +import de.grimsi.gameyfin.core.plugins.config.PluginConfigRepository import de.grimsi.gameyfin.pluginapi.core.GameyfinPlugin import io.github.oshai.kotlinlogging.KotlinLogging import org.pf4j.CompoundPluginLoader diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginDto.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginDto.kt new file mode 100644 index 0000000..af02972 --- /dev/null +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginDto.kt @@ -0,0 +1,11 @@ +package de.grimsi.gameyfin.core.plugins.management + +import org.pf4j.PluginState + +data class PluginDto( + val id: String, + val name: String, + val version: String, + val author: String, + val state: PluginState +) \ No newline at end of file diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementEndpoint.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementEndpoint.kt new file mode 100644 index 0000000..be5c478 --- /dev/null +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementEndpoint.kt @@ -0,0 +1,19 @@ +package de.grimsi.gameyfin.core.plugins.management + +import com.vaadin.hilla.Endpoint +import de.grimsi.gameyfin.core.Role +import jakarta.annotation.security.RolesAllowed + +@Endpoint +@RolesAllowed(Role.Names.ADMIN) +class PluginManagementEndpoint( + private val pluginManagementService: PluginManagementService +) { + fun getPlugins() = pluginManagementService.getPlugins() + + fun startPlugin(pluginId: String) = pluginManagementService.startPlugin(pluginId) + + fun stopPlugin(pluginId: String) = pluginManagementService.stopPlugin(pluginId) + + fun restartPlugin(pluginId: String) = pluginManagementService.restartPlugin(pluginId) +} \ No newline at end of file diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementService.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementService.kt new file mode 100644 index 0000000..2d4582a --- /dev/null +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagementService.kt @@ -0,0 +1,32 @@ +package de.grimsi.gameyfin.core.plugins.management + +import org.springframework.stereotype.Service + +@Service +class PluginManagementService( + private val pluginManager: GameyfinPluginManager +) { + fun getPlugins(): List { + return pluginManager.plugins.map { + PluginDto( + it.pluginId, + it.descriptor.pluginDescription, + it.descriptor.version, + it.descriptor.provider, + it.pluginState + ) + } + } + + fun startPlugin(pluginId: String) { + pluginManager.startPlugin(pluginId) + } + + fun stopPlugin(pluginId: String) { + pluginManager.stopPlugin(pluginId) + } + + fun restartPlugin(pluginId: String) { + pluginManager.restart(pluginId) + } +} \ 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/management/PluginManagerConfig.kt similarity index 88% rename from gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginManagerConfig.kt rename to gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagerConfig.kt index ed0c751..af383c2 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/PluginManagerConfig.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/plugins/management/PluginManagerConfig.kt @@ -1,5 +1,6 @@ -package de.grimsi.gameyfin.core.plugins +package de.grimsi.gameyfin.core.plugins.management +import de.grimsi.gameyfin.core.plugins.config.PluginConfigRepository import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.context.annotation.Bean 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 70fae7e..4c6014f 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 @@ -9,11 +9,8 @@ import de.grimsi.gameyfin.pluginapi.core.PluginConfigElement import de.grimsi.gameyfin.pluginapi.core.PluginConfigError import de.grimsi.gameyfin.pluginapi.gamemetadata.GameMetadata import de.grimsi.gameyfin.pluginapi.gamemetadata.GameMetadataFetcher -import de.grimsi.gameyfin.pluginapi.gamemetadata.Genre -import de.grimsi.gameyfin.pluginapi.gamemetadata.Theme import org.pf4j.Extension import org.pf4j.PluginWrapper -import org.slf4j.LoggerFactory import java.time.Instant import kotlin.collections.filter @@ -52,8 +49,6 @@ class IgdbPlugin(wrapper: PluginWrapper) : GameyfinPlugin(wrapper) { @Extension class IgdbMetadataFetcher : GameMetadataFetcher { - private val log = LoggerFactory.getLogger(javaClass) - override fun fetchMetadata(gameId: String): GameMetadata { val findGameByName = APICalypse() .fields("*") @@ -71,76 +66,13 @@ class IgdbPlugin(wrapper: PluginWrapper) : GameyfinPlugin(wrapper) { criticRating = game.aggregatedRating.toInt(), developedBy = game.involvedCompaniesList.filter { it.developer }.map { it.company.name }, publishedBy = game.involvedCompaniesList.filter { it.publisher }.map { it.company.name }, - genres = game.genresList.map { mapGenre(it) }, - themes = game.themesList.map { mapTheme(it) }, + genres = game.genresList.map { Mapper.genre(it) }, + themes = game.themesList.map { Mapper.theme(it) }, screenshotUrls = listOf(), videoUrls = listOf(), features = listOf(), perspectives = listOf() ) } - - private fun mapGenre(genre: proto.Genre): Genre { - return when (genre.slug) { - "pinball" -> Genre.PINBALL - "adventure" -> Genre.ADVENTURE - "indie" -> Genre.INDIE - "arcade" -> Genre.ARCADE - "visual-novel" -> Genre.VISUAL_NOVEL - "card-and-board-game" -> Genre.CARD_AND_BOARD_GAME - "moba" -> Genre.MOBA - "point-and-click" -> Genre.POINT_AND_CLICK - "fighting" -> Genre.FIGHTING - "shooter" -> Genre.SHOOTER - "music" -> Genre.MUSIC - "platform" -> Genre.PLATFORM - "puzzle" -> Genre.PUZZLE - "racing" -> Genre.RACING - "real-time-strategy-rts" -> Genre.REAL_TIME_STRATEGY - "role-playing-rpg" -> Genre.ROLE_PLAYING - "simulator" -> Genre.SIMULATOR - "sport" -> Genre.SPORT - "strategy" -> Genre.STRATEGY - "turn-based-strategy-tbs" -> Genre.TURN_BASED_STRATEGY - "tactical" -> Genre.TACTICAL - "hack-and-slash-beat-em-up" -> Genre.HACK_AND_SLASH_BEAT_EM_UP - "quiz-trivia" -> Genre.QUIZ_TRIVIA - else -> { - log.warn("Unknown genre: {}", genre.slug) - Genre.UNKNOWN - } - } - } - - private fun mapTheme(theme: proto.Theme): Theme { - return when (theme.slug) { - "action" -> Theme.ACTION - "fantasy" -> Theme.FANTASY - "horror" -> Theme.HORROR - "sci-fi" -> Theme.SCIENCE_FICTION - "mystery" -> Theme.MYSTERY - "thriller" -> Theme.THRILLER - "survival" -> Theme.SURVIVAL - "historical" -> Theme.HISTORICAL - "stealth" -> Theme.STEALTH - "comedy" -> Theme.COMEDY - "business" -> Theme.BUSINESS - "drama" -> Theme.DRAMA - "non-fiction" -> Theme.NON_FICTION - "sandbox" -> Theme.SANDBOX - "educational" -> Theme.EDUCATIONAL - "kids" -> Theme.KIDS - "open-world" -> Theme.OPEN_WORLD - "warfare" -> Theme.WARFARE - "party" -> Theme.PARTY - "4x-explore-expand-exploit-and-exterminate" -> Theme.FOUR_X - "erotic" -> Theme.EROTIC - "romance" -> Theme.ROMANCE - else -> { - log.warn("Unknown theme: {}", theme.slug) - Theme.UNKNOWN - } - } - } } } \ No newline at end of file diff --git a/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/Mapper.kt b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/Mapper.kt new file mode 100644 index 0000000..475975e --- /dev/null +++ b/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/Mapper.kt @@ -0,0 +1,74 @@ +package de.grimsi.gameyfin.plugins.igdb + +import de.grimsi.gameyfin.pluginapi.gamemetadata.Genre +import de.grimsi.gameyfin.pluginapi.gamemetadata.Theme +import org.slf4j.LoggerFactory + +class Mapper { + companion object { + private val log = LoggerFactory.getLogger(javaClass) + + fun genre(genre: proto.Genre): Genre { + return when (genre.slug) { + "pinball" -> Genre.PINBALL + "adventure" -> Genre.ADVENTURE + "indie" -> Genre.INDIE + "arcade" -> Genre.ARCADE + "visual-novel" -> Genre.VISUAL_NOVEL + "card-and-board-game" -> Genre.CARD_AND_BOARD_GAME + "moba" -> Genre.MOBA + "point-and-click" -> Genre.POINT_AND_CLICK + "fighting" -> Genre.FIGHTING + "shooter" -> Genre.SHOOTER + "music" -> Genre.MUSIC + "platform" -> Genre.PLATFORM + "puzzle" -> Genre.PUZZLE + "racing" -> Genre.RACING + "real-time-strategy-rts" -> Genre.REAL_TIME_STRATEGY + "role-playing-rpg" -> Genre.ROLE_PLAYING + "simulator" -> Genre.SIMULATOR + "sport" -> Genre.SPORT + "strategy" -> Genre.STRATEGY + "turn-based-strategy-tbs" -> Genre.TURN_BASED_STRATEGY + "tactical" -> Genre.TACTICAL + "hack-and-slash-beat-em-up" -> Genre.HACK_AND_SLASH_BEAT_EM_UP + "quiz-trivia" -> Genre.QUIZ_TRIVIA + else -> { + log.warn("Unknown genre: {}", genre.slug) + Genre.UNKNOWN + } + } + } + + fun theme(theme: proto.Theme): Theme { + return when (theme.slug) { + "action" -> Theme.ACTION + "fantasy" -> Theme.FANTASY + "horror" -> Theme.HORROR + "sci-fi" -> Theme.SCIENCE_FICTION + "mystery" -> Theme.MYSTERY + "thriller" -> Theme.THRILLER + "survival" -> Theme.SURVIVAL + "historical" -> Theme.HISTORICAL + "stealth" -> Theme.STEALTH + "comedy" -> Theme.COMEDY + "business" -> Theme.BUSINESS + "drama" -> Theme.DRAMA + "non-fiction" -> Theme.NON_FICTION + "sandbox" -> Theme.SANDBOX + "educational" -> Theme.EDUCATIONAL + "kids" -> Theme.KIDS + "open-world" -> Theme.OPEN_WORLD + "warfare" -> Theme.WARFARE + "party" -> Theme.PARTY + "4x-explore-expand-exploit-and-exterminate" -> Theme.FOUR_X + "erotic" -> Theme.EROTIC + "romance" -> Theme.ROMANCE + else -> { + log.warn("Unknown theme: {}", theme.slug) + Theme.UNKNOWN + } + } + } + } +} \ 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 deleted file mode 100644 index bc7bf3e..0000000 --- a/plugins/igdb/src/main/kotlin/de/grimsi/gameyfin/plugins/igdb/dto/TwitchOAuthTokenDto.kt +++ /dev/null @@ -1,7 +0,0 @@ -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 diff --git a/plugins/igdb/src/main/resources/MANIFEST.MF b/plugins/igdb/src/main/resources/MANIFEST.MF index 51b060a..c398490 100644 --- a/plugins/igdb/src/main/resources/MANIFEST.MF +++ b/plugins/igdb/src/main/resources/MANIFEST.MF @@ -1,5 +1,6 @@ Manifest-Version: 1.0 -Plugin-Id: igdb Plugin-Class: de.grimsi.gameyfin.plugins.igdb.IgdbPlugin -Plugin-Version: 1.0.0-SNAPSHOT +Plugin-Id: igdb +Plugin-Description: IGDB Plugin +Plugin-Version: 1.0.0-alpha1 Plugin-Provider: grimsi