User:Tanhamman/ChatHacks2
Appearance
/*
* ChatHacks.js, by Monchoman45 and FANDOM Open Source Library. * Version 8.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) {
'use strict'; if (window.ChatHacks) { return; } var config = mw.config.get([ 'wgChatMyAvatarUrl', 'wgCanonicalSpecialPageName', 'wgSassParams', 'wgSiteName', 'wgUserName' ]), ChatHacks = { /* eslint-disable max-len */ staffIcon: window.ChatHacksIconStaff || 'https://images.wikia.nocookie.net/wikiaglobal/images/6/6c/Staff_icon.png', modIcon: window.ChatHacksIconMod || 'https://images.wikia.nocookie.net/monchbox/images/6/6b/Icon-chatmod.png', pingSound: window.ChatHacksPingSound || 'https://images.wikia.nocookie.net/monchbox/images/0/01/Beep-sound.ogg', /* eslint-enable max-len */ _loaded: 0, handleIcon: function(msg) { var icon, vd = window.mainRoom.viewDiscussion, user = vd.model.users.findByName(msg.get('name')); if (!user) { return; } if (user.get('isStaff')) { icon = $('<img>', { 'class': 'stafficon', 'src': this.staffIcon }); } else if (user.get('isModerator')) { icon = $('<img>', { 'class': 'modicon', 'src': this.modIcon }); } if (icon && window.ChatHacksNoStar !== true) { vd.chatUL .children() .last() .children('.username') .append(' ', icon); } }, handlePing: function(msg) { if ( !window.mainRoom.isInitialized || msg.get('name') === config.wgUserName || msg.get('isInlineAlert') ) { return; } var text = msg.get('text').toLowerCase(); if ( this.$pings .val() .trim() .split('\n') .some(function(ping) { var p = ping.trim().toLowerCase(); return p && text.indexOf(p) !== -1; }) ) { if (!this.hasFocus) { if (window.ChatHacksPingSound !== false) { this.$sound.html( $('<audio>', { autoplay: true, src: this.pingSound }) ); } if (!this.dinged) { this.dinged = true; this.titleorig = document.title; this.ding = setInterval( $.proxy(this.flashTitle, this), 500 ); } } this.vd.scrollToBottom(); this.vd.chatUL .children() .last() .children('.message') .addClass('ping'); } }, iconPing: function(msg) { this.handleIcon(msg); this.handlePing(msg); }, setAway: function() { this.inlineAlert(ChatHacks.i18n.msg('away').escape()); window.mainRoom.socket.send(new window.models.SetStatusCommand({ statusState: window.STATUS_STATE_AWAY, statusMessage: }).xport()); }, setBack: function() { /** * If we have sent this command (but just haven't finished coming * back yet), don't keep spamming the server with this command */ if (this.comingBackFromAway) { return; } this.comingBackFromAway = true; this.inlineAlert(ChatHacks.i18n.msg('back').escape()); window.mainRoom.socket.send(new window.models.SetStatusCommand({ statusState: window.STATUS_STATE_PRESENT, statusMessage: }).xport()); }, sendMessage: function(event) { if (!this.active) { return true; } if (event.which !== 13 || event.shiftKey) { return false; } event.preventDefault(); window.mainRoom.resetActivityTimer(); var $input = this.viewDiscussion.getTextInput(), send = ChatHacks.preparse($input.val().trim()), value = $input.val().trim(); if (value && send && value.length <= this.maxCharacterLimit) { var entry = new window.models.ChatEntry({ name: config.wgUserName, text: value }); if (this.isMain()) { this.socket.send(entry.xport()); } else { if ( this.afterInitQueue.length < 1 || this.model.users.length < 2 ) { this.mainController.socket.send( this.model.privateRoom.xport() ); } if (this.isInitialized) { this.socket.send(entry.xport()); } else { this.afterInitQueue.push(entry.xport()); // temp chat entry in case of slow connection time entry.set({ avatarSrc: config.wgChatMyAvatarUrl, temp: true }); this.model.chats.add(entry); } } } $input.val().focus(); $('body').removeClass('warn limit-near limit-reached'); }, inlineAlert: function(text) { text.split('\n').forEach(function(line) { window.mainRoom.model.chats.add( new window.models.InlineAlert({ text: line }) ); }); window.mainRoom.viewDiscussion.scrollToBottom(); }, flashTitle: function() { if (document.title === this.titleorig) { document.title = this.i18n.msg( 'activity', config.wgSiteName ).plain(); } else if (this.titleorig) { document.title = this.titleorig; } }, preparse: function(input) { var commands = this.commands, com = input.slice(1) .trim() .replace(/\s+/g, ' ') .split(' '), ref = com.shift(); if (input.charAt(0) === '/' && ref.length > 0) { while (typeof commands[ref] === 'string') { ref = commands[ref]; } if ( typeof commands[ref] === 'object' && // /me does not have a handler typeof commands[ref].handler === 'function' ) { var param = com.join(' '); if (commands[ref].user && !param.trim()) { this.inlineAlert(this.i18n.msg( 'erruser', input.split(' ')[0] ).escape()); return false; } var ret = commands[ref].handler.call(this, param); if (typeof ret === 'string') { $('#Write [name="message"]').val(ret); return true; } return ret; } } return true; }, baseMod: function(user, action) { $.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) { this.inlineAlert(this.i18n.msg.apply( this.i18n, this.getModMsg(result, action, user) ).escape()); }, this ) ); }, this)); }, getModMsg: function(result, action, user) { if (action === 'remove') { if (result.userrights.removed[0] === 'chatmoderator') { return ['demodded', user]; } return ['notmod', result.userrights.user]; } else if (result.userrights.added[0] === 'chatmoderator') { return ['modded', user]; } return ['alreadymod', result.userrights.user]; }, commands: { // Contains data about the /me command 'me': { msg: true }, 'away': 'afk', 'afk': { handler: function() { // If you're away, hitting enter has already sent you back if (!$('#ChatHeader .User').hasClass('away')) { this.toggleAway(); } } }, // Clear the active chat window 'clear': { handler: function() { this.clearWindow(); } }, // Nobody cares 'nc': { msg: true, handler: function(com) { return '[[' + this.i18n.msg('uncyc').plain() + '|' + (com || this.i18n.msg('nobodycares').plain()) + ']]'; } }, // IRCpwnt 'devoice': { handler: function(com) { return '* ChanServ set channel mode -v ' + (com || config.wgUserName); } }, // Too young 'coppa': { handler: function(com) { return 'http://en-wp.org/wiki/COPPA ' + (com || this.i18n.msg('coppa').plain()); } }, // Idle 'silence': function() { return 'People idle, enjoy the silence. ' + 'https://youtu.be/diT3FvDHMyo'; }, // ¯\_(ツ)_/¯ 'shrug': { handler: function(com) { return (com || ) + ' ¯\\_(ツ)_/¯'; } }, // Kick a user 'kick': { user: true, handler: function(com) { window.mainRoom.kick({ name: com }); } }, 'kickban': 'ban', 'kb': 'ban', // Ban a user 'ban': { user: true, handler: function(com) { window.mainRoom.socket.send(new window.models.BanCommand({ userToBan: com, // 1 day is enough, idk, no time specified time: '36400', // TODO: i18n reason: 'Misbehaving in chat' }).xport()); } }, // Unban a user 'unban': { user: true, handler: function(com) { window.mainRoom.socket.send(new window.models.BanCommand({ // Empty ban command === unban userToBan: com }).xport()); } }, // Make a user a mod 'mod': { handler: function(com) { this.baseMod(com, 'add'); } }, // Remove a user's mod right 'demod': { user: true, handler: function(com) { this.baseMod(com, 'remove'); } }, // Block a user from private chatting you 'block': { user: true, handler: function(com) { window.mainRoom.blockPrivate({name: com}); } }, // Unblock a user from private chatting you 'unblock': { user: true, handler: function(com) { window.mainRoom.allowPrivate({name: com}); } }, 'chat': 'private', 'room': 'private', // Invoke a private room 'private': { user: true, handler: function(com) { var users = com.replace(/\s*,\s*/g, ',').split(','), curRoom = window.mainRoom.model.privateUsers .findByName(users[0]); if (curRoom) { window.mainRoom.showRoom(curRoom.attributes.roomId); } else { window.mainRoom.openPrivateChat(users); } } }, 'roomid': 'id', 'id': { handler: function() { this.inlineAlert( this.i18n.msg('id', window.mainRoom.roomId).escape() ); } }, // Send a message to yourself 'self': { handler: function(com) { var ar = window.mainRoom.activeRoom, room = ar === null ? window.mainRoom : window.mainRoom.chats.privates[ar]; room.model.chats.add(new window.models.ChatEntry({ name: config.wgUserName, text: this.i18n.msg('self').plain() + ' ' + com, avatarSrc: config.wgChatMyAvatarUrl })); this.viewDiscussion.scrollToBottom(); } }, 'help': { handler: function(com) { if (com) { var ref = com; while (typeof this.commands[ref] === 'string') { ref = this.commands[ref]; } if (this.i18n.msg('help-' + ref).exists) { var cmd = this.commands[ref], example = '/' + ref; if (cmd.msg) { example += ' ' + this.i18n.msg( 'help-' + ref + '-example' ).plain(); } else if (cmd.user) { example += ' ' + this.i18n.msg('exampleuser').plain(); } this.inlineAlert( this.i18n.msg( 'help', ref, this.i18n.msg('help-' + ref).plain() ).parse() + '\n' + this.i18n.msg('example').escape() + ': ' + $('', { 'class': 'chathacks-example', 'text': example }).prop('outerHTML') ); window.mainRoom.viewDiscussion.chatUL .children('li') .last() .children('span.chathacks-example') .click(this.exampleClick); } else { this.inlineAlert( this.i18n.msg('nohelp', ref).escape() ); } } else { var str = []; for (var i in this.commands) { if (typeof this.commands[i] === 'object') { str.push(i); } } this.inlineAlert( this.i18n.msg('commands', str.join(', ')).escape() ); } } } }, focus: function() { if (this.ding) { clearInterval(this.ding); this.ding = 0; } if (this.titleorig) { document.title = this.titleorig; } this.hasFocus = true; this.dinged = false; }, blur: function() { this.hasFocus = false; }, toggleAway: function(msg) { if ($('#ChatHeader .User').hasClass('away')) { window.mainRoom.setBack(); } else { window.mainRoom.setAway(msg || ); } }, clearWindow: function() { this.vd.chatUL.empty(); window.mainRoom.inlineAlert(this.i18n.msg('cleared').escape()); this.vd.chatUL.find( '#entry-' + window.mainRoom.model.chats.models.slice(-1)[0].cid ).removeClass('continued'); }, openPings: function() { this.$pings.removeClass('hidden'); }, closePings: function() { this.$pings.addClass('hidden'); $.storage.set('pingphrases', $('#pings').val().split('\n'), { expires: 99999, path: '/' }); }, initVars: function() { this.hasFocus = document.hasFocus(); this.dinged = false; this.ding = 0; if (document.title) { this.titleorig = document.title; } this.vd = window.mainRoom.viewDiscussion; }, initBinding: function() { window.mainRoom.model.chats.bind( 'afteradd', $.proxy(this.iconPing, this) ); window.NodeChatController.prototype.setAway = this.setAway; window.NodeChatController.prototype.setBack = this.setBack; window.NodeChatController.prototype.sendMessage = this.sendMessage; window.NodeChatController.prototype.inlineAlert = this.inlineAlert; this.vd.unbind('sendMessage'); this.vd.bind( 'sendMessage', $.proxy(window.mainRoom.sendMessage, window.mainRoom) ); }, initExamples: function() { mw.util.addCSS( '.inline-alert span.chathacks-example {' + 'color: ' + config.wgSassParams['color-links'] + ';' + '}' ); }, exampleClick: function() { window.mainRoom.viewDiscussion .getTextInput() .val($(this).text()); }, initButtons: function() { this.buttons = { toggleAway: new window.dev.chat.Button({ name: 'ChatHacks AFK', attr: { click: $.proxy(this.toggleAway, this), text: this.i18n.msg('afk').plain() } }), clearWindow: new window.dev.chat.Button({ name: 'ChatHacks clear', attr: { click: $.proxy(this.clearWindow, this), text: this.i18n.msg('clear').plain() } }), pingPhrases: new window.dev.chat.Button({ name: 'ChatHacks ping phrases', attr: { id: 'pingspan', text: this.i18n.msg('pingphrases').plain(), append: [ $('<textarea>', { 'id': 'pings', 'class': 'hidden', 'text': $.storage.get('pingphrases') ? $.storage.get('pingphrases').join('\n') : config.wgUserName }) ] } }) }; }, initPings: function() { this.$pings = $('#pings'); $('#pingspan') .on('mouseover', $.proxy(this.openPings, this)) .on('mouseout', $.proxy(this.closePings, this)); }, initialized: function() { this.initVars(); this.initBinding(); this.initExamples(); this.initButtons(); this.initPings(); window.mainRoom.inlineAlert(this.i18n.msg('init').parse()); mw.hook('chathacks.loaded').fire(this); }, initImports: function() { importArticles( { type: 'script', articles: [ 'u:dev:MediaWiki:Chat-js.js', 'u:dev:MediaWiki:I18n-js/code.js' ] }, { type: 'style', articles: ['u:dev:MediaWiki:ChatHacks.css'] } ); }, initWindow: function() { $(window) .unbind('mousemove') .unbind('focus') .unbind('keypress') .bind('focus', $.proxy(this.focus, this)) .bind('blur', $.proxy(this.blur, this)); }, initSound: function() { this.$sound = $('', { id: 'sound' }).appendTo(document.body); }, initPreload: function() { mw.hook('dev.i18n').add($.proxy(this.preloadI18n, this)); mw.hook('dev.chat.render').add($.proxy(this.preload, this)); }, preloadI18n: function(i18n) { i18n.loadMessages('ChatHacks').then( $.proxy(this.preloadedI18n, this) ); }, preloadedI18n: function(i18n) { this.i18n = i18n; this.preload(); }, preload: function() { if (++this._loaded === 2) { this.initialized(); } }, initChat: function() { this.initImports(); this.initWindow(); this.initSound(); this.initPreload(); mw.hook('chathacks.commands').fire(this.commands); }, chatCheck: function(e) { if ( typeof e === 'object' && Object.prototype.hasOwnProperty.call(e, 'preventDefault') ) { e.preventDefault(); } $(document.body) .find('.WikiaChatLink, .start-a-chat-button') .each($.proxy(this.convertChatLink, this)); }, convertChatLink: function(_, el) { $(el) .removeClass('WikiaChatLink start-a-chat-button') .removeAttr('href') .click($.proxy(this.openChatWindow, this)); }, openChatWindow: function() { this.chatwindow = window.open( mw.util.getUrl('Special:Chat'), 'chat' ); this.chatwindow.onload = $.proxy(this.onChatWindowLoad, this); }, onChatWindowLoad: function() { this.chatwindow.importArticles({ type: 'script', articles: [ 'u:c:User:' + config.wgUserName + '/global.js', 'User:' + config.wgUserName + '/wikia.js' ] }); }, initNotChat: function() { var check = $.proxy(this.chatCheck, this); $(document.body).on( 'click', 'a[href^="' + mw.util.getUrl('Special:Chat') + '"]', check ); mw.hook('wikipage.content').add(check); $('#WikiaRail').on('afterLoad.rail', check); mw.hook('chathacks.loaded').fire(this); } }; window.ChatHacks = ChatHacks; if (config.wgCanonicalSpecialPageName === 'Chat') { ChatHacks.initChat(); } else { ChatHacks.initNotChat(); }
})(mediaWiki);