From 570568cd262385441f7b51d36f819ae1415ae973 Mon Sep 17 00:00:00 2001
From: InsanusMokrassar <ovsyannikov.alexey95@gmail.com>
Date: Wed, 20 Apr 2022 00:11:03 +0600
Subject: [PATCH 1/3] add actuality checker

---
 .../common/DefaultMessageContentCache.kt      | 99 ++++++++++---------
 .../media/common/MediaFileActualityChecker.kt | 50 ++++++++++
 2 files changed, 101 insertions(+), 48 deletions(-)
 create mode 100644 cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt

diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt
index 755e430..5c8c26a 100644
--- a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt
+++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt
@@ -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 {
@@ -56,54 +60,50 @@ 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 {
-                val savedFileContentAllocator = messagesFilesCache.get(k) ?: error("Unexpected absence of $k file for content ($simpleMessageContentCache)")
-                val newContent = bot.execute(
-                    when (savedSimpleContent.asInputMedia()) {
-                        is InputMediaAnimation -> SendAnimation(
-                            filesRefreshingChatId,
-                            MultipartFile(
-                                savedFileContentAllocator
-                            ),
-                            disableNotification = true
-                        )
-                        is InputMediaAudio -> SendAudio(
-                            filesRefreshingChatId,
-                            MultipartFile(
-                                savedFileContentAllocator
-                            ),
-                            disableNotification = true
-                        )
-                        is InputMediaVideo -> SendVideo(
-                            filesRefreshingChatId,
-                            MultipartFile(
-                                savedFileContentAllocator
-                            ),
-                            disableNotification = true
-                        )
-                        is InputMediaDocument -> SendDocument(
-                            filesRefreshingChatId,
-                            MultipartFile(
-                                savedFileContentAllocator
-                            ),
-                            disableNotification = true
-                        )
-                        is InputMediaPhoto -> SendPhoto(
-                            filesRefreshingChatId,
-                            MultipartFile(
-                                savedFileContentAllocator
-                            ),
-                            disableNotification = true
-                        )
-                    }
-                )
+        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()) {
+                    is InputMediaAnimation -> SendAnimation(
+                        filesRefreshingChatId,
+                        MultipartFile(
+                            savedFileContentAllocator
+                        ),
+                        disableNotification = true
+                    )
+                    is InputMediaAudio -> SendAudio(
+                        filesRefreshingChatId,
+                        MultipartFile(
+                            savedFileContentAllocator
+                        ),
+                        disableNotification = true
+                    )
+                    is InputMediaVideo -> SendVideo(
+                        filesRefreshingChatId,
+                        MultipartFile(
+                            savedFileContentAllocator
+                        ),
+                        disableNotification = true
+                    )
+                    is InputMediaDocument -> SendDocument(
+                        filesRefreshingChatId,
+                        MultipartFile(
+                            savedFileContentAllocator
+                        ),
+                        disableNotification = true
+                    )
+                    is InputMediaPhoto -> SendPhoto(
+                        filesRefreshingChatId,
+                        MultipartFile(
+                            savedFileContentAllocator
+                        ),
+                        disableNotification = true
+                    )
+                }
+            )
 
-                simpleMessageContentCache.update(k, newContent.content)
-                return newContent.content
-            }
+            simpleMessageContentCache.update(k, newContent.content)
+            return newContent.content
         }
         return savedSimpleContent
     }
@@ -122,7 +122,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)
     }
 }
diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt
new file mode 100644
index 0000000..5a3d258
--- /dev/null
+++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt
@@ -0,0 +1,50 @@
+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
+
+    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
+            }
+        }
+    }
+}

From d5ae880e77b203305687e20d86e0a03989f5eabf Mon Sep 17 00:00:00 2001
From: InsanusMokrassar <ovsyannikov.alexey95@gmail.com>
Date: Wed, 20 Apr 2022 00:19:25 +0600
Subject: [PATCH 2/3] add MediaFileActualityChecker

---
 .../cache/media/common/DefaultMessageContentCache.kt         | 4 ++++
 .../cache/media/common/MediaFileActualityChecker.kt          | 5 +++++
 2 files changed, 9 insertions(+)

diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt
index 5c8c26a..817cc92 100644
--- a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt
+++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt
@@ -52,6 +52,10 @@ class DefaultMessageContentCache<K>(
             messagesFilesCache.set(key, filename, inputAllocator)
         }.onFailure {
             simpleMessageContentCache.remove(key)
+        }.onSuccess {
+            with(mediaFileActualityChecker) {
+                bot.saved(content)
+            }
         }
 
         return key
diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt
index 5a3d258..a82127f 100644
--- a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt
+++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MediaFileActualityChecker.kt
@@ -11,6 +11,7 @@ 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
@@ -46,5 +47,9 @@ fun interface MediaFileActualityChecker {
                 true
             }
         }
+
+        override suspend fun TelegramBot.saved(mediaContent: MediaContent) {
+            fileIdChecksMap[mediaContent.media.fileId] = DateTime.now()
+        }
     }
 }

From c34d7597b47897cbf12e6f4635e8afc6ce965349 Mon Sep 17 00:00:00 2001
From: InsanusMokrassar <ovsyannikov.alexey95@gmail.com>
Date: Wed, 20 Apr 2022 00:21:23 +0600
Subject: [PATCH 3/3] start (?) 0.0.18

---
 gradle.properties | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/gradle.properties b/gradle.properties
index 260a53d..07d01f1 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -11,8 +11,8 @@ kotlin_serialisation_core_version=1.3.2
 
 github_release_plugin_version=2.2.12
 
-tgbotapi_version=0.38.12
-micro_utils_version=0.9.20
+tgbotapi_version=0.38.13
+micro_utils_version=0.9.22
 exposed_version=0.37.3
 plagubot_version=0.5.1
 
@@ -33,5 +33,5 @@ dokka_version=1.6.10
 # Project data
 
 group=dev.inmo
-version=0.0.17
-android_code_version=17
+version=0.0.18
+android_code_version=18