11package net .zomis .duga .chat ;
22
3- import java .io .UncheckedIOException ;
43import java .io .UnsupportedEncodingException ;
5- import java .net .URI ;
64import java .util .*;
7- import java .util .concurrent .BlockingQueue ;
8- import java .util .concurrent .ExecutorService ;
9- import java .util .concurrent .Executors ;
10- import java .util .concurrent .LinkedBlockingQueue ;
11- import java .util .concurrent .TimeUnit ;
5+ import java .util .concurrent .*;
126import java .util .logging .Level ;
137import java .util .logging .Logger ;
148import java .util .stream .Collectors ;
159
1610import org .apache .http .HttpRequest ;
1711import org .apache .http .HttpResponse ;
1812import org .apache .http .ProtocolException ;
19- import org .apache .http .client .RedirectHandler ;
2013import org .apache .http .client .RedirectStrategy ;
2114import org .apache .http .client .methods .HttpGet ;
2215import org .apache .http .client .methods .HttpUriRequest ;
3023import com .gistlabs .mechanize .document .json .JsonDocument ;
3124import com .gistlabs .mechanize .impl .MechanizeAgent ;
3225
33- /**
34- * @author Frank van Heeswijk
35- * @author Simon Forsberg
36- */
37- public class StackExchangeChatBot {
26+ public class StackExchangeChatBot implements ChatBot {
3827
3928 private final static Logger LOGGER = Logger .getLogger (StackExchangeChatBot .class .getSimpleName ());
29+
30+ @ Deprecated
4031 private static final WebhookParameters debugRoom = WebhookParameters .toRoom ("20298" );
4132
4233 private static final int MAX_MESSAGE_LENGTH = 500 ;
@@ -49,9 +40,6 @@ public class StackExchangeChatBot {
4940
5041 private final BotConfiguration configuration ;
5142
52- // @Autowired
53- // private ConfigService configService;
54-
5543 private String chatFKey ;
5644
5745 private String undeployGoodbyeText ;
@@ -173,9 +161,9 @@ private String retrieveFKey() {
173161 return joinForm .get ("fkey" ).getValue ();
174162 }
175163
176- public void postMessages (WebhookParameters params , final List <String > messages ) {
164+ public Future < List < ChatMessageResponse >> postMessages (WebhookParameters params , final List <String > messages ) {
177165 if (params == null ) {
178- params = new WebhookParameters ( );
166+ throw new NullPointerException ( "Params cannot be null, unable to post " + messages );
179167 }
180168 // params.useDefaultRoom(configuration.getRoomId());
181169 Objects .requireNonNull (messages , "messages" );
@@ -196,84 +184,114 @@ public void postMessages(WebhookParameters params, final List<String> messages)
196184 for (ChatMessage message : shortenedMessages ) {
197185 LOGGER .info ("Ignoring message for " + message .getRoom () + ": " + message .getMessage ());
198186 }
199- return ;
187+ return null ;
200188 }
201189
202190 System .out .println ("Adding messages to queue: " + shortenedMessages );
203191 messagesQueue .add (shortenedMessages );
192+ return null ;
204193 }
205194
206195 private void attemptPostMessageToChat (final ChatMessage message ) {
207196 System .out .println ("Real message post: " + message );
208197 Objects .requireNonNull (message , "message" );
209- try {
210- postMessageToChat ( message );
211- } catch ( ChatThrottleException ex ) {
198+ ChatMessageResponse response = postMessageToChat ( message );
199+ if ( response . getException () instanceof ChatThrottleException ) {
200+ ChatThrottleException ex = ( ChatThrottleException ) response . getException ();
212201 System .out .println ("Chat throttle" );
213202 LOGGER .info ("Sleeping for " + ex .getThrottleTiming () + " seconds, then reposting" );
214203 try {
215204 TimeUnit .SECONDS .sleep (ex .getThrottleTiming ());
216205 } catch (InterruptedException ex1 ) {
217206 Thread .currentThread ().interrupt ();
218207 }
219- try {
220- postMessageToChat ( message );
221- } catch ( ChatThrottleException | ProbablyNotLoggedInException ex1 ) {
222- LOGGER . log ( Level . INFO , "Failed to post message on retry" , ex1 );
223- }
224- } catch ( ProbablyNotLoggedInException ex ) {
208+ ChatMessageResponse response2 = postMessageToChat ( message );
209+ if ( response2 . hasException ()) {
210+ LOGGER . log ( Level . SEVERE , "Failed to post message on retry" , response2 . getException ());
211+ }
212+ }
213+ if ( response . getException () instanceof ProbablyNotLoggedInException ) {
225214 System .out .println ("Probably not logged in" );
226215 LOGGER .info ("Not logged in, logging in and then reposting" );
227216 login ();
228- try {
229- postMessageToChat (message );
230- } catch (ChatThrottleException | ProbablyNotLoggedInException ex1 ) {
231- LOGGER .log (Level .INFO , "Failed to post message on retry" , ex1 );
232- }
217+ ChatMessageResponse response2 = postMessageToChat (message );
218+ if (response2 .hasException ()) {
219+ LOGGER .log (Level .SEVERE , "Failed to post message on retry" , response2 .getException ());
220+ }
233221 }
234222 }
235223
236- private void postMessageToChat (final ChatMessage message ) throws ChatThrottleException , ProbablyNotLoggedInException {
224+ @ Override
225+ public Future <List <ChatMessageResponse >> postChat (WebhookParameters params , List <String > messages ) {
226+ return postMessages (params , messages );
227+ }
228+
229+ @ Override
230+ public void postSingle (WebhookParameters params , String message ) {
231+ postChat (params , Collections .singletonList (message ));
232+ }
233+
234+ @ Override
235+ public Future <ChatMessageResponse > postAsync (ChatMessage message ) {
236+ this .messagesQueue .add (Collections .singletonList (message ));
237+ return null ;
238+ }
239+
240+ @ Override
241+ public ChatMessageResponse postNowOnce (ChatMessage message ) {
242+ return postMessageToChat (message );
243+ }
244+
245+ @ Override
246+ public ChatMessageResponse postNow (ChatMessage message ) {
247+ return null ;
248+ }
249+
250+ private ChatMessageResponse postMessageToChat (final ChatMessage message ) {
237251 Objects .requireNonNull (message , "message" );
238252 Map <String , String > parameters = new HashMap <>();
239253 String text = message .getMessage ();
240254 text = text .replaceAll ("access_token=([0-9a-f]+)" , "access_token=xxxxxxxxxxxxxx" );
241255 parameters .put ("text" , text );
242256 parameters .put ("fkey" , this .chatFKey );
243257 System .out .println ("Okay, here we go!" );
258+ Resource response ;
244259 try {
245- Resource response = agent .post ("http://chat.stackexchange.com/chats/" + message .getRoom () + "/messages/new" , parameters );
246- System .out .println ("Response: " + response .getTitle ());
247- if (response instanceof JsonDocument ) {
248- System .out .println (response );
249- JsonDocument json = (JsonDocument ) response ;
250- System .out .println ("Success: " + json .getRoot ());
251- message .onSuccess ((JsonDocument ) response );
252- } else if (response instanceof HtmlDocument ) {
253- //failure
254- HtmlDocument htmlDocument = (HtmlDocument ) response ;
255- System .out .println ("Failure: " + htmlDocument );
256- HtmlElement body = htmlDocument .find ("body" );
257- if (body .getInnerHtml ().contains ("You can perform this action again in" )) {
258- int timing =
259- Integer .parseInt (body .getInnerHtml ().replaceAll ("You can perform this action again in" , "" )
260- .replaceAll ("seconds" , "" ).trim ());
261- throw new ChatThrottleException (timing );
262- }
263- else {
264- System .out .println (body .getInnerHtml ());
265- throw new ProbablyNotLoggedInException ();
266- }
267- }
268- else {
269- System .out .println ("Uknown response: " + response );
270- //even harder failure
271- throw new IllegalStateException ("unexpected response, response.getClass() = " + response .getClass ());
272- }
273- } catch (UnsupportedEncodingException ex ) {
274- System .out .println ("Unsupported encoding: " + ex );
275- throw new UncheckedIOException (ex );
276- }
260+ response = agent .post ("http://chat.stackexchange.com/chats/" +
261+ message .getRoom () + "/messages/new" , parameters );
262+ } catch (UnsupportedEncodingException e ) {
263+ return new ChatMessageResponse (e .toString (), e );
264+ }
265+
266+ System .out .println ("Response: " + response .getTitle ());
267+ if (response instanceof JsonDocument ) {
268+ System .out .println (response );
269+ JsonDocument json = (JsonDocument ) response ;
270+ System .out .println ("Success: " + json .getRoot ());
271+ message .onSuccess (json );
272+ return new ChatMessageResponse (Long .parseLong (json .getRoot ().getChild ("id" ).getValue ()),
273+ Long .parseLong (json .getRoot ().getChild ("time" ).getValue ()), json .getRoot ().toString ());
274+ }
275+
276+ if (response instanceof HtmlDocument ) {
277+ //failure
278+ HtmlDocument htmlDocument = (HtmlDocument ) response ;
279+ System .out .println ("Failure: " + htmlDocument );
280+ HtmlElement body = htmlDocument .find ("body" );
281+ if (body .getInnerHtml ().contains ("You can perform this action again in" )) {
282+ int timing =
283+ Integer .parseInt (body .getInnerHtml ().replaceAll ("You can perform this action again in" , "" )
284+ .replaceAll ("seconds" , "" ).trim ());
285+ return new ChatMessageResponse (body .getInnerHtml (), new ChatThrottleException (timing ));
286+ }
287+
288+ System .out .println (body .getInnerHtml ());
289+ return new ChatMessageResponse (body .getInnerHtml (), new ProbablyNotLoggedInException ());
290+ }
291+
292+ System .out .println ("Unknown response: " + response );
293+ //even harder failure
294+ throw new IllegalStateException ("unexpected response, response.getClass() = " + response .getClass ());
277295 }
278296
279297 public void stop () {
0 commit comments