From a8a448272da5f8dc5c9724ab0956de8921fa2340 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Fri, 30 Apr 2021 22:19:24 +0800
Subject: [PATCH] Add BotConfiguration.heartbeatStrategy

(cherry-picked from #1229)
---
 ...binary-compatibility-validator-android.api | 10 ++++++
 .../api/binary-compatibility-validator.api    | 10 ++++++
 .../kotlin/utils/BotConfiguration.kt          | 36 +++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api
index 06513a26a..116e6ee68 100644
--- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api
+++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api
@@ -5580,6 +5580,7 @@ public class net/mamoe/mirai/utils/BotConfiguration {
 	public final fun getDeviceInfo ()Lkotlin/jvm/functions/Function1;
 	public final fun getFirstReconnectDelayMillis ()J
 	public final fun getHeartbeatPeriodMillis ()J
+	public final fun getHeartbeatStrategy ()Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
 	public final fun getHeartbeatTimeoutMillis ()J
 	public final fun getHighwayUploadCoroutineCount ()I
 	public final fun getJson ()Lkotlinx/serialization/json/Json;
@@ -5624,6 +5625,7 @@ public class net/mamoe/mirai/utils/BotConfiguration {
 	public final fun setDeviceInfo (Lkotlin/jvm/functions/Function1;)V
 	public final fun setFirstReconnectDelayMillis (J)V
 	public final fun setHeartbeatPeriodMillis (J)V
+	public final fun setHeartbeatStrategy (Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;)V
 	public final fun setHeartbeatTimeoutMillis (J)V
 	public final fun setHighwayUploadCoroutineCount (I)V
 	public final fun setJson (Lkotlinx/serialization/json/Json;)V
@@ -5657,6 +5659,14 @@ public final class net/mamoe/mirai/utils/BotConfiguration$ContactListCache {
 	public final fun setSaveIntervalMillis (J)V
 }
 
+public final class net/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy : java/lang/Enum {
+	public static final field NONE Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static final field REGISTER Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static final field STAT_HB Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static fun valueOf (Ljava/lang/String;)Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static fun values ()[Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+}
+
 public final class net/mamoe/mirai/utils/BotConfiguration$MiraiProtocol : java/lang/Enum {
 	public static final field ANDROID_PAD Lnet/mamoe/mirai/utils/BotConfiguration$MiraiProtocol;
 	public static final field ANDROID_PHONE Lnet/mamoe/mirai/utils/BotConfiguration$MiraiProtocol;
diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api
index c49d7e93b..437bda100 100644
--- a/binary-compatibility-validator/api/binary-compatibility-validator.api
+++ b/binary-compatibility-validator/api/binary-compatibility-validator.api
@@ -5580,6 +5580,7 @@ public class net/mamoe/mirai/utils/BotConfiguration {
 	public final fun getDeviceInfo ()Lkotlin/jvm/functions/Function1;
 	public final fun getFirstReconnectDelayMillis ()J
 	public final fun getHeartbeatPeriodMillis ()J
+	public final fun getHeartbeatStrategy ()Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
 	public final fun getHeartbeatTimeoutMillis ()J
 	public final fun getHighwayUploadCoroutineCount ()I
 	public final fun getJson ()Lkotlinx/serialization/json/Json;
@@ -5624,6 +5625,7 @@ public class net/mamoe/mirai/utils/BotConfiguration {
 	public final fun setDeviceInfo (Lkotlin/jvm/functions/Function1;)V
 	public final fun setFirstReconnectDelayMillis (J)V
 	public final fun setHeartbeatPeriodMillis (J)V
+	public final fun setHeartbeatStrategy (Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;)V
 	public final fun setHeartbeatTimeoutMillis (J)V
 	public final fun setHighwayUploadCoroutineCount (I)V
 	public final fun setJson (Lkotlinx/serialization/json/Json;)V
@@ -5657,6 +5659,14 @@ public final class net/mamoe/mirai/utils/BotConfiguration$ContactListCache {
 	public final fun setSaveIntervalMillis (J)V
 }
 
+public final class net/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy : java/lang/Enum {
+	public static final field NONE Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static final field REGISTER Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static final field STAT_HB Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static fun valueOf (Ljava/lang/String;)Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+	public static fun values ()[Lnet/mamoe/mirai/utils/BotConfiguration$HeartbeatStrategy;
+}
+
 public final class net/mamoe/mirai/utils/BotConfiguration$MiraiProtocol : java/lang/Enum {
 	public static final field ANDROID_PAD Lnet/mamoe/mirai/utils/BotConfiguration$MiraiProtocol;
 	public static final field ANDROID_PHONE Lnet/mamoe/mirai/utils/BotConfiguration$MiraiProtocol;
diff --git a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt
index 06df38d1d..21c91a4d0 100644
--- a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt
+++ b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt
@@ -149,9 +149,44 @@ public open class BotConfiguration { // open for Java
      * 状态心跳包周期. 过长会导致掉线.
      * 该值会在登录时根据服务器下发的配置自动进行更新.
      * @since 2.6
+     * @see heartbeatStrategy
      */
     public var statHeartbeatPeriodMillis: Long = 300.secondsToMillis
 
+    /**
+     * 心跳策略.
+     * @since 2.6.3
+     */
+    public var heartbeatStrategy: HeartbeatStrategy = HeartbeatStrategy.STAT_HB
+
+    /**
+     * 心跳策略.
+     * @since 2.6.3
+     */
+    public enum class HeartbeatStrategy {
+        /**
+         * 使用 2.6.0 增加的*状态心跳* (Stat Heartbeat). 通常推荐这个模式.
+         *
+         * 该模式大多数情况下更稳定. 但有些账号使用这个模式时会遇到一段时间后发送消息成功但客户端不可见的问题.
+         */
+        STAT_HB,
+
+        /**
+         * 不发送状态心跳, 而是发送*切换在线状态* (可能会导致频繁的好友或客户端上线提示, 也可能产生短暂 (几秒) 发送消息不可见的问题).
+         *
+         * 建议在 [STAT_HB] 不可用时使用 [REGISTER].
+         */
+        REGISTER,
+
+        /**
+         * 不主动维护会话. 多数账号会每 16 分钟掉线然后重连. 则会有短暂的不可用时间.
+         *
+         * 仅当 [STAT_HB] 和 [REGISTER] 都造成无法接收等问题时使用.
+         * 同时请在 [https://github.com/mamoe/mirai/issues/1209] 提交问题.
+         */
+        NONE;
+    }
+
     /**
      * 每次心跳时等待结果的时间.
      * 一旦心跳超时, 整个网络服务将会重启 (将消耗约 1s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
@@ -513,6 +548,7 @@ public open class BotConfiguration { // open for Java
             new.heartbeatPeriodMillis = heartbeatPeriodMillis
             new.heartbeatTimeoutMillis = heartbeatTimeoutMillis
             new.statHeartbeatPeriodMillis = statHeartbeatPeriodMillis
+            new.heartbeatStrategy = heartbeatStrategy
             new.firstReconnectDelayMillis = firstReconnectDelayMillis
             new.reconnectPeriodMillis = reconnectPeriodMillis
             new.reconnectionRetryTimes = reconnectionRetryTimes