Compare commits

..

2 Commits

Author SHA1 Message Date
d5ae880e77 add MediaFileActualityChecker 2022-04-20 00:19:25 +06:00
570568cd26 add actuality checker 2022-04-20 00:11:03 +06:00
2 changed files with 110 additions and 48 deletions

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.libraries.cache.media.common
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DeleteMessage
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.get.GetFile
@ -16,6 +17,9 @@ class DefaultMessageContentCache<K>(
private val bot: TelegramBot,
private val filesRefreshingChatId: ChatId,
private val simpleMessageContentCache: MessagesSimpleCache<K>,
private val mediaFileActualityChecker: MediaFileActualityChecker = MediaFileActualityChecker.WithDelay(
MediaFileActualityChecker.Default(filesRefreshingChatId)
),
private val messagesFilesCache: MessagesFilesCache<K> = InMemoryMessagesFilesCache()
) : MessageContentCache<K> {
override suspend fun save(content: MessageContent): K {
@ -48,6 +52,10 @@ class DefaultMessageContentCache<K>(
messagesFilesCache.set(key, filename, inputAllocator)
}.onFailure {
simpleMessageContentCache.remove(key)
}.onSuccess {
with(mediaFileActualityChecker) {
bot.saved(content)
}
}
return key
@ -56,10 +64,7 @@ class DefaultMessageContentCache<K>(
override suspend fun get(k: K): MessageContent? {
val savedSimpleContent = simpleMessageContentCache.get(k) ?: return null
if (savedSimpleContent is MediaContent) {
runCatching {
bot.execute(GetFile(savedSimpleContent.media.fileId))
}.onFailure {
if (savedSimpleContent is MediaContent && !with(mediaFileActualityChecker) { bot.isActual(savedSimpleContent) }) {
val savedFileContentAllocator = messagesFilesCache.get(k) ?: error("Unexpected absence of $k file for content ($simpleMessageContentCache)")
val newContent = bot.execute(
when (savedSimpleContent.asInputMedia()) {
@ -104,7 +109,6 @@ class DefaultMessageContentCache<K>(
simpleMessageContentCache.update(k, newContent.content)
return newContent.content
}
}
return savedSimpleContent
}
@ -122,7 +126,10 @@ class DefaultMessageContentCache<K>(
bot: TelegramBot,
filesRefreshingChatId: ChatId,
simpleMessageContentCache: MessagesSimpleCache<String> = InMemoryMessagesSimpleCache(),
mediaFileActualityChecker: MediaFileActualityChecker = MediaFileActualityChecker.WithDelay(
MediaFileActualityChecker.Default(filesRefreshingChatId)
),
messagesFilesCache: MessagesFilesCache<String> = InMemoryMessagesFilesCache()
) = DefaultMessageContentCache(bot, filesRefreshingChatId, simpleMessageContentCache, messagesFilesCache)
) = DefaultMessageContentCache(bot, filesRefreshingChatId, simpleMessageContentCache, mediaFileActualityChecker, messagesFilesCache)
}
}

View File

@ -0,0 +1,55 @@
package dev.inmo.tgbotapi.libraries.cache.media.common
import com.soywiz.klock.DateTime
import com.soywiz.klock.milliseconds
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DeleteMessage
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.MilliSeconds
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
fun interface MediaFileActualityChecker {
suspend fun TelegramBot.isActual(mediaContent: MediaContent): Boolean
suspend fun TelegramBot.saved(mediaContent: MediaContent) {}
class Default(
private val checkingChatId: ChatId
) : MediaFileActualityChecker {
override suspend fun TelegramBot.isActual(mediaContent: MediaContent): Boolean {
return runCatching {
execute(mediaContent.createResend(checkingChatId)).also { sentMessage ->
execute(DeleteMessage(sentMessage.chat.id, sentMessage.messageId))
}
}.isSuccess
}
}
class WithDelay(
private val underhoodChecker: MediaFileActualityChecker,
private val checkingDelay: MilliSeconds = 24 * 60 * 60 * 1000L // one day
) : MediaFileActualityChecker {
private val fileIdChecksMap = mutableMapOf<FileId, DateTime>()
private val checkingDelayTimeSpan = checkingDelay.milliseconds
override suspend fun TelegramBot.isActual(mediaContent: MediaContent): Boolean {
val now = DateTime.now()
val lastCheck = fileIdChecksMap[mediaContent.media.fileId]
return if (lastCheck == null || now - lastCheck > checkingDelayTimeSpan) {
with(underhoodChecker) {
isActual(mediaContent)
}.also {
if (it) {
fileIdChecksMap[mediaContent.media.fileId] = now
}
}
} else {
true
}
}
override suspend fun TelegramBot.saved(mediaContent: MediaContent) {
fileIdChecksMap[mediaContent.media.fileId] = DateTime.now()
}
}
}