Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.gamzabat.algohub.auth.exception.GithubApiException;
import com.gamzabat.algohub.common.jwt.TokenProvider;
import com.gamzabat.algohub.common.jwt.dto.JwtDTO;
import com.gamzabat.algohub.common.logging.DiscordWebhookService;
import com.gamzabat.algohub.constants.ApiConstants;
import com.gamzabat.algohub.enums.Role;
import com.gamzabat.algohub.feature.user.domain.User;
Expand All @@ -48,6 +49,7 @@ public class OAuth2Service {
private String secretKey;
private final RestTemplate restTemplate;
private final UserRepository userRepository;
private final DiscordWebhookService webhookService;

@Transactional
public TokenResponse githubSignIn(String code) {
Expand Down Expand Up @@ -79,6 +81,8 @@ private void register(GithubUserDto githubUser) {
.build());
newUser.editNickname(createTemporaryNickname(githubUser.getLogin(), newUser.getId()));
newUser.editGithubName(githubUser.getLogin());

webhookService.sendRegisterMessage(newUser.getNickname(), "Github", newUser.getId());
}

private String createTemporaryNickname(String login, Long id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.gamzabat.algohub.common.logging;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@RequiredArgsConstructor
@Slf4j
public class DiscordWebhookService {
@Value("${noti_url:}")
private String webhookUrl;

private final RestTemplate restTemplate;

public void sendRegisterMessage(String username, String type, Long sid) {
String content = username + " λ‹˜μ΄ " + type + " λ°©μ‹μœΌλ‘œ " + sid + "번째둜 νšŒμ›κ°€μž… ν•˜μ…¨μŠ΅λ‹ˆλ‹€!! πŸŽ‰";
Copy link

Copilot AI May 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Hardcoding localized strings in code can hinder future localization; consider externalizing message templates or using a message source for maintainability.

Copilot uses AI. Check for mistakes.
this.send(content);
}

public void sendCreateGroupMessage(String username, String groupName) {
String content = username + " λ‹˜μ΄ " + groupName + " 그룹을 μƒμ„±ν•˜μ…¨μŠ΅λ‹ˆλ‹€ 😎";
this.send(content);
}

private void send(String message) {
try {
if (!StringUtils.hasText(webhookUrl)) {
log.debug("No webhook url provided");
return;
Comment on lines +35 to +37
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

webhook-prod.ymlμ—λ§Œ λ…Έν‹° μ£Όμ†Œ λ„£μ—ˆμŠ΅λ‹ˆλ‹€.

λ‚˜λ¨Έμ§€ μŠ€ν…Œμ΄μ§€λ©΄ λ¬΄μ‹œν•˜λ €κ³  ν•œκ±°κ³ , λ‹€λ₯Έ κ΅¬ν˜„ ν”„λž™ν‹°μŠ€λŠ”
μŠ€ν…Œμ΄μ§€λ§ˆλ‹€ Bean을 λ‹€λ₯΄κ²Œ μƒμ„±ν•˜λŠ”κ±΄λ° κ°„λ‹¨ν•œ λ°©λ²•μœΌλ‘œ..

}
Map<String, String> payload = new HashMap<>();
payload.put("content", message);
restTemplate.postForObject(webhookUrl, payload, String.class);
log.info("Webhook sent: {}", message);
} catch (Exception e) {
log.error("Error sending webhook message", e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.springframework.web.multipart.MultipartFile;

import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.gamzabat.algohub.common.logging.DiscordWebhookService;
import com.gamzabat.algohub.constants.BOJResultConstants;
import com.gamzabat.algohub.enums.ImageType;
import com.gamzabat.algohub.exception.StudyGroupValidationException;
Expand Down Expand Up @@ -88,6 +89,7 @@ public class StudyGroupService {
private final ObjectProvider<StudyGroupService> studyGroupServiceProvider;
private final NotificationSettingRepository notificationSettingRepository;
private final NotificationService notificationService;
private final DiscordWebhookService webhookService;

@Transactional
public GroupCodeResponse createGroup(User user, CreateGroupRequest request, MultipartFile profileImage) {
Expand Down Expand Up @@ -122,6 +124,8 @@ public GroupCodeResponse createGroup(User user, CreateGroupRequest request, Mult

saveGroupImage(profileImage, group);
log.info("success to save study group user_id={}", user.getId());

webhookService.sendCreateGroupMessage(user.getNickname(), group.getName());
return new GroupCodeResponse(inviteCode);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.gamzabat.algohub.common.jwt.TokenProvider;
import com.gamzabat.algohub.common.jwt.dto.JwtDTO;
import com.gamzabat.algohub.common.jwt.dto.ReissueTokenRequest;
import com.gamzabat.algohub.common.logging.DiscordWebhookService;
import com.gamzabat.algohub.common.redis.RedisService;
import com.gamzabat.algohub.enums.EmailType;
import com.gamzabat.algohub.enums.ImageType;
Expand Down Expand Up @@ -74,6 +75,7 @@ public class UserService {
private final RestTemplate restTemplate;
private final ResetPasswordRepository resetPasswordRepository;
private final EmailService emailService;
private final DiscordWebhookService webhookService;

@Transactional
public void register(RegisterRequest request, MultipartFile profileImage, String token) {
Expand All @@ -94,6 +96,8 @@ public void register(RegisterRequest request, MultipartFile profileImage, String

saveProfileImage(profileImage, user);
log.info("success to register user_id={}", user.getId());

webhookService.sendRegisterMessage(user.getNickname(), "SignUp", user.getId());
Copy link

Copilot AI May 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Webhook notifications are invoked in multiple services (UserService, OAuth2Service, StudyGroupService); extracting this logic into a shared utility or AOP advice could reduce duplication.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

λ°”λΉ μ΄μžμ‹μ•„

}

private void saveProfileImage(MultipartFile profileImage, User user) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

import com.gamzabat.algohub.common.jwt.TokenProvider;
import com.gamzabat.algohub.common.jwt.dto.JwtDTO;
import com.gamzabat.algohub.common.logging.DiscordWebhookService;
import com.gamzabat.algohub.common.redis.RedisService;
import com.gamzabat.algohub.enums.EmailType;
import com.gamzabat.algohub.enums.ImageType;
Expand Down Expand Up @@ -90,6 +91,8 @@ class UserServiceTest {
private ResetPasswordRepository resetPasswordRepository;
@Mock
private EmailService emailService;
@Mock
private DiscordWebhookService webhookService;
@Captor
private ArgumentCaptor<User> userCaptor;
@Captor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.springframework.mock.web.MockMultipartFile;

import com.gamzabat.algohub.common.DateFormatUtil;
import com.gamzabat.algohub.common.logging.DiscordWebhookService;
import com.gamzabat.algohub.enums.ImageType;
import com.gamzabat.algohub.enums.Role;
import com.gamzabat.algohub.exception.StudyGroupValidationException;
Expand Down Expand Up @@ -97,6 +98,8 @@ class StudyGroupServiceTest {
@Mock
private SolutionCommentRepository solutionCommentRepository;
@Mock
private DiscordWebhookService webhookService;
@Mock
private RankingRepository rankingRepository;
@Mock
private ObjectProvider<StudyGroupService> studyGroupServiceObjectProvider;
Expand Down
Loading