Jump to content

User:Tanhamman/ChatHacks2

From SpongeBob Wiki

/*

* 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);