这个库的源代码很短,基本思路是使用一个阻塞队列实现同步编程。
package com.example.botPort;
import com.example.botPort.base.CorrectTelegramLongPollingSessionBot;
import org.apache.shiro.session.Session;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.session.DefaultChatIdConverter;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Supplier;
public abstract class StatefulBotBase extends CorrectTelegramLongPollingSessionBot {
private final String WORKFLOW_KEY = "WORKFLOW";
private ExecutorService threadPool = Executors.newFixedThreadPool(4);
public StatefulBotBase() {}
public StatefulBotBase(DefaultBotOptions options) {
super(new DefaultChatIdConverter(), options);
}
public void setThreadPool(ExecutorService threadPool) {
this.threadPool = threadPool;
}
@Override
public void onUpdateReceived(Update update, Optional<Session> optional) {
try {
Session session = optional.get();
if (session.getAttribute(WORKFLOW_KEY) == null) {
WorkFlow workFlow = getWorkFlow();
session.setAttribute(WORKFLOW_KEY, workFlow);
WorkFlow flow = (WorkFlow) session.getAttribute(WORKFLOW_KEY);
flow.setBot(this);
threadPool.submit(flow);
}
WorkFlow flow = (WorkFlow) session.getAttribute(WORKFLOW_KEY);
flow.getQueue().put(update);
} catch (Exception e) {
e.printStackTrace();
}
}
public abstract WorkFlow getWorkFlow();
public abstract static class WorkFlow implements Runnable {
private final BlockingQueue<Update> queue = new LinkedBlockingQueue<>();
private TelegramLongPollingBot bot;
private BlockingQueue<Update> getQueue() {
return queue;
}
private void setBot(TelegramLongPollingBot bot) {
this.bot = bot;
}
protected abstract void chat(
Supplier<Update> updateSupplier, TelegramLongPollingBot sender);
@Override
public void run() {
while (true) {
try {
chat(
() -> {
try {
return queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
},
bot);
} catch (Exception ignore) {
}
}
}
}
}
使用方法也很简单,继承这个bot和对应的workflow,在按照一般的bot的注册方法注册这个bot即可。
package com.example.botPort;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.util.function.Supplier;
public class WordCountBot extends StatefulBotBase {
public WordCountBot(DefaultBotOptions options) {
super(options);
}
@Override
public WorkFlow getWorkFlow() {
return new WordCountFlow();
}
@Override
public String getBotUsername() {
return "wcflow";
}
@Override
public String getBotToken() {
return "";
}
class WordCountFlow extends WorkFlow {
@Override
protected void chat(Supplier<Update> updateSupplier, TelegramLongPollingBot sender) {
try {
Message message = updateSupplier.get().getMessage();
String text = message.getText();
int count = text.codePointCount(0, text.length());
sender.execute(
new SendMessage(message.getChatId() + "", count + " unicode characters."));
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
try {
TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);
TelegramLongPollingBot postBot = new WordCountBot();
telegramBotsApi.registerBot(postBot);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
这里使用的org.telegram.telegrambots库还非常不稳定,含有不少bug,虽然从包名看起来是官方库,但是我觉得另一个https://github.com/pengrad/java-telegram-bot-api 更稳定。