2025-07-04 14:31:04 +09:00

121 lines
4.6 KiB
JavaScript

const express = require('express');
const db = require('../db');
const router = express.Router();
const crypto = require('crypto');
const validator = require('validator');
router.get('/', (req, res) => {
try {
const sessions = db.prepare(
"SELECT id, uid, title, started_at, ended_at, sync_state, updated_at FROM sessions WHERE uid = ? ORDER BY started_at DESC"
).all(req.uid);
res.json(sessions);
} catch (error) {
console.error('Failed to get sessions:', error);
res.status(500).json({ error: 'Failed to retrieve sessions' });
}
});
router.post('/', (req, res) => {
const { title } = req.body;
const sessionId = crypto.randomUUID();
const now = Math.floor(Date.now() / 1000);
try {
db.prepare(
`INSERT INTO sessions (id, uid, title, started_at, updated_at)
VALUES (?, ?, ?, ?, ?)`
).run(sessionId, req.uid, title || 'New Conversation', now, now);
res.status(201).json({ id: sessionId, message: 'Session created successfully' });
} catch (error) {
console.error('Failed to create session:', error);
res.status(500).json({ error: 'Failed to create session' });
}
});
router.get('/:session_id', (req, res) => {
const { session_id } = req.params;
try {
const session = db.prepare("SELECT * FROM sessions WHERE id = ?").get(session_id);
if (!session) {
return res.status(404).json({ error: 'Session not found' });
}
const transcripts = db.prepare("SELECT * FROM transcripts WHERE session_id = ? ORDER BY start_at ASC").all(session_id);
const ai_messages = db.prepare("SELECT * FROM ai_messages WHERE session_id = ? ORDER BY sent_at ASC").all(session_id);
const summary = db.prepare("SELECT * FROM summaries WHERE session_id = ?").get(session_id);
res.json({
session,
transcripts,
ai_messages,
summary: summary || null
});
} catch (error) {
console.error(`Failed to get session ${session_id}:`, error);
res.status(500).json({ error: 'Failed to retrieve session details' });
}
});
router.delete('/:session_id', (req, res) => {
const { session_id } = req.params;
const session = db.prepare("SELECT id FROM sessions WHERE id = ?").get(session_id);
if (!session) {
return res.status(404).json({ error: 'Session not found' });
}
try {
db.transaction(() => {
db.prepare("DELETE FROM transcripts WHERE session_id = ?").run(session_id);
db.prepare("DELETE FROM ai_messages WHERE session_id = ?").run(session_id);
db.prepare("DELETE FROM summaries WHERE session_id = ?").run(session_id);
db.prepare("DELETE FROM sessions WHERE id = ?").run(session_id);
})();
res.status(200).json({ message: 'Session deleted successfully' });
} catch (error) {
console.error(`Failed to delete session ${session_id}:`, error);
res.status(500).json({ error: 'Failed to delete session' });
}
});
router.get('/search', (req, res) => {
const { q } = req.query;
if (!q || !validator.isLength(q, { min: 3 })) {
return res.status(400).json({ error: 'Query parameter "q" is required' });
}
// Sanitize and validate input
const sanitizedQuery = validator.escape(q.trim()); // Escapes HTML and special chars
if (sanitizedQuery.length === 0 || sanitizedQuery.length > 255) {
return res.status(400).json({ error: 'Query parameter "q" must be between 3 and 255 characters' });
}
try {
const searchQuery = `%${sanitizedQuery}%`;
const sessionIds = db.prepare(`
SELECT DISTINCT session_id FROM (
SELECT session_id FROM transcripts WHERE text LIKE ?
UNION
SELECT session_id FROM ai_messages WHERE content LIKE ?
UNION
SELECT session_id FROM summaries WHERE text LIKE ? OR tldr LIKE ?
)
`).all(searchQuery, searchQuery, searchQuery, searchQuery).map(row => row.session_id);
if (sessionIds.length === 0) {
return res.json([]);
}
const placeholders = sessionIds.map(() => '?').join(',');
const sessions = db.prepare(
`SELECT id, uid, title, started_at, ended_at, sync_state, updated_at FROM sessions WHERE id IN (${placeholders}) ORDER BY started_at DESC`
).all(sessionIds);
res.json(sessions);
} catch (error) {
console.error('Search failed:', error);
res.status(500).json({ error: 'Failed to perform search' });
}
});
module.exports = router;