Idealisan

基于Telegram Bot Java API Library的一个同步、有状态Bot库

这个库的源代码很短,基本思路是使用一个阻塞队列实现同步编程。

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();
        }
    }
分类

讨论 基于Telegram Bot Java API Library的一个同步、有状态Bot库

  1. idealisan idealisan说道:

    这里使用的org.telegram.telegrambots库还非常不稳定,含有不少bug,虽然从包名看起来是官方库,但是我觉得另一个https://github.com/pengrad/java-telegram-bot-api 更稳定。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注