Skip to content

Commit

Permalink
receive file message via group_upload support
Browse files Browse the repository at this point in the history
not tested yet, #111
  • Loading branch information
MrXiaoM committed Dec 7, 2024
1 parent 2918649 commit 7d6c17e
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 25 deletions.
4 changes: 4 additions & 0 deletions onebot/src/main/kotlin/client/config/BotConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class BotConfig(
* 心跳包检测时间 (秒),设为0关闭检测
*/
val heartbeatCheckSeconds: Int = 60,
/**
* 是否不接收群聊的 file 消息,使用 group_upload 事件作为群文件消息
*/
val useGroupUploadEventForFileMessage: Boolean = false,
val parentJob: Job? = null
) {
val isInReverseMode get() = reversedPort in 1..65535
Expand Down
2 changes: 2 additions & 0 deletions onebot/src/main/kotlin/sdk/entity/File.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ class File {
var size = 0L
@SerializedName("busid")
var busId = 0L
@SerializedName("url")
var url = ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class BotBuilder private constructor(
private var printInfo: Boolean = true,
private var noPlatform: Boolean = false,
private var useCQCode: Boolean = false,
private var useGroupUploadEventForFileMessage: Boolean = false,
private var logger: Logger? = null,
private var parentJob: Job? = null,
private var configuration: BotConfiguration = BotConfiguration {
Expand Down Expand Up @@ -72,6 +73,15 @@ public class BotBuilder private constructor(
this.retryRestMills = retryRestMills
}

/**
* 设置 WebSocket 心跳检查时间
*
* 设为 0 关闭心跳检查
*/
public fun heartbeatCheckSeconds(heartbeatCheckSeconds: Int): BotBuilder = apply {
this.heartbeatCheckSeconds = heartbeatCheckSeconds
}

/**
* 禁止打印连接时额外状态信息
*
Expand Down Expand Up @@ -103,6 +113,13 @@ public class BotBuilder private constructor(
this.useCQCode = true
}

/**
* 设置不接收群聊的 file 消息,使用 group_upload 事件作为群文件消息
*/
public fun useGroupUploadEventForFileMessage(): BotBuilder = apply {
this.useGroupUploadEventForFileMessage = true;
}

/**
* 覆写用于 Onebot 的日志记录器
*/
Expand Down Expand Up @@ -160,6 +177,7 @@ public class BotBuilder private constructor(
printInfo = printInfo,
noPlatform = noPlatform,
useCQCode = useCQCode,
useGroupUploadEventForFileMessage = useGroupUploadEventForFileMessage,
logger = logger,
parentJob = parentJob,
configuration = configuration,
Expand Down Expand Up @@ -197,6 +215,7 @@ interface IBotStarter {
printInfo: Boolean,
noPlatform: Boolean,
useCQCode: Boolean,
useGroupUploadEventForFileMessage: Boolean,
logger: Logger?,
parentJob: Job?,
configuration: BotConfiguration,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package top.mrxiaom.overflow.message.data

import net.mamoe.mirai.message.data.FileMessage

/**
* 带链接的文件消息
*
* 注意,这个消息类型提供的文件链接并不可靠,可能为空字符串。
*
* 基本上,仅在开启 use_group_upload_event_for_file_message 的情况下,从消息收到文件消息时可提供链接。
*/
interface FileMessageWithUrl : FileMessage {
val url: String
}

val FileMessage.withUrl: FileMessageWithUrl
get() = this as FileMessageWithUrl
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ data class Config(
var retryRestMills: Long = 60_000L,
@SerialName("heartbeat_check_seconds")
var heartbeatCheckSeconds: Int = 60,
@SerialName("use_group_upload_event_for_file_message")
var useGroupUploadEventForFileMessage: Boolean = false,
)
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ class Overflow : IMirai, CoroutineScope, LowLevelApiAccessor, OverflowAPI {
retryWaitMills = config.retryWaitMills,
retryRestMills = config.retryRestMills,
heartbeatCheckSeconds = config.heartbeatCheckSeconds,
useGroupUploadEventForFileMessage = config.useGroupUploadEventForFileMessage,
parentJob = job ?: defaultJob,
),
printInfo = printInfo,
Expand Down Expand Up @@ -295,6 +296,7 @@ class Overflow : IMirai, CoroutineScope, LowLevelApiAccessor, OverflowAPI {
printInfo: Boolean,
noPlatform: Boolean,
useCQCode: Boolean,
useGroupUploadEventForFileMessage: Boolean,
logger: Logger?,
parentJob: Job?,
configuration: BotConfiguration,
Expand All @@ -307,6 +309,7 @@ class Overflow : IMirai, CoroutineScope, LowLevelApiAccessor, OverflowAPI {
isAccessToken = token.isNotBlank(),
noPlatform = noPlatform,
useCQCode = useCQCode,
useGroupUploadEventForFileMessage = useGroupUploadEventForFileMessage,
retryTimes = retryTimes,
retryWaitMills = retryWaitMills,
retryRestMills = retryRestMills,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal class GroupWrapper(
get() = gson.toJson(implJson)
private var membersInternal: ContactList<MemberWrapper>? = null
private var anonymousInternal: HashMap<String, AnonymousMemberWrapper> = hashMapOf()
internal val emptyMessagesIdMap: HashMap<Long, Int> = hashMapOf()

val data: GroupInfoResp
get() = impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ import cn.evolvefield.onebot.client.handler.EventBus
import cn.evolvefield.onebot.client.listener.EventListener
import cn.evolvefield.onebot.sdk.util.jsonObject
import com.google.gson.JsonObject
import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.contact.nameCardOrNick
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.message.data.FileMessage
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.buildMessageChain
import net.mamoe.mirai.utils.MiraiInternalApi
import top.mrxiaom.overflow.event.MemberEssenceNoticeEvent
import top.mrxiaom.overflow.internal.Overflow
import top.mrxiaom.overflow.internal.contact.BotWrapper
import top.mrxiaom.overflow.internal.message.OnebotMessages.toMiraiMessage
import top.mrxiaom.overflow.internal.message.data.IncomingSource
import top.mrxiaom.overflow.internal.message.data.WrappedFileMessage
import top.mrxiaom.overflow.internal.utils.bot
import top.mrxiaom.overflow.internal.utils.group
import top.mrxiaom.overflow.internal.utils.queryProfile
Expand All @@ -32,7 +38,9 @@ internal fun addGroupListeners() {
GroupAdminNoticeListener(),
GroupEssenceNoticeListener(),
GroupCardChangeNoticeListener(),
GroupNameChangeListener()
GroupNameChangeListener(),
GroupUploadNoticeListener(),

).forEach(EventBus::addListener)
}

Expand All @@ -49,35 +57,22 @@ internal class GroupMessageListener : EventListener<GroupMessageEvent> {
val member = e.sender?.wrapAsMember(group, json ?: JsonObject()) ?: return

val message = e.toMiraiMessage(bot)
val messageString = message.toString()
val messageSource = IncomingSource.group(
bot = bot,
ids = intArrayOf(e.messageId),
internalIds = intArrayOf(e.messageId),
isOriginalMessageInitialized = true,
originalMessage = message,
sender = member,
time = (e.time / 1000).toInt()
)
val miraiMessage = messageSource.plus(message)
if (member.id == bot.id) {
bot.logger.verbose("[SYNC] [${group.name}(${group.id})] <- $messageString")
@Suppress("DEPRECATION") // TODO: 无法获取到哪个客户端发送的消息
bot.eventDispatcher.broadcastAsync(GroupMessageSyncEvent(
group, miraiMessage, member, member.nameCardOrNick, messageSource.time
))
} else {
bot.logger.verbose("[${group.name}(${group.id})] ${member.nameCardOrNick}(${member.id}) -> $messageString")
bot.eventDispatcher.broadcastAsync(GroupMessageEvent(
member.nameCardOrNick, member.permission, member, miraiMessage, messageSource.time
))
// 使用 group_upload 事件接收群文件时,忽略接收群文件类型消息
if (bot.impl.config.useGroupUploadEventForFileMessage && (message.isEmpty() || message.any { it is FileMessage })) {
group.emptyMessagesIdMap.put(member.id, e.messageId)
return
}
receiveGroupMessage(bot, member, message, e.messageId, e.time)
}
"anonymous" -> {
val group = bot.group(e.groupId)
val member = e.anonymous?.wrapAsMember(group) ?: return

val message = e.toMiraiMessage(bot)
// 匿名成员不会发文件
if (bot.impl.config.useGroupUploadEventForFileMessage && (message.isEmpty() || message.any { it is FileMessage })) {
return
}
val messageString = message.toString()
val messageSource = IncomingSource.group(
bot = bot,
Expand All @@ -101,6 +96,36 @@ internal class GroupMessageListener : EventListener<GroupMessageEvent> {
}
}
}

companion object {
internal fun receiveGroupMessage(bot: BotWrapper, member: NormalMember, message: MessageChain, messageId: Int, time: Long) {
val group = member.group
val messageString = message.toString()
val messageSource = IncomingSource.group(
bot = bot,
ids = intArrayOf(messageId),
internalIds = intArrayOf(messageId),
isOriginalMessageInitialized = true,
originalMessage = message,
sender = member,
time = (time / 1000).toInt()
)
val miraiMessage = messageSource.plus(message)
if (member.id == bot.id) {
bot.logger.verbose("[SYNC] [${group.name}(${group.id})] <- $messageString")
@Suppress("DEPRECATION") // TODO: 无法获取到哪个客户端发送的消息
bot.eventDispatcher.broadcastAsync(GroupMessageSyncEvent(
group, miraiMessage, member, member.nameCardOrNick, messageSource.time
))
} else {
bot.logger.verbose("[${group.name}(${group.id})] ${member.nameCardOrNick}(${member.id}) -> $messageString")
bot.eventDispatcher.broadcastAsync(GroupMessageEvent(
member.nameCardOrNick, member.permission, member, miraiMessage, messageSource.time
))
}
}

}
}

internal class GroupMessageRecallListener : EventListener<GroupMsgDeleteNoticeEvent> {
Expand Down Expand Up @@ -385,3 +410,27 @@ internal class GroupNameChangeListener : EventListener<GroupNameChangeNoticeEven
))
}
}
internal class GroupUploadNoticeListener : EventListener<GroupUploadNoticeEvent> {
override suspend fun onMessage(e: GroupUploadNoticeEvent) {
val bot = e.bot ?: return
val file = e.file ?: return
if (bot.checkId(e.groupId) {
"%onebot 返回了异常的数值 group_id=%value"
}) return
val group = bot.group(e.groupId)
val member = group.queryMember(e.userId)
if (member == null) {
bot.logger.warning("群文件上传事件找不到群员 ${e.groupId}:${e.userId}")
return
}
val messageId = group.emptyMessagesIdMap.remove(member.id)
if (messageId == null) {
bot.logger.warning("群文件上传事件找不到前置消息ID (来自群员 ${e.userId})")
return
}
val message = buildMessageChain {
add(WrappedFileMessage(file.id, file.busId.toInt(), file.name, file.size, file.url))
}
GroupMessageListener.receiveGroupMessage(bot, member, message, messageId, e.time)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import kotlinx.serialization.Serializable
import net.mamoe.mirai.contact.FileSupported
import net.mamoe.mirai.contact.file.AbsoluteFile
import net.mamoe.mirai.message.data.FileMessage
import top.mrxiaom.overflow.message.data.FileMessageWithUrl

@Serializable
internal data class WrappedFileMessage(
override val id: String,
override val internalId: Int,
override val name: String,
override val size: Long,
val url: String = ""
) : FileMessage {
override val url: String = ""
) : FileMessageWithUrl {
override suspend fun toAbsoluteFile(contact: FileSupported): AbsoluteFile? {
return contact.files.root.resolveFileById(id, true)
}
Expand Down

0 comments on commit 7d6c17e

Please sign in to comment.