mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2026-01-08 13:09:12 +00:00
Compare commits
18 Commits
0.5.0
...
b6fa2a6cd3
| Author | SHA1 | Date | |
|---|---|---|---|
| b6fa2a6cd3 | |||
| e24237beb3 | |||
| d2d3665c5e | |||
| 9ef9de2b8a | |||
| cef350667b | |||
| 80ed679241 | |||
| 39391636ac | |||
| 29a19df7fc | |||
| 250f88e2fe | |||
| bb433a6441 | |||
| 7a8166153f | |||
| 114add0391 | |||
| 58b1f26502 | |||
| ba3d054f0f | |||
| eef2bfce14 | |||
| fe96101631 | |||
| 7abb6efba3 | |||
| 2f0a823f7c |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,5 +1,25 @@
|
|||||||
# PlaguPoster
|
# PlaguPoster
|
||||||
|
|
||||||
|
## 0.5.5
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.5.4
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.5.3
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.5.2
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.5.1
|
||||||
|
|
||||||
|
* Add opportunity to set unique
|
||||||
|
|
||||||
## 0.5.0
|
## 0.5.0
|
||||||
|
|
||||||
* Dependencies update
|
* Dependencies update
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ allprojects {
|
|||||||
mavenLocal()
|
mavenLocal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
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,
|
val targetChatId: IdChatIdentifier? = null,
|
||||||
@SerialName("sourceChat")
|
@SerialName("sourceChat")
|
||||||
@Serializable(FullChatIdentifierSerializer::class)
|
@Serializable(FullChatIdentifierSerializer::class)
|
||||||
val sourceChatId: IdChatIdentifier,
|
val sourceChatId: IdChatIdentifier?,
|
||||||
@SerialName("cacheChat")
|
@SerialName("cacheChat")
|
||||||
@Serializable(FullChatIdentifierSerializer::class)
|
@Serializable(FullChatIdentifierSerializer::class)
|
||||||
val cacheChatId: IdChatIdentifier,
|
val cacheChatId: IdChatIdentifier,
|
||||||
@SerialName("targetChats")
|
@SerialName("targetChats")
|
||||||
val targetChatIds: List<@Serializable(FullChatIdentifierSerializer::class) IdChatIdentifier> = emptyList(),
|
val targetChatIds: List<@Serializable(FullChatIdentifierSerializer::class) IdChatIdentifier> = emptyList(),
|
||||||
|
@SerialName("sourceChats")
|
||||||
|
val sourceChatIds: List<@Serializable(FullChatIdentifierSerializer::class) IdChatIdentifier> = emptyList(),
|
||||||
) {
|
) {
|
||||||
val allTargetChatIds by lazy {
|
val allTargetChatIds by lazy {
|
||||||
listOfNotNull(targetChatId) + targetChatIds
|
(listOfNotNull(targetChatId) + targetChatIds).toSet()
|
||||||
|
}
|
||||||
|
val allSourceChatIds by lazy {
|
||||||
|
(listOfNotNull(sourceChatId) + sourceChatIds).toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -30,8 +35,8 @@ data class ChatConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun check(chatId: IdChatIdentifier) = when (chatId) {
|
fun check(chatId: IdChatIdentifier) = when (chatId) {
|
||||||
targetChatId,
|
in allTargetChatIds,
|
||||||
sourceChatId,
|
in allSourceChatIds,
|
||||||
cacheChatId -> true
|
cacheChatId -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package dev.inmo.plaguposter.common
|
package dev.inmo.plaguposter.common
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
|
||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -11,7 +8,7 @@ import kotlinx.serialization.Serializable
|
|||||||
data class ShortMessageInfo(
|
data class ShortMessageInfo(
|
||||||
@Serializable(FullChatIdentifierSerializer::class)
|
@Serializable(FullChatIdentifierSerializer::class)
|
||||||
val chatId: IdChatIdentifier,
|
val chatId: IdChatIdentifier,
|
||||||
val messageId: MessageIdentifier
|
val messageId: MessageId
|
||||||
)
|
)
|
||||||
|
|
||||||
fun Message.short() = ShortMessageInfo(chat.id, messageId)
|
fun Message.short() = ShortMessageInfo(chat.id, messageId)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ object CommonPlugin : Plugin {
|
|||||||
val config = koin.get<ChatConfig>()
|
val config = koin.get<ChatConfig>()
|
||||||
|
|
||||||
Log.iS { "Target chats info: ${config.allTargetChatIds.map { getChat(it) }.joinToString()}" }
|
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)}" }
|
Log.iS { "Cache chat info: ${getChat(config.cacheChatId)}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ android.enableJetifier=true
|
|||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.5.0
|
version=0.5.5
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kotlin = "1.9.20"
|
kotlin = "1.9.23"
|
||||||
kotlin-serialization = "1.6.0"
|
kotlin-serialization = "1.6.3"
|
||||||
|
|
||||||
plagubot = "7.3.0"
|
plagubot = "8.3.0"
|
||||||
tgbotapi = "9.3.0"
|
tgbotapi = "12.0.1"
|
||||||
microutils = "0.20.12"
|
microutils = "0.20.45"
|
||||||
kslog = "1.2.4"
|
kslog = "1.3.3"
|
||||||
krontab = "2.2.3"
|
krontab = "2.2.9"
|
||||||
plagubot-plugins = "0.16.0"
|
plagubot-plugins = "0.18.3"
|
||||||
|
|
||||||
dokka = "1.9.10"
|
dokka = "1.9.20"
|
||||||
|
|
||||||
psql = "42.6.0"
|
psql = "42.6.0"
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import dev.inmo.micro_utils.coroutines.actor
|
|||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
import dev.inmo.micro_utils.repos.deleteById
|
import dev.inmo.micro_utils.repos.deleteById
|
||||||
import dev.inmo.plagubot.Plugin
|
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.common.ChatConfig
|
import dev.inmo.plaguposter.common.ChatConfig
|
||||||
import dev.inmo.plaguposter.posts.models.NewPost
|
import dev.inmo.plaguposter.posts.models.NewPost
|
||||||
import dev.inmo.plaguposter.posts.models.PostContentInfo
|
import dev.inmo.plaguposter.posts.models.PostContentInfo
|
||||||
@@ -20,7 +23,10 @@ import dev.inmo.tgbotapi.extensions.api.edit.edit
|
|||||||
import dev.inmo.tgbotapi.extensions.api.forwardMessage
|
import dev.inmo.tgbotapi.extensions.api.forwardMessage
|
||||||
import dev.inmo.tgbotapi.extensions.api.send.send
|
import dev.inmo.tgbotapi.extensions.api.send.send
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitInlineMessageIdDataCallbackQuery
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitMessageDataCallbackQuery
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitMessageDataCallbackQuery
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.oneOf
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.parallel
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
||||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
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.dataButton
|
||||||
@@ -98,10 +104,12 @@ object Plugin : Plugin {
|
|||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
send(
|
runCatching {
|
||||||
chatsConfig.sourceChatId,
|
send(
|
||||||
"Can't find any messages for post $postId. So, deleting it"
|
chatsConfig.cacheChatId,
|
||||||
)
|
"Can't find any messages for post $postId. So, deleting it"
|
||||||
|
)
|
||||||
|
}
|
||||||
runCatching {
|
runCatching {
|
||||||
postsRepo.deleteById(postId)
|
postsRepo.deleteById(postId)
|
||||||
}
|
}
|
||||||
@@ -147,9 +155,18 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
val answer = waitMessageDataCallbackQuery().filter {
|
val answer = oneOf(
|
||||||
it.message.sameMessage(message)
|
parallel {
|
||||||
}.first()
|
waitMessageDataCallbackQuery().filter {
|
||||||
|
it.message.sameMessage(message)
|
||||||
|
}.first()
|
||||||
|
},
|
||||||
|
parallel {
|
||||||
|
waitInlineMessageIdDataCallbackQuery().filter {
|
||||||
|
it.data == yesData || it.data == noData
|
||||||
|
}.first()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (answer.data == yesData) {
|
if (answer.data == yesData) {
|
||||||
if (recheckActor.trySend(Unit).isSuccess) {
|
if (recheckActor.trySend(Unit).isSuccess) {
|
||||||
@@ -164,5 +181,14 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
koin.getOrNull<InlineTemplatesRepo>() ?.addTemplate(
|
||||||
|
OfferTemplate(
|
||||||
|
"Force posts check",
|
||||||
|
listOf(
|
||||||
|
Format("/force_garbage_collection")
|
||||||
|
),
|
||||||
|
"Force check posts without exists messages"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.dataButton
|
||||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
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.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||||
import dev.inmo.tgbotapi.types.message.ParseMode
|
import dev.inmo.tgbotapi.types.message.ParseMode
|
||||||
@@ -112,7 +113,7 @@ object Plugin : Plugin {
|
|||||||
firstContent.chatId,
|
firstContent.chatId,
|
||||||
text = config.text,
|
text = config.text,
|
||||||
parseMode = config.parseMode,
|
parseMode = config.parseMode,
|
||||||
replyToMessageId = firstContent.messageId,
|
replyParameters = ReplyParameters(firstContent.chatId, firstContent.messageId),
|
||||||
replyMarkup = InlineKeyboardMarkup(buttons),
|
replyMarkup = InlineKeyboardMarkup(buttons),
|
||||||
disableNotification = true
|
disableNotification = true
|
||||||
).also { sentMessage ->
|
).also { sentMessage ->
|
||||||
@@ -128,7 +129,7 @@ object Plugin : Plugin {
|
|||||||
suspend fun refreshPostMessage(
|
suspend fun refreshPostMessage(
|
||||||
postId: PostId,
|
postId: PostId,
|
||||||
chatId: IdChatIdentifier,
|
chatId: IdChatIdentifier,
|
||||||
messageId: MessageIdentifier
|
messageId: MessageId
|
||||||
) {
|
) {
|
||||||
val post = postsRepo.getById(postId) ?: return
|
val post = postsRepo.getById(postId) ?: return
|
||||||
val buttons = api.buttonsBuilders.chunked(config.buttonsPerRow).mapNotNull { row ->
|
val buttons = api.buttonsBuilders.chunked(config.buttonsPerRow).mapNotNull { row ->
|
||||||
@@ -146,7 +147,7 @@ object Plugin : Plugin {
|
|||||||
|
|
||||||
onMessageDataCallbackQuery (
|
onMessageDataCallbackQuery (
|
||||||
initialFilter = {
|
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)
|
val postId = it.data.removePrefix(PanelButtonsAPI.openGlobalMenuDataPrefix).let(::PostId)
|
||||||
@@ -155,7 +156,7 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
onMessageDataCallbackQuery(
|
onMessageDataCallbackQuery(
|
||||||
initialFilter = {
|
initialFilter = {
|
||||||
it.data.startsWith("delete ") && it.message.chat.id == chatsConfig.sourceChatId
|
it.data.startsWith("delete ") && it.message.chat.id in chatsConfig.allSourceChatIds
|
||||||
}
|
}
|
||||||
) { query ->
|
) { query ->
|
||||||
val postId = query.data.removePrefix("delete ").let(::PostId)
|
val postId = query.data.removePrefix("delete ").let(::PostId)
|
||||||
@@ -182,7 +183,7 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
onMessageDataCallbackQuery(
|
onMessageDataCallbackQuery(
|
||||||
initialFilter = {
|
initialFilter = {
|
||||||
it.data.startsWith("refresh ") && it.message.chat.id == chatsConfig.sourceChatId
|
it.data.startsWith("refresh ") && it.message.chat.id in chatsConfig.allSourceChatIds
|
||||||
}
|
}
|
||||||
) { query ->
|
) { query ->
|
||||||
val postId = query.data.removePrefix("refresh ").let(::PostId)
|
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.exposed.keyvalue.ExposedKeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.mappers.withMapper
|
import dev.inmo.micro_utils.repos.mappers.withMapper
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
|
||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
|
||||||
import kotlinx.serialization.builtins.PairSerializer
|
import kotlinx.serialization.builtins.PairSerializer
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
|
||||||
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageIdentifier.serializer())
|
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageId.serializer())
|
||||||
|
|
||||||
fun PostsMessages(
|
fun PostsMessages(
|
||||||
database: Database,
|
database: Database,
|
||||||
json: Json
|
json: Json
|
||||||
): KeyValueRepo<PostId, Pair<IdChatIdentifier, MessageIdentifier>> = ExposedKeyValueRepo<String, String>(
|
): KeyValueRepo<PostId, Pair<IdChatIdentifier, MessageId>> = ExposedKeyValueRepo<String, String>(
|
||||||
database,
|
database,
|
||||||
{ text("postId") },
|
{ text("postId") },
|
||||||
{ text("chatToMessage") },
|
{ text("chatToMessage") },
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package dev.inmo.plaguposter.posts.models
|
package dev.inmo.plaguposter.posts.models
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.extensions.utils.possiblyMediaGroupMessageOrNull
|
import dev.inmo.tgbotapi.extensions.utils.possiblyMediaGroupMessageOrNull
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
|
||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||||
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
|
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -13,8 +10,8 @@ import kotlinx.serialization.Serializable
|
|||||||
data class PostContentInfo(
|
data class PostContentInfo(
|
||||||
@Serializable(FullChatIdentifierSerializer::class)
|
@Serializable(FullChatIdentifierSerializer::class)
|
||||||
val chatId: IdChatIdentifier,
|
val chatId: IdChatIdentifier,
|
||||||
val messageId: MessageIdentifier,
|
val messageId: MessageId,
|
||||||
val group: String?,
|
val group: MediaGroupId?,
|
||||||
val order: Int
|
val order: Int
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
|||||||
import dev.inmo.plaguposter.posts.models.*
|
import dev.inmo.plaguposter.posts.models.*
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
import dev.inmo.tgbotapi.types.MessageId
|
||||||
|
|
||||||
interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId> {
|
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 getPostCreationTime(postId: PostId): DateTime?
|
||||||
suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo?
|
suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
single {
|
single {
|
||||||
val config = get<Config>()
|
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.models.RegisteredPost
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
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.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ class CachedPostsRepo(
|
|||||||
) {
|
) {
|
||||||
override val removedPostsFlow: Flow<RegisteredPost> by parentRepo::removedPostsFlow
|
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) {
|
doForAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||||
kvCache.values(it).also {
|
kvCache.values(it).also {
|
||||||
it.results.forEach {
|
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.KeyValuesRepo
|
||||||
import dev.inmo.micro_utils.repos.exposed.*
|
import dev.inmo.micro_utils.repos.exposed.*
|
||||||
import dev.inmo.plaguposter.posts.models.*
|
import dev.inmo.plaguposter.posts.models.*
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
|
|
||||||
internal class ExposedContentInfoRepo(
|
internal class ExposedContentInfoRepo(
|
||||||
@@ -21,9 +20,9 @@ internal class ExposedContentInfoRepo(
|
|||||||
|
|
||||||
val ResultRow.asObject
|
val ResultRow.asObject
|
||||||
get() = PostContentInfo(
|
get() = PostContentInfo(
|
||||||
IdChatIdentifier(get(chatIdColumn), get(threadIdColumn)),
|
IdChatIdentifier(RawChatId(get(chatIdColumn)), get(threadIdColumn) ?.let(::MessageThreadId)),
|
||||||
get(messageIdColumn),
|
MessageId(get(messageIdColumn)),
|
||||||
get(groupColumn),
|
get(groupColumn) ?.let(::MediaGroupId),
|
||||||
get(orderColumn)
|
get(orderColumn)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,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.IdChatIdentifier
|
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
import dev.inmo.tgbotapi.types.MessageId
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
@@ -93,10 +93,10 @@ class ExposedPostsRepo(
|
|||||||
post.content.forEach { contentInfo ->
|
post.content.forEach { contentInfo ->
|
||||||
insert {
|
insert {
|
||||||
it[postIdColumn] = post.id.string
|
it[postIdColumn] = post.id.string
|
||||||
it[chatIdColumn] = contentInfo.chatId.chatId
|
it[chatIdColumn] = contentInfo.chatId.chatId.long
|
||||||
it[threadIdColumn] = contentInfo.chatId.threadId
|
it[threadIdColumn] = contentInfo.chatId.threadId ?.long
|
||||||
it[messageIdColumn] = contentInfo.messageId
|
it[messageIdColumn] = contentInfo.messageId.long
|
||||||
it[groupColumn] = contentInfo.group
|
it[groupColumn] = contentInfo.group ?.string
|
||||||
it[orderColumn] = contentInfo.order
|
it[orderColumn] = contentInfo.order
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,13 +153,13 @@ class ExposedPostsRepo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId? {
|
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageId): PostId? {
|
||||||
return transaction(database) {
|
return transaction(database) {
|
||||||
with(contentRepo) {
|
with(contentRepo) {
|
||||||
select {
|
select {
|
||||||
chatIdColumn.eq(chatId.chatId)
|
chatIdColumn.eq(chatId.chatId.long)
|
||||||
.and(chatId.threadId ?.let { threadIdColumn.eq(it) } ?: threadIdColumn.isNull())
|
.and(chatId.threadId ?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull())
|
||||||
.and(messageIdColumn.eq(messageId))
|
.and(messageIdColumn.eq(messageId.long))
|
||||||
}.limit(1).firstOrNull() ?.get(postIdColumn)
|
}.limit(1).firstOrNull() ?.get(postIdColumn)
|
||||||
} ?.let(::PostId)
|
} ?.let(::PostId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,12 +119,12 @@ object Plugin : Plugin {
|
|||||||
null
|
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()))
|
startChain(RegistrationState.InProcess(it.chat.id, emptyList()))
|
||||||
}
|
}
|
||||||
|
|
||||||
onContentMessage(
|
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)))
|
startChain(RegistrationState.Finish(it.chat.id, PostContentInfo.fromMessage(it)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.inmo.plaguposter.ratings.selector
|
package dev.inmo.plaguposter.ratings.selector
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
import korlibs.time.DateTime
|
import korlibs.time.DateTime
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
@@ -9,13 +10,14 @@ import dev.inmo.plaguposter.ratings.selector.models.SelectorConfig
|
|||||||
class DefaultSelector (
|
class DefaultSelector (
|
||||||
private val config: SelectorConfig,
|
private val config: SelectorConfig,
|
||||||
private val ratingsRepo: RatingsRepo,
|
private val ratingsRepo: RatingsRepo,
|
||||||
private val postsRepo: PostsRepo
|
private val postsRepo: PostsRepo,
|
||||||
|
private val latestChosenRepo: KeyValueRepo<PostId, DateTime>
|
||||||
) : Selector {
|
) : Selector {
|
||||||
override suspend fun take(n: Int, now: DateTime, exclude: List<PostId>): List<PostId> {
|
override suspend fun take(n: Int, now: DateTime, exclude: List<PostId>): List<PostId> {
|
||||||
val result = mutableListOf<PostId>()
|
val result = mutableListOf<PostId>()
|
||||||
|
|
||||||
do {
|
do {
|
||||||
val selected = config.active(now.time) ?.rating ?.select(ratingsRepo, postsRepo, result + exclude, now) ?: break
|
val selected = config.active(now.time) ?.rating ?.select(ratingsRepo, postsRepo, result + exclude, now, latestChosenRepo) ?: break
|
||||||
result.add(selected)
|
result.add(selected)
|
||||||
} while (result.size < n)
|
} while (result.size < n)
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ package dev.inmo.plaguposter.ratings.selector.models
|
|||||||
|
|
||||||
import korlibs.time.DateTime
|
import korlibs.time.DateTime
|
||||||
import korlibs.time.seconds
|
import korlibs.time.seconds
|
||||||
import dev.inmo.micro_utils.pagination.FirstPagePagination
|
|
||||||
import dev.inmo.micro_utils.pagination.Pagination
|
|
||||||
import dev.inmo.micro_utils.pagination.utils.getAllByWithNextPaging
|
import dev.inmo.micro_utils.pagination.utils.getAllByWithNextPaging
|
||||||
import dev.inmo.micro_utils.repos.pagination.getAll
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
import dev.inmo.plaguposter.common.DateTimeSerializer
|
import dev.inmo.micro_utils.repos.unset
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
import dev.inmo.plaguposter.ratings.models.Rating
|
import dev.inmo.plaguposter.ratings.models.Rating
|
||||||
@@ -25,17 +23,23 @@ data class RatingConfig(
|
|||||||
val max: Rating? = null,
|
val max: Rating? = null,
|
||||||
val prefer: Prefer = Prefer.Random,
|
val prefer: Prefer = Prefer.Random,
|
||||||
val otherwise: RatingConfig? = null,
|
val otherwise: RatingConfig? = null,
|
||||||
val postAge: Seconds? = null
|
val postAge: Seconds? = null,
|
||||||
|
val uniqueCount: Int? = null
|
||||||
) {
|
) {
|
||||||
suspend fun select(
|
suspend fun select(
|
||||||
ratingsRepo: RatingsRepo,
|
ratingsRepo: RatingsRepo,
|
||||||
postsRepo: PostsRepo,
|
postsRepo: PostsRepo,
|
||||||
exclude: List<PostId>,
|
exclude: List<PostId>,
|
||||||
now: DateTime
|
now: DateTime,
|
||||||
|
latestChosenRepo: KeyValueRepo<PostId, DateTime>
|
||||||
): PostId? {
|
): PostId? {
|
||||||
var reversed: Boolean = false
|
var reversed: Boolean = false
|
||||||
var count: Int? = null
|
var count: Int? = null
|
||||||
val allowedCreationTime = now - (postAge ?: 0).seconds
|
val allowedCreationTime = now - (postAge ?: 0).seconds
|
||||||
|
val excludedByRepo = uniqueCount ?.let {
|
||||||
|
latestChosenRepo.getAll().toList().sortedBy { it.second }.takeLast(uniqueCount).map { it.first }
|
||||||
|
} ?: emptyList()
|
||||||
|
val resultExcluded = exclude + excludedByRepo
|
||||||
|
|
||||||
when (prefer) {
|
when (prefer) {
|
||||||
Prefer.Max -> {
|
Prefer.Max -> {
|
||||||
@@ -59,40 +63,53 @@ data class RatingConfig(
|
|||||||
ratingsRepo.getAllByWithNextPaging { keys(it) }
|
ratingsRepo.getAllByWithNextPaging { keys(it) }
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
ratingsRepo.getPostsWithRatingLessEq(max, exclude = exclude).keys
|
ratingsRepo.getPostsWithRatingLessEq(max, exclude = resultExcluded).keys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
when (max) {
|
when (max) {
|
||||||
null -> {
|
null -> {
|
||||||
ratingsRepo.getPostsWithRatingGreaterEq(min, exclude = exclude).keys
|
ratingsRepo.getPostsWithRatingGreaterEq(min, exclude = resultExcluded).keys
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
ratingsRepo.getPosts(min .. max, reversed, count, exclude = exclude).keys
|
ratingsRepo.getPosts(min .. max, reversed, count, exclude = resultExcluded).keys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.filter {
|
}.filter {
|
||||||
it !in exclude && (postsRepo.getPostCreationTime(it) ?.let { it < allowedCreationTime } ?: true)
|
it !in resultExcluded && (postsRepo.getPostCreationTime(it) ?.let { it < allowedCreationTime } ?: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (prefer) {
|
val resultPosts: PostId = when (prefer) {
|
||||||
Prefer.Max,
|
Prefer.Max,
|
||||||
Prefer.Min -> posts.firstOrNull()
|
Prefer.Min -> posts.firstOrNull()
|
||||||
Prefer.Random -> posts.randomOrNull()
|
Prefer.Random -> posts.randomOrNull()
|
||||||
} ?: otherwise ?.select(ratingsRepo, postsRepo, exclude, now)
|
} ?: otherwise ?.select(ratingsRepo, postsRepo, resultExcluded, now, latestChosenRepo) ?: return null
|
||||||
|
|
||||||
|
val postsToKeep = uniqueCount ?.let {
|
||||||
|
(excludedByRepo + resultPosts).takeLast(it)
|
||||||
|
} ?: return resultPosts
|
||||||
|
|
||||||
|
val postsToRemoveFromKeep = excludedByRepo.filter { it !in postsToKeep }
|
||||||
|
latestChosenRepo.unset(postsToRemoveFromKeep)
|
||||||
|
val postsToAdd = postsToKeep.filter { it !in excludedByRepo }
|
||||||
|
latestChosenRepo.set(
|
||||||
|
postsToAdd.associateWith { DateTime.now() }
|
||||||
|
)
|
||||||
|
|
||||||
|
return resultPosts
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable(Prefer.Serializer::class)
|
@Serializable(Prefer.Serializer::class)
|
||||||
sealed interface Prefer {
|
sealed interface Prefer {
|
||||||
val type: String
|
val type: String
|
||||||
@Serializable(Serializer::class)
|
@Serializable(Serializer::class)
|
||||||
object Max : Prefer { override val type: String = "max" }
|
data object Max : Prefer { override val type: String = "max" }
|
||||||
@Serializable(Serializer::class)
|
@Serializable(Serializer::class)
|
||||||
object Min : Prefer { override val type: String = "min" }
|
data object Min : Prefer { override val type: String = "min" }
|
||||||
@Serializable(Serializer::class)
|
@Serializable(Serializer::class)
|
||||||
object Random : Prefer { override val type: String = "random" }
|
data object Random : Prefer { override val type: String = "random" }
|
||||||
|
|
||||||
object Serializer : KSerializer<Prefer> {
|
object Serializer : KSerializer<Prefer> {
|
||||||
override val descriptor: SerialDescriptor = String.serializer().descriptor
|
override val descriptor: SerialDescriptor = String.serializer().descriptor
|
||||||
|
|||||||
@@ -1,14 +1,33 @@
|
|||||||
package dev.inmo.plaguposter.ratings.selector
|
package dev.inmo.plaguposter.ratings.selector
|
||||||
|
|
||||||
|
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.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.ratings.selector.models.SelectorConfig
|
import dev.inmo.plaguposter.ratings.selector.models.SelectorConfig
|
||||||
|
import korlibs.time.DateTime
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.qualifier
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
single { get<Json>().decodeFromJsonElement(SelectorConfig.serializer(), params["selector"] ?: return@single null) }
|
single { get<Json>().decodeFromJsonElement(SelectorConfig.serializer(), params["selector"] ?: return@single null) }
|
||||||
single<Selector> { DefaultSelector(get(), get(), get()) }
|
single<KeyValueRepo<PostId, DateTime>>(qualifier("latestChosenRepo")) {
|
||||||
|
ExposedKeyValueRepo(
|
||||||
|
get(),
|
||||||
|
{ text("post_id") },
|
||||||
|
{ double("date_time") },
|
||||||
|
"LatestChosenRepo"
|
||||||
|
).withMapper(
|
||||||
|
{ string },
|
||||||
|
{ unixMillis },
|
||||||
|
{ PostId(this) },
|
||||||
|
{ DateTime(this) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single<Selector> { DefaultSelector(get(), get(), get(), get(qualifier("latestChosenRepo"))) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package dev.inmo.plaguposter.ratings.source.repos
|
package dev.inmo.plaguposter.ratings.source.repos
|
||||||
|
|
||||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
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.cache.FullKVCache
|
||||||
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
||||||
import dev.inmo.plaguposter.common.ShortMessageInfo
|
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
import dev.inmo.tgbotapi.types.PollId
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
class CachedPollsToMessagesInfoRepo(
|
class CachedPollsToMessagesInfoRepo(
|
||||||
private val repo: PollsToMessagesInfoRepo,
|
private val repo: PollsToMessagesInfoRepo,
|
||||||
private val scope: CoroutineScope,
|
private val scope: CoroutineScope,
|
||||||
private val kvCache: FullKVCache<PollIdentifier, ShortMessageInfo> = FullKVCache()
|
private val kvCache: KeyValueRepo<PollId, ShortMessageInfo> = MapKeyValueRepo()
|
||||||
) : PollsToMessagesInfoRepo, KeyValueRepo<PollIdentifier, ShortMessageInfo> by repo.fullyCached(kvCache, scope)
|
) : PollsToMessagesInfoRepo, KeyValueRepo<PollId, ShortMessageInfo> by repo.fullyCached(kvCache, scope)
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package dev.inmo.plaguposter.ratings.source.repos
|
package dev.inmo.plaguposter.ratings.source.repos
|
||||||
|
|
||||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
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.cache.FullKVCache
|
||||||
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
import dev.inmo.tgbotapi.types.PollId
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
class CachedPollsToPostsIdsRepo(
|
class CachedPollsToPostsIdsRepo(
|
||||||
private val repo: PollsToPostsIdsRepo,
|
private val repo: PollsToPostsIdsRepo,
|
||||||
private val scope: CoroutineScope,
|
private val scope: CoroutineScope,
|
||||||
private val kvCache: FullKVCache<PollIdentifier, PostId> = FullKVCache()
|
private val kvCache: KeyValueRepo<PollId, PostId> = MapKeyValueRepo()
|
||||||
) : PollsToPostsIdsRepo, KeyValueRepo<PollIdentifier, PostId> by repo.fullyCached(kvCache, scope)
|
) : 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.micro_utils.repos.KeyValueRepo
|
||||||
import dev.inmo.plaguposter.common.ShortMessageInfo
|
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
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.micro_utils.repos.KeyValueRepo
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
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>
|
||||||
|
|||||||
@@ -37,6 +37,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.dataButton
|
||||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard
|
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.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.bold
|
import dev.inmo.tgbotapi.types.message.textsources.bold
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||||
@@ -129,7 +130,7 @@ object Plugin : Plugin {
|
|||||||
content.chatId,
|
content.chatId,
|
||||||
config.ratingOfferText,
|
config.ratingOfferText,
|
||||||
config.variants.keys.toList(),
|
config.variants.keys.toList(),
|
||||||
replyToMessageId = content.messageId
|
replyParameters = ReplyParameters(content.chatId, content.messageId)
|
||||||
)
|
)
|
||||||
pollsToPostsIdsRepo.set(sent.content.poll.id, postId)
|
pollsToPostsIdsRepo.set(sent.content.poll.id, postId)
|
||||||
pollsToMessageInfoRepo.set(sent.content.poll.id, sent.short())
|
pollsToMessageInfoRepo.set(sent.content.poll.id, sent.short())
|
||||||
@@ -242,7 +243,7 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onCommand("ratings", requireOnlyCommandInMessage = true) {
|
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 ratings = ratingsRepo.postsByRatings().toList().sortedByDescending { it.first }
|
||||||
val textSources = buildEntities {
|
val textSources = buildEntities {
|
||||||
+ "Ratings amount: " + bold("${ratings.sumOf { it.second.size }}") + "\n\n"
|
+ "Ratings amount: " + bold("${ratings.sumOf { it.second.size }}") + "\n\n"
|
||||||
@@ -260,8 +261,8 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
includeRootNavigationButtonsHandler(setOf(chatConfig.sourceChatId), ratingsRepo, postsRepo)
|
includeRootNavigationButtonsHandler(chatConfig.allSourceChatIds, ratingsRepo, postsRepo)
|
||||||
onMessageDataCallbackQuery("ratings_interactive", initialFilter = { it.message.chat.id == chatConfig.sourceChatId }) {
|
onMessageDataCallbackQuery("ratings_interactive", initialFilter = { it.message.chat.id in chatConfig.allSourceChatIds }) {
|
||||||
edit(
|
edit(
|
||||||
it.message,
|
it.message,
|
||||||
ratingsRepo.buildRootButtons()
|
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.initTable
|
||||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
||||||
import dev.inmo.plaguposter.common.ShortMessageInfo
|
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
|
||||||
import dev.inmo.tgbotapi.types.PollIdentifier
|
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
|
||||||
@@ -13,7 +11,7 @@ import org.jetbrains.exposed.sql.statements.*
|
|||||||
|
|
||||||
class ExposedPollsToMessagesInfoRepo(
|
class ExposedPollsToMessagesInfoRepo(
|
||||||
database: Database
|
database: Database
|
||||||
) : PollsToMessagesInfoRepo, AbstractExposedKeyValueRepo<PollIdentifier, ShortMessageInfo>(
|
) : PollsToMessagesInfoRepo, AbstractExposedKeyValueRepo<PollId, ShortMessageInfo>(
|
||||||
database,
|
database,
|
||||||
"polls_to_their_messages_info"
|
"polls_to_their_messages_info"
|
||||||
) {
|
) {
|
||||||
@@ -21,31 +19,32 @@ class ExposedPollsToMessagesInfoRepo(
|
|||||||
private val chatIdColumn = long("chat_id")
|
private val chatIdColumn = long("chat_id")
|
||||||
private val threadIdColumn = long("thread_id").nullable().default(null)
|
private val threadIdColumn = long("thread_id").nullable().default(null)
|
||||||
private val messageIdColumn = long("message_id")
|
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> = {
|
override val selectByValue: ISqlExpressionBuilder.(ShortMessageInfo) -> Op<Boolean> = {
|
||||||
chatIdColumn.eq(it.chatId.chatId).and(it.chatId.threadId ?.let { threadIdColumn.eq(it) } ?: threadIdColumn.isNull()).and(
|
chatIdColumn.eq(it.chatId.chatId.long)
|
||||||
messageIdColumn.eq(it.messageId)
|
.and(it.chatId.threadId?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull()).and(
|
||||||
|
messageIdColumn.eq(it.messageId.long)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
override val ResultRow.asKey: PollIdentifier
|
override val ResultRow.asKey: PollId
|
||||||
get() = get(keyColumn)
|
get() = PollId(get(keyColumn))
|
||||||
override val ResultRow.asObject: ShortMessageInfo
|
override val ResultRow.asObject: ShortMessageInfo
|
||||||
get() = ShortMessageInfo(
|
get() = ShortMessageInfo(
|
||||||
IdChatIdentifier(get(chatIdColumn), get(threadIdColumn)),
|
IdChatIdentifier(RawChatId(get(chatIdColumn)), get(threadIdColumn) ?.let(::MessageThreadId)),
|
||||||
get(messageIdColumn)
|
MessageId(get(messageIdColumn))
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initTable()
|
initTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(k: PollIdentifier, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
override fun update(k: PollId, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
||||||
it[chatIdColumn] = v.chatId.chatId
|
it[chatIdColumn] = v.chatId.chatId.long
|
||||||
it[threadIdColumn] = v.chatId.threadId
|
it[threadIdColumn] = v.chatId.threadId ?.long
|
||||||
it[messageIdColumn] = v.messageId
|
it[messageIdColumn] = v.messageId.long
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertKey(k: PollIdentifier, v: ShortMessageInfo, it: InsertStatement<Number>) {
|
override fun insertKey(k: PollId, v: ShortMessageInfo, it: InsertStatement<Number>) {
|
||||||
it[keyColumn] = k
|
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.initTable
|
||||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
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.*
|
||||||
import org.jetbrains.exposed.sql.statements.*
|
import org.jetbrains.exposed.sql.statements.*
|
||||||
|
|
||||||
class ExposedPollsToPostsIdsRepo(
|
class ExposedPollsToPostsIdsRepo(
|
||||||
database: Database
|
database: Database
|
||||||
) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo<PollIdentifier, PostId>(database, "polls_to_posts") {
|
) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo<PollId, PostId>(database, "polls_to_posts") {
|
||||||
override val keyColumn = text("poll_id")
|
override val keyColumn = text("poll_id")
|
||||||
val postIdColumn = text("postId")
|
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 selectByValue: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { postIdColumn.eq(it.string) }
|
||||||
override val ResultRow.asKey: PollIdentifier
|
override val ResultRow.asKey: PollId
|
||||||
get() = get(keyColumn)
|
get() = PollId(get(keyColumn))
|
||||||
override val ResultRow.asObject: PostId
|
override val ResultRow.asObject: PostId
|
||||||
get() = get(postIdColumn).let(::PostId)
|
get() = get(postIdColumn).let(::PostId)
|
||||||
|
|
||||||
@@ -23,11 +23,11 @@ class ExposedPollsToPostsIdsRepo(
|
|||||||
initTable()
|
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
|
it[postIdColumn] = v.string
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertKey(k: PollIdentifier, v: PostId, it: InsertStatement<Number>) {
|
override fun insertKey(k: PollId, v: PostId, it: InsertStatement<Number>) {
|
||||||
it[keyColumn] = k
|
it[keyColumn] = k.string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package dev.inmo.plaguposter.ratings.repo
|
|||||||
|
|
||||||
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
||||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
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.micro_utils.repos.cache.full.FullKeyValueCacheRepo
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.ratings.models.Rating
|
import dev.inmo.plaguposter.ratings.models.Rating
|
||||||
@@ -11,7 +11,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
class CachedRatingsRepo(
|
class CachedRatingsRepo(
|
||||||
private val base: RatingsRepo,
|
private val base: RatingsRepo,
|
||||||
private val scope: CoroutineScope,
|
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) {
|
) : RatingsRepo, KeyValueRepo<PostId, Rating> by FullKeyValueCacheRepo(base, kvCache, scope) {
|
||||||
override suspend fun getPosts(
|
override suspend fun getPosts(
|
||||||
range: ClosedRange<Rating>,
|
range: ClosedRange<Rating>,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import dev.inmo.micro_utils.koin.singleWithBinds
|
|||||||
import dev.inmo.micro_utils.repos.unset
|
import dev.inmo.micro_utils.repos.unset
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.common.useCache
|
import dev.inmo.plaguposter.common.useCache
|
||||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
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.*
|
||||||
@@ -14,7 +13,6 @@ 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.Koin
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
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) {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class ExposedRatingsRepo (
|
|||||||
count: Int?,
|
count: Int?,
|
||||||
exclude: List<PostId>
|
exclude: List<PostId>
|
||||||
): Map<PostId, Rating> = transaction(database) {
|
): Map<PostId, Rating> = transaction(database) {
|
||||||
select {
|
selectAll().where {
|
||||||
ratingsColumn.greaterEq(range.start.double).and(
|
ratingsColumn.greaterEq(range.start.double).and(
|
||||||
ratingsColumn.lessEq(range.endInclusive.double)
|
ratingsColumn.lessEq(range.endInclusive.double)
|
||||||
).and(
|
).and(
|
||||||
@@ -66,7 +66,7 @@ class ExposedRatingsRepo (
|
|||||||
count: Int?,
|
count: Int?,
|
||||||
exclude: List<PostId>
|
exclude: List<PostId>
|
||||||
) = transaction(database) {
|
) = 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
|
it.asKey to it.asObject
|
||||||
}
|
}
|
||||||
}.toMap()
|
}.toMap()
|
||||||
@@ -77,7 +77,7 @@ class ExposedRatingsRepo (
|
|||||||
count: Int?,
|
count: Int?,
|
||||||
exclude: List<PostId>
|
exclude: List<PostId>
|
||||||
): Map<PostId, Rating> = transaction(database) {
|
): 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
|
it.asKey to it.asObject
|
||||||
}
|
}
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
|||||||
@@ -51,7 +51,8 @@
|
|||||||
"to": "23:59"
|
"to": "23:59"
|
||||||
},
|
},
|
||||||
"rating": {
|
"rating": {
|
||||||
"prefer": "max"
|
"prefer": "max",
|
||||||
|
"uniqueCount": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -60,7 +61,8 @@
|
|||||||
"to": "00:00"
|
"to": "00:00"
|
||||||
},
|
},
|
||||||
"rating": {
|
"rating": {
|
||||||
"prefer": "max"
|
"prefer": "max",
|
||||||
|
"uniqueCount": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ services:
|
|||||||
POSTGRES_DB: "test"
|
POSTGRES_DB: "test"
|
||||||
volumes:
|
volumes:
|
||||||
- "./db/:/var/lib/postgresql/data"
|
- "./db/:/var/lib/postgresql/data"
|
||||||
|
- "/etc/timezone:/etc/timezone:ro"
|
||||||
plaguposter:
|
plaguposter:
|
||||||
image: insanusmokrassar/plaguposter:latest
|
image: insanusmokrassar/plaguposter:latest
|
||||||
container_name: "plaguposter"
|
container_name: "plaguposter"
|
||||||
restart: "unless-stopped"
|
restart: "unless-stopped"
|
||||||
volumes:
|
volumes:
|
||||||
- "./config.json:/config.json"
|
- "./config.json:/config.json"
|
||||||
|
- "/etc/timezone:/etc/timezone:ro"
|
||||||
depends_on:
|
depends_on:
|
||||||
- "plaguposter_postgres"
|
- "plaguposter_postgres"
|
||||||
links:
|
links:
|
||||||
|
|||||||
@@ -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.dataButton
|
||||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
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.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@@ -38,8 +38,8 @@ object Plugin : Plugin {
|
|||||||
@Serializable
|
@Serializable
|
||||||
private data class PublishState(
|
private data class PublishState(
|
||||||
override val context: ChatId,
|
override val context: ChatId,
|
||||||
val sourceMessageId: MessageIdentifier,
|
val sourceMessageId: MessageId,
|
||||||
val messageInReply: MessageIdentifier
|
val messageInReply: MessageId
|
||||||
) : State
|
) : State
|
||||||
@Serializable
|
@Serializable
|
||||||
internal data class Config(
|
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()
|
val keyboard = buildPage()
|
||||||
|
|
||||||
runCatchingSafely {
|
runCatchingSafely {
|
||||||
@@ -167,7 +167,7 @@ object Plugin : Plugin {
|
|||||||
|
|
||||||
onMessageDataCallbackQuery(
|
onMessageDataCallbackQuery(
|
||||||
Regex("^$pageCallbackDataQueryPrefix\\d+"),
|
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 { _ ->
|
val page = it.data.removePrefix(pageCallbackDataQueryPrefix).toIntOrNull() ?: let { _ ->
|
||||||
answer(it)
|
answer(it)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
|||||||
import dev.inmo.micro_utils.repos.unset
|
import dev.inmo.micro_utils.repos.unset
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||||
|
import korlibs.time.millisecondsLong
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|||||||
Reference in New Issue
Block a user