fixes and improvements

This commit is contained in:
InsanusMokrassar 2022-09-10 18:54:25 +06:00
parent b2719c0760
commit cea8ba47db
7 changed files with 116 additions and 59 deletions

View File

@ -15,8 +15,11 @@ data class AdminsCacheSettings(
*/
val disableRequestsRefreshMode: Boolean = false
) {
val refreshOnRequests: Boolean
val refreshOnCacheCalls: Boolean
get() = !disableRequestsRefreshMode
@Deprecated("Renamed", ReplaceWith("refreshOnCacheCalls"))
val refreshOnRequests: Boolean
get() = refreshOnCacheCalls
}
interface AdminsCacheSettingsAPI {

View File

@ -7,17 +7,19 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMe
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatChatMemberUpdatedMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.chat.member.AdministratorChatMember
import dev.inmo.tgbotapi.types.chat.member.ChatMemberUpdated
import dev.inmo.tgbotapi.types.update.abstracts.Update
import kotlinx.coroutines.Job
suspend fun BehaviourContext.activateAdminsChangesListening(
repo: DefaultAdminsCacheAPIRepo,
initialFilter: SimpleFilter<ChatMemberUpdated>? = null,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory
) {
): Job {
val me = getMe()
onChatMemberUpdated(initialFilter, markerFactory = markerFactory) {
return onChatMemberUpdated(initialFilter, markerFactory = markerFactory) {
when {
it.oldChatMemberState is AdministratorChatMember && it.newChatMemberState !is AdministratorChatMember ||
it.newChatMemberState is AdministratorChatMember && it.oldChatMemberState !is AdministratorChatMember -> {
@ -30,3 +32,13 @@ suspend fun BehaviourContext.activateAdminsChangesListening(
}
}
}
suspend fun BehaviourContext.activateAdminsChangesListening(
repo: DefaultAdminsCacheAPIRepo,
allowedChats: List<ChatId>
) = activateAdminsChangesListening(
repo,
{
it.chat.id in allowedChats
}
)

View File

@ -0,0 +1,37 @@
package dev.inmo.tgbotapi.libraries.cache.admins
import dev.inmo.tgbotapi.abstracts.FromUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.message.abstracts.Message
fun AdminsChecker(
adminsCacheAPI: AdminsCacheAPI
): SimpleFilter<Pair<ChatId, UserId>> = SimpleFilter {
adminsCacheAPI.isAdmin(it.first, it.second)
}
fun <T> AdminsChecker(
adminsCacheAPI: AdminsCacheAPI,
mapper: (T) -> Pair<ChatId, UserId>
): SimpleFilter<T> {
val baseChecker = AdminsChecker(adminsCacheAPI)
return SimpleFilter<T> {
baseChecker(mapper(it))
}
}
fun MessageAdminsChecker(
adminsCacheAPI: AdminsCacheAPI
) = SimpleFilter<Message> {
adminsCacheAPI.isAdmin(it)
}
fun AdminsChecker(
adminsCacheAPI: AdminsCacheAPI,
chatId: ChatId
) = SimpleFilter<FromUser> {
adminsCacheAPI.isAdmin(chatId, it.from.id)
}

View File

@ -3,7 +3,7 @@ package dev.inmo.tgbotapi.libraries.cache.admins
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.chat.get.getChatAdministrators
import dev.inmo.tgbotapi.extensions.api.chat.members.getChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.ExtendedBot
import dev.inmo.tgbotapi.types.chat.member.AdministratorChatMember
@ -34,7 +34,7 @@ class DefaultAdminsCacheAPI(
val lastUpdate = repo.lastUpdate(chatId)
return when {
settings == null -> null
settings.refreshOnRequests &&
settings.refreshOnCacheCalls &&
(lastUpdate == null || (DateTime.now() - lastUpdate).seconds > settings.refreshSeconds) -> {
bot.updateAdmins(chatId, repo, getBotInfo())
}
@ -42,6 +42,24 @@ class DefaultAdminsCacheAPI(
}
}
override suspend fun isAdmin(chatId: ChatId, userId: UserId): Boolean {
val settings = settingsAPI.getChatSettings(chatId)
val lastUpdate = repo.lastUpdate(chatId)
return when {
settings == null -> return false
settings.refreshOnCacheCalls && (lastUpdate == null || (DateTime.now() - lastUpdate).seconds > settings.refreshSeconds) -> {
bot.updateAdmins(chatId, repo, getBotInfo())
}
else -> {
val chatAdmins = repo.getChatAdmins(chatId)
if (chatAdmins == null) {
return bot.getChatMember(chatId, userId) is AdministratorChatMember
}
chatAdmins
}
}.any { it.user.id == userId }
}
override suspend fun sentByAdmin(groupContentMessage: GroupContentMessage<*>): Boolean {
return when (groupContentMessage) {
is AnonymousGroupContentMessage -> true

View File

@ -4,17 +4,40 @@ import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.message.abstracts.*
suspend fun AdminsCacheAPI.verifyMessageFromAdmin(message: ContentMessage<*>) = when (message) {
suspend inline fun AdminsCacheAPI.isAdmin(message: Message) = when (message) {
is CommonGroupContentMessage<*> -> isAdmin(message.chat.id, message.user.id)
is AnonymousGroupContentMessage<*> -> true
else -> false
}
suspend fun <R> ContentMessage<*>.doAfterVerification(adminsCacheAPI: AdminsCacheAPI, block: suspend () -> R): R? {
val verified = adminsCacheAPI.verifyMessageFromAdmin(this)
suspend inline fun AdminsCacheAPI.verifyMessageFromAdmin(message: Message) = isAdmin(message)
suspend inline fun <R : Any> AdminsCacheAPI.doIfAdmin(
chatId: ChatId,
userId: UserId,
block: () -> R
) = if(isAdmin(chatId, userId)) {
block()
} else {
null
}
suspend inline fun <R : Any> AdminsCacheAPI.doIfAdmin(
message: Message,
block: () -> R
) = if(isAdmin(message)) {
block()
} else {
null
}
suspend inline fun <R> ContentMessage<*>.doIfAdmin(adminsCacheAPI: AdminsCacheAPI, block: () -> R): R? {
val verified = adminsCacheAPI.isAdmin(this)
return if (verified) {
block()
} else {
null
}
}
suspend inline fun <R> ContentMessage<*>.doAfterVerification(adminsCacheAPI: AdminsCacheAPI, block: () -> R) = doIfAdmin(adminsCacheAPI, block)

View File

@ -53,6 +53,10 @@ class DefaultAdminsCacheAPIRepoImpl(
override suspend fun getChatAdmins(chatId: ChatId): List<AdministratorChatMember>? = suspendCoroutine {
actor.trySend(GetChatAdminsRepoAction(chatId, it))
}
override suspend fun tryGetChatAdmins(chatId: ChatId): List<AdministratorChatMember>? {
TODO("Not yet implemented")
}
override suspend fun setChatAdmins(chatId: ChatId, chatMembers: List<AdministratorChatMember>) = suspendCoroutine<Unit> {
actor.trySend(SetChatAdminsRepoAction(chatId, chatMembers, it))
}

View File

@ -1,7 +1,5 @@
package dev.inmo.tgbotapi.libraries.cache.admins
import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.KeyValuesRepo
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
@ -29,56 +27,9 @@ val telegramAdminsSerializationFormat = Json {
}
}
fun AdminsCacheAPI(
bot: TelegramBot,
database: Database,
scope: CoroutineScope
) : AdminsCacheAPI = DefaultAdminsCacheAPI(
bot,
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 }
),
scope
),
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) }
),
scope
)
)
fun BehaviourContext.createAdminsCacheAPI(database: Database) = AdminsCacheAPI(this, database, this)
fun BehaviourContext.AdminsCacheAPI(database: Database) = AdminsCacheAPI(this, database, this)
fun BehaviourContext.AdminsCacheAPI(
fun TelegramBot.createAdminsCacheAPI(
database: Database,
scope: CoroutineScope,
defaultAdminsCacheAPIRepo: DefaultAdminsCacheAPIRepo = DefaultAdminsCacheAPIRepoImpl(
@ -121,3 +72,12 @@ fun BehaviourContext.AdminsCacheAPI(
scope
)
) = DefaultAdminsCacheAPI(this, defaultAdminsCacheAPIRepo, adminsCacheSettingsAPI)
fun AdminsCacheAPI(
bot: TelegramBot,
database: Database,
scope: CoroutineScope
) : AdminsCacheAPI = bot.createAdminsCacheAPI(
database,
scope
)