imports are cool xD
This commit is contained in:
32
api_examples/update_game.json
Normal file
32
api_examples/update_game.json
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -7,9 +7,16 @@ import { importFromStashAPP, StashAPPConfig, updateActorsFromStashAPP } from '@/
|
|||||||
import { importFromPlaynite, PlayniteConfig } from '@/lib/playniteImporter';
|
import { importFromPlaynite, PlayniteConfig } from '@/lib/playniteImporter';
|
||||||
|
|
||||||
export default function ImporterView({ onBack }: { onBack: () => void }) {
|
export default function ImporterView({ onBack }: { onBack: () => void }) {
|
||||||
const [xbvrConfig, setXbvrConfig] = useState<XBVRConfig>({ url: 'http://192.168.1.102:4080' });
|
const [xbvrConfig, setXbvrConfig] = useState<XBVRConfig>({ url: import.meta.env.VITE_XBVR_URL || '' });
|
||||||
const [stashappConfig, setStashappConfig] = useState<StashAPPConfig>({ url: 'http://192.168.1.102:10001' });
|
const [stashappConfig, setStashappConfig] = useState<StashAPPConfig>({
|
||||||
const [playniteConfig, setPlayniteConfig] = useState<PlayniteConfig>({ ip: 'localhost', apiToken: '', port: 19821 });
|
url: import.meta.env.VITE_STASHAPP_URL || '',
|
||||||
|
apiKey: import.meta.env.VITE_STASHAPP_API_KEY || ''
|
||||||
|
});
|
||||||
|
const [playniteConfig, setPlayniteConfig] = useState<PlayniteConfig>({
|
||||||
|
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<ImportProgress>({
|
const [progress, setProgress] = useState<ImportProgress>({
|
||||||
current: 0,
|
current: 0,
|
||||||
total: 0,
|
total: 0,
|
||||||
@@ -167,6 +174,7 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
|
|||||||
{/* Importer Cards */}
|
{/* Importer Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
||||||
{/* XBVR Importer Card */}
|
{/* XBVR Importer Card */}
|
||||||
|
{xbvrConfig.url && (
|
||||||
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
||||||
<div className="flex items-start justify-between mb-4">
|
<div className="flex items-start justify-between mb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -221,8 +229,10 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* StashAPP Importer Card */}
|
{/* StashAPP Importer Card */}
|
||||||
|
{stashappConfig.url && (
|
||||||
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
||||||
<div className="flex items-start justify-between mb-4">
|
<div className="flex items-start justify-between mb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -288,8 +298,10 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* StashAPP Actor Updater Card */}
|
{/* StashAPP Actor Updater Card */}
|
||||||
|
{stashappConfig.url && (
|
||||||
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
||||||
<div className="flex items-start justify-between mb-4">
|
<div className="flex items-start justify-between mb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -344,8 +356,10 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Playnite Importer Card */}
|
{/* Playnite Importer Card */}
|
||||||
|
{playniteConfig.ip && playniteConfig.apiToken && (
|
||||||
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
<div className="bg-white border border-zinc-200 rounded-xl p-6 hover:border-[#6d28d9]/50 transition-colors">
|
||||||
<div className="flex items-start justify-between mb-4">
|
<div className="flex items-start justify-between mb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -422,6 +436,7 @@ export default function ImporterView({ onBack }: { onBack: () => void }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Progress Section */}
|
{/* Progress Section */}
|
||||||
|
|||||||
@@ -60,6 +60,29 @@ export interface PlayniteGamesResponse {
|
|||||||
export type LogCallback = (message: string) => void;
|
export type LogCallback = (message: string) => void;
|
||||||
export type ProgressCallback = (progress: Partial<ImportProgress>) => void;
|
export type ProgressCallback = (progress: Partial<ImportProgress>) => void;
|
||||||
|
|
||||||
|
async function fetchGameCover(baseUrl: string, headers: Record<string, string>, gameId: string): Promise<string | null> {
|
||||||
|
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(
|
export async function importFromPlaynite(
|
||||||
config: PlayniteConfig,
|
config: PlayniteConfig,
|
||||||
logCallback: LogCallback,
|
logCallback: LogCallback,
|
||||||
@@ -194,7 +217,6 @@ export async function importFromPlaynite(
|
|||||||
|
|
||||||
// Staff is for actors/performers only - leave empty for games
|
// Staff is for actors/performers only - leave empty for games
|
||||||
const staff: any[] = [];
|
const staff: any[] = [];
|
||||||
|
|
||||||
// Determine type based on genres/features
|
// Determine type based on genres/features
|
||||||
let type = 'Game';
|
let type = 'Game';
|
||||||
//if (game.genres?.includes('Visual Novel') || game.genres?.includes('Adventure')) {
|
//if (game.genres?.includes('Visual Novel') || game.genres?.includes('Adventure')) {
|
||||||
@@ -242,7 +264,7 @@ export async function importFromPlaynite(
|
|||||||
links: game.links || [],
|
links: game.links || [],
|
||||||
achievements: [],
|
achievements: [],
|
||||||
year: year.toString(),
|
year: year.toString(),
|
||||||
poster: null,
|
poster: game.coverBase64 || null,
|
||||||
banner: null,
|
banner: null,
|
||||||
rating: rating,
|
rating: rating,
|
||||||
category: 'Game',
|
category: 'Game',
|
||||||
|
|||||||
14
src/vite-env.d.ts
vendored
Normal file
14
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user