mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-15 00:30:02 +00:00
Finish plugin support implementation
Small refactoring
This commit is contained in:
@@ -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<any>();
|
||||
const [igdbConfig, setIgdbConfig] = useState<any>();
|
||||
const [plugins, setPlugins] = useState<PluginDto[]>([]);
|
||||
|
||||
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
|
||||
initialValues={{
|
||||
clientId: igdbConfig?.clientId,
|
||||
clientSecret: igdbConfig?.clientSecret
|
||||
}}
|
||||
enableReinitialize={true}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(formik: { values: any; isSubmitting: any; }) => (
|
||||
<Form>
|
||||
<div className="flex flex-row flex-grow justify-between mb-8">
|
||||
<h2 className="text-2xl font-bold">Plugins</h2>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<Button
|
||||
color="primary"
|
||||
isLoading={formik.isSubmitting}
|
||||
disabled={formik.isSubmitting || configSaved}
|
||||
type="submit"
|
||||
>
|
||||
{formik.isSubmitting ? "" : configSaved ? <Check/> : "Save"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row flex-grow justify-between mb-8">
|
||||
<h2 className="text-2xl font-bold">Plugins</h2>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row flex-1 justify-between gap-16">
|
||||
<div className="flex flex-col flex-grow">
|
||||
<Section title="IGDB"/>
|
||||
{igdbConfigMeta && igdbConfigMeta.map((entry: any) => (
|
||||
<Input key={entry.key} name={entry.key} label={entry.name} type="text"/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
<Divider className="mb-4"/>
|
||||
<div className="grid grid-cols-300px gap-4">
|
||||
{plugins.map((plugin) => <PluginManagementCard plugin={plugin} key={plugin.name}/>)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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<Role[]>([]);
|
||||
const [selectedRole, setSelectedRole] = useState<Selection>();
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
@@ -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<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -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<string | null>();
|
||||
const [error, setError] = useState<string | null>();
|
||||
|
||||
|
||||
@@ -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<string>("");
|
||||
|
||||
const timeoutRefresh = setInterval(updateTimeUntilExpiry, 1000);
|
||||
|
||||
@@ -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<Record<string, string>>();
|
||||
|
||||
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<string, string>);
|
||||
});
|
||||
}, []);
|
||||
|
||||
async function saveConfig(values: Record<string, string>) {
|
||||
await PluginConfigEndpoint.setConfigEntries(plugin.id, values);
|
||||
toast.success(`Configuration for ${plugin.name} saved!`);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange} backdrop="opaque" size="lg">
|
||||
<ModalContent>
|
||||
{(onClose) => (
|
||||
<Formik initialValues={pluginConfig}
|
||||
enableReinitialize={true}
|
||||
onSubmit={async (values: any) => {
|
||||
await saveConfig(values);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{(formik: { isSubmitting: any; }) => (
|
||||
<Form>
|
||||
<ModalHeader className="flex flex-col gap-1">{plugin.name} configuration</ModalHeader>
|
||||
<ModalBody>
|
||||
{pluginConfigMeta && pluginConfigMeta.map((entry: any) => (
|
||||
<Input key={entry.key} name={entry.key} label={entry.name} type="text"/>
|
||||
))}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant="light" onPress={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
color="primary"
|
||||
isLoading={formik.isSubmitting}
|
||||
disabled={formik.isSubmitting}
|
||||
type="submit"
|
||||
>
|
||||
{formik.isSubmitting ? "" : "Save"}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<>
|
||||
<Card className="flex flex-row justify-between p-2"
|
||||
isPressable={true} onPress={pluginConfigurationModal.onOpen}>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<Tooltip placement="right" content={`Plugin ${plugin.state!.toLowerCase()}`}>
|
||||
<PuzzlePiece size={64} weight="duotone" className={`text-${stateToColor(plugin.state)}`}/>
|
||||
</Tooltip>
|
||||
<div className="flex flex-col items-start gap-1">
|
||||
<div className="flex flex-row gap-2">
|
||||
<p className="font-semibold">{plugin.name}</p>
|
||||
<div className="text-sm">
|
||||
<Chip size="sm" radius="sm" className="text-xs">{plugin.version}</Chip>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm">Author: {plugin.author}</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<PluginConfigurationModal plugin={plugin}
|
||||
isOpen={pluginConfigurationModal.isOpen}
|
||||
onOpenChange={pluginConfigurationModal.onOpenChange}
|
||||
/>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
+1
-1
@@ -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
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package de.grimsi.gameyfin.core.plugins
|
||||
package de.grimsi.gameyfin.core.plugins.config
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
+9
-1
@@ -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<PluginConfigElement> {
|
||||
log.info { "Getting config metadata for plugin $pluginId" }
|
||||
val plugin = pluginManager.getPlugin(pluginId).plugin as GameyfinPlugin
|
||||
return plugin.configMetadata
|
||||
}
|
||||
|
||||
fun getConfig(pluginId: String): Map<String, String?> {
|
||||
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<String, String>) {
|
||||
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)
|
||||
+1
-1
@@ -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
|
||||
+2
-1
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
+19
@@ -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)
|
||||
}
|
||||
+32
@@ -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<PluginDto> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package de.grimsi.gameyfin.plugins.igdb.dto
|
||||
|
||||
data class TwitchOAuthTokenDto(
|
||||
val accessToken: String,
|
||||
val expiresIn: Int,
|
||||
val tokenType: String
|
||||
)
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user