Skip to content

Commit

Permalink
feat: Supports selective import of games from steam library
Browse files Browse the repository at this point in the history
  • Loading branch information
ximu3 committed Dec 21, 2024
1 parent 1fc084b commit 0afd9fe
Show file tree
Hide file tree
Showing 9 changed files with 481 additions and 145 deletions.
111 changes: 111 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 18 additions & 11 deletions src/main/adder/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ export async function addGameToDB({
id,
preExistingDbId,
screenshotUrl,
playingTime
playingTime,
noWatcherAction = false,
noIpcAction = false
}: {
dataSource: string
id: string
preExistingDbId?: string
screenshotUrl?: string
playingTime?: number
noWatcherAction?: boolean
noIpcAction?: boolean
}): Promise<void> {
const metadata = await getGameMetadata(dataSource, id)
const coverUrl = await getGameCover(dataSource, id)
Expand Down Expand Up @@ -74,17 +78,20 @@ export async function addGameToDB({

const mainWindow = BrowserWindow.getAllWindows()[0]

stopWatcher()

await setupWatcher(mainWindow)
if (!noWatcherAction) {
stopWatcher()
await setupWatcher(mainWindow)
}

mainWindow.webContents.send('reload-db-values', `games/${dbId}/cover.webp`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/background.webp`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/icon.png`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/metadata.json`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/record.json`)
await rebuildIndex()
await rebuildRecords()
if (!noIpcAction) {
mainWindow.webContents.send('reload-db-values', `games/${dbId}/cover.webp`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/background.webp`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/icon.png`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/metadata.json`)
mainWindow.webContents.send('reload-db-values', `games/${dbId}/record.json`)
await rebuildIndex()
await rebuildRecords()
}
}

/**
Expand Down
16 changes: 14 additions & 2 deletions src/main/adder/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,28 @@ export async function addGameToDatabase({
id,
preExistingDbId,
screenshotUrl,
playingTime
playingTime,
noWatcherAction = false,
noIpcAction = false
}: {
dataSource: string
id: string
preExistingDbId?: string
screenshotUrl?: string
playingTime?: number
noWatcherAction?: boolean
noIpcAction?: boolean
}): Promise<void> {
try {
await addGameToDB({ dataSource, id, preExistingDbId, screenshotUrl, playingTime })
await addGameToDB({
dataSource,
id,
preExistingDbId,
screenshotUrl,
playingTime,
noWatcherAction,
noIpcAction
})
} catch (error) {
log.error('Error adding game to database:', error)
throw error
Expand Down
42 changes: 18 additions & 24 deletions src/main/importer/steam/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@ import { FormattedGameInfo, GetOwnedGamesResponse } from './types'
import { addGameToDatabase } from '~/adder'
import { BrowserWindow } from 'electron'
import { stopWatcher, setupWatcher } from '~/watcher'
import { rebuildIndex } from '~/database/gameIndex'
import { rebuildRecords } from '~/database/record'

/**
* Getting information about a user's Steam library
* @param steamId - Steam User ID
* @returns Formatted Game Information Array
*/
export async function getUserSteamGames(steamId: string): Promise<FormattedGameInfo[]> {
try {
// Building API URLs
const url = new URL('https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/')
url.searchParams.append('key', import.meta.env.VITE_STEAM_API_KEY)
url.searchParams.append('steamid', steamId)
url.searchParams.append('format', 'json')
url.searchParams.append('include_appinfo', '1')
url.searchParams.append('include_played_free_games', '1')

// initiate a request
const response = await fetch(url.toString())

if (!response.ok) {
Expand All @@ -27,16 +25,14 @@ export async function getUserSteamGames(steamId: string): Promise<FormattedGameI

const data = (await response.json()) as GetOwnedGamesResponse

// Check response data
if (!data.response || !data.response.games) {
throw new Error('Invalid response format or empty game library')
}

// Formatting game data
return data.response.games.map((game) => ({
appId: game.appid,
name: game.name,
totalPlayingTime: game.playtime_forever * 60 * 1000 // Convert to milliseconds
totalPlayingTime: game.playtime_forever * 60 * 1000
}))
} catch (error) {
console.error('获取 Steam 游戏库失败:', error)
Expand All @@ -45,32 +41,26 @@ export async function getUserSteamGames(steamId: string): Promise<FormattedGameI
}

/**
* Add user's Steam games to database
* @param steamId - Steam User ID
* @returns Number of games added
* Importing selected Steam games into the database
*/
export async function importUserSteamGamesToDatabase(steamId: string): Promise<number> {
// Get window instance
export async function importSelectedSteamGames(games: FormattedGameInfo[]): Promise<number> {
const mainWindow = BrowserWindow.getAllWindows()[0]
stopWatcher()

try {
// Get user's Steam game list
const games = await getUserSteamGames(steamId)
const totalGames = games.length

// If there is no game, return directly to
if (totalGames === 0) {
mainWindow.webContents.send('import-steam-games-progress', {
current: 0,
total: 0,
status: 'completed',
message: '没有找到游戏'
message: '没有选择要导入的游戏'
})
return 0
}

// Send Initial Progress
// Send initial progress
mainWindow.webContents.send('import-steam-games-progress', {
current: 0,
total: totalGames,
Expand All @@ -85,7 +75,9 @@ export async function importUserSteamGamesToDatabase(steamId: string): Promise<n
await addGameToDatabase({
dataSource: 'steam',
id: game.appId.toString(),
playingTime: game.totalPlayingTime
playingTime: game.totalPlayingTime,
noWatcherAction: true,
noIpcAction: true
})

// Send progress updates
Expand All @@ -100,7 +92,7 @@ export async function importUserSteamGamesToDatabase(steamId: string): Promise<n
}
})
} catch (error) {
// Send error message but continue processing
// Send an error message but continue processing
mainWindow.webContents.send('import-steam-games-progress', {
current: i + 1,
total: totalGames,
Expand All @@ -118,7 +110,11 @@ export async function importUserSteamGamesToDatabase(steamId: string): Promise<n
await new Promise((resolve) => setTimeout(resolve, 300))
}

// Send Completion Message
await rebuildIndex()
await rebuildRecords()
await setupWatcher(mainWindow)

// Send a completion message
mainWindow.webContents.send('import-steam-games-progress', {
current: totalGames,
total: totalGames,
Expand All @@ -128,15 +124,13 @@ export async function importUserSteamGamesToDatabase(steamId: string): Promise<n

return totalGames
} catch (error) {
// Send error message
// Send an error message
mainWindow.webContents.send('import-steam-games-progress', {
current: 0,
total: 0,
status: 'error',
message: error instanceof Error ? error.message : '获取游戏列表失败'
message: error instanceof Error ? error.message : '导入游戏失败'
})
throw error
} finally {
await setupWatcher(mainWindow)
}
}
30 changes: 22 additions & 8 deletions src/main/importer/steam/services.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import { importUserSteamGamesToDatabase } from './common'
import { getUserSteamGames, importSelectedSteamGames } from './common'
import { FormattedGameInfo } from './types'
import log from 'electron-log/main.js'

/**
* Import user steam games to the database
* @param steamId The steam id of the user
* @returns A promise that resolves when the operation is complete.
* @throws An error if the operation fails.
* Getting information about a user's Steam library
* @param steamId Steam User ID
* @returns Steam Game Library Information
*/
export async function importUserSteamGamesToDB(steamId: string): Promise<void> {
export async function getSteamGames(steamId: string): Promise<FormattedGameInfo[]> {
try {
await importUserSteamGamesToDatabase(steamId)
return await getUserSteamGames(steamId)
} catch (error) {
log.error('Error adding user steam games to database:', error)
log.error('获取 Steam 游戏库失败:', error)
throw error
}
}

/**
* Import selected Steam games to the database
* @param games Selected Steam games
* @returns Number of games imported
*/
export async function importSteamGames(games: FormattedGameInfo[]): Promise<number> {
try {
return await importSelectedSteamGames(games)
} catch (error) {
log.error('导入 Steam 游戏失败:', error)
throw error
}
}
Loading

0 comments on commit 0afd9fe

Please sign in to comment.