chore: 初始提交 - 移除所有硬编码凭据,统一从环境变量读取

This commit is contained in:
yangxiangyuan
2026-06-11 17:10:58 +08:00
commit c223c79b36
1699 changed files with 313940 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
const express = require('express')
const Database = require('better-sqlite3')
const path = require('path')
const fs = require('fs')
const dataDir = path.join(process.cwd(), 'data')
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true })
const dbPath = path.join(dataDir, 'dlt_draws.db')
const db = new Database(dbPath)
// Initialize Tables
db.exec(`CREATE TABLE IF NOT EXISTS draws (
issue TEXT PRIMARY KEY,
date TEXT,
front TEXT,
back TEXT,
pool INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now'))
);`)
// Auth Helpers
const readCookieCfg = () => {
const cfgPath = path.join(process.cwd(), 'public', 'tools', 'dlt_draws', 'assets', 'auth_config.json')
let name = 'dlt_draws_gate'
let maxAge = 90 * 24 * 3600 * 1000
try {
if (fs.existsSync(cfgPath)) {
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'))
if (cfg.cookieName) name = String(cfg.cookieName)
const days = Number(cfg.max_age_days || 0)
if (Number.isFinite(days) && days > 0) maxAge = Math.min(days, 365) * 24 * 3600 * 1000
}
} catch {}
return { name, maxAge }
}
const parseCookie = (cookieStr) => {
const out = {}
String(cookieStr || '').split(/;\s*/).forEach(p => { const idx = p.indexOf('='); if (idx > 0) out[p.slice(0, idx)] = decodeURIComponent(p.slice(idx + 1)) })
return out
}
const checkAuth = (req, res, next) => {
try {
const cookies = parseCookie(req.headers.cookie || '')
const { name, maxAge } = readCookieCfg()
if (cookies[name] === '1' || cookies['nav_gate'] === '1') {
res.cookie(name, '1', { httpOnly: true, sameSite: 'lax', maxAge })
return next()
}
} catch {}
return res.status(401).json({ error: 'unauthorized' })
}
// Helpers
const pad2 = (n) => String(n).padStart(2, '0')
const arrToCsv = (arr) => (Array.isArray(arr) ? arr : String(arr).split(/[,,\s]+/).filter(Boolean))
.map((x) => pad2(parseInt(x, 10)))
.join(',')
const csvToArr = (csv) => String(csv).split(/[,,\s]+/).filter(Boolean).map((x) => parseInt(x, 10))
const bindRoutes = (app) => {
// Routes prefixed with /api/dlt
app.get('/auth/handshake', (req, res) => {
try {
const cookies = parseCookie(req.headers.cookie || '')
const { name } = readCookieCfg()
if (cookies[name] === '1' || cookies['nav_gate'] === '1') return res.json({ ok: true })
return res.status(401).json({ error: 'unauthorized' })
} catch (e) {
res.status(500).json({ ok: false, error: String(e.message || e) })
}
})
app.get('/auth/token', (req, res) => {
const cookies = parseCookie(req.headers.cookie || '')
const { name } = readCookieCfg()
if (cookies[name] === '1' || cookies['nav_gate'] === '1') return res.json({ ok: true })
return res.status(401).json({ error: 'unauthorized' })
})
app.get('/api/dlt/health', (req, res) => res.json({ status: 'ok' }))
app.get('/api/dlt/draws', checkAuth, (req, res) => {
const limit = Math.max(0, parseInt(req.query.limit || '0', 10) || 0)
const base = `SELECT issue, date, front, back, pool FROM draws ORDER BY CAST(issue AS INTEGER) ASC`
const sql = limit ? `${base} LIMIT ?` : base
try {
const rows = db.prepare(sql).all(limit ? [limit] : [])
res.json(rows.map((r) => ({
issue: r.issue,
date: r.date,
front: csvToArr(r.front),
back: csvToArr(r.back),
pool: r.pool || 0
})))
} catch (err) {
res.status(500).json({ error: err.message })
}
})
app.post('/api/dlt/draws/merge', checkAuth, (req, res) => {
const items = Array.isArray(req.body.rows) ? req.body.rows : []
if (!items.length) return res.status(400).json({ error: 'rows empty' })
let inserted = 0
try {
const insert = db.transaction((rows) => {
let count = 0
const stmt = db.prepare('INSERT OR IGNORE INTO draws(issue,date,front,back,pool) VALUES (?,?,?,?,?)')
for (const it of rows) {
const issue = String(it.issue || '').trim()
const date = String(it.date || '').trim()
const front = arrToCsv(it.front || it.frontArr || [])
const back = arrToCsv(it.back || it.backArr || [])
const pool = Number(it.pool || 0)
if (!issue || csvToArr(front).length !== 5 || csvToArr(back).length !== 2) continue
const info = stmt.run(issue, date, front, back, pool)
count += info.changes
}
return count
})
inserted = insert(items)
res.json({ inserted })
} catch (err) {
res.status(500).json({ error: err.message })
}
})
app.post('/api/dlt/draws/clear', checkAuth, (req, res) => {
try {
db.prepare('DELETE FROM draws').run()
res.json({ cleared: true })
} catch (err) {
res.status(500).json({ error: err.message })
}
})
}
module.exports = { bindRoutes }