2015-02-10 01:34:23 -05:00
var FFZ = window . FrankerFaceZ ,
utils = require ( "../utils" ) ,
2015-07-13 21:52:44 -04:00
constants = require ( "../constants" ) ,
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-10-17 18:05:44 -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>' ;
2015-07-04 17:06:36 -04:00
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-08-04 01:43:08 -04:00
FFZ . basic _settings . enhanced _moderation _cards = {
type : "boolean" ,
no _bttv : true ,
category : "Chat" ,
name : "Enhanced Moderation Cards" ,
help : "Improve moderation cards with hotkeys, additional buttons, chat history, and other information to make moderating easier." ,
get : function ( ) {
return this . settings . mod _card _hotkeys &&
this . settings . mod _card _info &&
this . settings . mod _card _history ;
} ,
set : function ( val ) {
this . settings . set ( 'mod_card_hotkeys' , val ) ;
this . settings . set ( 'mod_card_info' , val ) ;
this . settings . set ( 'mod_card_history' , val ) ;
}
} ;
FFZ . basic _settings . chat _hover _pause = {
type : "boolean" ,
no _bttv : true ,
category : "Chat" ,
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 misclicks." ,
get : 'chat_hover_pause' ,
set : 'chat_hover_pause'
} ;
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" ,
2015-08-04 01:43:08 -04:00
help : "Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks." ,
2015-07-04 17:06:36 -04:00
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."
} ;
2015-07-13 21:52:44 -04:00
FFZ . settings _info . mod _card _info = {
type : "boolean" ,
2015-07-18 21:10:27 -04:00
value : true ,
2015-07-13 21:52:44 -04:00
no _bttv : true ,
category : "Chat Moderation" ,
name : "Moderation Card Additional Information" ,
help : "Display a channel's follower count, view count, and account age on moderation cards."
} ;
2015-07-04 17:06:36 -04:00
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 ;
}
}
} ;
2015-10-17 18:05:44 -04:00
FFZ . settings _info . mod _buttons = {
type : "button" ,
// Special Values
// false = Ban/Unban
// integer = Timeout (that amount of time)
value : [ [ '' , false , false ] , [ '' , 600 , false ] ] , //, ['', 1, false]],
category : "Chat Moderation" ,
no _bttv : true ,
name : "Custom In-Line Moderation Icons" ,
help : "Change out the different in-line moderation icons to use any command quickly." ,
method : function ( ) {
var old _val = "" ;
for ( var i = 0 ; i < this . settings . mod _buttons . length ; i ++ ) {
var pair = this . settings . mod _buttons [ i ] ,
prefix = pair [ 0 ] , cmd = pair [ 1 ] , had _prefix = pair [ 2 ] ;
if ( cmd === false )
cmd = "<BAN>" ;
else if ( typeof cmd !== "string" )
cmd = '' + cmd ;
if ( ! had _prefix )
prefix = '' ;
else
prefix += '=' ;
if ( cmd . substr ( cmd . length - 7 ) === ' {user}' )
cmd = cmd . substr ( 0 , cmd . length - 7 ) ;
if ( cmd . indexOf ( ' ' ) !== - 1 )
old _val += ' ' + prefix + '"' + cmd + '"' ;
else
old _val += ' ' + prefix + cmd ;
}
var new _val = prompt ( "Custom In-Line Moderation Icons\n\nPlease enter a list of commands to be made available as mod icons within chat lines. Commands are separated by spaces. To include spaces in a command, surround the command with double quotes (\"). Use \"{user}\" to insert the user's username into the command, otherwise it will be appended to the end.\n\nExample: !permit \"!reg add {user}\"\n\nNumeric values will become timeout buttons for that number of seconds. The text \"<BAN>\" is a special value that will act like the normal Ban button in chat.\n\nTo assign a specific letter for use as the icon, specify it at the start of the command followed by an equals sign.\n\nExample: A=\"!reg add\"\n\nDefault: <BAN> 600" , old _val ) ;
if ( new _val === null || new _val === undefined )
return ;
var vals = [ ] , prefix = '' ;
new _val = new _val . trim ( ) ;
while ( new _val ) {
if ( new _val . charAt ( 1 ) === '=' ) {
prefix = new _val . charAt ( 0 ) ;
new _val = new _val . substr ( 2 ) ;
continue ;
}
if ( new _val . charAt ( 0 ) === '"' ) {
var end = new _val . indexOf ( '"' , 1 ) ;
if ( end === - 1 )
end = new _val . length ;
var segment = new _val . substr ( 1 , end - 1 ) ;
if ( segment ) {
vals . push ( [ prefix , segment ] ) ;
prefix = '' ;
}
new _val = new _val . substr ( end + 1 ) ;
} else {
var ind = new _val . indexOf ( ' ' ) ;
if ( ind === - 1 ) {
if ( new _val ) {
vals . push ( [ prefix , new _val ] ) ;
prefix = '' ;
}
new _val = '' ;
} else {
var segment = new _val . substr ( 0 , ind ) ;
if ( segment ) {
vals . push ( [ prefix , segment ] ) ;
prefix = '' ;
}
new _val = new _val . substr ( ind + 1 ) ;
}
}
}
var final = [ ] ;
for ( var i = 0 ; i < vals . length ; i ++ ) {
var had _prefix = false , prefix = vals [ i ] [ 0 ] , val = vals [ i ] [ 1 ] ;
if ( val === "<BAN>" )
val = false ;
var num = parseInt ( val ) ;
if ( num > 0 && num !== NaN )
val = num ;
if ( ! prefix ) {
var tmp ;
if ( typeof val === "string" )
tmp = /\w/ . exec ( val ) ;
else
tmp = utils . duration _string ( val ) ;
prefix = tmp && tmp . length ? tmp [ 0 ] . toUpperCase ( ) : "C" ;
} else
had _prefix = true ;
if ( typeof val === "string" && val . indexOf ( '{user}' ) === - 1 )
val += ' {user}' ;
final . push ( [ prefix , val , had _prefix ] ) ;
}
this . settings . set ( 'mod_buttons' , final ) ;
}
} ;
2015-07-13 21:52:44 -04:00
FFZ . settings _info . mod _card _buttons = {
type : "button" ,
value : [ ] ,
category : "Chat Moderation" ,
no _bttv : true ,
name : "Moderation Card Additional Buttons" ,
help : "Add additional buttons to moderation cards for running chat commands on those users." ,
method : function ( ) {
var old _val = "" ;
for ( var i = 0 ; i < this . settings . mod _card _buttons . length ; i ++ ) {
var cmd = this . settings . mod _card _buttons [ i ] ;
if ( cmd . indexOf ( ' ' ) !== - 1 )
old _val += ' "' + cmd + '"' ;
else
old _val += ' ' + cmd ;
}
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
var new _val = prompt ( "Moderation Card Additional Buttons\n\nPlease enter a list of additional commands to display buttons for on moderation cards. Commands are separated by spaces. To include spaces in a command, surround the command with double quotes (\"). Use \"{user}\" to insert the user's username into the command, otherwise it will be appended to the end.\n\nExample: !permit \"!reg add {user}\"" , old _val ) ;
if ( new _val === null || new _val === undefined )
return ;
var vals = [ ] ;
new _val = new _val . trim ( ) ;
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
while ( new _val ) {
if ( new _val . charAt ( 0 ) === '"' ) {
var end = new _val . indexOf ( '"' , 1 ) ;
if ( end === - 1 )
end = new _val . length ;
var segment = new _val . substr ( 1 , end - 1 ) ;
if ( segment )
vals . push ( segment ) ;
2015-08-04 01:43:08 -04:00
new _val = new _val . substr ( end + 1 ) ;
2015-07-13 21:52:44 -04:00
} else {
var ind = new _val . indexOf ( ' ' ) ;
if ( ind === - 1 ) {
if ( new _val )
vals . push ( new _val ) ;
new _val = '' ;
} else {
var segment = new _val . substr ( 0 , ind ) ;
if ( segment )
vals . push ( segment ) ;
new _val = new _val . substr ( ind + 1 ) ;
}
}
}
this . settings . set ( "mod_card_buttons" , vals ) ;
}
} ;
2015-07-04 17:06:36 -04:00
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-07-13 21:52:44 -04:00
ffzRebuildInfo : function ( ) {
var el = this . get ( 'element' ) ,
info = el && el . querySelector ( '.info' ) ;
if ( ! info )
return ;
var out = '<span class="stat tooltip" title="Total Views">' + constants . EYE + ' ' + utils . number _commas ( this . get ( 'cardInfo.user.views' ) || 0 ) + '</span>' ,
since = utils . parse _date ( this . get ( 'cardInfo.user.created_at' ) || '' ) ,
followers = this . get ( 'cardInfo.user.ffz_followers' ) ;
if ( typeof followers === "number" ) {
out += '<span class="stat tooltip" title="Followers">' + constants . HEART + ' ' + utils . number _commas ( followers || 0 ) + '</span>' ;
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
} else if ( followers === undefined ) {
var t = this ;
this . set ( 'cardInfo.user.ffz_followers' , false ) ;
Twitch . api . get ( "channels/" + this . get ( 'cardInfo.user.id' ) + '/follows' , { limit : 1 } ) . done ( function ( data ) {
t . set ( 'cardInfo.user.ffz_followers' , data . _total ) ;
t . ffzRebuildInfo ( ) ;
} ) . fail ( function ( data ) {
t . set ( 'cardInfo.user.ffz_followers' , undefined ) ;
} ) ;
}
if ( since ) {
var age = Math . floor ( ( Date . now ( ) - since . getTime ( ) ) / 1000 ) ;
if ( age > 0 ) {
out += '<span class="stat tooltip" title="Member Since: ' + ( age > 86400 ? since . toLocaleDateString ( ) : since . toLocaleString ( ) ) + '">' + constants . CLOCK + ' ' + utils . human _time ( age , 10 ) + '</span>' ;
}
}
info . innerHTML = out ;
} . observes ( "cardInfo.user.views" ) ,
2015-07-29 01:03:10 -04:00
userName : Ember . computed ( "cardInfo.user.id" , "cardInfo.user.display_name" , function ( ) {
var user _id = this . get ( "cardInfo.user.id" ) ,
alias = f . aliases [ user _id ] ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
return alias || this . get ( "cardInfo.user.display_name" ) || user _id . capitalize ( ) ;
} ) ,
2015-11-07 22:56:15 -05:00
willDestroy : function ( ) {
if ( f . _mod _card === this )
f . _mod _card = undefined ;
this . _super ( ) ;
} ,
2015-02-10 01:34:23 -05:00
didInsertElement : function ( ) {
this . _super ( ) ;
try {
2015-07-04 17:06:36 -04:00
if ( f . has _bttv )
2015-02-10 01:34:23 -05:00
return ;
2015-11-07 22:56:15 -05:00
f . _mod _card = this ;
2015-02-10 01:34:23 -05:00
var el = this . get ( 'element' ) ,
2015-07-13 21:52:44 -04:00
controller = this . get ( 'controller' ) ,
2015-07-29 01:03:10 -04:00
line ,
2015-08-04 01:43:08 -04:00
2015-10-17 18:05:44 -04:00
is _mod = controller . get ( 'cardInfo.isModeratorOrHigher' ) ,
2015-10-24 22:44:00 -04:00
chat = window . App && App . _ _container _ _ . lookup ( 'controller:chat' ) ,
user = f . get _user ( ) ,
2015-11-07 22:56:15 -05:00
room _id = chat && chat . get ( 'currentRoom.id' ) ,
is _broadcaster = user && room _id === user . login ,
2015-10-24 22:44:00 -04:00
2015-07-29 01:03:10 -04:00
user _id = controller . get ( 'cardInfo.user.id' ) ,
alias = f . aliases [ user _id ] ;
2015-11-07 22:56:15 -05:00
this . ffz _room _id = room _id ;
2015-07-29 01:03:10 -04:00
// Alias Display
if ( alias ) {
var name = el . querySelector ( 'h3.name' ) ,
link = name && name . querySelector ( 'a' ) ;
if ( link )
name = link ;
if ( name ) {
name . classList . add ( 'ffz-alias' ) ;
name . title = utils . sanitize ( controller . get ( 'cardInfo.user.display_name' ) || user _id . capitalize ( ) ) ;
jQuery ( name ) . tipsy ( ) ;
}
}
2015-02-10 01:34:23 -05:00
2015-02-10 02:42:11 -05:00
// Style it!
2015-07-13 21:52:44 -04:00
el . classList . add ( 'ffz-moderation-card' ) ;
// Info-tize it!
if ( f . settings . mod _card _info ) {
var info = document . createElement ( 'div' ) ,
after = el . querySelector ( 'h3.name' ) ;
if ( after ) {
el . classList . add ( 'ffz-has-info' ) ;
2015-08-04 01:43:08 -04:00
info . className = 'info channel-stats' ;
2015-07-13 21:52:44 -04:00
after . parentElement . insertBefore ( info , after . nextSibling ) ;
this . ffzRebuildInfo ( ) ;
}
}
// Additional Buttons
2015-10-17 18:05:44 -04:00
if ( is _mod && f . settings . mod _card _buttons && f . settings . mod _card _buttons . length ) {
2015-07-13 21:52:44 -04:00
line = document . createElement ( 'div' ) ;
line . className = 'extra-interface interface clearfix' ;
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
var cmds = { } ,
add _btn _click = function ( cmd ) {
var user _id = controller . get ( 'cardInfo.user.id' ) ,
cont = App . _ _container _ _ . lookup ( 'controller:chat' ) ,
room = cont && cont . get ( 'currentRoom' ) ;
2015-08-04 01:43:08 -04:00
2015-10-17 18:05:44 -04:00
room && room . send ( cmd . replace ( /{user}/g , user _id ) , true ) ;
2015-07-13 21:52:44 -04:00
} ,
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
add _btn _make = function ( cmd ) {
var btn = document . createElement ( 'button' ) ,
segment = cmd . split ( ' ' , 1 ) [ 0 ] ,
title = cmds [ segment ] > 1 ? cmd . split ( ' ' , cmds [ segment ] ) : [ segment ] ;
if ( /^[!~./]/ . test ( title [ 0 ] ) )
title [ 0 ] = title [ 0 ] . substr ( 1 ) ;
title = _ . map ( title , function ( s ) { return s . capitalize ( ) } ) . join ( ' ' ) ;
btn . className = 'button' ;
btn . innerHTML = utils . sanitize ( title ) ;
btn . title = utils . sanitize ( cmd . replace ( /{user}/g , controller . get ( 'cardInfo.user.id' ) || '{user}' ) ) ;
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
jQuery ( btn ) . tipsy ( ) ;
btn . addEventListener ( 'click' , add _btn _click . bind ( this , cmd ) ) ;
return btn ;
} ;
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
var cmds = { } ;
for ( var i = 0 ; i < f . settings . mod _card _buttons . length ; i ++ )
cmds [ f . settings . mod _card _buttons [ i ] . split ( ' ' , 1 ) [ 0 ] ] = ( cmds [ f . settings . mod _card _buttons [ i ] . split ( ' ' , 1 ) [ 0 ] ] || 0 ) + 1 ;
for ( var i = 0 ; i < f . settings . mod _card _buttons . length ; i ++ ) {
var cmd = f . settings . mod _card _buttons [ i ] ,
ind = cmd . indexOf ( '{user}' ) ;
if ( ind === - 1 )
cmd += ' {user}' ;
line . appendChild ( add _btn _make ( cmd ) )
}
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
el . appendChild ( line ) ;
}
// Key Handling
el . setAttribute ( 'tabindex' , 1 ) ;
if ( f . settings . mod _card _hotkeys ) {
el . classList . add ( 'no-mousetrap' ) ;
el . addEventListener ( 'keyup' , function ( e ) {
var key = e . keyCode || e . which ,
user _id = controller . get ( 'cardInfo.user.id' ) ,
is _mod = controller . get ( 'cardInfo.isModeratorOrHigher' ) ,
room = App . _ _container _ _ . lookup ( 'controller:chat' ) . get ( 'currentRoom' ) ;
if ( is _mod && key == keycodes . P )
2015-10-17 18:05:44 -04:00
room . send ( "/timeout " + user _id + " 1" , true ) ;
2015-07-13 21:52:44 -04:00
else if ( is _mod && key == keycodes . B )
2015-10-17 18:05:44 -04:00
room . send ( "/ban " + user _id , true ) ;
2015-07-13 21:52:44 -04:00
else if ( is _mod && key == keycodes . T )
2015-10-17 18:05:44 -04:00
room . send ( "/timeout " + user _id + " 600" , true ) ;
2015-07-13 21:52:44 -04:00
else if ( is _mod && key == keycodes . U )
2015-10-17 18:05:44 -04:00
room . send ( "/unban " + user _id , true ) ;
2015-07-13 21:52:44 -04:00
else if ( key != keycodes . ESC )
return ;
controller . send ( 'close' ) ;
} ) ;
}
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-10-17 18:05:44 -04:00
if ( is _mod ) {
2015-02-10 02:42:11 -05:00
el . classList . add ( 'ffz-is-mod' ) ;
2015-08-04 01:43:08 -04:00
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 )
2015-10-17 18:05:44 -04:00
room . send ( "/unban " + user _id , true ) ;
2015-07-04 17:06:36 -04:00
else
2015-10-17 18:05:44 -04:00
room . send ( "/timeout " + user _id + " " + timeout , true ) ;
2015-07-04 17:06:36 -04:00
} ,
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' ;
2015-10-17 18:05:44 -04:00
btn . innerHTML = utils . duration _string ( timeout ) ;
2015-07-04 17:06:36 -04:00
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
2015-07-13 21:52:44 -04:00
line = document . createElement ( 'div' ) ;
line . className = 'extra-interface 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-10-24 22:44:00 -04:00
var can _op = is _broadcaster || ( 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 ) ;
}
2015-07-13 21:52:44 -04:00
var msg _btn = el . querySelector ( ".interface > button.message-button" ) ;
if ( msg _btn ) {
msg _btn . innerHTML = 'W' ;
2015-02-10 01:34:23 -05:00
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-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
var real _msg = document . createElement ( 'button' ) ;
2015-07-29 01:03:10 -04:00
real _msg . className = 'message-button button glyph-only message tooltip' ;
2015-07-13 21:52:44 -04:00
real _msg . innerHTML = MESSAGE ;
real _msg . title = "Message User" ;
2015-08-04 01:43:08 -04:00
2015-07-13 21:52:44 -04:00
real _msg . addEventListener ( 'click' , function ( ) {
window . open ( 'http://www.twitch.tv/message/compose?to=' + controller . get ( 'cardInfo.user.id' ) ) ;
} )
msg _btn . parentElement . insertBefore ( real _msg , msg _btn . nextSibling ) ;
2015-02-10 01:34:23 -05:00
}
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
// Alias Button
var alias _btn = document . createElement ( 'button' ) ;
alias _btn . className = 'alias button glyph-only tooltip' ;
alias _btn . innerHTML = constants . EDIT ;
alias _btn . title = "Set Alias" ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
alias _btn . addEventListener ( 'click' , function ( ) {
var user = controller . get ( 'cardInfo.user.id' ) ,
alias = f . aliases [ user ] ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
var new _val = prompt ( "Alias for User: " + user + "\n\nPlease enter an alias for the user. Leave it blank to remove the alias." , alias ) ;
if ( new _val === null || new _val === undefined )
return ;
new _val = new _val . trim ( ) ;
if ( ! new _val )
new _val = undefined ;
f . aliases [ user ] = new _val ;
f . save _aliases ( ) ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
// Update UI
2015-07-31 17:44:20 -04:00
f . _update _alias ( user ) ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
Ember . propertyDidChange ( controller , 'userName' ) ;
var name = el . querySelector ( 'h3.name' ) ,
link = name && name . querySelector ( 'a' ) ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
if ( link )
name = link ;
if ( name )
2015-08-04 01:43:08 -04:00
name . classList . toggle ( 'ffz-alias' , new _val ) ;
2015-07-29 01:03:10 -04:00
} ) ;
2015-08-04 01:43:08 -04:00
2015-07-29 01:03:10 -04:00
if ( msg _btn )
msg _btn . parentElement . insertBefore ( alias _btn , msg _btn ) ;
else {
var follow _btn = el . querySelector ( ".interface > .follow-button" ) ;
if ( follow _btn )
follow _btn . parentElement . insertBefore ( alias _btn , follow _btn . nextSibling ) ;
}
2015-02-10 01:34:23 -05:00
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' ) ,
2015-11-11 16:03:27 -05:00
tmiSession = room . tmiSession || ( window . TMI && TMI . _sessions && TMI . _sessions [ 0 ] ) ,
room _id = room . get ( 'id' ) ,
user _id = controller . get ( 'cardInfo.user.id' ) ,
ffz _room = room && f . rooms && f . rooms [ room _id ] ,
user _history = ffz _room && ffz _room . user _history && ffz _room . user _history [ user _id ] || [ ] ,
history = document . createElement ( 'ul' ) ;
history . className = 'interface clearfix chat-history' ;
if ( user _history . length < 20 ) {
var before = user _history . length > 0 ? user _history [ 0 ] . date . getTime ( ) : Date . now ( ) ;
f . ws _send ( "user_history" , [ room _id , user _id , 50 - user _history . length ] , function ( success , data ) {
if ( ! success )
return ;
var i = data . length ,
was _at _top = history && history . scrollTop >= ( history . scrollHeight - history . clientHeight ) ,
first = true ;
while ( i -- ) {
var msg = data [ i ] ;
if ( ! msg )
continue ;
if ( typeof msg . date === "string" || typeof msg . date === "number" )
msg . date = utils . parse _date ( msg . date ) ;
if ( ! msg . date || msg . date . getTime ( ) >= before )
continue ;
if ( first ) {
first = false ;
history . insertBefore ( f . _build _mod _card _history ( {
date : msg . date ,
from : "jtv" ,
style : "admin" ,
cachedTokens : [ "(Server History Above)" ]
} ) , history . firstElementChild ) ;
}
if ( ! msg . style ) {
if ( msg . from === "jtv" )
msg . style = "admin" ;
else if ( msg . from === "twitchnotify" )
msg . style = "notification" ;
}
if ( msg . tags && typeof msg . tags . emotes === "string" )
try {
msg . tags . emotes = JSON . parse ( msg . tags . emotes ) ;
} catch ( err ) {
f . log ( "Error Parsing JSON Emotes: " + err ) ;
msg . tags . emotes = { } ;
}
if ( ! msg . cachedTokens || ! msg . cachedTokens . length )
f . tokenize _chat _line ( msg , true , room . get ( 'roomProperties.hide_chat_links' ) ) ;
history . insertBefore ( f . _build _mod _card _history ( msg ) , history . firstElementChild ) ;
if ( history . childElementCount >= 50 )
break ;
}
if ( was _at _top )
setTimeout ( function ( ) { history . scrollTop = history . scrollHeight ; } ) ;
} ) ;
}
2015-11-07 22:56:15 -05:00
2015-11-11 16:03:27 -05:00
for ( var i = 0 ; i < user _history . length ; i ++ )
history . appendChild ( f . _build _mod _card _history ( user _history [ i ] ) ) ;
2015-07-04 17:06:36 -04:00
2015-11-11 16:03:27 -05:00
el . appendChild ( history ) ;
2015-07-04 17:06:36 -04:00
2015-11-11 16:03:27 -05:00
// Lazy scroll-to-bottom
history . scrollTop = history . scrollHeight ;
2015-07-04 17:06:36 -04:00
}
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 ) { }
}
} } ) ;
}
2015-11-11 16:03:27 -05:00
FFZ . prototype . _build _mod _card _history = function ( line ) {
var l _el = document . createElement ( 'li' ) ,
f = this ;
l _el . className = 'message-line chat-line clearfix' ;
if ( line . ffz _has _mention )
l _el . classList . add ( 'ffz-mentioned' ) ;
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>' ;
// Interactivity
jQuery ( 'a.deleted-link' , l _el ) . click ( f . _deleted _link _click ) ;
jQuery ( 'img.emoticon' , l _el ) . click ( function ( e ) { f . _click _emote ( this , e ) } ) ;
jQuery ( '.html-tooltip' , l _el ) . tipsy ( { html : true } ) ;
return l _el ;
}
2015-07-31 17:44:20 -04:00
// ----------------
// Aliases
// ----------------
FFZ . prototype . _update _alias = function ( user ) {
var alias = this . aliases && this . aliases [ user ] ,
2015-08-04 01:43:08 -04:00
cap _name = FFZ . get _capitalization ( user ) ,
display _name = alias || cap _name ,
2015-07-31 17:44:20 -04:00
el = this . _roomv && this . _roomv . get ( 'element' ) ,
lines = el && el . querySelectorAll ( '.chat-line[data-sender="' + user + '"]' ) ;
2015-08-04 01:43:08 -04:00
2015-07-31 17:44:20 -04:00
if ( ! lines )
return ;
for ( var i = 0 , l = lines . length ; i < l ; i ++ ) {
var line = lines [ i ] ,
el _from = line . querySelector ( '.from' ) ;
2015-08-04 01:43:08 -04:00
2015-07-31 17:44:20 -04:00
el _from . classList . toggle ( 'ffz-alias' , alias ) ;
el _from . textContent = display _name ;
2015-08-04 01:43:08 -04:00
el _from . title = alias ? cap _name : '' ;
2015-07-31 17:44:20 -04:00
}
}
2015-02-10 01:34:23 -05:00
// ----------------
// 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 )
2015-10-17 18:05:44 -04:00
room . room . send ( "/timeout " + name + " 1" , true ) ;
2015-02-10 01:34:23 -05:00
}
}
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]" ;
2015-10-17 18:05:44 -04:00
room . room . send ( "/timeout " + args . join ( " " ) , true ) ;
2015-02-10 01:34:23 -05:00
}
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 )
2015-10-17 18:05:44 -04:00
room . room . send ( "/ban " + name , true ) ;
2015-02-10 01:34:23 -05:00
}
}
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 )
2015-10-17 18:05:44 -04:00
room . room . send ( "/unban " + name , true ) ;
2015-02-10 01:34:23 -05:00
}
}
2015-07-04 17:06:36 -04:00
FFZ . chat _commands . u . enabled = function ( ) { return this . settings . short _commands ; }