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:}