From 2367ee0fd90eff39fc8514b594cdcfeffee0c0a3 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Mon, 6 Dec 2021 15:32:51 +0000
Subject: [PATCH] Revert prohibition of sending file message: (#1716)

* Revert prohibition of sending file message:
- close #1715
- Report a warning in logging with stacktrace
- Show stacktrace only once

* Update util.kt
---
 .../commonMain/kotlin/ExceptionCollector.kt   |  6 ++-
 .../src/commonMain/kotlin/contact/util.kt     | 41 ++++++++++++++++---
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/mirai-core-utils/src/commonMain/kotlin/ExceptionCollector.kt b/mirai-core-utils/src/commonMain/kotlin/ExceptionCollector.kt
index dd7313ef8..43946c1ac 100644
--- a/mirai-core-utils/src/commonMain/kotlin/ExceptionCollector.kt
+++ b/mirai-core-utils/src/commonMain/kotlin/ExceptionCollector.kt
@@ -41,11 +41,15 @@ public open class ExceptionCollector {
         if (!hashCodes.add(hash(e))) return false // filter out duplications
         // we can also check suppressed exceptions of [e] but actual influence would be slight.
         beforeCollect(e)
-        this.last?.let { e.addSuppressed(it) }
+        this.last?.let { addSuppressed(e, it) }
         this.last = e
         return true
     }
 
+    protected open fun addSuppressed(receiver: Throwable, e: Throwable) {
+        receiver.addSuppressed(e)
+    }
+
     private fun hash(e: Throwable): Long {
         return e.stackTrace.fold(0L) { acc, stackTraceElement ->
             acc * 31 + hash(stackTraceElement).toLongUnsigned()
diff --git a/mirai-core/src/commonMain/kotlin/contact/util.kt b/mirai-core/src/commonMain/kotlin/contact/util.kt
index 2db086217..74f50050d 100644
--- a/mirai-core/src/commonMain/kotlin/contact/util.kt
+++ b/mirai-core/src/commonMain/kotlin/contact/util.kt
@@ -14,12 +14,9 @@ package net.mamoe.mirai.internal.contact
 import net.mamoe.mirai.Bot
 import net.mamoe.mirai.contact.*
 import net.mamoe.mirai.internal.message.LongMessageInternal
-import net.mamoe.mirai.internal.message.MiraiInternalMessageFlag
 import net.mamoe.mirai.internal.utils.estimateLength
 import net.mamoe.mirai.message.data.*
-import net.mamoe.mirai.utils.cast
-import net.mamoe.mirai.utils.castOrNull
-import net.mamoe.mirai.utils.verbose
+import net.mamoe.mirai.utils.*
 
 internal inline val Group.uin: Long get() = this.cast<GroupImpl>().uin
 internal inline val Group.groupCode: Long get() = this.id
@@ -34,13 +31,45 @@ internal fun Contact.logMessageSent(message: Message) {
 
 internal fun MessageChain.countImages(): Int = this.count { it is Image }
 
+private val logger by lazy { MiraiLogger.Factory.create(SendMessageHandler::class) }
+
+// Fixme: Remove in the future, see #1715
+private val fileMessageWarningShown = object : ExceptionCollector() {
+    override fun addSuppressed(receiver: Throwable, e: Throwable) {
+    }
+}
+
+// Fixme: Remove in the future, see #1715
+private val ALLOW_SENDING_FILE_MESSAGE = systemProp("mirai.message.allow.sending.file.message", false)
+
 internal fun Message.verifySendingValid() {
-    fun fail(msg: String): Nothing = throw IllegalArgumentException(msg)
+//    fun fail(msg: String): Nothing = throw IllegalArgumentException(msg)
     when (this) {
         is MessageChain -> {
             this.forEach { it.verifySendingValid() }
         }
-        is FileMessage -> fail("Sending FileMessage is not in support")
+        is FileMessage -> {
+            // Fixme: https://github.com/mamoe/mirai/issues/1715
+
+            if (!ALLOW_SENDING_FILE_MESSAGE) {
+                val e =
+                    Exception("This stacktrace might help you find your code causing this problem. It is shown once for each distinct line.")
+                val log =
+                    "Sending FileMessage manually is error-prone and is planned to be prohibited in the future. " +
+                            "Please use AbsoluteFolder.uploadNewFile (recommended) or RemoteFile.uploadAndSend instead (deprecated)." +
+                            "You can add JVM argument '-Dmirai.message.allow.sending.file.message=true' to ignore this warning, " +
+                            "however, your code might not work in the future."
+
+                // Show stacktrace for each call only once.
+                if (fileMessageWarningShown.collect(e)) {
+                    logger.warning(log, e)
+                } else {
+                    logger.warning(log)
+                }
+            }
+
+//            fail("Sending FileMessage is not in support")
+        }
     }
 }