From 2365b574d1b668e8b6ad450c5e3438f69c5e7ad2 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Mon, 27 Apr 2020 23:13:22 +0200 Subject: [PATCH] Cleanup metadata loader --- src/api/imdb_api.js | 4 +- src/directory_walker.js | 5 +- src/metadata_loader.js | 36 +++++++++++++-- src/old_metadata_loader.js | 94 -------------------------------------- src/util/encode-path.js | 7 +++ src/util/video-mime.js | 4 +- 6 files changed, 47 insertions(+), 103 deletions(-) delete mode 100644 src/old_metadata_loader.js create mode 100644 src/util/encode-path.js diff --git a/src/api/imdb_api.js b/src/api/imdb_api.js index 85a026e..12313c7 100644 --- a/src/api/imdb_api.js +++ b/src/api/imdb_api.js @@ -30,11 +30,11 @@ class ImdbApi { } search(type, title, year) { - return this.queryJson(ImdbApi.querySearch, { + return this.query(ImdbApi.querySearch, { 1: type, 2: title, 3: title, 4: year - }); + }).then(row => row.tconst); } static querySearch = ` diff --git a/src/directory_walker.js b/src/directory_walker.js index f96daa2..59a4071 100644 --- a/src/directory_walker.js +++ b/src/directory_walker.js @@ -1,5 +1,6 @@ import path from 'path'; import {promises as fsPromises} from 'fs'; +import encodePath from "./util/encode-path"; class FileManager { basePath; @@ -94,7 +95,7 @@ class FileManager { const media = await Promise.all(mediaFiles.map(fileName => this.videoMimeParser.parseMediaInfo(path.join(base, fileName)).then(metadata => { return { - src: encodeURI(path.relative(this.basePath, path.join(base, fileName))), + src: encodePath(path.relative(this.basePath, path.join(base, fileName))), ...metadata } }))); @@ -107,7 +108,7 @@ class FileManager { region: region, specifier: specifier, format: format, - src: encodeURI(path.relative(this.basePath, path.join(base, "subtitles", name))) + src: encodePath(path.relative(this.basePath, path.join(base, "subtitles", name))) } }), media: media diff --git a/src/metadata_loader.js b/src/metadata_loader.js index 1151072..3357826 100644 --- a/src/metadata_loader.js +++ b/src/metadata_loader.js @@ -2,6 +2,7 @@ import ranking_confidence from './util/statistics'; import uuid from 'uuid'; import path from "path"; import downloadFile from "./util/download-file"; +import encodePath from "./util/encode-path"; class MetadataLoader { imdb; @@ -130,22 +131,51 @@ class MetadataLoader { } : null; } + async identifyShow(title, year) { + /* + FIXME: Implement this properly, previous implementation for clarity below + + const imdbId = await this.imdb.search("tvSeries", title, year); + + const tvdbResults = await this.tvdb.getSeriesByImdbId(imdbId).catch((e) => console.error(e)); + const tvdbResult = tvdbResults[0]; + + if (!tvdbResult) return null; + + const tmdbResults = await this.tmdb.request(`find/${imdbId}`, { + "external_source": "imdb_id", + }).catch((e) => console.error(e)); + + const tmdbResult = tmdbResults.tv_results.sort((a, b) => { + return b.popularity - a.popularity; + })[0]; + + if (!tmdbResult) return null; + + return { + imdb: imdbId, + tvdb: tvdbResult.id, + tmdb: tmdbResult.id, + }; + */ + } + async processImages(basePath, filePath, images) { const imageData = !images ? [] : [ !images.logo ? null : !images.logo.url ? null : { type: "logo", url: images.logo.url, - src: encodeURI(path.relative(basePath, path.join(filePath, "metadata", `logo${path.extname(images.logo.url)}`))) + src: encodePath(path.relative(basePath, path.join(filePath, "metadata", `logo${path.extname(images.logo.url)}`))) }, !images.poster ? null : !images.poster.file_path ? null : { type: "poster", url: this.tmdb.getImageUrl(images.poster.file_path), - src: encodeURI(path.relative(basePath, path.join(filePath, "metadata", `poster${path.extname(images.poster.file_path)}`))) + src: encodePath(path.relative(basePath, path.join(filePath, "metadata", `poster${path.extname(images.poster.file_path)}`))) }, !images.backdrop ? null : !images.backdrop.file_path ? null : { type: "backdrop", url: this.tmdb.getImageUrl(images.backdrop.file_path), - src: encodeURI(path.relative(basePath, path.join(filePath, "metadata", `backdrop${path.extname(images.backdrop.file_path)}`))) + src: encodePath(path.relative(basePath, path.join(filePath, "metadata", `backdrop${path.extname(images.backdrop.file_path)}`))) } ].filter(el => el !== null); diff --git a/src/old_metadata_loader.js b/src/old_metadata_loader.js deleted file mode 100644 index 5dd6f7d..0000000 --- a/src/old_metadata_loader.js +++ /dev/null @@ -1,94 +0,0 @@ -// FIXME: Implement all this over to the metadata loader, and clean it up meanwhile - -async function identifyMovie(api, imdb, tvdb, title, year) { - const results = await api.request(`search/movie`, { - query: title, - primary_release_year: year - }).catch((e) => console.error(e)); - - const result = results.results.sort((a, b) => { - return b.popularity - a.popularity; - })[0]; - - return result ? { - tmdb: result.id - } : null; -} - -async function identifyShow(tmdbApi, imdbApi, tvdbApi, title, showYear) { - const imdbId = await utils.promisify(imdbApi, "get", idQuery, {1: "tvSeries", 2: title, 3: title, 4: showYear}) - .then((data) => data.tconst); - - const tvdbResults = await tvdbApi.getSeriesByImdbId(imdbId).catch((e) => console.error(e)); - const tvdbResult = tvdbResults[0]; - - if (!tvdbResult) return null; - - const tmdbResults = await tmdbApi.request(`find/${imdbId}`, { - "external_source": "imdb_id", - }).catch((e) => console.error(e)); - - const tmdbResult = tmdbResults.tv_results.sort((a, b) => { - return b.popularity - a.popularity; - })[0]; - - if (!tmdbResult) return null; - - return { - imdb: imdbId, - tvdb: tvdbResult.id, - tmdb: tmdbResult.id, - }; -} - -function downloadImage(url, filePath) { - return new Promise(((resolve, reject) => { - const file = fs.createWriteStream(filePath); - https.get(url, function (response) { - response.pipe(file); - file.on('finish', function () { - file.close(() => { - resolve(); - }); - }); - }).on('error', function (err) { - fs.unlink(filePath); - reject(err); - }); - })); -} - -async function processFile(isShow, tmdbApi, fanartApi, imdb, tvdbApi, uuid, filePath) { - const {name, year} = /^(?<name>.+) \((?<year>\d+)\)$/.exec(path.basename(filePath)).groups; - - const identifyFunction = isShow ? identifyShow : identifyMovie; - const ids = await identifyFunction(tmdbApi, imdb, tvdbApi, name, year); - if (ids === null) { - console.error(`No item in TMDB found for "${name}" from year "${year}" at path "${filePath}"`); - return - } - - function processImage(type, imageUrl) { - const ending = path.extname(imageUrl); - return downloadImage(imageUrl, path.join(filePath, `metadata/${type}${ending}`)); - } - - data.data.subtitles = processSubtitles(filePath); - data.data.hasLogo = !!hdMovieLogo; - data.data.src = path.join("/api/", isShow ? "Shows" : "Movies", encodeURIComponent(path.basename(filePath))); - - // Write metadata - await utils.promisify(fs, "writeFile", path.join(filePath, "metadata.json"), JSON.stringify(data.data)); - - // Creating metadata folder - if (!fs.existsSync(path.join(filePath, 'metadata'))) { - await fs.promises.mkdir(path.join(filePath, 'metadata')); - } - - // Writing images - await Promise.all([ - poster ? processImage("poster", tmdbApi.getImageUrl(poster.file_path)) : null, - backdrop ? processImage("backdrop", tmdbApi.getImageUrl(backdrop.file_path)) : null, - hdMovieLogo ? processImage("logo", hdMovieLogo.url) : null, - ].filter(el => el)); -} \ No newline at end of file diff --git a/src/util/encode-path.js b/src/util/encode-path.js new file mode 100644 index 0000000..69c3025 --- /dev/null +++ b/src/util/encode-path.js @@ -0,0 +1,7 @@ +import path from 'path'; + +function encodePath(filePath) { + return path.join(...filePath.split(path.sep).map(encodeURIComponent)) +} + +export default encodePath; \ No newline at end of file diff --git a/src/util/video-mime.js b/src/util/video-mime.js index 7a42433..32c0d9f 100644 --- a/src/util/video-mime.js +++ b/src/util/video-mime.js @@ -1,4 +1,4 @@ -import fs, {promises as fsPromises} from 'fs'; +import {promises as fsPromises} from 'fs'; import path from 'path'; import xml2json from 'xml2json'; import {exec} from 'child_process'; @@ -16,7 +16,7 @@ class VideoMimeParser { async parseMediaInfoDash(filePath) { const info = xml2json.toJson(await fsPromises.readFile(filePath), {object: true}); return { - container: "application/xml+dash", + container: "application/dash+xml", tracks: info.MPD.Period.AdaptationSet.map((track, i) => { return { id: i, -- GitLab