npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

xdccjs

v5.4.11

Published

download files from XDCC bots on IRC, complete implementation of the XDCC protocol

Downloads

278

Readme

Features :

xdccJS is a complete implementation of the XDCC protocol for nodejs.
It can also be used as a command-line downloader !

Table of contents

Installation

NPM

API

Getting started

There's three different way to import/require xdccJS depending on which environment it is running:

CommonJS

const XDCC = require('xdccjs')
const xdccJS = new XDCC.default({/*..options..*/})

Modules

import XDCC from 'xdccjs'
const xdccJS = new XDCC.default({/*..options..*/})

TypeScript

import XDCC from 'xdccjs'
const xdccJS = new XDCC({/*..options..*/})

Example

const XDCC = require('xdccjs')

const xdccJS = new XDCC.default({
  host: 'irc.server.net',
  port: 6667,
  chan: ['#welcome', '#fansub'],
  nickname: 'Leon',
  path: '/home/leon/downloads'
})

xdccJS.on('ready', () => {
  xdccJS.download('XDCC|BOT_RED', 5)
  xdccJS.download('XDCC|BOT_GREEN', '1-3, 55, 100-200')
  xdccJS.download('XDCC|BOT_BLUE', [12, 7, 10, 20])
  xdccJS.download('XDCC|BOT_ALPHA', ['5', '6'])
})

Options

Every parameter is optional, except for host.

const opts = {
  host: 'irc.server.net', // IRC hostname                                                   - required
  port: 6660, // IRC port                                                                   - default: 6667
  tls: {
    enable: true, // Enable TLS Support                                                     - default: false
    rejectUnauthorized: true, // Reject self-signed certificates                            - default: false
  },
  nickname: 'ItsMeJiPaix', // Nickname                                                      - default: xdccJS + random
  nickServ: 'complex_password', // Your NickServ password (no spaces)                       - default: undefined (disabled)
  chan: ['#candy', '#fruits'], // Array of channels                                         - default : [ ] (no chan)
  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]
  botNameMatch: false, // Block downloads if the bot's name does not match the request      - default: true
  throttle: 500, // Throttle download speed to n KiB/s                                       - default: undefined (disabled)
  queue: /soMething(.*)maTching/g //                                                        - default: undefined (disabled)
  // ^ Regex matching the bot's message when you're request is moved to a queue    
}

Config

xdccJS.config( parameters? : object ) change parameters during runtime
If there's a file downloading throttle and passivePort won't be applied until the next download

xdccJS.config({
  passivePort: [5000, 5001, 5002],
  throttle: 800,
  nickname: 'TrustMe',
  chan: ['#candy', '#fruits'], 
  path: 'download/subfolder',
  botNameMatch: false,
  retry: 5,
  timeout: 50,
  verbose: false,
  randomizeNick: true,
  queue: /soMething(.*)maTching/g
})

Download

xdccJS.download( bot : string, packets : string | number | number[] | string[], options?: { ipv6?: boolean ** throttle?: number } )
download() is asynchronous and returns a Job
options are optional, per job options.ipv6 parameter is only required when if a bot's is ipv6 AND uses passive DCC

xdccJS.on('ready', async () => {
  const blue = await xdccJS.download('XDCC|BLUE', '1-3, 8, 55')
  const yellow = await xdccJS.download('XDCC|YELLOW', 4)
  const red = await xdccJS.download('XDCC|RED', [12, 7, 10, 20])
  const purple = await xdccJS.download('XDCC|PURPLE', ['1', '3', '10', '20'])
})

Download queue detection

xdccJS will timeout any request after a certain amount of time when no file is sent (see Options.timeout), Which is exactly what happens when a bot puts you into queue.

To avoid this behavior you need to provide a regex matching the bot "queue message".

If you are clueless about regexes try regexlearn.com interactive tutorial.

const opts = {
  host: 'irc.server.com',
  timeout: 20 // defaut is 30
  queue: /request(.*)queued(.*)\d+\/\d+$/gi
  //=> excepted bot queue message: "Your request has been queued: position x/x"
}
const xdccJS = new XDCC(opts)

xdccJS.on('ready', async () =>{
  const queued = await xdccJS.download('BOT_WITH_LARGE_QUEUE', '1-5')
  //=> if the bot sends a message matching the regex, download won't fail
})

Jobs

Jobs are download() instances which are tied to the target nickname.
calling download() multiple times for the same target will update current job.

xdccJS.on('ready', async () => {
  // jobs are automatically updated
  const botA_1 = await xdccJS.download('BOT-A', 1)
  const botA_2 = await xdccJS.download('BOT-A', 2)
  const botA_3 = await xdccJS.download('BOT-A', 3)
  // botA_1 === botA_2 === botA_3


  // but each "target" has its own job
  const botB_1 = await xdccJS.download('DIFFERENT_TARGET', 4)
  // botA_1 !== botB_1

  // once a job's done, its lifetime ends
  botA_1.on('done', async () => {
    const botA_5 = await xdccJS.download('BOT-A', 5)
    // botA_1 !== botA_5
  })

  // Job options are overwritable
  await xdccJS.download('BOT-B', 1, { throttle: 500 })
  await xdccJS.download('BOT-B', 2, { throttle: 1000 })
  // => Both packets, 1 and 2, will be throttled at 1000 (latest)
})

You can also retrieve on going 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()

Jobs offer three options :

  1. Get job progress status :
    let status = job1.show()
    let isdone = job1.isDone()
    console.log(status)
    //=> { name: 'a-bot', queue: [98], now: 62, success: ['file.txt'], failed: [50] }
    console.log(isdone)
    //=> false
  2. Cancel a Job
    job2.cancel()
  3. Events to track progress (see events documentation)
    job.on('downloaded', (fileInfo) => {
      //=> a file has been downloaded
    })
    
    job.on('done', () => {
      //=> job has finished downloading all requested packages
    })
    
    // more below..

Events

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, eta) => {
        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, eta) => {
        console.log(`${percentage}% - ${eta} ms remaining`) //=> 10.55% - 153500 ms remaining
      })

[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, success: ['file.txt'], failed: [50] }
      })
    
      job.on('done', (job) => {
        console.log('Job2 is done!')
        console.log(job.show())
          //=> { name: 'a-bot', queue: [98], now: 62, success: ['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 }
      })

[Job].on( 'cancel' ) : Job canceled by user

  •   job.on('cancel', (message) => {
        console.error(message) //=> "cancelled by user"
      })

[xdccJS].on( 'debug' ) : debug message

  •   xdccJS.on('debug', (message) => {
        console.info(message)
      })

Pipes

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)
  })
})

Disconnect

// event triggered when all jobs are done.
xdccJS.on('can-quit', () => {
  xdccJS.quit() // this is how you disconnect from IRC
})

Advanced IRC commands

@kiwiirc/irc-framework is embed into xdccJS.
Check their client API documentation


xdccJS.on('ready', () => {
  // change nickname
  xdccJS.changeNick('new-nickname')
  // listen to kick events
  xdccJS.on('kick', (info) => {
    //=> do something..
  })
})

An extended version of this example is available here

Command-line Interface

Installation

npm install xdccjs -g

CLI Options

-V, --version              output the version number
-h, --host <server>        IRC server hostname - required
--port <number>            IRC server port - default: 6667
-n, --nickname <nickname>  Your nickname - default: xdccJS
--no-randomize             Disable nickname randomization - default: randomize
-c, --channel <chans...>   Channel(s) to join - optional
-p, --path <path>          Download path - optional
-b, --bot <botname>        XDCC bot nickname - required
-d, --download <packs...>  Packs to download - required
--throttle <number>        Throttle download speed (KiB/s) - default disabled
--nickserv <password>      Authenticate to NickServ - default: disabled
--passive-port <number>    Port to use for passive dccs - optional
--ipv6                     Use IPv6, only required if bot use both passive dcc and IPv6 - default: disabled
-r, --retry <number>       Number of attempts before skipping pack - optional
-t --timeout <number>      Time in seconds before a download is considered timed out - optional
-w, --wait <number>        Time to wait before sending download request - optional
--no-bot-name-match        Allow downloads from bot with nickname that doesn't match the request - optional
--queue <RegExp>           Regex to determine if the bot queued the request - optional
--tls                      enable SSL/TLS - optional
--no-insecure              Reject self-signed SSL/TLS certificates - optional
--save-profile <string>    save current options as a profile - optional
--delete-profile <string>  delete profile - optional
--set-profile <string>     set profile as default - optional
--list-profile             list all available profiles - optional
-q, --quiet                Disable console output - optional
--help                     display help for command

Usage

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 quotation marks between the bot name and download path as they often both include unescaped characeters or whitespaces, They are mandatory when using between --queue's regex (see examples below)

Profiles

You can use profiles to automatically load predefined options on startup

How to use profiles

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

Save Profile

xdccJS --save-profile "my_profile" --host "irc.server.net" --port 6669 --path "C:/Users/username/Desktop"

Saved profile are automatically set as default.

Change default profile

xdccJS --set-profile "my_profile"

Delete profile

xdccJS --delete-profile "my_profile"

List available profiles

 xdcJS --list-profile 

FYI

  • 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
      ```
    ```bash
        # ignores ALL profile options
        xdccJS --host "irc.mywnewserver.org"
  • 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 
  • an example with --queue regex:
  •     xdccJS --host "irc.server.com" --bot "SOME_BOT" --download "1-100" --queue "/request(.*)queued(.*)\d+\/\d+$/gi"
        # excepted bot queue message: "Your request has been queued: position x/x"
  • see why is queue important

Documentation

Full documentation is available here