feat: Implemented local game import (with a wizard)

feat: Implemented a radial virtual gamepad keyboard.
fix: Fixed shortcuts for file explorer
This commit is contained in:
Simeon Radivoev 2026-05-04 14:59:43 +03:00
parent e54a6ac8f0
commit 06b7e4074d
Signed by: simeonradivoev
GPG key ID: 7611A451D2A5D37A
66 changed files with 2216 additions and 416 deletions

View file

@ -42,17 +42,53 @@ export default class IgdbIntegration implements PluginType
{
await checkLoginAndRefreshTwitch();
ctx.hooks.games.gameLookup.tapPromise(desc.name, async ({ source, id }) =>
ctx.hooks.games.gameLookup.tapPromise(desc.name, async ({ source, id, search, matches }) =>
{
if (!process.env.TWITCH_CLIENT_ID) return;
if (source !== 'igdb') return;
const access_token = await secrets.get({ service: 'gamflow_twitch', name: 'access_token' });
if (access_token)
if (!access_token)
{
return;
}
if ((source === 'igdb' && id) || search)
{
const client = igdb.igdb(process.env.TWITCH_CLIENT_ID, access_token);
const { data } = await client.request('screenshots').pipe(igdb.fields(['game', 'url', 'image_id']), igdb.where('game', '=', Number(id))).execute();
return { screenshotUrls: data.filter(s => s.url).map(s => `https://images.igdb.com/igdb/image/upload/t_720p/${s.image_id}.webp`) };
const { data: games } = await this.queue.add(() => client.request('games')
.pipe(...(search ? [igdb.search(search)] : []),
igdb.fields(['id', 'name', 'summary', 'screenshots.image_id', 'slug', 'first_release_date', 'rating', 'genres.name', 'involved_companies.company.name', 'keywords.name', 'game_modes.name', 'cover.image_id', 'age_ratings.rating_category.rating', 'platforms.name', 'platforms.abbreviation', 'platforms.slug']),
...(source === 'igdb' && id ? [igdb.where('id', '=', Number(id))] : []),
igdb.limit(10)).execute());
matches.push(...games.filter(g => !!g.name)
.map(g =>
{
const lookup: GameLookup = {
source: 'igdb',
id: String(g.id),
coverUrl: g.cover ? `https://images.igdb.com/igdb/image/upload/t_720p/${g.cover.image_id}.webp` : undefined,
screenshotUrls: g.screenshots?.map(s => `https://images.igdb.com/igdb/image/upload/t_720p/${s.image_id}.webp`) ?? [],
name: g.name!,
summary: g.summary,
genres: g.genres?.map(g => g.name!) ?? [],
companies: g.involved_companies?.filter(c => c.company?.name).map(c => c.company?.name!) ?? [],
game_modes: g.game_modes?.map(m => m.name!) ?? [],
age_ratings: g.age_ratings?.map(r => r.rating_category?.rating!) ?? [],
player_count: undefined,
// UNIX date, needs to be converted
first_release_date: g.first_release_date ? g.first_release_date * 1000 : undefined,
average_rating: g.rating ?? undefined,
keywords: g.keywords?.map(k => k.name!) ?? [],
igdb_id: g.id,
platforms: g.platforms?.map(p => ({ id: p.id!, name: p.abbreviation, displayName: p.name!, slug: p.slug! })) ?? [],
slug: g.slug
};
return lookup;
}));
return;
}
});