responder.js

'use strict';

const bindLogger = require('./util/bind-logger');
const defaults = require('lodash/defaults');
let Bot; // Not set here to get around circular dependency

/**
 * Class representing a bot responder.
 */
class Responder {

	/**
	 * Create a bot responder.
	 * @param {Object} options - The responder options.
	 * @param {(String|Alias)} [options.alias] - The alias to respond with. This must be either an {@link Alias} or the name of one registered the bot.
	 */
	constructor(options) {
		if (this.constructor === Responder) {
			throw new Error('You cannot create an instance of Responder, it is designed to be extended');
		}
		this.options = defaults({}, options, Responder.defaults);
	}

	/**
	 * Register the responder to a bot.
	 * @access private
	 * @param {Bot} bot - The bot to register to.
	 * @returns {Responder} The calling responder instance.
	 * @throws {TypeError} Will throw if bot is not an instance of Bot.
	 */
	registerToBot(bot) {

		// NOTE: Bot is required here to get around a
		// circular dependency when the module is loaded
		Bot = Bot || require('./bot');

		if (!(bot instanceof Bot)) {
			throw new TypeError('Expected an instance of Bot');
		}

		this.bot = bot;
		this.log = bindLogger(bot.log, `${this.constructor.name}:`);

		return this;
	}

	/**
	 * Create a {@link Response} object which is ready to respond to an incoming message.
	 * @param {Object} message - The Slack message to create a response for.
	 * @returns {Response} The prepared response.
	 */
	respond(message) {
		const response = this.bot.replyTo(message);
		if (this.options.alias) {
			response.as(this.options.alias);
		}
		return response;
	}

	/**
	 * Get the responder as a string, for use in implicit type conversion.
	 * @access private
	 * @returns {String} The string representation.
	 */
	valueOf() {
		return `[object ${this.constructor.name}]`;
	}

	/**
	 * Get the responder as a plain object, for use in JSON conversion.
	 * @access private
	 * @returns {Object} The responder as a plain object.
	 */
	toJSON() {
		return this.options;
	}

	/**
	 * Get console-friendly representation of the responder.
	 * @access private
	 * @returns {String} The console-friendly representation.
	 */
	inspect() {
		return `${this.constructor.name} {}`;
	}

}

/**
 * The default options used when constructing a responder.
 * @static
 */
Responder.defaults = {};

module.exports = Responder;