mirror of
https://github.com/pischule/memevizor.git
synced 2025-12-19 06:56:42 +00:00
Add s3 integration
This commit is contained in:
6
Dockerfile
Normal file
6
Dockerfile
Normal 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"]
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.9.25"
|
kotlin("jvm") version "2.1.0"
|
||||||
kotlin("plugin.spring") version "1.9.25"
|
kotlin("plugin.spring") version "1.9.25"
|
||||||
id("org.springframework.boot") version "3.4.4"
|
id("org.springframework.boot") version "3.4.4"
|
||||||
id("io.spring.dependency-management") version "1.1.7"
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
@@ -30,6 +30,7 @@ dependencies {
|
|||||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||||
implementation("io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.3.0")
|
implementation("io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.3.0")
|
||||||
implementation("io.github.oshai:kotlin-logging-jvm:7.0.3")
|
implementation("io.github.oshai:kotlin-logging-jvm:7.0.3")
|
||||||
|
implementation(awssdk.services.s3)
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
|||||||
@@ -1 +1,13 @@
|
|||||||
rootProject.name = "memes-tv"
|
rootProject.name = "memes-tv"
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
versionCatalogs {
|
||||||
|
create("awssdk") {
|
||||||
|
from("aws.sdk.kotlin:version-catalog:1.4.56")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.pischule.memestv
|
|||||||
import com.github.kotlintelegrambot.Bot
|
import com.github.kotlintelegrambot.Bot
|
||||||
import com.github.kotlintelegrambot.bot
|
import com.github.kotlintelegrambot.bot
|
||||||
import com.github.kotlintelegrambot.dispatch
|
import com.github.kotlintelegrambot.dispatch
|
||||||
|
import com.github.kotlintelegrambot.dispatcher.message
|
||||||
import com.github.kotlintelegrambot.dispatcher.photos
|
import com.github.kotlintelegrambot.dispatcher.photos
|
||||||
import com.github.kotlintelegrambot.entities.ChatId
|
import com.github.kotlintelegrambot.entities.ChatId
|
||||||
import com.github.kotlintelegrambot.entities.reaction.ReactionType
|
import com.github.kotlintelegrambot.entities.reaction.ReactionType
|
||||||
@@ -18,7 +19,10 @@ val log = KotlinLogging.logger {}
|
|||||||
@Profile("!test")
|
@Profile("!test")
|
||||||
@EnableConfigurationProperties(BotProps::class)
|
@EnableConfigurationProperties(BotProps::class)
|
||||||
@Service
|
@Service
|
||||||
class BotService(val botProps: BotProps) {
|
class BotService(
|
||||||
|
private val botProps: BotProps,
|
||||||
|
private val fileUploaderService: FileUploaderService,
|
||||||
|
) {
|
||||||
private lateinit var bot: Bot
|
private lateinit var bot: Bot
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@@ -26,27 +30,61 @@ class BotService(val botProps: BotProps) {
|
|||||||
bot = bot {
|
bot = bot {
|
||||||
token = botProps.token
|
token = botProps.token
|
||||||
dispatch {
|
dispatch {
|
||||||
|
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("👍"))
|
||||||
|
).onError { error ->
|
||||||
|
log.warn { "Failed to react to message: $error" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Error) {
|
||||||
|
log.error(e) { "Error while handling message" }
|
||||||
|
}
|
||||||
|
}
|
||||||
photos {
|
photos {
|
||||||
val message = this.message
|
val message = this.message
|
||||||
|
|
||||||
|
if (message.chat.id != botProps.destinationChatId) {
|
||||||
|
bot.forwardMessage(
|
||||||
|
chatId = ChatId.fromId(botProps.destinationChatId),
|
||||||
|
fromChatId = ChatId.fromId(message.chat.id),
|
||||||
|
messageId = message.messageId,
|
||||||
|
).fold(
|
||||||
|
{
|
||||||
|
log.info { "Forwarded pictures message: $it" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
log.error { "Failed to forward message: $it" }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
bot.setMessageReaction(
|
bot.setMessageReaction(
|
||||||
chatId = ChatId.fromId(message.chat.id),
|
chatId = ChatId.fromId(message.chat.id),
|
||||||
messageId = message.messageId,
|
messageId = message.messageId,
|
||||||
reaction = listOf(ReactionType.Emoji("👀"))
|
reaction = listOf(ReactionType.Emoji("👀"))
|
||||||
)
|
).onError { error ->
|
||||||
|
log.warn { "Failed to react to message: $error" }
|
||||||
|
}
|
||||||
|
|
||||||
bot.forwardMessage(
|
|
||||||
chatId = ChatId.fromId(botProps.destinationChatId),
|
|
||||||
fromChatId = ChatId.fromId(message.chat.id),
|
|
||||||
messageId = message.messageId,
|
|
||||||
).fold(
|
|
||||||
{
|
|
||||||
log.info { "Forwarded pictures message: $it" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
log.error { "Failed to forward message: $it" }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/main/kotlin/com/pischule/memestv/FileUploaderService.kt
Normal file
21
src/main/kotlin/com/pischule/memestv/FileUploaderService.kt
Normal 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"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/main/kotlin/com/pischule/memestv/S3Config.kt
Normal file
24
src/main/kotlin/com/pischule/memestv/S3Config.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main/kotlin/com/pischule/memestv/S3Props.kt
Normal file
10
src/main/kotlin/com/pischule/memestv/S3Props.kt
Normal 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,
|
||||||
|
)
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.pischule.memestv
|
package com.pischule.memestv
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.springframework.boot.test.context.SpringBootTest
|
import org.springframework.boot.test.context.SpringBootTest
|
||||||
import org.springframework.test.context.ActiveProfiles
|
import org.springframework.test.context.ActiveProfiles
|
||||||
|
|
||||||
|
@Disabled
|
||||||
@ActiveProfiles("test")
|
@ActiveProfiles("test")
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class MemesTvApplicationTests {
|
class MemesTvApplicationTests {
|
||||||
|
|||||||
Reference in New Issue
Block a user