247 lines
7.8 KiB
JavaScript
247 lines
7.8 KiB
JavaScript
const express = require('express');
|
||
const router = express.Router();
|
||
const { pool } = require('../db');
|
||
const { requireAuth } = require('../middleware/auth');
|
||
const { processMessage, getUserInfo } = require('../services/ai-assistant');
|
||
|
||
// Получение списка диалогов пользователя
|
||
router.get('/conversations', requireAuth, async (req, res) => {
|
||
try {
|
||
const userId = req.session.userId;
|
||
|
||
const result = await pool.query(
|
||
`SELECT * FROM conversation_view
|
||
WHERE user_id = $1
|
||
ORDER BY updated_at DESC`,
|
||
[userId]
|
||
);
|
||
|
||
res.json(result.rows);
|
||
} catch (error) {
|
||
console.error('Error fetching conversations:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Получение сообщений диалога
|
||
router.get('/conversations/:id/messages', requireAuth, async (req, res) => {
|
||
try {
|
||
const userId = req.session.userId;
|
||
const conversationId = req.params.id;
|
||
|
||
// Проверка доступа к диалогу
|
||
const conversationCheck = await pool.query(
|
||
'SELECT id FROM conversations WHERE id = $1 AND user_id = $2',
|
||
[conversationId, userId]
|
||
);
|
||
|
||
if (conversationCheck.rows.length === 0) {
|
||
return res.status(403).json({ error: 'Access denied' });
|
||
}
|
||
|
||
const result = await pool.query(
|
||
`SELECT * FROM message_view
|
||
WHERE conversation_id = $1
|
||
ORDER BY created_at ASC`,
|
||
[conversationId]
|
||
);
|
||
|
||
res.json(result.rows);
|
||
} catch (error) {
|
||
console.error('Error fetching messages:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Отправка сообщения
|
||
router.post('/conversations/:id/messages', requireAuth, async (req, res) => {
|
||
try {
|
||
const userId = req.session.userId;
|
||
const conversationId = req.params.id;
|
||
const { content } = req.body;
|
||
|
||
if (!content || content.trim() === '') {
|
||
return res.status(400).json({ error: 'Message content is required' });
|
||
}
|
||
|
||
// Проверка доступа к диалогу
|
||
const conversationCheck = await pool.query(
|
||
'SELECT id FROM conversations WHERE id = $1 AND user_id = $2',
|
||
[conversationId, userId]
|
||
);
|
||
|
||
if (conversationCheck.rows.length === 0) {
|
||
return res.status(403).json({ error: 'Access denied' });
|
||
}
|
||
|
||
// Обновление времени последней активности диалога
|
||
await pool.query('UPDATE conversations SET updated_at = NOW() WHERE id = $1', [conversationId]);
|
||
|
||
// Сохранение сообщения пользователя
|
||
const userMessageResult = await pool.query(
|
||
`INSERT INTO messages
|
||
(conversation_id, sender_type, sender_id, content, channel)
|
||
VALUES ($1, 'user', $2, $3, 'web')
|
||
RETURNING *`,
|
||
[conversationId, userId, content]
|
||
);
|
||
|
||
// Получение информации о пользователе для ИИ
|
||
const userInfo = await getUserInfo(userId);
|
||
|
||
// Обработка сообщения ИИ-ассистентом
|
||
const aiResponse = await processMessage(userId, content, userInfo.language || 'ru');
|
||
|
||
// Сохранение ответа ИИ
|
||
const aiMessageResult = await pool.query(
|
||
`INSERT INTO messages
|
||
(conversation_id, sender_type, content, channel)
|
||
VALUES ($1, 'ai', $2, 'web')
|
||
RETURNING *`,
|
||
[conversationId, aiResponse]
|
||
);
|
||
|
||
res.json({
|
||
userMessage: userMessageResult.rows[0],
|
||
aiMessage: aiMessageResult.rows[0],
|
||
});
|
||
} catch (error) {
|
||
console.error('Error sending message:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Создание нового диалога
|
||
router.post('/conversations', requireAuth, async (req, res) => {
|
||
try {
|
||
const userId = req.session.userId;
|
||
const { title } = req.body;
|
||
|
||
// Создание нового диалога
|
||
const result = await pool.query(
|
||
`INSERT INTO conversations (user_id, title)
|
||
VALUES ($1, $2)
|
||
RETURNING *`,
|
||
[userId, title || 'Новый диалог']
|
||
);
|
||
|
||
res.json(result.rows[0]);
|
||
} catch (error) {
|
||
console.error('Error creating conversation:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Обновление заголовка диалога
|
||
router.put('/conversations/:id', requireAuth, async (req, res) => {
|
||
try {
|
||
const userId = req.session.userId;
|
||
const conversationId = req.params.id;
|
||
const { title } = req.body;
|
||
|
||
if (!title || title.trim() === '') {
|
||
return res.status(400).json({ error: 'Title is required' });
|
||
}
|
||
|
||
// Проверка доступа к диалогу
|
||
const conversationCheck = await pool.query(
|
||
'SELECT id FROM conversations WHERE id = $1 AND user_id = $2',
|
||
[conversationId, userId]
|
||
);
|
||
|
||
if (conversationCheck.rows.length === 0) {
|
||
return res.status(403).json({ error: 'Access denied' });
|
||
}
|
||
|
||
// Обновление заголовка
|
||
const result = await pool.query(
|
||
'UPDATE conversations SET title = $1 WHERE id = $2 RETURNING *',
|
||
[title, conversationId]
|
||
);
|
||
|
||
res.json(result.rows[0]);
|
||
} catch (error) {
|
||
console.error('Error updating conversation:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Удаление диалога
|
||
router.delete('/conversations/:id', requireAuth, async (req, res) => {
|
||
try {
|
||
const userId = req.session.userId;
|
||
const conversationId = req.params.id;
|
||
|
||
// Проверка доступа к диалогу
|
||
const conversationCheck = await pool.query(
|
||
'SELECT id FROM conversations WHERE id = $1 AND user_id = $2',
|
||
[conversationId, userId]
|
||
);
|
||
|
||
if (conversationCheck.rows.length === 0) {
|
||
return res.status(403).json({ error: 'Access denied' });
|
||
}
|
||
|
||
// Удаление диалога (каскадно удалит все сообщения)
|
||
await pool.query('DELETE FROM conversations WHERE id = $1', [conversationId]);
|
||
|
||
res.json({ success: true });
|
||
} catch (error) {
|
||
console.error('Error deleting conversation:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Маршруты для администраторов
|
||
|
||
// Получение всех диалогов (только для администраторов)
|
||
router.get('/admin/conversations', requireAuth, async (req, res) => {
|
||
try {
|
||
// Проверка прав администратора
|
||
if (!req.session.isAdmin) {
|
||
return res.status(403).json({ error: 'Admin access required' });
|
||
}
|
||
|
||
const result = await pool.query(
|
||
`SELECT * FROM conversation_view
|
||
ORDER BY updated_at DESC`
|
||
);
|
||
|
||
res.json(result.rows);
|
||
} catch (error) {
|
||
console.error('Error fetching all conversations:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
// Получение статистики по каналам (только для администраторов)
|
||
router.get('/admin/stats/channels', requireAuth, async (req, res) => {
|
||
try {
|
||
// Проверка прав администратора
|
||
if (!req.session.isAdmin) {
|
||
return res.status(403).json({ error: 'Admin access required' });
|
||
}
|
||
|
||
const result = await pool.query(
|
||
`SELECT
|
||
channel,
|
||
COUNT(*) AS message_count,
|
||
COUNT(DISTINCT conversation_id) AS conversation_count,
|
||
COUNT(DISTINCT sender_id) AS user_count,
|
||
MIN(created_at) AS first_message,
|
||
MAX(created_at) AS last_message
|
||
FROM
|
||
messages
|
||
GROUP BY
|
||
channel`
|
||
);
|
||
|
||
res.json(result.rows);
|
||
} catch (error) {
|
||
console.error('Error fetching channel stats:', error);
|
||
res.status(500).json({ error: 'Internal server error' });
|
||
}
|
||
});
|
||
|
||
module.exports = router;
|