simple-robot / simpler-robot

Simple Robot,一个bot风格的Kotlin多平台事件调度框架,异步高效、Java友好!/ A Bot-style Kotlin Multiplatform event scheduling framework, asynchronous and high-performance, java-friendly! 🐱😼😻😸
https://simbot.forte.love
GNU Lesser General Public License v3.0
521 stars 43 forks source link

3.0中,转发消息是否有对应的message类型或可以使用3.0的message构建的方式 #401

Closed 112292454 closed 2 years ago

112292454 commented 2 years ago

版本号

v3.0

疑问描述

我看了issue#169里面您说明的,使用mirai的MiraiMessageContentBuilder构建forwardMessage来实现转发消息的方式。 但是现在我将消息整个使用3.0的messages来发送,而mirai的组件似乎自然地,并不支持直接使用messages或者element来构建;之后我去

https://simple-robot-library.github.io/simbot3-main-apiDoc/v3.0.0.preview.20.0/simbot-apis/simbot-api/love.forte.simbot.message/index.html

https://simbot.forte.love/docs/defition/

看了说明文档,也没有在里面发现类似转发消息的类。 是否我在这过程中忽略了什么地方;或者有什么比较方便的,由新的message转换到最开始那个构建转发的办法?

ForteScarlet commented 2 years ago

如果希望在simbot3中发送转发消息,以一个群消息事件为例:

    @Listener
    public void onGroupMessageEvent(MiraiGroupMessageEvent event) {
        // 得到此事件的所在群,并得到这个群原生的mirai contact对象。
        // 其他Mirai组件特供的对象也都有类似的功能,例如 MiraiMember.getOriginalContact
        // 可以通过此方式来得到mirai原生的对象类型。
        final Group groupContact = event.getGroup().getOriginalContact();

        // 事件也是一样的。你可以在simbot所包装的Mirai事件中直接得到mirai原生事件。
        // 这里的 GroupMessageEvent是mirai的事件类型,而不是simbot的。
        final GroupMessageEvent originalEvent = event.getOriginalEvent();

        // 同理,消息也是。除了部分simbot标准消息类型以外(例如simbot中的At、Text),
        // 所有由mirai组件特殊实现的消息类型都会实现 MiraiSimbotMessage 接口。
        // 所有从接收的事件中得到的、由mirai组件特殊实现的消息类型都会实现 OriginalMiraiComputableSimbotMessage 接口。

        // 但是,如果你更希望直接操作原本的mirai消息链,则可能会更加方便。上文中我们已经得到了mirai的原生消息类型,
        // 因此你可以直接得到此事件的最原始的消息链。

        // mirai原生的消息链对象
        final MessageChain messageChain = originalEvent.getMessage();

        final ForwardMessageBuilder builder = new ForwardMessageBuilder(groupContact);
        // 转发当前这条消息。
        // 使用一开始说到的方式,得到当前消息事件的发送者,然后把消息链放进去。
        builder.add(event.getAuthor().getOriginalContact(), messageChain);

        // 构建转发消息
        final ForwardMessage forwardMessage = builder.build();

        // 发送消息
        // 两种方式。第一种,通过simbot的 send/sendBlocking 发送。将ForwardMessage转化为simbot的消息对象即可。
        // 第二种,你上面得到了mirai原生的群对象,那么你可以直接通过mirai本身的api发送。
        // 这里以第一种为例。
        event.sendBlocking(MiraiMessageParserUtil.asSimbotMessage(forwardMessage));
    }

其中需要注意的地方:

112292454 commented 2 years ago

好家伙九点 这效率 太强了 看了您的代码和这里面一些类具体的关系 我理解是 现在3.0消息类型(Text这种simbot.message下的)还没有实现转发消息,因此只能用mirai的api。这其中simbot提供了一个过渡对接的封装,比如MiraiGroupMessageEvent;而上面与之前那个issue的转发方式相仿,在getOriginalxxxx()之后就整个是使用mirai的内容来构建消息,最后再转换成simbot的消息对象或者直接发送 这样子吗? 我目前想实现的功能类似于一个比较通用的public Messages buileForwardMsgByList (ArrayList<Messages> messagesList)(参考上面的代码似乎还需要传入一个event来得到contact才能构建?),通过已有的数个messages得到转发消息(为了避免刷屏)。 如果是上面的情况,想法就是解析传入的Messages,然后用mirai的api来重新构建消息内容、再构建成转发形式、返回。发现这第一步的功能MiraiMessageParserUtil.toOriginalMiraiMessage()看名字似乎已经实现了;但它最后一个参数的Continuation不是很理解是什么,怎么得到;contact生搬硬套用前面的不知道是否可行

ForteScarlet commented 2 years ago

发现这第一步的功能MiraiMessageParserUtil.toOriginalMiraiMessage()看名字似乎已经实现了;但它最后一个参数的Continuation不是很理解是什么,怎么得到;

toOriginalMiraiMessage 实际上应当是一个不应暴露给Java的Kotlin API。

如果希望合并多个消息 ,参考:

@Listener
public void onGroupMessageEvent(MiraiGroupMessageEvent event) {
        // 得到此事件的所在群,并得到这个群原生的mirai contact对象。
        // 其他Mirai组件特供的对象也都有类似的功能,例如 MiraiMember.getOriginalContact
        // 可以通过此方式来得到mirai原生的对象类型。
        final Group groupContact = event.getGroup().getOriginalContact();

        // 准备转发消息
        final ForwardMessageBuilder builder = new ForwardMessageBuilder(groupContact);

        // 假设这里有多个消息。
        // 在构建转发消息的过程中,对于一个完整的消息,使用 MessageContent 会更简单。
        // 如果执意要使用Messages而不是MessageContent,那么你需要再遍历Messages中的每一个消息元素,并分别单独的判断并处理。
        List<MessageContent> messageContentList = new ArrayList<>();

        //
        for (MessageContent messageContent : messageContentList) {
            // 如果 messageContent 来自于mirai组件事件,那么他就会是 MiraiReceivedMessageContent 类型。
            if (messageContent instanceof MiraiReceivedMessageContent) {
                // 得到原始的消息链
                final MessageChain originalMessageChain = ((MiraiReceivedMessageContent) messageContent).getOriginalMessageChain();

                // 拼接到转发消息中
                // 这里假设转发消息中的'发送人'都是当前事件的人。
                final Member originalAuthor = event.getAuthor().getOriginalContact();
                builder.add(originalAuthor, originalMessageChain);
            }
        }

        // 构建转发消息
        final ForwardMessage forwardMessage = builder.build();

        // 发送消息
        // 两种方式。第一种,通过simbot的 send/sendBlocking 发送。将ForwardMessage转化为simbot的消息对象即可。
        // 第二种,你上面得到了mirai原生的群对象,那么你可以直接通过mirai本身的api发送。
        // 第一种:
        event.sendBlocking(MiraiMessageParserUtil.asSimbotMessage(forwardMessage));
        // 第二种:
        // groupContact.sendMessage(forwardMessage);
    }

其他方面:可以追踪 https://github.com/simple-robot/simbot-component-mirai/issues/56 来关注对转发消息内容封装的进度、提供贡献或参与讨论。

ForliyScarlet commented 2 years ago

此issue已经在「等待反馈」状态下5日未应答。如果在「陈旧」状态下逾期2日将会被视为无效过期并关闭。

ForliyScarlet commented 2 years ago

此issue已经在「陈旧」状态下逾期2日未应答, 视为无效过期并关闭。