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+ }
0 commit comments