xdccJS is a complete implementation of the XDCC protocol for nodejs.
It can also be used as a command-line downloader !
- Batch downloads :
1-3, 5, 32-35, 101
- Resume file and auto-retry
- Pipes!
- Passive DCC
- Check advanced examples and see what else you can do
const XDCC = require('xdccjs').default
// or
import XDCC from 'xdccjs'
Minimal configuration :
let opts = {
host: 'irc.server.net', // will use default port 6667
path: '/my/download/folder' // absolute and relative paths both work
}
const xdccJS = new XDCC(opts)
Advanced configuration :
Except for host
every parameter is optional, but you can also define a set of options to your preference :
const opts = {
host: 'irc.server.net', // IRC hostname - required
port: 6660, // IRC port - default: 6667
nickname: 'ItsMeJiPaix', // Nickname - default: xdccJS + random
chan: ['#candy', '#fruits'], // Array of channels - default : [ ]
path: 'downloads', // Download path or 'false' - default: false (which enables piping)
retry: 2, // Nb of retries before skip - default: 1
timeout: 50, // Nb of seconds before a download is considered timed out - default: 30
verbose: true, // Display download progress and jobs status - default: false
randomizeNick: false, // Add random numbers at end of nickname - default: true
passivePort: [5000, 5001, 5002], // Array of port(s) to use with Passive DCC - default: [5001]
secure: false, // Allow/Deny files sent by bot with different name than the one requested - default: true
}
xdccJS.download( bot : string, packets : string | number | number[] )
xdccJS.on('ready', () => {
xdccJS.download('XDCC|BLUE', '1-3, 8, 55')
xdccJS.download('XDCC|YELLOW', 4)
xdccJS.download('XDCC|RED', [12, 7, 10, 20])
xdccJS.download('XDCC|PURPLE', ['1', '3', '10', '20'])
})
.download() is asynchronous and returns a job
const job1 = await xdccJS.download('a-bot', [33, 50, 62, 98])
const job2 = await xdccJS.download('XDCC|RED', [1, 3, 10, 20])
xdccJS.download('XDCC|CYAN').then(job3 => {
// do something
})
- Get job progress status :
let status = job1.show() console.log(status) //=> { name: 'a-bot', queue: [98], now: 62, sucess: ['file.txt'], failed: [50] }
- Cancel a Job
job2.cancel()
- Events (see events documentation)
Jobs are stored by bot nickname : .download()
will update matching jobs
xdccJS.on('ready', async () => {
const job1 = await xdccJS.download('XDCC|BLUE', '1-3, 8, 55') // job1 is created
const job2 = await xdccJS.download('XDCC|RED', [1, 3, 10, 20]) // job2 is created
await xdccJS.download('XDCC|BLUE', 23) // job1 is updated
await xdccJS.download('XDCC|RED', '150-155') // job2 is updated
})
You can also search jobs with :xdccJS.jobs()
xdccJS.jobs( bot : string | undefined )
// find job by botname
const job = await xdccJS.jobs('bot-name')
// retrieve all jobs at once
const arrayOfJobs = await xdccJS.jobs()
Most events are accessible both from xdccJS or a Job scope
FYI: those examples are for the sake of showing xdccJS capabilities, if you need download status to be displayed in a nice way just start xdccJS with parameter verbose = true
[xdccJS].on( 'ready' ) : xdccJS is ready to download
-
xdccJS.on('ready', async ()=> { // download() here })
[xdccJS | Job].on( 'downloading' ) : Data is being received (a file is downloading)
-
xdccJS.on('downloading', (fileInfo, received, percentage) => { console.log(fileInfo) //=> { file: 'filename.pdf', filePath: '/path/to/filename.pdf', length: 5844849 } console.log(`downloading: '${fileInfo.file}'`) //=> downloading: 'your file.pdf' }) job.on('downloading', (fileInfo, received, percentage) => { console.log(percentage) //=> 10.55 })
[xdccJS | Job].on( 'downloaded' ) : A file successfully downloaded
-
xdccJS.on('downloaded', (fileInfo) => { console.log(fileInfo.filePath) //=> /home/user/xdccJS/downloads/myfile.pdf }) job.on('downloaded', (fileInfo) => { console.log('Job1 has downloaded:' + fileInfo.filePath) //=> Job1 has downloaded: /home/user/xdccJS/downloads/myfile.pdf console.log(fileInfo) //=> { file: 'filename.pdf', filePath: '/home/user/xdccJS/downloads/myfile.pdf', length: 5844849 } })
[xdccJS | Job].on( 'done' ) : A job has no remaining package in queue
-
xdccJS.on('done', (job) => { console.log(job.show()) //=> { name: 'a-bot', queue: [98], now: 62, sucess: ['file.txt'], failed: [50] } }) job.on('done', (job) => { console.log('Job2 is done!') console.log(job.show()) //=> { name: 'a-bot', queue: [98], now: 62, sucess: ['file.txt'], failed: [50] } })
[xdccJS | Job].on( 'pipe' ) : A pipe is available (see pipe documentation)
-
xdccJS.on('pipe', (stream, fileInfo) => { stream.pipe(somewhere) console.log(fileInfo) //=> { file: 'filename.pdf', filePath: 'pipe', length: 5844849 } }) job.on('pipe', (stream, fileInfo) => { stream.pipe(somewhere) console.log(fileInfo) //=> { file: 'filename.pdf', filePath: 'pipe', length: 5844849 } })
[xdccJS].on( 'error' ) : Connection Errors
-
xdccJS.on('error', (err) => { err instanceof Error //=> true console.error(err.message) //=> UNREACHABLE HOST 1.1.1.1:6667 })
[Job].on( 'error' ) : Job interrupted/canceled or connexion with bot unreachable
-
job.on('error', (message, fileInfo) => { console.error(message) //=> timeout: no response from XDCC|BLUE console.log(fileInfo) //=> { file: 'filename.pdf', filePath: 'pipe', length: 5844849 } })
In order to use pipes xdccJS need to be initialized with path option set to false
// This example will start vlc.exe then play the video while it's downloading.
const opts = {
host: 'irc.server.net',
path: false,
}
const xdccJS = new XDCC(opts)
// Start VLC
const { spawn } = require('child_process')
const vlcPath = path.normalize('C:\\Program Files\\VideoLAN\\VLC\\vlc.exe')
const vlc = spawn(vlcPath, ['-'])
xdccJS.on('ready', async () => {
const Job = await xdccJS.download('bot', 155)
// send data to VLC that plays the file
Job.on('pipe', stream => {
stream.pipe(vlc.stdin)
})
})
// event triggered when all jobs are done.
xdccJS.on('can-quit', () => {
xdccJS.quit() // this is how you disconnect from IRC
})
xdccJS uses @kiwiirc/irc-framework client which is entirely accessible via the irc
property.
Check their client API documentation
// middlewares
xdccJS.irc.use(middleware)
xdccJS.on('ready', () => {
// change nickname
xdccJS.irc.changeNick('new-nickname')
// listen to kick events
xdccJS.irc.on('kick', (info) => {
//=> do something..
})
})
An extended version of this example is available here
npm install xdccjs -g
Options:
-V, --version output the version number
-h, --host <server> IRC server hostname
--port <number> IRC server port
-b, --bot <botname> xdcc bot nickname
-d, --download <packs...> pack number(s) to download
-p, --path <path> download path
-n, --nickname <nickname> Your IRC nickname
-c, --channel [chan...] channel(s) to join (without #)
-r, --retry <number> number of attempts before skipping pack
-q, --quiet disable console output
--passive-port <number> port used for passive dccs
--no-randomize Disable nickname randomization
-w, --wait [number] wait time (in seconds) in channel(s) before sending download request (default: 0)
--no-secure Allow files sent by bot with different name than the one requested
--save-profile [string] save current options as a profile
--delete-profile [string] delete profile
--set-profile [string] set profile as default
--list-profile list all available profiles
--help display help for command
xdccJS --host irc.server.net --bot "XDCC-BOT|BLUE" --download 1-5,100-105 --path "/home/user/downloads"
Alternatively, if you want to pipe the file just ommit the --path
option :
xdccJS --host irc.server.net --bot "XDCC-BOT|RED" --download 110 | vlc -
I recommend using double quotes between the bot name
and download path
as they often both include unescaped characeters or whitespaces
You can use profiles to automatically load predefined options on startup
Save a predefined set of options:
# save a profile with name "my_profile"
xdccJS --save-profile "my_profile" --host "irc.server.net" --port "6669" --path "C:/Users/JiPaix/Desktop"
# use "my_profile" settings
xdccJS --bot "XDCC|BOT" --download "1132-1137"
You can override profile settings:
# use "my_profile" profile, change download path
xdccJS --bot "XDCC|BOT" --download "1132-1137" --path "/home/user/new/path"
If a profile provide at least a --host
you can use the lazy mode:
xdccJS "/msg XDCC|BOT xdcc send 1132-1337" # quotes are important here
xdccJS --save-profile "my_profile" --host "irc.server.net" --port 6669 --path "C:/Users/username/Desktop"
Saved profile are automatically set as default.
xdccJS --set-profile "my_profile"
xdccJS --delete-profile "my_profile"
xdcJS --list-profile
- hashtags for channels and packs are optional :
-
--channel "#my-channel" --download "#132" # is the same as --channel "my-channel" --download "132"
-
- given options prevails over the one provided by profiles :
- except for
--host
, which results in xdccJS ignoring the current profile - example:
# current profile has --wait 5, but this time you need --wait 50 xdccJS --bot "mybot" --download "125-130" --wait 50
# ignores ALL profile options xdccJS --host "irc.mywnewserver.org"
- except for
- options
--bot
and--path
often contains special characters and/or whitespaces :-
# this wont work --path /home/user/my folder --bot XDCC|BOT --download 123-125 # fixed --path "/home/user/my folder" --bot "XDCC|BOT" --download 123-125
-
Full documentation is available here