diff --git a/.github/workflows/production_build_deploy.yml b/.github/workflows/production_build_deploy.yml
index 42e25ff59..b89c84e06 100644
--- a/.github/workflows/production_build_deploy.yml
+++ b/.github/workflows/production_build_deploy.yml
@@ -76,6 +76,8 @@ jobs:
images: ${{ env.DOCKERHUB_IMAGE_FULL_NAME }}
tags: |
type=semver,pattern={{version}}
+ flavor: |
+ latest=false
# 멀티 아키텍처 지원을 위한 QEMU 설정
- name: Set up QEMU
diff --git a/src/main/java/com/gdschongik/gdsc/domain/discord/handler/NonCommandHandler.java b/src/main/java/com/gdschongik/gdsc/domain/discord/handler/NonCommandHandler.java
new file mode 100644
index 000000000..cf9e882de
--- /dev/null
+++ b/src/main/java/com/gdschongik/gdsc/domain/discord/handler/NonCommandHandler.java
@@ -0,0 +1,37 @@
+package com.gdschongik.gdsc.domain.discord.handler;
+
+import static com.gdschongik.gdsc.global.common.constant.DiscordConstant.*;
+
+import com.gdschongik.gdsc.global.util.DiscordUtil;
+import java.util.Objects;
+import lombok.RequiredArgsConstructor;
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.entities.Role;
+import net.dv8tion.jda.api.events.GenericEvent;
+import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class NonCommandHandler implements DiscordEventHandler {
+
+ private final DiscordUtil discordUtil;
+
+ @Override
+ public void delegate(GenericEvent genericEvent) {
+ MessageReceivedEvent event = (MessageReceivedEvent) genericEvent;
+ Role adminRole = discordUtil.findRoleByName(ADMIN_ROLE_NAME);
+
+ Member member = Objects.requireNonNull(event.getMember());
+
+ if (member.getUser().isBot()) {
+ return;
+ }
+
+ if (member.getRoles().contains(adminRole)) {
+ return;
+ }
+
+ event.getMessage().delete().queue();
+ }
+}
diff --git a/src/main/java/com/gdschongik/gdsc/domain/email/application/UnivEmailVerificationLinkSendService.java b/src/main/java/com/gdschongik/gdsc/domain/email/application/UnivEmailVerificationLinkSendService.java
index 0de91e51b..d398625ef 100644
--- a/src/main/java/com/gdschongik/gdsc/domain/email/application/UnivEmailVerificationLinkSendService.java
+++ b/src/main/java/com/gdschongik/gdsc/domain/email/application/UnivEmailVerificationLinkSendService.java
@@ -34,11 +34,17 @@ public class UnivEmailVerificationLinkSendService {
private final MemberUtil memberUtil;
public static final Duration VERIFICATION_CODE_TIME_TO_LIVE = Duration.ofMinutes(10);
- private static final String NOTIFICATION_MESSAGE = "
"
- + "
안녕하세요 GDSC Hongik 재학생 인증 메일입니다.
"
- + "
아래의 링크를 %d분 안에 클릭해주세요.
"
- + "
감사합니다.
"
- + "CODE :
";
+ private static final String NOTIFICATION_MESSAGE =
+ """
+
+
GDSC Hongik 재학생 인증 메일
+
안녕하세요!
+
GDSC Hongik 커뮤니티에 지원해주셔서 대단히 감사드립니다.
+
아래의 버튼을 클릭하여 재학생 인증을 완료해주세요. 링크는 %d분 동안 유효합니다.
+
재학생 인증하기
+
감사합니다.
GDSC Hongik Team
+
+""";
public void send(String univEmail) {
hongikUnivEmailValidator.validate(univEmail);
@@ -60,7 +66,7 @@ private void validateUnivEmailNotVerified(String univEmail) {
}
private String writeMailContentWithVerificationLink(String verificationLink) {
- return String.format(NOTIFICATION_MESSAGE, VERIFICATION_CODE_TIME_TO_LIVE.toMinutes()) + verificationLink;
+ return NOTIFICATION_MESSAGE.formatted(VERIFICATION_CODE_TIME_TO_LIVE.toMinutes(), verificationLink);
}
private void saveUnivEmailVerification(String univEmail, String verificationCode) {
diff --git a/src/main/java/com/gdschongik/gdsc/domain/member/domain/Member.java b/src/main/java/com/gdschongik/gdsc/domain/member/domain/Member.java
index aa579a899..6273b3793 100644
--- a/src/main/java/com/gdschongik/gdsc/domain/member/domain/Member.java
+++ b/src/main/java/com/gdschongik/gdsc/domain/member/domain/Member.java
@@ -246,4 +246,10 @@ public boolean isGrantAvailable() {
return false;
}
}
+
+ // 기타 로직
+
+ public void updateLastLoginAt() {
+ this.lastLoginAt = LocalDateTime.now();
+ }
}
diff --git a/src/main/java/com/gdschongik/gdsc/global/common/constant/DiscordConstant.java b/src/main/java/com/gdschongik/gdsc/global/common/constant/DiscordConstant.java
index e33e4c6c4..64f467957 100644
--- a/src/main/java/com/gdschongik/gdsc/global/common/constant/DiscordConstant.java
+++ b/src/main/java/com/gdschongik/gdsc/global/common/constant/DiscordConstant.java
@@ -5,7 +5,9 @@ public class DiscordConstant {
private DiscordConstant() {}
// 공통 상수
+ public static final String DISCORD_BOT_STATUS_CONTENT = "정상영업";
public static final String MEMBER_ROLE_NAME = "커뮤니티-멤버";
+ public static final String ADMIN_ROLE_NAME = "운영진";
// 인증코드 발급 커맨드
public static final String COMMAND_NAME_ISSUING_CODE = "인증코드";
diff --git a/src/main/java/com/gdschongik/gdsc/global/common/constant/EmailConstant.java b/src/main/java/com/gdschongik/gdsc/global/common/constant/EmailConstant.java
index abc4e3067..330eb0cd3 100644
--- a/src/main/java/com/gdschongik/gdsc/global/common/constant/EmailConstant.java
+++ b/src/main/java/com/gdschongik/gdsc/global/common/constant/EmailConstant.java
@@ -5,7 +5,7 @@ public class EmailConstant {
public static final String VERIFY_EMAIL_API_ENDPOINT = "/onboarding/verify-email?%s=";
public static final String VERIFY_EMAIL_REQUEST_PARAMETER_KEY = "token";
public static final String HONGIK_UNIV_MAIL_DOMAIN = "@g.hongik.ac.kr";
- public static final String SENDER_PERSONAL = "GDSC Hongik 운영팀";
+ public static final String SENDER_PERSONAL = "GDSC Hongik";
public static final String SENDER_ADDRESS = "gdsc.hongik@gmail.com";
public static final String VERIFICATION_EMAIL_SUBJECT = "GDSC Hongik 이메일 인증 코드입니다.";
diff --git a/src/main/java/com/gdschongik/gdsc/global/config/DiscordConfig.java b/src/main/java/com/gdschongik/gdsc/global/config/DiscordConfig.java
index 970b2bebc..dbfb90760 100644
--- a/src/main/java/com/gdschongik/gdsc/global/config/DiscordConfig.java
+++ b/src/main/java/com/gdschongik/gdsc/global/config/DiscordConfig.java
@@ -31,7 +31,7 @@ public class DiscordConfig {
@ConditionalOnProperty(value = "discord.enabled", havingValue = "true", matchIfMissing = true)
public JDA jda() {
JDA jda = JDABuilder.createDefault(discordProperty.getToken())
- .setActivity(Activity.playing("테스트"))
+ .setActivity(Activity.playing(DISCORD_BOT_STATUS_CONTENT))
.enableIntents(GatewayIntent.GUILD_MESSAGES, GatewayIntent.MESSAGE_CONTENT, GatewayIntent.GUILD_MEMBERS)
.setMemberCachePolicy(MemberCachePolicy.ALL)
.build();
diff --git a/src/main/java/com/gdschongik/gdsc/global/discord/listener/NonCommandListener.java b/src/main/java/com/gdschongik/gdsc/global/discord/listener/NonCommandListener.java
new file mode 100644
index 000000000..5fe745342
--- /dev/null
+++ b/src/main/java/com/gdschongik/gdsc/global/discord/listener/NonCommandListener.java
@@ -0,0 +1,26 @@
+package com.gdschongik.gdsc.global.discord.listener;
+
+import com.gdschongik.gdsc.domain.discord.handler.NonCommandHandler;
+import com.gdschongik.gdsc.global.discord.Listener;
+import com.gdschongik.gdsc.global.property.DiscordProperty;
+import lombok.RequiredArgsConstructor;
+import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
+import net.dv8tion.jda.api.hooks.ListenerAdapter;
+import org.jetbrains.annotations.NotNull;
+
+@Listener
+@RequiredArgsConstructor
+public class NonCommandListener extends ListenerAdapter {
+
+ private final DiscordProperty discordProperty;
+ private final NonCommandHandler nonCommandHandler;
+
+ @Override
+ public void onMessageReceived(@NotNull MessageReceivedEvent event) {
+ String eventChannelId = event.getChannel().getId();
+
+ if (eventChannelId.equals(discordProperty.getCommandChannelId())) {
+ nonCommandHandler.delegate(event);
+ }
+ }
+}
diff --git a/src/main/java/com/gdschongik/gdsc/global/property/DiscordProperty.java b/src/main/java/com/gdschongik/gdsc/global/property/DiscordProperty.java
index 56367fb22..860537b14 100644
--- a/src/main/java/com/gdschongik/gdsc/global/property/DiscordProperty.java
+++ b/src/main/java/com/gdschongik/gdsc/global/property/DiscordProperty.java
@@ -11,4 +11,5 @@ public class DiscordProperty {
private final String token;
private final String serverId;
+ private final String commandChannelId;
}
diff --git a/src/main/java/com/gdschongik/gdsc/global/security/CustomUserService.java b/src/main/java/com/gdschongik/gdsc/global/security/CustomUserService.java
index affb8e41b..4ab53c807 100644
--- a/src/main/java/com/gdschongik/gdsc/global/security/CustomUserService.java
+++ b/src/main/java/com/gdschongik/gdsc/global/security/CustomUserService.java
@@ -19,6 +19,7 @@ public class CustomUserService extends DefaultOAuth2UserService {
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
Member member = fetchOrCreate(oAuth2User);
+ member.updateLastLoginAt();
return new CustomOAuth2User(oAuth2User, member);
}
diff --git a/src/main/resources/application-discord.yml b/src/main/resources/application-discord.yml
index fd6ab39f4..7acb534b9 100644
--- a/src/main/resources/application-discord.yml
+++ b/src/main/resources/application-discord.yml
@@ -1,3 +1,4 @@
discord:
token: ${DISCORD_BOT_TOKEN:}
server-id: ${DISCORD_SERVER_ID:}
+ command-channel-id: ${DISCORD_COMMAND_CHANNEL_ID:}