2015-02-10 01:34:23 -05:00
var FFZ = window . FrankerFaceZ ,
utils = require ( "../utils" ) ,
2015-07-04 17:06:36 -04:00
helpers ,
2015-02-10 01:34:23 -05:00
keycodes = {
ESC : 27 ,
P : 80 ,
B : 66 ,
2015-05-17 19:02:57 -04:00
T : 84 ,
U : 85
2015-02-10 01:34:23 -05:00
} ,
2015-02-10 02:42:11 -05:00
MESSAGE = '<svg class="svg-messages" height="16px" version="1.1" viewBox="0 0 18 18" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M1,15V3h16v12H1z M15.354,5.354l-0.707-0.707L9,10.293L3.354,4.646L2.646,5.354L6.293,9l-3.646,3.646l0.707,0.707L7,9.707l1.646,1.646h0.707L11,9.707l3.646,3.646l0.707-0.707L11.707,9L15.354,5.354z" fill-rule="evenodd"></path></svg>' ,
2015-07-04 17:06:36 -04:00
CHECK = '<svg class="svg-unban" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path fill-rule="evenodd" clip-rule="evenodd" fill="#888888" d="M6.5,12.75L2,8.25l2-2l2.5,2.5l5.5-5.5l2,2L6.5,12.75z"/></svg>' ,
DURATIONS = { } ,
duration _string = function ( val ) {
if ( val === 1 )
return 'Purge' ;
if ( DURATIONS [ val ] )
return DURATIONS [ val ] ;
var weeks , days , hours , minutes , seconds ;
weeks = Math . floor ( val / 604800 ) ;
seconds = val % 604800 ;
days = Math . floor ( seconds / 86400 ) ;
seconds %= 86400 ;
hours = Math . floor ( seconds / 3600 ) ;
seconds %= 3600 ;
minutes = Math . floor ( seconds / 60 ) ;
seconds %= 60 ;
var out = DURATIONS [ val ] = ( weeks ? weeks + 'w' : '' ) + ( ( days || ( weeks && ( hours || minutes || seconds ) ) ) ? days + 'd' : '' ) + ( ( hours || ( ( weeks || days ) && ( minutes || seconds ) ) ) ? hours + 'h' : '' ) + ( ( minutes || ( ( weeks || days || hours ) && seconds ) ) ? minutes + 'm' : '' ) + ( seconds ? seconds + 's' : '' ) ;
return out ;
} ;
try {
helpers = window . require && window . require ( "ember-twitch-chat/helpers/chat-line-helpers" ) ;
} catch ( err ) { }
2015-02-10 01:34:23 -05:00
// ----------------
// Settings
// ----------------
2015-07-04 17:06:36 -04:00
FFZ . settings _info . chat _hover _pause = {
2015-02-10 01:34:23 -05:00
type : "boolean" ,
value : false ,
2015-05-17 19:02:57 -04:00
no _bttv : true ,
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
category : "Chat Moderation" ,
name : "Pause Chat Scrolling on Mouse Hover" ,
help : "Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link mis-clicks." ,
on _update : function ( val ) {
if ( ! this . _roomv )
return ;
if ( val )
this . _roomv . ffzEnableFreeze ( ) ;
else
this . _roomv . ffzDisableFreeze ( ) ;
}
} ;
FFZ . settings _info . short _commands = {
type : "boolean" ,
value : true ,
no _bttv : true ,
category : "Chat Moderation" ,
name : "Short Moderation Commands" ,
help : "Use /t, /b, and /u in chat in place of /timeout, /ban, /unban for quicker moderation, and use /p for 1 second timeouts."
} ;
FFZ . settings _info . mod _card _hotkeys = {
type : "boolean" ,
value : false ,
no _bttv : true ,
category : "Chat Moderation" ,
name : "Moderation Card Hotkeys" ,
help : "With a moderation card selected, press B to ban the user, T to time them out for 10 minutes, P to time them out for 1 second, or U to unban them. ESC closes the card."
} ;
FFZ . settings _info . mod _card _history = {
type : "boolean" ,
value : false ,
no _bttv : true ,
category : "Chat Moderation" ,
name : "Moderation Card History" ,
help : "Display a few of the user's previously sent messages on moderation cards." ,
on _update : function ( val ) {
if ( val || ! this . rooms )
return ;
// Delete all history~!
for ( var room _id in this . rooms ) {
var room = this . rooms [ room _id ] ;
if ( room )
room . user _history = undefined ;
}
}
} ;
FFZ . settings _info . mod _card _durations = {
type : "button" ,
value : [ 300 , 600 , 3600 , 43200 , 86400 , 604800 ] ,
category : "Chat Moderation" ,
no _bttv : true ,
name : "Moderation Card Timeout Buttons" ,
help : "Add additional timeout buttons to moderation cards with specific durations." ,
method : function ( ) {
var old _val = this . settings . mod _card _durations . join ( ", " ) ,
new _val = prompt ( "Moderation Card Timeout Buttons\n\nPlease enter a comma-separated list of durations that you would like to have timeout buttons for. Durations must be expressed in seconds.\n\nEnter \"reset\" without quotes to return to the default value." , old _val ) ;
if ( new _val === null || new _val === undefined )
return ;
if ( new _val === "reset" )
new _val = FFZ . settings _info . mod _card _durations . value . join ( ", " ) ;
// Split them up.
new _val = new _val . trim ( ) . split ( /[ ,]+/ ) ;
var vals = [ ] ;
for ( var i = 0 ; i < new _val . length ; i ++ ) {
var val = parseInt ( new _val [ i ] ) ;
if ( val === 0 )
val = 1 ;
if ( val !== NaN && val > 0 )
vals . push ( val ) ;
}
this . settings . set ( "mod_card_durations" , vals ) ;
}
2015-02-10 01:34:23 -05:00
} ;
// ----------------
// Initialization
// ----------------
FFZ . prototype . setup _mod _card = function ( ) {
2015-07-04 17:06:36 -04:00
this . log ( "Modifying Mousetrap stopCallback so we can catch ESC." ) ;
var orig _stop = Mousetrap . stopCallback ;
Mousetrap . stopCallback = function ( e , element , combo ) {
if ( element . classList . contains ( 'no-mousetrap' ) )
return true ;
return orig _stop ( e , element , combo ) ;
}
Mousetrap . bind ( "up up down down left right left right b a enter" , function ( ) {
var el = document . querySelector ( ".app-main" ) || document . querySelector ( ".ember-chat-container" ) ;
el && el . classList . toggle ( 'ffz-flip' ) ;
} ) ;
2015-02-10 01:34:23 -05:00
this . log ( "Hooking the Ember Moderation Card view." ) ;
2015-05-17 19:02:57 -04:00
var Card = App . _ _container _ _ . resolve ( 'component:moderation-card' ) ,
2015-02-10 01:34:23 -05:00
f = this ;
Card . reopen ( {
2015-07-04 17:06:36 -04:00
ffzForceRedraw : function ( ) {
this . rerender ( ) ;
} . observes ( "cardInfo.isModeratorOrHigher" , "cardInfo.user" ) ,
2015-02-10 01:34:23 -05:00
didInsertElement : function ( ) {
this . _super ( ) ;
2015-05-17 19:02:57 -04:00
window . _card = this ;
2015-02-10 01:34:23 -05:00
try {
2015-07-04 17:06:36 -04:00
if ( f . has _bttv )
2015-02-10 01:34:23 -05:00
return ;
var el = this . get ( 'element' ) ,
2015-05-17 19:02:57 -04:00
controller = this . get ( 'controller' ) ;
2015-02-10 01:34:23 -05:00
2015-02-10 02:42:11 -05:00
// Style it!
2015-07-04 17:06:36 -04:00
if ( f . settings . mod _card _hotkeys || ( f . settings . mod _card _durations && f . settings . mod _card _durations . length ) )
el . classList . add ( 'ffz-moderation-card' ) ;
2015-02-10 02:42:11 -05:00
2015-02-10 01:34:23 -05:00
// Only do the big stuff if we're mod.
2015-05-17 19:02:57 -04:00
if ( controller . get ( 'cardInfo.isModeratorOrHigher' ) ) {
2015-02-10 02:42:11 -05:00
el . classList . add ( 'ffz-is-mod' ) ;
2015-02-10 01:34:23 -05:00
el . setAttribute ( 'tabindex' , 1 ) ;
// Key Handling
2015-07-04 17:06:36 -04:00
if ( f . settings . mod _card _hotkeys ) {
el . classList . add ( 'no-mousetrap' ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
el . addEventListener ( 'keyup' , function ( e ) {
var key = e . keyCode || e . which ,
user _id = controller . get ( 'cardInfo.user.id' ) ,
room = App . _ _container _ _ . lookup ( 'controller:chat' ) . get ( 'currentRoom' ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
if ( key == keycodes . P )
room . send ( "/timeout " + user _id + " 1" ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
else if ( key == keycodes . B )
room . send ( "/ban " + user _id ) ;
2015-05-17 19:02:57 -04:00
2015-07-04 17:06:36 -04:00
else if ( key == keycodes . T )
room . send ( "/timeout " + user _id + " 600" ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
else if ( key == keycodes . U )
room . send ( "/unban " + user _id ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
else if ( key != keycodes . ESC )
return ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
controller . send ( 'close' ) ;
} ) ;
}
2015-02-10 01:34:23 -05:00
var btn _click = function ( timeout ) {
2015-07-04 17:06:36 -04:00
var user _id = controller . get ( 'cardInfo.user.id' ) ,
room = App . _ _container _ _ . lookup ( 'controller:chat' ) . get ( 'currentRoom' ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
if ( timeout === - 1 )
room . send ( "/unban " + user _id ) ;
else
room . send ( "/timeout " + user _id + " " + timeout ) ;
} ,
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
btn _make = function ( timeout ) {
var btn = document . createElement ( 'button' )
btn . className = 'button' ;
btn . innerHTML = duration _string ( timeout ) ;
btn . title = "Timeout User for " + utils . number _commas ( timeout ) + " Second" + ( timeout != 1 ? "s" : "" ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
if ( f . settings . mod _card _hotkeys && timeout === 600 )
btn . title = "(T)" + btn . title . substr ( 1 ) ;
else if ( f . settings . mod _card _hotkeys && timeout === 1 )
btn . title = "(P)urge - " + btn . title ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
jQuery ( btn ) . tipsy ( ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
btn . addEventListener ( 'click' , btn _click . bind ( this , timeout ) ) ;
return btn ;
} ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
if ( f . settings . mod _card _durations && f . settings . mod _card _durations . length ) {
// Extra Moderation
var line = document . createElement ( 'div' ) ;
line . className = 'interface clearfix' ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
line . appendChild ( btn _make ( 1 ) ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
var s = document . createElement ( 'span' ) ;
s . className = 'right' ;
line . appendChild ( s ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
for ( var i = 0 ; i < f . settings . mod _card _durations . length ; i ++ )
s . appendChild ( btn _make ( f . settings . mod _card _durations [ i ] ) ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
el . appendChild ( line ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
// Fix Other Buttons
this . $ ( "button.timeout" ) . remove ( ) ;
}
var ban _btn = el . querySelector ( 'button.ban' ) ;
if ( f . settings . mod _card _hotkeys )
ban _btn . setAttribute ( 'title' , '(B)an User' ) ;
2015-02-10 01:34:23 -05:00
2015-07-04 17:06:36 -04:00
// Unban Button
2015-02-10 01:34:23 -05:00
var unban _btn = document . createElement ( 'button' ) ;
unban _btn . className = 'unban button glyph-only light' ;
2015-02-10 02:42:11 -05:00
unban _btn . innerHTML = CHECK ;
2015-07-04 17:06:36 -04:00
unban _btn . title = ( f . settings . mod _card _hotkeys ? "(U)" : "U" ) + "nban User" ;
2015-02-10 01:34:23 -05:00
jQuery ( unban _btn ) . tipsy ( ) ;
unban _btn . addEventListener ( "click" , btn _click . bind ( this , - 1 ) ) ;
jQuery ( ban _btn ) . after ( unban _btn ) ;
}
// More Fixing Other Buttons
var op _btn = el . querySelector ( 'button.mod' ) ;
if ( op _btn ) {
2015-05-17 19:02:57 -04:00
var is _owner = controller . get ( 'cardInfo.isChannelOwner' ) ,
user = ffz . get _user ( ) ;
can _op = is _owner || ( user && user . is _admin ) || ( user && user . is _staff ) ;
2015-02-10 01:34:23 -05:00
if ( ! can _op )
op _btn . parentElement . removeChild ( op _btn ) ;
}
var msg _btn = el . querySelector ( ".interface > button" ) ;
2015-05-17 19:02:57 -04:00
if ( msg _btn && msg _btn . classList . contains ( "message-button" ) ) {
2015-02-10 01:34:23 -05:00
msg _btn . innerHTML = MESSAGE ;
msg _btn . classList . add ( 'glyph-only' ) ;
msg _btn . classList . add ( 'message' ) ;
2015-07-04 17:06:36 -04:00
msg _btn . title = "Whisper User" ;
2015-02-10 01:34:23 -05:00
jQuery ( msg _btn ) . tipsy ( ) ;
}
2015-07-04 17:06:36 -04:00
// Message History
if ( f . settings . mod _card _history ) {
var Chat = App . _ _container _ _ . lookup ( 'controller:chat' ) ,
room = Chat && Chat . get ( 'currentRoom' ) ,
ffz _room = room && f . rooms && f . rooms [ room . get ( 'id' ) ] ,
user _history = ffz _room && ffz _room . user _history && ffz _room . user _history [ controller . get ( 'cardInfo.user.id' ) ] ;
if ( user _history && user _history . length ) {
var history = document . createElement ( 'ul' ) ,
alternate = false ;
history . className = 'interface clearfix chat-history' ;
for ( var i = 0 ; i < user _history . length ; i ++ ) {
var line = user _history [ i ] ,
l _el = document . createElement ( 'li' ) ;
l _el . className = 'message-line chat-line' ;
l _el . classList . toggle ( 'ffz-alternate' , alternate ) ;
alternate = ! alternate ;
if ( line . style )
l _el . classList . add ( line . style ) ;
l _el . innerHTML = ( helpers ? '<span class="timestamp float-left">' + helpers . getTime ( line . date ) + '</span> ' : '' ) + '<span class="message">' + ( line . style === 'action' ? '*' + line . from + ' ' : '' ) + f . render _tokens ( line . cachedTokens ) + '</span>' ;
// Banned Links
var bad _links = l _el . querySelectorAll ( 'a.deleted-link' ) ;
for ( var x = 0 ; x < bad _links . length ; x ++ )
bad _links [ x ] . addEventListener ( "click" , f . _deleted _link _click ) ;
jQuery ( 'a' , l _el ) . tipsy ( { html : true } ) ;
history . appendChild ( l _el ) ;
}
el . appendChild ( history ) ;
// Lazy scroll-to-bottom
history . scrollTop = history . scrollHeight ;
}
}
2015-07-06 00:09:21 -04:00
// Reposition the menu if it's off-screen.
var el _bound = el . getBoundingClientRect ( ) ,
body _bound = document . body . getBoundingClientRect ( ) ;
if ( el _bound . bottom > body _bound . bottom ) {
var offset = el _bound . bottom - body _bound . bottom ;
if ( el _bound . top - offset > body _bound . top )
el . style . top = ( el _bound . top - offset ) + "px" ;
}
2015-02-10 01:34:23 -05:00
// Focus the Element
this . $ ( ) . draggable ( {
start : function ( ) {
el . focus ( ) ;
} } ) ;
el . focus ( ) ;
} catch ( err ) {
try {
f . error ( "ModerationCardView didInsertElement: " + err ) ;
} catch ( err ) { }
}
} } ) ;
}
// ----------------
// Chat Commands
// ----------------
2015-07-04 17:06:36 -04:00
FFZ . chat _commands . purge = function ( room , args ) {
2015-02-10 01:34:23 -05:00
if ( ! args || ! args . length )
return "Purge Usage: /p username [more usernames separated by spaces]" ;
if ( args . length > 10 )
return "Please only purge up to 10 users at once." ;
for ( var i = 0 ; i < args . length ; i ++ ) {
var name = args [ i ] ;
if ( name )
room . room . send ( "/timeout " + name + " 1" ) ;
}
}
2015-07-04 17:06:36 -04:00
FFZ . chat _commands . p = function ( room , args ) {
return FFZ . chat _commands . purge . bind ( this ) ( room , args ) ;
}
FFZ . chat _commands . p . enabled = function ( ) { return this . settings . short _commands ; }
2015-02-10 01:34:23 -05:00
FFZ . chat _commands . t = function ( room , args ) {
if ( ! args || ! args . length )
return "Timeout Usage: /t username [duration]" ;
room . room . send ( "/timeout " + args . join ( " " ) ) ;
}
2015-07-04 17:06:36 -04:00
FFZ . chat _commands . t . enabled = function ( ) { return this . settings . short _commands ; }
2015-02-10 01:34:23 -05:00
FFZ . chat _commands . b = function ( room , args ) {
if ( ! args || ! args . length )
return "Ban Usage: /b username [more usernames separated by spaces]" ;
if ( args . length > 10 )
return "Please only ban up to 10 users at once." ;
for ( var i = 0 ; i < args . length ; i ++ ) {
var name = args [ i ] ;
if ( name )
room . room . send ( "/ban " + name ) ;
}
}
2015-07-04 17:06:36 -04:00
FFZ . chat _commands . b . enabled = function ( ) { return this . settings . short _commands ; }
2015-02-10 01:34:23 -05:00
FFZ . chat _commands . u = function ( room , args ) {
if ( ! args || ! args . length )
2015-02-24 00:33:29 -05:00
return "Unban Usage: /u username [more usernames separated by spaces]" ;
2015-02-10 01:34:23 -05:00
if ( args . length > 10 )
return "Please only unban up to 10 users at once." ;
for ( var i = 0 ; i < args . length ; i ++ ) {
var name = args [ i ] ;
if ( name )
room . room . send ( "/unban " + name ) ;
}
}
2015-07-04 17:06:36 -04:00
FFZ . chat _commands . u . enabled = function ( ) { return this . settings . short _commands ; }