aibanking.dev / server.js
admin08077's picture
Update server.js
816e87e verified
raw
history blame
4.87 kB
import express from 'express';
import cors from 'cors';
import path from 'path';
import { fileURLToPath } from 'url';
import sqlite3 from 'sqlite3';
import bcrypt from 'bcryptjs';
const app = express();
const port = process.env.PORT || 7860;
// --- Database Initialization ---
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const dbPath = path.join(__dirname, 'database.db');
const db = new sqlite3.Database(dbPath);
db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
role TEXT DEFAULT 'Standard Node',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
role TEXT NOT NULL,
content TEXT NOT NULL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(user_id) REFERENCES users(id)
)
`);
});
let activeSession = null;
// Mock Citi Data
const CITI_ACCOUNTS = {
accountGroupDetails: [{
accountGroup: "CHECKING",
checkingAccountsDetails: [{
productName: "Corporate Mastery Checking",
accountNickname: "Main Ops Node",
accountDescription: "Corporate Mastery Checking - 9594",
balanceType: "ASSET",
displayAccountNumber: "XXXXXX9594",
accountId: "citi_acc_99201",
currencyCode: "USD",
accountStatus: "ACTIVE",
currentBalance: 1245000.50,
availableBalance: 1240000.00
}],
totalCurrentBalance: { localCurrencyCode: "USD", localCurrencyBalanceAmount: 1245000.50 },
totalAvailableBalance: { localCurrencyCode: "USD", localCurrencyBalanceAmount: 1240000.00 }
}],
customer: { customerId: "citi_cust_884102" }
};
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Auth API
app.get('/api/auth/me', (req, res) => res.json({ isAuthenticated: !!activeSession, user: activeSession }));
app.post('/api/auth/login', (req, res) => {
const { username, password } = req.body;
db.get('SELECT * FROM users WHERE username = ?', [username], async (err, user) => {
if (err || !user) return res.status(401).json({ success: false, message: 'Invalid node' });
const match = await bcrypt.compare(password, user.password_hash);
if (match) {
activeSession = { id: `USR-${user.id}`, dbId: user.id, name: user.username, role: user.role, lastLogin: new Date().toISOString() };
res.json({ success: true, user: activeSession });
} else {
res.status(401).json({ success: false });
}
});
});
app.post('/api/auth/logout', (req, res) => { activeSession = null; res.json({ success: true }); });
// Gemini REST Proxy (Exact Implementation as per user's curl requirement)
app.post('/api/gemini/generate', async (req, res) => {
try {
// Hugging Face secrets are available via process.env
const apiKey = process.env.GEMINI_API_KEY;
if (!apiKey) {
console.error("FATAL: GEMINI_API_KEY secret is not configured in Hugging Face Space.");
return res.status(500).json({ error: 'GEMINI_API_KEY missing from environment secrets.' });
}
const { contents } = req.body;
// User requested specifically gemini-2.5-flash in the URL
const targetUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
const proxyUrl = `https://corsproxy.io/?url=${encodeURIComponent(targetUrl)}`;
const response = await fetch(proxyUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': apiKey
},
body: JSON.stringify({
contents: contents
})
});
const data = await response.json();
if (data.error) {
console.error("Gemini API returned error:", data.error);
return res.status(response.status || 500).json({ error: data.error.message || 'Upstream Error' });
}
// Standardize text response for frontend consumption
const text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
res.json({ text, candidates: data.candidates });
} catch (error) {
console.error("Server proxy error:", error);
res.status(500).json({ error: error.message });
}
});
// Citi Proxy
app.get('/api/accounts/account-transactions/partner/v1/accounts/details', (req, res) => res.json(CITI_ACCOUNTS));
// Serve Frontend
const __dist = path.join(__dirname, 'dist');
app.use(express.static(__dist));
// SPA Fallback
app.use((req, res) => {
if (req.path.startsWith('/api')) return res.status(404).json({ error: 'Endpoint missing' });
res.sendFile(path.join(__dist, 'index.html'));
});
app.listen(port, '0.0.0.0', () => console.log(`[Lumina Proxy] Node Online on Port ${port}`));