forked from couchone/sIRCouch
/
log.js
136 lines (120 loc) · 4.93 KB
/
log.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
var request = require('request'),
sys = require('sys'),
irc = require('./IRC/lib/irc');
var ircOptions = {
server: 'irc.freenode.net'
};
var defaults = {
couchdb: 'http://127.0.0.1:5984/couchdbirc',
nick : 'couchlogbot',
room : '#couchlog',
roomPass : '******',
couchUser: '',
couchPass: '',
hello: ''
};
if(process.env.help) {
console.log('The following environment variables set the behaviour:');
console.log('');
console.log('Name\tDefault');
console.log('=-=-=-=-=-=-=-=');
for (var key in defaults) {
console.log(key + '\t' + '"' + defaults[key] + '"');
}
process.exit(0);
}
var opts = {};
for (var key in defaults) {
opts[key] = process.env[key] || defaults[key];
}
var couchdb_uri = 'http://' + (opts.couchUser == '' ? '' : opts.couchUser + ':' + opts.couchPass + '@') + opts.couchdb.replace(/^http:\/\//, '').replace(/\/$/, '');
var couchOptions = {
uri: couchdb_uri,
method:'POST',
headers:{'content-type':'application/json'}
};
var bot = new irc(ircOptions);
bot.connect(function () {
bot.nick(opts.nick);
if (opts.roomPass) {
bot.join(opts.room, opts.roomPass);
} else {
bot.join(opts.room);
}
if(opts.hello) {
setTimeout(function() { bot.privmsg(opts.room, opts.hello); }, 1000);
}
bot.addListener('privmsg', function (message) {
if (message.params.length === 2) {
message.channel = message.params[0];
message.message = message.params[1];
delete message.params;
}
if (message.channel === opts.room) {
message.timestamp = new Date();
couchOptions.body = JSON.stringify(message);
couchOptions.headers['content-length'] = couchOptions.body.length;
request(couchOptions, function (err, resp, body) {
sys.puts(body);
});
if(message.message && new RegExp(opts.nick).test(message.message)) {
var cmd_re = new RegExp(opts.nick + '.*?\\s(\\w+)\\s*(.*)$');
var cmd_match = message.message.match(cmd_re);
if(!cmd_match) {
bot.privmsg(opts.room, 'Who said my name? Type `' + opts.nick + ' help` for command listing');
} else {
// Command is one word, and the options are "key1=val1 key2=val2" pairs, converted to an object.
var command = cmd_match[1];
var cmd_opts = cmd_match[2].split(/\s+/)
.map(function(pair) { return pair.split(/=/) })
.reduce(function(state, kv) { if(kv[0] && kv[1]) { state[kv[0]] = kv[1]; } return state }, {});
if(command == 'help') {
[ 'Supported commands:'
, ' help -- display help'
, ' search -- mandatory: tag=some_hashtag or link=some_word_or_nick; optional: limit=NN aloud=true'
].forEach(function(line) { bot.privmsg(opts.room, line) });
} else if(command == 'search') {
if(!('tag' in cmd_opts) && !('link' in cmd_opts)) {
bot.privmsg(opts.room, "Unknown search. Use `help` command to see syntax.");
} else {
function say(line) {
return bot.privmsg(cmd_opts.aloud ? opts.room : message.person.nick, line);
}
var keyword = cmd_opts.tag || cmd_opts.link
, startkey = [keyword, null]
, endkey = [keyword, {}]
, limit = parseInt(cmd_opts.limit || '5') // This will be done client-side to show 5/10 results found.
, view = cmd_opts.tag ? 'tags-by-timestamp' : 'links-by-timestamp'
;
startkey = encodeURIComponent(JSON.stringify(startkey));
endkey = encodeURIComponent(JSON.stringify(endkey));
var query = { uri: couchdb_uri + '/_design/logs/_view/' + view + '?include_docs=true&reduce=false&startkey=' + startkey + '&endkey=' + endkey };
request(query, function(er, resp, body) {
if(er) {
say('HTTP error: ' + body);
} else {
body = JSON.parse(body);
if(body.error) {
say('Query error: ' + JSON.stringify(body));
} else {
if(body.rows.length == 0) {
say('Query for ' + cmd_match[2] + ' -- No results found');
} else {
if(limit > body.rows.length)
limit = body.rows.length;
say('query for ' + cmd_match[2] + ' returned ' + limit + '/' + body.rows.length);
// The elements are in correct order for IRC (oldest first). But slice the *latest* `limit` of them to display.
body.rows.slice(body.rows.length - limit).forEach(function(row) {
say(row.doc.timestamp + ' ' + row.doc.person.nick + ': ' + row.doc.message);
})
}
}
}
})
}
}
}
}
}
});
});