package com.xuqm.im.controller; import com.xuqm.common.model.ApiResponse; import com.xuqm.im.entity.ImFriendEntity; import com.xuqm.im.repository.ImFriendRepository; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @RestController @RequestMapping("/api/im/friends") public class FriendController { private final ImFriendRepository friendRepository; public FriendController(ImFriendRepository friendRepository) { this.friendRepository = friendRepository; } @GetMapping public ResponseEntity>> listFriends( @AuthenticationPrincipal String userId, @RequestParam String appKey) { List friendIds = friendRepository.findByAppIdAndUserId(appKey, userId) .stream() .map(ImFriendEntity::getFriendId) .toList(); return ResponseEntity.ok(ApiResponse.success(friendIds)); } @PostMapping public ResponseEntity> addFriend( @AuthenticationPrincipal String userId, @RequestParam String appKey, @RequestParam String friendId) { return ResponseEntity.ok(ApiResponse.success(addFriendLink(appKey, userId, friendId))); } @PostMapping("/batch") public ResponseEntity>> addFriends( @AuthenticationPrincipal String userId, @RequestParam String appKey, @RequestBody FriendBatchRequest req) { List links = new ArrayList<>(); for (String friendId : unique(req.friendIds())) { if (friendId == null || friendId.isBlank() || userId.equals(friendId)) { continue; } links.add(addFriendLink(appKey, userId, friendId)); } return ResponseEntity.ok(ApiResponse.success(links)); } @DeleteMapping("/{friendId}") public ResponseEntity> removeFriend( @AuthenticationPrincipal String userId, @PathVariable String friendId, @RequestParam String appKey) { friendRepository.deleteByAppIdAndUserIdAndFriendId(appKey, userId, friendId); friendRepository.deleteByAppIdAndUserIdAndFriendId(appKey, friendId, userId); return ResponseEntity.ok(ApiResponse.success(null)); } @DeleteMapping public ResponseEntity> removeAllFriends( @AuthenticationPrincipal String userId, @RequestParam String appKey) { friendRepository.deleteByAppIdAndUserId(appKey, userId); friendRepository.deleteByAppIdAndFriendId(appKey, userId); return ResponseEntity.ok(ApiResponse.ok()); } @PostMapping("/batch/remove") public ResponseEntity> removeFriends( @AuthenticationPrincipal String userId, @RequestParam String appKey, @RequestBody FriendBatchRequest req) { for (String friendId : unique(req.friendIds())) { if (friendId == null || friendId.isBlank() || userId.equals(friendId)) { continue; } friendRepository.deleteByAppIdAndUserIdAndFriendId(appKey, userId, friendId); friendRepository.deleteByAppIdAndUserIdAndFriendId(appKey, friendId, userId); } return ResponseEntity.ok(ApiResponse.success(null)); } @PutMapping("/{friendId}/group") public ResponseEntity> setFriendGroup( @AuthenticationPrincipal String userId, @PathVariable String friendId, @RequestParam String appKey, @RequestParam(required = false) String groupName) { ImFriendEntity link = friendRepository.findByAppIdAndUserIdAndFriendId(appKey, userId, friendId) .orElseGet(() -> addFriendLink(appKey, userId, friendId)); link.setFriendGroup(normalizeGroup(groupName)); return ResponseEntity.ok(ApiResponse.success(friendRepository.save(link))); } @GetMapping("/groups") public ResponseEntity>> listFriendGroups( @AuthenticationPrincipal String userId, @RequestParam String appKey) { List groups = friendRepository.findByAppIdAndUserId(appKey, userId).stream() .map(ImFriendEntity::getFriendGroup) .filter(group -> group != null && !group.isBlank()) .distinct() .sorted() .toList(); return ResponseEntity.ok(ApiResponse.success(groups)); } @GetMapping("/groups/{groupName}") public ResponseEntity>> listFriendsByGroup( @AuthenticationPrincipal String userId, @RequestParam String appKey, @PathVariable String groupName) { List friendIds = friendRepository .findByAppIdAndUserIdAndFriendGroup(appKey, userId, normalizeGroup(groupName)) .stream() .map(ImFriendEntity::getFriendId) .toList(); return ResponseEntity.ok(ApiResponse.success(friendIds)); } private ImFriendEntity addFriendLink(String appKey, String userId, String friendId) { ImFriendEntity forward = friendRepository .findByAppIdAndUserIdAndFriendId(appKey, userId, friendId) .orElseGet(() -> { ImFriendEntity e = new ImFriendEntity(); e.setAppId(appKey); e.setUserId(userId); e.setFriendId(friendId); return friendRepository.save(e); }); friendRepository.findByAppIdAndUserIdAndFriendId(appKey, friendId, userId) .orElseGet(() -> { ImFriendEntity e = new ImFriendEntity(); e.setAppId(appKey); e.setUserId(friendId); e.setFriendId(userId); return friendRepository.save(e); }); return forward; } private List unique(List friendIds) { return friendIds == null ? List.of() : new ArrayList<>(new LinkedHashSet<>(friendIds)); } private String normalizeGroup(String groupName) { return groupName == null || groupName.isBlank() ? null : groupName.trim(); } @PostMapping("/check") public ResponseEntity>> checkFriends( @AuthenticationPrincipal String userId, @RequestParam String appKey, @RequestBody FriendCheckRequest req) { List results = new ArrayList<>(); for (String friendId : req.friendIds() == null ? List.of() : req.friendIds()) { boolean isFriend = friendRepository.existsByAppIdAndUserIdAndFriendId(appKey, userId, friendId) || friendRepository.existsByAppIdAndUserIdAndFriendId(appKey, friendId, userId); results.add(new FriendCheckResult(friendId, isFriend)); } return ResponseEntity.ok(ApiResponse.success(results)); } public record FriendBatchRequest(List friendIds) {} public record FriendCheckRequest(List friendIds) {} public record FriendCheckResult(String userId, boolean isFriend) {} }