mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2026-05-31 10:27:20 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 194a26fa36 | |||
| e190ace1f2 | |||
| 0f2a0c24b2 | |||
| a65e7598ba | |||
| 53cc851944 | |||
| 815391d3f6 | |||
| f06d91e38f | |||
| 028f1f48e8 | |||
| 18180e67f6 | |||
| 1091f1141b | |||
| 7dbc5ef254 | |||
| 380e6e1117 | |||
| d5d924401b | |||
| 53e74745aa | |||
| bae2c67136 | |||
| c579fb576c | |||
| a1cffd688e | |||
| 5cab93a7fb | |||
| 1d200c38e4 | |||
| 9ebadfe1e4 | |||
| 333f807c97 | |||
| 9ae7238974 | |||
| 275cc13ea7 | |||
| cdcdb4ef00 | |||
| aeb3bf1f3d | |||
| 569f15330c | |||
| defc83740d | |||
| 66b2b21c1c | |||
| 63800ce19c |
24
CHANGELOG.md
24
CHANGELOG.md
@@ -1,5 +1,29 @@
|
|||||||
# PlaguPoster
|
# PlaguPoster
|
||||||
|
|
||||||
|
## 0.11.1
|
||||||
|
|
||||||
|
* Update `PlaguBot` dependency to allow using of `proxy` section in config
|
||||||
|
|
||||||
|
## 0.11.0
|
||||||
|
|
||||||
|
## 0.10.1
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.10.0
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.9.0
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
|
||||||
|
## 0.8.0
|
||||||
|
|
||||||
|
* Dependencies update
|
||||||
|
* `Ratings`:
|
||||||
|
* Add autoclearing of ratings without target posts each half hours
|
||||||
|
|
||||||
## 0.7.0
|
## 0.7.0
|
||||||
|
|
||||||
* Dependencies update
|
* Dependencies update
|
||||||
|
|||||||
22
build.gradle
22
build.gradle
@@ -2,23 +2,41 @@ buildscript {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
|
||||||
maven { url "https://plugins.gradle.org/m2/" }
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
|
mavenLocal()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath libs.kotlin.gradle.plugin
|
classpath libs.kotlin.gradle.plugin
|
||||||
classpath libs.kotlin.serialization.plugin
|
classpath libs.kotlin.serialization.plugin
|
||||||
classpath libs.kotlin.dokka.plugin
|
classpath libs.kotlin.dokka.plugin
|
||||||
|
classpath libs.github.release
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.nmcp.aggregation)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
|
||||||
|
nmcpAggregation {
|
||||||
|
centralPortal {
|
||||||
|
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
|
||||||
|
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
|
||||||
|
validationTimeout = Duration.ofHours(4)
|
||||||
|
publishingType = System.getenv('PUBLISHING_TYPE') != "" ? System.getenv('PUBLISHING_TYPE') : "USER_MANAGED"
|
||||||
|
}
|
||||||
|
|
||||||
|
publishAllProjectsProbablyBreakingProjectIsolation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
||||||
|
mavenLocal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
changelog_parser.sh
Normal file → Executable file
0
changelog_parser.sh
Normal file → Executable file
@@ -11,15 +11,14 @@ import kotlinx.coroutines.SupervisorJob
|
|||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
import kotlinx.serialization.json.booleanOrNull
|
import kotlinx.serialization.json.booleanOrNull
|
||||||
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
|
||||||
|
|
||||||
object CommonPlugin : Plugin {
|
object CommonPlugin : Plugin {
|
||||||
private val Log = logger
|
private val Log = logger
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
single { CoroutineScope(Dispatchers.Default + SupervisorJob()) }
|
single { CoroutineScope(Dispatchers.Default + SupervisorJob()) }
|
||||||
val useCache = (params["useCache"] as? JsonPrimitive) ?.booleanOrNull ?: true
|
val useCache = (config["useCache"] as? JsonPrimitive) ?.booleanOrNull ?: true
|
||||||
useCache(useCache)
|
useCache(useCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,21 +11,28 @@ private String getCurrentVersionChangelog() {
|
|||||||
return changelogDataOS.toString().trim()
|
return changelogDataOS.toString().trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new File(projectDir, "secret.gradle").exists()) {
|
def githubTokenVariableName = "GITHUB_RELEASE_TOKEN"
|
||||||
apply from: './secret.gradle'
|
def githubTokenVariableFromEnv = System.getenv(githubTokenVariableName)
|
||||||
|
|
||||||
|
def secretFile = new File(projectDir, "secret.gradle")
|
||||||
|
if (secretFile.exists() || project.hasProperty(githubTokenVariableName) || (githubTokenVariableFromEnv != "" && githubTokenVariableFromEnv != null)) {
|
||||||
|
if (secretFile.exists()) {
|
||||||
|
apply from: './secret.gradle'
|
||||||
|
}
|
||||||
apply plugin: "com.github.breadmoirai.github-release"
|
apply plugin: "com.github.breadmoirai.github-release"
|
||||||
|
def githubReleaseToken = project.hasProperty(githubTokenVariableName) ? project.property(githubTokenVariableName).toString() : githubTokenVariableFromEnv
|
||||||
|
|
||||||
githubRelease {
|
githubRelease {
|
||||||
token "${project.property('GITHUB_RELEASE_TOKEN')}"
|
token githubReleaseToken
|
||||||
|
|
||||||
owner "InsanusMokrassar"
|
owner = "InsanusMokrassar"
|
||||||
repo "PlaguPoster"
|
repo = "PlaguPoster"
|
||||||
|
|
||||||
tagName "v${project.version}"
|
tagName = "v${project.version}"
|
||||||
releaseName "${project.version}"
|
releaseName = "${project.version}"
|
||||||
targetCommitish "${project.version}"
|
targetCommitish = "${project.version}"
|
||||||
|
|
||||||
body getCurrentVersionChangelog()
|
body = getCurrentVersionChangelog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ android.enableJetifier=true
|
|||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.7.0
|
version=0.11.1
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kotlin = "2.0.20"
|
kotlin = "2.3.10"
|
||||||
kotlin-serialization = "1.7.2"
|
kotlin-serialization = "1.10.0"
|
||||||
|
|
||||||
plagubot = "9.2.0"
|
plagubot = "11.1.0"
|
||||||
tgbotapi = "18.1.0"
|
tgbotapi = "32.0.0"
|
||||||
microutils = "0.22.2"
|
microutils = "0.29.1"
|
||||||
kslog = "1.3.6"
|
kslog = "1.6.0"
|
||||||
krontab = "2.4.0"
|
krontab = "2.8.0"
|
||||||
plagubot-plugins = "0.21.0"
|
plagubot-plugins = "0.25.0"
|
||||||
|
|
||||||
dokka = "1.9.20"
|
nmcp = "1.4.4"
|
||||||
|
|
||||||
|
dokka = "2.0.0"
|
||||||
|
|
||||||
psql = "42.6.0"
|
psql = "42.6.0"
|
||||||
|
|
||||||
|
github-release = "2.5.2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
|
||||||
kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
||||||
@@ -42,8 +46,11 @@ psql = { module = "org.postgresql:postgresql", version.ref = "psql" }
|
|||||||
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
kotlin-serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" }
|
kotlin-serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" }
|
||||||
kotlin-dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
kotlin-dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
||||||
|
github-release = { module = "com.github.breadmoirai:github-release", version.ref = "github-release" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|
||||||
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
||||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||||
|
|
||||||
|
nmcp-aggregation = { id = "com.gradleup.nmcp.aggregation", version.ref = "nmcp" }
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import dev.inmo.kslog.common.w
|
|||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
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
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ private val actualPlugin = dev.inmo.plagubot.plugins.inline.queries.Plugin
|
|||||||
object Plugin : Plugin by actualPlugin {
|
object Plugin : Plugin by actualPlugin {
|
||||||
private val log = TagLogger("InlinePlugin")
|
private val log = TagLogger("InlinePlugin")
|
||||||
|
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(params: JsonObject) {
|
||||||
single { actualPlugin }
|
single { actualPlugin }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import dev.inmo.plagubot.Plugin
|
|||||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
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.models.OfferTemplate
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
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
|
||||||
@@ -32,13 +33,13 @@ 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.MilliSeconds
|
import dev.inmo.tgbotapi.types.MilliSeconds
|
||||||
|
import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle
|
||||||
import dev.inmo.tgbotapi.utils.bold
|
import dev.inmo.tgbotapi.utils.bold
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
@@ -49,10 +50,8 @@ object Plugin : Plugin {
|
|||||||
val throttlingMillis: MilliSeconds = 1000,
|
val throttlingMillis: MilliSeconds = 1000,
|
||||||
val doFullCheck: Boolean = false
|
val doFullCheck: Boolean = false
|
||||||
)
|
)
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
params["messagesChecker"] ?.let { element ->
|
registerConfig<Config>("messagesChecker") { null }
|
||||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), element) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val gcLogger = KSLog("GarbageCollector")
|
private val gcLogger = KSLog("GarbageCollector")
|
||||||
@@ -150,7 +149,7 @@ object Plugin : Plugin {
|
|||||||
message,
|
message,
|
||||||
text = "Are you sure want to trigger posts garbage collecting?",
|
text = "Are you sure want to trigger posts garbage collecting?",
|
||||||
replyMarkup = flatInlineKeyboard {
|
replyMarkup = flatInlineKeyboard {
|
||||||
dataButton("Sure", yesData)
|
dataButton("Sure", yesData, style = KeyboardButtonStyle.Primary)
|
||||||
dataButton("No", noData)
|
dataButton("No", noData)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package dev.inmo.plaguposter.posts.panel
|
package dev.inmo.plaguposter.posts.panel
|
||||||
|
|
||||||
import com.benasher44.uuid.uuid4
|
import com.benasher44.uuid.uuid4
|
||||||
|
import dev.inmo.micro_utils.coroutines.runCatchingLogging
|
||||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||||
|
import dev.inmo.micro_utils.coroutines.subscribeLoggingDropExceptions
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
import dev.inmo.micro_utils.koin.getAllDistinct
|
import dev.inmo.micro_utils.koin.getAllDistinct
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
|
||||||
import dev.inmo.micro_utils.repos.cache.cached
|
|
||||||
import dev.inmo.micro_utils.repos.cache.full.cached
|
|
||||||
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
import dev.inmo.micro_utils.repos.cache.full.fullyCached
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
import dev.inmo.plaguposter.common.ChatConfig
|
import dev.inmo.plaguposter.common.ChatConfig
|
||||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||||
import dev.inmo.plaguposter.common.useCache
|
import dev.inmo.plaguposter.common.useCache
|
||||||
@@ -34,6 +34,7 @@ import dev.inmo.tgbotapi.types.MessageId
|
|||||||
import dev.inmo.tgbotapi.types.ReplyParameters
|
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.buttons.KeyboardButtonStyle
|
||||||
import dev.inmo.tgbotapi.types.message.ParseMode
|
import dev.inmo.tgbotapi.types.message.ParseMode
|
||||||
import dev.inmo.tgbotapi.utils.bold
|
import dev.inmo.tgbotapi.utils.bold
|
||||||
import dev.inmo.tgbotapi.utils.buildEntities
|
import dev.inmo.tgbotapi.utils.buildEntities
|
||||||
@@ -41,7 +42,6 @@ import dev.inmo.tgbotapi.utils.italic
|
|||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
@@ -55,10 +55,8 @@ object Plugin : Plugin {
|
|||||||
val rootButtonText: String = "◀️",
|
val rootButtonText: String = "◀️",
|
||||||
val refreshButtonText: String? = "\uD83D\uDD04"
|
val refreshButtonText: String? = "\uD83D\uDD04"
|
||||||
)
|
)
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(params: JsonObject) {
|
||||||
params["panel"] ?.let { element ->
|
registerConfig<Config>("panel") { null }
|
||||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), element) }
|
|
||||||
}
|
|
||||||
single {
|
single {
|
||||||
val config = getOrNull<Config>() ?: Config()
|
val config = getOrNull<Config>() ?: Config()
|
||||||
val builtInButtons = listOfNotNull(
|
val builtInButtons = listOfNotNull(
|
||||||
@@ -74,7 +72,8 @@ object Plugin : Plugin {
|
|||||||
PanelButtonBuilder {
|
PanelButtonBuilder {
|
||||||
CallbackDataInlineKeyboardButton(
|
CallbackDataInlineKeyboardButton(
|
||||||
text,
|
text,
|
||||||
"refresh ${it.id.string}"
|
"refresh ${it.id.string}",
|
||||||
|
style = KeyboardButtonStyle.Primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +101,7 @@ object Plugin : Plugin {
|
|||||||
basePostsMessages
|
basePostsMessages
|
||||||
}
|
}
|
||||||
|
|
||||||
postsRepo.newObjectsFlow.subscribeSafelyWithoutExceptions(this) {
|
postsRepo.newObjectsFlow.subscribeLoggingDropExceptions(this) {
|
||||||
val firstContent = it.content.first()
|
val firstContent = it.content.first()
|
||||||
val buttons = api.buttonsBuilders.chunked(config.buttonsPerRow).mapNotNull { row ->
|
val buttons = api.buttonsBuilders.chunked(config.buttonsPerRow).mapNotNull { row ->
|
||||||
row.mapNotNull { builder ->
|
row.mapNotNull { builder ->
|
||||||
@@ -167,7 +166,7 @@ object Plugin : Plugin {
|
|||||||
edit(
|
edit(
|
||||||
query.message,
|
query.message,
|
||||||
replyMarkup = flatInlineKeyboard {
|
replyMarkup = flatInlineKeyboard {
|
||||||
dataButton("\uD83D\uDDD1", approveData)
|
dataButton("\uD83D\uDDD1", approveData, style = KeyboardButtonStyle.Danger)
|
||||||
api.RootPanelButtonBuilder.buildButton(post) ?.let(::add)
|
api.RootPanelButtonBuilder.buildButton(post) ?.let(::add)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -189,7 +188,7 @@ object Plugin : Plugin {
|
|||||||
val postId = query.data.removePrefix("refresh ").let(::PostId)
|
val postId = query.data.removePrefix("refresh ").let(::PostId)
|
||||||
val (chatId, messageId) = postsMessages.get(postId) ?: return@onMessageDataCallbackQuery
|
val (chatId, messageId) = postsMessages.get(postId) ?: return@onMessageDataCallbackQuery
|
||||||
|
|
||||||
runCatchingSafely {
|
runCatching {
|
||||||
refreshPostMessage(
|
refreshPostMessage(
|
||||||
postId,
|
postId,
|
||||||
chatId,
|
chatId,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import dev.inmo.tgbotapi.types.*
|
|||||||
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.v1.jdbc.Database
|
||||||
|
|
||||||
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageId.serializer())
|
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageId.serializer())
|
||||||
|
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ class PostPublisher(
|
|||||||
contents.singleOrNull() ?.also {
|
contents.singleOrNull() ?.also {
|
||||||
targetChatIds.forEach { targetChatId ->
|
targetChatIds.forEach { targetChatId ->
|
||||||
runCatching {
|
runCatching {
|
||||||
bot.copyMessage(targetChatId, it.chatId, it.messageId)
|
bot.copyMessage(fromChatId = it.chatId, messageId = it.messageId, toChatId = targetChatId)
|
||||||
}.onFailure { _ ->
|
}.onFailure { _ ->
|
||||||
runCatching {
|
runCatching {
|
||||||
bot.forwardMessage(
|
bot.forwardMessage(
|
||||||
fromChatId = it.chatId,
|
fromChatId = it.chatId,
|
||||||
toChatId = cachingChatId,
|
messageId = it.messageId,
|
||||||
messageId = it.messageId
|
toChatId = cachingChatId
|
||||||
)
|
)
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
bot.copyMessage(targetChatId, it)
|
bot.copyMessage(targetChatId, it)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
|||||||
import dev.inmo.micro_utils.koin.singleWithBinds
|
import dev.inmo.micro_utils.koin.singleWithBinds
|
||||||
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.database
|
||||||
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
||||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||||
@@ -23,10 +24,9 @@ import dev.inmo.tgbotapi.extensions.api.edit.edit
|
|||||||
import dev.inmo.tgbotapi.extensions.api.send.reply
|
import dev.inmo.tgbotapi.extensions.api.send.reply
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
import dev.inmo.tgbotapi.types.message.textsources.regularTextSource
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
@@ -37,8 +37,8 @@ object Plugin : Plugin {
|
|||||||
val autoRemoveMessages: Boolean = true,
|
val autoRemoveMessages: Boolean = true,
|
||||||
val deleteAfterPublishing: Boolean = true
|
val deleteAfterPublishing: Boolean = true
|
||||||
)
|
)
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
val configJson = params["posts"] ?: this@Plugin.let {
|
val configJson = config["posts"] ?: this@Plugin.let {
|
||||||
it.logger.w {
|
it.logger.w {
|
||||||
"Unable to load posts plugin due to absence of `posts` key in config"
|
"Unable to load posts plugin due to absence of `posts` key in config"
|
||||||
}
|
}
|
||||||
@@ -90,9 +90,9 @@ object Plugin : Plugin {
|
|||||||
postsRepo.deleteById(postId)
|
postsRepo.deleteById(postId)
|
||||||
|
|
||||||
if (postsRepo.contains(postId)) {
|
if (postsRepo.contains(postId)) {
|
||||||
edit(it, it.content.textSources + regular(UnsuccessfulSymbol))
|
edit(it, it.content.textSources + regularTextSource(UnsuccessfulSymbol))
|
||||||
} else {
|
} else {
|
||||||
edit(it, it.content.textSources + regular(SuccessfulSymbol))
|
edit(it, it.content.textSources + regularTextSource(SuccessfulSymbol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ 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.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.v1.core.Column
|
||||||
|
import org.jetbrains.exposed.v1.core.ReferenceOption
|
||||||
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
|
import org.jetbrains.exposed.v1.core.Table
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
|
|
||||||
internal class ExposedContentInfoRepo(
|
internal class ExposedContentInfoRepo(
|
||||||
override val database: Database,
|
override val database: Database,
|
||||||
|
|||||||
@@ -13,11 +13,19 @@ import dev.inmo.tgbotapi.types.IdChatIdentifier
|
|||||||
import dev.inmo.tgbotapi.types.MessageId
|
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.v1.core.Op
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
|
import org.jetbrains.exposed.v1.core.and
|
||||||
import org.jetbrains.exposed.sql.statements.*
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.v1.core.inList
|
||||||
|
import org.jetbrains.exposed.v1.core.isNull
|
||||||
|
import org.jetbrains.exposed.v1.core.statements.InsertStatement
|
||||||
|
import org.jetbrains.exposed.v1.core.statements.UpdateBuilder
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.deleteWhere
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
|
||||||
class ExposedPostsRepo(
|
class ExposedPostsRepo(
|
||||||
override val database: Database
|
override val database: Database
|
||||||
@@ -37,8 +45,8 @@ class ExposedPostsRepo(
|
|||||||
|
|
||||||
override val primaryKey: PrimaryKey = PrimaryKey(idColumn)
|
override val primaryKey: PrimaryKey = PrimaryKey(idColumn)
|
||||||
|
|
||||||
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { idColumn.eq(it.string) }
|
override val selectById: (PostId) -> Op<Boolean> = { idColumn.eq(it.string) }
|
||||||
override val selectByIds: ISqlExpressionBuilder.(List<PostId>) -> Op<Boolean> = { idColumn.inList(it.map { it.string }) }
|
override val selectByIds: (List<PostId>) -> Op<Boolean> = { idColumn.inList(it.map { it.string }) }
|
||||||
override val ResultRow.asId: PostId
|
override val ResultRow.asId: PostId
|
||||||
get() = PostId(get(idColumn))
|
get() = PostId(get(idColumn))
|
||||||
override val ResultRow.asObject: RegisteredPost
|
override val ResultRow.asObject: RegisteredPost
|
||||||
@@ -132,8 +140,8 @@ class ExposedPostsRepo(
|
|||||||
}.associateBy { it.id }
|
}.associateBy { it.id }
|
||||||
val existsIds = posts.keys.toList()
|
val existsIds = posts.keys.toList()
|
||||||
transaction(db = database) {
|
transaction(db = database) {
|
||||||
val deleted = deleteWhere(null, null) {
|
val deleted = deleteWhere {
|
||||||
selectByIds(it, existsIds)
|
selectByIds(existsIds)
|
||||||
}
|
}
|
||||||
with(contentRepo) {
|
with(contentRepo) {
|
||||||
deleteWhere {
|
deleteWhere {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import dev.inmo.tgbotapi.extensions.utils.extensions.sameChat
|
|||||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
||||||
import dev.inmo.tgbotapi.extensions.utils.textContentOrNull
|
import dev.inmo.tgbotapi.extensions.utils.textContentOrNull
|
||||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
|
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
|
||||||
|
import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle
|
||||||
import dev.inmo.tgbotapi.utils.regular
|
import dev.inmo.tgbotapi.utils.regular
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
@@ -56,7 +57,8 @@ object Plugin : Plugin {
|
|||||||
flatInlineKeyboard {
|
flatInlineKeyboard {
|
||||||
dataButton(
|
dataButton(
|
||||||
"Finish",
|
"Finish",
|
||||||
buttonUuid
|
buttonUuid,
|
||||||
|
style = KeyboardButtonStyle.Primary,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
task javadocsJar(type: Jar) {
|
task javadocsJar(type: Jar) {
|
||||||
@@ -19,46 +20,30 @@ publishing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
developers {
|
developers {
|
||||||
|
developer {
|
||||||
developer {
|
id = "InsanusMokrassar"
|
||||||
id = "InsanusMokrassar"
|
name = "Aleksei Ovsiannikov"
|
||||||
name = "Aleksei Ovsiannikov"
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
email = "ovsyannikov.alexey95@gmail.com"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
licenses {
|
licenses {
|
||||||
|
license {
|
||||||
}
|
name = "MIT License"
|
||||||
}
|
url = "https://opensource.org/licenses/MIT"
|
||||||
repositories {
|
|
||||||
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) {
|
|
||||||
maven {
|
|
||||||
name = "Gitea"
|
|
||||||
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven")
|
|
||||||
|
|
||||||
credentials(HttpHeaderCredentials) {
|
|
||||||
name = "Authorization"
|
|
||||||
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN')
|
|
||||||
}
|
|
||||||
|
|
||||||
authentication {
|
|
||||||
header(HttpHeaderAuthentication)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
|
}
|
||||||
maven {
|
}
|
||||||
name = "sonatype"
|
repositories {
|
||||||
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
|
if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
|
||||||
|
maven {
|
||||||
credentials {
|
name = "InmoNexus"
|
||||||
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
|
url = uri("https://nexus.inmo.dev/repository/maven-releases/")
|
||||||
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
|
|
||||||
}
|
credentials {
|
||||||
|
username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
|
||||||
|
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,13 +52,13 @@ publishing {
|
|||||||
|
|
||||||
if (project.hasProperty("signing.gnupg.keyName")) {
|
if (project.hasProperty("signing.gnupg.keyName")) {
|
||||||
apply plugin: 'signing'
|
apply plugin: 'signing'
|
||||||
|
|
||||||
signing {
|
signing {
|
||||||
useGpgCmd()
|
useGpgCmd()
|
||||||
|
|
||||||
sign publishing.publications
|
sign publishing.publications
|
||||||
}
|
}
|
||||||
|
|
||||||
task signAll {
|
task signAll {
|
||||||
tasks.withType(Sign).forEach {
|
tasks.withType(Sign).forEach {
|
||||||
dependsOn(it)
|
dependsOn(it)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"licenses":[],"mavenConfig":{"name":"${project.name}","description":"${project.name}","url":"https://github.com/InsanusMokrassar/PlaguPoster","vcsUrl":"https://github.com/InsanusMokrassar/PlaguPoster.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"Gitea","url":"https://git.inmo.dev/api/packages/InsanusMokrassar/maven","credsType":{"type":"dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository.CredentialsType.HttpHeaderCredentials","headerName":"Authorization","headerValueProperty":"GITEA_TOKEN"}},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}}
|
{"licenses":[{"id":"MIT","title":"MIT License","url":"https://opensource.org/licenses/MIT"}],"mavenConfig":{"name":"${project.name}","description":"${project.name}","url":"https://github.com/InsanusMokrassar/PlaguPoster","vcsUrl":"https://github.com/InsanusMokrassar/PlaguPoster.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}}
|
||||||
@@ -11,6 +11,7 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api project(":plaguposter.common")
|
api project(":plaguposter.common")
|
||||||
api project(":plaguposter.posts")
|
api project(":plaguposter.posts")
|
||||||
|
api libs.krontab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import dev.inmo.plagubot.Plugin
|
|||||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
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.models.OfferTemplate
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
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
|
||||||
@@ -24,7 +25,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onComman
|
|||||||
import dev.inmo.tgbotapi.types.Seconds
|
import dev.inmo.tgbotapi.types.Seconds
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ object Plugin : Plugin {
|
|||||||
val skipPostAge: Seconds? = null
|
val skipPostAge: Seconds? = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(params: JsonObject) {
|
||||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), params["gc"] ?: return@single null) }
|
registerConfig<Config>("gc") { null }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ 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.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
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 korlibs.time.DateTime
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
import org.koin.core.qualifier.qualifier
|
import org.koin.core.qualifier.qualifier
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
single { get<Json>().decodeFromJsonElement(SelectorConfig.serializer(), params["selector"] ?: return@single null) }
|
registerConfig<SelectorConfig>("selector") { null }
|
||||||
single<KeyValueRepo<PostId, DateTime>>(qualifier("latestChosenRepo")) {
|
single<KeyValueRepo<PostId, DateTime>>(qualifier("latestChosenRepo")) {
|
||||||
ExposedKeyValueRepo(
|
ExposedKeyValueRepo(
|
||||||
get(),
|
get(),
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package dev.inmo.plaguposter.ratings.source
|
|||||||
import com.benasher44.uuid.uuid4
|
import com.benasher44.uuid.uuid4
|
||||||
import dev.inmo.kslog.common.e
|
import dev.inmo.kslog.common.e
|
||||||
import dev.inmo.kslog.common.logger
|
import dev.inmo.kslog.common.logger
|
||||||
|
import dev.inmo.micro_utils.common.fixed
|
||||||
|
import dev.inmo.micro_utils.coroutines.runCatchingLogging
|
||||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
import dev.inmo.micro_utils.pagination.firstPageWithOneElementPagination
|
import dev.inmo.micro_utils.pagination.firstPageWithOneElementPagination
|
||||||
@@ -10,10 +12,12 @@ import dev.inmo.micro_utils.repos.id
|
|||||||
import dev.inmo.micro_utils.repos.pagination.getAll
|
import dev.inmo.micro_utils.repos.pagination.getAll
|
||||||
import dev.inmo.micro_utils.repos.set
|
import dev.inmo.micro_utils.repos.set
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
|
import dev.inmo.plagubot.database
|
||||||
import dev.inmo.plaguposter.common.*
|
import dev.inmo.plaguposter.common.*
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
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.models.OfferTemplate
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
||||||
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
||||||
@@ -40,23 +44,28 @@ 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.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.buttons.KeyboardButtonStyle
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
import dev.inmo.tgbotapi.types.keyboardButtonRequestUserLimit
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.boldTextSource
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.regularTextSource
|
||||||
import dev.inmo.tgbotapi.types.polls.InputPollOption
|
import dev.inmo.tgbotapi.types.polls.InputPollOption
|
||||||
import dev.inmo.tgbotapi.types.polls.PollOption
|
import dev.inmo.tgbotapi.types.polls.PollOption
|
||||||
|
import dev.inmo.tgbotapi.utils.bold
|
||||||
import dev.inmo.tgbotapi.utils.buildEntities
|
import dev.inmo.tgbotapi.utils.buildEntities
|
||||||
import dev.inmo.tgbotapi.utils.extensions.makeSourceString
|
import dev.inmo.tgbotapi.utils.extensions.makeSourceString
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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.core.qualifier.named
|
import org.koin.core.qualifier.named
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
private val ratingVariantsQualifier = named("ratingsVariants")
|
private val ratingVariantsQualifier = named("ratingsVariants")
|
||||||
|
private const val attachedSymbolControlSymbol = "\${attached_symbol}"
|
||||||
|
private const val currentRatingControlSymbol = "\${rating}"
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal data class Config(
|
internal data class Config(
|
||||||
@@ -64,13 +73,13 @@ object Plugin : Plugin {
|
|||||||
val variants: RatingsVariants,
|
val variants: RatingsVariants,
|
||||||
val autoAttach: Boolean,
|
val autoAttach: Boolean,
|
||||||
val ratingOfferText: String,
|
val ratingOfferText: String,
|
||||||
val panelButtonText: String = "Ratings"
|
val panelButtonText: String = "Ratings $attachedSymbolControlSymbol",
|
||||||
|
val ratingEnabledStyle: KeyboardButtonStyle? = null,
|
||||||
|
val ratingDisabledStyle: KeyboardButtonStyle? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(params: JsonObject) {
|
||||||
single {
|
registerConfig<Config>("ratingsPolls")
|
||||||
get<Json>().decodeFromJsonElement(Config.serializer(), params["ratingsPolls"] ?: error("Unable to load config for rating polls in $params"))
|
|
||||||
}
|
|
||||||
single<RatingsVariants>(ratingVariantsQualifier) { get<Config>().variants }
|
single<RatingsVariants>(ratingVariantsQualifier) { get<Config>().variants }
|
||||||
|
|
||||||
single { ExposedPollsToPostsIdsRepo(database) }
|
single { ExposedPollsToPostsIdsRepo(database) }
|
||||||
@@ -113,12 +122,22 @@ object Plugin : Plugin {
|
|||||||
val panelApi = koin.getOrNull<PanelButtonsAPI>()
|
val panelApi = koin.getOrNull<PanelButtonsAPI>()
|
||||||
val chatConfig = koin.get<ChatConfig>()
|
val chatConfig = koin.get<ChatConfig>()
|
||||||
|
|
||||||
|
val panelApiOnPollUpdatesUpdateTrigger: suspend (PostId) -> Unit = if (config.panelButtonText.contains(currentRatingControlSymbol)) {
|
||||||
|
{
|
||||||
|
panelApi ?.forceRefresh(it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
onPollUpdates (markerFactory = { it.id }) { poll ->
|
onPollUpdates (markerFactory = { it.id }) { poll ->
|
||||||
val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates
|
val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates
|
||||||
val newRating = poll.options.sumOf {
|
val newRating = poll.options.sumOf {
|
||||||
(variantsTransformer(it.textSources.makeSourceString()) ?.double ?.times(it.votes)) ?: 0.0
|
(variantsTransformer(it.textSources.makeSourceString()) ?.double ?.times(it.votes)) ?: 0.0
|
||||||
}
|
}
|
||||||
ratingsRepo.set(postId, Rating(newRating))
|
ratingsRepo.set(postId, Rating(newRating))
|
||||||
|
panelApiOnPollUpdatesUpdateTrigger(postId)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun attachPoll(postId: PostId): Boolean {
|
suspend fun attachPoll(postId: PostId): Boolean {
|
||||||
@@ -198,17 +217,17 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attachPoll(postId)) {
|
if (attachPoll(postId)) {
|
||||||
runCatchingSafely {
|
runCatchingLogging {
|
||||||
edit(
|
edit(
|
||||||
it,
|
it,
|
||||||
it.content.textSources + regular(" $SuccessfulSymbol")
|
it.content.textSources + regularTextSource(" $SuccessfulSymbol")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runCatchingSafely {
|
runCatchingLogging {
|
||||||
edit(
|
edit(
|
||||||
it,
|
it,
|
||||||
it.content.textSources + regular(" $UnsuccessfulSymbol")
|
it.content.textSources + regularTextSource(" $UnsuccessfulSymbol")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,17 +252,17 @@ object Plugin : Plugin {
|
|||||||
|
|
||||||
|
|
||||||
if (detachPoll(postId)) {
|
if (detachPoll(postId)) {
|
||||||
runCatchingSafely {
|
runCatchingLogging {
|
||||||
edit(
|
edit(
|
||||||
it,
|
it,
|
||||||
it.content.textSources + regular(" $SuccessfulSymbol")
|
it.content.textSources + regularTextSource(" $SuccessfulSymbol")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runCatchingSafely {
|
runCatchingLogging {
|
||||||
edit(
|
edit(
|
||||||
it,
|
it,
|
||||||
it.content.textSources + regular(" $UnsuccessfulSymbol")
|
it.content.textSources + regularTextSource(" $UnsuccessfulSymbol")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,13 +314,69 @@ object Plugin : Plugin {
|
|||||||
panelApi ?.apply {
|
panelApi ?.apply {
|
||||||
add(
|
add(
|
||||||
PanelButtonBuilder {
|
PanelButtonBuilder {
|
||||||
|
suspend fun isEnabled() = pollsToPostsIdsRepo.keys(it.id, firstPageWithOneElementPagination).results.any()
|
||||||
|
val enabled = let { _ ->
|
||||||
|
var enabled: Boolean? = null
|
||||||
|
suspend {
|
||||||
|
enabled ?: (isEnabled().also { enabled = it })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val rating = let { _ ->
|
||||||
|
var rating: Rating? = null
|
||||||
|
suspend {
|
||||||
|
if (isEnabled()) {
|
||||||
|
rating ?: ratingsRepo.get(it.id) ?.also { rating = it }
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val resultText = config.panelButtonText
|
||||||
|
.let {
|
||||||
|
if (it.contains(attachedSymbolControlSymbol)) {
|
||||||
|
it.replace(
|
||||||
|
attachedSymbolControlSymbol,
|
||||||
|
if (enabled()) {
|
||||||
|
SuccessfulSymbol
|
||||||
|
} else {
|
||||||
|
UnsuccessfulSymbol
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.let {
|
||||||
|
if (it.contains(currentRatingControlSymbol)) {
|
||||||
|
val rating = rating()
|
||||||
|
if (rating != null) {
|
||||||
|
it.replace(
|
||||||
|
currentRatingControlSymbol,
|
||||||
|
rating.double.roundToInt().toString()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it.replace(
|
||||||
|
currentRatingControlSymbol,
|
||||||
|
UnsuccessfulSymbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.take(12) // maximal text appropriate for this button
|
||||||
CallbackDataInlineKeyboardButton(
|
CallbackDataInlineKeyboardButton(
|
||||||
config.panelButtonText + if (pollsToPostsIdsRepo.keys(it.id, firstPageWithOneElementPagination).results.any()) {
|
resultText,
|
||||||
SuccessfulSymbol
|
"toggle_ratings ${it.id.string}",
|
||||||
|
style = if (config.ratingEnabledStyle != null || config.ratingDisabledStyle != null) {
|
||||||
|
if (enabled()) {
|
||||||
|
config.ratingEnabledStyle
|
||||||
|
} else {
|
||||||
|
config.ratingDisabledStyle
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
UnsuccessfulSymbol
|
null
|
||||||
},
|
}
|
||||||
"toggle_ratings ${it.id.string}"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ 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.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.v1.core.Op
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
|
import org.jetbrains.exposed.v1.core.and
|
||||||
import org.jetbrains.exposed.sql.statements.*
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.isNull
|
||||||
|
import org.jetbrains.exposed.v1.core.statements.UpdateBuilder
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
|
|
||||||
class ExposedPollsToMessagesInfoRepo(
|
class ExposedPollsToMessagesInfoRepo(
|
||||||
database: Database
|
database: Database
|
||||||
@@ -19,8 +22,8 @@ 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.(PollId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
override val selectById: (PollId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||||
override val selectByValue: ISqlExpressionBuilder.(ShortMessageInfo) -> Op<Boolean> = {
|
override val selectByValue: (ShortMessageInfo) -> Op<Boolean> = {
|
||||||
chatIdColumn.eq(it.chatId.chatId.long)
|
chatIdColumn.eq(it.chatId.chatId.long)
|
||||||
.and(it.chatId.threadId?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull()).and(
|
.and(it.chatId.threadId?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull()).and(
|
||||||
messageIdColumn.eq(it.messageId.long)
|
messageIdColumn.eq(it.messageId.long)
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ 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.PollId
|
import dev.inmo.tgbotapi.types.PollId
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.v1.core.Op
|
||||||
import org.jetbrains.exposed.sql.statements.*
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.statements.UpdateBuilder
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
|
|
||||||
class ExposedPollsToPostsIdsRepo(
|
class ExposedPollsToPostsIdsRepo(
|
||||||
database: Database
|
database: Database
|
||||||
) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo<PollId, 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.(PollId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
override val selectById: (PollId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||||
override val selectByValue: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { postIdColumn.eq(it.string) }
|
override val selectByValue: (PostId) -> Op<Boolean> = { postIdColumn.eq(it.string) }
|
||||||
override val ResultRow.asKey: PollId
|
override val ResultRow.asKey: PollId
|
||||||
get() = PollId(get(keyColumn))
|
get() = PollId(get(keyColumn))
|
||||||
override val ResultRow.asObject: PostId
|
override val ResultRow.asObject: PostId
|
||||||
|
|||||||
18
ratings/src/commonMain/kotlin/models/Config.kt
Normal file
18
ratings/src/commonMain/kotlin/models/Config.kt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package dev.inmo.plaguposter.ratings.models
|
||||||
|
|
||||||
|
import dev.inmo.krontab.EveryHourScheduler
|
||||||
|
import dev.inmo.krontab.KrontabTemplate
|
||||||
|
import dev.inmo.krontab.buildSchedule
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal data class RatingsConfig(
|
||||||
|
@SerialName("manualRecheckKrontab")
|
||||||
|
val manualRecheckKrontabTemplate: KrontabTemplate = "0 /30 *"
|
||||||
|
) {
|
||||||
|
@Transient
|
||||||
|
val manualRecheckKrontab
|
||||||
|
get() = buildSchedule(manualRecheckKrontabTemplate)
|
||||||
|
}
|
||||||
@@ -1,21 +1,30 @@
|
|||||||
package dev.inmo.plaguposter.ratings
|
package dev.inmo.plaguposter.ratings
|
||||||
|
|
||||||
|
import dev.inmo.krontab.utils.asTzFlowWithDelays
|
||||||
|
import dev.inmo.kslog.common.TagLogger
|
||||||
|
import dev.inmo.kslog.common.i
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
import dev.inmo.micro_utils.koin.singleWithBinds
|
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.plagubot.config
|
||||||
|
import dev.inmo.plagubot.database
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
import dev.inmo.plaguposter.common.useCache
|
import dev.inmo.plaguposter.common.useCache
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
|
import dev.inmo.plaguposter.ratings.Plugin.setupBotPlugin
|
||||||
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
||||||
|
import dev.inmo.plaguposter.ratings.models.RatingsConfig
|
||||||
import dev.inmo.plaguposter.ratings.repo.*
|
import dev.inmo.plaguposter.ratings.repo.*
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
private val Log = TagLogger("RatingsPlugin")
|
||||||
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
single { ExposedRatingsRepo(database) }
|
single { ExposedRatingsRepo(database) }
|
||||||
singleWithBinds<RatingsRepo> {
|
singleWithBinds<RatingsRepo> {
|
||||||
val base = get<ExposedRatingsRepo>()
|
val base = get<ExposedRatingsRepo>()
|
||||||
@@ -26,12 +35,24 @@ object Plugin : Plugin {
|
|||||||
base
|
base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerConfig(RatingsConfig.serializer(), "ratings") { RatingsConfig() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
override suspend fun startPlugin(koin: Koin) {
|
||||||
|
super.startPlugin(koin)
|
||||||
|
val config = koin.config<RatingsConfig>()
|
||||||
|
val scope = koin.get<CoroutineScope>()
|
||||||
val ratingsRepo = koin.get<RatingsRepo>()
|
val ratingsRepo = koin.get<RatingsRepo>()
|
||||||
koin.get<PostsRepo>().deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(this) {
|
val postsRepo = koin.get<PostsRepo>()
|
||||||
|
postsRepo.deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(scope) {
|
||||||
ratingsRepo.unset(it)
|
ratingsRepo.unset(it)
|
||||||
}
|
}
|
||||||
|
config.manualRecheckKrontab.asTzFlowWithDelays().subscribeSafelyWithoutExceptions(scope) {
|
||||||
|
Log.i { "Start clearing ratings without registered posts" }
|
||||||
|
val postsIdsToRemove = ratingsRepo.getAll().keys - postsRepo.getAll().keys
|
||||||
|
Log.i { "Posts to remove: $postsIdsToRemove" }
|
||||||
|
ratingsRepo.unset(postsIdsToRemove.toList())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,17 @@ 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.plaguposter.ratings.models.Rating
|
import dev.inmo.plaguposter.ratings.models.Rating
|
||||||
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.v1.core.Op
|
||||||
import org.jetbrains.exposed.sql.statements.*
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.v1.core.and
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.core.greaterEq
|
||||||
|
import org.jetbrains.exposed.v1.core.lessEq
|
||||||
|
import org.jetbrains.exposed.v1.core.notInList
|
||||||
|
import org.jetbrains.exposed.v1.core.statements.UpdateBuilder
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.Query
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
|
||||||
class ExposedRatingsRepo (
|
class ExposedRatingsRepo (
|
||||||
database: Database
|
database: Database
|
||||||
@@ -18,8 +26,8 @@ class ExposedRatingsRepo (
|
|||||||
) {
|
) {
|
||||||
override val keyColumn = text("post_id")
|
override val keyColumn = text("post_id")
|
||||||
val ratingsColumn = double("rating")
|
val ratingsColumn = double("rating")
|
||||||
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
override val selectById: (PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||||
override val selectByValue: ISqlExpressionBuilder.(Rating) -> Op<Boolean> = { ratingsColumn.eq(it.double) }
|
override val selectByValue: (Rating) -> Op<Boolean> = { ratingsColumn.eq(it.double) }
|
||||||
override val ResultRow.asKey: PostId
|
override val ResultRow.asKey: PostId
|
||||||
get() = get(keyColumn).let(::PostId)
|
get() = get(keyColumn).let(::PostId)
|
||||||
override val ResultRow.asObject: Rating
|
override val ResultRow.asObject: Rating
|
||||||
|
|||||||
@@ -41,7 +41,11 @@
|
|||||||
"Results": 0
|
"Results": 0
|
||||||
},
|
},
|
||||||
"autoAttach": true,
|
"autoAttach": true,
|
||||||
"ratingOfferText": "What do you think about it?"
|
"ratingOfferText": "What do you think about it?",
|
||||||
|
"panelButtonText": "Ratings ${attached_symbol}",
|
||||||
|
"ratingEnabledStyle": "success",
|
||||||
|
"ratingDisabledStyle": "danger",
|
||||||
|
"_note": "For panelButtonText you may use two control symbols: ${attached_symbol} to attach icon about enabled state and ${rating} to enable rating showing in button"
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
"items": [
|
"items": [
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import dev.inmo.plaguposter.common.SuccessfulSymbol
|
|||||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
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.models.OfferTemplate
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
||||||
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
||||||
@@ -26,11 +27,10 @@ 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.MessageId
|
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.regularTextSource
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
@@ -45,10 +45,8 @@ object Plugin : Plugin {
|
|||||||
internal data class Config(
|
internal data class Config(
|
||||||
val panelButtonText: String? = "Publish"
|
val panelButtonText: String? = "Publish"
|
||||||
)
|
)
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(params: JsonObject) {
|
||||||
params["publish_command"] ?.let { configJson ->
|
registerConfig<Config>("publish_command") { null }
|
||||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
|
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
|
||||||
@@ -91,7 +89,7 @@ object Plugin : Plugin {
|
|||||||
|
|
||||||
edit(
|
edit(
|
||||||
it,
|
it,
|
||||||
it.content.textSources + regular(SuccessfulSymbol)
|
it.content.textSources + regularTextSource(SuccessfulSymbol)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +113,7 @@ object Plugin : Plugin {
|
|||||||
PanelButtonBuilder {
|
PanelButtonBuilder {
|
||||||
CallbackDataInlineKeyboardButton(
|
CallbackDataInlineKeyboardButton(
|
||||||
text,
|
text,
|
||||||
"publish ${it.id.string}"
|
"publish ${it.id.string}",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import dev.inmo.plagubot.Plugin
|
|||||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
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.models.OfferTemplate
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||||
|
import dev.inmo.plagubot.registerConfig
|
||||||
import dev.inmo.plaguposter.common.ChatConfig
|
import dev.inmo.plaguposter.common.ChatConfig
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.repo.ReadPostsRepo
|
import dev.inmo.plaguposter.posts.repo.ReadPostsRepo
|
||||||
@@ -40,7 +41,6 @@ import kotlinx.coroutines.flow.collectIndexed
|
|||||||
import kotlinx.coroutines.flow.take
|
import kotlinx.coroutines.flow.take
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
||||||
|
|
||||||
@@ -62,8 +62,8 @@ object Plugin : Plugin {
|
|||||||
@Transient
|
@Transient
|
||||||
val format: DateFormat = DateFormat(dateTimeFormat)
|
val format: DateFormat = DateFormat(dateTimeFormat)
|
||||||
}
|
}
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(params: JsonObject) {
|
||||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), params["timer_trigger"] ?: return@single null) }
|
registerConfig<Config>("timer_trigger") { null }
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(FlowPreview::class)
|
@OptIn(FlowPreview::class)
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
package dev.inmo.plaguposter.triggers.timer.disablers.autoposts
|
package dev.inmo.plaguposter.triggers.timer.disablers.autoposts
|
||||||
|
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
|
||||||
import dev.inmo.micro_utils.koin.singleWithRandomQualifier
|
import dev.inmo.micro_utils.koin.singleWithRandomQualifier
|
||||||
import dev.inmo.micro_utils.koin.singleWithRandomQualifierAndBinds
|
|
||||||
import dev.inmo.micro_utils.pagination.FirstPagePagination
|
import dev.inmo.micro_utils.pagination.FirstPagePagination
|
||||||
import dev.inmo.micro_utils.repos.unset
|
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
|
||||||
import dev.inmo.plaguposter.triggers.selector_with_timer.AutopostFilter
|
import dev.inmo.plaguposter.triggers.selector_with_timer.AutopostFilter
|
||||||
import dev.inmo.plaguposter.triggers.timer.TimersRepo
|
import dev.inmo.plaguposter.triggers.timer.TimersRepo
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
singleWithRandomQualifier<AutopostFilter> {
|
singleWithRandomQualifier<AutopostFilter> {
|
||||||
val timersRepo = get<TimersRepo>()
|
val timersRepo = get<TimersRepo>()
|
||||||
AutopostFilter { _, dateTime ->
|
AutopostFilter { _, dateTime ->
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
|||||||
import dev.inmo.plaguposter.triggers.timer.TimersRepo
|
import dev.inmo.plaguposter.triggers.timer.TimersRepo
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
singleWithRandomQualifier(createdAtStart = true) {
|
singleWithRandomQualifier(createdAtStart = true) {
|
||||||
val timersRepo = get<TimersRepo>()
|
val timersRepo = get<TimersRepo>()
|
||||||
val ratingsRepo = get<RatingsRepo>()
|
val ratingsRepo = get<RatingsRepo>()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import dev.inmo.plaguposter.posts.models.RegisteredPost
|
|||||||
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
||||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton
|
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton
|
||||||
|
import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle
|
||||||
|
|
||||||
class TimerPanelButton(
|
class TimerPanelButton(
|
||||||
private val timersRepo: TimersRepo
|
private val timersRepo: TimersRepo
|
||||||
@@ -18,7 +19,12 @@ class TimerPanelButton(
|
|||||||
|
|
||||||
return CallbackDataInlineKeyboardButton(
|
return CallbackDataInlineKeyboardButton(
|
||||||
"⏰ ${ if (publishingTime == null) UnsuccessfulSymbol else SuccessfulSymbol }",
|
"⏰ ${ if (publishingTime == null) UnsuccessfulSymbol else SuccessfulSymbol }",
|
||||||
"$timerSetPrefix ${post.id}"
|
"$timerSetPrefix ${post.id}",
|
||||||
|
style = if (publishingTime == null) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
KeyboardButtonStyle.Success
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package dev.inmo.plaguposter.triggers.timer
|
package dev.inmo.plaguposter.triggers.timer
|
||||||
|
|
||||||
import korlibs.time.DateTime
|
|
||||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
import dev.inmo.micro_utils.koin.singleWithRandomQualifierAndBinds
|
import dev.inmo.micro_utils.koin.singleWithRandomQualifierAndBinds
|
||||||
import dev.inmo.micro_utils.repos.set
|
import dev.inmo.micro_utils.repos.set
|
||||||
@@ -9,24 +7,19 @@ import dev.inmo.plagubot.Plugin
|
|||||||
import dev.inmo.plaguposter.common.ChatConfig
|
import dev.inmo.plaguposter.common.ChatConfig
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
||||||
import dev.inmo.plaguposter.posts.repo.ReadPostsRepo
|
|
||||||
import dev.inmo.plaguposter.triggers.timer.repo.ExposedTimersRepo
|
import dev.inmo.plaguposter.triggers.timer.repo.ExposedTimersRepo
|
||||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
|
||||||
import dev.inmo.tgbotapi.extensions.api.send.reply
|
import dev.inmo.tgbotapi.extensions.api.send.reply
|
||||||
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.triggers_handling.onCommand
|
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
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
|
import org.koin.dsl.binds
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(config: JsonObject) {
|
||||||
single { ExposedTimersRepo(get(), get(), get()) } binds arrayOf(TimersRepo::class)
|
single { ExposedTimersRepo(get(), get(), get()) } binds arrayOf(TimersRepo::class)
|
||||||
single(createdAtStart = true) { TimersHandler(get(), get(), get()) }
|
single(createdAtStart = true) { TimersHandler(get(), get(), get()) }
|
||||||
singleWithRandomQualifierAndBinds { TimerPanelButton(get()) }
|
singleWithRandomQualifierAndBinds { TimerPanelButton(get()) }
|
||||||
|
|||||||
@@ -11,15 +11,12 @@ 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.triggers.timer.TimersRepo
|
import dev.inmo.plaguposter.triggers.timer.TimersRepo
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import org.jetbrains.exposed.sql.Column
|
import org.jetbrains.exposed.v1.core.Op
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
import org.jetbrains.exposed.sql.ISqlExpressionBuilder
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
import org.jetbrains.exposed.sql.Op
|
import org.jetbrains.exposed.v1.core.statements.UpdateBuilder
|
||||||
import org.jetbrains.exposed.sql.ResultRow
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
|
||||||
import org.jetbrains.exposed.sql.statements.UpdateBuilder
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
|
||||||
|
|
||||||
class ExposedTimersRepo(
|
class ExposedTimersRepo(
|
||||||
database: Database,
|
database: Database,
|
||||||
@@ -31,8 +28,8 @@ class ExposedTimersRepo(
|
|||||||
) {
|
) {
|
||||||
override val keyColumn = text("post_id")
|
override val keyColumn = text("post_id")
|
||||||
private val dateTimeColumn = long("date_time")
|
private val dateTimeColumn = long("date_time")
|
||||||
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
override val selectById: (PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||||
override val selectByValue: ISqlExpressionBuilder.(DateTime) -> Op<Boolean> = { dateTimeColumn.eq(it.unixMillisLong) }
|
override val selectByValue: (DateTime) -> Op<Boolean> = { dateTimeColumn.eq(it.unixMillisLong) }
|
||||||
override val ResultRow.asKey: PostId
|
override val ResultRow.asKey: PostId
|
||||||
get() = PostId(get(keyColumn))
|
get() = PostId(get(keyColumn))
|
||||||
override val ResultRow.asObject: DateTime
|
override val ResultRow.asObject: DateTime
|
||||||
|
|||||||
Reference in New Issue
Block a user