try to fix this spaghetti of a code
This commit is contained in:
@@ -53,6 +53,11 @@ function createHttpApp(repository, sessions, lobbies, config) {
|
||||
const users = await repository.users(); const index = users.findIndex(entry => entry.username === user.username);
|
||||
res.json({leaderboard: users.slice(0, 10), self: {...users[index], position: index + 1}});
|
||||
}));
|
||||
app.post('/easter-egg', authorized(async (req, res, user) => {
|
||||
const code = req.body?.code;
|
||||
if (!['ILIKEMONEY', 'FRETUX', 'KRISHD', 'LOSERNOOB'].includes(code)) throw new AppError('INVALID_EASTER_EGG', 'Unknown terminal command.', 400);
|
||||
res.json(await repository.redeemEasterEgg(user.username, code));
|
||||
}));
|
||||
for (const [route, type] of [['/lobby/create', 'lobby:create'], ['/lobby/join', 'lobby:join'], ['/lobby/leave', 'lobby:leave'], ['/poker/start', 'poker:start'], ['/poker/action', 'poker:action']]) {
|
||||
app.post(route, authorized(async (req, res, user) => {
|
||||
const message = {...req.body, type};
|
||||
|
||||
+43
-7
@@ -29,11 +29,11 @@ async function createRepository(filename, {beforeCommit = async () => {}} = {})
|
||||
}
|
||||
await transaction(async tx => {
|
||||
const {user_version: version} = await tx.get('PRAGMA user_version');
|
||||
if (version > 1) throw new Error('Database schema is newer than this application');
|
||||
if (version === 1) return;
|
||||
const old = await tx.get("SELECT name FROM sqlite_master WHERE type='table' AND name='users'");
|
||||
if (old) await tx.exec('ALTER TABLE users RENAME TO legacy_users');
|
||||
await tx.exec(`
|
||||
if (version > 4) throw new Error('Database schema is newer than this application');
|
||||
if (version === 0) {
|
||||
const old = await tx.get("SELECT name FROM sqlite_master WHERE type='table' AND name='users'");
|
||||
if (old) await tx.exec('ALTER TABLE users RENAME TO legacy_users');
|
||||
await tx.exec(`
|
||||
CREATE TABLE users (
|
||||
username TEXT PRIMARY KEY COLLATE NOCASE,
|
||||
password_hash TEXT NOT NULL,
|
||||
@@ -44,12 +44,28 @@ async function createRepository(filename, {beforeCommit = async () => {}} = {})
|
||||
CREATE TABLE commands (id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL, result TEXT NOT NULL, created_at INTEGER NOT NULL);
|
||||
CREATE TABLE ledger (id INTEGER PRIMARY KEY, command_id TEXT NOT NULL, username TEXT NOT NULL REFERENCES users(username), delta INTEGER NOT NULL, reason TEXT NOT NULL);
|
||||
CREATE TABLE migrations (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL);
|
||||
CREATE TABLE easter_eggs (username TEXT NOT NULL REFERENCES users(username), code TEXT NOT NULL, used_at INTEGER NOT NULL, PRIMARY KEY(username, code));
|
||||
`);
|
||||
if (old) {
|
||||
if (old) {
|
||||
// Fails and rolls back rather than silently rounding or losing invalid balances.
|
||||
await tx.exec(`INSERT INTO users(username, password_hash, money) SELECT username, password_hash, money FROM legacy_users; INSERT INTO ledger(command_id,username,delta,reason) SELECT 'schema-v1:' || username, username, money, 'Opening balance migration' FROM users; DROP TABLE legacy_users;`);
|
||||
}
|
||||
await tx.exec('PRAGMA user_version = 4');
|
||||
} else if (version === 1) {
|
||||
await tx.exec('CREATE TABLE easter_eggs (username TEXT NOT NULL REFERENCES users(username), code TEXT NOT NULL, used_at INTEGER NOT NULL, PRIMARY KEY(username, code)); PRAGMA user_version = 4');
|
||||
} else if (version === 2) {
|
||||
const broken = await tx.all("SELECT username, delta FROM ledger WHERE reason = 'Easter egg: KRISHD' AND delta < 0");
|
||||
for (const entry of broken) {
|
||||
const letters = [...entry.username].filter(character => /[a-z]/i.test(character)).length;
|
||||
const correction = -entry.delta * letters;
|
||||
if (!Number.isSafeInteger(correction)) throw new Error('Invalid KRISHD repair amount');
|
||||
await tx.run('UPDATE users SET money = money + ? WHERE username = ?', correction, entry.username);
|
||||
await tx.run('INSERT INTO ledger(command_id,username,delta,reason) VALUES(?,?,?,?)', `repair:KRISHD:${entry.username}`, entry.username, correction, 'KRISHD multiplier repair');
|
||||
}
|
||||
await tx.exec("UPDATE easter_eggs SET code = 'FRETUX' WHERE code = 'FRETUKS'; PRAGMA user_version = 4");
|
||||
} else if (version === 3) {
|
||||
await tx.exec("UPDATE easter_eggs SET code = 'FRETUX' WHERE code = 'FRETUKS'; PRAGMA user_version = 4");
|
||||
}
|
||||
await tx.exec('PRAGMA user_version = 1');
|
||||
});
|
||||
} catch (error) { await release(); await db.close(); throw error; }
|
||||
const read = work => queue.run(['database'], () => work(db));
|
||||
@@ -65,6 +81,26 @@ async function createRepository(filename, {beforeCommit = async () => {}} = {})
|
||||
catch (error) { if (error.code === 'SQLITE_CONSTRAINT') throw new AppError('USERNAME_EXISTS', 'Username already exists', 409); throw error; }
|
||||
},
|
||||
setSession: (username, sessionHash) => transaction(tx => tx.run('UPDATE users SET session_hash = ? WHERE username = ?', sessionHash, username)),
|
||||
async redeemEasterEgg(username, code) {
|
||||
const repeatable = code === 'LOSERNOOB';
|
||||
return transaction(async tx => {
|
||||
const user = await tx.get('SELECT money FROM users WHERE username = ?', username);
|
||||
if (!user) throw new AppError('USER_NOT_FOUND', 'Account no longer exists', 404);
|
||||
if (!repeatable && await tx.get('SELECT 1 FROM easter_eggs WHERE username = ? AND code = ?', username, code)) {
|
||||
throw new AppError('EASTER_EGG_USED', 'This terminal command was already used.', 409);
|
||||
}
|
||||
const multiplier = code === 'FRETUX' ? 2 : code === 'KRISHD' ? [...username].filter(character => /[a-z]/i.test(character)).length : 1;
|
||||
const next = code === 'ILIKEMONEY' ? user.money + 1000 : user.money * multiplier;
|
||||
if (!Number.isSafeInteger(next) || next < 0) throw new AppError('BALANCE_LIMIT', 'This command would exceed the chip limit.', 409);
|
||||
const delta = next - user.money;
|
||||
if (!repeatable) await tx.run('INSERT INTO easter_eggs(username,code,used_at) VALUES(?,?,?)', username, code, Date.now());
|
||||
if (delta) {
|
||||
await tx.run('UPDATE users SET money = ? WHERE username = ?', next, username);
|
||||
await tx.run('INSERT INTO ledger(command_id,username,delta,reason) VALUES(?,?,?,?)', `easter:${code}:${username}`, username, delta, `Easter egg: ${code}`);
|
||||
}
|
||||
return {balance: next, effect: repeatable ? 'matrix' : 'credits'};
|
||||
});
|
||||
},
|
||||
async recover() {
|
||||
return transaction(async tx => {
|
||||
const rows = await tx.all('SELECT id,state FROM lobbies');
|
||||
|
||||
Reference in New Issue
Block a user