Advertisement
ShaggyZE1

Unlimited MAL Iignore List

Feb 1st, 2023
645
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Unlimited MAL Ignore list
  3. // @namespace    http://tampermonkey.net/
  4. // @version      0.81
  5. // @description  Ignore an unlimited amount of users. Comes with custom settings: delete the entire post, replace the content of the message with a custom message, replace or delete the avatar, keep or delete the signature.
  6. // @author       Only_Brad
  7. // @match        https://myanimelist.net/*
  8. // @run-at document-end
  9. // ==/UserScript==
  10.  
  11. (function() {
  12.     const POSTS_URL = "forum/?topicid";
  13.     const TOPICS_URL = "forum/?board";
  14.     const TOPICS_SEARCH_URL = "forum/search?";
  15.     const CLUB_TOPICS_URL_1 = "clubs.php";
  16.     const CLUB_TOPICS_URL_2 = "forum/?clubid";
  17.     const PROFILE_URL = "/profile";
  18.     const COMTOCOM_URL = "comtocom.php";
  19.     const COMMENTS_URL = "comments.php";
  20.     const BLACKLIST_URL = "https://myanimelist.net/blacklist";
  21.  
  22.     const BLACKLIST_KEY = "ignore-list";
  23.     const SETTINGS_KEY = "ignore-list-settings";
  24.  
  25.     const YOU_SELECTOR = ".header-profile-link";
  26.     const POST_USERS_SELECTOR = ".profile";
  27.     const TOPIC_USERS_SELECTOR = ".forum_postusername a";
  28.     const MESSAGE_SELECTOR = ".content [id^=message]";
  29.     const AVATAR_SELECTOR = ".forum-icon";
  30.     const USER_PROFILE_SELECTOR = "[href^='/profile']";
  31.     const USER_INFO_SELECTOR = "[id^=messageuser]";
  32.     const SIGNATURE_SELECTOR = ".sig";
  33.     const FORUM_MESSAGE_SELECTOR = "[id^=msg]";
  34.     const FORUM_MSG_NAME_SELECTOR = ".username a";
  35.     const FORUM_ACTION_BAR_SELECTOR = "[id^=postEditButtons]";
  36.     const PROFILE_MSG_SELECTOR = "[id^=comBox]";
  37.     const PROFILE_MSG_NAME_SELECTOR = ".text a.fw-b";
  38.     const PROFILE_MSG_AVATAR_SELECTOR = ".image";
  39.     const PROFILE_MSG_TEXT_SELECTOR = ".text .comment-text";
  40.     const PROFILE_MSG_ACTION_BAR_SELECTOR = ".text > div.pb8 > a";
  41.     const COMTOCOM_SELECTOR = "[id^=comBox]";
  42.     const COMTOCOM_NAME_SELECTOR = ".dark_text a";
  43.     const COMTOCOM_AVATAR_SELECTOR = ".picSurround a";
  44.     const COMTOCOM_TEXT_SELECTOR = "[id^=comtext]";
  45.     const COMTOCOM_ACTION_BAR_SELECTOR = ".dark_text a"
  46.  
  47.     const IGNORE = 0;
  48.     const REPLACE = 1;
  49.     const DO_NOTHING = 2;
  50.  
  51.     let blacklist;
  52.     let settings;
  53.  
  54.     //routing
  55.     if (window.location.href.includes(POSTS_URL)) {
  56.         handlePosts();
  57.     } else if (
  58.         window.location.href.includes(TOPICS_URL) ||
  59.         window.location.href.includes(TOPICS_SEARCH_URL) ||
  60.         window.location.href.includes(CLUB_TOPICS_URL_1) ||
  61.         window.location.href.includes(CLUB_TOPICS_URL_2)
  62.     ) {
  63.         handleTopics();
  64.     } else if (window.location.href.includes(PROFILE_URL)) {
  65.         handleProfileMsgs();
  66.     } else if (window.location.href.includes(COMTOCOM_URL)) {
  67.         handleComToCom();
  68.     } else if (window.location.href.includes(COMMENTS_URL)) {
  69.         handleComToCom();
  70.     } else if (window.location.href === BLACKLIST_URL) {
  71.         handleBlacklist();
  72.     }
  73.  
  74.     //GM_addStyle equivalent that works on firefox
  75.     function addStyle(css) {
  76.         const style = document.getElementById("addStyleBy8626") || (function() {
  77.             const style = document.createElement('style');
  78.             style.type = 'text/css';
  79.             style.id = "addStyleBy8626";
  80.             document.head.appendChild(style);
  81.             return style;
  82.         })();
  83.         style.innerHTML += css;
  84.     }
  85.  
  86.     //helper functions to load from localStorage
  87.     function loadBlackList() {
  88.         blacklist = JSON.parse(localStorage.getItem(BLACKLIST_KEY)) || [];
  89.     }
  90.  
  91.     function saveBlackList() {
  92.         localStorage.setItem(BLACKLIST_KEY, JSON.stringify(blacklist));
  93.     }
  94.  
  95.     function loadSettings() {
  96.         settings = JSON.parse(localStorage.getItem(SETTINGS_KEY)) || {
  97.             replaceAvatar: false,
  98.             replaceProfileAvatar: false,
  99.             removeSignatures: true,
  100.             postMode: IGNORE,
  101.             profileMsgMode: IGNORE,
  102.             removeTopics: true,
  103.             customPost: "",
  104.             customAvatar: "",
  105.             customProfileMsg: "",
  106.             customProfileAvatar: "",
  107.             specificCustomPost: {},
  108.             specificCustomProfileMsg: {}
  109.         };
  110.         if (!settings.specificCustomPost) settings.specificCustomPost = {};
  111.         if (!settings.specificCustomProfileMsg) settings.specificCustomProfileMsg = {};
  112.     }
  113.  
  114.     function saveSetting(key, value) {
  115.         if (typeof key === "object") {
  116.             settings[key.key][key.subkey] = value;
  117.         } else {
  118.             settings[key] = value;
  119.         }
  120.         localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));
  121.     }
  122.  
  123.     //functions called by the routers
  124.     function handlePosts() {
  125.         loadBlackList();
  126.         loadSettings();
  127.         addPostsBlackListButtons();
  128.  
  129.         switch (settings.postMode) {
  130.             case IGNORE:
  131.                 ignorePosts();
  132.                 return;
  133.             case REPLACE:
  134.                 replacePosts();
  135.                 break;
  136.             case DO_NOTHING:
  137.                 break;
  138.             default:
  139.                 saveSetting("postMode", IGNORE);
  140.                 ignorePosts();
  141.                 break;
  142.         }
  143.  
  144.         if (settings.replaceAvatar) replaceAvatar();
  145.         if (settings.removeSignatures) removeSignatures();
  146.     }
  147.  
  148.     function handleTopics() {
  149.         loadBlackList();
  150.         loadSettings();
  151.         if (settings.removeTopics) {
  152.             ignoreTopics();
  153.         }
  154.     }
  155.  
  156.     function handleProfileMsgs() {
  157.         loadBlackList();
  158.         loadSettings();
  159.         addProfileMsgBlackListButtons();
  160.  
  161.         switch (settings.profileMsgMode) {
  162.             case IGNORE:
  163.                 ignoreProfileMsgs();
  164.                 return;
  165.             case REPLACE:
  166.                 replaceProfileMsg();
  167.                 break;
  168.             case DO_NOTHING:
  169.                 break;
  170.             default:
  171.                 saveSetting("profileMsgMode", IGNORE);
  172.                 ignoreProfileMsgs();
  173.                 break;
  174.         }
  175.  
  176.         if (settings.replaceProfileAvatar) replaceProfileAvatar();
  177.     }
  178.  
  179.     function handleComToCom() {
  180.         loadBlackList();
  181.         loadSettings();
  182.         addComToComBlackListButtons();
  183.  
  184.         switch (settings.profileMsgMode) {
  185.             case IGNORE:
  186.                 ignoreComToCom();
  187.                 return;
  188.             case REPLACE:
  189.                 replaceComToCom();
  190.                 break;
  191.             case DO_NOTHING:
  192.                 break;
  193.             default:
  194.                 saveSetting("profileMsgMode", IGNORE);
  195.                 ignoreComToCom();
  196.                 break;
  197.         }
  198.  
  199.         if (settings.replaceProfileAvatar) replaceComToComAvatar();
  200.     }
  201.  
  202.     function handleBlacklist() {
  203.         loadBlackList();
  204.         loadSettings();
  205.  
  206.         document.title = "Blacklist - MyAnimeList.net";
  207.  
  208.         //remove the 404 stuff
  209.         document.querySelector("h1").textContent = "Ignore List";
  210.         document.querySelector(".error404").remove();
  211.  
  212.         //CSS
  213.         addStyle(".flex{display:flex;gap:20px;margin-top:10px;}.user{display:flex;margin:10px}.name{margin-right:20px}.name{border-bottom:solid #000 1px}.name[contenteditable]{min-width:100px;border-bottom:solid #000 1px}.name[contenteditable]:focus{border:none;outline:solid red 5px}.page-common #content{display:flex;justify-content:center;}.settings{display:flex;gap:25px;}.settings>*{padding: 25px;}.customPost{width:100% !important;}.select-users{font-size:1rem;padding:10px;font-weight:bold;}");
  214.  
  215.         //HTML for the blacklist
  216.         document.getElementById("content").innerHTML =
  217.             `<div data-blacklist class="black-list"></div>
  218.         <div data-add-user class="add-user">
  219.             <div data-user class="user">
  220.                 <div data-name class="name" contenteditable="true" onclick="this.focus()"></div>
  221.                 <button data-add class="add">Add</div>
  222.             </div>
  223.         </div>`
  224.  
  225.         //HTML for the settings
  226.         const settings = document.createElement("div");
  227.         settings.innerHTML = `
  228.             <h2>Settings</h2>
  229.             <form>
  230.                 <div class="settings">
  231.                     <div class="posts">
  232.                         <h3>Posts</h3>
  233.                         <div class="form-check">
  234.                             <input class="form-check-input" type="radio" name="posts" id="doNothingPosts" data-clickable-setting="doNothingPosts">
  235.                             <label class="form-check-label" for="doNothingPosts">
  236.                                 Do nothing
  237.                             </label>
  238.                         </div>
  239.                         <div class="form-check">
  240.                             <input class="form-check-input" type="radio" name="posts" id="hidePosts" data-clickable-setting="hidePosts">
  241.                             <label class="form-check-label" for="hidePosts">
  242.                                 Hide posts
  243.                             </label>
  244.                         </div>
  245.                         <div class="form-check">
  246.                             <input class="form-check-input" type="radio" name="posts" id="replacePosts" data-clickable-setting="replacePosts">
  247.                             <label class="form-check-label" for="replacePosts">
  248.                                 Replace posts with a custom message
  249.                             </label>
  250.                         </div>
  251.                         <textarea class="form-control customPost" name="customPost" id="customPost" data-text-setting="customPost"></textarea>
  252.                     </div>
  253.                     <div class="posts-extra">
  254.                         <h3>Posts extra options</h3>
  255.                         <div class="form-check">
  256.                             <input class="form-check-input" type="checkbox" name="replaceAvatar" id="replaceAvatar" data-clickable-setting="replaceAvatar">
  257.                             <label class="form-check-label" for="replaceAvatar">
  258.                                 Replace avatars with a custom avatar
  259.                             </label>
  260.                             <input class="form-control" type="text" name="customAvatar" id="customAvatar" data-text-setting="customAvatar">
  261.                             <br>
  262.                             <small>Leave it empty to remove the avatar</small>
  263.                         </div>
  264.                         <div class="form-check" style="margin-top: 10px;">
  265.                             <input class="form-check-input" type="checkbox" name="removeSignatures" id="removeSignatures" data-clickable-setting="removeSignatures">
  266.                             <label class="form-check-label" for="removeSignatures">
  267.                                 Hide the signature
  268.                             </label>
  269.                         </div>
  270.                         <small style="margin-top: 20px; display: block;"><strong>These settings have no effect if the Posts setting is set to "Hide Posts"</strong></small>
  271.                     </div>
  272.                     <div class="topics">
  273.                         <h3>Topics</h3>
  274.                         <div class="form-check">
  275.                             <input class="form-check-input" type="checkbox" name="removeTopics" id="removeTopics" data-clickable-setting="removeTopics">
  276.                             <label class="form-check-label" for="removeTopics">
  277.                                 Hide topics
  278.                             </label>
  279.                         </div>
  280.                     </div>
  281.                 </div>
  282.                 <div class="settings">
  283.                     <div class="profile-messages">
  284.                         <h3>Profile messages</h3>
  285.                         <div class="form-check">
  286.                             <input class="form-check-input" type="radio" name="profileMsgs" id="doNothingProfileMsgs" data-clickable-setting="doNothingProfileMsgs">
  287.                             <label class="form-check-label" for="doNothingProfileMsgs">
  288.                                 Do nothing
  289.                             </label>
  290.                     </div>
  291.                     <div class="form-check">
  292.                         <input class="form-check-input" type="radio" name="profileMsgs" id="hideProfileMsgs" data-clickable-setting="hideProfileMsgs">
  293.                         <label class="form-check-label" for="hideProfileMsgs">
  294.                             Hide profile messages
  295.                         </label>
  296.                     </div>
  297.                         <div class="form-check">
  298.                             <input class="form-check-input" type="radio" name="profileMsgs" id="replaceProfileMsgs" data-clickable-setting="replaceProfileMsgs">
  299.                             <label class="form-check-label" for="replaceProfileMsgs">
  300.                                 Replace profile messages with a custom message
  301.                             </label>
  302.                         </div>
  303.                         <textarea class="form-control customPost" name="customProfileMsg" id="customProfileMsg" data-text-setting="customProfileMsg"></textarea>
  304.                     </div>
  305.                     <div class="profile-messages-extra">
  306.                         <h3>Profile messages extra options</h3>
  307.                         <div class="form-check">
  308.                             <input class="form-check-input" type="checkbox" name="replaceProfileAvatar" id="replaceProfileAvatar" data-clickable-setting="replaceProfileAvatar">
  309.                             <label class="form-check-label" for="replaceProfileAvatar">
  310.                                 Replace profile message avatar with a custom avatar
  311.                             </label>
  312.                             <input class="form-control" type="text" name="customProfileAvatar" id="customProfileAvatar" data-text-setting="customProfileAvatar">
  313.                             <br>
  314.                             <small>Leave it empty to remove the avatar</small>
  315.                         </div>
  316.                         <small style="margin-top: 20px; display: block;"><strong>These settings have no effect if the Profile Messages setting setting is set to "Hide profile messages"</strong></small>
  317.                     </div>
  318.                 </div>
  319.                 <select name="users" class="select-users" data-select-users></select>
  320.                 <div class="flex">
  321.                     <div class="form-check">
  322.                         <label class="form-check-label" for="specificCustomPost">
  323.                             Replace this user's posts with a specific custom message
  324.                        </label>
  325.                        <textarea class="form-control customPost" name="specificCustomPost" id="specificCustomPost" data-text-setting="specificCustomPost"></textarea>
  326.                    </div>
  327.                    <div class="form-check">
  328.                        <label class="form-check-label" for="specificCustomProfileMsg">
  329.                            Replace this user's profile messages with a custom message
  330.                         </label>
  331.                         <textarea class="form-control customPost" name="specificCustomProfileMsg" id="specificCustomProfileMsg" data-text-setting="specificCustomProfileMsg"></textarea>
  332.                     </div>
  333.                 </div>
  334.             </form>`;
  335.  
  336.         document.getElementById("content").insertAdjacentElement("afterend", settings);
  337.  
  338.         startEventListeners();
  339.         loadSettingsIntoInputs();
  340.     }
  341.  
  342.     function clickedSetting(e) {
  343.         const input = e.target;
  344.         switch (input.dataset.clickableSetting) {
  345.             case "doNothingPosts":
  346.                 saveSetting("postMode", DO_NOTHING);
  347.                 break;
  348.             case "hidePosts":
  349.                 saveSetting("postMode", IGNORE);
  350.                 break;
  351.             case "replacePosts":
  352.                 saveSetting("postMode", REPLACE);
  353.                 break;
  354.             case "replaceAvatar":
  355.                 saveSetting("replaceAvatar", input.checked);
  356.                 break;
  357.             case "removeTopics":
  358.                 saveSetting("removeTopics", input.checked);
  359.                 break;
  360.             case "removeSignatures":
  361.                 saveSetting("removeSignatures", input.checked);
  362.                 break;
  363.             case "doNothingProfileMsgs":
  364.                 saveSetting("profileMsgMode", DO_NOTHING);
  365.                 break;
  366.             case "hideProfileMsgs":
  367.                 saveSetting("profileMsgMode", IGNORE);
  368.                 break;
  369.             case "replaceProfileMsgs":
  370.                 saveSetting("profileMsgMode", REPLACE);
  371.                 break;
  372.             case "replaceProfileAvatar":
  373.                 saveSetting("replaceProfileAvatar", input.checked);
  374.                 break;
  375.             default:
  376.                 return;
  377.         }
  378.     }
  379.  
  380.     function textSetting(e) {
  381.         const input = e.target;
  382.         switch (input.dataset.textSetting) {
  383.             case "customPost":
  384.                 saveSetting("customPost", input.value);
  385.                 break;
  386.             case "customAvatar":
  387.                 saveSetting("customAvatar", input.value);
  388.                 break;
  389.             case "customProfileMsg":
  390.                 saveSetting("customProfileMsg", input.value);
  391.                 break;
  392.             case "customProfileAvatar":
  393.                 saveSetting("customProfileAvatar", input.value);
  394.                 break;
  395.             case "specificCustomProfileMsg":
  396.                 {
  397.                     const selectedUser = document.querySelector("[data-select-users]").value;
  398.                     saveSetting({ key: "specificCustomProfileMsg", subkey: selectedUser }, input.value);
  399.                     break;
  400.                 }
  401.             case "specificCustomPost":
  402.                 {
  403.                     const selectedUser = document.querySelector("[data-select-users]").value;
  404.                     saveSetting({ key: "specificCustomPost", subkey: selectedUser }, input.value);
  405.                     break;
  406.                 }
  407.             default:
  408.                 return;
  409.         }
  410.     }
  411.  
  412.     function startEventListeners() {
  413.         document.querySelector("[data-add]").addEventListener("click", addNode);
  414.         document.querySelectorAll("[data-clickable-setting]").forEach(clickable => {
  415.             clickable.addEventListener("click", clickedSetting);
  416.         });
  417.         document.querySelectorAll("[data-text-setting]").forEach(text => {
  418.             text.addEventListener("input", textSetting);
  419.         });
  420.         document.querySelector("[data-select-users]").addEventListener("change", loadSpecificMessages)
  421.         blacklist.forEach(createNode);
  422.         blacklist.forEach(addUserToSelect);
  423.     }
  424.  
  425.     function loadSettingsIntoInputs() {
  426.         switch (settings.postMode) {
  427.             case DO_NOTHING:
  428.                 document.getElementById("doNothingPosts").checked = true;
  429.                 break;
  430.             case IGNORE:
  431.                 document.getElementById("hidePosts").checked = true;
  432.                 break;
  433.             case REPLACE:
  434.                 document.getElementById("replacePosts").checked = true;
  435.                 break;
  436.             default:
  437.                 document.getElementById("hidePosts").checked = true;
  438.                 saveSetting("postMode", IGNORE);
  439.                 break;
  440.         }
  441.  
  442.         switch (settings.profileMsgMode) {
  443.             case DO_NOTHING:
  444.                 document.getElementById("doNothingProfileMsgs").checked = true;
  445.                 break;
  446.             case IGNORE:
  447.                 document.getElementById("hideProfileMsgs").checked = true;
  448.                 break;
  449.             case REPLACE:
  450.                 document.getElementById("replaceProfileMsgs").checked = true;
  451.                 break;
  452.             default:
  453.                 document.getElementById("hideProfileMsgs").checked = true;
  454.                 saveSetting("profileMsgMode", IGNORE);
  455.                 break;
  456.         }
  457.  
  458.         if (settings.removeTopics) {
  459.             document.getElementById("removeTopics").checked = true;
  460.         }
  461.         if (settings.removeSignatures) {
  462.             document.getElementById("removeSignatures").checked = true;
  463.         }
  464.         if (settings.replaceAvatar) {
  465.             document.getElementById("replaceAvatar").checked = true;
  466.         }
  467.         if (settings.replaceProfileAvatar) {
  468.             document.getElementById("replaceProfileAvatar").checked = true;
  469.         }
  470.  
  471.         document.getElementById("customPost").value = settings.customPost || "";
  472.         document.getElementById("customAvatar").value = settings.customAvatar || "";
  473.         document.getElementById("customProfileMsg").value = settings.customProfileMsg || "";
  474.         document.getElementById("customProfileAvatar").value = settings.customProfileAvatar || "";
  475.  
  476.         document.querySelector("[data-select-users]").dispatchEvent(new Event("change"));
  477.     }
  478.  
  479.     function alterPosts(action) {
  480.         document.querySelectorAll(POST_USERS_SELECTOR).forEach(user => {
  481.             console.log("user = " + user.querySelector(FORUM_MSG_NAME_SELECTOR).textContent);
  482.             if (!blacklist.includes(user.querySelector(FORUM_MSG_NAME_SELECTOR).textContent)) return;
  483.             let post = user.parentNode;
  484.             //for (let i = 0; i < 4; i++) {
  485.                 post = post.parentNode;
  486.             //}
  487.             action(post, user);
  488.         });
  489.     }
  490.  
  491.     function alterProfileMessages(action) {
  492.         document.querySelectorAll(PROFILE_MSG_SELECTOR).forEach(profileMessage => {
  493.             const username = profileMessage.querySelector(PROFILE_MSG_NAME_SELECTOR).textContent;
  494.             if (!blacklist.includes(username)) return;
  495.             action(profileMessage, username);
  496.         });
  497.     }
  498.  
  499.     function alterComToCom(action) {
  500.         document.querySelectorAll(COMTOCOM_SELECTOR).forEach(comMessage => {
  501.             const username = comMessage.querySelector(COMTOCOM_NAME_SELECTOR).textContent;
  502.             if (!blacklist.includes(username)) return;
  503.             action(comMessage, username);
  504.         });
  505.     }
  506.  
  507.     function ignorePosts() {
  508.         alterPosts(post => {
  509.             post.style.display = "none";
  510.             post.previousElementSibling.style.display = "none";
  511.         });
  512.     }
  513.  
  514.     function replacePosts() {
  515.         alterPosts((post, user) => {
  516.             const username = user.querySelector(FORUM_MSG_NAME_SELECTOR).textContent;
  517.             const specificCustomPost = settings.specificCustomPost[username];
  518.             console.log("post = " + post + "user = " + user + " usename = " + username + " msg = " + MESSAGE_SELECTOR + " specific = " + specificCustomPost);
  519.             post.querySelector(MESSAGE_SELECTOR).innerHTML = specificCustomPost ? specificCustomPost : settings.customPost;
  520.         });
  521.     }
  522.  
  523.     function replaceProfileMsg() {
  524.         alterProfileMessages((profileMessage, username) => {
  525.             const specificCustomProfileMsg = settings.specificCustomProfileMsg[username];
  526.             profileMessage.querySelector(PROFILE_MSG_TEXT_SELECTOR).innerHTML = specificCustomProfileMsg ? specificCustomProfileMsg : settings.customProfileMsg;
  527.         });
  528.     }
  529.  
  530.     function replaceComToCom() {
  531.         alterComToCom((comMessage, username) => {
  532.             const specificCustomProfileMsg = settings.specificCustomProfileMsg[username];
  533.             comMessage.querySelector(COMTOCOM_TEXT_SELECTOR).innerHTML = specificCustomProfileMsg ? specificCustomProfileMsg : settings.customProfileMsg;
  534.         });
  535.     }
  536.  
  537.     function ignoreTopics() {
  538.         document.querySelectorAll(TOPIC_USERS_SELECTOR).forEach(user => {
  539.             if (!blacklist.includes(user.textContent)) return;
  540.             user.closest("tr").style.display = "none";
  541.         });
  542.     }
  543.  
  544.     function ignoreProfileMsgs() {
  545.         alterProfileMessages(profileMessage => {
  546.             profileMessage.style.display = "none";
  547.         });
  548.     }
  549.  
  550.     function ignoreComToCom() {
  551.         alterComToCom(comMessage => {
  552.             comMessage.style.display = "none";
  553.         });
  554.     }
  555.  
  556.     function replaceAvatar() {
  557.         alterPosts((post, user) => {
  558.             const avatar = user.querySelector(AVATAR_SELECTOR);
  559.  
  560.             if (!avatar) {
  561.                 if (settings.customAvatar === "") return;
  562.  
  563.                 const avatar = document.createElement("a");
  564.                 avatar.href = user.querySelector(USER_PROFILE_SELECTOR).href;
  565.                 avatar.className = "forum-icon";
  566.                 avatar.innerHTML = `
  567.                     <img class=" lazyloaded" data-src="${settings.customAvatar}" vspace="2" border="0" src="${settings.customAvatar}" width="100" height="125">`;
  568.                 user.querySelector(USER_INFO_SELECTOR).insertAdjacentElement('afterend', avatar);
  569.             } else {
  570.                 if (settings.customAvatar === "") {
  571.                     avatar.style.display = "none";
  572.                     return;
  573.                 }
  574.  
  575.                 const img = avatar.querySelector("img");
  576.                 img.src = settings.customAvatar;
  577.                 img.setAttribute("data-src", settings.customAvatar);
  578.                 img.setAttribute("width", 100);
  579.                 img.setAttribute("height", 125);
  580.             }
  581.         });
  582.     }
  583.  
  584.     function replaceProfileAvatar() {
  585.         alterProfileMessages(profileMessage => {
  586.             const avatar = profileMessage.querySelector(PROFILE_MSG_AVATAR_SELECTOR);
  587.  
  588.             if (settings.customProfileAvatar === "") {
  589.                 avatar.style.display = "none";
  590.                 return;
  591.             }
  592.  
  593.             const img = avatar.querySelector("img");
  594.             img.src = settings.customProfileAvatar;
  595.             img.setAttribute("data-src", settings.customProfileAvatar);
  596.         });
  597.     }
  598.  
  599.     function replaceComToComAvatar() {
  600.         alterComToCom(comMessage => {
  601.             const avatar = comMessage.querySelector(COMTOCOM_AVATAR_SELECTOR);
  602.  
  603.             if (settings.customProfileAvatar === "") {
  604.                 avatar.style.display = "none";
  605.                 return;
  606.             }
  607.  
  608.             const img = avatar.querySelector("img");
  609.             img.src = settings.customProfileAvatar;
  610.             img.setAttribute("data-src", settings.customProfileAvatar);
  611.         });
  612.     }
  613.  
  614.     function removeSignatures() {
  615.         alterPosts(post => {
  616.             const signature = post.querySelector(SIGNATURE_SELECTOR);
  617.             if (!signature) return;
  618.             signature.style.display = "none";
  619.         });
  620.     }
  621.  
  622.     function addPostsBlackListButtons() {
  623.         document.querySelectorAll(FORUM_MESSAGE_SELECTOR).forEach(forumMessage => {
  624.             const actionBar = forumMessage.querySelector(FORUM_ACTION_BAR_SELECTOR);
  625.             const username = forumMessage.querySelector(FORUM_MSG_NAME_SELECTOR).textContent;
  626.             if (!blacklist.includes(username)) {
  627.                 addBlackListButton(actionBar, username);
  628.             } else {
  629.                 addUnBlackListButton(actionBar, username);
  630.             }
  631.         });
  632.     }
  633.  
  634.     function addProfileMsgBlackListButtons() {
  635.         document.querySelectorAll(PROFILE_MSG_SELECTOR).forEach(profileMessage => {
  636.             let actionBar = profileMessage.querySelector(PROFILE_MSG_ACTION_BAR_SELECTOR);
  637.             const username = profileMessage.querySelector(PROFILE_MSG_NAME_SELECTOR).textContent;
  638.  
  639.             //this happens when you are looking at someone elses profile, create the actionBar.
  640.             if (!actionBar) {
  641.                 actionBar = document.createElement("div");
  642.                 actionBar.className = "postActions ar mt4";
  643.                 profileMessage.querySelector(PROFILE_MSG_TEXT_SELECTOR).insertAdjacentElement("afterend", actionBar);
  644.             }
  645.  
  646.             if (!blacklist.includes(username)) {
  647.                 addBlackListLink(actionBar, username, " | ");
  648.             } else {
  649.                 addUnBlackListLink(actionBar, username, " | ");
  650.             }
  651.         });
  652.     }
  653.  
  654.     function addComToComBlackListButtons() {
  655.         document.querySelectorAll(COMTOCOM_SELECTOR).forEach(comMessage => {
  656.             let actionBar = comMessage.querySelector(COMTOCOM_ACTION_BAR_SELECTOR);
  657.             const username = comMessage.querySelector(COMTOCOM_NAME_SELECTOR).textContent;
  658.  
  659.             //this happens when you manually enter the url of com-to-com between 2 users other than you.
  660.             if (!actionBar) {
  661.                 const actionBarContainer = document.createElement("div");
  662.                 actionBarContainer.style.marginTop = "10px";
  663.                 actionBar = document.createElement("small");
  664.                 actionBarContainer.appendChild(actionBar);
  665.                 comMessage.querySelector(COMTOCOM_TEXT_SELECTOR).insertAdjacentElement("afterend", actionBarContainer);
  666.             }
  667.  
  668.             if (!blacklist.includes(username)) {
  669.                 addBlackListLink(actionBar, username, " | ");
  670.             } else {
  671.                 addUnBlackListLink(actionBar, username, " | ");
  672.             }
  673.         });
  674.     }
  675.  
  676.     function addBlackListLink(actionBar, username, separator) {
  677.         const you = document.querySelector(YOU_SELECTOR).textContent;
  678.         if (username == you) return
  679.         const a = document.createElement("a");
  680.         a.href = "javascript:void(0)";
  681.         a.textContent = "Blacklist User";
  682.         a.dataset.username = username;
  683.         a.onclick = blacklistUser;
  684.  
  685.         actionBar.after(a);
  686.  
  687.         if (separator) {
  688.             actionBar.after(document.createTextNode(separator));
  689.         }
  690.     }
  691.  
  692.     function addUnBlackListLink(actionBar, username, separator) {
  693.         const a = document.createElement("a");
  694.         a.href = "javascript:void(0)";
  695.         a.textContent = "UnBlacklist User";
  696.         a.dataset.username = username;
  697.         a.onclick = blacklistUser;
  698.  
  699.         actionBar.after(a);
  700.  
  701.         if (separator) {
  702.             actionBar.after(document.createTextNode(separator));
  703.         }
  704.     }
  705.  
  706.     function addBlackListButton(actionBar, username, separator) {
  707.         const you = document.querySelector(YOU_SELECTOR).textContent;
  708.         if (username == you) return
  709.         const a = document.createElement("button");
  710.         a.href = "javascript:void(0)";
  711.         a.textContent = "Blacklist User";
  712.         a.classList.add("mal-btn");
  713.         a.dataset.username = username;
  714.         a.onclick = blacklistUser;
  715.  
  716.         if (actionBar.childElementCount > 0 && separator) {
  717.             actionBar.prepend(document.createTextNode(separator));
  718.         }
  719.         actionBar.prepend(a);
  720.     }
  721.  
  722.     function addUnBlackListButton(actionBar, username, separator) {
  723.         const a = document.createElement("button");
  724.         a.href = "javascript:void(0)";
  725.         a.textContent = "UnBlacklist User";
  726.         a.classList.add("mal-btn");
  727.         a.dataset.username = username;
  728.         a.onclick = blacklistUser;
  729.  
  730.         if (actionBar.childElementCount > 0 && separator) {
  731.             actionBar.prepend(document.createTextNode(separator));
  732.         }
  733.         actionBar.prepend(a);
  734.     }
  735.  
  736.     function blacklistUser(e) {
  737.         const username = e.target.dataset.username;
  738.  
  739.         if (blacklist.includes(username)) {
  740.         removeUser(username);
  741.         window.location.reload();
  742.         } else {
  743.         addUser(username);
  744.         window.location.reload();
  745.         }
  746.     }
  747.  
  748.     //Add a user to the blacklist
  749.     function addUser(username) {
  750.         blacklist.push(username);
  751.         saveBlackList();
  752.     }
  753.  
  754.     //Remove a user from the blacklist if it's there
  755.     function removeUser(userName) {
  756.         blacklist = blacklist.filter(name => userName !== name);
  757.         saveBlackList();
  758.     }
  759.  
  760.     //remove the user node from the html code and then update the localStorage
  761.     function removeNode(e) {
  762.         const row = e.target.parentNode;
  763.         const name = row.querySelector("[data-name]").textContent;
  764.         row.remove();
  765.         removeUser(name);
  766.         removeUserFromSelect(name);
  767.     }
  768.  
  769.     //modify the user node from the html code and then update the localStorage
  770.     function saveNode(e) {
  771.         const newName = e.target.textContent;
  772.         const previousName = e.target.dataset.previousName;
  773.  
  774.         previousName && removeUser(previousName);
  775.  
  776.         if (newName !== "") {
  777.             addUser(newName);
  778.             e.target.dataset.previousName = newName;
  779.         } else {
  780.             e.target.parentNode.remove();
  781.         }
  782.     }
  783.  
  784.     //add a new user node to the html code and then update the localStorage
  785.     function addNode(e) {
  786.         const node = e.target.parentNode;
  787.         const usernameNode = node.querySelector("[data-name]");
  788.         const username = usernameNode.textContent;
  789.         usernameNode.textContent = "";
  790.  
  791.         if (!blacklist.includes(username)) {
  792.             createNode(username);
  793.             addUser(username);
  794.             addUserToSelect(username);
  795.         }
  796.     }
  797.  
  798.     //create the user node then add it the html code
  799.     function createNode(username) {
  800.         const newUser = document.createElement("div");
  801.         newUser.setAttribute("data-user", "");
  802.         newUser.className = "user";
  803.         newUser.innerHTML = `<div data-name class="name" contenteditable="true" onclick="this.focus()" data-previous-name="${username}">${username}</div>
  804.         <button data-remove class="remove">Remove</button>`;
  805.         newUser.querySelector("[data-name]").addEventListener("focusout", saveNode);
  806.         newUser.querySelector("[data-remove]").addEventListener("click", removeNode);
  807.         document.querySelector("[data-blacklist]").append(newUser);
  808.     }
  809.  
  810.     //add the users inside the the user select element
  811.     function addUserToSelect(username) {
  812.         const selectUser = document.querySelector("[data-select-users]");
  813.         const option = document.createElement("option");
  814.         option.value = option.textContent = username;
  815.         selectUser.appendChild(option);
  816.     }
  817.  
  818.     //remove the user from the select list
  819.     function removeUserFromSelect(username) {
  820.         const userOption = document.querySelector(`[data-select-users] [value="${username}"]`);
  821.         if (userOption) userOption.remove();
  822.     }
  823.  
  824.     //load a custom post and custom profile message of a specific blacklisted user into the 2 text areas designated for these inputs
  825.     function loadSpecificMessages(e) {
  826.         const userCustomPost = settings.specificCustomPost[e.target.value];
  827.         const userCustomProfileMsg = settings.specificCustomProfileMsg[e.target.value];
  828.         const customPost = document.getElementById("specificCustomPost");
  829.         const customProfileMsg = document.getElementById("specificCustomProfileMsg");
  830.  
  831.         customPost.value = userCustomPost ? userCustomPost : "";
  832.         customProfileMsg.value = userCustomProfileMsg ? userCustomProfileMsg : "";
  833.     }
  834. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement