Modifications to module system:

* Renamed Module to JanetModule to reduce chance of clashes with NodeJS module
* Changes to event dispatcher - different PubSub instances for each type of event
* Fixed issues with arguments and scoping when modules triggered
This commit is contained in:
Lewis Dale 2017-02-03 23:00:23 +00:00
parent 4c55837193
commit 7b48f9bc21
6 changed files with 92 additions and 27 deletions

View File

@ -1,10 +1,10 @@
{ {
"irc": { "irc": {
"server": "jfc.im", "server": "localhost",
"port": 6697, "port": 6667,
"user": "Janet", "user": "Janet",
"channels": [ "channels": [
"#team2" "#botchannel"
] ]
} }
} }

View File

@ -1,15 +1,18 @@
const fs = require('fs') const fs = require('fs')
const irc = require('irc') const irc = require('irc')
const PubSub = require('pubsub-js')
const MessagePubSub = require('pubsub-js')
class Janet { class Janet {
constructor() { constructor() {
this.config = this.loadConfig() this.config = this.loadConfig()
this.modules = {
'pm': [], this.events = {
'join': [], 'join': require('pubsub-js'),
'message': [] 'message': require('pubsub-js')
} }
this.loadModules() this.loadModules()
@ -21,6 +24,20 @@ class Janet {
} }
) )
this.client.addListener('message', (from, to, message) => {
if(message.substr(0,6) === "Janet,") {
let command = message.replace('Janet, ','').trim()
this.events.message.publish(command, {
from: from,
to: to,
message: message
})
}
})
this.client.addListener('join', (channel, who) => {
PubSub.publish('join', who)
})
} }
/** /**
@ -37,19 +54,29 @@ class Janet {
loadModules() { loadModules() {
let files = fs.readdirSync('modules') let files = fs.readdirSync('modules')
for (let file of files) { for (let file of files) {
if (file.substr(-3) === '.js') { if (file.substr(-3) === '.js') {
let title = file.substr(0, file.length - 3) let title = file.substr(0, file.length - 3)
if (title !== 'module') { if (title !== 'janetmodule') {
let module = require('./modules/' + title) let module = require('./modules/' + title)(this)
for(let method of module.methods) { for(let method of module.methods) {
if (method in this.modules) { this.events[method].subscribe(module.command, (...args) => {
this.modules[method].push(module) module.respond(...args) })
} }
} }
} }
} }
} }
/**
* Says a phrase across all of the joined channels
*/
say(phrase) {
for (let channel of this.config.irc.channels) {
this.client.say(channel, phrase)
}
} }
} }

View File

@ -1,21 +1,27 @@
const Module = require('./module') const JanetModule = require('./janetmodule')
class Greet extends Module { /**
* A simple greet module that says a friendly hello when somebody joins
* @author Lewis Dale
*/
class Greet extends JanetModule {
constructor() { constructor(client) {
super({ super({
name: 'Greet', name: 'Greet',
showInHelp: false, showInHelp: false,
command: 'Hello', command: 'join',
methods: ['join'] methods: ['join']
}) }, client)
this.test = {}
} }
respond(input) { respond(event, who) {
return "Hello, " + input if (who !== "Janet") {
this.client.say("Hello, " + who)
}
} }
} }
module.exports = new Greet() module.exports = (client) => {
return new Greet(client)
}

View File

@ -1,4 +1,4 @@
class Module { class JanetModule {
/** /**
* Construct a new Modules instance * Construct a new Modules instance
@ -8,7 +8,7 @@ class Module {
* @param opts.command: The command that triggers the action * @param opts.command: The command that triggers the action
* @param opts.methods: A list of contact methods where the command is available * @param opts.methods: A list of contact methods where the command is available
*/ */
constructor(opts = {}) { constructor(opts = {}, client) {
let keys = [ let keys = [
'name', 'name',
'showInHelp', 'showInHelp',
@ -22,6 +22,11 @@ class Module {
} }
this[key] = opts[key] this[key] = opts[key]
if (client === undefined || client === null) {
throw new TypeError("Client object was not passed to the module")
}
this.client = client
} }
} }
@ -30,9 +35,9 @@ class Module {
* Response to the input, triggered by the command * Response to the input, triggered by the command
* @return A string response * @return A string response
*/ */
respond(input) { respond() {
throw new TypeError("Function respond has not been implemented. Please override Module.respond()") throw new TypeError("Function respond has not been implemented. Please override Module.respond()")
} }
} }
module.exports = Module module.exports = JanetModule

25
modules/time.js Normal file
View File

@ -0,0 +1,25 @@
const JanetModule = require('./janetmodule')
/**
* A simple command to ask Janet the current time
* @author Lewis Dale
*/
class Time extends JanetModule {
constructor(client) {
super({
name: 'Time',
showInHelp: true,
command: 'what time is it?',
methods: ['message']
}, client)
}
respond(event, data) {
let date = new Date()
this.client.say(data.from + ", it is currently " + date.toTimeString())
}
}
module.exports = (client) => {
return new Time(client)
}

View File

@ -4,6 +4,7 @@
"description": "A NodeJS-based IRC bot", "description": "A NodeJS-based IRC bot",
"main": "janet.js", "main": "janet.js",
"scripts": { "scripts": {
"start": "node janet.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
@ -17,6 +18,7 @@
"author": "Lewis Dale <lewis@lewisdale.co.uk>", "author": "Lewis Dale <lewis@lewisdale.co.uk>",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"irc": "^0.5.2" "irc": "^0.5.2",
"pubsub-js": "^1.5.4"
} }
} }