const express = require('express'); const path = require('path'); const cookieParser = require('cookie-parser'); const crypto = require('crypto'); const app = express(); const port = 7860; app.use(express.json()); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'dist'))); const OAUTH_CLIENT_ID = process.env.OAUTH_CLIENT_ID; const OAUTH_CLIENT_SECRET = process.env.OAUTH_CLIENT_SECRET; const OAUTH_SCOPES = process.env.OAUTH_SCOPES || "openid profile"; const OPENID_PROVIDER_URL = process.env.OPENID_PROVIDER_URL || "https://huggingface.co"; const SPACE_HOST = process.env.SPACE_HOST; const REDIRECT_URI = SPACE_HOST ? `https://${SPACE_HOST}/oauth/callback` : `http://localhost:${port}/oauth/callback`; app.post('/api/craft', async (req, res) => { const { content, variation } = req.body; const apiKey = process.env.BLABLADOR_API_KEY; if (!apiKey) { return res.status(500).json({ error: 'BLABLADOR_API_KEY is not configured on the server.' }); } const model = content.length > 500 ? 'alias-large' : 'alias-fast'; const prompt = `You are a professional content creator. Help me craft a ${variation || 'social media post'} based on the following content:\n\n${content}\n\nProvide 3 distinct and engaging variations.`; try { const response = await fetch('https://api.helmholtz-blablador.fz-juelich.de/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: model, messages: [ { role: 'system', content: 'You are a helpful assistant that helps craft engaging marketing and social media content.' }, { role: 'user', content: prompt } ], temperature: 0.7 }) }); if (!response.ok) { const errorData = await response.json(); return res.status(response.status).json(errorData); } const data = await response.json(); res.json({ result: data.choices[0].message.content }); } catch (error) { console.error('Blablador API error:', error); res.status(500).json({ error: 'Failed to connect to Blablador API.' }); } }); app.get('/api/config', (req, res) => { res.json({ clientId: OAUTH_CLIENT_ID, scopes: OAUTH_SCOPES, }); }); app.get('/login', (req, res) => { if (!OAUTH_CLIENT_ID) { return res.status(500).json({ error: "OAuth is not configured (missing OAUTH_CLIENT_ID)" }); } const state = crypto.randomBytes(16).toString('hex'); res.cookie('oauth_state', state, { httpOnly: true, maxAge: 600000 }); // 10 mins const authUrl = `${OPENID_PROVIDER_URL}/oauth/authorize` + `?client_id=${OAUTH_CLIENT_ID}` + `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` + `&scope=${encodeURIComponent(OAUTH_SCOPES)}` + `&response_type=code` + `&state=${state}`; res.redirect(authUrl); }); app.get('/oauth/callback', async (req, res) => { const { code, state } = req.query; const savedState = req.cookies.oauth_state; if (!state || state !== savedState) { console.error("State mismatch:", { state, savedState }); return res.status(403).json({ error: "Invalid OAuth state" }); } res.clearCookie('oauth_state'); const tokenUrl = `${OPENID_PROVIDER_URL}/oauth/token`; const authStr = Buffer.from(`${OAUTH_CLIENT_ID}:${OAUTH_CLIENT_SECRET}`).toString('base64'); try { const tokenResp = await fetch(tokenUrl, { method: 'POST', headers: { 'Authorization': `Basic ${authStr}`, 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code: code, redirect_uri: REDIRECT_URI, client_id: OAUTH_CLIENT_ID, }) }); if (!tokenResp.ok) { const errorText = await tokenResp.text(); console.error("Token exchange failed:", errorText); return res.status(400).json({ error: "Failed to retrieve access token" }); } const tokenData = await tokenResp.json(); const accessToken = tokenData.access_token; const userResp = await fetch("https://huggingface.co/api/whoami-v2", { headers: { "Authorization": `Bearer ${accessToken}` } }); const userInfo = await userResp.json(); // Set cookie and redirect back to app res.cookie('hf_user', JSON.stringify(userInfo), { path: '/', httpOnly: false }); res.redirect('/'); } catch (error) { console.error("OAuth callback error:", error); res.status(500).json({ error: "Authentication failed" }); } }); app.get('/api/user', (req, res) => { if (req.cookies.hf_user) { try { res.json(JSON.parse(req.cookies.hf_user)); } catch (e) { res.status(400).json({ error: "Invalid user cookie" }); } } else { res.status(401).json({ error: "Not authenticated" }); } }); app.get('/api/logout', (req, res) => { res.clearCookie('hf_user'); res.redirect('/'); }); app.get('/health', (req, res) => { res.status(200).send('OK'); }); app.use((req, res) => { res.sendFile(path.join(__dirname, 'dist', 'index.html')); }); app.listen(port, () => { console.log(`Server running on port ${port}`); });