Website Changes Monitor

Automatically tracks and notifies HTML changes on any websites!

当前为 2024-03-28 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Website Changes Monitor
// @namespace    https://greasyfork.org/en/users/670188-hacker09?sort=daily_installs
// @version      1
// @description  Automatically tracks and notifies HTML changes on any websites!
// @author       hacker09
// @include      *
// @icon         https://i.imgur.com/0kx5i9q.png
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_listValues
// @grant        GM_deleteValue
// @grant        GM.xmlHttpRequest
// @grant        GM_registerMenuCommand
// @connect      *
// ==/UserScript==

(function() {
  'use strict';
  GM_registerMenuCommand('Add/Remove Website', () => { open('https://f.org/tracker/settings.html', '_blank'); }); //Add a settings button on the Tampermonkey menu

  /* function sortObject(obj) {
    return Object.keys(obj).sort().reduce((sorted, key) => {
        sorted[key] = obj[key];
        return sorted;
    }, {});
} */

  GM_listValues().forEach(function(url) { //For each website on the Tampermonkey storage
    if (url.match(/I_am_a_Dev|^Number$/) === null) //If the current item aren't the variables I_am_a_Dev/Number$
    {
      GM.xmlHttpRequest({ //Start a new xmlHttpRequest
        method: GM_getValue(url, {}).method, //Add the xmlHttpRequest method
        url: url.replace(/Counter\d+/, ''), //Add the xmlHttpRequest method
        headers: GM_getValue(url, {}).header, //Add the xmlHttpRequest header
        data: GM_getValue(url, {}).body, //Add the xmlHttpRequest body
        onload: ({ responseText }) => { //When the xmlHttpRequest is completed
          //if (JSON.stringify(sortObject(GM_getValue(url, {}).HTML)) !== JSON.stringify(sortObject(responseText))) //If the HTML changed
          if (GM_getValue(url, {}).HTML !== responseText) //If the HTML changed
          { //Starts the if condition
            console.table([{'old': GM_getValue(url, {}).HTML, "new": responseText, "if": GM_getValue(url, {}).HTML !== responseText}])
            GM_setValue(url, { "HTML": responseText, "method": GM_getValue(url, {}).method, "header": GM_getValue(url, {}).header, "body": GM_getValue(url, {}).body}); //Add the new HTML on the Tampermonkey storage
            //open(url, '_blank'); //Open the updated website on a new tab
          } //Finishes the if condition
        } //Finishes the onload function
      }); //Finishes the xmlHttpRequest function
    } //Finishes the if condition
  }); //Finishes the function

  //2024 //"action=action_search&vars=%7B%22_wpsearch%22%3A%22ca393a549e%22%2C%22taxonomy%22%3A%22none%22%2C%22search%22%3A%22none%22%2C%22term%22%3A%22none%22%2C%22type%22%3A%22movies%22%2C%22genres%22%3A%5B%5D%2C%22years%22%3A%5B%22113364%22%5D%2C%22sort%22%3A%221%22%2C%22page%22%3A1%7D"

  if (location.href === 'https://f.org/tracker/settings.html') { //If the user is on the page settings website
    document.head.remove(); //Remove the current page head
    document.body.remove(); //Remove the current page body
    document.querySelector("html").innerHTML = `<title>Website Changes Monitor manager</title><style>body { margin: 0; min-width: 250px; } * { box-sizing: border-box; } ul { margin: 0; padding: 0; } ul li { position: relative; padding: 12px 8px 12px 40px; list-style-type: none; background: #eee; font-size: 18px; transition: 0.2s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } ul li:nth-child(odd) { background: #f9f9f9; } ul li:hover { background: #ddd; } .close { cursor: pointer; position: absolute; right: 0; top: 0; padding: 12px 16px 12px 16px; } .close:hover { background-color: #f44336; color: white; } .header { background-color: #000000; padding: 30px 40px; color: white; text-align: center; } .title { margin: 5px; } .subtitle { text-align: left; } .header:after { content: ""; display: table; clear: both; } .footer { background-color: #000000; padding: 5px 40px; color: white; } input { margin: 0; border: none; border-radius: 0; width: 75%; height: 45px; padding: 10px; float: left; font-size: 16px; } .addBtn { padding: 10px; width: 25%; height: 45px; background: #d9d9d9; color: #555; float: left; text-align: center; font-size: 16px; cursor: pointer; transition: 0.3s; border-radius: 0; } .addBtn:hover { background-color: #bbb; }</style></head><body><div class="header"><h2 class="title">Website Changes Monitor</h2><h3 class="subtitle">Trusted websites:</h3><input type="text" id="Input" placeholder="e.g. reddit.com"><span class="addBtn">Add</span></div><ul id="List"></ul><div class="footer"><h4 class="subtitle">All data is stored in the UserScript's local storage.</h4></div></body> `; //Add the script settings page on the website

    document.getElementsByClassName('addBtn')[0].addEventListener('click', async () => { //If the Add Button is clicked on the page
      GM_getValue("Number") === undefined ? GM_setValue("Number", "Counter1") : GM_setValue("Number", "Counter"+(parseInt(GM_getValue("Number").match(/\d+/)[0]) + 1)); //Create/increase the counter

      GM_getValue("I_am_a_Dev") !== undefined && GM_getValue("I_am_a_Dev").match(/yes|no/) !== null ? '' : GM_setValue("I_am_a_Dev", prompt('OK = Enable advanced developer settings.\nCancel = Simple settings.', 'yes') || 'no'); //Save the user options/data

      if (document.getElementById('Input').value !== '') { //If the user is not trying to add a blank website
        if (GM_getValue("I_am_a_Dev") === 'yes') //If the user is a Dev
        { //Starts the if condition
          var method = prompt('OK = GET request.\nCancel = POST request.', 'GET') || 'POST'; //Ask and save the method
          var header = prompt('OK = Paste the fetch headers.\nCancel = Blank headers.') || '{}'; //Ask and save the header
          var body = prompt('OK = Paste the fetch body/data.\nCancel = Blank body.') || ''; //Ask and save the body
        } //Finishes the if condition

        GM_getValue("I_am_a_Dev") === 'yes' ? GM_setValue(GM_getValue("Number") + `${document.getElementById('Input').value}`, { "HTML": '', "method": method, "header": header !== '{}' ? JSON.parse(header.replace(/\s+/g, ' ').trim()) : '{}', "body": body}) : GM_setValue(GM_getValue("Number") + `${document.getElementById('Input').value}`, { "HTML": '', "method": 'GET', "header": '{}', "body": ''}); //Add the website on the Tampermonkey storage
      } //Finishes the if condition
      await new Promise(resolve => setTimeout(resolve, 2000)); //Wait 1.5 secs to reload
      location.reload(); //Reload the page
    }); //Finishes the onclick function

    GM_listValues().forEach(async function(Storedwebsite) { //For each website on the Tampermonkey storage
      Storedwebsite.match(/I_am_a_Dev|^Number$/) === null ? document.getElementById('List').insertAdjacentHTML('beforeend', `<li>${Storedwebsite.replace(/Counter\d+/, '')}<span class='close'>✘</span></li>`) : ''; //Add the website/close button into the list
      document.querySelector('li:last-child .close')?.addEventListener('click', function() { //When X is clicked
        GM_deleteValue(Storedwebsite); //Remove the website from the Tampermonkey storage
        this.parentElement.style.display = 'none'; //Hide the removed website from the page list
      }); //Finishes the onclick function
    }); //Finishes the function
  } //Finishes the if condition
})();