This commit is contained in:
2026-02-09 17:34:39 +03:00
commit 76bbc2a630
14 changed files with 275 additions and 0 deletions

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

37
.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

38
build.gradle Normal file
View File

@@ -0,0 +1,38 @@
plugins {
id 'java'
id 'org.springframework.boot' version '4.0.2'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'ru.ilug'
version = '0.0.1-SNAPSHOT'
description = 'Demo project for Spring Boot'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

1
settings.gradle Normal file
View File

@@ -0,0 +1 @@
rootProject.name = 'my_telegram_bot'

View File

@@ -0,0 +1,22 @@
package ru.ilug.telegram_bot;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.annotation.Nullable;
import lombok.Data;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GetUpdates {
@Nullable
private Integer offset;
@Nullable
private Integer limit;
@Nullable
private Integer timeout;
@Nullable
@JsonProperty("allowed_updates")
private String[] allowedUpdates;
}

View File

@@ -0,0 +1,15 @@
package ru.ilug.telegram_bot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class MyTelegramBotApplication {
public static void main(String[] args) {
SpringApplication.run(MyTelegramBotApplication.class, args);
}
}

View File

@@ -0,0 +1,14 @@
package ru.ilug.telegram_bot;
import jakarta.annotation.Nullable;
import lombok.Data;
@Data
public class ResponseParameters {
@Nullable
private Integer migrateToChatId;
@Nullable
private Integer retryAfter;
}

View File

@@ -0,0 +1,38 @@
package ru.ilug.telegram_bot;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.List;
@Component
public class TelegramClient {
private final WebClient webClient;
public TelegramClient(@Value("${application.telegram.token}") String telegramToken) {
webClient = WebClient.builder()
.baseUrl("https://api.telegram.org/bot" + telegramToken)
.defaultHeaders(headers -> {
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
})
.build();
}
@PostMapping
public Mono<TelegramResponse<List<UpdateDto>>> getUpdates(GetUpdates request) {
return webClient.post()
.uri("/getUpdates")
.bodyValue(request)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<>() {
});
}
}

View File

@@ -0,0 +1,22 @@
package ru.ilug.telegram_bot;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.annotation.Nullable;
import lombok.Data;
@Data
public class TelegramResponse<T> {
private boolean ok;
@Nullable
private String description;
@Nullable
private T result;
@JsonProperty("error_code")
private int errorCode;
@Nullable
private ResponseParameters parameters;
}

View File

@@ -0,0 +1,50 @@
package ru.ilug.telegram_bot;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
@Slf4j
@Service
@RequiredArgsConstructor
public class TelegramService {
private final TelegramClient telegramClient;
private Integer lastUpdateId;
@EventListener(ContextRefreshedEvent.class)
public void onStart() {
Mono.delay(Duration.ofMillis(3000))
.flatMapMany(i -> update())
.repeat()
.subscribe();
}
public Flux<UpdateDto> update() {
GetUpdates request = new GetUpdates();
request.setOffset(lastUpdateId);
return telegramClient.getUpdates(request)
.doOnNext(response -> {
if (!response.isOk()) {
throw new RuntimeException(response.getDescription());
}
}).flatMapIterable(response -> {
assert response.getResult() != null;
return response.getResult();
}).doOnNext(this::update);
}
private void update(UpdateDto updateDto) {
log.info("Get update with id: {}", updateDto.getUpdateId());
lastUpdateId = updateDto.getUpdateId() + 1;
}
}

View File

@@ -0,0 +1,12 @@
package ru.ilug.telegram_bot;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class UpdateDto {
@JsonProperty("update_id")
private int updateId;
}

View File

@@ -0,0 +1,3 @@
spring.application.name=my-telegram-bot
application.telegram.token=

View File

@@ -0,0 +1,13 @@
package ru.ilug.telegram_bot;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MyTelegramBotApplicationTests {
@Test
void contextLoads() {
}
}