mirror of
https://github.com/InsanusMokrassar/TelegramBotApiLibraries.git
synced 2024-12-22 16:47:16 +00:00
first version of adminbot
This commit is contained in:
parent
3fe45e4aec
commit
e638aff72a
@ -6,3 +6,12 @@ plugins {
|
|||||||
|
|
||||||
apply from: "$mppProjectWithSerializationPresetPath"
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api "dev.inmo:tgbotapi:$tgbotapi_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package dev.inmo.tgbotapi.libraries.cache.admins
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
||||||
|
|
||||||
|
interface AdminsCacheAPI {
|
||||||
|
suspend fun getChatAdmins(chatId: ChatId): List<AdministratorChatMember>?
|
||||||
|
suspend fun isAdmin(userId: UserId, chatId: ChatId): Boolean
|
||||||
|
|
||||||
|
suspend fun settings(): AdminsCacheSettingsAPI
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package dev.inmo.tgbotapi.libraries.cache.admins
|
||||||
|
|
||||||
|
import com.soywiz.klock.minutes
|
||||||
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
|
import dev.inmo.tgbotapi.types.Seconds
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AdminsCacheSettings(
|
||||||
|
val refreshSeconds: Seconds = 10.minutes.seconds.toInt(),
|
||||||
|
/**
|
||||||
|
* In case this setting set up to true, will request admins list just from time to time instead of refreshing on
|
||||||
|
* requests
|
||||||
|
*/
|
||||||
|
val disableRequestsRefreshMode: Boolean = false
|
||||||
|
) {
|
||||||
|
val refreshOnRequests: Boolean
|
||||||
|
get() = !disableRequestsRefreshMode
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AdminsCacheSettingsAPI {
|
||||||
|
suspend fun getChatSettings(chatId: ChatId): AdminsCacheSettings?
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MutableAdminsCacheSettingsAPI : AdminsCacheSettingsAPI {
|
||||||
|
val chatSettingsUpdatedFlow: SharedFlow<Pair<ChatId, AdminsCacheSettings>>
|
||||||
|
|
||||||
|
suspend fun setChatSettings(chatId: ChatId, settings: AdminsCacheSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AdminsCacheSettingsAPI.asMutable(): MutableAdminsCacheSettingsAPI? = this as? MutableAdminsCacheSettingsAPI
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class StaticAdminsCacheSettingsAPI(
|
||||||
|
private val settings: Map<ChatId, AdminsCacheSettings>
|
||||||
|
) : AdminsCacheSettingsAPI {
|
||||||
|
override suspend fun getChatSettings(chatId: ChatId): AdminsCacheSettings? = settings[chatId]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
package dev.inmo.tgbotapi.libraries.cache.admins
|
||||||
|
|
||||||
|
import com.soywiz.klock.DateTime
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.extensions.api.chat.get.getChatAdministrators
|
||||||
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
interface DefaultAdminsCacheAPIRepo {
|
||||||
|
suspend fun getChatAdmins(chatId: ChatId): List<AdministratorChatMember>?
|
||||||
|
suspend fun setChatAdmins(chatId: ChatId, chatMembers: List<AdministratorChatMember>)
|
||||||
|
suspend fun lastUpdate(chatId: ChatId): DateTime?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class DefaultAdminsCacheAPI(
|
||||||
|
private val bot: TelegramBot,
|
||||||
|
private val repo: DefaultAdminsCacheAPIRepo,
|
||||||
|
private val settingsAPI: AdminsCacheSettingsAPI
|
||||||
|
) : AdminsCacheAPI {
|
||||||
|
private suspend fun triggerUpdate(chatId: ChatId): List<AdministratorChatMember> {
|
||||||
|
val admins = bot.getChatAdministrators(chatId)
|
||||||
|
repo.setChatAdmins(chatId, admins)
|
||||||
|
return admins
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getChatAdmins(chatId: ChatId): List<AdministratorChatMember>? {
|
||||||
|
val settings = settingsAPI.getChatSettings(chatId)
|
||||||
|
val lastUpdate = repo.lastUpdate(chatId)
|
||||||
|
return when {
|
||||||
|
settings == null -> null
|
||||||
|
settings.refreshOnRequests &&
|
||||||
|
(lastUpdate == null || (DateTime.now() - lastUpdate).seconds > settings.refreshSeconds) -> {
|
||||||
|
triggerUpdate(chatId)
|
||||||
|
}
|
||||||
|
else -> repo.getChatAdmins(chatId) ?: triggerUpdate(chatId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun isAdmin(userId: UserId, chatId: ChatId): Boolean = getChatAdmins(chatId) ?.any {
|
||||||
|
it.user.id == userId
|
||||||
|
} == true
|
||||||
|
|
||||||
|
override suspend fun settings(): AdminsCacheSettingsAPI = settingsAPI
|
||||||
|
|
||||||
|
}
|
25
cache/admins/micro_utils/build.gradle
vendored
Normal file
25
cache/admins/micro_utils/build.gradle
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
plugins {
|
||||||
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
id "com.android.library"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api "dev.inmo:micro_utils.repos.common:$micro_utils_version"
|
||||||
|
api project(":tgbotapi.libraries.cache.admins.common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jvmMain {
|
||||||
|
dependencies {
|
||||||
|
api "dev.inmo:micro_utils.repos.exposed:$micro_utils_version"
|
||||||
|
api "org.jetbrains.kotlinx:kotlinx-serialization-cbor:$kotlin_serialisation_core_version"
|
||||||
|
api "org.jetbrains.exposed:exposed-jdbc:$exposed_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package dev.inmo.tgbotapi.libraries.cache.admins.micro_utils
|
||||||
|
|
||||||
|
import com.soywiz.klock.DateTime
|
||||||
|
import dev.inmo.micro_utils.coroutines.actor
|
||||||
|
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.tgbotapi.libraries.cache.admins.DefaultAdminsCacheAPIRepo
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
|
private sealed class RepoActions<T> {
|
||||||
|
abstract val toReturn: Continuation<T>
|
||||||
|
}
|
||||||
|
private class GetUpdateDateTimeRepoAction(
|
||||||
|
val chatId: ChatId,
|
||||||
|
override val toReturn: Continuation<DateTime?>
|
||||||
|
) : RepoActions<DateTime?>()
|
||||||
|
private class GetChatAdminsRepoAction(
|
||||||
|
val chatId: ChatId,
|
||||||
|
override val toReturn: Continuation<List<AdministratorChatMember>?>
|
||||||
|
) : RepoActions<List<AdministratorChatMember>?>()
|
||||||
|
private class SetChatAdminsRepoAction(
|
||||||
|
val chatId: ChatId,
|
||||||
|
val newValue: List<AdministratorChatMember>,
|
||||||
|
override val toReturn: Continuation<Unit>
|
||||||
|
) : RepoActions<Unit>()
|
||||||
|
|
||||||
|
class DefaultAdminsCacheAPIRepo(
|
||||||
|
private val adminsRepo: KeyValuesRepo<ChatId, AdministratorChatMember>,
|
||||||
|
private val updatesRepo: KeyValueRepo<ChatId, MilliSeconds>,
|
||||||
|
private val scope: CoroutineScope
|
||||||
|
) : DefaultAdminsCacheAPIRepo {
|
||||||
|
private val actor = scope.actor<RepoActions<*>>(Channel.UNLIMITED) {
|
||||||
|
safelyWithoutExceptions {
|
||||||
|
when (it) {
|
||||||
|
is GetUpdateDateTimeRepoAction -> it.toReturn.resume(
|
||||||
|
updatesRepo.get(it.chatId) ?.let { DateTime(it.toDouble()) }
|
||||||
|
)
|
||||||
|
is GetChatAdminsRepoAction -> it.toReturn.resume(adminsRepo.getAll(it.chatId))
|
||||||
|
is SetChatAdminsRepoAction -> {
|
||||||
|
adminsRepo.clear(it.chatId)
|
||||||
|
adminsRepo.set(it.chatId, it.newValue)
|
||||||
|
updatesRepo.set(it.chatId, DateTime.now().unixMillisLong)
|
||||||
|
it.toReturn.resume(Unit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getChatAdmins(chatId: ChatId): List<AdministratorChatMember>? = suspendCoroutine {
|
||||||
|
actor.offer(GetChatAdminsRepoAction(chatId, it))
|
||||||
|
}
|
||||||
|
override suspend fun setChatAdmins(chatId: ChatId, chatMembers: List<AdministratorChatMember>) = suspendCoroutine<Unit> {
|
||||||
|
actor.offer(SetChatAdminsRepoAction(chatId, chatMembers, it))
|
||||||
|
}
|
||||||
|
override suspend fun lastUpdate(chatId: ChatId): DateTime? = suspendCoroutine {
|
||||||
|
actor.offer(GetUpdateDateTimeRepoAction(chatId, it))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package dev.inmo.tgbotapi.libraries.cache.admins.micro_utils
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.tgbotapi.libraries.cache.admins.*
|
||||||
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
class DynamicAdminsCacheSettingsAPI(
|
||||||
|
private val repo: KeyValueRepo<ChatId, AdminsCacheSettings>,
|
||||||
|
private val scope: CoroutineScope
|
||||||
|
) : AdminsCacheSettingsAPI, MutableAdminsCacheSettingsAPI {
|
||||||
|
override val chatSettingsUpdatedFlow: SharedFlow<Pair<ChatId, AdminsCacheSettings>>
|
||||||
|
get() = repo.onNewValue.shareIn(scope, SharingStarted.Eagerly)
|
||||||
|
|
||||||
|
override suspend fun setChatSettings(chatId: ChatId, settings: AdminsCacheSettings) {
|
||||||
|
repo.set(chatId, settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getChatSettings(chatId: ChatId): AdminsCacheSettings {
|
||||||
|
val settings = repo.get(chatId)
|
||||||
|
return if (settings == null) {
|
||||||
|
val newSettings = AdminsCacheSettings()
|
||||||
|
setChatSettings(chatId, newSettings)
|
||||||
|
newSettings
|
||||||
|
} else {
|
||||||
|
settings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package dev.inmo.tgbotapi.libraries.cache.admins
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedOneToManyKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.mappers.withMapper
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DefaultAdminsCacheAPIRepo
|
||||||
|
import dev.inmo.tgbotapi.libraries.cache.admins.micro_utils.DynamicAdminsCacheSettingsAPI
|
||||||
|
import dev.inmo.tgbotapi.types.toChatId
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.serialization.cbor.Cbor
|
||||||
|
import kotlinx.serialization.decodeFromByteArray
|
||||||
|
import kotlinx.serialization.encodeToByteArray
|
||||||
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
|
||||||
|
|
||||||
|
private val serializationFormat = Cbor
|
||||||
|
|
||||||
|
fun AdminsCacheAPI(
|
||||||
|
bot: TelegramBot,
|
||||||
|
database: Database,
|
||||||
|
scope: CoroutineScope,
|
||||||
|
repo: dev.inmo.tgbotapi.libraries.cache.admins.DefaultAdminsCacheAPIRepo = DefaultAdminsCacheAPIRepo(
|
||||||
|
ExposedOneToManyKeyValueRepo(
|
||||||
|
database,
|
||||||
|
{ long("chatId") },
|
||||||
|
{ blob("member") },
|
||||||
|
"AdminsTable"
|
||||||
|
).withMapper(
|
||||||
|
keyFromToTo = { chatId },
|
||||||
|
valueFromToTo = { ExposedBlob(serializationFormat.encodeToByteArray(this)) },
|
||||||
|
keyToToFrom = { toChatId() },
|
||||||
|
valueToToFrom = { serializationFormat.decodeFromByteArray(bytes) }
|
||||||
|
),
|
||||||
|
ExposedKeyValueRepo(
|
||||||
|
database,
|
||||||
|
{ long("chatId") },
|
||||||
|
{ long("datetime") },
|
||||||
|
"AdminsUpdatesTimesTable"
|
||||||
|
).withMapper(
|
||||||
|
keyFromToTo = { chatId },
|
||||||
|
keyToToFrom = { toChatId() }
|
||||||
|
),
|
||||||
|
scope
|
||||||
|
),
|
||||||
|
settingsAPI: AdminsCacheSettingsAPI = DynamicAdminsCacheSettingsAPI(
|
||||||
|
ExposedKeyValueRepo(
|
||||||
|
database,
|
||||||
|
{ long("chatId") },
|
||||||
|
{ blob("settings") },
|
||||||
|
"DynamicAdminsCacheSettingsAPI"
|
||||||
|
).withMapper(
|
||||||
|
keyFromToTo = { chatId },
|
||||||
|
valueFromToTo = { ExposedBlob(serializationFormat.encodeToByteArray(this)) },
|
||||||
|
keyToToFrom = { toChatId() },
|
||||||
|
valueToToFrom = { serializationFormat.decodeFromByteArray(bytes) }
|
||||||
|
),
|
||||||
|
scope
|
||||||
|
)
|
||||||
|
) : AdminsCacheAPI = DefaultAdminsCacheAPI(
|
||||||
|
bot,
|
||||||
|
repo,
|
||||||
|
settingsAPI
|
||||||
|
)
|
1
cache/admins/micro_utils/src/main/AndroidManifest.xml
vendored
Normal file
1
cache/admins/micro_utils/src/main/AndroidManifest.xml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest package="dev.inmo.tgbotapi.libraries.cache.admins.micro_utils"/>
|
@ -13,6 +13,7 @@ github_release_plugin_version=2.2.12
|
|||||||
|
|
||||||
tgbotapi_version=0.32.8
|
tgbotapi_version=0.32.8
|
||||||
micro_utils_version=0.4.26
|
micro_utils_version=0.4.26
|
||||||
|
exposed_version=0.29.1
|
||||||
|
|
||||||
# ANDROID
|
# ANDROID
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
rootProject.name = 'tgbotapi.libraries'
|
rootProject.name = 'tgbotapi.libraries'
|
||||||
|
|
||||||
String[] includes = [
|
String[] includes = [
|
||||||
":cache:admins",
|
":cache:admins:common",
|
||||||
|
":cache:admins:micro_utils",
|
||||||
":cache:media"
|
":cache:media"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user