Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

regMessageTextDecorators 和 regMessageRender 目前不太灵活 || regMessageTextDecorators and regMessageRender are currently less flexible #127

Closed
kkqy opened this issue Jul 27, 2023 · 8 comments

Comments

@kkqy
Copy link

kkqy commented Jul 27, 2023

这两个函数和regMessageInterpreter不同,regMessageInterpreter是“附加”,
而regMessageTextDecorators 和 regMessageRender是“覆盖”,这就导致了一些可能冲突的问题。

我看内置的bbcode插件使用了regMessageTextDecorators 和 regMessageRender 这两个注册函数,覆盖了内置的url、image、card、mention、emoji、serialize的类型消息的生成和渲染,

我的插件想注册其它的消息类型,而我使用regMessageTextDecorators 就覆盖了bbcode的设置,
如果我的插件在bbcode之前加载,那bbcode就把我的MessageTextDecorators给覆盖了。
姑且认为我的插件,属于第三方插件,“大概率”是在bbcode之后加载,我先用getMessageTextDecorators获取原本的MessageTextDecorators,然后合并到我自己的MessageTextDecorators里,再调用regMessageTextDecorators。
也许问题解决了,
而regMessageRender的问题也一样,bbcode这个插件会解析消息然后使用BBCode这个组件来展示,
而我想解析我自己的消息类型,又要同时照顾bbcode也能正常解析,我也得像刚刚那样,regMessageRender之前先getMessageRender,然后再通过一些判断合并到自己的MessageRender,再调用regMessageRender。
伪代码如下:

const oldMessageRender = getMessageRender()
regMessageRender((message) => {
    if(isMyMessage(message)){
        return <MyComponent message={message} />;
    }
    return oldMessageRender(message)
});
const oldDecorators=getMessageTextDecorators()
regMessageTextDecorators(() => ({
    mymessage: () => {
       //自定义消息
    },
    ...oldDecorators
}));

这样的代码也太hack了。

是我用法不对吗?
我现在的需求就是要自定一个消息类型,比如一个菜单面板,对方收到消息以后可以直接点击这个菜单上的功能,然后后端做出相应反应。
我看了一下喵言喵语,这个插件用的是regMessageInterpreter来解析消息,需要用户手动点一下,而且不能自定义渲染的内容,只能做类似翻译的功能,不符合我的需求。
然后看了一下bbcode这个插件, regMessageTextDecorators 和 regMessageRender 应该就是我想要的东西,但就是有上面描述的”覆盖“问题,如果多个插件都用了这两个函数,就冲突竞争了。

理想的状态应该是,有个函数能够注册消息类型,然后绑定一个专用的解析函数。
例如:

  注册消息类型
regMessageType("my-menu",(content)=>{ return <MyMenuComponent  conent={content} />})
  发送消息,第一个参数是类型,第二个参数是内容
actions.sendMsg("my-menu",content)

这个每个插件就只需要关注自己定义的消息类型就可以了。

而目前tailchat的设计是,所有消息都是string,没有单独的type的标记,然后靠解析这个纯文本来渲染不同的消息类型,比如bbcode那种类HTML的文本,或者markdown这种。
这种设计遇到多个插件都想解析消息的时候,就会出现“竞争”问题。


These two functions are different from regMessageInterpreter, regMessageInterpreter is "additional",
And regMessageTextDecorators and regMessageRender are "overrides", which leads to some possible conflicts.

I see that the built-in bbcode plug-in uses the two registration functions regMessageTextDecorators and regMessageRender, covering the generation and rendering of built-in url, image, card, mention, emoji, and serialize type messages.

My plugin wants to register other message types, and I use regMessageTextDecorators to override the bbcode settings,
If my plugin is loaded before bbcode, then bbcode overrides my MessageTextDecorators.
Let’s just think that my plug-in belongs to a third-party plug-in. It is “highly likely” to be loaded after bbcode. I first use getMessageTextDecorators to get the original MessageTextDecorators, then merge them into my own MessageTextDecorators, and then call regMessageTextDecorators.
Maybe problem solved,
The problem with regMessageRender is the same. The bbcode plugin will parse the message and then use the BBCode component to display it.
And I want to parse my own message type, and at the same time take care of the normal parsing of bbcode. I also have to getMessageRender before regMessageRender, and then merge it into my own MessageRender through some judgments, and then call regMessageRender.
The pseudo code is as follows:

const oldMessageRender = getMessageRender()
regMessageRender((message) => {
    if(isMyMessage(message)){
        return <MyComponent message={message} />;
    }
    return oldMessageRender(message)
});
const oldDecorators = getMessageTextDecorators()
regMessageTextDecorators(() => ({
    mymessage: () => {
       //custom message
    },
    ...oldDecorators
}));

Such code is too hacky.

Is my usage wrong?
My current requirement is to customize a message type, such as a menu panel. After receiving the message, the other party can directly click on the function on this menu, and then the backend will respond accordingly.
I took a look at Miaoyan Miaoyu. This plug-in uses regMessageInterpreter to parse messages. It needs to be manually clicked by the user, and the rendered content cannot be customized. It can only do translation-like functions, which does not meet my needs.
Then I took a look at the bbcode plugin. regMessageTextDecorators and regMessageRender should be what I want, but there is the "overwriting" problem described above. If multiple plugins use these two functions, they will conflict and compete.

Ideally, there should be a function that can register the message type, and then bind a dedicated parsing function.
For example:

  Registration message type
regMessageType("my-menu",(content)=>{ return <MyMenuComponent content={content} />})
  Send a message, the first parameter is the type, the second parameter is the content
actions. sendMsg("my-menu", content)

Each plug-in only needs to pay attention to the message type defined by itself.

The current design of tailchat is that all messages are strings, without a separate type mark, and then rely on parsing this plain text to render different message types, such as HTML-like text like bbcode, or markdown.
This design encounters a "competition" problem when multiple plug-ins want to parse the message.

@github-actions github-actions bot changed the title regMessageTextDecorators 和 regMessageRender 目前不太灵活 regMessageTextDecorators 和 regMessageRender 目前不太灵活 || regMessageTextDecorators and regMessageRender are currently less flexible Jul 27, 2023
@kkqy
Copy link
Author

kkqy commented Jul 28, 2023

实测
const oldMessageRender = getMessageRender()
这样不行。
因为文档欠缺,我以为 getMessageRender是一个函数,调用以后返回render函数本身,
实际测试发现getMessageRender居然不是regMessageRender的“反面”,
getMessageRender本身就是那个render函数……。
但是这种写法也不行

const oldMessageRender = getMessageRender
regMessageRender((message) => {
    if(isMyMessage(message)){
        return <MyComponent message={message} />;
    }
    return oldMessageRender(message)
});

无限递归爆栈了。

我现在只能暂时放弃兼顾bbcode了。


Measured
const oldMessageRender = getMessageRender()
That does not work.
Because of the lack of documentation, I thought that getMessageRender is a function that returns the render function itself after calling,
The actual test found that getMessageRender is not the "opposite" of regMessageRender,
getMessageRender itself is that render function....
But this way of writing doesn't work either

const oldMessageRender = getMessageRender
regMessageRender((message) => {
    if(isMyMessage(message)){
        return <MyComponent message={message} />;
    }
    return oldMessageRender(message)
});

Infinite recursion exploded the stack.

I can only temporarily give up taking into account bbcode now.

@moonrailgun
Copy link
Contributor

moonrailgun commented Jul 28, 2023

感谢你对tailchat的关注。
首先getMessageRender 意思是语法解释器,即目的在于处理一种富文本的语法,比如bbcode,比如markdown、html、或者其他的语法。

你想要实现的效果应该是由其中的卡片消息类型提供,你可以使用regPluginCardItem 来注册你自己的消息卡片渲染类型。在bbcode语法中应该是这样的 [card type="<your custom card>"][/card]

关于文档,因为我目前没有太多精力去处理一些比较技术细节的文档,因此对你造成的困扰非常抱歉。同时Tailchat正如他的代码设计一样是一个非常开放且兼容的社区,如果你对此有一些想法欢迎给tailchat提交文档方面的pr,让我们一起来共建自由开放的tailchat社区


Thank you for your interest in tailchat.
First of all, getMessageRender means a grammar interpreter, that is, the purpose is to process a rich text grammar, such as bbcode, such as markdown, html, or other grammars.

The effect you want to achieve should be provided by the card message type, you can use regPluginCardItem to register your own message card rendering type. In bbcode syntax it should look like [card type="<your custom card>"][/card]

Regarding the documentation, because I don't have much energy to deal with some more technical details of the documentation, I am very sorry for the trouble you have caused. At the same time, Tailchat is a very open and compatible community just like its code design. If you have some ideas about this, please submit a pr for the documentation to tailchat. Let us build a free and open tailchat community

@kkqy
Copy link
Author

kkqy commented Jul 28, 2023

regPluginCardItem

感谢您的回复,因为没有文档,所以之前不知道regPluginCardItem这个东西是用来做啥的。
我现在去琢磨一下


regPluginCardItem

Thank you for your reply, because there is no documentation, so I didn't know what regPluginCardItem is used for.
I'm going to think about it now

@kkqy kkqy closed this as completed Jul 28, 2023
@kkqy
Copy link
Author

kkqy commented Jul 28, 2023

我看了一下,@capital/common里没有导出 regPluginCardItem ,我自己手动处理了一下,由于我对typescript不是太熟悉,所以暂时不提交pr。


I took a look and found that regPluginCardItem was not exported in @capital/common. I manually processed it myself. Since I am not very familiar with typescript, I will not submit pr for now.

@kkqy kkqy reopened this Jul 28, 2023
@moonrailgun
Copy link
Contributor

moonrailgun commented Jul 28, 2023

导出了,可能是因为这是最近才导出的,配置声明文件可能不准确。我更新一下


Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update

moonrailgun added a commit that referenced this issue Jul 28, 2023
@kkqy
Copy link
Author

kkqy commented Jul 28, 2023

导出了,可能是因为这是最近才导出的,配置声明文件可能不准确。我更新一下

Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update

我看文档,后端插件开发环境部分也是TODO,
但是根据文档的插件部署说明,后端插件只要符合文件命名规则就会自动加载,我参考内置的后端插件,将我的插件目录放到server/plugins里并没有自动加载。
同时我在server目录下
执行了
pnpm plugin:install xxx.xxx.xxx
手动安装我的插件,也提示成功
但是访问
http://localhost:11000/health
也没看到我的插件。
是漏掉什么步骤了?

@moonrailgun
Copy link
Contributor

moonrailgun commented Jul 28, 2023

导出了,可能是因为这是最近才导出的,配置声明文件可能不准确。我更新一下
Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update

我看文档,后端插件开发环境部分也是TODO, 但是根据文档的插件部署说明,后端插件只要符合文件命名规则就会自动加载,我参考内置的后端插件,将我的插件目录放到server/plugins里并没有自动加载。 同时我在server目录下 执行了 pnpm plugin:install xxx.xxx.xxx 手动安装我的插件,也提示成功 但是访问 http://localhost:11000/health 也没看到我的插件。 是漏掉什么步骤了?

是在开发模式下加载的么?看你的描述步骤没有哪里不对


Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update
Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update

I read the documentation, the backend plug-in development environment part is also TODO, but according to the plug-in deployment instructions in the document, the back-end plug-in will be automatically loaded as long as it conforms to the file naming rules. I refer to the built-in back-end plug-in and put my plug-in directory in There is no automatic loading in server/plugins. At the same time, I executed pnpm plugin:install xxx.xxx.xxx in the server directory to manually install my plug-in, and it also prompted success, but I did not see my plug-in when I visited http://localhost:11000/health. What step is missing?

Is it loaded in development mode? There is nothing wrong with your description steps

@kkqy
Copy link
Author

kkqy commented Jul 28, 2023

导出了,可能是因为这是最近才导出的,配置声明文件可能不准确。我更新一下
Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update

我看文档,后端插件开发环境部分也是TODO, 但是根据文档的插件部署说明,后端插件只要符合文件命名规则就会自动加载,我参考内置的后端插件,将我的插件目录放到server/plugins里并没有自动加载。 同时我在server目录下 执行了 pnpm plugin:install xxx.xxx.xxx 手动安装我的插件,也提示成功 但是访问 http://localhost:11000/health 也没看到我的插件。 是漏掉什么步骤了?

是在开发模式下加载的么?看你的描述步骤没有哪里不对

Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update
Exported, probably because it was exported recently, the configuration declaration file may be inaccurate. I will update

I read the documentation, the backend plug-in development environment part is also TODO, but according to the plug-in deployment instructions in the document, the back-end plug-in will be automatically loaded as long as it conforms to the file naming rules. I refer to the built-in back-end plug-in and put my plug-in directory in There is no automatic loading in server/plugins. At the same time, I executed pnpm plugin:install xxx.xxx.xxx in the server directory to manually install my plug-in, and it also prompted success, but I did not see my plug-in when I visited http://localhost:11000/health. What step is missing?

Is it loaded in development mode? There is nothing wrong with your description steps

找到原因了,我为了方便源码管理,我是把我的后端插件单独放的一个git项目,然后用mklink把项目目录链接到/server/plugins里的,但是moleculer居然不认这个软连接……我删掉软连接以后,把项目文件夹复制过来就好了。

@kkqy kkqy closed this as completed Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants