Closed PureBasics closed 2 months ago
I've been running bots with docker compose.
telegram-bot.Dockerfile
## Clone service
FROM alpine/git:latest as clone
WORKDIR /clone
RUN git clone https://<token>@github.com/DEHuckaKpyT/some-telegram-bot.git
## Build service
FROM gradle:8.7-jdk17 AS build
WORKDIR /build/some-telegram-bot
COPY --from=clone /clone/some-telegram-bot /build/some-telegram-bot
RUN ["chmod", "+x", "gradlew"]
RUN gradle bootJar
## Run service
FROM openjdk:17-oracle
COPY --from=build /build/some-telegram-bot/build/libs/some-telegram-bot-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
docker-compose.yaml
version: "3"
services:
database:
image: postgres:16
environment:
POSTGRES_DB: some_telegram_bot
POSTGRES_PASSWORD: 11
POSTGRES_USER: postgres
logging:
driver: "none"
restart: no
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "9200:5432"
telegram-bot:
image: telegram-bot
build:
dockerfile: ./telegram-bot.Dockerfile
command: >
--DATASOURCE_URL=jdbc:postgresql://database:5432/some_telegram_bot
--TELEGRAM_BOT_TOKEN=<token>
--TELEGRAM_BOT_USERNAME=some_bot
depends_on:
- database
restart: no
ports:
- "9201:8080"
volumes:
postgres-data:
docker compose build --no-cache && docker compose up -d
@PureBasics, or can you write exception message? It should be in the log after Internal error. Receiving updates will be resumed after 5000 milliseconds
.
@PureBasics, or can you write exception message? It should be in the log after
Internal error. Receiving updates will be resumed after 5000 milliseconds
.
Unfortunately, the log ends with this message:
`2024-07-13 12:44:49 2024-07-13T10:44:49.798Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path ''
2024-07-13 12:44:49 2024-07-13T10:44:49.819Z INFO 1 --- [ main] c.DriveFy.DriveFy.DriveFyApplicationKt : Started DriveFyApplicationKt in 6.211 seconds (process running for 6.727)
2024-07-13 12:44:50 Response Code: 200
2024-07-13 12:44:50 2024-07-13T10:44:50.805Z INFO 1 --- [atcher-worker-1] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver
2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Starting telegram-bot 'Test'..
2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [atcher-worker-2] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver
2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Telegram-bot 'Test' started.
2024-07-13 12:44:50 2024-07-13T10:44:50.857Z ERROR 1 --- [atcher-worker-1] i.g.d.t.r.LongPollingUpdateReceiver : Internal error. Receiving updates will be resumed after 5000 milliseconds.
2024-07-13 12:44:50
2024-07-13 12:44:50 kotlinx.coroutines.JobCancellationException: Parent job is Completed
2024-07-13 12:44:50`
My very simple Dockerfile:
FROM openjdk:17-jdk-alpine
WORKDIR /app
EXPOSE 8080
COPY build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Hmm. It works for me with this Dockerfile.
Maybe more details are needed. Like spring version, bot modules, bot version, kotlin version
2024-07-13 12:44:50 2024-07-13T10:44:50.805Z INFO 1 --- [atcher-worker-1] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver 2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Starting telegram-bot 'Test'.. 2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [atcher-worker-2] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver 2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Telegram-bot 'Test' started.
I see a strange thing. For some reason you have LongPollingUpdateReceiver running twice (Started update receiver
). This should not be..
build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.2.5"
id("io.spring.dependency-management") version "1.1.4"
kotlin("jvm") version "1.9.23"
kotlin("plugin.spring") version "1.9.23"
id("org.jetbrains.kotlin.plugin.jpa") version "2.0.0"
}
group = "com.DriveFy"
version = "0.0.1-SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation:3.3.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.hateoas:spring-hateoas:2.3.0")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
implementation("org.mariadb.jdbc:mariadb-java-client:2.2.0")
implementation("mysql:mysql-connector-java:5.1.13")
implementation("io.github.dehuckakpyt.telegrambot:telegram-bot-core:0.9.7")
implementation("io.github.dehuckakpyt.telegrambot:telegram-bot-spring:0.9.7")
implementation("com.opencsv:opencsv:3.7")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.security:spring-security-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
My Bot implementation:
@Service
class TelegramBotService(@Value("\${telegram-bot.token}") private val botToken: String, @Value("\${telegram-bot.username}") private val botUsername: String, @Lazy val companyService: CompanyService) {
lateinit var bot: TelegramBot
var started = false
fun start() {
val config = TelegramBotConfig().apply {
token = botToken
username = botUsername
receiving {
handling {
startCommand()
helpCommand()
}
}
}
val context = TelegramBotFactory.createTelegramBotContext(config)
bot = context.telegramBot
val updateReceiver = context.updateReceiver
updateReceiver.start()
readlnOrNull()
updateReceiver.stop()
}
fun BotHandling.startCommand() {
command("/start") {
sendMessage("start command works")
}
}
fun BotHandling.helpCommand() {
command("/help") {
sendMessage("help command works")
}
}
fun sendMessage(chatId: String, message: String){
runBlocking {
bot.sendMessage(chatId, message)
}
}
}
2024-07-13 12:44:50 2024-07-13T10:44:50.805Z INFO 1 --- [atcher-worker-1] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver 2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Starting telegram-bot 'Test'.. 2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [atcher-worker-2] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver 2024-07-13 12:44:50 2024-07-13T10:44:50.812Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Telegram-bot 'Test' started.
I see a strange thing. For some reason you have LongPollingUpdateReceiver running twice (
Started update receiver
). This should not be..
Yes, I noticed that too. It only happens in the Dockerfile, not when I start the Spring app directly.
fun start() {
this function invokes once? Maybe you are creating the same bot twice?
I only call it here. This should only run once at startup
@Component
class StartupRunner(
val telegramBotService: TelegramBotService
) : ApplicationRunner {
override fun run(args: ApplicationArguments) {
telegramBotService.start()
}
}
I've added a log statement to that:
@Component
class StartupRunner(
val telegramBotService: TelegramBotService
) : ApplicationRunner {
override fun run(args: ApplicationArguments) {
println("START TELEGRAM BOT")
telegramBotService.start()
}
}
Only runs once
2024-07-13 13:36:17 START TELEGRAM BOT
2024-07-13 13:36:18 2024-07-13T11:36:18.735Z INFO 1 --- [atcher-worker-2] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver
2024-07-13 13:36:18 2024-07-13T11:36:18.742Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Starting telegram-bot 'Test'..
2024-07-13 13:36:18 2024-07-13T11:36:18.742Z INFO 1 --- [atcher-worker-1] i.g.d.t.r.LongPollingUpdateReceiver : Started update receiver
2024-07-13 13:36:18 2024-07-13T11:36:18.742Z INFO 1 --- [ main] mBotInitializationConfig$$SpringCGLIB$$0 : Telegram-bot 'Test' started.
2024-07-13 13:36:18 2024-07-13T11:36:18.793Z ERROR 1 --- [atcher-worker-2] i.g.d.t.r.LongPollingUpdateReceiver : Internal error. Receiving updates will be resumed after 5000 milliseconds.
2024-07-13 13:36:18
2024-07-13 13:36:18 kotlinx.coroutines.JobCancellationException: Parent job is Completed
2024-07-13 13:36:18
If it's no secret. And why don't you want to declare the bot via an annotation in the config? It will be started with application. https://dehuckakpyt.github.io/telegram-bot/get-started.html
@EnableTelegramBot
@Configuration
class BotConfig
And you can inject TelegramBot wherever you like bot: TelegramBot
Youc can configure it also like this:
@EnableTelegramBot
@Configuration
class BotConfig {
@Bean
fun telegramBotConfig(): TelegramBotConfig = TelegramBotConfig().apply {
receiving {
exceptionHandler = { WSExceptionHandler(telegramBot, receiving.messageTemplate, templating.templater) }
}
}
}
It still might not solve your problem, but it will definitely make the code cleaner.
I think I know what the problem is. The console is not available in the docker. you can't write something like readlnOrNull()
.
You could try removing those two lines to check.
readlnOrNull()
updateReceiver.stop()
The issue was that the bot started twice. I had included the @EnableTelegramBot
annotation and also called my own start method.
I realize now that I should have read the documentation more carefully.
Thank you so much for your help! Without it, I would've spent hours searching for the problem.
I'll try to improve the description in the documentation a bit. I don't promise that it will be soon. But I want to)
And one other observation. I suggest using a database to store states inside the bot. I saw in the dependencies that you use a database. You could just add a dependency for that io.github.dehuckakpyt.telegrambot:telegram-bot-source-jpa:0.9.7a
https://dehuckakpyt.github.io/telegram-bot/spring-jpa.html
*At least it should work just by adding the dependency. Otherwise dependency is useless)
The Telegram Bot works perfectly in my Spring application locally. However, in a Docker container, I get the following error:
[atcher-worker-1] i.g.d.t.r.LongPollingUpdateReceiver : Internal error. Receiving updates will be resumed after 5000 milliseconds.
I know this isn't directly related to this Wrapper itself, but I'm hoping someone might have a solution.
Does the Telegram bot require any specific port to be open?
I've been stuck on this problem for 2 days and don't know how to proceed.
Thank you!