// ==UserScript== // @name Trakt.tv | Charts - Ratings Distribution // @description Adds a ratings distribution (number of users who rated a title 1/10, 2/10 etc.) chart to title summary pages. Also allows for rating the title by clicking on the bars of the chart. See README for details. // @version 1.0.8 // @namespace https://github.com/Fenn3c401 // @author Fenn3c401 // @license GPL-3.0-or-later // @homepageURL https://github.com/Fenn3c401/Trakt.tv-Userscript-Collection#readme // @supportURL https://github.com/Fenn3c401/Trakt.tv-Userscript-Collection/issues // @updateURL https://update.greasyfork.org/scripts/550071.meta.js // @downloadURL https://raw.githubusercontent.com/Fenn3c401/Trakt.tv-Userscript-Collection/main/userscripts/dist/pmdf6nr9.min.user.js // @icon https://trakt.tv/assets/logos/logomark.square.gradient-b644b16c38ff775861b4b1f58c1230f6a097a2466ab33ae00445a505c33fcb91.svg // @match https://trakt.tv/* // @match https://classic.trakt.tv/* // @run-at document-start // @require https://cdn.jsdelivr.net/npm/chart.js@4.4.9/dist/chart.umd.min.js // @grant unsafeWindow // @grant GM_info // @grant GM_addStyle // @grant GM_setValue // @grant GM.xmlHttpRequest // @connect walter-r2.trakt.tv // ==/UserScript== /* README ### General - By installing the [Trakt.tv | Trakt API Wrapper](f785bub0.md) userscript you can speed up the ratings distribution data fetching. */ "use strict";let $,traktApiWrapper;const numFormatCompact=new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:1});numFormatCompact.formatTLC=i=>numFormatCompact.format(i).toLowerCase(),addStyles(),document.addEventListener("turbo:load",async()=>{if(!/^\/(shows|movies)\//.test(location.pathname)||($??=unsafeWindow.jQuery,traktApiWrapper??=unsafeWindow.userscriptTraktApiWrapper,!$))return;const i=$("#summary-wrapper"),e=i.find("#summary-ratings-wrapper"),t=e.find(".trakt-rating > a").attr("href");if(!t)return;const r=$('
').appendTo(i.find(".shadow-base")).find("canvas"),[a,s]=await Promise.all([getRatingsData(t),getFanartBrightness(i)]),n=()=>{new Chart(r[0].getContext("2d"),{type:"bar",data:getChartData(a,s),options:getChartOptions(a,e)})};document.hidden?$(document).one("visibilitychange",n):n()},{capture:!0});async function getRatingsData(i){let e;if(traktApiWrapper){const t=i.split("/").slice(1,-1),r=isNaN(t[1])?t[1]:$(".summary-user-rating").attr(`data-${t[0].slice(0,-1)}-id`),a=await traktApiWrapper[t[4]??t[2]??t[0]].ratings({id:r,season:t[3],episode:t[5]});e={distribution:Object.values(a.distribution),votes:a.votes}}else{const t=await fetch(i),r=new DOMParser().parseFromString(await t.text(),"text/html");e={distribution:JSON.parse($(r).find("#charts-wrapper script").text().match(/ratingsDistribution = (\[.*\])/)[1]),votes:$("#summary-ratings-wrapper").data("vote-count")}}return e.distribution.length===11&&(console.warn(GM_info.script.name.replace("Trakt.tv","Userscript")+": Malformed ratings distribution data.",e.distribution.toString()),e.distribution.shift()),e}function getFanartBrightness(i){const e=i.find("> .full-screenshot"),t=async()=>{const r=e.css("background-image").match(/https.*webp/)?.[0];if(!r)return .5;const a=await GM.xmlHttpRequest({url:r,responseType:"blob",fetch:!0});if(a.status!==200)throw new Error(`XHR for: ${a.finalUrl} failed with status: ${a.status}`);const s=URL.createObjectURL(a.response),n=new Image;n.src=s,await n.decode(),URL.revokeObjectURL(s);const o=document.createElement("canvas");o.width=n.naturalWidth,o.height=n.naturalHeight;const c=o.getContext("2d");c.drawImage(n,0,0);const u=n.naturalWidth/4,p=n.naturalHeight/4,d=c.getImageData(3*u,2*p,u,p).data;let m=0,g=d.length/16;for(let l=0;l