forked from GitHub/dbot
Merge git://github.com/reality/depressionbot
This commit is contained in:
commit
6830ed73e1
30
modules/event/README.md
Normal file
30
modules/event/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
## Event
|
||||||
|
|
||||||
|
Emit events for whatever you want man idk.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
This is a library module designed for other modules to use to emit various
|
||||||
|
events at any point, and also to attach functions to said events. These are
|
||||||
|
similar to command hooks, however their advantage is that they may be called
|
||||||
|
anywhere in your code; they are particularly useful when you want to attach a
|
||||||
|
callback to a listener.
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
#### addHook(eventName, callback)
|
||||||
|
This function will set a given callback to be executed every time the
|
||||||
|
emit API function is executed with the given event name. The arguments of your
|
||||||
|
callback are defined as an array in the emit call.
|
||||||
|
|
||||||
|
The best place to add hooks to commands is in the 'onLoad' function of your
|
||||||
|
module, as this ensures it will be run while all other modules are loaded so
|
||||||
|
nothing will be missed.
|
||||||
|
|
||||||
|
#### emit(eventName, [ arguments ])
|
||||||
|
This function executes all of the functions associated with the given eventName,
|
||||||
|
passing your given array of arguments.
|
||||||
|
|
||||||
|
For example, to emit an event when you detect a nick change:
|
||||||
|
|
||||||
|
dbot.api.event.emit('nick_changed', [ event.server, newNick ]);
|
28
modules/event/event.js
Normal file
28
modules/event/event.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Module Name: event
|
||||||
|
* Description: Allow other modules to emit events and that
|
||||||
|
*/
|
||||||
|
var _ = require('underscore')._;
|
||||||
|
|
||||||
|
var event = function(dbot) {
|
||||||
|
this.dbot = dbot;
|
||||||
|
this.hooks = {};
|
||||||
|
this.api = {
|
||||||
|
'addHook': function(eventName, callback) {
|
||||||
|
if(!_.has(this.hooks, eventName)) this.hooks[eventName] = [];
|
||||||
|
this.hooks[eventName].push(callback);
|
||||||
|
},
|
||||||
|
|
||||||
|
'emit': function(eventName, args) {
|
||||||
|
if(_.has(this.hooks, eventName)) {
|
||||||
|
_.each(this.hooks[eventName], function(callback) {
|
||||||
|
callback.apply(callback.module, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.fetch = function(dbot) {
|
||||||
|
return new event(dbot);
|
||||||
|
};
|
@ -34,17 +34,19 @@ var link = function(dbot) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'~ud': function(event) {
|
'~ud': function(event) {
|
||||||
var reqUrl = 'http://api.urbandictionary.com/v0/define?term=' + event.params[1];
|
var query = event.input[1];
|
||||||
|
var reqUrl = 'http://api.urbandictionary.com/v0/define?term=' + encodeURI(query);
|
||||||
request(reqUrl, function(error, response, body) {
|
request(reqUrl, function(error, response, body) {
|
||||||
var result = JSON.parse(body);
|
var result = JSON.parse(body);
|
||||||
if(_.has(result, 'result_type') && result.result_type != 'no_results') {
|
if(_.has(result, 'result_type') && result.result_type != 'no_results') {
|
||||||
event.reply(event.params[1] + ': ' + result.list[0].definition);
|
event.reply(query + ': ' + result.list[0].definition.split('\n')[0]);
|
||||||
} else {
|
} else {
|
||||||
event.reply(event.user + ': No definition found.');
|
event.reply(event.user + ': No definition found.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
commands['~ud'].regex = [/~ud (.+)/, 2];
|
||||||
this.commands = commands;
|
this.commands = commands;
|
||||||
|
|
||||||
this.listener = function(event) {
|
this.listener = function(event) {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 616cc9f8f23afa6941c1c130626aeb851716c5aa
|
Subproject commit 33886df41d84c160270b581f072e710e4c9d00e8
|
@ -46,3 +46,11 @@ Return a list of aliases for a given primary user.
|
|||||||
|
|
||||||
#### isOnline(server, user, channel, useLowerCase)
|
#### isOnline(server, user, channel, useLowerCase)
|
||||||
Return whether a user is online in a given channel on the given server.
|
Return whether a user is online in a given channel on the given server.
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
#### nick_changed(server, newNick)
|
||||||
|
This is executed when a new alias is added for a user.
|
||||||
|
|
||||||
|
#### new_user(server, nick)
|
||||||
|
This is executed when a new primary user is added to the known users DB.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ignorable": false,
|
"ignorable": false,
|
||||||
|
"dependencies": [ "command", "event" ],
|
||||||
"dbKeys": [ "knownUsers" ],
|
"dbKeys": [ "knownUsers" ],
|
||||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md"
|
"help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md"
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,15 @@ var pages = function(dbot) {
|
|||||||
if(connections.hasOwnProperty(connection) &&
|
if(connections.hasOwnProperty(connection) &&
|
||||||
connections[connection].channels.hasOwnProperty(channel)) {
|
connections[connection].channels.hasOwnProperty(channel)) {
|
||||||
|
|
||||||
|
var chanData = dbot.api.stats.getChanStats(connection, channel, ["freq"]);
|
||||||
|
var chanFreq = [];
|
||||||
|
for(var i=0; i <= 6; i++){
|
||||||
|
for(var j=0; j <= 23; j++){
|
||||||
|
chanFreq.push(chanData.fields.freq.raw[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var userData = { "active": [], "inactive": [], "offline": []};
|
var userData = { "active": [], "inactive": [], "offline": []};
|
||||||
|
|
||||||
var reply = dbot.api.stats.getChanUsersStats(connection, channel, [
|
var reply = dbot.api.stats.getChanUsersStats(connection, channel, [
|
||||||
"lines", "words", "lincent", "wpl", "in_mentions"
|
"lines", "words", "lincent", "wpl", "in_mentions"
|
||||||
]);
|
]);
|
||||||
@ -60,8 +67,14 @@ var pages = function(dbot) {
|
|||||||
|
|
||||||
var userDataSorted = (userData.active.concat(userData.inactive)).concat(userData.offline);
|
var userDataSorted = (userData.active.concat(userData.inactive)).concat(userData.offline);
|
||||||
|
|
||||||
res.render('users', { 'name': dbot.config.name, 'connection': connection,
|
res.render('users', {
|
||||||
'channel': channel, 'nicks': userDataSorted });
|
'name': dbot.config.name,
|
||||||
|
'connection': connection,
|
||||||
|
'channel': channel,
|
||||||
|
'userStats': userDataSorted,
|
||||||
|
'chanFreq': chanFreq,
|
||||||
|
'chanFreqLen': chanFreq.length });
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
res.render_core('error', { 'name': dbot.config.name, 'message': 'No such connection or channel.' });
|
res.render_core('error', { 'name': dbot.config.name, 'message': 'No such connection or channel.' });
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ var users = function(dbot) {
|
|||||||
nick = this.api.resolveUser(event.server, nick);
|
nick = this.api.resolveUser(event.server, nick);
|
||||||
} else {
|
} else {
|
||||||
knownUsers.users.push(nick);
|
knownUsers.users.push(nick);
|
||||||
|
dbot.api.emit('new_user', [ event.server, nick ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_.include(channelUsers, nick)) {
|
if(!_.include(channelUsers, nick)) {
|
||||||
@ -57,7 +58,7 @@ var users = function(dbot) {
|
|||||||
var newNick = event.params.substr(1);
|
var newNick = event.params.substr(1);
|
||||||
if(!this.api.isKnownUser(newNick)) {
|
if(!this.api.isKnownUser(newNick)) {
|
||||||
knownUsers.aliases[newNick] = this.api.resolveUser(event.server, event.user);
|
knownUsers.aliases[newNick] = this.api.resolveUser(event.server, event.user);
|
||||||
if(_.has(dbot.modules, 'stats')) dbot.api.stats.renameStats(event.server, newNick);
|
dbot.api.event.emit('nick_change', [ event.server, newNick ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
@ -78,6 +79,7 @@ var users = function(dbot) {
|
|||||||
nick = this.api.resolveUser(event.server, nick);
|
nick = this.api.resolveUser(event.server, nick);
|
||||||
} else {
|
} else {
|
||||||
knownUsers.users.push(nick);
|
knownUsers.users.push(nick);
|
||||||
|
dbot.api.emit('new_user', [ event.server, nick ]);
|
||||||
}
|
}
|
||||||
if(!_.include(channelUsers, nick)) {
|
if(!_.include(channelUsers, nick)) {
|
||||||
channelUsers.push(nick);
|
channelUsers.push(nick);
|
||||||
|
67
run.js
67
run.js
@ -5,32 +5,36 @@ var fs = require('fs'),
|
|||||||
require('./snippets');
|
require('./snippets');
|
||||||
|
|
||||||
var DBot = function(timers) {
|
var DBot = function(timers) {
|
||||||
// Load DB
|
|
||||||
var rawDB;
|
/*** Load the DB ***/
|
||||||
try {
|
|
||||||
var rawDB = fs.readFileSync('db.json', 'utf-8');
|
if(fs.existsSync('db.json')) {
|
||||||
} catch(err) {
|
try {
|
||||||
this.db = {}; // If no db file, make empty one
|
this.db = JSON.parse(fs.readFileSync('db.json', 'utf-8'));
|
||||||
|
} catch(err) {
|
||||||
|
console.log('Error loading db.json. Stopping: ' + err);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.db = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if(!_.has(this.db, 'config')) {
|
||||||
if(!this.db) { // If it wasn't empty
|
this.db.config = {};
|
||||||
this.db = JSON.parse(rawDB);
|
}
|
||||||
}
|
|
||||||
if(!_.has(this.db, 'config')) {
|
/*** Load the Config ***/
|
||||||
this.db.config = {};
|
|
||||||
}
|
if(!fs.existsSync('config.json')) {
|
||||||
} catch(err) {
|
console.log('Error: config.json file does not exist. Stopping');
|
||||||
console.log('Syntax error in db.json. Stopping: ' + err);
|
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load config
|
|
||||||
this.config = _.clone(this.db.config);
|
this.config = _.clone(this.db.config);
|
||||||
try {
|
try {
|
||||||
_.defaults(this.config, JSON.parse(fs.readFileSync('config.json', 'utf-8')));
|
_.defaults(this.config, JSON.parse(fs.readFileSync('config.json', 'utf-8')));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log('Config file is invalid. Stopping');
|
console.log('Config file is invalid. Stopping: ' + err);
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +48,8 @@ var DBot = function(timers) {
|
|||||||
// Load missing config directives from sample file
|
// Load missing config directives from sample file
|
||||||
_.defaults(this.config, defaultConfig);
|
_.defaults(this.config, defaultConfig);
|
||||||
|
|
||||||
// Load Strings file
|
/*** Load main strings ***/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
|
this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
@ -220,13 +225,17 @@ DBot.prototype.reloadModules = function() {
|
|||||||
// Load the module data
|
// Load the module data
|
||||||
_.each([ 'commands', 'pages', 'api' ], function(property) {
|
_.each([ 'commands', 'pages', 'api' ], function(property) {
|
||||||
var propertyObj = {};
|
var propertyObj = {};
|
||||||
try {
|
|
||||||
var propertyKey = require.resolve(moduleDir + property);
|
if(fs.existsSync(moduleDir + property + '.js')) {
|
||||||
if(propertyKey) delete require.cache[propertyKey];
|
try {
|
||||||
propertyObj = require(moduleDir + property).fetch(this);
|
var propertyKey = require.resolve(moduleDir + property);
|
||||||
} catch(err) {
|
if(propertyKey) delete require.cache[propertyKey];
|
||||||
console.log('Module error (' + module.name + ') in ' + property + ': ' + err);
|
propertyObj = require(moduleDir + property).fetch(this);
|
||||||
}
|
} catch(err) {
|
||||||
|
this.status[name] = 'Error loading ' + propertyKey + ': ' + err + ' - ' + err.stack.split('\n')[1].trim();
|
||||||
|
console.log('Module error (' + module.name + ') in ' + property + ': ' + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!_.has(module, property)) module[property] = {};
|
if(!_.has(module, property)) module[property] = {};
|
||||||
_.extend(module[property], propertyObj);
|
_.extend(module[property], propertyObj);
|
||||||
@ -286,7 +295,11 @@ DBot.prototype.reloadModules = function() {
|
|||||||
|
|
||||||
_.each(this.modules, function(module, name) {
|
_.each(this.modules, function(module, name) {
|
||||||
if(module.onLoad) {
|
if(module.onLoad) {
|
||||||
module.onLoad();
|
try {
|
||||||
|
module.onLoad();
|
||||||
|
} catch(err) {
|
||||||
|
this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
@ -43,7 +43,10 @@ block content
|
|||||||
h1
|
h1
|
||||||
#{primary}
|
#{primary}
|
||||||
small
|
small
|
||||||
"#{profile.tagline}"
|
if(profile.tagline)
|
||||||
|
"#{profile.tagline}"
|
||||||
|
div#backlink
|
||||||
|
a(href='/profile/'+connection) « Profiles
|
||||||
|
|
||||||
div.row.profile_row#profile_data
|
div.row.profile_row#profile_data
|
||||||
div.span3
|
div.span3
|
||||||
@ -92,6 +95,3 @@ block content
|
|||||||
#{chan.fields.wpl.data}
|
#{chan.fields.wpl.data}
|
||||||
td
|
td
|
||||||
#{chan.fields.in_mentions.data}
|
#{chan.fields.in_mentions.data}
|
||||||
ul.pager
|
|
||||||
li.previous
|
|
||||||
a(href='/profile/'+connection) ← Back to #{connection}.
|
|
||||||
|
@ -14,6 +14,9 @@ block content
|
|||||||
div.page-header.profile_page-header
|
div.page-header.profile_page-header
|
||||||
h1
|
h1
|
||||||
#{connection}
|
#{connection}
|
||||||
|
div#backlink
|
||||||
|
a(href='../connections') « Connections
|
||||||
|
|
||||||
ul.thumbnails
|
ul.thumbnails
|
||||||
each profile, key in profiles
|
each profile, key in profiles
|
||||||
if profile.hasOwnProperty('profile') && profile.profile.avatar
|
if profile.hasOwnProperty('profile') && profile.profile.avatar
|
||||||
|
@ -2,9 +2,50 @@ extends ../layout
|
|||||||
|
|
||||||
block content
|
block content
|
||||||
script(type="text/javascript", src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js")
|
script(type="text/javascript", src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js")
|
||||||
|
style
|
||||||
|
.chart rect {
|
||||||
|
fill: steelblue;
|
||||||
|
}
|
||||||
|
.chart rect:hover {
|
||||||
|
fill: #000;
|
||||||
|
}
|
||||||
|
|
||||||
script
|
script
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
// d3.js Graph
|
||||||
|
var w = 5.595;
|
||||||
|
var h = 120;
|
||||||
|
|
||||||
|
var x = d3.scale.linear()
|
||||||
|
.domain([0,1])
|
||||||
|
.range([0,w]);
|
||||||
|
|
||||||
|
var y = d3.scale.linear()
|
||||||
|
.domain([0,100])
|
||||||
|
.rangeRound([0,h]);
|
||||||
|
|
||||||
|
var chart = d3.select($("#chanFreqChart")[0]).append("svg")
|
||||||
|
.attr("class", "chart")
|
||||||
|
.attr("width", w * #{chanFreqLen} - 1)
|
||||||
|
.attr("height", h);
|
||||||
|
|
||||||
|
chart.selectAll("rect")
|
||||||
|
.data([#{chanFreq}])
|
||||||
|
.enter().append("rect")
|
||||||
|
.attr("x", function(d, i) { return x(i) - .5; })
|
||||||
|
.attr("y", function(d) { return h - y(d) - .5; })
|
||||||
|
.attr("width", w)
|
||||||
|
.attr("height", function(d) { return y(d); })
|
||||||
|
.attr("title", function(d){ return y(d); });
|
||||||
|
|
||||||
|
chart.append("line")
|
||||||
|
.attr("x1", 0)
|
||||||
|
.attr("x2", w * #{chanFreqLen})
|
||||||
|
.attr("y1", h - .5)
|
||||||
|
.attr("y2", h - .5)
|
||||||
|
.style("stroke", "#000");
|
||||||
|
|
||||||
|
|
||||||
// Allowing forcing of string stats data to sort as numeric
|
// Allowing forcing of string stats data to sort as numeric
|
||||||
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
|
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
|
||||||
"forcenum-pre": function ( a ) {
|
"forcenum-pre": function ( a ) {
|
||||||
@ -22,6 +63,8 @@ block content
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
$('.tip').tooltip();
|
$('.tip').tooltip();
|
||||||
|
$('rect').tooltip({
|
||||||
|
});
|
||||||
$('.data').dataTable({
|
$('.data').dataTable({
|
||||||
"aoColumnDefs": [
|
"aoColumnDefs": [
|
||||||
{ "aDataSort": [ 1, 0 ], "asSorting": [ "asc" ], "aTargets": [ 0 ] },
|
{ "aDataSort": [ 1, 0 ], "asSorting": [ "asc" ], "aTargets": [ 0 ] },
|
||||||
@ -40,9 +83,16 @@ block content
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
h3 Users of #{channel} on #{connection}
|
div.page-header.profile_page-header
|
||||||
|
h1
|
||||||
|
#{channel}
|
||||||
|
small
|
||||||
|
#{connection}
|
||||||
div#backlink
|
div#backlink
|
||||||
a(href='/channels/'+connection) « Channel List
|
a(href='/channels/'+connection) « Channel List
|
||||||
|
div#row
|
||||||
|
div.barchart#chanFreqChart
|
||||||
|
hr
|
||||||
div#row
|
div#row
|
||||||
table.table.table-hover.data
|
table.table.table-hover.data
|
||||||
thead
|
thead
|
||||||
@ -55,7 +105,7 @@ block content
|
|||||||
th Verbosity
|
th Verbosity
|
||||||
th Mentions
|
th Mentions
|
||||||
tbody
|
tbody
|
||||||
-each nick in nicks
|
-each nick in userStats
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
a(href='/profile/'+connection+'/'+nick.primary)
|
a(href='/profile/'+connection+'/'+nick.primary)
|
||||||
|
Loading…
Reference in New Issue
Block a user