Skip to content

Commit 48ba1a9

Browse files
authored
Merge pull request #208 from JECT-Study/feature/slangcheck
Feature:SlangFilter 추가 닉네임에 욕설 유무 포함
2 parents dba8b7b + 6171e0b commit 48ba1a9

7 files changed

Lines changed: 2223 additions & 5 deletions

File tree

src/main/java/com/ject/vs/user/adapter/web/UserController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ public ResponseEntity<NicknameCheckResponse> isUniqueNickname(@AuthenticationPri
4141
return ResponseEntity.ok(response);
4242
}
4343

44+
@PostMapping("/nickname/slang")
45+
public ResponseEntity<NicknameCheckResponse> checkNicknameSlang(@AuthenticationPrincipal Long userId, @RequestBody UserNicknameRec nickname) {
46+
return ResponseEntity.ok(userService.checkNicknameSlang(nickname.nickname(), userId));
47+
}
48+
4449
@Operation(summary = "닉네임 추천", description = "사용 가능한 랜덤 닉네임을 추천합니다.")
4550
@GetMapping("/nickname/suggest")
4651
public ResponseEntity<UserNicknameRec> suggestNickname(@AuthenticationPrincipal Long userId) {

src/main/java/com/ject/vs/user/domain/User.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public void initializeDefault(String email, Year birthYear, Gender gender, Strin
6363
this.nickname = nickname;
6464
}
6565

66+
public static void modifyImageColor(User user, ImageColor imageColor) {
67+
user.imageColor = imageColor;
68+
}
69+
6670
public static void modifyAccount(User user, String nickname, ImageColor imageColor) {
6771
user.nickname = nickname;
6872
user.imageColor = imageColor;

src/main/java/com/ject/vs/user/exception/UserErrorCode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
public enum UserErrorCode implements ErrorCode {
1010

1111
USER_NOT_FOUND("E400000", "사용자 정보가 없습니다.", 404),
12-
USER_NOT_REGISTER("E400001", "등록되지 않은 사용자입니다.", 404);
12+
USER_NOT_REGISTER("E400001", "등록되지 않은 사용자입니다.", 404),
13+
USER_NICKNAME_DUPLICATE("E400002", "중복된 닉네임입니다.", 404);
1314

1415
private final String code;
1516
private final String message;

src/main/java/com/ject/vs/user/port/UserService.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,18 @@ public User findOrCreate(String email) {
2929
.orElseGet(() -> userRepository.save(User.createWithEmail(email)));
3030
}
3131

32-
public User findByEmail(String email) {
33-
return userRepository.findByEmail(email)
32+
public NicknameCheckResponse checkNickname(String nickName, Long userId) {
33+
userRepository.findById(userId)
3434
.orElseThrow(() -> new BusinessException(UserErrorCode.USER_NOT_FOUND));
35+
36+
return new NicknameCheckResponse(userRepository.isNicknameAvailable(nickName));
3537
}
3638

37-
public NicknameCheckResponse checkNickname(String nickName, Long userId) {
39+
public NicknameCheckResponse checkNicknameSlang(String nickName, Long userId) {
3840
userRepository.findById(userId)
3941
.orElseThrow(() -> new BusinessException(UserErrorCode.USER_NOT_FOUND));
4042

41-
return new NicknameCheckResponse(userRepository.isNicknameAvailable(nickName));
43+
return new NicknameCheckResponse(!wordService.containSlang(nickName));
4244
}
4345

4446
public UserProfileResponse setupAdditionalInfo(UserExtraInfo userInfo, Long userId) {
@@ -80,6 +82,15 @@ public UserMyPageResponse modifyInfo(Long userId, UserModifyInfoRequest req) {
8082
User user = userRepository.findById(userId)
8183
.orElseThrow(() -> new BusinessException(UserErrorCode.USER_NOT_FOUND));
8284

85+
if(req.nickname().equals(user.getNickname())) {
86+
User.modifyImageColor(user, req.imageColor());
87+
88+
return new UserMyPageResponse(user.getEmail(), user.getNickname(), user.getImageColor());
89+
}
90+
else if(!userRepository.isNicknameAvailable(req.nickname())) {
91+
throw new BusinessException(UserErrorCode.USER_NICKNAME_DUPLICATE);
92+
}
93+
8394
User.modifyAccount(user, req.nickname(), req.imageColor());
8495

8596
return new UserMyPageResponse(user.getEmail(), user.getNickname(), user.getImageColor());

src/main/java/com/ject/vs/user/port/WordService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.ject.vs.user.port;
22

33
import com.ject.vs.user.domain.UserRepository;
4+
import com.ject.vs.util.SlangFilter;
45
import jakarta.annotation.PostConstruct;
56
import lombok.RequiredArgsConstructor;
67
import lombok.extern.slf4j.Slf4j;
@@ -28,12 +29,14 @@ public class WordService {
2829

2930
private List<String> words2 = new ArrayList<>();
3031
private List<String> words3 = new ArrayList<>();
32+
private List<String> slang = new ArrayList<>();
3133

3234
@PostConstruct
3335
public void init() {
3436
try {
3537
words2 = loadWords("classpath:data/ko_words_2.txt");
3638
words3 = loadWords("classpath:data/ko_words_3.txt");
39+
slang = loadWords("classpath:data/slang.txt");
3740
} catch (IOException e) {
3841
log.error("단어 로딩 실패", e);
3942
}
@@ -77,4 +80,8 @@ public String generateNickname() {
7780

7881
return ret;
7982
}
83+
84+
public boolean containSlang(String input) {
85+
return SlangFilter.containsSlang(input, slang);
86+
}
8087
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.ject.vs.util;
2+
3+
import java.util.List;
4+
5+
public class SlangFilter {
6+
private static int[] buildFailure(char[] pattern) {
7+
int m = pattern.length;
8+
int[] fail = new int[m];
9+
fail[0] = 0;
10+
int j = 0;
11+
12+
for(int i = 1; i < m; i++) {
13+
while(j > 0 && pattern[i] != pattern[j]) {
14+
j = fail[j-1];
15+
}
16+
if(pattern[i] == pattern[j]) j++;
17+
fail[i] = j;
18+
}
19+
return fail;
20+
}
21+
22+
private static boolean kmpContains(char[] text, char[] pattern) {
23+
int n = text.length;
24+
int m = pattern.length;
25+
if(m == 0) return false;
26+
27+
int[] fail = buildFailure(pattern);
28+
int j = 0;
29+
30+
for(int i = 0; i < n; i++) {
31+
while(j > 0 && text[i] != pattern[j]) {
32+
j = fail[j-1];
33+
}
34+
if(text[i] == pattern[j]) j++;
35+
if(j == m) return true;
36+
}
37+
return false;
38+
}
39+
40+
public static boolean containsSlang(String input, List<String> slangList) {
41+
if(input == null || input.isBlank()) return false;
42+
char[] text = input.toCharArray();
43+
44+
for(String slang : slangList) {
45+
if(kmpContains(text, slang.toCharArray())) return true;
46+
}
47+
return false;
48+
}
49+
}

0 commit comments

Comments
 (0)