RocketChat / Rocket.Chat.Apps-engine

The Rocket.Chat Apps engine and definitions.

Home Page:https://rocketchat.github.io/Rocket.Chat.Apps-engine/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

executePreMessageSentModify failes

opened this issue · comments

I am trying to modify a message before it is send, but I get the following error in the logs.

Is this a problem of my code, or is the error in the apps-engine?

"{"stack":"TypeError: Converting circular structure to JSON\n --> starting at object with constructor 'Timeout'\n | property '_idlePrev' -> object with constructor 'TimersList'\n --- property '_idleNext' closes the circle\n at JSON.stringify ()\n at /snap/rocketchat-server/1442/programs/server/npm/node_modules/@rocket.chat/apps-engine/server/logging/AppConsole.js:64:34\n at Array.map ()\n at AppConsole.addEntry (/snap/rocketchat-server/1442/programs/server/npm/node_modules/@rocket.chat/apps-engine/server/logging/AppConsole.js:56:25)\n at AppConsole.debug (/snap/rocketchat-server/1442/programs/server/npm/node_modules/@rocket.chat/apps-engine/server/logging/AppConsole.js:23:14)\n at ProxiedApp. (/snap/rocketchat-server/1442/programs/server/npm/node_modules/@rocket.chat/apps-engine/server/ProxiedApp.js:74:24)\n at Generator.next ()\n at fulfilled (/snap/rocketchat-server/1442/programs/server/npm/node_modules/@rocket.chat/apps-engine/server/ProxiedApp.js:4:58)\n at /snap/rocketchat-server/1442/programs/server/npm/node_modules/meteor/promise/node_modules/meteor-promise/fiber_pool.js:43:40","message":"Converting circular structure to JSON\n --> starting at object with constructor 'Timeout'\n | property '_idlePrev' -> object with constructor 'TimersList'\n --- property '_idleNext' closes the circle"}"

Name Version
RC Version 3.6.2
Apps Engine Version 1.17.0
"@types/node": "^14.11.2",
"@rocket.chat/apps-engine": "^1.4.0", //(1.18 didn't work either)
"typescript": "^2.9.1"

Do you have your source code anywhere? Looks like you're trying to convert something to json and it's actually a circular javascript object that references itself or objects in it reference each other. I'd venture to say it is your code but can't say for sure.

Sure ;)

The slash command seems to work fine, so here the code of the edit

code
import {
    IConfigurationExtend,
    IEnvironmentRead,
    IHttp,
    ILogger,
    IMessageBuilder,
    IPersistence,
    IRead,
} from "@rocket.chat/apps-engine/definition/accessors";
import { App } from "@rocket.chat/apps-engine/definition/App";
import { IMessage, IPreMessageSentModify } from "@rocket.chat/apps-engine/definition/messages";
import { IAppInfo } from "@rocket.chat/apps-engine/definition/metadata";
import { MyCommand } from "./MyCommand";

export class MyApp extends App implements IPreMessageSentModify {
    private matcher: RegExp = /(^|\ )#(\d+)(\s|$)/g;

    constructor(info: IAppInfo, logger: ILogger) {
        super(info, logger);
    }

    public async checkPreMessageSentModify(
        message: IMessage,
        read: IRead,
        http: IHttp,
    ): Promise<boolean> {
        if (typeof message.text !== "string") {
            return false;
        }

        const result = message.text.match(this.matcher);

        return result ? result.length !== 0 : false;
    }

    public async executePreMessageSentModify(
        message: IMessage,
        builder: IMessageBuilder,
        read: IRead,
        http: IHttp,
        persistence: IPersistence,
    ): Promise<IMessage> {
        if (typeof message.text !== "string") {
            return message;
        }

        const mylink = message.text.match(this.matcher);

        if (mylink && mylink.length > 0) {
            for (const link of mylink) {
                const parts = this.matcher.exec(link);

                if (!parts || parts.length < 1) {
                    continue;
                }

                const newLink = `[${link}](someDifferentLink/${parts[0]})`;

                message.text = message.text.replace(link, newLink);
            }
        }

        return message;
    }

    protected async extendConfiguration(
        configuration: IConfigurationExtend,
        environmentRead: IEnvironmentRead,
    ): Promise<void> {
        await configuration.slashCommands.provideSlashCommand(new MyCommand());
    }
}

@d-gubert @lolimay any idea about this? From what I can see at a quick glance, nothing stands out about his code that would cause the error.

Hey! Yeah, this does look like a bug on the Apps-Engine. It happens because the app's logger logs the value returned by your method, and breaks when it has a circular dependency in it. The "more correct™️" way to handle this event would be to actually use the builder: IMessageBuilder param to modify whatever information you want in your message, and then return a builder.getMessage() in the end - this message will not have the circular dependency.

It does have some justification to it: the message: IMessage parameter you receive in your executePreMessageSentModify is actually a frozen message object, and any modifications to it are silently ignored, because you should be using the builder instead.

That said, this behavior is for sure not intuitive and prone to cause confusion. We should have it better documented.

@d-gubert thank you very much. That worked

by the way, I copied the code from @graywolf336's repo, is it there wrong as well?


Thanks for the fast resolution :D
do you want this issue to stay open as reminder to update the documentation?