dbothook
Version:
Discord bot list poster and stats retriever
153 lines (135 loc) • 4.9 kB
JavaScript
const EventEmitter = require('eventemitter3');
const express = require('express');
const path = require('path');
const fs = require('fs');
/**
* A class that posts server count to listing site(s).
* @constructor
* @param {HookOptions} [options] The options needed to construct the hook
*/
class DBotHook extends EventEmitter {
constructor(options = {}) {
super();
if (typeof options !== 'object')
throw new Error('The options are not in an object.');
/**
* Whether or not endpoints has been added
* @type {boolean}
*/
this.endpointsAdded = false;
/**
* The authorization secrets the hook is using
* @type {AuthorizationSecrets}
*/
this.authSecrets = options.authSecrets || {};
/**
* The express application being used
* @type {Express}
*/
this.app = options.app || express();
/**
* The server created from {@link #listen}
* @type {Server}
*/
this.server = null;
}
/**
* Loads endpoints into the application
* @param {string} [prefix='/'] The prefix to add before the path (which would be the {@link ServiceKey})
*/
addEndpoints(prefix = '/') {
if (this.endpointsAdded) return;
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: true }));
// Load all endpoints from the "endpoints" folder
const endpoints = fs.readdirSync(path.join(__dirname, './endpoints'));
for (let i = 0; i < endpoints.length; i++) {
const endpointClass = require(path.join(__dirname, './endpoints', endpoints[i]));
const endpoint = new endpointClass(this);
this.app.use(prefix + endpoint.name, endpoint.createRoute());
}
this.endpointsAdded = true;
}
/**
* Convenience method for app.listen()
* @param {...any} args The args that are sent to the application
* @see https://expressjs.com/en/4x/api.html#app.listen
*/
listen(...args) {
if (!this.endpointsAdded) this.addEndpoints();
return this.server = this.app.listen(...args);
}
}
module.exports = DBotHook;
/**
* A key that a service uses to identify itself. Available services:
* * arcanebotcenter
* * botlistspace
* * botsfordiscord
* * discordboats
* * discordbotlist
* * glennbotlist
* * listmybots
* * mythicalbots
* * topgg
* @typedef {string} ServiceKey
*/
/**
* The type of event the {@link RichEvent} is. This would be most commonly `vote`.
* * vote
* * like (from listmybots)
* * unlike (from listmybots)
* @typedef {string} RichEventType
*/
/**
* An object that includes authorization secrets for all botlists.
* Each key can either have a secret or be `true` to accept *all* requests regardless of authorization.
*
* Note: `arcanebotcenter` and `botlistspace` gives you a secret instead of setting one.
* @typedef {Object.<ServiceKey, string|boolean>} AuthorizationSecrets
*/
/**
* Options for a hook.
* @typedef {Object} HookOptions
* @property {AuthorizationSecrets} [authSecrets] The authorization secrets the hook will use
* @property {Express} [app] The application to use, will initiate a new application if not defined
*/
/**
* A generic event object.
* @typedef {Object} Event
*
* These properties need to be synched with RichEvent and ErrorEvent.
* There is no JSDoc way of extending typdefs that compiles into an extended interface in TS
* or that is correctly read as an extension by the docs website.
* @property {ServiceKey} list The service endpoint this event occured in
* @property {Request} request The request that emitted this event
*/
/**
* An event object that is returned and parsed at the end of an endpoint call.
* See the README.md of dbothook.js to see which service returns what values.
* @typedef {Object} RichEvent
*
* These properties are from the Event typedef:
* @property {ServiceKey} list The service endpoint this event occured in
* @property {Request} request The request that emitted this event
*
* @property {Object} data The raw data that the service posted
* @property {number} timestamp The time when this event was emitted
* @property {RichEventType} type The type of event
* @property {boolean} test Whether or not the event was a test sent from the service.
* Make sure you check this first before processing anything.
* @property {string} userId The user's ID that emitted the event
* @property {string} [botId] The bot's ID that the user is calling the event towards
* @property {string} [username] The user's username
* @property {string} [discriminator] The user's discriminator (i.e. `#0001`)
*/
/**
* A event emitted after an error.
* @typedef {Object} ErrorEvent
*
* These properties are from the Event typedef:
* @property {ServiceKey} list The service endpoint this event occured in
* @property {Request} request The request that emitted this event
*
* @property {Error} error The error that occurred
*/