add supporters section to homepage
Shows paying squadrons as pill links (SHORT // LONG → /squadrons/<short>) above the footer, with a 15-min server-side cache backed by entitlements DB + SQUADRONS.json. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+46
-1
@@ -98,6 +98,7 @@ fs.mkdirSync(REPLAYS_ROOT, { recursive: true });
|
||||
const LEGACY_REPLAYS_ROOT = path.join(__dirname, '..', 'replays');
|
||||
const ENTITLEMENTS_DB_PATH = path.join(STORAGE_ROOT, 'entitlements.db');
|
||||
const SQUADRONS_DB_PATH = path.join(STORAGE_ROOT, 'squadrons.db');
|
||||
const SQUADRONS_JSON_PATH = path.join(STORAGE_ROOT, 'SQUADRONS.json');
|
||||
const entitlementsDb = new sqlite3.Database(ENTITLEMENTS_DB_PATH);
|
||||
const squadronsDb = fs.existsSync(SQUADRONS_DB_PATH)
|
||||
? new sqlite3.Database(SQUADRONS_DB_PATH, sqlite3.OPEN_READONLY)
|
||||
@@ -824,12 +825,56 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
// ── Supporters (paying squadrons) ────────────────────────────────────────────
|
||||
let _supportersCache = null;
|
||||
let _supportersCacheAt = 0;
|
||||
const SUPPORTERS_TTL = 15 * 60 * 1000;
|
||||
|
||||
function getSupporters() {
|
||||
if (_supportersCache && Date.now() - _supportersCacheAt < SUPPORTERS_TTL) {
|
||||
return Promise.resolve(_supportersCache);
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
let squads;
|
||||
try {
|
||||
squads = JSON.parse(fs.readFileSync(SQUADRONS_JSON_PATH, 'utf8'));
|
||||
} catch {
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
entitlementsDb.all(
|
||||
`SELECT guild_id FROM guild_entitlements WHERE status='active'
|
||||
UNION SELECT guild_id FROM discord_entitlements
|
||||
UNION SELECT guild_id FROM manual_entitlements WHERE expires_at > strftime('%s','now')`,
|
||||
[],
|
||||
(err, rows) => {
|
||||
if (err) return resolve([]);
|
||||
const paying = new Set(rows.map(r => r.guild_id));
|
||||
const seen = new Map();
|
||||
for (const [gid, sq] of Object.entries(squads)) {
|
||||
if (paying.has(gid) && !seen.has(sq.SQ_ShortHand_Name)) {
|
||||
seen.set(sq.SQ_ShortHand_Name, sq.SQ_LongHandName);
|
||||
}
|
||||
}
|
||||
const result = [...seen.entries()]
|
||||
.map(([short, long]) => ({ short, long }))
|
||||
.sort((a, b) => a.long.localeCompare(b.long));
|
||||
_supportersCache = result;
|
||||
_supportersCacheAt = Date.now();
|
||||
resolve(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Routes
|
||||
app.get('/', (req, res) => {
|
||||
app.get('/', async (req, res) => {
|
||||
const siteUrl = (process.env.PRODUCTION_DOMAIN || 'https://sre.pawjob.us').replace(/\/$/, '');
|
||||
const supporters = await getSupporters().catch(() => []);
|
||||
|
||||
res.render('index', {
|
||||
botName: 'Toothless SQB Bot',
|
||||
supporters,
|
||||
metaTitle: "Toothless' SRE Bot",
|
||||
metaDescription: 'The Best Squadron Battles Bot.',
|
||||
metaUrl: `${siteUrl}/`,
|
||||
|
||||
Reference in New Issue
Block a user