2013-08-18 22:10:19 +02:00
var _ = require ( 'underscore' ) . _ ,
uuid = require ( 'node-uuid' ) ;
2013-05-06 23:56:45 +02:00
2013-04-14 16:35:49 +02:00
var commands = function ( dbot ) {
var commands = {
/*** Kick Management ***/
2013-07-01 19:03:04 +02:00
'~quiet' : function ( event ) {
2016-03-20 18:48:07 +01:00
var server = event . server ,
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" ;
this . api . quietUser ( server , quieter , duration , channel , quietee , reason , function ( response ) {
event . reply ( response ) ;
} ) ;
} ,
'~timeout' : function ( event ) {
var server = event . server ,
quieter = event . rUser ,
duration = this . config . timeoutTime ,
channel = event . channel . name ,
quietee = event . input [ 1 ] ,
reason = event . input [ 2 ] || "N/A" ;
reason += ' #timeout' ;
dbot . api . users . resolveUser ( server , quietee , function ( err , user ) {
if ( ! err && user ) {
if ( ! _ . has ( this . recentTimeouts , user . id ) ) {
this . recentTimeouts [ user . id ] = 0 ;
}
this . recentTimeouts [ user . id ] += 1 ;
setTimeout ( function ( ) {
this . recentTimeouts [ user . id ] -= 1 ;
if ( this . recentTimeouts [ user . id ] == 0 ) {
delete this . recentTimeouts [ user . id ] ;
}
2016-03-20 18:51:48 +01:00
} . bind ( this ) , 3600000 ) ;
2016-03-20 18:48:07 +01:00
if ( this . recentTimeouts [ user . id ] == 3 ) {
duration = null ;
reason += ' #permatimeout' ;
2016-03-20 18:51:48 +01:00
dbot . say ( event . server , dbot . config . servers [ event . server ] . admin _channel , quietee + ' has been given three timeouts in the last hour, and so has been quieted indefinitely in ' + channel + '. Please review.' ) ;
2016-03-20 18:48:07 +01:00
}
this . api . quietUser ( server , quieter , duration , channel , quietee , reason , function ( response ) {
event . reply ( response ) ;
} ) ;
}
} . bind ( this ) ) ;
2013-07-01 19:03:04 +02:00
} ,
2013-07-01 19:38:25 +02:00
'~unquiet' : function ( event ) {
var server = event . server ,
quieter = event . user ,
2014-02-03 18:37:38 +01:00
channel = ( event . input [ 1 ] || event . channel . name ) . trim ( ) ,
2013-07-01 19:38:25 +02:00
quietee = event . input [ 2 ] . trim ( ) ;
2014-02-03 18:37:38 +01:00
if ( _ . has ( this . hosts [ server ] , quietee ) ) {
2015-01-30 01:07:45 +01:00
if ( _ . include ( this . config . quietBans , channel ) ) {
this . api . unban ( server , this . hosts [ server ] [ quietee ] , channel ) ;
} else {
this . api . unquiet ( server , this . hosts [ server ] [ quietee ] , channel ) ;
}
2014-02-03 18:37:38 +01:00
event . reply ( dbot . t ( 'unquieted' , { 'quietee' : quietee } ) ) ;
dbot . api . report . notify ( 'unquiet' , server , event . rUser , channel ,
dbot . t ( 'unquiet_notify' , {
'unquieter' : quieter ,
'quietee' : quietee
2016-01-28 19:29:51 +01:00
} ) , false , quietee ) ;
2013-07-01 19:38:25 +02:00
}
} ,
2013-05-06 23:56:45 +02:00
2013-04-14 16:35:49 +02:00
'~ckick' : function ( event ) {
var server = event . server ,
kicker = event . user ,
kickee = event . input [ 2 ] ,
channel = event . input [ 1 ] ,
reason = event . input [ 3 ] ;
2013-11-29 07:16:33 +01:00
if ( _ . isUndefined ( channel ) ) {
channel = event . channel . name ;
}
channel = channel . trim ( ) ;
2013-04-14 16:35:49 +02:00
this . api . kick ( server , kickee , channel , reason + ' (requested by ' + kicker + ')' ) ;
2013-05-06 23:56:45 +02:00
2013-08-28 00:01:44 +02:00
dbot . api . report . notify ( 'kick' , server , event . rUser , channel , dbot . t ( 'ckicked' , {
2013-04-14 16:35:49 +02:00
'kicker' : kicker ,
'kickee' : kickee ,
2013-05-06 23:56:45 +02:00
'reason' : reason
2016-01-28 19:29:51 +01:00
} ) , false , kickee ) ;
2013-05-06 23:56:45 +02:00
} ,
// Kick and ban from all channels on the network.
'~nban' : function ( event ) {
2013-06-10 18:15:28 +02:00
if ( ! event . input ) return ;
2013-05-06 23:56:45 +02:00
var server = event . server ,
banner = event . user ,
2013-06-10 18:15:28 +02:00
timeout = event . input [ 1 ] ,
banee = event . input [ 2 ] ,
reason = event . input [ 3 ] ,
2013-06-30 19:22:16 +02:00
adminChannel = dbot . config . servers [ server ] . admin _channel ,
2014-07-21 23:34:04 +02:00
channels = _ . keys ( dbot . instance . connections [ server ] . channels ) ,
2013-06-10 00:50:11 +02:00
network = event . server ;
if ( this . config . network _name [ event . server ] ) {
network = this . config . network _name [ event . server ] ;
}
2013-05-06 23:56:45 +02:00
2013-06-09 23:07:17 +02:00
dbot . api . nickserv . getUserHost ( event . server , banee , function ( host ) {
// Add host record entry
2013-06-10 18:15:28 +02:00
if ( host ) {
2016-01-28 19:29:51 +01:00
if ( ( reason . match ( '#line' ) || reason . match ( '#specialk' ) || reason . match ( '#kline' ) ) && _ . include ( dbot . access . moderator ( ) , event . rUser . primaryNick ) ) {
var t = ' !P ' ;
if ( timeout ) {
t = ' !T ' + ( timeout * 60 ) ;
}
dbot . say ( event . server , 'operserv' , 'akill add ' + banee + t + banee + ' banned by ' + banner + ': ' + reason ) ;
}
2015-10-27 20:30:32 +01:00
// Ban from current channel first
this . api . ban ( server , host , event . channel ) ;
this . api . kick ( server , banee , event . channel , reason +
2016-01-28 19:29:51 +01:00
' (network-wide ban)' ) ;
2015-10-27 20:30:32 +01:00
channels = _ . without ( channels , event . channel ) ;
2016-01-28 19:29:51 +01:00
if ( ! _ . isUndefined ( adminChannel ) ) {
channels = _ . without ( channels , adminChannel ) ;
} else {
adminChannel = event . channel . name ;
}
2015-10-27 20:30:32 +01:00
2015-10-27 20:36:51 +01:00
// Ban the user from all channels
var i = 0 ;
var banChannel = function ( channels ) {
if ( i >= channels . length ) return ;
var channel = channels [ i ] ;
this . api . ban ( server , host , channel ) ;
this . api . kick ( server , banee , channel , reason +
2016-01-28 19:29:51 +01:00
' (network-wide ban)' ) ;
2015-10-27 20:38:10 +01:00
i ++ ; banChannel ( channels ) ;
2015-10-27 20:36:51 +01:00
} . bind ( this ) ;
banChannel ( channels ) ;
2013-06-10 18:15:28 +02:00
this . hosts [ event . server ] [ banee ] = host ;
// Create notify string
2013-06-10 18:59:56 +02:00
if ( ! _ . isUndefined ( timeout ) ) {
2016-01-15 22:36:24 +01:00
timeout = timeout . trim ( ) ;
var msTimeout = new Date ( new Date ( ) . getTime ( ) + ( parseFloat ( timeout ) * 3600000 ) ) ;
if ( _ . has ( dbot . modules , 'remind' ) ) {
msTimeout = dbot . api . remind . parseTime ( timeout ) ;
2016-01-16 00:22:59 +01:00
if ( ! msTimeout ) {
return event . reply ( 'Invalid time. Remember you must give e.g. 5m now.' ) ;
}
2016-01-28 19:29:51 +01:00
timeout = timeout . replace ( /([\d]+)d/ , '$1 days' ) . replace ( /([\d]+)h/ , '$1 hours ' ) . replace ( /([\d]+)m/ , '$1 minutes ' ) . replace ( /([\d]+)s/ , '$1 seconds' ) . trim ( ) ;
2016-01-15 22:36:24 +01:00
} else {
timeout += ' hours' ;
}
2013-06-10 18:15:28 +02:00
if ( ! _ . has ( this . tempBans , event . server ) ) this . tempBans [ event . server ] = { } ;
2013-06-10 18:59:56 +02:00
this . tempBans [ event . server ] [ banee ] = msTimeout ;
this . internalAPI . addTempBan ( event . server , banee , msTimeout ) ;
var notifyString = dbot . t ( 'tbanned' , {
'network' : network ,
'banner' : banner ,
'banee' : banee ,
'hours' : timeout ,
'reason' : reason
} ) ;
} else {
2013-06-10 18:15:28 +02:00
var notifyString = dbot . t ( 'nbanned' , {
'network' : network ,
'banner' : banner ,
'banee' : banee ,
'reason' : reason
} ) ;
2013-06-10 18:59:56 +02:00
}
2013-06-10 18:15:28 +02:00
// Add qutoe category documenting ban
2013-08-18 22:10:19 +02:00
if ( this . config . document _bans ) {
var id = uuid . v4 ( ) ;
var banRecord = {
'id' : id ,
'time' : new Date ( ) . getTime ( ) ,
'server' : server ,
'banee' : banee ,
'banner' : banner ,
'host' : host ,
'reason' : reason
} ;
this . db . save ( 'nbans' , id , banRecord , function ( ) { } ) ;
2013-07-05 00:37:34 +02:00
}
2013-06-10 18:15:28 +02:00
// Notify moderators, banee
2013-06-30 19:22:16 +02:00
if ( ! _ . isUndefined ( adminChannel ) ) {
2013-06-10 18:15:28 +02:00
channels = _ . without ( channels , adminChannel ) ;
2013-06-30 19:22:16 +02:00
} else {
adminChannel = event . channel . name ;
}
2016-01-28 19:29:51 +01:00
dbot . api . report . notify ( 'ban' , server , event . rUser , adminChannel , notifyString , false , banee ) ;
2013-06-30 19:22:16 +02:00
dbot . say ( event . server , adminChannel , notifyString ) ;
2013-06-10 18:15:28 +02:00
2013-06-30 19:22:16 +02:00
if ( ! _ . isUndefined ( timeout ) ) {
dbot . say ( event . server , banee , dbot . t ( 'tbanned_notify' , {
'network' : network ,
'banner' : banner ,
'reason' : reason ,
'hours' : timeout ,
'admin_channel' : adminChannel
} ) ) ;
} else {
dbot . say ( event . server , banee , dbot . t ( 'nbanned_notify' , {
'network' : network ,
'banner' : banner ,
'reason' : reason ,
'hours' : timeout ,
'admin_channel' : adminChannel
} ) ) ;
2013-06-10 18:15:28 +02:00
}
2014-02-07 16:20:24 +01:00
// err
dbot . say ( event . server , 'NickServ' , 'FREEZE ' + banee + ' ON ' + reason ) ;
2013-06-10 18:15:28 +02:00
} else {
event . reply ( dbot . t ( 'no_user' , { 'user' : banee } ) ) ;
2013-06-09 23:07:17 +02:00
}
} . bind ( this ) ) ;
2013-05-06 23:56:45 +02:00
} ,
2013-06-10 00:50:11 +02:00
'~nunban' : function ( event ) {
var unbanee = event . params [ 1 ] ,
2013-09-08 01:02:04 +02:00
unbanner = event . rUser ;
2013-06-10 00:50:11 +02:00
2013-06-10 18:15:28 +02:00
this . api . networkUnban ( event . server , unbanee , unbanner , function ( err ) {
if ( err ) {
event . reply ( dbot . t ( 'nunban_error' , { 'unbanee' : unbanee } ) ) ;
2013-06-10 00:50:11 +02:00
}
2013-06-10 18:15:28 +02:00
} ) ;
2013-06-10 00:50:11 +02:00
} ,
2013-05-06 23:56:45 +02:00
2013-04-14 16:35:49 +02:00
/*** Kick Stats ***/
// Give the number of times a given user has been kicked and has kicked
// other people.
'~kickcount' : function ( event ) {
var username = event . params [ 1 ] ;
if ( ! _ . has ( dbot . db . kicks , username ) ) {
var kicks = '0' ;
} else {
var kicks = dbot . db . kicks [ username ] ;
}
if ( ! _ . has ( dbot . db . kickers , username ) ) {
var kicked = '0' ;
} else {
var kicked = dbot . db . kickers [ username ] ;
}
event . reply ( dbot . t ( 'user_kicks' , {
'user' : username ,
'kicks' : kicks ,
'kicked' : kicked
} ) ) ;
} ,
// Output a list of the people who have been kicked the most and those
// who have kicked other people the most.
'~kickstats' : function ( event ) {
var orderedKickLeague = function ( list , topWhat ) {
var kickArr = _ . chain ( list )
. pairs ( )
. sortBy ( function ( kick ) { return kick [ 1 ] } )
. reverse ( )
. first ( 10 )
. value ( ) ;
var kickString = "Top " + topWhat + ": " ;
for ( var i = 0 ; i < kickArr . length ; i ++ ) {
kickString += kickArr [ i ] [ 0 ] + " (" + kickArr [ i ] [ 1 ] + "), " ;
}
return kickString . slice ( 0 , - 2 ) ;
} ;
event . reply ( orderedKickLeague ( dbot . db . kicks , 'Kicked' ) ) ;
event . reply ( orderedKickLeague ( dbot . db . kickers , 'Kickers' ) ) ;
2016-02-16 18:32:29 +01:00
} ,
'~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 ) ) {
2016-02-16 18:39:10 +01:00
this . voteQuiets [ user . id ] = { 'user' : user . id , 'channel' : event . channel , 'yes' : [ event . rUser . primaryNick ] , 'no' : [ ] } ;
2016-02-16 18:32:29 +01:00
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 ] ;
2016-02-16 18:37:09 +01:00
if ( event . channel != vq . channel ) {
return event . reply ( 'Vote must be in ' + vq . channel ) ;
}
2016-02-16 18:32:29 +01:00
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 ] ;
2016-02-16 18:37:09 +01:00
if ( event . channel != vq . channel ) {
return event . reply ( 'Vote must be in ' + vq . channel ) ;
}
2016-02-16 18:32:29 +01:00
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 ) ) ;
2013-04-14 16:35:49 +02:00
}
} ;
2013-05-06 23:56:45 +02:00
_ . each ( commands , function ( command ) {
command . access = 'moderator' ;
} ) ;
2013-05-17 10:58:11 +02:00
commands [ '~kickcount' ] . access = 'regular' ;
commands [ '~kickstats' ] . access = 'regular' ;
2016-02-16 18:32:29 +01:00
commands [ '~votequiet' ] . access = 'regular' ;
commands [ '~voteyes' ] . access = 'regular' ;
commands [ '~voteno' ] . access = 'regular' ;
2013-09-07 19:55:48 +02:00
commands [ '~quiet' ] . access = 'voice' ;
2016-03-20 18:48:07 +01:00
commands [ '~timeout' ] . access = 'voice' ;
2013-09-07 19:55:48 +02:00
commands [ '~unquiet' ] . access = 'voice' ;
2016-01-28 19:29:51 +01:00
commands [ '~nban' ] . access = 'power_user' ;
commands [ '~nunban' ] . access = 'power_user' ;
2013-05-17 10:58:11 +02:00
2013-12-29 19:38:24 +01:00
commands [ '~ckick' ] . regex = /^ckick (#[^ ]+ )?([^ ]+) ?(.*)?$/ ;
2016-04-11 23:53:57 +02:00
commands [ '~nban' ] . regex = /^nban (\d[\d\.dhmsy]+)? ?([^ ]+) (.+)$/ ;
2016-01-28 19:41:44 +01:00
commands [ '~quiet' ] . regex = /^quiet (\d[\d\.hms]+)? ?(#[^ ]+ )?([^ ]+) ?(.*)?$/ ;
2016-03-20 18:48:07 +01:00
commands [ '~timeout' ] . regex = /^timeout ([^ ]+) ?(.*)?$/ ;
2013-12-29 19:38:24 +01:00
commands [ '~unquiet' ] . regex = /^unquiet (#[^ ]+ )?([^ ]+) ?$/ ;
2016-02-16 18:32:29 +01:00
commands [ '~votequiet' ] . regex = [ /^votequiet ([^ ]+) (.+)$/ , 3 ] ;
2013-04-14 16:35:49 +02:00
return commands ;
} ;
exports . fetch = function ( dbot ) {
return commands ( dbot ) ;
} ;