您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Add IMDb, Rotten Tomatoes, and Metacritic ratings to Filmweb
当前为
// ==UserScript== // @name Filmweb External Ratings // @namespace http://tampermonkey.net/ // @version 1.0 // @description Add IMDb, Rotten Tomatoes, and Metacritic ratings to Filmweb // @author mrkkr // @match http*://www.filmweb.pl/serial/* // @match http*://www.filmweb.pl/film/* // @match http*://www.filmweb.pl/tvshow/* // @match http*://www.imdb.com/* // @match http*://www.rottentomatoes.com/* // @match http*://www.metacritic.com/* // @grant GM_xmlhttpRequest // @connect imdb.com // @connect rottentomatoes.com // @connect metacritic.com // ==/UserScript== (function() { 'use strict'; const ICONS = { imdb: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA6ElEQVQ4ja2TsQ3CMBBF/0UMgSgYgBkyAANkBEZgBLqUkWgzAiPQMgINI7CBaGgQhbElY4JQPsnS6c7/7/587wB/GAA7ADcAKYAYJ+IL9bV0JoX73I0AKgmqAbQAngBGAE8JagCcdG5MUEQGqT0AGwBHOZ8A7LXxCmCpdR1LyVyqL3rj2mm6AnCQzEbzRZ1dVMWdU5VIHqPFKJc+c5MC0CvTWvPGBE34JV0JwFwL3GfqtKi7WQbVHlXY1Dwp/Gv3w2I6W6MjgK0UzRpHXX1qXQN4fwsITRmAfaSp86bKHNgF8L9kpXEeE/QBWUU9pW4s4WYAAAAASUVORK5CYII=', rotten: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAABP0lEQVQ4jZWSPUsDQRCGn7vceSpiYSMIAUEQRLCxsLSxFgv/goWNjYU/wcI/YGlhYWdlYyEIFoJgIQiCIBgQBU0uzd3u7FjcJZcYc+oLL8w+M/PO7MwK/hm+5wngxvdcqT1nwRmwD/QkSS7DMLyW1k5cK8ltxJmwNgQuAC0iQ2BDRC6ttdPGUkQi4AfYBHaAHeAd6AFC0zQP1tqRqvzFHSilWiKyBawppUZhGN7XwDmXK6UcMPX9WVFV6jWIyJox5tj3/XPf91/CMHwDMMaMAE9ExsCZMebUWvtVOVBKrQJdYB5fVBTFR3WmtR4Dpz+Ps8YLlNYqpZaAh6IoPqvAOZc75144514rQGayB6K1XhGRO+dc3DRutdYbwKDMZO4EVdtF8gocAQNjzKQEp8AYeAL6ZSZzG4lI2xgzKRtXRG6/AduYkKWrJqV7AAAAAElFTkSuQmCC', metacritic: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAtUlEQVQ4jWNgoBAwQun/+BSzYBH7j0UNXgW4DPgPBTjlYQrwGYBNDqcBMAOI0YzTAGI1YzcAj2asBhDQjGEAIc3oBox/u3b3PwMDw38GBob/x95s2Y1LM7IBr7+c3//405n9/xkYGP4ffX1i/pH3x3bj0oxiwJsvF/Yfen9s938GBob/h94d2X3o3ZHd2DQjG3Dg3eHdB94d3v2fgYHh/4G3B3cfendkNy7NSAacs7XlGXEpBgDZMJSlUEFhkwAAAABJRU5ErkJggg==' }; async function getIMDbRating(title, year) { try { const imdbIdMatch = document.querySelector('a[href*="www.imdb.com/title/tt"]'); if (!imdbIdMatch) return null; const imdbId = imdbIdMatch.href.match(/tt\d+/)[0]; const response = await fetch(`https://www.imdb.com/title/${imdbId}/`); const text = await response.text(); const ratingMatch = text.match(/"ratingValue":\s*"([^"]+)"/); if (!ratingMatch) return null; return { rating: ratingMatch[1], url: `https://www.imdb.com/title/${imdbId}/` }; } catch (error) { console.error('Error fetching IMDb rating:', error); return null; } } async function getRottenTomatoesRating(title, year) { try { const url = `https://www.rottentomatoes.com/search?search=${encodeURIComponent(title)}`; const response = await fetch(url); const text = await response.text(); const rtUrlMatch = text.match(new RegExp(`href="([^"]+${year}[^"]+)"`)); if (!rtUrlMatch) return null; const rtUrl = 'https://www.rottentomatoes.com' + rtUrlMatch[1]; const movieResponse = await fetch(rtUrl); const movieText = await movieResponse.text(); const ratingMatch = movieText.match(/tomatometer">(\d+)%/); if (!ratingMatch) return null; return { rating: ratingMatch[1] + '%', url: rtUrl }; } catch (error) { console.error('Error fetching Rotten Tomatoes rating:', error); return null; } } async function getMetacriticRating(title, year) { try { const searchUrl = `https://www.metacritic.com/search/movie/${encodeURIComponent(title)}/results`; const response = await fetch(searchUrl); const text = await response.text(); const mcUrlMatch = text.match(new RegExp(`href="([^"]+${year}[^"]+)"`)); if (!mcUrlMatch) return null; const mcUrl = 'https://www.metacritic.com' + mcUrlMatch[1]; const movieResponse = await fetch(mcUrl); const movieText = await movieResponse.text(); const ratingMatch = movieText.match(/metascore_w[^>]+>(\d+)</); if (!ratingMatch) return null; return { rating: ratingMatch[1], url: mcUrl }; } catch (error) { console.error('Error fetching Metacritic rating:', error); return null; } } function createRatingElement(icon, rating, url) { const container = document.createElement('div'); container.style.cssText = ` display: inline-flex; align-items: center; margin: 0 10px; cursor: pointer; padding: 5px 10px; border-radius: 4px; background: rgba(0,0,0,0.05); transition: background 0.2s; `; container.onmouseover = () => container.style.background = 'rgba(0,0,0,0.1)'; container.onmouseout = () => container.style.background = 'rgba(0,0,0,0.05)'; const img = document.createElement('img'); img.src = icon; img.style.cssText = ` width: 16px; height: 16px; margin-right: 8px; `; const span = document.createElement('span'); span.textContent = rating || 'N/A'; span.style.cssText = ` font-weight: bold; color: #333; `; container.appendChild(img); container.appendChild(span); if (url) { container.addEventListener('click', () => window.open(url, '_blank')); } return container; } async function init() { if (!document.querySelector('.filmCoverSection__title')) { setTimeout(init, 100); return; } const titleElement = document.querySelector('.filmCoverSection__title'); if (!titleElement) return; const title = titleElement.textContent.trim(); const year = document.querySelector('.filmCoverSection__year')?.textContent.trim() || ''; const ratingsContainer = document.createElement('div'); ratingsContainer.style.cssText = ` margin-top: 15px; display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; `; const filmCoverSection = document.querySelector('.filmCoverSection__card'); if (!filmCoverSection) return; const placeholders = { imdb: createRatingElement(ICONS.imdb, 'Loading...', null), rotten: createRatingElement(ICONS.rotten, 'Loading...', null), metacritic: createRatingElement(ICONS.metacritic, 'Loading...', null) }; Object.values(placeholders).forEach(el => ratingsContainer.appendChild(el)); filmCoverSection.appendChild(ratingsContainer); try { const [imdb, rotten, metacritic] = await Promise.all([ getIMDbRating(title, year), getRottenTomatoesRating(title, year), getMetacriticRating(title, year) ]); if (imdb) placeholders.imdb.replaceWith(createRatingElement(ICONS.imdb, imdb.rating, imdb.url)); if (rotten) placeholders.rotten.replaceWith(createRatingElement(ICONS.rotten, rotten.rating, rotten.url)); if (metacritic) placeholders.metacritic.replaceWith(createRatingElement(ICONS.metacritic, metacritic.rating, metacritic.url)); } catch (error) { console.error('Error fetching ratings:', error); } } init(); })();