Modularised web routes and views

This commit is contained in:
Daniel Evans 2012-12-24 05:47:47 +00:00
parent 88d2abab58
commit e544c909ec
14 changed files with 204 additions and 145 deletions

View File

@ -217,10 +217,36 @@ var poll = function(dbot) {
commands['~pdesc'].regex = [/~pdesc ([^ ]+)/, 2]; commands['~pdesc'].regex = [/~pdesc ([^ ]+)/, 2];
commands['~count'].regex = [/~count ([^ ]+)/, 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 { return {
'name': 'poll', 'name': 'poll',
'ignorable': true, 'ignorable': true,
'commands': commands 'commands': commands,
'pages': pages
}; };
}; };

View File

@ -267,10 +267,34 @@ var quotes = function(dbot) {
commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2]; commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2];
commands['~qadd'].regex = [/^~qadd ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; 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 { return {
'name': 'quotes', 'name': 'quotes',
'ignorable': true, 'ignorable': true,
'commands': commands, 'commands': commands,
'pages': pages,
'listener': function(event) { 'listener': function(event) {
// Reality Once listener // Reality Once listener

View File

@ -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 { return {
'name': 'users', 'name': 'users',
'ignorable': false, 'ignorable': false,
@ -37,6 +96,8 @@ var users = function(dbot) {
} }
}, },
'pages': pages,
'listener': function(event) { 'listener': function(event) {
var knownUsers = getServerUsers(event); var knownUsers = getServerUsers(event);
if(event.action == 'JOIN') { if(event.action == 'JOIN') {

View File

@ -1,4 +1,5 @@
var express = require('express'); var express = require('express'),
fs = require('fs');
var webInterface = function(dbot) { var webInterface = function(dbot) {
var pub = 'public'; var pub = 'public';
@ -11,112 +12,32 @@ var webInterface = function(dbot) {
res.render('index', { 'name': dbot.config.name }); 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); 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 { return {
'name': 'web', 'name': 'web',
'ignorable': false, 'ignorable': false,
'reloadPages': reloadPages,
'onDestroy': function() { 'onDestroy': function() {
app.close(); app.close();

24
run.js
View File

@ -118,6 +118,7 @@ DBot.prototype.reloadModules = function() {
this.rawModules = []; this.rawModules = [];
this.modules = []; this.modules = [];
this.pages = {};
this.commands = {}; this.commands = {};
this.commandMap = {}; // Map of which commands belong to which modules this.commandMap = {}; // Map of which commands belong to which modules
this.usage = {}; this.usage = {};
@ -168,6 +169,8 @@ DBot.prototype.reloadModules = function() {
var module = rawModule.fetch(this); var module = rawModule.fetch(this);
this.rawModules.push(rawModule); this.rawModules.push(rawModule);
module.name = name;
if(module.listener) { if(module.listener) {
var listenOn = module.on; var listenOn = module.on;
if(!(listenOn instanceof Array)) { 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 // Load the module usage data
try { try {
var usage = JSON.parse(fs.readFileSync(moduleDir + 'usage.json', 'utf-8')); var usage = JSON.parse(fs.readFileSync(moduleDir + 'usage.json', 'utf-8'));
@ -237,9 +252,18 @@ DBot.prototype.reloadModules = function() {
} }
} }
}.bind(this)); }.bind(this));
this.reloadPages();
this.save(); 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) { DBot.prototype.cleanNick = function(key) {
key = key.toLowerCase(); key = key.toLowerCase();
while(key.endsWith("_")) { while(key.endsWith("_")) {

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
div#backlink div#backlink

39
views/poll/polls.jade Normal file
View File

@ -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')

View File

@ -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')

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
div#backlink div#backlink

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
div#backlink div#backlink

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
h3 Channels on #{connection} h3 Channels on #{connection}

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
h3 Current Connections h3 Current Connections

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
h3 #{user}'s profile h3 #{user}'s profile

View File

@ -1,4 +1,4 @@
extends layout extends ../layout
block content block content
h3 Users currently in #{channel} on #{connection} h3 Users currently in #{channel} on #{connection}