Unshortcut links on twitter.com

replace musky t.co links with actual links to actual web sites

As of 2023-08-19. See the latest version.

// ==UserScript==
// @name        Unshortcut links on twitter.com
// @description replace musky t.co links with actual links to actual web sites
// @namespace   Itsnotlupus Industries
// @author      itsnotlupus
// @license     MIT
// @version     1.0
// @match       https://twitter.com/*
// @grant       none
// @require     https://greasyfork.org/scripts/472943-itsnotlupus-middleman/code/middleman.js
// ==/UserScript==

/* jshint esversion:11 */

function unshortcut(obj) {
  const map = {};
  // 1st pass: gather associations between t.co and actual URLs
  (function populateURLMap(obj) {
    if (obj.url && obj.expanded_url) map[obj.url] = obj.expanded_url;
    Object.keys(obj).forEach(k => obj[k] && typeof obj[k] == "object" && populateURLMap(obj[k]));
  })(obj);
  // 2d pass: replace (almost) any string that contains a t.co string
  (function replaceURLs(obj) {
    Object.keys(obj).forEach(key => ({
      string() { if (map[obj[key]] && key!=='full_text') obj[key] = map[obj[key]]; },
      object() { replaceURLs(obj[key]); }
    }[typeof obj[key]]?.()));
  })(obj);
  return obj;
}

middleMan.addHook("https://twitter.com/i/api/graphql/*", {
  async responseHandler(req, res, err) {
    return Response.json(unshortcut(await res.json()), {
      status: res.status,
      headers: res.headers
    });
  }
});