Advertisement
Cpt_mathix

MyAnimeList - Ignore User

May 6th, 2016
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name           Ignore_MAL_User
  3. // @namespace      Ignore_MAL_User
  4. // @description    Allows a user to blacklist other users so that their posts are automatically collapsed.
  5. // @include        *://myanimelist.net/forum/*
  6. // @require        https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
  7. // @version        1.0.8
  8. // @grant GM_listValues
  9. // @grant GM_deleteValue
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // ==/UserScript==
  13.  
  14. //Blacklist is an object that holds the usernames of all blocked users
  15. function blacklist() {
  16.     //Blacklist is loaded from persistent data store.
  17.     this.list = [];
  18.     this.list = GM_listValues().map(GM_getValue);
  19.  
  20.     //Blacklist from the built-in ignore feature
  21.     this.MALList = [];
  22.  
  23.     //Get the number of ignored usernames for later use.
  24.     this.numSettings = this.list.length;
  25. }
  26.  
  27. //The add method will add a user to the blacklist object and set it as script specific persistent data.
  28. blacklist.prototype.add = function (userID, username) {
  29.     //Add the value to the persistent data.
  30.     GM_setValue(userID, username);
  31.  
  32.     //Update the list to reflect the added username
  33.     this.list = [];
  34.     this.list = GM_listValues().map(GM_getValue);
  35.  
  36.     return true;
  37. };
  38.  
  39. //is returns true if the userID has this username or false otherwise
  40. blacklist.prototype.is = function (userID, username) {
  41.     if (GM_getValue(userID, false) === false) {
  42.         return false;
  43.     }
  44.     else if (GM_getValue(userID) === username) {
  45.         return true;
  46.     }
  47.     return false;
  48. };
  49.  
  50. //The rem function removes a user from the blacklist.
  51. blacklist.prototype.rem = function (username) {
  52.     GM_deleteValue(username);
  53.  
  54.     //Reload blacklist's list to update it after an item is removed.
  55.     this.list = [];
  56.     this.list = GM_listValues().map(GM_getValue);
  57. };
  58.  
  59. //The is_in method checks if a user has been blacklisted
  60. blacklist.prototype.is_in = function (username) {
  61.     //Check if we have a username or a userID
  62.     if (parseInt(username, 10) == username) {
  63.         if (GM_getValue(username, false) !== false) {
  64.             return true;
  65.         }
  66.     }
  67.     else {
  68.         //Go through the list and compare for username, if it's not found return false.
  69.         for (var i = 0; i < this.list.length; i++) {
  70.             if (this.list[i] == username) {
  71.                 return true;
  72.             }
  73.         }
  74.         //Go through the MALlist and compare for username, if it's not found return false.
  75.         for (var j = 0; j < this.MALList.length; j++) {
  76.             if (this.MALList[j] == username) {
  77.                 this.MALList.splice(j, 1);
  78.                 return true;
  79.             }
  80.         }
  81.     }
  82.  
  83.     //If not found by the above methods, the user is not in the blacklist.
  84.     return false;
  85. };
  86.  
  87. /*** START USER POST OBJECT ***/
  88. //The user_post object has a name, a userID (usually), and various methods for expanding or collapsing posts and is created given the jquery object of the post.
  89. function user_post(ele) {
  90.     var postParent = ele.parent().parent();
  91.     this.ele = ele;
  92.     this.msgId = ele.attr('id').match(/\d+/);
  93.     this.forumMsg = $('#forumMsg' + this.msgId);
  94.     this.userPost = this.ele;
  95.     this.postActions = ele.siblings('div.postActions');
  96.     this.sig = ele.siblings('div.sig');
  97.     this.userInfo = postParent.prev();
  98.     //The useravatar may not exist, if it doesn't set the id to false.
  99.     this.userID = this.userInfo.find('img[src^="//cdn.myanimelist.net/images/useravatars/"]');
  100.     if (this.userID.length <= 0) {
  101.         this.userID = false;
  102.     }
  103.     //Otherwise get the ID from the image URL
  104.     else {
  105.         this.userID = this.userID.attr('src').substring(46, this.userID.attr('src').lastIndexOf('.'));
  106.     }
  107.     this.username = this.userInfo.find('a[href^="/profile/"]').text();
  108.  
  109.     //Flag that tells whether the post is ignored or not
  110.     this.ignoring = false;
  111.     //A post is locked when the user is ignored by the built-in ignore feature
  112.     this.locked = this.forumMsg.hasClass('hide-message');
  113.  
  114.     //If locked, add user to MALList
  115.     if (this.locked)
  116.         blackList.MALList.push(this.username);
  117.  
  118.     //Fix up the dom a bit.
  119.     var tempUserInfo = this.userInfo.html();
  120.     tempUserInfo = '<div class="user_info_block">' + tempUserInfo  + '</div>';
  121.     this.userInfo.html(tempUserInfo);
  122.  
  123.     /*** Adding display elements ***/
  124.     //For moderators and admins, make their rank bold and red.
  125.     var infoHTML = '<span style="display:none;" class="userInfo"><a href="/profile/' + this.username +
  126.         '"><strong>' + this.username + '</strong></a><br>';
  127.  
  128.     //Add display elements depending on rank
  129.     if (this.userInfo.filter(':contains("Forum Moderator")').length > 0) {
  130.         infoHTML = infoHTML + '<span style="color:red; font-weight:bold;">Forum Moderator</span><br>';
  131.     }
  132.     else if (this.userInfo.filter(':contains("Site Administrator")').length > 0) {
  133.         infoHTML = infoHTML + '<span style="color:red; font-weight:bold;">Site Administrator</span>';
  134.     }
  135.     else if (this.userInfo.filter(':contains("Anime Moderator")').length > 0) {
  136.         infoHTML = infoHTML + '<span style="color:red; font-weight:bold;">Anime Moderator</span><br>';
  137.     }
  138.     else if (this.userInfo.filter(':contains("Manga Moderator")').length > 0) {
  139.         infoHTML = infoHTML + '<span style="color:red; font-weight:bold;">Manga Moderator</span><br>';
  140.     }
  141.     else if (this.userInfo.filter(':contains("DB Administrator")').length > 0) {
  142.         infoHTML = infoHTML + '<span style="color:red; font-weight:bold;">DB Administrator</span>';
  143.     }
  144.  
  145.     //If online, add an online note, otherwise say offline
  146.     if (this.userInfo.filter(':contains("Online")').length > 0) {
  147.         infoHTML = infoHTML + '<span style="color:green;">Online</span></span>';
  148.     }
  149.     else  {
  150.         infoHTML = infoHTML + '<br>Offline</span>';
  151.     }
  152.     this.userInfo.children('div').after(infoHTML);
  153.  
  154.     //Set the ignore user link
  155.     if (!this.locked)
  156.         this.postActions.children('div').prepend('<a class="ign_user_post_lnk" href="javascript:void(0);">Ignore User</a> -');
  157.     else
  158.         this.postActions.children('div').prepend('<a class="forum_settings_lnk" href="/editprofile.php?go=forumoptions">Unignore User</a> - ');
  159.  
  160. }
  161.  
  162. //Returns whether the user should be ignored or not.
  163. user_post.prototype.to_ignore = function () {
  164.     //If we don't have a userID for the user, check with their username.
  165.     if (this.userID === false) {
  166.         //Check if the username is in the blacklist, if they are, they need to be ignored.
  167.         if (blackList.is_in(this.username)) {
  168.             return true;
  169.         }
  170.     }
  171.     //Otherwise get the username substring from the element.
  172.     else {
  173.         //Ignore the user if blacklisted.
  174.         if (blackList.is_in(this.userID)) {
  175.             return true;
  176.         }
  177.     }
  178.     return false;
  179. };
  180.  
  181. //Returns mod warning message.
  182. user_post.prototype.mod_warn = function () {
  183.     //The warning that a user should be given when attempting to blacklist an admin/forum mod
  184.     return  'Warning! This user is a site admin or moderator. You are free to ignore this user, ' +
  185.         'however, remember that moderators or admins will occasionally post warnings. If ' +
  186.         'such a warning is posted and you fail to adhere to it your account could be banned ' +
  187.         'temporarily or permanently from all MAL services. Are you still sure you want to ignore this user?';  
  188. };
  189.  
  190. //Gives the user a message if they are trying to ignore a mod.
  191. //Returns true if the username should still be ignored and false otherwise.
  192. user_post.prototype.check_mod = function () {
  193.     //Check for administrator/forum moderator ranks in the userinfo section and return a warning.
  194.     if (this.userInfo.filter(':contains("Forum Moderator")').length > 0 || this.userInfo.filter(':contains("Administrator")').length > 0) {
  195.         return confirm(this.mod_warn());
  196.     }
  197.     //If it is not a mod, return false.
  198.     return true;
  199. };
  200.  
  201. //Adds the appropriate onclick function to the ignore user or expand/collapse link below each post.
  202. user_post.prototype.add_link_event = function () {
  203.     //Get the username of the current post so it can be passed to the event handling funciton
  204.     var username = this.username;
  205.     var userID = this.userID;
  206.     var thisObj = this;
  207.  
  208.     //We are adding the whole ignore user event.
  209.     this.postActions.find('a.ign_user_post_lnk').bind('click', function () {
  210.         //If the userID doesn't exist, set the key to the username.
  211.         if (userID === false) {
  212.             userID = username;
  213.         }
  214.  
  215.         //If already ignored (Determined by blacklist state)... then unignore them!
  216.         if (thisObj.to_ignore() === true) {
  217.             //We're unignoring, update the links. Make sure to unignore all possible variations.
  218.             blackList.rem(userID);
  219.             blackList.rem(username);
  220.             objs.toggle_user(username, true);
  221.         }
  222.         //Otherwise ignore them...
  223.         else {
  224.             //Check if the user is a moderator, if so...
  225.             if (thisObj.check_mod()) {
  226.                 //If blacklisted successfully... toggle the user posts
  227.                 if (blackList.add(userID, username)) {
  228.                     objs.toggle_user(username, false);
  229.                 }
  230.             }
  231.         }
  232.     });
  233. };
  234.  
  235. //binds or unbinds the click event to toggle post visibility
  236. user_post.prototype.add_click_event = function(add) {
  237.     if (add) {
  238.         this.forumMsg.find('.forum_category').on('click', function() {
  239.             $(this).next().slideToggle(300);
  240.         });
  241.     } else {
  242.         this.forumMsg.find('.forum_category').off('click');
  243.     }
  244. };
  245.  
  246. //Makes a post visible or invisible.
  247. user_post.prototype.toggle_vis = function () {
  248.     if (this.forumMsg.hasClass('hide-message')) {
  249.         this.forumMsg.removeClass('hide-message');
  250.         this.forumMsg.find('.forum-topic-message-wrapper').slideDown(300);
  251.  
  252.         //If we are unignoring the user... update the links
  253.         if (this.ignoring) {
  254.             this.postActions.find('a.ign_user_post_lnk').text('Ignore User');
  255.         }
  256.     } else {
  257.         this.forumMsg.addClass('hide-message');
  258.         this.forumMsg.find('.forum-topic-message-wrapper').slideUp(300);
  259.  
  260.         //Update the links
  261.         this.postActions.find('a.ign_user_post_lnk').text('Unignore User');
  262.     }
  263. };
  264.  
  265. //Checks if the user has changed their nick. If they have, it checks if the new nick is already ignored. If not, it blacklists the new nick.
  266. user_post.prototype.check_new_nick = function () {
  267.     var pass_userID;
  268.     if (parseInt(this.userID, 10) != this.userID) {
  269.         pass_userID = this.username;
  270.     }
  271.     else {
  272.         pass_userID = this.userID;
  273.     }
  274.  
  275.     if (!blackList.is(pass_userID, this.username) && (blackList.is_in(this.userID))) {
  276.         //Blacklist the new nick
  277.         blackList.add(pass_userID, this.username);
  278.     }
  279. };
  280.  
  281. /*** END USER POST OBJECT ***/
  282.  
  283. /*** START USER QUOTE OBJECT ***/
  284. //This object is for quotes and has to rely on usernames.
  285. function user_quote(ele) {
  286.     this.quote = ele;
  287.  
  288.     //Get the username from the quote
  289.     this.username = this.quote.children('strong:first').text();
  290.     //There are various cases due to scripts used for quotes that we will want to cover:
  291.     if (this.username.indexOf('[') > this.username.indexOf(' ')) {
  292.         this.username = this.username.substring(0, this.username.indexOf('['));
  293.     }
  294.     else {
  295.         this.username = this.username.substring(0, this.username.indexOf(' '));
  296.     }
  297.  
  298.     //Flag to tell whether a comment is ignored or not.
  299.     this.vis = true;
  300.  
  301.     //Add a link to the quote for expanding/collapsing
  302.     this.quote.after('<br style="display:none;" class="ign_user_quote"/><a class="ign_user_quote_lnk" href="javascript:void(0);"></a><br style="display:none;" class="ign_user_quote"/>');
  303. }
  304.  
  305. //Checks if the quote user should be ignored or not
  306. user_quote.prototype.to_ignore = function () {
  307.     if (blackList.is_in(this.username)) {
  308.         return true;
  309.     }
  310.     return false;
  311. };
  312.  
  313. //Toggles visibility of quotes
  314. user_quote.prototype.toggle_vis = function () {
  315.     if (this.vis === false) {
  316.         this.quote.attr('style', 'display:block;');
  317.  
  318.         //Add the collapse link
  319.         this.quote.next().next().filter('a.ign_user_quote_lnk').text('Collapse ' + this.username + '\'s quote');
  320.  
  321.         //If we are unignoring the user... update the links.
  322.         if (!this.to_ignore()) {
  323.             this.quote.next().filter('.ign_user_quote').attr('style', 'display:none;');
  324.             this.quote.next().next().filter('a.ign_user_quote_lnk').text('');
  325.             this.quote.next().next().next().filter('.ign_user_quote').attr('style', 'display:none;');
  326.         }
  327.  
  328.         //Update the visibility flag
  329.         this.vis = true;
  330.     }
  331.     else {
  332.         //Make sure the contents are encapsulated before hiding them.
  333.         this.quote.attr('style', 'display:none;');
  334.  
  335.         //Change the text of the expand link.
  336.         this.quote.next().next().filter('a.ign_user_quote_lnk').text('Expand ' + this.username + '\'s quote.');
  337.         this.quote.next().attr('style', 'display:inline;');
  338.         this.quote.next().next().next().attr('style', 'display:inline;');
  339.  
  340.         //Update the visibility flag
  341.         this.vis = false;
  342.     }
  343. };
  344.  
  345. //Adds the events to the collapse/expand link for ignored quotes.
  346. user_quote.prototype.add_link_event = function () {
  347.     var thisObj = this;
  348.     this.quote.next().next().filter('a.ign_user_quote_lnk').bind('click', function () {
  349.         thisObj.toggle_vis();
  350.     });
  351. };
  352. /*** END USER QUOTE OBJECT ***/
  353.  
  354. /*** START USER OBJECTS OBJECT ***/
  355. //The object is a list of the user_post and user_quote objects.
  356. function user_objects() {
  357.     this.posts = [];
  358.     this.quotes = [];
  359.  
  360.     //An internal pointer that starts just before the first array index.
  361.     this.pointer = -1;
  362. }
  363.  
  364. //Adds an object to the list
  365. user_objects.prototype.add = function (obj) {
  366.     //If it's a post object, add it to the post list, otherwise add it to the quote list.
  367.     if (typeof(obj.quote) == 'undefined') {
  368.         this.posts[this.posts.length] = obj;
  369.     }
  370.     else {
  371.         this.quotes[this.quotes.length] = obj;
  372.     }
  373. };
  374.  
  375. //Loops through posts and quotes and collapses all authored by the given username.
  376. user_objects.prototype.toggle_user = function (username, unignoring) {
  377.     //Find each post and quote from that user and toggle the visibility.
  378.     for (var i = 0; i < this.posts.length || i < this.quotes.length; i++) {
  379.         if (i < this.posts.length) {
  380.             var forumMessage = this.posts[i];
  381.             if (forumMessage.username === username && !forumMessage.locked) {
  382.                 //Flag the post as being ignored
  383.                 forumMessage.ignoring = true;
  384.  
  385.                 //Toggle the post only if it isn't in the state that we want it to be in.
  386.                 if (forumMessage.vis !== unignoring) {
  387.                     //Add visibility click event or remove it
  388.                     forumMessage.add_click_event(!unignoring);
  389.  
  390.                     //Add or remove classes for visibility control
  391.                     forumMessage.forumMsg.toggleClass('forum-topic-message-ignored-user');
  392.  
  393.                     //Toggle visibility of the post
  394.                     forumMessage.toggle_vis();
  395.                 }
  396.  
  397.                 //Flag the post as not being ignored.
  398.                 forumMessage.ignoring = false;
  399.             }
  400.         }
  401.         if (i < this.quotes.length && this.quotes[i].username === username) {
  402.             if (this.quotes[i].vis !== unignoring) {
  403.                 this.quotes[i].toggle_vis();
  404.             }
  405.             //Remove the 'collapse post' link on any posts that were expanded previous to unignoring the user.
  406.             else if (this.quotes[i].quote.next().next().text().length > 0) {
  407.                 //Remove expand/collapse link text
  408.                 this.quotes[i].quote.next().next().text('');
  409.                 //Remove first break line
  410.                 this.quotes[i].quote.next().attr('style', 'display:none;');
  411.                 //Remove final break line
  412.                 this.quotes[i].quote.next().next().next().attr('style', 'display:none;');
  413.             }
  414.         }
  415.     }
  416. };
  417.  
  418. //Advances the pointer by one and returns true, if there are no more objects in the list it returns false
  419. user_objects.prototype.next = function () {
  420.     this.pointer++;
  421.     if (this.pointer >= this.posts.length && this.pointer >= this.quotes.length) {
  422.         //Reset the pointer and return false
  423.         this.pointer = -1;
  424.         return false;
  425.     }
  426.     else {
  427.         return true;
  428.     }
  429. };
  430.  
  431. //Gets the post object at the current pointer position.
  432. user_objects.prototype.currObj = function (isPost) {
  433.     if (isPost === true && typeof(this.posts[this.pointer]) !== 'undefined') {
  434.         return this.posts[this.pointer];
  435.     }
  436.     else if (isPost === false && typeof(this.quotes[this.pointer]) !== 'undefined') {  
  437.         return this.quotes[this.pointer];
  438.     }
  439.     else {
  440.         //Return false if the object does not exist.
  441.         return false;
  442.     }
  443. };
  444. /*** END USER OBJECTS OBJECT ***/
  445.  
  446. //This function adds the links that allow you to ignore or unignore a user
  447. function ign_main() {
  448.     //Add an ignore user link to each post and ignore posts of blacklisted users.
  449.     $('div.clearfix div.clearfix[id^="message"]').each(function () {
  450.         var currPost = new user_post($(this));
  451.  
  452.         //Add the post to the objects list.
  453.         objs.add(currPost);
  454.  
  455.         //Check if this username is new or not
  456.         currPost.check_new_nick();
  457.  
  458.         //Check for quotes in the post that are from ignored users.
  459.         currPost.userPost.find('div.quotetext').each(function () {
  460.             //Create the quote object
  461.             var currQuote = new user_quote($(this));
  462.  
  463.             //Add the quote to the user_objects() object
  464.             objs.add(currQuote);
  465.         });
  466.     });
  467.  
  468.     //Traverse the user_objects post list and ignore the blacklisted users.
  469.     while (objs.next()) {
  470.         //Get the objects
  471.         var currQuoteObj = objs.currObj(false);
  472.         var currPostObj = objs.currObj(true);
  473.  
  474.         if (currPostObj !== false) {
  475.             //If the user is blacklisted, collapse their posts.
  476.             if (currPostObj.vis === true && currPostObj.to_ignore()) {
  477.                 objs.toggle_user(currPostObj.username, false);
  478.             }
  479.  
  480.             //Add the link event to the current post's link.
  481.             currPostObj.add_link_event();
  482.         }
  483.         if (currQuoteObj !== false) {
  484.             //If the user is blacklisted, collapse their quotes.
  485.             if (currQuoteObj.vis === true && currQuoteObj.to_ignore()) {
  486.                 objs.toggle_user(currQuoteObj.username, false);
  487.             }
  488.  
  489.             //Add expand/collapse quote events.
  490.             currQuoteObj.add_link_event();
  491.         }
  492.     }
  493.     //Add the control panel link for the script.
  494. }
  495.  
  496. //Opens a control panel and lists the ignored users. A user can then remove ignores or settings here.
  497. function open_CP() {
  498.     return false;
  499. }
  500.  
  501. //Blacklist and user_objects are global objects.
  502. var blackList = new blacklist();
  503. var objs = new user_objects();
  504.  
  505. //Alter the interface to reflect the user's blacklists. Greasemonkey will wait for the DOM for us, jquery seems compelled to wait for images, so a straight function call will do.
  506. //$('td.forum_boardrow1:last div:last').ready(ign_main);
  507. ign_main();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement