All checks were successful
Deploy production / deploy (push) Successful in 1m6s
98 lines
3.2 KiB
TypeScript
98 lines
3.2 KiB
TypeScript
import { pollFaceit } from './faceit';
|
|
import { pollLeetify } from './leetify';
|
|
import { pollPubg } from './pubg';
|
|
import { pollSteamShareCodes } from './steam';
|
|
import { pollUbisoft } from './ubisoft';
|
|
import { hoursSince } from './store';
|
|
import type { Account, Db, GameEnv, RunOptions, SourceResult } from './types';
|
|
|
|
// One ingest pass over every enabled games.accounts row. Order matters: Leetify first so the
|
|
// Steam share-code chain can start from a code Leetify gave us.
|
|
export const SOURCE_ORDER = ['leetify', 'faceit', 'steam', 'pubg', 'ubisoft'] as const;
|
|
/** Minimum hours between polls per source (the poller ticks every 20 minutes). */
|
|
const DUE_HOURS: Record<string, number> = {
|
|
leetify: 0.3,
|
|
faceit: 6,
|
|
steam: 0.3,
|
|
pubg: 0.3,
|
|
ubisoft: 0.3
|
|
};
|
|
|
|
/** Which keys each source needs; shown (names only) on the owner's view of the pages. */
|
|
export function missingKeys(env: GameEnv): Record<string, string[]> {
|
|
const need = (...k: (keyof GameEnv)[]) => k.filter((x) => !env[x]);
|
|
return {
|
|
leetify: [],
|
|
faceit: [],
|
|
steam: need('STEAM_WEB_API_KEY', 'CS2_AUTH_CODE'),
|
|
pubg: need('PUBG_API_KEY'),
|
|
ubisoft: need('UBI_EMAIL', 'UBI_PASSWORD')
|
|
};
|
|
}
|
|
|
|
export async function runIngest(
|
|
sql: Db,
|
|
env: GameEnv,
|
|
opts: RunOptions = {}
|
|
): Promise<SourceResult[]> {
|
|
const accounts = await sql<Account[]>`
|
|
select id, game, source, external_id as "externalId", name, state, last_success_at as "lastSuccessAt"
|
|
from games.accounts where enabled order by id`;
|
|
const results: SourceResult[] = [];
|
|
for (const source of SOURCE_ORDER) {
|
|
if (opts.only?.length && !opts.only.includes(source)) continue;
|
|
for (const account of accounts.filter((a) => a.source === source)) {
|
|
const label = account.name ?? account.externalId;
|
|
if (!opts.backfill && !opts.force && hoursSince(account.lastSuccessAt) < DUE_HOURS[source])
|
|
continue;
|
|
if (missingKeys(env)[source]?.length) {
|
|
results.push({
|
|
game: account.game,
|
|
source,
|
|
account: label,
|
|
status: 'skipped',
|
|
added: 0,
|
|
note: `needs ${missingKeys(env)[source].join(', ')}`
|
|
});
|
|
continue;
|
|
}
|
|
await sql`update games.accounts set last_polled_at = now() where id = ${account.id}`;
|
|
try {
|
|
const r =
|
|
source === 'leetify'
|
|
? await pollLeetify(sql, account, env, opts)
|
|
: source === 'faceit'
|
|
? await pollFaceit(sql, account, opts)
|
|
: source === 'steam'
|
|
? await pollSteamShareCodes(sql, account, env)
|
|
: source === 'pubg'
|
|
? await pollPubg(sql, account, env, opts)
|
|
: await pollUbisoft(sql, account, env, opts);
|
|
const skipped = 'skipped' in r && r.skipped;
|
|
if (!skipped)
|
|
await sql`update games.accounts set last_success_at = now(), last_error = null where id = ${account.id}`;
|
|
results.push({
|
|
game: account.game,
|
|
source,
|
|
account: label,
|
|
status: skipped ? 'skipped' : 'ok',
|
|
added: 'added' in r ? (r.added ?? 0) : 0,
|
|
note: r.note
|
|
});
|
|
} catch (e) {
|
|
const message = (e as Error).message.slice(0, 300);
|
|
await sql`update games.accounts set last_error = ${message} where id = ${account.id}`;
|
|
results.push({
|
|
game: account.game,
|
|
source,
|
|
account: label,
|
|
status: 'error',
|
|
added: 0,
|
|
note: message
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|