16 Commits
0.5.6 ... 0.7.0

19 changed files with 100 additions and 64 deletions

View File

@@ -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

View File

@@ -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
View File

@@ -1,4 +1,5 @@
.idea
.kotlin/
out/*
*.iml
target

View File

@@ -1,5 +1,13 @@
# PlaguPoster
## 0.7.0
* Dependencies update
## 0.6.0
* Dependencies update
## 0.5.6
* `Ratings`:

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -25,7 +25,6 @@ kotlin {
jsTest {
dependencies {
implementation libs.kotlin.test.js
implementation libs.kotlin.test.junit
}
}
}

View File

@@ -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
}

View File

@@ -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
}
}
}

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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()
)
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}

View File

@@ -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" .

View File

@@ -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
}