discordjs-file-explorer
Version:
File explorer command for Discord.JS bots
285 lines (254 loc) • 12.3 kB
JavaScript
//Dependencies
const { MessageButton, MessageActionRow } = require('discord-buttons');
const { MessageEmbed } = require('discord.js');
const FileManagerDJS = require('./src/classes/FileManagerDJS');
const fileExplorer = new FileManagerDJS('/../..');
let fileSystemCollector = undefined;
//Export
module.exports = (client, config) => {
//
if (!config || !config.prefix || !config.commandName) throw 'Missing config params';
client.on('message', async (message) => {
if (!message.content.startsWith(config.prefix)) return;
if (message.content.slice(1) != config.commandName) return;
const embed = new MessageEmbed()
.setColor('#FFFF00')
.setThumbnail('https://images-ext-1.discordapp.net/external/mrcYkeF2JU_mDJLy4No_txFOLmoLLjiPNcVpri9y4So/https/i.pinimg.com/originals/50/f2/c7/50f2c7301beeb83dd72f540854a0ecec.gif')
embed.setPath = () => {
embed.setDescription(`**Current path:** \`${fileExplorer.currentPath}\`\n**Page:** ${fileExplorer.currentPage + 1}/${fileExplorer.pages.length}`);
}
const fileEmbed = new MessageEmbed()
.setColor('#FFFF00');
fileEmbed.setFileName = (fileName) => {
fileEmbed.setDescription(`Requested file: ${fileName}`)
};
fileExplorer.buttons = generateButtons(fileExplorer.getAll());
fileExplorer.pages = pages(fileExplorer.buttons).pages;
fileExplorer.currentPage = 0;
embed.setPath();
const msg = await message.channel.send({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
if (fileSystemCollector) {
fileSystemCollector.stop();
}
fileSystemCollector = msg.createButtonCollector((button) => button.clicker.user.id == message.author.id);
fileSystemCollector.on('collect', (button) => {
const buttonArgs = button.id.split('-*')
if(button.defer) button.defer()
else button.reply.defer()
const switchF = {
folder: () => {
fileExplorer.goTo(buttonArgs[1]);
fileExplorer.currentPage = 0;
fileExplorer.buttons = generateButtons(fileExplorer.getAll());
fileExplorer.buttons.unshift(
new MessageButton()
.setID('back-*')
.setEmoji('⤴️')
.setStyle('3')
);
fileExplorer.pages = pages(fileExplorer.buttons).pages;
embed.setPath();
msg.edit({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
},
file: async () => {
fileEmbed.setFileName(buttonArgs[1]);
const choosedOption = await buttonOptions([{ id: 'download', label: 'Download', style: '3' }, { id: 'delete', label: 'Delete', style: '4' }, { id: 'cancel', label: 'Cancel', style: '1' }], message, buttonArgs[1]);
const switchFile = {
download: () => {
message.channel.send({
embed: fileEmbed,
files: [{
attachment: fileExplorer.filePath(buttonArgs[1]),
name: buttonArgs[1]
}]
})
},
delete: () => {
fileExplorer.deleteFile(buttonArgs[1])
fileExplorer.read();
fileExplorer.currentPage = 0;
fileExplorer.buttons = generateButtons(fileExplorer.getAll());
if (!fileExplorer.isRoot()) {
fileExplorer.buttons.unshift(
new MessageButton()
.setID('back-*')
.setEmoji('⤴️')
.setStyle('3')
);
}
fileExplorer.pages = pages(fileExplorer.buttons).pages;
embed.setPath();
msg.edit({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
},
cancel: () => { }
}
switchFile[choosedOption]();
},
back: () => {
fileExplorer.goBack();
fileExplorer.currentPage = 0;
fileExplorer.buttons = generateButtons(fileExplorer.getAll());
if (!fileExplorer.isRoot()) {
fileExplorer.buttons.unshift(
new MessageButton()
.setID('back-*')
.setEmoji('⤴️')
.setStyle('3')
);
}
fileExplorer.pages = pages(fileExplorer.buttons).pages;
embed.setPath();
msg.edit({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
},
nextPage: () => {
if (!fileExplorer.pages[fileExplorer.currentPage + 1]) {
fileExplorer.currentPage = 0;
} else ++fileExplorer.currentPage
embed.setPath();
msg.edit({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
},
backPage: () => {
if (!fileExplorer.pages[fileExplorer.currentPage - 1]) {
fileExplorer.currentPage = fileExplorer.pages.length - 1;
} else --fileExplorer.currentPage
embed.setPath();
msg.edit({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
},
upload: async () => {
const uploadEmbed = new MessageEmbed()
.setDescription('Send the file you want to upload:')
.setFooter('Timeout: 60 seconds')
const uploadMessage = await message.channel.send(uploadEmbed);
const uploadFilter = (collected) => collected.attachments?.first() && message.author.id == collected.author.id;
const messageCollector = message.channel.createMessageCollector(uploadFilter, { time: 60000 })
messageCollector.on('collect', async (collected) => {
const file = collected.attachments.first()
uploadEmbed.footer = undefined;
uploadEmbed.description = undefined;
uploadEmbed.setTitle('Uploading your file...')
.setThumbnail('https://c.tenor.com/I6kN-6X7nhAAAAAj/loading-buffering.gif')
uploadMessage.edit({ embed: uploadEmbed });
try {
await fileExplorer.downloadFromUrl(file.attachment, file.name);
messageCollector.stop()
}
catch {
const opt = await buttonOptions([{ id: 'yes', label: 'Yes', style: '3' }, { id: 'cancel', label: 'Cancel', style: '4' }], message, `This folder already has a file named ${file.name}\nDo you want to overwrite?`)
const switchConfirm = {
yes: async () => {
await fileExplorer.downloadFromUrl(file.attachment, file.name, true);
messageCollector.stop();
},
cancel: () => {
messageCollector.stop();
}
}
switchConfirm[opt]();
}
collected.delete();
})
messageCollector.on('end', () => {
uploadMessage.delete()
fileExplorer.read();
fileExplorer.buttons = generateButtons(fileExplorer.getAll());
if (!fileExplorer.isRoot()) {
fileExplorer.buttons.unshift(
new MessageButton()
.setID('back-*')
.setEmoji('⤴️')
.setStyle('3')
);
}
fileExplorer.pages = pages(fileExplorer.buttons).pages;
embed.setPath();
msg.edit({ embed: embed, components: fileExplorer.pages[fileExplorer.currentPage] });
})
}
}
switchF[buttonArgs[0]]();
})
})
}
//Functions
async function buttonOptions(buttonsData, message, description) {
return new Promise(async resolve => {
const row = new MessageActionRow();
buttonsData.forEach((button) => {
row.addComponent(
new MessageButton()
.setLabel(button.label)
.setID(button.id)
.setStyle(button.style)
)
})
const optionsEmbed = new MessageEmbed()
.setDescription(description)
.setFooter('Timeout: 60 seconds');
const msg = await message.channel.send({ embed: optionsEmbed, component: row });
const collector = msg.createButtonCollector((button) => button.clicker.user.id == message.author.id, { time: 60000 });
collector.on('collect', (button) => {
collector.stop();
msg.delete();
resolve(button.id)
})
})
}
function generateButtons(files) {
const buttons = [];
for (file of files) {
const fileType = file.isDirectory() ? 'folder' : 'file';
const button = new MessageButton()
.setLabel(file.name)
.setID(`${fileType}-*${file.name}`)
switch (fileType) {
case 'file':
button.setEmoji('🧾')
.setStyle('1')
break;
case 'folder':
button.setEmoji('📁')
.setStyle('2')
break;
}
buttons.push(button);
}
return buttons;
}
function pages(buttons) {
const forward = new MessageButton()
.setLabel('>')
.setID('nextPage-*')
.setStyle('3')
const backward = new MessageButton()
.setLabel('<')
.setID('backPage-*')
.setStyle('3')
const upload = new MessageButton()
.setLabel('Upload')
.setEmoji('📨')
.setID('upload-*')
.setStyle('3')
const rowsList = [];
let rows = [];
let row = new MessageActionRow();
for (let i = 0; i < buttons.length; i++) {
if (!rows.length) {
row.addComponent(backward)
.addComponent(forward)
.addComponent(upload)
rows.push(row);
row = new MessageActionRow();
}
const button = buttons[i];
row.addComponent(button);
if (row.components.length == 5 || !buttons[i + 1]) {
rows.push(row);
row = new MessageActionRow();
}
if (rows.length == 5 || !buttons[i + 1]) {
rowsList.push(rows);
rows = [];
}
}
return { pages: rowsList };
}