165 lines
8.6 KiB
JavaScript
165 lines
8.6 KiB
JavaScript
![]() |
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,
|
|||
|
};
|