mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2025-12-05 20:45:40 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2612ec6e9 | |||
| 0273284023 | |||
| 9af72d5d0f | |||
| b879426f9d | |||
| 18b8ce0d3d | |||
| a4686a56df | |||
| e567f5b3b4 | |||
| 3941c1dfed | |||
| 0bdd965a4a | |||
| ad967c002a | |||
| e3958aff3f | |||
| ae6993efba | |||
| 991b0ef3d3 | |||
| aa6c62d66e | |||
| e6a0d67444 | |||
| 16bd62da51 | |||
| edc75a09ee | |||
| 0f958f94cb | |||
| 69320a3b62 | |||
| b6fa2a6cd3 | |||
| e24237beb3 | |||
| d2d3665c5e | |||
| 9ef9de2b8a | |||
| cef350667b | |||
| 80ed679241 | |||
| 39391636ac | |||
| 29a19df7fc | |||
| 250f88e2fe | |||
| bb433a6441 |
1
.github/workflows/build_and_publish.yml
vendored
1
.github/workflows/build_and_publish.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
java-version: 17
|
||||
- name: Rewrite version
|
||||
run: |
|
||||
printf "\norg.gradle.jvmargs=-Xmx1g -Xms500m\nkotlin.daemon.jvmargs=-Xmx1g -Xms500m\norg.gradle.daemon=false" >> gradle.properties
|
||||
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
|
||||
cat gradle.properties | sed -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
|
||||
rm gradle.properties
|
||||
|
||||
1
.github/workflows/docker-publish.yml
vendored
1
.github/workflows/docker-publish.yml
vendored
@@ -16,6 +16,7 @@ jobs:
|
||||
java-version: 17
|
||||
- name: Rewrite version
|
||||
run: |
|
||||
printf "\norg.gradle.jvmargs=-Xmx1g -Xms500m\nkotlin.daemon.jvmargs=-Xmx1g -Xms500m\norg.gradle.daemon=false" >> gradle.properties
|
||||
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
|
||||
if [[ "$branch" != "master" ]]; then
|
||||
cat gradle.properties | sed -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.idea
|
||||
.kotlin/
|
||||
out/*
|
||||
*.iml
|
||||
target
|
||||
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,5 +1,31 @@
|
||||
# PlaguPoster
|
||||
|
||||
## 0.7.0
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.6.0
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.5.6
|
||||
|
||||
* `Ratings`:
|
||||
* `GC`:
|
||||
* Now GC will autoclear ratings even if post is absent in posts repo
|
||||
|
||||
## 0.5.5
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.5.4
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.5.3
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.5.2
|
||||
|
||||
* Dependencies update
|
||||
|
||||
@@ -18,7 +18,7 @@ allprojects {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url "https://git.inmo.dev/api/packages/InsanusMokrassar/maven" }
|
||||
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,15 +12,20 @@ data class ChatConfig(
|
||||
val targetChatId: IdChatIdentifier? = null,
|
||||
@SerialName("sourceChat")
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
val sourceChatId: IdChatIdentifier,
|
||||
val sourceChatId: IdChatIdentifier?,
|
||||
@SerialName("cacheChat")
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
val cacheChatId: IdChatIdentifier,
|
||||
@SerialName("targetChats")
|
||||
val targetChatIds: List<@Serializable(FullChatIdentifierSerializer::class) IdChatIdentifier> = emptyList(),
|
||||
@SerialName("sourceChats")
|
||||
val sourceChatIds: List<@Serializable(FullChatIdentifierSerializer::class) IdChatIdentifier> = emptyList(),
|
||||
) {
|
||||
val allTargetChatIds by lazy {
|
||||
listOfNotNull(targetChatId) + targetChatIds
|
||||
(listOfNotNull(targetChatId) + targetChatIds).toSet()
|
||||
}
|
||||
val allSourceChatIds by lazy {
|
||||
(listOfNotNull(sourceChatId) + sourceChatIds).toSet()
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -30,8 +35,8 @@ data class ChatConfig(
|
||||
}
|
||||
|
||||
fun check(chatId: IdChatIdentifier) = when (chatId) {
|
||||
targetChatId,
|
||||
sourceChatId,
|
||||
in allTargetChatIds,
|
||||
in allSourceChatIds,
|
||||
cacheChatId -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package dev.inmo.plaguposter.common
|
||||
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -11,7 +8,7 @@ import kotlinx.serialization.Serializable
|
||||
data class ShortMessageInfo(
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
val chatId: IdChatIdentifier,
|
||||
val messageId: MessageIdentifier
|
||||
val messageId: MessageId
|
||||
)
|
||||
|
||||
fun Message.short() = ShortMessageInfo(chat.id, messageId)
|
||||
|
||||
@@ -27,7 +27,7 @@ object CommonPlugin : Plugin {
|
||||
val config = koin.get<ChatConfig>()
|
||||
|
||||
Log.iS { "Target chats info: ${config.allTargetChatIds.map { getChat(it) }.joinToString()}" }
|
||||
Log.iS { "Source chat info: ${getChat(config.sourceChatId)}" }
|
||||
Log.iS { "Source chats info: ${config.allSourceChatIds.map { getChat(it) }.joinToString()}" }
|
||||
Log.iS { "Cache chat info: ${getChat(config.cacheChatId)}" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
kotlin.code.style=official
|
||||
org.gradle.jvmargs=-Xmx1024m
|
||||
org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
@@ -10,4 +9,4 @@ android.enableJetifier=true
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.5.2
|
||||
version=0.7.0
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
[versions]
|
||||
|
||||
kotlin = "1.9.21"
|
||||
kotlin-serialization = "1.6.2"
|
||||
kotlin = "2.0.20"
|
||||
kotlin-serialization = "1.7.2"
|
||||
|
||||
plagubot = "7.4.1"
|
||||
tgbotapi = "9.4.2"
|
||||
microutils = "0.20.19"
|
||||
kslog = "1.3.1"
|
||||
krontab = "2.2.4"
|
||||
plagubot-plugins = "0.17.1"
|
||||
plagubot = "9.2.0"
|
||||
tgbotapi = "18.1.0"
|
||||
microutils = "0.22.2"
|
||||
kslog = "1.3.6"
|
||||
krontab = "2.4.0"
|
||||
plagubot-plugins = "0.21.0"
|
||||
|
||||
dokka = "1.9.10"
|
||||
dokka = "1.9.20"
|
||||
|
||||
psql = "42.6.0"
|
||||
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -25,7 +25,6 @@ kotlin {
|
||||
jsTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.js
|
||||
implementation libs.kotlin.test.junit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,13 @@ project.group = "$group"
|
||||
apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
jvm {
|
||||
compilations.main {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
}
|
||||
}
|
||||
js (IR) {
|
||||
browser()
|
||||
nodejs()
|
||||
@@ -31,10 +37,14 @@ kotlin {
|
||||
jsTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.js
|
||||
implementation libs.kotlin.test.junit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
|
||||
@@ -104,10 +104,12 @@ object Plugin : Plugin {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
send(
|
||||
chatsConfig.sourceChatId,
|
||||
"Can't find any messages for post $postId. So, deleting it"
|
||||
)
|
||||
runCatching {
|
||||
send(
|
||||
chatsConfig.cacheChatId,
|
||||
"Can't find any messages for post $postId. So, deleting it"
|
||||
)
|
||||
}
|
||||
runCatching {
|
||||
postsRepo.deleteById(postId)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageId
|
||||
import dev.inmo.tgbotapi.types.ReplyParameters
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.ParseMode
|
||||
@@ -112,7 +113,7 @@ object Plugin : Plugin {
|
||||
firstContent.chatId,
|
||||
text = config.text,
|
||||
parseMode = config.parseMode,
|
||||
replyToMessageId = firstContent.messageId,
|
||||
replyParameters = ReplyParameters(firstContent.chatId, firstContent.messageId),
|
||||
replyMarkup = InlineKeyboardMarkup(buttons),
|
||||
disableNotification = true
|
||||
).also { sentMessage ->
|
||||
@@ -128,7 +129,7 @@ object Plugin : Plugin {
|
||||
suspend fun refreshPostMessage(
|
||||
postId: PostId,
|
||||
chatId: IdChatIdentifier,
|
||||
messageId: MessageIdentifier
|
||||
messageId: MessageId
|
||||
) {
|
||||
val post = postsRepo.getById(postId) ?: return
|
||||
val buttons = api.buttonsBuilders.chunked(config.buttonsPerRow).mapNotNull { row ->
|
||||
@@ -146,7 +147,7 @@ object Plugin : Plugin {
|
||||
|
||||
onMessageDataCallbackQuery (
|
||||
initialFilter = {
|
||||
it.data.startsWith(PanelButtonsAPI.openGlobalMenuDataPrefix) && it.message.chat.id == chatsConfig.sourceChatId
|
||||
it.data.startsWith(PanelButtonsAPI.openGlobalMenuDataPrefix) && it.message.chat.id in chatsConfig.allSourceChatIds
|
||||
}
|
||||
) {
|
||||
val postId = it.data.removePrefix(PanelButtonsAPI.openGlobalMenuDataPrefix).let(::PostId)
|
||||
@@ -155,7 +156,7 @@ object Plugin : Plugin {
|
||||
}
|
||||
onMessageDataCallbackQuery(
|
||||
initialFilter = {
|
||||
it.data.startsWith("delete ") && it.message.chat.id == chatsConfig.sourceChatId
|
||||
it.data.startsWith("delete ") && it.message.chat.id in chatsConfig.allSourceChatIds
|
||||
}
|
||||
) { query ->
|
||||
val postId = query.data.removePrefix("delete ").let(::PostId)
|
||||
@@ -182,7 +183,7 @@ object Plugin : Plugin {
|
||||
}
|
||||
onMessageDataCallbackQuery(
|
||||
initialFilter = {
|
||||
it.data.startsWith("refresh ") && it.message.chat.id == chatsConfig.sourceChatId
|
||||
it.data.startsWith("refresh ") && it.message.chat.id in chatsConfig.allSourceChatIds
|
||||
}
|
||||
) { query ->
|
||||
val postId = query.data.removePrefix("refresh ").let(::PostId)
|
||||
|
||||
@@ -4,21 +4,18 @@ import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.mappers.withMapper
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import kotlinx.serialization.builtins.PairSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
|
||||
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageIdentifier.serializer())
|
||||
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageId.serializer())
|
||||
|
||||
fun PostsMessages(
|
||||
database: Database,
|
||||
json: Json
|
||||
): KeyValueRepo<PostId, Pair<IdChatIdentifier, MessageIdentifier>> = ExposedKeyValueRepo<String, String>(
|
||||
): KeyValueRepo<PostId, Pair<IdChatIdentifier, MessageId>> = ExposedKeyValueRepo<String, String>(
|
||||
database,
|
||||
{ text("postId") },
|
||||
{ text("chatToMessage") },
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package dev.inmo.plaguposter.posts.models
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.utils.possiblyMediaGroupMessageOrNull
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -13,8 +10,8 @@ import kotlinx.serialization.Serializable
|
||||
data class PostContentInfo(
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
val chatId: IdChatIdentifier,
|
||||
val messageId: MessageIdentifier,
|
||||
val group: String?,
|
||||
val messageId: MessageId,
|
||||
val group: MediaGroupId?,
|
||||
val order: Int
|
||||
) {
|
||||
companion object {
|
||||
|
||||
@@ -5,10 +5,10 @@ import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageId
|
||||
|
||||
interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId> {
|
||||
suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId?
|
||||
suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageId): PostId?
|
||||
suspend fun getPostCreationTime(postId: PostId): DateTime?
|
||||
suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo?
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ object Plugin : Plugin {
|
||||
}
|
||||
single {
|
||||
val config = get<Config>()
|
||||
PostPublisher(get(), get(), config.chats.cacheChatId, config.chats.allTargetChatIds, config.deleteAfterPublishing)
|
||||
PostPublisher(get(), get(), config.chats.cacheChatId, config.chats.allTargetChatIds.toList(), config.deleteAfterPublishing)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.models.RegisteredPost
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageId
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@@ -34,7 +34,7 @@ class CachedPostsRepo(
|
||||
) {
|
||||
override val removedPostsFlow: Flow<RegisteredPost> by parentRepo::removedPostsFlow
|
||||
|
||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId? {
|
||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageId): PostId? {
|
||||
doForAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||
kvCache.values(it).also {
|
||||
it.results.forEach {
|
||||
|
||||
@@ -4,8 +4,7 @@ import com.benasher44.uuid.uuid4
|
||||
import dev.inmo.micro_utils.repos.KeyValuesRepo
|
||||
import dev.inmo.micro_utils.repos.exposed.*
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import org.jetbrains.exposed.sql.*
|
||||
|
||||
internal class ExposedContentInfoRepo(
|
||||
@@ -21,9 +20,9 @@ internal class ExposedContentInfoRepo(
|
||||
|
||||
val ResultRow.asObject
|
||||
get() = PostContentInfo(
|
||||
IdChatIdentifier(get(chatIdColumn), get(threadIdColumn)),
|
||||
get(messageIdColumn),
|
||||
get(groupColumn),
|
||||
IdChatIdentifier(RawChatId(get(chatIdColumn)), get(threadIdColumn) ?.let(::MessageThreadId)),
|
||||
MessageId(get(messageIdColumn)),
|
||||
get(groupColumn) ?.let(::MediaGroupId),
|
||||
get(orderColumn)
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,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.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageId
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.exposed.sql.*
|
||||
@@ -48,7 +48,7 @@ class ExposedPostsRepo(
|
||||
id,
|
||||
DateTime(get(createdColumn)),
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(id.string) }.map {
|
||||
selectAll().where { postIdColumn.eq(id.string) }.map {
|
||||
it.asObject
|
||||
}
|
||||
}
|
||||
@@ -69,14 +69,14 @@ class ExposedPostsRepo(
|
||||
id,
|
||||
DateTime(get(createdColumn)),
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(id.string) }.map {
|
||||
selectAll().where { postIdColumn.eq(id.string) }.map {
|
||||
it.asObject
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun createAndInsertId(value: NewPost, it: InsertStatement<Number>): PostId {
|
||||
override fun createAndInsertId(value: NewPost, it: UpdateBuilder<Int>): PostId {
|
||||
val id = PostId(uuid4().toString())
|
||||
it[idColumn] = id.string
|
||||
return id
|
||||
@@ -93,10 +93,10 @@ class ExposedPostsRepo(
|
||||
post.content.forEach { contentInfo ->
|
||||
insert {
|
||||
it[postIdColumn] = post.id.string
|
||||
it[chatIdColumn] = contentInfo.chatId.chatId
|
||||
it[threadIdColumn] = contentInfo.chatId.threadId
|
||||
it[messageIdColumn] = contentInfo.messageId
|
||||
it[groupColumn] = contentInfo.group
|
||||
it[chatIdColumn] = contentInfo.chatId.chatId.long
|
||||
it[threadIdColumn] = contentInfo.chatId.threadId ?.long
|
||||
it[messageIdColumn] = contentInfo.messageId.long
|
||||
it[groupColumn] = contentInfo.group ?.string
|
||||
it[orderColumn] = contentInfo.order
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class ExposedPostsRepo(
|
||||
}
|
||||
}
|
||||
|
||||
override fun insert(value: NewPost, it: InsertStatement<Number>) {
|
||||
override fun insert(value: NewPost, it: UpdateBuilder<Int>) {
|
||||
super.insert(value, it)
|
||||
it[createdColumn] = DateTime.now().unixMillis
|
||||
}
|
||||
@@ -144,7 +144,7 @@ class ExposedPostsRepo(
|
||||
existsIds
|
||||
} else {
|
||||
existsIds.filter {
|
||||
select { selectById(it) }.limit(1).none()
|
||||
selectAll().where { selectById(it) }.limit(1).none()
|
||||
}
|
||||
}
|
||||
}.forEach {
|
||||
@@ -153,25 +153,25 @@ class ExposedPostsRepo(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId? {
|
||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageId): PostId? {
|
||||
return transaction(database) {
|
||||
with(contentRepo) {
|
||||
select {
|
||||
chatIdColumn.eq(chatId.chatId)
|
||||
.and(chatId.threadId ?.let { threadIdColumn.eq(it) } ?: threadIdColumn.isNull())
|
||||
.and(messageIdColumn.eq(messageId))
|
||||
selectAll().where {
|
||||
chatIdColumn.eq(chatId.chatId.long)
|
||||
.and(chatId.threadId ?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull())
|
||||
.and(messageIdColumn.eq(messageId.long))
|
||||
}.limit(1).firstOrNull() ?.get(postIdColumn)
|
||||
} ?.let(::PostId)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPostCreationTime(postId: PostId): DateTime? = transaction(database) {
|
||||
select { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
|
||||
selectAll().where { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
|
||||
}
|
||||
|
||||
override suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo? = transaction(database) {
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(postId.string) }.limit(1).firstOrNull() ?.asObject
|
||||
selectAll().where { postIdColumn.eq(postId.string) }.limit(1).firstOrNull() ?.asObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,12 +119,12 @@ object Plugin : Plugin {
|
||||
null
|
||||
}
|
||||
|
||||
onCommand("start_post", initialFilter = { it.sameChat(config.sourceChatId) }) {
|
||||
onCommand("start_post", initialFilter = { config.allSourceChatIds.any { chatId -> it.sameChat(chatId) } }) {
|
||||
startChain(RegistrationState.InProcess(it.chat.id, emptyList()))
|
||||
}
|
||||
|
||||
onContentMessage(
|
||||
initialFilter = { it.sameChat(config.sourceChatId) && !FirstSourceIsCommandsFilter(it) }
|
||||
initialFilter = { config.allSourceChatIds.any { chatId -> it.sameChat(chatId) } && !FirstSourceIsCommandsFilter(it) }
|
||||
) {
|
||||
startChain(RegistrationState.Finish(it.chat.id, PostContentInfo.fromMessage(it)))
|
||||
}
|
||||
|
||||
@@ -5,15 +5,22 @@ import korlibs.time.seconds
|
||||
import dev.inmo.krontab.KrontabTemplate
|
||||
import dev.inmo.krontab.toSchedule
|
||||
import dev.inmo.krontab.utils.asFlowWithDelays
|
||||
import dev.inmo.kslog.common.KSLog
|
||||
import dev.inmo.kslog.common.i
|
||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.koin.singleWithRandomQualifier
|
||||
import dev.inmo.micro_utils.repos.*
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.plaguposter.ratings.models.Rating
|
||||
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
||||
import dev.inmo.tgbotapi.types.Seconds
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.*
|
||||
@@ -59,12 +66,23 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
config.autoclear ?.let { autoclear ->
|
||||
val autoClearLogger = KSLog("autoclear")
|
||||
suspend fun doAutoClear() {
|
||||
autoClearLogger.i { "Start autoclear" }
|
||||
val dropCreatedBefore = DateTime.now() - (autoclear.skipPostAge ?: 0).seconds
|
||||
ratingsRepo.getPostsWithRatingLessEq(autoclear.rating).keys.forEach {
|
||||
if ((postsRepo.getPostCreationTime(it) ?: return@forEach) < dropCreatedBefore) {
|
||||
postsRepo.deleteById(it)
|
||||
}
|
||||
autoClearLogger.i { "Posts drop created before: ${dropCreatedBefore.toStringDefault()}" }
|
||||
val idsToDelete = ratingsRepo.getPostsWithRatingLessEq(autoclear.rating).keys.also {
|
||||
autoClearLogger.i { "Selected posts by rating: $it" }
|
||||
}.filter {
|
||||
val postCreationDateTime = postsRepo.getPostCreationTime(it) ?: (dropCreatedBefore - 1.seconds) // do dropping if post creation time is not available
|
||||
postCreationDateTime < dropCreatedBefore
|
||||
}
|
||||
autoClearLogger.i { "Filtered posts by datetime: $idsToDelete" }
|
||||
if (idsToDelete.isNotEmpty()) {
|
||||
runCatching { ratingsRepo.unset(idsToDelete) }
|
||||
autoClearLogger.i { "Ratings dropped" }
|
||||
runCatching { postsRepo.deleteById(idsToDelete) }
|
||||
autoClearLogger.i { "Posts dropped" }
|
||||
}
|
||||
}
|
||||
runCatchingSafely {
|
||||
@@ -73,6 +91,13 @@ object Plugin : Plugin {
|
||||
autoclear.autoClearKrontab.toSchedule().asFlowWithDelays().subscribeSafelyWithoutExceptions(scope) {
|
||||
doAutoClear()
|
||||
}
|
||||
|
||||
onCommand("clean_posts_by_ratings") {
|
||||
doAutoClear()
|
||||
}
|
||||
koin.getOrNull<InlineTemplatesRepo>() ?.addTemplate(
|
||||
OfferTemplate("Force autoclear", listOf(Format("/clean_posts_by_ratings")))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ suspend fun BehaviourContext.includeRootNavigationButtonsHandler(
|
||||
|
||||
edit(
|
||||
it.message,
|
||||
onPageUpdate(SimplePagination(page, size), args.drop(3).toTypedArray()) ?: return@runCatchingSafely
|
||||
replyMarkup = onPageUpdate(SimplePagination(page, size), args.drop(3).toTypedArray()) ?: return@runCatchingSafely
|
||||
)
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ suspend fun BehaviourContext.includeRootNavigationButtonsHandler(
|
||||
if (prefix == RootButtonsShowRatingData) {
|
||||
runCatchingSafely {
|
||||
val rating = ratingRaw.toDoubleOrNull() ?: return@runCatchingSafely
|
||||
edit(it.message, ratingsRepo.buildRatingButtons(postsRepo, Rating(rating)))
|
||||
edit(it.message, replyMarkup = ratingsRepo.buildRatingButtons(postsRepo, Rating(rating)))
|
||||
}
|
||||
|
||||
answer(it)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package dev.inmo.plaguposter.ratings.source.repos
|
||||
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.MapKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
||||
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||
import dev.inmo.tgbotapi.types.PollId
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
class CachedPollsToMessagesInfoRepo(
|
||||
private val repo: PollsToMessagesInfoRepo,
|
||||
private val scope: CoroutineScope,
|
||||
private val kvCache: FullKVCache<PollIdentifier, ShortMessageInfo> = FullKVCache()
|
||||
) : PollsToMessagesInfoRepo, KeyValueRepo<PollIdentifier, ShortMessageInfo> by repo.fullyCached(kvCache, scope)
|
||||
private val kvCache: KeyValueRepo<PollId, ShortMessageInfo> = MapKeyValueRepo()
|
||||
) : PollsToMessagesInfoRepo, KeyValueRepo<PollId, ShortMessageInfo> by repo.fullyCached(kvCache, scope)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package dev.inmo.plaguposter.ratings.source.repos
|
||||
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.MapKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||
import dev.inmo.tgbotapi.types.PollId
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
class CachedPollsToPostsIdsRepo(
|
||||
private val repo: PollsToPostsIdsRepo,
|
||||
private val scope: CoroutineScope,
|
||||
private val kvCache: FullKVCache<PollIdentifier, PostId> = FullKVCache()
|
||||
) : PollsToPostsIdsRepo, KeyValueRepo<PollIdentifier, PostId> by repo.fullyCached(kvCache, scope)
|
||||
private val kvCache: KeyValueRepo<PollId, PostId> = MapKeyValueRepo()
|
||||
) : PollsToPostsIdsRepo, KeyValueRepo<PollId, PostId> by repo.fullyCached(kvCache, scope)
|
||||
|
||||
@@ -3,6 +3,6 @@ package dev.inmo.plaguposter.ratings.source.repos
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||
import dev.inmo.tgbotapi.types.PollId
|
||||
|
||||
interface PollsToMessagesInfoRepo : KeyValueRepo<PollIdentifier, ShortMessageInfo>
|
||||
interface PollsToMessagesInfoRepo : KeyValueRepo<PollId, ShortMessageInfo>
|
||||
|
||||
@@ -2,6 +2,6 @@ package dev.inmo.plaguposter.ratings.source.repos
|
||||
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||
import dev.inmo.tgbotapi.types.PollId
|
||||
|
||||
interface PollsToPostsIdsRepo : KeyValueRepo<PollIdentifier, PostId>
|
||||
interface PollsToPostsIdsRepo : KeyValueRepo<PollId, PostId>
|
||||
|
||||
@@ -28,6 +28,7 @@ import dev.inmo.plaguposter.ratings.utils.postsByRatings
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll
|
||||
import dev.inmo.tgbotapi.extensions.api.send.reply
|
||||
import dev.inmo.tgbotapi.extensions.api.send.send
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
@@ -37,10 +38,14 @@ import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard
|
||||
import dev.inmo.tgbotapi.types.ReplyParameters
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.message.textsources.bold
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import dev.inmo.tgbotapi.types.polls.InputPollOption
|
||||
import dev.inmo.tgbotapi.types.polls.PollOption
|
||||
import dev.inmo.tgbotapi.utils.buildEntities
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeSourceString
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -111,7 +116,7 @@ object Plugin : Plugin {
|
||||
onPollUpdates (markerFactory = { it.id }) { poll ->
|
||||
val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates
|
||||
val newRating = poll.options.sumOf {
|
||||
(variantsTransformer(it.text) ?.double ?.times(it.votes)) ?: 0.0
|
||||
(variantsTransformer(it.textSources.makeSourceString()) ?.double ?.times(it.votes)) ?: 0.0
|
||||
}
|
||||
ratingsRepo.set(postId, Rating(newRating))
|
||||
}
|
||||
@@ -128,8 +133,10 @@ object Plugin : Plugin {
|
||||
val sent = send(
|
||||
content.chatId,
|
||||
config.ratingOfferText,
|
||||
config.variants.keys.toList(),
|
||||
replyToMessageId = content.messageId
|
||||
options = config.variants.map {
|
||||
InputPollOption(it.key)
|
||||
},
|
||||
replyParameters = ReplyParameters(content.chatId, content.messageId)
|
||||
)
|
||||
pollsToPostsIdsRepo.set(sent.content.poll.id, postId)
|
||||
pollsToMessageInfoRepo.set(sent.content.poll.id, sent.short())
|
||||
@@ -242,7 +249,7 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
onCommand("ratings", requireOnlyCommandInMessage = true) {
|
||||
if (it.chat.id == chatConfig.sourceChatId) {
|
||||
if (it.chat.id in chatConfig.allSourceChatIds) {
|
||||
val ratings = ratingsRepo.postsByRatings().toList().sortedByDescending { it.first }
|
||||
val textSources = buildEntities {
|
||||
+ "Ratings amount: " + bold("${ratings.sumOf { it.second.size }}") + "\n\n"
|
||||
@@ -260,11 +267,11 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
includeRootNavigationButtonsHandler(setOf(chatConfig.sourceChatId), ratingsRepo, postsRepo)
|
||||
onMessageDataCallbackQuery("ratings_interactive", initialFilter = { it.message.chat.id == chatConfig.sourceChatId }) {
|
||||
includeRootNavigationButtonsHandler(chatConfig.allSourceChatIds, ratingsRepo, postsRepo)
|
||||
onMessageDataCallbackQuery("ratings_interactive", initialFilter = { it.message.chat.id in chatConfig.allSourceChatIds }) {
|
||||
edit(
|
||||
it.message,
|
||||
ratingsRepo.buildRootButtons()
|
||||
replyMarkup = ratingsRepo.buildRootButtons()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@ package dev.inmo.plaguposter.ratings.source.repos
|
||||
import dev.inmo.micro_utils.repos.exposed.initTable
|
||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
||||
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
|
||||
@@ -13,7 +11,7 @@ import org.jetbrains.exposed.sql.statements.*
|
||||
|
||||
class ExposedPollsToMessagesInfoRepo(
|
||||
database: Database
|
||||
) : PollsToMessagesInfoRepo, AbstractExposedKeyValueRepo<PollIdentifier, ShortMessageInfo>(
|
||||
) : PollsToMessagesInfoRepo, AbstractExposedKeyValueRepo<PollId, ShortMessageInfo>(
|
||||
database,
|
||||
"polls_to_their_messages_info"
|
||||
) {
|
||||
@@ -21,31 +19,32 @@ class ExposedPollsToMessagesInfoRepo(
|
||||
private val chatIdColumn = long("chat_id")
|
||||
private val threadIdColumn = long("thread_id").nullable().default(null)
|
||||
private val messageIdColumn = long("message_id")
|
||||
override val selectById: ISqlExpressionBuilder.(PollIdentifier) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||
override val selectById: ISqlExpressionBuilder.(PollId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||
override val selectByValue: ISqlExpressionBuilder.(ShortMessageInfo) -> Op<Boolean> = {
|
||||
chatIdColumn.eq(it.chatId.chatId).and(it.chatId.threadId ?.let { threadIdColumn.eq(it) } ?: threadIdColumn.isNull()).and(
|
||||
messageIdColumn.eq(it.messageId)
|
||||
chatIdColumn.eq(it.chatId.chatId.long)
|
||||
.and(it.chatId.threadId?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull()).and(
|
||||
messageIdColumn.eq(it.messageId.long)
|
||||
)
|
||||
}
|
||||
override val ResultRow.asKey: PollIdentifier
|
||||
get() = get(keyColumn)
|
||||
override val ResultRow.asKey: PollId
|
||||
get() = PollId(get(keyColumn))
|
||||
override val ResultRow.asObject: ShortMessageInfo
|
||||
get() = ShortMessageInfo(
|
||||
IdChatIdentifier(get(chatIdColumn), get(threadIdColumn)),
|
||||
get(messageIdColumn)
|
||||
IdChatIdentifier(RawChatId(get(chatIdColumn)), get(threadIdColumn) ?.let(::MessageThreadId)),
|
||||
MessageId(get(messageIdColumn))
|
||||
)
|
||||
|
||||
init {
|
||||
initTable()
|
||||
}
|
||||
|
||||
override fun update(k: PollIdentifier, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
||||
it[chatIdColumn] = v.chatId.chatId
|
||||
it[threadIdColumn] = v.chatId.threadId
|
||||
it[messageIdColumn] = v.messageId
|
||||
override fun update(k: PollId, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
||||
it[chatIdColumn] = v.chatId.chatId.long
|
||||
it[threadIdColumn] = v.chatId.threadId ?.long
|
||||
it[messageIdColumn] = v.messageId.long
|
||||
}
|
||||
|
||||
override fun insertKey(k: PollIdentifier, v: ShortMessageInfo, it: InsertStatement<Number>) {
|
||||
it[keyColumn] = k
|
||||
override fun insertKey(k: PollId, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,19 @@ package dev.inmo.plaguposter.ratings.source.repos
|
||||
import dev.inmo.micro_utils.repos.exposed.initTable
|
||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||
import dev.inmo.tgbotapi.types.PollId
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
|
||||
class ExposedPollsToPostsIdsRepo(
|
||||
database: Database
|
||||
) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo<PollIdentifier, PostId>(database, "polls_to_posts") {
|
||||
) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo<PollId, PostId>(database, "polls_to_posts") {
|
||||
override val keyColumn = text("poll_id")
|
||||
val postIdColumn = text("postId")
|
||||
override val selectById: ISqlExpressionBuilder.(PollIdentifier) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||
override val selectById: ISqlExpressionBuilder.(PollId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||
override val selectByValue: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { postIdColumn.eq(it.string) }
|
||||
override val ResultRow.asKey: PollIdentifier
|
||||
get() = get(keyColumn)
|
||||
override val ResultRow.asKey: PollId
|
||||
get() = PollId(get(keyColumn))
|
||||
override val ResultRow.asObject: PostId
|
||||
get() = get(postIdColumn).let(::PostId)
|
||||
|
||||
@@ -23,11 +23,11 @@ class ExposedPollsToPostsIdsRepo(
|
||||
initTable()
|
||||
}
|
||||
|
||||
override fun update(k: PollIdentifier, v: PostId, it: UpdateBuilder<Int>) {
|
||||
override fun update(k: PollId, v: PostId, it: UpdateBuilder<Int>) {
|
||||
it[postIdColumn] = v.string
|
||||
}
|
||||
|
||||
override fun insertKey(k: PollIdentifier, v: PostId, it: InsertStatement<Number>) {
|
||||
it[keyColumn] = k
|
||||
override fun insertKey(k: PollId, v: PostId, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package dev.inmo.plaguposter.ratings.repo
|
||||
|
||||
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
||||
import dev.inmo.micro_utils.pagination.utils.optionallyReverse
|
||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||
import dev.inmo.micro_utils.repos.MapKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.cache.full.FullKeyValueCacheRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.ratings.models.Rating
|
||||
@@ -11,28 +13,32 @@ import kotlinx.coroutines.CoroutineScope
|
||||
class CachedRatingsRepo(
|
||||
private val base: RatingsRepo,
|
||||
private val scope: CoroutineScope,
|
||||
private val kvCache: FullKVCache<PostId, Rating> = FullKVCache()
|
||||
private val kvCache: MapKeyValueRepo<PostId, Rating> = MapKeyValueRepo()
|
||||
) : RatingsRepo, KeyValueRepo<PostId, Rating> by FullKeyValueCacheRepo(base, kvCache, scope) {
|
||||
private suspend fun getPosts(
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>,
|
||||
ratingFilter: (Rating) -> Boolean
|
||||
): Map<PostId, Rating> {
|
||||
return kvCache.getAll().filter { (it, rating) ->
|
||||
it !in exclude && ratingFilter(rating)
|
||||
}.let {
|
||||
if (count == null) {
|
||||
it
|
||||
} else {
|
||||
val keys = it.keys.optionallyReverse(reversed).take(count)
|
||||
keys.associateWith { id -> it.getValue(id) }
|
||||
}
|
||||
}
|
||||
}
|
||||
override suspend fun getPosts(
|
||||
range: ClosedRange<Rating>,
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> {
|
||||
val result = mutableMapOf<PostId, Rating>()
|
||||
|
||||
doForAllWithNextPaging {
|
||||
kvCache.keys(it).also {
|
||||
it.results.forEach {
|
||||
val rating = get(it) ?: return@forEach
|
||||
if (it !in exclude && rating in range) {
|
||||
result[it] = rating
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.toMap()
|
||||
): Map<PostId, Rating> = getPosts(reversed, count, exclude) {
|
||||
it in range
|
||||
}
|
||||
|
||||
override suspend fun getPostsWithRatingGreaterEq(
|
||||
@@ -40,22 +46,16 @@ class CachedRatingsRepo(
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> = getPosts(
|
||||
then .. Rating(Double.MAX_VALUE),
|
||||
reversed,
|
||||
count,
|
||||
exclude
|
||||
)
|
||||
): Map<PostId, Rating> = getPosts(reversed, count, exclude) {
|
||||
it >= then
|
||||
}
|
||||
|
||||
override suspend fun getPostsWithRatingLessEq(
|
||||
then: Rating,
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> = getPosts(
|
||||
Rating(Double.MIN_VALUE) .. then,
|
||||
reversed,
|
||||
count,
|
||||
exclude
|
||||
)
|
||||
): Map<PostId, Rating> = getPosts(reversed, count, exclude) {
|
||||
it <= then
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import dev.inmo.micro_utils.koin.singleWithBinds
|
||||
import dev.inmo.micro_utils.repos.unset
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.common.useCache
|
||||
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.*
|
||||
@@ -14,7 +13,6 @@ 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) {
|
||||
|
||||
@@ -33,7 +33,7 @@ class ExposedRatingsRepo (
|
||||
it[ratingsColumn] = v.double
|
||||
}
|
||||
|
||||
override fun insertKey(k: PostId, v: Rating, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PostId, v: Rating, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class ExposedRatingsRepo (
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> = transaction(database) {
|
||||
select {
|
||||
selectAll().where {
|
||||
ratingsColumn.greaterEq(range.start.double).and(
|
||||
ratingsColumn.lessEq(range.endInclusive.double)
|
||||
).and(
|
||||
@@ -66,7 +66,7 @@ class ExposedRatingsRepo (
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
) = transaction(database) {
|
||||
select { ratingsColumn.greaterEq(then.double).and(keyColumn.notInList(exclude.map { it.string })) }.optionallyLimit(count).optionallyReverse(reversed).map {
|
||||
selectAll().where { ratingsColumn.greaterEq(then.double).and(keyColumn.notInList(exclude.map { it.string })) }.optionallyLimit(count).optionallyReverse(reversed).map {
|
||||
it.asKey to it.asObject
|
||||
}
|
||||
}.toMap()
|
||||
@@ -77,7 +77,7 @@ class ExposedRatingsRepo (
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> = transaction(database) {
|
||||
select { ratingsColumn.lessEq(then.double).and(keyColumn.notInList(exclude.map { it.string })) }.optionallyLimit(count).optionallyReverse(reversed).map {
|
||||
selectAll().where { ratingsColumn.lessEq(then.double).and(keyColumn.notInList(exclude.map { it.string })) }.optionallyLimit(count).optionallyReverse(reversed).map {
|
||||
it.asKey to it.asObject
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
@@ -15,7 +15,7 @@ function assert_success() {
|
||||
|
||||
app=plaguposter
|
||||
version="`grep ../gradle.properties -e "^version=" | sed -e "s/version=\(.*\)/\1/"`"
|
||||
server=insanusmokrassar
|
||||
server=docker.inmo.dev
|
||||
|
||||
assert_success ../gradlew build
|
||||
assert_success sudo docker build -t $app:"$version" .
|
||||
|
||||
@@ -24,7 +24,7 @@ import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageId
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import kotlinx.coroutines.flow.first
|
||||
@@ -38,8 +38,8 @@ object Plugin : Plugin {
|
||||
@Serializable
|
||||
private data class PublishState(
|
||||
override val context: ChatId,
|
||||
val sourceMessageId: MessageIdentifier,
|
||||
val messageInReply: MessageIdentifier
|
||||
val sourceMessageId: MessageId,
|
||||
val messageInReply: MessageId
|
||||
) : State
|
||||
@Serializable
|
||||
internal data class Config(
|
||||
|
||||
@@ -151,7 +151,7 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
onCommand("autoschedule_panel", initialFilter = { it.sameChat(chatConfig.sourceChatId) }) {
|
||||
onCommand("autoschedule_panel", initialFilter = { chatConfig.allSourceChatIds.any { chatId -> it.sameChat(chatId) } }) {
|
||||
val keyboard = buildPage()
|
||||
|
||||
runCatchingSafely {
|
||||
@@ -167,7 +167,7 @@ object Plugin : Plugin {
|
||||
|
||||
onMessageDataCallbackQuery(
|
||||
Regex("^$pageCallbackDataQueryPrefix\\d+"),
|
||||
initialFilter = { it.message.sameChat(chatConfig.sourceChatId) }
|
||||
initialFilter = { chatConfig.allSourceChatIds.any { sourceChatId -> it.message.sameChat(sourceChatId) } }
|
||||
) {
|
||||
val page = it.data.removePrefix(pageCallbackDataQueryPrefix).toIntOrNull() ?: let { _ ->
|
||||
answer(it)
|
||||
|
||||
@@ -7,6 +7,7 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.repos.unset
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||
import korlibs.time.millisecondsLong
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@@ -50,7 +50,7 @@ class ExposedTimersRepo(
|
||||
it[dateTimeColumn] = v.unixMillisLong
|
||||
}
|
||||
|
||||
override fun insertKey(k: PostId, v: DateTime, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PostId, v: DateTime, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user