Last active
January 23, 2024 03:15
-
-
Save ulternate/dc4da8a7897f614e6a56fae94c429985 to your computer and use it in GitHub Desktop.
How many of the top billed cast are dead?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a silly little project created after a friend mentioned a movie and I saw | |
// that most of the cast photos were black and white. That got me thinking, how many | |
// of the top billed cast are still alive? Or how many are now dead? | |
// | |
// This will use the TMDB API to get the cast list for the movie/tv show | |
// and then if they're dead, it'll display that. | |
// | |
// This is untested, written in little time instead of focussing on other things I should be doing. | |
// | |
// No warranty provided. Feel free to do with this what you want. | |
// | |
// If you make a Jellyfin plugin to do this please let me know :D | |
// INSTRUCTIONS: | |
// - Get a TMDB API token | |
// - Get tampermonkey | |
// - Have Jellyfin | |
// - Create a tampermonkey script and paste this in the body. | |
// - Replace the API placeholder with your API key. | |
'use strict'; | |
const API_ACCESS_KEY_TOKEN = 'REPLACE_THIS_WITH_YOUR_ACCESS_KEY_TOKEN'; | |
const HEADERS = { Authorization: `Bearer ${API_ACCESS_KEY_TOKEN}` }; | |
// Some simple loading/info items that will be put in the media info section for your media. | |
let dedInfoItem = document.createElement('div'); | |
let dedSkullSpan = document.createElement('span'); | |
let dedSkullLoading = document.createElement('div'); | |
dedSkullSpan.innerHTML = '💀'; // Skull icon. | |
dedSkullLoading.innerHTML = '⚆'; // Circle with dot right icon. | |
dedSkullLoading.style.display = 'inline-block'; // We need a div because spans don't animate, but we don't want it to be a block as that wraps to the new line. | |
dedInfoItem.appendChild(dedSkullSpan); | |
dedSkullSpan.after(dedSkullLoading); | |
dedInfoItem.className = 'mediaInfoItem'; | |
// Animate the loading icon while we wait for the info to load. | |
dedSkullLoading.animate([{ transform: "rotate(360deg)" }], { duration: 2000, iterations: Infinity }); | |
// Don't try query the TMDB API until the cast list is in the DOM. | |
(new MutationObserver(check)).observe(document, {childList: true, subtree: true}); | |
async function check(changes, observer) { | |
// Current class selector for the cast list images (at least the first 15). | |
if (document.querySelector('.personCard button.textActionButton')) { | |
observer.disconnect(); | |
// Put the loading icon in the right spot: | |
document.querySelector('.mediaInfoItem.mediaInfoCriticRating').after(dedInfoItem); | |
// Trigger the code now to get the ded percent :D. | |
const movieResults = await getDedResults(); | |
dedSkullLoading.remove(); | |
// Show the ratio of ded to not ded. | |
dedSkullSpan.after(`${movieResults.ded} / ${movieResults.total}`); | |
} | |
} | |
async function getActorId(name) { | |
// Get the TMDB id for the actor with the given name, just return the first if there are multiple. | |
const response = await fetch(`https://api.themoviedb.org/3/search/person?query=${name}`, { headers: HEADERS }); | |
const data = await response.json(); | |
const { results } = data; | |
if (Array.isArray(results)) { | |
return results[0].id; | |
} | |
// TBH I don't know if I handle this case properly... This was an ADHD project, what you gonna do? | |
return null; | |
}; | |
async function getDed(actorId) { | |
// Is the actor ded or not? | |
const response = await fetch(`https://api.themoviedb.org/3/person/${actorId}`, { headers: HEADERS }); | |
const data = await response.json(); | |
const { deathday } = data; | |
return deathday !== null; | |
}; | |
async function getDedResults() { | |
let cast = []; | |
let ded = []; | |
const castMembers = Array.from(document.querySelectorAll(".personCard button.textActionButton")); | |
for (const item of castMembers) { | |
const castName = item.innerText; | |
if (!castName) { | |
continue; | |
} | |
const actorId = await getActorId(castName); | |
if (actorId) { | |
cast.push(actorId); | |
if (await getDed(actorId)) { | |
ded.push(actorId); | |
} | |
} | |
} | |
return { ded: ded.length, total: cast.length }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment