Skip to content

Commit 5cb05fc

Browse files
authored
✏ Add support for discord.js v14 (#436)
1 parent 52bd127 commit 5cb05fc

File tree

5 files changed

+43
-37
lines changed

5 files changed

+43
-37
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "discord-backup",
3-
"version": "3.2.1",
3+
"version": "3.3.0",
44
"description": "A complete framework to facilitate server backup using discord.js v12",
55
"main": "lib/index.js",
66
"files": [
@@ -31,7 +31,7 @@
3131
},
3232
"homepage": "https://github.com/Androz2091/discord-backup#readme",
3333
"dependencies": {
34-
"discord.js": "^13.6.0"
34+
"discord.js": "^14.2.0"
3535
},
3636
"devDependencies": {
3737
"@types/node": "^17.0.30",

src/create.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88
TextChannelData,
99
VoiceChannelData
1010
} from './types';
11-
import type { CategoryChannel, Collection, Guild, GuildChannel, Snowflake, TextChannel, ThreadChannel, VoiceChannel } from 'discord.js';
11+
import type { CategoryChannel, ChannelType, Collection, Guild, GuildChannel, Snowflake, TextChannel, ThreadChannel, VoiceChannel } from 'discord.js';
1212
import nodeFetch from 'node-fetch';
1313
import { fetchChannelPermissions, fetchTextChannelData, fetchVoiceChannelData } from './util';
1414
import { MemberData } from './types/MemberData';
@@ -112,7 +112,7 @@ export async function getChannels(guild: Guild, options: CreateOptions) {
112112
};
113113
// Gets the list of the categories and sort them by position
114114
const categories = (guild.channels.cache
115-
.filter((ch) => ch.type === 'GUILD_CATEGORY') as Collection<Snowflake, CategoryChannel>)
115+
.filter((ch) => ch.type === ChannelType.GuildCategory) as Collection<Snowflake, CategoryChannel>)
116116
.sort((a, b) => a.position - b.position)
117117
.toJSON() as CategoryChannel[];
118118
for (const category of categories) {
@@ -125,7 +125,7 @@ export async function getChannels(guild: Guild, options: CreateOptions) {
125125
const children = category.children.sort((a, b) => a.position - b.position).toJSON();
126126
for (const child of children) {
127127
// For each child channel
128-
if (child.type === 'GUILD_TEXT'|| child.type === 'GUILD_NEWS') {
128+
if (child.type === ChannelType.GuildText || child.type === ChannelType.GuildNews) {
129129
const channelData: TextChannelData = await fetchTextChannelData(child as TextChannel, options); // Gets the channel data
130130
categoryData.children.push(channelData); // And then push the child in the categoryData
131131
} else {
@@ -138,15 +138,15 @@ export async function getChannels(guild: Guild, options: CreateOptions) {
138138
// Gets the list of the other channels (that are not in a category) and sort them by position
139139
const others = (guild.channels.cache
140140
.filter((ch) => {
141-
return !ch.parent && ch.type !== 'GUILD_CATEGORY'
142-
&& ch.type !== 'GUILD_STORE' // there is no way to restore store channels, ignore them
143-
&& ch.type !== 'GUILD_NEWS_THREAD' && ch.type !== 'GUILD_PRIVATE_THREAD' && ch.type !== 'GUILD_PUBLIC_THREAD' // threads will be saved with fetchTextChannelData
141+
return !ch.parent && ch.type !== ChannelType.GuildCategory
142+
//&& ch.type !== 'GUILD_STORE' // there is no way to restore store channels, ignore them
143+
&& ch.type !== ChannelType.GuildNewsThread && ch.type !== ChannelType.GuildPrivateThread && ch.type !== ChannelType.GuildPublicThread // threads will be saved with fetchTextChannelData
144144
}) as Collection<Snowflake, Exclude<GuildChannel, ThreadChannel>>)
145145
.sort((a, b) => a.position - b.position)
146146
.toJSON();
147147
for (const channel of others) {
148148
// For each channel
149-
if (channel.type === 'GUILD_TEXT' || channel.type === 'GUILD_NEWS') {
149+
if (channel.type === ChnanelType.GuildText || channel.type === ChannelType.GuildNews) {
150150
const channelData: TextChannelData = await fetchTextChannelData(channel as TextChannel, options); // Gets the channel data
151151
channels.others.push(channelData); // Update channels object
152152
} else {

src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { BackupData, BackupInfos, CreateOptions, LoadOptions } from './types/';
22
import type { Guild } from 'discord.js';
3-
import { SnowflakeUtil, Intents } from 'discord.js';
3+
import { SnowflakeUtil, IntentsBitField } from 'discord.js';
44

55
import nodeFetch from 'node-fetch';
66
import { sep } from 'path';
@@ -76,8 +76,8 @@ export const create = async (
7676
) => {
7777
return new Promise<BackupData>(async (resolve, reject) => {
7878

79-
const intents = new Intents(guild.client.options.intents);
80-
if (!intents.has('GUILDS')) return reject('GUILDS intent is required');
79+
const intents = new IntentsBitField(guild.client.options.intents);
80+
if (!intents.has(IntentsBitField.Flags.Guilds)) return reject('Guilds intent is required');
8181

8282
try {
8383
const backupData: BackupData = {

src/load.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { BackupData, LoadOptions } from './types';
2-
import type { Emoji, Guild, GuildChannel, Role, VoiceChannel } from 'discord.js';
2+
import type { ChannelType, Emoji, Guild, GuildFeature, GuildChannel, Role, VoiceChannel } from 'discord.js';
33
import { loadCategory, loadChannel } from './util';
44

55
/**
@@ -31,7 +31,7 @@ export const loadConfig = (guild: Guild, backupData: BackupData): Promise<Guild[
3131
if (backupData.defaultMessageNotifications) {
3232
configPromises.push(guild.setDefaultMessageNotifications(backupData.defaultMessageNotifications));
3333
}
34-
const changeableExplicitLevel = guild.features.includes('COMMUNITY');
34+
const changeableExplicitLevel = guild.features.includes(GuildFeature.Community);
3535
if (backupData.explicitContentFilter && changeableExplicitLevel) {
3636
configPromises.push(guild.setExplicitContentFilter(backupData.explicitContentFilter));
3737
}
@@ -97,7 +97,7 @@ export const loadChannels = (guild: Guild, backupData: BackupData, options: Load
9797
export const loadAFK = (guild: Guild, backupData: BackupData): Promise<Guild[]> => {
9898
const afkPromises: Promise<Guild>[] = [];
9999
if (backupData.afk) {
100-
afkPromises.push(guild.setAFKChannel(guild.channels.cache.find((ch) => ch.name === backupData.afk.name && ch.type === 'GUILD_VOICE') as VoiceChannel));
100+
afkPromises.push(guild.setAFKChannel(guild.channels.cache.find((ch) => ch.name === backupData.afk.name && ch.type === ChannelType.GuildVoice) as VoiceChannel));
101101
afkPromises.push(guild.setAFKTimeout(backupData.afk.timeout));
102102
}
103103
return Promise.all(afkPromises);

src/util.ts

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ import type {
1111
import type {
1212
CategoryChannel,
1313
ChannelLogsQueryOptions,
14+
ChannelType,
1415
Collection,
1516
Guild,
17+
GuildFeature,
18+
GuildDefaultMessageNotifications,
19+
GuildSystemChannelFlags,
1620
GuildChannelCreateOptions,
1721
Message,
1822
OverwriteData,
@@ -28,10 +32,10 @@ import type {
2832
import nodeFetch from 'node-fetch';
2933

3034
const MaxBitratePerTier: Record<PremiumTier, number> = {
31-
NONE: 64000,
32-
TIER_1: 128000,
33-
TIER_2: 256000,
34-
TIER_3: 384000
35+
None: 64000,
36+
Tier1: 128000,
37+
Tier2: 256000,
38+
Tier3: 384000
3539
};
3640

3741
/**
@@ -61,7 +65,7 @@ export function fetchChannelPermissions(channel: TextChannel | VoiceChannel | Ca
6165
export async function fetchVoiceChannelData(channel: VoiceChannel) {
6266
return new Promise<VoiceChannelData>(async (resolve) => {
6367
const channelData: VoiceChannelData = {
64-
type: 'GUILD_VOICE',
68+
type: ChannelType.GuildVoice,
6569
name: channel.name,
6670
bitrate: channel.bitrate,
6771
userLimit: channel.userLimit,
@@ -129,12 +133,12 @@ export async function fetchTextChannelData(channel: TextChannel | NewsChannel, o
129133
type: channel.type,
130134
name: channel.name,
131135
nsfw: channel.nsfw,
132-
rateLimitPerUser: channel.type === 'GUILD_TEXT' ? channel.rateLimitPerUser : undefined,
136+
rateLimitPerUser: channel.type === ChannelType.GuildText ? channel.rateLimitPerUser : undefined,
133137
parent: channel.parent ? channel.parent.name : null,
134138
topic: channel.topic,
135139
permissions: fetchChannelPermissions(channel),
136140
messages: [],
137-
isNews: channel.type === 'GUILD_NEWS',
141+
isNews: channel.type === ChannelType.GuildNews,
138142
threads: []
139143
};
140144
/* Fetch channel threads */
@@ -176,7 +180,7 @@ export async function fetchTextChannelData(channel: TextChannel | NewsChannel, o
176180
export async function loadCategory(categoryData: CategoryData, guild: Guild) {
177181
return new Promise<CategoryChannel>((resolve) => {
178182
guild.channels.create(categoryData.name, {
179-
type: 'GUILD_CATEGORY'
183+
type: ChannelType.GuildCategory
180184
}).then(async (category) => {
181185
// When the category is created
182186
const finalPermissions: OverwriteData[] = [];
@@ -209,7 +213,8 @@ export async function loadChannel(
209213

210214
const loadMessages = (channel: TextChannel | ThreadChannel, messages: MessageData[], previousWebhook?: Webhook): Promise<Webhook|void> => {
211215
return new Promise(async (resolve) => {
212-
const webhook = previousWebhook || await (channel as TextChannel).createWebhook('MessagesBackup', {
216+
const webhook = previousWebhook || await (channel as TextChannel).createWebhook({
217+
name: 'MessagesBackup',
213218
avatar: channel.client.user.displayAvatarURL()
214219
}).catch(() => {});
215220
if (!webhook) return resolve();
@@ -238,16 +243,17 @@ export async function loadChannel(
238243
}
239244

240245
const createOptions: GuildChannelCreateOptions = {
246+
name: channelData.name,
241247
type: null,
242248
parent: category
243249
};
244-
if (channelData.type === 'GUILD_TEXT' || channelData.type === 'GUILD_NEWS') {
250+
if (channelData.type === ChannelType.GuildText || channelData.type === ChannelType.GuildNews) {
245251
createOptions.topic = (channelData as TextChannelData).topic;
246252
createOptions.nsfw = (channelData as TextChannelData).nsfw;
247253
createOptions.rateLimitPerUser = (channelData as TextChannelData).rateLimitPerUser;
248254
createOptions.type =
249-
(channelData as TextChannelData).isNews && guild.features.includes('NEWS') ? 'GUILD_NEWS' : 'GUILD_TEXT';
250-
} else if (channelData.type === 'GUILD_VOICE') {
255+
(channelData as TextChannelData).isNews && guild.features.includes(GuildFeature.News) ? ChannelType.GuildNews : ChannelType.GuildText;
256+
} else if (channelData.type === ChannelType.GuildVoice) {
251257
// Downgrade bitrate
252258
let bitrate = (channelData as VoiceChannelData).bitrate;
253259
const bitrates = Object.values(MaxBitratePerTier);
@@ -256,9 +262,9 @@ export async function loadChannel(
256262
}
257263
createOptions.bitrate = bitrate;
258264
createOptions.userLimit = (channelData as VoiceChannelData).userLimit;
259-
createOptions.type = 'GUILD_VOICE';
265+
createOptions.type = ChannelType.GuildVoice;
260266
}
261-
guild.channels.create(channelData.name, createOptions).then(async (channel) => {
267+
guild.channels.create(createOptions).then(async (channel) => {
262268
/* Update channel permissions */
263269
const finalPermissions: OverwriteData[] = [];
264270
channelData.permissions.forEach((perm) => {
@@ -272,7 +278,7 @@ export async function loadChannel(
272278
}
273279
});
274280
await channel.permissionOverwrites.set(finalPermissions);
275-
if (channelData.type === 'GUILD_TEXT') {
281+
if (channelData.type === ChannelType.GuildText) {
276282
/* Load messages */
277283
let webhook: Webhook|void;
278284
if ((channelData as TextChannelData).messages.length > 0) {
@@ -282,8 +288,8 @@ export async function loadChannel(
282288
if ((channelData as TextChannelData).threads.length > 0) { //&& guild.features.includes('THREADS_ENABLED')) {
283289
await Promise.all((channelData as TextChannelData).threads.map(async (threadData) => {
284290
let autoArchiveDuration = threadData.autoArchiveDuration;
285-
if (!guild.features.includes('SEVEN_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 10080) autoArchiveDuration = 4320;
286-
if (!guild.features.includes('THREE_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 4320) autoArchiveDuration = 1440;
291+
//if (!guild.features.includes('SEVEN_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 10080) autoArchiveDuration = 4320;
292+
//if (!guild.features.includes('THREE_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 4320) autoArchiveDuration = 1440;
287293
return (channel as TextChannel).threads.create({
288294
name: threadData.name,
289295
autoArchiveDuration
@@ -329,16 +335,16 @@ export async function clearGuild(guild: Guild) {
329335
guild.setIcon(null);
330336
guild.setBanner(null).catch(() => {});
331337
guild.setSplash(null).catch(() => {});
332-
guild.setDefaultMessageNotifications('ONLY_MENTIONS');
338+
guild.setDefaultMessageNotifications(GuildDefaultMessageNotifications.OnlyMentions);
333339
guild.setWidgetSettings({
334340
enabled: false,
335341
channel: null
336342
});
337-
if (!guild.features.includes('COMMUNITY')) {
338-
guild.setExplicitContentFilter('DISABLED');
339-
guild.setVerificationLevel('NONE');
343+
if (!guild.features.includes(GuildFeature.Community)) {
344+
guild.setExplicitContentFilter(GuildExplicitContentFilter.Disabled);
345+
guild.setVerificationLevel(GuildVerificationLevel.None);
340346
}
341347
guild.setSystemChannel(null);
342-
guild.setSystemChannelFlags(['SUPPRESS_GUILD_REMINDER_NOTIFICATIONS', 'SUPPRESS_JOIN_NOTIFICATIONS', 'SUPPRESS_PREMIUM_SUBSCRIPTIONS']);
348+
guild.setSystemChannelFlags([GuildSystemChannelFlags.SuppressGuildReminderNotifications, GuildSystemChannelFlags.SuppressJoinNotifications, GuildSystemChannelFlags.SuppressPremiumSubscriptions]);
343349
return;
344350
}

0 commit comments

Comments
 (0)