MediaWiki:ChatHacks.js

/* * ChatHacks.js, by Monchoman45. * Version 7.0 * * Features: *  Ability to clear your chat window *  A host of slash commands *  Ability to create multi user private chats *  Inline alerts every time your away status changes *  Icons next to messages by staff and chat mods in the room *  Pings when someone mentions your name or any other specified phrases */ (function(mw) {   if (window.ChatHacksLoaded) {        return;    }    window.ChatHacksLoaded = true;    var username = mw.config.get('wgUserName');    if (mw.config.get('wgCanonicalSpecialPageName') === 'Chat') {        window.hasFocus = true;        window.dinged = false;        window.ding = 0;        window.titleorig = document.title;        var i18n = {};        // Function for adding messages to the window        NodeChatDiscussion.prototype.iconPing = function (chat) {            var icon = '';            var i;            for (i in this.model.users.models) {                if (this.model.users.models[i].attributes.name == chat.attributes.name) {                    if (this.model.users.models[i].attributes.isStaff) {                        icon = $(' ', { 'class': 'stafficon', src: window.ChatHacksIconStaff || 'https://images.wikia.nocookie.net/wikiaglobal/images/6/6c/Staff_icon.png' });                   } else if (this.model.users.models[i].attributes.isModerator) {                        icon = $(' ', { 'class': 'modicon', src: window.ChatHacksIconMod || 'https://images.wikia.nocookie.net/monchbox/images/6/6b/Icon-chatmod.png' });                   }                    break;                }            }            if (icon && window.ChatHacksNoStar !== true) {                this.chatUL.children.last.children('.username').append(' ', icon);            }            if (mainRoom.isInitialized && chat.attributes.name != username && !chat.attributes.isInlineAlert) {                // resolve HTML                var text = chat.attributes.text;                var pings = $('#pings').val.trim.split('\n');                for (i = 0; i < pings.length; i++) {                    if (text.toLowerCase.indexOf(pings[i].toLowerCase) != -1 || this != mainRoom.viewDiscussion) {                        // Only annoy people if the window isn't focused                        if (!window.hasFocus) {                            if (window.ChatHacksPingSound !== false) {                                document.getElementById('sound').innerHTML = $(' ').attr({ autoplay: true, src: window.ChatHacksPingSound || 'https://images.wikia.nocookie.net/monchbox/images/0/01/Beep-sound.ogg' }).prop('outerHTML');                           }                            if (!window.dinged) {                                window.dinged = true;                                window.ding = setInterval(flashTitle, 500);                            }                        }                        this.scrollToBottom;                        if (this == mainRoom.viewDiscussion) {                            var ref = text.toLowerCase.indexOf(pings[i].toLowerCase);                            var phrase = text.slice(ref, ref + pings[i].length);                            this.chatUL.children.last.children('.message').addClass('ping');                        }                        break;                    }                }            }            // Kill emoticons            this.chatUL.children.last.children('.message img').each(function { this.outerHTML = '' + this.title + ' '; });       };        mw.hook('chathacks.mainRoomIsReady').add(function  { mainRoom.model.chats.bind('afteradd', $.proxy(mainRoom.viewDiscussion.iconPing, mainRoom.viewDiscussion)); });       // Away status functions        NodeChatController.prototype.setAway = function  {            this.inlineAlert(i18n['away']);            mainRoom.socket.send(new models.SetStatusCommand({                statusState: STATUS_STATE_AWAY,                statusMessage:             }).xport);        };        NodeChatController.prototype.setBack = function  {            // if we have sent this command (but just haven't finished coming back yet), don't keep spamming the server w/ this command            if ( !this.comingBackFromAway ) {                this.comingBackFromAway = true;                this.inlineAlert(i18n['back']);                mainRoom.socket.send(new models.SetStatusCommand({                    statusState: STATUS_STATE_PRESENT,                    statusMessage:                 }).xport);            }        };        // Send message function        // TODO: UPDATE WITH MESSAGE LIMITING CODE NodeChatController.prototype.sendMessage = function (event) { if (!this.active) { return true; }           if (event.which == 13 && !event.shiftKey) { event.preventDefault; mainRoom.resetActivityTimer; var inputField = this.viewDiscussion.getTextInput; var send = preparse.call(this, inputField.val); if (inputField.val && send) { var chatEntry = new models.ChatEntry({                       roomId: this.roomId,                        name: username,                        text: inputField.val                    }); // is prive if (this.isPrivate === true) { if (this.afterInitQueue.length < 1 || this.model.users.length < 2) { this.mainController.socket.send(this.model.privateRoom.xport); }                       if (!this.isInitialized) { this.afterInitQueue.push(chatEntry.xport); // temp chat entry in case of slow connection time chatEntry.set({temp : true, avatarSrc: wgAvatarUrl }); this.model.chats.add(chatEntry); } else { this.socket.send(chatEntry.xport); }                   } else { this.socket.send(chatEntry.xport); }                   event.preventDefault; }               inputField.val(''); $.log('submitting form'); inputField.focus; }       };        mw.hook('chathacks.mainRoomIsReady').add(function  {            mainRoom.viewDiscussion.unbind('sendMessage');            mainRoom.viewDiscussion.bind('sendMessage', $.proxy(mainRoom.sendMessage, mainRoom));        }); NodeChatController.prototype.inlineAlert = function (text) { for(var i in text.split('\n')) { mainRoom.model.chats.add(                   new models.InlineAlert({text: text.split('\n')[i]})                ); }           this.viewDiscussion.scrollToBottom; };       function flashTitle { if (document.title == window.titleorig) { document.title = i18n['activity'].replace(/\$1/g, wgSiteName); } else { document.title = window.titleorig; }       }        // parse slash commands // return true to send text to chat unparsed //       false to discard it after parsing function preparse(input) { var commands = window.commands, com = input.slice(1) .trim .replace(/\s+/g, ' ') .split(' '), ref = com.shift, done = false; if ((input.charAt(0) === '/') && (ref.length > 0)) { while (typeof commands[ref] === 'string') { ref = commands[ref]; }               if (typeof commands[ref] === 'function') { return commands[ref].call(this, com.join(' '), input); }           }            return true; }       function baseMod(user, action) { if (user) { $.getJSON(mw.util.wikiScript('api'), {                   action: 'query',                    list: 'users',                    ustoken: 'userrights',                    ususers: user,                    format: 'json'                }, $.proxy(function (token) { var params = { format: 'json', action: 'userrights', user: user, token: token.query.users[0].userrightstoken };                   params[action] = 'chatmoderator'; $.post(mw.util.wikiScript('api'), params, $.proxy(function (result) { if (action === 'remove') { if (result.userrights.removed[0] == 'chatmoderator') { this.inlineAlert(i18n['demodded'].replace(/\$1/g, user)); } else { this.inlineAlert(i18n['notmod'].replace(/\$1/g, result.userrights.user)); }                       } else { if (result.userrights.added[0] == 'chatmoderator') { this.inlineAlert(i18n['modded'].replace(/\$1/g, user)); } else { this.inlineAlert(i18n['alreadymod'].replace(/\$1/g, result.userrights.user)); }                       }                    }, this)); }, this)); } else { this.inlineAlert(i18n['erruser'].replace(/\$1/g, text.split(' ')[0])); }       }        window.commands = { away: 'afk', afk: function { if ($('#ChatHeader .User').hasClass('away') === false) { // if you're away, hitting enter has already sent you back toggleAway; }           },            // Clear the active chat window clear: function { clearWindow; },           // Nobody cares nc: function (com) { $('#Write [name="message"]').val( + (com || i18n['nobodycares']) + ); return true; },           // IRCpwnt devoice: function (com) { $('#Write [name="message"]').val('* ChanServ set channel mode -v ' + (com || username)); return true; },           // Too young coppa: function (com) { $('#Write [name="message"]').val('https://coppa.org/ ' + (com || i18n['coppa'])); return true; },           // Idle silence: function { $('#Write [name="message"]').val('People idle, enjoy the silence. https://www.youtube.com/watch?v=diT3FvDHMyo'); return true; },           // ¯\_(ツ)_/¯ shrug: function(com) { $('#Write [name="message"]').val((com || '') + ' ¯\\_(ツ)_/¯'); return true; },           // Kick a user kick: function (com, text) { if (com) { mainRoom.kick({                       name: com                    }); } else { this.inlineAlert(i18n['erruser'].replace(/\$1/g, text.split(' ')[0])); }           },            ban: 'kickban', kb: 'kickban', // Kickban a user kickban: function (com, text) { if (com) { mainRoom.socket.send(new models.BanCommand({ userToBan: com, time: '36400', // 1 day it's enough, idk, no time specified reason: 'Misbehaving in chat' // i guess }).xport); } else { this.inlineAlert(i18n['erruser'].replace(/\$1/g, text.split(' ')[0])); }           },            // Unban a user unban: function (com, text) { if (com) { mainRoom.socket.send(new models.BanCommand({ userToBan: com // Empty ban command === unban }).xport); } else { this.inlineAlert(i18n['erruser'].replace(/\$1/g, text.split(' ')[0])); }           },            // Make a user a mod mod: function (com, text) { baseMod.call(this, com, 'add'); },           // Remove a user's mod right demod: function (com) { baseMod.call(this, com, 'remove'); },           // Block a user from private chatting you block: function (com, text) { if (com) { this.blockPrivate({name: com}); } else { this.inlineAlert(i18n['erruser'].replace(/\$1/g, text.split(' ')[0])); }           },            // Unblock a user from private chatting you - should merge this into a toggle unblock: function (com, text) { if (com) { this.allowPrivate({name: com}); } else { this.inlineAlert(i18n['erruser'].replace(/\$1/g, text.split(' ')[0])); }           },            chat: 'private', room: 'private', // Invoke a private room private: function (com, text) { if (com.length > 0) { var users = com.replace(/\s*,\s*/g, ',').split(','); var curRoom = mainRoom.model.privateUsers.findByName(users[0]); if (!curRoom) { mainRoom.openPrivateChat(users); } else { mainRoom.showRoom(curRoom.attributes.roomId); }               } else { this.inlineAlert(i18n.erruser.replace(/\$1/g, text.replace(/\s+$/, ''))); }           },            roomid: 'id', id: function (com, text) { this.inlineAlert(i18n['id'] + ': ' + this.roomId); },           // Send a message to yourself self: function (com, text) { var newstr = ''; for (var i = 0; i < com.length; i++) { switch(com.charAt(i)) { case '[': if (com.charAt(i + 1) == '[') { var k = com.indexOf(']', i); if (com.charAt(k + 1) == ']') { var link = com.substring(i + 2, k); var linktext = link; if (link.indexOf('|') != -1) { link = link.substring(0, link.indexOf('|')); linktext = linktext.substring(linktext.indexOf('|') + 1, linktext.length); }                                   newstr += '' + linktext + ''; i = k + 1; }                           } else if (com.substring(i + 1, i + 8) == 'http://' || com.substring(i + 1, i + 9) == 'https://') { var k = com.indexOf(']', i); var splstr = com.substring(i + 1, k).split(' '); var link = splstr.shift; var linktext = splstr.join(' ') || '[1]'; newstr += '' + linktext + ''; i = k;                           } break; default: newstr += com.charAt(i); break; }               }                this.viewDiscussion.chatUL.append(                    $('').append( $(' ', {                           'class': 'avatar',                            src: $('#ChatHeader .User img').attr('src')                        }), $(' ', {                           'class': 'username',                            text: username                        }), $(' ', {                           'class': 'message self',                            text: i18n['self'] + ' ' + newstr                        }) )               );                this.viewDiscussion.scrollToBottom; },           help: function (com, text) { var str; if (com) { var ref = com.replace(/ /g, '.'); str = ''; var subcoms = []; while (typeof window.commands[ref] === 'string') { ref = window.commands[ref]; }                   if (i18n['help-' + ref]) { str += i18n['help'] .replace(/\$1/g, ref.replace(/\./g, ' ')) .replace(/\$2/g, i18n['help-' + ref]                               .replace(/\$1/g, i18n['example'])                                .replace(/\$2/g, i18n['exampleuser'])                            ) .trim; }                   var command = window.commands[ref]; if (str !== '') { this.inlineAlert(str); } else { this.inlineAlert(i18n['nohelp'].replace(/\$1/g, ref)); }               } else { str = []; for (var i in window.commands) { if (typeof window.commands[i] == 'function') { str.push(i); }                   }                    this.inlineAlert(i18n['commands'].replace(/\$1/g, str.join(', '))); }           }        };        mw.hook('chathacks.commands').fire(window.commands); function toggleAway(msg) { if (!msg) { msg = ''; }           if ($('#ChatHeader .User').hasClass('away')) { mainRoom.setBack; } else { mainRoom.setAway(msg); }       }        toggleAway.prototype.back = function  { //Force back status if ($('#ChatHeader .User').hasClass('away')) { mainRoom.setBack; }       };        toggleAway.prototype.away = function (msg) { //Force away status if (!msg) { msg = ''; }           if (!$('#ChatHeader .User').hasClass('away')) { mainRoom.setAway(msg); }       };        function clearWindow { mainRoom.viewDiscussion.chatUL.empty; mainRoom.inlineAlert(i18n['cleared']); mainRoom.viewDiscussion.chatUL .find('#entry-' + mainRoom.model.chats.models.slice(-1)[0].cid) .removeClass('continued'); }       // Returns the NodeChatController for the active window function active { if (mainRoom.activeRoom && mainRoom.activeRoom != 'main') { return mainRoom.chats.privates[mainRoom.activeRoom]; } else { return mainRoom; }       }        mw.hook('chathacks.i18n').add(function(i18nd) {            //Cache i18n data            $.extend(i18n, i18nd);            //Button handling            mw.hook('dev.chat').add(function(chat) { //Add a 'go afk', 'clear chat' and 'ping phrases' button var buttons = { toggleAway: new chat.button({                       name: 'ChatHacks ' + i18n['afk'],                        attr: {                            click: toggleAway,                            text: i18n['afk']                        }                    }), clearWindow: new chat.button({                       name: 'ChatHacks '+ i18n['clear'],                        attr: {                            click: clearWindow,                            text: i18n['clear']                        }                    }), pingPhrases: $((new chat.button({                       name: 'ChatHacks ping phrases',                        attr: {                            id: 'pingspan',                            text: i18n['pingphrases']                        }                    })).el).append($(' ', { id: 'pings', css: { display: 'none' },                       text: ($.cookie('pingphrases')) ? $.cookie('pingphrases').split('\\n').join('\n') : username }))               };                // Add an interface for adding pings $('#pingspan').on('mouseover', function(event) {                   $('#pings').show;                }); $('#pingspan').on('mouseout', function(event) {                   $('#pings').hide;                    $.cookie('pingphrases', $('#pings').val.split('\n').join('\\n'), {expires: 99999, path: '/'});                }); });           // Initialisation message            mw.hook('chathacks.mainRoomIsReady').add(function  { mainRoom.inlineAlert(i18n['init']); });       });        mw.hook('dev.chat.render').add(function(mainRoom) {            mw.hook('chathacks.mainRoomIsReady').fire;        }); importArticle({           type: 'script',            article: 'u:dev:Chat-js.js'        }); importArticle({           type: 'script',            article: 'u:dev:ChatHacks.js/i18n.js'        }); importArticle({           type: 'style',            article: 'u:dev:MediaWiki:ChatHacks.css'        }); $(function {            // Unbind all of the window listeners that set your status to back            $(window).unbind('mousemove').unbind('focus').unbind('keypress');            // Bind focus and blur for handling page title on ding            $(window).bind('focus', function  { //for fixing the title after you've been dinged document.title = window.titleorig; clearInterval(window.ding); window.hasFocus = true; window.dinged = false; });           $(window).bind('blur', function  { window.hasFocus = false; });           // Add the sound space            $(document.body).append($(' ', { id: 'sound' }));        }); } else { // Not chat function chatCheck(e) { if (typeof e == 'object' && e.hasOwnProperty('preventDefault')) { e.preventDefault; }           $(document.body).find('.WikiaChatLink, .start-a-chat-button').each(function {                this.classList.remove('start-a-chat-button');                this.removeAttribute('href');                this.onclick = openChatWindow;            }); }       function openChatWindow { window.chatwindow = window.open('/wiki/Special:Chat', 'chat'); window.chatwindow.onload = function { window.chatwindow.importArticles({                   type: 'script',                    articles: [                        'u:c:User:' + username + '/global.js',                        'User:' + username + '/wikia.js'                    ]                }); };       }        $(function  {            $(document.body).on('click', 'a[href^="/wiki/Special:Chat"]', chatCheck);            mw.hook('wikipage.content').add(chatCheck);            $('#WikiaRail').on('afterLoad.rail', chatCheck);        }); } }(mediaWiki));