Reflex/backend/controllers/actionController.js

165 lines
8.6 KiB
JavaScript
Raw Normal View History

2025-05-21 22:13:09 +07:00
const User = require('../models/User'); // Нам нужна модель User
const Conversation = require('../models/Conversation'); // Добавляем модель Conversation
// @desc Лайкнуть пользователя
// @route POST /api/actions/like/:userId
// @access Private
const likeUser = async (req, res, next) => {
const likedUserId = req.params.userId; // ID пользователя, которого лайкают
const currentUserId = req.user._id; // ID текущего пользователя (из protect middleware)
console.log(`[ACTION_CTRL] Пользователь ${currentUserId} лайкает пользователя ${likedUserId}`);
try {
// 0. Проверка, не лайкает ли пользователь сам себя
if (currentUserId.equals(likedUserId)) {
const error = new Error('Вы не можете лайкнуть самого себя.');
error.statusCode = 400;
throw error;
}
// 1. Найти обоих пользователей
const currentUser = await User.findById(currentUserId);
const likedUser = await User.findById(likedUserId);
if (!currentUser || !likedUser) {
const error = new Error('Один из пользователей не найден.');
error.statusCode = 404;
throw error;
}
// 2. Проверить, не был ли этот пользователь уже лайкнут или пропущен текущим пользователем
if (currentUser.liked.includes(likedUserId)) {
console.log(`[ACTION_CTRL] Пользователь ${likedUserId} уже был лайкнут пользователем ${currentUserId}`);
// Можно вернуть информацию о существующем лайке или просто успешный ответ
return res.status(200).json({ message: 'Пользователь уже был лайкнут ранее.', isMatch: currentUser.matches.includes(likedUserId) });
}
if (currentUser.passed.includes(likedUserId)) {
// Если пользователь был ранее пропущен, убираем его из passed и продолжаем как обычный лайк
currentUser.passed.pull(likedUserId);
console.log(`[ACTION_CTRL] Пользователь ${likedUserId} был ранее пропущен, теперь лайкнут пользователем ${currentUserId}`);
}
// 3. Добавить likedUserId в массив 'liked' текущего пользователя
currentUser.liked.addToSet(likedUserId); // addToSet добавляет, только если элемента еще нет
// 4. Проверить на взаимный лайк (мэтч)
let isMatch = false;
let conversationId = null; // Инициализируем conversationId
// Проверяем, лайкал ли 'likedUser' текущего пользователя ('currentUser')
if (likedUser.liked.includes(currentUserId)) {
isMatch = true;
// Если мэтч, добавляем друг друга в массивы 'matches'
currentUser.matches.addToSet(likedUserId);
likedUser.matches.addToSet(currentUserId);
await likedUser.save(); // Сохраняем изменения для likedUser
console.log(`[ACTION_CTRL] !!! МЭТЧ !!! между ${currentUserId} и ${likedUserId}`);
// Автоматическое создание или получение диалога при мэтче
try {
let conversation = await Conversation.findOne({
participants: { $all: [currentUserId, likedUserId] }
});
if (!conversation) {
console.log(`[ACTION_CTRL] Создание нового диалога для мэтча между ${currentUserId} и ${likedUserId}`);
conversation = new Conversation({
participants: [currentUserId, likedUserId]
});
await conversation.save();
console.log(`[ACTION_CTRL] Новый диалог создан с ID: ${conversation._id}`);
} else {
console.log(`[ACTION_CTRL] Диалог для мэтча между ${currentUserId} и ${likedUserId} уже существует: ${conversation._id}`);
}
conversationId = conversation._id; // Сохраняем ID диалога
} catch (convError) {
console.error(`[ACTION_CTRL] Ошибка при создании/получении диалога для мэтча:`, convError.message);
// Не прерываем основной ответ из-за ошибки создания чата,
// но логируем. В реальном приложении здесь могла бы быть
// более сложная обработка или уведомление администратора.
}
// TODO: Здесь можно будет добавить логику для отправки уведомления о мэтче
}
await currentUser.save(); // Сохраняем изменения для currentUser
const responseJson = {
message: isMatch ? 'Это мэтч! Вы понравились друг другу!' : 'Лайк успешно поставлен.',
isMatch: isMatch,
};
if (isMatch && conversationId) {
responseJson.conversationId = conversationId;
}
res.status(200).json(responseJson);
} catch (error) {
console.error(`[ACTION_CTRL] Ошибка при лайке пользователя ${likedUserId} пользователем ${currentUserId}:`, error.message);
// Если statusCode не установлен ошибкой, errorHandler поставит 500
// Для ошибок типа "не найден" мы уже ставим 404
next(error);
}
};
// @desc Пропустить/дизлайкнуть пользователя
// @route POST /api/actions/pass/:userId
// @access Private
const passUser = async (req, res, next) => {
const passedUserId = req.params.userId; // ID пользователя, которого пропускают
const currentUserId = req.user._id; // ID текущего пользователя
console.log(`[ACTION_CTRL] Пользователь ${currentUserId} пропускает пользователя ${passedUserId}`);
try {
// 0. Проверка, не пропускает ли пользователь сам себя
if (currentUserId.equals(passedUserId)) {
const error = new Error('Вы не можете пропустить самого себя.');
error.statusCode = 400;
throw error;
}
const currentUser = await User.findById(currentUserId);
const userToPass = await User.findById(passedUserId); // Проверяем, что такой пользователь существует
if (!currentUser || !userToPass) {
const error = new Error('Один из пользователей не найден.');
error.statusCode = 404;
throw error;
}
// 1. Добавить passedUserId в массив 'passed' текущего пользователя
currentUser.passed.addToSet(passedUserId);
// 2. Если этот пользователь был ранее лайкнут, убрать его из лайков
// (на случай, если пользователь передумал, хотя UI обычно не дает так сделать без "анлайка")
if (currentUser.liked.includes(passedUserId)) {
currentUser.liked.pull(passedUserId);
// Также нужно проверить, не был ли это мэтч, и если да, то убрать из мэтчей у обоих
if (currentUser.matches.includes(passedUserId)) {
currentUser.matches.pull(passedUserId);
userToPass.matches.pull(currentUserId);
await userToPass.save(); // Сохраняем изменения для другого пользователя
console.log(`[ACTION_CTRL] Мэтч между ${currentUserId} и ${passedUserId} был разорван из-за пропуска.`);
}
}
await currentUser.save();
res.status(200).json({
message: 'Пользователь успешно пропущен.',
// passed: currentUser.passed
});
} catch (error) {
console.error(`[ACTION_CTRL] Ошибка при пропуске пользователя ${passedUserId} пользователем ${currentUserId}:`, error.message);
next(error);
}
};
module.exports = {
likeUser,
passUser,
};