Closed LegendaryZer0 closed 3 years ago
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
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:80 Forwarding https://b44ecce72666.ngrok.io -> http://localhost:80
@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.
EDIT: in that example, if you start spring boot server on 8080 port ngrok urls must be:
Forwarding http://b44ecce72666.ngrok.io -> http://localhost:8080 Forwarding https://b44ecce72666.ngrok.io -> http://localhost:8080
One might wonder, why do we need ngrok? - The point is that if we just specify localhost, Telegram will not understand where to send messages. if you already have a server with a public ip address, use it.
Hi @LegendaryZer0 , I am following your codes here. But I still didn't know, what's the contents of MainService
here? Could you please give me some lead on this?
Ah sorry, just realized MainService
is just a parser for the update
object. Means we can directly process whatever update
object contains. Your codes save my day. thanks! ✌️
Hi! I am using telegrambots-spring-boot-starter v 5.2.0 and trying register my webHookBot Here's my bot config:
bot.url=https://74e437885ee9.ngrok.io
bot.path=adam
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:
Controller:
NOTE: I seemd some info here: https://github.com/rubenlagus/TelegramBots/wiki/How-To-Update
On the fifth step you do this:
TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class, defaultWebhookInstance);
but what is it defaultWebhookInstance? When i trying put here DefaultWebhook it produce NullPointerExceptionBut when i trying put DefaultWebhook class instead it produce NullPointerException What i made wrong?