333 lines
17 KiB
JavaScript
333 lines
17 KiB
JavaScript
|
// ==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 + `<div
|
||
|
class="flex-none pl-3.5 pt-2 xs:pl-8 lg:pt-0">
|
||
|
<button id="blockMemberButton"
|
||
|
class="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-normal text-sm py-2 px-3.5 font-normal text-center justify-center inline-flex"
|
||
|
data-color="red"
|
||
|
type="button">
|
||
|
<span class="xs:inline-block">` +
|
||
|
buttonLabel + '</span></button></div>';
|
||
|
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;
|
||
|
}
|
||
|
})();
|