diff --git a/backend/middleware/auth.js b/backend/middleware/auth.js index ce55a83..9acef9c 100644 --- a/backend/middleware/auth.js +++ b/backend/middleware/auth.js @@ -31,18 +31,57 @@ const authenticate = async (req, res, next) => { const initData = req.headers['x-telegram-init-data']; if (!initData) { + console.warn('⚠️ Нет x-telegram-init-data заголовка'); return res.status(401).json({ error: 'Не авторизован' }); } // Получаем user из initData - const urlParams = new URLSearchParams(initData); + let urlParams; + try { + urlParams = new URLSearchParams(initData); + } catch (e) { + // Если initData не URLSearchParams, попробуем как JSON + try { + const parsed = JSON.parse(initData); + if (parsed.user) { + req.telegramUser = parsed.user; + // Найти или создать пользователя + let user = await User.findOne({ telegramId: parsed.user.id.toString() }); + if (!user) { + user = new User({ + telegramId: parsed.user.id.toString(), + username: parsed.user.username || parsed.user.first_name, + firstName: parsed.user.first_name, + lastName: parsed.user.last_name, + photoUrl: parsed.user.photo_url + }); + await user.save(); + console.log(`✅ Создан новый пользователь: ${user.username}`); + } + req.user = user; + return next(); + } + } catch (e2) { + console.error('❌ Ошибка парсинга initData:', e2.message); + return res.status(401).json({ error: 'Неверный формат данных авторизации' }); + } + } + const userParam = urlParams.get('user'); if (!userParam) { + console.warn('⚠️ Нет user параметра в initData'); return res.status(401).json({ error: 'Данные пользователя не найдены' }); } - const telegramUser = JSON.parse(userParam); + let telegramUser; + try { + telegramUser = JSON.parse(userParam); + } catch (e) { + console.error('❌ Ошибка парсинга user:', e.message); + return res.status(401).json({ error: 'Ошибка парсинга данных пользователя' }); + } + req.telegramUser = telegramUser; // Проверка подписи Telegram (только в production и если есть токен) diff --git a/backend/routes/search.js b/backend/routes/search.js index 1903633..bc39195 100644 --- a/backend/routes/search.js +++ b/backend/routes/search.js @@ -118,23 +118,40 @@ router.get('/anime', authenticate, async (req, res) => { tags: query, limit, pid: page - } + }, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + }, + timeout: 30000 }); - const posts = (response.data.post || []).map(post => ({ + // Обработка разных форматов ответа Gelbooru + let postsData = []; + if (Array.isArray(response.data)) { + postsData = response.data; + } else if (response.data && response.data.post) { + postsData = Array.isArray(response.data.post) ? response.data.post : [response.data.post]; + } else if (response.data && Array.isArray(response.data)) { + postsData = response.data; + } + + const posts = postsData.map(post => ({ id: post.id, url: createProxyUrl(post.file_url), - preview: createProxyUrl(post.preview_url), - tags: post.tags ? post.tags.split(' ') : [], - rating: post.rating, - score: post.score, + preview: createProxyUrl(post.preview_url || post.thumbnail_url || post.file_url), + tags: post.tags ? (typeof post.tags === 'string' ? post.tags.split(' ') : post.tags) : [], + rating: post.rating || 'unknown', + score: post.score || 0, source: 'gelbooru' })); res.json({ posts }); } catch (error) { - console.error('Ошибка Gelbooru API:', error); - res.status(500).json({ error: 'Ошибка поиска' }); + console.error('Ошибка Gelbooru API:', error.message); + if (error.response) { + console.error('Gelbooru ответ:', error.response.status, error.response.data); + } + res.status(500).json({ error: 'Ошибка поиска Gelbooru', details: error.message }); } }); @@ -188,18 +205,36 @@ router.get('/anime/tags', authenticate, async (req, res) => { name_pattern: `${query}%`, orderby: 'count', limit: 10 - } + }, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + }, + timeout: 30000 }); - const tags = (response.data.tag || []).map(tag => ({ - name: tag.name, - count: tag.count - })); + // Обработка разных форматов ответа Gelbooru + let tagsData = []; + if (Array.isArray(response.data)) { + tagsData = response.data; + } else if (response.data && response.data.tag) { + tagsData = Array.isArray(response.data.tag) ? response.data.tag : [response.data.tag]; + } else if (response.data && Array.isArray(response.data)) { + tagsData = response.data; + } + + const tags = tagsData.map(tag => ({ + name: tag.name || tag.tag || '', + count: tag.count || tag.post_count || 0 + })).filter(tag => tag.name); res.json({ tags }); } catch (error) { - console.error('Ошибка получения тегов:', error); - res.status(500).json({ error: 'Ошибка получения тегов' }); + console.error('Ошибка получения тегов Gelbooru:', error.message); + if (error.response) { + console.error('Gelbooru ответ:', error.response.status, error.response.data); + } + // В случае ошибки возвращаем пустой массив вместо ошибки + res.json({ tags: [] }); } }); diff --git a/frontend/src/components/CommentsModal.css b/frontend/src/components/CommentsModal.css index 112e97a..aa4f123 100644 --- a/frontend/src/components/CommentsModal.css +++ b/frontend/src/components/CommentsModal.css @@ -7,9 +7,8 @@ bottom: 0; background: var(--bg-secondary); z-index: 999; /* Выше навигации (50) */ - pointer-events: all; - touch-action: none; overflow: hidden; + /* Убираем touch-action: none чтобы не блокировать клики */ } .comments-modal { @@ -18,8 +17,7 @@ background: var(--bg-secondary); display: flex; flex-direction: column; - pointer-events: all; - touch-action: auto; + /* Убираем pointer-events и touch-action чтобы клики работали */ } .comments-modal .modal-header { @@ -183,8 +181,7 @@ display: flex; gap: 8px; z-index: 1000; - pointer-events: all; - touch-action: auto; + /* Убираем pointer-events и touch-action чтобы клики работали */ } .comment-form input { @@ -195,7 +192,7 @@ color: var(--text-primary); font-size: 15px; border: none; - pointer-events: all; + /* Убираем pointer-events чтобы клики работали */ } .send-btn { @@ -210,7 +207,7 @@ border: none; cursor: pointer; flex-shrink: 0; - pointer-events: all; + /* Убираем pointer-events чтобы клики работали */ } .send-btn svg { diff --git a/frontend/src/components/CommentsModal.jsx b/frontend/src/components/CommentsModal.jsx index 8ac4fe4..e411a7f 100644 --- a/frontend/src/components/CommentsModal.jsx +++ b/frontend/src/components/CommentsModal.jsx @@ -41,9 +41,16 @@ export default function CommentsModal({ post, onClose, onUpdate }) { return d.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' }) } + const handleOverlayClick = (e) => { + // Закрывать только при клике на overlay, не на контент + if (e.target === e.currentTarget) { + onClose() + } + } + return ( -
-
+
+
e.stopPropagation()}> {/* Хедер */}
@@ -51,7 +57,7 @@ export default function PostMenu({ post, currentUser, onClose, onDelete }) {
-
+
e.stopPropagation()}>