diff --git a/api_examples/update_game.json b/api_examples/update_game.json new file mode 100644 index 0000000..3a13b0c --- /dev/null +++ b/api_examples/update_game.json @@ -0,0 +1,32 @@ +{ + "type": "Game", + "title": "1-2-Switch", + "playtime": 120, + "completionStatus": "Completed", + "favorite": true, + "communityScore": 55, + "userScore": 80, + "achievements": [ + { + "name": "First Victory", + "description": "Win your first game", + "icon": "https://example.com/achievement-icon.png", + "unlocked": true, + "unlocked_date": "2026-04-09T18:00:00" + }, + { + "name": "Master Player", + "description": "Win 100 games", + "icon": "https://example.com/master-icon.png", + "unlocked": true, + "unlocked_date": "2026-04-09T20:30:00" + }, + { + "name": "Champion", + "description": "Win 1000 games", + "icon": "https://example.com/champion-icon.png", + "unlocked": false, + "unlocked_date": null + } + ] +} diff --git a/src/components/ImporterView.tsx b/src/components/ImporterView.tsx index 20f27af..54fd2d9 100644 --- a/src/components/ImporterView.tsx +++ b/src/components/ImporterView.tsx @@ -7,9 +7,16 @@ import { importFromStashAPP, StashAPPConfig, updateActorsFromStashAPP } from '@/ import { importFromPlaynite, PlayniteConfig } from '@/lib/playniteImporter'; export default function ImporterView({ onBack }: { onBack: () => void }) { - const [xbvrConfig, setXbvrConfig] = useState({ url: 'http://192.168.1.102:4080' }); - const [stashappConfig, setStashappConfig] = useState({ url: 'http://192.168.1.102:10001' }); - const [playniteConfig, setPlayniteConfig] = useState({ ip: 'localhost', apiToken: '', port: 19821 }); + const [xbvrConfig, setXbvrConfig] = useState({ url: import.meta.env.VITE_XBVR_URL || '' }); + const [stashappConfig, setStashappConfig] = useState({ + url: import.meta.env.VITE_STASHAPP_URL || '', + apiKey: import.meta.env.VITE_STASHAPP_API_KEY || '' + }); + const [playniteConfig, setPlayniteConfig] = useState({ + ip: import.meta.env.VITE_PLAYNITE_IP || '', + apiToken: import.meta.env.VITE_PLAYNITE_API_TOKEN || '', + port: parseInt(import.meta.env.VITE_PLAYNITE_PORT || '19821') + }); const [progress, setProgress] = useState({ current: 0, total: 0, @@ -167,7 +174,8 @@ export default function ImporterView({ onBack }: { onBack: () => void }) { {/* Importer Cards */}
{/* XBVR Importer Card */} -
+ {xbvrConfig.url && ( +
@@ -221,9 +229,11 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
+ )} {/* StashAPP Importer Card */} -
+ {stashappConfig.url && ( +
@@ -288,9 +298,11 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
+ )} {/* StashAPP Actor Updater Card */} -
+ {stashappConfig.url && ( +
@@ -344,9 +356,11 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
+ )} {/* Playnite Importer Card */} -
+ {playniteConfig.ip && playniteConfig.apiToken && ( +
@@ -422,6 +436,7 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
+ )}
{/* Progress Section */} diff --git a/src/lib/playniteImporter.ts b/src/lib/playniteImporter.ts index 5bbcab1..eb873f6 100644 --- a/src/lib/playniteImporter.ts +++ b/src/lib/playniteImporter.ts @@ -60,6 +60,29 @@ export interface PlayniteGamesResponse { export type LogCallback = (message: string) => void; export type ProgressCallback = (progress: Partial) => void; +async function fetchGameCover(baseUrl: string, headers: Record, gameId: string): Promise { + try { + const coverResponse = await fetch(`${baseUrl}/api/games/${gameId}/cover`, { + method: 'GET', + headers + }); + + if (!coverResponse.ok) { + return null; + } + + const blob = await coverResponse.blob(); + const arrayBuffer = await blob.arrayBuffer(); + const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer))); + + // Determine MIME type from blob + const mimeType = blob.type || 'image/jpeg'; + return `data:${mimeType};base64,${base64}`; + } catch (error) { + return null; + } +} + export async function importFromPlaynite( config: PlayniteConfig, logCallback: LogCallback, @@ -194,7 +217,6 @@ export async function importFromPlaynite( // Staff is for actors/performers only - leave empty for games const staff: any[] = []; - // Determine type based on genres/features let type = 'Game'; //if (game.genres?.includes('Visual Novel') || game.genres?.includes('Adventure')) { @@ -242,7 +264,7 @@ export async function importFromPlaynite( links: game.links || [], achievements: [], year: year.toString(), - poster: null, + poster: game.coverBase64 || null, banner: null, rating: rating, category: 'Game', diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..77afa14 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,14 @@ +/// + +interface ImportMetaEnv { + readonly VITE_XBVR_URL?: string; + readonly VITE_STASHAPP_URL?: string; + readonly VITE_STASHAPP_API_KEY?: string; + readonly VITE_PLAYNITE_IP?: string; + readonly VITE_PLAYNITE_PORT?: string; + readonly VITE_PLAYNITE_API_TOKEN?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +}