From 53630d4864aa29bd30da08183ccf099e5527a47e Mon Sep 17 00:00:00 2001
From: InsanusMokrassar <ovsyannikov.alexey95@gmail.com>
Date: Fri, 9 Sep 2022 19:16:19 +0600
Subject: [PATCH] rework of plagubot part of admins plugin

---
 .../micro_utils/DefaultAdminsCacheAPI.kt      |  8 ++-
 .../libraries/cache/admins/AdminsCacheAPI.kt  | 16 ++---
 .../libraries/cache/admins/AdminsPlugin.kt    | 69 ++++++++++++++++---
 3 files changed, 74 insertions(+), 19 deletions(-)

diff --git a/cache/admins/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/micro_utils/DefaultAdminsCacheAPI.kt b/cache/admins/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/micro_utils/DefaultAdminsCacheAPI.kt
index 0027b85..bfb6249 100644
--- a/cache/admins/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/micro_utils/DefaultAdminsCacheAPI.kt
+++ b/cache/admins/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/micro_utils/DefaultAdminsCacheAPI.kt
@@ -28,7 +28,7 @@ private class SetChatAdminsRepoAction(
     override val toReturn: Continuation<Unit>
 ) : RepoActions<Unit>()
 
-class DefaultAdminsCacheAPIRepo(
+class DefaultAdminsCacheAPIRepoImpl(
     private val adminsRepo: KeyValuesRepo<ChatId, AdministratorChatMember>,
     private val updatesRepo: KeyValueRepo<ChatId, MilliSeconds>,
     private val scope: CoroutineScope
@@ -60,3 +60,9 @@ class DefaultAdminsCacheAPIRepo(
         actor.trySend(GetUpdateDateTimeRepoAction(chatId, it))
     }
 }
+
+fun DefaultAdminsCacheAPIRepo(
+    adminsRepo: KeyValuesRepo<ChatId, AdministratorChatMember>,
+    updatesRepo: KeyValueRepo<ChatId, MilliSeconds>,
+    scope: CoroutineScope
+) = DefaultAdminsCacheAPIRepoImpl(adminsRepo, updatesRepo, scope)
diff --git a/cache/admins/micro_utils/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheAPI.kt b/cache/admins/micro_utils/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheAPI.kt
index 5a57304..c7609a2 100644
--- a/cache/admins/micro_utils/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheAPI.kt
+++ b/cache/admins/micro_utils/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheAPI.kt
@@ -5,20 +5,18 @@ import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedKeyValuesRepo
 import dev.inmo.micro_utils.repos.mappers.withMapper
 import dev.inmo.tgbotapi.bot.TelegramBot
 import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
-import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DefaultAdminsCacheAPIRepo
+import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DefaultAdminsCacheAPIRepoImpl
 import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DynamicAdminsCacheSettingsAPI
 import dev.inmo.tgbotapi.types.*
 import dev.inmo.tgbotapi.types.chat.member.*
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.serialization.*
-import kotlinx.serialization.cbor.Cbor
 import kotlinx.serialization.json.Json
 import kotlinx.serialization.modules.SerializersModule
 import kotlinx.serialization.modules.polymorphic
 import org.jetbrains.exposed.sql.Database
-import org.jetbrains.exposed.sql.statements.api.ExposedBlob
 
-private val serializationFormat = Json {
+val telegramAdminsSerializationFormat = Json {
     ignoreUnknownKeys = true
     serializersModule = SerializersModule {
         polymorphic(AdministratorChatMember::class) {
@@ -35,7 +33,7 @@ fun AdminsCacheAPI(
     scope: CoroutineScope
 ) : AdminsCacheAPI = DefaultAdminsCacheAPI(
     bot,
-    DefaultAdminsCacheAPIRepo(
+    DefaultAdminsCacheAPIRepoImpl(
         ExposedKeyValuesRepo(
             database,
             { long("chatId") },
@@ -43,9 +41,9 @@ fun AdminsCacheAPI(
             "AdminsTable"
         ).withMapper<ChatId, AdministratorChatMember, Identifier, String>(
             keyFromToTo = { chatId },
-            valueFromToTo = { serializationFormat.encodeToString(this) },
+            valueFromToTo = { telegramAdminsSerializationFormat.encodeToString(this) },
             keyToToFrom = { toChatId() },
-            valueToToFrom = { serializationFormat.decodeFromString(this) }
+            valueToToFrom = { telegramAdminsSerializationFormat.decodeFromString(this) }
         ),
         ExposedKeyValueRepo(
             database,
@@ -68,9 +66,9 @@ fun AdminsCacheAPI(
             "DynamicAdminsCacheSettingsAPI"
         ).withMapper<ChatId, AdminsCacheSettings, Identifier, String>(
             keyFromToTo = { chatId },
-            valueFromToTo = { serializationFormat.encodeToString(this) },
+            valueFromToTo = { telegramAdminsSerializationFormat.encodeToString(this) },
             keyToToFrom = { toChatId() },
-            valueToToFrom = { serializationFormat.decodeFromString(this) }
+            valueToToFrom = { telegramAdminsSerializationFormat.decodeFromString(this) }
         ),
         scope
     )
diff --git a/cache/admins/plagubot/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsPlugin.kt b/cache/admins/plagubot/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsPlugin.kt
index a53a14a..1527c76 100644
--- a/cache/admins/plagubot/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsPlugin.kt
+++ b/cache/admins/plagubot/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsPlugin.kt
@@ -1,17 +1,24 @@
 package dev.inmo.tgbotapi.libraries.cache.admins
 
+import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
+import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedKeyValuesRepo
+import dev.inmo.micro_utils.repos.mappers.withMapper
 import dev.inmo.plagubot.Plugin
 import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
-import dev.inmo.tgbotapi.types.ChatId
+import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DefaultAdminsCacheAPIRepoImpl
+import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DynamicAdminsCacheSettingsAPI
+import dev.inmo.tgbotapi.types.*
+import dev.inmo.tgbotapi.types.chat.member.AdministratorChatMember
+import kotlinx.coroutines.*
 import kotlinx.coroutines.flow.*
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
+import kotlinx.serialization.*
 import kotlinx.serialization.json.JsonObject
 import org.jetbrains.exposed.sql.Database
 import org.koin.core.Koin
 import org.koin.core.module.Module
+import org.koin.core.qualifier.named
 import org.koin.core.scope.Scope
 
 val Scope.adminsPlugin: AdminsPlugin?
@@ -28,6 +35,7 @@ class AdminsPlugin : Plugin {
     private val databaseToAdminsCacheAPI = mutableMapOf<Database, MutableStateFlow<AdminsCacheAPI?>>()
     private val mutex = Mutex()
 
+    @Deprecated("Will be removed soon due to its redundancy")
     suspend fun adminsAPI(database: Database): AdminsCacheAPI {
         val flow = mutex.withLock {
             databaseToAdminsCacheAPI.getOrPut(database){ MutableStateFlow(null) }
@@ -37,16 +45,59 @@ class AdminsPlugin : Plugin {
 
     override fun Module.setupDI(database: Database, params: JsonObject) {
         single { this@AdminsPlugin }
+        val scopeQualifier = named("admins plugin scope")
+        single(scopeQualifier) { CoroutineScope(Dispatchers.IO + SupervisorJob()) }
+        single<DefaultAdminsCacheAPIRepo> {
+            DefaultAdminsCacheAPIRepoImpl(
+                ExposedKeyValuesRepo(
+                    database,
+                    { long("chatId") },
+                    { text("member") },
+                    "AdminsTable"
+                ).withMapper<ChatId, AdministratorChatMember, Identifier, String>(
+                    keyFromToTo = { chatId },
+                    valueFromToTo = { telegramAdminsSerializationFormat.encodeToString(this) },
+                    keyToToFrom = { toChatId() },
+                    valueToToFrom = { telegramAdminsSerializationFormat.decodeFromString(this) }
+                ),
+                ExposedKeyValueRepo(
+                    database,
+                    { long("chatId") },
+                    { long("datetime") },
+                    "AdminsUpdatesTimesTable"
+                ).withMapper<ChatId, Long, Identifier, Long>(
+                    keyFromToTo = { chatId },
+                    valueFromToTo = { this },
+                    keyToToFrom = { toChatId() },
+                    valueToToFrom = { this }
+                ),
+                get(scopeQualifier)
+            )
+        }
+        single<AdminsCacheSettingsAPI> {
+            DynamicAdminsCacheSettingsAPI(
+                ExposedKeyValueRepo(
+                    database,
+                    { long("chatId") },
+                    { text("settings") },
+                    "DynamicAdminsCacheSettingsAPI"
+                ).withMapper<ChatId, AdminsCacheSettings, Identifier, String>(
+                    keyFromToTo = { chatId },
+                    valueFromToTo = { telegramAdminsSerializationFormat.encodeToString(this) },
+                    keyToToFrom = { toChatId() },
+                    valueToToFrom = { telegramAdminsSerializationFormat.decodeFromString(this) }
+                ),
+                get(scopeQualifier)
+            )
+        }
+        single { DefaultAdminsCacheAPI(get(), get(), get()) }
     }
 
     override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
         with(koin) {
-            mutex.withLock {
-                val flow = databaseToAdminsCacheAPI.getOrPut(koin.get()){ MutableStateFlow(null) }
-                if (flow.value == null) {
-                    flow.value = AdminsCacheAPI(koin.get())
-                }
-            }
+            activateAdminsChangesListening(
+                get()
+            )
         }
     }
 }