返回首頁 

Greasy Fork is available in English.

Show Rottentomatoes meter

Show Rotten Tomatoes score on imdb.com, metacritic.com, letterboxd.com, BoxOfficeMojo, serienjunkies.de, Amazon, Google Play, allmovie.com, Wikipedia, themoviedb.org, movies.com, tvmaze.com, tvguide.com, followshows.com, thetvdb.com, tvnfo.com, save.tv


Установить этот скрипт?
Рекомендуемый автором скрипт

Вам также может понравится Show Rottentomatoes meter - Trakt UI Addon.


Установить этот скрипт
// ==UserScript==// @name        Show Rottentomatoes meter// @description Show Rotten Tomatoes score on imdb.com, metacritic.com, letterboxd.com, BoxOfficeMojo, serienjunkies.de, Amazon, Google Play, allmovie.com, Wikipedia, themoviedb.org, movies.com, tvmaze.com, tvguide.com, followshows.com, thetvdb.com, tvnfo.com, save.tv// @namespace   cuzi// @grant       GM_xmlhttpRequest// @grant       GM_setValue// @grant       GM_getValue// @grant       unsafeWindow// @grant       GM.xmlHttpRequest// @grant       GM.setValue// @grant       GM.getValue// @require     https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js// @license     GPL-3.0-or-later; https://www.gnu.org/licenses/gpl-3.0.txt// @icon        https://raw.githubusercontent.com/hfg-gmuend/openmoji/master/color/72x72/1F345.png// @version     48// @connect     www.rottentomatoes.com// @connect     algolia.net// @connect     flixster.com// @connect     imdb.com// @match       https://www.rottentomatoes.com/// @match       https://play.google.com/store/movies/details/*// @match       https://www.amazon.ca/*// @match       https://www.amazon.co.jp/*// @match       https://www.amazon.co.uk/*// @match       https://smile.amazon.co.uk/*// @match       https://www.amazon.com.au/*// @match       https://www.amazon.com.mx/*// @match       https://www.amazon.com/*// @match       https://smile.amazon.com/*// @match       https://www.amazon.de/*// @match       https://smile.amazon.de/*// @match       https://www.amazon.es/*// @match       https://www.amazon.fr/*// @match       https://www.amazon.in/*// @match       https://www.amazon.it/*// @match       https://www.imdb.com/title/*// @match       https://www.serienjunkies.de/*// @match       http://www.serienjunkies.de/*// @match       https://www.boxofficemojo.com/movies/*// @match       https://www.boxofficemojo.com/release/*// @match       https://www.allmovie.com/movie/*// @match       https://en.wikipedia.org/*// @match       https://www.fandango.com/*// @match       https://www.themoviedb.org/movie/*// @match       https://www.themoviedb.org/tv/*// @match       https://letterboxd.com/film/*// @match       https://letterboxd.com/film/*/image*// @match       https://www.tvmaze.com/shows/*// @match       https://www.tvguide.com/tvshows/*// @match       https://followshows.com/show/*// @match       https://thetvdb.com/series/*// @match       https://thetvdb.com/movies/*// @match       https://tvnfo.com/tv/*// @match       https://www.metacritic.com/movie/*// @match       https://www.metacritic.com/tv/*// @match       https://www.nme.com/reviews/*// @match       https://itunes.apple.com/*// @match       https://epguides.com/*// @match       https://www.epguides.com/*// @match       https://www.cc.com/*// @match       https://www.amc.com/*// @match       https://www.amcplus.com/*// @match       https://rlsbb.ru/*/// @match       https://www.sho.com/*// @match       https://www.gog.com/*// @match       https://psa.wf/*// @match       https://www.save.tv/*// @match       https://www.wikiwand.com/*// @match       https://trakt.tv/*// ==/UserScript==/* global GM, $, unsafeWindow *//* jshint asi: true, esversion: 8 */const scriptName = 'Show Rottentomatoes meter'const baseURL = 'https://www.rottentomatoes.com'const baseURLOpenTab = baseURL + '/search/?search={query}'const algoliaURL = 'https://{domain}-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent={agent}&x-algolia-api-key={sId}&x-algolia-application-id={aId}'const algoliaAgent = 'Algolia for JavaScript (4.12.0); Browser (lite)'const flixsterEMSURL = 'https://flixster.com/api/ems/v2/emsId/{emsId}'const cacheExpireAfterHours = 4const emojiTomato = String.fromCodePoint(0x1F345)const emojiGreenApple = String.fromCodePoint(0x1F34F)const emojiStrawberry = String.fromCodePoint(0x1F353)const emojiPopcorn = '\uD83C\uDF7F'const emojiGreenSalad = '\uD83E\uDD57'const emojiNauseated = '\uD83E\uDD22'// Detect dark theme of darkreader.org extension or normal css dark theme from browserconst darkTheme = ('darkreaderScheme' in document.documentElement.dataset && document.documentElement.dataset.darkreaderScheme) || (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)function minutesSince (time) {const seconds = ((new Date()).getTime() - time.getTime()) / 1000return seconds > 60 ? parseInt(seconds / 60) + ' min ago' : 'now'}function intersection (setA, setB) {// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Setconst _intersection = new Set()for (const elem of setB) {if (setA.has(elem)) {_intersection.add(elem)}}return _intersection}function asyncRequest (data) { // No cache (unlike in the Metacritic userscript)return new Promise(function (resolve, reject) {const defaultHeaders = {Referer: data.url,'User-Agent': navigator.userAgent}const defaultData = {method: 'GET',onload: (response) => resolve(response),onerror: (response) => reject(response)}if ('headers' in data) {data.headers = Object.assign(defaultHeaders, data.headers)} else {data.headers = defaultHeaders}data = Object.assign(defaultData, data)console.debug(`${scriptName}: GM.xmlHttpRequest`, data)GM.xmlHttpRequest(data)})}const parseLDJSONCache = {}function parseLDJSON (keys, condition) {if (document.querySelector('script[type="application/ld+json"]')) {const xmlEntitiesElement = document.createElement('div')const xmlEntitiesPattern = /&(?:#x[a-f0-9]+|#[0-9]+|[a-z0-9]+);?/igconst xmlEntities = function (s) {s = s.replace(xmlEntitiesPattern, (m) => {xmlEntitiesElement.innerHTML = mreturn xmlEntitiesElement.textContent})return s}const decodeXmlEntities = function (jsonObj) {// Traverse through object, decoding all stringsif (jsonObj !== null && typeof jsonObj === 'object') {Object.entries(jsonObj).forEach(([key, value]) => {// key is either an array index or object keyjsonObj[key] = decodeXmlEntities(value)})} else if (typeof jsonObj === 'string') {return xmlEntities(jsonObj)}return jsonObj}const data = []const scripts = document.querySelectorAll('script[type="application/ld+json"]')for (let i = 0; i < scripts.length; i++) {let jsonldif (scripts[i].innerText in parseLDJSONCache) {jsonld = parseLDJSONCache[scripts[i].innerText]} else {try {jsonld = JSON.parse(scripts[i].innerText)parseLDJSONCache[scripts[i].innerText] = jsonld} catch (e) {parseLDJSONCache[scripts[i].innerText] = nullcontinue}}if (jsonld) {if (Array.isArray(jsonld)) {data.push(...jsonld)} else {data.push(jsonld)}}}for (let i = 0; i < data.length; i++) {try {if (data[i] && data[i] && (typeof condition !== 'function' || condition(data[i]))) {if (Array.isArray(keys)) {const r = []for (let j = 0; j < keys.length; j++) {r.push(data[i][keys[j]])}return decodeXmlEntities(r)} else if (keys) {return decodeXmlEntities(data[i][keys])} else if (typeof condition === 'function') {return decodeXmlEntities(data[i]) // Return whole object}}} catch (e) {continue}}return decodeXmlEntities(data)}return null}function askFlixsterEMS (emsId) {return new Promise(function flixsterEMSRequest (resolve) {GM.getValue('flixsterEmsCache', '{}').then(function (s) {const flixsterEmsCache = JSON.parse(s)// Delete algoliaCached values, that are expiredfor (const prop in flixsterEmsCache) {if ((new Date()).getTime() - (new Date(flixsterEmsCache[prop].time)).getTime() > cacheExpireAfterHours * 60 * 60 * 1000) {delete flixsterEmsCache[prop]}}// Check cache or request new contentif (emsId in flixsterEmsCache) {return resolve(flixsterEmsCache[emsId])}const url = flixsterEMSURL.replace('{emsId}', encodeURIComponent(emsId))GM.xmlHttpRequest({method: 'GET',url,onload: function (response) {let data = nulltry {data = JSON.parse(response.responseText)} catch (e) {console.error(`${scriptName}: flixster ems JSON Error\nURL: ${url}`)console.error(e)data = {}}// Save to flixsterEmsCachedata.time = (new Date()).toJSON()flixsterEmsCache[emsId] = dataGM.setValue('flixsterEmsCache', JSON.stringify(flixsterEmsCache))resolve(data)},onerror: function (response) {console.error(`${scriptName}: flixster ems GM.xmlHttpRequest Error: ${response.status}\nURL: ${url}\nResponse:\n${response.responseText}`)resolve(null)}})})})}async function addFlixsterEMS (orgData) {const flixsterData = await askFlixsterEMS(orgData.emsId)if (!flixsterData || !('tomatometer' in flixsterData)) {return orgData}if ('certifiedFresh' in flixsterData.tomatometer && flixsterData.tomatometer.certifiedFresh) {orgData.meterClass = 'certified_fresh'}if ('numReviews' in flixsterData.tomatometer && flixsterData.tomatometer.numReviews) {orgData.numReviews = flixsterData.tomatometer.numReviewsif ('freshCount' in flixsterData.tomatometer && flixsterData.tomatometer.freshCount != null) {orgData.freshCount = flixsterData.tomatometer.freshCount}if ('rottenCount' in flixsterData.tomatometer && flixsterData.tomatometer.rottenCount != null) {orgData.rottenCount = flixsterData.tomatometer.rottenCount}}if ('consensus' in flixsterData.tomatometer && flixsterData.tomatometer.consensus) {orgData.consensus = flixsterData.tomatometer.consensus}if ('avgScore' in flixsterData.tomatometer && flixsterData.tomatometer.avgScore != null) {orgData.avgScore = flixsterData.tomatometer.avgScore}if ('userRatingSummary' in flixsterData) {if ('scoresCount' in flixsterData.userRatingSummary && flixsterData.userRatingSummary.scoresCount) {orgData.audienceCount = flixsterData.userRatingSummary.scoresCount} else if ('dtlScoreCount' in flixsterData.userRatingSummary && flixsterData.userRatingSummary.dtlScoreCount) {orgData.audienceCount = flixsterData.userRatingSummary.dtlScoreCount}if ('wtsCount' in flixsterData.userRatingSummary && flixsterData.userRatingSummary.wtsCount) {orgData.audienceWantToSee = flixsterData.userRatingSummary.wtsCount} else if ('dtlWtsCount' in flixsterData.userRatingSummary && flixsterData.userRatingSummary.dtlWtsCount) {orgData.audienceWantToSee = flixsterData.userRatingSummary.dtlWtsCount}if ('reviewCount' in flixsterData.userRatingSummary && flixsterData.userRatingSummary.reviewCount) {orgData.audienceReviewCount = flixsterData.userRatingSummary.reviewCount}if ('avgScore' in flixsterData.userRatingSummary && flixsterData.userRatingSummary.avgScore) {orgData.audienceAvgScore = flixsterData.userRatingSummary.avgScore}}return orgData}function updateAlgolia () {// Get algolia data from https://www.rottentomatoes.com/const algoliaSearch = { aId: null, sId: null }if (unsafeWindow.RottenTomatoes && 'thirdParty' in unsafeWindow.RottenTomatoes && 'algoliaSearch' in unsafeWindow.RottenTomatoes.thirdParty) {if (typeof (unsafeWindow.RottenTomatoes.thirdParty.algoliaSearch.aId) === 'string' && typeof (unsafeWindow.RottenTomatoes.thirdParty.algoliaSearch.sId) === 'string') {algoliaSearch.aId = unsafeWindow.RottenTomatoes.thirdParty.algoliaSearch.aId // x-algolia-application-idalgoliaSearch.sId = unsafeWindow.RottenTomatoes.thirdParty.algoliaSearch.sId // x-algolia-api-key}}if (algoliaSearch.aId) {GM.setValue('algoliaSearch', JSON.stringify(algoliaSearch)).then(function () {console.debug(`${scriptName}: Updated algoliaSearch: ${JSON.stringify(algoliaSearch)}`)})} else {console.debug(`${scriptName}: algoliaSearch.aId is ${algoliaSearch.aId}`)}}function meterBar (data) {// Create the "progress" bar with the meter scorelet barColor = 'grey'let bgColor = darkTheme ? '#3e3e3e' : '#ECE4B5'let color = 'black'let width = 0let textInside = ''let textAfter = ''if (data.meterClass === 'certified_fresh') {barColor = '#C91B22'color = 'yellow'textInside = emojiStrawberry + ' ' + data.meterScore.toLocaleString() + '%'width = data.meterScore || 0} else if (data.meterClass === 'fresh') {barColor = '#C91B22'color = 'white'textInside = emojiTomato + ' ' + data.meterScore.toLocaleString() + '%'width = data.meterScore || 0} else if (data.meterClass === 'rotten') {color = 'gray'barColor = '#94B13C'if (data.meterScore && data.meterScore > 30) {textAfter = '<span style="font-size: 15px;padding-top: 2px;display: inline-block;">' + data.meterScore.toLocaleString() + '%</span>'textInside = '<span style="font-size:13px">' + emojiGreenApple + '</span>'} else {textAfter = data.meterScore.toLocaleString() + '% <span style="font-size:13px">' + emojiGreenApple + '</span>'}width = data.meterScore || 0} else {bgColor = barColor = '#787878'color = 'silver'textInside = 'N/A'width = 100}let title = 'Critics ' + (typeof data.meterScore === 'number' ? data.meterScore.toLocaleString() : 'N/A') + '% ' + data.meterClasslet avg = ''if ('avgScore' in data) {const node = document.createElement('span')node.innerHTML = data.consensustitle += '\nAverage score: ' + data.avgScore.toLocaleString() + ' / 10'avg = '<span style="font-weight:bolder">' + data.avgScore.toLocaleString() + '</span>/10'}if ('numReviews' in data && typeof data.numReviews === 'number') {title += ' from ' + data.numReviews.toLocaleString() + ' reviews'if ('freshCount' in data && data.numReviews > 0) {const p = parseInt(100 * parseFloat(data.freshCount) / parseFloat(data.numReviews))title += '\n' + data.freshCount.toLocaleString() + '/' + data.numReviews.toLocaleString() + ' ' + p + '% fresh reviews'}if ('rottenCount' in data) {const p = parseInt(100 * parseFloat(data.rottenCount) / parseFloat(data.numReviews))title += '\n' + data.rottenCount.toLocaleString() + '/' + data.numReviews.toLocaleString() + ' ' + p + '% rotten reviews'}}if ('consensus' in data) {const node = document.createElement('span')node.innerHTML = data.consensustitle += '\n' + node.textContent}return '<div title="' + title + '" style="cursor:help;">' +'<div style="float:left; margin-top:1px; width:100px; overflow: hidden;height: 20px;background-color: ' + bgColor + ';color: ' + color + ';text-align:center; border-radius: 4px;box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);">' +'<div style="width:' + width + '%; background-color: ' + barColor + '; color: ' + color + '; font-size:14px; font-weight:bold; text-align:center; float:left; height: 100%;line-height: 20px;box-shadow: inset 0 -1px 0 rgba(0,0,0,0.15);transition: width 0.6s ease;">' +textInside +'</div>' +textAfter +'</div>' +'<div style="float:left; padding: 3px 0px 0px 3px;">' + avg + '</div>' +'<div style="clear:left;"></div>' +'</div>'}function audienceBar (data) {// Create the "progress" bar with the audience scoreif (!('audienceScore' in data) || data.audienceScore === null) {return ''}let barColor = 'grey'let bgColor = darkTheme ? '#3e3e3e' : '#ECE4B5'let color = 'black'let width = 0let textInside = ''let textAfter = ''let avg = ''if (data.audienceClass === 'red_popcorn') {barColor = '#C91B22'color = data.audienceScore > 94 ? 'yellow' : 'white'textInside = emojiPopcorn + ' ' + data.audienceScore.toLocaleString() + '%'width = data.audienceScore} else if (data.audienceClass === 'green_popcorn') {color = 'gray'barColor = '#94B13C'if (data.audienceScore > 30) {textAfter = '<span style="font-size: 15px;padding-top: 2px;display: inline-block;">' + data.audienceScore.toLocaleString() + '%</span>'textInside = '<span style="font-size:13px">' + emojiGreenSalad + '</span>'} else {textAfter = data.audienceScore.toLocaleString() + '% <span style="font-size:13px">' + emojiNauseated + '</span>'}width = data.audienceScore} else {bgColor = barColor = '#787878'color = 'silver'textInside = 'N/A'width = 100}let title = 'Audience ' + (typeof data.audienceScore === 'number' ? data.audienceScore.toLocaleString() : 'N/A') + '% ' + data.audienceClassconst titleLine2 = []if ('audienceCount' in data && typeof data.audienceCount === 'number') {titleLine2.push(data.audienceCount.toLocaleString() + ' Votes')}if ('audienceReviewCount' in data) {titleLine2.push(data.audienceReviewCount.toLocaleString() + ' Reviews')}if ('audienceAvgScore' in data && typeof data.audienceAvgScore === 'number') {titleLine2.push('Average score: ' + data.audienceAvgScore.toLocaleString() + ' / 5 stars')avg = '<span style="font-weight:bolder">' + data.audienceAvgScore.toLocaleString() + '</span>/5'}if ('audienceWantToSee' in data && typeof data.audienceWantToSee === 'number') {titleLine2.push(data.audienceWantToSee.toLocaleString() + ' want to see')}title = title + (titleLine2 ? ('\n' + titleLine2.join('\n')) : '')return '<div title="' + title + '" style="cursor:help;">' +'<div style="float:left; margin-top:1px; width:100px; overflow: hidden;height: 20px;background-color: ' + bgColor + ';color: ' + color + ';text-align:center; border-radius: 4px;box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);">' +'<div style="width:' + width + '%; background-color: ' + barColor + '; color: ' + color + '; font-size:14px; font-weight:bold; text-align:center; float:left; height: 100%;line-height: 20px;box-shadow: inset 0 -1px 0 rgba(0,0,0,0.15);transition: width 0.6s ease;">' +textInside +'</div>' +textAfter +'</div>' +'<div style="float:left; padding: 3px 0px 0px 3px;">' + avg + '</div>' +'<div style="clear:left;"></div>' +'</div>'}const current = {type: null,query: null,year: null}async function loadMeter (query, type, year) {// Load data from rotten tomatoes search API or from cachecurrent.type = typecurrent.query = querycurrent.year = yearconst algoliaCache = JSON.parse(await GM.getValue('algoliaCache', '{}'))// Delete algoliaCached values, that are expiredfor (const prop in algoliaCache) {if ((new Date()).getTime() - (new Date(algoliaCache[prop].time)).getTime() > cacheExpireAfterHours * 60 * 60 * 1000) {delete algoliaCache[prop]}}const algoliaSearch = JSON.parse(await GM.getValue('algoliaSearch', '{}'))// Check cache or request new contentif (query in algoliaCache) {// Use cached responseconsole.debug(`${scriptName}: Use cached algolia response`)handleAlgoliaResponse(algoliaCache[query])} else if ('aId' in algoliaSearch && 'sId' in algoliaSearch) {// Use algolia.net APIconst url = algoliaURL.replace('{domain}', algoliaSearch.aId.toLowerCase()).replace('{aId}', encodeURIComponent(algoliaSearch.aId)).replace('{sId}', encodeURIComponent(algoliaSearch.sId)).replace('{agent}', encodeURIComponent(algoliaAgent))GM.xmlHttpRequest({method: 'POST',url,data: '{"requests":[{"indexName":"content_rt","query":"' + query.replace('"', '') + '","params":"filters=isEmsSearchable%20%3D%201&hitsPerPage=20"}]}',onload: function (response) {// Save to algoliaCacheresponse.time = (new Date()).toJSON()// Chrome fix: Otherwise JSON.stringify(cache) omits responseTextconst newobj = {}for (const key in response) {newobj[key] = response[key]}newobj.responseText = response.responseTextalgoliaCache[query] = newobjGM.setValue('algoliaCache', JSON.stringify(algoliaCache))handleAlgoliaResponse(response)},onerror: function (response) {console.error(`${scriptName}: algoliaSearch GM.xmlHttpRequest Error: ${response.status}\nURL: ${url}\nResponse:\n${response.responseText}`)}})} else {console.error(`${scriptName}: algoliaSearch not configured`)window.alert(scriptName + ' userscript\n\nYou need to visit www.rottentomatoes.com at least once before the script can work.\n\nThe script needs to read some API keys from the website.')showMeter('ALGOLIA_NOT_CONFIGURED', new Date())}}function matchQuality (title, year, currentSet) {if (title === current.query && year === current.year) {return 104 + year}if (title.toLowerCase() === current.query.toLowerCase() && year === current.year) {return 103 + year}if (title === current.query && current.year) {return 102 - Math.abs(year - current.year)}if (title.toLowerCase() === current.query.toLowerCase() && current.year) {return 101 - Math.abs(year - current.year)}if (title.replace(/\(.+\)/, '').trim() === current.query && current.year) {return 100 - Math.abs(year - current.year)}if (title === current.query) {return 8}if (title.replace(/\(.+\)/, '').trim() === current.query) {return 7}if (title.startsWith(current.query)) {return 6}if (current.query.indexOf(title) !== -1) {return 5}if (title.indexOf(current.query) !== -1) {return 4}if (current.query.toLowerCase().indexOf(title.toLowerCase()) !== -1) {return 3}if (title.toLowerCase().indexOf(current.query.toLowerCase()) !== -1) {return 2}const titleSet = new Set(title.replace(/[^a-z ]/gi, ' ').split(' '))const score = intersection(titleSet, currentSet).size - 20if (year === current.year) {return score + 1}return score}async function handleAlgoliaResponse (response) {// Handle GM.xmlHttpRequest responseconst rawData = JSON.parse(response.responseText)// Filter according to typeconst hits = rawData.r###lts[0].hits.filter(hit => hit.type === current.type)// Change data structureconst arr = []hits.forEach(function (hit) {const r###lt = {name: hit.title,year: parseInt(hit.releaseYear),url: '/' + (current.type === 'tv' ? 'tv' : 'm') + '/' + ('vanity' in hit ? hit.vanity : hit.title.toLowerCase()),meterClass: null,meterScore: null,audienceClass: null,audienceScore: null,emsId: hit.emsId}if ('rottenTomatoes' in hit) {if ('criticsIconUrl' in hit.rottenTomatoes) {r###lt.meterClass = hit.rottenTomatoes.criticsIconUrl.match(/\/(\w+)\.png/)[1]}if ('criticsScore' in hit.rottenTomatoes) {r###lt.meterScore = hit.rottenTomatoes.criticsScore}if ('audienceIconUrl' in hit.rottenTomatoes) {r###lt.audienceClass = hit.rottenTomatoes.audienceIconUrl.match(/\/(\w+)\.png/)[1]}if ('audienceScore' in hit.rottenTomatoes) {r###lt.audienceScore = hit.rottenTomatoes.audienceScore}if ('certifiedFresh' in hit.rottenTomatoes && hit.rottenTomatoes.certifiedFresh) {r###lt.meterClass = 'certified_fresh'}}arr.push(r###lt)})// Sort r###lts by closest matchconst currentSet = new Set(current.query.replace(/[^a-z ]/gi, ' ').split(' '))arr.sort(function (a, b) {if (!Object.prototype.hasOwnProperty.call(a, 'matchQuality')) {a.matchQuality = matchQuality(a.name, a.year, currentSet)}if (!Object.prototype.hasOwnProperty.call(b, 'matchQuality')) {b.matchQuality = matchQuality(b.name, b.year, currentSet)}return b.matchQuality - a.matchQuality})if (arr.length > 0 && arr[0].meterScore) {// Get more details for first r###ltarr[0] = await addFlixsterEMS(arr[0])}if (arr) {showMeter(arr, new Date(response.time))} else {console.debug(`${scriptName}: No r###lts for ${current.query}`)}}function showMeter (arr, time) {// Show a small box in the right lower corner$('#mcdiv321rotten').remove()let main, divdiv = main = $('<div id="mcdiv321rotten"></div>').appendTo(document.body)div.css({position: 'fixed',bottom: 0,right: 0,minWidth: 100,maxWidth: 400,maxHeight: '95%',overflow: 'auto',backgroundColor: darkTheme ? '#262626' : 'white',border: darkTheme ? '2px solid #444' : '2px solid #bbb',borderRadius: ' 6px',boxShadow: '0 0 3px 3px rgba(100, 100, 100, 0.2)',color: darkTheme ? 'white' : 'black',padding: ' 3px',zIndex: '5010001',fontFamily: 'Helvetica,Arial,sans-serif'})const CSS = `<style>#mcdiv321rotten {transition:bottom 0.7s, height 0.5s;}</style>`$(CSS).appendTo(div)if (arr === 'ALGOLIA_NOT_CONFIGURED') {$('<div>You need to visit <a href="https://www.rottentomatoes.com/">www.rottentomatoes.com</a> at least once to enable the script.</div>').appendTo(main)return}// First r###lt$('<div class="firstR###lt"><a style="font-size:small; color:#136CB2; " href="' + baseURL + arr[0].url + '">' + arr[0].name + ' (' + arr[0].year + ')</a>' + meterBar(arr[0]) + audienceBar(arr[0]) + '</div>').appendTo(main)// Shall the following r###lts be collapsed by default?if ((arr.length > 1 && arr[0].matchQuality > 10) || arr.length > 10) {$('<span style="color:gray;font-size: x-small">More r###lts...</span>').appendTo(main).click(function () { more.css('display', 'block'); this.parentNode.removeChild(this) })const more = div = $('<div style="display:none"></div>').appendTo(main)}// More r###ltsfor (let i = 1; i < arr.length; i++) {$('<div><a style="font-size:small; color:#136CB2; " href="' + baseURL + arr[i].url + '">' + arr[i].name + ' (' + arr[i].year + ')</a>' + meterBar(arr[i]) + audienceBar(arr[i]) + '</div>').appendTo(div)}// Footerconst sub = $('<div></div>').appendTo(main)$('<time style="color:#b6b6b6; font-size: 11px;" datetime="' + time + '" title="' + time.toLocaleTimeString() + ' ' + time.toLocaleDateString() + '">' + minutesSince(time) + '</time>').appendTo(sub)$('<a style="color:#b6b6b6; font-size: 11px;" target="_blank" href="' + baseURLOpenTab.replace('{query}', encodeURIComponent(current.query)) + '" title="Open Rotten Tomatoes">@rottentomatoes.com</a>').appendTo(sub)$('<span title="Hide me" style="cursor:pointer; float:right; color:#b6b6b6; font-size: 11px; padding-left:5px;padding-top:3px">&#10062;</span>').appendTo(sub).click(function () {document.body.removeChild(this.parentNode.parentNode)})}const Always = () => trueconst sites = {googleplay: {host: ['play.google.com'],condition: Always,products: [{condition: () => ~document.location.href.indexOf('/movies/details/'),type: 'movie',data: () => document.querySelector('*[itemprop=name]').textContent}]},imdb: {host: ['imdb.com'],condition: () => !~document.location.pathname.indexOf('/mediaviewer') && !~document.location.pathname.indexOf('/mediaindex') && !~document.location.pathname.indexOf('/videoplayer'),products: [{condition: function () {const e = document.querySelector("meta[property='og:type']")if (e && e.content === 'video.movie') {return true} else if (document.querySelector('[data-testid="hero__pageTitle"]') && !document.querySelector('[data-testid="hero-subnav-bar-left-block"] a[href*="episodes/"]')) {return true}return false},type: 'movie',data: async function () {let year = nulllet ld = nullif (document.querySelector('script[type="application/ld+json"]')) {ld = parseLDJSON(['name', 'alternateName', 'datePublished'])if (ld.length > 2) {year = parseInt(ld[2].match(/\d{4}/)[0])}}const pageNotEnglish = document.querySelector('[for="nav-language-selector"]').textContent.toLowerCase() !== 'en' || !navigator.language.startsWith('en')const pageNotMovieHomePage = !document.title.match(/(.+?)\s+(\((\d+)\))? - IMDb/)// If the page is not in English or the browser is not in English, request page in English.// Then the title in <h1> will be the English title and Metacritic always uses the English title.if (pageNotEnglish || pageNotMovieHomePage) {// Set language cookie to English, request current page in English, then restore language cookie or expire it if it didn't exist beforeconst imdbID = document.location.pathname.match(/\/title\/(\w+)/)[1]const homePageUrl = 'https://www.imdb.com/title/' + imdbID + '/?ref_=nv_sr_1'const langM = document.cookie.match(/lc-main=([^;]+)/)const langBefore = langM ? langM[0] : ';expires=Thu, 01 Jan 1970 00:00:01 GMT'document.cookie = 'lc-main=en-US'const response = await asyncRequest({url: homePageUrl,headers: {'Accept-Language': 'en-US,en'}}).catch(function (response) {console.warn('ShowRottentomatoes: Error imdb02\nurl=' + homePageUrl + '\nstatus=' + response.status)})document.cookie = 'lc-main=' + langBefore// Extract <h1> titleconst parts = response.responseText.split('</span></h1>')[0].split('>')const title = parts[parts.length - 1]if (!year) {// extract yearconst yearM = response.responseText.match(/href="\/title\/\w+\/releaseinfo.*">(\d{4})<\/a>/)if (yearM) {year = yearM[1]}}console.debug('ShowRottentomatoes: Movie title from English page:', title, year)return [title, year]} else if (ld) {if (ld.length > 1 && ld[1]) {console.debug('ShowRottentomatoes: Movie ld+json alternateName', ld[1], year)return [ld[1], year]}console.debug('ShowRottentomatoes: Movie ld+json name', ld[0], year)return [ld[0], year]} else {const m = document.title.match(/(.+?)\s+(\((\d+)\))? - /)console.debug('ShowRottentomatoes: Movie <title>', [m[1], m[3]])return [m[1], parseInt(m[3])]}}},{condition: function () {const e = document.querySelector("meta[property='og:type']")if (e && e.content === 'video.tv_show') {return true} else if (document.querySelector('[data-testid="hero-subnav-bar-left-block"] a[href*="episodes/"]')) {return true}return false},type: 'tv',data: async function () {let year = nulllet ld = nullif (document.querySelector('script[type="application/ld+json"]')) {ld = parseLDJSON(['name', 'alternateName', 'datePublished'])if (ld.length > 2) {year = parseInt(ld[2].match(/\d{4}/)[0])}}const pageNotEnglish = document.querySelector('[for="nav-language-selector"]').textContent.toLowerCase() !== 'en' || !navigator.language.startsWith('en')const pageNotMovieHomePage = !document.title.match(/(.+?)\s+\(.+(\d{4})–.{0,4}\) - IMDb/)// If the page is not in English or the browser is not in English, request page in English.// Then the title in <h1> will be the English title and Metacritic always uses the English title.if (pageNotEnglish || pageNotMovieHomePage) {const imdbID = document.location.pathname.match(/\/title\/(\w+)/)[1]const homePageUrl = 'https://www.imdb.com/title/' + imdbID + '/?ref_=nv_sr_1'// Set language cookie to English, request current page in English, then restore language cookie or expire it if it didn't exist beforeconst langM = document.cookie.match(/lc-main=([^;]+)/)const langBefore = langM ? langM[0] : ';expires=Thu, 01 Jan 1970 00:00:01 GMT'document.cookie = 'lc-main=en-US'const response = await asyncRequest({url: homePageUrl,headers: {'Accept-Language': 'en-US,en'}}).catch(function (response) {console.warn('ShowRottentomatoes: Error imdb03\nurl=' + homePageUrl + '\nstatus=' + response.status)})document.cookie = 'lc-main=' + langBefore// Extract <h1> titleconst parts = response.responseText.split('</span></h1>')[0].split('>')const title = parts[parts.length - 1]if (!year) {// extract yearconst yearM = response.responseText.match(/href="\/title\/\w+\/releaseinfo.*">(\d{4})/)if (yearM) {year = yearM[1]}}console.debug('ShowRottentomatoes: TV title from English page:', title, year)return [title, year]} else if (ld) {if (ld.length > 1 && ld[1]) {console.debug('ShowRottentomatoes: TV ld+json alternateName', ld[1], year)return [ld[1], year]}console.debug('ShowRottentomatoes: TV ld+json name', ld[0], year)return [ld[0], year]} else {const m = document.title.match(/(.+?)\s+\(.+(\d{4}).+/)console.debug('ShowRottentomatoes: TV <title>', [m[1], m[2]])return [m[1], parseInt(m[2])]}}}]},'tv.com': {host: ['www.tv.com'],condition: () => document.querySelector("meta[property='og:type']"),products: [{condition: () => document.querySelector("meta[property='og:type']").content === 'tv_show' && document.querySelector('h1[data-name]'),type: 'tv',data: () => document.querySelector('h1[data-name]').dataset.name}]},metacritic: {host: ['www.metacritic.com'],condition: () => document.querySelector("meta[property='og:type']"),products: [{condition: () => document.querySelector("meta[property='og:type']").content === 'video.movie',type: 'movie',data: function () {let year = nullif (document.querySelector('.release_year')) {year = parseInt(document.querySelector('.release_year').firstChild.textContent)} else if (document.querySelector('.release_data .data')) {year = document.querySelector('.release_data .data').textContent.match(/(\d{4})/)[1]}return [document.querySelector("meta[property='og:title']").content, year]}},{condition: () => document.querySelector("meta[property='og:type']").content === 'video.tv_show',type: 'tv',data: function () {let title = document.querySelector("meta[property='og:title']").contentlet year = nullif (title.match(/\s\(\d{4}\)$/)) {year = parseInt(title.match(/\s\((\d{4})\)$/)[1])title = title.replace(/\s\(\d{4}\)$/, '') // Remove year} else if (document.querySelector('.release_date')) {year = document.querySelector('.release_date').textContent.match(/(\d{4})/)[1]}return [title, year]}}]},serienjunkies: {host: ['www.serienjunkies.de'],condition: Always,products: [{condition: () => document.getElementById('serienlinksbreit2aktuell'),type: 'tv',data: () => document.querySelector('h1').textContent.trim()},{condition: () => document.location.pathname.search(/vod\/film\/.{3,}/) !== -1,type: 'movie',data: () => document.querySelector('h1').textContent.trim()}]},amazon: {host: ['amazon.'],condition: Always,products: [{condition: () => (document.querySelector('[data-automation-id=title]') && (document.getElementsByClassName('av-season-single').length ||document.querySelector('[data-automation-id="num-of-seasons-badge"]') ||document.getElementById('tab-selector-episodes') ||document.getElementById('av-droplist-av-atf-season-selector'))),type: 'tv',data: () => document.querySelector('[data-automation-id=title]').textContent.trim()},{condition: () => ((document.getElementsByClassName('av-season-single').length ||document.querySelector('[data-automation-id="num-of-seasons-badge"]') ||document.getElementById('tab-selector-episodes') ||document.getElementById('av-droplist-av-atf-season-selector')) && Array.from(document.querySelectorAll('script[type="text/template"]')).map(e => e.innerHTML.match(/parentTitle"\s*:\s*"(.+?)"/)).some((x) => x != null)),type: 'tv',data: () => Array.from(document.querySelectorAll('script[type="text/template"]')).map(e => e.innerHTML.match(/parentTitle"\s*:\s*"(.+?)"/)).filter((x) => x != null)[0][1]},{condition: () => document.querySelector('[data-automation-id=title]'),type: 'movie',data: () => document.querySelector('[data-automation-id=title]').textContent.trim().replace(/\[.{1,8}\]/, '')},{condition: () => document.querySelector('#watchNowContainer a[href*="/gp/video/"]'),type: 'movie',data: () => document.getElementById('productTitle').textContent.trim()}]},BoxOfficeMojo: {host: ['boxofficemojo.com'],condition: () => Always,products: [{condition: () => document.location.pathname.startsWith('/release/'),type: 'movie',data: function () {let year = nullconst cells = document.querySelectorAll('#body .mojo-summary-values .a-section span')for (let i = 0; i < cells.length; i++) {if (~cells[i].innerText.indexOf('Release Date')) {year = parseInt(cells[i].nextElementSibling.textContent.match(/\d{4}/)[0])break}}return [document.querySelector('meta[name=title]').content, year]}},{condition: () => ~document.location.search.indexOf('id=') && document.querySelector('#body table:nth-child(2) tr:first-child b'),type: 'movie',data: function () {let year = nulltry {const tds = document.querySelectorAll('#body table:nth-child(2) tr:first-child table table table td')for (let i = 0; i < tds.length; i++) {if (~tds[i].innerText.indexOf('Release Date')) {year = parseInt(tds[i].innerText.match(/\d{4}/)[0])break}}} catch (e) { }return [document.querySelector('#body table:nth-child(2) tr:first-child b').firstChild.textContent, year]}}]},AllMovie: {host: ['allmovie.com'],condition: () => document.querySelector('h2[itemprop=name].movie-title'),products: [{condition: () => document.querySelector('h2[itemprop=name].movie-title'),type: 'movie',data: () => document.querySelector('h2[itemprop=name].movie-title').firstChild.textContent.trim()}]},'en.wikipedia': {host: ['en.wikipedia.org'],condition: Always,products: [{condition: function () {if (!document.querySelector('.infobox .summary')) {return false}const r = /\d\d\d\d films/return $('#catlinks a').filter((i, e) => e.firstChild.textContent.match(r)).length},type: 'movie',data: () => document.querySelector('.infobox .summary').firstChild.textContent},{condition: function () {if (!document.querySelector('.infobox .summary')) {return false}const r = /television series/return $('#catlinks a').filter((i, e) => e.firstChild.textContent.match(r)).length},type: 'tv',data: () => document.querySelector('.infobox .summary').firstChild.textContent}]},fandango: {host: ['fandango.com'],condition: () => document.querySelector("meta[property='og:title']"),products: [{condition: Always,type: 'movie',data: () => document.querySelector("meta[property='og:title']").content.match(/(.+?)\s+\(\d{4}\)/)[1].trim()}]},themoviedb: {host: ['themoviedb.org'],condition: () => document.querySelector("meta[property='og:type']"),products: [{condition: () => document.querySelector("meta[property='og:type']").content === 'movie' ||document.querySelector("meta[property='og:type']").content === 'video.movie',type: 'movie',data: function () {let year = nulltry {year = parseInt(document.querySelector('.release_date').innerText.match(/\d{4}/)[0])} catch (e) {}return [document.querySelector("meta[property='og:title']").content, year]}},{condition: () => document.querySelector("meta[property='og:type']").content === 'tv' ||document.querySelector("meta[property='og:type']").content === 'tv_series' ||document.querySelector("meta[property='og:type']").content.indexOf('tv_show') !== -1,type: 'tv',data: () => document.querySelector("meta[property='og:title']").content}]},letterboxd: {host: ['letterboxd.com'],condition: () => unsafeWindow.filmData && 'name' in unsafeWindow.filmData,products: [{condition: Always,type: 'movie',data: () => [unsafeWindow.filmData.name, unsafeWindow.filmData.releaseYear]}]},TVmaze: {host: ['tvmaze.com'],condition: () => document.querySelector('h1'),products: [{condition: Always,type: 'tv',data: () => document.querySelector('h1').firstChild.textContent}]},TVGuide: {host: ['tvguide.com'],condition: Always,products: [{condition: () => document.location.pathname.startsWith('/tvshows/'),type: 'tv',data: function () {if (document.querySelector('meta[itemprop=name]')) {return document.querySelector('meta[itemprop=name]').content} else {return document.querySelector("meta[property='og:title']").content.split('|')[0]}}}]},followshows: {host: ['followshows.com'],condition: Always,products: [{condition: () => document.querySelector("meta[property='og:type']").content === 'video.tv_show',type: 'tv',data: () => document.querySelector("meta[property='og:title']").content}]},TheTVDB: {host: ['thetvdb.com'],condition: Always,products: [{condition: () => document.location.pathname.startsWith('/series/'),type: 'tv',data: () => document.getElementById('series_title').firstChild.textContent.trim()},{condition: () => document.location.pathname.startsWith('/movies/'),type: 'movie',data: () => document.getElementById('series_title').firstChild.textContent.trim()}]},TVNfo: {host: ['tvnfo.com'],condition: () => document.querySelector('#title #name'),products: [{condition: Always,type: 'tv',data: function () {const years = document.querySelector('#title #years').textContent.trim()const title = document.querySelector('#title #name').textContent.replace(years, '').trim()let year = nullif (years) {try {year = years.match(/\d{4}/)[0]} catch (e) {}}return [title, year]}}]},nme: {host: ['nme.com'],condition: () => document.location.pathname.startsWith('/reviews/'),products: [{condition: () => document.querySelector('.tdb-breadcrumbs a[href*="/reviews/film-reviews"]'),type: 'movie',data: function () {let year = nulltry {year = parseInt(document.querySelector('*[itemprop=datePublished]').content.match(/\d{4}/)[0])} catch (e) {}try {return [document.title.match(/[‘'](.+?)[’']/)[1], year]} catch (e) {try {return [document.querySelector('h1.tdb-title-text').textContent.match(/[‘'](.+?)[’']/)[1], year]} catch (e) {return [document.querySelector('h1').textContent.match(/:\s*(.+)/)[1].trim(), year]}}}},{condition: () => document.querySelector('.tdb-breadcrumbs a[href*="/reviews/tv-reviews"]'),type: 'tv',data: () => document.querySelector('h1.tdb-title-text').textContent.match(/‘(.+?)’/)[1]}]},itunes: {host: ['itunes.apple.com'],condition: Always,products: [{condition: () => ~document.location.href.indexOf('/movie/'),type: 'movie',data: () => parseLDJSON('name', (j) => (j['@type'] === 'Movie'))},{condition: () => ~document.location.href.indexOf('/tv-season/'),type: 'tv',data: function () {let name = parseLDJSON('name', (j) => (j['@type'] === 'TVSeries'))if (~name.indexOf(', Season')) {name = name.split(', Season')[0]}return name}}]},epguides: {host: ['epguides.com'],condition: () => document.getElementById('eplist'),products: [{condition: () => document.getElementById('eplist') && document.querySelector('.center.titleblock h2'),type: 'tv',data: () => document.querySelector('.center.titleblock h2').textContent.trim()}]},ComedyCentral: {host: ['cc.com'],condition: () => document.location.pathname.startsWith('/shows/'),products: [{condition: () => document.location.pathname.split('/').length === 3 && document.querySelector("meta[property='og:title']"),type: 'tv',data: () => document.querySelector("meta[property='og:title']").content.replace('| Comedy Central', '').trim()},{condition: () => document.location.pathname.split('/').length === 3 && document.title.match(/(.+?)\s+-\s+Series/),type: 'tv',data: () => document.title.match(/(.+?)\s+-\s+Series/)[1]}]},AMC: {host: ['amc.com'],condition: () => document.location.pathname.startsWith('/shows/'),products: [{condition: () => document.location.pathname.split('/').length === 3 && document.querySelector("meta[property='og:type']") && document.querySelector("meta[property='og:type']").content.indexOf('tv_show') !== -1,type: 'tv',data: () => document.querySelector('.video-card-description h1').textContent.trim()}]},AMCplus: {host: ['amcplus.com'],condition: () => Always,products: [{condition: () => document.title.match(/Watch .+? |/),type: 'tv',data: () => document.title.match(/Watch (.+?) |/)[1].trim()}]},RlsBB: {host: ['rlsbb.ru'],condition: () => document.querySelectorAll('.post').length === 1,products: [{condition: () => document.querySelector('#post-wrapper .entry-meta a[href*="/category/movies/"]'),type: 'movie',data: () => document.querySelector('h1.entry-title').textContent.match(/(.+?)\s+\d{4}/)[1].trim()},{condition: () => document.querySelector('#post-wrapper .entry-meta a[href*="/category/tv-shows/"]'),type: 'tv',data: () => document.querySelector('h1.entry-title').textContent.match(/(.+?)\s+S\d{2}/)[1].trim()}]},showtime: {host: ['sho.com'],condition: Always,products: [{condition: () => parseLDJSON('@type') === 'Movie',type: 'movie',data: () => parseLDJSON('name', (j) => (j['@type'] === 'Movie'))},{condition: () => parseLDJSON('@type') === 'TVSeries',type: 'tv',data: () => parseLDJSON('name', (j) => (j['@type'] === 'TVSeries'))}]},gog: {host: ['www.gog.com'],condition: () => document.querySelector('.productcard-basics__title'),products: [{condition: () => document.location.pathname.split('/').length > 2 && (document.location.pathname.split('/')[1] === 'movie' ||document.location.pathname.split('/')[2] === 'movie'),type: 'movie',data: () => document.querySelector('.productcard-basics__title').textContent}]},psapm: {host: ['psa.wf'],condition: Always,products: [{condition: () => document.location.pathname.startsWith('/movie/'),type: 'movie',data: function () {const title = document.querySelector('h1').textContent.trim()const m = title.match(/(.+)\((\d+)\)$/)if (m) {return [m[1].trim(), parseInt(m[2])]} else {return title}}},{condition: () => document.location.pathname.startsWith('/tv-show/'),type: 'tv',data: () => document.querySelector('h1').textContent.trim()}]},'save.tv': {host: ['save.tv'],condition: () => document.location.pathname.startsWith('/STV/M/obj/archive/'),products: [{condition: () => document.location.pathname.startsWith('/STV/M/obj/archive/'),type: 'movie',data: function () {let title = nullif (document.querySelector("span[data-bind='text:OrigTitle']")) {title = document.querySelector("span[data-bind='text:OrigTitle']").textContent} else {title = document.querySelector("h2[data-bind='text:Title']").textContent}let year = nullif (document.querySelector("span[data-bind='text:ProductionYear']")) {year = parseInt(document.querySelector("span[data-bind='text:ProductionYear']").textContent)}return [title, year]}}]},wikiwand: {host: ['www.wikiwand.com'],condition: Always,products: [{condition: function () {const title = document.querySelector('h1').textContent.toLowerCase()const subtitle = document.querySelector('h2[class*="subtitle"]') ? document.querySelector('h2[class*="subtitle"]').textContent.toLowerCase() : ''if (title.indexOf('film') === -1 && !subtitle) {return false}return title.indexOf('film') !== -1 ||subtitle.indexOf('film') !== -1 ||subtitle.indexOf('movie') !== -1},type: 'movie',data: () => document.querySelector('h1').textContent.replace(/\((\d{4} )?film\)/i, '').trim()},{condition: function () {const title = document.querySelector('h1').textContent.toLowerCase()const subtitle = document.querySelector('h2[class*="subtitle"]') ? document.querySelector('h2[class*="subtitle"]').textContent.toLowerCase() : ''if (title.indexOf('tv series') === -1 && !subtitle) {return false}return title.indexOf('tv series') !== -1 ||subtitle.indexOf('television') !== -1 ||subtitle.indexOf('tv series') !== -1},type: 'tv',data: () => document.querySelector('h1').textContent.replace(/\(tv series\)/i, '').trim()}]},trakt: {host: ['trakt.tv'],condition: Always,products: [{condition: () => document.location.pathname.startsWith('/movies/'),type: 'movie',data: function () {const title = Array.from(document.querySelector('.summary h1').childNodes).filter(node => node.nodeType === node.TEXT_NODE).map(node => node.textContent).join(' ').trim()const year = document.querySelector('.summary h1 .year').textContentreturn [title, year]}},{condition: () => document.location.pathname.startsWith('/shows/'),type: 'tv',data: () => Array.from(document.querySelector('.summary h1').childNodes).filter(node => node.nodeType === node.TEXT_NODE).map(node => node.textContent).join(' ').trim()}]}}async function main () {let dataFound = falsefor (const name in sites) {const site = sites[name]if (site.host.some(function (e) { return ~this.indexOf(e) || e === '*' }, document.location.hostname) && site.condition()) {for (let i = 0; i < site.products.length; i++) {if (site.products[i].condition()) {// Try to retrieve item name from pagelet datatry {data = await site.products[i].data()} catch (e) {data = falseconsole.error(`${scriptName}: Error in data() of site='${name}', type='${site.products[i].type}'`)console.error(e)}if (data) {if (Array.isArray(data)) {if (data[1]) {loadMeter(data[0].trim(), site.products[i].type, parseInt(data[1]))} else {loadMeter(data[0].trim(), site.products[i].type)}} else {loadMeter(data.trim(), site.products[i].type)}dataFound = true}break}}break}}return dataFound}async function adaptForMetaScript () {// Move this container above the meta container if the meta container is on the right sideconst rottenC = document.getElementById('mcdiv321rotten')const metaC = document.getElementById('mcdiv123')if (!metaC || !rottenC) {return}const rottenBounds = rottenC.getBoundingClientRect()let bottom = 0if (metaC) {const metaBounds = metaC.getBoundingClientRect()if (Math.abs(metaBounds.right - rottenBounds.right) < 20 && metaBounds.top > 20) {bottom += metaBounds.height}}if (bottom > 0) {rottenC.style.bottom = bottom + 'px'}}(async function () {if (document.location.href === 'https://www.rottentomatoes.com/') {updateAlgolia()}const firstRunR###lt = await main()let lastLoc = document.location.hreflet lastContent = document.body.innerTextlet lastCounter = 0async function newpage () {if (lastContent === document.body.innerText && lastCounter < 15) {window.setTimeout(newpage, 500)lastCounter++} else {lastContent = document.body.innerTextlastCounter = 0const re = await main()if (!re) { // No page matched or no data foundwindow.setTimeout(newpage, 1000)}}}window.setInterval(function () {adaptForMetaScript()if (document.location.href !== lastLoc) {lastLoc = document.location.href$('#mcdiv321rotten').remove()window.setTimeout(newpage, 1000)}}, 500)if (!firstRunR###lt) {// Initial run had no match, let's try again there may be new contentwindow.setTimeout(main, 2000)}})()