Skip to content

Commit

Permalink
✏ Add support for discord.js v14 (#436)
Browse files Browse the repository at this point in the history
  • Loading branch information
lolollllo authored Aug 21, 2022
1 parent 52bd127 commit 5cb05fc
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 37 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "discord-backup",
"version": "3.2.1",
"version": "3.3.0",
"description": "A complete framework to facilitate server backup using discord.js v12",
"main": "lib/index.js",
"files": [
Expand Down Expand Up @@ -31,7 +31,7 @@
},
"homepage": "https://github.com/Androz2091/discord-backup#readme",
"dependencies": {
"discord.js": "^13.6.0"
"discord.js": "^14.2.0"
},
"devDependencies": {
"@types/node": "^17.0.30",
Expand Down
14 changes: 7 additions & 7 deletions src/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
TextChannelData,
VoiceChannelData
} from './types';
import type { CategoryChannel, Collection, Guild, GuildChannel, Snowflake, TextChannel, ThreadChannel, VoiceChannel } from 'discord.js';
import type { CategoryChannel, ChannelType, Collection, Guild, GuildChannel, Snowflake, TextChannel, ThreadChannel, VoiceChannel } from 'discord.js';
import nodeFetch from 'node-fetch';
import { fetchChannelPermissions, fetchTextChannelData, fetchVoiceChannelData } from './util';
import { MemberData } from './types/MemberData';
Expand Down Expand Up @@ -112,7 +112,7 @@ export async function getChannels(guild: Guild, options: CreateOptions) {
};
// Gets the list of the categories and sort them by position
const categories = (guild.channels.cache
.filter((ch) => ch.type === 'GUILD_CATEGORY') as Collection<Snowflake, CategoryChannel>)
.filter((ch) => ch.type === ChannelType.GuildCategory) as Collection<Snowflake, CategoryChannel>)
.sort((a, b) => a.position - b.position)
.toJSON() as CategoryChannel[];
for (const category of categories) {
Expand All @@ -125,7 +125,7 @@ export async function getChannels(guild: Guild, options: CreateOptions) {
const children = category.children.sort((a, b) => a.position - b.position).toJSON();
for (const child of children) {
// For each child channel
if (child.type === 'GUILD_TEXT'|| child.type === 'GUILD_NEWS') {
if (child.type === ChannelType.GuildText || child.type === ChannelType.GuildNews) {
const channelData: TextChannelData = await fetchTextChannelData(child as TextChannel, options); // Gets the channel data
categoryData.children.push(channelData); // And then push the child in the categoryData
} else {
Expand All @@ -138,15 +138,15 @@ export async function getChannels(guild: Guild, options: CreateOptions) {
// Gets the list of the other channels (that are not in a category) and sort them by position
const others = (guild.channels.cache
.filter((ch) => {
return !ch.parent && ch.type !== 'GUILD_CATEGORY'
&& ch.type !== 'GUILD_STORE' // there is no way to restore store channels, ignore them
&& ch.type !== 'GUILD_NEWS_THREAD' && ch.type !== 'GUILD_PRIVATE_THREAD' && ch.type !== 'GUILD_PUBLIC_THREAD' // threads will be saved with fetchTextChannelData
return !ch.parent && ch.type !== ChannelType.GuildCategory
//&& ch.type !== 'GUILD_STORE' // there is no way to restore store channels, ignore them
&& ch.type !== ChannelType.GuildNewsThread && ch.type !== ChannelType.GuildPrivateThread && ch.type !== ChannelType.GuildPublicThread // threads will be saved with fetchTextChannelData
}) as Collection<Snowflake, Exclude<GuildChannel, ThreadChannel>>)
.sort((a, b) => a.position - b.position)
.toJSON();
for (const channel of others) {
// For each channel
if (channel.type === 'GUILD_TEXT' || channel.type === 'GUILD_NEWS') {
if (channel.type === ChnanelType.GuildText || channel.type === ChannelType.GuildNews) {
const channelData: TextChannelData = await fetchTextChannelData(channel as TextChannel, options); // Gets the channel data
channels.others.push(channelData); // Update channels object
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { BackupData, BackupInfos, CreateOptions, LoadOptions } from './types/';
import type { Guild } from 'discord.js';
import { SnowflakeUtil, Intents } from 'discord.js';
import { SnowflakeUtil, IntentsBitField } from 'discord.js';

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

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

try {
const backupData: BackupData = {
Expand Down
6 changes: 3 additions & 3 deletions src/load.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BackupData, LoadOptions } from './types';
import type { Emoji, Guild, GuildChannel, Role, VoiceChannel } from 'discord.js';
import type { ChannelType, Emoji, Guild, GuildFeature, GuildChannel, Role, VoiceChannel } from 'discord.js';
import { loadCategory, loadChannel } from './util';

/**
Expand Down Expand Up @@ -31,7 +31,7 @@ export const loadConfig = (guild: Guild, backupData: BackupData): Promise<Guild[
if (backupData.defaultMessageNotifications) {
configPromises.push(guild.setDefaultMessageNotifications(backupData.defaultMessageNotifications));
}
const changeableExplicitLevel = guild.features.includes('COMMUNITY');
const changeableExplicitLevel = guild.features.includes(GuildFeature.Community);
if (backupData.explicitContentFilter && changeableExplicitLevel) {
configPromises.push(guild.setExplicitContentFilter(backupData.explicitContentFilter));
}
Expand Down Expand Up @@ -97,7 +97,7 @@ export const loadChannels = (guild: Guild, backupData: BackupData, options: Load
export const loadAFK = (guild: Guild, backupData: BackupData): Promise<Guild[]> => {
const afkPromises: Promise<Guild>[] = [];
if (backupData.afk) {
afkPromises.push(guild.setAFKChannel(guild.channels.cache.find((ch) => ch.name === backupData.afk.name && ch.type === 'GUILD_VOICE') as VoiceChannel));
afkPromises.push(guild.setAFKChannel(guild.channels.cache.find((ch) => ch.name === backupData.afk.name && ch.type === ChannelType.GuildVoice) as VoiceChannel));
afkPromises.push(guild.setAFKTimeout(backupData.afk.timeout));
}
return Promise.all(afkPromises);
Expand Down
50 changes: 28 additions & 22 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ import type {
import type {
CategoryChannel,
ChannelLogsQueryOptions,
ChannelType,
Collection,
Guild,
GuildFeature,
GuildDefaultMessageNotifications,
GuildSystemChannelFlags,
GuildChannelCreateOptions,
Message,
OverwriteData,
Expand All @@ -28,10 +32,10 @@ import type {
import nodeFetch from 'node-fetch';

const MaxBitratePerTier: Record<PremiumTier, number> = {
NONE: 64000,
TIER_1: 128000,
TIER_2: 256000,
TIER_3: 384000
None: 64000,
Tier1: 128000,
Tier2: 256000,
Tier3: 384000
};

/**
Expand Down Expand Up @@ -61,7 +65,7 @@ export function fetchChannelPermissions(channel: TextChannel | VoiceChannel | Ca
export async function fetchVoiceChannelData(channel: VoiceChannel) {
return new Promise<VoiceChannelData>(async (resolve) => {
const channelData: VoiceChannelData = {
type: 'GUILD_VOICE',
type: ChannelType.GuildVoice,
name: channel.name,
bitrate: channel.bitrate,
userLimit: channel.userLimit,
Expand Down Expand Up @@ -129,12 +133,12 @@ export async function fetchTextChannelData(channel: TextChannel | NewsChannel, o
type: channel.type,
name: channel.name,
nsfw: channel.nsfw,
rateLimitPerUser: channel.type === 'GUILD_TEXT' ? channel.rateLimitPerUser : undefined,
rateLimitPerUser: channel.type === ChannelType.GuildText ? channel.rateLimitPerUser : undefined,
parent: channel.parent ? channel.parent.name : null,
topic: channel.topic,
permissions: fetchChannelPermissions(channel),
messages: [],
isNews: channel.type === 'GUILD_NEWS',
isNews: channel.type === ChannelType.GuildNews,
threads: []
};
/* Fetch channel threads */
Expand Down Expand Up @@ -176,7 +180,7 @@ export async function fetchTextChannelData(channel: TextChannel | NewsChannel, o
export async function loadCategory(categoryData: CategoryData, guild: Guild) {
return new Promise<CategoryChannel>((resolve) => {
guild.channels.create(categoryData.name, {
type: 'GUILD_CATEGORY'
type: ChannelType.GuildCategory
}).then(async (category) => {
// When the category is created
const finalPermissions: OverwriteData[] = [];
Expand Down Expand Up @@ -209,7 +213,8 @@ export async function loadChannel(

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

const createOptions: GuildChannelCreateOptions = {
name: channelData.name,
type: null,
parent: category
};
if (channelData.type === 'GUILD_TEXT' || channelData.type === 'GUILD_NEWS') {
if (channelData.type === ChannelType.GuildText || channelData.type === ChannelType.GuildNews) {
createOptions.topic = (channelData as TextChannelData).topic;
createOptions.nsfw = (channelData as TextChannelData).nsfw;
createOptions.rateLimitPerUser = (channelData as TextChannelData).rateLimitPerUser;
createOptions.type =
(channelData as TextChannelData).isNews && guild.features.includes('NEWS') ? 'GUILD_NEWS' : 'GUILD_TEXT';
} else if (channelData.type === 'GUILD_VOICE') {
(channelData as TextChannelData).isNews && guild.features.includes(GuildFeature.News) ? ChannelType.GuildNews : ChannelType.GuildText;
} else if (channelData.type === ChannelType.GuildVoice) {
// Downgrade bitrate
let bitrate = (channelData as VoiceChannelData).bitrate;
const bitrates = Object.values(MaxBitratePerTier);
Expand All @@ -256,9 +262,9 @@ export async function loadChannel(
}
createOptions.bitrate = bitrate;
createOptions.userLimit = (channelData as VoiceChannelData).userLimit;
createOptions.type = 'GUILD_VOICE';
createOptions.type = ChannelType.GuildVoice;
}
guild.channels.create(channelData.name, createOptions).then(async (channel) => {
guild.channels.create(createOptions).then(async (channel) => {
/* Update channel permissions */
const finalPermissions: OverwriteData[] = [];
channelData.permissions.forEach((perm) => {
Expand All @@ -272,7 +278,7 @@ export async function loadChannel(
}
});
await channel.permissionOverwrites.set(finalPermissions);
if (channelData.type === 'GUILD_TEXT') {
if (channelData.type === ChannelType.GuildText) {
/* Load messages */
let webhook: Webhook|void;
if ((channelData as TextChannelData).messages.length > 0) {
Expand All @@ -282,8 +288,8 @@ export async function loadChannel(
if ((channelData as TextChannelData).threads.length > 0) { //&& guild.features.includes('THREADS_ENABLED')) {
await Promise.all((channelData as TextChannelData).threads.map(async (threadData) => {
let autoArchiveDuration = threadData.autoArchiveDuration;
if (!guild.features.includes('SEVEN_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 10080) autoArchiveDuration = 4320;
if (!guild.features.includes('THREE_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 4320) autoArchiveDuration = 1440;
//if (!guild.features.includes('SEVEN_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 10080) autoArchiveDuration = 4320;
//if (!guild.features.includes('THREE_DAY_THREAD_ARCHIVE') && autoArchiveDuration === 4320) autoArchiveDuration = 1440;
return (channel as TextChannel).threads.create({
name: threadData.name,
autoArchiveDuration
Expand Down Expand Up @@ -329,16 +335,16 @@ export async function clearGuild(guild: Guild) {
guild.setIcon(null);
guild.setBanner(null).catch(() => {});
guild.setSplash(null).catch(() => {});
guild.setDefaultMessageNotifications('ONLY_MENTIONS');
guild.setDefaultMessageNotifications(GuildDefaultMessageNotifications.OnlyMentions);
guild.setWidgetSettings({
enabled: false,
channel: null
});
if (!guild.features.includes('COMMUNITY')) {
guild.setExplicitContentFilter('DISABLED');
guild.setVerificationLevel('NONE');
if (!guild.features.includes(GuildFeature.Community)) {
guild.setExplicitContentFilter(GuildExplicitContentFilter.Disabled);
guild.setVerificationLevel(GuildVerificationLevel.None);
}
guild.setSystemChannel(null);
guild.setSystemChannelFlags(['SUPPRESS_GUILD_REMINDER_NOTIFICATIONS', 'SUPPRESS_JOIN_NOTIFICATIONS', 'SUPPRESS_PREMIUM_SUBSCRIPTIONS']);
guild.setSystemChannelFlags([GuildSystemChannelFlags.SuppressGuildReminderNotifications, GuildSystemChannelFlags.SuppressJoinNotifications, GuildSystemChannelFlags.SuppressPremiumSubscriptions]);
return;
}

0 comments on commit 5cb05fc

Please sign in to comment.