· 5 years ago · Sep 26, 2020, 04:46 PM
1const hasPreviewOpened = (mut) => {
2 //just several booleans to check if the preview modal for the movie has been mounted
3 let previousSiblingBool, targetBool, addedNodesBool
4 if (mut.previousSibling) {
5 previousSiblingBool = mut.previousSibling.className === "previewModal--metadatAndControls-info"
6 }
7 if (mut.target) {
8 targetBool = mut.target.className === "previewModal--metadatAndControls-container"
9 }
10 if (mut.addedNodes[0]) {
11 addedNodesBool = mut.addedNodes[0].className === "focus-trap-wrapper previewModal--wrapper mini-modal"
12 }
13 return (
14 (previousSiblingBool && targetBool)
15 || addedNodesBool
16 )
17}
18
19const getTitleFromMutations = (mutations) => {
20 // a function which returns null if title node not mounted and the title otherwise
21
22 const hasModalWithTitle = (mut) => {
23 // a function with a few booleans to spot if the div with the title has been mounted to dom
24 if (!mut.target.parentNode) {
25 return false
26 }
27 return (
28 mut.target.parentNode.innerHTML.length < 10000 &&
29 mut.target.parentNode.innerHTML.includes('<div class="previewModal--player-titleTreatment-left previewModal--player-titleTreatment mini-modal mini-modal"><img class="previewModal--player-titleTreatment-logo" alt="')
30 )
31 }
32
33 if (mutations.some(hasModalWithTitle)) {
34 // find the node with the title as alt of the preview image
35 const rightNode = mutations.filter(mut => {
36 if (mut.target.parentNode === null) return false
37 return mut.target.parentNode.innerHTML.includes('<div class="previewModal--player-titleTreatment-left previewModal--player-titleTreatment mini-modal mini-modal"><img class="previewModal--player-titleTreatment-logo" alt="')
38 })
39 if (
40 rightNode.length < 1 ||
41 !rightNode[0] ||
42 !rightNode[0].addedNodes ||
43 !rightNode[0].addedNodes[0]
44 ) return null
45 return rightNode[0].addedNodes[0].alt
46 }
47 return null
48}
49
50const getMovieDetails = () => {
51 // a function to get the movie details from the preview modal
52 const [evidenceTags, maturityNumber, duration] = [
53 document.querySelector(".evidence-list"),
54 document.querySelectorAll(".maturity-number"),
55 document.querySelector(".duration")
56 ]
57 if (evidenceTags && maturityNumber && duration) {
58 return [
59 Array.from(evidenceTags.childNodes).map(c => c.innerText),
60 maturityNumber[1].innerText,
61 duration.innerText
62 ]
63 }
64 return null
65}
66
67const getRightMovie = (title, d) => {
68 // if cache already contains title :
69 // make sure that the current title held through mutations fits the movie details
70 // in any case return the right title by comparing the movie details given in preview
71 if (movies[title]) {
72 const keys = Object.keys(movies)
73 const i = keys.findIndex(k => {
74 return (
75 movies[k].maturity === d[1] &&
76 movies[k].length === d[2] &&
77 movies[k].tags.join("") === d[0].join("")
78 )
79 })
80 return keys[i]
81 }
82
83 // if the cache does not contain a key which matches the title in arguments
84 // append to cache and return title
85 movies[title] = {
86 tags: d[0],
87 maturity: d[1],
88 length: d[2]
89 }
90 return title
91}
92
93const movies = {}, baseUrl = "https://api.imdflix.tk/movie?"
94let title, isIntervalOn = false, isFetching = false
95
96const observer = new MutationObserver(function(mutations, me) {
97 // some mutation will hold the movie title during hovering
98 // other mutations will return null
99 const getTitleAttempt = getTitleFromMutations(mutations)
100 title = getTitleAttempt ? getTitleAttempt : title
101
102 if (mutations.some(hasPreviewOpened) && !isIntervalOn) {
103 // when the preview is opened and there's not a interval already running
104
105 // initialise a timer for the interval
106 let timer = 0
107 const waitForTags = setInterval(() => {
108 // set boolean to not run another interval
109 isIntervalOn = true
110 timer += 100
111
112 // try to get the node with imdb ratings to make sure, it's not already inserted
113 // wait for the node with movie tags to be mounted (AJAX)
114 const movieRatings = document.querySelector(".jaunie-class")
115 const evidenceTags = document.querySelector(".evidence-tags")
116 if (evidenceTags !== null && movieRatings === null && !isFetching) {
117 // check cached titles
118 const realTitle = getRightMovie(title, getMovieDetails())
119
120 // fetch the API
121 // then append rating and reset booleans which make sure operation is only done once
122 isFetching = true
123 fetch(`${baseUrl}title=${encodeURI(realTitle)}`)
124 .then(res => res.json())
125 .then(data => {
126 let span = document.createElement("span")
127 span.innerHTML = `IMDB: ${data[0].value}`
128 span.classList.add("jaunie-class")
129 evidenceTags.appendChild(span)
130 clearInterval(waitForTags)
131 previewIsMounted = false
132 isIntervalOn = false
133 isFetching = false
134 })
135 }
136 // if interval takes too long, remove it to not clog the dom
137 if (timer > 4000) {
138 clearInterval(waitForTags)
139 isIntervalOn = false
140 }
141 }, 100)
142 }
143})
144
145observer.observe(document, {
146 childList: true,
147 subtree: true
148})
149