Skip to content

Commit 72661ec

Browse files
committed
Add an action to manually check if a user is verified for a suspect
For fallbacks, mostly. Shouldn't truly be needed.
1 parent 735b408 commit 72661ec

File tree

3 files changed

+65
-40
lines changed

3 files changed

+65
-40
lines changed

src/actions.ts

+63-38
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as pathModule from 'path';
99
import * as crypto from 'crypto';
1010
import * as url from 'url';
1111
import {Config} from './config-loader';
12-
import {Ladder} from './ladder';
12+
import {Ladder, LadderEntry} from './ladder';
1313
import {Replays} from './replays';
1414
import {ActionError, QueryHandler, Server} from './server';
1515
import {Session} from './user';
@@ -80,6 +80,51 @@ const smogonFetch = async (targetUrl: string, method: string, data: {[k: string]
8080
});
8181
};
8282

83+
function checkSuspectVerified(
84+
rating: LadderEntry,
85+
suspect: {formatid: string, start_date: number},
86+
reqs: Record<string, number | null>
87+
) {
88+
let reqsMet = 0;
89+
let reqCount = 0;
90+
const userData: Partial<{elo: number, gxe: number, coil: number}> = {};
91+
for (const k in reqs) {
92+
if (!reqs[k as 'elo' | 'coil' | 'gxe']) continue;
93+
reqCount++;
94+
switch (k) {
95+
case 'coil':
96+
const N = rating.w + rating.l + rating.t;
97+
const coilNum = Math.round(40.0 * rating.gxe * Math.pow(2.0, -coil[suspect.formatid] / N));
98+
if (coilNum >= reqs.coil!) {
99+
reqsMet++;
100+
}
101+
userData.coil = coilNum;
102+
break;
103+
case 'elo': case 'gxe':
104+
if (reqs[k] && rating[k] >= reqs[k]!) {
105+
reqsMet++;
106+
}
107+
userData[k] = rating[k];
108+
break;
109+
}
110+
}
111+
if (
112+
// sanity check for reqs existing just to be totally safe
113+
(reqsMet >= 1 && reqsMet === reqCount) &&
114+
// did not play games before the test began
115+
(rating?.first_played && rating.first_played > suspect.start_date)
116+
) {
117+
void smogonFetch("tools/api/suspect-verify", "POST", {
118+
userid: rating.userid,
119+
format: suspect.formatid,
120+
reqs: {required: reqs, actual: userData},
121+
suspectStartDate: suspect.start_date,
122+
});
123+
return true;
124+
}
125+
return false;
126+
}
127+
83128
export const actions: {[k: string]: QueryHandler} = {
84129
async register(params) {
85130
this.verifyCrossDomainRequest();
@@ -372,43 +417,7 @@ export const actions: {[k: string]: QueryHandler} = {
372417
if (suspect) {
373418
const reqs = {elo: suspect.elo, gxe: suspect.gxe, coil: suspect.gxe};
374419
for (const rating of [p1rating, p2rating]) {
375-
let reqsMet = 0;
376-
let reqCount = 0;
377-
const userData: Partial<{elo: number, gxe: number, coil: number}> = {};
378-
for (const k in reqs) {
379-
if (!reqs[k as 'elo' | 'coil' | 'gxe']) continue;
380-
reqCount++;
381-
switch (k) {
382-
case 'coil':
383-
const N = rating.w + rating.l + rating.t;
384-
const coilNum = Math.round(40.0 * rating.gxe * Math.pow(2.0, -coil[formatid] / N));
385-
if (coilNum >= reqs.coil!) {
386-
reqsMet++;
387-
}
388-
userData.coil = coilNum;
389-
break;
390-
case 'elo': case 'gxe':
391-
if (reqs[k] && rating[k] >= reqs[k]!) {
392-
reqsMet++;
393-
}
394-
userData[k] = rating[k];
395-
break;
396-
}
397-
}
398-
const ratingData = await ladder.getRating(rating.userid);
399-
if (
400-
// sanity check for reqs existing just to be totally safe
401-
(reqsMet >= 1 && reqsMet === reqCount) &&
402-
// did not play games before the test began
403-
(ratingData?.first_played && ratingData.first_played > suspect.start_date)
404-
) {
405-
void smogonFetch("tools/api/suspect-verify", "POST", {
406-
userid: rating.userid,
407-
format: formatid,
408-
reqs: {required: reqs, actual: userData},
409-
suspectStartDate: suspect.start_date,
410-
});
411-
}
420+
checkSuspectVerified(rating, suspect, reqs);
412421
}
413422
}
414423
out.actionsuccess = true;
@@ -1076,6 +1085,22 @@ export const actions: {[k: string]: QueryHandler} = {
10761085
await tables.suspects.delete(id);
10771086
return {success: true};
10781087
},
1088+
async 'suspects/verify'(params) {
1089+
if (this.getIp() !== Config.restartip) {
1090+
throw new ActionError("Access denied.");
1091+
}
1092+
const id = toID(params.format);
1093+
if (!id) throw new ActionError("No format ID specified.");
1094+
const suspect = await tables.suspects.get(id);
1095+
if (!suspect) throw new ActionError("There is no ongoing suspect for " + id);
1096+
const userid = toID(params.userid);
1097+
if (!userid || userid.length > 18) throw new ActionError("Invalid userid Pprovided.");
1098+
const rating = await tables.ladder.get(userid);
1099+
if (!rating) throw new ActionError("That user has no ratings in the given ladder.");
1100+
return {
1101+
result: checkSuspectVerified(rating, suspect, {elo: suspect.elo, coil: suspect.coil, gxe: suspect.gxe}),
1102+
};
1103+
},
10791104
};
10801105

10811106
if (Config.actions) {

src/schemas/ntbb-suspects.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
-- Unfortunately necessary to be a table in order to properly synchronize
33
-- cross-processes
44

5-
CREATE TABLE ntbb_suspects (
5+
CREATE TABLE `ntbb_suspects` (
66
formatid varchar(100) NOT NULL PRIMARY KEY,
77
start_date bigint(20) NOT NULL,
88
elo int,

src/tables.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,4 @@ export const suspects = psdb.getTable<{
149149
coil: number | null;
150150
gxe: number | null;
151151
elo: number | null;
152-
}>("ntbb_suspects", 'formatid');
152+
}>("suspects", 'formatid');

0 commit comments

Comments
 (0)