Skip to content

Commit bbed564

Browse files
committed
feat: standalone@3.0.4
1 parent 632ee01 commit bbed564

7 files changed

Lines changed: 43 additions & 40 deletions

File tree

standalone/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cap-standalone",
3-
"version": "3.0.3",
3+
"version": "3.0.4",
44
"keywords": [
55
"algorithm",
66
"anti-abuse",

standalone/public/js/dashboard.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,8 @@ function renderKeyDetail() {
319319
<div class="stat-item">
320320
<div class="stat-bar red"></div>
321321
<div class="stat-label">Failed</div>
322-
<div class="stat-value" id="statFailed">${formatCompact(Math.max(0, (s.challenges || 0) - (s.verified || 0)))}</div>
323-
<div id="trendFailed">${trendHtml(Math.max(0, (s.challenges || 0) - (s.verified || 0)), key.prevStats ? Math.max(0, (key.prevStats.challenges || 0) - (key.prevStats.verified || 0)) : null)}</div>
322+
<div class="stat-value" id="statFailed">${formatCompact(s.failed || 0)}</div>
323+
<div id="trendFailed">${trendHtml(s.failed, key.prevStats?.failed)}</div>
324324
</div>
325325
<div class="stat-item">
326326
<div class="stat-bar purple"></div>
@@ -903,7 +903,7 @@ function renderChart(chartData) {
903903
datasets: [
904904
mkDataset("Challenges", "challenges", "#89b4fa"),
905905
mkDataset("Verified", "verified", "#a6e3a1"),
906-
mkDataset("Failed", (d) => Math.max(0, (d.challenges || 0) - (d.verified || 0)), "#f38ba8"),
906+
mkDataset("Failed", "failed", "#f38ba8"),
907907
],
908908
},
909909
options: {

standalone/src/cap.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,6 @@ export const capServer = new Elysia({
360360
const bucket = hourlyBucket();
361361
const fnf = (p) => { p.catch(() => {}); };
362362

363-
fnf(db.hincrby(`metrics:challenges:${params.siteKey}`, bucket, 1));
364-
365363
(async () => {
366364
if (!ip) return;
367365
const cachedHeaders = getHeaders();
@@ -625,7 +623,7 @@ export const capServer = new Elysia({
625623
await db.set(`token:${redeemToken}`, String(tokenExpires));
626624
await db.expire(`token:${redeemToken}`, tokenTtlSecs);
627625

628-
await db.hincrby(`solutions:${params.siteKey}`, bucket, 1);
626+
await db.hincrby(`metrics:verified:${params.siteKey}`, bucket, 1);
629627

630628
if (payload.iat) {
631629
const latencyMs = Date.now() - payload.iat;

standalone/src/demo.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ function generateChartData(rng, key, duration) {
302302

303303
let totalChallenges = 0;
304304
let totalVerified = 0;
305+
let totalFailed = 0;
305306
let totalLatSum = 0;
306307
let totalLatCount = 0;
307308
let totalRateLimited = 0;
@@ -323,24 +324,27 @@ function generateChartData(rng, key, duration) {
323324
const challenges = Math.max(0, Math.round(base * jitter));
324325
const failRate = key.failRate * (1 + (rng() - 0.5) * 0.6);
325326
const verified = Math.max(0, Math.round(challenges * (1 - failRate)));
327+
const failed = Math.max(0, challenges - verified);
326328
const rateLimited = Math.round(challenges * (0.005 + rng() * 0.015));
327329
const avgLatency = Math.round(2000 + rng() * 6000);
328330

329331
totalChallenges += challenges;
330332
totalVerified += verified;
333+
totalFailed += failed;
331334
totalRateLimited += rateLimited;
332335
if (challenges > 0) {
333336
totalLatSum += avgLatency * challenges;
334337
totalLatCount += challenges;
335338
}
336339

337-
data.push({ bucket, challenges, verified, rateLimited });
340+
data.push({ bucket, challenges, verified, failed, rateLimited });
338341
}
339342

340343
return {
341344
stats: {
342345
challenges: totalChallenges,
343346
verified: totalVerified,
347+
failed: totalFailed,
344348
rateLimited: totalRateLimited,
345349
avgLatency: totalLatCount > 0 ? Math.round(totalLatSum / totalLatCount) : 0,
346350
},
@@ -426,6 +430,7 @@ export function demoGetKey(siteKey, chartDuration = "today") {
426430
prevStats = {
427431
challenges: Math.round(stats.challenges * (0.7 + prevRng() * 0.6)),
428432
verified: Math.round(stats.verified * (0.7 + prevRng() * 0.6)),
433+
failed: Math.round(stats.failed * (0.7 + prevRng() * 0.6)),
429434
avgLatency: Math.round(stats.avgLatency * (0.8 + prevRng() * 0.4)),
430435
rateLimited: Math.round(stats.rateLimited * (0.5 + prevRng() * 1.0)),
431436
};

standalone/src/server.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const server = new Elysia({
9292

9393
return await Promise.all(
9494
keys.map(async (key) => {
95-
const data = await hgetall(`solutions:${key.siteKey}`);
95+
const data = await hgetall(`metrics:verified:${key.siteKey}`);
9696
const current = sumSolutions(data, currentStart);
9797
const previous = sumSolutions(data, previousStart, currentStart);
9898

@@ -249,9 +249,9 @@ export const server = new Elysia({
249249
prevStartTime = startTime - periodLen;
250250
}
251251

252-
const [challengesH, verifiedH, ratelimitedH, latSumH, latCountH] = await Promise.all([
253-
hgetall(`metrics:challenges:${sk}`),
252+
const [verifiedH, failedH, ratelimitedH, latSumH, latCountH] = await Promise.all([
254253
hgetall(`metrics:verified:${sk}`),
254+
hgetall(`metrics:failed:${sk}`),
255255
hgetall(`metrics:ratelimited:${sk}`),
256256
hgetall(`metrics:latency_sum:${sk}`),
257257
hgetall(`metrics:latency_count:${sk}`),
@@ -280,8 +280,8 @@ export const server = new Elysia({
280280

281281
const chartData = [];
282282
if (bucketSize === day) {
283-
const chM = aggregateDaily(challengesH, startTime, endTime);
284283
const veM = aggregateDaily(verifiedH, startTime, endTime);
284+
const faM = aggregateDaily(failedH, startTime, endTime);
285285
const rlM = aggregateDaily(ratelimitedH, startTime, endTime);
286286

287287
const numDays =
@@ -296,20 +296,26 @@ export const server = new Elysia({
296296
const currentDayStart = Math.floor(now / day) * day;
297297
for (let i = 0; i < numDays; i++) {
298298
const b = currentDayStart - (numDays - 1 - i) * day;
299+
const verified = veM.get(b) || 0;
300+
const failed = faM.get(b) || 0;
299301
chartData.push({
300302
bucket: b,
301-
challenges: chM.get(b) || 0,
302-
verified: veM.get(b) || 0,
303+
challenges: verified + failed,
304+
verified,
305+
failed,
303306
rateLimited: rlM.get(b) || 0,
304307
});
305308
}
306309
} else {
307-
const allBuckets = new Set([...chM.keys(), ...veM.keys(), ...rlM.keys()]);
310+
const allBuckets = new Set([...veM.keys(), ...faM.keys(), ...rlM.keys()]);
308311
for (const b of [...allBuckets].sort((a, c) => a - c)) {
312+
const verified = veM.get(b) || 0;
313+
const failed = faM.get(b) || 0;
309314
chartData.push({
310315
bucket: b,
311-
challenges: chM.get(b) || 0,
312-
verified: veM.get(b) || 0,
316+
challenges: verified + failed,
317+
verified,
318+
failed,
313319
rateLimited: rlM.get(b) || 0,
314320
});
315321
}
@@ -320,32 +326,36 @@ export const server = new Elysia({
320326
for (let h = startHour; h <= endHour; h++) {
321327
const b = h * 3600;
322328
const bs = String(b);
329+
const verified = Number(verifiedH[bs] || 0);
330+
const failed = Number(failedH[bs] || 0);
323331
chartData.push({
324332
bucket: b,
325-
challenges: Number(challengesH[bs] || 0),
326-
verified: Number(verifiedH[bs] || 0),
333+
challenges: verified + failed,
334+
verified,
335+
failed,
327336
rateLimited: Number(ratelimitedH[bs] || 0),
328337
});
329338
}
330339
}
331340

332-
const totalChallenges = sumRange(challengesH, startTime, endTime);
333341
const totalVerified = sumRange(verifiedH, startTime, endTime);
342+
const totalFailed = sumRange(failedH, startTime, endTime);
334343
const totalRateLimited = sumRange(ratelimitedH, startTime, endTime);
335344
const totalLatSum = sumRange(latSumH, startTime, endTime);
336345
const totalLatCount = sumRange(latCountH, startTime, endTime);
337346
const avgLatency = totalLatCount > 0 ? Math.round(totalLatSum / totalLatCount) : 0;
338347

339348
let prevStats = null;
340349
if (prevStartTime !== null) {
341-
const pChallenges = sumRange(challengesH, prevStartTime, prevEndTime);
342350
const pVerified = sumRange(verifiedH, prevStartTime, prevEndTime);
351+
const pFailed = sumRange(failedH, prevStartTime, prevEndTime);
343352
const pRateLimited = sumRange(ratelimitedH, prevStartTime, prevEndTime);
344353
const pLatSum = sumRange(latSumH, prevStartTime, prevEndTime);
345354
const pLatCount = sumRange(latCountH, prevStartTime, prevEndTime);
346355
prevStats = {
347-
challenges: pChallenges,
356+
challenges: pVerified + pFailed,
348357
verified: pVerified,
358+
failed: pFailed,
349359
avgLatency: pLatCount > 0 ? Math.round(pLatSum / pLatCount) : 0,
350360
rateLimited: pRateLimited,
351361
};
@@ -359,8 +369,9 @@ export const server = new Elysia({
359369
config: JSON.parse(key.config),
360370
},
361371
stats: {
362-
challenges: totalChallenges,
372+
challenges: totalVerified + totalFailed,
363373
verified: totalVerified,
374+
failed: totalFailed,
364375
avgLatency,
365376
rateLimited: totalRateLimited,
366377
},
@@ -492,8 +503,6 @@ export const server = new Elysia({
492503
const sk = params.siteKey;
493504
await Promise.all([
494505
db.del(`key:${sk}`),
495-
db.del(`solutions:${sk}`),
496-
db.del(`metrics:challenges:${sk}`),
497506
db.del(`metrics:verified:${sk}`),
498507
db.del(`metrics:failed:${sk}`),
499508
db.del(`metrics:ratelimited:${sk}`),

standalone/src/siteverify.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ import { Elysia } from "elysia";
44
import { db } from "./db.js";
55
import { checkCorsOrigin } from "./settings-cache.js";
66

7-
function hourlyBucket() {
8-
return String(Math.floor(Date.now() / 1000 / 3600) * 3600);
9-
}
10-
117
export const siteverifyServer = new Elysia({
128
detail: {
139
tags: ["Challenges"],
@@ -60,16 +56,13 @@ export const siteverifyServer = new Elysia({
6056

6157
if (!expires) {
6258
set.status = 404;
63-
await db.hincrby(`metrics:failed:${sitekey}`, hourlyBucket(), 1);
6459
return { success: false, error: "Token not found" };
6560
}
6661

6762
if (Number(expires) < Date.now()) {
6863
set.status = 403;
69-
await db.hincrby(`metrics:failed:${sitekey}`, hourlyBucket(), 1);
7064
return { success: false, error: "Token expired" };
7165
}
7266

73-
await db.hincrby(`metrics:verified:${sitekey}`, hourlyBucket(), 1);
7467
return { success: true };
7568
});

standalone/src/static.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const resolveSafePath = (rel) => {
1818

1919
export const publicStatic = new Elysia().get(
2020
"/public/*",
21-
async ({ cookie, set, request, redirect }) => {
21+
async ({ cookie, set, request, redirect, headers }) => {
2222
const rawPath = new URL(request.url).pathname.replace(/^\/public\/?/, "");
2323
let rel;
2424
try {
@@ -39,7 +39,7 @@ export const publicStatic = new Elysia().get(
3939

4040
if (!allowUnauthed && !authed) {
4141
set.status = 401;
42-
redirect("/")
42+
redirect("/");
4343
return { success: false, error: "Unauthorized" };
4444
}
4545

@@ -49,12 +49,10 @@ export const publicStatic = new Elysia().get(
4949
return { success: false, error: "Not found" };
5050
}
5151

52-
set.headers["Cache-Control"] = allowUnauthed
53-
? "public, max-age=86400"
54-
: "private, max-age=3600";
55-
set.headers["X-Content-Type-Options"] = "nosniff";
56-
set.headers["Content-Type"] = f.type || "application/octet-stream";
52+
headers["content-type"] = f.type || "application/octet-stream";
53+
headers["cache-control"] = allowUnauthed ? "public, max-age=86400" : "private, max-age=3600";
54+
headers["x-content-type-options"] = "nosniff";
5755

58-
return new Response(f);
56+
return f;
5957
},
6058
);

0 commit comments

Comments
 (0)