您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add Rotten Tomatoes, IMDb, and Letterboxd links/icons next to movie titles on amctheatres site
// ==UserScript== // @name AMC → Rotten Tomatoes + IMDb + Letterboxd Links // @namespace http://tampermonkey.net/ // @version 1.01 // @description Add Rotten Tomatoes, IMDb, and Letterboxd links/icons next to movie titles on amctheatres site // @author Chatgpt and me // @match *://www.amctheatres.com/movie-theatres/* // @match *://www.amctheatres.com/movies/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; function cleanTitle(title) { let clean = title.trim(); // General removals clean = clean.replace(/\bQ&A.*$/i, ""); clean = clean.split("/")[0]; clean = clean.replace(/[-–]\s*studio ghibli fest\s*\d{4}/gi, ""); clean = clean.replace(/\bstudio ghibli fest\s*\d{4}/gi, ""); clean = clean.replace(/\bstudio ghibli fest\b/gi, ""); clean = clean.replace(/[-–]\s*\d+(st|nd|rd|th)?\s+anniversary\b/gi, ""); clean = clean.replace(/\b\d+(st|nd|rd|th)?\s+anniversary\b/gi, ""); clean = clean.replace(/\bunrated\b/gi, ""); clean = clean.replace(/\b4k\b/gi, ""); clean = clean.replace(/\b3d\b/gi, ""); clean = clean.replace(/\bfathom\s*\d{4}\b/gi, ""); clean = clean.replace(/\bfathom\b/gi, ""); clean = clean.replace(/\bopening night fan event\b/gi, ""); clean = clean.replace(/\bopening night\b/gi, ""); clean = clean.replace(/\bfan event\b/gi, ""); clean = clean.replace(/\bspecial screening\b/gi, ""); clean = clean.replace(/\bdouble feature\b/gi, ""); clean = clean.replace(/\([^)]*\)/g, ""); // Targeted cleanups const cutPhrases = [ " - Opening Weekend Event", "Private Theatre", "Early Access", "Sneak Peak", "IMAX", "Sensory Friendly Screening" ]; for (let phrase of cutPhrases) { const regex = new RegExp(`[:\\-]?\\s*${phrase}.*$`, "i"); clean = clean.replace(regex, ""); } return clean.trim(); } // Rotten Tomatoes slug function makeRtSlug(title) { let clean = cleanTitle(title).toLowerCase(); clean = clean.replace(/&/g, " and "); clean = clean.replace(/[':;!?,.\-–]/g, ""); clean = clean.replace(/\s+/g, "_"); clean = clean.replace(/^_+|_+$/g, ""); return clean.trim(); } // Letterboxd slug function makeLbSlug(title) { let clean = cleanTitle(title) .toLowerCase() .normalize("NFD").replace(/[\u0300-\u036f]/g, ""); // remove accents clean = clean.replace(/&/g, " "); // drop ampersands (treat as space) clean = clean.replace(/['":;!?,.]/g, ""); // remove punctuation clean = clean.replace(/[-–]/g, " "); // treat dashes as spaces clean = clean.replace(/\s+/g, "-"); // spaces -> hyphens clean = clean.replace(/-+/g, "-"); // collapse multiple hyphens clean = clean.replace(/^-+|-+$/g, ""); // trim leading/trailing hyphens return clean.trim(); } function addLinks() { const movieTitleEls = document.querySelectorAll("h2.font-bold, h3.font-bold, .md\\:text-2xl.font-bold"); movieTitleEls.forEach(movieTitleEl => { const rawTitle = movieTitleEl.textContent.trim(); if (!rawTitle || /amc/i.test(rawTitle)) return; if (movieTitleEl.querySelector(".rt-btn, .imdb-btn, .lb-btn")) return; // Rotten Tomatoes const rtSlug = makeRtSlug(rawTitle); const rtUrl = `https://www.rottentomatoes.com/m/${rtSlug}`; const rtLink = document.createElement("a"); rtLink.href = rtUrl; rtLink.target = "_blank"; rtLink.title = "View on Rotten Tomatoes"; rtLink.className = "rt-btn"; rtLink.style.cssText = ` display:inline-flex;align-items:center;justify-content:center; background-color:#d92323;color:white;font-size:15px;font-weight:bold; text-decoration:none;border-radius:50%;width:24.5px;height:24.5px; margin-left:4px;vertical-align:middle;box-shadow:0 1px 3px rgba(0,0,0,0.2); cursor:pointer; `; rtLink.textContent = "🍅"; // IMDb const imdbQuery = encodeURIComponent(cleanTitle(rawTitle)); const imdbUrl = `https://www.imdb.com/find/?q=${imdbQuery}`; const imdbLink = document.createElement("a"); imdbLink.href = imdbUrl; imdbLink.target = "_blank"; imdbLink.title = "Search on IMDb"; imdbLink.className = "imdb-btn"; imdbLink.style.cssText = ` display:inline-flex;align-items:center;justify-content:center; background-color:#f5c518;color:black;font-size:12px;font-weight:bold; text-decoration:none;border-radius:3px;width:32px;height:24.5px; margin-left:4px;vertical-align:middle;box-shadow:0 1px 3px rgba(0,0,0,0.2); cursor:pointer;font-family:Arial, sans-serif; `; imdbLink.textContent = "IMDb"; // Letterboxd const lbSlug = makeLbSlug(rawTitle); const lbUrl = `https://letterboxd.com/film/${lbSlug}/`; const lbLink = document.createElement("a"); lbLink.href = lbUrl; lbLink.target = "_blank"; lbLink.title = "View on Letterboxd"; lbLink.className = "lb-btn"; lbLink.style.cssText = ` display:inline-flex;align-items:center;justify-content:center; text-decoration:none;margin-left:4px;vertical-align:middle;cursor:pointer; `; lbLink.innerHTML = ` <div style="display:flex;"> <div style=" width:24.5px;height:24.5px;border-radius:50%;background:#ff8000; display:flex;align-items:center;justify-content:center; font-size:12px;font-weight:bold;color:white;font-family:Arial, sans-serif; box-shadow:0 1px 3px rgba(0,0,0,0.2);margin-right:-5px;"> L </div> <div style=" width:24.5px;height:24.5px;border-radius:50%;background:#00e054; display:flex;align-items:center;justify-content:center; font-size:12px;font-weight:bold;color:black;font-family:Arial, sans-serif; box-shadow:0 1px 3px rgba(0,0,0,0.2);margin-right:-5px;"> T </div> <div style=" width:24.5px;height:24.5px;border-radius:50%;background:#00bfff; display:flex;align-items:center;justify-content:center; font-size:12px;font-weight:bold;color:black;font-family:Arial, sans-serif; box-shadow:0 1px 3px rgba(0,0,0,0.2);"> B </div> </div> `; movieTitleEl.appendChild(rtLink); movieTitleEl.appendChild(imdbLink); movieTitleEl.appendChild(lbLink); }); } addLinks(); const observer = new MutationObserver(addLinks); observer.observe(document.body, { childList: true, subtree: true }); })();