2015-06-05 03:59:28 -04:00
var FFZ = window . FrankerFaceZ ,
utils = require ( "./utils" ) ,
2015-07-04 17:06:36 -04:00
constants = require ( "./constants" ) ,
2015-06-05 03:59:28 -04:00
helpers ,
2015-11-14 23:52:49 -05:00
conv _helpers ,
2016-06-22 14:23:03 -04:00
emote _helpers ,
2016-07-13 02:06:50 -04:00
bits _helpers ,
bits _service ,
2016-11-21 20:36:17 -05:00
bits _tags ,
2015-06-05 03:59:28 -04:00
2016-08-09 20:45:28 -04:00
HOP = Object . prototype . hasOwnProperty ,
2017-04-05 19:12:11 -04:00
FAV _MARKER = '<span class="ffz-favorite"></span>' ,
2016-07-13 02:31:26 -04:00
EXPLANATION _WARN = '<hr>This link has been sent to you via a whisper rather than standard chat, and has not been checked or approved of by any moderators or staff members. Please treat this link with caution and do not visit it if you do not trust the sender.' ,
2015-07-29 01:03:10 -04:00
2015-06-05 03:59:28 -04:00
reg _escape = function ( str ) {
return str . replace ( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g , "\\$&" ) ;
} ,
2016-08-09 20:45:28 -04:00
LINK = /(?:https?:\/\/)?(?:[-a-zA-Z0-9@:%_\+~#=]+\.)+[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=()]*)/g ,
2015-08-21 19:00:48 -04:00
2017-03-01 22:02:21 -05:00
CLIP _URL = /^(?:https?:\/\/)?clips\.twitch\.tv\/(\w+?\/?\w*?)(?:\/edit)?(?:[\?#]|$)/ ,
VIDEO _URL = /^(?:https?:\/\/)?(?:www\.)twitch\.tv\/(?:\w+\/v|videos)\/(\w+)$/ ,
2016-07-13 02:06:50 -04:00
2015-07-29 01:03:10 -04:00
LINK _SPLIT = /^(?:(https?):\/\/)?(?:(.*?)@)?([^\/:]+)(?::(\d+))?(.*?)(?:\?(.*?))?(?:\#(.*?))?$/ ,
YOUTUBE _CHECK = /^(?:https?:\/\/)?(?:m\.|www\.)?youtu(?:be\.com|\.be)\/(?:v\/|watch\/|.*?(?:embed|watch).*?v=)?([a-zA-Z0-9\-_]+)$/ ,
IMGUR _PATH = /^\/(?:gallery\/)?[A-Za-z0-9]+(?:\.(?:png|jpg|jpeg|gif|gifv|bmp))?$/ ,
IMAGE _EXT = /\.(?:png|jpg|jpeg|gif|bmp)$/i ,
IMAGE _DOMAINS = [ ] ,
2015-08-21 19:00:48 -04:00
2015-07-29 01:03:10 -04:00
is _image = function ( href , any _domain ) {
var match = href . match ( LINK _SPLIT ) ;
if ( ! match )
return ;
var domain = match [ 3 ] . toLowerCase ( ) , port = match [ 4 ] ,
path = match [ 5 ] ;
// Don't allow non-standard ports.
if ( port && port !== '80' && port !== '443' )
return false ;
// imgur-specific checks.
if ( domain === 'i.imgur.com' || domain === 'imgur.com' || domain === 'www.imgur.com' || domain === 'm.imgur.com' )
return IMGUR _PATH . test ( path ) ;
2015-08-21 19:00:48 -04:00
return any _domain ? IMAGE _EXT . test ( path ) : IMAGE _DOMAINS . indexOf ( domain ) !== - 1 ;
2015-11-14 23:52:49 -05:00
} ,
2015-08-21 19:00:48 -04:00
2015-07-29 01:03:10 -04:00
image _iframe = function ( href , extra _class ) {
2015-10-17 18:05:44 -04:00
return '<iframe class="ffz-image-hover' + ( extra _class ? ' ' + extra _class : '' ) + '" allowtransparency="true" src="' + constants . SERVER + 'script/img-proxy.html#' + utils . quote _attr ( href ) + '"></iframe>' ;
2015-07-29 01:03:10 -04:00
} ,
load _link _data = function ( href , success , data ) {
if ( ! success )
return ;
this . _link _data [ href ] = data ;
2015-10-24 22:38:04 -07:00
//data.unsafe = false;
2015-07-29 01:03:10 -04:00
2016-07-13 02:31:26 -04:00
if ( ! this . settings . link _info )
return ;
2015-07-29 01:03:10 -04:00
2016-07-13 02:31:26 -04:00
// If this link is unsafe, add the unsafe-link class to all instances of the link.
if ( data . unsafe )
jQuery ( 'a.chat-link[data-url="' + href + '"]' ) . addClass ( 'unsafe-link' ) ;
2015-07-29 01:03:10 -04:00
} ;
2015-06-05 03:59:28 -04:00
2015-07-04 17:06:36 -04:00
FFZ . SRC _IDS = { } ,
FFZ . src _to _id = function ( src ) {
2016-10-12 20:54:09 -04:00
if ( Object . hasOwnProperty . call ( FFZ . SRC _IDS , src ) )
2015-07-04 17:06:36 -04:00
return FFZ . SRC _IDS [ src ] ;
var match = /\/emoticons\/v1\/(\d+)\/1\.0/ . exec ( src ) ,
id = match ? parseInt ( match [ 1 ] ) : null ;
2016-10-12 20:54:09 -04:00
if ( typeof id === "number" && ( isNaN ( id ) || ! isFinite ( id ) ) )
2015-07-04 17:06:36 -04:00
id = null ;
FFZ . SRC _IDS [ src ] = id ;
return id ;
} ;
2015-10-27 14:25:13 -04:00
FFZ . _emote _mirror _swap = function ( img ) {
var src , attempts = parseInt ( img . getAttribute ( 'data-alt-attempts' ) ) || 0 ;
if ( attempts > 3 )
return ;
img . setAttribute ( 'data-alt-attempts' , attempts + 1 ) ;
2016-03-23 19:28:22 -04:00
var id = img . getAttribute ( 'data-emote' ) ,
2016-07-13 02:31:26 -04:00
src = '//' + img . src . split ( '//' ) [ 1 ] ;
2015-10-27 14:25:13 -04:00
2016-03-23 19:28:22 -04:00
if ( src . substr ( 0 , constants . TWITCH _BASE . length ) === constants . TWITCH _BASE ) {
2015-10-27 14:25:13 -04:00
img . src = constants . EMOTE _MIRROR _BASE + id + ".png" ;
img . srcset = "" ;
} else {
2015-11-14 23:52:49 -05:00
img . src = constants . TWITCH _BASE + id + "/1.0" ;
img . srcset = utils . build _srcset ( id ) ;
2015-10-27 14:25:13 -04:00
}
}
2015-07-13 21:52:44 -04:00
// ---------------------
2015-07-18 21:10:27 -04:00
// Settings
2015-07-13 21:52:44 -04:00
// ---------------------
2016-08-09 20:45:28 -04:00
var ts = new Date ( 0 ) . toLocaleTimeString ( ) . toUpperCase ( ) ,
default _24 = ts . lastIndexOf ( 'PM' ) === - 1 && ts . lastIndexOf ( 'AM' ) === - 1 ;
2015-07-13 21:52:44 -04:00
FFZ . settings _info . twenty _four _timestamps = {
2016-08-09 20:45:28 -04:00
type : "select" ,
options : {
0 : "12-Hour" + ( default _24 ? '' : ' (Default)' ) ,
1 : "12-Hour Zero-Padded" ,
2 : "24-Hour" + ( default _24 ? ' (Default)' : '' ) ,
3 : "24-Hour Zero-Padded"
} ,
value : default _24 ? 2 : 0 ,
process _value : function ( val ) {
if ( val === false )
return 0 ;
else if ( val === true )
return 2 ;
else if ( typeof val === 'string' )
return parseInt ( val ) || 0 ;
return val ;
} ,
2015-07-13 21:52:44 -04:00
category : "Chat Appearance" ,
no _bttv : true ,
2016-08-09 20:45:28 -04:00
name : "Timestamp Format" ,
help : "Display timestamps in chat in the 24 hour format rather than 12 hour." ,
on _update : function ( val ) {
// Update existing chat lines.
var CL = utils . ember _resolve ( 'component:chat/chat-line' ) ,
views = ( CL && helpers && helpers . getTime ) ? utils . ember _views ( ) : { } ;
for ( var vid in views ) {
var view = views [ vid ] ;
if ( view instanceof CL )
view . $ ( '.timestamp' ) . text ( view . get ( 'timestamp' ) ) ;
}
}
} ;
2015-07-13 21:52:44 -04:00
2015-08-28 22:54:12 -04:00
FFZ . settings _info . timestamp _seconds = {
type : "boolean" ,
value : false ,
category : "Chat Appearance" ,
no _bttv : true ,
name : "Timestamp Seconds" ,
help : "Display seconds in chat timestamps."
} ;
2015-07-18 21:10:27 -04:00
FFZ . settings _info . show _deleted _links = {
type : "boolean" ,
value : false ,
category : "Chat Moderation" ,
no _bttv : true ,
name : "Show Deleted Links" ,
help : "Do not delete links based on room settings or link length."
2016-10-18 00:35:31 -04:00
} ;
2015-07-18 21:10:27 -04:00
2016-11-28 17:00:27 -05:00
FFZ . settings _info . clickable _mentions = {
type : 'boolean' ,
value : true ,
category : 'Chat Moderation' ,
no _bttv : true ,
name : 'Clickable Mentions' ,
help : 'Make mentions in chat starting with an at sign (<code>@</code>) open the user\'s moderation card when clicked.' ,
on _update : utils . toggle _cls ( 'ffz-clickable-mentions' )
}
2015-07-18 21:10:27 -04:00
// ---------------------
// Setup
// ---------------------
FFZ . prototype . setup _tokenization = function ( ) {
2015-07-31 21:40:51 -04:00
// Tooltip Data
this . _twitch _emotes = { } ;
this . _twitch _emote _to _set = { } ;
this . _twitch _set _to _channel = { } ;
this . _link _data = { } ;
2015-08-21 19:00:48 -04:00
2015-07-31 21:40:51 -04:00
this . load _twitch _emote _data ( ) ;
2016-11-28 17:00:27 -05:00
utils . toggle _cls ( 'ffz-clickable-mentions' ) ( this . settings . clickable _mentions ) ;
2015-08-21 19:00:48 -04:00
2016-05-20 17:30:34 -04:00
try {
2016-05-25 01:06:27 -04:00
helpers = window . require && window . require ( "web-client/helpers/chat/chat-line-helpers" ) ;
2016-05-20 17:30:34 -04:00
} catch ( err ) { }
2015-07-18 21:10:27 -04:00
if ( ! helpers )
return this . log ( "Unable to get chat helper functions." ) ;
2015-08-21 19:00:48 -04:00
2016-07-13 02:06:50 -04:00
try {
bits _helpers = window . require && window . require ( "web-client/utilities/bits/tokenize" ) ;
} catch ( err ) {
this . error ( "Unable to get bits tokenizer." , err ) ;
}
2017-01-18 18:33:56 -05:00
bits _service = utils . ember _lookup ( 'service:bits-emotes' ) ;
if ( ! bits _service )
bits _service = utils . ember _lookup ( 'service:bits-rendering-config' ) ;
2016-11-21 20:36:17 -05:00
bits _tags = utils . ember _lookup ( 'service:bits-tags' ) ;
2016-07-13 02:06:50 -04:00
2016-05-20 17:30:34 -04:00
try {
conv _helpers = window . require && window . require ( "web-client/helpers/twitch-conversations/conversation-line-helpers" ) ;
} catch ( err ) {
this . error ( "Unable to get conversation helper functions." , err ) ;
}
2015-11-14 23:52:49 -05:00
2016-06-22 14:23:03 -04:00
try {
emote _helpers = window . require && window . require ( "web-client/utilities/tmi-emotes" ) . default ;
} catch ( err ) {
this . error ( "Unable to get tmi-emotes helper function." , err ) ;
}
2015-07-18 21:10:27 -04:00
this . log ( "Hooking Ember chat line helpers." ) ;
var f = this ;
2015-08-21 19:00:48 -04:00
2015-07-18 21:10:27 -04:00
// Timestamp Display
2016-10-05 02:16:36 -04:00
helpers . getTime = function ( e , show _ampm ) {
2015-07-18 21:10:27 -04:00
if ( e === undefined || e === null )
2016-08-09 20:45:28 -04:00
return '?:??' + ( f . settings . timestamp _seconds ? ':??' : '' ) ;
2015-07-18 21:10:27 -04:00
2015-07-13 21:52:44 -04:00
var hours = e . getHours ( ) ,
2015-08-28 22:54:12 -04:00
minutes = e . getMinutes ( ) ,
2016-08-09 20:45:28 -04:00
seconds = e . getSeconds ( ) ,
2015-08-21 19:00:48 -04:00
2016-10-05 02:16:36 -04:00
s = f . settings . twenty _four _timestamps ,
pm = false ;
2016-08-09 20:45:28 -04:00
if ( s < 2 ) {
2016-10-05 02:16:36 -04:00
if ( hours > 12 ) {
2016-08-09 20:45:28 -04:00
hours -= 12 ;
2016-10-05 02:16:36 -04:00
pm = true ;
}
2016-08-09 20:45:28 -04:00
else if ( hours === 0 )
hours = 12 ;
}
2015-08-21 19:00:48 -04:00
2016-10-05 02:16:36 -04:00
return ( ( s === 1 || s === 3 ) && hours < 10 ? '0' : '' ) + hours + ':' + ( minutes < 10 ? '0' : '' ) + minutes + ( f . settings . timestamp _seconds ? ':' + ( seconds < 10 ? '0' : '' ) + seconds : '' ) + ( show _ampm && s < 2 ? '<span class="cp-hidden">' + ( pm ? 'pm' : 'am' ) + '</span>' : '' ) ;
2015-07-13 21:52:44 -04:00
} ;
2015-07-18 21:10:27 -04:00
// Linkify Messages
helpers . linkifyMessage = function ( tokens , delete _links ) {
var show _deleted = f . settings . show _deleted _links ;
2015-08-21 19:00:48 -04:00
2015-07-18 21:10:27 -04:00
return _ . chain ( tokens ) . map ( function ( token ) {
2016-07-13 02:31:26 -04:00
if ( token . type === "text" )
token = token . text ;
2016-03-23 19:28:22 -04:00
2015-07-18 21:10:27 -04:00
if ( ! _ . isString ( token ) )
return token ;
2015-08-21 19:00:48 -04:00
2015-07-18 21:10:27 -04:00
var matches = token . match ( LINK ) ;
if ( ! matches || ! matches . length )
return [ token ] ;
2015-08-21 19:00:48 -04:00
2015-07-18 21:10:27 -04:00
return _ . zip (
token . split ( LINK ) ,
_ . map ( matches , function ( e ) {
2016-07-13 02:31:26 -04:00
var long = e . length > 255 ,
out = {
type : "link" ,
length : e . length ,
isDeleted : ! show _deleted && ( delete _links || long ) ,
isLong : long ,
isMailTo : e . indexOf ( "@" ) > - 1 && ( - 1 === e . indexOf ( "/" ) || e . indexOf ( "@" ) < e . indexOf ( "/" ) ) ,
text : e ,
link : e
} ;
if ( ! out . isMailTo && ! e . match ( /^(?:https?:\/\/)/ ) )
out . link = "http://" + e ;
return out ;
2015-07-18 21:10:27 -04:00
} )
) ;
} ) . flatten ( ) . compact ( ) . value ( ) ;
} ;
}
2016-09-09 17:34:20 -04:00
// ------------------------
// Display Name Formatting
// ------------------------
FFZ . prototype . format _display _name = function ( display _name , user _id , disable _alias , disable _intl , disable _html ) {
var setting = this . settings . username _display ,
alias = this . aliases [ user _id ] ,
name _matches = ! display _name || display _name . trim ( ) . toLowerCase ( ) === user _id ,
tooltip ,
display _name ;
if ( setting === 0 )
display _name = user _id ;
else if ( setting === 1 )
display _name = name _matches ? ( display _name || ( user _id && user _id . capitalize ( ) ) ) : user _id ;
else {
display _name = utils . sanitize ( display _name || ( user _id && user _id . capitalize ( ) ) ) ;
if ( ! disable _intl && setting === 3 && ! name _matches )
2016-10-11 21:41:35 -04:00
display _name += disable _html ? ' (' + user _id + ')' : ' <span class="intl-login">(' + user _id + ')</span>' ;
2016-09-09 17:34:20 -04:00
else if ( ( ( disable _intl && setting === 3 ) || setting === 4 ) && ! name _matches )
tooltip = user _id ;
}
if ( ! disable _alias && alias ) {
if ( display _name )
tooltip = display _name + ( tooltip ? ' (' + tooltip + ')' : '' ) ;
display _name = utils . sanitize ( alias ) ;
}
return [ display _name , tooltip ] ;
}
2015-07-31 21:40:51 -04:00
// ---------------------
// Twitch Emote Data
// ---------------------
FFZ . prototype . load _twitch _emote _data = function ( tries ) {
2017-03-27 18:03:10 -04:00
var f = this ;
f . _twitch _set _to _channel [ 0 ] = "--global--" ;
f . _twitch _set _to _channel [ 33 ] = "--turbo-faces--" ;
f . _twitch _set _to _channel [ 42 ] = "--turbo-faces--" ;
f . _twitch _set _to _channel [ 19194 ] = "--prime--" ;
f . _twitch _set _to _channel [ 19151 ] = "--curse--" ;
this . log ( "Loading Twitch Emote Data (Try " + ( tries || 0 ) + ")" ) ;
jQuery . ajax ( constants . SERVER + "twitch_emotes.json" )
2015-07-31 21:40:51 -04:00
. done ( function ( data ) {
2017-03-27 18:03:10 -04:00
f . log ( "Loaded Twitch Emote Data" , data ) ;
2015-07-31 21:40:51 -04:00
for ( var set _id in data ) {
2017-03-27 18:03:10 -04:00
var set = data [ set _id ] ,
old _id = f . _twitch _set _to _channel [ set _id ] ;
2015-07-31 21:40:51 -04:00
if ( ! set )
continue ;
2017-03-27 18:03:10 -04:00
if ( ! old _id || old _id . indexOf ( '--' ) === - 1 )
f . _twitch _set _to _channel [ set _id ] = set . name ;
2015-07-31 21:40:51 -04:00
for ( var i = 0 , l = set . emotes . length ; i < l ; i ++ )
2017-03-27 18:03:10 -04:00
f . _twitch _emote _to _set [ set . emotes [ i ] ] = set _id ;
2015-07-31 21:40:51 -04:00
}
2015-08-21 19:00:48 -04:00
2015-07-31 21:40:51 -04:00
} ) . fail ( function ( data ) {
2017-03-27 18:03:10 -04:00
f . log ( "Error loading Twitch Emote Data" , data ) ;
2015-07-31 21:40:51 -04:00
if ( data . status === 404 )
return ;
2015-08-21 19:00:48 -04:00
2015-07-31 21:40:51 -04:00
tries = ( tries || 0 ) + 1 ;
if ( tries < 10 )
2017-03-27 18:03:10 -04:00
setTimeout ( f . load _twitch _emote _data . bind ( f , tries ) , 1000 ) ;
2015-07-31 21:40:51 -04:00
} ) ;
}
2016-03-23 19:28:22 -04:00
// ---------------------
// Tooltip Rendering
// ---------------------
FFZ . prototype . render _tooltip = function ( el ) {
2016-07-13 02:31:26 -04:00
var f = this ,
func = function ( ) {
2016-07-13 02:06:50 -04:00
if ( this . classList . contains ( 'ffz-bit' ) ) {
var amount = parseInt ( this . getAttribute ( 'data-amount' ) . replace ( /,/g , '' ) ) ,
individuals = JSON . parse ( this . getAttribute ( 'data-individuals' ) || "null" ) ,
2016-11-21 20:36:17 -05:00
prefix = this . getAttribute ( 'data-prefix' ) ,
tier = bits _service . ffz _get _tier ( prefix , amount ) ,
2016-07-13 02:06:50 -04:00
preview _url ,
image ,
out = utils . number _commas ( amount ) + ' Bit' + utils . pluralize ( amount ) ;
if ( f . settings . emote _image _hover )
2017-01-18 18:33:56 -05:00
preview _url = bits _service . ffz _get _preview ( prefix , amount ) ; //tier[1]);
2016-07-13 02:06:50 -04:00
if ( individuals && individuals . length > 1 ) {
out += '<br>' ;
individuals . sort ( ) . reverse ( ) ;
for ( var i = 0 ; i < individuals . length && i < 12 ; i ++ )
2016-12-15 18:39:23 -05:00
out += f . render _token ( false , false , true , { type : "bits" , prefix : individuals [ i ] [ 1 ] , amount : individuals [ i ] [ 0 ] } ) ;
2016-07-13 02:06:50 -04:00
if ( individuals . length >= 12 )
out += '<br>(and ' + ( individuals . length - 12 ) + ' more)' ;
}
image = preview _url ? '<img style="height:112px" class="emoticon ffz-image-hover" src="' + preview _url + '"?_=preview">' : '' ;
return image + out ;
} else if ( this . classList . contains ( 'emoticon' ) ) {
2017-04-05 19:12:11 -04:00
var can _favorite = this . classList . contains ( 'ffz-can-favorite' ) ,
preview _url , width = 0 , height = 0 , image , set _id , emote , emote _set ,
2016-10-22 17:27:13 -04:00
emote _id = this . getAttribute ( 'data-ffz-emote' ) ,
2016-10-25 14:44:22 -04:00
modifiers = this . getAttribute ( 'data-modifier-info' ) ,
2016-10-22 17:27:13 -04:00
mod _text = '' ;
if ( modifiers ) {
mod _text = '<hr>' + _ . map ( JSON . parse ( modifiers ) , function ( m ) {
emote _set = f . emote _sets [ m [ 0 ] ] ;
emote = emote _set && emote _set . emoticons [ m [ 1 ] ] ;
2016-12-07 17:58:05 -05:00
return emote ? f . render _token ( true , true , true , emote . token ) + ' - ' + ( emote . hidden ? '???' : utils . sanitize ( emote . name ) ) : '' ;
2016-10-22 17:27:13 -04:00
} ) . join ( '<br>' ) ;
}
2016-07-13 02:31:26 -04:00
if ( emote _id ) {
2016-04-11 18:57:25 -04:00
if ( emote _id == "93269" )
return '' ;
2016-07-13 02:31:26 -04:00
set _id = this . getAttribute ( 'data-ffz-set' ) ;
emote _set = f . emote _sets [ set _id ] ;
emote = emote _set && emote _set . emoticons [ emote _id ] ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
if ( emote ) {
2017-04-05 19:12:11 -04:00
var favorite _key = 'ffz-' + ( emote _set . hasOwnProperty ( 'source_ext' ) ? 'ext-' + emote _set . source _ext + '-' + emote _set . source _id : emote _set . id ) ,
favorites = f . settings . favorite _emotes [ favorite _key ] || [ ] ,
is _favorite = ! can _favorite && favorites . indexOf ( emote && emote . id ) !== - 1 ;
2016-07-13 02:31:26 -04:00
var owner = emote . owner ,
title = emote _set . title || "Global" ,
2016-11-20 13:43:12 -05:00
source = emote _set . source || "FFZ" ,
source _line = emote _set . source _line || ( source + ' ' + title ) ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
if ( f . settings . emote _image _hover ) {
if ( emote . urls [ 4 ] ) {
height = emote . height * 4 ;
width = emote . width * 4 ;
preview _url = emote . urls [ 4 ] ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
} else if ( emote . urls [ 2 ] ) {
height = emote . height * 2 ;
width = emote . width * 2 ;
}
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
if ( width > 186 )
height *= 186 / width ;
height = Math . min ( 186 , height ) ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
} else
preview _url = null ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
//image = preview_url ? `<img style="height:${height}px" class="emoticon ffz-image-hover" src="${preview_url}?_=preview">` : '';
image = preview _url ? '<img style="height:' + height + 'px" class="emoticon ffz-image-hover" src="' + preview _url + '"?_=preview">' : '' ;
2017-04-05 19:12:11 -04:00
return ( is _favorite ? FAV _MARKER : '' ) + image + 'Emoticon: ' + ( emote . hidden ? '???' : utils . sanitize ( emote . name ) ) + '<br>' + source _line + ( owner ? '<br>By: ' + utils . sanitize ( owner . display _name ) : '' ) + mod _text ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
//return `${image}Emoticon: ${emote.hidden ? '???' : emote.name}<br>${source} ${title}${owner ? '<br>By: ' + owner.display_name : ""}`;
}
}
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
emote _id = this . getAttribute ( 'data-emote' ) ;
if ( emote _id ) {
set _id = f . _twitch _emote _to _set [ emote _id ] ;
emote _set = set _id && f . _twitch _set _to _channel [ set _id ] ;
2017-04-05 19:12:11 -04:00
var set _type = "Channel" ,
favorite _key = 'twitch-' + set _id ,
Chat = utils . ember _lookup ( 'controller:chat' ) ,
tmi = Chat && Chat . get ( 'currentRoom.tmiSession' ) ,
twitch _sets = ( tmi && tmi . getEmotes ( ) || { 'emoticon_sets' : { } } ) [ 'emoticon_sets' ] ;
if ( ! emote _set && twitch _sets [ set _id ] ) {
var set = twitch _sets [ set _id ] ;
if ( set . length === 1 )
favorite _key = 'twitch-inventory' ;
}
var favorites = set _id && f . settings . favorite _emotes [ favorite _key ] || [ ] ,
is _favorite = ! can _favorite && favorites . indexOf ( parseInt ( emote _id ) ) !== - 1 ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
preview _url = f . settings . emote _image _hover && ( constants . TWITCH _BASE + emote _id + '/3.0' ) ;
//image = preview_url ? `<img style="height:112px" class="emoticon ffz-image-hover" src="${preview_url}?_=preview">` : '';
image = preview _url ? '<img style="height:112px" class="emoticon ffz-image-hover" src="' + preview _url + '"?_=preview">' : '' ;
2016-03-23 19:28:22 -04:00
2016-04-11 18:57:25 -04:00
// Global OR Golden Kappa
2016-07-13 02:31:26 -04:00
if ( emote _set === "--global--" || emote _id === '80393' ) {
emote _set = "Twitch Global" ;
set _type = null ;
} else if ( emote _set === "--twitch-turbo--" || emote _set === "turbo" || emote _set === "--turbo-faces--" ) {
emote _set = "Twitch Turbo" ;
set _type = null ;
2016-10-11 21:41:35 -04:00
} else if ( emote _set === '--prime--' || emote _set === '--prime-faces--' ) {
emote _set = "Twitch Prime" ;
set _type = null ;
2016-07-13 02:31:26 -04:00
}
if ( this . classList . contains ( 'ffz-tooltip-no-credit' ) )
2017-04-05 19:12:11 -04:00
return ( is _favorite ? FAV _MARKER : '' ) + image + utils . sanitize ( this . alt ) + mod _text ;
2016-07-13 02:31:26 -04:00
else
2017-04-05 19:12:11 -04:00
return ( is _favorite ? FAV _MARKER : '' ) + image + 'Emoticon: ' + utils . sanitize ( this . alt ) + '<br>' + ( set _type ? set _type + ': ' : '' ) + emote _set + mod _text ;
2016-07-13 02:31:26 -04:00
//return `${image}Emoticon: ${this.alt}<br>${set_type ? set_type + ": " : ""}${emote_set}`;
}
emote _id = this . getAttribute ( 'data-ffz-emoji' ) ;
if ( emote _id ) {
emote = f . emoji _data [ emote _id ] ;
var src = emote && ( f . settings . parse _emoji === 3 ? emote . one _src : ( f . settings . parse _emoji === 2 ? emote . noto _src : emote . tw _src ) ) ;
2017-04-05 19:12:11 -04:00
var favorites = f . settings . favorite _emotes . emoji || [ ] ,
is _favorite = ! can _favorite && favorites . indexOf ( emote . raw ) !== - 1 ;
2016-07-13 02:31:26 -04:00
preview _url = f . settings . emote _image _hover && src ;
//image = preview_url ? `<img style="height:72px" class="emoticon ffz-image-hover" src="${preview_url}">` : '';
image = preview _url ? '<img style="height:72px" class="emoticon ffz-image-hover" src="' + preview _url + '"?_=preview">' : '' ;
2017-04-05 19:12:11 -04:00
return ( is _favorite ? FAV _MARKER : '' ) + image + "Emoji: " + this . alt + '<br>Name: ' + emote . name + ( emote . short _name ? '<br>Short Name :' + emote . short _name + ':' : '' ) + ( emote . cat ? '<br>Category: ' + utils . sanitize ( constants . EMOJI _CATEGORIES [ emote . cat ] || emote . cat ) : '' ) + mod _text ;
2016-07-13 02:31:26 -04:00
//return `${image}Emoji: ${this.alt}<br>Name: ${emote.name}${emote.short_name ? '<br>Short Name: :' + emote.short_name + ':' : ''}`;
}
} else if ( this . classList . contains ( 'email-link' ) ) {
var url = this . getAttribute ( "data-url" ) ;
return url ? "E-Mail " + url . substr ( 7 ) : '' ;
} else if ( this . classList . contains ( 'chat-link' ) ) {
// TODO: A lot of shit. Lookup data.
var url = this . getAttribute ( "data-url" ) ,
2016-07-13 02:06:50 -04:00
data = url && f . _link _data [ url ] ,
preview _url = null ,
preview _iframe = true ,
image = '' ,
2016-07-13 02:31:26 -04:00
text = '' ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
if ( ! url )
return ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:06:50 -04:00
// Do we have data?
if ( data && data !== true ) {
text = data . html ;
preview _url = data . image ;
preview _iframe = data . image _iframe !== undefined ? data . image _iframe : true ;
} else
preview _url = is _image ( url , f . settings . image _hover _all _domains ) ? url : null ;
if ( f . settings . link _image _hover && preview _url )
if ( preview _iframe )
image = image _iframe ( url ) ;
else
image = '<img class="emoticon ffz-image-hover" src="' + utils . quote _attr ( preview _url ) + '">' ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
// If it's not a deleted link, don't waste time showing the URL in the tooltip.
if ( this . classList . contains ( 'deleted-link' ) )
2016-12-07 17:58:05 -05:00
text = utils . sanitize ( url ) ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
if ( this . classList . contains ( 'warn-link' ) )
text += EXPLANATION _WARN ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
return image + text ; //`${image}${text}`;
}
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
f . log ( "Unable to Build Tooltip For: " + this . className , this ) ;
return "" ;
} ;
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
return el ? func ( el ) : func ;
2016-03-23 19:28:22 -04:00
} ;
2015-06-05 03:59:28 -04:00
// ---------------------
// Tokenization
// ---------------------
2015-11-07 22:56:15 -05:00
FFZ . prototype . tokenize _conversation _line = function ( message , prevent _notification ) {
var msg = message . get ( 'body' ) ,
user = this . get _user ( ) ,
from _user = message . get ( 'from.username' ) ,
from _me = user && from _user === user . login ,
emotes = message . get ( 'tags.emotes' ) ,
tokens = [ msg ] ;
2015-11-14 23:52:49 -05:00
if ( conv _helpers && conv _helpers . checkActionMessage )
tokens = conv _helpers . checkActionMessage ( tokens ) ;
2016-06-22 14:23:03 -04:00
if ( emote _helpers )
emotes = emote _helpers ( emotes ) ;
2015-11-07 22:56:15 -05:00
// Standard Tokenization
2016-10-18 00:35:31 -04:00
if ( helpers && helpers . linkifyMessage && this . settings . parse _links )
2015-11-07 22:56:15 -05:00
tokens = helpers . linkifyMessage ( tokens ) ;
2016-09-09 17:34:20 -04:00
if ( user && user . login && helpers && helpers . mentionizeMessage ) {
2015-11-07 22:56:15 -05:00
tokens = helpers . mentionizeMessage ( tokens , user . login , from _me ) ;
2016-09-09 17:34:20 -04:00
// Display names~~
if ( ! from _me && user . name && user . name . trim ( ) . toLowerCase ( ) !== user . login )
tokens = helpers . mentionizeMessage ( tokens , user . name , from _me ) ;
}
2016-07-13 02:06:50 -04:00
if ( helpers && helpers . emoticonizeMessage && emotes && this . settings . parse _emoticons )
2015-11-07 22:56:15 -05:00
tokens = helpers . emoticonizeMessage ( tokens , emotes ) ;
// FrankerFaceZ Extras
tokens = this . _remove _banned ( tokens ) ;
2016-07-13 02:06:50 -04:00
if ( this . settings . parse _emoticons && this . settings . parse _emoticons !== 2 )
tokens = this . tokenize _emotes ( from _user , undefined , tokens , from _me ) ;
2015-11-07 22:56:15 -05:00
if ( this . settings . parse _emoji )
tokens = this . tokenize _emoji ( tokens ) ;
// Capitalization
var display _name = message . get ( 'from.displayName' ) ;
2016-10-14 20:43:34 -04:00
if ( display _name && display _name . length && display _name !== 'jtv' )
2015-11-07 22:56:15 -05:00
FFZ . capitalization [ from _user ] = [ display _name . trim ( ) , Date . now ( ) ] ;
// Mentions!
if ( ! from _me )
tokens = this . tokenize _mentions ( tokens ) ;
// TODO: Notifications?
return tokens ;
}
2016-03-24 15:30:43 -04:00
FFZ . prototype . tokenize _vod _line = function ( msgObject , delete _links ) {
2016-07-13 02:31:26 -04:00
var cached = msgObject . get ( 'cachedTokens' ) ;
if ( cached )
return cached ;
2016-03-24 15:30:43 -04:00
2016-07-13 02:31:26 -04:00
var msg = msgObject . get ( 'message' ) ,
room _id = msgObject . get ( 'room' ) ,
from _user = msgObject . get ( 'from' ) ,
user = this . get _user ( ) ,
from _me = user && from _user === user . login ,
emotes = msgObject . get ( 'tags.emotes' ) ,
2016-09-09 17:34:20 -04:00
2016-07-13 02:31:26 -04:00
tokens = [ msg ] ;
2016-03-24 15:30:43 -04:00
2016-10-18 00:35:31 -04:00
if ( helpers && helpers . linkifyMessage && this . settings . parse _links )
2016-07-13 02:31:26 -04:00
tokens = helpers . linkifyMessage ( tokens , delete _links ) ;
2016-03-24 15:30:43 -04:00
2016-09-09 17:34:20 -04:00
if ( user && user . login && helpers && helpers . mentionizeMessage ) {
2016-07-13 02:31:26 -04:00
tokens = helpers . mentionizeMessage ( tokens , user . login , from _me ) ;
2016-03-24 15:30:43 -04:00
2016-09-09 17:34:20 -04:00
// Display names~~
if ( ! from _me && user . name && user . name . trim ( ) . toLowerCase ( ) !== user . login )
tokens = helpers . mentionizeMessage ( tokens , user . name , from _me ) ;
}
2016-07-13 02:31:26 -04:00
if ( helpers && helpers . emoticonizeMessage && emotes && this . settings . parse _emoticons )
tokens = helpers . emoticonizeMessage ( tokens , emotes ) ;
2016-03-24 15:30:43 -04:00
2016-07-13 02:31:26 -04:00
// FrankerFaceZ Extras
tokens = this . _remove _banned ( tokens ) ;
2016-07-13 02:06:50 -04:00
if ( this . settings . parse _emoticons && this . settings . parse _emoticons !== 2 )
2016-07-13 02:31:26 -04:00
tokens = this . tokenize _emotes ( from _user , room _id , tokens , from _me ) ;
if ( this . settings . parse _emoji )
tokens = this . tokenize _emoji ( tokens ) ;
var display = msgObject . get ( 'tags.display-name' ) ;
2016-10-14 20:43:34 -04:00
if ( display && display . length && display !== 'jtv' )
2016-07-13 02:31:26 -04:00
FFZ . capitalization [ from _user ] = [ display . trim ( ) , Date . now ( ) ] ;
if ( ! from _me ) {
tokens = this . tokenize _mentions ( tokens ) ;
for ( var i = 0 ; i < tokens . length ; i ++ ) {
var token = tokens [ i ] ;
if ( token . type === 'mention' && ! token . isOwnMessage ) {
msgObject . set ( 'ffz_has_mention' , true ) ;
break ;
}
}
}
msgObject . set ( 'cachedTokens' , tokens ) ;
return tokens ;
2016-03-24 15:30:43 -04:00
}
2016-11-21 20:36:17 -05:00
FFZ . prototype . _tokenize _bits = function ( tokens ) {
if ( bits _helpers && bits _helpers . tokenizeBits )
try {
return bits _helpers . tokenizeBits ( tokens ,
2016-12-23 13:40:05 -05:00
bits _tags && bits _tags . get ( 'allTagNames' ) ,
bits _service && bits _service . get ( 'regexes' ) ) ;
2016-11-21 20:36:17 -05:00
} catch ( err ) { }
return tokens ;
}
2017-01-30 16:36:33 -05:00
FFZ . prototype . tokenize _chat _line = function ( msgObject , prevent _notification , delete _links , disable _cache ) {
if ( msgObject . cachedTokens && ! disable _cache )
2015-06-05 03:59:28 -04:00
return msgObject . cachedTokens ;
2016-07-13 02:31:26 -04:00
var msg = msgObject . message ,
room _id = msgObject . room ,
from _user = msgObject . from ,
user = this . get _user ( ) ,
from _me = user && from _user === user . login ,
2016-07-13 02:06:50 -04:00
tags = msgObject . tags || { } ,
2016-07-13 02:31:26 -04:00
emotes = tags . emotes ,
2016-10-19 13:55:12 -04:00
tokens = [ msg ] ,
mod _or _higher = tags . mod || from _user === room _id || tags [ 'user-type' ] === 'staff' || tags [ 'user-type' ] === 'admin' || tags [ 'user-type' ] === 'global_mod' ;
2015-06-05 03:59:28 -04:00
2016-07-13 02:06:50 -04:00
// Standard Tokenization
2016-11-21 20:36:17 -05:00
if ( tags . bits )
tokens = this . _tokenize _bits ( tokens ) ;
2016-07-13 02:06:50 -04:00
// For Later
//if ( helpers && helpers.tokenizeRichContent )
// tokens = helpers.tokenizeRichContent(tokens, tags.content, delete_links);
2016-06-02 20:04:40 -04:00
2016-10-18 00:35:31 -04:00
if ( helpers && helpers . linkifyMessage && this . settings . parse _links )
2016-10-19 13:55:12 -04:00
tokens = helpers . linkifyMessage ( tokens , delete _links && ! mod _or _higher ) ;
2015-07-18 21:10:27 -04:00
2016-09-09 17:34:20 -04:00
if ( user && user . login && helpers && helpers . mentionizeMessage ) {
2015-06-05 03:59:28 -04:00
tokens = helpers . mentionizeMessage ( tokens , user . login , from _me ) ;
2015-07-06 00:09:21 -04:00
2016-09-09 17:34:20 -04:00
// Display names~~
if ( ! from _me && user . name && user . name . trim ( ) . toLowerCase ( ) !== user . login )
tokens = helpers . mentionizeMessage ( tokens , user . name , from _me ) ;
}
2016-07-13 02:06:50 -04:00
if ( helpers && helpers . emoticonizeMessage && this . settings . parse _emoticons )
2015-07-18 21:10:27 -04:00
tokens = helpers . emoticonizeMessage ( tokens , emotes ) ;
2015-06-05 03:59:28 -04:00
// FrankerFaceZ Extras
tokens = this . _remove _banned ( tokens ) ;
2016-07-13 02:06:50 -04:00
if ( tags . bits && this . settings . collect _bits ) {
2016-12-15 18:39:23 -05:00
var stuff = { } ,
into _one = this . settings . collect _bits === 2 ;
2016-07-13 02:06:50 -04:00
for ( var i = 0 ; i < tokens . length ; i ++ )
if ( tokens [ i ] && tokens [ i ] . type === "bits" ) {
tokens [ i ] . hidden = true ;
2016-12-15 18:39:23 -05:00
var real _prefix = tokens [ i ] . prefix ,
prefix = into _one ? 'Cheer' : real _prefix ,
2016-11-21 20:36:17 -05:00
amount = tokens [ i ] . amount || 0 ,
grouped = stuff [ prefix ] = stuff [ prefix ] || { total : 0 , individuals : [ ] } ;
grouped . total += amount ;
2016-12-15 18:39:23 -05:00
grouped . individuals . push ( [ amount , real _prefix ] ) ;
2016-07-13 02:06:50 -04:00
}
2016-11-21 20:36:17 -05:00
for ( var prefix in stuff )
tokens . splice ( 0 , 0 , {
type : "bits" ,
prefix : prefix ,
amount : stuff [ prefix ] . total ,
individuals : stuff [ prefix ] . individuals ,
length : 0
} ) ;
2016-07-13 02:06:50 -04:00
}
2015-07-04 17:06:36 -04:00
if ( this . settings . parse _emoji )
tokens = this . tokenize _emoji ( tokens ) ;
2016-10-22 17:27:13 -04:00
if ( this . settings . parse _emoticons && this . settings . parse _emoticons !== 2 )
tokens = this . tokenize _emotes ( from _user , room _id , tokens , from _me ) ;
2015-06-05 03:59:28 -04:00
// Capitalization
2016-07-13 02:06:50 -04:00
var display = tags [ 'display-name' ] ;
2016-10-14 20:43:34 -04:00
if ( display && display . length && display !== 'jtv' )
2015-11-07 22:56:15 -05:00
FFZ . capitalization [ from _user ] = [ display . trim ( ) , Date . now ( ) ] ;
2015-06-05 03:59:28 -04:00
// Mentions!
if ( ! from _me ) {
tokens = this . tokenize _mentions ( tokens ) ;
2016-11-13 14:37:19 -05:00
var st = this . settings . remove _filtered ;
2015-06-05 03:59:28 -04:00
for ( var i = 0 ; i < tokens . length ; i ++ ) {
2016-03-23 19:28:22 -04:00
var token = tokens [ i ] ,
2016-11-13 14:37:19 -05:00
is _mention = token . type === "mention" ,
is _removed = token . type === "deleted" || token . censoredLink ;
if ( is _removed )
if ( st === 2 )
msgObject . ffz _removed = true ;
else if ( st === 1 ) {
msgObject . ffz _deleted = true ;
msgObject . deleted = true ;
}
2016-03-23 19:28:22 -04:00
2016-07-13 02:31:26 -04:00
if ( ! is _mention || token . isOwnMessage )
continue ;
2015-06-05 03:59:28 -04:00
// We have a mention!
2016-07-13 02:31:26 -04:00
msgObject . ffz _has _mention = true ;
2015-06-05 03:59:28 -04:00
2016-09-30 13:09:03 -04:00
// If it's a historical message we don't want to update any other UI.
if ( msg . tags && msg . tags . historical )
continue ;
2015-12-12 13:28:35 -05:00
// If we have chat tabs/rows, update the status.
if ( room _id && ! this . has _bttv && this . _chatv ) {
var room = this . rooms [ room _id ] && this . rooms [ room _id ] . room ;
if ( room . _ffz _tab && ! room . _ffz _tab . classList . contains ( 'active' ) ) {
room . _ffz _tab . classList . add ( 'tab-mentioned' ) ;
var was _hidden = room . _ffz _tab . classList . contains ( 'hidden' ) ;
if ( was _hidden ) {
room . _ffz _tab . classList . remove ( 'hidden' ) ;
this . _chatv . $ ( '.chat-room' ) . css ( 'top' , this . _chatv . _ffz _tabs . offsetHeight + "px" ) ;
}
}
if ( room . _ffz _row && ! room . _ffz _row . classList . contains ( 'active' ) )
room . _ffz _row . classList . add ( 'row-mentioned' ) ;
2015-06-05 03:59:28 -04:00
}
// Display notifications if that setting is enabled. Also make sure
// that we have a chat view because showing a notification when we
// can't actually go to it is a bad thing.
2015-07-04 17:06:36 -04:00
if ( this . _chatv && this . settings . highlight _notifications && ! this . embed _in _dash && ! document . hasFocus ( ) && ! prevent _notification ) {
2015-06-05 03:59:28 -04:00
var room = this . rooms [ room _id ] && this . rooms [ room _id ] . room ,
2016-12-23 13:40:05 -05:00
controller = utils . ember _lookup ( 'controller:chat' ) ,
2015-06-05 03:59:28 -04:00
room _name ;
2015-07-13 21:52:44 -04:00
// Make sure we have UI for this channel.
2016-12-23 13:40:05 -05:00
if ( this . settings . pinned _rooms . indexOf ( room _id ) !== - 1 ||
room _id === this . _chatv . _ffz _host ||
room . get ( 'isGroupRoom' ) ||
( controller && room === controller . get ( 'currentChannelRoom' ) ) ) {
2015-07-13 21:52:44 -04:00
if ( room && room . get ( 'isGroupRoom' ) )
room _name = room . get ( 'tmiRoom.displayName' ) ;
else
room _name = FFZ . get _capitalization ( room _id ) ;
2015-08-21 19:00:48 -04:00
2015-11-07 22:56:15 -05:00
display = display || Twitch . display . capitalize ( from _user ) ;
2015-08-21 19:00:48 -04:00
2015-07-13 21:52:44 -04:00
if ( msgObject . style === 'action' )
msg = '* ' + display + ' ' + msg ;
else
msg = display + ': ' + msg ;
2015-08-21 19:00:48 -04:00
2015-07-13 21:52:44 -04:00
var f = this ;
if ( msgObject . style === 'whisper' )
this . show _notification (
msg ,
"Twitch Chat Whisper" ,
"ffz_whisper_notice" ,
2015-07-18 21:10:27 -04:00
( this . settings . notification _timeout * 1000 ) ,
2015-07-13 21:52:44 -04:00
function ( ) {
window . focus ( ) ;
}
2015-07-04 17:06:36 -04:00
) ;
2015-07-13 21:52:44 -04:00
else
this . show _notification (
msg ,
"Twitch Chat Mention in " + room _name ,
room _id ,
2015-07-18 21:10:27 -04:00
( this . settings . notification _timeout * 1000 ) ,
2015-07-13 21:52:44 -04:00
function ( ) {
window . focus ( ) ;
2016-12-23 13:40:05 -05:00
room && controller && controller . focusRoom ( room ) ;
2015-07-13 21:52:44 -04:00
}
2015-07-04 17:06:36 -04:00
) ;
2015-07-13 21:52:44 -04:00
}
2015-06-05 03:59:28 -04:00
}
break ;
}
}
2016-11-28 17:00:27 -05:00
// Tokenize users last.
tokens = this . tokenize _users ( tokens ) ;
2017-01-30 16:36:33 -05:00
if ( ! disable _cache )
msgObject . cachedTokens = tokens ;
2015-06-05 03:59:28 -04:00
return tokens ;
}
2015-07-06 00:09:21 -04:00
FFZ . prototype . tokenize _line = function ( user , room , message , no _emotes , no _emoji ) {
2015-06-05 03:59:28 -04:00
if ( typeof message === "string" )
message = [ message ] ;
if ( helpers && helpers . linkifyMessage )
message = helpers . linkifyMessage ( message ) ;
if ( helpers && helpers . mentionizeMessage ) {
var u = this . get _user ( ) ;
2016-09-09 17:34:20 -04:00
if ( u && u . login ) {
2015-06-05 03:59:28 -04:00
message = helpers . mentionizeMessage ( message , u . login , user === u . login ) ;
2016-09-09 17:34:20 -04:00
// Display names~~
if ( ! user === u . login && u . name && u . name . trim ( ) . toLowerCase ( ) !== u . login )
tokens = helpers . mentionizeMessage ( tokens , u . name , from _me ) ;
}
2015-06-05 03:59:28 -04:00
}
2016-07-13 02:06:50 -04:00
if ( ! no _emotes && this . settings . parse _emoticons && this . settings . parse _emoticons !== 2 )
2015-06-05 03:59:28 -04:00
message = this . tokenize _emotes ( user , room , message ) ;
2015-07-06 00:09:21 -04:00
if ( this . settings . parse _emoji && ! no _emoji )
message = this . tokenize _emoji ( message ) ;
2015-06-05 03:59:28 -04:00
2016-11-28 17:00:27 -05:00
message = this . tokenize _users ( message ) ;
2015-06-05 03:59:28 -04:00
return message ;
}
2016-04-11 18:57:25 -04:00
FFZ . prototype . tokenize _feed _body = function ( message , emotes , user _id , room _id ) {
2016-03-31 19:47:17 -04:00
"use strict" ;
2016-03-23 19:28:22 -04:00
2016-03-31 19:47:17 -04:00
if ( typeof message === "string" )
message = [ { type : "text" , text : message } ] ;
2015-11-14 23:52:49 -05:00
2016-03-31 19:47:17 -04:00
if ( helpers && helpers . linkifyMessage )
message = helpers . linkifyMessage ( message ) ;
2015-11-19 02:45:56 -05:00
2016-08-09 20:45:28 -04:00
// We want to tokenize emoji first to make sure that they don't cause issues
// with the indices used by emoticonizeMessage.
message = this . tokenize _emoji ( message ) ;
2016-07-13 02:06:50 -04:00
if ( helpers && helpers . emoticonizeMessage && this . settings . parse _emoticons )
2016-03-31 19:47:17 -04:00
message = helpers . emoticonizeMessage ( message , emotes ) ;
// Tokenize Lines
var tokens = [ ] , token ;
for ( var i = 0 ; i < message . length ; i ++ ) {
token = message [ i ] ;
if ( ! token )
continue ;
if ( typeof token !== "string" )
if ( token . type === "text" )
token = token . text ;
else {
tokens . push ( token ) ;
continue ;
}
2015-07-04 17:06:36 -04:00
2016-03-31 19:47:17 -04:00
var segments = token . split ( /\n/g ) ;
while ( segments . length ) {
tokens . push ( { type : "text" , text : segments . shift ( ) } ) ;
if ( segments . length )
tokens . push ( { type : "raw" , html : "</p><p>" } ) ;
}
}
2015-07-04 17:06:36 -04:00
2016-07-13 02:06:50 -04:00
if ( this . settings . parse _emoticons && this . settings . parse _emoticons !== 2 )
tokens = this . tokenize _emotes ( user _id , room _id , tokens )
2015-07-04 17:06:36 -04:00
2016-03-31 19:47:17 -04:00
return tokens ;
}
2015-07-29 01:03:10 -04:00
2016-07-13 02:06:50 -04:00
FFZ . prototype . render _token = function ( render _links , warn _links , render _bits , token ) {
2016-03-31 19:47:17 -04:00
if ( ! token )
return "" ;
if ( token . hidden )
return "" ;
else if ( token . type === "raw" )
return token . html ;
2016-11-28 17:00:27 -05:00
else if ( token . type === "user" )
return '<span data-user="' + utils . quote _attr ( token . user ) + '" class="user-token">' + utils . sanitize ( token . text ) + '</span>' ;
2016-03-31 19:47:17 -04:00
else if ( token . type === "emoticon" ) {
var src = token . imgSrc , srcset , cls , extra ;
if ( token . ffzEmote ) {
var emote _set = this . emote _sets && this . emote _sets [ token . ffzEmoteSet ] ,
emote = emote _set && emote _set . emoticons && emote _set . emoticons [ token . ffzEmote ] ;
srcset = emote ? emote . srcSet : token . srcSet ;
//extra = (emote ? ` data-ffz-emote="${emote.id}"` : '') + (emote_set ? ` data-ffz-set="${emote_set.id}"` : '');
extra = ( emote ? ' data-ffz-emote="' + emote . id + '"' : '' ) + ( emote _set ? ' data-ffz-set="' + emote _set . id + '"' : '' )
2015-07-04 17:06:36 -04:00
2016-03-31 19:47:17 -04:00
} else if ( token . ffzEmoji ) {
var setting = this . settings . parse _emoji ;
if ( setting === 0 || ( setting === 1 && ! token . tw ) || ( setting === 2 && ! token . noto ) || ( setting === 3 && ! token . one ) )
return token . altText ;
src = setting === 3 ? token . one _src : ( setting === 2 ? token . noto _src : token . tw _src ) ;
//extra = ` data-ffz-emoji="${token.ffzEmoji}" height="18px"`;
extra = ' data-ffz-emoji="' + token . ffzEmoji + '" height="18px"' ;
cls = ' emoji' ;
} else {
var id = FFZ . src _to _id ( src ) ,
replacement = this . settings . replace _bad _emotes && constants . EMOTE _REPLACEMENTS [ id ] ;
//extra = ` data-emote="${id}" onerror="FrankerFaceZ._emote_mirror_swap(this)"`;
extra = ' data-emote="' + id + '" onerror="FrankerFaceZ._emote_mirror_swap(this)"' ;
if ( replacement ) {
src = constants . EMOTE _REPLACEMENT _BASE + replacement ;
srcset = '' ;
} else
srcset = utils . build _srcset ( id ) ;
2015-07-04 17:06:36 -04:00
}
2015-06-05 03:59:28 -04:00
2016-03-31 19:47:17 -04:00
//return `<img class="emoticon ffz-tooltip${cls||''}"${extra||''} src="${utils.quote_attr(src)}"${srcset ? ' srcset="' + utils.quote_attr(srcset) + '"' : ''} alt="${utils.quote_attr(token.altText)}">`;
2016-10-22 17:27:13 -04:00
var f = this , prefix = '' , suffix = '' ;
if ( token . modifiers && token . modifiers . length ) {
2016-10-27 12:49:31 -04:00
prefix = '<span class="emoticon modified-emoticon"' + ( token . ffzEmote ? ' data-ffz-emote="' + token . ffzEmote + '"' : '' ) + '>' ;
2016-10-22 17:27:13 -04:00
suffix = _ . map ( token . modifiers , function ( t ) {
return '<span>' + f . render _token ( render _links , warn _links , render _bits , t ) + '</span>' ;
} ) . join ( '' ) + '</span>' ;
2016-10-25 14:44:22 -04:00
extra += ' data-ffz-modifiers="' + utils . quote _attr ( _ . map ( token . modifiers , function ( t ) { return t . ffzEmote } ) . join ( ' ' ) ) + '" data-modifier-info="' + utils . quote _attr ( JSON . stringify ( _ . map ( token . modifiers , function ( t ) { return [ t . ffzEmoteSet , t . ffzEmote ] } ) ) ) + '"' ;
2016-10-22 17:27:13 -04:00
}
return prefix + '<img class="emoticon ffz-tooltip' + ( cls || '' ) + '"' + ( extra || '' ) + ' src="' + utils . quote _attr ( src ) + '"' + ( srcset ? ' srcset="' + utils . quote _attr ( srcset ) + '"' : '' ) + ' alt="' + utils . quote _attr ( token . altText ) + '">' + suffix ;
2016-03-31 19:47:17 -04:00
}
2015-08-21 19:00:48 -04:00
2016-05-06 02:23:12 -04:00
else if ( token . type === "tag" ) {
var link = Twitch . uri . game ( "Creative" ) + "/" + token . tag ;
return '<a href="' + utils . quote _attr ( link ) + '" data-tag="' + utils . quote _attr ( token . tag ) + '" class="ffz-creative-tag-link">' + utils . sanitize ( token . text ) + '</a>' ;
}
2016-03-31 19:47:17 -04:00
else if ( token . type === "link" ) {
var text = token . title || ( token . isLong && '<long link>' ) || ( token . isDeleted && '<deleted link>' ) || ( warn _links && '<whispered link>' ) || token . text ;
2015-06-05 03:59:28 -04:00
2016-03-31 19:47:17 -04:00
if ( ! render _links && render _links !== undefined )
return utils . sanitize ( text ) ;
2015-08-21 19:00:48 -04:00
2016-03-31 19:47:17 -04:00
var href = token . link || token . text ,
cls = '' ;
2015-08-21 19:00:48 -04:00
2016-03-31 19:47:17 -04:00
if ( token . isMailTo ) {
// E-Mail Link
cls = 'email-link' ;
href = 'mailto:' + href ;
2016-03-23 19:28:22 -04:00
2016-03-31 19:47:17 -04:00
} else {
// Web Link
cls = 'chat-link' ;
2015-08-21 19:00:48 -04:00
2016-03-31 19:47:17 -04:00
if ( this . settings . link _info ) {
if ( ! ( this . _link _data && this . _link _data [ href ] ) ) {
this . _link _data = this . _link _data || { } ;
this . _link _data [ href ] = true ;
2016-07-13 02:06:50 -04:00
var success = load _link _data . bind ( this , href ) ,
2017-03-01 22:02:21 -05:00
clip _info = CLIP _URL . exec ( href ) ,
video _info = VIDEO _URL . exec ( href ) ;
2016-07-13 02:06:50 -04:00
if ( clip _info ) {
var clips = utils . ember _lookup ( 'service:clips' ) ;
2017-03-01 22:02:21 -05:00
clips && clips . getClipInfo ( clip _info [ 1 ] ) . then ( function ( data ) {
2016-07-13 02:06:50 -04:00
success ( true , {
image : data . previewImage ,
image _iframe : false ,
html : '<span class="ffz-clip-title">' + utils . sanitize ( data . title ) + '</span>' +
'Channel: ' + utils . sanitize ( data . broadcasterDisplayName ) +
'<br>Game: ' + utils . sanitize ( data . game )
} ) ;
} ) ;
2017-03-01 22:02:21 -05:00
} else if ( video _info ) {
utils . api . get ( "videos/" + video _info [ 1 ] , undefined , { version : 5 } )
. then ( function ( data ) {
success ( true , {
image : data . preview . large ,
image _iframe : false ,
html : '<span class="ffz-clip-title">' + utils . sanitize ( data . title ) + ' [' + utils . time _to _string ( data . length ) + ']</span>' +
'Channel: ' + utils . sanitize ( data . channel . display _name ) +
'<br>Game: ' + utils . sanitize ( data . game )
} ) } ) ;
2016-07-13 02:06:50 -04:00
} else
this . ws _send ( "get_link" , href , success ) ;
2016-03-31 19:47:17 -04:00
}
}
}
2015-08-21 19:00:48 -04:00
2016-03-31 19:47:17 -04:00
// Deleted Links
var actual _href = href ;
if ( token . isDeleted ) {
cls = 'deleted-link ' + cls ;
href = '#' ;
2016-03-23 19:28:22 -04:00
2016-03-31 19:47:17 -04:00
} else if ( warn _links ) {
cls = 'warn-link deleted-link ' + cls ;
href = '#' ;
2015-06-05 03:59:28 -04:00
}
2016-05-06 02:23:12 -04:00
//return `<a class="ffz-tooltip ${cls}" data-text="${utils.quote_attr(token.text)}" data-url="${utils.quote_attr(actual_href)}" href="${utils.quote_attr(href||'#')}" target="_blank" rel="noopener">${utils.sanitize(text)}</a>`;
return '<a class="ffz-tooltip' + ( cls ? ' ' + cls : '' ) + '" data-text="' + utils . quote _attr ( token . text ) + '" data-url="' + utils . quote _attr ( actual _href ) + '" href="' + utils . quote _attr ( href || '#' ) + '" target="_blank" rel="noopener">' + utils . sanitize ( text ) + '</a>' ;
2016-03-31 19:47:17 -04:00
}
2016-07-13 02:06:50 -04:00
else if ( token . type === "bits" ) {
2016-11-21 20:36:17 -05:00
var tier = render _bits && bits _service . ffz _get _tier ( token . prefix , token . amount ) || [ null , null ] ;
2016-07-13 02:06:50 -04:00
if ( ! tier [ 1 ] )
return 'cheer' + token . amount ;
2016-11-21 20:36:17 -05:00
var prefix = utils . quote _attr ( token . prefix ) ;
return '<span class="emoticon ffz-bit ffz-tooltip bit-prefix-' + prefix + ' bit-tier-' + tier [ 0 ] + '"' + ( token . individuals ? ' data-individuals="' + utils . quote _attr ( JSON . stringify ( token . individuals ) ) + '"' : '' ) + ' data-prefix="' + prefix + '" data-amount="' + utils . number _commas ( token . amount ) + '" alt="cheer' + token . amount + '"></span>' ;
2016-07-13 02:06:50 -04:00
}
2016-12-23 13:40:05 -05:00
else if ( token . type === 'bits-tag' ) {
return '<span class="bits-tag mentioning">' + utils . sanitize ( token . tag ) + '</span>' ;
}
2016-03-31 19:47:17 -04:00
else if ( token . type === "deleted" )
2016-06-22 14:23:03 -04:00
return '<span class="deleted-word html-tooltip" title="' + utils . quote _san ( token . text ) + '" data-text="' + utils . sanitize ( token . text ) + '">×××</span>' ;
//return `<span class="deleted-word html-tooltip" title="${utils.quote_attr(token.text)}" data-text="${utils.sanitize(token.text)}">×××</span>`;
2015-06-05 03:59:28 -04:00
2016-03-31 19:47:17 -04:00
else if ( token . type === "mention" )
return '<span class="' + ( token . isOwnMessage ? 'mentioning' : 'mentioned' ) + '">' + utils . sanitize ( token . user ) + '</span>' ;
//return `<span class="${token.isOwnMessage ? 'mentioning' : 'mentioned'}">${utils.sanitize(token.user)}</span>`;
2016-03-23 19:28:22 -04:00
2016-03-31 19:47:17 -04:00
else if ( token . deletedLink || token . text )
return utils . sanitize ( token . text ) ;
2015-06-05 03:59:28 -04:00
2016-03-31 19:47:17 -04:00
else if ( typeof token !== "string" )
2016-07-13 02:06:50 -04:00
return '<b class="html-tooltip" title="<div style="text-align:left">' + utils . quote _attr ( JSON . stringify ( token , null , 2 ) ) + '</div>">[unknown token]</b>' ;
//return `<b class="html-tooltip" title="<div style="text-align:left">${utils.quote_attr(JSON.stringify(token,null,2))}</div>">[unknown token]</b>`;
2016-03-23 19:28:22 -04:00
2016-03-31 19:47:17 -04:00
return utils . sanitize ( token ) ;
}
2016-07-13 02:06:50 -04:00
FFZ . prototype . render _tokens = function ( tokens , render _links , warn _links , render _bits ) {
return _ . map ( tokens , this . render _token . bind ( this , render _links , warn _links , render _bits ) ) . join ( "" ) ;
2015-06-05 03:59:28 -04:00
}
2016-05-06 02:23:12 -04:00
// ---------------------
// Creative Tags
// ---------------------
2016-05-12 00:11:50 -04:00
FFZ . prototype . tokenize _ctags = function ( tokens , tags _only ) {
2016-05-06 02:23:12 -04:00
"use strict" ;
if ( typeof tokens === "string" )
tokens = [ tokens ] ;
var banned _tags = window . SiteOptions && SiteOptions . creative _banned _tags && SiteOptions . creative _banned _tags . split ( ',' ) || [ ] ,
new _tokens = [ ] ;
for ( var i = 0 , l = tokens . length ; i < l ; i ++ ) {
var token = tokens [ i ] ;
if ( ! token )
continue ;
if ( typeof token !== "string" )
if ( token . type === "text" )
token = token . text ;
else {
2016-05-12 00:11:50 -04:00
! tags _only && new _tokens . push ( token ) ;
2016-05-06 02:23:12 -04:00
continue ;
}
var segments = token . split ( ' ' ) ,
text = [ ] , segment , tag ;
for ( var x = 0 , y = segments . length ; x < y ; x ++ ) {
segment = segments [ x ] ;
tag = segment . substr ( 1 ) . toLowerCase ( ) ;
if ( segment . charAt ( 0 ) === '#' && banned _tags . indexOf ( tag ) === - 1 ) {
if ( text . length ) {
2016-05-12 00:11:50 -04:00
! tags _only && new _tokens . push ( { type : "text" , text : text . join ( ' ' ) + ' ' } ) ;
2016-05-06 02:23:12 -04:00
text = [ ] ;
}
new _tokens . push ( { type : "tag" , text : segment , tag : tag } ) ;
text . push ( '' ) ;
} else
text . push ( segment ) ;
}
2016-05-12 00:11:50 -04:00
if ( ! tags _only && ( text . length > 1 || ( text . length === 1 && text [ 0 ] !== '' ) ) )
2016-05-06 02:23:12 -04:00
new _tokens . push ( { type : "text" , text : text . join ( ' ' ) } ) ;
}
return new _tokens ;
}
2015-06-05 03:59:28 -04:00
// ---------------------
// Emoticon Processing
// ---------------------
2016-11-28 17:00:27 -05:00
FFZ . prototype . tokenize _users = function ( tokens ) {
"use strict" ;
if ( typeof tokens === "string" )
tokens = [ tokens ] ;
var new _tokens = [ ] ;
for ( var i = 0 , l = tokens . length ; i < l ; i ++ ) {
var token = tokens [ i ] ;
if ( ! token )
continue ;
if ( typeof token !== "string" )
if ( token . type === "text" )
token = token . text ;
else {
new _tokens . push ( token ) ;
continue ;
}
var segments = token . split ( /(@[a-z0-9][a-z0-9_]{3,24})/i ) ;
for ( var x = 0 , y = segments . length ; x < y ; x += 2 ) {
var text = segments [ x ] || '' ,
match = segments [ x + 1 ] || '' ;
if ( text . length )
new _tokens . push ( { type : 'text' , text : text } ) ;
if ( match . length )
new _tokens . push ( { type : 'user' , text : match , user : match . substr ( 1 ) } ) ;
}
}
return new _tokens ;
}
2015-06-05 03:59:28 -04:00
FFZ . prototype . tokenize _emotes = function ( user , room , tokens , do _report ) {
2016-07-13 02:31:26 -04:00
"use strict" ;
var sets = this . getEmotes ( user , room ) ,
emotes = { } ,
emote ,
new _tokens = [ ] ;
if ( ! tokens || ! tokens . length || ! sets || ! sets . length )
return tokens ;
// Build an object with all of our emotes.
for ( var i = 0 ; i < sets . length ; i ++ ) {
var emote _set = this . emote _sets [ sets [ i ] ] ;
if ( emote _set && emote _set . emoticons )
for ( var emote _id in emote _set . emoticons ) {
emote = emote _set . emoticons [ emote _id ] ;
2016-08-09 20:45:28 -04:00
if ( ! HOP . call ( emotes , emote . name ) )
2016-07-13 02:31:26 -04:00
emotes [ emote . name ] = emote ;
}
}
if ( typeof tokens === "string" )
tokens = [ tokens ] ;
2016-10-22 17:27:13 -04:00
var last _token ;
2016-07-13 02:31:26 -04:00
for ( var i = 0 , l = tokens . length ; i < l ; i ++ ) {
var token = tokens [ i ] ;
if ( ! token )
continue ;
if ( typeof token !== "string" )
if ( token . type === "text" )
token = token . text ;
else {
2016-10-22 17:27:13 -04:00
if ( ! token . modifiers && token . type === 'emoticon' )
token . modifiers = [ ] ;
2016-07-13 02:31:26 -04:00
new _tokens . push ( token ) ;
2016-10-22 17:27:13 -04:00
last _token = token ;
2016-07-13 02:31:26 -04:00
continue ;
}
// Split the token!
2016-10-22 17:27:13 -04:00
var segments = token . split ( / +/ ) ,
2016-07-13 02:31:26 -04:00
text = [ ] , segment ;
for ( var x = 0 , y = segments . length ; x < y ; x ++ ) {
segment = segments [ x ] ;
2016-08-09 20:45:28 -04:00
if ( HOP . call ( emotes , segment ) ) {
2016-07-13 02:31:26 -04:00
emote = emotes [ segment ] ;
2016-10-22 17:27:13 -04:00
// Is this emote a modifier?
if ( emote . modifier && last _token && last _token . modifiers && ( ! text . length || ( text . length === 1 && text [ 0 ] === '' ) ) ) {
if ( last _token . modifiers . indexOf ( emote . token ) === - 1 )
last _token . modifiers . push ( emote . token ) ;
if ( do _report && room )
this . add _usage ( room , emote ) ;
continue ;
}
2016-07-13 02:31:26 -04:00
if ( text . length ) {
// We have pending text. Join it together, with an extra space
// on the end for good measure.
2016-10-22 17:27:13 -04:00
var token = { type : "text" , text : text . join ( ' ' ) + ' ' } ;
new _tokens . push ( token ) ;
if ( token . text . trim ( ) . length )
last _token = token ;
2016-07-13 02:31:26 -04:00
text = [ ]
}
// Push this emote to the tokens.
2016-10-23 20:38:09 -04:00
var token = _ . extend ( { } , emote . token ) ;
2016-10-22 17:27:13 -04:00
token . modifiers = [ ] ;
new _tokens . push ( token ) ;
last _token = token ;
2016-07-13 02:31:26 -04:00
if ( do _report && room )
this . add _usage ( room , emote ) ;
// Finally, push an empty string to text so that this emote gets spaced.
text . push ( '' ) ;
} else
text . push ( segment ) ;
}
// Add any left over text from this segment.
if ( text . length > 1 || ( text . length === 1 && text [ 0 ] !== '' ) )
new _tokens . push ( { type : "text" , text : text . join ( ' ' ) } ) ;
}
return new _tokens ;
2015-06-05 03:59:28 -04:00
}
2015-07-04 17:06:36 -04:00
// ---------------------
// Emoji Processing
// ---------------------
FFZ . prototype . tokenize _emoji = function ( tokens ) {
2016-07-13 02:31:26 -04:00
"use strict" ;
if ( ! tokens || ! tokens . length || ! this . emoji _data )
return tokens ;
if ( typeof tokens === "string" )
tokens = [ tokens ] ;
var new _tokens = [ ] ;
for ( var i = 0 , l = tokens . length ; i < l ; i ++ ) {
var token = tokens [ i ] ;
if ( ! token )
continue ;
if ( typeof token !== "string" )
if ( token . type === "text" )
token = token . text ;
else {
new _tokens . push ( token ) ;
continue ;
}
var segments = token . split ( constants . EMOJI _REGEX ) ,
text = null ;
while ( segments . length ) {
text = ( text || '' ) + segments . shift ( ) ;
if ( segments . length ) {
var match = segments . shift ( ) ,
eid = utils . emoji _to _codepoint ( match ) ,
data = this . emoji _data [ eid ] ;
if ( data ) {
if ( text && text . length )
2016-08-09 20:45:28 -04:00
new _tokens . push ( text ) ;
2016-12-10 22:54:53 -05:00
new _tokens . push ( _ . extend ( { modifiers : [ ] } , data . token ) ) ;
2016-07-13 02:31:26 -04:00
text = null ;
} else
text = ( text || '' ) + match ;
}
}
if ( text && text . length )
2016-08-09 20:45:28 -04:00
new _tokens . push ( text ) ;
2016-07-13 02:31:26 -04:00
}
return new _tokens ;
2015-07-04 17:06:36 -04:00
}
2015-06-05 03:59:28 -04:00
// ---------------------
// Mention Parsing
// ---------------------
FFZ . _regex _cache = { } ;
FFZ . _get _regex = function ( word ) {
return FFZ . _regex _cache [ word ] = FFZ . _regex _cache [ word ] || RegExp ( "\\b" + reg _escape ( word ) + "\\b" , "ig" ) ;
}
FFZ . _words _to _regex = function ( list ) {
var regex = FFZ . _regex _cache [ list ] ;
if ( ! regex ) {
var reg = "" ;
for ( var i = 0 ; i < list . length ; i ++ ) {
if ( ! list [ i ] )
continue ;
2016-09-30 13:09:03 -04:00
reg += ( reg ? "|" : "" ) + ( list [ i ] . substr ( 0 , 6 ) === "regex:" ? list [ i ] . substr ( 6 ) : reg _escape ( list [ i ] ) ) ;
2015-06-05 03:59:28 -04:00
}
2016-03-23 19:28:22 -04:00
regex = FFZ . _regex _cache [ list ] = new RegExp ( "(^|.*?" + constants . SEPARATORS + ")(" + reg + ")(?=$|" + constants . SEPARATORS + ")" , "ig" ) ;
2015-06-05 03:59:28 -04:00
}
return regex ;
}
FFZ . prototype . tokenize _mentions = function ( tokens ) {
var mention _words = this . settings . keywords ;
if ( ! mention _words || ! mention _words . length )
return tokens ;
if ( typeof tokens === "string" )
tokens = [ tokens ] ;
var regex = FFZ . _words _to _regex ( mention _words ) ,
new _tokens = [ ] ;
for ( var i = 0 ; i < tokens . length ; i ++ ) {
var token = tokens [ i ] ;
2016-07-13 02:31:26 -04:00
if ( token . type === "text" )
token = token . text ;
2015-06-05 03:59:28 -04:00
2016-03-23 19:28:22 -04:00
if ( ! _ . isString ( token ) || ! token . match ( regex ) ) {
2015-06-05 03:59:28 -04:00
new _tokens . push ( token ) ;
continue ;
}
token = token . replace ( regex , function ( all , prefix , match ) {
new _tokens . push ( prefix ) ;
new _tokens . push ( {
2016-07-13 02:31:26 -04:00
type : "mention" ,
length : match . length ,
user : match ,
isOwnMessage : false ,
2015-06-05 03:59:28 -04:00
} ) ;
return "" ;
} ) ;
if ( token )
new _tokens . push ( token ) ;
}
return new _tokens ;
2015-07-04 17:06:36 -04:00
}
// ---------------------
// Handling Bad Stuff
// ---------------------
FFZ . prototype . _deleted _link _click = function ( e ) {
if ( ! this . classList . contains ( "deleted-link" ) )
return true ;
2016-07-13 02:31:26 -04:00
// Stop from Navigating
2016-03-23 19:28:22 -04:00
e . preventDefault ( ) ;
2015-07-04 17:06:36 -04:00
// Get the URL
2016-03-23 19:28:22 -04:00
var link = this . getAttribute ( 'data-url' ) ,
text = this . getAttribute ( 'data-text' ) || link ,
2015-07-04 17:06:36 -04:00
f = FrankerFaceZ . get ( ) ;
// Delete Old Stuff
this . classList . remove ( 'deleted-link' ) ;
2016-07-13 02:31:26 -04:00
this . classList . remove ( 'warn-link' ) ;
2015-07-04 17:06:36 -04:00
// Set up the Link
2016-03-23 19:28:22 -04:00
this . href = link ;
this . target = "_blank" ;
this . textContent = text ;
2015-07-04 17:06:36 -04:00
2016-03-23 19:28:22 -04:00
// Refresh tipsy.
2016-07-13 02:31:26 -04:00
jQuery ( this ) . trigger ( 'mouseout' ) . trigger ( 'mouseover' ) ;
2015-11-19 02:45:56 -05:00
}
// ---------------------
// History Loading
// ---------------------
2016-10-05 01:31:10 -04:00
/ * F F Z . p r o t o t y p e . p a r s e _ h i s t o r y = f u n c t i o n ( h i s t o r y , p u r g e d , b a d _ i d s , r o o m _ i d , d e l e t e _ l i n k s , t m i S e s s i o n , p e r _ l i n e ) {
2015-11-19 02:45:56 -05:00
var i = history . length , was _cleared = false ;
purged = purged || { } ;
2016-07-13 02:06:50 -04:00
bad _ids = bad _ids || { } ;
2015-11-19 02:45:56 -05:00
while ( i -- ) {
var msg = history [ i ] ,
2016-07-13 02:06:50 -04:00
msg _id = msg . tags && msg . tags . id ,
is _deleted = msg . ffz _deleted = purged [ msg . from ] || ( msg _id && bad _ids [ msg _id ] ) || false ;
2015-11-19 02:45:56 -05:00
if ( is _deleted && ! this . settings . prevent _clear )
msg . deleted = true ;
if ( ! msg . room && room _id )
msg . room = room _id ;
if ( typeof msg . date === "string" || typeof msg . date === "number" )
msg . date = utils . parse _date ( msg . date ) ;
if ( ! msg . color )
msg . color = msg . tags && msg . tags . color ? msg . tags . color : tmiSession && msg . from ? tmiSession . getColor ( msg . from ) : "#755000" ;
if ( ! msg . labels || ! msg . labels . length ) {
var labels = msg . labels = [ ] ;
if ( msg . room && msg . room === msg . from )
labels . push ( "owner" ) ;
else if ( msg . tags ) {
var ut = msg . tags [ 'user-type' ] ;
if ( ut === 'mod' || ut === 'staff' || ut === 'admin' || ut === 'global_mod' )
labels . push ( ut ) ;
}
if ( msg . tags ) {
if ( msg . tags . turbo )
labels . push ( "turbo" ) ;
if ( msg . tags . subscriber )
labels . push ( "subscriber" ) ;
}
}
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" )
msg . tags . emotes = utils . uncompressEmotes ( msg . tags . emotes ) ;
2016-06-05 22:12:54 -04:00
if ( msg . tags && typeof msg . tags . badges === "string" )
msg . tags . badges = utils . uncompressBadges ( msg . tags . badges ) ;
2015-11-19 02:45:56 -05:00
if ( ! msg . cachedTokens || ! msg . cachedTokens . length )
this . tokenize _chat _line ( msg , true , delete _links ) ;
// CLEARCHAT
if ( msg . tags && msg . tags . target === '@@' )
was _cleared = true ;
2016-07-13 02:06:50 -04:00
else if ( msg . tags && msg . tags . target ) {
var ban _reason = msg . tags && msg . tags [ 'ban-reason' ] ,
ban _id = ban _reason && constants . UUID _TEST . exec ( ban _reason ) ;
if ( ban _id ) {
bad _ids [ ban _id [ 1 ] ] = true ;
ban _reason = ban _reason . substr ( 0 , ban _reason . length - ban _id [ 0 ] . length ) ;
msg . tags [ 'ban-reason' ] = ban _reason ? ban _reason : undefined ;
} else
purged [ msg . tags . target ] = true ;
}
2015-11-19 02:45:56 -05:00
// Per-line
if ( per _line && ! per _line ( msg ) )
break ;
}
return [ history , purged , was _cleared ] ;
2016-10-05 01:31:10 -04:00
} * /