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?
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.
With require
unresolved imports do not result in errors, instead they are simply undefined
. This is the reason for one of the problems in your post title. Resolved imports are of type any
, which is useless when it comes to getting information about what you're working with (which properties your imports have).
With import
statements the compiler checks whether discord-js
has what you'd like to import. This also allows your editor to warn you of any unresolved imports, which would prevent you from using non-existing properties of undefined
.
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.
The options
parameter of send
can be of type WebhookMessageCreateOptions.
WebhookMessageCreateOptions
extends Omit<MessageCreateOptions, 'nonce' | 'reply' | 'stickers'>
, which is MessageCreateOptions
without the specified properties.
MessageCreateOptions extends BaseMessageOptionsWithPoll
BaseMessageOptionsWithPoll extends BaseMessageOptions
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.