From 9453c513b828f9b893095c33af4fb4e5cf1d1e80 Mon Sep 17 00:00:00 2001 From: Elizabeth Cray Date: Thu, 10 Aug 2023 02:36:29 +0000 Subject: [PATCH] Version 1 --- tampermonkey.js | 332 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 tampermonkey.js diff --git a/tampermonkey.js b/tampermonkey.js new file mode 100644 index 0000000..02b0514 --- /dev/null +++ b/tampermonkey.js @@ -0,0 +1,332 @@ +// ==UserScript== +// @name Fet Group Blocker +// @namespace http://tampermonkey.net/ +// @version 0.1 +// @description Block all users in a given FetLife Group +// @author ⬡-Drone 4661 +// @match https://fetlife.com/* +// @icon https://www.google.com/s2/favicons?sz=64&domain=fetlife.com +// @grant none +// ==/UserScript== + + +const expiration = 6000000; +const appendButton = () => { + let joinButton = document.getElementsByClassName("flex-none pl-3.5 pt-2 xs:pl-8 lg:pt-0"); + if (joinButton.length < 1) { + return; + } + let parentFlex = joinButton[0].parentElement; + let buttonLabel = "🛑 Block Group Members"; + if (localStorage.getItem("FetlifeBlocker") !== null) { + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + if (blocker.group.toString() === window.location.href.split("/")[4]) { + if (blocker.activation + expiration /*10 minutes*/ < Date.now() || blocker.status === "expired") { + console.log("Expired but from the button adder"); + buttonLabel = "❌ Auto-Block Expired"; + } else { + switch (blocker.status) { + case "nav": + case "scrape": + buttonLabel = "🔄️ Scanning..."; + break; + case "block": + buttonLabel = "🔄️ Blocking..."; + break; + case "complete": + buttonLabel = "✅ Blocking Complete"; + break; + default: + break; + } + } + } + + } + parentFlex.innerHTML = parentFlex.innerHTML + `
+
'; + let blockMemberButton = document.getElementById("blockMemberButton"); + blockMemberButton.onclick = () => { + // Scrape group members + // Block each member + if (localStorage.getItem("FetlifeBlocker") === null) { + // First click + localStorage.setItem("FetlifeBlocker", JSON.stringify({ + "origin": window.location.href, + "members": [], + "group": parseInt(window.location.href.split("/")[4]), + "activation": Date.now(), + "status": "nav" + })); + window.location.href = "https://fetlife.com/groups/" + parseInt(window.location.href.split("/")[4]) + "/members?page=1"; + } else { + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + if (blocker.status == "complete" || blocker.status == "expired") { + // First click + localStorage.setItem("FetlifeBlocker", JSON.stringify({ + "origin": window.location.href, + "members": [], + "group": parseInt(window.location.href.split("/")[4]), + "activation": Date.now(), + "status": "nav" + })); + window.location.href = "https://fetlife.com/groups/" + parseInt(window.location.href.split("/")[4]) + "/members?page=1"; + } + } + }; + return; +}; + +const navigateToNextPage = () => { + // get next page num from processed nav + // if already last page, update localStorage and return to origin + // localstorage (FetlifeBlocker -> null, FetLifeBlockedUsers -> +=members) + let nav = document.getElementsByClassName("pagination mt-6 text-center"); + if (nav.length > 0) { + if (nav[0].children[nav[0].children.length - 1].toString().includes("members")){ + // not last page yet + window.location.href = nav[0].children[nav[0].children.length - 1].toString(); + return; + } + } + // last page + // All members have been scraped + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + blocker.status = "block"; + localStorage.setItem("FetlifeBlocker", JSON.stringify(blocker)); + window.location.href = blocker.origin; + return; +}; + +const scrapeMembers = () => { + if ( document.body.classList.toString().includes("page-loading") ) { + // still loading + // Retry after 1.5 seconds + setTimeout(scrapeMembers, 1500); + return; + } + // get all members + let users = []; + // Foe each column + document.getElementsByClassName("w-full px-1 md:w-1/2").forEach(i => { + // For each member element + for (let y = 0; y < i.children.length; y++){ + let userElement = i.children[y].children[0].children[0].children[1].children[0].children[0]; + let UserID = userElement.href.split("/")[4]; + let UserName = userElement.innerText; + users.push({ + "id": UserID, + "name": UserName + }); + } + }); + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + users.forEach(i => { + if (!blocker.members.some(e => e.id === i.id)) { + blocker.members.push(i); + } + }); + localStorage.setItem("FetlifeBlocker", JSON.stringify(blocker)); + + navigateToNextPage(); +}; + +const nextUser = () => { + let userBlock = JSON.parse(localStorage.getItem("FetlifeUserBlock")); + if (userBlock === null) { + window.location.href = "https://fetlife.com/groups"; + return; + } + // Navigate to next user + if (userBlock.users.length < 1) { + // No users left + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + blocker.status = "complete"; + localStorage.setItem("FetlifeBlocker", JSON.stringify(blocker)); + localStorage.removeItem("FetlifeUserBlock"); + window.location.href = userBlock.origin; + } else { + window.location.href = "https://fetlife.com/users/" + userBlock.users[0].id; + } + return; +}; + +(function() { + 'use strict'; + switch (window.location.pathname.split("/")[1]) { + case "groups": + if (/^[0-9]+$/.test(window.location.pathname.split("/")[2].toLowerCase())){ + appendButton(); + if (localStorage.getItem("FetlifeBlocker") !== null) { + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + // Block run expired.. reset to null + if (blocker.activation + expiration /*10 minutes*/ < Date.now()) { + console.log("Expired"); + blocker.status = "expired"; + blocker.members = []; + localStorage.setItem("FetlifeBlocker", JSON.stringify(blocker)); + // localStorage.removeItem("FetlifeBlocker"); + return; + } + switch (blocker.status) { + case "nav": + if (!window.location.href.toLowerCase().startsWith("https://fetlife.com/groups/" + blocker.group + "/members")) { + // not on a member page, navigate to next page + window.location.href = "https://fetlife.com/groups/" + blocker.group + "/members?page=1"; + return; + }else { + // on a member page now + blocker.status = "scrape"; + localStorage.setItem("FetlifeBlocker", JSON.stringify(blocker)); + window.location.href = "https://fetlife.com/groups/" + blocker.group + "/members?page=1"; + return; + } + break; + case "scrape": + scrapeMembers(); + break; + case "block": + // Prepare data for user page cycling + localStorage.setItem("FetlifeUserBlock", JSON.stringify({ + "origin": blocker.origin, + "users": blocker.members, + "activation": Date.now(), + })); + // Navigate to first user + window.location.href = "https://fetlife.com/users/" + blocker.members[0].id; + break; + case "complete": + console.log("TODO: Announce errors if any, otherwise complete!"); + let errors = localStorage.getItem("FetlifeError")?JSON.parse(localStorage.getItem("FetlifeError")):[]; + if (errors.length > 0) { + console.log("Errors: ", errors.length); + } else { + console.log("No errors"); + } + localStorage.removeItem("FetlifeError"); + break; + case "expired": + console.log("Expired, but from status processing"); + localStorage.removeItem("FetlifeError"); + break; + default: + // TODO? + break; + } + } + } + break; + case "users": + // If on a user page + if (/^[0-9]+$/.test(window.location.pathname.split("/")[2].toLowerCase())){ + console.log("User page"); + // check localstorage + if (localStorage.getItem("FetlifeUserBlock") !== null) { + let userBlock = JSON.parse(localStorage.getItem("FetlifeUserBlock")); + console.log("UserBlock: ", window.location.pathname.split("/")[2]); + // check within 10 minutes + if (userBlock.activation + expiration /*10 minutes*/ < Date.now()) { + localStorage.removeItem("FetlifeUserBlock"); + console.log("Expired"); + return; + } + // if user in list, block and nav to next user + if (userBlock.users.some(e => e.id.toString() === window.location.pathname.split("/")[2])) { + // If user already blocked, remove from list and skip + if (document.getElementsByTagName("body")[0].innerText.toLowerCase().includes("you've blocked")){ + console.log(`User ${window.location.pathname.split("/")[2]} already blocked`); + // Remove user listing from localstorage + userBlock.users = userBlock.users.filter(e => e.id.toString() !== window.location.pathname.split("/")[2]); + localStorage.setItem("FetlifeUserBlock", JSON.stringify(userBlock)); + // Navigate to next user + nextUser(); + return; + } else if (document.getElementsByTagName("body")[0].innerText.toLowerCase().includes("isn't available")) { + console.log(`User ${window.location.pathname.split("/")[2]} not available`); + // Remove user listing from localstorage + userBlock.users = userBlock.users.filter(e => e.id.toString() !== window.location.pathname.split("/")[2]); + localStorage.setItem("FetlifeUserBlock", JSON.stringify(userBlock)); + let errors = localStorage.getItem("FetlifeError")?JSON.parse(localStorage.getItem("FetlifeError")):[]; + errors.push({ + "user": window.location.pathname.split("/")[2], + "error": "User not available" + }); + localStorage.setItem("FetlifeError", JSON.stringify(errors)); + // Navigate to next user + nextUser(); + return; + } else { + // Block user + console.log("TODO: Block user"); + let blockButton = document.querySelectorAll('[title="Block"]'); + if (blockButton.length > 0) { + console.log("Clicking block"); + blockButton[0].click(); + setTimeout( () => { + // If can't block + let confirmButton = document.getElementsByClassName("relative no-underline items-center rounded-sm select-none border link red-100 border-red-600 hover-red-100 bg-red-600 hover:bg-red-700 transition fill-red-100 leading-tighter text-md py-2 px-2 xs:px-3.5 font-normal text-center justify-center flex w-full"); + if (confirmButton.length > 0) { + userBlock.users = userBlock.users.filter(e => e.id.toString() !== window.location.pathname.split("/")[2]); + localStorage.setItem("FetlifeUserBlock", JSON.stringify(userBlock)); + if (confirmButton[0].innerText.toLowerCase().includes("gotcha")) { + // Cannot block user + console.log("Cannot block user" + window.location.pathname.split("/")[2]); + let FetLifeError = localStorage.getItem("FetlifeError")?JSON.parse(localStorage.getItem("FetlifeError")):[]; + FetLifeError.push({ + "user": window.location.pathname.split("/")[2], + "error": "Cannot block user" + }); + // remove user from list + userBlock.users = userBlock.users.filter(e => e.id.toString() !== window.location.pathname.split("/")[2]); + localStorage.setItem("FetlifeUserBlock", JSON.stringify(userBlock)); + localStorage.setItem("FetlifeError", JSON.stringify(FetLifeError)); + nextUser(); + } else { + console.log("User " + window.location.pathname.split("/")[2] + " blocked"); + confirmButton[0].click(); + setTimeout( () => { + location.reload(); + }, 5000); + } + } + }, 500); + } else { + console.log("No block button"); + } + } + + }else { + // Navigate to fist user in list + if (userBlock.users.length < 1) { + // No users left + console.log("Missing current page user: No users left"); + localStorage.removeItem("FetlifeUserBlock"); + let blocker = JSON.parse(localStorage.getItem("FetlifeBlocker")); + blocker.status = "complete"; + localStorage.setItem("FetlifeBlocker", JSON.stringify(blocker)); + window.location.href = userBlock.origin; + } else { + console.log("Missing current page user: Navigating to next user"); + window.location.href = "https://fetlife.com/users/" + userBlock.users[0].id; + } + return; + } + return; + } else { + console.log("No users to block"); + } + } else { + console.log("Not a user page"); + } + break; + default: + console.log("Not a group or user page"); + break; + } +})();