-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
93 lines (82 loc) · 3.46 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
const axios = require('axios');
const cheerio = require('cheerio');
const RT_URL = 'https://www.rottentomatoes.com';
const RT_API_URL = 'https://www.rottentomatoes.com/api/private/v2.0/search/';
const now = new Date();
const YS = now.getFullYear() - 1;
const YE = now.getFullYear() + 1;
/**
* scrapes https://www.rottentomatoes.com/ using their private search API
* OMDB wasn't cutting it as it gets updates less frequently
*
* @param {String} title
* @param {Number} yearStart - year start
* @param {Number} yearEnd - year end
* @return {Promise}
*/
module.exports = (title, yearStart = YS, yearEnd = YE) => new Promise(async (resolve, reject) => {
try {
const response = await axios.get(RT_API_URL, {
params: {
limit: 2,
q: title,
},
});
// In Yellow pages we trust - movie title must === match!
// eslint-disable-next-line
const moviesWithinRange = response.data.movies.filter(movie => movie.year >= yearStart && movie.year <= yearEnd && movie.name.trim().toLocaleLowerCase() === title.trim().toLocaleLowerCase());
if (moviesWithinRange.length === 0) {
reject(null);
return;
}
const movie = moviesWithinRange.pop(); // POP-IT!
const movie411 = Object.create(null); // all the stolen data will be stored here
const movieResponse = await axios.get(`${RT_URL}${movie.url}`);
const $ = cheerio.load(movieResponse.data);
const { name, contentRating = 'NR', aggregateRating = null, actors, director, author, genre } = JSON.parse($('script#jsonLdSchema').text());
const [release = null, runtime = null] = $('ul.content-meta.info time[datetime]').toArray();
const synopsisPlus = $('div#movieSynopsis').text(); // this sometimes™ carries `stars...` info which can be long
const synopsis = synopsisPlus.search(/stars/i) > -1 ? synopsisPlus.slice(0, synopsisPlus.slice(0, synopsisPlus.search(/stars/i)).lastIndexOf('.') + 1) : synopsisPlus;
Object.assign(movie411, {
name,
release: release ? $(release).text().replace(/\n/g, '').trim() : release,
runtime: runtime ? $(runtime).text().replace(/\n/g, '').trim() : runtime,
contentRating,
aggregateRating,
actors,
director,
author,
genre,
synopsis,
poster: $('a#poster_link > img').attr('src') || null,
});
// this will always resolve
const videoClipPromise = url => new Promise((resolveTrailer) => {
axios
.get(url, {
maxRedirects: 1,
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30',
},
})
.then((directVideo) => {
resolveTrailer(directVideo);
}, (err) => {
resolveTrailer(err.response);
});
});
const videoClips = JSON.parse($.html().match(/var videoClips = (\[.+\]);/)[1]);
// eslint-disable-next-line
const videosDirectURL = await axios.all(videoClips.map(videoClip => videoClipPromise(videoClip.urls.mp4)));
// this is the part where you fix your face
// Yes, I'm going to be mutating [enhancing] `videoClips` with `directHls` links
videosDirectURL.forEach((directVideo, index) => {
// eslint-disable-next-line
videoClips[index].urls.directHls = directVideo.status === 200 ? directVideo.request._options.href : null;
});
Object.assign(movie411, { trailers: videoClips });
resolve(movie411);
} catch (err) {
reject(err);
}
});