UNPKG

bots

Version:

Build robust networks of bots that can react to events

190 lines (163 loc) 5.74 kB
# The main `Bot` class that all robots are created from, this contains the # main functions for assembling a bot. {EventEmitter} = require 'events' request = require 'request' fs = require 'fs' # Get the current version from `package.json`. exports.version = JSON.parse(fs.readFileSync(__dirname + "/../package.json")).version # Factory method for creating a new `Bot` instance. Accepts a name # argument, which is the name given to the bot. # # var bots = require('bots'); # # var coolbot = bots.createBot('coolbot 1.0.0'); # exports.createBot = (name) -> new Bot name # The `Bot` class, inherits from `EventEmitter` so it can notify plugins of # certain lifecycle events. exports.Bot = class Bot extends EventEmitter # Creates a new `Bot` with the given name. Sets up the bot ready to be # configured. constructor: (@name) -> @handlers = [] @interfaces = [] @descriptions = {} setup: (nickname, callback) -> if typeof(nickname) is 'function' callback = nickname else @nickname = nickname callback @desc, @hear # Adds a description of a piece of the robots functionality, this is used # for the robots builtin `help` phrase. # # * **phrase** - The String representing the phase the bot recognises. # * **functionality** - The String describing the phrase (optional). # # #### Example # # bot.desc('image me THING', 'Get a random image of THING'); # desc: (phrase, functionality) => @descriptions[phrase] = functionality # Add a `pattern` to the robots repotoire. This is matched against incoming # messages and if they match then the message is passed to `callback`. # # * **pattern** - The RegEx to match against the message body. # * **callback** - The Function to be invoked when the pattern is matched. # # #### Example # # bot.hear(/ping/, function(message) { # message.say('PONG'); # }); # hear: (pattern, callback) => @handlers.push [pattern, callback] # Add an interface to the robot. This is allows the 'bot to communicate # with the outside world. See the `Cli` and `XMPP` interfaces for examples, # the interface should inherit from EventEmitter, and emit a `message` # event when there is a new message on the interface. # # var bots = require('bots'); # var coolbot = bots.createBot('coolbot 1.0.0'); # coolbot.use(bots.cli()); # use: (interface) -> @interfaces.push interface interface.on 'message', @dispatch # Dispatches an incoming message to any handlers that match the message # body. This can be used to fake message to the bot, useful for testing # the bot. Takes a `message` object with `body` and `say` properties. # # coolbot.dispatch({ # message: 'ping', # say: function(text, callback) { # console.log(text); # callback(); # } # }); # dispatch: (message) => for pair in @handlers if @nickname continue unless message.body.match(new RegExp("^#{@nickname}")) [ pattern, handler ] = pair handler.call(@, message) if message.match = message.body.match(pattern) # Start the bot up, calls listen on the registered interfaces. This registers # the **help** phrase that the bot will always repond to. Emits a `start` # event when setup is complete. # # coolbot.on('start', function() { # console.log("coolbot started"); # }); # coolbot.start(); # start: -> interface.listen() for interface in @interfaces @hear /help/, @help @emit 'start' stop: (finished) -> console.log "\nStopping #{@name}" closing = @interfaces.length for interface in @interfaces interface.close -> finished() if --closing is 0 # Reset the bot's `handlers` and `descriptions`, note this does not stop # the registered interfaces from listening. reset: (callback) -> @handlers = [] @descriptions = [] callback?() # Helper method for making a `GET` request, proxies to the `request` # method. get: (uri, body, callback) -> @request('GET', uri, body, callback) # Helper method for making a `POST` request, proxies to the `request` # method. post: (uri, body, callback) -> @request('POST', uri, body, callback) # Handler for the default help action, gathers all of the registered # descriptions and sends a message describing each action. help: (message) -> if Object.keys(@descriptions).length is 0 return message.say "I do not have any actions yet." message.say "I listen for the following…", => for phrase, functionality of @descriptions if functionality output = phrase + ": " + functionality else output = phrase message.say output # Helper to make http requests, tries to automatically handle JSON input and # output. request: (method, uri, body, callback) -> options = { method: method, uri: uri } options.headers = { 'User-Agent': @name } if typeof(body) is 'function' and not callback callback = body body = null if typeof body is 'string' options.body = body else options.json = body request options, (err, response, body) -> try body = JSON.parse body catch e # Ignore and pass through the raw body. callback? body, response # Command line interface. exports.cli = -> Cli = require './interfaces/cli' new Cli # Campfire interface. exports.campfire = (args...) -> Campfire = require './interfaces/campfire' new Campfire args... # XMPP interface. exports.xmpp = (args...) -> Xmpp = require './interfaces/xmpp' new Xmpp args... exports.generate = require './generator'