import BaseService from './BaseService.js'; import Friendship from '../models/community/friendship.js'; import User from '../models/community/user.js'; import { Op } from 'sequelize'; import UserParam from '../models/community/user_param.js'; import UserParamType from '../models/type/user_param.js'; import UserParamValue from '../models/type/user_param_value.js'; import { notifyUser } from '../utils/socket.js'; class FriendshipService extends BaseService { genders = {}; async endFriendship(hashedUserId, friendUserId) { const user = await this.getUserByHashedId(hashedUserId); const friend = await this.getUserByHashedId(friendUserId); if (!user) throw new Error('User not found.'); const friendship = await Friendship.findOne({ where: { [Op.or]: [ { user1Id: user.id, user2Id: friend.id }, { user1Id: friend.id, user2Id: user.id }, ], }, }); if (!friendship) throw new Error('Friendship not found.'); await friendship.destroy(); notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId }); } async acceptFriendship(hashedUserId, friendUserId) { const user = await this.getUserByHashedId(hashedUserId); const friend = await this.getUserByHashedId(friendUserId); if (!user) throw new Error('User not found.'); const friendship = await Friendship.findOne({ where: { user1Id: friend.id, user2Id: user.id, accepted: false }, }); if (!friendship) throw new Error('Cannot accept this friendship.'); friendship.accepted = true; await friendship.save(); notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId }); } async rejectFriendship(hashedUserId, friendUserId) { const user = await this.getUserByHashedId(hashedUserId); const friend = await this.getUserByHashedId(friendUserId); if (!user) throw new Error('User not found.'); const friendship = await Friendship.findOne({ where: { user1Id: friend.id, user2Id: user.id, accepted: false }, }); if (!friendship) throw new Error('Cannot reject this friendship.'); friendship.denied = true; await friendship.save(); notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId }); } async withdrawRequest(hashedUserId, friendUserId) { const user = await this.getUserByHashedId(hashedUserId); const friend = await this.getUserByHashedId(friendUserId); if (!user) throw new Error('User not found.'); const friendship = await Friendship.findOne({ where: { user1Id: user.id, user2Id: friend.id, accepted: false }, }); if (!friendship) throw new Error('Cannot withdraw this request.'); await friendship.destroy(); notifyUser(friend.hashedId, 'friendshipChanged', { userId: user.hashedId }); } async getFriendships(hashedUserId, acceptedOnly) { const user = await this.getUserByHashedId(hashedUserId); if (!user) throw new Error('User not found.'); const whereCondition = acceptedOnly ? { accepted: true, withdrawn: false, denied: false } : {}; const friendships = await Friendship.findAll({ where: { ...whereCondition, [Op.or]: [ { user1Id: user.id }, { user2Id: user.id }, ], }, include: [ { model: User, as: 'friendSender', attributes: ['username', 'hashedId'], include: [ { model: UserParam, as: 'user_params', required: false, include: [ { model: UserParamType, as: 'paramType', required: true, where: { description: 'gender' }, attributes: ['description'], }, ], attributes: ['value'], }, ], }, { model: User, as: 'friendReceiver', attributes: ['username', 'hashedId'], include: [ { model: UserParam, as: 'user_params', required: false, include: [ { model: UserParamType, as: 'paramType', required: true, where: { description: 'gender' }, attributes: ['description'], }, ], attributes: ['value'], }, ], }, ], }); const processedFriendships = await Promise.all( friendships.map(async (friendship) => { const isInitiator = friendship.user1Id === user.id; const otherUser = isInitiator ? friendship.friendReceiver : friendship.friendSender; const genderParam = otherUser.user_params?.find(param => param.paramType.description === 'gender'); const gender = genderParam ? await this.getGender(genderParam) : null; return { id: friendship.id, user: { username: otherUser.username, hashedId: otherUser.hashedId, gender, }, accepted: friendship.accepted, denied: friendship.denied, withdrawn: friendship.withdrawn, isInitiator, }; }) ); return processedFriendships; } async getGender(genderParam) { if (!this.genders) { this.genders = {}; } if (this.genders[genderParam.value]) return this.genders[genderParam.value]; const genderObject = await UserParamValue.findOne({ where: { id: genderParam.value }, }); if (genderObject) { this.genders[genderParam.value] = genderObject.value; return genderObject.value; } return ''; } } export default new FriendshipService();