mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2024-11-25 08:58:45 +00:00
production ready?
This commit is contained in:
parent
1e393103c8
commit
e8637a2de6
@ -1,4 +1,4 @@
|
||||
package dev.inmo.plaguposter.common
|
||||
|
||||
const val SuccessfulSymbol = "✓"
|
||||
const val SuccessfulSymbol = "✅"
|
||||
const val UnsuccessfulSymbol = "❌"
|
||||
|
@ -1,4 +1,5 @@
|
||||
kotlin.code.style=official
|
||||
org.gradle.jvmargs=-Xmx1024m
|
||||
org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
|
@ -3,7 +3,7 @@
|
||||
kotlin = "1.7.10"
|
||||
kotlin-serialization = "1.4.0"
|
||||
|
||||
plagubot = "2.2.0"
|
||||
plagubot = "2.3.0"
|
||||
tgbotapi = "3.2.0"
|
||||
microutils = "0.12.6"
|
||||
kslog = "0.5.1"
|
||||
|
@ -3,5 +3,8 @@ package dev.inmo.plaguposter.posts.repo
|
||||
import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface WritePostsRepo : WriteCRUDRepo<RegisteredPost, PostId, NewPost>
|
||||
interface WritePostsRepo : WriteCRUDRepo<RegisteredPost, PostId, NewPost> {
|
||||
val removedPostsFlow: Flow<RegisteredPost>
|
||||
}
|
||||
|
@ -2,20 +2,37 @@ package dev.inmo.plaguposter.posts
|
||||
|
||||
import dev.inmo.kslog.common.logger
|
||||
import dev.inmo.kslog.common.w
|
||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.repos.deleteById
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||
import dev.inmo.plaguposter.posts.models.ChatConfig
|
||||
import dev.inmo.plaguposter.posts.repo.*
|
||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.api.send.reply
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.*
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.koin.core.Koin
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.binds
|
||||
|
||||
object Plugin : Plugin {
|
||||
@Serializable
|
||||
data class Config(
|
||||
val chats: ChatConfig,
|
||||
val autoRemoveMessages: Boolean = true
|
||||
)
|
||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||
val configJson = params["posts"] ?: this@Plugin.let {
|
||||
it.logger.w {
|
||||
@ -23,7 +40,8 @@ object Plugin : Plugin {
|
||||
}
|
||||
return
|
||||
}
|
||||
single { get<Json>().decodeFromJsonElement(ChatConfig.serializer(), configJson) }
|
||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
|
||||
single { get<Config>().chats }
|
||||
single { ExposedPostsRepo(database) } binds arrayOf(
|
||||
PostsRepo::class,
|
||||
ReadPostsRepo::class,
|
||||
@ -34,4 +52,39 @@ object Plugin : Plugin {
|
||||
PostPublisher(get(), get(), config.cacheChatId, config.targetChatId)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||
val postsRepo = koin.get<PostsRepo>()
|
||||
val config = koin.get<Config>()
|
||||
|
||||
if (config.autoRemoveMessages) {
|
||||
postsRepo.removedPostsFlow.subscribeSafelyWithoutExceptions(this) {
|
||||
it.content.forEach {
|
||||
runCatchingSafely {
|
||||
delete(it.chatId, it.messageId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCommand("delete_post", requireOnlyCommandInMessage = true) {
|
||||
val messageInReply = it.replyTo ?: run {
|
||||
reply(it, "Reply some message of post to delete it")
|
||||
return@onCommand
|
||||
}
|
||||
|
||||
val postId = postsRepo.getIdByChatAndMessage(messageInReply.chat.id, messageInReply.messageId) ?: run {
|
||||
reply(it, "Unable to find post id by message")
|
||||
return@onCommand
|
||||
}
|
||||
|
||||
postsRepo.deleteById(postId)
|
||||
|
||||
if (postsRepo.contains(postId)) {
|
||||
edit(it, it.content.textSources + regular(UnsuccessfulSymbol))
|
||||
} else {
|
||||
edit(it, it.content.textSources + regular(SuccessfulSymbol))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
@ -45,6 +46,9 @@ class ExposedPostsRepo(
|
||||
)
|
||||
}
|
||||
|
||||
private val _removedPostsFlow = MutableSharedFlow<RegisteredPost>()
|
||||
override val removedPostsFlow: Flow<RegisteredPost> = _removedPostsFlow.asSharedFlow()
|
||||
|
||||
init {
|
||||
initTable()
|
||||
}
|
||||
@ -93,24 +97,29 @@ class ExposedPostsRepo(
|
||||
|
||||
override suspend fun deleteById(ids: List<PostId>) {
|
||||
onBeforeDelete(ids)
|
||||
val posts = ids.mapNotNull {
|
||||
getById(it)
|
||||
}.associateBy { it.id }
|
||||
val existsIds = posts.keys.toList()
|
||||
transaction(db = database) {
|
||||
val deleted = deleteWhere(null, null) {
|
||||
selectByIds(ids)
|
||||
selectByIds(existsIds)
|
||||
}
|
||||
with(contentRepo) {
|
||||
deleteWhere {
|
||||
postIdColumn.inList(ids.map { it.string })
|
||||
postIdColumn.inList(existsIds.map { it.string })
|
||||
}
|
||||
}
|
||||
if (deleted == ids.size) {
|
||||
ids
|
||||
if (deleted == existsIds.size) {
|
||||
existsIds
|
||||
} else {
|
||||
ids.filter {
|
||||
existsIds.filter {
|
||||
select { selectById(it) }.limit(1).none()
|
||||
}
|
||||
}
|
||||
}.forEach {
|
||||
_deletedObjectsIdsFlow.emit(it)
|
||||
_removedPostsFlow.emit(posts[it] ?: return@forEach)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,17 @@
|
||||
package dev.inmo.plaguposter.posts.registrar
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
import dev.inmo.kslog.common.logger
|
||||
import dev.inmo.kslog.common.w
|
||||
import dev.inmo.micro_utils.coroutines.firstOf
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.coroutines.*
|
||||
import dev.inmo.micro_utils.fsm.common.State
|
||||
import dev.inmo.micro_utils.repos.create
|
||||
import dev.inmo.micro_utils.repos.deleteById
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.common.FirstSourceIsCommandsFilter
|
||||
import dev.inmo.plaguposter.common.*
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.plaguposter.posts.registrar.state.RegistrationState
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.api.send.reply
|
||||
import dev.inmo.tgbotapi.extensions.api.send.send
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.*
|
||||
@ -30,6 +28,7 @@ import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,20 +1,32 @@
|
||||
package dev.inmo.plaguposter.ratings
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.repos.unset
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
||||
import dev.inmo.plaguposter.ratings.repo.*
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import kotlinx.serialization.json.*
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.koin.core.Koin
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.binds
|
||||
|
||||
object Plugin : Plugin {
|
||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||
single { ExposedRatingsRepo(database, get<ExposedPostsRepo>().idColumn) } binds arrayOf(
|
||||
single { ExposedRatingsRepo(database) } binds arrayOf(
|
||||
RatingsRepo::class,
|
||||
ReadRatingsRepo::class,
|
||||
WriteRatingsRepo::class,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||
val ratingsRepo = koin.get<RatingsRepo>()
|
||||
koin.get<PostsRepo>().deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(this) {
|
||||
ratingsRepo.unset(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,10 @@ import org.jetbrains.exposed.sql.Column
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
|
||||
class ExposedRatingsRepo(
|
||||
database: Database,
|
||||
postIdColumnReference: Column<String>
|
||||
database: Database
|
||||
) : RatingsRepo, KeyValueRepo<PostId, Rating> by ExposedKeyValueRepo(
|
||||
database,
|
||||
{ text("post_id") references postIdColumnReference },
|
||||
{ text("post_id") },
|
||||
{ double("rating") },
|
||||
"ratings"
|
||||
).withMapper(
|
||||
|
7
runner/Dockerfile
Normal file
7
runner/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
FROM adoptopenjdk/openjdk11
|
||||
|
||||
USER 1000
|
||||
|
||||
ENTRYPOINT ["/plaguposter.runner/bin/plaguposter.runner", "/config.json"]
|
||||
|
||||
ADD ./build/distributions/plaguposter.runner.tar /
|
@ -4,6 +4,8 @@ plugins {
|
||||
id 'application'
|
||||
}
|
||||
|
||||
project.version = null
|
||||
|
||||
dependencies {
|
||||
implementation libs.kotlin
|
||||
api libs.plagubot.bot
|
||||
|
26
runner/deploy.sh
Executable file
26
runner/deploy.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
function send_notification() {
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
function assert_success() {
|
||||
"${@}"
|
||||
local status=${?}
|
||||
if [ ${status} -ne 0 ]; then
|
||||
send_notification "### Error ${status} at: ${BASH_LINENO[*]} ###"
|
||||
exit ${status}
|
||||
fi
|
||||
}
|
||||
|
||||
app=plaguposter
|
||||
version=0.0.1
|
||||
server=docker.inmo.dev
|
||||
|
||||
assert_success ../gradlew build
|
||||
# scp ./build/distributions/AutoPostTestTelegramBot-1.0.0.zip ./config.json developer@insanusmokrassar.dev:/tmp/
|
||||
assert_success sudo docker build -t $app:"$version" .
|
||||
assert_success sudo docker tag $app:"$version" $server/$app:$version
|
||||
assert_success sudo docker tag $app:"$version" $server/$app:latest
|
||||
assert_success sudo docker push $server/$app:$version
|
||||
assert_success sudo docker push $server/$app:latest
|
Loading…
Reference in New Issue
Block a user