Skip to content

Commit 88b1d9e

Browse files
authored
Merge pull request #194 from Team-HMH/develop
deploy - develop -> main
2 parents 0121176 + f19afda commit 88b1d9e

File tree

14 files changed

+198
-15
lines changed

14 files changed

+198
-15
lines changed

β€Žbuild.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ dependencies {
5656
// Test
5757
testImplementation 'org.springframework.boot:spring-boot-starter-test'
5858
testImplementation 'org.springframework.security:spring-security-test'
59+
60+
// Slack
61+
implementation 'com.slack.api:slack-api-client:1.27.2'
5962
}
6063

6164
tasks.named('test') {

β€Žsrc/main/java/sopt/org/hmh/domain/admin/service/AdminFacade.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import sopt.org.hmh.domain.admin.dto.response.AdminTokenResponse;
1313
import sopt.org.hmh.domain.admin.exception.AdminError;
1414
import sopt.org.hmh.domain.admin.exception.AdminException;
15+
import sopt.org.hmh.domain.challenge.domain.Challenge;
1516
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeError;
1617
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeException;
1718
import sopt.org.hmh.domain.challenge.service.ChallengeService;
@@ -65,15 +66,17 @@ public void changeUserInfo(AdminUserInfoRequest request) {
6566
@Transactional
6667
public void changeDailyChallengeInfo(AdminDailyChallengeRequest request) {
6768
Long currentChallengeId = userService.getCurrentChallengeIdByUserId(request.userId());
69+
Challenge challenge = challengeService.findByIdOrElseThrow(currentChallengeId);
6870
List<Status> statuses = request.statuses();
6971
LocalDate challengeDate = request.startDate();
7072

71-
validateStatusesPeriod(currentChallengeId, statuses);
73+
validateStatusesPeriod(challenge, statuses);
74+
challenge.changeStartDate(challengeDate);
7275
dailyChallengeService.changeInfoOfDailyChallenges(currentChallengeId, statuses, challengeDate);
7376
}
7477

75-
private void validateStatusesPeriod(Long challengeId, List<Status> statuses) {
76-
Integer challengePeriod = challengeService.getChallengePeriod(challengeId);
78+
private void validateStatusesPeriod(Challenge challenge, List<Status> statuses) {
79+
Integer challengePeriod = challenge.getPeriod();
7780
if (challengePeriod != statuses.size()) {
7881
throw new ChallengeException(ChallengeError.INVALID_PERIOD_NUMERIC);
7982
}

β€Žsrc/main/java/sopt/org/hmh/domain/auth/service/AuthFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public LoginResponse signup(SocialSignUpRequest request, String socialAccessToke
4141
SocialPlatform socialPlatform = request.socialPlatform();
4242
String socialId = this.getSocialIdBySocialAccessToken(socialPlatform, socialAccessToken);
4343

44-
User newUser = userService.addUser(socialPlatform, socialId, request.name());
44+
User newUser = userService.addUser(socialPlatform, socialId, request.name(), os);
4545
Long newUserId = newUser.getId();
4646

4747
userService.registerOnboardingInfo(request, newUserId);

β€Žsrc/main/java/sopt/org/hmh/domain/challenge/domain/Challenge.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ private Challenge(Integer period, Long userId, Long goalTime, List<ChallengeApp>
5050
this.apps = apps;
5151
this.startDate = startDate;
5252
}
53+
54+
public void changeStartDate(LocalDate startDate) {
55+
this.startDate = startDate;
56+
}
5357
}

β€Žsrc/main/java/sopt/org/hmh/domain/challenge/service/ChallengeService.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,4 @@ public List<ChallengeApp> getCurrentChallengeAppByChallengeId(Long challengeId)
3535
public Challenge addChallenge(Challenge challenge) {
3636
return challengeRepository.save(challenge);
3737
}
38-
39-
public Integer getChallengePeriod(Long challengeId) {
40-
return this.findByIdOrElseThrow(challengeId).getPeriod();
41-
}
4238
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package sopt.org.hmh.domain.slack;
2+
3+
import com.slack.api.Slack;
4+
import com.slack.api.model.Attachment;
5+
import com.slack.api.webhook.WebhookPayloads;
6+
import lombok.RequiredArgsConstructor;
7+
import lombok.extern.slf4j.Slf4j;
8+
import org.springframework.stereotype.Component;
9+
10+
import java.io.IOException;
11+
import java.util.List;
12+
13+
@Slf4j
14+
@Component
15+
@RequiredArgsConstructor
16+
public class SlackSender {
17+
18+
private final Slack slackClient = Slack.getInstance();
19+
20+
public void sendSlackNotification(String webhookUrl, String title, Attachment attachment) {
21+
try {
22+
slackClient.send(webhookUrl, WebhookPayloads.payload(p -> p
23+
.text(title)
24+
.attachments(List.of(attachment))
25+
));
26+
} catch (IOException slackError) {
27+
log.debug("Slack 톡신 μ˜ˆμ™Έ λ°œμƒ: {}", slackError.getMessage());
28+
}
29+
}
30+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package sopt.org.hmh.domain.slack.builder;
2+
3+
import com.slack.api.model.Attachment;
4+
import jakarta.servlet.http.HttpServletRequest;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.beans.factory.annotation.Value;
7+
import org.springframework.stereotype.Component;
8+
import sopt.org.hmh.domain.slack.SlackSender;
9+
import sopt.org.hmh.domain.slack.constant.SlackStatus;
10+
11+
import java.time.LocalDateTime;
12+
import java.time.format.DateTimeFormatter;
13+
import java.util.List;
14+
15+
@Component
16+
@RequiredArgsConstructor
17+
public class ErrorSlackMessageBuilder implements SlackMessageBuilder {
18+
19+
@Value("${slack.webhook.serverErrorWebUrl}")
20+
private String serverErrorWebUrl;
21+
22+
private final SlackSender slackSender;
23+
24+
public void sendNotification(SlackStatus status, Exception e, HttpServletRequest request) {
25+
slackSender.sendSlackNotification(serverErrorWebUrl, status.getTitle(),
26+
generateSlackAttachment(status, e, request));
27+
}
28+
29+
@Override
30+
public Attachment generateSlackAttachment(SlackStatus status, Object... params) {
31+
Exception e = (Exception) params[0];
32+
HttpServletRequest request = (HttpServletRequest) params[1];
33+
34+
String requestTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(LocalDateTime.now());
35+
36+
return Attachment.builder()
37+
.color(changeColorToHex(status.getColor()))
38+
.title(requestTime + " λ°œμƒ 였λ₯˜ 둜그")
39+
.fields(List.of(
40+
generateSlackField("User Info", "- ID : " + request.getRemoteUser()),
41+
generateSlackField("Request URL", "[" + request.getMethod() + "] " + request.getRequestURI()),
42+
generateSlackField("Error Info", e.getMessage())))
43+
.build();
44+
}
45+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package sopt.org.hmh.domain.slack.builder;
2+
3+
import com.slack.api.model.Attachment;
4+
import lombok.RequiredArgsConstructor;
5+
import org.springframework.beans.factory.annotation.Value;
6+
import org.springframework.stereotype.Component;
7+
import sopt.org.hmh.domain.slack.SlackSender;
8+
import sopt.org.hmh.domain.slack.constant.SlackStatus;
9+
import sopt.org.hmh.domain.user.repository.UserRepository;
10+
11+
import java.util.List;
12+
13+
@Component
14+
@RequiredArgsConstructor
15+
public class NewUserSlackMessageBuilder implements SlackMessageBuilder{
16+
17+
@Value("${slack.webhook.newUserWebUrl}")
18+
private String newUserWebUrl;
19+
20+
private final SlackSender slackSender;
21+
private final UserRepository userRepository;
22+
23+
public void sendNotification(SlackStatus status, String userName, String os) {
24+
slackSender.sendSlackNotification(
25+
newUserWebUrl,
26+
status.getTitle(),
27+
generateSlackAttachment(status, userName, os));
28+
}
29+
30+
@Override
31+
public Attachment generateSlackAttachment(SlackStatus status, Object... params) {
32+
String userName = (String) params[0];
33+
String os = (String) params[1];
34+
35+
return Attachment.builder()
36+
.color(changeColorToHex(status.getColor()))
37+
.title("μƒˆλ‘œμš΄ μœ μ € '" + userName + "'λ‹˜μ΄ κ°€μž…ν–ˆμŠ΅λ‹ˆλ‹€!")
38+
.fields(List.of(
39+
generateSlackField("총 μœ μ € 수", " πŸ‘‰ " + userRepository.count() + "λͺ…"),
40+
generateSlackField("κ°€μž…ν•œ OS", "πŸ‘‰ " + os)))
41+
.build();
42+
}
43+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package sopt.org.hmh.domain.slack.builder;
2+
3+
import com.slack.api.model.Attachment;
4+
import com.slack.api.model.Field;
5+
import sopt.org.hmh.domain.slack.constant.SlackStatus;
6+
7+
public interface SlackMessageBuilder {
8+
9+
Attachment generateSlackAttachment(SlackStatus status, Object... params);
10+
11+
default String changeColorToHex(java.awt.Color color) {
12+
return String.format("%06X", (0xFFFFFF & color.getRGB()));
13+
}
14+
15+
default Field generateSlackField(String title, String value) {
16+
return Field.builder()
17+
.title(title)
18+
.value(value)
19+
.valueShortEnough(false)
20+
.build();
21+
}
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package sopt.org.hmh.domain.slack.constant;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
@Getter
7+
@RequiredArgsConstructor
8+
public enum SlackStatus {
9+
NEW_USER_SIGNUP(java.awt.Color.GREEN, "πŸŽ‰ μ‹ κ·œ μœ μ € νšŒμ› κ°€μž… λ°œμƒ"),
10+
INTERNAL_ERROR(java.awt.Color.ORANGE, "🚨 μ„œλ²„ λ‚΄λΆ€ μ—λŸ¬ λ°œμƒ"),
11+
CLIENT_ERROR(java.awt.Color.RED, "😭 μ„œλ²„ 였λ₯˜ λ°œμƒ");
12+
13+
private final java.awt.Color color;
14+
private final String title;
15+
}

0 commit comments

Comments
Β (0)