Greasy Fork

Letterboxd: IMDb, TMDB & Stremio Badges

Swap out text links for IMDb, TMDB and Stremio icons badges

当前为 2025-06-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         Letterboxd: IMDb, TMDB & Stremio Badges
// @description  Swap out text links for IMDb, TMDB and Stremio icons badges
// @namespace    https://greasyfork.org/en/scripts/540982-letterboxd-imdb-tmdb-stremio-badges
// @version      1
// @match        https://letterboxd.com/film/*
// @match        https://letterboxd.com/*/film/*
// @author       TheSina
// @license MIT
// @grant        none
// ==/UserScript==
/* jshint esversion: 6 */
(function () {
  'use strict';

  // 1) inject CSS overrides + badge styles
  const style = document.createElement('style');
  style.textContent = `
    p.text-link.text-footer {
      display: flex !important;
      align-items: center !important;
      flex-wrap: nowrap !important;
    }
    p.text-link.text-footer a.micro-button {
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      margin: 0 8px !important;
      padding: 2px !important;
      position: relative !important;   /* ← for badge positioning */
    }
    p.text-link.text-footer img {
      width: 36px !important;
      height: 36px !important;
      vertical-align: middle !important;
    }
    /* common badge */
    .stremio-badge {
      position: absolute;
      top: -4px;
      right: -4px;
      width: 16px;
      height: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 10px;
      font-weight: bold;
      color: white;
      border-radius: 3px;
    }

    .stremio-badge.app { background: linear-gradient(to bottom right, #8e44ad, #3498db); }
    .stremio-badge.web { background: linear-gradient(to bottom right, #8e44ad, #3498db); }
  `;
  document.head.appendChild(style);

  function injectStremioButtons() {
    const footer = document.querySelector('p.text-link.text-footer');
    if (!footer || footer.dataset.sbInjected) return;
    footer.dataset.sbInjected = 'true';

    const imdbA = footer.querySelector('a[data-track-action="IMDb"]');
    const tmdbA = footer.querySelector('a[data-track-action="TMDB"]');
    if (!imdbA || !tmdbA) return;
    const m = imdbA.href.match(/tt\d+/);
    if (!m) return;
    const id = m[0];

    const swapFav = (a, domain) => {
      a.textContent = '';
      const img = document.createElement('img');
      img.src = `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;
      a.appendChild(img);
    };
    swapFav(imdbA, 'imdb.com');
    swapFav(tmdbA, 'themoviedb.org');

    // Stremio Web
    const stWeb = document.createElement('a');
    stWeb.className = 'micro-button track-event';
    stWeb.dataset.trackAction = 'Stremio Web';
    stWeb.href = `https://web.stremio.com/#/detail/movie/${id}/${id}`;
    stWeb.target = '_blank';
    stWeb.title = 'Open in Stremio Web';
    const webImg = document.createElement('img');
    webImg.src = 'https://www.google.com/s2/favicons?domain=web.stremio.com&sz=64';
    stWeb.appendChild(webImg);
    // badge
    const webBadge = document.createElement('span');
    webBadge.className = 'stremio-badge web';
    webBadge.textContent = 'W';
    stWeb.appendChild(webBadge);

    tmdbA.after(stWeb);

    // Stremio App
    const stApp = document.createElement('a');
    stApp.className = 'micro-button track-event';
    stApp.dataset.trackAction = 'Stremio App';
    stApp.href = `stremio://detail/movie/${id}`;
    stApp.title = 'Open in Stremio App';
    const appImg = document.createElement('img');
    appImg.src = 'https://www.google.com/s2/favicons?domain=web.stremio.com&sz=64';
    stApp.appendChild(appImg);
    // badge
    const appBadge = document.createElement('span');
    appBadge.className = 'stremio-badge app';
    appBadge.textContent = 'A';
    stApp.appendChild(appBadge);

    stWeb.after(stApp);
  }

  // initial + PJAX + MutationObserver
  injectStremioButtons();
  document.addEventListener('pjax:complete', injectStremioButtons);
  new MutationObserver(injectStremioButtons)
    .observe(document.body, {
      childList: true,
      subtree: true
    });

})();