Add the plebleader daily sync and package the archive CLI
`sync` refreshes the token chain first, then fetches new BeatLeader and ScoreSaber scores (with a day of overlap), their replays, score stats, leaderboards and map zips, and re-snapshots every played hash on Sundays. The flake's plebleader-archive package runs the CLI with Node's type stripping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,10 +26,10 @@ export async function exportSSPlayer(playerId: string): Promise<void> {
|
||||
console.log(`ScoreSaber player ${playerId}: ${saveSnapshotIfChanged(ss(playerId, 'player'), r.body) ? 'saved' : 'unchanged'}`);
|
||||
}
|
||||
|
||||
/** Page `sort=recent` until scores are older than `sinceUnix`. */
|
||||
export async function exportSSScores(playerId: string, sinceUnix: number): Promise<void> {
|
||||
/** Page `sort=recent` until scores are older than `sinceUnix`. Returns the new items. */
|
||||
export async function exportSSScores(playerId: string, sinceUnix: number): Promise<SSItem[]> {
|
||||
console.log(`ScoreSaber scores for ${playerId} since ${new Date(sinceUnix * 1000).toISOString()}`);
|
||||
let added = 0;
|
||||
const added: SSItem[] = [];
|
||||
let seen = 0;
|
||||
for (let page = 1; ; page++) {
|
||||
const r = await get(`${SS_API}/player/${playerId}/scores?limit=100&page=${page}&sort=recent`, { limiter: limiters.scoresaber });
|
||||
@@ -44,12 +44,18 @@ export async function exportSSScores(playerId: string, sinceUnix: number): Promi
|
||||
const file = ss(playerId, 'scores', `${item.score.id}.json`);
|
||||
if (exists(file)) continue;
|
||||
save(file, JSON.stringify(item));
|
||||
added++;
|
||||
added.push(item);
|
||||
}
|
||||
console.log(` page ${page}: ${seen} in window, ${added} new (total on server ${json.metadata.total})`);
|
||||
console.log(` page ${page}: ${seen} in window, ${added.length} new (total on server ${json.metadata.total})`);
|
||||
if (reachedCutoff || json.playerScores.length < 100) break;
|
||||
}
|
||||
updateState(`scoresaber:${playerId}`, { scoresSince: sinceUnix, lastScoresRun: new Date().toISOString() });
|
||||
return added;
|
||||
}
|
||||
|
||||
/** Newest archived ScoreSaber score time for a player (unix seconds), 0 when there is none. */
|
||||
export function newestSSScoreTime(playerId: string): number {
|
||||
return archivedSSScores(playerId).reduce((max, it) => Math.max(max, Math.floor(Date.parse(it.score.timeSet) / 1000)), 0);
|
||||
}
|
||||
|
||||
/** Download replays for archived scores with hasReplay, oldest first, ~10.5 s apart. */
|
||||
|
||||
Reference in New Issue
Block a user