mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-05 05:14:43 +08:00
支持获取消息记录 (漫游消息) (#1520)
* Support roaming messages for friend * Remove `RoamingMessage.getMessage` * Remove `RoamingAuthenticator` * Mark `@JavaFriendlyAPI` * apiDump Co-authored-by: Karlatemp <karlatemp@vip.qq.com>
This commit is contained in:
parent
3b7e85f3c5
commit
ef301cc6e5
@ -331,7 +331,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/AudioSupported, net/mamoe/mirai/contact/User {
|
||||
public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/AudioSupported, net/mamoe/mirai/contact/User, net/mamoe/mirai/contact/roaming/RoamingSupported {
|
||||
public fun delete ()V
|
||||
public abstract fun delete (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun nudge ()Lnet/mamoe/mirai/message/action/FriendNudge;
|
||||
@ -748,6 +748,57 @@ public final class net/mamoe/mirai/contact/announcement/OnlineAnnouncementKt {
|
||||
public static final fun getBot (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;)Lnet/mamoe/mirai/Bot;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessage {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public abstract fun getContact ()Lnet/mamoe/mirai/contact/Contact;
|
||||
public abstract fun getIds ()[I
|
||||
public abstract fun getInternalIds ()[I
|
||||
public abstract fun getSender ()J
|
||||
public abstract fun getTarget ()J
|
||||
public abstract fun getTime ()J
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessageFilter {
|
||||
public static final field ANY Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public static final field Companion Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter$Companion;
|
||||
public static final field RECEIVED Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public static final field SENT Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public fun and (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public abstract fun invoke (Lnet/mamoe/mirai/contact/roaming/RoamingMessage;)Z
|
||||
public fun not ()Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public fun or (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/contact/roaming/RoamingMessageFilter$Companion {
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessages {
|
||||
public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow;
|
||||
public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
|
||||
public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getAllMessagesStream ()Ljava/util/stream/Stream;
|
||||
public fun getAllMessagesStream (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getAllMessagesStream (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Ljava/util/stream/Stream;
|
||||
public fun getAllMessagesStream (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Ljava/util/stream/Stream;
|
||||
public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow;
|
||||
public abstract fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getMessagesIn$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
|
||||
public static synthetic fun getMessagesIn$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getMessagesStream (JJ)Ljava/util/stream/Stream;
|
||||
public fun getMessagesStream (JJLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getMessagesStream (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Ljava/util/stream/Stream;
|
||||
public abstract fun getMessagesStream (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Ljava/util/stream/Stream;
|
||||
public static synthetic fun getMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingSupported : net/mamoe/mirai/contact/Contact {
|
||||
public abstract fun getRoamingMessages ()Lnet/mamoe/mirai/contact/roaming/RoamingMessages;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/data/FriendInfo : net/mamoe/mirai/data/UserInfo {
|
||||
public abstract fun getNick ()Ljava/lang/String;
|
||||
public abstract fun getRemark ()Ljava/lang/String;
|
||||
|
@ -331,7 +331,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/AudioSupported, net/mamoe/mirai/contact/User {
|
||||
public abstract interface class net/mamoe/mirai/contact/Friend : kotlinx/coroutines/CoroutineScope, net/mamoe/mirai/contact/AudioSupported, net/mamoe/mirai/contact/User, net/mamoe/mirai/contact/roaming/RoamingSupported {
|
||||
public fun delete ()V
|
||||
public abstract fun delete (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun nudge ()Lnet/mamoe/mirai/message/action/FriendNudge;
|
||||
@ -748,6 +748,57 @@ public final class net/mamoe/mirai/contact/announcement/OnlineAnnouncementKt {
|
||||
public static final fun getBot (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;)Lnet/mamoe/mirai/Bot;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessage {
|
||||
public fun getBot ()Lnet/mamoe/mirai/Bot;
|
||||
public abstract fun getContact ()Lnet/mamoe/mirai/contact/Contact;
|
||||
public abstract fun getIds ()[I
|
||||
public abstract fun getInternalIds ()[I
|
||||
public abstract fun getSender ()J
|
||||
public abstract fun getTarget ()J
|
||||
public abstract fun getTime ()J
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessageFilter {
|
||||
public static final field ANY Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public static final field Companion Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter$Companion;
|
||||
public static final field RECEIVED Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public static final field SENT Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public fun and (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public abstract fun invoke (Lnet/mamoe/mirai/contact/roaming/RoamingMessage;)Z
|
||||
public fun not ()Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
public fun or (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/contact/roaming/RoamingMessageFilter$Companion {
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessages {
|
||||
public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow;
|
||||
public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
|
||||
public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getAllMessagesStream ()Ljava/util/stream/Stream;
|
||||
public fun getAllMessagesStream (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getAllMessagesStream (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Ljava/util/stream/Stream;
|
||||
public fun getAllMessagesStream (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Ljava/util/stream/Stream;
|
||||
public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow;
|
||||
public abstract fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getMessagesIn$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
|
||||
public static synthetic fun getMessagesIn$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getMessagesStream (JJ)Ljava/util/stream/Stream;
|
||||
public fun getMessagesStream (JJLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getMessagesStream (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Ljava/util/stream/Stream;
|
||||
public abstract fun getMessagesStream (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun getMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Ljava/util/stream/Stream;
|
||||
public static synthetic fun getMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/contact/roaming/RoamingSupported : net/mamoe/mirai/contact/Contact {
|
||||
public abstract fun getRoamingMessages ()Lnet/mamoe/mirai/contact/roaming/RoamingMessages;
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/data/FriendInfo : net/mamoe/mirai/data/UserInfo {
|
||||
public abstract fun getNick ()Ljava/lang/String;
|
||||
public abstract fun getRemark ()Ljava/lang/String;
|
||||
|
@ -15,6 +15,7 @@ package net.mamoe.mirai.contact
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.roaming.RoamingSupported
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.action.FriendNudge
|
||||
@ -34,7 +35,7 @@ import net.mamoe.mirai.utils.NotStableForInheritance
|
||||
* @see FriendMessageEvent
|
||||
*/
|
||||
@NotStableForInheritance
|
||||
public interface Friend : User, CoroutineScope, AudioSupported {
|
||||
public interface Friend : User, CoroutineScope, AudioSupported, RoamingSupported {
|
||||
/**
|
||||
* 向这个对象发送消息.
|
||||
*
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.contact.roaming
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
|
||||
/**
|
||||
* @since 2.8
|
||||
*/
|
||||
public fun interface RoamingMessageFilter {
|
||||
public operator fun invoke(roamingMessage: RoamingMessage): Boolean
|
||||
|
||||
|
||||
public infix fun and(other: RoamingMessageFilter): RoamingMessageFilter {
|
||||
return RoamingMessageFilter { this.invoke(it) && other.invoke(it) }
|
||||
}
|
||||
|
||||
public infix fun or(other: RoamingMessageFilter): RoamingMessageFilter {
|
||||
return RoamingMessageFilter { this.invoke(it) || other.invoke(it) }
|
||||
}
|
||||
|
||||
public fun not(): RoamingMessageFilter {
|
||||
return RoamingMessageFilter { !this.invoke(it) }
|
||||
}
|
||||
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* 筛选任何消息 (相当于不筛选)
|
||||
*/
|
||||
@JvmField
|
||||
public val ANY: RoamingMessageFilter = RoamingMessageFilter { true }
|
||||
|
||||
/**
|
||||
* 筛选 bot 接收的消息
|
||||
*/
|
||||
@JvmField
|
||||
public val RECEIVED: RoamingMessageFilter = RoamingMessageFilter { it.sender != it.bot.id }
|
||||
|
||||
/**
|
||||
* 筛选 bot 发送的消息
|
||||
*/
|
||||
@JvmField
|
||||
public val SENT: RoamingMessageFilter = RoamingMessageFilter { it.sender == it.bot.id }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 还未解析的漫游消息.
|
||||
*
|
||||
* @since 2.8
|
||||
*/
|
||||
public interface RoamingMessage {
|
||||
public val contact: Contact
|
||||
public val bot: Bot get() = contact.bot
|
||||
|
||||
/**
|
||||
* 发送人 id
|
||||
*/
|
||||
public val sender: Long
|
||||
|
||||
/**
|
||||
* 收信人或群的 id
|
||||
*/
|
||||
public val target: Long
|
||||
|
||||
/**
|
||||
* 时间戳, 单位为秒, 服务器时间.
|
||||
*/
|
||||
public val time: Long
|
||||
|
||||
/**
|
||||
* @see MessageSource.ids
|
||||
*/
|
||||
public val ids: IntArray
|
||||
|
||||
/**
|
||||
* @see MessageSource.internalIds
|
||||
*/
|
||||
public val internalIds: IntArray
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:JvmBlockingBridge
|
||||
|
||||
package net.mamoe.mirai.contact.roaming
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.utils.JavaFriendlyAPI
|
||||
import java.util.stream.Stream
|
||||
|
||||
/**
|
||||
* 漫游消息记录管理器.
|
||||
*
|
||||
* @since 2.8
|
||||
* @see RoamingSupported
|
||||
*/
|
||||
public interface RoamingMessages {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get list
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 查询指定时间段内的漫游消息记录.
|
||||
*
|
||||
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
|
||||
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
|
||||
*
|
||||
* 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响.
|
||||
*
|
||||
* @param timeStart 起始时间, UTC+8 时间戳, 单位为秒. 可以为 `0`, 即表示从可以获取的最早的消息起. 负数将会被看是 `0`.
|
||||
* @param timeEnd 结束时间, UTC+8 时间戳, 单位为秒. 可以为 [Long.MAX_VALUE], 即表示到可以获取的最晚的消息为止. 低于 [timeStart] 的值将会被看作是 [timeStart] 的值.
|
||||
* @param filter 过滤器.
|
||||
*/
|
||||
public suspend fun getMessagesIn(
|
||||
timeStart: Long,
|
||||
timeEnd: Long,
|
||||
filter: RoamingMessageFilter? = null
|
||||
): Flow<MessageChain>
|
||||
|
||||
/**
|
||||
* 查询所有漫游消息记录.
|
||||
*
|
||||
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
|
||||
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
|
||||
*
|
||||
* 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响.
|
||||
*
|
||||
* @param filter 过滤器.
|
||||
*/
|
||||
public suspend fun getAllMessages(
|
||||
filter: RoamingMessageFilter? = null
|
||||
): Flow<MessageChain> = getMessagesIn(0, Long.MAX_VALUE, filter)
|
||||
|
||||
/**
|
||||
* 查询指定时间段内的漫游消息记录.
|
||||
*
|
||||
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
|
||||
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
|
||||
*
|
||||
* 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响.
|
||||
*
|
||||
* @param timeStart 起始时间, UTC+8 时间戳, 单位为秒. 可以为 `0`, 即表示从可以获取的最早的消息起. 负数将会被看是 `0`.
|
||||
* @param timeEnd 结束时间, UTC+8 时间戳, 单位为秒. 可以为 [Long.MAX_VALUE], 即表示到可以获取的最晚的消息为止. 低于 [timeStart] 的值将会被看作是 [timeStart] 的值.
|
||||
* @param filter 过滤器.
|
||||
*/
|
||||
@Suppress("OVERLOADS_INTERFACE")
|
||||
@JvmOverloads
|
||||
@JavaFriendlyAPI
|
||||
public suspend fun getMessagesStream(
|
||||
timeStart: Long,
|
||||
timeEnd: Long,
|
||||
filter: RoamingMessageFilter? = null
|
||||
): Stream<MessageChain>
|
||||
|
||||
/**
|
||||
* 查询所有漫游消息记录.
|
||||
*
|
||||
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
|
||||
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
|
||||
*
|
||||
* 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响.
|
||||
*
|
||||
* @param filter 过滤器.
|
||||
*/
|
||||
@Suppress("OVERLOADS_INTERFACE")
|
||||
@JvmOverloads
|
||||
@JavaFriendlyAPI
|
||||
public suspend fun getAllMessagesStream(
|
||||
filter: RoamingMessageFilter? = null
|
||||
): Stream<MessageChain> = getMessagesStream(0, Long.MAX_VALUE, filter)
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:JvmBlockingBridge
|
||||
|
||||
package net.mamoe.mirai.contact.roaming
|
||||
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
|
||||
/**
|
||||
* 支持查询漫游消息记录的 [Contact].
|
||||
* @since 2.8
|
||||
*/
|
||||
public interface RoamingSupported : Contact {
|
||||
/**
|
||||
* 获取漫游消息记录管理器.
|
||||
*/
|
||||
public val roamingMessages: RoamingMessages
|
||||
}
|
@ -17,10 +17,12 @@ package net.mamoe.mirai.internal.contact
|
||||
import net.mamoe.mirai.LowLevelApi
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessages
|
||||
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.contact.roaming.RoamingMessagesImplFriend
|
||||
import net.mamoe.mirai.internal.message.OfflineAudioImpl
|
||||
import net.mamoe.mirai.internal.network.highway.*
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Cmd0x346
|
||||
@ -61,8 +63,8 @@ internal class FriendImpl(
|
||||
override val info: FriendInfoImpl,
|
||||
) : Friend, AbstractUser(bot, parentCoroutineContext, info) {
|
||||
override suspend fun delete() {
|
||||
check(bot.friends[this.id] != null) {
|
||||
"Friend ${this.id} had already been deleted"
|
||||
check(bot.friends[id] != null) {
|
||||
"Friend $id had already been deleted"
|
||||
}
|
||||
bot.network.run {
|
||||
FriendList.DelFriend.invoke(bot.client, this@FriendImpl).sendAndExpect().also {
|
||||
@ -145,4 +147,6 @@ internal class FriendImpl(
|
||||
|
||||
return audio!!
|
||||
}
|
||||
|
||||
override val roamingMessages: RoamingMessages by lazy { RoamingMessagesImplFriend(this) }
|
||||
}
|
||||
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.internal.contact.roaming
|
||||
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessage
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessageFilter
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessages
|
||||
import net.mamoe.mirai.internal.contact.AbstractContact
|
||||
import net.mamoe.mirai.internal.contact.FriendImpl
|
||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetRoamMsgReq
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.util.stream.Stream
|
||||
|
||||
internal sealed class RoamingMessagesImpl : RoamingMessages {
|
||||
abstract val contact: AbstractContact
|
||||
|
||||
override suspend fun getMessagesIn(
|
||||
timeStart: Long,
|
||||
timeEnd: Long,
|
||||
filter: RoamingMessageFilter?
|
||||
): Flow<MessageChain> {
|
||||
return flow {
|
||||
var lastMessageTime = timeEnd.coerceAtLeast(timeStart).coerceAtLeast(1)
|
||||
var random = 0L
|
||||
while (currentCoroutineContext().isActive) {
|
||||
val resp = requestRoamMsg(timeStart, lastMessageTime, random)
|
||||
val messages = resp.messages ?: break
|
||||
if (filter == null || filter === RoamingMessageFilter.ANY) {
|
||||
// fast path
|
||||
messages.forEach { emit(it.toMessageChainOnline(contact.bot)) }
|
||||
} else {
|
||||
for (message in messages) {
|
||||
if (filter.invoke(createRoamingMessage(message, messages))) {
|
||||
emit(message.toMessageChainOnline(contact.bot))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastMessageTime = resp.lastMessageTime
|
||||
random = resp.random
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createRoamingMessage(
|
||||
message: MsgComm.Msg,
|
||||
messages: List<MsgComm.Msg>
|
||||
) = object : RoamingMessage {
|
||||
override val contact: Contact get() = this@RoamingMessagesImpl.contact
|
||||
override val sender: Long get() = message.msgHead.fromUin
|
||||
override val target: Long
|
||||
get() = message.msgHead.groupInfo?.groupCode ?: message.msgHead.toUin
|
||||
override val time: Long get() = message.msgHead.msgTime.toLongUnsigned()
|
||||
override val ids: IntArray by lazy { messages.mapToIntArray { it.msgHead.msgSeq } }
|
||||
override val internalIds: IntArray by lazy {
|
||||
messages.mapToIntArray { it.msgBody.richText.attr?.random ?: 0 } // other client 消息的这个是0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JavaFriendlyAPI
|
||||
override suspend fun getMessagesStream(
|
||||
timeStart: Long,
|
||||
timeEnd: Long,
|
||||
filter: RoamingMessageFilter?,
|
||||
): Stream<MessageChain> {
|
||||
return stream {
|
||||
var lastMessageTime = timeEnd
|
||||
var random = 0L
|
||||
while (true) {
|
||||
val resp = runBlocking {
|
||||
requestRoamMsg(timeStart, lastMessageTime, random)
|
||||
}
|
||||
|
||||
val messages = resp.messages ?: break
|
||||
if (filter == null || filter === RoamingMessageFilter.ANY) {
|
||||
messages.forEach { yield(runBlocking { it.toMessageChainOnline(contact.bot) }) }
|
||||
} else {
|
||||
for (message in messages) {
|
||||
if (filter.invoke(createRoamingMessage(message, messages))) {
|
||||
yield(runBlocking { message.toMessageChainOnline(contact.bot) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastMessageTime = resp.lastMessageTime
|
||||
random = resp.random
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract suspend fun requestRoamMsg(
|
||||
timeStart: Long,
|
||||
lastMessageTime: Long,
|
||||
random: Long
|
||||
): MessageSvcPbGetRoamMsgReq.Response
|
||||
}
|
||||
|
||||
internal class RoamingMessagesImplFriend(
|
||||
override val contact: FriendImpl
|
||||
) : RoamingMessagesImpl() {
|
||||
override suspend fun requestRoamMsg(
|
||||
timeStart: Long,
|
||||
lastMessageTime: Long,
|
||||
random: Long
|
||||
): MessageSvcPbGetRoamMsgReq.Response {
|
||||
return MessageSvcPbGetRoamMsgReq.createForFriend(
|
||||
client = contact.bot.client,
|
||||
uin = contact.id,
|
||||
timeStart = timeStart,
|
||||
lastMsgTime = lastMessageTime,
|
||||
random = random,
|
||||
maxCount = 1000,
|
||||
sig = byteArrayOf(),
|
||||
pwd = byteArrayOf()
|
||||
).sendAndExpect(contact.bot).value.check()
|
||||
}
|
||||
}
|
@ -50,6 +50,27 @@ internal suspend fun List<MsgComm.Msg>.toMessageChainOnline(
|
||||
return toMessageChain(bot, groupIdOrZero, true, messageSourceKind).refineDeep(bot, refineContext)
|
||||
}
|
||||
|
||||
internal suspend fun MsgComm.Msg.toMessageChainOnline(
|
||||
bot: Bot,
|
||||
refineContext: RefineContext = EmptyRefineContext,
|
||||
): MessageChain {
|
||||
fun getSourceKind(c2cCmd: Int): MessageSourceKind {
|
||||
return when (c2cCmd) {
|
||||
11 -> MessageSourceKind.FRIEND // bot 给其他人发消息
|
||||
4 -> MessageSourceKind.FRIEND // bot 给自己作为好友发消息 (非 other client)
|
||||
1 -> MessageSourceKind.GROUP
|
||||
else -> error("Could not get source kind from c2cCmd: $c2cCmd")
|
||||
}
|
||||
}
|
||||
|
||||
val kind = getSourceKind(msgHead.c2cCmd)
|
||||
val groupId = when (kind) {
|
||||
MessageSourceKind.GROUP -> msgHead.groupInfo?.groupCode ?: 0
|
||||
else -> 0
|
||||
}
|
||||
return listOf(this).toMessageChainOnline(bot, groupId, kind, refineContext)
|
||||
}
|
||||
|
||||
//internal fun List<MsgComm.Msg>.toMessageChainOffline(
|
||||
// bot: Bot,
|
||||
// groupIdOrZero: Long,
|
||||
|
@ -135,6 +135,7 @@ internal object KnownPacketFactories {
|
||||
MessageSvcPushForceOffline,
|
||||
MessageSvcPbSendMsg,
|
||||
MessageSvcPbDeleteMsg,
|
||||
MessageSvcPbGetRoamMsgReq,
|
||||
FriendList.GetFriendGroupList,
|
||||
FriendList.DelFriend,
|
||||
FriendList.GetTroopListSimplify,
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.QQAndroidClient
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgSvc
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
||||
import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.utils.Either
|
||||
import net.mamoe.mirai.utils.Either.Companion.mapRight
|
||||
import net.mamoe.mirai.utils.FailureResponse
|
||||
import net.mamoe.mirai.utils.checked
|
||||
|
||||
internal class CheckedResponse<T>(
|
||||
val value: Either<FailureResponse, T>
|
||||
) : Packet
|
||||
|
||||
internal object MessageSvcPbGetRoamMsgReq :
|
||||
OutgoingPacketFactory<CheckedResponse<MessageSvcPbGetRoamMsgReq.Response>>("MessageSvc.PbGetRoamMsg") {
|
||||
|
||||
class Response(
|
||||
val messages: List<MsgComm.Msg>?,
|
||||
val lastMessageTime: Long,
|
||||
val random: Long,
|
||||
val sig: ByteArray, // 似乎没被用到, 服务器每次返回不同
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
fun createForFriend(
|
||||
client: QQAndroidClient,
|
||||
uin: Long,
|
||||
timeStart: Long,
|
||||
lastMsgTime: Long, // 上次 resp 中的, 否则为期待的 time end
|
||||
random: Long = 0,
|
||||
maxCount: Int = 1000,
|
||||
sig: ByteArray = EMPTY_BYTE_ARRAY, // 客户端每次请求相同
|
||||
pwd: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
) = buildOutgoingUniPacket(client) {
|
||||
writeProtoBuf(
|
||||
MsgSvc.PbGetRoamMsgReq.serializer(), MsgSvc.PbGetRoamMsgReq(
|
||||
peerUin = uin,
|
||||
beginMsgtime = timeStart,
|
||||
lastMsgtime = lastMsgTime,
|
||||
checkPwd = 1, // always
|
||||
readCnt = maxCount,
|
||||
subcmd = 1,
|
||||
reqType = 1,
|
||||
sig = sig,
|
||||
pwd = pwd,
|
||||
random = random,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): CheckedResponse<Response> {
|
||||
val resp = readProtoBuf(MsgSvc.PbGetRoamMsgResp.serializer())
|
||||
if (resp.result == 1) return CheckedResponse(
|
||||
Either.right(
|
||||
Response(
|
||||
null,
|
||||
resp.lastMsgtime,
|
||||
resp.random,
|
||||
resp.sig,
|
||||
)
|
||||
)
|
||||
) // finished
|
||||
return CheckedResponse(resp.checked().mapRight {
|
||||
Response(
|
||||
messages = resp.msg.asReversed(),
|
||||
lastMessageTime = resp.lastMsgtime,
|
||||
random = resp.random,
|
||||
sig = resp.sig,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user