-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create script to generate combined data blob
- Loading branch information
1 parent
5f248d1
commit c8e5eff
Showing
6 changed files
with
253 additions
and
53 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const { MovieDb } = require("moviedb-promise"); | ||
const { dailyCache } = require("./cache"); | ||
require("dotenv").config(); | ||
|
||
const moviedb = new MovieDb(process.env.MOVIEDB_API_KEY); | ||
|
||
const searchMovieAndCacheResults = ({ | ||
slug, | ||
year: yearValue, | ||
normalizedTitle, | ||
}) => | ||
dailyCache(`moviedb-search-${yearValue || "no-year"}-${slug}`, async () => { | ||
const getPayload = (additional = {}) => ({ | ||
query: normalizedTitle, | ||
...additional, | ||
}); | ||
|
||
// If there's no year provided, just search for the title | ||
if (!yearValue) { | ||
return moviedb.searchMovie(getPayload()); | ||
} | ||
|
||
const year = parseInt(yearValue, 10); | ||
|
||
// Try to find a movie first released on that year | ||
let search = await moviedb.searchMovie( | ||
getPayload({ primary_release_year: year }), | ||
); | ||
|
||
// If there's no matches, then try to find a movie with some release related | ||
// to that year | ||
if (search.results.length === 0) { | ||
search = await moviedb.searchMovie(getPayload({ year })); | ||
} | ||
|
||
// If there's no matches, sometimes the movie listing has the year off by 1, | ||
// so try to find a movie with some release related to the next year | ||
if (search.results.length === 0) { | ||
return moviedb.searchMovie(getPayload({ year: year + 1 })); | ||
} | ||
|
||
return search; | ||
}); | ||
|
||
const getMovieInfoAndCacheResults = ({ id }) => | ||
dailyCache(`moviedb-info-${id}`, async () => { | ||
const payload = { | ||
id, | ||
append_to_response: "credits,external_ids,keywords,release_dates,videos", | ||
}; | ||
return moviedb.movieInfo(payload); | ||
}); | ||
|
||
module.exports = { | ||
searchMovieAndCacheResults, | ||
getMovieInfoAndCacheResults, | ||
}; |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
const { writeFileSync } = require("node:fs"); | ||
const path = require("node:path"); | ||
const { nanoid } = require("nanoid"); | ||
const { compress, trimUndefinedRecursively } = require("compress-json"); | ||
const getSites = require("../common/get-sites"); | ||
const normalizeTitle = require("../common/normalize-title"); | ||
const { getMovieInfoAndCacheResults } = require("../common/get-movie-data"); | ||
const { parseMinsToMs } = require("../common/utils"); | ||
|
||
const getId = () => nanoid(8); | ||
|
||
const getCertification = ({ release_dates: { results } }) => { | ||
const result = results.find(({ iso_3166_1: locale }) => locale === "GB"); | ||
if (!result) return undefined; | ||
|
||
const { release_dates: releaseDates } = result; | ||
const releaseDateWithCertification = releaseDates.find( | ||
({ certification }) => !!certification, | ||
); | ||
|
||
if (!releaseDateWithCertification) return undefined; | ||
return releaseDateWithCertification.certification; | ||
}; | ||
|
||
const getDirectors = ({ credits: { crew } }) => | ||
crew | ||
.filter(({ job }) => job.toLowerCase() === "director") | ||
.map(({ id, name }) => ({ id, name })); | ||
|
||
const getActors = ({ credits: { cast } }) => | ||
cast | ||
.slice(0, 10) | ||
.filter(({ popularity }) => popularity >= 5) | ||
.map(({ id, name }) => ({ id, name })); | ||
|
||
const getGenres = ({ genres }) => genres; | ||
|
||
const getYoutubeTrailer = ({ videos: { results } }) => { | ||
const trailer = results.find( | ||
({ type, site }) => | ||
type.toLowerCase() === "trailer" && site.toLowerCase() === "youtube", | ||
); | ||
return trailer ? trailer.key : undefined; | ||
}; | ||
|
||
const getImddId = ({ external_ids: externalIds = {} }) => externalIds.imdb_id; | ||
|
||
const data = getSites().reduce((mapping, site) => { | ||
let attributes; | ||
let shows; | ||
try { | ||
attributes = require( | ||
path.join(__dirname, "..", "cinemas", `${site}`, "attributes.js"), | ||
); | ||
shows = require(path.join(__dirname, "..", "output", `${site}-shows.json`)); | ||
} catch (e) { | ||
return mapping; | ||
} | ||
return { ...mapping, [site]: { attributes, shows } }; | ||
}, {}); | ||
|
||
const siteData = { | ||
venues: {}, | ||
people: {}, | ||
genres: {}, | ||
movies: {}, | ||
}; | ||
|
||
(async function () { | ||
for (cinema in data) { | ||
console.log(`[🎞️ Cinema: ${cinema}]`); | ||
const venueId = getId(); | ||
const { | ||
attributes: { name, url, address, geo }, | ||
shows, | ||
} = data[cinema]; | ||
|
||
siteData.venues[venueId] = { | ||
id: venueId, | ||
name, | ||
url, | ||
address, | ||
geo, | ||
}; | ||
|
||
for (show of shows) { | ||
const { title, url, overview, performances, moviedb } = show; | ||
|
||
let movieInfo; | ||
if (moviedb) { | ||
const outputTitle = title.slice(0, 35); | ||
process.stdout.write( | ||
` - Retriving data for ${outputTitle} ... ${"".padEnd(35 - outputTitle.length, " ")}`, | ||
); | ||
try { | ||
movieInfo = await getMovieInfoAndCacheResults(moviedb); | ||
console.log(`\t✅ Retrieved`); | ||
} catch (e) { | ||
console.log(`\t❌ Error retriving`); | ||
throw e; | ||
} | ||
} | ||
|
||
const movieId = movieInfo ? movieInfo.id : getId(); | ||
if (!siteData.movies[movieId]) { | ||
if (movieInfo) { | ||
const directors = getDirectors(movieInfo); | ||
const actors = getActors(movieInfo); | ||
const genres = getGenres(movieInfo); | ||
|
||
directors.forEach((crew) => (siteData.people[crew.id] = crew)); | ||
actors.forEach((cast) => (siteData.people[cast.id] = cast)); | ||
genres.forEach((genre) => (siteData.genres[genre.id] = genre)); | ||
|
||
siteData.movies[movieId] = { | ||
id: movieId, | ||
title: movieInfo.title, | ||
normalizedTitla: normalizeTitle(movieInfo.title), | ||
certification: getCertification(movieInfo), | ||
overview: movieInfo.overview, | ||
year: movieInfo.release_date.split("-")[0], | ||
duration: parseMinsToMs(movieInfo.runtime), | ||
directors: directors.map(({ id }) => id), | ||
actors: actors.map(({ id }) => id), | ||
genres: genres.map(({ id }) => id), | ||
imdbId: getImddId(movieInfo), | ||
youtubeTrailer: getYoutubeTrailer(movieInfo), | ||
posterPath: movieInfo.poster_path, | ||
showings: {}, | ||
performances: [], | ||
}; | ||
} else { | ||
siteData.movies[movieId] = { | ||
id: movieId, | ||
title: title, | ||
isUnmatched: true, | ||
showings: {}, | ||
performances: [], | ||
}; | ||
} | ||
} | ||
|
||
const showingId = getId(); | ||
const movie = siteData.movies[movieId]; | ||
|
||
movie.showings[showingId] = { | ||
id: showingId, | ||
venueId, | ||
title: title !== movie.title ? title : undefined, | ||
url, | ||
overview, | ||
}; | ||
|
||
movie.performances = movie.performances.concat( | ||
performances.map(({ time, notes, bookingUrl }) => ({ | ||
showingId, | ||
time, | ||
notes: notes !== "" ? notes : undefined, | ||
bookingUrl, | ||
})), | ||
); | ||
} | ||
console.log(" "); | ||
} | ||
|
||
process.stdout.write(`Compressing data ... `); | ||
try { | ||
const dataFile = `./output/combined-data.json`; | ||
trimUndefinedRecursively(siteData); | ||
const compressed = compress(siteData).toString(); | ||
console.log(`✅ Compressed`); | ||
|
||
writeFileSync(dataFile, compressed); | ||
console.log(`🗂️ Combined file created`); | ||
} catch (e) { | ||
console.log(`\t❌ Error compressing`); | ||
throw e; | ||
} | ||
})(); |
File renamed without changes.