Skip to content

Commit 3abc82c

Browse files
committed
feat: Use addnonce over addjson
1 parent 61f68cc commit 3abc82c

4 files changed

Lines changed: 33 additions & 35 deletions

File tree

src/cache/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const PSCronJobs: { manager: PSCronJobManager | null } = { manager: null
2121
export const PSNoPrefixHelp: { [key: string]: Date } = {};
2222
export const PSQuoteRoomPrefs: { [key: string]: { room: string; at: Date } } = {};
2323
export const PSKuncInProgress: { [key: string]: boolean } = {};
24+
export const PSPointsNonce: { [key: string]: Record<string, Record<string, number>> | null } = {};
2425

2526
// Games
2627
export const PSGames: { [key in keyof Games]?: Record<string, CommonGame> } = {};

src/ps/commands/points.tsx

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import assert from 'node:assert';
21
import { uploadToPastie } from 'ps-client/tools';
32

4-
import { PSRoomConfigs } from '@/cache';
3+
import { PSPointsNonce, PSRoomConfigs } from '@/cache';
54
import {
65
type BulkPointsDataInput,
76
type Model as PointsModel,
@@ -137,9 +136,9 @@ export const command: PSCommand[] = [
137136
},
138137
},
139138
{
140-
name: 'addjson',
139+
name: 'addnonce',
141140
help: null,
142-
syntax: 'CMD [json data]',
141+
syntax: 'CMD [nonce]',
143142
perms: 'driver',
144143
flags: { conceal: true, noDisplay: true, routePMs: true },
145144
categories: ['points'],
@@ -149,39 +148,27 @@ export const command: PSCommand[] = [
149148
const roomConfig = PSRoomConfigs[message.target.id];
150149
if (!roomConfig.points) throw new ChatError($T('COMMANDS.POINTS.ROOM_NO_POINTS', { room: message.target.title }));
151150

152-
let json;
153-
try {
154-
json = JSON.parse(arg);
155-
} catch {
156-
throw new ChatError('Invalid JSON.' as ToTranslate);
157-
}
158-
try {
159-
// TODO: Maybe use zod here?
160-
assert.equal(typeof json, 'object');
161-
assert.equal(Array.isArray(json), false);
162-
Object.entries(json).forEach(([user, value]) => {
163-
assert.ok(toId(user));
164-
assert.equal(typeof value, 'object');
165-
assert.equal(Array.isArray(value), false);
166-
Object.entries(value!).forEach(([type, amount]) => {
167-
assert(roomConfig.points?.types[type]);
168-
assert.equal(typeof amount, 'number');
169-
assert.equal(Math.round(amount), amount);
170-
});
171-
});
172-
} catch {
173-
throw new ChatError($T('INVALID_ARGUMENTS'));
174-
}
151+
const nonce = arg.trim();
152+
if (!nonce) throw new ChatError('Nonce not provided.' as ToTranslate);
153+
const data = PSPointsNonce[nonce];
154+
155+
if (data === null) throw new ChatError(`Already added points for ${nonce}!` as ToTranslate);
156+
if (!data) throw new ChatError(`Invalid nonce ${nonce}.` as ToTranslate);
175157

176-
const data: Record<string, Record<string, number>> = json;
177158
const pointsData: BulkPointsDataInput = Object.fromEntries(
178159
Object.entries(data).map(([name, points]) => {
179160
const id = toId(name);
180161
return [id, { id, name, points }];
181162
})
182163
);
183164

184-
await bulkAddPoints(pointsData, message.target.id);
165+
PSPointsNonce[nonce] = null;
166+
try {
167+
await bulkAddPoints(pointsData, message.target.id);
168+
} catch (err) {
169+
PSPointsNonce[nonce] = data;
170+
throw err;
171+
}
185172
broadcast('Added points!' as ToTranslate);
186173
},
187174
},

src/ps/handlers/tours.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { Temporal } from '@js-temporal/polyfill';
22

3-
import { PSRoomConfigs } from '@/cache';
3+
import { PSPointsNonce, PSRoomConfigs } from '@/cache';
44
import { prefix } from '@/config/ps';
55
import { bulkAddPoints } from '@/database/points';
66
import { TimeZone } from '@/ps/handlers/cron/constants';
77
import getSecretFunction from '@/secrets/functions';
8-
import { Button } from '@/utils/components/ps';
8+
import { Button, Form } from '@/utils/components/ps';
99
import { errorLog } from '@/utils/logger';
1010

1111
import type { Client } from 'ps-client';
12+
import { randomString } from '@/utils/random';
1213

1314
export type BracketNode = {
1415
team: string;
@@ -146,9 +147,12 @@ export function tourHandler(this: Client, roomId: string, line: string, isIntro?
146147
return;
147148
}
148149

149-
const jsonData: Record<string, Record<string, number>> = Object.fromEntries(
150+
const nonce = randomString();
151+
// TODO: Add mapValues
152+
PSPointsNonce[nonce] = Object.fromEntries(
150153
Object.entries(pointsToAdd).map(([user, amount]) => [user, { [pointsType.id]: amount }])
151154
);
155+
152156
room.sendHTML(
153157
<div className="infobox">
154158
<p>
@@ -158,9 +162,9 @@ export function tourHandler(this: Client, roomId: string, line: string, isIntro?
158162
.join(', ')}
159163
</p>
160164
<p>
161-
<Button name="send" value={`/botmsg ${this.status.username},${prefix}@${roomId} addjson ${JSON.stringify(jsonData)}`}>
162-
Add Points!
163-
</Button>
165+
<Form value={`/botmsg ${this.status.username},${prefix}@${roomId} addnonce ${nonce}`}>
166+
<button>Add Points!</button>
167+
</Form>
164168
</p>
165169
</div>
166170
);

src/utils/random.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ function sample(input: null | number | [number, number] | Record<string, number>
4646
}
4747

4848
export { sample };
49+
50+
export function randomString(length = 16, rng?: RNGSource): string {
51+
const RNG = useRNG(rng);
52+
const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.split('');
53+
return Array.from({ length }, () => validChars.random(RNG)).join('');
54+
}

0 commit comments

Comments
 (0)