We want to keep the original message to be shown in Discord later

So we have successfully make a profanity chat filter in our backend system. We replaced the bad words with asterisk character on client side. But we also want to keep the original message when it’s shown in discord. So I attempted to make a singleton so that I can use the variable later to be called after hook. Somehow this method is failed and we don’t know why. Can you guys explains why it’s give me error? And also why we can’t use "module: AMD" ?

Hello,
To give you more clearer answer I think there is a need for more details about profanity filter implementation and from where are you sending messages to the Discord channel.

If you are sending message to Discord channel from the Client then:

  1. You can read message
  2. Decode it
  3. Do profanity checks
  4. Create a new structure for Original and Sanitized messages
  5. Replace the original message content with your fresh one.
  6. Show a sanitized message on the client side and use the original version for sending to the discord channel.

The example below is in Golang but the logic may be applied in any other one.

initializer.RegisterBeforeRt("ChannelMessageSend", func(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *rtapi.Envelope) (*rtapi.Envelope, error) {
		message := in.GetChannelMessageSend()

		type outgoingMessage struct {
			Sanitized string `json:"sanitized"`
			Original  string `json:"original"`
		}

		type incomingMessage struct {
			Message string `json:"message"`
		}

		var msg = incomingMessage{}

		json.Unmarshal([]byte(message.GetContent()), &msg)
		
		sanitized := msg.Message
		if strings.Contains(msg.Message, "bad word") {
			sanitized = strings.ReplaceAll(msg.Message, "bad word", "*")
		}

		var newMessage = outgoingMessage{
			Sanitized: sanitized,
			Original:  msg.Message,
		}

		encoded, _ := json.Marshal(newMessage)
		message.Content = string(encoded)
		return in, nil
})

you know there’s a before hook and after hook. so we just do it once in before hook? I thought we need some sort of public variable so we can call it later in after hook. anyway this is the code in typescript
before hook

function FilterChat(content: string): string {
    // Replace each bad word with asterisks
    for (const badWord of filtered_text_list) {
        const regex = new RegExp(`\\b${badWord}\\b`, 'gi');
        const asterisks = Array(badWord.length + 1).join('*');
        content = content.replace(regex, asterisks);
    }
    return content;
}

let FilterChat_BeforeHook: nkruntime.RtBeforeHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, envelope: nkruntime.Envelope): nkruntime.Envelope {
    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }

    logger.info('Bad out: ' + e.channelMessageSend.content);
    // const myInstance = singleton.getInstance();
    // myInstance.originalMessage = e.channelMessageSend.content; // Used later in after hook
    // Filter the chat content
    // e.channelMessageSend.original = e.channelMessageSend.content;
    e.channelMessageSend.content = FilterChat(e.channelMessageSend.content);


    return e;
}

after hook

let Webhook_AfterHook: nkruntime.RtAfterHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.Envelope | null, input: nkruntime.Envelope) {
    let e = input as nkruntime.EnvelopeChannelMessageSend;
    let user = nk.accountGetId(ctx.userId);

    if (e == null) {
        return e;
    }
    try {
        logger.info('Custom ID : ' + user.customId);
        logger.info("Channel : " + e.channelMessageSend.channelId);
        logger.info("User Chat : " + e.channelMessageSend.content);
        
        // const myInstance = singleton.getInstance();
        // logger.info("Original : " + myInstance.originalMessage);

        let messageContent = JSON.parse(e.channelMessageSend.content);
        let allowedType = [2, 5, 6];
        let allowed = false;

        allowedType.forEach(n => {
            if (messageContent.messageType == n) allowed = true;
        });
        if (!allowed) return e;

        let body = JSON.stringify({
            'chat_contents': JSON.parse(e.channelMessageSend.content),
            'user_id': user.customId,
            'display_name': user.user.displayName,
            'channel_name': e.channelMessageSend.channelId
        });

        logger.debug("[Discord Webhook] User Nickname : %s | Channel : %s | Sending to Discord Chat : %s", user.user.displayName, e.channelMessageSend.channelId, e.channelMessageSend.content);
        logger.debug("[Discord Webhook] Discord API Reply : %s", postWebhookDiscord(nk, body));
    } catch (error) {
        logger.error('[Discord Webhook] Caught exception: %s', error.message);
    }

    return e;
};

You can use before/after hooks. If you follow my code, you will get a sanitized and original message after the hook so you can get the original message from there.
Otherwise, you can send it to the discord channel directly into the before hook. If you do it like that you will save on payload, because in the first example you have to duplicate content. (to have the original version in after hook.)

I’m more to a unity developer than backend programmer(actually only just about 4 days getting into this because unfortunately our backend programmer is kinda busy). So I might need a little help :sweat_smile:
So I change the code like this based on your golang example:
before hook

let FilterChat_BeforeHook: nkruntime.RtBeforeHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, envelope: nkruntime.Envelope): nkruntime.Envelope {
    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }
    
    const msg: IncomingMessage = JSON.parse(e.channelMessageSend.content);

    let sanitized: string = FilterChat(msg.message);

    const newMessage: OutgoingMessage = {
        sanitized,
        original: msg.message,
    };

    const encoded: string = JSON.stringify(newMessage);
    e.channelMessageSend.content = encoded;

    return e;
}

after hook

let Webhook_AfterHook: nkruntime.RtAfterHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.Envelope | null, input: nkruntime.Envelope) {
    let e = input as nkruntime.EnvelopeChannelMessageSend;
    let user = nk.accountGetId(ctx.userId);

    if (e == null) {
        return e;
    }
    try {
        logger.info('Custom ID : ' + user.customId);
        logger.info("Channel : " + e.channelMessageSend.channelId);
        logger.info("User Chat : " + e.channelMessageSend.content);
        
        const outgoing: OutgoingMessage = JSON.parse(e.channelMessageSend.content);
        logger.info("Ori: " + outgoing.original);
        logger.info("Let: " + outgoing.sanitized);
        // const myInstance = singleton.getInstance();
        // logger.info("Original : " + myInstance.originalMessage);

        let messageContent = JSON.parse(e.channelMessageSend.content);
        let allowedType = [2, 5, 6];
        let allowed = false;

        allowedType.forEach(n => {
            if (messageContent.messageType == n) allowed = true;
        });
        if (!allowed) return e;

        let body = JSON.stringify({
            'chat_contents': JSON.parse(e.channelMessageSend.content),
            'user_id': user.customId,
            'display_name': user.user.displayName,
            'channel_name': e.channelMessageSend.channelId
        });

        logger.debug("[Discord Webhook] User Nickname : %s | Channel : %s | Sending to Discord Chat : %s", user.user.displayName, e.channelMessageSend.channelId, e.channelMessageSend.content);
        logger.debug("[Discord Webhook] Discord API Reply : %s", postWebhookDiscord(nk, body));
    } catch (error) {
        logger.error('[Discord Webhook] Caught exception: %s', error.message);
    }

    return e;
};

I thought my code is correct but then I tested it in WebGL build I got error like this when I sent the message
image

inside the FilterChat

function FilterChat(content: string): string {
    // Replace each bad word with asterisks
    for (const badWord of filtered_text_list) {
        const regex = new RegExp(`\\b${badWord}\\b`, 'gi');
        const asterisks = Array(badWord.length + 1).join('*');
        content = content.replace(regex, asterisks);
    }
    return content;
}

Hello,
You have to slightly change how you access your message:

Before Hook
I have change msg.message to msg[“message”] because it’s not an object but map so you cant access it’s property like this: msg.message

I also created OutgoingMessage type to be more clear.

let FilterChat_BeforeHook: nkruntime.RtBeforeHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, envelope: nkruntime.Envelope): nkruntime.Envelope {
    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }

    const msg = JSON.parse(e.channelMessageSend.content);

    let sanitized: string = FilterChat(msg['message']);

    type OutgoingMessage = {
        sanitized: string,
        original: string
    }

    const newMessage: OutgoingMessage = {
        sanitized: sanitized,
        original: msg['message'],
    };

    const encoded: string = JSON.stringify(newMessage);
    e.channelMessageSend.content = encoded;

    return e;
}

After Hook
The same si here, you have to access outgoing like this: outgoing[“original”] / outgoing[“sanitized”]

let Webhook_AfterHook: nkruntime.RtAfterHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.Envelope | null, input: nkruntime.Envelope) {
    let e = input as nkruntime.EnvelopeChannelMessageSend;
    let user = nk.accountGetId(ctx.userId);

    if (e == null) {
        return e;
    }
    try {
        logger.info('Custom ID : ' + user.customId);
        logger.info("Channel : " + e.channelMessageSend.channelId);
        logger.info("User Chat : " + e.channelMessageSend.content);
        
        const outgoing: OutgoingMessage = JSON.parse(e.channelMessageSend.content);
        logger.info("Ori: " + outgoing['original']);
        logger.info("Let: " + outgoing['sanitized']);
        // const myInstance = singleton.getInstance();
        // logger.info("Original : " + myInstance.originalMessage);

        let messageContent = JSON.parse(e.channelMessageSend.content);
        let allowedType = [2, 5, 6];
        let allowed = false;

        allowedType.forEach(n => {
            if (messageContent.messageType == n) allowed = true;
        });
        if (!allowed) return e;

        let body = JSON.stringify({
            'chat_contents': JSON.parse(e.channelMessageSend.content),
            'user_id': user.customId,
            'display_name': user.user.displayName,
            'channel_name': e.channelMessageSend.channelId
        });

        logger.debug("[Discord Webhook] User Nickname : %s | Channel : %s | Sending to Discord Chat : %s", user.user.displayName, e.channelMessageSend.channelId, e.channelMessageSend.content);
        logger.debug("[Discord Webhook] Discord API Reply : %s", postWebhookDiscord(nk, body));
    } catch (error) {
        logger.error('[Discord Webhook] Caught exception: %s', error.message);
    }

    return e;
};

I’ve changed my code like u said into this.
before hook

let FilterChat_BeforeHook: nkruntime.RtBeforeHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, envelope: nkruntime.Envelope): nkruntime.Envelope {
    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }

    const msg = JSON.parse(e.channelMessageSend.content);

    let sanitized: string = FilterChat(msg['message']);

    // Moved
    type OutgoingMessage = {
        sanitized: string,
        original: string
    }

    const newMessage: OutgoingMessage = {
        sanitized: sanitized,
        original: msg['message'],
    };

    const encoded: string = JSON.stringify(newMessage);
    e.channelMessageSend.content = encoded;

    return e;
}

after hook

let Webhook_AfterHook: nkruntime.RtAfterHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.Envelope | null, input: nkruntime.Envelope) {
    let e = input as nkruntime.EnvelopeChannelMessageSend;
    let user = nk.accountGetId(ctx.userId);

    if (e == null) {
        return e;
    }
    try {
        logger.info('Custom ID : ' + user.customId);
        logger.info("Channel : " + e.channelMessageSend.channelId);
        logger.info("User Chat : " + e.channelMessageSend.content);
        
        const outgoing: OutgoingMessage = JSON.parse(e.channelMessageSend.content);
        logger.info("Ori: " + outgoing['original']);
        logger.info("Let: " + outgoing['sanitized']);
        // const myInstance = singleton.getInstance();
        // logger.info("Original : " + myInstance.originalMessage);

        let messageContent = JSON.parse(e.channelMessageSend.content);
        let allowedType = [2, 5, 6];
        let allowed = false;

        allowedType.forEach(n => {
            if (messageContent.messageType == n) allowed = true;
        });
        if (!allowed) return e;

        let body = JSON.stringify({
            'chat_contents': outgoing['original'],
            'user_id': user.customId,
            'display_name': user.user.displayName,
            'channel_name': e.channelMessageSend.channelId
        });

        logger.debug("[Discord Webhook] User Nickname : %s | Channel : %s | Sending to Discord Chat : %s", user.user.displayName, e.channelMessageSend.channelId, outgoing['original']);
        logger.debug("[Discord Webhook] Discord API Reply : %s", postWebhookDiscord(nk, body));
    } catch (error) {
        logger.error('[Discord Webhook] Caught exception: %s', error.message);
    }

    return e;
};

but I still got the error:

Failed to send chatSystem.Net.WebSockets.WebSocketException (0x80004005): TypeError: Cannot read property 'replace' of undefined or null at FilterChat (main.js:417:19(34))
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at Nakama.Socket+<SendAsync>d__122.MoveNext () [0x00276] in <d01a1ab406b942858643e7b02b34ec11>:0 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at Nakama.Socket+<WriteChatMessageAsync>d__118.MoveNext () [0x000b6] in <d01a1ab406b942858643e7b02b34ec11>:0 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <695d1cc93cca45069c528c15c9fdd749>:0 
  at Cosmize.Feature.Nakama.NakamaNetworkManager+<>c__DisplayClass66_0+<<SendChat>g__SafeSendChat|1>d.MoveNext () [0x00045] in C:\Users\SHINTA VR\Documents\Fork\cosmize-experience-unity\Assets\Cosmize\Scripts\Feature\Nakama\NakamaNetworkManager.cs:729 
UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
Cosmize.Core.LogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[]) (at Assets/Cosmize/Scripts/Core/LogHandler.cs:34)
UnityEngine.Debug:LogWarning (object)
Cosmize.Feature.Nakama.NakamaNetworkManager/<>c__DisplayClass66_0/<<SendChat>g__SafeSendChat|1>d:MoveNext () (at Assets/Cosmize/Scripts/Feature/Nakama/NakamaNetworkManager.cs:733)
Cysharp.Threading.Tasks.CompilerServices.AsyncUniTask`1<Cosmize.Feature.Nakama.NakamaNetworkManager/<>c__DisplayClass66_0/<<SendChat>g__SafeSendChat|1>d>:Run () (at Library/PackageCache/com.cysharp.unitask@e999268305/Runtime/CompilerServices/StateMachineRunner.cs:189)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Nakama.IChannelMessageAck>:SetException (System.Exception)
Nakama.Socket/<WriteChatMessageAsync>d__118:MoveNext ()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Nakama.WebSocketMessageEnvelope>:SetException (System.Exception)
Nakama.Socket/<SendAsync>d__122:MoveNext ()
UnityEngine.UnitySynchronizationContext:ExecuteTasks ()

could it be probably we don’t need to do json.parse in before hook?

anyway I just moved the type OutgoingMessage into another file together with the IncomingMessage

type OutgoingMessage = {
    sanitized: string;
    original: string;
}

type IncomingMessage = {
    message: string;
}

Are you using IncomingMessage in before hook? if yes, that might be a problem.
I tested it just now, and it’s working fine.

Before Hook

let FilterChat_BeforeHook: nkruntime.RtBeforeHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, envelope: nkruntime.Envelope): nkruntime.Envelope {
    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }
    // As you can see, I am not using IncomingMessage
    const msg = JSON.parse(e.channelMessageSend.content);

    let sanitized: string = FilterChat(msg['message']);

    const newMessage: OutgoingMessage = {
        sanitized: sanitized,
        original: msg['message'],
    };

    const encoded: string = JSON.stringify(newMessage);
    e.channelMessageSend.content = encoded;

    return e;
}

After Hook


let Webhook_AfterHook: nkruntime.RtAfterHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.Envelope | null, input: nkruntime.Envelope) {
    let e = input as nkruntime.EnvelopeChannelMessageSend;
    let user = nk.accountGetId(ctx.userId);

    if (e == null) {
        return e;
    }
    try {
        logger.info('Custom ID : ' + user.customId);
        logger.info("Channel : " + e.channelMessageSend.channelId);
        logger.info("User Chat : " + e.channelMessageSend.content);

        const outgoing: OutgoingMessage = JSON.parse(e.channelMessageSend.content);
        logger.info("Ori: " + outgoing['original']);
        logger.info("Let: " + outgoing['sanitized']);
        // const myInstance = singleton.getInstance();
        // logger.info("Original : " + myInstance.originalMessage);

        let messageContent = JSON.parse(e.channelMessageSend.content);
        let allowedType = [2, 5, 6];
        let allowed = false;

        allowedType.forEach(n => {
            if (messageContent.messageType == n) allowed = true;
        });
        if (!allowed) return e;

        let body = JSON.stringify({
            'chat_contents': outgoing['original'],
            'user_id': user.customId,
            'display_name': user.user.displayName,
            'channel_name': e.channelMessageSend.channelId
        });

        logger.debug("[Discord Webhook] User Nickname : %s | Channel : %s | Sending to Discord Chat : %s", user.user.displayName, e.channelMessageSend.channelId, outgoing['original']);
        logger.debug("[Discord Webhook] Discord API Reply : %s", postWebhookDiscord(nk, body));
    } catch (error) {
        logger.error('[Discord Webhook] Caught exception: %s', error.message);
    }

    return e;
};

I think the problem is not there sir. Because I also tested your script and I still got this error
image
Just FYI this is the previous working code in before hook


    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }

    logger.info('Bad out: ' + e.channelMessageSend.content);
    // const myInstance = singleton.getInstance();
    // myInstance.originalMessage = e.channelMessageSend.content;
    // Filter the chat content
    // e.channelMessageSend.original = e.channelMessageSend.content;
    e.channelMessageSend.content = FilterChat(e.channelMessageSend.content);

    return e;

As you can see the code above is not using Json.Parse.
Also may I ask where did you get the 'message' in msg['message']?

Hello,
I just checked about msg[‘message’] it’s coming from my test application (Sorry for that).
You would not have it.

So, here is an updated version of the hooks.
The problem I see is that you might have to parse messages on the client side. (For me, using JS library for client message comes JSON encoded).
Before Hook

let FilterChat_BeforeHook: nkruntime.RtBeforeHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, envelope: nkruntime.Envelope): nkruntime.Envelope {
    let e = envelope as nkruntime.EnvelopeChannelMessageSend;
    if (!e || !e.channelMessageSend || !e.channelMessageSend.content) {
        return e;
    }

    let sanitized: string = FilterChat(e.channelMessageSend.content);

    const newMessage: OutgoingMessage = {
        sanitized: sanitized,
        original: e.channelMessageSend.content,
    };

    e.channelMessageSend.content = JSON.stringify(newMessage);

    return e;
}

After Hook

let Webhook_AfterHook: nkruntime.RtAfterHookFunction<nkruntime.Envelope> = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.Envelope | null, input: nkruntime.Envelope) {
    let e = input as nkruntime.EnvelopeChannelMessageSend;
    let user = nk.accountGetId(ctx.userId);

    if (e == null) {
        return e;
    }
    try {
        logger.info('Custom ID : ' + user.customId);
        logger.info("Channel : " + e.channelMessageSend.channelId);
        logger.info("User Chat : " + e.channelMessageSend.content);

        const outgoing: OutgoingMessage = JSON.parse(e.channelMessageSend.content);
        logger.info("Ori: " + outgoing.original);
        logger.info("Let: " + outgoing.sanitized);
        // const myInstance = singleton.getInstance();
        // logger.info("Original : " + myInstance.originalMessage);

        let messageContent = JSON.parse(e.channelMessageSend.content);
        let allowedType = [2, 5, 6];
        let allowed = false;

        allowedType.forEach(n => {
            if (messageContent.messageType == n) allowed = true;
        });
        if (!allowed) return e;

        let body = JSON.stringify({
            'chat_contents': outgoing.original,
            'user_id': user.customId,
            'display_name': user.user.displayName,
            'channel_name': e.channelMessageSend.channelId
        });

        logger.debug("[Discord Webhook] User Nickname : %s | Channel : %s | Sending to Discord Chat : %s", user.user.displayName, e.channelMessageSend.channelId, outgoing.original);
        logger.debug("[Discord Webhook] Discord API Reply : %s", postWebhookDiscord(nk, body));
    } catch (error) {
        logger.error('[Discord Webhook] Caught exception: %s', error.message);
    }

    return e;
};

Hello, I have been helped by our backend programmer. After some hours struggling to resolve the error we somehow made it!
Thanks @gbarnovi for your help!