mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2025-12-06 13:05:39 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2612ec6e9 | |||
| 0273284023 | |||
| 9af72d5d0f | |||
| b879426f9d | |||
| 18b8ce0d3d | |||
| a4686a56df | |||
| e567f5b3b4 | |||
| 3941c1dfed | |||
| 0bdd965a4a | |||
| ad967c002a | |||
| e3958aff3f | |||
| ae6993efba | |||
| 991b0ef3d3 | |||
| aa6c62d66e | |||
| e6a0d67444 | |||
| 16bd62da51 |
1
.github/workflows/build_and_publish.yml
vendored
1
.github/workflows/build_and_publish.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
java-version: 17
|
||||
- name: Rewrite version
|
||||
run: |
|
||||
printf "\norg.gradle.jvmargs=-Xmx1g -Xms500m\nkotlin.daemon.jvmargs=-Xmx1g -Xms500m\norg.gradle.daemon=false" >> gradle.properties
|
||||
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
|
||||
cat gradle.properties | sed -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
|
||||
rm gradle.properties
|
||||
|
||||
1
.github/workflows/docker-publish.yml
vendored
1
.github/workflows/docker-publish.yml
vendored
@@ -16,6 +16,7 @@ jobs:
|
||||
java-version: 17
|
||||
- name: Rewrite version
|
||||
run: |
|
||||
printf "\norg.gradle.jvmargs=-Xmx1g -Xms500m\nkotlin.daemon.jvmargs=-Xmx1g -Xms500m\norg.gradle.daemon=false" >> gradle.properties
|
||||
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
|
||||
if [[ "$branch" != "master" ]]; then
|
||||
cat gradle.properties | sed -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.idea
|
||||
.kotlin/
|
||||
out/*
|
||||
*.iml
|
||||
target
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# PlaguPoster
|
||||
|
||||
## 0.7.0
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.6.0
|
||||
|
||||
* Dependencies update
|
||||
|
||||
## 0.5.6
|
||||
|
||||
* `Ratings`:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
kotlin.code.style=official
|
||||
org.gradle.jvmargs=-Xmx1024m
|
||||
org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
@@ -10,4 +9,4 @@ android.enableJetifier=true
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.5.6
|
||||
version=0.7.0
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
[versions]
|
||||
|
||||
kotlin = "1.9.23"
|
||||
kotlin-serialization = "1.6.3"
|
||||
kotlin = "2.0.20"
|
||||
kotlin-serialization = "1.7.2"
|
||||
|
||||
plagubot = "8.3.0"
|
||||
tgbotapi = "12.0.1"
|
||||
microutils = "0.20.45"
|
||||
kslog = "1.3.3"
|
||||
krontab = "2.2.9"
|
||||
plagubot-plugins = "0.18.3"
|
||||
plagubot = "9.2.0"
|
||||
tgbotapi = "18.1.0"
|
||||
microutils = "0.22.2"
|
||||
kslog = "1.3.6"
|
||||
krontab = "2.4.0"
|
||||
plagubot-plugins = "0.21.0"
|
||||
|
||||
dokka = "1.9.20"
|
||||
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -25,7 +25,6 @@ kotlin {
|
||||
jsTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.js
|
||||
implementation libs.kotlin.test.junit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,13 @@ project.group = "$group"
|
||||
apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
jvm {
|
||||
compilations.main {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
}
|
||||
}
|
||||
js (IR) {
|
||||
browser()
|
||||
nodejs()
|
||||
@@ -31,10 +37,14 @@ kotlin {
|
||||
jsTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.js
|
||||
implementation libs.kotlin.test.junit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class ExposedPostsRepo(
|
||||
id,
|
||||
DateTime(get(createdColumn)),
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(id.string) }.map {
|
||||
selectAll().where { postIdColumn.eq(id.string) }.map {
|
||||
it.asObject
|
||||
}
|
||||
}
|
||||
@@ -69,14 +69,14 @@ class ExposedPostsRepo(
|
||||
id,
|
||||
DateTime(get(createdColumn)),
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(id.string) }.map {
|
||||
selectAll().where { postIdColumn.eq(id.string) }.map {
|
||||
it.asObject
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun createAndInsertId(value: NewPost, it: InsertStatement<Number>): PostId {
|
||||
override fun createAndInsertId(value: NewPost, it: UpdateBuilder<Int>): PostId {
|
||||
val id = PostId(uuid4().toString())
|
||||
it[idColumn] = id.string
|
||||
return id
|
||||
@@ -104,7 +104,7 @@ class ExposedPostsRepo(
|
||||
}
|
||||
}
|
||||
|
||||
override fun insert(value: NewPost, it: InsertStatement<Number>) {
|
||||
override fun insert(value: NewPost, it: UpdateBuilder<Int>) {
|
||||
super.insert(value, it)
|
||||
it[createdColumn] = DateTime.now().unixMillis
|
||||
}
|
||||
@@ -144,7 +144,7 @@ class ExposedPostsRepo(
|
||||
existsIds
|
||||
} else {
|
||||
existsIds.filter {
|
||||
select { selectById(it) }.limit(1).none()
|
||||
selectAll().where { selectById(it) }.limit(1).none()
|
||||
}
|
||||
}
|
||||
}.forEach {
|
||||
@@ -156,7 +156,7 @@ class ExposedPostsRepo(
|
||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageId): PostId? {
|
||||
return transaction(database) {
|
||||
with(contentRepo) {
|
||||
select {
|
||||
selectAll().where {
|
||||
chatIdColumn.eq(chatId.chatId.long)
|
||||
.and(chatId.threadId ?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull())
|
||||
.and(messageIdColumn.eq(messageId.long))
|
||||
@@ -166,12 +166,12 @@ class ExposedPostsRepo(
|
||||
}
|
||||
|
||||
override suspend fun getPostCreationTime(postId: PostId): DateTime? = transaction(database) {
|
||||
select { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
|
||||
selectAll().where { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
|
||||
}
|
||||
|
||||
override suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo? = transaction(database) {
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(postId.string) }.limit(1).firstOrNull() ?.asObject
|
||||
selectAll().where { postIdColumn.eq(postId.string) }.limit(1).firstOrNull() ?.asObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import korlibs.time.seconds
|
||||
import dev.inmo.krontab.KrontabTemplate
|
||||
import dev.inmo.krontab.toSchedule
|
||||
import dev.inmo.krontab.utils.asFlowWithDelays
|
||||
import dev.inmo.kslog.common.KSLog
|
||||
import dev.inmo.kslog.common.i
|
||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.koin.singleWithRandomQualifier
|
||||
@@ -64,14 +66,23 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
config.autoclear ?.let { autoclear ->
|
||||
val autoClearLogger = KSLog("autoclear")
|
||||
suspend fun doAutoClear() {
|
||||
autoClearLogger.i { "Start autoclear" }
|
||||
val dropCreatedBefore = DateTime.now() - (autoclear.skipPostAge ?: 0).seconds
|
||||
ratingsRepo.getPostsWithRatingLessEq(autoclear.rating).keys.forEach {
|
||||
autoClearLogger.i { "Posts drop created before: ${dropCreatedBefore.toStringDefault()}" }
|
||||
val idsToDelete = ratingsRepo.getPostsWithRatingLessEq(autoclear.rating).keys.also {
|
||||
autoClearLogger.i { "Selected posts by rating: $it" }
|
||||
}.filter {
|
||||
val postCreationDateTime = postsRepo.getPostCreationTime(it) ?: (dropCreatedBefore - 1.seconds) // do dropping if post creation time is not available
|
||||
if (postCreationDateTime < dropCreatedBefore) {
|
||||
ratingsRepo.unset(it)
|
||||
postsRepo.deleteById(it)
|
||||
}
|
||||
postCreationDateTime < dropCreatedBefore
|
||||
}
|
||||
autoClearLogger.i { "Filtered posts by datetime: $idsToDelete" }
|
||||
if (idsToDelete.isNotEmpty()) {
|
||||
runCatching { ratingsRepo.unset(idsToDelete) }
|
||||
autoClearLogger.i { "Ratings dropped" }
|
||||
runCatching { postsRepo.deleteById(idsToDelete) }
|
||||
autoClearLogger.i { "Posts dropped" }
|
||||
}
|
||||
}
|
||||
runCatchingSafely {
|
||||
|
||||
@@ -122,7 +122,7 @@ suspend fun BehaviourContext.includeRootNavigationButtonsHandler(
|
||||
|
||||
edit(
|
||||
it.message,
|
||||
onPageUpdate(SimplePagination(page, size), args.drop(3).toTypedArray()) ?: return@runCatchingSafely
|
||||
replyMarkup = onPageUpdate(SimplePagination(page, size), args.drop(3).toTypedArray()) ?: return@runCatchingSafely
|
||||
)
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ suspend fun BehaviourContext.includeRootNavigationButtonsHandler(
|
||||
if (prefix == RootButtonsShowRatingData) {
|
||||
runCatchingSafely {
|
||||
val rating = ratingRaw.toDoubleOrNull() ?: return@runCatchingSafely
|
||||
edit(it.message, ratingsRepo.buildRatingButtons(postsRepo, Rating(rating)))
|
||||
edit(it.message, replyMarkup = ratingsRepo.buildRatingButtons(postsRepo, Rating(rating)))
|
||||
}
|
||||
|
||||
answer(it)
|
||||
|
||||
@@ -28,6 +28,7 @@ import dev.inmo.plaguposter.ratings.utils.postsByRatings
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll
|
||||
import dev.inmo.tgbotapi.extensions.api.send.reply
|
||||
import dev.inmo.tgbotapi.extensions.api.send.send
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
@@ -41,7 +42,10 @@ import dev.inmo.tgbotapi.types.ReplyParameters
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.message.textsources.bold
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import dev.inmo.tgbotapi.types.polls.InputPollOption
|
||||
import dev.inmo.tgbotapi.types.polls.PollOption
|
||||
import dev.inmo.tgbotapi.utils.buildEntities
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeSourceString
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -112,7 +116,7 @@ object Plugin : Plugin {
|
||||
onPollUpdates (markerFactory = { it.id }) { poll ->
|
||||
val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates
|
||||
val newRating = poll.options.sumOf {
|
||||
(variantsTransformer(it.text) ?.double ?.times(it.votes)) ?: 0.0
|
||||
(variantsTransformer(it.textSources.makeSourceString()) ?.double ?.times(it.votes)) ?: 0.0
|
||||
}
|
||||
ratingsRepo.set(postId, Rating(newRating))
|
||||
}
|
||||
@@ -129,7 +133,9 @@ object Plugin : Plugin {
|
||||
val sent = send(
|
||||
content.chatId,
|
||||
config.ratingOfferText,
|
||||
config.variants.keys.toList(),
|
||||
options = config.variants.map {
|
||||
InputPollOption(it.key)
|
||||
},
|
||||
replyParameters = ReplyParameters(content.chatId, content.messageId)
|
||||
)
|
||||
pollsToPostsIdsRepo.set(sent.content.poll.id, postId)
|
||||
@@ -265,7 +271,7 @@ object Plugin : Plugin {
|
||||
onMessageDataCallbackQuery("ratings_interactive", initialFilter = { it.message.chat.id in chatConfig.allSourceChatIds }) {
|
||||
edit(
|
||||
it.message,
|
||||
ratingsRepo.buildRootButtons()
|
||||
replyMarkup = ratingsRepo.buildRootButtons()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class ExposedPollsToMessagesInfoRepo(
|
||||
it[messageIdColumn] = v.messageId.long
|
||||
}
|
||||
|
||||
override fun insertKey(k: PollId, v: ShortMessageInfo, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PollId, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class ExposedPollsToPostsIdsRepo(
|
||||
it[postIdColumn] = v.string
|
||||
}
|
||||
|
||||
override fun insertKey(k: PollId, v: PostId, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PollId, v: PostId, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package dev.inmo.plaguposter.ratings.repo
|
||||
|
||||
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
||||
import dev.inmo.micro_utils.pagination.utils.optionallyReverse
|
||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.MapKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.cache.full.FullKeyValueCacheRepo
|
||||
@@ -13,26 +15,30 @@ class CachedRatingsRepo(
|
||||
private val scope: CoroutineScope,
|
||||
private val kvCache: MapKeyValueRepo<PostId, Rating> = MapKeyValueRepo()
|
||||
) : RatingsRepo, KeyValueRepo<PostId, Rating> by FullKeyValueCacheRepo(base, kvCache, scope) {
|
||||
private suspend fun getPosts(
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>,
|
||||
ratingFilter: (Rating) -> Boolean
|
||||
): Map<PostId, Rating> {
|
||||
return kvCache.getAll().filter { (it, rating) ->
|
||||
it !in exclude && ratingFilter(rating)
|
||||
}.let {
|
||||
if (count == null) {
|
||||
it
|
||||
} else {
|
||||
val keys = it.keys.optionallyReverse(reversed).take(count)
|
||||
keys.associateWith { id -> it.getValue(id) }
|
||||
}
|
||||
}
|
||||
}
|
||||
override suspend fun getPosts(
|
||||
range: ClosedRange<Rating>,
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> {
|
||||
val result = mutableMapOf<PostId, Rating>()
|
||||
|
||||
doForAllWithNextPaging {
|
||||
kvCache.keys(it).also {
|
||||
it.results.forEach {
|
||||
val rating = get(it) ?: return@forEach
|
||||
if (it !in exclude && rating in range) {
|
||||
result[it] = rating
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.toMap()
|
||||
): Map<PostId, Rating> = getPosts(reversed, count, exclude) {
|
||||
it in range
|
||||
}
|
||||
|
||||
override suspend fun getPostsWithRatingGreaterEq(
|
||||
@@ -40,22 +46,16 @@ class CachedRatingsRepo(
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> = getPosts(
|
||||
then .. Rating(Double.MAX_VALUE),
|
||||
reversed,
|
||||
count,
|
||||
exclude
|
||||
)
|
||||
): Map<PostId, Rating> = getPosts(reversed, count, exclude) {
|
||||
it >= then
|
||||
}
|
||||
|
||||
override suspend fun getPostsWithRatingLessEq(
|
||||
then: Rating,
|
||||
reversed: Boolean,
|
||||
count: Int?,
|
||||
exclude: List<PostId>
|
||||
): Map<PostId, Rating> = getPosts(
|
||||
Rating(Double.MIN_VALUE) .. then,
|
||||
reversed,
|
||||
count,
|
||||
exclude
|
||||
)
|
||||
): Map<PostId, Rating> = getPosts(reversed, count, exclude) {
|
||||
it <= then
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class ExposedRatingsRepo (
|
||||
it[ratingsColumn] = v.double
|
||||
}
|
||||
|
||||
override fun insertKey(k: PostId, v: Rating, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PostId, v: Rating, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function assert_success() {
|
||||
|
||||
app=plaguposter
|
||||
version="`grep ../gradle.properties -e "^version=" | sed -e "s/version=\(.*\)/\1/"`"
|
||||
server=insanusmokrassar
|
||||
server=docker.inmo.dev
|
||||
|
||||
assert_success ../gradlew build
|
||||
assert_success sudo docker build -t $app:"$version" .
|
||||
|
||||
@@ -50,7 +50,7 @@ class ExposedTimersRepo(
|
||||
it[dateTimeColumn] = v.unixMillisLong
|
||||
}
|
||||
|
||||
override fun insertKey(k: PostId, v: DateTime, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PostId, v: DateTime, it: UpdateBuilder<Int>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user