Uwev2/src/inc/irc/listcache.js

125 lines
3.2 KiB
JavaScript
Raw Normal View History

2017-11-07 18:22:41 +01:00
var _ = require('lodash'),
Events = require(__dirname + '/irc').Events;
function ListCache() {
this.lists = {};
};
// ========================================
// this object manages list caching, in a normal single client
// scenario, grabbing the list on request is fine, but irc-factory
// isnt really designed for single client usage
// the ircanywhere use case requires lists to be available to all, for
// all networks.
ListCache.prototype.requestList = function(ircObject, search, page, limit) {
if (!Events) {
Events = require(__dirname + '/irc').Events;
}
var self = this,
key = ircObject.key;
if (key === '') {
return false;
}
if (!this.lists[key]) {
this.createList(ircObject);
ircObject.raw(['LIST']);
Events.once([ircObject.key, 'listend'], function() {
self.filterList(ircObject, search, page, limit);
});
// no cache is available? request one and wait to filter it
} else {
self.filterList(ircObject, search, page, limit);
// looks like we already have a cached list, pass it straight to filter
}
clearTimeout(this.lists[key].deleteTimer);
this.lists[key].deleteTimer = setTimeout(function() {
delete self.lists[key];
}, 600000);
// lets set a timer to trash this data if its not been requested in a while (10min)
// the only reason we cache it is to prevent people doing /list then /list, then /list
// and blocking the process
};
ListCache.prototype.filterList = function(ircObject, search, page, limit) {
var key = ircObject.key,
regex = new RegExp('(' + search + ')', 'i'),
list = this.lists[key];
if (key === '' || !list) {
return false;
}
// make sure the list exists
var output = {
list: [],
raw: [],
search: search.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\$&").replace(/\(\.\*\)/g, '*'),
page: page,
limit: limit,
time: new Date()
};
var clone = _.cloneDeep(list.list);
var buffer = _.sortBy(clone, function(channel) {
return 0 - channel.users;
});
// sort it
buffer = _.filter(buffer, function(channel) {
return regex.test(channel.channel);
});
// filter via the search parameters
buffer = _.take(_.rest(buffer, (page - 1) * limit), limit);
// paginate
for (var c in buffer) {
var channel = buffer[c];
output.raw.push(channel.raw);
delete buffer[c].raw;
}
// i don't really like this, but we pull .raw from channel objects
// and push it into the output
Events.emit([ircObject.key, 'list'], _.extend(output, {
list: buffer
}));
// emit the list event
};
ListCache.prototype.createList = function(ircObject) {
var key = ircObject.key;
if (key === '' || this.lists[key]) {
return false;
}
this.lists[key] = {
key: key,
requestedAt: new Date(),
deleteTimer: null,
list: []
};
};
ListCache.prototype.insertListData = function(ircObject, message) {
var key = ircObject.key;
if (key !== '' && !this.lists[key]) {
this.createList(key);
}
this.lists[key].list.push({
channel: message.params[1],
users: message.params[2],
topic: message.params[3],
raw: message.raw
});
};
// ========================================
exports.ListCache = new ListCache();