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
|
package dev.inmo.plaguposter.common
|
||||||
|
|
||||||
const val SuccessfulSymbol = "✓"
|
const val SuccessfulSymbol = "✅"
|
||||||
const val UnsuccessfulSymbol = "❌"
|
const val UnsuccessfulSymbol = "❌"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
|
org.gradle.jvmargs=-Xmx1024m
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
kotlin.js.generate.externals=true
|
kotlin.js.generate.externals=true
|
||||||
kotlin.incremental=true
|
kotlin.incremental=true
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
kotlin = "1.7.10"
|
kotlin = "1.7.10"
|
||||||
kotlin-serialization = "1.4.0"
|
kotlin-serialization = "1.4.0"
|
||||||
|
|
||||||
plagubot = "2.2.0"
|
plagubot = "2.3.0"
|
||||||
tgbotapi = "3.2.0"
|
tgbotapi = "3.2.0"
|
||||||
microutils = "0.12.6"
|
microutils = "0.12.6"
|
||||||
kslog = "0.5.1"
|
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.ReadCRUDRepo
|
||||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
||||||
import dev.inmo.plaguposter.posts.models.*
|
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.logger
|
||||||
import dev.inmo.kslog.common.w
|
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.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.exposed.ExposedPostsRepo
|
||||||
import dev.inmo.plaguposter.posts.models.ChatConfig
|
import dev.inmo.plaguposter.posts.models.ChatConfig
|
||||||
import dev.inmo.plaguposter.posts.repo.*
|
import dev.inmo.plaguposter.posts.repo.*
|
||||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
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.ChatId
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
import org.koin.core.Koin
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
import org.koin.dsl.binds
|
import org.koin.dsl.binds
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
|
@Serializable
|
||||||
|
data class Config(
|
||||||
|
val chats: ChatConfig,
|
||||||
|
val autoRemoveMessages: Boolean = true
|
||||||
|
)
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
val configJson = params["posts"] ?: this@Plugin.let {
|
val configJson = params["posts"] ?: this@Plugin.let {
|
||||||
it.logger.w {
|
it.logger.w {
|
||||||
@ -23,7 +40,8 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
single { get<Json>().decodeFromJsonElement(ChatConfig.serializer(), configJson) }
|
single { get<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
|
||||||
|
single { get<Config>().chats }
|
||||||
single { ExposedPostsRepo(database) } binds arrayOf(
|
single { ExposedPostsRepo(database) } binds arrayOf(
|
||||||
PostsRepo::class,
|
PostsRepo::class,
|
||||||
ReadPostsRepo::class,
|
ReadPostsRepo::class,
|
||||||
@ -34,4 +52,39 @@ object Plugin : Plugin {
|
|||||||
PostPublisher(get(), get(), config.cacheChatId, config.targetChatId)
|
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.plaguposter.posts.repo.PostsRepo
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
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 {
|
init {
|
||||||
initTable()
|
initTable()
|
||||||
}
|
}
|
||||||
@ -93,24 +97,29 @@ class ExposedPostsRepo(
|
|||||||
|
|
||||||
override suspend fun deleteById(ids: List<PostId>) {
|
override suspend fun deleteById(ids: List<PostId>) {
|
||||||
onBeforeDelete(ids)
|
onBeforeDelete(ids)
|
||||||
|
val posts = ids.mapNotNull {
|
||||||
|
getById(it)
|
||||||
|
}.associateBy { it.id }
|
||||||
|
val existsIds = posts.keys.toList()
|
||||||
transaction(db = database) {
|
transaction(db = database) {
|
||||||
val deleted = deleteWhere(null, null) {
|
val deleted = deleteWhere(null, null) {
|
||||||
selectByIds(ids)
|
selectByIds(existsIds)
|
||||||
}
|
}
|
||||||
with(contentRepo) {
|
with(contentRepo) {
|
||||||
deleteWhere {
|
deleteWhere {
|
||||||
postIdColumn.inList(ids.map { it.string })
|
postIdColumn.inList(existsIds.map { it.string })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deleted == ids.size) {
|
if (deleted == existsIds.size) {
|
||||||
ids
|
existsIds
|
||||||
} else {
|
} else {
|
||||||
ids.filter {
|
existsIds.filter {
|
||||||
select { selectById(it) }.limit(1).none()
|
select { selectById(it) }.limit(1).none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.forEach {
|
}.forEach {
|
||||||
_deletedObjectsIdsFlow.emit(it)
|
_deletedObjectsIdsFlow.emit(it)
|
||||||
|
_removedPostsFlow.emit(posts[it] ?: return@forEach)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
package dev.inmo.plaguposter.posts.registrar
|
package dev.inmo.plaguposter.posts.registrar
|
||||||
|
|
||||||
import com.benasher44.uuid.uuid4
|
import dev.inmo.micro_utils.coroutines.*
|
||||||
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.fsm.common.State
|
import dev.inmo.micro_utils.fsm.common.State
|
||||||
import dev.inmo.micro_utils.repos.create
|
import dev.inmo.micro_utils.repos.create
|
||||||
|
import dev.inmo.micro_utils.repos.deleteById
|
||||||
import dev.inmo.plagubot.Plugin
|
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.models.*
|
||||||
import dev.inmo.plaguposter.posts.registrar.state.RegistrationState
|
import dev.inmo.plaguposter.posts.registrar.state.RegistrationState
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
import dev.inmo.tgbotapi.extensions.api.delete
|
import dev.inmo.tgbotapi.extensions.api.delete
|
||||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
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.api.send.send
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.*
|
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.abstracts.ContentMessage
|
||||||
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
@ -1,20 +1,32 @@
|
|||||||
package dev.inmo.plaguposter.ratings
|
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.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
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.exposed.ExposedRatingsRepo
|
||||||
import dev.inmo.plaguposter.ratings.repo.*
|
import dev.inmo.plaguposter.ratings.repo.*
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
import org.koin.core.Koin
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
import org.koin.dsl.binds
|
import org.koin.dsl.binds
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
single { ExposedRatingsRepo(database, get<ExposedPostsRepo>().idColumn) } binds arrayOf(
|
single { ExposedRatingsRepo(database) } binds arrayOf(
|
||||||
RatingsRepo::class,
|
RatingsRepo::class,
|
||||||
ReadRatingsRepo::class,
|
ReadRatingsRepo::class,
|
||||||
WriteRatingsRepo::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
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
|
||||||
class ExposedRatingsRepo(
|
class ExposedRatingsRepo(
|
||||||
database: Database,
|
database: Database
|
||||||
postIdColumnReference: Column<String>
|
|
||||||
) : RatingsRepo, KeyValueRepo<PostId, Rating> by ExposedKeyValueRepo(
|
) : RatingsRepo, KeyValueRepo<PostId, Rating> by ExposedKeyValueRepo(
|
||||||
database,
|
database,
|
||||||
{ text("post_id") references postIdColumnReference },
|
{ text("post_id") },
|
||||||
{ double("rating") },
|
{ double("rating") },
|
||||||
"ratings"
|
"ratings"
|
||||||
).withMapper(
|
).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'
|
id 'application'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project.version = null
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation libs.kotlin
|
implementation libs.kotlin
|
||||||
api libs.plagubot.bot
|
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