mirror of
https://github.com/reality/dbot.git
synced 2024-11-30 16:09:27 +01:00
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) {
|
||||
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) {
|
||||
var result = JSON.parse(body);
|
||||
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 {
|
||||
event.reply(event.user + ': No definition found.');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
commands['~ud'].regex = [/~ud (.+)/, 2];
|
||||
this.commands = commands;
|
||||
|
||||
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)
|
||||
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,
|
||||
"dependencies": [ "command", "event" ],
|
||||
"dbKeys": [ "knownUsers" ],
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md"
|
||||
}
|
||||
|
@ -26,8 +26,15 @@ var pages = function(dbot) {
|
||||
if(connections.hasOwnProperty(connection) &&
|
||||
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 reply = dbot.api.stats.getChanUsersStats(connection, channel, [
|
||||
"lines", "words", "lincent", "wpl", "in_mentions"
|
||||
]);
|
||||
@ -60,8 +67,14 @@ var pages = function(dbot) {
|
||||
|
||||
var userDataSorted = (userData.active.concat(userData.inactive)).concat(userData.offline);
|
||||
|
||||
res.render('users', { 'name': dbot.config.name, 'connection': connection,
|
||||
'channel': channel, 'nicks': userDataSorted });
|
||||
res.render('users', {
|
||||
'name': dbot.config.name,
|
||||
'connection': connection,
|
||||
'channel': channel,
|
||||
'userStats': userDataSorted,
|
||||
'chanFreq': chanFreq,
|
||||
'chanFreqLen': chanFreq.length });
|
||||
|
||||
} else {
|
||||
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);
|
||||
} else {
|
||||
knownUsers.users.push(nick);
|
||||
dbot.api.emit('new_user', [ event.server, nick ]);
|
||||
}
|
||||
|
||||
if(!_.include(channelUsers, nick)) {
|
||||
@ -57,7 +58,7 @@ var users = function(dbot) {
|
||||
var newNick = event.params.substr(1);
|
||||
if(!this.api.isKnownUser(newNick)) {
|
||||
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);
|
||||
@ -78,6 +79,7 @@ var users = function(dbot) {
|
||||
nick = this.api.resolveUser(event.server, nick);
|
||||
} else {
|
||||
knownUsers.users.push(nick);
|
||||
dbot.api.emit('new_user', [ event.server, nick ]);
|
||||
}
|
||||
if(!_.include(channelUsers, nick)) {
|
||||
channelUsers.push(nick);
|
||||
|
67
run.js
67
run.js
@ -5,32 +5,36 @@ var fs = require('fs'),
|
||||
require('./snippets');
|
||||
|
||||
var DBot = function(timers) {
|
||||
// Load DB
|
||||
var rawDB;
|
||||
try {
|
||||
var rawDB = fs.readFileSync('db.json', 'utf-8');
|
||||
} catch(err) {
|
||||
this.db = {}; // If no db file, make empty one
|
||||
|
||||
/*** Load the DB ***/
|
||||
|
||||
if(fs.existsSync('db.json')) {
|
||||
try {
|
||||
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(!this.db) { // If it wasn't empty
|
||||
this.db = JSON.parse(rawDB);
|
||||
}
|
||||
if(!_.has(this.db, 'config')) {
|
||||
this.db.config = {};
|
||||
}
|
||||
} catch(err) {
|
||||
console.log('Syntax error in db.json. Stopping: ' + err);
|
||||
if(!_.has(this.db, 'config')) {
|
||||
this.db.config = {};
|
||||
}
|
||||
|
||||
/*** Load the Config ***/
|
||||
|
||||
if(!fs.existsSync('config.json')) {
|
||||
console.log('Error: config.json file does not exist. Stopping');
|
||||
process.exit();
|
||||
}
|
||||
|
||||
// Load config
|
||||
|
||||
this.config = _.clone(this.db.config);
|
||||
try {
|
||||
_.defaults(this.config, JSON.parse(fs.readFileSync('config.json', 'utf-8')));
|
||||
} catch(err) {
|
||||
console.log('Config file is invalid. Stopping');
|
||||
console.log('Config file is invalid. Stopping: ' + err);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
@ -44,7 +48,8 @@ var DBot = function(timers) {
|
||||
// Load missing config directives from sample file
|
||||
_.defaults(this.config, defaultConfig);
|
||||
|
||||
// Load Strings file
|
||||
/*** Load main strings ***/
|
||||
|
||||
try {
|
||||
this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
|
||||
} catch(err) {
|
||||
@ -220,13 +225,17 @@ DBot.prototype.reloadModules = function() {
|
||||
// Load the module data
|
||||
_.each([ 'commands', 'pages', 'api' ], function(property) {
|
||||
var propertyObj = {};
|
||||
try {
|
||||
var propertyKey = require.resolve(moduleDir + property);
|
||||
if(propertyKey) delete require.cache[propertyKey];
|
||||
propertyObj = require(moduleDir + property).fetch(this);
|
||||
} catch(err) {
|
||||
console.log('Module error (' + module.name + ') in ' + property + ': ' + err);
|
||||
}
|
||||
|
||||
if(fs.existsSync(moduleDir + property + '.js')) {
|
||||
try {
|
||||
var propertyKey = require.resolve(moduleDir + property);
|
||||
if(propertyKey) delete require.cache[propertyKey];
|
||||
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] = {};
|
||||
_.extend(module[property], propertyObj);
|
||||
@ -286,7 +295,11 @@ DBot.prototype.reloadModules = function() {
|
||||
|
||||
_.each(this.modules, function(module, name) {
|
||||
if(module.onLoad) {
|
||||
module.onLoad();
|
||||
try {
|
||||
module.onLoad();
|
||||
} catch(err) {
|
||||
this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim();
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
|
@ -43,7 +43,10 @@ block content
|
||||
h1
|
||||
#{primary}
|
||||
small
|
||||
"#{profile.tagline}"
|
||||
if(profile.tagline)
|
||||
"#{profile.tagline}"
|
||||
div#backlink
|
||||
a(href='/profile/'+connection) « Profiles
|
||||
|
||||
div.row.profile_row#profile_data
|
||||
div.span3
|
||||
@ -92,6 +95,3 @@ block content
|
||||
#{chan.fields.wpl.data}
|
||||
td
|
||||
#{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
|
||||
h1
|
||||
#{connection}
|
||||
div#backlink
|
||||
a(href='../connections') « Connections
|
||||
|
||||
ul.thumbnails
|
||||
each profile, key in profiles
|
||||
if profile.hasOwnProperty('profile') && profile.profile.avatar
|
||||
|
@ -2,9 +2,50 @@ extends ../layout
|
||||
|
||||
block content
|
||||
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
|
||||
$(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
|
||||
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
|
||||
"forcenum-pre": function ( a ) {
|
||||
@ -22,6 +63,8 @@ block content
|
||||
} );
|
||||
|
||||
$('.tip').tooltip();
|
||||
$('rect').tooltip({
|
||||
});
|
||||
$('.data').dataTable({
|
||||
"aoColumnDefs": [
|
||||
{ "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
|
||||
a(href='/channels/'+connection) « Channel List
|
||||
div#row
|
||||
div.barchart#chanFreqChart
|
||||
hr
|
||||
div#row
|
||||
table.table.table-hover.data
|
||||
thead
|
||||
@ -55,7 +105,7 @@ block content
|
||||
th Verbosity
|
||||
th Mentions
|
||||
tbody
|
||||
-each nick in nicks
|
||||
-each nick in userStats
|
||||
tr
|
||||
td
|
||||
a(href='/profile/'+connection+'/'+nick.primary)
|
||||
|
Loading…
Reference in New Issue
Block a user