From e544c909ecd2f07c311500dfa475e605e65152c7 Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Mon, 24 Dec 2012 05:47:47 +0000 Subject: [PATCH] Modularised web routes and views --- modules/poll/poll.js | 28 ++++++- modules/quotes/quotes.js | 24 ++++++ modules/users/users.js | 61 ++++++++++++++ modules/web/web.js | 123 ++++++----------------------- run.js | 24 ++++++ views/{ => poll}/polllist.jade | 2 +- views/poll/polls.jade | 39 +++++++++ views/polls.jade | 36 --------- views/{ => quotes}/quotelist.jade | 2 +- views/{ => quotes}/quotes.jade | 2 +- views/{ => users}/channels.jade | 2 +- views/{ => users}/connections.jade | 2 +- views/{ => users}/user.jade | 2 +- views/{ => users}/users.jade | 2 +- 14 files changed, 204 insertions(+), 145 deletions(-) rename views/{ => poll}/polllist.jade (94%) create mode 100644 views/poll/polls.jade delete mode 100644 views/polls.jade rename views/{ => quotes}/quotelist.jade (94%) rename views/{ => quotes}/quotes.jade (98%) rename views/{ => users}/channels.jade (93%) rename views/{ => users}/connections.jade (91%) rename views/{ => users}/user.jade (95%) rename views/{ => users}/users.jade (94%) diff --git a/modules/poll/poll.js b/modules/poll/poll.js index 8c79a02..988664f 100644 --- a/modules/poll/poll.js +++ b/modules/poll/poll.js @@ -216,11 +216,37 @@ var poll = function(dbot) { commands['~vote'].regex = [/~vote ([^ ]+) ([^ ]+)/, 3]; commands['~pdesc'].regex = [/~pdesc ([^ ]+)/, 2]; commands['~count'].regex = [/~count ([^ ]+)/, 2]; + + var pages = { + // Shows the results of a poll + '/polls/:key': function(req, res) { + var key = req.params.key.toLowerCase(); + if(dbot.db.polls.hasOwnProperty(key) && dbot.db.polls[key].hasOwnProperty('description')) { + // tally the votes + var totalVotes = 0; + for( var v in dbot.db.polls[key].votes ) { + var N = Number(dbot.db.polls[key].votes[v]); + if( !isNaN(N) ) { + totalVotes += N; + } + } + res.render('polls', { 'name': dbot.config.name, 'description': dbot.db.polls[key].description, 'votees': Object.keys(dbot.db.polls[key].votees), 'options': dbot.db.polls[key].votes, locals: { 'totalVotes': totalVotes, 'url_regex': RegExp.prototype.url_regex() } }); + } else { + res.render('error', { 'name': dbot.config.name, 'message': 'No polls under that key.' }); + } + }, + + // Lists all of the polls + '/polls': function(req, res) { + res.render('polllist', { 'name': dbot.config.name, 'polllist': Object.keys(dbot.db.polls) }); + }, + }; return { 'name': 'poll', 'ignorable': true, - 'commands': commands + 'commands': commands, + 'pages': pages }; }; diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 7d8b1f3..aa77ad6 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -267,10 +267,34 @@ var quotes = function(dbot) { commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2]; commands['~qadd'].regex = [/^~qadd ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; + var pages = { + // Lists quotes in a category + '/quotes/:key': function(req, res) { + var key = req.params.key.toLowerCase(); + if(dbot.db.quoteArrs.hasOwnProperty(key)) { + res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[key], locals: { 'url_regex': RegExp.prototype.url_regex() } }); + } else { + res.render('error', { 'name': dbot.config.name, 'message': 'No quotes under that key.' }); + } + }, + + // Show quote list. + '/quotes': function(req, res) { + res.render('quotelist', { 'name': dbot.config.name, 'quotelist': Object.keys(dbot.db.quoteArrs) }); + }, + + // Load random quote category page + '/rq': function(req, res) { + var rCategory = Object.keys(dbot.db.quoteArrs).random(); + res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[rCategory], locals: { 'url_regex': RegExp.prototype.url_regex() } }); + }, + }; + return { 'name': 'quotes', 'ignorable': true, 'commands': commands, + 'pages': pages, 'listener': function(event) { // Reality Once listener diff --git a/modules/users/users.js b/modules/users/users.js index d4f6afa..8f1a217 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -21,6 +21,65 @@ var users = function(dbot) { } }); + var pages = { + '/connections': function(req, res) { + var connections = Object.keys(dbot.instance.connections); + res.render('connections', { 'name': dbot.config.name, 'connections': connections }); + }, + + '/channels/:connection': function(req, res) { + var connection = req.params.connection; + if(dbot.instance.connections.hasOwnProperty(connection)) { + var channels = Object.keys(dbot.instance.connections[connection].channels); + res.render('channels', { 'name': dbot.config.name, 'connection': connection, 'channels': channels}); + } else { + res.render_core('error', { 'name': dbot.config.name, 'message': 'No such connection.' }); + } + }, + + '/users/:connection/:channel': function(req, res) { + var connection = req.params.connection; + var channel = '#' + req.params.channel; + var connections = dbot.instance.connections; + + if(connections.hasOwnProperty(connection) && + connections[connection].channels.hasOwnProperty(channel)) { + var nicks = Object.keys(connections[connection].channels[channel].nicks); + res.render('users', { 'name': dbot.config.name, 'connection': connection, + 'channel': channel, 'nicks': nicks }); + } else { + res.render_core('error', { 'name': dbot.config.name, 'message': 'No such connection or channel.' }); + } + }, + + '/user/:connection/:channel/:user': function(req, res) { + var connection = req.params.connection; + var channel = '#' + req.params.channel; + var user = dbot.cleanNick(req.params.user); + + var quoteCount = 'no'; + if(dbot.db.quoteArrs.hasOwnProperty(user)) { + var quoteCount = dbot.db.quoteArrs[user].length; + } + + if(!dbot.db.kicks.hasOwnProperty(req.params.user)) { + var kicks = '0'; + } else { + var kicks = dbot.db.kicks[req.params.user]; + } + + if(!dbot.db.kickers.hasOwnProperty(req.params.user)) { + var kicked = '0'; + } else { + var kicked = dbot.db.kickers[req.params.user]; + } + + res.render('user', { 'name': dbot.config.name, 'user': req.params.user, + 'channel': channel, 'connection': connection, 'cleanUser': user, + 'quotecount': quoteCount, 'kicks': kicks, 'kicked': kicked }); + }, + }; + return { 'name': 'users', 'ignorable': false, @@ -36,6 +95,8 @@ var users = function(dbot) { } } }, + + 'pages': pages, 'listener': function(event) { var knownUsers = getServerUsers(event); diff --git a/modules/web/web.js b/modules/web/web.js index 9fc3f3c..3f3b897 100644 --- a/modules/web/web.js +++ b/modules/web/web.js @@ -1,4 +1,5 @@ -var express = require('express'); +var express = require('express'), + fs = require('fs'); var webInterface = function(dbot) { var pub = 'public'; @@ -11,112 +12,32 @@ var webInterface = function(dbot) { res.render('index', { 'name': dbot.config.name }); }); - app.get('/connections', function(req, res) { - var connections = Object.keys(dbot.instance.connections); - res.render('connections', { 'name': dbot.config.name, 'connections': connections }); - }); - - app.get('/channels/:connection', function(req, res) { - var connection = req.params.connection; - if(dbot.instance.connections.hasOwnProperty(connection)) { - var channels = Object.keys(dbot.instance.connections[connection].channels); - res.render('channels', { 'name': dbot.config.name, 'connection': connection, 'channels': channels}); - } else { - res.render('error', { 'name': dbot.config.name, 'message': 'No such connection.' }); - } - }); - - app.get('/users/:connection/:channel', function(req, res) { - var connection = req.params.connection; - var channel = '#' + req.params.channel; - var connections = dbot.instance.connections; - - if(connections.hasOwnProperty(connection) && - connections[connection].channels.hasOwnProperty(channel)) { - var nicks = Object.keys(connections[connection].channels[channel].nicks); - res.render('users', { 'name': dbot.config.name, 'connection': connection, - 'channel': channel, 'nicks': nicks }); - } else { - res.render('error', { 'name': dbot.config.name, 'message': 'No such connection or channel.' }); - } - }); - - app.get('/user/:connection/:channel/:user', function(req, res) { - var connection = req.params.connection; - var channel = '#' + req.params.channel; - var user = dbot.cleanNick(req.params.user); - - var quoteCount = 'no'; - if(dbot.db.quoteArrs.hasOwnProperty(user)) { - var quoteCount = dbot.db.quoteArrs[user].length; - } - - if(!dbot.db.kicks.hasOwnProperty(req.params.user)) { - var kicks = '0'; - } else { - var kicks = dbot.db.kicks[req.params.user]; - } - - if(!dbot.db.kickers.hasOwnProperty(req.params.user)) { - var kicked = '0'; - } else { - var kicked = dbot.db.kickers[req.params.user]; - } - - res.render('user', { 'name': dbot.config.name, 'user': req.params.user, - 'channel': channel, 'connection': connection, 'cleanUser': user, - 'quotecount': quoteCount, 'kicks': kicks, 'kicked': kicked }); - }); - - // Lists the quote categories - app.get('/quotes', function(req, res) { - res.render('quotelist', { 'name': dbot.config.name, 'quotelist': Object.keys(dbot.db.quoteArrs) }); - }); - - // Lists quotes in a category - app.get('/quotes/:key', function(req, res) { - var key = req.params.key.toLowerCase(); - if(dbot.db.quoteArrs.hasOwnProperty(key)) { - res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[key], locals: { 'url_regex': RegExp.prototype.url_regex() } }); - } else { - res.render('error', { 'name': dbot.config.name, 'message': 'No quotes under that key.' }); - } - }); - - // Load random quote category page - app.get('/rq', function(req, res) { - var rCategory = Object.keys(dbot.db.quoteArrs).random(); - res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[rCategory], locals: { 'url_regex': RegExp.prototype.url_regex() } }); - }); - - // Lists all of the polls - app.get('/polls', function(req, res) { - res.render('polllist', { 'name': dbot.config.name, 'polllist': Object.keys(dbot.db.polls) }); - }); - - // Shows the results of a poll - app.get('/polls/:key', function(req, res) { - var key = req.params.key.toLowerCase(); - if(dbot.db.polls.hasOwnProperty(key) && dbot.db.polls[key].hasOwnProperty('description')) { - // tally the votes - var totalVotes = 0; - for( var v in dbot.db.polls[key].votes ) { - var N = Number(dbot.db.polls[key].votes[v]); - if( !isNaN(N) ) { - totalVotes += N; - } - } - res.render('polls', { 'name': dbot.config.name, 'description': dbot.db.polls[key].description, 'votees': Object.keys(dbot.db.polls[key].votees), 'options': dbot.db.polls[key].votes, locals: { 'totalVotes': totalVotes, 'url_regex': RegExp.prototype.url_regex() } }); - } else { - res.render('error', { 'name': dbot.config.name, 'message': 'No polls under that key.' }); - } - }); app.listen(dbot.config.web.webPort); + var reloadPages = function(pages) { + for(var p in pages) { + if( pages.hasOwnProperty(p) ) { + var func = pages[p]; + var mod = func.module; + app.get(p, (function(req, resp) { + // Crazy shim to seperate module views. + var shim = Object.create(resp); + shim.render = (function(view, one, two) { + // Render with express.js + resp.render(this.module.name + '/' + view, one, two); + }).bind(this); + shim.render_core = resp.render; + this.call(this.module, req, shim); + }).bind(func)); + } + } + }; + return { 'name': 'web', 'ignorable': false, + 'reloadPages': reloadPages, 'onDestroy': function() { app.close(); diff --git a/run.js b/run.js index 26ddcea..f773749 100644 --- a/run.js +++ b/run.js @@ -118,6 +118,7 @@ DBot.prototype.reloadModules = function() { this.rawModules = []; this.modules = []; + this.pages = {}; this.commands = {}; this.commandMap = {}; // Map of which commands belong to which modules this.usage = {}; @@ -168,6 +169,8 @@ DBot.prototype.reloadModules = function() { var module = rawModule.fetch(this); this.rawModules.push(rawModule); + module.name = name; + if(module.listener) { var listenOn = module.on; if(!(listenOn instanceof Array)) { @@ -194,6 +197,18 @@ DBot.prototype.reloadModules = function() { } } + // Load module web bits + if(module.pages) { + var newpages = module.pages; + for(var key in newpages) + { + if(newpages.hasOwnProperty(key) && Object.prototype.isFunction(newpages[key])) { + this.pages[key] = newpages[key]; + this.pages[key].module = module; + } + } + } + // Load the module usage data try { var usage = JSON.parse(fs.readFileSync(moduleDir + 'usage.json', 'utf-8')); @@ -237,9 +252,18 @@ DBot.prototype.reloadModules = function() { } } }.bind(this)); + this.reloadPages(); this.save(); }; +DBot.prototype.reloadPages = function() { + for( var m in this.modules ) { + if( Object.prototype.isFunction(this.modules[m].reloadPages)) { + this.modules[m].reloadPages(this.pages); + } + } +} + DBot.prototype.cleanNick = function(key) { key = key.toLowerCase(); while(key.endsWith("_")) { diff --git a/views/polllist.jade b/views/poll/polllist.jade similarity index 94% rename from views/polllist.jade rename to views/poll/polllist.jade index 128458a..1623492 100644 --- a/views/polllist.jade +++ b/views/poll/polllist.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content div#backlink diff --git a/views/poll/polls.jade b/views/poll/polls.jade new file mode 100644 index 0000000..80e25f6 --- /dev/null +++ b/views/poll/polls.jade @@ -0,0 +1,39 @@ +extends ../layout + +block content + div#backlink + a(href='/polls/') « Poll list + h2 #{description} + p Voters (#{locals.totalVotes}): + -each voter in votees + | #{voter} + ul#votelist + -var hasYouTubeVids=false + -each votes,option in options + -var percentage = votes/locals.totalVotes*100 + -if(options.hasOwnProperty(option)) + -if(option.match(locals.url_regex)) + li.option + -if(option.match(/(jpg|png|gif|jpeg|tiff)$/)) + a(href=option) + img(src=option) + -else if(option.match(/youtube.com\/watch/)) + -hasYouTubeVids = true + span(class='ytplaceholder') + =option + -else + a(href=option) + =option + -else + li.option #{option} + li.option-votes + .vote-track + -if(!isNaN(percentage)) + .vote-percentage(style="width: #{percentage}%") + case votes + when 1: #{votes} vote + default: #{votes} votes + -if(!isNaN(percentage)) + |(#{percentage.toFixed(2)}%) + -if(hasYouTubeVids) + script(src='/ytembed.js') diff --git a/views/polls.jade b/views/polls.jade deleted file mode 100644 index 504f3d3..0000000 --- a/views/polls.jade +++ /dev/null @@ -1,36 +0,0 @@ -div#backlink - a(href='/polls/') « Poll list -h2 #{description} -p Voters (#{locals.totalVotes}): - -each voter in votees - | #{voter} -ul#votelist - -var hasYouTubeVids=false - -each votes,option in options - -var percentage = votes/locals.totalVotes*100 - -if(options.hasOwnProperty(option)) - -if(option.match(locals.url_regex)) - li.option - -if(option.match(/(jpg|png|gif|jpeg|tiff)$/)) - a(href=option) - img(src=option) - -else if(option.match(/youtube.com\/watch/)) - -hasYouTubeVids = true - span(class='ytplaceholder') - =option - -else - a(href=option) - =option - -else - li.option #{option} - li.option-votes - .vote-track - -if(!isNaN(percentage)) - .vote-percentage(style="width: #{percentage}%") - case votes - when 1: #{votes} vote - default: #{votes} votes - -if(!isNaN(percentage)) - |(#{percentage.toFixed(2)}%) - -if(hasYouTubeVids) - script(src='/ytembed.js') diff --git a/views/quotelist.jade b/views/quotes/quotelist.jade similarity index 94% rename from views/quotelist.jade rename to views/quotes/quotelist.jade index df97c7b..d038e0a 100644 --- a/views/quotelist.jade +++ b/views/quotes/quotelist.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content div#backlink diff --git a/views/quotes.jade b/views/quotes/quotes.jade similarity index 98% rename from views/quotes.jade rename to views/quotes/quotes.jade index 38c73e1..a40d12e 100644 --- a/views/quotes.jade +++ b/views/quotes/quotes.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content div#backlink diff --git a/views/channels.jade b/views/users/channels.jade similarity index 93% rename from views/channels.jade rename to views/users/channels.jade index 7cebf54..6315ab6 100644 --- a/views/channels.jade +++ b/views/users/channels.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content h3 Channels on #{connection} diff --git a/views/connections.jade b/views/users/connections.jade similarity index 91% rename from views/connections.jade rename to views/users/connections.jade index dd1e63b..0e7f06f 100644 --- a/views/connections.jade +++ b/views/users/connections.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content h3 Current Connections diff --git a/views/user.jade b/views/users/user.jade similarity index 95% rename from views/user.jade rename to views/users/user.jade index 8d1a680..072362e 100644 --- a/views/user.jade +++ b/views/users/user.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content h3 #{user}'s profile diff --git a/views/users.jade b/views/users/users.jade similarity index 94% rename from views/users.jade rename to views/users/users.jade index d043702..d20c9e2 100644 --- a/views/users.jade +++ b/views/users/users.jade @@ -1,4 +1,4 @@ -extends layout +extends ../layout block content h3 Users currently in #{channel} on #{connection}