获取回复消息(QuoteReply)指向原文的实现思路
-
总所周知,腾讯服务器给你返回的 QuoteReply 的源消息并不是富文本消息,也就是说,图片会“退化”为
[图片]
等等。如果我们想做回复消息搜图之类的功能,这给我们带来了比较多的麻烦。但是,我们可以取到源消息的 MessageSource,只要你本地存了聊天记录,就能够通过 MessageSource 获取相应消息。按照这个思路,我们只要跟QQ客户端一样,把消息存到本地,需要时获取即可。
具体实现
本帖中将使用 Mirai Hibernate Plugin 插件储存聊天记录,演示获取回复消息原文的方法。
引用依赖
// build.gradle(.kts) repositories { mavenCentral() } dependencies { compileOnly("xyz.cssxsh.mirai:mirai-hibernate-plugin:依赖版本") } // hibernate 6 和 HikariCP 5 需要 jdk11 mirai { jvmTarget = JavaVersion.VERSION_11 }
//author("MrXiaoM") // 在主类插件信息处声明插件依赖关系 dependsOn("xyz.cssxsh.mirai.plugin.mirai-hibernate-plugin", false)
Kotlin
val QuoteReply.originalMessageFromLocal: MessageChain get() = MiraiHibernateRecorder[source].firstOrNull()?.toMessageChain() ?: source.originalMessage // 使用示例 @EventHandler fun GroupMessageEvent.listen() { // 检测回复消息 message[QuoteReply.Key]?.run { val original = originalMessageFromLocal // do sth. } }
Java
public static MessageChain getOriginalMessageFromLocal(QuoteReply quote) { Optional<MessageRecord> record = MiraiHibernateRecorder.INSTANCE.get(quote.getSource()).stream().findFirst(); return record.map(MessageRecord::toMessageChain).orElseGet(() -> quote.getSource().getOriginalMessage()); } // 使用示例 @EventHandler public void onGroupMessage(GroupMessageEvent event) { // 检测回复消息 QuoteReply quote = event.getMessage().get(QuoteReply.Key); if (quote != null) { MessageChain original = getOriginalMessageFromLocal(quote); // do sth. } }
-
-
您好,请教一下,我启动后MiraiHibernateRecorder.INSTANCE是null,然后我看readme里面说需要手动对 xyz.cssxsh.mirai.hibernate.factory 进行初始化,和对 MiraiHibernateRecorder 进行注册,但是我没找到factory,也不知道怎么初始化
-
@nannanness 但是 MiraiHibernateRecorder 是单例类,它的实例不可能为 null。
说的手动注册,是指需要在 EventChannel 注册它为 listenerHost -
你好,我注册了MiraiHibernateRecorder,但是调用的时候报错了,好像是实例化的问题,能帮忙看下吗
Exception in thread "DefaultDispatcher-worker-2" java.lang.RuntimeException: Exception while trying to handle coroutine exception
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:29)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:196)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlin.UninitializedPropertyAccessException: lateinit property factory has not been initialized
at xyz.cssxsh.mirai.hibernate.MiraiHibernateUtilsKt.getFactory(MiraiHibernateUtils.kt:74)
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder.merge(MiraiHibernateRecorder.kt:30)
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder.access$merge(MiraiHibernateRecorder.kt:28)
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder$record$11.invokeSuspend(MiraiHibernateRecorder.kt:152)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
... 5 more
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [net.mamoe.mirai.event.SimpleListenerHost$special$$inlined$CoroutineExceptionHandler$1@58551237, StandaloneCoroutine{Cancelling}@6e8d0dfb, Dispatchers.Default]
Caused by: java.lang.NoClassDefFoundError: jakarta/persistence/PersistenceException
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder.handleException(MiraiHibernateRecorder.kt:545)
at net.mamoe.mirai.event.SimpleListenerHost$special$$inlined$CoroutineExceptionHandler$1.handleException(CoroutineExceptionHandler.kt:111)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:25)
... 12 more
Caused by: java.lang.ClassNotFoundException: jakarta.persistence.PersistenceException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 15 more
Exception in thread "DefaultDispatcher-worker-7" java.lang.RuntimeException: Exception while trying to handle coroutine exception
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:29)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:196)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlin.UninitializedPropertyAccessException: lateinit property factory has not been initialized
at xyz.cssxsh.mirai.hibernate.MiraiHibernateUtilsKt.getFactory(MiraiHibernateUtils.kt:74)
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder.merge(MiraiHibernateRecorder.kt:30)
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder.access$merge(MiraiHibernateRecorder.kt:28)
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder$record$1.invokeSuspend(MiraiHibernateRecorder.kt:44)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
... 5 more
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [net.mamoe.mirai.event.SimpleListenerHost$special$$inlined$CoroutineExceptionHandler$1@58551237, StandaloneCoroutine{Cancelling}@2e304ce3, Dispatchers.Default]
Caused by: java.lang.NoClassDefFoundError: jakarta/persistence/PersistenceException
at xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder.handleException(MiraiHibernateRecorder.kt:545)
at net.mamoe.mirai.event.SimpleListenerHost$special$$inlined$CoroutineExceptionHandler$1.handleException(CoroutineExceptionHandler.kt:111)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:25)
... 12 more
Caused by: java.lang.ClassNotFoundException: jakarta.persistence.PersistenceException
... 15 more
2023-11-28 19:43:16.075 [SpringApplicationShutdownHook] INFO o.s.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default' -
Caused by: java.lang.ClassNotFoundException: jakarta.persistence.PersistenceException
明显运行时环境缺东西了
-
@MrXiaoM 在 获取回复消息(QuoteReplay)指向原文的实现思路 中说:
return record.map(MessageRecord::toMessageChain).orElseGet(() -> quote.getSource().getOriginalMessage());
测了多次,疑似发现 当原消息所含图片的
isEmoji=true
时,有这几种情况:-
用户A在PC端发送图片1,用户A在PC端引用回复图片1且触发bot指令,后台还是
[图片]
而不是富文本 -
用户A在PC端发送图片1,用户A在手机端引用回复图片1且触发bot指令,后台能获得富文本
-
另一用户B发送图片1(设备任意),用户A在PC端引用回复图片1且触发bot指令,后台能获得富文本
主要就是1.那个用户自己引用回复自己的图没法解析出来就挺不理解的……应该有八九成的复现率,剩下的例外概率自己也搞不清楚了……
Mirai Hibernate Plugin 那边还没有研究明白没去看实际聊天记录数据库里存的是什么样子 -