438 lines
15 KiB
Java
438 lines
15 KiB
Java
package com.lions.dev.service;
|
|
|
|
import com.lions.dev.entity.friends.Friendship;
|
|
import com.lions.dev.entity.social.SocialPost;
|
|
import com.lions.dev.entity.users.Users;
|
|
import com.lions.dev.exception.UserNotFoundException;
|
|
import com.lions.dev.repository.FriendshipRepository;
|
|
import com.lions.dev.repository.SocialPostRepository;
|
|
import com.lions.dev.repository.UsersRepository;
|
|
import com.lions.dev.dto.events.ReactionEvent;
|
|
import org.eclipse.microprofile.reactive.messaging.Channel;
|
|
import org.eclipse.microprofile.reactive.messaging.Emitter;
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.transaction.Transactional;
|
|
import org.jboss.logging.Logger;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* Service de gestion des posts sociaux.
|
|
*
|
|
* Ce service contient la logique métier pour la création, récupération,
|
|
* mise à jour et suppression des posts sociaux.
|
|
*/
|
|
@ApplicationScoped
|
|
public class SocialPostService {
|
|
|
|
private static final Logger logger = Logger.getLogger(SocialPostService.class);
|
|
|
|
@Inject
|
|
SocialPostRepository socialPostRepository;
|
|
|
|
@Inject
|
|
UsersRepository usersRepository;
|
|
|
|
@Inject
|
|
FriendshipRepository friendshipRepository;
|
|
|
|
@Inject
|
|
NotificationService notificationService;
|
|
|
|
@Inject
|
|
@Channel("reactions")
|
|
Emitter<ReactionEvent> reactionEmitter; // v2.0 - Publie dans Kafka
|
|
|
|
/**
|
|
* Récupère tous les posts avec pagination.
|
|
*
|
|
* @param page Le numéro de la page (0-indexé)
|
|
* @param size La taille de la page
|
|
* @return Liste paginée des posts
|
|
*/
|
|
public List<SocialPost> getAllPosts(int page, int size) {
|
|
logger.info("[SocialPostService] Récupération de tous les posts (page: " + page + ", size: " + size + ")");
|
|
return socialPostRepository.findAllWithPagination(page, size);
|
|
}
|
|
|
|
/**
|
|
* Récupère tous les posts d'un utilisateur.
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
* @return Liste des posts de l'utilisateur
|
|
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
|
*/
|
|
public List<SocialPost> getPostsByUserId(UUID userId) {
|
|
logger.info("[SocialPostService] Récupération des posts pour l'utilisateur ID : " + userId);
|
|
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[SocialPostService] Utilisateur non trouvé avec l'ID : " + userId);
|
|
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
|
}
|
|
|
|
return socialPostRepository.findByUserId(userId);
|
|
}
|
|
|
|
/**
|
|
* Crée un nouveau post social.
|
|
*
|
|
* @param content Le contenu du post
|
|
* @param userId L'ID de l'utilisateur créateur
|
|
* @param imageUrl L'URL de l'image (optionnel)
|
|
* @return Le post créé
|
|
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
|
*/
|
|
@Transactional
|
|
public SocialPost createPost(String content, UUID userId, String imageUrl) {
|
|
logger.info("[SocialPostService] Création d'un post par l'utilisateur ID : " + userId);
|
|
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[SocialPostService] Utilisateur non trouvé avec l'ID : " + userId);
|
|
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
|
}
|
|
|
|
SocialPost post = new SocialPost(content, user);
|
|
if (imageUrl != null && !imageUrl.isEmpty()) {
|
|
post.setImageUrl(imageUrl);
|
|
}
|
|
|
|
socialPostRepository.persist(post);
|
|
logger.info("[SocialPostService] Post créé avec succès : " + post.getId());
|
|
|
|
// Créer des notifications pour tous les amis
|
|
try {
|
|
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, 0, Integer.MAX_VALUE);
|
|
// v2.0 - Utiliser les nouveaux noms de champs
|
|
String userName = user.getFirstName() + " " + user.getLastName();
|
|
|
|
for (Friendship friendship : friendships) {
|
|
Users friend = friendship.getUser().equals(user)
|
|
? friendship.getFriend()
|
|
: friendship.getUser();
|
|
|
|
String notificationTitle = "Nouveau post de " + userName;
|
|
String notificationMessage = userName + " a publié un nouveau post : " +
|
|
(content.length() > 50 ? content.substring(0, 50) + "..." : content);
|
|
|
|
notificationService.createNotification(
|
|
notificationTitle,
|
|
notificationMessage,
|
|
"post",
|
|
friend.getId(),
|
|
null
|
|
);
|
|
}
|
|
logger.info("[SocialPostService] Notifications créées pour " + friendships.size() + " ami(s)");
|
|
} catch (Exception e) {
|
|
logger.error("[SocialPostService] Erreur lors de la création des notifications : " + e.getMessage());
|
|
}
|
|
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* Récupère un post par son ID.
|
|
*
|
|
* @param postId L'ID du post
|
|
* @return Le post trouvé
|
|
*/
|
|
public SocialPost getPostById(UUID postId) {
|
|
logger.info("[SocialPostService] Récupération du post ID : " + postId);
|
|
|
|
SocialPost post = socialPostRepository.findById(postId);
|
|
if (post == null) {
|
|
logger.error("[SocialPostService] Post non trouvé avec l'ID : " + postId);
|
|
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
|
}
|
|
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* Met à jour un post.
|
|
*
|
|
* @param postId L'ID du post
|
|
* @param content Le nouveau contenu
|
|
* @param imageUrl La nouvelle URL d'image (optionnel)
|
|
* @return Le post mis à jour
|
|
*/
|
|
@Transactional
|
|
public SocialPost updatePost(UUID postId, String content, String imageUrl) {
|
|
logger.info("[SocialPostService] Mise à jour du post ID : " + postId);
|
|
|
|
SocialPost post = socialPostRepository.findById(postId);
|
|
if (post == null) {
|
|
logger.error("[SocialPostService] Post non trouvé avec l'ID : " + postId);
|
|
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
|
}
|
|
|
|
post.setContent(content);
|
|
if (imageUrl != null) {
|
|
post.setImageUrl(imageUrl);
|
|
}
|
|
|
|
socialPostRepository.persist(post);
|
|
logger.info("[SocialPostService] Post mis à jour avec succès");
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* Supprime un post.
|
|
*
|
|
* @param postId L'ID du post
|
|
* @return true si le post a été supprimé, false sinon
|
|
*/
|
|
@Transactional
|
|
public boolean deletePost(UUID postId) {
|
|
logger.info("[SocialPostService] Suppression du post ID : " + postId);
|
|
|
|
SocialPost post = socialPostRepository.findById(postId);
|
|
if (post == null) {
|
|
logger.error("[SocialPostService] Post non trouvé avec l'ID : " + postId);
|
|
return false;
|
|
}
|
|
|
|
socialPostRepository.delete(post);
|
|
logger.info("[SocialPostService] Post supprimé avec succès");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Recherche des posts par contenu.
|
|
*
|
|
* @param query Le terme de recherche
|
|
* @return Liste des posts correspondant à la recherche
|
|
*/
|
|
public List<SocialPost> searchPosts(String query) {
|
|
logger.info("[SocialPostService] Recherche de posts avec la requête : " + query);
|
|
return socialPostRepository.searchByContent(query);
|
|
}
|
|
|
|
/**
|
|
* Like un post (incrémente le compteur de likes).
|
|
*
|
|
* @param postId L'ID du post
|
|
* @param userId L'ID de l'utilisateur qui like (v2.0)
|
|
* @return Le post mis à jour
|
|
*/
|
|
@Transactional
|
|
public SocialPost likePost(UUID postId, UUID userId) {
|
|
logger.info("[SocialPostService] Like du post ID : " + postId + " par utilisateur : " + userId);
|
|
|
|
SocialPost post = socialPostRepository.findById(postId);
|
|
if (post == null) {
|
|
logger.error("[SocialPostService] Post non trouvé avec l'ID : " + postId);
|
|
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
|
}
|
|
|
|
post.incrementLikes();
|
|
socialPostRepository.persist(post);
|
|
|
|
// Notification pour l'auteur du post (sauf auto-like)
|
|
try {
|
|
Users author = post.getUser();
|
|
if (author != null && !author.getId().equals(userId)) {
|
|
Users liker = usersRepository.findById(userId);
|
|
String likerName = liker != null ? liker.getFirstName() + " " + liker.getLastName() : "Quelqu'un";
|
|
notificationService.createNotification(
|
|
"Nouveau like",
|
|
likerName + " a aimé votre post",
|
|
"post",
|
|
author.getId(),
|
|
null
|
|
);
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("[SocialPostService] Erreur création notification like : " + e.getMessage());
|
|
}
|
|
|
|
// TEMPS RÉEL: Publier dans Kafka (v2.0)
|
|
try {
|
|
Map<String, Object> reactionData = new HashMap<>();
|
|
reactionData.put("ownerId", post.getUser().getId().toString()); // Propriétaire du post
|
|
reactionData.put("likesCount", post.getLikesCount());
|
|
reactionData.put("postTitle", post.getContent().length() > 50
|
|
? post.getContent().substring(0, 50) + "..."
|
|
: post.getContent());
|
|
|
|
ReactionEvent event = new ReactionEvent(
|
|
postId.toString(), // targetId
|
|
"post", // targetType
|
|
userId.toString(), // userId qui réagit
|
|
"like", // reactionType
|
|
reactionData
|
|
);
|
|
|
|
reactionEmitter.send(event);
|
|
logger.info("[SocialPostService] Réaction like publiée dans Kafka pour post: " + postId);
|
|
} catch (Exception e) {
|
|
logger.error("[SocialPostService] Erreur publication Kafka: " + e.getMessage());
|
|
// Ne pas bloquer le like si Kafka échoue
|
|
}
|
|
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* Ajoute un commentaire à un post (incrémente le compteur de commentaires).
|
|
*
|
|
* @param postId L'ID du post
|
|
* @param userId L'ID de l'utilisateur qui commente (v2.0)
|
|
* @param commentContent Le contenu du commentaire (v2.0)
|
|
* @return Le post mis à jour
|
|
*/
|
|
@Transactional
|
|
public SocialPost addComment(UUID postId, UUID userId, String commentContent) {
|
|
logger.info("[SocialPostService] Ajout de commentaire au post ID : " + postId + " par utilisateur : " + userId);
|
|
|
|
SocialPost post = socialPostRepository.findById(postId);
|
|
if (post == null) {
|
|
logger.error("[SocialPostService] Post non trouvé avec l'ID : " + postId);
|
|
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
|
}
|
|
|
|
post.incrementComments();
|
|
socialPostRepository.persist(post);
|
|
|
|
// Notification pour l'auteur du post (sauf auto-commentaire)
|
|
try {
|
|
Users author = post.getUser();
|
|
if (author != null && !author.getId().equals(userId)) {
|
|
Users commenter = usersRepository.findById(userId);
|
|
String commenterName = commenter != null ? commenter.getFirstName() + " " + commenter.getLastName() : "Quelqu'un";
|
|
String preview = commentContent != null && commentContent.length() > 60
|
|
? commentContent.substring(0, 60) + "..."
|
|
: (commentContent != null ? commentContent : "");
|
|
notificationService.createNotification(
|
|
"Nouveau commentaire",
|
|
commenterName + " a commenté votre post : " + preview,
|
|
"post",
|
|
author.getId(),
|
|
null
|
|
);
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("[SocialPostService] Erreur création notification commentaire : " + e.getMessage());
|
|
}
|
|
|
|
// TEMPS RÉEL: Publier dans Kafka (v2.0)
|
|
try {
|
|
Users commenter = usersRepository.findById(userId);
|
|
Map<String, Object> reactionData = new HashMap<>();
|
|
reactionData.put("ownerId", post.getUser().getId().toString()); // Propriétaire du post
|
|
reactionData.put("commentsCount", post.getCommentsCount());
|
|
reactionData.put("commentContent", commentContent != null && commentContent.length() > 100
|
|
? commentContent.substring(0, 100) + "..."
|
|
: commentContent);
|
|
reactionData.put("commenterName", commenter != null
|
|
? commenter.getFirstName() + " " + commenter.getLastName()
|
|
: "Utilisateur");
|
|
|
|
ReactionEvent event = new ReactionEvent(
|
|
postId.toString(), // targetId
|
|
"post", // targetType
|
|
userId.toString(), // userId qui commente
|
|
"comment", // reactionType
|
|
reactionData
|
|
);
|
|
|
|
reactionEmitter.send(event);
|
|
logger.info("[SocialPostService] Réaction comment publiée dans Kafka pour post: " + postId);
|
|
} catch (Exception e) {
|
|
logger.error("[SocialPostService] Erreur publication Kafka: " + e.getMessage());
|
|
// Ne pas bloquer le commentaire si Kafka échoue
|
|
}
|
|
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* Partage un post (incrémente le compteur de partages).
|
|
*
|
|
* @param postId L'ID du post
|
|
* @param userId L'ID de l'utilisateur qui partage (v2.0)
|
|
* @return Le post mis à jour
|
|
*/
|
|
@Transactional
|
|
public SocialPost sharePost(UUID postId, UUID userId) {
|
|
logger.info("[SocialPostService] Partage du post ID : " + postId + " par utilisateur : " + userId);
|
|
|
|
SocialPost post = socialPostRepository.findById(postId);
|
|
if (post == null) {
|
|
logger.error("[SocialPostService] Post non trouvé avec l'ID : " + postId);
|
|
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
|
}
|
|
|
|
post.incrementShares();
|
|
socialPostRepository.persist(post);
|
|
|
|
// TEMPS RÉEL: Publier dans Kafka (v2.0)
|
|
try {
|
|
Map<String, Object> reactionData = new HashMap<>();
|
|
reactionData.put("ownerId", post.getUser().getId().toString()); // Propriétaire du post
|
|
reactionData.put("sharesCount", post.getSharesCount());
|
|
|
|
ReactionEvent event = new ReactionEvent(
|
|
postId.toString(), // targetId
|
|
"post", // targetType
|
|
userId.toString(), // userId qui partage
|
|
"share", // reactionType
|
|
reactionData
|
|
);
|
|
|
|
reactionEmitter.send(event);
|
|
logger.info("[SocialPostService] Réaction share publiée dans Kafka pour post: " + postId);
|
|
} catch (Exception e) {
|
|
logger.error("[SocialPostService] Erreur publication Kafka: " + e.getMessage());
|
|
// Ne pas bloquer le partage si Kafka échoue
|
|
}
|
|
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* Récupère les posts de l'utilisateur et de ses amis (relations d'amitié acceptées).
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
* @param page Le numéro de la page (0-indexé)
|
|
* @param size La taille de la page
|
|
* @return Liste paginée des posts de l'utilisateur et de ses amis
|
|
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
|
*/
|
|
public List<SocialPost> getPostsByFriends(UUID userId, int page, int size) {
|
|
logger.info("[SocialPostService] Récupération des posts des amis pour l'utilisateur ID : " + userId);
|
|
|
|
Users user = usersRepository.findById(userId);
|
|
if (user == null) {
|
|
logger.error("[SocialPostService] Utilisateur non trouvé avec l'ID : " + userId);
|
|
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
|
}
|
|
|
|
// Récupérer toutes les relations d'amitié acceptées
|
|
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, 0, Integer.MAX_VALUE);
|
|
|
|
// Extraire les IDs des amis
|
|
List<UUID> friendIds = friendships.stream()
|
|
.map(friendship -> {
|
|
// L'ami est soit dans 'user' soit dans 'friend', selon qui a initié la relation
|
|
return friendship.getUser().equals(user)
|
|
? friendship.getFriend().getId()
|
|
: friendship.getUser().getId();
|
|
})
|
|
.distinct()
|
|
.collect(Collectors.toList());
|
|
|
|
logger.info("[SocialPostService] " + friendIds.size() + " ami(s) trouvé(s) pour l'utilisateur ID : " + userId);
|
|
|
|
// Récupérer les posts de l'utilisateur et de ses amis
|
|
return socialPostRepository.findPostsByFriends(userId, friendIds, page, size);
|
|
}
|
|
}
|
|
|