Skip to content

Commit b64309e

Browse files
authored
Merge pull request #27 from DevKor-github/dev
Dev to main
2 parents 36c75d0 + 2673cc0 commit b64309e

13 files changed

Lines changed: 714 additions & 323 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
push:
55
branches:
66
- main
7-
- chore/#4
87
jobs:
98
deploy:
109
runs-on: ubuntu-latest
@@ -58,8 +57,11 @@ jobs:
5857
fi
5958
6059
echo "[deploy] start new app"
61-
DB_PASSWORD=${{ secrets.DB_PASSWORD }} \
62-
nohup java -jar build/libs/workingdead-0.0.1-SNAPSHOT.jar > app.log 2>&1 &
60+
61+
export DB_PASSWORD='${{ secrets.DB_PASSWORD }}'
62+
export DISCORD_TOKEN='${{ secrets.DISCORD_TOKEN }}'
63+
64+
nohup java -jar build/libs/workingdead-0.0.1-SNAPSHOT.jar > app.log 2>&1 &
6365
6466
echo $! > app.pid
6567

src/main/java/com/workingdead/chatbot/command/WendyCommand.java

Lines changed: 167 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package com.workingdead.chatbot.command;
22

33
import com.workingdead.chatbot.scheduler.WendyScheduler;
4-
import com.workingdead.meet.service.WendyService;
4+
import com.workingdead.chatbot.service.WendyService;
5+
import java.util.concurrent.CompletableFuture;
6+
import java.util.concurrent.TimeUnit;
57
import net.dv8tion.jda.api.entities.Member;
68
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
79
import net.dv8tion.jda.api.entities.emoji.Emoji;
10+
import net.dv8tion.jda.api.events.interaction.component.EntitySelectInteractionEvent;
11+
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
812
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
913
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
1014
import net.dv8tion.jda.api.hooks.ListenerAdapter;
15+
import net.dv8tion.jda.api.interactions.components.selections.EntitySelectMenu;
16+
import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
1117
import org.springframework.stereotype.Component;
1218

1319
import java.util.List;
@@ -22,12 +28,27 @@ public class WendyCommand extends ListenerAdapter {
2228

2329
private final Map<String, String> participantCheckMessages = new ConcurrentHashMap<>();
2430
private final Map<String, Boolean> waitingForDateInput = new ConcurrentHashMap<>();
31+
32+
private static final String ATTENDEE_SELECT_MENU_ID = "wendy-attendees";
33+
private static final String WEEK_SELECT_MENU_ID = "wendy-weeks";
34+
private static final String WEEK_SELECT_MENU_REVOTE_ID = "wendy-weeks-revote";
2535

2636
public WendyCommand(WendyService wendyService, WendyScheduler wendyScheduler) {
2737
this.wendyService = wendyService;
2838
this.wendyScheduler = wendyScheduler;
2939
}
30-
40+
41+
@Override
42+
public void onGuildJoin(net.dv8tion.jda.api.events.guild.GuildJoinEvent event) {
43+
TextChannel defaultChannel = event.getGuild().getDefaultChannel().asTextChannel();
44+
if (defaultChannel != null) {
45+
defaultChannel.sendMessage("""
46+
안녕하세요! 일정 조율 도우미 웬디가 서버에 합류했어요 :D
47+
일정을 조율하려면 채팅에 **'웬디 시작'** 이라고 입력해 주세요!
48+
""").queue();
49+
}
50+
}
51+
3152
@Override
3253
public void onMessageReceived(MessageReceivedEvent event) {
3354
if (event.getAuthor().isBot()) return;
@@ -54,14 +75,14 @@ public void onMessageReceived(MessageReceivedEvent event) {
5475
return;
5576
}
5677

57-
// 2.1~2.2 날짜 범위 입력
58-
if (waitingForDateInput.getOrDefault(channelId, false)) {
59-
Integer weeks = extractWeeks(content);
60-
if (weeks != null) {
61-
handleDateInput(channel, member, weeks, false);
62-
return;
63-
}
64-
}
78+
// // 2.1~2.2 날짜 범위 입력
79+
// if (waitingForDateInput.getOrDefault(channelId, false)) {
80+
// Integer weeks = extractWeeks(content);
81+
// if (weeks != null) {
82+
// handleDateInput(channel, member, weeks, false);
83+
// return;
84+
// }
85+
// }
6586

6687
// 4.2 재투표
6788
if (content.equals("웬디 재투표")) {
@@ -75,30 +96,84 @@ public void onMessageReceived(MessageReceivedEvent event) {
7596
return;
7697
}
7798
}
78-
99+
79100
@Override
80-
public void onMessageReactionAdd(MessageReactionAddEvent event) {
81-
if (event.getUser() != null && event.getUser().isBot()) return;
82-
83-
String channelId = event.getChannel().getId();
84-
String messageId = event.getMessageId();
85-
86-
String checkMessageId = participantCheckMessages.get(channelId);
87-
if (checkMessageId == null || !checkMessageId.equals(messageId)) {
101+
public void onEntitySelectInteraction(EntitySelectInteractionEvent event) {
102+
if (!ATTENDEE_SELECT_MENU_ID.equals(event.getComponentId())) {
88103
return;
89104
}
90-
91-
if (!event.getReaction().getEmoji().equals(Emoji.fromUnicode("✅"))) {
105+
106+
String channelId = event.getChannel().getId();
107+
if (!wendyService.isSessionActive(channelId)) {
92108
return;
93109
}
94-
95-
event.retrieveMember().queue(member -> {
96-
if (member != null) {
97-
wendyService.addParticipant(channelId, member.getId(), member.getEffectiveName());
98-
System.out.println("[Command] Participant added: " + member.getEffectiveName());
99-
}
110+
111+
event.getMentions().getMembers().forEach(member -> {
112+
wendyService.addParticipant(channelId, member.getId(), member.getEffectiveName());
113+
System.out.println("[Command] Participant added via select menu: " + member.getEffectiveName());
100114
});
115+
116+
event.reply("참석자 명단이 업데이트됐어요!").setEphemeral(true).queue();
117+
101118
}
119+
120+
@Override
121+
public void onStringSelectInteraction(StringSelectInteractionEvent event) {
122+
String componentId = event.getComponentId();
123+
if (!WEEK_SELECT_MENU_ID.equals(componentId) && !WEEK_SELECT_MENU_REVOTE_ID.equals(componentId)) {
124+
return;
125+
}
126+
127+
String channelId = event.getChannel().getId();
128+
if (!wendyService.isSessionActive(channelId)) {
129+
return;
130+
}
131+
132+
// 하나만 선택하게 설정할 예정이므로 첫 번째 값만 사용
133+
String value = event.getValues().get(0);
134+
int weeks;
135+
try {
136+
weeks = Integer.parseInt(value);
137+
} catch (NumberFormatException e) {
138+
event.reply("선택한 값이 올바르지 않아요. 다시 시도해주세요!").setEphemeral(true).queue();
139+
return;
140+
}
141+
142+
TextChannel channel = event.getChannel().asTextChannel();
143+
Member member = event.getMember();
144+
if (member == null) {
145+
event.reply("사용자 정보를 가져올 수 없어요. 다시 시도해주세요!").setEphemeral(true).queue();
146+
return;
147+
}
148+
149+
boolean isRevote = WEEK_SELECT_MENU_REVOTE_ID.equals(componentId);
150+
handleDateInput(channel, member, weeks, isRevote);
151+
event.reply("투표 날짜 범위를 선택하셨어요!").setEphemeral(true).queue();
152+
}
153+
154+
// @Override
155+
// public void onMessageReactionAdd(MessageReactionAddEvent event) {
156+
// if (event.getUser() != null && event.getUser().isBot()) return;
157+
//
158+
// String channelId = event.getChannel().getId();
159+
// String messageId = event.getMessageId();
160+
//
161+
// String checkMessageId = participantCheckMessages.get(channelId);
162+
// if (checkMessageId == null || !checkMessageId.equals(messageId)) {
163+
// return;
164+
// }
165+
//
166+
// if (!event.getReaction().getEmoji().equals(Emoji.fromUnicode("✅"))) {
167+
// return;
168+
// }
169+
//
170+
// event.retrieveMember().queue(member -> {
171+
// if (member != null) {
172+
// wendyService.addParticipant(channelId, member.getId(), member.getEffectiveName());
173+
// System.out.println("[Command] Participant added: " + member.getEffectiveName());
174+
// }
175+
// });
176+
// }
102177

103178
private void handleStart(TextChannel channel) {
104179
String channelId = channel.getId();
@@ -110,35 +185,70 @@ private void handleStart(TextChannel channel) {
110185
안녕하세요! 일정 조율 도우미 웬디에요 :D
111186
지금부터 여러분의 일정 조율을 도와드릴게요
112187
""").queue();
113-
114-
channel.sendMessage("인원 파악을 위해 참석자분들은 ✅를 남겨주세요!")
115-
.queue(message -> {
116-
participantCheckMessages.put(channelId, message.getId());
117-
message.addReaction(Emoji.fromUnicode("✅")).queue();
118-
System.out.println("[Command] Session started: " + channelId);
119-
});
120-
121-
channel.sendMessage("몇 주 뒤의 일정을 계획하시나요? :D\n(ex. 2주 뒤)").queue();
122-
waitingForDateInput.put(channelId, true);
188+
189+
190+
// 참석자 입력용 엔티티 셀렉트 메뉴 (유저 선택 드롭다운)
191+
EntitySelectMenu attendeeMenu = EntitySelectMenu.create(ATTENDEE_SELECT_MENU_ID, EntitySelectMenu.SelectTarget.USER)
192+
.setPlaceholder("참석자를 선택 / 검색해 주세요.")
193+
.setRequiredRange(1, 25)
194+
.build();
195+
196+
channel.sendMessage("인원 파악을 위해 참석자분들을 알려주세요!\n원하는 참석자들을 아래 드롭다운에서 선택해주세요.")
197+
.setActionRow(attendeeMenu)
198+
.queue();
199+
200+
// 2.1 날짜 범위 파악 질문 (드롭다운 방식)
201+
StringSelectMenu weekMenu = StringSelectMenu.create(WEEK_SELECT_MENU_ID)
202+
.setPlaceholder("몇 주 뒤의 일정을 계획하시나요?")
203+
.addOption("이번 주", "0")
204+
.addOption("1주 뒤", "1")
205+
.addOption("2주 뒤", "2")
206+
.addOption("3주 뒤", "3")
207+
.addOption("4주 뒤", "4")
208+
.addOption("5주 뒤", "5")
209+
.addOption("6주 뒤", "6")
210+
.build();
211+
212+
channel.sendMessage("몇 주 뒤의 일정을 계획하시나요? :D")
213+
.setActionRow(weekMenu)
214+
.queue();
123215
}
124216

125217
private void handleDateInput(TextChannel channel, Member member, int weeks, boolean isRevote) {
126218
String channelId = channel.getId();
127-
String userName = member.getEffectiveName();
219+
String userMention = member.getAsMention();
220+
String channelName = channel.getName();
128221

129222
waitingForDateInput.put(channelId, false);
130223

131-
channel.sendMessage(userName + " 님이 " + weeks + "주 뒤를 선택하셨어요!").queue();
224+
channel.sendMessage(userMention + " 님이 " + weeks + "주 뒤를 선택하셨어요!").queue();
132225
channel.sendMessage("해당 일정의 투표를 만들어드릴게요 :D").queue();
133226
channel.sendMessage("(투표 늦게 하는 사람 대머리🧑‍🦲)").queue();
134227
channel.sendMessage("투표를 생성 중입니다🛜").queue();
135228

136229
String voteUrl = isRevote
137-
? wendyService.recreateVote(channelId, weeks)
138-
: wendyService.createVote(channelId, weeks);
230+
? wendyService.recreateVote(channelId, channelName, weeks)
231+
: wendyService.createVote(channelId, channelName, weeks);
139232

140233
channel.sendMessage(voteUrl).queue();
141234
wendyScheduler.startSchedule(channel);
235+
236+
237+
// // 투표 제한시간(24시간) + 30분 후 자동 종료 스케줄
238+
// CompletableFuture
239+
// .delayedExecutor(3 * 60 + 30, TimeUnit.SECONDS)
240+
// .execute(() -> {
241+
// String chId = channel.getId();
242+
// // 스케줄러 정리 + 세션 종료
243+
// wendyScheduler.stopSchedule(chId);
244+
// wendyService.endSession(chId);
245+
//
246+
// // 안내 메시지 전송
247+
// channel.sendMessage("""
248+
// 투표 제한 시간이 지나 웬디가 자동으로 종료되었어요 :D
249+
// 다시 일정 조율이 필요하시면 '웬디 시작'을 입력해 주세요!
250+
// """).queue();
251+
// });
142252
}
143253

144254
private void handleRevote(TextChannel channel) {
@@ -150,8 +260,22 @@ private void handleRevote(TextChannel channel) {
150260
}
151261

152262
wendyScheduler.stopSchedule(channelId);
153-
channel.sendMessage("몇 주 뒤의 일정을 계획하시나요? :D\n(ex. 2주 뒤)").queue();
154-
waitingForDateInput.put(channelId, true);
263+
264+
265+
StringSelectMenu weekMenu = StringSelectMenu.create(WEEK_SELECT_MENU_REVOTE_ID)
266+
.setPlaceholder("몇 주 뒤의 일정을 다시 계획하시나요?")
267+
.addOption("이번 주", "0")
268+
.addOption("1주 뒤", "1")
269+
.addOption("2주 뒤", "2")
270+
.addOption("3주 뒤", "3")
271+
.addOption("4주 뒤", "4")
272+
.addOption("5주 뒤", "5")
273+
.addOption("6주 뒤", "6")
274+
.build();
275+
276+
channel.sendMessage("몇 주 뒤의 일정을 계획하시나요? :D")
277+
.setActionRow(weekMenu)
278+
.queue();
155279
}
156280

157281
private void handleEnd(TextChannel channel) {

0 commit comments

Comments
 (0)