mirror of
https://github.com/tiennm99/vngeoguessr.git
synced 2026-10-11 03:13:56 +00:00
npm run leaderboard:import writes a decrypted backup back to Redis. It is a dry run until --apply, prints the destination prefix first, and accepts only score and distance board keys. By default each backed-up score is set and newer players are kept; --replace rewrites each board exactly. Members go in up to 1000 per ZADD through a new zAddMany helper. docs/leaderboard-backup.md covers what the backup holds, decrypting it and restoring it. The gitignore now covers the decrypted and encrypted file names the workflow uses, not only the dated export.
52 lines
2.3 KiB
JavaScript
52 lines
2.3 KiB
JavaScript
// Write a leaderboard backup back to Redis.
|
|
//
|
|
// Usage: node scripts/import-leaderboards.mjs <backup.json> [--replace] [--apply]
|
|
// backup.json decrypted output of export-leaderboards.mjs
|
|
// --replace delete each board in the file before writing it, so it ends
|
|
// up exactly as backed up; without it each backed-up member's
|
|
// score is set and newer members are kept
|
|
// --apply actually write; without it the script only reports what it
|
|
// would do
|
|
//
|
|
// Needs the Upstash pair (UPSTASH_REDIS_REST_URL/_TOKEN or KV_REST_API_URL/
|
|
// _TOKEN) in .env or the environment, and KEY_PREFIX if the target uses one.
|
|
// This writes to whatever database those point at, usually production: run
|
|
// `npm run leaderboard:export` first so the restore itself can be undone.
|
|
|
|
import { readFileSync } from 'node:fs';
|
|
import { getUpstash } from '../src/lib/upstash.js';
|
|
import { applyEnvFile } from './lib/env.mjs';
|
|
import { parseBackup, restoreBoards } from './lib/leaderboard-restore.mjs';
|
|
|
|
applyEnvFile();
|
|
|
|
const args = process.argv.slice(2);
|
|
const file = args.find((arg) => !arg.startsWith('--'));
|
|
const replace = args.includes('--replace');
|
|
const apply = args.includes('--apply');
|
|
if (!file) {
|
|
console.error('Usage: node scripts/import-leaderboards.mjs <backup.json> [--replace] [--apply]');
|
|
process.exit(1);
|
|
}
|
|
|
|
const backup = parseBackup(readFileSync(file, 'utf8'));
|
|
const h = getUpstash();
|
|
const boardCount = Object.keys(backup.boards).length;
|
|
const memberCount = Object.values(backup.boards).reduce((sum, entries) => sum + entries.length, 0);
|
|
|
|
console.log(`Backup: ${file} (exported ${backup.exportedAt ?? 'unknown'}, prefix "${backup.prefix ?? 'unknown'}")`);
|
|
console.log(`Target: prefix "${h.prefix}"`);
|
|
console.log(`Content: ${boardCount} boards, ${memberCount} members`);
|
|
console.log(`Mode: ${replace ? 'replace (each board is deleted, then rewritten)' : 'merge (backed-up scores are set, newer members kept)'}`);
|
|
if (backup.prefix && backup.prefix !== h.prefix) {
|
|
console.log(`Note: the backup came from prefix "${backup.prefix}" and will be written under "${h.prefix}"`);
|
|
}
|
|
|
|
if (!apply) {
|
|
console.log('\nDry run, nothing written. Add --apply to write.');
|
|
process.exit(0);
|
|
}
|
|
|
|
const result = await restoreBoards(h, backup.boards, replace);
|
|
console.log(`\nRestored ${result.boards} boards, ${result.members} members.`);
|