From da33d941bb3e3fde10c9e674b40fe2f4dcfd5566 Mon Sep 17 00:00:00 2001 From: mrbesen Date: Thu, 7 Feb 2019 06:30:28 +0100 Subject: [PATCH] added AsyncHandling --- src/de/mrbesen/telegram/AsyncHandler.java | 91 +++++++++++++++++++ src/de/mrbesen/telegram/TelegramAPI.java | 44 ++++++++- src/de/mrbesen/telegram/objects/TMessage.java | 2 +- src/de/mrbesen/telegram/objects/TUser.java | 42 ++++++--- 4 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 src/de/mrbesen/telegram/AsyncHandler.java diff --git a/src/de/mrbesen/telegram/AsyncHandler.java b/src/de/mrbesen/telegram/AsyncHandler.java new file mode 100644 index 0000000..f02c390 --- /dev/null +++ b/src/de/mrbesen/telegram/AsyncHandler.java @@ -0,0 +1,91 @@ +package de.mrbesen.telegram; + +import java.util.LinkedList; +import java.util.List; + +import org.json.JSONObject; + +public class AsyncHandler implements Runnable { + + private List tasks = new LinkedList<>(); + private Thread asynchandlerthread = null; + private TelegramAPI api; + + public AsyncHandler(TelegramAPI api) { + this.api = api; + } + + public void enque(Task t) { + tasks.add(t); + + //make sure its running + if(asynchandlerthread == null) { + asynchandlerthread = new Thread(this, "AsyncHandler"); + asynchandlerthread.start(); + } + } + + public void enque(String request, String parameters) { + enque(new Task(request, parameters)); + } + + @Override + public void run() { + while(!tasks.isEmpty()) { + Task current = tasks.remove(0); + + //run task + try { + try { + Object obj = api.request(current.apimethod, current.parameters); + Callback callb = current.callback; + while(callb != null) { + obj = (Object) callb.callObj(obj); + callb = callb.next; + // throw new Exception("Callbacktype missmatch! Got " + obj.getClass().getSimpleName() + " Wanted: " + wanted.getSimpleName() ); + } + } catch(Throwable t) { + if(current.exceptionhandl == null) + throw t; + current.exceptionhandl.call(t); + } + } catch(Throwable t) { + System.out.println("Error executing Task: "); + t.printStackTrace(); + } + } + asynchandlerthread = null; + } + + public static class Task { + String apimethod; + String parameters; + Callback callback = null; + Callback exceptionhandl = null; + + public Task(String apimethod, String parameters) { + this.apimethod = apimethod; + this.parameters = parameters; + } + + public Task(String apimethod, String parameters, Callback callback) { + this.apimethod = apimethod; + this.parameters = parameters; + this.callback = callback; + } + + public Task setExceptionhandl(Callback exceptionhandl) { + this.exceptionhandl = exceptionhandl; + return this; + } + } + + public static abstract class Callback { + public Callback next = null; + public abstract K call(T j) throws Throwable; + @SuppressWarnings("unchecked") + public K callObj(Object j) throws Throwable { + return call((T) j); + } + } +} diff --git a/src/de/mrbesen/telegram/TelegramAPI.java b/src/de/mrbesen/telegram/TelegramAPI.java index c8f4fb9..100236b 100644 --- a/src/de/mrbesen/telegram/TelegramAPI.java +++ b/src/de/mrbesen/telegram/TelegramAPI.java @@ -11,6 +11,8 @@ import javax.net.ssl.HttpsURLConnection; import org.json.JSONArray; import org.json.JSONObject; +import de.mrbesen.telegram.AsyncHandler.Callback; +import de.mrbesen.telegram.AsyncHandler.Task; import de.mrbesen.telegram.MessageBuilder.SendableMessage; import de.mrbesen.telegram.commands.CommandManager; import de.mrbesen.telegram.event.Event; @@ -44,6 +46,19 @@ public class TelegramAPI implements Runnable { private CommandManager cmdmgr = new CommandManager(); private EventManager evntmgr = new EventManager(); + //async + private AsyncHandler async = new AsyncHandler(this); + public static Callback IOE400supressor = new Callback() { + @Override + public Void call(Throwable t) throws Throwable { + if(t instanceof IOException) { + if(t.getMessage().startsWith("Server returned HTTP response code: 400")) + return null; + } + throw t; + } + }; + Log log = new Log4JLog(); public TelegramAPI(String apikey) { @@ -63,6 +78,22 @@ public class TelegramAPI implements Runnable { } } + public void request(Task task) { + async.enque(task); + } + + public void request(String request, String parameter, boolean async) { + if(async) { + this.async.enque(request, parameter); + } else { + try { + request(request, parameter); + } catch(IOException e) { + e.printStackTrace(); + } + } + } + public JSONObject request(String request, String parameter) throws IOException { //do https stuff URL url = new URL(API_URL + apikey + "/" + request); @@ -72,9 +103,9 @@ public class TelegramAPI implements Runnable { OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream()); wr.write(parameter); wr.flush(); - + log.log( "request: " + request + " content " + parameter + " -> " + con.getResponseCode() + ", " + con.getResponseMessage()); - + Scanner s = new Scanner(con.getInputStream()); StringBuilder sb_apianswer = new StringBuilder(); while(s.hasNextLine()) { @@ -247,6 +278,15 @@ public class TelegramAPI implements Runnable { return updateInterval; } + public static Callback getCallbackAdapter(TelegramAPI api) { + return new Callback() { + @Override + public TMessage call(JSONObject j) { + return new TMessage(j.getJSONObject("result"), api); + } + }; + } + protected class TelegramAPIUpdate { protected int update_id = 0; private TMessage msg = null; diff --git a/src/de/mrbesen/telegram/objects/TMessage.java b/src/de/mrbesen/telegram/objects/TMessage.java index df614e8..de00c43 100644 --- a/src/de/mrbesen/telegram/objects/TMessage.java +++ b/src/de/mrbesen/telegram/objects/TMessage.java @@ -26,7 +26,7 @@ public class TMessage extends JSONBased { if(from == null) { throw new RuntimeException("no from defined!"); } else { - return TUser.sendMessage(api, chatid != 0 ? chatid : from.getID(), msg, rm, message_id); + return TUser.sendMessage(api, chatid != 0 ? chatid : from.getID(), msg, rm, message_id, false, null); } // try { // return api.request("sendMessage", "chat_id=" + from.getID() + "&text=" + msg + "&reply_to_message_id=" + message_id ).getBoolean("ok") ; diff --git a/src/de/mrbesen/telegram/objects/TUser.java b/src/de/mrbesen/telegram/objects/TUser.java index e3cb85e..25aab05 100644 --- a/src/de/mrbesen/telegram/objects/TUser.java +++ b/src/de/mrbesen/telegram/objects/TUser.java @@ -5,6 +5,8 @@ import java.net.URLEncoder; import org.json.JSONObject; +import de.mrbesen.telegram.AsyncHandler.Callback; +import de.mrbesen.telegram.AsyncHandler.Task; import de.mrbesen.telegram.TelegramAPI; public class TUser { @@ -80,7 +82,7 @@ public class TUser { } public boolean sendMessage(String text, TReplyMarkup rm, int reply_to_msg) { - return sendMessage(api, id, text, rm, reply_to_msg); + return sendMessage(api, id, text, rm, reply_to_msg, false, null); } /** @@ -92,7 +94,7 @@ public class TUser { * @param reply_to_msg 0 = no reply * @return */ - public static boolean sendMessage(TelegramAPI api, int userid, String text, TReplyMarkup rm, int reply_to_msg) { + public static boolean sendMessage(TelegramAPI api, int userid, String text, TReplyMarkup rm, int reply_to_msg, boolean async, Callback callb) { if(api == null) { System.err.println("api == null!"); return false; @@ -100,9 +102,14 @@ public class TUser { String replyto = (reply_to_msg > 0 ? "&reply_to_message_id=" +reply_to_msg : ""); try { String replymarkup = parseRPMU(rm); - return api.request("sendMessage", "chat_id=" + userid - + "&text=" + URLEncoder.encode(text, "UTF-8") - + replymarkup + replyto).getBoolean("ok"); + String param = "chat_id=" + userid + + "&text=" + URLEncoder.encode(text, "UTF-8") + replymarkup + replyto; + if(async) + return api.request("sendMessage", param).getBoolean("ok"); + + Callback< JSONObject, TMessage> adapter = TelegramAPI.getCallbackAdapter(api); + adapter.next = callb; + api.request(new Task("sendMessage", param, adapter).setExceptionhandl(TelegramAPI.IOE400supressor)); } catch (IOException e) { e.printStackTrace(); } @@ -123,17 +130,24 @@ public class TUser { } public boolean sendImage(String caption, String url) { - return sendImage(api, id, caption, url, null) != null; + return sendImage(api, id, caption, url, null, null) != null; } - public static TMessage sendImage(TelegramAPI api, int userid, String caption, String url, TReplyMarkup rply) { + public static TMessage sendImage(TelegramAPI api, int userid, String caption, String url, TReplyMarkup rply, Callback async) { try { String cap = ""; if(caption != null) { if(!caption.isEmpty()) cap = "&caption=" + caption; } - return new TMessage(api.request("sendPhoto", "chat_id=" + userid + parseRPMU(rply) + cap + "&photo=" + url).getJSONObject("result"), api); + + String params = "chat_id=" + userid + parseRPMU(rply) + cap + "&photo=" + url; + if(async == null) + return new TMessage(api.request("sendPhoto", params).getJSONObject("result"), api); + + Callback< JSONObject, TMessage> adapter = TelegramAPI.getCallbackAdapter(api); + adapter.next = async; + api.request(new Task("sendPhoto", params, adapter).setExceptionhandl(TelegramAPI.IOE400supressor)); } catch (IOException e) { e.printStackTrace(); } @@ -141,17 +155,23 @@ public class TUser { } public boolean sendAnimation(String caption, String url) { - return sendAnimation(api, id, caption, url, null) != null; + return sendAnimation(api, id, caption, url, null, null) != null; } - public static TMessage sendAnimation(TelegramAPI api, int userid, String caption, String url, TReplyMarkup rply) { + public static TMessage sendAnimation(TelegramAPI api, int userid, String caption, String url, TReplyMarkup rply, Callback async) { try { String cap = ""; if(caption != null) { if(!caption.isEmpty()) cap = "&caption=" + caption; } - return new TMessage(api.request("sendAnimation", "chat_id=" + userid + parseRPMU(rply) + cap + "&animation=" + url).getJSONObject("result"), api); + String params = "chat_id=" + userid + parseRPMU(rply) + cap + "&animation=" + url; + if(async == null) + return new TMessage(api.request("sendAnimation", params).getJSONObject("result"), api); + + Callback< JSONObject, TMessage> adapter = TelegramAPI.getCallbackAdapter(api); + adapter.next = async; + api.request(new Task("sendAnimation", params, adapter).setExceptionhandl(TelegramAPI.IOE400supressor)); } catch (IOException e) { e.printStackTrace(); }