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 39538bc1f..b79868e72 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -330,7 +330,7 @@ public abstract interface class net/mamoe/mirai/contact/FileSupported : net/mamo public abstract fun getFilesRoot ()Lnet/mamoe/mirai/utils/RemoteFile; } -public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/User { +public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/User, net/mamoe/mirai/contact/VoiceSupported { public fun delete ()V public abstract fun delete (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun getId ()J @@ -345,7 +345,7 @@ public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/corouti public abstract fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/Contact, net/mamoe/mirai/contact/FileSupported { +public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/Contact, net/mamoe/mirai/contact/FileSupported, net/mamoe/mirai/contact/VoiceSupported { public static final field Companion Lnet/mamoe/mirai/contact/Group$Companion; public abstract fun contains (J)Z public fun contains (Lnet/mamoe/mirai/contact/NormalMember;)Z @@ -371,8 +371,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 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; } public final class net/mamoe/mirai/contact/Group$Companion { @@ -571,6 +569,11 @@ public abstract interface class net/mamoe/mirai/contact/UserOrBot : net/mamoe/mi public abstract fun nudge ()Lnet/mamoe/mirai/message/action/Nudge; } +public abstract interface class net/mamoe/mirai/contact/VoiceSupported : net/mamoe/mirai/contact/Contact { + 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; +} + public class net/mamoe/mirai/data/Announcement { public static final field Companion Lnet/mamoe/mirai/data/Announcement$Companion; public static final fun create (JLjava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/data/AnnouncementParameters;)Lnet/mamoe/mirai/data/Announcement; @@ -5399,8 +5402,14 @@ public abstract interface class net/mamoe/mirai/utils/ExternalResource : java/io public static fun uploadAsImage (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadAsImage (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;)Lnet/mamoe/mirai/message/data/Image; public static fun uploadAsImage (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public static fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public static fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;)Lnet/mamoe/mirai/message/data/Voice; public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/FileMessage; public static fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/data/FileMessage; @@ -5468,8 +5477,14 @@ public final class net/mamoe/mirai/utils/ExternalResource$Companion { public static synthetic fun uploadAsImage$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/File;Lnet/mamoe/mirai/contact/Contact;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun uploadAsImage$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/InputStream;Lnet/mamoe/mirai/contact/Contact;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/message/data/Image; public static synthetic fun uploadAsImage$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/InputStream;Lnet/mamoe/mirai/contact/Contact;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public final fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public final fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public final fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;)Lnet/mamoe/mirai/message/data/Voice; public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/FileMessage; public final fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/data/FileMessage; diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index 415fc4c71..3e5d96c08 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -330,7 +330,7 @@ public abstract interface class net/mamoe/mirai/contact/FileSupported : net/mamo public abstract fun getFilesRoot ()Lnet/mamoe/mirai/utils/RemoteFile; } -public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/User { +public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/User, net/mamoe/mirai/contact/VoiceSupported { public fun delete ()V public abstract fun delete (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun getId ()J @@ -345,7 +345,7 @@ public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/corouti public abstract fun sendMessage (Lnet/mamoe/mirai/message/data/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/Contact, net/mamoe/mirai/contact/FileSupported { +public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/Contact, net/mamoe/mirai/contact/FileSupported, net/mamoe/mirai/contact/VoiceSupported { public static final field Companion Lnet/mamoe/mirai/contact/Group$Companion; public abstract fun contains (J)Z public fun contains (Lnet/mamoe/mirai/contact/NormalMember;)Z @@ -371,8 +371,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 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; } public final class net/mamoe/mirai/contact/Group$Companion { @@ -571,6 +569,11 @@ public abstract interface class net/mamoe/mirai/contact/UserOrBot : net/mamoe/mi public abstract fun nudge ()Lnet/mamoe/mirai/message/action/Nudge; } +public abstract interface class net/mamoe/mirai/contact/VoiceSupported : net/mamoe/mirai/contact/Contact { + 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; +} + public class net/mamoe/mirai/data/Announcement { public static final field Companion Lnet/mamoe/mirai/data/Announcement$Companion; public static final fun create (JLjava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/data/AnnouncementParameters;)Lnet/mamoe/mirai/data/Announcement; @@ -5399,8 +5402,14 @@ public abstract interface class net/mamoe/mirai/utils/ExternalResource : java/io public static fun uploadAsImage (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadAsImage (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;)Lnet/mamoe/mirai/message/data/Image; public static fun uploadAsImage (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public static fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public static fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;)Lnet/mamoe/mirai/message/data/Voice; public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public static fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/FileMessage; public static fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/data/FileMessage; @@ -5468,8 +5477,14 @@ public final class net/mamoe/mirai/utils/ExternalResource$Companion { public static synthetic fun uploadAsImage$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/File;Lnet/mamoe/mirai/contact/Contact;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun uploadAsImage$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/InputStream;Lnet/mamoe/mirai/contact/Contact;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/message/data/Image; public static synthetic fun uploadAsImage$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/InputStream;Lnet/mamoe/mirai/contact/Contact;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public final fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public final fun uploadAsVoice (Ljava/io/File;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public final fun uploadAsVoice (Ljava/io/InputStream;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;)Lnet/mamoe/mirai/message/data/Voice; public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/Contact;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;)Lnet/mamoe/mirai/message/data/Voice; + public final fun uploadAsVoice (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/VoiceSupported;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/FileMessage; public final fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun uploadTo (Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/data/FileMessage; diff --git a/mirai-core-api/src/commonMain/kotlin/contact/Friend.kt b/mirai-core-api/src/commonMain/kotlin/contact/Friend.kt index b4d2e1638..4e4ab0306 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/Friend.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/Friend.kt @@ -32,7 +32,7 @@ import net.mamoe.mirai.message.data.toPlainText * @see FriendMessageEvent */ @JvmBlockingBridge -public interface Friend : User, CoroutineScope { +public interface Friend : User, CoroutineScope, VoiceSupported { /** * QQ 号码 */ diff --git a/mirai-core-api/src/commonMain/kotlin/contact/Group.kt b/mirai-core-api/src/commonMain/kotlin/contact/Group.kt index 497fe1421..6752be224 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/Group.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/Group.kt @@ -32,7 +32,7 @@ import net.mamoe.mirai.utils.OverFileSizeMaxException * 群. */ @JvmBlockingBridge -public interface Group : Contact, CoroutineScope, FileSupported { +public interface Group : Contact, CoroutineScope, FileSupported, VoiceSupported { /** * 群名称. * @@ -157,18 +157,6 @@ public interface Group : Contact, CoroutineScope, FileSupported { public override suspend fun sendMessage(message: String): MessageReceipt = this.sendMessage(message.toPlainText()) - /** - * 上传一个语音消息以备发送. - * - * - **请手动关闭 [resource]** - * - 请使用 amr 或 silk 格式 - * - * @see ExternalResource.uploadAsVoice - * - * @throws EventCancelledException 当发送消息事件被取消 - * @throws OverFileSizeMaxException 当语音文件过大而被服务器拒绝上传时. (最大大小约为 1 MB) - */ - public suspend fun uploadVoice(resource: ExternalResource): Voice /** diff --git a/mirai-core-api/src/commonMain/kotlin/contact/VoiceSupported.kt b/mirai-core-api/src/commonMain/kotlin/contact/VoiceSupported.kt new file mode 100644 index 000000000..54cf615ff --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/contact/VoiceSupported.kt @@ -0,0 +1,37 @@ +/* + * 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.contact + +import net.mamoe.kjbb.JvmBlockingBridge +import net.mamoe.mirai.message.data.Voice +import net.mamoe.mirai.utils.ExternalResource +import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsVoice +import net.mamoe.mirai.utils.OverFileSizeMaxException + +/** + * 支持发送语音的 [Contact] + * + * @since 2.7 + */ +public interface VoiceSupported : Contact { + /** + * 上传一个语音消息以备发送. + * + * - **请手动关闭 [resource]** + * - 请使用 amr 或 silk 格式 + * + * @since 2.7 + * @see ExternalResource.uploadAsVoice + * @throws OverFileSizeMaxException 当语音文件过大而被服务器拒绝上传时. (最大大小约为 1 MB) + */ + @JvmBlockingBridge + public suspend fun uploadVoice(resource: ExternalResource): Voice + +} diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Voice.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Voice.kt index 7bece5387..4406ff76a 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Voice.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Voice.kt @@ -11,6 +11,7 @@ package net.mamoe.mirai.message.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient import net.mamoe.mirai.contact.Group import net.mamoe.mirai.utils.ExternalResource import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsVoice @@ -39,6 +40,10 @@ public abstract class PttMessage : MessageContent { @MiraiExperimentalApi public abstract val fileSize: Long + + @MiraiInternalApi + @Transient + public var pttInternalInstance: Any? = null } /** diff --git a/mirai-core-api/src/commonMain/kotlin/utils/ExternalResource.kt b/mirai-core-api/src/commonMain/kotlin/utils/ExternalResource.kt index 1e712992d..51eff0d6c 100644 --- a/mirai-core-api/src/commonMain/kotlin/utils/ExternalResource.kt +++ b/mirai-core-api/src/commonMain/kotlin/utils/ExternalResource.kt @@ -19,7 +19,7 @@ import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact.Companion.sendImage import net.mamoe.mirai.contact.Contact.Companion.uploadImage import net.mamoe.mirai.contact.FileSupported -import net.mamoe.mirai.contact.Group +import net.mamoe.mirai.contact.VoiceSupported import net.mamoe.mirai.internal.utils.ExternalResourceImplByByteArray import net.mamoe.mirai.internal.utils.ExternalResourceImplByFile import net.mamoe.mirai.message.MessageReceipt @@ -384,15 +384,52 @@ public interface ExternalResource : Closeable { * * **服务器仅支持音频格式 `silk` 或 `amr`**. 需要调用方手动[关闭资源][ExternalResource.close]. * - * 目前仅支持发送给群. - * * @throws OverFileSizeMaxException + * @since 2.7 + * @see VoiceSupported.uploadVoice */ @JvmBlockingBridge @JvmStatic - public suspend fun ExternalResource.uploadAsVoice(contact: Contact): Voice { - if (contact is Group) return contact.uploadVoice(this) - else throw UnsupportedOperationException("Uploading Voice is only supported for Group yet.") + public suspend fun ExternalResource.uploadAsVoice(contact: VoiceSupported): Voice { + return contact.uploadVoice(this) } + + @JvmBlockingBridge + @JvmStatic + @Deprecated("For binary compatibility", level = DeprecationLevel.WARNING) + @JvmName("uploadAsVoice") + public suspend fun ExternalResource.uploadAsVoice(contact: Contact): Voice { + if (contact is VoiceSupported) return contact.uploadVoice(this) + else throw UnsupportedOperationException("Contact `$contact` is not supported uploading voice") + } + + /** + * 读取 [InputStream] 到临时文件并将其作为语音上传至 [contact] 后构造 [Voice], + * 上传后只会得到 [Voice] 实例, 而不会将语音发送到目标群或好友 + * + * 注意:本函数不会关闭流. + * + * @since 2.7 + * @throws OverFileSizeMaxException + * @see VoiceSupported.uploadVoice + */ + @JvmStatic + @JvmBlockingBridge + public suspend fun InputStream.uploadAsVoice(contact: VoiceSupported): Voice = + runBIO { toExternalResource() }.withUse { uploadAsVoice(contact) } + + /** + * 将文件作为语音上传后构造 [Voice]. + * 上传后只会得到 [Voice] 实例, 而不会将语音发送到目标群或好友 + * + * @since 2.7 + * @throws OverFileSizeMaxException + * @see VoiceSupported.uploadVoice + */ + @JvmStatic + @JvmBlockingBridge + public suspend fun File.uploadAsVoice(contact: VoiceSupported): Voice = + toExternalResource().withUse { uploadAsVoice(contact) } + } -} \ No newline at end of file +} diff --git a/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt b/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt index f4af6ecbb..ec968f8d3 100644 --- a/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt @@ -21,16 +21,29 @@ package net.mamoe.mirai.internal.contact import kotlinx.atomicfu.AtomicInt import kotlinx.atomicfu.atomic import net.mamoe.mirai.LowLevelApi +import net.mamoe.mirai.Mirai import net.mamoe.mirai.contact.Friend import net.mamoe.mirai.data.FriendInfo import net.mamoe.mirai.event.events.FriendMessagePostSendEvent import net.mamoe.mirai.event.events.FriendMessagePreSendEvent import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.contact.info.FriendInfoImpl +import net.mamoe.mirai.internal.network.highway.* +import net.mamoe.mirai.internal.network.protocol.data.proto.Cmd0x346 +import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody +import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.PttStore +import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.voiceCodec import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList import net.mamoe.mirai.internal.utils.C2CPkgMsgParsingCache +import net.mamoe.mirai.internal.utils.io.serialization.loadAs +import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.message.MessageReceipt -import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.message.data.Message +import net.mamoe.mirai.message.data.Voice +import net.mamoe.mirai.utils.ExternalResource +import net.mamoe.mirai.utils.recoverCatchingSuppressed +import net.mamoe.mirai.utils.toByteArray +import net.mamoe.mirai.utils.toUHexString import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext @@ -81,4 +94,63 @@ internal class FriendImpl( } override fun toString(): String = "Friend($id)" + + override suspend fun uploadVoice(resource: ExternalResource): Voice = bot.network.run { + val voice = Voice( + "${resource.md5.toUHexString("")}.amr", + resource.md5, + resource.size, + resource.voiceCodec, + "" + ) + kotlin.runCatching { + val resp = Highway.uploadResourceBdh( + bot = bot, + resource = resource, + kind = ResourceKind.PRIVATE_VOICE, + commandId = 26, + extendInfo = PttStore.C2C.createC2CPttStoreBDHExt(bot, this@FriendImpl.uin, resource) + .toByteArray(Cmd0x346.ReqBody.serializer()) + ) + // resp._miraiContentToString("UV resp") + val c346resp = resp.extendInfo!!.loadAs(Cmd0x346.RspBody.serializer()) + if (c346resp.msgApplyUploadRsp == null) { + error("Upload failed") + } + voice.pttInternalInstance = ImMsgBody.Ptt( + fileType = 4, + srcUin = bot.uin, + fileUuid = c346resp.msgApplyUploadRsp.uuid, + fileMd5 = resource.md5, + fileName = resource.md5 + ".amr".toByteArray(), + fileSize = resource.size.toInt(), + boolValid = true, + ) + }.recoverCatchingSuppressed { + when (val resp = PttStore.GroupPttUp(bot.client, bot.id, id, resource).sendAndExpect()) { + is PttStore.GroupPttUp.Response.RequireUpload -> { + tryServersUpload( + bot, + resp.uploadIpList.zip(resp.uploadPortList), + resource.size, + ResourceKind.GROUP_VOICE, + ChannelKind.HTTP + ) { ip, port -> + Mirai.Http.postPtt(ip, port, resource, resp.uKey, resp.fileKey) + } + voice.pttInternalInstance = ImMsgBody.Ptt( + fileType = 4, + srcUin = bot.uin, + fileUuid = resp.fileId.toByteArray(), + fileMd5 = resource.md5, + fileName = resource.md5 + ".amr".toByteArray(), + fileSize = resource.size.toInt(), + boolValid = true, + ) + } + } + }.getOrThrow() + + return voice + } } diff --git a/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt b/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt index 9e198d52d..3ee2d80c9 100644 --- a/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt +++ b/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt @@ -9,7 +9,6 @@ package net.mamoe.mirai.internal.message -import io.ktor.util.* import kotlinx.io.core.discardExact import kotlinx.io.core.readUInt import kotlinx.io.core.readUShort @@ -520,5 +519,5 @@ internal object ReceiveMessageTransformer { fileSize.toLong(), format, kotlinx.io.core.String(downPara) - ) + ).also { it.pttInternalInstance = this } } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Cmd0x346.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Cmd0x346.kt new file mode 100644 index 000000000..ec290842f --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Cmd0x346.kt @@ -0,0 +1,588 @@ +/* + * 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 + */ +@file:Suppress("unused", "SpellCheckingInspection") + +package net.mamoe.mirai.internal.network.protocol.data.proto + +import kotlinx.serialization.Serializable +import kotlinx.serialization.protobuf.ProtoNumber +import net.mamoe.mirai.internal.utils.io.ProtoBuf +import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY + +@Serializable +internal class Cmd0x346 : ProtoBuf { + @Serializable + internal class AddrList( + @JvmField @ProtoNumber(2) val strIp: List = emptyList(), + @JvmField @ProtoNumber(3) val strDomain: String = "", + @JvmField @ProtoNumber(4) val port: Int = 0 + ) : ProtoBuf + + @Serializable + internal class ApplyCleanTrafficReq : ProtoBuf + + @Serializable + internal class ApplyCleanTrafficRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyCopyFromReq( + @JvmField @ProtoNumber(10) val srcUin: Long = 0L, + @JvmField @ProtoNumber(20) val srcGroup: Long = 0L, + @JvmField @ProtoNumber(30) val srcSvcid: Int = 0, + @JvmField @ProtoNumber(40) val srcParentfolder: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(50) val srcUuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(60) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val dstUin: Long = 0L, + @JvmField @ProtoNumber(80) val fileSize: Long = 0L, + @JvmField @ProtoNumber(90) val fileName: String = "", + @JvmField @ProtoNumber(100) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(110) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyCopyFromRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(40) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyCopyToReq( + @JvmField @ProtoNumber(10) val dstId: Long = 0L, + @JvmField @ProtoNumber(20) val dstUin: Long = 0L, + @JvmField @ProtoNumber(30) val dstSvcid: Int = 0, + @JvmField @ProtoNumber(40) val srcUin: Long = 0L, + @JvmField @ProtoNumber(50) val fileSize: Long = 0L, + @JvmField @ProtoNumber(60) val fileName: String = "", + @JvmField @ProtoNumber(70) val localFilepath: String = "", + @JvmField @ProtoNumber(80) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class ApplyCopyToRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val fileKey: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyDownloadAbsReq( + @JvmField @ProtoNumber(10) val uin: Long = 0L, + @JvmField @ProtoNumber(20) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class ApplyDownloadAbsRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val msgDownloadInfo: Cmd0x346.DownloadInfo? = null + ) : ProtoBuf + + @Serializable + internal class ApplyDownloadReq( + @JvmField @ProtoNumber(10) val uin: Long = 0L, + @JvmField @ProtoNumber(20) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(30) val ownerType: Int = 0, + @JvmField @ProtoNumber(500) val extUintype: Int = 0, + @JvmField @ProtoNumber(501) val needHttpsUrl: Int = 0 + ) : ProtoBuf + + @Serializable + internal class ApplyDownloadRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val msgDownloadInfo: Cmd0x346.DownloadInfo? = null, + @JvmField @ProtoNumber(40) val msgFileInfo: Cmd0x346.FileInfo? = null + ) : ProtoBuf + + @Serializable + internal class ApplyForwardFileReq( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(40) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(50) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyForwardFileRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(40) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(50) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class ApplyGetTrafficReq : ProtoBuf + + @Serializable + internal class ApplyGetTrafficRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val useFileSize: Long = 0L, + @JvmField @ProtoNumber(40) val useFileNum: Int = 0, + @JvmField @ProtoNumber(50) val allFileSize: Long = 0L, + @JvmField @ProtoNumber(60) val allFileNum: Int = 0 + ) : ProtoBuf + + @Serializable + internal class ApplyListDownloadReq( + @JvmField @ProtoNumber(10) val uin: Long = 0L, + @JvmField @ProtoNumber(20) val beginIndex: Int = 0, + @JvmField @ProtoNumber(30) val reqCount: Int = 0 + ) : ProtoBuf + + @Serializable + internal class ApplyListDownloadRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val totalCount: Int = 0, + @JvmField @ProtoNumber(40) val beginIndex: Int = 0, + @JvmField @ProtoNumber(50) val rspCount: Int = 0, + @JvmField @ProtoNumber(60) val isEnd: Int = 0, + @JvmField @ProtoNumber(70) val msgFileList: List = emptyList() + ) : ProtoBuf + + @Serializable + internal class ApplyUploadHitReq( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val fileSize: Long = 0L, + @JvmField @ProtoNumber(40) val fileName: String = "", + @JvmField @ProtoNumber(50) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(60) val localFilepath: String = "", + @JvmField @ProtoNumber(70) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(80) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyUploadHitReqV2( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val fileSize: Long = 0L, + @JvmField @ProtoNumber(40) val fileName: String = "", + @JvmField @ProtoNumber(50) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(60) val _3sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(80) val localFilepath: String = "", + @JvmField @ProtoNumber(90) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(100) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyUploadHitReqV3( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val fileSize: Long = 0L, + @JvmField @ProtoNumber(40) val fileName: String = "", + @JvmField @ProtoNumber(50) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(60) val sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val localFilepath: String = "", + @JvmField @ProtoNumber(80) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(90) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyUploadHitRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val uploadIp: String = "", + @JvmField @ProtoNumber(40) val uploadPort: Int = 0, + @JvmField @ProtoNumber(50) val uploadDomain: String = "", + @JvmField @ProtoNumber(60) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val uploadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(80) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(90) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(100) val uploadDns: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyUploadHitRspV2( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val uploadIp: String = "", + @JvmField @ProtoNumber(40) val uploadPort: Int = 0, + @JvmField @ProtoNumber(50) val uploadDomain: String = "", + @JvmField @ProtoNumber(60) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val uploadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(80) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(90) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(100) val uploadHttpsPort: Int = 443, + @JvmField @ProtoNumber(110) val uploadHttpsDomain: String = "", + @JvmField @ProtoNumber(120) val uploadDns: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyUploadHitRspV3( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val uploadIp: String = "", + @JvmField @ProtoNumber(40) val uploadPort: Int = 0, + @JvmField @ProtoNumber(50) val uploadDomain: String = "", + @JvmField @ProtoNumber(60) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val uploadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(80) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(90) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(100) val uploadDns: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyUploadReq( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val fileType: Int = 0, + @JvmField @ProtoNumber(40) val fileSize: Long = 0L, + @JvmField @ProtoNumber(50) val fileName: ByteArray = EMPTY_BYTE_ARRAY, //String = "", + @JvmField @ProtoNumber(60) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val localFilepath: String = "", + @JvmField @ProtoNumber(80) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(90) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyUploadReqV2( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val fileSize: Long = 0L, + @JvmField @ProtoNumber(40) val fileName: String = "", + @JvmField @ProtoNumber(50) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(60) val _3sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val localFilepath: String = "", + @JvmField @ProtoNumber(80) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(90) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyUploadReqV3( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val fileSize: Long = 0L, + @JvmField @ProtoNumber(40) val fileName: String = "", + @JvmField @ProtoNumber(50) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(60) val sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(70) val localFilepath: String = "", + @JvmField @ProtoNumber(80) val dangerLevel: Int = 0, + @JvmField @ProtoNumber(90) val totalSpace: Long = 0L + ) : ProtoBuf + + @Serializable + internal class ApplyUploadRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(40) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(50) val uploadedSize: Long = 0L, + @JvmField @ProtoNumber(60) val uploadIp: String = "", + @JvmField @ProtoNumber(70) val uploadDomain: String = "", + @JvmField @ProtoNumber(80) val uploadPort: Int = 0, + @JvmField @ProtoNumber(90) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(100) val uploadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(110) val boolFileExist: Boolean = false, + @JvmField @ProtoNumber(120) val packSize: Int = 0, + @JvmField @ProtoNumber(130) val strUploadipList: List = emptyList(), + @JvmField @ProtoNumber(140) val uploadDns: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyUploadRspV2( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(40) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(50) val uploadedSize: Long = 0L, + @JvmField @ProtoNumber(60) val uploadIp: String = "", + @JvmField @ProtoNumber(70) val uploadDomain: String = "", + @JvmField @ProtoNumber(80) val uploadPort: Int = 0, + @JvmField @ProtoNumber(90) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(100) val uploadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(110) val boolFileExist: Boolean = false, + @JvmField @ProtoNumber(120) val packSize: Int = 0, + @JvmField @ProtoNumber(130) val strUploadipList: List = emptyList(), + @JvmField @ProtoNumber(140) val httpsvrApiVer: Int = 0, + @JvmField @ProtoNumber(141) val sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(142) val uploadHttpsPort: Int = 443, + @JvmField @ProtoNumber(143) val uploadHttpsDomain: String = "", + @JvmField @ProtoNumber(150) val uploadDns: String = "", + @JvmField @ProtoNumber(160) val uploadLanip: String = "" + ) : ProtoBuf + + @Serializable + internal class ApplyUploadRspV3( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val totalSpace: Long = 0L, + @JvmField @ProtoNumber(40) val usedSpace: Long = 0L, + @JvmField @ProtoNumber(50) val uploadedSize: Long = 0L, + @JvmField @ProtoNumber(60) val uploadIp: String = "", + @JvmField @ProtoNumber(70) val uploadDomain: String = "", + @JvmField @ProtoNumber(80) val uploadPort: Int = 0, + @JvmField @ProtoNumber(90) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(100) val uploadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(110) val boolFileExist: Boolean = false, + @JvmField @ProtoNumber(120) val packSize: Int = 0, + @JvmField @ProtoNumber(130) val strUploadipList: List = emptyList(), + @JvmField @ProtoNumber(140) val uploadHttpsPort: Int = 443, + @JvmField @ProtoNumber(150) val uploadHttpsDomain: String = "", + @JvmField @ProtoNumber(160) val uploadDns: String = "", + @JvmField @ProtoNumber(170) val uploadLanip: String = "" + ) : ProtoBuf + + @Serializable + internal class DeleteFileReq( + @JvmField @ProtoNumber(10) val uin: Long = 0L, + @JvmField @ProtoNumber(20) val peerUin: Long = 0L, + @JvmField @ProtoNumber(30) val deleteType: Int = 0, + @JvmField @ProtoNumber(40) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class DeleteFileRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "" + ) : ProtoBuf + + @Serializable + internal class DelMessageReq( + @JvmField @ProtoNumber(1) val uinSender: Long = 0L, + @JvmField @ProtoNumber(2) val uinReceiver: Long = 0L, + @JvmField @ProtoNumber(10) val msgTime: Int = 0, + @JvmField @ProtoNumber(20) val msgRandom: Int = 0, + @JvmField @ProtoNumber(30) val msgSeqNo: Int = 0 + ) : ProtoBuf + + @Serializable + internal class DownloadInfo( + @JvmField @ProtoNumber(10) val downloadKey: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(20) val downloadIp: String = "", + @JvmField @ProtoNumber(30) val downloadDomain: String = "", + @JvmField @ProtoNumber(40) val port: Int = 0, + @JvmField @ProtoNumber(50) val downloadUrl: String = "", + @JvmField @ProtoNumber(60) val strDownloadipList: List = emptyList(), + @JvmField @ProtoNumber(70) val cookie: String = "", + @JvmField @ProtoNumber(80) val httpsPort: Int = 443, + @JvmField @ProtoNumber(90) val httpsDownloadDomain: String = "", + @JvmField @ProtoNumber(110) val downloadDns: String = "" + ) : ProtoBuf + + @Serializable + internal class DownloadSuccReq( + @JvmField @ProtoNumber(10) val uin: Long = 0L, + @JvmField @ProtoNumber(20) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class DownloadSuccRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val int32DownStat: Int = 0 + ) : ProtoBuf + + @Serializable + internal class ExtensionReq( + @JvmField @ProtoNumber(1) val id: Long = 0L, + @JvmField @ProtoNumber(2) val type: Long = 0L, + @JvmField @ProtoNumber(3) val dstPhonenum: String = "", + @JvmField @ProtoNumber(4) val int32PhoneConvertType: Int = 0, + @JvmField @ProtoNumber(20) val sig: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(100) val routeId: Long = 0L, + @JvmField @ProtoNumber(90100) val msgDelMessageReq: Cmd0x346.DelMessageReq? = null, + @JvmField @ProtoNumber(90200) val downloadUrlType: Int = 0, + @JvmField @ProtoNumber(90300) val pttFormat: Int = 0, + @JvmField @ProtoNumber(90400) val isNeedInnerIp: Int = 0, + @JvmField @ProtoNumber(90500) val netType: Int = 255, + @JvmField @ProtoNumber(90600) val voiceType: Int = 0, + @JvmField @ProtoNumber(90700) val fileType: Int = 0, + @JvmField @ProtoNumber(90800) val pttTime: Int = 0, + @JvmField @ProtoNumber(90900) val bdhCmdid: Int = 0, + @JvmField @ProtoNumber(91000) val reqTransferType: Int = 0, + @JvmField @ProtoNumber(91100) val isAuto: Int = 0 + ) : ProtoBuf + + @Serializable + internal class ExtensionRsp( + @JvmField @ProtoNumber(1) val transferType: Int = 0, + @JvmField @ProtoNumber(2) val channelType: Int = 0, + @JvmField @ProtoNumber(3) val allowRetry: Int = 0, + @JvmField @ProtoNumber(4) val serverAddrIpv6List: Cmd0x346.AddrList? = null + ) : ProtoBuf + + @Serializable + internal class FileInfo( + @JvmField @ProtoNumber(1) val uin: Long = 0L, + @JvmField @ProtoNumber(2) val dangerEvel: Int = 0, + @JvmField @ProtoNumber(3) val fileSize: Long = 0L, + @JvmField @ProtoNumber(4) val lifeTime: Int = 0, + @JvmField @ProtoNumber(5) val uploadTime: Int = 0, + @JvmField @ProtoNumber(6) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(7) val fileName: String = "", + @JvmField @ProtoNumber(90) val absFileType: Int = 0, + @JvmField @ProtoNumber(100) val _10mMd5: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(101) val sha: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(110) val clientType: Int = 0, + @JvmField @ProtoNumber(120) val ownerUin: Long = 0L, + @JvmField @ProtoNumber(121) val peerUin: Long = 0L, + @JvmField @ProtoNumber(130) val expireTime: Int = 0 + ) : ProtoBuf + + @Serializable + internal class FileQueryReq( + @JvmField @ProtoNumber(10) val uin: Long = 0L, + @JvmField @ProtoNumber(20) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class FileQueryRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val msgFileInfo: Cmd0x346.FileInfo? = null + ) : ProtoBuf + + @Serializable + internal class RecallFileReq( + @JvmField @ProtoNumber(1) val uin: Long = 0L, + @JvmField @ProtoNumber(2) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class RecallFileRsp( + @JvmField @ProtoNumber(1) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(2) val retMsg: String = "" + ) : ProtoBuf + + @Serializable + internal class RecvListQueryReq( + @JvmField @ProtoNumber(1) val uin: Long = 0L, + @JvmField @ProtoNumber(2) val beginIndex: Int = 0, + @JvmField @ProtoNumber(3) val reqCount: Int = 0 + ) : ProtoBuf + + @Serializable + internal class RecvListQueryRsp( + @JvmField @ProtoNumber(1) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(2) val retMsg: String = "", + @JvmField @ProtoNumber(3) val fileTotCount: Int = 0, + @JvmField @ProtoNumber(4) val beginIndex: Int = 0, + @JvmField @ProtoNumber(5) val rspFileCount: Int = 0, + @JvmField @ProtoNumber(6) val isEnd: Int = 0, + @JvmField @ProtoNumber(7) val msgFileList: List = emptyList() + ) : ProtoBuf + + @Serializable + internal class RenewFileReq( + @JvmField @ProtoNumber(1) val uin: Long = 0L, + @JvmField @ProtoNumber(2) val uuid: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(3) val addTtl: Int = 0 + ) : ProtoBuf + + @Serializable + internal class RenewFileRsp( + @JvmField @ProtoNumber(1) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(2) val retMsg: String = "" + ) : ProtoBuf + + @Serializable + internal class ReqBody( + @JvmField @ProtoNumber(1) val cmd: Int = 0, + @JvmField @ProtoNumber(2) val seq: Int = 0, + @JvmField @ProtoNumber(3) val msgRecvListQueryReq: Cmd0x346.RecvListQueryReq? = null, + @JvmField @ProtoNumber(4) val msgSendListQueryReq: Cmd0x346.SendListQueryReq? = null, + @JvmField @ProtoNumber(5) val msgRenewFileReq: Cmd0x346.RenewFileReq? = null, + @JvmField @ProtoNumber(6) val msgRecallFileReq: Cmd0x346.RecallFileReq? = null, + @JvmField @ProtoNumber(7) val msgApplyUploadReq: Cmd0x346.ApplyUploadReq? = null, + @JvmField @ProtoNumber(8) val msgApplyUploadHitReq: Cmd0x346.ApplyUploadHitReq? = null, + @JvmField @ProtoNumber(9) val msgApplyForwardFileReq: Cmd0x346.ApplyForwardFileReq? = null, + @JvmField @ProtoNumber(10) val msgUploadSuccReq: Cmd0x346.UploadSuccReq? = null, + @JvmField @ProtoNumber(11) val msgDeleteFileReq: Cmd0x346.DeleteFileReq? = null, + @JvmField @ProtoNumber(12) val msgDownloadSuccReq: Cmd0x346.DownloadSuccReq? = null, + @JvmField @ProtoNumber(13) val msgApplyDownloadAbsReq: Cmd0x346.ApplyDownloadAbsReq? = null, + @JvmField @ProtoNumber(14) val msgApplyDownloadReq: Cmd0x346.ApplyDownloadReq? = null, + @JvmField @ProtoNumber(15) val msgApplyListDownloadReq: Cmd0x346.ApplyListDownloadReq? = null, + @JvmField @ProtoNumber(16) val msgFileQueryReq: Cmd0x346.FileQueryReq? = null, + @JvmField @ProtoNumber(17) val msgApplyCopyFromReq: Cmd0x346.ApplyCopyFromReq? = null, + @JvmField @ProtoNumber(18) val msgApplyUploadReqV2: Cmd0x346.ApplyUploadReqV2? = null, + @JvmField @ProtoNumber(19) val msgApplyUploadReqV3: Cmd0x346.ApplyUploadReqV3? = null, + @JvmField @ProtoNumber(20) val msgApplyUploadHitReqV2: Cmd0x346.ApplyUploadHitReqV2? = null, + @JvmField @ProtoNumber(21) val msgApplyUploadHitReqV3: Cmd0x346.ApplyUploadHitReqV3? = null, + @JvmField @ProtoNumber(101) val businessId: Int = 0, + @JvmField @ProtoNumber(102) val clientType: Int = 0, + @JvmField @ProtoNumber(90000) val msgApplyCopyToReq: Cmd0x346.ApplyCopyToReq? = null, + @JvmField @ProtoNumber(90001) val msgApplyCleanTrafficReq: Cmd0x346.ApplyCleanTrafficReq? = null, + @JvmField @ProtoNumber(90002) val msgApplyGetTrafficReq: Cmd0x346.ApplyGetTrafficReq? = null, + @JvmField @ProtoNumber(99999) val msgExtensionReq: Cmd0x346.ExtensionReq? = null + ) : ProtoBuf + + @Serializable + internal class RspBody( + @JvmField @ProtoNumber(1) val cmd: Int = 0, + @JvmField @ProtoNumber(2) val seq: Int = 0, + @JvmField @ProtoNumber(3) val msgRecvListQueryRsp: Cmd0x346.RecvListQueryRsp? = null, + @JvmField @ProtoNumber(4) val msgSendListQueryRsp: Cmd0x346.SendListQueryRsp? = null, + @JvmField @ProtoNumber(5) val msgRenewFileRsp: Cmd0x346.RenewFileRsp? = null, + @JvmField @ProtoNumber(6) val msgRecallFileRsp: Cmd0x346.RecallFileRsp? = null, + @JvmField @ProtoNumber(7) val msgApplyUploadRsp: Cmd0x346.ApplyUploadRsp? = null, + @JvmField @ProtoNumber(8) val msgApplyUploadHitRsp: Cmd0x346.ApplyUploadHitRsp? = null, + @JvmField @ProtoNumber(9) val msgApplyForwardFileRsp: Cmd0x346.ApplyForwardFileRsp? = null, + @JvmField @ProtoNumber(10) val msgUploadSuccRsp: Cmd0x346.UploadSuccRsp? = null, + @JvmField @ProtoNumber(11) val msgDeleteFileRsp: Cmd0x346.DeleteFileRsp? = null, + @JvmField @ProtoNumber(12) val msgDownloadSuccRsp: Cmd0x346.DownloadSuccRsp? = null, + @JvmField @ProtoNumber(13) val msgApplyDownloadAbsRsp: Cmd0x346.ApplyDownloadAbsRsp? = null, + @JvmField @ProtoNumber(14) val msgApplyDownloadRsp: Cmd0x346.ApplyDownloadRsp? = null, + @JvmField @ProtoNumber(15) val msgApplyListDownloadRsp: Cmd0x346.ApplyListDownloadRsp? = null, + @JvmField @ProtoNumber(16) val msgFileQueryRsp: Cmd0x346.FileQueryRsp? = null, + @JvmField @ProtoNumber(17) val msgApplyCopyFromRsp: Cmd0x346.ApplyCopyFromRsp? = null, + @JvmField @ProtoNumber(18) val msgApplyUploadRspV2: Cmd0x346.ApplyUploadRspV2? = null, + @JvmField @ProtoNumber(19) val msgApplyUploadRspV3: Cmd0x346.ApplyUploadRspV3? = null, + @JvmField @ProtoNumber(20) val msgApplyUploadHitRspV2: Cmd0x346.ApplyUploadHitRspV2? = null, + @JvmField @ProtoNumber(21) val msgApplyUploadHitRspV3: Cmd0x346.ApplyUploadHitRspV3? = null, + @JvmField @ProtoNumber(90000) val msgApplyCopyToRsp: Cmd0x346.ApplyCopyToRsp? = null, + @JvmField @ProtoNumber(90001) val msgApplyCleanTrafficRsp: Cmd0x346.ApplyCleanTrafficRsp? = null, + @JvmField @ProtoNumber(90002) val msgApplyGetTrafficRsp: Cmd0x346.ApplyGetTrafficRsp? = null, + @JvmField @ProtoNumber(99999) val msgExtensionRsp: Cmd0x346.ExtensionRsp? = null + ) : ProtoBuf + + @Serializable + internal class SendListQueryReq( + @JvmField @ProtoNumber(1) val uin: Long = 0L, + @JvmField @ProtoNumber(2) val beginIndex: Int = 0, + @JvmField @ProtoNumber(3) val reqCount: Int = 0 + ) : ProtoBuf + + @Serializable + internal class SendListQueryRsp( + @JvmField @ProtoNumber(1) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(2) val retMsg: String = "", + @JvmField @ProtoNumber(3) val fileTotCount: Int = 0, + @JvmField @ProtoNumber(4) val beginIndex: Int = 0, + @JvmField @ProtoNumber(5) val rspFileCount: Int = 0, + @JvmField @ProtoNumber(6) val isEnd: Int = 0, + @JvmField @ProtoNumber(7) val totLimit: Long = 0L, + @JvmField @ProtoNumber(8) val usedLimit: Long = 0L, + @JvmField @ProtoNumber(9) val msgFileList: List = emptyList() + ) : ProtoBuf + + @Serializable + internal class UploadSuccReq( + @JvmField @ProtoNumber(10) val senderUin: Long = 0L, + @JvmField @ProtoNumber(20) val recverUin: Long = 0L, + @JvmField @ProtoNumber(30) val uuid: ByteArray = EMPTY_BYTE_ARRAY + ) : ProtoBuf + + @Serializable + internal class UploadSuccRsp( + @JvmField @ProtoNumber(10) val int32RetCode: Int = 0, + @JvmField @ProtoNumber(20) val retMsg: String = "", + @JvmField @ProtoNumber(30) val msgFileInfo: Cmd0x346.FileInfo? = null + ) : ProtoBuf +} + \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt index 3eea3b67a..71323cf46 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt @@ -51,11 +51,8 @@ import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf -import net.mamoe.mirai.message.data.MessageSourceKind -import net.mamoe.mirai.message.data.MessageSourceKind.STRANGER -import net.mamoe.mirai.message.data.MessageSourceKind.TEMP -import net.mamoe.mirai.message.data.PlainText -import net.mamoe.mirai.message.data.buildMessageChain +import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.message.data.MessageSourceKind.* import net.mamoe.mirai.utils.cast import net.mamoe.mirai.utils.debug import net.mamoe.mirai.utils.read @@ -447,7 +444,11 @@ internal suspend fun MsgComm.Msg.transform(bot: QQAndroidBot, fromSync: Boolean } 208 -> { // friend ptt - return null + val target = bot.getFriend(msgHead.fromUin) + ?: return null + val lsc = listOf(this).toMessageChainOnline(bot, 0, FRIEND) + + return FriendMessageEvent(target, lsc, msgHead.msgTime) } 529 -> { diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbSendMsg.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbSendMsg.kt index 112081714..0f80ec9b4 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbSendMsg.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbSendMsg.kt @@ -145,6 +145,25 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory ImMsgBody.MsgBody( richText = ImMsgBody.RichText( - elems = it.toRichTextElems(messageTarget = targetFriend, withGeneralFlags = true) + elems = subChain.toRichTextElems(messageTarget = targetFriend, withGeneralFlags = true), + ptt = subChain[PttMessage]?.toPtt(), ) ) }, @@ -341,23 +361,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory