Skip to content

Commit 36c75d0

Browse files
authored
Merge pull request #24 from DevKor-github/dev
Dev
2 parents 6283d76 + def31fd commit 36c75d0

9 files changed

Lines changed: 569 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
HELP.md
2+
.env
23
.gradle
34
build/
45
!gradle/wrapper/gradle-wrapper.jar

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ dependencies {
4646
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
4747
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8'
4848
implementation "org.springframework.session:spring-session-jdbc"
49+
implementation 'net.dv8tion:JDA:5.0.0-beta.24'
4950

5051
}
5152

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package com.workingdead.chatbot.command;
2+
3+
import com.workingdead.chatbot.scheduler.WendyScheduler;
4+
import com.workingdead.meet.service.WendyService;
5+
import net.dv8tion.jda.api.entities.Member;
6+
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
7+
import net.dv8tion.jda.api.entities.emoji.Emoji;
8+
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
9+
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
10+
import net.dv8tion.jda.api.hooks.ListenerAdapter;
11+
import org.springframework.stereotype.Component;
12+
13+
import java.util.List;
14+
import java.util.Map;
15+
import java.util.concurrent.ConcurrentHashMap;
16+
17+
@Component
18+
public class WendyCommand extends ListenerAdapter {
19+
20+
private final WendyService wendyService;
21+
private final WendyScheduler wendyScheduler;
22+
23+
private final Map<String, String> participantCheckMessages = new ConcurrentHashMap<>();
24+
private final Map<String, Boolean> waitingForDateInput = new ConcurrentHashMap<>();
25+
26+
public WendyCommand(WendyService wendyService, WendyScheduler wendyScheduler) {
27+
this.wendyService = wendyService;
28+
this.wendyScheduler = wendyScheduler;
29+
}
30+
31+
@Override
32+
public void onMessageReceived(MessageReceivedEvent event) {
33+
if (event.getAuthor().isBot()) return;
34+
35+
String content = event.getMessage().getContentRaw().trim();
36+
TextChannel channel = event.getChannel().asTextChannel();
37+
String channelId = channel.getId();
38+
Member member = event.getMember();
39+
40+
// 1.1 웬디 시작
41+
if (content.equals("웬디 시작")) {
42+
handleStart(channel);
43+
return;
44+
}
45+
46+
// 4.1 도움말
47+
if (content.equals("/help") || content.equals("웬디 도움말")) {
48+
handleHelp(channel);
49+
return;
50+
}
51+
52+
// 세션 체크
53+
if (!wendyService.isSessionActive(channelId)) {
54+
return;
55+
}
56+
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+
}
65+
66+
// 4.2 재투표
67+
if (content.equals("웬디 재투표")) {
68+
handleRevote(channel);
69+
return;
70+
}
71+
72+
// 3.1 웬디 종료
73+
if (content.equals("웬디 종료")) {
74+
handleEnd(channel);
75+
return;
76+
}
77+
}
78+
79+
@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)) {
88+
return;
89+
}
90+
91+
if (!event.getReaction().getEmoji().equals(Emoji.fromUnicode("✅"))) {
92+
return;
93+
}
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+
}
100+
});
101+
}
102+
103+
private void handleStart(TextChannel channel) {
104+
String channelId = channel.getId();
105+
List<Member> members = channel.getMembers();
106+
107+
wendyService.startSession(channelId, members);
108+
109+
channel.sendMessage("""
110+
안녕하세요! 일정 조율 도우미 웬디에요 :D
111+
지금부터 여러분의 일정 조율을 도와드릴게요
112+
""").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);
123+
}
124+
125+
private void handleDateInput(TextChannel channel, Member member, int weeks, boolean isRevote) {
126+
String channelId = channel.getId();
127+
String userName = member.getEffectiveName();
128+
129+
waitingForDateInput.put(channelId, false);
130+
131+
channel.sendMessage(userName + " 님이 " + weeks + "주 뒤를 선택하셨어요!").queue();
132+
channel.sendMessage("해당 일정의 투표를 만들어드릴게요 :D").queue();
133+
channel.sendMessage("(투표 늦게 하는 사람 대머리🧑‍🦲)").queue();
134+
channel.sendMessage("투표를 생성 중입니다🛜").queue();
135+
136+
String voteUrl = isRevote
137+
? wendyService.recreateVote(channelId, weeks)
138+
: wendyService.createVote(channelId, weeks);
139+
140+
channel.sendMessage(voteUrl).queue();
141+
wendyScheduler.startSchedule(channel);
142+
}
143+
144+
private void handleRevote(TextChannel channel) {
145+
String channelId = channel.getId();
146+
147+
if (!wendyService.hasPreviousVote(channelId)) {
148+
channel.sendMessage("아직 진행된 투표가 없어요🗑️").queue();
149+
return;
150+
}
151+
152+
wendyScheduler.stopSchedule(channelId);
153+
channel.sendMessage("몇 주 뒤의 일정을 계획하시나요? :D\n(ex. 2주 뒤)").queue();
154+
waitingForDateInput.put(channelId, true);
155+
}
156+
157+
private void handleEnd(TextChannel channel) {
158+
String channelId = channel.getId();
159+
160+
wendyScheduler.stopSchedule(channelId);
161+
wendyService.endSession(channelId);
162+
163+
participantCheckMessages.remove(channelId);
164+
waitingForDateInput.remove(channelId);
165+
166+
channel.sendMessage("""
167+
웬디는 여기서 눈치껏 빠질게요 :D
168+
모두 알찬 시간 보내세요!
169+
""").queue();
170+
System.out.println("[Command] Session ended: " + channelId);
171+
}
172+
173+
private void handleHelp(TextChannel channel) {
174+
channel.sendMessage("""
175+
웬디는 다음과 같은 기능이 있어요!
176+
177+
**'웬디 시작'**: 일정 조율을 시작해요
178+
**'웬디 종료'**: 작동을 종료해요
179+
**'웬디 재투표'**: 동일한 참석자로 투표를 다시 올려요
180+
""").queue();
181+
}
182+
183+
private Integer extractWeeks(String content) {
184+
String numbers = content.replaceAll("[^0-9]", "");
185+
if (numbers.isEmpty()) return null;
186+
try {
187+
int weeks = Integer.parseInt(numbers);
188+
if (weeks < 1 || weeks > 12) return null;
189+
return weeks;
190+
} catch (NumberFormatException e) {
191+
return null;
192+
}
193+
}
194+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.workingdead.chatbot.dto;
2+
3+
import java.util.List;
4+
5+
public class VoteResult {
6+
private String voteUrl;
7+
private List<RankResult> rankings;
8+
9+
public VoteResult() {}
10+
11+
public VoteResult(String voteUrl, List<RankResult> rankings) {
12+
this.voteUrl = voteUrl;
13+
this.rankings = rankings;
14+
}
15+
16+
public boolean isEmpty() {
17+
return rankings == null || rankings.isEmpty();
18+
}
19+
20+
public String getVoteUrl() { return voteUrl; }
21+
public void setVoteUrl(String voteUrl) { this.voteUrl = voteUrl; }
22+
public List<RankResult> getRankings() { return rankings; }
23+
public void setRankings(List<RankResult> rankings) { this.rankings = rankings; }
24+
25+
public static class RankResult {
26+
private int rank;
27+
private String dateTime;
28+
private List<Voter> voters;
29+
30+
public RankResult() {}
31+
public RankResult(int rank, String dateTime, List<Voter> voters) {
32+
this.rank = rank;
33+
this.dateTime = dateTime;
34+
this.voters = voters;
35+
}
36+
37+
public int getRank() { return rank; }
38+
public String getDateTime() { return dateTime; }
39+
public List<Voter> getVoters() { return voters; }
40+
}
41+
42+
public static class Voter {
43+
private String name;
44+
private Integer priority;
45+
46+
public Voter() {}
47+
public Voter(String name, Integer priority) {
48+
this.name = name;
49+
this.priority = priority;
50+
}
51+
52+
public String getName() { return name; }
53+
public Integer getPriority() { return priority; }
54+
55+
@Override
56+
public String toString() {
57+
return priority != null ? name + "(" + priority + ")" : name;
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)