Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

register webhook tg bot using spring boot

I am using telegrambots-spring-boot-starter v 5.2.0 and trying register my bot Here's my bot config:

bot.url=https://74e437885ee9.ngrok.io

bot.path=adam

    @Slf4j
@Configuration
public class BotConfig {
  @Value("${bot.url}")
  private String BOT_URL;

  @Bean
  public SetWebhook setWebhookInstance() {
    return SetWebhook.builder().url(BOT_URL).build();
  }
  // Create it as
  @Bean
  public AdamSmithBot adamSmithBot(SetWebhook setWebhookInstance) throws TelegramApiException {
    AdamSmithBot adamSmithBot = new AdamSmithBot(setWebhookInstance);
    //        DefaultWebhook defaultWebhook = new DefaultWebhook();
    //        defaultWebhook.setInternalUrl(BOT_URL);
    //        defaultWebhook.registerWebhook(adamSmithBot);

    TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);
    log.info("SetWebHook from AdamSmith bot {}", adamSmithBot.getSetWebhook());
    telegramBotsApi.registerBot(adamSmithBot, adamSmithBot.getSetWebhook());
    return adamSmithBot;
  }
}

But it dont working, but when i send this request, it working perfectly and updates recieve to me https://api.telegram.org/MY_TOKEN_HERE/setWebhook?url=https://74e437885ee9.ngrok.io

I think my mistake in BotConfig,but i also publush my other clases bot and controller:

    public class AdamSmithBot extends SpringWebhookBot {
  @Value("${bot.token}")
  private String TOKEN;

  @Value("${bot.name}")
  private String BOT_USERNAME;

  @Value("${bot.path}")
  private String BOT_PATH;

  public AdamSmithBot(SetWebhook setWebhook) {

    super(setWebhook);
  }

  public AdamSmithBot(DefaultBotOptions options, SetWebhook setWebhook) {
    super(options, setWebhook);
  }

  @Override
  public String getBotUsername() {
    return BOT_USERNAME;
  }

  @Override
  public String getBotToken() {
    return TOKEN;
  }

  @Override
  public BotApiMethod<?> onWebhookUpdateReceived(Update update) {

    if (update.getMessage() != null && update.getMessage().hasText()) {
      Long chatId = update.getMessage().getChatId();
      try {
        execute(new SendMessage(chatId.toString(), "HI HANDSOME " + update.getMessage().getText()));

      } catch (TelegramApiException e) {
        throw new IllegalStateException(e);
      }
    }
    return null;
  }

  @Override
  public String getBotPath() {
    return "adam";
  }
}

Controller:

    @Slf4j
@RestController
public class WebHookBotRecieveController {
    @Autowired
    private AdamSmithBot adamSmithBot;
    @PostMapping("/")
    public void getUpdate(@RequestBody Update update){
        log.info("some update recieved {}",update.toString());
        adamSmithBot.onWebhookUpdateReceived(update);

    }
    @PostMapping("/callback/adam")
    public void getUpdateWithDifferentUrl(@RequestBody Update update){
        log.info("some update recieved {}",update.toString());
        adamSmithBot.onWebhookUpdateReceived(update);

    }
}

NOTE: I seemd some info here: https://github.com/rubenlagus/TelegramBots/wiki/How-To-Update

They do that: https://i.sstatic.net/9JKRT.png

But when i trying put DefaultWebhook class instead it produce NullPointerException What i made wrong?

EDIT : I refactored some code @Value("${bot.url}") private String BOT_URL; - where was null value (fixed),reloaded library, but now i have that exception:

Caused by: javax.ws.rs.ProcessingException: Failed to start Grizzly HTTP server: Cannot assign requested address: bind
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer(GrizzlyHttpServerFactory.java:270) ~[jersey-container-grizzly2-http-2.33.jar:na]
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer(GrizzlyHttpServerFactory.java:93) ~[jersey-container-grizzly2-http-2.33.jar:na]
    at org.telegram.telegrambots.updatesreceivers.DefaultWebhook.startServer(DefaultWebhook.java:64) ~[telegrambots-5.2.0.jar:na]
    at org.telegram.telegrambots.meta.TelegramBotsApi.<init>(TelegramBotsApi.java:50) ~[telegrambots-meta-5.2.0.jar:na]
    at ru.website.selenium.bot.telegram.config.BotConfig.adamSmithBot(BotConfig.java:44) ~[classes/:na]
    at ru.website.selenium.bot.telegram.config.BotConfig$$EnhancerBySpringCGLIB$$4eb8259d.CGLIB$adamSmithBot$0(<generated>) ~[classes/:na]
    at ru.website.selenium.bot.telegram.config.BotConfig$$EnhancerBySpringCGLIB$$4eb8259d$$FastClassBySpringCGLIB$$1e185cfd.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.8.jar:5.3.8]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.8.jar:5.3.8]
    at ru.website.selenium.bot.telegram.config.BotConfig$$EnhancerBySpringCGLIB$$4eb8259d.adamSmithBot(<generated>) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.8.jar:5.3.8]
    ... 39 common frames omitted
Caused by: java.net.BindException: Cannot assign requested address: bind
    at java.base/sun.nio.ch.Net.bind0(Native Method) ~[na:na]
    at java.base/sun.nio.ch.Net.bind(Net.java:461) ~[na:na]
    at java.base/sun.nio.ch.Net.bind(Net.java:453) ~[na:na]
    at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:227) ~[na:na]
    at java.base/sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:80) ~[na:na]
    at org.glassfish.grizzly.nio.transport.TCPNIOBindingHandler.bindToChannelAndAddress(TCPNIOBindingHandler.java:107) ~[grizzly-framework-2.4.4.jar:2.4.4]
    at org.glassfish.grizzly.nio.transport.TCPNIOBindingHandler.bind(TCPNIOBindingHandler.java:64) ~[grizzly-framework-2.4.4.jar:2.4.4]
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.bind(TCPNIOTransport.java:215) ~[grizzly-framework-2.4.4.jar:2.4.4]
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.bind(TCPNIOTransport.java:195) ~[grizzly-framework-2.4.4.jar:2.4.4]
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.bind(TCPNIOTransport.java:186) ~[grizzly-framework-2.4.4.jar:2.4.4]
    at org.glassfish.grizzly.http.server.NetworkListener.start(NetworkListener.java:711) ~[grizzly-http-server-2.4.4.jar:2.4.4]
    at org.glassfish.grizzly.http.server.HttpServer.start(HttpServer.java:256) ~[grizzly-http-server-2.4.4.jar:2.4.4]
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer(GrizzlyHttpServerFactory.java:267) ~[jersey-container-grizzly2-http-2.33.jar:na]
    ... 53 common frames omitted

Process finished with exit code 0

like image 994
handsome16 Avatar asked Apr 27 '26 00:04

handsome16


1 Answers

Okay, I get it, I didn't know that TelegramBotApi runs a grizzly server underneath and that was the reason for my mistakes For those who ever come here with the same problem, I will describe the solution : Let's start with the fact that for the test on localhost we need a public address , e.g. ngrok , then we have to do the following, start grizzli on , let's say port 80 (localhost), specify the correct ngrok url , and then run spring boot application on , let's say port 8080, examples in the code

For ex. ngrok forwarding: Forwarding http://b44ecce72666.ngrok.io -> http://localhost:8080 Forwarding https://b44ecce72666.ngrok.io -> http://localhost:8080

@Slf4j
@Configuration
public class BotConfig {
//  @Value("${bot.url}")
//  @NotNull
//  @NotEmpty
//  private String BOT_URL;

  @Value("${bot.token}")
  @NotNull
  @NotEmpty
  private String TOKEN;

  @Value("${bot.name}")
  @NotNull
  @NotEmpty
  private String BOT_USERNAME;

  @Bean
  public SetWebhook setWebhookInstance() {
    return SetWebhook.builder().url("https://b44ecce72666.ngrok.io").build();
  } // public address, now it is ngrok, in the future it will (i think) be the server address
  // Create it as
  @Bean
  public AdamSmithBot adamSmithBot(SetWebhook setWebhookInstance) throws TelegramApiException {

    AdamSmithBot adamSmithBot = new AdamSmithBot(setWebhookInstance);
    adamSmithBot.setBOT_USERNAME(BOT_USERNAME);
    adamSmithBot.setTOKEN(TOKEN);
    adamSmithBot.setBOT_PATH("adam");
    DefaultWebhook defaultWebhook = new DefaultWebhook();

    defaultWebhook.setInternalUrl(
        "http://localhost:80"); // the port to start the server, on the localhost computer, on the server it
                                // be the server address
    //   defaultWebhook.registerWebhook(adamSmithBot);

    TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class, defaultWebhook);

    log.info("SetWebHook from AdamSmith bot {}", setWebhookInstance);
    adamSmithBot.getBotUsername();
    telegramBotsApi.registerBot(adamSmithBot, setWebhookInstance);
    return adamSmithBot;
   
  }
}

Next is code of webhook bot:

@Slf4j
@Setter
public class AdamSmithBot extends SpringWebhookBot {
  @Value("${bot.token}")
  private String TOKEN;

  @Value("${bot.name}")
  private String BOT_USERNAME;

  @Value("${bot.path}")
  private String BOT_PATH;
  @Autowired
  private MainService mainService;

  public AdamSmithBot(SetWebhook setWebhook) {

    super(setWebhook);
  }

  public AdamSmithBot(DefaultBotOptions options, SetWebhook setWebhook) {
    super(options, setWebhook);
  }

  @Override
  public String getBotUsername() {

    log.info("BOT_USERNAME FROM ADAM BOT {}",BOT_USERNAME);
    return BOT_USERNAME;
  }

  @Override
  public String getBotToken() {
    return TOKEN;
  }

  @Override
  public BotApiMethod<?> onWebhookUpdateReceived(Update update) { //All messages coming from the grizzly server will trigger this method
    log.info("Message teext {}",update.toString());
    if (update.getMessage() != null && update.getMessage().hasText()) {
      Long chatId = update.getMessage().getChatId();

      List<PartialBotApiMethod<Message>> listOfCommands=  mainService.receiveUpdate(update);
        listOfCommands.forEach(x->{
          try {
          if(x instanceof SendMessage){

              execute((SendMessage)x);

          }
          if(x instanceof SendPhoto){
            execute((SendPhoto) x);
          }
          } catch (TelegramApiException e) {
            e.printStackTrace();
          }
        });


    }
    return null;
  }

  @Override
  public String getBotPath() {
    return "adam"; //any other path here
  }
}

My code is excessive in some places, and too fancy, but it's not hard to figure out. If you have any suggestions on how to make it better, I'd love to hear them.

like image 134
handsome16 Avatar answered Apr 28 '26 23:04

handsome16



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!