whoburnedmore 0.9.8 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +84 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -167,11 +167,40 @@ async function devicePoll(deviceCode) {
|
|
|
167
167
|
}
|
|
168
168
|
return body;
|
|
169
169
|
}
|
|
170
|
+
async function refreshCliToken(anonKey) {
|
|
171
|
+
try {
|
|
172
|
+
const { status, body } = await post("/v1/auth/cli/refresh", { anonKey });
|
|
173
|
+
if (status === 200 && typeof body.token === "string" && body.token) {
|
|
174
|
+
return { token: body.token, handle: body.handle ?? "" };
|
|
175
|
+
}
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
async function bindDeviceKey(token, anonKey) {
|
|
181
|
+
try {
|
|
182
|
+
const { status } = await post(
|
|
183
|
+
"/v1/me/devices/bind",
|
|
184
|
+
{ anonKey },
|
|
185
|
+
token
|
|
186
|
+
);
|
|
187
|
+
return status === 200 || status === 409;
|
|
188
|
+
} catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
170
192
|
async function submit(token, payload) {
|
|
171
193
|
const { status, body } = await post("/v1/submit", payload, token);
|
|
172
194
|
if (status === 401) throw new UnauthorizedError();
|
|
173
195
|
if (status !== 200) {
|
|
174
196
|
const err = body;
|
|
197
|
+
if (status === 403 && err.error === "account blocked") {
|
|
198
|
+
const reason = err.reason ? `
|
|
199
|
+
Reason: ${err.reason}` : "";
|
|
200
|
+
const appeal = err.appealUrl ? `
|
|
201
|
+
If you think this is a mistake, appeal at: ${err.appealUrl}` : "";
|
|
202
|
+
throw new Error(`Your account is blocked.${reason}${appeal}`);
|
|
203
|
+
}
|
|
175
204
|
const details = err.details?.length ? `
|
|
176
205
|
- ${err.details.join("\n - ")}` : "";
|
|
177
206
|
throw new Error(`${err.error ?? `submit failed (HTTP ${status})`}${details}`);
|
|
@@ -260,6 +289,9 @@ function loadConfig(dir = defaultConfigDir()) {
|
|
|
260
289
|
if (typeof parsed.launchNotificationDeliveredAt === "number" && Number.isFinite(parsed.launchNotificationDeliveredAt)) {
|
|
261
290
|
config.launchNotificationDeliveredAt = parsed.launchNotificationDeliveredAt;
|
|
262
291
|
}
|
|
292
|
+
if (typeof parsed.deviceBoundAt === "number" && Number.isFinite(parsed.deviceBoundAt)) {
|
|
293
|
+
config.deviceBoundAt = parsed.deviceBoundAt;
|
|
294
|
+
}
|
|
263
295
|
return Object.keys(config).length > 0 ? config : null;
|
|
264
296
|
} catch {
|
|
265
297
|
return null;
|
|
@@ -295,6 +327,10 @@ function recordSync(dir = defaultConfigDir(), when = Date.now()) {
|
|
|
295
327
|
const config = loadConfig(dir) ?? {};
|
|
296
328
|
saveConfig(dir, { ...config, lastSyncAt: when });
|
|
297
329
|
}
|
|
330
|
+
function recordDeviceBound(dir = defaultConfigDir(), when = Date.now()) {
|
|
331
|
+
const config = loadConfig(dir) ?? {};
|
|
332
|
+
saveConfig(dir, { ...config, deviceBoundAt: when });
|
|
333
|
+
}
|
|
298
334
|
function saveAuth(dir = defaultConfigDir(), auth = { cliToken: "" }) {
|
|
299
335
|
const config = loadConfig(dir) ?? {};
|
|
300
336
|
saveConfig(dir, { ...config, cliToken: auth.cliToken, handle: auth.handle });
|
|
@@ -7036,7 +7072,6 @@ var OrgSettingsInput = external_exports.object({
|
|
|
7036
7072
|
name: external_exports.string().min(1).max(120).optional(),
|
|
7037
7073
|
description: external_exports.string().max(2e3).nullable().optional(),
|
|
7038
7074
|
accentColor: HexColor.optional(),
|
|
7039
|
-
logoUrl: external_exports.string().url().max(500).nullable().optional(),
|
|
7040
7075
|
boardVisibility: OrgBoardVisibility.optional(),
|
|
7041
7076
|
window: OrgWindow.optional(),
|
|
7042
7077
|
joinPolicy: OrgJoinPolicy.partial().optional()
|
|
@@ -8281,6 +8316,12 @@ async function run(flags) {
|
|
|
8281
8316
|
const canSignIn = !flags.quiet && Boolean(process.stdout.isTTY);
|
|
8282
8317
|
if (cfg?.cliToken) {
|
|
8283
8318
|
await submitSignedIn(cfg.cliToken, payload, flags, canSignIn);
|
|
8319
|
+
return;
|
|
8320
|
+
}
|
|
8321
|
+
const healed = cfg?.anonKey ? await refreshCliToken(cfg.anonKey) : null;
|
|
8322
|
+
if (healed) {
|
|
8323
|
+
saveAuth(void 0, { cliToken: healed.token, handle: healed.handle });
|
|
8324
|
+
await submitSignedIn(healed.token, payload, flags, canSignIn);
|
|
8284
8325
|
} else if (canSignIn) {
|
|
8285
8326
|
const auth = await ensureSignedIn();
|
|
8286
8327
|
if (!auth) return;
|
|
@@ -8299,6 +8340,11 @@ async function run(flags) {
|
|
|
8299
8340
|
function sleep(ms) {
|
|
8300
8341
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
8301
8342
|
}
|
|
8343
|
+
async function refreshCliTokenFromConfig() {
|
|
8344
|
+
const cfg = loadConfig();
|
|
8345
|
+
if (!cfg?.anonKey) return null;
|
|
8346
|
+
return refreshCliToken(cfg.anonKey);
|
|
8347
|
+
}
|
|
8302
8348
|
async function ensureSignedIn() {
|
|
8303
8349
|
const cfg = loadConfig();
|
|
8304
8350
|
if (cfg?.cliToken) return { token: cfg.cliToken, handle: cfg.handle ?? "" };
|
|
@@ -8338,16 +8384,25 @@ async function ensureSignedIn() {
|
|
|
8338
8384
|
return null;
|
|
8339
8385
|
}
|
|
8340
8386
|
async function submitSignedIn(token, payload, flags, interactive) {
|
|
8387
|
+
let activeToken = token;
|
|
8341
8388
|
let result;
|
|
8342
8389
|
try {
|
|
8343
8390
|
result = await submit(token, payload);
|
|
8344
8391
|
} catch (err) {
|
|
8345
8392
|
if (err instanceof UnauthorizedError) {
|
|
8346
|
-
|
|
8347
|
-
if (
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8393
|
+
const healed = await refreshCliTokenFromConfig();
|
|
8394
|
+
if (healed) {
|
|
8395
|
+
saveAuth(void 0, { cliToken: healed.token, handle: healed.handle });
|
|
8396
|
+
activeToken = healed.token;
|
|
8397
|
+
result = await submit(healed.token, payload);
|
|
8398
|
+
} else {
|
|
8399
|
+
clearAuth();
|
|
8400
|
+
if (!interactive) return;
|
|
8401
|
+
const auth = await ensureSignedIn();
|
|
8402
|
+
if (!auth) return;
|
|
8403
|
+
activeToken = auth.token;
|
|
8404
|
+
result = await submit(auth.token, payload);
|
|
8405
|
+
}
|
|
8351
8406
|
} else {
|
|
8352
8407
|
throw err;
|
|
8353
8408
|
}
|
|
@@ -8356,6 +8411,14 @@ async function submitSignedIn(token, payload, flags, interactive) {
|
|
|
8356
8411
|
recordSync();
|
|
8357
8412
|
} catch {
|
|
8358
8413
|
}
|
|
8414
|
+
try {
|
|
8415
|
+
const cfgNow = loadConfig();
|
|
8416
|
+
if (!cfgNow?.deviceBoundAt) {
|
|
8417
|
+
const key = ensureAnonKey();
|
|
8418
|
+
if (await bindDeviceKey(activeToken, key)) recordDeviceBound();
|
|
8419
|
+
}
|
|
8420
|
+
} catch {
|
|
8421
|
+
}
|
|
8359
8422
|
const baseUrl = result.orgBoardUrl ?? result.boardUrl ?? result.profileUrl;
|
|
8360
8423
|
if (!flags.quiet) {
|
|
8361
8424
|
console.log(
|
|
@@ -8384,6 +8447,20 @@ async function submitSignedIn(token, payload, flags, interactive) {
|
|
|
8384
8447
|
)
|
|
8385
8448
|
);
|
|
8386
8449
|
}
|
|
8450
|
+
if (result.quarantinedDates && result.quarantinedDates.length > 0) {
|
|
8451
|
+
const days = result.quarantinedDates.map((d) => sanitizeServerText(d)).join(", ");
|
|
8452
|
+
console.log();
|
|
8453
|
+
console.log(
|
|
8454
|
+
pc2.yellow(
|
|
8455
|
+
` \u26A0 These day(s) were held off the leaderboard as an anomaly: ${days}`
|
|
8456
|
+
)
|
|
8457
|
+
);
|
|
8458
|
+
console.log(
|
|
8459
|
+
pc2.dim(
|
|
8460
|
+
" Your data is kept, not deleted. Run `npx whoburnedmore verify` to get back on the board, or appeal at whoburnedmore.com/appeal to have these days reviewed and restored."
|
|
8461
|
+
)
|
|
8462
|
+
);
|
|
8463
|
+
}
|
|
8387
8464
|
if (isTrustedWebUrl(baseUrl)) {
|
|
8388
8465
|
console.log(pc2.dim(" Opening your dashboard in your browser\u2026"));
|
|
8389
8466
|
openBrowser(baseUrl);
|
|
@@ -8681,7 +8758,7 @@ function printHelp() {
|
|
|
8681
8758
|
${pc2.bold("usage")}
|
|
8682
8759
|
npx whoburnedmore sign in, burn + land on the public leaderboard, open your dashboard
|
|
8683
8760
|
npx whoburnedmore --board=CODE compare with friends \u2014 sign in and join their board
|
|
8684
|
-
npx whoburnedmore --org=SLUG
|
|
8761
|
+
npx whoburnedmore --org=SLUG --pass=CODE join your organization's board (companies/hackathons)
|
|
8685
8762
|
npx whoburnedmore --local build the dashboard on your machine and open it (offline)
|
|
8686
8763
|
npx whoburnedmore --dry-run print exactly what would be sent, send nothing
|
|
8687
8764
|
npx whoburnedmore --no-submit collect locally, send nothing (no dashboard)
|