Players get a fast TTL-backed homepage (local profile / Cloudflare D1) with dense UI polish; login unlocks /home without blocking on every OpenDota refresh. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
2.7 KiB
JavaScript
97 lines
2.7 KiB
JavaScript
/**
|
|
* POST /api/players/publish
|
|
*
|
|
* Body: { account_id, match_id }
|
|
* Optional header: X-Climperor-Publish-Secret
|
|
*
|
|
* Enqueues Cloudflare Queue sync (D1 + R2). No longer writes OSS profile JSON.
|
|
*/
|
|
import { enqueueRefresh, jsonResponse } from "./_db.js";
|
|
|
|
function envOf(context) {
|
|
return (context && context.env) || {};
|
|
}
|
|
|
|
function intField(v, fallback = 0) {
|
|
const n = Number(v);
|
|
return Number.isFinite(n) ? Math.trunc(n) : fallback;
|
|
}
|
|
|
|
export async function onRequestPost(context) {
|
|
try {
|
|
const env = envOf(context);
|
|
const expected = (env.PLAYER_PAGES_PUBLISH_SECRET || "").trim();
|
|
if (expected) {
|
|
const got = (
|
|
context.request.headers.get("X-Climperor-Publish-Secret") || ""
|
|
).trim();
|
|
if (got !== expected) {
|
|
return jsonResponse({ error: "forbidden" }, 403);
|
|
}
|
|
}
|
|
|
|
let body;
|
|
try {
|
|
body = await context.request.json();
|
|
} catch {
|
|
return jsonResponse({ error: "invalid json" }, 400);
|
|
}
|
|
|
|
const accountId = intField(body && body.account_id, -1);
|
|
const matchId = intField(body && body.match_id, -1);
|
|
if (accountId <= 0 || matchId <= 0) {
|
|
return jsonResponse({ error: "account_id and match_id required" }, 400);
|
|
}
|
|
|
|
if (!env.SYNC_QUEUE) {
|
|
return jsonResponse({ error: "sync queue not configured" }, 503);
|
|
}
|
|
|
|
// Mark public_share when PC publishes intentionally.
|
|
if (env.DB) {
|
|
const now = new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
const steamid = String(BigInt(accountId) + 76561197960265728n);
|
|
await env.DB.prepare(
|
|
`INSERT INTO users (account_id, steamid, personaname, avatar, public_share, created_at, last_login_at)
|
|
VALUES (?, ?, NULL, NULL, 1, ?, ?)
|
|
ON CONFLICT(account_id) DO UPDATE SET public_share = 1, last_login_at = excluded.last_login_at`
|
|
)
|
|
.bind(accountId, steamid, now, now)
|
|
.run();
|
|
}
|
|
|
|
const queued = await enqueueRefresh(env, {
|
|
kind: "publish_match",
|
|
account_id: accountId,
|
|
match_id: matchId,
|
|
public_share: true,
|
|
});
|
|
if (!queued) {
|
|
return jsonResponse({ error: "enqueue failed" }, 503);
|
|
}
|
|
return jsonResponse({
|
|
ok: true,
|
|
queued: true,
|
|
account_id: accountId,
|
|
match_id: matchId,
|
|
});
|
|
} catch (e) {
|
|
return jsonResponse(
|
|
{ error: "publish failed", detail: String((e && e.message) || e) },
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function onRequestOptions() {
|
|
return new Response(null, {
|
|
status: 204,
|
|
headers: {
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
"Access-Control-Allow-Headers": "Content-Type, X-Climperor-Publish-Secret",
|
|
"Access-Control-Max-Age": "86400",
|
|
},
|
|
});
|
|
}
|