typescriptdiscorddiscord.js

"MessagedEmbed field values must be non-empty strings" and "Cannot read properties of undefined (reading 'Link') error message


I am making a discord bot and I'm kinda new to this. I get both errors all the times, one after I fix the other. I figured it might have something to do with Typescript strict.

'use strict';
require('dotenv').config();

Object.defineProperty(exports, '__esModule', { value: true });

const {
    MessageEmbed,
    WebhookClient,
    ButtonBuilder,
    ButtonStyle,
    ActionRowBuilder,
} = require('discord.js');
const { webhookId, webhookToken } = require('./webhook-config.json');
const webhookClient = new WebhookClient({ id: webhookId, token: webhookToken });
const http = require('http');
const host = 'http://localhost:3000';

const tiktokUsername = process.env.tiktokUsername;
const url_roominfo = host + '/roominfo?tiktokUsername=' + tiktokUsername;
const link = 'https://www.tiktok.com/' + tiktokUsername + '/live';

http
    .get(url_roominfo, res => {
        let body = '';

        res.on('data', chunk => {
            body += chunk;
        });

        res.on('end', () => {
            try {
                const json = JSON.parse(body);

                const embed = new MessageEmbed({
                    color: 0x5aedf2,
                    title: json.title,
                    url: link,
                    author: {
                        name: json.owner.nickname + ' is now live on Tiktok!',
                        icon_url: json.cover.url_list[0],
                        url: link,
                    },
                    fields: [
                        {
                            name: 'Game',
                            value: json.game_tag[0].show_name,
                            inline: true,
                        },
                        {
                            name: 'View',
                            value: json.user_count,
                            inline: true,
                        },
                    ],
                });

                const button = new ButtonBuilder({
                    type: 2,
                    style: ButtonStyle.Link,
                    label: 'Watch Stream',
                    url: json.share_url,
                });

                const row = new ActionRowBuilder().addComponents(button);

                webhookClient.send({
                    content: '@everyone ' + json.owner.nickname + ' is live now🔴',
                    components: [row],
                    embeds: [embed],
                });
            } catch (error) {
                console.error(error.message);
            }
        });
    })
    .on('error', error => {
        console.error(error.message);
    });

I'm supposedly making a discord bot that notifies me once a certain tiktok user goes live. Any suggestions how I might fix this?


Solution

  • Your TypeScript code contains require statements. This leads me to believe you're writing a CommonJS-type node application. While there is nothing wrong with that, I highly suggest you instead write ESM modules (ECMAScript modules). It's the modern standard and it's not much effort to migrate if your project is still in its creation-phase.

    In your package.json ensure "type": "module" exists.

    Change the ts or cts file extension of your bot program to mts. Remove the Object.defineProperty(exports, "__esModule", { value: true }); line -> it's unnecessary in an ESM module. Remove all lines that contain require from your code.

    At the top of your code, after "use strict"; (which is technically unnecessary, since ESM modules are strict by default) put

    import { WebhookClient, ButtonBuilder, ButtonStyle, ActionRowBuilder } from 'discord.js';
    import { APIEmbed } from 'discord-api-types/v10';
    
    import { webhookId, webhookToken } from './webhook-config.json';
    
    import http from 'http';
    
    import dotenv from 'dotenv';
    dotenv.config();
    

    In Typescript you'd benefit from not using require and instead rely on import, because you get better Type-safety from it.

    As you can see MessageEmbed doesn't exist in "discord-js". Instead there is now APIEmbed, from 'discord-api-types', a dependency of 'discord.js'. If you have 'discord.js' installed you already have 'discord-api-types' installed.

    How you could have figured out that you need APIEmbed: You can figure out what WebhookClient.send expects by working yourself backwards through the documentation.

    1. The options parameter of send can be of type WebhookMessageCreateOptions.

    2. WebhookMessageCreateOptions extends Omit<MessageCreateOptions, 'nonce' | 'reply' | 'stickers'>, which is MessageCreateOptions without the specified properties.

    3. MessageCreateOptions extends BaseMessageOptionsWithPoll

    4. BaseMessageOptionsWithPoll extends BaseMessageOptions

    5. BaseMessageOptions has a property embeds, which is of type readonly (JSONEncodable<APIEmbed> | APIEmbed)[]. You're mainly interested in APIEmbed, which is the interface that isn't specified by 'discord-js' and instead is specified by it's dependency 'discord-api-types'.

    With the imports fixed you can replace MessageEmbed with APIEmbed. Since APIEmbed is an interface it doesn't have a constructor, so you can only tell Typescript to create an object that conforms to APIEmbed. Equally type-safe, different syntax.

    Replace

    const embed = new MessageEmbed(
    
                {
    

    with

    const embed: APIEmbed = {
    

    and at the end of that definition replace

        }
    
    );
    

    with just

    };
    

    All fields inside the definition remain the same.

    There exists another problem: ActionRowBuilder is a generic class that must receive typing information. This is clarified in a warning here. You've already imported the ButtonBuilder which you have to use as typing information.

    Replace

    const row = new ActionRowBuilder()
    

    with

    const row = (new ActionRowBuilder<ButtonBuilder>())
    

    These changes should allow you to compile your project without errors. There could be other runtime issues, but it should get you on the right track.