Skip to content

Instantly share code, notes, and snippets.

@emiflake
Last active February 8, 2019 20:22
Show Gist options
  • Save emiflake/ed9bf54a447edf3fafb0670640538f83 to your computer and use it in GitHub Desktop.
Save emiflake/ed9bf54a447edf3fafb0670640538f83 to your computer and use it in GitHub Desktop.
Discord downloader
const Discord = require('discord.js');
const R = require('ramda');
const bot = new Discord.Client();
const request = require('request');
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const prog = require("commander");
prog
.version('0.0.0')
.usage('<token> <channelid>')
.parse(process.argv);
bot.on('ready', async () => {
console.log("[i] Logged in!");
// Try a normal guild channel
let channel = bot.channels.get(prog.args[1]);
// Try a dm channel
if ( !channel ) channel = bot.users.get(prog.args[1]).dmChannel;
if ( !channel ) {
throw new Error("Invalid id");
}
console.log(`[i] Found channel '${channel.name}'`);
console.log(`[i] Fetching messages`);
// This function accumulates all of the messages in a channel
const accumulate = (channel) => new Promise((resolve, reject) => {
let accumulator;
const next = (before) => {
// The hard-limit of a fetchMessages request is 100, so we apply the limit.
// If we didn't supply a 'before' id, we don't pass it.
return channel.fetchMessages(before ? {limit: 100, before: before} : {limit: 100}).then(messages => {
if ( accumulator ) {
accumulator = accumulator.concat(messages);
}
else {
// If we didn't initialize the accumulator yet, we can do it now.
accumulator = messages;
}
if ( messages.size < 100 ) return Promise.resolve(accumulator);
else return next(messages.last().id)
}).catch( e => console.error(`[!] ${e.toString()}`))
}
// Pass through to the promise.
next().then(resolve).catch(reject);
});
const messages = await accumulate(channel);
const images = messages.filter( message => message.attachments.size > 0 );
// Extract imageURLs from messages
const imageURLs = images.map(i => i.attachments.map( a => a.url)).reduce( ( a, b ) => a.concat(b) );
console.log(`[i] Ok, we're going to download ${imageURLs.length} files`);
// Create a directory so the files actually don't throw an error.
mkdirp(path.join(__dirname, 'downloads'), async () => {
const next = (i) => {
const imageURL = imageURLs[i];
console.log(`[i] Downloading ${R.last(imageURL.split('/'))}`);
const stream = request(imageURL).pipe(fs.createWriteStream(path.join(__dirname, 'downloads', `[${i}] ${R.last(imageURL.split('/'))}`)));
stream.on('finish', () => {
if ( i + 1 < imageURLs.length ) next(i + 1);
});
}
next(0);
});
});
// Finally, log in.
bot.login(prog.args[0]);
console.log("[i] Logging in...")

How to use this

First, grab/install node from https://nodejs.org/en/download/current/ Then download all of these files into a directory (click here). After you have downloaded the files, open a console in that directory. You can do this by Shift + Right Clicking the directory and clicking 'Open Command Window here'. After you have opened the command window, you have to runer npm install in order to install all of the dependecies. Then, when it is installed, you can simply node index.js <your-token> <channel-id> In order to get your token, follow these instructions. And in order to get the channel id, enable Developer Mode (in Settings -> Appearance) and then right click the desired channel.

If you have any issues with this program, feel free to message me on emiflake#3939

{
"name": "discord-dl",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"commander": "^2.11.0",
"commando": "0.0.2",
"discord.js": "^11.1.0",
"mkdirp": "^0.5.1",
"ramda": "^0.24.1",
"request": "^2.81.0",
"request-promise": "^4.2.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "WolfgangTS",
"license": "ISC"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment