ChatGPT / Grok Scripts

// ==UserScript==
// @name         Inline favicon for Twitch & Twitter/X links
// @namespace    https://chat.openai.com/
// @version      2.1
// @description  Draws a small favicon inside every Twitch or Twitter/X link
// @author       You
// @match       *://8chan.moe/*
// @match       *://8chan.se/*
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  /* ------ ICON DATA URIs (from the user) ------ */
  const ICON_TWITCH =
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAABmUlEQVRYCe1VsU7DMBA9V3wAn8CfIJYw8gt8AZCVhfAFqCAhJqQKFqYqG5SlIDFUAin8QfiDzh0SfG3c2pdzmthtusTLxXe+e89354uAinUX5FcZQFRxxNl0PhICnXu2CNsE1zH39I365sDP3pTVT94em/6lDHDgpstmdwaBtsHxKksCuwA3CLh2O9aU1hUD2/Ro09cyA7qyze+OQJcBdhI2aULbhLTpaeyuBK1m4POBFkAbxWXTZjWTZ4BkuIgpp+61it5KBhB88rQCD0ciUgS8X4EKZJMGeA798H0Fjj5bzYABDjCQ4BeUaO0M0D+e/s7/viGOL+EQBOxTANzLmg9k2k85W20CnDPqfmNIP+7hRILbVgIzKN1cHfYi8PMC069HOFDBGJlkMzgKx2LK2OYqZwJFfdmUF2DpOnA859yE6lkVYFSkWa/65srBmYAKwMgF+KtIGVtJZW8dcrQf5DlR4bYRGOPvXgIZLJmnueZNOXDUuTbh2u62AVJ9YwJVQ4UGr7Nv1IQZznLLRKsD5nXmJsgjrwAW538rgn7SMeXfWAAAAABJRU5ErkJggg==";

  const ICON_TWITTER =
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAADSklEQVRYCe1WTWgTURCeeUlsUrcpSr1Uk9haBBUP/lAPSql/B4vVglChkBQsFE+CCnqQHvw9CfXiQfHSNEHRQ71ERUVvVipUESxtlbZJtVLQHpqkSdtsxtnqptl1N6amoIc8CO/NzDc/mZ2Z9wCKq5iBf5wBXC7/7kB0MxCdI8IdSFADSF/5HHLY6OJwi/Ob6qcqGK2jSqlvbC8mFZ4mAI8/ug8Qt4e90nVVIZ/d44+dJaBrRLRCj0fESQS6wMG42NsRxrwbb3WeUHGaANz+6S4i8AnEjrCv7IoKyrV7AvFDaVl+lAujyhDhld0KR+cAKsZanIMKX6hCZWfnG5U9TXTZ7Y/eqgmQU6HNVv1LspKcvmMmz+Yj4CzTU8kU9KVl4VJlmgAYFFcFnKr2WTk2sL57uknl6ffRz4laTn2lnm9EM66EAPfzVz8f8UrPVIw2AITXquDnTmvlNPS4uqZ73d3R9ur7VJ4tJ5Tzcp7REdgU8ZU9yNB80NTAhrszrrn51AAQSNmgzBkxwQX1HEgMCAFDaYJyonRnRv6Hgw1tnhGfI5INs2YTaJGTmMI2AghyQWhkCzgiB8sauUoaOTNLXqLCPqlX0jiZS8I9/vclXK0f2dEmPbhAeupTw0IhasxoaoAL5S3/dnMBLrdzHi/Yr/H8i9AE4LBbO7kqYkbAQnk8iB4b2dAEMNxc+kWgOMntOG8ELoRnFdaQkb4mAAXAYzgoEA5yJt4YKfwVD+HJqNc+ZKT7WwAKiCfiFiTs52IcMVJaKk+Q9ZKZjqYLMiCEQS7Em9wRhS/Eh2Ffaa+ZIcMM8EX0AlGcNlPKn4/jTrvUlgtvGICiEPFJN9AiDig3GA/MJY8dpZAFWI5/aMapXAFoRrEZsCo4Uyun5J58Lx42GgUhjmVfOma2cwZQHYhtTcl0ipVb2bnNzEg2f+EBgqIh7F1pOHiysco5EwA/Rvbw82AnIa3mC8fNBVjH3VClVzClEWX+nrcdJHUMtuJ3U5xOkAlA4bu74of5ojlDCPXcixqZTm+RRIhzy4YsNrw62iK9XxTkdzJ0Uu1PuGVINXLad/EjYhuD1rC5VTwh4kA4wXmbYHqMWzW0zlH2tLcZE/m5K6KKGfgPM/ADvPsYMf7jeCoAAAAASUVORK5CYII=";

  const SITES = [
    { domains: ["twitch.tv", "www.twitch.tv"], icon: ICON_TWITCH },
    {
      domains: ["twitter.com", "www.twitter.com", "x.com", "www.x.com"],
      icon: ICON_TWITTER
    }
  ];

  /* ------ CORE ------ */
  function applyFavicon(link, icon) {
    if (link.dataset.faviconApplied) return;            // skip if done

    link.style.display = "inline-block";                // single inline node
    link.style.backgroundImage = `url(${icon})`;
    link.style.backgroundRepeat = "no-repeat";
    link.style.backgroundPosition = "left center";
    link.style.backgroundSize = "16px 16px";
    link.style.paddingLeft = "20px";                    // room for icon
    link.dataset.faviconApplied = "true";
  }

  function scan() {
    document.querySelectorAll("a[href]").forEach((a) => {
      const url = a.href.toLowerCase();
      SITES.forEach(({ domains, icon }) => {
        if (domains.some((d) => url.includes(d))) applyFavicon(a, icon);
      });
    });
  }

  /* initial & dynamic runs */
  scan();
  new MutationObserver(scan).observe(document.body, { childList: true, subtree: true });
})();
// ==UserScript==
// @name         Twitch Link Hover‑Preview
// @namespace    https://chat.openai.com/
// @version      2025‑04‑24f
// @description  Shows 320×180 Twitch thumbnails on hover
// @author       You
// @match       *://8chan.moe/*
// @match       *://8chan.se/*
// @run-at       document-idle
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(() => {
  "use strict";

  const RE = /^(?:https?:\/\/)?(?:www\.)?twitch\.tv\/([A-Za-z0-9_]+)(?:\/|$)/i;
  const URL  = s=>`https://static-cdn.jtvnw.net/previews-ttv/live_user_${s}-320x180.jpg`;
  const URL4 ="https://static-cdn.jtvnw.net/ttv-static/404_preview-320x180.jpg";

  /* fetch url → data:image/jpeg;base64,... */
  const toB64 = ab=>btoa(String.fromCharCode(...new Uint8Array(ab)));
  const fetchB64=u=>new Promise(r=>{
    GM_xmlhttpRequest({method:"GET",url:u,responseType:"arraybuffer",
      onload:x=>x.status===200?r(`data:image/jpeg;base64,${toB64(x.response)}`):r(null),
      onerror:()=>r(null),ontimeout:()=>r(null)});
  });

  const cache=new Map();            // streamer → dataURL
  async function getImg(s){
    if(cache.has(s)) return cache.get(s);
    let d=await fetchB64(URL(s)); if(!d) d=await fetchB64(URL4);
    cache.set(s,d||""); return d;
  }

  /* floating img */
  const img=document.createElement("img");
  img.style.cssText="position:fixed;width:320px;height:180px;object-fit:cover;pointer-events:none;border-radius:4px;box-shadow:0 2px 10px rgba(0,0,0,.4);z-index:2147483647;display:none";
  document.body.appendChild(img);

  const pos=e=>{
    const pad=16,W=320,H=180,{clientX:x,clientY:y}=e;
    let l=x+pad,t=y+pad; if(l+W>innerWidth)l=x-W-pad; if(t+H>innerHeight)t=y-H-pad;
    img.style.left=l+"px";img.style.top=t+"px";
  };

  let active=null;

  document.addEventListener("mouseover",async e=>{
    const a=e.target.closest("a[href]");
    const match=a?.href.match(RE);               // null if not a twitch link
    if(!match){                                  // ↳ mouse is now over non‑Twitch content
      if(active){ active=null; img.style.display="none"; } // hide if needed
      return;
    }
    if(a===active) return;                       // still on same link

    active=a; pos(e); img.style.display="block";
    const data=await getImg(match[1].toLowerCase());
    if(active===a && data) img.src=data;
  });

  document.addEventListener("mousemove",e=>{ if(active) pos(e); });
})();
Edit
Pub: 24 Apr 2025 04:56 UTC
Edit: 24 Apr 2025 11:57 UTC
Views: 34