// ==UserScript== // @name Letterboxd++ // @namespace https://github.com/shmup/lbpp // @description Add customized search links with favicons to Letterboxd movie pages // @author Jared Miller (shmup) // @license GPL-3.0-or-later // @match https://letterboxd.com/film/* // @grant none // @run-at document-end // @version 1.73 // @downloadURL https://update.greasyfork.icu/scripts/510028/Letterboxd%2B%2B.user.js // @updateURL https://update.greasyfork.icu/scripts/510028/Letterboxd%2B%2B.meta.js // ==/UserScript== (function () { "use strict"; const styles = ` .link-container { margin-top: 10px; padding: 10px; display: inline-block; } .links-flex { display: flex; flex-wrap: wrap; gap: 10px; } .custom-link { align-items: center; background-color: rgb(14, 116, 162); border-radius: 3px; color: #fff; display: flex; font-weight: bold; padding: 5px 10px; text-decoration: none; transition: background-color 0.3s; } .custom-link:hover { color: #fff; background-color: rgb(5, 85, 122); } .custom-link img { width: 16px; height: 16px; margin-right: 5px; vertical-align: middle; } `; function addStyles(styles) { const styleSheet = document.createElement("style"); styleSheet.innerText = styles; document.head.appendChild(styleSheet); } function getMovieTitle() { const titleElement = document.querySelector( ".primaryname" ); return titleElement ? titleElement.textContent.trim().replace(/\s+/g, " ") : null; } function getReleaseYear() { const yearElement = document.querySelector("div.releaseyear a"); return yearElement ? yearElement.textContent.trim() : null; } function createLink(href, text, icon) { const domain = new URL(href).hostname; const faviconUrl = icon || `https://www.google.com/s2/favicons?domain=${domain}`; const link = document.createElement("a"); link.href = href; link.target = "_blank"; link.classList.add("custom-link"); link.title = `Search on ${domain}`; const img = document.createElement("img"); img.src = faviconUrl; img.onerror = () => { link.textContent = `🔍 ${text}`; }; link.appendChild(img); const span = document.createElement("span"); span.textContent = text; link.appendChild(span); return link; } function addLinks(links) { const detailsDiv = document.querySelector("div.details"); if (!detailsDiv) return; const linkContainer = document.createElement("div"); linkContainer.classList.add("link-container"); const flexContainer = document.createElement("div"); flexContainer.classList.add("links-flex"); links.forEach(({ href, text, icon = "" }) => { const link = createLink(href, text, icon); flexContainer.appendChild(link); }); linkContainer.appendChild(flexContainer); detailsDiv.insertAdjacentElement('afterend', linkContainer); } function init() { const movieTitle = getMovieTitle(); const releaseYear = getReleaseYear(); console.debug(movieTitle, releaseYear) if (!movieTitle || !releaseYear) return; const searchQueries = { BITSEARCH: `${movieTitle} ${releaseYear}`, BTDIG: `${movieTitle} ${releaseYear}`, TD: `${movieTitle} ${releaseYear}`, TPB: `${movieTitle} ${releaseYear}`, WIKI: `${movieTitle} (${releaseYear} film)`, YT: `${movieTitle} ${releaseYear} trailer`, IA: `title:(${movieTitle}) AND mediatype:(movies)`, }; const links = [ { text: "YT", href: `https://www.youtube.com/results?search_query=${encodeURIComponent(searchQueries.YT)}`, }, { text: "IA", href: `https://archive.org/search.php?query=${encodeURIComponent(searchQueries.IA)}`, }, { text: "WIKI", href: `https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(searchQueries.WIKI)}&ns0=1`, }, { text: "TD", icon: "https://www.torrentday.com/favicon.ico", href: `https://www.torrentday.com/t?q=${encodeURIComponent(searchQueries.TD)};o=seeders&qf=#torrents`, }, { text: "TPB", href: `https://thepiratebay.org/search.php?q=${encodeURIComponent(searchQueries.TPB)}&video=on&search=Pirate+Search&page=0&orderby=`, }, { text: "BTDIG", href: `https://btdig.com/search?q=${encodeURIComponent(searchQueries.BTDIG)}`, }, { text: "BITSEARCH", href: `https://bitsearch.to/search?q=${encodeURIComponent(searchQueries.BITSEARCH)}`, }, ]; addStyles(styles); addLinks(links); } init(); })();