kinaiok
Initial deployment setup for Hugging Face Spaces
5ef6e9d
import { Router } from "express";
import { db, configTable, geminiAccountsTable } from "@workspace/db";
import { eq, sql } from "drizzle-orm";
import { OTP_KEY, SITE_CONFIG_KEYS } from "./admin";
const router = Router();
const TOKEN_KEY = "geminigen_bearer_token";
const REFRESH_TOKEN_KEY = "geminigen_refresh_token";
router.post("/receive-tokens", async (req, res) => {
const { otp, access_token, refresh_token, label } = req.body as {
otp?: string;
access_token?: string;
refresh_token?: string;
label?: string;
};
if (!otp || !access_token) {
return res.status(400).json({ error: "otp ε’Œ access_token η‚ΊεΏ…ε‘«" });
}
const row = await db
.select()
.from(configTable)
.where(eq(configTable.key, OTP_KEY))
.limit(1);
if (!row.length) {
return res.status(401).json({ error: "OTP η„‘ζ•ˆζˆ–ε·²ιŽζœŸοΌŒθ«‹ι‡ζ–°η”’η”Ÿζ›Έη±€" });
}
const [storedOtp, expiresAtStr] = row[0].value.split(":");
const expiresAt = Number(expiresAtStr);
if (storedOtp !== otp || Date.now() > expiresAt) {
return res.status(401).json({ error: "OTP η„‘ζ•ˆζˆ–ε·²ιŽζœŸοΌŒθ«‹ι‡ζ–°η”’η”Ÿζ›Έη±€" });
}
// Delete OTP (one-time use)
await db.delete(configTable).where(eq(configTable.key, OTP_KEY));
if (label) {
// Save to pool as a new account
await db.insert(geminiAccountsTable).values({
label: label.trim(),
bearerToken: access_token,
refreshToken: refresh_token || null,
isActive: true,
});
return res.json({ success: true, message: `εΈ³ζˆΆγ€Œ${label}γ€ε·²εŠ ε…₯ Token 池!` });
}
// Legacy: save as single token in config
await db
.insert(configTable)
.values({ key: TOKEN_KEY, value: access_token, updatedAt: new Date() })
.onConflictDoUpdate({ target: configTable.key, set: { value: access_token, updatedAt: new Date() } });
if (refresh_token) {
await db
.insert(configTable)
.values({ key: REFRESH_TOKEN_KEY, value: refresh_token, updatedAt: new Date() })
.onConflictDoUpdate({ target: configTable.key, set: { value: refresh_token, updatedAt: new Date() } });
}
return res.json({ success: true, message: "Token 已成功同ζ­₯!" });
});
// ── Public site config (logo, Google Ads) ─────────────────────────────────────
const PUBLIC_SITE_KEYS = ["logo_url", "site_name", "google_ads_enabled", "google_ads_client", "google_ads_slot"];
router.get("/site-config", async (_req, res) => {
const rows = await db
.select()
.from(configTable)
.where(sql`${configTable.key} = ANY(ARRAY[${sql.raw(PUBLIC_SITE_KEYS.map(k => `'${k}'`).join(","))}]::text[])`);
const config: Record<string, string> = {};
for (const row of rows) config[row.key] = row.value;
res.json(config);
});
export default router;