Skip to content

Instantly share code, notes, and snippets.

@MarksCode
Created September 30, 2024 22:21
Show Gist options
  • Save MarksCode/5c71f8aeb6ed295f4870a1b5b204223c to your computer and use it in GitHub Desktop.
Save MarksCode/5c71f8aeb6ed295f4870a1b5b204223c to your computer and use it in GitHub Desktop.
Bulk Remove LinkedIn Connections
// ==UserScript==
// @name LinkedIn Connection Remover
// @author Ron Marks
// @version 1.0
// @description Bulk Remove LinkedIn Connections
// @match https://www.linkedin.com/mynetwork/invite-connect/connections/
// @run-at document-end
// @grant unsafeWindow
// ==/UserScript==
const LIST_CLASS = "scaffold-finite-scroll__content";
const CONNECTION_CLASS = "mn-connection-card";
const checkedConnections = [];
let messageObserver = null;
function waitForListElToExist() {
return new Promise((resolve) => {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (!mutation.addedNodes) return;
for (let i = 0; i < mutation.addedNodes.length; i++) {
const node = mutation.addedNodes[i];
if (node.classList && node.classList.contains(LIST_CLASS)) {
observer.disconnect();
resolve(node);
return;
}
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
});
}
/**
* Observes new connection elements.
* @param {HTMLElement} connectionsListEl
* @param {(connectionEl: HTMLElement) => void} callback
*/
function observeNewConnections(connectionsListEl, callback) {
if (messageObserver) {
messageObserver.disconnect();
}
messageObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (!mutation.addedNodes) return;
for (let i = 0; i < mutation.addedNodes.length; i++) {
const node = mutation.addedNodes[i];
if (node.classList && node.classList.contains(CONNECTION_CLASS)) {
callback(node);
}
}
});
});
messageObserver.observe(connectionsListEl, {
childList: true,
subtree: true,
});
// Initial log of existing connections
const initialConnections =
connectionsListEl.getElementsByClassName(CONNECTION_CLASS);
for (let i = 0; i < initialConnections.length; i++) {
callback(initialConnections[i]);
}
}
function addRadioBoxToConnection(connectionEl) {
const radioBox = document.createElement("input");
radioBox.type = "checkbox";
radioBox.style.position = "absolute";
radioBox.style.top = "50%";
radioBox.style.left = "6px";
radioBox.style.transform = "translateY(-50%)";
radioBox.style.opacity = 1;
radioBox.style.width = "20px";
radioBox.style.height = "20px";
radioBox.style.pointerEvents = "all";
radioBox.style.margin = 0;
radioBox.addEventListener("change", (e) => {
if (e.target.checked) {
checkedConnections.push(connectionEl);
} else {
checkedConnections.splice(checkedConnections.indexOf(connectionEl), 1);
}
});
connectionEl.prepend(radioBox);
}
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
async function removeConnection(connectionEl) {
const dropdown = connectionEl.querySelector(".artdeco-dropdown__trigger");
if (dropdown) {
dropdown.click();
}
await sleep(1000);
const removeButton = Array.from(connectionEl.querySelectorAll("button")).find(
(el) => el.innerText === "Remove connection"
);
if (removeButton) {
removeButton.click();
}
await sleep(1500);
const confirmButton = document.body.querySelector(
"button[data-test-dialog-primary-btn]"
);
if (confirmButton) {
confirmButton.click();
}
await sleep(500);
}
function removeConnections() {
const firstConnection = checkedConnections[0];
console.log("REMOVING CONNECTIONS", checkedConnections);
if (!firstConnection) {
return;
}
removeConnection(firstConnection).then(() => {
checkedConnections.shift();
if (checkedConnections.length) {
removeConnections();
}
});
}
function addRemoveButton() {
const button = document.createElement("button");
button.textContent = "Remove Selected";
button.style.position = "fixed";
button.style.top = "50%";
button.style.right = "20%";
button.style.transform = "translateY(-50%)";
button.style.zIndex = 9999;
button.style.padding = "10px";
button.style.border = "1px solid black";
button.style.backgroundColor = "#cb112d";
button.style.color = "white";
button.style.cursor = "pointer";
button.style.borderRadius = "5px";
button.style.boxShadow = "0 2px 4px 0 rgba(0,0,0,0.2)";
button.addEventListener("click", () => {
removeConnections();
});
document.body.appendChild(button);
}
(async function () {
addRemoveButton();
const listEl = await waitForListElToExist();
observeNewConnections(listEl, addRadioBoxToConnection);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment