Add s3 integration

This commit is contained in:
2025-04-07 23:01:40 +03:00
parent d422606b44
commit d369b6fac1
8 changed files with 129 additions and 15 deletions

6
Dockerfile Normal file
View File

@@ -0,0 +1,6 @@
FROM openjdk:eclipse-temurin:17-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

View File

@@ -1,5 +1,5 @@
plugins {
kotlin("jvm") version "1.9.25"
kotlin("jvm") version "2.1.0"
kotlin("plugin.spring") version "1.9.25"
id("org.springframework.boot") version "3.4.4"
id("io.spring.dependency-management") version "1.1.7"
@@ -30,6 +30,7 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.3.0")
implementation("io.github.oshai:kotlin-logging-jvm:7.0.3")
implementation(awssdk.services.s3)
developmentOnly("org.springframework.boot:spring-boot-devtools")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
testImplementation("org.springframework.boot:spring-boot-starter-test")

View File

@@ -1 +1,13 @@
rootProject.name = "memes-tv"
dependencyResolutionManagement {
repositories {
mavenCentral()
}
versionCatalogs {
create("awssdk") {
from("aws.sdk.kotlin:version-catalog:1.4.56")
}
}
}

View File

@@ -3,6 +3,7 @@ package com.pischule.memestv
import com.github.kotlintelegrambot.Bot
import com.github.kotlintelegrambot.bot
import com.github.kotlintelegrambot.dispatch
import com.github.kotlintelegrambot.dispatcher.message
import com.github.kotlintelegrambot.dispatcher.photos
import com.github.kotlintelegrambot.entities.ChatId
import com.github.kotlintelegrambot.entities.reaction.ReactionType
@@ -18,7 +19,10 @@ val log = KotlinLogging.logger {}
@Profile("!test")
@EnableConfigurationProperties(BotProps::class)
@Service
class BotService(val botProps: BotProps) {
class BotService(
private val botProps: BotProps,
private val fileUploaderService: FileUploaderService,
) {
private lateinit var bot: Bot
@PostConstruct
@@ -26,15 +30,39 @@ class BotService(val botProps: BotProps) {
bot = bot {
token = botProps.token
dispatch {
photos {
val message = this.message
message {
try {
val chatId = message.chat.id
val replyToPhotos = message.replyToMessage
?.photo
?.takeIf { it.isNotEmpty() }
if (chatId == botProps.destinationChatId
&& message.text?.lowercase() == "this"
&& replyToPhotos != null
) {
val maxResPhoto = replyToPhotos.last().fileId
val fileBytes = bot.downloadFileBytes(maxResPhoto)
fileBytes?.let {
log.info { "Downloaded a file $maxResPhoto from telegram" }
fileUploaderService.uploadFile(it)
log.info { "Uploaded a file $maxResPhoto to s3" }
bot.setMessageReaction(
chatId = ChatId.fromId(message.chat.id),
messageId = message.messageId,
reaction = listOf(ReactionType.Emoji("👀"))
)
reaction = listOf(ReactionType.Emoji("👍"))
).onError { error ->
log.warn { "Failed to react to message: $error" }
}
}
}
} catch (e: Error) {
log.error(e) { "Error while handling message" }
}
}
photos {
val message = this.message
if (message.chat.id != botProps.destinationChatId) {
bot.forwardMessage(
chatId = ChatId.fromId(botProps.destinationChatId),
fromChatId = ChatId.fromId(message.chat.id),
@@ -48,6 +76,16 @@ class BotService(val botProps: BotProps) {
}
)
}
bot.setMessageReaction(
chatId = ChatId.fromId(message.chat.id),
messageId = message.messageId,
reaction = listOf(ReactionType.Emoji("👀"))
).onError { error ->
log.warn { "Failed to react to message: $error" }
}
}
}
}

View File

@@ -0,0 +1,21 @@
package com.pischule.memestv
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.PutObjectRequest
import aws.smithy.kotlin.runtime.content.ByteStream
import org.springframework.stereotype.Service
@Service
class FileUploaderService(
private val s3Client: S3Client,
private val s3Props: S3Props,
) {
suspend fun uploadFile(fileBytes: ByteArray) {
s3Client.putObject(PutObjectRequest{
body = ByteStream.fromBytes(fileBytes)
bucket = s3Props.bucket
key = "_.jpeg"
})
}
}

View File

@@ -0,0 +1,24 @@
package com.pischule.memestv
import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider
import aws.sdk.kotlin.services.s3.S3Client
import aws.smithy.kotlin.runtime.net.url.Url
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@EnableConfigurationProperties(S3Props::class)
@Configuration
class S3Config {
@Bean
fun s3Client(s3Props: S3Props): S3Client {
return S3Client {
endpointUrl = Url.parse("https://storage.yandexcloud.net")
region = "ru-central1"
credentialsProvider = StaticCredentialsProvider {
accessKeyId = s3Props.accessKeyId
secretAccessKey = s3Props.secretAccessKey
}
}
}
}

View File

@@ -0,0 +1,10 @@
package com.pischule.memestv
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("s3")
data class S3Props(
val accessKeyId: String,
val secretAccessKey: String,
val bucket: String,
)

View File

@@ -1,9 +1,11 @@
package com.pischule.memestv
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles
@Disabled
@ActiveProfiles("test")
@SpringBootTest
class MemesTvApplicationTests {