Add mention suggestions and admin list

This commit is contained in:
Tim
2025-07-31 17:57:25 +08:00
parent a02129b8f9
commit c541306494
9 changed files with 146 additions and 3 deletions

View File

@@ -196,6 +196,16 @@ public class UserController {
.collect(java.util.stream.Collectors.toList());
}
/**
* List all administrator users.
*/
@GetMapping("/admins")
public java.util.List<UserDto> admins() {
return userService.getAdmins().stream()
.map(this::toDto)
.collect(java.util.stream.Collectors.toList());
}
@GetMapping("/{identifier}/all")
public ResponseEntity<UserAggregateDto> userAggregate(@PathVariable("identifier") String identifier,
@RequestParam(value = "postsLimit", required = false) Integer postsLimit,

View File

@@ -31,5 +31,7 @@ public enum NotificationType {
/** A user requested registration approval */
REGISTER_REQUEST,
/** A user redeemed an activity reward */
ACTIVITY_REDEEM
ACTIVITY_REDEEM,
/** You were mentioned in a post or comment */
MENTION
}

View File

@@ -64,6 +64,7 @@ public class CommentService {
notificationService.createNotification(u, NotificationType.USER_ACTIVITY, post, comment, null, null, null, null);
}
}
notificationService.notifyMentions(content, author, post, comment);
return comment;
}
@@ -102,6 +103,7 @@ public class CommentService {
notificationService.createNotification(u, NotificationType.USER_ACTIVITY, parent.getPost(), comment, null, null, null, null);
}
}
notificationService.notifyMentions(content, author, parent.getPost(), comment);
return comment;
}

View File

@@ -11,6 +11,11 @@ import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.Executor;
@@ -28,6 +33,8 @@ public class NotificationService {
@Value("${app.website-url}")
private String websiteUrl;
private static final Pattern MENTION_PATTERN = Pattern.compile("@([A-Za-z0-9_]+)");
private String buildPayload(String body, String url) {
// try {
// return new ObjectMapper().writeValueAsString(Map.of(
@@ -144,4 +151,22 @@ public class NotificationService {
.orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found"));
return notificationRepository.countByUserAndRead(user, false);
}
public void notifyMentions(String content, User fromUser, Post post, Comment comment) {
if (content == null || fromUser == null) {
return;
}
Matcher matcher = MENTION_PATTERN.matcher(content);
Set<String> names = new HashSet<>();
while (matcher.find()) {
names.add(matcher.group(1));
}
for (String name : names) {
userRepository.findByUsername(name).ifPresent(target -> {
if (!target.getId().equals(fromUser.getId())) {
createNotification(target, NotificationType.MENTION, post, comment, null, fromUser, null, null);
}
});
}
}
}

View File

@@ -139,6 +139,7 @@ public class PostService {
null);
}
}
notificationService.notifyMentions(content, author, post, null);
return post;
}
@@ -407,6 +408,7 @@ public class PostService {
post.setTags(new java.util.HashSet<>(tags));
Post updated = postRepository.save(post);
imageUploader.adjustReferences(oldContent, content);
notificationService.notifyMentions(content, user, updated, null);
return updated;
}

View File

@@ -185,4 +185,11 @@ public class UserService {
user.setPassword(passwordEncoder.encode(newPassword));
return userRepository.save(user);
}
/**
* Get all administrator accounts.
*/
public java.util.List<User> getAdmins() {
return userRepository.findByRole(Role.ADMIN);
}
}