NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==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.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;
}
.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];
// replace text with favicon
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 App (insert first)
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);
const appBadge = document.createElement('span');
appBadge.className = 'stremio-badge app';
appBadge.textContent = 'A';
stApp.appendChild(appBadge);
// Stremio Web (insert after App)
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);
const webBadge = document.createElement('span');
webBadge.className = 'stremio-badge web';
webBadge.textContent = 'W';
stWeb.appendChild(webBadge);
// inject in desired order: App first, then Web
tmdbA.after(stApp);
stApp.after(stWeb);
}
// run on initial load, PJAX navs, and DOM changes
injectStremioButtons();
document.addEventListener('pjax:complete', injectStremioButtons);
new MutationObserver(injectStremioButtons).observe(document.body, {
childList: true,
subtree: true
});
})();