Merge remote-tracking branch 'origin/dev' into maven-central

# Conflicts:
#	.github/workflows/bintray.yml
#	.github/workflows/release.yml
This commit is contained in:
Karlatemp 2021-02-10 09:48:44 +08:00
commit 32ef89add1
No known key found for this signature in database
GPG Key ID: 21FBDDF664FF06F8
32 changed files with 285 additions and 187 deletions

View File

@ -19,13 +19,13 @@ jobs:
run: chmod -R 777 *
- name: Init gradle project
run: ./gradlew clean --info --stacktrace
run: ./gradlew clean --scan
- name: Build mirai-core series
run: ./gradlew assemble --info --stacktrace
run: ./gradlew assemble --scan
- name: mirai-core Tests
run: ./gradlew check --info --stacktrace
run: ./gradlew check --scan
build-all:
runs-on: ubuntu-latest
@ -45,10 +45,10 @@ jobs:
run: chmod -R 777 *
- name: Init gradle project
run: ./gradlew clean --info --stacktrace
run: ./gradlew clean --scan
- name: Build all
run: ./gradlew assemble --info --stacktrace
run: ./gradlew assemble --scan
- name: All Tests
run: ./gradlew check --info --stacktrace
run: ./gradlew check --scan

View File

@ -51,7 +51,7 @@ jobs:
BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}
- name: Init gradle project
run: ./gradlew clean --info
run: ./gradlew clean --scan
- name: Check keys
run: >
@ -68,25 +68,25 @@ jobs:
- name: fillBuildConstants
run: >
./gradlew
fillBuildConstants --info --stacktrace
fillBuildConstants --scan
- name: Assemble
run: ./gradlew assemble --info --stacktrace
run: ./gradlew assemble --scan
- name: Check
run: ./gradlew check --info --stacktrace
run: ./gradlew check --scan
- name: Gradle :mirai-core-utils:publish
run: >
./gradlew :mirai-core-utils:publish --info --stacktrace
./gradlew :mirai-core-utils:publish --scan
- name: Gradle :mirai-core-api:publish
run: >
./gradlew :mirai-core-api:publish --info --stacktrace
./gradlew :mirai-core-api:publish --scan
- name: Gradle :mirai-core:publish
run: >
./gradlew :mirai-core:publish --info --stacktrace
./gradlew :mirai-core:publish --scan
- name: Gradle :mirai-core-all:publish
run: >
@ -115,7 +115,7 @@ jobs:
- name: Publish Gradle plugin
run: >
./gradlew
:mirai-console-gradle:publishPlugins --info --stacktrace
:mirai-console-gradle:publishPlugins --scan
-Dgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }} -Pgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }}
-Dgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }} -Pgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }}

View File

@ -89,25 +89,16 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve
public fun calculateGroupUinByGroupCode (J)J
public abstract fun constructMessageSource (JLnet/mamoe/mirai/message/data/MessageSourceKind;JJ[II[ILnet/mamoe/mirai/message/data/MessageChain;)Lnet/mamoe/mirai/message/data/OfflineMessageSource;
public abstract fun createImage (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image;
public synthetic fun deleteGroupAnnouncement (Lnet/mamoe/mirai/Bot;JLjava/lang/String;)Lkotlin/Unit;
public fun deleteGroupAnnouncement (Lnet/mamoe/mirai/Bot;JLjava/lang/String;)V
public fun downloadForwardMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;)Ljava/util/List;
public abstract fun downloadForwardMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun downloadLongMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/MessageChain;
public abstract fun downloadLongMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getBotFactory ()Lnet/mamoe/mirai/BotFactory;
public abstract fun getFileCacheStrategy ()Lnet/mamoe/mirai/utils/FileCacheStrategy;
public fun getGroupAnnouncement (Lnet/mamoe/mirai/Bot;JLjava/lang/String;)Lnet/mamoe/mirai/data/GroupAnnouncement;
public fun getGroupVoiceDownloadUrl (Lnet/mamoe/mirai/Bot;[BJJ)Ljava/lang/String;
public abstract fun getHttp ()Lio/ktor/client/HttpClient;
public fun getOnlineOtherClientsList (Lnet/mamoe/mirai/Bot;Z)Ljava/util/List;
public abstract fun getOnlineOtherClientsList (Lnet/mamoe/mirai/Bot;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun getOnlineOtherClientsList$default (Lnet/mamoe/mirai/IMirai;Lnet/mamoe/mirai/Bot;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public fun getRawGroupActiveData (Lnet/mamoe/mirai/Bot;JI)Lnet/mamoe/mirai/data/GroupActiveData;
public fun getRawGroupAnnouncements (Lnet/mamoe/mirai/Bot;JII)Lnet/mamoe/mirai/data/GroupAnnouncementList;
public fun getRawGroupHonorListData (Lnet/mamoe/mirai/Bot;JLnet/mamoe/mirai/data/GroupHonorType;)Lnet/mamoe/mirai/data/GroupHonorListData;
public fun getRawGroupList (Lnet/mamoe/mirai/Bot;)Lkotlin/sequences/Sequence;
public fun getRawGroupMemberList (Lnet/mamoe/mirai/Bot;JJJ)Lkotlin/sequences/Sequence;
public fun getUin (Lnet/mamoe/mirai/contact/ContactOrBot;)J
public synthetic fun ignoreInvitedJoinGroupRequest (Lnet/mamoe/mirai/event/events/BotInvitedJoinGroupRequestEvent;)Lkotlin/Unit;
public fun ignoreInvitedJoinGroupRequest (Lnet/mamoe/mirai/event/events/BotInvitedJoinGroupRequestEvent;)V
@ -116,15 +107,10 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve
public fun ignoreMemberJoinRequest (Lnet/mamoe/mirai/event/events/MemberJoinRequestEvent;Z)V
public abstract fun ignoreMemberJoinRequest (Lnet/mamoe/mirai/event/events/MemberJoinRequestEvent;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun ignoreMemberJoinRequest$default (Lnet/mamoe/mirai/IMirai;Lnet/mamoe/mirai/event/events/MemberJoinRequestEvent;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public synthetic fun muteAnonymousMember (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Ljava/lang/String;JI)Lkotlin/Unit;
public fun muteAnonymousMember (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Ljava/lang/String;JI)V
public fun queryImageUrl (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/data/Image;)Ljava/lang/String;
public abstract fun queryImageUrl (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/data/Image;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun queryProfile (Lnet/mamoe/mirai/Bot;J)Lnet/mamoe/mirai/data/UserProfile;
public abstract fun queryProfile (Lnet/mamoe/mirai/Bot;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun recallFriendMessageRaw (Lnet/mamoe/mirai/Bot;J[I[II)Z
public fun recallGroupMessageRaw (Lnet/mamoe/mirai/Bot;J[I[I)Z
public fun recallGroupTempMessageRaw (Lnet/mamoe/mirai/Bot;JJ[I[II)Z
public synthetic fun recallMessage (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/data/MessageSource;)Lkotlin/Unit;
public fun recallMessage (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/data/MessageSource;)V
public abstract fun recallMessage (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@ -136,17 +122,10 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve
public fun rejectNewFriendRequest (Lnet/mamoe/mirai/event/events/NewFriendRequestEvent;Z)V
public abstract fun rejectNewFriendRequest (Lnet/mamoe/mirai/event/events/NewFriendRequestEvent;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun rejectNewFriendRequest$default (Lnet/mamoe/mirai/IMirai;Lnet/mamoe/mirai/event/events/NewFriendRequestEvent;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public fun sendGroupAnnouncement (Lnet/mamoe/mirai/Bot;JLnet/mamoe/mirai/data/GroupAnnouncement;)Ljava/lang/String;
public fun sendNudge (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/action/Nudge;Lnet/mamoe/mirai/contact/Contact;)Z
public abstract fun sendNudge (Lnet/mamoe/mirai/Bot;Lnet/mamoe/mirai/message/action/Nudge;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun setFileCacheStrategy (Lnet/mamoe/mirai/utils/FileCacheStrategy;)V
public abstract fun setHttp (Lio/ktor/client/HttpClient;)V
public synthetic fun solveBotInvitedJoinGroupRequestEvent (Lnet/mamoe/mirai/Bot;JJJZ)Lkotlin/Unit;
public fun solveBotInvitedJoinGroupRequestEvent (Lnet/mamoe/mirai/Bot;JJJZ)V
public synthetic fun solveMemberJoinRequestEvent (Lnet/mamoe/mirai/Bot;JJLjava/lang/String;JLjava/lang/Boolean;ZLjava/lang/String;)Lkotlin/Unit;
public fun solveMemberJoinRequestEvent (Lnet/mamoe/mirai/Bot;JJLjava/lang/String;JLjava/lang/Boolean;ZLjava/lang/String;)V
public synthetic fun solveNewFriendRequestEvent (Lnet/mamoe/mirai/Bot;JJLjava/lang/String;ZZ)Lkotlin/Unit;
public fun solveNewFriendRequestEvent (Lnet/mamoe/mirai/Bot;JJLjava/lang/String;ZZ)V
}
public abstract interface annotation class net/mamoe/mirai/LowLevelApi : java/lang/annotation/Annotation {
@ -183,6 +162,8 @@ public abstract interface class net/mamoe/mirai/LowLevelApiAccessor {
public abstract fun recallGroupMessageRaw (Lnet/mamoe/mirai/Bot;J[I[ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun recallGroupTempMessageRaw (Lnet/mamoe/mirai/Bot;JJ[I[II)Z
public abstract fun recallGroupTempMessageRaw (Lnet/mamoe/mirai/Bot;JJ[I[IILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public synthetic fun refreshKeys (Lnet/mamoe/mirai/Bot;)Lkotlin/Unit;
public fun refreshKeys (Lnet/mamoe/mirai/Bot;)V
public abstract fun refreshKeys (Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendGroupAnnouncement (Lnet/mamoe/mirai/Bot;JLnet/mamoe/mirai/data/GroupAnnouncement;)Ljava/lang/String;
public abstract fun sendGroupAnnouncement (Lnet/mamoe/mirai/Bot;JLnet/mamoe/mirai/data/GroupAnnouncement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@ -205,12 +186,9 @@ public final class net/mamoe/mirai/Mirai {
public abstract interface class net/mamoe/mirai/contact/AnonymousMember : net/mamoe/mirai/contact/Member {
public abstract fun getAnonymousId ()Ljava/lang/String;
public synthetic fun mute (I)Lkotlin/Unit;
public fun mute (I)V
public fun nudge ()Lnet/mamoe/mirai/message/action/MemberNudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/Nudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/UserNudge;
public fun queryProfile ()Lnet/mamoe/mirai/data/UserProfile;
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@ -373,12 +351,10 @@ public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/corouti
public fun nudge ()Lnet/mamoe/mirai/message/action/FriendNudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/Nudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/UserNudge;
public fun queryProfile ()Lnet/mamoe/mirai/data/UserProfile;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
public abstract fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
}
public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/Contact {
@ -405,7 +381,6 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin
public fun setEssenceMessage (Lnet/mamoe/mirai/message/data/MessageSource;)Z
public abstract fun setEssenceMessage (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun setName (Ljava/lang/String;)V
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
public fun uploadVoice (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Voice;
public abstract fun uploadVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
@ -441,10 +416,10 @@ public abstract interface class net/mamoe/mirai/contact/Member : net/mamoe/mirai
public fun mute (I)V
public abstract fun mute (ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun nudge ()Lnet/mamoe/mirai/message/action/MemberNudge;
public fun queryProfile ()Lnet/mamoe/mirai/data/UserProfile;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public abstract fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
public abstract fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
}
public final class net/mamoe/mirai/contact/MemberKt {
@ -490,12 +465,9 @@ public abstract interface class net/mamoe/mirai/contact/NormalMember : net/mamoe
public synthetic fun kick (Ljava/lang/String;)Lkotlin/Unit;
public fun kick (Ljava/lang/String;)V
public abstract fun kick (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public synthetic fun mute (I)Lkotlin/Unit;
public fun mute (I)V
public fun nudge ()Lnet/mamoe/mirai/message/action/MemberNudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/Nudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/UserNudge;
public fun queryProfile ()Lnet/mamoe/mirai/data/UserProfile;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
@ -505,7 +477,6 @@ public abstract interface class net/mamoe/mirai/contact/NormalMember : net/mamoe
public synthetic fun unmute ()Lkotlin/Unit;
public fun unmute ()V
public abstract fun unmute (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
}
public final class net/mamoe/mirai/contact/NormalMemberKt {
@ -518,7 +489,6 @@ public abstract interface class net/mamoe/mirai/contact/OtherClient : net/mamoe/
public abstract fun getBot ()Lnet/mamoe/mirai/Bot;
public fun getId ()J
public abstract fun getInfo ()Lnet/mamoe/mirai/contact/OtherClientInfo;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
@ -575,12 +545,10 @@ public abstract interface class net/mamoe/mirai/contact/Stranger : kotlinx/corou
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/Nudge;
public fun nudge ()Lnet/mamoe/mirai/message/action/StrangerNudge;
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/UserNudge;
public fun queryProfile ()Lnet/mamoe/mirai/data/UserProfile;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
public abstract fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
}
public final class net/mamoe/mirai/contact/StrangerKt {
@ -589,10 +557,6 @@ public final class net/mamoe/mirai/contact/StrangerKt {
}
public abstract interface class net/mamoe/mirai/contact/TempUser : net/mamoe/mirai/contact/User {
public fun queryProfile ()Lnet/mamoe/mirai/data/UserProfile;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
}
public abstract interface class net/mamoe/mirai/contact/User : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/Contact, net/mamoe/mirai/contact/UserOrBot {
@ -606,7 +570,6 @@ public abstract interface class net/mamoe/mirai/contact/User : kotlinx/coroutine
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
public abstract fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/message/data/Image;
}
public final class net/mamoe/mirai/contact/UserKt {
@ -5087,6 +5050,7 @@ public final class net/mamoe/mirai/message/data/RichMessage$Key : net/mamoe/mira
public final class net/mamoe/mirai/message/data/RichMessageKind : java/lang/Enum {
public static final field FORWARD Lnet/mamoe/mirai/message/data/RichMessageKind;
public static final field LONG Lnet/mamoe/mirai/message/data/RichMessageKind;
public static final field MUSIC_SHARE Lnet/mamoe/mirai/message/data/RichMessageKind;
public static fun valueOf (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/RichMessageKind;
public static fun values ()[Lnet/mamoe/mirai/message/data/RichMessageKind;
}
@ -5401,6 +5365,7 @@ public class net/mamoe/mirai/utils/BotConfiguration {
public static synthetic fun fileBasedDeviceInfo$default (Lnet/mamoe/mirai/utils/BotConfiguration;Ljava/lang/String;ILjava/lang/Object;)V
public final fun getAutoReconnectOnForceOffline ()Z
public final fun getBotLoggerSupplier ()Lkotlin/jvm/functions/Function1;
public final fun getCacheDirSupplier ()Lkotlin/jvm/functions/Function0;
public static final fun getDefault ()Lnet/mamoe/mirai/utils/BotConfiguration;
public final fun getDeviceInfo ()Lkotlin/jvm/functions/Function1;
public final fun getFirstReconnectDelayMillis ()J
@ -5442,6 +5407,7 @@ public class net/mamoe/mirai/utils/BotConfiguration {
public static synthetic fun redirectNetworkLogToFile$default (Lnet/mamoe/mirai/utils/BotConfiguration;Ljava/io/File;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public final fun setAutoReconnectOnForceOffline (Z)V
public final fun setBotLoggerSupplier (Lkotlin/jvm/functions/Function1;)V
public final fun setCacheDirSupplier (Lkotlin/jvm/functions/Function0;)V
public final fun setDeviceInfo (Lkotlin/jvm/functions/Function1;)V
public final fun setFirstReconnectDelayMillis (J)V
public final fun setFriendListCache (Lnet/mamoe/mirai/utils/BotConfiguration$FriendListCache;)V

View File

@ -140,10 +140,20 @@ subprojects {
tasks.register("cleanExceptIntellij") {
group = "build"
allprojects.forEach { proj ->
if (proj.name != "mirai-console-intellij")
if (proj.name != "mirai-console-intellij") {
// Type mismatch
// proj.tasks.findByName("clean")?.let(::dependsOn)
proj.tasks.findByName("clean")?.let { dependsOn(it) }
}
}
}
extensions.findByName("buildScan")?.withGroovyBuilder {
setProperty("termsOfServiceUrl", "https://gradle.com/terms-of-service")
setProperty("termsOfServiceAgree", "yes")
}
fun Project.useIr() {
kotlinCompilations?.forEach { kotlinCompilation ->

View File

@ -32,7 +32,7 @@ object Versions {
const val io = "0.1.16"
const val coroutinesIo = "0.1.16"
const val blockingBridge = "1.7.4"
const val blockingBridge = "1.10.0"
const val androidGradlePlugin = "3.5.3"

View File

@ -22,7 +22,6 @@
[NoneBot]: https://github.com/nonebot/nonebot2
[RedBeanN/node-mirai]: https://github.com/RedBeanN/node-mirai
[Logiase/gomirai]: https://github.com/Logiase/gomirai
[StageGuard/mirai-rhinojs-sdk]: https://github.com/StageGuard/mirai-rhinojs-sdk
[cyanray/mirai-cpp]: https://github.com/cyanray/mirai-cpp
[Chlorie/miraipp]: https://github.com/Chlorie/miraipp-template
[Executor-Cheng/mirai-CSharp]: https://github.com/Executor-Cheng/mirai-CSharp
@ -36,29 +35,29 @@
[Rhino]: https://github.com/mozilla/rhino
[OneBot]: https://github.com/howmanybots/onebot
[Nambers/MiraiCP]: https://github.com/Nambers/MiraiCP
| 技术 | 实现 | 维护者及项目地址 |
|:-------------------|:-----------------------------|:--------------------------------------------|
| ***Mirai Http*** | Mirai 标准 | [mamoe/mirai-api-http] |
| *OneBot Http* | [OneBot] 标准 | [yyuueexxiinngg/onebot-kotlin] |
| `C++` | JNI | [Nambers/MiraiCP]
| `Kotlin Scripting` | JVM | [iTXTech/mirai-kts] |
| `Python` | *Mirai Http* | [Graia Framework][GraiaProject/Application] |
| `Python` | *Mirai Http* / *OneBot Http* | [NoneBot] |
| `C++` | JNI | [Nambers/MiraiCP] |
| `C++` | *Mirai Http* | [cyanray/mirai-cpp] |
| `C++` | *Mirai Http* | [Chlorie/miraipp] |
| `C#` | *Mirai Http* | [Executor-Cheng/mirai-CSharp] |
| `C#` | *Mirai Http* | [Hyperai][theGravityLab/ProjHyperai] |
| `Rust` | *Mirai Http* | [HoshinoTented/mirai-rs] |
| `JavaScript` | [Rhino] / JVM | [iTXTech/mirai-js] |
| `JavaScript` | Node.js / *Mirai Http* | [RedBeanN/node-mirai] |
| `JavaScript` | TypeScript / *Mirai Http* | [YunYouJun/mirai-ts] |
| `JavaScript` | Node.js / *Mirai Http* | [drinkal/Mirai-js] |
| `.Net/C#` | *Mirai Http* | [Hyperai][theGravityLab/ProjHyperai] |
| `Go` | *Mirai Http* | [Logiase/gomirai] |
| `易语言` | *Mirai Http* | [only52607/e-mirai] |
| *酷 Q DLL 插件* | JNI | [iTXTech/mirai-native] |
> 排名不分先后
> *想在这里添加你的项目?欢迎[提交 PR](https://github.com/mamoe/mirai/edit/dev/docs/README.md)。*
特别地,有一些 SDK 直接基于 mirai-core 开发,不需要 [`mirai-console`]

View File

@ -43,6 +43,7 @@ public suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
*
* @see BotFactory 构造 [Bot] 的工厂, [Bot] 唯一的构造方式.
*/
@JvmBlockingBridge
public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
/**
* Bot 配置
@ -161,7 +162,6 @@ public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
* @throws LoginFailedException 正常登录失败时抛出
* @see alsoLogin `.apply { login() }` 捷径
*/
@JvmBlockingBridge
public suspend fun login()
/**
@ -232,7 +232,6 @@ public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
* 挂起协程直到 [Bot] 协程被关闭 ([Bot.close]).
* 即使 [Bot] 离线, 也会等待直到协程关闭.
*/
@JvmBlockingBridge
public suspend fun join(): Unit = supervisorJob.join()
@ -243,7 +242,6 @@ public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
*
* @param cause 原因. null 时视为正常关闭, null 时视为异常关闭
*/
@JvmBlockingBridge
public suspend fun closeAndJoin(cause: Throwable? = null) {
close(cause)
join()

View File

@ -41,6 +41,7 @@ public val Mirai: IMirai by lazy { findMiraiInstance() }
*
* @see Mirai 获取实例
*/
@JvmBlockingBridge
public interface IMirai : LowLevelApiAccessor {
/**
* 请优先使用 [BotFactory.INSTANCE]
@ -121,13 +122,11 @@ public interface IMirai : LowLevelApiAccessor {
* @see IMirai.recallMessage (扩展函数) 接受参数 [MessageChain]
* @see MessageSource.recall 撤回消息扩展
*/
@JvmBlockingBridge
public suspend fun recallMessage(bot: Bot, source: MessageSource)
/**
* 发送戳一戳消息
*/
@JvmBlockingBridge
public suspend fun sendNudge(bot: Bot, nudge: Nudge, receiver: Contact): Boolean
/**
@ -143,7 +142,6 @@ public interface IMirai : LowLevelApiAccessor {
*
* @see Image.queryUrl [Image] 的扩展函数
*/
@JvmBlockingBridge
public suspend fun queryImageUrl(bot: Bot, image: Image): String
/**
@ -151,7 +149,6 @@ public interface IMirai : LowLevelApiAccessor {
*
* @since 2.1
*/
@JvmBlockingBridge
public suspend fun queryProfile(bot: Bot, targetId: Long): UserProfile
/**
@ -173,7 +170,6 @@ public interface IMirai : LowLevelApiAccessor {
/**
* @since 2.3
*/
@JvmBlockingBridge
public suspend fun downloadLongMessage(
bot: Bot,
resourceId: String,
@ -182,7 +178,6 @@ public interface IMirai : LowLevelApiAccessor {
/**
* @since 2.3
*/
@JvmBlockingBridge
public suspend fun downloadForwardMessage(
bot: Bot,
resourceId: String,
@ -193,7 +188,6 @@ public interface IMirai : LowLevelApiAccessor {
*
* @param event 好友验证的事件对象
*/
@JvmBlockingBridge
public suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent)
/**
@ -202,7 +196,6 @@ public interface IMirai : LowLevelApiAccessor {
* @param event 好友验证的事件对象
* @param blackList 拒绝后是否拉入黑名单
*/
@JvmBlockingBridge
public suspend fun rejectNewFriendRequest(event: NewFriendRequestEvent, blackList: Boolean = false)
/**
@ -210,7 +203,6 @@ public interface IMirai : LowLevelApiAccessor {
*
* @param event 加群验证的事件对象
*/
@JvmBlockingBridge
public suspend fun acceptMemberJoinRequest(event: MemberJoinRequestEvent)
/**
@ -219,7 +211,6 @@ public interface IMirai : LowLevelApiAccessor {
* @param event 加群验证的事件对象
* @param blackList 拒绝后是否拉入黑名单
*/
@JvmBlockingBridge
public suspend fun rejectMemberJoinRequest(
event: MemberJoinRequestEvent,
blackList: Boolean = false,
@ -230,7 +221,6 @@ public interface IMirai : LowLevelApiAccessor {
* 获取在线的 [OtherClient] 列表
* @param mayIncludeSelf 服务器返回的列表可能包含 [Bot] 自己. [mayIncludeSelf] `false` 会排除自己
*/
@JvmBlockingBridge
public suspend fun getOnlineOtherClientsList(
bot: Bot,
mayIncludeSelf: Boolean = false
@ -242,7 +232,6 @@ public interface IMirai : LowLevelApiAccessor {
* @param event 加群验证的事件对象
* @param blackList 忽略后是否拉入黑名单
*/
@JvmBlockingBridge
public suspend fun ignoreMemberJoinRequest(event: MemberJoinRequestEvent, blackList: Boolean = false)
/**
@ -250,7 +239,6 @@ public interface IMirai : LowLevelApiAccessor {
*
* @param event 邀请入群的事件对象
*/
@JvmBlockingBridge
public suspend fun acceptInvitedJoinGroupRequest(event: BotInvitedJoinGroupRequestEvent)
/**
@ -258,7 +246,6 @@ public interface IMirai : LowLevelApiAccessor {
*
* @param event 邀请入群的事件对象
*/
@JvmBlockingBridge
public suspend fun ignoreInvitedJoinGroupRequest(event: BotInvitedJoinGroupRequestEvent)
}

View File

@ -36,6 +36,7 @@ public annotation class LowLevelApi
* **警告**: 所有的低级 API 都可能在任意时刻不经过任何警告和迭代就被修改. 因此非常不建议在任何情况下使用这些 API.
*/
@LowLevelApi
@JvmBlockingBridge
public interface LowLevelApiAccessor {
/**
* 主动刷新 keys, SKey, PSKey .
@ -70,7 +71,6 @@ public interface LowLevelApiAccessor {
* @see recallMessage
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun recallGroupMessageRaw(
bot: Bot,
groupCode: Long,
@ -83,7 +83,6 @@ public interface LowLevelApiAccessor {
* @see recallMessage
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun recallFriendMessageRaw(
bot: Bot,
targetId: Long,
@ -97,7 +96,6 @@ public interface LowLevelApiAccessor {
* @see recallMessage
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun recallGroupTempMessageRaw(
bot: Bot,
groupUin: Long,
@ -111,7 +109,6 @@ public interface LowLevelApiAccessor {
* 向服务器查询群列表. 返回值高 32 bits uin, 32 bits groupCode
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun getRawGroupList(bot: Bot): Sequence<Long>
/**
@ -123,7 +120,6 @@ public interface LowLevelApiAccessor {
* @see IMirai.calculateGroupUinByGroupCode 使用 groupCode 计算 groupUin
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun getRawGroupMemberList(
bot: Bot,
groupUin: Long,
@ -137,7 +133,6 @@ public interface LowLevelApiAccessor {
*/
@LowLevelApi
@MiraiExperimentalApi
@JvmBlockingBridge
public suspend fun getRawGroupAnnouncements(
bot: Bot,
groupId: Long,
@ -151,7 +146,6 @@ public interface LowLevelApiAccessor {
* @return 公告的fid
*/
@LowLevelApi
@JvmBlockingBridge
@MiraiExperimentalApi
public suspend fun sendGroupAnnouncement(
bot: Bot,
@ -165,7 +159,6 @@ public interface LowLevelApiAccessor {
* @param fid [GroupAnnouncement.fid]
*/
@LowLevelApi
@JvmBlockingBridge
@MiraiExperimentalApi
public suspend fun deleteGroupAnnouncement(
bot: Bot,
@ -178,7 +171,6 @@ public interface LowLevelApiAccessor {
* @param fid [GroupAnnouncement.fid]
*/
@LowLevelApi
@JvmBlockingBridge
@MiraiExperimentalApi
public suspend fun getGroupAnnouncement(
bot: Bot,
@ -193,7 +185,6 @@ public interface LowLevelApiAccessor {
* page从0开始传入可以得到发言列表
*/
@LowLevelApi
@JvmBlockingBridge
@MiraiExperimentalApi
public suspend fun getRawGroupActiveData(bot: Bot, groupId: Long, page: Int = -1): GroupActiveData
@ -203,7 +194,6 @@ public interface LowLevelApiAccessor {
*/
@LowLevelApi
@MiraiExperimentalApi
@JvmBlockingBridge
public suspend fun getRawGroupHonorListData(
bot: Bot,
groupId: Long,
@ -214,7 +204,6 @@ public interface LowLevelApiAccessor {
/**
* 处理一个账号请求添加机器人为好友的事件
*/
@JvmBlockingBridge
@LowLevelApi
public suspend fun solveNewFriendRequestEvent(
bot: Bot,
@ -229,7 +218,6 @@ public interface LowLevelApiAccessor {
* 处理被邀请加入一个群请求事件
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun solveBotInvitedJoinGroupRequestEvent(
bot: Bot,
eventId: Long,
@ -242,7 +230,6 @@ public interface LowLevelApiAccessor {
* 处理账号请求加入群事件
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun solveMemberJoinRequestEvent(
bot: Bot,
eventId: Long,
@ -258,7 +245,6 @@ public interface LowLevelApiAccessor {
* 查询语音的下载连接
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun getGroupVoiceDownloadUrl(
bot: Bot,
md5: ByteArray,
@ -272,7 +258,6 @@ public interface LowLevelApiAccessor {
* @param anonymousId [AnonymousMember.anonymousId]
*/
@LowLevelApi
@JvmBlockingBridge
public suspend fun muteAnonymousMember(
bot: Bot,
anonymousId: String,

View File

@ -27,6 +27,7 @@ import java.io.InputStream
/**
* 联系对象, 即可以与 [Bot] 互动的对象. 包含 [用户][User], [][Group].
*/
@JvmBlockingBridge
public interface Contact : ContactOrBot, CoroutineScope {
/**
* 这个联系对象所属 [Bot].
@ -57,14 +58,12 @@ public interface Contact : ContactOrBot, CoroutineScope {
*
* @return 消息回执. [引用][MessageReceipt.quote] [撤回][MessageReceipt.recall] 这条消息.
*/
@JvmBlockingBridge
public suspend fun sendMessage(message: Message): MessageReceipt<Contact>
/**
* 发送纯文本消息
* @see sendMessage
*/
@JvmBlockingBridge
public suspend fun sendMessage(message: String): MessageReceipt<Contact> = this.sendMessage(message.toPlainText())
/**
@ -84,9 +83,9 @@ public interface Contact : ContactOrBot, CoroutineScope {
* @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时抛出. (最大大小约为 20 MB, mirai 限制的大小为 30 MB)
*/
@JvmBlockingBridge
public suspend fun uploadImage(resource: ExternalResource): Image
@JvmBlockingBridge
public companion object {
/**
* 读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人
@ -98,7 +97,6 @@ public interface Contact : ContactOrBot, CoroutineScope {
* @see FileCacheStrategy
*/
@JvmStatic
@JvmBlockingBridge
@JvmOverloads
public suspend fun <C : Contact> C.sendImage(
imageStream: InputStream,
@ -112,7 +110,6 @@ public interface Contact : ContactOrBot, CoroutineScope {
* @see FileCacheStrategy
*/
@JvmStatic
@JvmBlockingBridge
@JvmOverloads
public suspend fun <C : Contact> C.sendImage(
file: File,
@ -124,7 +121,6 @@ public interface Contact : ContactOrBot, CoroutineScope {
*
* @see Contact.sendMessage 最终调用, 发送消息.
*/
@JvmBlockingBridge
@JvmStatic
public suspend fun <C : Contact> C.sendImage(resource: ExternalResource): MessageReceipt<C> =
resource.sendAsImageTo(this)
@ -139,7 +135,6 @@ public interface Contact : ContactOrBot, CoroutineScope {
* @throws OverFileSizeMaxException
*/
@JvmStatic
@JvmBlockingBridge
@JvmOverloads
public suspend fun Contact.uploadImage(
imageStream: InputStream,
@ -152,7 +147,6 @@ public interface Contact : ContactOrBot, CoroutineScope {
* @throws OverFileSizeMaxException
*/
@JvmStatic
@JvmBlockingBridge
@JvmOverloads
public suspend fun Contact.uploadImage(
file: File,
@ -165,7 +159,6 @@ public interface Contact : ContactOrBot, CoroutineScope {
*/
@Throws(OverFileSizeMaxException::class)
@JvmStatic
@JvmBlockingBridge
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXTENSION_SHADOWED_BY_MEMBER")
@kotlin.internal.LowPriorityInOverloadResolution // for better Java API
public suspend fun Contact.uploadImage(resource: ExternalResource): Image = this.uploadImage(resource)

View File

@ -31,6 +31,7 @@ import net.mamoe.mirai.message.data.toPlainText
*
* @see FriendMessageEvent
*/
@JvmBlockingBridge
public interface Friend : User, CoroutineScope {
/**
* QQ 号码
@ -62,7 +63,6 @@ public interface Friend : User, CoroutineScope {
*
* @return 消息回执. [引用][MessageReceipt.quote] [撤回][MessageReceipt.recall] 这条消息.
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: Message): MessageReceipt<Friend>
/**
@ -70,14 +70,12 @@ public interface Friend : User, CoroutineScope {
*
* @see FriendDeleteEvent 好友删除事件
*/
@JvmBlockingBridge
public suspend fun delete()
/**
* 发送纯文本消息
* @see sendMessage
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: String): MessageReceipt<Friend> =
this.sendMessage(message.toPlainText())

View File

@ -25,6 +25,7 @@ import net.mamoe.mirai.utils.OverFileSizeMaxException
/**
* .
*/
@JvmBlockingBridge
public interface Group : Contact, CoroutineScope {
/**
* 群名称.
@ -123,7 +124,6 @@ public interface Group : Contact, CoroutineScope {
* @throws IllegalStateException 当机器人为群主时
* @return 退出成功时 true; 已经退出时 false
*/
@JvmBlockingBridge
public suspend fun quit(): Boolean
/**
@ -141,14 +141,12 @@ public interface Group : Contact, CoroutineScope {
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: Message): MessageReceipt<Group>
/**
* 发送纯文本消息
* @see sendMessage
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: String): MessageReceipt<Group> =
this.sendMessage(message.toPlainText())
@ -163,7 +161,6 @@ public interface Group : Contact, CoroutineScope {
* @throws EventCancelledException 当发送消息事件被取消
* @throws OverFileSizeMaxException 当语音文件过大而被服务器拒绝上传时. (最大大小约为 1 MB)
*/
@JvmBlockingBridge
public suspend fun uploadVoice(resource: ExternalResource): Voice
@ -175,7 +172,6 @@ public interface Group : Contact, CoroutineScope {
*
* @since 2.2
*/
@JvmBlockingBridge
public suspend fun setEssenceMessage(source: MessageSource): Boolean
public companion object {

View File

@ -34,6 +34,7 @@ import net.mamoe.mirai.utils.WeakRefProperty
* - [Member.asFriend] 转换为 [Friend]
* - [Member.asStranger] 转换为 [Stranger]
*/
@JvmBlockingBridge
public interface Member : User {
/**
* 所在的群.
@ -79,7 +80,6 @@ public interface Member : User {
*
* @see Member.mute 支持 Kotlin [kotlin.time.Duration] 的扩展
*/
@JvmBlockingBridge
public suspend fun mute(durationSeconds: Int)
/**

View File

@ -27,6 +27,7 @@ import kotlin.time.ExperimentalTime
* 群成员可能也是好友, 但他们在对象类型上不同.
* 群成员可以通过 [asFriend] 得到相关好友对象.
*/
@JvmBlockingBridge
public interface NormalMember : Member {
/**
* 群名片. 可能为空.
@ -88,7 +89,6 @@ public interface NormalMember : Member {
*
* @throws PermissionDeniedException 无权限修改时抛出
*/
@JvmBlockingBridge
public suspend fun unmute()
/**
@ -100,7 +100,6 @@ public interface NormalMember : Member {
* @throws PermissionDeniedException 无权限修改时
*
*/
@JvmBlockingBridge
public suspend fun kick(message: String)
/**
@ -122,14 +121,12 @@ public interface NormalMember : Member {
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: Message): MessageReceipt<NormalMember>
/**
* 发送纯文本消息
* @see sendMessage
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: String): MessageReceipt<NormalMember> =
this.sendMessage(message.toPlainText())

View File

@ -39,6 +39,7 @@ import net.mamoe.mirai.message.data.toPlainText
*
* @see StrangerMessageEvent
*/
@JvmBlockingBridge
public interface Stranger : User, CoroutineScope {
/**
* QQ 号码
@ -66,7 +67,6 @@ public interface Stranger : User, CoroutineScope {
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: Message): MessageReceipt<Stranger>
/**
@ -74,14 +74,12 @@ public interface Stranger : User, CoroutineScope {
*
* @see StrangerRelationChangeEvent.Deleted 陌生人删除事件
*/
@JvmBlockingBridge
public suspend fun delete()
/**
* 发送纯文本消息
* @see sendMessage
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: String): MessageReceipt<Stranger> =
this.sendMessage(message.toPlainText())

View File

@ -36,6 +36,7 @@ import net.mamoe.mirai.message.data.toPlainText
*
* 对于同一个 [Bot] 任何一个人的 [User] 实例都是单一的.
*/
@JvmBlockingBridge
public interface User : Contact, UserOrBot, CoroutineScope {
/**
* QQ 号码
@ -72,14 +73,12 @@ public interface User : Contact, UserOrBot, CoroutineScope {
*
* @return 消息回执. [引用][MessageReceipt.quote] [撤回][MessageReceipt.recall] 这条消息.
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: Message): MessageReceipt<User>
/**
* 发送纯文本消息
* @see sendMessage
*/
@JvmBlockingBridge
public override suspend fun sendMessage(message: String): MessageReceipt<User> =
this.sendMessage(message.toPlainText())
@ -95,7 +94,6 @@ public interface User : Contact, UserOrBot, CoroutineScope {
*
* @since 2.1
*/
@JvmBlockingBridge
public suspend fun queryProfile(): UserProfile = Mirai.queryProfile(bot, this.id)
}

View File

@ -39,6 +39,7 @@ import net.mamoe.mirai.utils.MiraiInternalApi
* @see MessageReceipt.sourceIds ids
* @see MessageReceipt.sourceTime 源时间
*/
@JvmBlockingBridge
public open class MessageReceipt<out C : Contact> @MiraiInternalApi constructor(
/**
* 指代发送出去的消息.
@ -59,7 +60,6 @@ public open class MessageReceipt<out C : Contact> @MiraiInternalApi constructor(
*
* @see IMirai.recallMessage
*/
@JvmBlockingBridge
public suspend inline fun recall() {
return Mirai.recallMessage(target.bot, source)
}
@ -82,7 +82,6 @@ public open class MessageReceipt<out C : Contact> @MiraiInternalApi constructor(
* 引用这条消息并回复.
* @see MessageSource.quote 引用一条消息
*/
@JvmBlockingBridge
public suspend inline fun quoteReply(message: Message): MessageReceipt<C> {
@Suppress("UNCHECKED_CAST")
return target.sendMessage(this.quote() + message) as MessageReceipt<C>
@ -92,7 +91,6 @@ public open class MessageReceipt<out C : Contact> @MiraiInternalApi constructor(
* 引用这条消息并回复.
* @see MessageSource.quote 引用一条消息
*/
@JvmBlockingBridge
public suspend inline fun quoteReply(message: String): MessageReceipt<C> {
return this.quoteReply(PlainText(message))
}

View File

@ -98,6 +98,9 @@ public interface RichMessage : MessageContent, ConstrainSingle {
@Serializable
@SerialName(LightApp.SERIAL_NAME)
public data class LightApp(override val content: String) : RichMessage, CodableMessage {
// implementation notes: LightApp is always decoded as LightAppInternal
// which are transformed as RefinableMessage to LightApp
public companion object Key : AbstractMessageKey<LightApp>({ it.safeCast() }) {
public const val SERIAL_NAME: String = "LightApp"
}

View File

@ -108,8 +108,14 @@ public enum class RichMessageKind {
/**
* 合并转发
* @see ForwardMessage
*/
FORWARD,
// TODO: 2021/2/3 MusicShare RichMessageKind
/**
* 音乐分享
* @see MusicShare
* @since 2.4
*/
MUSIC_SHARE,
}

View File

@ -56,6 +56,11 @@ public open class BotConfiguration { // open for Java
*/
public var workingDir: File = File(".")
/**
* 缓存数据目录
*/
public var cacheDirSupplier: (() -> File) = { workingDir.resolve("cache") }
/**
* Json 序列化器, 使用 'kotlinx.serialization'
*/
@ -396,11 +401,11 @@ public open class BotConfiguration { // open for Java
*/
public class FriendListCache @JvmOverloads constructor(
/**
* 缓存文件位置, 相对于 [workingDir] 的路径.
* 缓存文件位置, 相对于 [cacheDirSupplier] 的路径.
*
* 注意: 保存的文件仅供内部使用, 将来可能会变化.
*/
public val cacheFile: File = File("cache/friends.json"),
public val cacheFile: File = File("friends.json"),
/**
* 在有好友列表修改时自动保存间隔
*/
@ -432,11 +437,11 @@ public open class BotConfiguration { // open for Java
*/
public class GroupMemberListCache @JvmOverloads constructor(
/**
* 缓存目录位置, 相对于 [workingDir] 的路径.
* 缓存目录位置, 相对于 [cacheDirSupplier] 的路径.
*
* 注意: 保存的文件仅供内部使用, 将来可能会变化.
*/
public val cacheDir: File = File("cache/groups"),
public val cacheDir: File = File("groups"),
/**
* 在有成员列表修改时自动保存间隔
*/
@ -470,6 +475,7 @@ public open class BotConfiguration { // open for Java
return BotConfiguration().also { new ->
// To structural order
new.workingDir = workingDir
new.cacheDirSupplier = cacheDirSupplier
new.json = json
new.parentCoroutineContext = parentCoroutineContext
new.heartbeatPeriodMillis = heartbeatPeriodMillis

View File

@ -68,7 +68,7 @@ internal abstract class AbstractBot<N : BotNetworkHandler> constructor(
}
// region network
internal val serverList: MutableList<Pair<String, Int>> = DefaultServerList.toMutableList()
internal val serverList: MutableList<Pair<String, Int>> = mutableListOf()
val network: N get() = _network
@ -148,8 +148,11 @@ internal abstract class AbstractBot<N : BotNetworkHandler> constructor(
bot.logger.info { "Connection lost, retrying login ($causeMessage)" }
bot.asQQAndroidBot().client.run {
if (serverList.isEmpty()) {
bot.asQQAndroidBot().bdhSyncer.loadServerListFromCache()
if (serverList.isEmpty()) {
serverList.addAll(DefaultServerList)
} else Unit
} else serverList.removeAt(0)
}

View File

@ -25,6 +25,7 @@ import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
import net.mamoe.mirai.internal.contact.uin
import net.mamoe.mirai.internal.message.*
import net.mamoe.mirai.internal.network.*
import net.mamoe.mirai.internal.network.handler.BdhSessionSyncer
import net.mamoe.mirai.internal.network.handler.QQAndroidBotNetworkHandler
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketWithRespType
@ -57,6 +58,8 @@ internal class QQAndroidBot constructor(
private val account: BotAccount,
configuration: BotConfiguration
) : AbstractBot<QQAndroidBotNetworkHandler>(configuration, account.id) {
val bdhSyncer: BdhSessionSyncer = BdhSessionSyncer(this)
var client: QQAndroidClient = initClient()
private set
@ -79,7 +82,7 @@ internal class QQAndroidBot constructor(
val friendListCache: FriendListCache? by lazy {
configuration.friendListCache?.cacheFile?.let { cacheFile ->
val ret = configuration.workingDir.resolve(cacheFile).loadAs(FriendListCache.serializer(), JsonForCache) ?: FriendListCache()
val ret = configuration.cacheDirSupplier().resolve(cacheFile).loadAs(FriendListCache.serializer(), JsonForCache) ?: FriendListCache()
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
bot.eventChannel.parentScope(this@QQAndroidBot)
@ -130,6 +133,7 @@ internal class QQAndroidBot constructor(
@ThisApiMustBeUsedInWithConnectionLockBlock
@Throws(LoginFailedException::class) // only
override suspend fun relogin(cause: Throwable?) {
bdhSyncer.loadFromCache()
client.useNextServers { host, port ->
network.closeEverythingAndRelogin(host, port, cause, 0)
}

View File

@ -87,6 +87,9 @@ internal data class ForwardMessageInternal(override val content: String, val res
internal interface RefinableMessage : SingleMessage {
/**
* This message [RefinableMessage] will be replaced by return value of [refine]
*/
suspend fun refine(
contact: Contact,
context: MessageChain,

View File

@ -278,7 +278,7 @@ private object ReceiveMessageTransformer {
}
}
list.add(LightApp(content).refine())
list.add(LightAppInternal(content))
}
private fun decodeCustomElem(

View File

@ -12,42 +12,48 @@ package net.mamoe.mirai.internal.message
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import net.mamoe.mirai.message.data.LightApp
import net.mamoe.mirai.message.data.MusicKind
import net.mamoe.mirai.message.data.MusicShare
import net.mamoe.mirai.message.data.SingleMessage
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.safeCast
private val json = Json {
ignoreUnknownKeys = true
}
internal data class LightAppInternal(
override val content: String
) : RichMessage, RefinableMessage {
companion object Key :
AbstractPolymorphicMessageKey<RichMessage, LightAppInternal>(RichMessage, { it.safeCast() })
internal fun LightApp.tryDeserialize(): LightAppStruct? {
return kotlin.runCatching {
json.decodeFromString(LightAppStruct.serializer(), this.content)
}.getOrNull()
}
/**
* 识别 app 内容, 如果有必要
*/
internal fun LightApp.refine(): SingleMessage {
val struct = tryDeserialize() ?: return this
override suspend fun refine(contact: Contact, context: MessageChain): Message {
val struct = tryDeserialize() ?: return LightApp(content)
struct.run {
if (meta.music != null) {
MusicKind.values().find { it.appId.toInt() == meta.music.appid }?.let { musicType ->
meta.music.run {
return MusicShare(
return RichMessageOrigin(
LightApp(content),
null,
RichMessageKind.MUSIC_SHARE
) + MusicShare(
kind = musicType, title = title, summary = desc,
jumpUrl = jumpUrl, pictureUrl = preview, musicUrl = musicUrl, brief = prompt
)
}
}
}
}
return this
return LightApp(content)
}
}
private val json = Json {
ignoreUnknownKeys = true
isLenient = true
}
internal fun LightAppInternal.tryDeserialize(): LightAppStruct? {
return kotlin.runCatching {
json.decodeFromString(LightAppStruct.serializer(), this.content)
}.getOrNull()
}
/*

View File

@ -84,7 +84,7 @@ internal class GroupMemberListCaches(
}
private val cacheDir by lazy {
bot.configuration.groupMemberListCache!!.cacheDir.let { bot.configuration.workingDir.resolve(it) }
bot.configuration.groupMemberListCache!!.cacheDir.let { bot.configuration.cacheDirSupplier().resolve(it) }
}
private fun resolveCacheFile(groupCode: Long): File {

View File

@ -19,6 +19,7 @@ import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.String
import kotlinx.io.core.toByteArray
import kotlinx.io.core.writeFully
import kotlinx.serialization.Serializable
import net.mamoe.mirai.data.OnlineStatus
import net.mamoe.mirai.internal.BotAccount
import net.mamoe.mirai.internal.QQAndroidBot
@ -281,11 +282,6 @@ internal open class QQAndroidClient(
lateinit var t104: ByteArray
/**
* from ConfigPush.PushReq
*/
@JvmField
val bdhSession: CompletableDeferred<BdhSession> = CompletableDeferred()
}
internal fun BytePacketBuilder.writeLoginExtraData(loginExtraData: LoginExtraData) {
@ -298,6 +294,7 @@ internal fun BytePacketBuilder.writeLoginExtraData(loginExtraData: LoginExtraDat
}
}
@Serializable
internal class BdhSession(
val sigSession: ByteArray,
val sessionKey: ByteArray,

View File

@ -0,0 +1,120 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.internal.network.handler
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.PairSerializer
import kotlinx.serialization.builtins.serializer
import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.BdhSession
import net.mamoe.mirai.internal.network.JsonForCache
import java.io.File
private val ServerListSerializer: KSerializer<List<Pair<String, Int>>> =
ListSerializer(PairSerializer(String.serializer(), Int.serializer()))
@OptIn(ExperimentalCoroutinesApi::class)
internal class BdhSessionSyncer(
private val bot: QQAndroidBot
) {
var bdhSession: CompletableDeferred<BdhSession> = CompletableDeferred()
val hasSession: Boolean get() = bdhSession.isCompleted
fun overrideSession(
session: BdhSession,
doSave: Boolean = true
) {
bdhSession.complete(session)
bdhSession = CompletableDeferred(session)
if (doSave) {
saveToCache()
}
}
private val sessionCacheFile: File
get() = bot.configuration.cacheDirSupplier().resolve("session.json")
private val serverListCacheFile: File
get() = bot.configuration.cacheDirSupplier().resolve("serverlist.json")
fun loadServerListFromCache() {
val serverListCacheFile = this.serverListCacheFile
if (serverListCacheFile.isFile) {
bot.network.logger.verbose("Loading server list from cache.")
kotlin.runCatching {
val list = JsonForCache.decodeFromString(ServerListSerializer, serverListCacheFile.readText())
bot.serverList.clear()
bot.serverList.addAll(list)
}.onFailure {
bot.network.logger.warning("Error in loading server list from cache", it)
}
} else {
bot.network.logger.verbose("No server list cached.")
}
}
fun loadFromCache() {
val sessionCacheFile = this.sessionCacheFile
if (sessionCacheFile.isFile) {
bot.network.logger.verbose("Loading BdhSession from cache file")
kotlin.runCatching {
overrideSession(
JsonForCache.decodeFromString(BdhSession.serializer(), sessionCacheFile.readText()),
doSave = false
)
}.onFailure {
bot.network.logger.warning("Error in loading BdhSession from cache", it)
}
} else {
bot.network.logger.verbose("No BdhSession cache")
}
}
fun saveServerListToCache() {
val serverListCacheFile = this.serverListCacheFile
serverListCacheFile.parentFile?.mkdirs()
bot.network.logger.verbose("Saving server list to cache")
kotlin.runCatching {
serverListCacheFile.writeText(
JsonForCache.encodeToString(
ServerListSerializer,
bot.serverList
)
)
}.onFailure {
bot.network.logger.warning("Error in saving ServerList to cache.", it)
}
}
fun saveToCache() {
val sessionCacheFile = this.sessionCacheFile
sessionCacheFile.parentFile?.mkdirs()
if (bdhSession.isCompleted) {
bot.network.logger.verbose("Saving bdh session to cache")
kotlin.runCatching {
sessionCacheFile.writeText(
JsonForCache.encodeToString(
BdhSession.serializer(),
bdhSession.getCompleted()
)
)
}.onFailure {
bot.network.logger.warning("Error in saving BdhSession to cache.", it)
}
} else {
sessionCacheFile.delete()
bot.network.logger.verbose("No BdhSession to save to cache")
}
}
}

View File

@ -359,24 +359,20 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
logger.info { "Awaiting ConfigPushSvc.PushReq." }
when (val resp: ConfigPushSvc.PushReq.PushReqResponse? = nextEventOrNull(20_000)) {
null -> {
kotlin.runCatching { bot.client.bdhSession.completeExceptionally(CancellationException("Timeout waiting for ConfigPushSvc.PushReq")) }
val hasSession = bot.bdhSyncer.hasSession
kotlin.runCatching { bot.bdhSyncer.bdhSession.completeExceptionally(CancellationException("Timeout waiting for ConfigPushSvc.PushReq")) }
if (!hasSession) {
logger.warning { "Missing ConfigPushSvc.PushReq. File uploading may be affected." }
} else {
logger.warning { "Missing ConfigPushSvc.PushReq. Using latest response. File uploading may be affected." }
}
}
is ConfigPushSvc.PushReq.PushReqResponse.Success -> {
logger.info { "ConfigPushSvc.PushReq: Success." }
}
is ConfigPushSvc.PushReq.PushReqResponse.ChangeServer -> {
bot.logger.info { "Server requires reconnect." }
bot.logger.info { "Server list: ${resp.serverList.joinToString()}." }
if (resp.serverList.isNotEmpty()) {
bot.serverList.clear()
resp.serverList.shuffled().forEach {
bot.serverList.add(it.host to it.port)
}
}
bot.launch { BotOfflineEvent.RequireReconnect(bot).broadcast() }
logger.info { "ConfigPushSvc.PushReq: Require reconnect" }
// handled in ConfigPushSvc
return@launch
}
}

View File

@ -59,7 +59,7 @@ internal object Highway {
fallbackSession: (Throwable) -> BdhSession = { throw IllegalStateException("Failed to get bdh session", it) }
): BdhUploadResponse {
val bdhSession = kotlin.runCatching {
val deferred = bot.client.bdhSession
val deferred = bot.bdhSyncer.bdhSession
// no need to care about timeout. proceed by bot init
@OptIn(ExperimentalCoroutinesApi::class)
if (noBdhAwait) deferred.getCompleted() else deferred.await()

View File

@ -199,9 +199,12 @@ internal open class KeyWithCreationTime(
}
internal suspend inline fun QQAndroidClient.useNextServers(crossinline block: suspend (host: String, port: Int) -> Unit) {
if (bot.serverList.isEmpty()) {
bot.bdhSyncer.loadServerListFromCache()
if (bot.serverList.isEmpty()) {
bot.serverList.addAll(DefaultServerList)
}
}
retryCatchingExceptions(bot.serverList.size, except = LoginFailedException::class) l@{
val pair = bot.serverList[0]
runCatchingExceptions {

View File

@ -9,10 +9,14 @@
package net.mamoe.mirai.internal.network.protocol.packet.login
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.io.core.ByteReadPacket
import kotlinx.serialization.Serializable
import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.message.contextualBugReportException
import net.mamoe.mirai.internal.network.BdhSession
@ -30,6 +34,7 @@ import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.readUniPacket
import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
import net.mamoe.mirai.internal.utils.io.serialization.writeJceStruct
import net.mamoe.mirai.utils.info
import net.mamoe.mirai.utils.toUHexString
import java.lang.IllegalStateException
import net.mamoe.mirai.internal.network.protocol.data.jce.PushReq as PushReqJceStruct
@ -110,7 +115,7 @@ internal class ConfigPushSvc {
val bigDataChannel = fileStoragePushFSSvcList.bigDataChannel
if (bigDataChannel?.vBigdataPbBuf == null) {
client.bdhSession.completeExceptionally(IllegalStateException("BdhSession not received."))
bot.bdhSyncer.bdhSession.completeExceptionally(IllegalStateException("BdhSession not received."))
return
}
@ -134,16 +139,35 @@ internal class ConfigPushSvc {
session
}.fold(
onSuccess = {
client.bdhSession.complete(it)
bdhSyncer.overrideSession(it)
},
onFailure = { cause ->
val e = IllegalStateException("Failed to decode BdhSession", cause)
client.bdhSession.completeExceptionally(e)
bdhSyncer.bdhSession.completeExceptionally(e)
logger.error(e)
}
)
}
fun handleRequireReconnect(resp: PushReqResponse.ChangeServer) {
bot.logger.info { "Server requires reconnect." }
bot.logger.info { "Server list: ${resp.serverList.joinToString()}." }
if (resp.serverList.isNotEmpty()) {
bot.serverList.clear()
resp.serverList.shuffled().forEach {
bot.serverList.add(it.host to it.port)
}
}
bot.bdhSyncer.saveToCache()
bot.bdhSyncer.saveServerListToCache()
bot.launch {
delay(1000)
BotOfflineEvent.RequireReconnect(bot).broadcast()
}
}
when (packet) {
is PushReqResponse.Success -> {
handleSuccess(packet)
@ -172,6 +196,10 @@ internal class ConfigPushSvc {
// writePacket(this.build().debugPrintThis())
}
}
is PushReqResponse.ChangeServer -> {
handleRequireReconnect(packet)
return null
}
else -> {
// handled in QQABot
return null