mirror of
https://github.com/ergosteur/misc-userscripts.git
synced 2026-04-19 13:09:33 -04:00
add current script collection
This commit is contained in:
135
expand-tco-links.user.js
Normal file
135
expand-tco-links.user.js
Normal file
@@ -0,0 +1,135 @@
|
||||
// ==UserScript==
|
||||
// @name Expand t.co links (live replace, Location header fixed)
|
||||
// @namespace ergosteur
|
||||
// @version 0.7
|
||||
// @description Expand t.co shortlinks into final URLs by parsing Location header
|
||||
// @match https://twitter.com/*
|
||||
// @match https://x.com/*
|
||||
// @grant GM_registerMenuCommand
|
||||
// @grant GM_xmlhttpRequest
|
||||
// ==/UserScript==
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function showTextareaDialog(title, callback) {
|
||||
const overlay = document.createElement("div");
|
||||
overlay.style.position = "fixed";
|
||||
overlay.style.top = 0;
|
||||
overlay.style.left = 0;
|
||||
overlay.style.width = "100%";
|
||||
overlay.style.height = "100%";
|
||||
overlay.style.background = "rgba(0,0,0,0.7)";
|
||||
overlay.style.zIndex = 999999;
|
||||
|
||||
const box = document.createElement("div");
|
||||
box.style.position = "absolute";
|
||||
box.style.top = "50%";
|
||||
box.style.left = "50%";
|
||||
box.style.transform = "translate(-50%, -50%)";
|
||||
box.style.background = "#fff";
|
||||
box.style.padding = "20px";
|
||||
box.style.borderRadius = "8px";
|
||||
box.style.maxWidth = "600px";
|
||||
box.style.width = "80%";
|
||||
box.style.display = "flex";
|
||||
box.style.flexDirection = "column";
|
||||
|
||||
const label = document.createElement("div");
|
||||
label.textContent = title;
|
||||
label.style.marginBottom = "8px";
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.style.width = "100%";
|
||||
textarea.style.height = "300px";
|
||||
textarea.style.whiteSpace = "pre";
|
||||
|
||||
const controls = document.createElement("div");
|
||||
controls.style.marginTop = "8px";
|
||||
controls.style.display = "flex";
|
||||
controls.style.justifyContent = "space-between";
|
||||
controls.style.alignItems = "center";
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.textContent = "Expand";
|
||||
|
||||
const status = document.createElement("div");
|
||||
status.textContent = "Ready.";
|
||||
|
||||
controls.appendChild(button);
|
||||
controls.appendChild(status);
|
||||
|
||||
box.appendChild(label);
|
||||
box.appendChild(textarea);
|
||||
box.appendChild(controls);
|
||||
overlay.appendChild(box);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
button.onclick = () => {
|
||||
const val = textarea.value.trim();
|
||||
if (!val) {
|
||||
overlay.remove();
|
||||
return;
|
||||
}
|
||||
callback(textarea, status);
|
||||
};
|
||||
}
|
||||
|
||||
function expandOne(link) {
|
||||
return new Promise((resolve) => {
|
||||
GM_xmlhttpRequest({
|
||||
method: "GET", // GET is safer than HEAD for t.co
|
||||
url: link,
|
||||
redirect: "manual", // we want the Location header
|
||||
onload: (resp) => {
|
||||
let out = link;
|
||||
|
||||
// responseHeaders is a string in Tampermonkey
|
||||
const headers = resp.responseHeaders.split(/\r?\n/);
|
||||
const locLine = headers.find(h => /^location:/i.test(h));
|
||||
if (locLine) {
|
||||
out = locLine.split(/:\s*/i)[1].trim();
|
||||
}
|
||||
|
||||
resolve(out);
|
||||
},
|
||||
onerror: () => resolve(link)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function expandLinks() {
|
||||
showTextareaDialog("Paste t.co links (one per line):", async (textarea, status) => {
|
||||
let lines = textarea.value.split(/\r?\n/);
|
||||
const total = lines.length;
|
||||
|
||||
for (let i = 0; i < total; i++) {
|
||||
const line = lines[i].trim();
|
||||
if (!line) continue;
|
||||
|
||||
status.textContent = `Expanding ${i + 1}/${total}...`;
|
||||
const full = await expandOne(line);
|
||||
|
||||
lines[i] = full;
|
||||
textarea.value = lines.join("\n");
|
||||
|
||||
textarea.scrollTop = textarea.scrollHeight; // auto-scroll
|
||||
}
|
||||
|
||||
status.textContent = `Done! Expanded ${total} links.`;
|
||||
|
||||
const blob = new Blob([lines.join("\n")], {type: "text/plain"});
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const dl = document.createElement("a");
|
||||
dl.href = url;
|
||||
dl.download = "expanded_links.txt";
|
||||
dl.textContent = "⬇ Download results";
|
||||
dl.style.marginLeft = "10px";
|
||||
|
||||
status.appendChild(dl);
|
||||
});
|
||||
}
|
||||
|
||||
GM_registerMenuCommand("Expand t.co Links", expandLinks);
|
||||
})();
|
||||
Reference in New Issue
Block a user