diff --git a/modules/kick/commands.js b/modules/kick/commands.js index f11132a..f16594e 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -6,88 +6,15 @@ var commands = function(dbot) { /*** Kick Management ***/ '~quiet': function(event) { var server = event.server, - quieter = event.user, + quieter = event.rUser, duration = event.input[1], channel = (event.input[2] || event.channel.name).trim(), quietee = event.input[3].trim(), reason = event.input[4] || "N/A"; - dbot.api.nickserv.getUserHost(server, quietee, function(host) { - // Add host record entry - if(host) { - this.hosts[server][quietee] = host; - - if(!_.isUndefined(duration) && !_.isNull(duration)) { - duration = duration.trim(); - var msTimeout = new Date(new Date().getTime() + (parseFloat(duration) * 60000)); - if(_.has(dbot.modules, 'remind')) { - msTimeout = dbot.api.remind.parseTime(duration); - if(!msTimeout) { - return event.reply('Invalid time. Remember you must give e.g. 5m now.'); - } - duration = duration.replace(/([\d]+)d/, '$1 days').replace(/([\d]+)h/, '$1 hours ').replace(/([\d]+)m/, '$1 minutes ').replace(/([\d]+)s/, '$1 seconds').trim(); - } else { - duration += ' minutes'; - } - - var vStatus = dbot.instance.connections[server].channels[channel].nicks[quietee].voice; - dbot.api.timers.addTimeout(msTimeout, function() { - if(_.has(this.hosts[server], quietee)) { - if(_.include(this.config.quietBans, channel)) { - this.api.unban(server, this.hosts[server][quietee], channel); - this.api.voice(server, quietee, channel); - } else { - this.api.unquiet(server, this.hosts[server][quietee], channel); - } - - dbot.api.users.resolveUser(server, dbot.config.name, function(err, user) { - dbot.api.report.notify('unquiet', server, user, channel, - dbot.t('unquiet_notify', { - 'unquieter': dbot.config.name, - 'quietee': quietee - }), false, quietee); - }); - } - }.bind(this)); - event.reply(dbot.t('tquieted', { - 'quietee': quietee, - 'minutes': duration - })); - dbot.api.report.notify('quiet', server, event.rUser, channel, - dbot.t('tquiet_notify', { - 'minutes': duration, - 'quieter': event.rUser.primaryNick, - 'quietee': quietee, - 'reason': reason - }), false, quietee - ); - } else { - event.reply(dbot.t('quieted', { 'quietee': quietee })); - dbot.api.report.notify('quiet', server, event.rUser, channel, - dbot.t('quiet_notify', { - 'quieter': quieter, - 'quietee': quietee, - 'reason': reason - }), false, quietee); - } - - this.api.devoice(server, quietee, channel); - - if(_.include(this.config.quietBans, channel)) { - this.api.ban(server, this.hosts[server][quietee], channel); - } else { - this.api.quiet(server, host, channel); - } - - if(reason.indexOf('#warn') !== -1) { - dbot.api.warning.warn(server, event.rUser, quietee, - 'Quieted in ' + channel + ' for ' + reason, channel, - function() {}); - } - } else { - event.reply(dbot.t('no_user', { 'user': quietee })); - } - }.bind(this)); + this.api.quietUser(server, quieter, duration, channel, quietee, reason, function(response) { + event.reply(response); + }); }, '~unquiet': function(event) { @@ -329,6 +256,112 @@ var commands = function(dbot) { event.reply(orderedKickLeague(dbot.db.kicks, 'Kicked')); event.reply(orderedKickLeague(dbot.db.kickers, 'Kickers')); + }, + + '~votequiet': function(event) { + var target = event.input[1], + reason = event.input[2]; + + if(_.has(event.channel.nicks, target)) { + dbot.api.users.resolveUser(event.server, target, function(err, user) { + if(!err && user) { + if(_.include(dbot.access.power_user(), user.primaryNick) || target == dbot.config.name) { + return event.reply('User is immune to votequiet.'); + } + + if(!_.has(this.voteQuiets, user.id)) { + this.voteQuiets[user.id] = { 'user': user.id, 'yes': [event.rUser.primaryNick], 'no': [] }; + event.reply(event.user + ' has started a vote to quiet ' + target + ' for "' + reason + '." Type either "~voteyes ' + target + '" or "~voteno ' + target + '" in the next 40 seconds.'); + + setTimeout(function() { + var vq = this.voteQuiets[user.id]; + vq.spent = true; + if(vq.yes.length >= 3 && vq.no.length < 2) { + event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').'); + + this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, reason + '[votequiet]', function(response) { + event.reply(response); + }); + } else { + event.reply('Attempt to quiet ' + target + ' failed. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').'); + } + + var nString = 'A votequiet was attempted on ' + target + ' in ' + event.channel + '. It was initiated by ' + event.rUser.primaryNick + '. ' + + vq.yes.join(', ') + ' voted yes (' + vq.yes.length + '). '; + if(vq.no.length > 0) { + nString += vq.no.join(', ') + ' voted no (' + vq.no.length + ').' + } + + dbot.api.report.notify('votequiet', event.server, event.rUser, event.channel, nString, false, target); + + setTimeout(function() { + delete this.voteQuiets[user.id]; + }.bind(this), 600000); + }.bind(this), 40000); + } else { + if(this.voteQuiets[user.id].spent) { + event.reply('A votequiet attempt has already been made on this user in the last 10 minutes.'); + } else { + event.reply('There is already a votequiet attempt active for this user.'); + } + } + } else { + event.reply('Target does not seem to be in the channel.'); + } + }.bind(this)); + } else { + event.reply('Target does not seem to be in the channel.'); + } + }, + + '~voteyes': function(event) { + var target = event.params[1]; + + dbot.api.users.resolveUser(event.server, target, function(err, user) { + if(!err && user) { + if(user.id == event.rUser.id) { + return event.reply('You cannot vote on your own silencing. Be good.'); + } + if(_.has(this.voteQuiets, user.id) && !this.voteQuiets[user.id].spent) { + var vq = this.voteQuiets[user.id]; + if(!_.include(vq.yes, event.rUser.primaryNick) && !_.include(vq.no, event.rUser.primaryNick)) { + vq.yes.push(event.rUser.primaryNick); + event.reply('Voted yes on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').'); + } else { + event.reply('You have already voted.'); + } + } else { + event.reply('There is no active votequiet for this user. You can start one by typing "~votequiet ' + target + ' [reason].'); + } + } else { + event.reply('No idea who that is m8'); + } + }.bind(this)); + }, + + '~voteno': function(event) { + var target = event.params[1]; + + dbot.api.users.resolveUser(event.server, target, function(err, user) { + if(!err && user) { + if(user.id == event.rUser.id) { + return event.reply('You cannot vote on your own silencing. Be good.'); + } + if(_.has(this.voteQuiets, user.id) && !this.voteQuiets[user.id].spent) { + var vq = this.voteQuiets[user.id]; + if(!_.include(vq.yes, event.rUser.primaryNick) && !_.include(vq.no, event.rUser.primaryNick)) { + vq.no.push(event.rUser.primaryNick); + event.reply('Voted no on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').'); + } else { + event.reply('You have already voted.'); + } + } else { + event.reply('There is no active votequiet for this user. You can start one by typing "~votequiet ' + target + ' [reason].'); + } + } else { + event.reply('No idea who that is m8'); + } + }.bind(this)); } }; @@ -338,6 +371,9 @@ var commands = function(dbot) { commands['~kickcount'].access = 'regular'; commands['~kickstats'].access = 'regular'; + commands['~votequiet'].access = 'regular'; + commands['~voteyes'].access = 'regular'; + commands['~voteno'].access = 'regular'; commands['~quiet'].access = 'voice'; commands['~unquiet'].access = 'voice'; commands['~nban'].access = 'power_user'; @@ -347,6 +383,7 @@ var commands = function(dbot) { commands['~nban'].regex = /^nban (\d[\d\.dhms]+)? ?([^ ]+) (.+)$/; commands['~quiet'].regex = /^quiet (\d[\d\.hms]+)? ?(#[^ ]+ )?([^ ]+) ?(.*)?$/; commands['~unquiet'].regex = /^unquiet (#[^ ]+ )?([^ ]+) ?$/; + commands['~votequiet'].regex = [/^votequiet ([^ ]+) (.+)$/, 3]; return commands; }; diff --git a/modules/kick/kick.js b/modules/kick/kick.js index 4978724..0682e19 100644 --- a/modules/kick/kick.js +++ b/modules/kick/kick.js @@ -32,6 +32,85 @@ var kick = function(dbot) { dbot.instance.connections[server].send('MODE ' + channel + ' -b *!*@' + host); }, + 'quietUser': function(server, quieter, duration, channel, quietee, reason, callback) { + dbot.api.nickserv.getUserHost(server, quietee, function(host) { + // Add host record entry + if(host) { + this.hosts[server][quietee] = host; + + if(!_.isUndefined(duration) && !_.isNull(duration)) { + duration = duration.trim(); + var msTimeout = new Date(new Date().getTime() + (parseFloat(duration) * 60000)); + if(_.has(dbot.modules, 'remind')) { + msTimeout = dbot.api.remind.parseTime(duration); + if(!msTimeout) { + return callback('Invalid time. Remember you must give e.g. 5m now.'); + } + duration = duration.replace(/([\d]+)d/, '$1 days').replace(/([\d]+)h/, '$1 hours ').replace(/([\d]+)m/, '$1 minutes ').replace(/([\d]+)s/, '$1 seconds').trim(); + } else { + duration += ' minutes'; + } + + var vStatus = dbot.instance.connections[server].channels[channel].nicks[quietee].voice; + dbot.api.timers.addTimeout(msTimeout, function() { + if(_.has(this.hosts[server], quietee)) { + if(_.include(this.config.quietBans, channel)) { + this.api.unban(server, this.hosts[server][quietee], channel); + this.api.voice(server, quietee, channel); + } else { + this.api.unquiet(server, this.hosts[server][quietee], channel); + } + + dbot.api.users.resolveUser(server, dbot.config.name, function(err, user) { + dbot.api.report.notify('unquiet', server, user, channel, + dbot.t('unquiet_notify', { + 'unquieter': dbot.config.name, + 'quietee': quietee + }), false, quietee); + }); + } + }.bind(this)); + callback(dbot.t('tquieted', { + 'quietee': quietee, + 'minutes': duration + })); + dbot.api.report.notify('quiet', server, quieter, channel, + dbot.t('tquiet_notify', { + 'minutes': duration, + 'quieter': quieter.primaryNick, + 'quietee': quietee, + 'reason': reason + }), false, quietee + ); + } else { + callback(dbot.t('quieted', { 'quietee': quietee })); + dbot.api.report.notify('quiet', server, quieter, channel, + dbot.t('quiet_notify', { + 'quieter': quieter, + 'quietee': quietee, + 'reason': reason + }), false, quietee); + } + + this.api.devoice(server, quietee, channel); + + if(_.include(this.config.quietBans, channel)) { + this.api.ban(server, this.hosts[server][quietee], channel); + } else { + this.api.quiet(server, host, channel); + } + + if(reason.indexOf('#warn') !== -1) { + dbot.api.warning.warn(server, quieter, quietee, + 'Quieted in ' + channel + ' for ' + reason, channel, + function() {}); + } + } else { + event.reply(dbot.t('no_user', { 'user': quietee })); + } + }.bind(this)); + }, + 'networkUnban': function(server, unbanee, unbanner, callback) { var channels = dbot.config.servers[server].channels, network = this.config.network_name[server] || server, @@ -139,6 +218,7 @@ var kick = function(dbot) { if(!_.has(dbot.db, 'tempBans')) dbot.db.tempBans = {}; this.hosts = dbot.db.hosts; this.tempBans = dbot.db.tempBans; + this.voteQuiets = {}; _.each(this.tempBans, function(bans, server) { _.each(bans, function(timeout, nick) {