您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
sc2tv.ru chat with extra features
// ==UserScript== // @name peka2tv chat // @namespace http://chat.sc2tv.ru // @description sc2tv.ru chat with extra features // @author Winns // @copyright 27.04.2013, Winns // @include http://chat.sc2tv.ru/* // @include http://sc2tv.ru/* // @match http://chat.sc2tv.ru/* // @match http://sc2tv.ru/* // @version 2.0.31 // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_getResourceText // @resource peka2tv_chat_css https://raw.githubusercontent.com/Winns/p2tv/master/peka2tv_chat2/peka2tv_chat.css // @run-at document-end // ==/UserScript== (function () { GM_addStyle (GM_getResourceText ('peka2tv_chat_css')); function GM_wait() { if (typeof unsafeWindow.$ == 'undefined') setTimeout( GM_wait, 100 ); else GM_run(); } GM_wait(); function GM_run() { var $ = unsafeWindow.$; var HOST = window.location.host, SUBDOMAIN = HOST.split('.')[0]; FILE = location.pathname.substring(1); if ((SUBDOMAIN === 'chat') && (FILE === 'index.htm')) { // Run chat // ================================================== function GM_runChat() { /* ====== Variables ====== */ var cfg = { el: { chat: '#wchat-msgs-wrapper', chatInput: '#wchat-input', chatPopUpClose: '.wchat-menu-popup-close', chatPopUp: '.wchat-menu-popup', channelsWrapper: '#wchat-chanells-wrapper', streamerBtn: '#wchat-btn-streamer', privateSmiles: '.wchat-smile-private', userName: '.wchat-nick', userMenu: '#wchat-usermenu-wrapper', userMenuName: '.wchat-usermenu-name', userMenuClose: '#wchat-usermenu-wrapper .wchat-usermenu-close', userMenuBan: '#wchat-usermenu-wrapper .wchat-usermenu-banmenu .wchat-btn', userMenuBanCallback: '#wchat-usermenu-wrapper .wchat-usermenu-banmenu .wchat-usermenu-callback', menuButtons: '#wchat-menu-inner-wrapper .wchat-btn', menuWrapper: '#wchat-menu-wrapper', userState: '#wchat-menu-inner-wrapper .wchat-userstate', cfgFriendList: '#wchat-cfg-friendlist select', cfgFriendListBtn: '#wchat-cfg-friendlist .wchat-btn', cfgIgnoreList: '#wchat-cfg-ignorelist select', cfgIgnoreListBtn: '#wchat-cfg-ignorelist .wchat-btn', cfgSmilesSize: '#wchat-cfg-smiles select', cfgFontSize: '#wchat-cfg-fontsize select', cfgMsgsLimit: '#wchat-cfg-msgslimit select', cfgFriendsMsgStyle: '#wchat-cfg-friendsmsgstyle select', cfgForUserMsgStyle: '#wchat-cfg-forusermsgstyle select', cfgNickColor: '#wchat-cfg-nickcolor input', cfgNickIcon: '#wchat-cfg-nickicon input', cfgWrapper: '#wchat-cfg-wrapper', admWrapper: '#wchat-adm-wrapper', linksWrapper: '#wchat-links-wrapper', forYouWrapper: '#wchat-foryou-wrapper', smilesWrapper: '#wchat-smiles-wrapper' }, eventMessages: { capsAbuse: 'Слишком много капса.', autoBan: 'Что-то не так с вашим сообщением, возможно превышен лимит смайлов.', pleaseLogIn: 'Please log in...', banned: 'Вы забанены до ' }, userMenuUserSetup: { name: null, userId: null, msgId: null }, userInfo: null, chatURL: 'http://chat.sc2tv.ru/', chatGate: 'http://chat.sc2tv.ru/gate.php', channelId: decodeURIComponent((new RegExp('[?|&]channelId=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null, channelsList: null, streamerName: '', streamTitle: '', chatMessagesLimit: GM_getValue('wchat_chatMessagesLimit') || 50, chatInterval: null, inputCaretPosition: 0, messages: null, smiles: unsafeWindow.smiles, friendList: JSON.parse( GM_getValue('wchat_friendList') || '{}' ), ignoreList: JSON.parse( GM_getValue('wchat_ignoreList') || '{}' ), smilesSize: GM_getValue('wchat_smilesSize') || 1, fontSize: GM_getValue('wchat_fontSize') || 12, friendsMsgStyle: GM_getValue('wchat_friendsMsgStyle') || 'wchat-msg-friend-style-default', forUserMsgStyle: GM_getValue('wchat_forUserMsgStyle') || 'wchat-msg-foruser-style-default', nickColor: GM_getValue('wchat_nickColor') || true, nickIcon: GM_getValue('wchat_nickIcon') || true, doScroll: true, time: { scroll: 900, newMsg: 900, hide: 300, show: 300, removeMsg: 800, userMenu: 180, banMsg: 3000, toggleChannels: 300, ajaxRetryOnError: 1000, scrollTimer: 2500, // auto scroll disabled for n seconds after user scroll or mousedown chatUpdateInterval: 4000 } } var templates = {}; /* ===== Templates ====== */ templates.chat = function() { var html = ''; html += '<div id="wchat-wrapper">'; html += '<div id="wchat-chanells-wrapper"></div>'; html += '<div id="wchat-msgs-wrapper"></div>'; html += '<div id="wchat-menu-wrapper">'; html += templates.cfgWrapper(); html += templates.admWrapper(); html += templates.linksWrapper(); html += templates.forYouWrapper(); html += templates.userMenu(); html += '<div id="wchat-menu-inner-wrapper">'; html += '<div class="input-wrapper"><textarea id="wchat-input" placeholder="Сообщение..." maxlength="1024"></textarea>'; html += '<div id="wchat-btn-streamer" class="wchat-btn" title="Написать стримеру">S</div>'; html += '<div id="wchat-btn-smiles" class="wchat-btn" title="Смайлы" data-target="smilesWrapper"></div>'; html += '</div>'; html += templates.userState(); html += '<div id="wchat-menu-control">'; html += '<div class="wchat-btn" title="Настройки" data-target="cfgWrapper">CFG</div>'; html += '<div class="wchat-btn" title="Сообщения от администрации" data-target="admWrapper">ADM</div>'; html += '<div class="wchat-btn" title="Ссылки из чата" data-target="linksWrapper">LINKS</div>'; html += '<div class="wchat-btn disabled" title="Сообщения адресованные вам" data-target="forYouWrapper">4YOU</div>'; html += '</div>'; html += '</div>'; html += '</div>'; html += '</div>'; return html; } templates.chatMSG = function( data ) { var html = '', messageStyle = getMessageStyle( data ), msgData = 'data-userid="'+ data.uid +'" data-msgid="'+ data.id +'"'; html += '<div class="wchat-msg '+ messageStyle.msg +'" title="'+ data.date +'">'; html += messageStyle.icons +'<span class="wchat-nick '+ messageStyle.nick +'" '+ msgData +' >'+ data.name +'</span> <span class="wchat-msg-text">'+ msg2html(data.message) +'</span>'; html += '</div>'; return html; } templates.smile = function( data ) { var style = 'width: '+ Math.floor(data.width * cfg.smilesSize) +'px; height: '+ Math.floor(data.height * cfg.smilesSize)+'px;'; return '<img src="img/'+ data.img +'" title="'+ data.code +'" style="'+ style +'" />'; } templates.smilesWrapper = function() { var html = '', smilesHtml = '', smile, noAccess, privateSmile, userLoggedIn = isUserLoggedIn(), userRoles = cfg.userInfo.roleIds.slice(); for (var i=0; i < cfg.smiles.length; i++) { smile = cfg.smiles[ i ]; privateSmile = ''; // check if user have access to smile if (( userLoggedIn ) && ( smile.private )) { noAccess = true; for (var j=0; j < userRoles.length; j++) { if (smile.roles.indexOf( userRoles[ j ] ) !== -1) { noAccess = false; break; } } if (noAccess) { privateSmile = ' class="wchat-smile-private" title="Платные смайлы"'; } } smilesHtml += '<div'+ privateSmile +'><img src="/img/'+ smile.img +'" title="'+ smile.code +'" /></div>'; } html += '<div id="wchat-smiles-wrapper" class="wchat-menu-popup">'; html += '<div class="wchat-menu-popup-close"><span>Смайлы</span><div>✕</div></div>'; html += '<div class="wchat-menu-popup-content">'+ smilesHtml +'</div>'; html += '</div>'; return html; } templates.cfgWrapper = function() { var html = ''; html += '<div id="wchat-cfg-wrapper" class="wchat-menu-popup">'; html += '<div class="wchat-menu-popup-close"><span>Настройки</span><div>✕</div></div>'; html += '<div class="wchat-menu-popup-content">'; html += '<ul>'; html += '<li id="wchat-cfg-friendlist">'; html += 'В друзьях <br><select></select><br><div class="wchat-btn">УДАЛИТЬ</div>'; html += '</li>'; html += '<li id="wchat-cfg-ignorelist">'; html += 'В игноре <br><select></select><br><div class="wchat-btn">УДАЛИТЬ</div>'; html += '</li>'; html += '<li id="wchat-cfg-smiles">'; html += 'Размер смайлов '; html += '<select>'; html += '<option>2</option>'; html += '<option>1.5</option>'; html += '<option>1.25</option>'; html += '<option>1</option>'; html += '<option>0.9</option>'; html += '<option>0.8</option>'; html += '<option>0.7</option>'; html += '<option>0.6</option>'; html += '<option>0.5</option>'; html += '<option title="Выключить смайлы">0</option>'; html += '</select>'; html += '</li>'; html += '<li id="wchat-cfg-fontsize">'; html += 'Размер шрифта '; html += '<select>'; html += '<option>40</option><option>36</option><option>32</option><option>28</option>'; html += '<option>24</option><option>20</option><option>18</option><option>16</option>'; html += '<option>15</option><option>14</option><option>13</option><option>12</option>'; html += '<option>11</option><option>10</option><option>9</option><option>8</option>'; html += '</select>'; html += '</li>'; html += '<li id="wchat-cfg-nickcolor">'; html += 'Цветные ники <input type="checkbox">'; html += '</li>'; html += '<li id="wchat-cfg-nickicon">'; html += 'Иконки ников <input type="checkbox">'; html += '</li>'; html += '<li id="wchat-cfg-msgslimit">'; html += 'Лимит сообщений в чате '; html += '<select>'; html += '<option>250</option>'; html += '<option>200</option>'; html += '<option>150</option>'; html += '<option>100</option>'; html += '<option>50</option>'; html += '<option>20</option>'; html += '<option>10</option>'; html += '</select>'; html += '</li>'; html += '<li id="wchat-cfg-friendsmsgstyle">'; html += 'Friends msg style '; html += '<select>'; html += '<option data-class="wchat-msg-friend-style-default">default</option>'; html += '<option data-class="wchat-msg-friend-style-grgray">gray gradient</option>'; html += '<option data-class="wchat-msg-friend-style-grgray3d">gray gradient + 3d</option>'; html += '</select>'; html += '</li>'; html += '<li id="wchat-cfg-forusermsgstyle">'; html += '4YOU msg style '; html += '<select>'; html += '<option data-class="wchat-msg-foruser-style-default">default</option>'; html += '<option data-class="wchat-msg-foruser-style-classic">classic</option>'; html += '<option data-class="wchat-msg-foruser-style-grbrown">brown gradient</option>'; html += '<option data-class="wchat-msg-foruser-style-grbrown3d">brown gradient + 3d</option>'; html += '<option data-class="wchat-msg-foruser-style-grgreen">green gradient</option>'; html += '<option data-class="wchat-msg-foruser-style-grgreen3d">green gradient + 3d</option>'; html += '</select>'; html += '</li>'; html += '<li id="wchat-cfg-about">'; html += '<a href="http://chat.sc2tv.ru/history.htm" target="_blank">История сообщений</a>, '; html += '<a href="http://sc2tv.ru/chat-rules" target="_blank">Правила</a>, '; html += '<a href="http://chat.sc2tv.ru/automoderation_history.htm" target="_blank">Баны</a>'; html += '</li>'; html += '<li id="wchat-cfg-about">'; html += 'peka2tv chat <a href="https://github.com/Winns/p2tv/tree/master/peka2tv_chat2" target="_blank">v2.x</a><br>'; html += 'Установить старую версию <a href="https://github.com/Winns/p2tv/tree/master/peka2tv_chat" target="_blank">v1.x</a>'; html += '</li>'; html += '</ul>'; html += '</div>'; html += '</div>'; return html; } templates.channels = function() { var html = '', id, text, textHTML, title = cfg.streamTitle, streamer = cfg.streamerName; if ((cfg.streamerName == '') && (cfg.streamTitle == '')) text = textHTML = 'Unknown channel'; else { if (cfg.streamerName === undefined) text = textHTML = cfg.streamTitle; else { text = cfg.streamerName +': '+ cfg.streamTitle; textHTML = '<em>'+ cfg.streamerName +':</em> '+ cfg.streamTitle; } } html += '<div id="wchat-chanells-title" title="'+ text +'">'; html += textHTML +'<span></span><a href="http://chat.sc2tv.ru/index.htm?channelId='+ cfg.channelId +'" title="Full screen chat" target="_blank">→</a>'; html += '</div>'; html += '<div id="wchat-chanells-list">'; html += '<div class="wchat-select-menu">'; for (var i=0; i < cfg.channelsList.length; i++) { id = cfg.channelsList[ i ].channelId; title = cfg.channelsList[ i ].channelTitle; streamer = cfg.channelsList[ i ].streamerName; if (streamer === undefined) text = textHTML = title; else { text = streamer +': '+title; textHTML = '<em>'+ streamer +':</em> '+ title; } html += '<div title="'+ text +'" data-chanell-id="'+ id +'" data-streamer="'+ streamer +'">'+ textHTML +'</div>'; } html += '</div>'; html += '</div>'; return html; } templates.admWrapper = function() { var html = ''; html += '<div id="wchat-adm-wrapper" class="wchat-menu-popup">'; html += '<div class="wchat-menu-popup-close"><span>Сообщения от администрации</span><div>✕</div></div>'; html += '<div class="wchat-menu-popup-content"></div>'; html += '</div>'; return html; } templates.linksWrapper = function() { var html = ''; html += '<div id="wchat-links-wrapper" class="wchat-menu-popup">'; html += '<div class="wchat-menu-popup-close"><span>Ссылки из чата</span><div>✕</div></div>'; html += '<div class="wchat-menu-popup-content"></div>'; html += '</div>'; return html; } templates.forYouWrapper = function() { var html = ''; html += '<div id="wchat-foryou-wrapper" class="wchat-menu-popup">'; html += '<div class="wchat-menu-popup-close"><span>Сообщения адресованные вам</span><div>✕</div></div>'; html += '<div class="wchat-menu-popup-content"></div>'; html += '</div>'; return html; } templates.userMenu = function() { var html = ''; html += '<div id="wchat-usermenu-wrapper">'; html += '<div class="wchat-usermenu-close"><span class="wchat-usermenu-name"></span><div>✕</div></div>'; html += '<div class="wchat-usermenu-content">'; html += '<ul>'; html += '<li data-action="answer">Ответить</li>'; html += '<li data-action="channel"><a href="" target="_blank">Канал пользователя</a></li>'; html += '<li data-action="add-to-friends">Добавить в друзья</li>'; html += '<li data-action="send-private-msg">Послать ЛС</li>'; html += '<li data-action="banmenu">Забанить</li>'; html += '<li data-action="add-to-ignore">Добавить в игнор</li>'; html += '</ul>'; html += '</div>'; html += '<div class="wchat-usermenu-banmenu">'; html += '<div>Причина бана</div>'; html += '<select>'; html += '<option data-reason-id="1">Мат</option>'; html += '<option data-reason-id="2">Завуалированый мат</option>'; html += '<option data-reason-id="3">Угрозы жизни и здоровью</option>'; html += '<option data-reason-id="4">Лёгкие оскорбления</option>'; html += '<option data-reason-id="5">Серьёзные оскорбления</option>'; html += '<option data-reason-id="6">Национализм, нацизм</option>'; html += '<option data-reason-id="7">Реклама</option>'; html += '<option data-reason-id="8">Спам</option>'; html += '<option data-reason-id="9">Клевета</option>'; html += '<option data-reason-id="10">Негативный троллинг</option>'; html += '<option data-reason-id="11">Транслит, удаффщина, капсы</option>'; html += '<option data-reason-id="12">Вредные ссылки</option>'; html += '<option data-reason-id="13">Вредные флэшмобы</option>'; html += '<option data-reason-id="14">Спойлер</option>'; html += '</select>'; html += '<br><div class="wchat-btn">Забанить</div>'; html += '<div class="wchat-usermenu-callback"></div>'; html += '</div>'; html += '</div>'; return html; } templates.userState = function() { var html = ''; if ( !isUserLoggedIn() ) { html = '<div class="wchat-userstate">'+ cfg.eventMessages.pleaseLogIn +'</div>'; } return html; } /* ====== Functions ====== */ /* === jQuery === */ $.fn.selectRange = function(start, end) { if(!end) end = start; return this.each(function() { if (this.setSelectionRange) { this.focus(); this.setSelectionRange(start, end); } else if (this.createTextRange) { var range = this.createTextRange(); range.collapse(true); range.moveEnd('character', end); range.moveStart('character', start); range.select(); } }); }; /* === Script === */ function isUserLoggedIn() { if ((cfg.userInfo === '') || (cfg.userInfo === null) || (cfg.userInfo === undefined)) { return false; } else { if (cfg.userInfo.type === 'anon') { return false; } else { return true; } } } function getBanInfo() { var info = { isBanned: false, banExpire: '' }; if ((cfg.userInfo !== '') || (cfg.userInfo !== null) || (cfg.userInfo !== undefined)) { if ((cfg.userInfo.type === 'bannedInChat') || (cfg.userInfo.type === 'bannedOnSite')) { info.isBanned = true; info.banExpire = new Date( cfg.userInfo.banExpirationTime * 1000 ).toLocaleString(); } } return info; } function msg2html( data ) { // bb codes parser var html = [ '<b>$1</b>', '<a href="$1" target="_blank">$2</a>' ]; var bb = [ /\[b\](.*?)\[\/b\]/g, /\[url=(.*?)\](.*?)\[\/url\]/g ]; for (var i=0; i < bb.length; i++) { data = data.replace( bb[i], html[i] ); } // url shortener data = data.replace( /\[url\](.*?)\[\/url\]/g, function( match, url ) { var text; if (url.length > 40) text = url.substr(0, 26) +'...'+ url.substr(url.length - 11); else text = url; text = text.replace(/(http[s]?:\/\/)?(www\.)?/i, ''); if (text.length < 1) text = 'link'; return '<a href="'+ url +'" target="_blank">'+ text +'</a>'; }); // smiles data = data.replace( /:s(:[-a-z0-9]{2,}:)/gi, function( match, code ) { var smile = ''; for (var i=0; i < cfg.smiles.length; i++) { if (cfg.smiles[i].code == code) { smile = templates.smile( cfg.smiles[i] ); } } return smile; }); return data; } function readChat( renderCfg ) { $.getJSON( cfg.chatURL + 'memfs/channel-' + cfg.channelId + '.json', function( messages ){ if ( messages != undefined ) { messages = messages.messages; // get new messages var newMessages = []; if (cfg.messages === null) { newMessages = messages; renderMessages( newMessages, renderCfg ); } else { var newId, oldId, isOldMsg; for (var i=0, lenI = messages.length; i < lenI; i++) { newId = messages[i].id; isOldMsg = false; for (var j=0, lenJ = cfg.messages.length; j < lenJ; j++) { oldId = cfg.messages[j].id; if (newId == oldId) { isOldMsg = true; break; } } if (!isOldMsg) { newMessages.push( messages[i] ); } } renderMessages( newMessages, renderCfg ); } cfg.messages = messages; // chat widgets if (newMessages.length > 0) { widgetChatLinks( newMessages ); widgetAdmMsgs( newMessages ); widgetMsgsForYou( newMessages ); } } }); } function checkMsgCount() { var msgsEl = $(cfg.el.chat).find('div'); if (msgsEl.length > cfg.chatMessagesLimit) msgsEl.slice(0, msgsEl.length - cfg.chatMessagesLimit).remove(); } function renderMessages( data, renderCfg ) { if (data.length < 1) return; var html = '', oldMsgs = $(cfg.el.chat).find('.wchat-msg'), newMsgs; if (renderCfg === undefined) { renderCfg = {scroll: 'animation', fade: true, append: true }; } else { if (!renderCfg.hasOwnProperty( 'scroll' )) { renderCfg.scroll = 'animation'; } if (!renderCfg.hasOwnProperty( 'fade' )) { renderCfg.fade = true; } if (!renderCfg.hasOwnProperty( 'append' )) { renderCfg.append = true; } } // form msgs html for (var i=0; i < data.length; i++) { html = templates.chatMSG( data[i] ) + html; } // push new msgs if ( renderCfg.append ) $(cfg.el.chat).append( html ); else $(cfg.el.chat).html( html ); // animate new msgs newMsgs = $(cfg.el.chat).find('.wchat-msg').not( oldMsgs ); if ( newMsgs.length ) { if ( renderCfg.fade ) newMsgs.fadeTo( cfg.time.newMsg, 1 ); else newMsgs.css( 'opacity', 1 ); switch ( renderCfg.scroll ) { case 'animation': // scroll, del msg over limit // if mousedown and scroll = false if ( (!$( cfg.el.chat+':active' ).length) && cfg.doScroll ) { $(cfg.el.chat).animate({ scrollTop: $(cfg.el.chat)[0].scrollHeight - ($(cfg.el.chat).height()+0.001) }, cfg.time.scroll, function(){ checkMsgCount(); } ); } break; case 'instant': $(cfg.el.chat).scrollTop( $(cfg.el.chat)[0].scrollHeight - ($(cfg.el.chat).height()+0.001) ); checkMsgCount(); break; } } } function clearChat() { cfg.messages = null; $(cfg.el.chat).html(''); readChat( {scroll: 'instant'} ); } function getMessageStyle( data ) { var o = { msg: '', nick: '', icons: '' }; // If logged in if (isUserLoggedIn()) { // if @ ignore list if ( cfg.ignoreList.hasOwnProperty(data.uid) ) o.msg += ' wchat-msg-ignore'; // message for you var msgForUserRegExp = new RegExp('\\[b\\]' + escapeData( cfg.userInfo.name ) + '\\[/b\\],','gi'); if ( data.message.search( msgForUserRegExp ) != -1 ) { o.msg += ' wchat-msg-foruser '+ cfg.forUserMsgStyle; } else { // if @ friend list if ( cfg.friendList.hasOwnProperty(data.uid) ) o.msg += ' wchat-msg-friend '+ cfg.friendsMsgStyle; } } switch ( data.uid ) { case '-2': o.msg += ' wchat-msg-primetime'; o.nick += ' wchat-user-primetime'; o.icons += '<i class="wchat-icon wchat-icon-primetime"></i> '; break; // primetime bot case '-1': o.msg += ' wchat-msg-system'; o.nick += ' wchat-user-system'; o.icons += '<i class="wchat-icon wchat-icon-system"></i> '; break; // system message }; // If nick colors ON if (cfg.nickColor) { switch (data.role) { case 'user': o.nick += 'wchat-user-default'; break; case 'userstream-editor': o.nick += 'wchat-user-userstream-editor'; break; case 'moderator': o.nick += 'wchat-user-moderator'; break; case 'editor': o.nick += 'wchat-user-editor'; break; case 'root': o.nick += 'wchat-user-root'; break; case 'streamer': o.nick += 'wchat-user-streamer'; break; case 'prime-streamer': o.nick += 'wchat-user-primestreamer'; break; case 'admin': case 'color-red': o.nick += 'wchat-user-admin'; break; case 'color-purple': o.nick += 'wchat-user-purple'; break; case 'color-pink': o.nick += 'wchat-user-pink'; break; default: o.nick += 'wchat-user-default'; break; } } else { o.nick = 'wchat-user-default'; } // If nick icons ON if (cfg.nickIcon) { // top supporter if (data.roleIds.indexOf( 24 ) !== -1) o.icons += '<i class="wchat-icon wchat-icon-topsupporter"></i> '; switch ( data.uid ) { case '51245': o.icons += '<i class="wchat-icon wchat-icon-pes"></i> '; break; // pes }; } return o; } function sendMessage() { var msg = $( cfg.el.chatInput ).val(); // sanitize user msg msg = msg.replace( /[^\u0020-\u007E\u0400-\u045F\u0490\u0491\u0207\u0239\u2012\u2013\u2014]+/g, '' ); msg = msg.replace( /[\s]+/g, ' ' ); // check for caps abuse if ( unsafeWindow.IsStringCapsOrAbuse( msg ) == true ) { alert( cfg.eventMessages.capsAbuse ); return; } // fix smiles msg = fixSmileCode( msg ); // fix url msg = unsafeWindow.AddUrlBBCode( msg ); // check for auto ban if ( unsafeWindow.CheckForAutoBan( msg ) == true ) { alert( cfg.eventMessages.autoBan ); return; } $( cfg.el.chatInput ).attr( 'readonly', 'readonly' ); // post message $.post( cfg.chatGate, { task: 'WriteMessage', message: msg, channel_id: cfg.channelId, token: cfg.userInfo.token }, function( data ) { var jsonData = $.parseJSON( data ); if( jsonData.error == '' ) { $( cfg.el.chatInput ).val(''); readChat(); } else { // error } $( cfg.el.chatInput ).removeAttr( 'readonly' ); } ); } function escapeData( data ) { return data.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); } function fixSmileCode( data ) { var smilePattern; for( i=0; i < cfg.smiles.length; i++) { smilePattern = new RegExp( escapeData( cfg.smiles[ i ].code ), 'gi' ); data = data.replace( smilePattern, ':s' + cfg.smiles[ i ].code ); } return data; } function saveCaretePosition() { cfg.inputCaretPosition = $(cfg.el.chatInput)[0].selectionStart; } /* === User menu === */ function userMenuShow() { $( cfg.el.userMenu ).animate( {right: -$( cfg.el.userMenu ).width()}, cfg.time.userMenu ); } function userMenuHide() { $( cfg.el.userMenu ).animate( {right: 0}, cfg.time.userMenu ); } function voteBan( reasonId ) { $.post( cfg.chatGate, { task: 'CitizenVoteForUserBan', messageId: cfg.userMenuUserSetup.msgId, banUserId: cfg.userMenuUserSetup.userId, userName: cfg.userMenuUserSetup.name, reasonId: reasonId, token: cfg.userInfo.token }, function( data ) { $( cfg.el.userMenuBanCallback ).html( $.parseJSON( data ).result ); setTimeout(function() { userMenuHide(); }, cfg.time.banMsg); } ); } function addToFriends( id, name ) { cfg.friendList[ id ] = name; GM_setValue('wchat_friendList', JSON.stringify( cfg.friendList ) ); if (isIgnored( id )) removeIgnore( id ); $( cfg.el.userName +'[data-userid="'+ id +'"]' ).parent() .addClass('wchat-msg-friend '+ cfg.friendsMsgStyle); } function removeFriend( id ) { delete cfg.friendList[ id ]; GM_setValue('wchat_friendList', JSON.stringify( cfg.friendList ) ); $( cfg.el.userName +'[data-userid="'+ id +'"]' ).parent() .removeClass('wchat-msg-friend') .removeClass(function (index, elClass) { return (elClass.match (/\wchat-msg-friend-style\S+/g) || []).join(' '); }); } function isFriend( id ) { if ( cfg.friendList.hasOwnProperty( id ) ) return true; else return false; } function addToIgnore( id, name ) { cfg.ignoreList[ id ] = name; GM_setValue('wchat_ignoreList', JSON.stringify( cfg.ignoreList ) ); if (isFriend( id )) removeFriend( id ); $( cfg.el.userName +'[data-userid="'+ id +'"]' ).parent().addClass('wchat-msg-ignore'); } function removeIgnore( id ) { delete cfg.ignoreList[ id ]; GM_setValue('wchat_ignoreList', JSON.stringify( cfg.ignoreList ) ); $( cfg.el.userName +'[data-userid="'+ id +'"]' ).parent().removeClass('wchat-msg-ignore'); } function isIgnored( id ) { if ( cfg.ignoreList.hasOwnProperty( id ) ) return true; else return false; } function getUserInfo() { $.ajax({ url: cfg.chatGate + '?task=GetUserInfo&ref=' + document.referrer, dataType: 'json', success: function( data ) { cfg.userInfo = data; onUserInfoUpdate(); }, error: function() { setTimeout(function() { getUserInfo(); }, cfg.time.ajaxRetryOnError); } }); } function onUserInfoUpdate() { if ( isUserLoggedIn() ) { // if user banned if ( getBanInfo().isBanned ) { $( cfg.el.userState ).html( cfg.eventMessages.banned + getBanInfo().banExpire ); return; } // hide user state overlay $( cfg.el.userState ).fadeOut( cfg.time.hide ); // activate '4YOU' button $('.wchat-btn.disabled[data-target="forYouWrapper"]').removeClass('disabled'); // append smiles window if ( !$( cfg.el.smilesWrapper ).length ) { $( cfg.el.menuWrapper ).prepend( templates.smilesWrapper() ); } } } function getChannelsInfo() { $.ajax({ url: cfg.chatURL + 'memfs/channels.json', dataType: 'json', success: function( jsonData ) { cfg.channelsList = jsonData.channel; onChannelsInfoUpdate(); }, error: function() { setTimeout(function() { getChannelsInfo(); }, cfg.time.ajaxRetryOnError); } }); } function onChannelsInfoUpdate() { for (var i=0; i < cfg.channelsList.length; i++) { if ( cfg.channelsList[ i ].channelId == cfg.channelId ) { cfg.streamerName = cfg.channelsList[ i ].streamerName; cfg.streamTitle = cfg.channelsList[ i ].channelTitle; } } // add channels to cfg menu $( cfg.el.channelsWrapper ).html( templates.channels() ); } function toggleChannels() { var el = $('#wchat-chanells-list'); el.toggleClass('active'); if ( !el.hasClass('active') ) { el.stop(true, false).animate({top: '-183px' }, cfg.time.toggleChannels ); } else { el.stop(true, false).animate({top: '12px' }, cfg.time.toggleChannels ); } } /* ====== Chat widgets ====== */ /* === Links === */ function widgetChatLinks( data ) { var msg, hasLink, html = '', newMsgs, duplicate; for (var i=0; i < data.length; i++ ) { msg = data[ i ].message; hasLink = msg.match( /\[url\](.*?)\[\/url\]/g ); if ( hasLink ) { // check for duplicate duplicate = $( cfg.el.linksWrapper ).find('.wchat-nick[data-msgid="'+ data[ i ].id +'"]').length; if ( !duplicate ) html = templates.chatMSG( data[ i ] ) + html; } } $( cfg.el.linksWrapper ).find('.wchat-menu-popup-content').append( html ); var messages = $( cfg.el.linksWrapper ).find('.wchat-msg'); messages.css({opacity: 1}); // remove messages over limit if (messages.length > cfg.chatMessagesLimit) { messages.slice(0, messages.length-cfg.chatMessagesLimit).remove(); } } /* === Adm === */ function widgetAdmMsgs( data ) { var html = '', duplicate; for (var i=0; i < data.length; i++) { if ( data[ i ].role != 'user' ) { // check for duplicate duplicate = $( cfg.el.admWrapper ).find('.wchat-nick[data-msgid="'+ data[ i ].id +'"]').length; if ( !duplicate ) html = templates.chatMSG( data[ i ] ) + html; } } $( cfg.el.admWrapper ).find('.wchat-menu-popup-content').append( html ); var messages = $( cfg.el.admWrapper ).find('.wchat-msg'); messages.css({opacity: 1}); // remove messages over limit if (messages.length > cfg.chatMessagesLimit) { messages.slice(0, messages.length-cfg.chatMessagesLimit).remove(); } } /* === 4You === */ function widgetMsgsForYou( data ) { var html = '', duplicate, msgForUserRegExp = new RegExp('\\[b\\]' + escapeData( cfg.userInfo.name ) + '\\[/b\\],','gi'); for (var i=0; i < data.length; i++ ) { if ( data[ i ].message.search( msgForUserRegExp ) != -1 ) { // check for duplicate duplicate = $( cfg.el.forYouWrapper ).find('.wchat-nick[data-msgid="'+ data[ i ].id +'"]').length; if ( !duplicate ) html = templates.chatMSG( data[ i ] ) + html; } }; $( cfg.el.forYouWrapper ).find('.wchat-menu-popup-content').append( html ); var messages = $( cfg.el.forYouWrapper ).find('.wchat-msg'); messages.css({opacity: 1}); // remove messages over limit if (messages.length > cfg.chatMessagesLimit) { messages.slice(0, messages.length-cfg.chatMessagesLimit).remove(); } } /* === Cfg === */ function updateCfgFrame() { var html = ''; // friend list for (var key in cfg.friendList) { html += '<option data-id="'+ key +'">'+ cfg.friendList[ key ] +'</option>'; } $( cfg.el.cfgFriendList ).html( html ); // ignore list html = ''; for (var key in cfg.ignoreList) { html += '<option data-id="'+ key +'">'+ cfg.ignoreList[ key ] +'</option>'; } $( cfg.el.cfgIgnoreList ).html( html ); $( cfg.el.cfgSmilesSize ).val( cfg.smilesSize ); $( cfg.el.cfgFontSize ).val( cfg.fontSize ); $( cfg.el.cfgNickColor ).prop('checked', cfg.nickColor); $( cfg.el.cfgNickIcon ).prop('checked', cfg.nickIcon); $( cfg.el.cfgMsgsLimit ).val( cfg.chatMessagesLimit ); $( cfg.el.cfgFriendsMsgStyle ).find('option[data-class="'+ cfg.friendsMsgStyle +'"]').attr('selected', 'selected'); $( cfg.el.cfgForUserMsgStyle).find('option[data-class="'+ cfg.forUserMsgStyle +'"]').attr('selected', 'selected'); } function setSmilesSize( size ) { GM_setValue( 'wchat_smilesSize', size.toString() ); cfg.smilesSize = size; renderMessages( cfg.messages, {scroll: 'off', fade: false, append: false} ); } function setFontSize( size ) { GM_setValue( 'wchat_fontSize', size.toString() ); cfg.fontSize = size; $( cfg.el.chat ).css('font-size', cfg.fontSize +'px'); } function setNickColor( val ) { GM_setValue( 'wchat_nickColor', val ); cfg.nickColor = val; renderMessages( cfg.messages, {scroll: 'off', fade: false, append: false} ); } function setNickIcon( val ) { GM_setValue( 'wchat_nickIcon', val ); cfg.nickIcon = val; renderMessages( cfg.messages, {scroll: 'off', fade: false, append: false} ); } function setMsgsLimit( limit ) { GM_setValue( 'wchat_chatMessagesLimit', limit.toString() ); cfg.chatMessagesLimit = limit; renderMessages( cfg.messages, {scroll: 'instant', fade: false, append: false} ); } function setFriendsMsgStyle( style ) { GM_setValue( 'wchat_friendsMsgStyle', style ); cfg.friendsMsgStyle = style; $('.wchat-msg-friend') .removeClass(function (index, elClass) { return (elClass.match (/\wchat-msg-friend-style\S+/g) || []).join(' '); }) .addClass( cfg.friendsMsgStyle ); } function setForUserMsgStyle( style ) { GM_setValue( 'wchat_forUserMsgStyle', style ); cfg.forUserMsgStyle = style; $('.wchat-msg-foruser') .removeClass(function (index, elClass) { return (elClass.match (/\wchat-msg-foruser-style\S+/g) || []).join(' '); }) .addClass( cfg.forUserMsgStyle ); } /* ====== Init ====== */ function init() { /* === Render === */ $('body').append( templates.chat() ); /* === Elements === */ // stop jquery scroll animation on user scroll $(cfg.el.chat).on('wheel mousedown', function(){ $(cfg.el.chat).stop(); cfg.doScroll = false; clearTimeout( cfg.sctollTimer ); cfg.sctollTimer = setTimeout(function() { cfg.doScroll = true; }, cfg.time.scrollTimer); }); // fix scroll animation on window resize $(window).on('resize', function() { var el = $(cfg.el.chat); if (el.scrollTop() >= el[0].scrollHeight - el.height()) { el.scrollTop( el[0].scrollHeight - (el.height()+1) ); } }); /* === Channels === */ // set new channel $( document ).on('click', cfg.el.channelsWrapper +' .wchat-select-menu div', function() { cfg.channelId = $(this).attr('data-chanell-id'); clearChat(); toggleChannels(); onChannelsInfoUpdate(); }); // open channel menu $( document ).on('click', '#wchat-chanells-title span', function() { toggleChannels(); }); /* === Chat input === */ // submit message on "enter" $( cfg.el.chatInput ).on('keypress', function(e){ if (e.which == 13) { e.preventDefault(); sendMessage(); return false; } }); // fix pageUp, pageDown @ textarea bug (chrome) $( cfg.el.chatInput ).on('keydown', function(e){ if ((e.which == 33) || (e.which == 34)) { e.stopPropagation(); e.preventDefault(); return false; } }); // save caret position $( cfg.el.chatInput ).on('mouseup input paste change blur keypress', function(e){ saveCaretePosition(); }); /* === Chat popup === */ // close $ ( document ).on('click', cfg.el.chatPopUpClose, function() { $(this).parent().toggleClass('active'); $(this).parent().animate({top: 0 }, cfg.time.hide ); }); /* === Streamer === */ // handle streamer button $( cfg.el.streamerBtn ).on('click', function() { if ( (cfg.streamerName != '') && (cfg.streamerName != undefined) ){ var streamer = '[b]'+ cfg.streamerName +'[/b], ', msg = $(cfg.el.chatInput).val(); if (msg.substr(0, streamer.length) != streamer) { $(cfg.el.chatInput).val( streamer + msg ); } $(cfg.el.chatInput).selectRange( streamer.length + msg.length ); } }); /* === handle popup show === */ $( document ).on('click', cfg.el.menuButtons +':not(.disabled)', function(){ var target = $(this).attr('data-target'); if (target) { switch (target) { case 'cfgWrapper': updateCfgFrame(); break; } // hide other frames $( cfg.el.chatPopUp ).not( $(cfg.el[target]) ) .removeClass('active') .animate({top: '0' }, cfg.time.hide ); $( cfg.el[ target ] ).toggleClass('active'); if ($( cfg.el[ target ] ).hasClass('active')) { $( cfg.el[ target ] ).animate({top: -$(cfg.el[ target ]).height() }, cfg.time.show ); } else { $( cfg.el[ target ] ).animate({top: '0' }, cfg.time.hide ); } } }); /* === Smiles === */ // handle smile post $( document ).on('click', cfg.el.smilesWrapper + ' .wchat-menu-popup-content div:not(.wchat-smile-private)', function() { var smile = ' '+ $(this).find('img').attr('title') +' ', inputLength = $( cfg.el.chatInput ).val().length, textBeforeCaret = $( cfg.el.chatInput ).val().substring( 0, cfg.inputCaretPosition ), textAfterCaret = $( cfg.el.chatInput ).val().substring( cfg.inputCaretPosition, inputLength ); // insert smile $(cfg.el.chatInput).val( textBeforeCaret + smile + textAfterCaret ); // close window $( cfg.el.smilesWrapper ).removeClass('active').animate({top: '0' }, cfg.time.hide ); // restor cursor position $(cfg.el.chatInput).selectRange( cfg.inputCaretPosition + smile.length ); }); // on private smile click $( document ).on('click', cfg.el.privateSmiles, function() { window.open('http://prime.sc2tv.ru/donate','_blank'); }); /* === User menu (on username click) === */ // show $( document ).on('click', cfg.el.userName, function() { if ( isUserLoggedIn() ){ var userMenu = $( cfg.el.userMenu ), userMenuHeight = userMenu.outerHeight(), chatHeight = $(cfg.el.chat).outerHeight(), msgPosition = $(this).position(), chatMenuPosition = $(cfg.el.menuWrapper).position(), top = -(chatHeight - msgPosition.top), text = ''; if (-top < userMenuHeight) { top = -userMenu.outerHeight(); } userMenu.css('top', top ); userMenu.find( cfg.el.userMenuName ).html( $(this).text() ); // hide ban menu, show default menu userMenu.find('.wchat-usermenu-banmenu').hide(); userMenu.find('.wchat-usermenu-content').show(); // save data to variable cfg.userMenuUserSetup = { name: $(this).text(), userId: $(this).attr('data-userid'), msgId: $(this).attr('data-msgid') } // handle add/remove friend text if (isFriend( cfg.userMenuUserSetup.userId )) { text = 'Удалить из друзей'; } else { text = 'Добавить в друзья'; } $( cfg.el.userMenu ).find('.wchat-usermenu-content ul li[data-action="add-to-friends"]').text( text ); // handle add/remove ignore text if (isIgnored( cfg.userMenuUserSetup.userId )) { text = 'Удалить из игнора'; } else { text = 'Добавить в игнор'; } $( cfg.el.userMenu ).find('.wchat-usermenu-content ul li[data-action="add-to-ignore"]').text( text ); // Create user channel url var nick = $( cfg.el.userMenuName ).text(); nick = $.trim( nick ) .toLowerCase() .replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '') .replace(/ /g, '-'); $( cfg.el.userMenu ) .find('.wchat-usermenu-content ul li[data-action="channel"] a') .attr( 'href', 'http://sc2tv.ru/channel/'+ nick ); userMenuShow(); } }); // hide $( cfg.el.userMenuClose ).on('click', function() { userMenuHide(); }); // on menu click $( cfg.el.userMenu ).find('ul li[data-action]').on('click', function() { var action = $(this).attr('data-action'); switch( action ) { case 'answer': var nick = '[b]'+ $( cfg.el.userMenuName ).text() +'[/b], '; $( cfg.el.chatInput ).val( nick ); $( cfg.el.chatInput ).selectRange( nick.length ); userMenuHide(); break; case 'banmenu': // hide default menu, show ban menu $( cfg.el.userMenu ).find('.wchat-usermenu-content').hide(); $( cfg.el.userMenuBanCallback ).html(''); $( cfg.el.userMenu ).find('.wchat-usermenu-banmenu').show(); break; case 'send-private-msg': var id = cfg.userMenuUserSetup.userId; window.open('http://sc2tv.ru/messages/new/'+ id,'_blank'); break; case 'add-to-friends': var id = cfg.userMenuUserSetup.userId, nick = $( cfg.el.userMenuName ).text(); if (isFriend( cfg.userMenuUserSetup.userId )) { removeFriend( id ); } else { addToFriends( id, nick ); } userMenuHide(); break; case 'add-to-ignore': var id = cfg.userMenuUserSetup.userId, nick = $( cfg.el.userMenuName ).text(); if (isIgnored( cfg.userMenuUserSetup.userId )) { removeIgnore( id ); } else { addToIgnore( id, nick ); } userMenuHide(); break; } }); // ban menu $( cfg.el.userMenuBan ).on('click', function() { var reasonId = $(this).parent().find('option:selected').attr('data-reason-id'); voteBan( reasonId ); }); /* ====== Cfg ====== */ /* === Cfg init === */ setFontSize( cfg.fontSize ); /* === Friend list === */ $( cfg.el.cfgFriendListBtn ).on('click', function() { removeFriend( $( cfg.el.cfgFriendList ).find(':selected').attr('data-id') ); updateCfgFrame(); }); /* === Ignore list === */ $( cfg.el.cfgIgnoreListBtn ).on('click', function() { removeIgnore( $( cfg.el.cfgIgnoreList ).find(':selected').attr('data-id') ); updateCfgFrame(); }); /* === Smiles size === */ $( cfg.el.cfgSmilesSize ).on('change', function() { setSmilesSize( $(this).val() ); }); /* === Font size === */ $( cfg.el.cfgFontSize ).on('change', function() { setFontSize( $(this).val() ); }); /* === Nick color === */ $( cfg.el.cfgNickColor ).on('change', function() { setNickColor( this.checked ); }); /* === Nick icon === */ $( cfg.el.cfgNickIcon).on('change', function() { setNickIcon( this.checked ); }); /* === Messages limit === */ $( cfg.el.cfgMsgsLimit ).on('change', function() { setMsgsLimit( $(this).val() ); }); /* === Friends msgs style === */ $( cfg.el.cfgFriendsMsgStyle ).on('change', function() { setFriendsMsgStyle( $(this).find(':selected').attr('data-class') ); }); /* === 4YOU msgs style === */ $( cfg.el.cfgForUserMsgStyle ).on('change', function() { setForUserMsgStyle( $(this).find(':selected').attr('data-class') ); }); /* === Script === */ // shutdown original chat unsafeWindow.StopChat(); // get chat data from server setTimeout(function() { readChat( {scroll: 'instant'} ); }, 250); // updata chat data on interval if (cfg.chatInterval != null) { clearInterval( cfg.chatInterval ); } cfg.chatInterval = setInterval(function() { readChat() }, cfg.time.chatUpdateInterval); } getUserInfo(); getChannelsInfo(); init(); } // END Run chat function GM_waitChat() { if ((typeof unsafeWindow.StopChat == 'undefined') || (typeof unsafeWindow.smiles == 'undefined') || (typeof unsafeWindow.AddUrlBBCode == 'undefined')) setTimeout( GM_waitChat, 100 ); else GM_runChat(); } GM_waitChat(); } else { // END (if SUBDOMAIN = chat) // add wrapper to iframe, to fix fullscreen button $( 'html' ).css( 'min-height', '100%' ); $( 'body' ).css( 'min-height', '100%' ); $( '#tab_chat iframe' ) .wrap( '<div id="wchat-iframe-fix" style="display: inline-block; position: relative; min-height: 100%;"></div>' ); $( '#wchat-iframe-fix' ) .append( '<div id="wchat-fullscreen" onclick="change_screen(); return false;"></div>' ); $( '#chat-switch-screen-btn' ) .appendTo( '#wchat-iframe-fix' ).hide(); } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址