Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
d3e278d117 | |||
c3e29a2c40 | |||
0e2ab20a21 | |||
9440f84b41 | |||
b9d0616774 | |||
39ce902b5f | |||
e5495bc833 | |||
6bf1eb8387 | |||
2b9b0dab06 | |||
64016a859c | |||
014e58a45b | |||
279dca0286 | |||
97b72385a3 | |||
1fe7bc64d3 | |||
a4a0b8e649 | |||
e0f531004f | |||
1e7b3f4794 | |||
d359b89851 | |||
6ca91303b3 | |||
7d1e478260 | |||
e2eb71a1a6 | |||
39d99685d1 | |||
7a5b2d72ca | |||
9dc407180d | |||
f6196f3a1f | |||
589fd898f2 | |||
4429763547 | |||
0085e7b77c | |||
b8854cb482 | |||
812d3f8df1 | |||
b7315a1766 | |||
a88f8b5cf5 | |||
35eb9e71c6 | |||
a51a07c238 | |||
58e5286b3b | |||
9b6da7080b | |||
add7f5ece2 | |||
1de6e05cfa | |||
112722d1c5 | |||
57db456a80 | |||
7e8de1156d | |||
9f7829b28a | |||
545e328b07 | |||
225faa948d | |||
aee04b5a13 | |||
d2e0ab9a3f |
|
@ -5,4 +5,4 @@ A API that does most of the work, when creating Telegram bots.
|
||||||
[![Build Status](https://jenkins.mrbesen.de/buildStatus/icon?job=TelegramAPI)](https://jenkins.mrbesen.de/job/TelegramAPI)
|
[![Build Status](https://jenkins.mrbesen.de/buildStatus/icon?job=TelegramAPI)](https://jenkins.mrbesen.de/job/TelegramAPI)
|
||||||
|
|
||||||
#### Download last Build
|
#### Download last Build
|
||||||
[Download] (https://jenkins.mrbesen.de/job/TelegramAPI/lastSuccessfulBuild/artifact/target/TelegramAPI-0.0.1-SNAPSHOT.jar)
|
[Download](https://jenkins.mrbesen.de/job/TelegramAPI/lastSuccessfulBuild/artifact/target/TelegramAPI-0.0.3.jar)
|
29
pom.xml
29
pom.xml
|
@ -3,7 +3,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>TelegramAPI</groupId>
|
<groupId>TelegramAPI</groupId>
|
||||||
<artifactId>TelegramAPI</artifactId>
|
<artifactId>TelegramAPI</artifactId>
|
||||||
<version>0.0.2</version>
|
<version>0.0.3</version>
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -13,8 +13,9 @@
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.10.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>de/mrbesen/test/**</exclude>
|
<exclude>de/mrbesen/test/**</exclude>
|
||||||
|
@ -23,29 +24,44 @@
|
||||||
<target />
|
<target />
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-api</artifactId>
|
<artifactId>log4j-api</artifactId>
|
||||||
<version>2.11.1</version>
|
<version>2.18.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-core</artifactId>
|
<artifactId>log4j-core</artifactId>
|
||||||
<version>2.11.1</version>
|
<version>2.18.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>org.json</groupId>
|
||||||
<artifactId>json</artifactId>
|
<artifactId>json</artifactId>
|
||||||
<version>20180813</version>
|
<version>20201115</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>LATEST</version>
|
<version>1.18.24</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -54,5 +70,4 @@
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -1,93 +1,65 @@
|
||||||
package de.mrbesen.telegram;
|
package de.mrbesen.telegram;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class AsyncHandler implements Runnable {
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
private List<Task> tasks = new LinkedList<>();
|
public class AsyncHandler {
|
||||||
private Thread asynchandlerthread = null;
|
|
||||||
private TelegramAPI api;
|
|
||||||
|
|
||||||
|
private List<Task> fasttasks = new LinkedList<>();
|
||||||
|
private List<Task> slowtasks = new LinkedList<>();
|
||||||
|
|
||||||
|
private AsyncHandlerThread[] asynchandlerthread;
|
||||||
|
private static final String THREADPREFIX = "AsyncTgHandler-";
|
||||||
|
|
||||||
|
// just use 2 async threads
|
||||||
public AsyncHandler(TelegramAPI api) {
|
public AsyncHandler(TelegramAPI api) {
|
||||||
this.api = api;
|
this(api, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow as many as threadCount threads to handle Async Tasks
|
||||||
|
public AsyncHandler(TelegramAPI api, int threadCount) {
|
||||||
|
if (threadCount < 2) {
|
||||||
|
threadCount = 2;
|
||||||
|
}
|
||||||
|
asynchandlerthread = new AsyncHandlerThread[threadCount];
|
||||||
|
|
||||||
|
asynchandlerthread[0] = new AsyncHandlerThread(fasttasks, THREADPREFIX + "Fast-0", api);
|
||||||
|
|
||||||
|
for (int i = 1; i < threadCount; ++i) {
|
||||||
|
asynchandlerthread[i] = new AsyncHandlerThread(slowtasks, THREADPREFIX + "Slow-" + i, api);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
for (AsyncHandlerThread t : asynchandlerthread) {
|
||||||
|
t.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enque(Task t) {
|
public void enque(Task t) {
|
||||||
enque(t, false);
|
enque(t, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enque(Task t, boolean priority) {
|
public void enque(Task t, boolean isSlowMethod, boolean priority) {
|
||||||
if(priority) {
|
List<Task> tasks = isSlowMethod ? slowtasks : fasttasks;
|
||||||
|
|
||||||
|
if (priority) {
|
||||||
synchronized (tasks) {
|
synchronized (tasks) {
|
||||||
tasks.add(0, t);
|
tasks.add(0, t);
|
||||||
|
tasks.notifyAll();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
synchronized (tasks) {
|
synchronized (tasks) {
|
||||||
tasks.add(t);
|
tasks.add(t);
|
||||||
|
tasks.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//make sure its running
|
|
||||||
if(asynchandlerthread == null) {
|
|
||||||
asynchandlerthread = new Thread(this, "AsyncHandler");
|
|
||||||
asynchandlerthread.start();
|
|
||||||
} else if(!asynchandlerthread.isAlive()) {
|
|
||||||
asynchandlerthread = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enque(String request, String parameters) {
|
public void enque(String request, String parameters, long userid) {
|
||||||
enque(new Task(request, parameters));
|
enque(new Task(request, parameters, userid));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int failed = 0;
|
|
||||||
while(!tasks.isEmpty()) {
|
|
||||||
Task current;
|
|
||||||
|
|
||||||
synchronized (tasks) {
|
|
||||||
current = tasks.remove(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(current == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//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() );
|
|
||||||
}
|
|
||||||
failed = 0;
|
|
||||||
} catch(UnknownHostException ex) {//host(api.telegram.org) is good -> bad inet
|
|
||||||
failed ++;
|
|
||||||
if(failed > 10)
|
|
||||||
try {
|
|
||||||
Thread.yield();
|
|
||||||
Thread.sleep(1000);//wait 1 second
|
|
||||||
} catch(InterruptedException ignored) {}
|
|
||||||
//reenque
|
|
||||||
enque(current);
|
|
||||||
} 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 {
|
public static class Task {
|
||||||
|
@ -95,18 +67,19 @@ public class AsyncHandler implements Runnable {
|
||||||
String parameters;
|
String parameters;
|
||||||
Callback<JSONObject, ?> callback = null;
|
Callback<JSONObject, ?> callback = null;
|
||||||
Callback<Throwable, ?> exceptionhandl = null;
|
Callback<Throwable, ?> exceptionhandl = null;
|
||||||
|
final long userid;
|
||||||
public Task(String apimethod, String parameters) {
|
|
||||||
this.apimethod = apimethod;
|
public Task(String apimethod, String parameters, long userid) {
|
||||||
this.parameters = parameters;
|
this(apimethod, parameters, userid, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task(String apimethod, String parameters, Callback<JSONObject, ?> callback) {
|
public Task(String apimethod, String parameters, long userid, Callback<JSONObject, ?> callback) {
|
||||||
this.apimethod = apimethod;
|
this.apimethod = apimethod;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
|
this.userid = userid;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task setExceptionhandl(Callback<Throwable, ?> exceptionhandl) {
|
public Task setExceptionhandl(Callback<Throwable, ?> exceptionhandl) {
|
||||||
this.exceptionhandl = exceptionhandl;
|
this.exceptionhandl = exceptionhandl;
|
||||||
return this;
|
return this;
|
||||||
|
@ -115,7 +88,9 @@ public class AsyncHandler implements Runnable {
|
||||||
|
|
||||||
public static abstract class Callback<T extends Object, K extends Object> {
|
public static abstract class Callback<T extends Object, K extends Object> {
|
||||||
public Callback<K, ?> next = null;
|
public Callback<K, ?> next = null;
|
||||||
|
|
||||||
public abstract K call(T j) throws Throwable;
|
public abstract K call(T j) throws Throwable;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public K callObj(Object j) throws Throwable {
|
public K callObj(Object j) throws Throwable {
|
||||||
return call((T) j);
|
return call((T) j);
|
||||||
|
|
99
src/main/java/de/mrbesen/telegram/AsyncHandlerThread.java
Normal file
99
src/main/java/de/mrbesen/telegram/AsyncHandlerThread.java
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package de.mrbesen.telegram;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.AsyncHandler.Callback;
|
||||||
|
import de.mrbesen.telegram.AsyncHandler.Task;
|
||||||
|
|
||||||
|
public class AsyncHandlerThread implements Runnable {
|
||||||
|
|
||||||
|
private boolean shouldrun = false;
|
||||||
|
private TelegramAPI api;
|
||||||
|
private int failed = 0;
|
||||||
|
|
||||||
|
private Thread thread;
|
||||||
|
|
||||||
|
private List<Task> tasks;
|
||||||
|
|
||||||
|
AsyncHandlerThread(List<Task> tasks, String name, TelegramAPI api) {
|
||||||
|
this.tasks = tasks;
|
||||||
|
this.api = api;
|
||||||
|
shouldrun = true;
|
||||||
|
thread = new Thread(this, name);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
shouldrun = false;
|
||||||
|
|
||||||
|
thread.interrupt();
|
||||||
|
|
||||||
|
try {
|
||||||
|
thread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (shouldrun) {
|
||||||
|
Task t;
|
||||||
|
|
||||||
|
synchronized (tasks) {
|
||||||
|
while (tasks.isEmpty()) {
|
||||||
|
try {
|
||||||
|
tasks.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t = tasks.remove(0);
|
||||||
|
tasks.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// run task
|
||||||
|
try {
|
||||||
|
processTask(t);
|
||||||
|
} catch (Throwable thro) {
|
||||||
|
api.log.log("Error executing Task: ");
|
||||||
|
thro.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processTask(Task t) throws Throwable {
|
||||||
|
try {
|
||||||
|
Object obj = api.request(t.apimethod, t.parameters, t.userid);
|
||||||
|
Callback<?, ?> callb = t.callback;
|
||||||
|
while (callb != null) {
|
||||||
|
obj = (Object) callb.callObj(obj);
|
||||||
|
callb = callb.next;
|
||||||
|
// throw new Exception("Callbacktype missmatch! Got " +
|
||||||
|
// obj.getClass().getSimpleName() + " Wanted: " + wanted.getSimpleName() );
|
||||||
|
}
|
||||||
|
failed = 0;
|
||||||
|
} catch (UnknownHostException ex) { // host(api.telegram.org) is good -> bad inet
|
||||||
|
failed++;
|
||||||
|
if (failed > 10)
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000); // wait 1 second
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// reenque
|
||||||
|
synchronized (tasks) {
|
||||||
|
tasks.add(0, t);
|
||||||
|
}
|
||||||
|
} catch (Throwable thro) {
|
||||||
|
if (t.exceptionhandl == null)
|
||||||
|
throw thro;
|
||||||
|
api.log.log("Exception " + thro.getClass().getSimpleName() + " handled by "
|
||||||
|
+ t.exceptionhandl.getClass().getSimpleName());
|
||||||
|
t.exceptionhandl.call(thro);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
package de.mrbesen.telegram;
|
package de.mrbesen.telegram;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
|
|
||||||
import de.mrbesen.telegram.AsyncHandler.Callback;
|
import de.mrbesen.telegram.AsyncHandler.Callback;
|
||||||
import de.mrbesen.telegram.objects.TMessage;
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
import de.mrbesen.telegram.objects.TReplyMarkup;
|
import de.mrbesen.telegram.objects.TReplyMarkup;
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
public class MessageBuilder {
|
public class MessageBuilder {
|
||||||
|
|
||||||
|
@ -14,7 +16,8 @@ public class MessageBuilder {
|
||||||
private Formatting format = Formatting.None;
|
private Formatting format = Formatting.None;
|
||||||
private boolean silent = false;
|
private boolean silent = false;
|
||||||
private boolean no_web_view = false;
|
private boolean no_web_view = false;
|
||||||
private long reciver_id = 0;
|
private boolean allow_sending_without_reply = false;
|
||||||
|
private long receiver_id = 0;
|
||||||
private int reply_to_message_id = 0;
|
private int reply_to_message_id = 0;
|
||||||
private TReplyMarkup markup = null;
|
private TReplyMarkup markup = null;
|
||||||
private boolean async = false;
|
private boolean async = false;
|
||||||
|
@ -25,14 +28,21 @@ public class MessageBuilder {
|
||||||
private String attachment = null;
|
private String attachment = null;
|
||||||
private String caption = null;
|
private String caption = null;
|
||||||
private int updates = 0;
|
private int updates = 0;
|
||||||
|
private TelegramAPI api = null;
|
||||||
|
|
||||||
|
public MessageBuilder(TelegramAPI api) {
|
||||||
|
this.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageBuilder() { }
|
||||||
|
|
||||||
public MessageBuilder setReciver(long id) {
|
public MessageBuilder setReciver(long id) {
|
||||||
reciver_id = id;
|
receiver_id = id;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageBuilder setReciver(TUser user) {
|
public MessageBuilder setReciver(TUser user) {
|
||||||
reciver_id = user.getID();
|
receiver_id = user.getID();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +80,7 @@ public class MessageBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageBuilder setReplyTo(TMessage msg) {
|
public MessageBuilder setReplyTo(TMessage msg) {
|
||||||
if(reciver_id == 0)
|
if(receiver_id == 0)
|
||||||
setReciver(msg.getChatID());
|
setReciver(msg.getChatID());
|
||||||
return setReplyTo(msg.getMessageID());
|
return setReplyTo(msg.getMessageID());
|
||||||
}
|
}
|
||||||
|
@ -107,15 +117,20 @@ public class MessageBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageBuilder setAttachment(Attachment type, String cont) {
|
public MessageBuilder setAttachment(Attachment type, String cont) {
|
||||||
|
if(cont == null) {
|
||||||
|
if(type != Attachment.none) throw new IllegalArgumentException("cont == null requires type == none");
|
||||||
|
attachmenttype = type;
|
||||||
|
attachment = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
if(attachmenttype != Attachment.none) {
|
if(attachmenttype != Attachment.none) {
|
||||||
throw new IllegalArgumentException("You can only attach one thing!");
|
throw new IllegalArgumentException("You can only attach one thing!");
|
||||||
}
|
}
|
||||||
if(cont == null) {
|
|
||||||
throw new IllegalArgumentException("attachment empty!");
|
|
||||||
}
|
|
||||||
attachmenttype = type;
|
attachmenttype = type;
|
||||||
try {
|
try {
|
||||||
attachment = URLEncoder.encode(cont, "UTF-8");
|
attachment = URLEncoder.encode(cont, "UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -137,8 +152,18 @@ public class MessageBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* should fail when a message, thats replyed to is not existent default is true
|
||||||
|
* @param b
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public MessageBuilder setFailwithoutReply(boolean b) {
|
||||||
|
allow_sending_without_reply = !b;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SendableMessage build() {
|
public SendableMessage build() {
|
||||||
if(reciver_id == 0) {
|
if(receiver_id == 0) {
|
||||||
throw new MissingException("Reciver");
|
throw new MissingException("Reciver");
|
||||||
}
|
}
|
||||||
String optionals = "";
|
String optionals = "";
|
||||||
|
@ -179,35 +204,39 @@ public class MessageBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(no_web_view) {
|
if(no_web_view) {
|
||||||
optionals += "&disable_web_page_preview=" + no_web_view;
|
optionals += "&disable_web_page_preview=true";
|
||||||
}
|
}
|
||||||
if(silent) {
|
if(silent) {
|
||||||
optionals += "&disable_notification=" + silent;
|
optionals += "&disable_notification=true";
|
||||||
|
}
|
||||||
|
if(allow_sending_without_reply) {
|
||||||
|
optionals += "&allow_sending_without_reply=true";
|
||||||
}
|
}
|
||||||
|
|
||||||
String q = "chat_id=" + reciver_id + text + optionals + attachment;
|
String q = "chat_id=" + receiver_id + text + optionals + attachment;
|
||||||
if(async) {
|
if(async) {
|
||||||
AsyncSendable tmp = new AsyncSendable(cmd, q, callback, excpt);
|
AsyncSendable tmp = new AsyncSendable(cmd, q, receiver_id, callback, excpt);
|
||||||
tmp.prio = asyncprio;
|
tmp.prio = asyncprio;
|
||||||
|
tmp.isSlow = attachmenttype != Attachment.none;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
return new SendableMessage(cmd, q);
|
return new SendableMessage(cmd, q, receiver_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is only allowed, when the Message builder was contructed using a api
|
||||||
|
* @return the send TMessage when the Message Builder is used SYNC, or null when the Message Builder is used ASYNC or has encountered an error.
|
||||||
|
*/
|
||||||
|
public TMessage send() {
|
||||||
|
return api.sendMessage(build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
class SendableMessage {
|
class SendableMessage {
|
||||||
private String q;
|
private final String command;
|
||||||
private String command;
|
private final String q;
|
||||||
|
private final long userid;
|
||||||
public SendableMessage(String cmd, String q) {
|
|
||||||
this.q = q;
|
|
||||||
command = cmd;
|
|
||||||
}
|
|
||||||
String getQ() {
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
String getCommand() {
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncSendable extends SendableMessage {
|
class AsyncSendable extends SendableMessage {
|
||||||
|
@ -215,9 +244,10 @@ public class MessageBuilder {
|
||||||
Callback<TMessage, ?> callback;
|
Callback<TMessage, ?> callback;
|
||||||
Callback<Throwable, Void> excpt = null;
|
Callback<Throwable, Void> excpt = null;
|
||||||
boolean prio = false;
|
boolean prio = false;
|
||||||
|
boolean isSlow = false; // is it expected that this message is slow to porcess? sendMedia
|
||||||
|
|
||||||
public AsyncSendable(String cmd, String q, Callback<TMessage, ?> clb, Callback<Throwable, Void> excpt) {
|
public AsyncSendable(String cmd, String q, long userid, Callback<TMessage, ?> clb, Callback<Throwable, Void> excpt) {
|
||||||
super(cmd, q);
|
super(cmd, q, userid);
|
||||||
callback = clb;
|
callback = clb;
|
||||||
this.excpt = excpt;
|
this.excpt = excpt;
|
||||||
}
|
}
|
||||||
|
@ -249,6 +279,8 @@ public class MessageBuilder {
|
||||||
Animation;
|
Animation;
|
||||||
|
|
||||||
public static Attachment getForFileExt(String extention) {
|
public static Attachment getForFileExt(String extention) {
|
||||||
|
if(extention == null) return Document;
|
||||||
|
|
||||||
if(extention.startsWith("."))
|
if(extention.startsWith("."))
|
||||||
extention = extention.substring(1);
|
extention = extention.substring(1);
|
||||||
|
|
||||||
|
|
|
@ -1,54 +1,51 @@
|
||||||
package de.mrbesen.telegram;
|
package de.mrbesen.telegram;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
|
|
||||||
import de.mrbesen.telegram.commands.FeedbackCommand;
|
|
||||||
import de.mrbesen.telegram.commands.JSONCommandHandler;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import de.mrbesen.telegram.AsyncHandler.Callback;
|
import de.mrbesen.telegram.AsyncHandler.Callback;
|
||||||
import de.mrbesen.telegram.AsyncHandler.Task;
|
import de.mrbesen.telegram.AsyncHandler.Task;
|
||||||
import de.mrbesen.telegram.MessageBuilder.AsyncSendable;
|
import de.mrbesen.telegram.MessageBuilder.AsyncSendable;
|
||||||
import de.mrbesen.telegram.MessageBuilder.SendableMessage;
|
import de.mrbesen.telegram.MessageBuilder.SendableMessage;
|
||||||
import de.mrbesen.telegram.commands.CommandManager;
|
import de.mrbesen.telegram.commands.CommandManager;
|
||||||
|
import de.mrbesen.telegram.commands.FeedbackCommand;
|
||||||
import de.mrbesen.telegram.event.Event;
|
import de.mrbesen.telegram.event.Event;
|
||||||
import de.mrbesen.telegram.event.EventManager;
|
import de.mrbesen.telegram.event.EventManager;
|
||||||
import de.mrbesen.telegram.event.events.UserCallbackEvent;
|
import de.mrbesen.telegram.event.events.*;
|
||||||
import de.mrbesen.telegram.event.events.UserSendAudioEvent;
|
|
||||||
import de.mrbesen.telegram.event.events.UserSendMessageEvent;
|
|
||||||
import de.mrbesen.telegram.log.Log;
|
import de.mrbesen.telegram.log.Log;
|
||||||
import de.mrbesen.telegram.log.Log4JLog;
|
import de.mrbesen.telegram.log.Log4JLog;
|
||||||
import de.mrbesen.telegram.log.SimpleLog;
|
import de.mrbesen.telegram.log.SimpleLog;
|
||||||
import de.mrbesen.telegram.objects.JSONBased.Member;
|
import de.mrbesen.telegram.objects.JSONBased.Member;
|
||||||
import de.mrbesen.telegram.objects.TAudio;
|
import de.mrbesen.telegram.objects.TFile;
|
||||||
import de.mrbesen.telegram.objects.TMessage;
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
import de.mrbesen.telegram.objects.TReplyMarkup;
|
import de.mrbesen.telegram.objects.TReplyMarkup;
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
import de.mrbesen.telegram.objects.TUser.Status;
|
import de.mrbesen.telegram.objects.TUser.Status;
|
||||||
import sun.awt.image.ImageWatched;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.*;
|
||||||
|
import java.util.stream.Collector;
|
||||||
|
|
||||||
|
import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
|
||||||
|
import static java.util.stream.Collector.Characteristics.UNORDERED;
|
||||||
|
|
||||||
public class TelegramAPI implements Runnable {
|
public class TelegramAPI implements Runnable {
|
||||||
|
|
||||||
private static final String API_URL = "https://api.telegram.org/bot";
|
private static final String API_URL_DEFAULT = "https://api.telegram.org/bot";
|
||||||
private static final String TOKENREGEX = "^\\d{4,10}:[\\w-]{12,64}$";
|
private static final String TOKENREGEX = "^\\d{4,10}:[\\w-]{12,64}$";
|
||||||
private static final int TELEGRAMFILESIZELIMIT = 20000000;//20MB filesize https://core.telegram.org/bots/api#sending-files
|
private static final int TELEGRAMFILESIZELIMIT = 20000000;//20MB filesize https://core.telegram.org/bots/api#sending-files
|
||||||
public static final String APIVERSION = "3.8";//May 18, 2019
|
public static final String APIVERSION = "3.10";//Jan 16, 2021
|
||||||
|
|
||||||
private int msg_offset = 0;
|
private int msg_offset = 0;
|
||||||
private int updateInterval = 60;
|
private int updateInterval = 60;
|
||||||
private String apikey;
|
|
||||||
private String botname;
|
private String botname;
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
private boolean run = true;
|
private boolean run = true;
|
||||||
|
@ -56,6 +53,7 @@ public class TelegramAPI implements Runnable {
|
||||||
private boolean longpolling = true;
|
private boolean longpolling = true;
|
||||||
@Setter @Getter
|
@Setter @Getter
|
||||||
private boolean disableFeedback = false;
|
private boolean disableFeedback = false;
|
||||||
|
private String apiurl;
|
||||||
|
|
||||||
private String helpmessage = "generic helppage\nuse TelegramAPI.setHelpText(java.lang.String) to change this.";
|
private String helpmessage = "generic helppage\nuse TelegramAPI.setHelpText(java.lang.String) to change this.";
|
||||||
|
|
||||||
|
@ -63,14 +61,16 @@ public class TelegramAPI implements Runnable {
|
||||||
protected int fetchedUpdates = 0;
|
protected int fetchedUpdates = 0;
|
||||||
protected long start = 0;
|
protected long start = 0;
|
||||||
|
|
||||||
private LinkedList<TUser> users = new LinkedList<>();
|
private Map<Long, TUser> users = new TreeMap<>();
|
||||||
@Setter
|
@Setter
|
||||||
private List<Long> admins = new LinkedList<>(); //required for feedback
|
private List<Long> admins = new LinkedList<>(); //required for feedback
|
||||||
private CommandManager cmdmgr = new CommandManager(this);
|
private CommandManager cmdmgr = new CommandManager(this);
|
||||||
private EventManager evntmgr = new EventManager();
|
private EventManager evntmgr = new EventManager();
|
||||||
|
|
||||||
|
private FeedbackCommand feedbackCmd = null;
|
||||||
|
|
||||||
//async
|
//async
|
||||||
private AsyncHandler async = new AsyncHandler(this);
|
private AsyncHandler async = null;
|
||||||
public static Callback<Throwable, Void> IOE400supressor = new Callback<Throwable, Void>() {
|
public static Callback<Throwable, Void> IOE400supressor = new Callback<Throwable, Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void call(Throwable t) throws Throwable {
|
public Void call(Throwable t) throws Throwable {
|
||||||
|
@ -88,84 +88,129 @@ public class TelegramAPI implements Runnable {
|
||||||
* please only use if bot is not used in groups
|
* please only use if bot is not used in groups
|
||||||
* @param apikey
|
* @param apikey
|
||||||
*/
|
*/
|
||||||
public TelegramAPI(String apikey) {
|
|
||||||
botname = "";
|
public TelegramAPI(String apikey) { this(null, apikey); }
|
||||||
if (!apikey.matches(TOKENREGEX) ) {
|
|
||||||
throw new IllegalArgumentException("Invalid API key: " + apikey);
|
public TelegramAPI(String apiurl, String apikey) {
|
||||||
}
|
this(apiurl, apikey, "");
|
||||||
this.apikey = apikey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TelegramAPI(String apikey, String botname) {
|
public TelegramAPI(String apiurl, String apikey, String botname) {
|
||||||
this.botname = botname;
|
this.apiurl = (apiurl == null ? API_URL_DEFAULT : apiurl);
|
||||||
|
this.botname = botname != null ? botname : "";
|
||||||
|
|
||||||
if (!apikey.matches(TOKENREGEX) ) {
|
if (!apikey.matches(TOKENREGEX) ) {
|
||||||
throw new IllegalArgumentException("Invalid API key: " + apikey);
|
throw new IllegalArgumentException("Invalid API key: " + apikey);
|
||||||
}
|
}
|
||||||
this.apikey = apikey;
|
this.apiurl += apikey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
|
start(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//start with a specified threadcount for async operations
|
||||||
|
public void start(int threadCount) {
|
||||||
if(thread == null) {
|
if(thread == null) {
|
||||||
|
async = new AsyncHandler(this, threadCount);
|
||||||
if(!disableFeedback) {
|
if(!disableFeedback) {
|
||||||
//init Feedback
|
//init Feedback
|
||||||
FeedbackCommand fcmd = new FeedbackCommand();
|
feedbackCmd = new FeedbackCommand(this, admins);
|
||||||
cmdmgr.registerCommand("feedback", fcmd);
|
cmdmgr.registerCommand("feedback", feedbackCmd);
|
||||||
}
|
}
|
||||||
run = true;
|
run = true;
|
||||||
thread = new Thread(this, "TelegramAPI");
|
thread = new Thread(this, "TelegramAPI");
|
||||||
thread.start();
|
thread.start();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Still Running.");
|
throw new IllegalStateException("Still Running.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAdmin(long admin) {
|
public void addAdmin(long admin) {
|
||||||
admins.add(admin);
|
admins.add(admin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAdmin(long admin) { return admins.contains(admin); }
|
||||||
|
|
||||||
public void request(Task task) {
|
public void request(Task task) {
|
||||||
async.enque(task);
|
async.enque(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestAsync(String request, String parameter) {
|
public void requestAsync(String request, String parameter, long userid) {
|
||||||
this.async.enque(request, parameter);
|
this.async.enque(request, parameter, userid);
|
||||||
}
|
|
||||||
|
|
||||||
public JSONObject request(String request, String parameter) throws IOException {
|
|
||||||
return request(request, parameter, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject request(String request, String parameter, boolean logging) throws IOException {
|
public JSONObject request(String request, String parameter, long userid) throws IOException {
|
||||||
|
return request(request, parameter, userid,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject request(String request, String parameter, long userid, boolean logging) throws IOException {
|
||||||
//do https stuff
|
//do https stuff
|
||||||
URL url = new URL(API_URL + apikey + "/" + request);
|
boolean toomany = true; //für retry after 429 error
|
||||||
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
|
int trycount = 0;
|
||||||
con.setDoInput(true);
|
while(toomany) {
|
||||||
con.setDoOutput(true);
|
toomany = false;
|
||||||
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
|
++trycount;
|
||||||
wr.write(parameter);
|
URL url = new URL(apiurl + "/" + request);
|
||||||
wr.flush();
|
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||||
|
con.setDoInput(true);
|
||||||
|
con.setDoOutput(true);
|
||||||
|
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
|
||||||
|
wr.write(parameter);
|
||||||
|
wr.flush();
|
||||||
|
|
||||||
if(logging) {
|
if (logging) {
|
||||||
String small = parameter;
|
String small = parameter;
|
||||||
if(small.length() > 60) {
|
if (small.length() > 60) {
|
||||||
small = small.substring(0, Math.min(60, small.length())) + "...";
|
small = small.substring(0, Math.min(60, small.length())) + "...";
|
||||||
|
}
|
||||||
|
log.log("request: " + request + " content " + small + " -> " + con.getResponseCode() + " " + con.getResponseMessage());
|
||||||
}
|
}
|
||||||
log.log("request: " + request + " content " + small + " -> " + con.getResponseCode() + ", " + con.getResponseMessage());
|
int response = con.getResponseCode();
|
||||||
}
|
if (response == 200) {
|
||||||
|
return new JSONObject(readfromIS(con.getInputStream()));
|
||||||
|
} else {
|
||||||
|
String errdesc = "[No description available]";
|
||||||
|
try {
|
||||||
|
//try to read error message
|
||||||
|
JSONObject returned = new JSONObject(readfromIS(con.getErrorStream()));
|
||||||
|
errdesc = returned.getString("description");
|
||||||
|
} catch (Throwable ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
if(con.getResponseCode() == 200) {
|
log.log("Request failed error: \"" + errdesc + "\" detailed request: " + request + "?" + parameter);
|
||||||
return new JSONObject(readfromIS(con.getInputStream()));
|
|
||||||
} else {
|
//catch 429 too many error
|
||||||
String errdesc = "[No description available]";
|
if (response == 429) {
|
||||||
try {
|
if(trycount < 10) toomany = true;
|
||||||
//try to read error message
|
|
||||||
JSONObject returned = new JSONObject(readfromIS(con.getErrorStream()));
|
//try to read timeout
|
||||||
errdesc = returned.getString("description");
|
//too Many Requests: retry after 19
|
||||||
} catch(Throwable ignore) { }
|
int timeout = 10;
|
||||||
throw new APIError(parameter, request, con.getResponseCode(), null, errdesc);
|
int idx = errdesc.lastIndexOf(" ");
|
||||||
//throw new IOException("API request returned HTTP " + con.getResponseCode() + " (" + con.getResponseMessage() + ") for action " + request + "\nurl: " + url.toString() + "\nparams: " + parameter + "\nerror description: " + errdesc);
|
try {
|
||||||
|
timeout = Integer.parseInt(errdesc.substring(idx))+1;
|
||||||
|
log.log("timeout read: " + timeout);
|
||||||
|
} catch(NumberFormatException | StringIndexOutOfBoundsException e ) {}
|
||||||
|
try {
|
||||||
|
log.log("Got 429 -> sleep for " + timeout + " seconds");
|
||||||
|
Thread.sleep(timeout * 1000);
|
||||||
|
} catch(InterruptedException e) {}
|
||||||
|
|
||||||
|
if(trycount < 10) continue;
|
||||||
|
} else if(response == 403) {
|
||||||
|
if(errdesc.equals("Forbidden: bot was blocked by the user")) {
|
||||||
|
if(userid != 0)
|
||||||
|
evntmgr.callEvent(new UserBlockedBotEvent(getUser(userid)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new APIError(parameter, request, con.getResponseCode(), null, errdesc);
|
||||||
|
//throw new IOException("API request returned HTTP " + con.getResponseCode() + " (" + con.getResponseMessage() + ") for action " + request + "\nurl: " + url.toString() + "\nparams: " + parameter + "\nerror description: " + errdesc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//unreachable code?
|
||||||
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String readfromIS(InputStream is) {
|
protected String readfromIS(InputStream is) {
|
||||||
|
@ -177,7 +222,7 @@ public class TelegramAPI implements Runnable {
|
||||||
s.close();
|
s.close();
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendAsync(long chatid, String msg) {
|
public void sendAsync(long chatid, String msg) {
|
||||||
sendMessage(new MessageBuilder().setAsync().setReciver(chatid).setText(msg).build());
|
sendMessage(new MessageBuilder().setAsync().setReciver(chatid).setText(msg).build());
|
||||||
}
|
}
|
||||||
|
@ -195,11 +240,11 @@ public class TelegramAPI implements Runnable {
|
||||||
AsyncSendable asyncm = (AsyncSendable) msg;
|
AsyncSendable asyncm = (AsyncSendable) msg;
|
||||||
Callback<JSONObject, TMessage> adapter = getCallbackAdapter(this);
|
Callback<JSONObject, TMessage> adapter = getCallbackAdapter(this);
|
||||||
adapter.next = asyncm.callback;
|
adapter.next = asyncm.callback;
|
||||||
Task t = new Task(msg.getCommand(), msg.getQ(), adapter);
|
Task t = new Task(msg.getCommand(), msg.getQ(), msg.getUserid(), adapter);
|
||||||
t.setExceptionhandl(asyncm.excpt == null ? IOE400supressor : asyncm.excpt);
|
t.setExceptionhandl(asyncm.excpt == null ? IOE400supressor : asyncm.excpt);
|
||||||
async.enque(t);
|
async.enque(t, asyncm.isSlow, asyncm.prio);
|
||||||
} else {
|
} else {
|
||||||
JSONObject o = request(msg.getCommand(), msg.getQ(), true);
|
JSONObject o = request(msg.getCommand(), msg.getQ(), msg.getUserid(), true);
|
||||||
return new TMessage(o.getJSONObject("result"), this);
|
return new TMessage(o.getJSONObject("result"), this);
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
|
@ -208,6 +253,68 @@ public class TelegramAPI implements Runnable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is always async
|
||||||
|
* @param cmds cmdname -> description
|
||||||
|
*/
|
||||||
|
public void setBotCommand(Map<String, String> cmds) {
|
||||||
|
//build json obj
|
||||||
|
JSONArray arr = cmds.entrySet().stream().map(e -> new JSONObject().put("command", e.getKey()).put("description", e.getKey())).collect(new Collector<JSONObject, JSONArray, JSONArray>() {
|
||||||
|
@Override
|
||||||
|
public Supplier<JSONArray> supplier() {
|
||||||
|
return JSONArray::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiConsumer<JSONArray, JSONObject> accumulator() {
|
||||||
|
return JSONArray::put;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BinaryOperator<JSONArray> combiner() {
|
||||||
|
return (a,b) -> { b.forEach(a::put); return b; };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function<JSONArray, JSONArray> finisher() {
|
||||||
|
return a -> a;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Characteristics> characteristics() {
|
||||||
|
Set<Characteristics> c = new HashSet<>();
|
||||||
|
c.add(IDENTITY_FINISH);
|
||||||
|
c.add(UNORDERED);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//commit
|
||||||
|
Task t = new Task("setMyCommands", "commands=" + arr.toString(), 0, null);
|
||||||
|
async.enque(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFeedbackCallback(Function<TUser, String> clb) {
|
||||||
|
if(!disableFeedback && feedbackCmd != null)
|
||||||
|
feedbackCmd.setFeedbackCallback(clb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TFile getFile(final String fileid) throws IOException {
|
||||||
|
JSONObject jfile = request("getFile", "file_id=" + fileid, 0);
|
||||||
|
return new TFile(jfile.getJSONObject("result"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getFile(final String fileid, Consumer<TFile> callback) {
|
||||||
|
async.enque(new Task("getFile", "file_id=" + fileid, 0, new Callback<JSONObject, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call(JSONObject j) throws Throwable {
|
||||||
|
TFile file = new TFile(j.getJSONObject("result"));
|
||||||
|
callback.accept(file);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}), true, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void sendTypedMessage(final String msg, final TUser user, final int seconds) {
|
public void sendTypedMessage(final String msg, final TUser user, final int seconds) {
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -220,7 +327,7 @@ public class TelegramAPI implements Runnable {
|
||||||
sendMessage(new MessageBuilder().setText(msg).setReciver(user.getID()).build());
|
sendMessage(new MessageBuilder().setText(msg).setReciver(user.getID()).build());
|
||||||
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void answerCallbackQuery(String callbackid, String text, boolean async) {
|
public void answerCallbackQuery(String callbackid, String text, boolean async) {
|
||||||
|
@ -228,10 +335,10 @@ public class TelegramAPI implements Runnable {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(async) {
|
if(async) {
|
||||||
requestAsync("answerCallbackQuery", "callback_query_id=" + callbackid + "&text=" + text);
|
requestAsync("answerCallbackQuery", "callback_query_id=" + callbackid + "&text=" + text, 0);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
request("answerCallbackQuery", "callback_query_id=" + callbackid + "&text=" + text);
|
request("answerCallbackQuery", "callback_query_id=" + callbackid + "&text=" + text, 0);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -254,7 +361,7 @@ public class TelegramAPI implements Runnable {
|
||||||
rply = "&reply_markup=" + URLEncoder.encode(rm.toJSONString(), "UTF-8");
|
rply = "&reply_markup=" + URLEncoder.encode(rm.toJSONString(), "UTF-8");
|
||||||
String q = "chat_id=" + chatid + "&message_id=" + msg_id + "&caption=" + URLEncoder.encode(newCaption, "UTF-8") + rply;
|
String q = "chat_id=" + chatid + "&message_id=" + msg_id + "&caption=" + URLEncoder.encode(newCaption, "UTF-8") + rply;
|
||||||
if(async) {
|
if(async) {
|
||||||
Task t = new Task("editMessageCaption", q);
|
Task t = new Task("editMessageCaption", q, chatid);
|
||||||
t.setExceptionhandl(new Callback<Throwable, Void>() {
|
t.setExceptionhandl(new Callback<Throwable, Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void call(Throwable j) throws Throwable {
|
public Void call(Throwable j) throws Throwable {
|
||||||
|
@ -270,7 +377,7 @@ public class TelegramAPI implements Runnable {
|
||||||
});
|
});
|
||||||
this.async.enque(t);
|
this.async.enque(t);
|
||||||
} else {
|
} else {
|
||||||
request("editMessageCaption", q);
|
request("editMessageCaption", q, chatid);
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
log.log("", e);
|
log.log("", e);
|
||||||
|
@ -280,32 +387,25 @@ public class TelegramAPI implements Runnable {
|
||||||
public void updateMarkup(long chatid, int msg_id, TReplyMarkup rm, boolean async) {
|
public void updateMarkup(long chatid, int msg_id, TReplyMarkup rm, boolean async) {
|
||||||
try {
|
try {
|
||||||
if(rm == null) return;//nope
|
if(rm == null) return;//nope
|
||||||
|
|
||||||
String q = "chat_id=" + chatid + "&message_id=" + msg_id + "&reply_markup=" + URLEncoder.encode(rm.toJSONString(), "UTF-8");
|
String q = "chat_id=" + chatid + "&message_id=" + msg_id + "&reply_markup=" + URLEncoder.encode(rm.toJSONString(), "UTF-8");
|
||||||
|
|
||||||
if(async) {
|
if(async) {
|
||||||
this.async.enque("editMessageReplyMarkup", q);
|
this.async.enque("editMessageReplyMarkup", q, chatid);
|
||||||
} else {
|
} else {
|
||||||
request("editMessageReplyMarkup", q);
|
request("editMessageReplyMarkup", q, chatid);
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
log.log("", e);
|
log.log("", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
run = false;
|
run = false;
|
||||||
|
if(thread == null) return;
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
Thread.yield();//try to not get into that loop
|
|
||||||
while(isRunning()) {
|
|
||||||
thread.interrupt();
|
|
||||||
Thread.yield();
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
} catch(InterruptedException e) {}
|
|
||||||
}
|
|
||||||
log.log("tapi stoped.");
|
|
||||||
thread = null;
|
thread = null;
|
||||||
|
log.log("TelegramAPI stoped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -338,12 +438,12 @@ public class TelegramAPI implements Runnable {
|
||||||
|
|
||||||
private void fetchUpdates() {
|
private void fetchUpdates() {
|
||||||
try {
|
try {
|
||||||
processUpdates(request("getUpdates", "offset=" + msg_offset + "&timeout=" + (longpolling ? updateInterval : 1), false));
|
processUpdates(request("getUpdates", "offset=" + msg_offset + "&timeout=" + (longpolling ? updateInterval : 1), 0,false));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.log("error getting updates.", e);
|
log.log("error getting updates.", e);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(e instanceof ConnectException ? 10000 : 500);
|
||||||
} catch(InterruptedException ignored) {}
|
} catch(InterruptedException ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,23 +460,27 @@ public class TelegramAPI implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TUser getUser(String name) {
|
public TUser getUser(String name) {
|
||||||
for(TUser us : users) {
|
for(TUser us : users.values()) {
|
||||||
if(us.getName().equals(name))
|
if(us.getName().equals(name))
|
||||||
return us;
|
return us;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TUser getUser(int id) {
|
public TUser getUser(long id, boolean createIfNotExitsts) {
|
||||||
for(TUser us : users) {
|
TUser u = users.get(id);
|
||||||
if(us.getID() == id)
|
if(u != null || !createIfNotExitsts)
|
||||||
return us;
|
return u;
|
||||||
}
|
u = new TUser(id, this);
|
||||||
TUser u = new TUser(id, this);
|
evntmgr.callEvent(new NewUserEvent(u));
|
||||||
users.add(u);
|
users.put(id, u);
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TUser getUser(long id) {
|
||||||
|
return getUser(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets a user by id from the known user lists,
|
* gets a user by id from the known user lists,
|
||||||
* if no user found, it creates a new User and adds it to the list.
|
* if no user found, it creates a new User and adds it to the list.
|
||||||
|
@ -384,12 +488,12 @@ public class TelegramAPI implements Runnable {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public TUser getUser(JSONObject json) {
|
public TUser getUser(JSONObject json) {
|
||||||
int id = json.getInt("id");
|
long id = json.getLong("id");
|
||||||
TUser user = getUser(id);
|
TUser user = getUser(id, false);
|
||||||
if(user != null)
|
if(user != null)
|
||||||
return user;
|
return user;
|
||||||
user = new TUser(json, this);
|
user = new TUser(json, this);
|
||||||
users.add(user);
|
users.put(id, user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,9 +521,9 @@ public class TelegramAPI implements Runnable {
|
||||||
public EventManager getEventManager() {
|
public EventManager getEventManager() {
|
||||||
return evntmgr;
|
return evntmgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* seconds to wait for longpolling or milliseconds to wait petween shortpolling
|
* seconds to wait for longpolling or milliseconds to wait between shortpolling
|
||||||
* @param d
|
* @param d
|
||||||
*/
|
*/
|
||||||
public void setUpdateInterval(int d) {
|
public void setUpdateInterval(int d) {
|
||||||
|
@ -445,7 +549,7 @@ public class TelegramAPI implements Runnable {
|
||||||
public static boolean isSendable(long filesize) {
|
public static boolean isSendable(long filesize) {
|
||||||
return filesize < TELEGRAMFILESIZELIMIT;
|
return filesize < TELEGRAMFILESIZELIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Callback<JSONObject, TMessage> getCallbackAdapter(TelegramAPI api) {
|
public static Callback<JSONObject, TMessage> getCallbackAdapter(TelegramAPI api) {
|
||||||
return new Callback<JSONObject, TMessage>() {
|
return new Callback<JSONObject, TMessage>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -458,7 +562,6 @@ public class TelegramAPI implements Runnable {
|
||||||
protected class TelegramAPIUpdate {
|
protected class TelegramAPIUpdate {
|
||||||
protected int update_id = 0;
|
protected int update_id = 0;
|
||||||
private TMessage msg = null;
|
private TMessage msg = null;
|
||||||
private boolean isCommand = false;
|
|
||||||
|
|
||||||
protected TelegramAPIUpdate(JSONObject json, TelegramAPI api) {
|
protected TelegramAPIUpdate(JSONObject json, TelegramAPI api) {
|
||||||
update_id = json.getInt("update_id");
|
update_id = json.getInt("update_id");
|
||||||
|
@ -468,9 +571,8 @@ public class TelegramAPI implements Runnable {
|
||||||
|
|
||||||
String text = msg.getText();
|
String text = msg.getText();
|
||||||
if(text != null) {
|
if(text != null) {
|
||||||
if(text.matches("^\\/(\\w*)(@(\\w*))?")) {
|
if(text.matches("^\\/(\\w+)(@(\\w+))?(\\s.*)?")) { //is a command
|
||||||
text = text.substring(1);//remove '/'
|
text = text.substring(1);//remove '/'
|
||||||
isCommand = true;
|
|
||||||
if(text.contains("@")) {//check name
|
if(text.contains("@")) {//check name
|
||||||
int at = text.indexOf('@');
|
int at = text.indexOf('@');
|
||||||
int end = text.indexOf(' ', at+1);
|
int end = text.indexOf(' ', at+1);
|
||||||
|
@ -485,56 +587,58 @@ public class TelegramAPI implements Runnable {
|
||||||
cmdmgr.onCommand(text, msg.getFrom(), msg);
|
cmdmgr.onCommand(text, msg.getFrom(), msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Event e = null;
|
Event e = new UserSendMessageEvent(msg);
|
||||||
if(getMsg().has(Member.audio)) {
|
//call feedback cmd first
|
||||||
e = new UserSendAudioEvent(getUser(), new TAudio((JSONObject) getMsg().get(Member.audio)));
|
if(!disableFeedback) {
|
||||||
} else if(getMsg().has(Member.video)) {
|
if (feedbackCmd.onMsg((UserSendMessageEvent) e)) {
|
||||||
|
e = null;
|
||||||
} else if(getMsg().has(Member.document)) {
|
}
|
||||||
|
|
||||||
} else if(getMsg().has(Member.invoice)) {
|
|
||||||
|
|
||||||
} else if(getMsg().has(Member.location)) {
|
|
||||||
|
|
||||||
} else if(getMsg().has(Member.video_note)) {
|
|
||||||
|
|
||||||
} else if(getMsg().has(Member.game)) {
|
|
||||||
|
|
||||||
} else if(getMsg().has(Member.contact)) {
|
|
||||||
|
|
||||||
} else if(getMsg().has(Member.sticker)) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
e = new UserSendMessageEvent(getMsg());
|
|
||||||
}
|
}
|
||||||
getEventManager().callEvent(e);
|
getEventManager().callEvent(e);
|
||||||
|
return; //do not process other events
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event e = null;
|
||||||
|
//process media events
|
||||||
|
if(msg.has(Member.audio)) {
|
||||||
|
e = new UserSendAudioEvent(msg);
|
||||||
|
} else if(msg.has(Member.video)) {
|
||||||
|
//TODO
|
||||||
|
} else if(msg.has(Member.document)) {
|
||||||
|
e = new UserSendDocumentEvent(msg);
|
||||||
|
} else if(msg.has(Member.photo)) {
|
||||||
|
e = new UserSendPhotoEvent(msg);
|
||||||
|
} else if(msg.has(Member.invoice)) {
|
||||||
|
//TODO
|
||||||
|
} else if(msg.has(Member.location)) {
|
||||||
|
//TODO
|
||||||
|
} else if(msg.has(Member.video_note)) {
|
||||||
|
//TODO
|
||||||
|
} else if(msg.has(Member.game)) {
|
||||||
|
//TODO
|
||||||
|
} else if(msg.has(Member.contact)) {
|
||||||
|
//TODO
|
||||||
|
} else if(msg.has(Member.sticker)) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
getEventManager().callEvent(e);
|
||||||
} else if(json.has("callback_query")) {
|
} else if(json.has("callback_query")) {
|
||||||
JSONObject cbq = json.getJSONObject("callback_query");
|
JSONObject cbq = json.getJSONObject("callback_query");
|
||||||
TUser from = api.getUser(cbq.getJSONObject("from"));
|
TUser from = api.getUser(cbq.getJSONObject("from"));
|
||||||
String data = cbq.getString("data");
|
String data = cbq.getString("data");
|
||||||
String id = cbq.getString("id");
|
String id = cbq.getString("id");
|
||||||
TMessage msg = new TMessage(cbq.getJSONObject("message"), api);
|
TMessage msg = new TMessage(cbq.getJSONObject("message"), api);
|
||||||
getEventManager().callEvent(new UserCallbackEvent(from, data, id, msg));
|
UserCallbackEvent event = new UserCallbackEvent(from, data, id, msg);
|
||||||
|
|
||||||
|
if(!disableFeedback) {
|
||||||
|
if (!feedbackCmd.onCallback(event))
|
||||||
|
getEventManager().callEvent(event);
|
||||||
|
} else {
|
||||||
|
getEventManager().callEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getUpdate_id() {
|
|
||||||
return update_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TMessage getMsg() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TUser getUser() {
|
|
||||||
return msg.getFrom();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isCommand() {
|
|
||||||
return isCommand;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum JSONObjectType {
|
public enum JSONObjectType {
|
||||||
|
@ -561,7 +665,7 @@ public class TelegramAPI implements Runnable {
|
||||||
|
|
||||||
public class APIError extends IOException {
|
public class APIError extends IOException {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
String params;
|
String params;
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
package de.mrbesen.telegram;
|
package de.mrbesen.telegram;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
|
import com.sun.net.httpserver.HttpServer;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
|
||||||
import com.sun.net.httpserver.HttpHandler;
|
|
||||||
import com.sun.net.httpserver.HttpServer;
|
|
||||||
|
|
||||||
//for https server: https://stackoverflow.com/questions/2308479/simple-java-https-server
|
//for https server: https://stackoverflow.com/questions/2308479/simple-java-https-server
|
||||||
//for jks store: https://stackoverflow.com/questions/2138940/import-pem-into-java-key-store
|
//for jks store: https://stackoverflow.com/questions/2138940/import-pem-into-java-key-store
|
||||||
public class WebhookTelegramAPI extends TelegramAPI implements HttpHandler {
|
public class WebhookTelegramAPI extends TelegramAPI implements HttpHandler {
|
||||||
|
@ -47,7 +46,7 @@ public class WebhookTelegramAPI extends TelegramAPI implements HttpHandler {
|
||||||
if(externaladdr.endsWith("/"))
|
if(externaladdr.endsWith("/"))
|
||||||
externaladdr = externaladdr.substring(0, externaladdr.length()-1);
|
externaladdr = externaladdr.substring(0, externaladdr.length()-1);
|
||||||
|
|
||||||
request("setWebhook", "url=" + externaladdr + "/" + pw + "&allowed_updates=" + allowedupd);
|
request("setWebhook", "url=" + externaladdr + "/" + pw + "&allowed_updates=" + allowedupd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebhookTelegramAPI(String apikey, String externaladdr) throws IOException {
|
public WebhookTelegramAPI(String apikey, String externaladdr) throws IOException {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class CommandManager {
|
||||||
try {
|
try {
|
||||||
if(cmdhand instanceof JSONCommandHandler) {
|
if(cmdhand instanceof JSONCommandHandler) {
|
||||||
result = ((JSONCommandHandler) cmdhand).onCommand(sender, cmd, args, json);
|
result = ((JSONCommandHandler) cmdhand).onCommand(sender, cmd, args, json);
|
||||||
} else if( cmdhand instanceof CommandHandler){
|
} else if( cmdhand instanceof CommandHandler) {
|
||||||
result = ((CommandHandler) cmdhand).onCommand(sender, cmd, args);
|
result = ((CommandHandler) cmdhand).onCommand(sender, cmd, args);
|
||||||
}
|
}
|
||||||
if(result)
|
if(result)
|
||||||
|
@ -53,13 +53,14 @@ public class CommandManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerCommand(ICommandHandler handler) {
|
public void registerCommand(ICommandHandler handler) {
|
||||||
registerCommand(null, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerCommand(String cmd, ICommandHandler handler) {
|
|
||||||
if(handler == null) {
|
if(handler == null) {
|
||||||
throw new NullPointerException("handler is not allowed to be null");
|
throw new NullPointerException("handler is not allowed to be null");
|
||||||
}
|
}
|
||||||
handlerlist.add(handler);
|
handlerlist.add(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void registerCommand(String cmd, ICommandHandler handler) {
|
||||||
|
registerCommand(handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package de.mrbesen.telegram.commands;
|
package de.mrbesen.telegram.commands;
|
||||||
|
|
||||||
import com.sun.istack.internal.Nullable;
|
|
||||||
import de.mrbesen.telegram.AsyncHandler;
|
import de.mrbesen.telegram.AsyncHandler;
|
||||||
import de.mrbesen.telegram.MessageBuilder;
|
import de.mrbesen.telegram.MessageBuilder;
|
||||||
import de.mrbesen.telegram.TelegramAPI;
|
import de.mrbesen.telegram.TelegramAPI;
|
||||||
|
@ -9,37 +8,43 @@ import de.mrbesen.telegram.event.events.UserSendMessageEvent;
|
||||||
import de.mrbesen.telegram.objects.TInlineKeyboardMarkup;
|
import de.mrbesen.telegram.objects.TInlineKeyboardMarkup;
|
||||||
import de.mrbesen.telegram.objects.TMessage;
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class FeedbackCommand implements JSONCommandHandler {
|
public class FeedbackCommand implements JSONCommandHandler {
|
||||||
|
|
||||||
protected final TInlineKeyboardMarkup cancel = new TInlineKeyboardMarkup(1);
|
protected final TInlineKeyboardMarkup cancelMarkup = TInlineKeyboardMarkup.makeSingleButton("❌ cancel", CANCELFEEDBACK);
|
||||||
protected final Map<Long, TMessage> awaitingFeedback = new TreeMap<>(); //maps users chat id -> message that said "please send feedback" TODO: make persistent?
|
protected final Map<Long, TMessage> awaitingFeedback = new TreeMap<>(); //maps users chat id -> message that said "please send feedback" TODO: make persistent?
|
||||||
|
protected final Map<Long, Long[]> answer = new TreeMap<>(); // chatid -> [chatid, messageid] to answer to; next message from key will be fwd to value[0] and reply to value[1]
|
||||||
protected final TelegramAPI api;
|
protected final TelegramAPI api;
|
||||||
protected final Collection<Long> admins;
|
protected final List<Long> admins;
|
||||||
protected final static String CANCELFEEDBACK = "cancelfeedback", REPLYFEEDBACK = "replyFeedback ";
|
protected final static String CANCELFEEDBACK = "cancelfeedback", REPLYFEEDBACK = "replyFeedback ";
|
||||||
|
@Setter
|
||||||
|
private Function<TUser, String> feedbackCallback = null;
|
||||||
|
|
||||||
|
|
||||||
public FeedbackCommand(TelegramAPI api, Collection<Long> admins) {
|
public FeedbackCommand(TelegramAPI api, List<Long> admins) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.admins = admins;
|
this.admins = (admins == null ? new LinkedList<>() : admins);
|
||||||
//build markup
|
|
||||||
cancel.addCallbackButton("❌ cancel", CANCELFEEDBACK, 0);
|
|
||||||
api.getEventManager().registerEvent(UserSendMessageEvent.class, this::onMsg);
|
|
||||||
api.getEventManager().registerEvent(UserCallbackEvent.class, this::onCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(TUser sender, String cmd, String[] args, TMessage json) {
|
public boolean onCommand(TUser sender, String cmd, String[] args, TMessage json) {
|
||||||
|
if(json.getChatID() < 0) return false; //do not handle group chats
|
||||||
|
|
||||||
if(cmd.equalsIgnoreCase("feedback")) {
|
if(cmd.equalsIgnoreCase("feedback")) {
|
||||||
removeMsg(sender.getID(), null);
|
removeMsg(sender.getID(), null);
|
||||||
awaitingFeedback.put(sender.getID(), null);
|
awaitingFeedback.put(sender.getID(), null);
|
||||||
MessageBuilder mb = new MessageBuilder();
|
MessageBuilder mb = new MessageBuilder();
|
||||||
mb.setAsync().setMarkup(cancel).setText("Your next Message will be forwarded to the admins.")
|
mb.setAsync().setReciver(sender).setMarkup(cancelMarkup).setText("Your next message will be forwarded to the admins.")
|
||||||
.setCallback(new AsyncHandler.Callback<TMessage, Object>() {
|
.setCallback(new AsyncHandler.Callback<TMessage, Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object call(TMessage msg) throws Throwable {
|
public Object call(TMessage msg) {
|
||||||
awaitingFeedback.put(sender.getID(), msg);
|
awaitingFeedback.put(sender.getID(), msg);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -50,48 +55,108 @@ public class FeedbackCommand implements JSONCommandHandler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onMsg(Object event) {
|
public boolean onMsg(UserSendMessageEvent e) {
|
||||||
UserSendMessageEvent e = (UserSendMessageEvent) event;
|
|
||||||
TUser user = e.getUser();
|
TUser user = e.getUser();
|
||||||
TMessage msg = e.getMessage();
|
TMessage msg = e.getMsg();
|
||||||
if(isFeedback(msg.getText())) {
|
if (awaitingFeedback.containsKey(user.getID())) { //user send a feedback
|
||||||
if (awaitingFeedback.containsKey(user.getID())) {
|
removeMsg(user.getID(), e.getMsg());
|
||||||
removeMsg(user.getID(), e.getMessage());
|
if(isFeedback(msg.getText())) {
|
||||||
|
|
||||||
//fwd to admins
|
//fwd to admins
|
||||||
admins.forEach(a -> TMessage.forwardAsync(api, a, msg));
|
admins.forEach(a -> TMessage.forwardAsync(api, a, msg));
|
||||||
|
|
||||||
StringBuilder info = new StringBuilder("Feedbackinfo:\n");
|
MessageBuilder mb = createInfo(user, msg.getMessageID(), true);
|
||||||
info.append("userid: ").append(user.getID());
|
admins.forEach(a -> api.sendMessage(mb.setReciver(a).build()));
|
||||||
info.append("\nusername: ").append(user.getName());
|
} else {
|
||||||
info.append("\nfullname: ").append(user.getFirstName()).append(' ').append(user.getLastName());
|
System.out.println("feedback omitted: " + msg.getText());
|
||||||
TInlineKeyboardMarkup markup = new TInlineKeyboardMarkup(1);
|
}
|
||||||
markup.addUrlButton("chat with user", "tg://" + user.getName(), 1);
|
return true;
|
||||||
markup.addCallbackButton("reply ↩", REPLYFEEDBACK + user.getID() + " " + msg.getMessageID(), 1);
|
} else { //reply to a message
|
||||||
admins.forEach(a -> api.sendAsync(a, info.toString()));
|
Long[] rplymsg = answer.remove(user.getID());
|
||||||
|
if(rplymsg != null) {
|
||||||
|
if(admins.contains(user.getID())) {
|
||||||
|
System.out.println("admin answered feedback!");
|
||||||
|
//admin to user -> copy text send as new msg from bot to disguise admin
|
||||||
|
TInlineKeyboardMarkup mu = new TInlineKeyboardMarkup(1);
|
||||||
|
mu.addCallbackButton("↩ reply", buildRplyCallback(user.getID(), msg.getMessageID()), 1);
|
||||||
|
|
||||||
|
MessageBuilder mb = new MessageBuilder().setAsync().setReciver(rplymsg[0])
|
||||||
|
.setReplyTo(Math.toIntExact(rplymsg[1])).setText(msg.getText()).setMarkup(mu);
|
||||||
|
api.sendMessage(mb.build());
|
||||||
|
} else {
|
||||||
|
System.out.println("user answered feedback!");
|
||||||
|
//user to admin -> fwd message
|
||||||
|
TMessage.forwardAsync(api, rplymsg[0], msg);
|
||||||
|
|
||||||
|
//send info
|
||||||
|
MessageBuilder mb = createInfo(user, msg.getMessageID(), false);
|
||||||
|
api.sendMessage(mb.setReciver(rplymsg[0]).setReplyTo(Math.toIntExact(rplymsg[1])).build());
|
||||||
|
}
|
||||||
|
System.out.println("Feedback reply from " + user.getID() + " to " + rplymsg[0] + ":" + rplymsg[1] + " send.");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCallback(Object event) {
|
protected MessageBuilder createInfo(TUser u, int msgid, boolean firstmsg) {
|
||||||
UserCallbackEvent e = (UserCallbackEvent) event;
|
String info = "Feedbackinfo:\n" + "userid: " + u.getID() + "\nusername: " + u.getName() + "\nfullname: " + u.getFirstName() + ' ' + u.getLastName();
|
||||||
|
|
||||||
|
MessageBuilder mb = new MessageBuilder().setAsync();
|
||||||
|
|
||||||
|
if(firstmsg && feedbackCallback != null) {
|
||||||
|
try {
|
||||||
|
info += '\n' + feedbackCallback.apply(u);
|
||||||
|
mb.setNoWebView(true);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
info += "\nError getting information: " + t.getMessage();
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TInlineKeyboardMarkup markup = new TInlineKeyboardMarkup(1);
|
||||||
|
markup.addUrlButton("chat with user", "https://t.me/" + u.getName(), 1);
|
||||||
|
markup.addCallbackButton("↩ reply", buildRplyCallback(u.getID(), msgid), 1);
|
||||||
|
return mb.setText(info).setFormatting(MessageBuilder.Formatting.HTML).setMarkup(markup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onCallback(UserCallbackEvent e) {
|
||||||
if(e.getData().equals(CANCELFEEDBACK)) {
|
if(e.getData().equals(CANCELFEEDBACK)) {
|
||||||
removeMsg(e.getUser().getID(), e.getMsg());
|
removeMsg(e.getUser().getID(), e.getMsg());
|
||||||
api.answerCallbackQuery(e.getID(), "Cancelled", true);
|
api.answerCallbackQuery(e.getID(), "Cancelled", true);
|
||||||
|
return true;
|
||||||
} else if(e.getData().startsWith(REPLYFEEDBACK)) {
|
} else if(e.getData().startsWith(REPLYFEEDBACK)) {
|
||||||
String rest = e.getData().substring(REPLYFEEDBACK.length());
|
String rest = e.getData().substring(REPLYFEEDBACK.length());
|
||||||
//TODO
|
long chatid = 0;
|
||||||
|
long msgid = -1;
|
||||||
|
try {
|
||||||
|
String[] spl = rest.split(" ",2);
|
||||||
|
long adminid = Long.parseLong(spl[0]);
|
||||||
|
msgid = Integer.parseInt(spl[1]);
|
||||||
|
//convert admin id to chat id
|
||||||
|
if(adminid <= 0) {
|
||||||
|
chatid = admins.get((int) -adminid);
|
||||||
|
} else
|
||||||
|
chatid = adminid;
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
api.answerCallbackQuery(e.getID(), "Error. Sorry :/", true);
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
if(msgid > -1) {
|
||||||
|
answer.put(e.getUser().getID(), new Long[]{chatid, msgid});
|
||||||
|
api.answerCallbackQuery(e.getID(), "Write a Message", true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* looks up msg from awaiting feedback map, if not present try to use fallback_msg
|
* looks up msg from awaiting feedback map, if not present try to use fallback_msg
|
||||||
* is Async
|
* is Async
|
||||||
* removes user from awaitingFeedback
|
* removes user from awaitingFeedback
|
||||||
* @param chat
|
*
|
||||||
* @param fallback_msg
|
|
||||||
*/
|
*/
|
||||||
protected void removeMsg(long chat, @Nullable TMessage fallback_msg) {
|
protected void removeMsg(long chat, TMessage fallback_msg) {
|
||||||
TMessage msg = awaitingFeedback.remove(chat);
|
TMessage msg = awaitingFeedback.remove(chat);
|
||||||
if(msg == null) msg = fallback_msg;
|
if(msg == null) msg = fallback_msg;
|
||||||
|
|
||||||
|
@ -105,6 +170,20 @@ public class FeedbackCommand implements JSONCommandHandler {
|
||||||
*/
|
*/
|
||||||
protected boolean isFeedback(String msg) {
|
protected boolean isFeedback(String msg) {
|
||||||
msg = msg.trim();
|
msg = msg.trim();
|
||||||
return !msg.startsWith("/") && msg.length() > 5 && !msg.startsWith("http");
|
return (!msg.startsWith("/")) && (msg.length() > 5) && (!msg.startsWith("http"));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getAdminID(long adminchat) {
|
||||||
|
for(int i = 0; i < admins.size(); i++) {
|
||||||
|
if(admins.get(i) == adminchat)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildRplyCallback(long user, int msgid) {
|
||||||
|
int adminid = getAdminID(user);
|
||||||
|
if(adminid >= 0) user = -adminid;
|
||||||
|
return REPLYFEEDBACK + user + " " + msgid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,5 @@
|
||||||
package de.mrbesen.telegram.event;
|
package de.mrbesen.telegram.event;
|
||||||
|
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
public interface Event {
|
||||||
|
|
||||||
public class Event {
|
|
||||||
|
|
||||||
private TUser user;
|
|
||||||
|
|
||||||
public Event(TUser u) {
|
|
||||||
user = u;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TUser getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,22 @@
|
||||||
package de.mrbesen.telegram.event;
|
package de.mrbesen.telegram.event;
|
||||||
|
|
||||||
import de.mrbesen.telegram.TelegramAPI;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class EventManager {
|
public class EventManager {
|
||||||
|
|
||||||
private HashMap<Class<? extends Event>, ArrayList<Consumer>> listeners = new HashMap<>();
|
private HashMap<Class<? extends Event>, ArrayList<Consumer<? extends Event>>> listeners = new HashMap<>();
|
||||||
|
|
||||||
public EventManager() {}
|
public EventManager() {}
|
||||||
|
|
||||||
public void registerEvent(Class<? extends Event> eventtype, Consumer handler) {
|
public <T extends Event> void registerEvent(Class<T> eventtype, Consumer<T> handler) {
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
|
|
||||||
//get list
|
//get list
|
||||||
ArrayList<Consumer> list = listeners.get(eventtype);
|
ArrayList<Consumer<? extends Event>> list = listeners.get(eventtype);
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
//create and add list
|
//create and add list
|
||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
|
@ -33,9 +29,9 @@ public class EventManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Event callEvent(Event e) {
|
public Event callEvent(Event e) {
|
||||||
if(e == null)
|
if(e == null) return null;
|
||||||
throw new NullPointerException("event is not allowed to be null!");
|
|
||||||
ArrayList<Consumer> listner = listeners.get(e.getClass());
|
ArrayList<Consumer<? extends Event>> listner = listeners.get(e.getClass());
|
||||||
if(listner != null) {
|
if(listner != null) {
|
||||||
for (Consumer listn : listner) {
|
for (Consumer listn : listner) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.event.Event;
|
||||||
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MessageEvent implements Event {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private TMessage msg;
|
||||||
|
|
||||||
|
public TUser getUser() {
|
||||||
|
return msg.getFrom();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* its not given that the user has never seen this bot, its just the first time since the last restart
|
||||||
|
*/
|
||||||
|
public class NewUserEvent extends UserEvent {
|
||||||
|
public NewUserEvent(TUser user) {
|
||||||
|
super(user);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
|
||||||
|
public class UserBlockedBotEvent extends UserEvent {
|
||||||
|
public UserBlockedBotEvent(TUser user) {
|
||||||
|
super(user);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,37 +1,30 @@
|
||||||
package de.mrbesen.telegram.event.events;
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import de.mrbesen.telegram.event.Event;
|
import de.mrbesen.telegram.event.Event;
|
||||||
import de.mrbesen.telegram.objects.TMessage;
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
|
||||||
public class UserCallbackEvent extends Event {
|
public class UserCallbackEvent extends MessageEvent {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final String data;
|
private final String data;
|
||||||
private final TMessage msg;
|
@Getter
|
||||||
private final String id;
|
private final String ID;
|
||||||
|
@Getter
|
||||||
|
private final TUser user;
|
||||||
|
|
||||||
public UserCallbackEvent(TUser u, String data, String id, TMessage msg) {
|
public UserCallbackEvent(TUser u, String data, String id, TMessage msg) {
|
||||||
super(u);
|
super(msg);
|
||||||
|
user = u;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.msg = msg;
|
this.ID = id;
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TMessage getMsg() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getData() {
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject asJSON() {
|
public JSONObject asJSON() {
|
||||||
return new JSONObject(data);
|
return new JSONObject(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.event.Event;
|
||||||
|
import de.mrbesen.telegram.objects.TUser;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserEvent implements Event {
|
||||||
|
@Getter
|
||||||
|
private final TUser user;
|
||||||
|
}
|
|
@ -1,19 +1,17 @@
|
||||||
package de.mrbesen.telegram.event.events;
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
import de.mrbesen.telegram.event.Event;
|
import de.mrbesen.telegram.objects.JSONBased;
|
||||||
import de.mrbesen.telegram.objects.TAudio;
|
import de.mrbesen.telegram.objects.TAudio;
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
public class UserSendAudioEvent extends Event {
|
public class UserSendAudioEvent extends MessageEvent {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private TAudio audio;
|
private TAudio audio;
|
||||||
|
|
||||||
public UserSendAudioEvent(TUser u, TAudio a) {
|
public UserSendAudioEvent(TMessage msg) {
|
||||||
super(u);
|
super(msg);
|
||||||
audio = a;
|
audio = new TAudio(msg.get(JSONBased.Member.audio));
|
||||||
}
|
|
||||||
|
|
||||||
public TAudio getAudio() {
|
|
||||||
return audio;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.objects.JSONBased;
|
||||||
|
import de.mrbesen.telegram.objects.TDocument;
|
||||||
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class UserSendDocumentEvent extends MessageEvent {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private TDocument document;
|
||||||
|
|
||||||
|
public UserSendDocumentEvent(TMessage msg) {
|
||||||
|
super(msg);
|
||||||
|
document = new TDocument(msg.get(JSONBased.Member.document));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +1,10 @@
|
||||||
package de.mrbesen.telegram.event.events;
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
import de.mrbesen.telegram.event.Event;
|
|
||||||
import de.mrbesen.telegram.objects.TMessage;
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
import de.mrbesen.telegram.objects.TUser;
|
|
||||||
|
|
||||||
public class UserSendMessageEvent extends Event {
|
public class UserSendMessageEvent extends MessageEvent {
|
||||||
|
|
||||||
private TMessage m;
|
|
||||||
|
|
||||||
public UserSendMessageEvent(TMessage m) {
|
public UserSendMessageEvent(TMessage m) {
|
||||||
super(m.getFrom());
|
super(m);
|
||||||
this.m = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TMessage getMessage() {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TUser getUser() {
|
|
||||||
return m.getFrom();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.mrbesen.telegram.event.events;
|
||||||
|
|
||||||
|
import de.mrbesen.telegram.objects.JSONBased;
|
||||||
|
import de.mrbesen.telegram.objects.TMessage;
|
||||||
|
import de.mrbesen.telegram.objects.TPhotoSize;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class UserSendPhotoEvent extends MessageEvent {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private TPhotoSize[] photos;
|
||||||
|
|
||||||
|
public UserSendPhotoEvent(TMessage msg) {
|
||||||
|
super(msg);
|
||||||
|
|
||||||
|
JSONArray pics = msg.get(JSONBased.Member.photo);
|
||||||
|
photos = new TPhotoSize[pics.length()];
|
||||||
|
for (int i = 0; i < pics.length(); i++) {
|
||||||
|
JSONObject pic = pics.getJSONObject(i);
|
||||||
|
photos[i] = new TPhotoSize(pic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,24 @@
|
||||||
package de.mrbesen.telegram.log;
|
package de.mrbesen.telegram.log;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class SimpleLog extends Log {
|
public class SimpleLog extends Log {
|
||||||
|
|
||||||
|
private PrintStream out = System.out;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void log(String msg) {
|
public void log(String msg) {
|
||||||
System.out.println(msg);
|
out.println(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void log(String msg, Throwable t) {
|
public void log(String msg, Throwable t) {
|
||||||
System.out.println(msg);
|
out.println(msg);
|
||||||
t.printStackTrace(System.out);
|
t.printStackTrace(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,8 @@ public class JSONBased {
|
||||||
|
|
||||||
//===== FILE =====
|
//===== FILE =====
|
||||||
file_path, // String
|
file_path, // String
|
||||||
|
file_id, // String
|
||||||
|
file_unique_id, //String
|
||||||
//===== END FILE =====
|
//===== END FILE =====
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TAudio extends TDocument {
|
public class TAudio extends TDocument {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private int duration;
|
private int duration;
|
||||||
|
|
||||||
public TAudio(JSONObject o) {
|
public TAudio(JSONObject o) {
|
||||||
|
@ -10,8 +13,4 @@ public class TAudio extends TDocument {
|
||||||
duration = o.getInt("duration");
|
duration = o.getInt("duration");
|
||||||
allowedmembers = new Member[] {Member.performer, Member.title, Member.mime_type, Member.file_size};
|
allowedmembers = new Member[] {Member.performer, Member.title, Member.mime_type, Member.file_size};
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDuration() {
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,6 @@ public class TDocument extends TSendable {
|
||||||
|
|
||||||
public TDocument(JSONObject o) {
|
public TDocument(JSONObject o) {
|
||||||
super(o);
|
super(o);
|
||||||
allowedmembers = new Member[] {Member.thumb, Member.file_name, Member.mime_type, Member.file_size};
|
allowedmembers = new Member[] {Member.file_id, Member.file_unique_id, Member.thumb, Member.file_name, Member.mime_type, Member.file_size};
|
||||||
}
|
|
||||||
|
|
||||||
public String getFile_id() {
|
|
||||||
return file_id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TFile extends TDocument {
|
public class TFile extends TSendable {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final String filePath;
|
||||||
|
|
||||||
public TFile(JSONObject json) {
|
public TFile(JSONObject json) {
|
||||||
super(json);
|
super(json);
|
||||||
allowedmembers = new Member[] {Member.file_size, Member.file_path};
|
allowedmembers = new Member[] {Member.file_size, Member.file_path, Member.file_id, Member.file_unique_id};
|
||||||
|
|
||||||
|
if(has(Member.file_path))
|
||||||
|
filePath = get(Member.file_path);
|
||||||
|
else
|
||||||
|
filePath = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,31 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TInlineKeyboardMarkup implements TReplyMarkup {
|
public class TInlineKeyboardMarkup implements TReplyMarkup {
|
||||||
|
|
||||||
ArrayList<JSONArray> arr_btn = new ArrayList<>();
|
List<JSONArray> arr_btn;
|
||||||
|
|
||||||
public TInlineKeyboardMarkup() {
|
public TInlineKeyboardMarkup() {
|
||||||
this(1);
|
this(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rows is a hint, how many lines will be needed
|
||||||
|
*/
|
||||||
public TInlineKeyboardMarkup(int rows) {
|
public TInlineKeyboardMarkup(int rows) {
|
||||||
if(rows < 1)
|
arr_btn = new ArrayList<>(rows);
|
||||||
throw new IllegalArgumentException("You need at least one row.");
|
|
||||||
arr_btn = new ArrayList<JSONArray>();
|
for(int row = 0; row < rows; ++row) {
|
||||||
|
arr_btn.add(row, new JSONArray());
|
||||||
for( int row = 0; row < rows; row++ ) {
|
|
||||||
arr_btn.add(new JSONArray());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert button in first line
|
* Insert button in first line
|
||||||
* @param title
|
* @param title
|
||||||
|
@ -36,21 +40,64 @@ public class TInlineKeyboardMarkup implements TReplyMarkup {
|
||||||
* Insert button in nth line
|
* Insert button in nth line
|
||||||
* @param title
|
* @param title
|
||||||
* @param url
|
* @param url
|
||||||
* @param row
|
* @param row (1 indexed)
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public TInlineKeyboardMarkup addUrlButton(String title, String url, int row) {
|
public TInlineKeyboardMarkup addUrlButton(String title, String url, int row) {
|
||||||
arr_btn.get(row-1).put(new JSONObject().put("text", title).put("url", url));
|
addButton(row, new JSONObject().put("text", title).put("url", url));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert button in nth line
|
||||||
|
* @param title
|
||||||
|
* @param callback
|
||||||
|
* @param row (1 indexed)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public TInlineKeyboardMarkup addCallbackButton(String title, String callback, int row) {
|
public TInlineKeyboardMarkup addCallbackButton(String title, String callback, int row) {
|
||||||
arr_btn.get(row-1).put(new JSONObject().put("text", title).put("callback_data", callback));
|
addButton(row, new JSONObject().put("text", title).put("callback_data", callback));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a button, check if the row is available first
|
||||||
|
* @param row
|
||||||
|
* @param btn
|
||||||
|
*/
|
||||||
|
private void addButton(int row, JSONObject btn) {
|
||||||
|
--row;
|
||||||
|
if(arr_btn.size() < row) {
|
||||||
|
//row existiert noch nicht
|
||||||
|
row = arr_btn.size(); //auf nächst größte Zeile setzten, damit keine leerzeilen entstehen
|
||||||
|
//resize
|
||||||
|
arr_btn.add(row, new JSONArray());
|
||||||
|
}
|
||||||
|
JSONArray arr = arr_btn.get(row);
|
||||||
|
arr.put(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TInlineKeyboardMarkup makeYesNo(String yes, String no) {
|
||||||
|
return makeYesNo(yes, no, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TInlineKeyboardMarkup makeYesNo(String yes, String no, String dataprefix) {
|
||||||
|
if(dataprefix == null) dataprefix = "";
|
||||||
|
TInlineKeyboardMarkup kb = new TInlineKeyboardMarkup(1);
|
||||||
|
kb.addCallbackButton(yes, dataprefix + "yes", 1);
|
||||||
|
kb.addCallbackButton(no, dataprefix + "no", 1);
|
||||||
|
return kb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TInlineKeyboardMarkup makeSingleButton(String btn, String callback) {
|
||||||
|
TInlineKeyboardMarkup kb = new TInlineKeyboardMarkup(1);
|
||||||
|
kb.addCallbackButton(btn, callback, 1);
|
||||||
|
return kb;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toJSONString() {
|
public String toJSONString() {
|
||||||
|
arr_btn.removeIf(a -> a.isEmpty()); //remove empty rows
|
||||||
return new JSONObject().put("inline_keyboard", new JSONArray(arr_btn)).toString();
|
return new JSONObject().put("inline_keyboard", new JSONArray(arr_btn)).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import de.mrbesen.telegram.AsyncHandler.Task;
|
import de.mrbesen.telegram.AsyncHandler.Task;
|
||||||
import de.mrbesen.telegram.TelegramAPI;
|
import de.mrbesen.telegram.TelegramAPI;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class TMessage extends JSONBased {
|
public class TMessage extends JSONBased {
|
||||||
|
|
||||||
|
@ -29,12 +29,6 @@ public class TMessage extends JSONBased {
|
||||||
} else {
|
} else {
|
||||||
return TUser.sendMessage(api, chatid != 0 ? chatid : from.getID(), msg, rm, message_id, false, null);
|
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") ;
|
|
||||||
// } catch (IOException | NullPointerException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
public boolean reply(String msg) {
|
public boolean reply(String msg) {
|
||||||
return reply(msg, null);
|
return reply(msg, null);
|
||||||
|
@ -46,7 +40,7 @@ public class TMessage extends JSONBased {
|
||||||
public static TMessage forward(TelegramAPI api, long userid, TMessage tmsg) {
|
public static TMessage forward(TelegramAPI api, long userid, TMessage tmsg) {
|
||||||
try {
|
try {
|
||||||
String fro = String.valueOf(tmsg.forward_from == null ? tmsg.from.getID() : tmsg.forward_from.getID());
|
String fro = String.valueOf(tmsg.forward_from == null ? tmsg.from.getID() : tmsg.forward_from.getID());
|
||||||
return new TMessage(api.request("forwardMessage", "chat_id=" + userid + "&from_chat_id=" + fro + "&message_id=" + tmsg.message_id).getJSONObject("result"), api);
|
return new TMessage(api.request("forwardMessage", "chat_id=" + userid + "&from_chat_id=" + fro + "&message_id=" + tmsg.message_id, userid).getJSONObject("result"), api);
|
||||||
} catch (IOException | NullPointerException e) {
|
} catch (IOException | NullPointerException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +49,7 @@ public class TMessage extends JSONBased {
|
||||||
|
|
||||||
public static void forwardAsync(TelegramAPI api, long userid, TMessage tmsg) {
|
public static void forwardAsync(TelegramAPI api, long userid, TMessage tmsg) {
|
||||||
String fro = String.valueOf(tmsg.forward_from == null ? tmsg.from.getID() : tmsg.forward_from.getID());
|
String fro = String.valueOf(tmsg.forward_from == null ? tmsg.from.getID() : tmsg.forward_from.getID());
|
||||||
api.request(new Task("forwardMessage", "chat_id=" + userid + "&from_chat_id=" + fro + "&message_id=" + tmsg.message_id));
|
api.request(new Task("forwardMessage", "chat_id=" + userid + "&from_chat_id=" + fro + "&message_id=" + tmsg.message_id, userid));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TMessage(JSONObject json, TelegramAPI api) {
|
public TMessage(JSONObject json, TelegramAPI api) {
|
||||||
|
@ -100,6 +94,49 @@ public class TMessage extends JSONBased {
|
||||||
return message_id;
|
return message_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the FileID if a file is attached to this message. If More than one File is attached to this message only one file id is returned
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getFileID() {
|
||||||
|
TSendable t = getFile();
|
||||||
|
return t == null ? null : t.getFile_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the FileName if a file is attached to this message. If More than one File is attached to this message only one filename is returned
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getFileName() {
|
||||||
|
try {
|
||||||
|
TSendable t = getFile();
|
||||||
|
return t == null ? null : t.get(Member.file_name); //TSendable does not garuantee a filename
|
||||||
|
} catch (JSONException e) {
|
||||||
|
return ""; //file exists but has no name?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a file if one is connected to this message
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private TSendable getFile() {
|
||||||
|
try {
|
||||||
|
if(has(Member.document))
|
||||||
|
return new TDocument(get(Member.document));
|
||||||
|
else if(has(Member.video))
|
||||||
|
return new TVideo(get(Member.video));
|
||||||
|
else if(has(Member.audio))
|
||||||
|
return new TAudio(get(Member.audio));
|
||||||
|
else if(has(Member.voice))
|
||||||
|
return new TAudio(get(Member.voice)); //TODO: suboptimal, eine Voice als audio zu verstehen, sollte aber funktionieren, da alle nicht optinalen felder gleich sind
|
||||||
|
else return null;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void delete(TelegramAPI api, long chatid, int msgid) {
|
public static void delete(TelegramAPI api, long chatid, int msgid) {
|
||||||
delete(api, chatid, msgid, false);
|
delete(api, chatid, msgid, false);
|
||||||
}
|
}
|
||||||
|
@ -107,10 +144,10 @@ public class TMessage extends JSONBased {
|
||||||
public static void delete(TelegramAPI api, long chatid, int msgid, boolean async) {
|
public static void delete(TelegramAPI api, long chatid, int msgid, boolean async) {
|
||||||
String q = "chat_id=" + chatid + "&message_id=" + msgid;
|
String q = "chat_id=" + chatid + "&message_id=" + msgid;
|
||||||
if(async) {
|
if(async) {
|
||||||
api.requestAsync("deleteMessage", q);
|
api.requestAsync("deleteMessage", q, chatid);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
api.request("deleteMessage", q);
|
api.request("deleteMessage", q, chatid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TPhotoSize extends TDocument {
|
public class TPhotoSize extends TSendable {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private int width, height;
|
private int width, height;
|
||||||
|
|
||||||
public TPhotoSize(JSONObject json) {
|
public TPhotoSize(JSONObject json) {
|
||||||
|
@ -12,12 +14,4 @@ public class TPhotoSize extends TDocument {
|
||||||
height = json.getInt("height");
|
height = json.getInt("height");
|
||||||
allowedmembers = new Member[] {Member.file_size};
|
allowedmembers = new Member[] {Member.file_size};
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TSendable extends JSONBased {
|
public class TSendable extends JSONBased {
|
||||||
|
|
||||||
|
@Getter
|
||||||
protected String file_id;
|
protected String file_id;
|
||||||
|
@Getter
|
||||||
|
protected int file_size;
|
||||||
|
|
||||||
public void set(Member mem, Object value ) {
|
public void set(Member mem, Object value) {
|
||||||
if(isAllowed(mem)) {
|
if(isAllowed(mem)) {
|
||||||
if(value instanceof Integer)
|
if(value instanceof Integer)
|
||||||
base_json.put(mem.name(), (int) value);
|
base_json.put(mem.name(), (int) value);
|
||||||
|
@ -22,10 +26,6 @@ public class TSendable extends JSONBased {
|
||||||
public TSendable(JSONObject o) {
|
public TSendable(JSONObject o) {
|
||||||
super(o);
|
super(o);
|
||||||
file_id = o.getString("file_id");
|
file_id = o.getString("file_id");
|
||||||
}
|
file_size = o.optInt("file_size", -1);
|
||||||
|
|
||||||
public boolean upload() {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package de.mrbesen.telegram.objects;
|
package de.mrbesen.telegram.objects;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import de.mrbesen.telegram.AsyncHandler.Callback;
|
import de.mrbesen.telegram.AsyncHandler.Callback;
|
||||||
import de.mrbesen.telegram.MessageBuilder;
|
import de.mrbesen.telegram.MessageBuilder;
|
||||||
import de.mrbesen.telegram.MessageBuilder.Attachment;
|
import de.mrbesen.telegram.MessageBuilder.Attachment;
|
||||||
import de.mrbesen.telegram.TelegramAPI;
|
import de.mrbesen.telegram.TelegramAPI;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class TUser {
|
public class TUser {
|
||||||
|
|
||||||
|
@ -20,6 +19,7 @@ public class TUser {
|
||||||
private String lastName;//optional
|
private String lastName;//optional
|
||||||
@Getter
|
@Getter
|
||||||
private String langcode; // optional
|
private String langcode; // optional
|
||||||
|
@Getter
|
||||||
private boolean isBot = false;
|
private boolean isBot = false;
|
||||||
|
|
||||||
private TelegramAPI api = null;
|
private TelegramAPI api = null;
|
||||||
|
@ -48,14 +48,6 @@ public class TUser {
|
||||||
langcode = o.getString("language_code");
|
langcode = o.getString("language_code");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLangcode() {
|
|
||||||
return langcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBot() {
|
|
||||||
return isBot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return uname;
|
return uname;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +85,7 @@ public class TUser {
|
||||||
|
|
||||||
public void sendStatus(Status status) {
|
public void sendStatus(Status status) {
|
||||||
try {
|
try {
|
||||||
api.request("sendChatAction", "chat_id="+ ID +"&action=" + status.getAPIName());
|
api.request("sendChatAction", "chat_id="+ ID +"&action=" + status.getAPIName(), ID);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Failed to send status.");
|
System.err.println("Failed to send status.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
status = error
|
|
||||||
name = PropertiesConfig
|
|
||||||
|
|
||||||
filters = threshold
|
|
||||||
|
|
||||||
filter.threshold.type = ThresholdFilter
|
|
||||||
filter.threshold.level = debug
|
|
||||||
|
|
||||||
appenders = console
|
|
||||||
|
|
||||||
appender.console.type = Console
|
|
||||||
appender.console.name = STDOUT
|
|
||||||
appender.console.layout.type = PatternLayout
|
|
||||||
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
|
|
||||||
|
|
||||||
rootLogger.level = info
|
|
||||||
rootLogger.appenderRefs = stdout
|
|
||||||
rootLogger.appenderRef.stdout.ref = STDOUT
|
|
Loading…
Reference in New Issue
Block a user