Affinity to You

Shows the "Affinity to You" % that all users who have commented on any topic on MAL have with you!

当前为 2023-01-30 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Affinity to You
// @namespace    AffinityShow
// @version      0.14
// @description  Shows the "Affinity to You" % that all users who have commented on any topic on MAL have with you!
// @author       hacker09
// @match        https://myanimelist.net/forum/?topicid=*
// @icon         https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://myanimelist.net&size=64
// @run-at       document-end
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
  'use strict';
  var TimesExecuted = 0; //Create a new global variable
  var UserAffinityList = []; //Create a new global array
  var MALUserParsedList = new Map(); //Creates a new map to later add all non-dup mal usernames on the page
  var ScriptUsername = document.querySelector("a.header-profile-link").innerText; //Gets the script username

  var AffinityList = document.createElement("button"); //Creates a btn element
  AffinityList.setAttribute("style", "display: none; background-color: snow; margin-left: 10px;"); //The CSS for the "button"
  AffinityList.setAttribute("id", "AffinityList"); //Adds an ID to the button
  AffinityList.setAttribute("class", "inputButton"); //Adds a class to the button

  var ShowAffinityList = document.createElement("input"); //Creates an a element
  ShowAffinityList.setAttribute("style", "background-color: #4165ba;"); //The CSS for the input btn
  ShowAffinityList.setAttribute("id", "ShowAffinityList"); //Adds an ID to the input btn
  ShowAffinityList.setAttribute("class", "inputButton"); //Adds a class to the input btn
  ShowAffinityList.setAttribute("value", "      Show Affinity list"); //Adds the input btn default text
  ShowAffinityList.setAttribute("readonly", "readonly"); //Make the input btn default text not editable

  if (document.body.innerText.match('Topic Locked - Top') !== null) //If the topic is locked
  { //Starts the if condition
    document.querySelector("div[style*='float: left;']").prepend(AffinityList); //Append the button above the topic locked message
    document.querySelector("div[style*='float: left;']").prepend(ShowAffinityList); //Append the button above the topic locked message
  } //Finishes the if condition
  else //If the topic isn't locked
  { //Starts the else condition
    document.querySelector(".js-topic-top").after(AffinityList); //Append the button above the text box element
    document.querySelector(".js-topic-top").after(ShowAffinityList); //Append the input btn above the text box element
  } //Finishes the else condition

  document.querySelector("#ShowAffinityList").onclick = function() { //When the Show Affinity button is clicked
    var AffinityList = document.querySelector("#AffinityList"); //Store the Affinity List to a variable
    if (AffinityList.style.display === 'none') { //If the Affinity list is hidden
      AffinityList.style.display = ''; //Show the Affinity List
      document.querySelector("#ShowAffinityList").value = "      Hide Affinity list"; //Change the Show Affinity List text to Hide Affinity List
    } else { //If the Affinity list is being shown
      AffinityList.style.display = 'none'; //Hide the Affinity List
      document.querySelector("#ShowAffinityList").value = "      Show Affinity list"; //Change the Hide Affinity List text to Show Affinity List
    } //Finishes the else condition
  }; //Finishes the onclick event listener

  if (GM_getValue('Date') === undefined) //If the date wasn't yet stored on tampermonkey
  { //Starts the if condition
    GM_setValue('Date', new Date().getMonth()); //Get and save the actual month as a number
  } //Finishes the if condition

  if (new Date().getMonth() !== GM_getValue('Date')) //If the month number stored on tampermonkey is a previous month
  { //Starts the if condition
    GM_listValues().forEach(function(a) { //ForEach data stored on tampermonkey
      if (a !== GM_getValue('Date')) //If the current looped element isn't the past month number stored on tampermonkey
      { //Starts the if condition
        GM_deleteValue(a); //Delete the actual looped value of the TamperMonkey storage
      } //Finishes the if condition
    }); //Finishes the foreach condition to erase all the users stored on tampermonkey
  } //Finishes the if condition

  window.onscroll = function() { //Starts the onscroll event listener
    TimesExecuted += 1; //Sum the total amount of times that the page was scrolled
    if (TimesExecuted === 1) //If it's the first time that the page was scrolled
    { //Starts the if condition
      MALUserParsedList.set(ScriptUsername, {}); //Add the script username to the map,so that the script won't fetch the script user profile
      MALUserParsedList.set('removed-user', {}); //Add the 'removed-user' username to the map,so that the script won't fetch the non existent user profile
      document.querySelectorAll('.username a').forEach(async function(UserName) { //Execute this function for each username on the topic page

        if (!MALUserParsedList.has(UserName.innerText) && GM_getValue(UserName.innerText) !== undefined) { //If the username isn't already on the map and is stored on tampermonkey
          MALUserParsedList.set(UserName.innerText, {}); //Add the username on the map

          if (GM_getValue(UserName.innerText).match(/-\d+(?:\.\d+)?(?=%)/) === null && GM_getValue(UserName.innerText).match('Unknown') === null) //If the - symbol doesn't exist and if the affinity isn't Unknown on the tampermonkey stored data for this user
          { //Starts the if condition
            UserAffinityList.push('<a href="' + UserName.href + '" target="_blank" title="Click to open the ' + UserName.innerText + '\'s Profile">' + UserName.innerText + ' ' + GM_getValue(UserName.innerText).match(/\d+(?:\.\d+)?(?=%)/)[0] + '%</a>'); //Store all the topic User Names and links
          } //Finishes the if condition

          [...document.querySelectorAll('.username')].filter(a => a.textContent.includes(UserName.innerText)).forEach(a => a.parentNode.insertAdjacentHTML("beforeend", '<br>' + GM_getValue(UserName.innerText))); //Add the affinity % to every topic reply that matches the fetched profile username
        } //Finishes the if condition


        if (!MALUserParsedList.has(UserName.innerText) && GM_getValue(UserName.innerText) === undefined) { //If the username isn't already on the map and isn't stored on tampermonkey
          MALUserParsedList.set(UserName.innerText, {}); //Add the username on the map

          const html = await (await fetch('https://myanimelist.net/profile/' + UserName.innerText)).text(); //Gets the fetch response
          var newDocument = new DOMParser().parseFromString(html, 'text/html'); //Parses the fetch response
          var AffinityPercentage; //Make the variable global
          if (newDocument.querySelector("span[class*='bar-inner']") !== null) //If the element containing the affinity % exists
          { //Starts the if condition
            AffinityPercentage = newDocument.querySelector("span[class*='bar-inner']").innerText.replace('--', '-').trim(); //Gets the affinity %
          } //Finishes the if condition
          else //If the element containing the affinity % doesn't exist
          { //Starts the else condition
            AffinityPercentage = ' Unknown'; //Sets the affinity % to Unknown
          } //Finishes the else condition

          if (AffinityPercentage.match('-') === null && AffinityPercentage.match('Unknown') === null) //If the - symbol doesn't exist and if the affinity isn't Unknown
          { //Starts the if condition
            UserAffinityList.push('<a href="' + UserName.href + '" target="_blank" title="Click to open the ' + UserName.innerText + '\'s Profile">' + UserName.innerText + ' ' + AffinityPercentage + '</a>'); //Store all the topic User Names and links

            AffinityPercentage = '<a href="https://myanimelist.net/sharedanime.php?u1=' + UserName.innerText + '&u2=' + ScriptUsername + '" target="_blank" title="Click to open the Shared Anime page between you and ' + UserName.innerText + '"><strong style="color:blue; font-weight: normal;">Affinity to You ' + AffinityPercentage + '</strong></a>'; //Make the text blue
          } //Finishes the if condition
          else //If the - symbol DOESN'T exist
          { //Starts the else condition
            AffinityPercentage = '<a href="https://myanimelist.net/sharedanime.php?u1=' + UserName.innerText + '&u2=' + ScriptUsername + '" target="_blank" title="Click to open the Shared Anime page between you and ' + UserName.innerText + '"><strong style="color:red; font-weight: normal;">Affinity to You ' + AffinityPercentage + '</strong>'; //Make the text red
          } //Finishes the else condition

          GM_setValue(UserName.innerText, AffinityPercentage); //Get and save the UserName and the AffinityPercentage on tampermonkey
          [...document.querySelectorAll('.username')].filter(a => a.textContent.includes(UserName.innerText)).forEach(a => a.parentNode.insertAdjacentHTML("beforeend", '<br>' + AffinityPercentage)); //Add the affinity % to every topic reply that matches the fetched profile username
        } //Finishes the if condition

        if (UserAffinityList.length != 0) //If there are any users that have a positive affinity with you in the page
        { //Starts the if condition
          document.querySelector("#AffinityList").innerHTML = UserAffinityList.sort(function(a, b) { //Add the sorted list to the button element
            var aA = parseFloat(a.match(/\d+(?:\.\d+)?(?=%)/)); //Get only the Affinity % number
            var bA = parseFloat(b.match(/\d+(?:\.\d+)?(?=%)/)); //Get only the Affinity % number
            return bA > aA ? 1 : -1; //Compare the Affinity % and sort the array
          }).join('<br><br>'); //Finishes the sorting condition and add "spaces" between the links
        } //Finishes the if condition
        else //If there are NO users that have a positive affinity with you in the page
        { //Starts the else condition
          document.querySelector("#AffinityList").innerHTML = '<strong style="color:red; font-weight: normal;">No one here has a positive affinity with you</strong>'; //Add a text
        } //Finishes the else condition

      }); //Finishes the async function
    } //Finishes the if condition
  }; //Finishes the onscroll event listener
})();