Bootstrap telegram bot on quarkus and camel.

Overview

Code is here: https://github.com/achernetsov/quarkus-telegram-camel-bootstrap

Components:

  1. Quarkus
  2. Camel (telegram integration based on camel-telegram component)
  3. JDBC (h2)

Bot accepts /start command, extracts and persists telegram user and sends different greetings for new and existing user.

Bot logic is implemented on camel routes.

Try it

  1. Create telegram bot in botfather
  2. Save bot token in .env file (see .env.example)
  3. Run service: ./mvnw quarkus:dev
  4. Write /start in telegram bot
  5. Bot will process input:
  • It will search if user was previously saved; if not - it will create one and then answer
  • If user was saved previously, it will answer with different message

Telegram chat screenshot

What’s cool about it

Telegram integration is implemented on camel-telegram component. This is all code needed to consume message:

@ApplicationScoped
public class TelegramIncomingMsgProcessor extends RouteBuilder {

    @ConfigProperty(name = "telegram.token")
    private String token;

    @Override
    public void configure() {
        // @formatter:off
        from("telegram:bots?authorizationToken=" + token)
                .log("${body}")
                .choice()
                    .when(simple("${body} == '/start'")).to(StartCommand.COMMAND)
                    .otherwise().to(StartCommand.COMMAND)
                .endChoice();

        // @formatter:on
    }
}

Command logic is also implemented on camel:

@ApplicationScoped
public class StartCommand extends RouteBuilder {
    public static final String COMMAND = "direct:tg-cmd-start";

    private static final String IS_NEW_USER_HEADER = "is_new_user";

    @ConfigProperty(name = "telegram.token")
    private String token;

    @Inject
    private TelegramUserService telegramUserService;

    @Override
    public void configure() {
        // @formatter:off
        from(COMMAND)
                .to("direct:find-or-create-user")
                .to("direct:send-greeting");

        // out: TelegramUser
        from("direct:find-or-create-user")
                .log("searching for existing user")
                .process(exchange -> {
                    Message in = exchange.getIn();
                    IncomingMessage message = in.getBody(IncomingMessage.class);
                    User from = message.getFrom();

                    Optional<TelegramUser> maybeUser = telegramUserService.findById(from.getId());
                    in.setHeader(IS_NEW_USER_HEADER, maybeUser.isEmpty());
                    TelegramUser telegramUser;
                    if (maybeUser.isEmpty()){
                        telegramUser = new TelegramUser(from.getId(), from.getUsername(), from.getFirstName());
                        telegramUserService.persist(telegramUser);
                    } else {
                        telegramUser = maybeUser.get();
                    }
                    in.setBody(telegramUser);
                });

        // in: TelegramUser, header: is_new user
        from("direct:send-greeting")
                .setHeader("firstname", simple("${body.getFirstName()}"))
                .choice()
                .when(simple("${headers.is_new_user} == false"))
                    .log("Existing user found, sending greeting")
                    // this is how message is sent using camel-telegram component
                    .setBody(simple("Welcome once again, ${headers.firstname}!"))
                    .to("telegram:bots?authorizationToken=" + token)
                .otherwise()
                    .log("New user is created, sending greeting")
                    .setBody(simple("You are new here, ${headers.firstname}, nice to meet you!"))
                    .to("telegram:bots?authorizationToken=" + token)
                .end();
        // @formatter:on
    }
}