const express = require('express'); const router = express.Router(); const { authenticate } = require('../middleware/auth'); const User = require('../models/User'); const Post = require('../models/Post'); const Notification = require('../models/Notification'); const ALLOWED_SEARCH_PREFERENCES = ['furry', 'anime']; // Получить профиль пользователя router.get('/:id', authenticate, async (req, res) => { try { const user = await User.findById(req.params.id) .select('-__v') .populate('followers', 'username firstName lastName photoUrl') .populate('following', 'username firstName lastName photoUrl'); if (!user) { return res.status(404).json({ error: 'Пользователь не найден' }); } // Проверить подписку текущего пользователя const isFollowing = user.followers.some(f => f._id.equals(req.user._id)); res.json({ user: { id: user._id, username: user.username, firstName: user.firstName, lastName: user.lastName, photoUrl: user.photoUrl, bio: user.bio, followersCount: user.followers.length, followingCount: user.following.length, followers: user.followers, following: user.following, isFollowing, createdAt: user.createdAt } }); } catch (error) { console.error('Ошибка получения профиля:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); // Получить посты пользователя router.get('/:id/posts', authenticate, async (req, res) => { try { const { page = 1, limit = 20 } = req.query; const query = { author: req.params.id }; // Применить фильтры текущего пользователя if (req.user.settings?.whitelist?.noNSFW) { query.isNSFW = false; } if (req.user.settings?.whitelist?.noHomo) { query.isHomo = { $ne: true }; } const posts = await Post.find(query) .populate('author', 'username firstName lastName photoUrl') .sort({ createdAt: -1 }) .limit(limit * 1) .skip((page - 1) * limit) .exec(); const count = await Post.countDocuments(query); res.json({ posts, totalPages: Math.ceil(count / limit), currentPage: page }); } catch (error) { console.error('Ошибка получения постов:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); // Подписаться / отписаться router.post('/:id/follow', authenticate, async (req, res) => { try { if (req.params.id === req.user._id.toString()) { return res.status(400).json({ error: 'Нельзя подписаться на себя' }); } const targetUser = await User.findById(req.params.id); if (!targetUser) { return res.status(404).json({ error: 'Пользователь не найден' }); } const isFollowing = targetUser.followers.includes(req.user._id); if (isFollowing) { // Отписаться targetUser.followers = targetUser.followers.filter(id => !id.equals(req.user._id)); req.user.following = req.user.following.filter(id => !id.equals(targetUser._id)); } else { // Подписаться targetUser.followers.push(req.user._id); req.user.following.push(targetUser._id); // Создать уведомление const notification = new Notification({ recipient: targetUser._id, sender: req.user._id, type: 'follow' }); await notification.save(); } await targetUser.save(); await req.user.save(); res.json({ following: !isFollowing, followersCount: targetUser.followers.length }); } catch (error) { console.error('Ошибка подписки:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); // Обновить профиль router.put('/profile', authenticate, async (req, res) => { try { const { bio, settings } = req.body; if (bio !== undefined) { req.user.bio = bio; } if (settings) { req.user.settings = req.user.settings || {}; if (settings.whitelist) { const currentWhitelist = req.user.settings.whitelist && typeof req.user.settings.whitelist.toObject === 'function' ? req.user.settings.whitelist.toObject() : { ...(req.user.settings.whitelist || {}) }; req.user.settings.whitelist = { ...currentWhitelist, ...settings.whitelist }; } if (settings.searchPreference) { req.user.settings.searchPreference = ALLOWED_SEARCH_PREFERENCES.includes(settings.searchPreference) ? settings.searchPreference : 'furry'; } if (!req.user.settings.searchPreference) { req.user.settings.searchPreference = 'furry'; } if (!req.user.settings.whitelist) { req.user.settings.whitelist = { noNSFW: true, noHomo: true }; } else { if (req.user.settings.whitelist.noNSFW === undefined) { req.user.settings.whitelist.noNSFW = true; } if (req.user.settings.whitelist.noHomo === undefined) { req.user.settings.whitelist.noHomo = true; } } req.user.markModified('settings'); } await req.user.save(); res.json({ message: 'Профиль обновлен', user: req.user }); } catch (error) { console.error('Ошибка обновления профиля:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); // Поиск пользователей router.get('/search/:query', authenticate, async (req, res) => { try { const users = await User.find({ $or: [ { username: { $regex: req.params.query, $options: 'i' } }, { firstName: { $regex: req.params.query, $options: 'i' } }, { lastName: { $regex: req.params.query, $options: 'i' } } ] }) .select('username firstName lastName photoUrl') .limit(10); res.json({ users }); } catch (error) { console.error('Ошибка поиска пользователей:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); // Получить топ пользователей по билетам (Monthly Ladder) router.get('/ladder/top', authenticate, async (req, res) => { try { const { limit = 5 } = req.query; const limitNum = parseInt(limit); // Получить топ пользователей по билетам (исключаем glpshchn00) // Берем немного больше, чтобы гарантировать топ 5 после фильтрации const topUsers = await User.find({ banned: { $ne: true }, username: { $ne: 'glpshchn00' } }) .select('username firstName lastName photoUrl tickets') .sort({ tickets: -1 }) .limit(limitNum) .lean(); // Найти позицию текущего пользователя (исключаем glpshchn00) const userTickets = req.user.tickets || 0; const userRank = await User.countDocuments({ tickets: { $gt: userTickets }, banned: { $ne: true }, username: { $ne: 'glpshchn00' } }) + 1; // Исключить glpshchn00 из отображения const isExcludedUser = req.user.username === 'glpshchn00'; // Проверить, есть ли текущий пользователь в топе const currentUserInTop = !isExcludedUser && topUsers.some(u => u._id.toString() === req.user._id.toString()); // Если пользователь не в топе и не исключен, добавить его отдельно let currentUserData = null; if (!isExcludedUser && !currentUserInTop) { currentUserData = { _id: req.user._id, username: req.user.username, firstName: req.user.firstName, lastName: req.user.lastName, photoUrl: req.user.photoUrl, tickets: req.user.tickets || 0, rank: userRank }; } else if (!isExcludedUser && currentUserInTop) { // Если в топе, добавить rank к существующему пользователю topUsers.forEach((user, index) => { if (user._id.toString() === req.user._id.toString()) { user.rank = index + 1; } }); } // Добавить rank к топ пользователям topUsers.forEach((user, index) => { user.rank = index + 1; }); res.json({ topUsers, currentUser: currentUserData, currentUserRank: isExcludedUser ? null : (currentUserInTop ? topUsers.find(u => u._id.toString() === req.user._id.toString())?.rank : userRank) }); } catch (error) { console.error('Ошибка получения топа:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); module.exports = router;