mirror of
https://github.com/knightcrawler-stremio/knightcrawler.git
synced 2024-12-20 03:29:51 +00:00
adds episode decomposing based on date
This commit is contained in:
19
lib/cache.js
19
lib/cache.js
@@ -7,10 +7,12 @@ const METADATA_PREFIX = `${GLOBAL_KEY_PREFIX}|metadata`;
|
|||||||
const TORRENT_FILES_KEY_PREFIX = `stremio-tpb|files`;
|
const TORRENT_FILES_KEY_PREFIX = `stremio-tpb|files`;
|
||||||
|
|
||||||
const GLOBAL_TTL = process.env.METADATA_TTL || 7 * 24 * 60 * 60; // 7 days
|
const GLOBAL_TTL = process.env.METADATA_TTL || 7 * 24 * 60 * 60; // 7 days
|
||||||
|
const MEMORY_TTL = process.env.METADATA_TTL || 2 * 60 * 60; // 2 hours
|
||||||
|
|
||||||
const MONGO_URI = process.env.MONGODB_URI;
|
const MONGO_URI = process.env.MONGODB_URI;
|
||||||
|
|
||||||
const cache = initiateCache();
|
const memoryCache = initiateMemoryCache();
|
||||||
|
const remoteCache = initiateRemoteCache();
|
||||||
const torrentFilesCache = initiateTorrentFilesCache();
|
const torrentFilesCache = initiateTorrentFilesCache();
|
||||||
|
|
||||||
function initiateTorrentFilesCache() {
|
function initiateTorrentFilesCache() {
|
||||||
@@ -27,7 +29,7 @@ function initiateTorrentFilesCache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initiateCache() {
|
function initiateRemoteCache() {
|
||||||
if (MONGO_URI) {
|
if (MONGO_URI) {
|
||||||
return cacheManager.caching({
|
return cacheManager.caching({
|
||||||
store: mangodbStore,
|
store: mangodbStore,
|
||||||
@@ -46,6 +48,13 @@ function initiateCache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initiateMemoryCache() {
|
||||||
|
return cacheManager.caching({
|
||||||
|
store: 'memory',
|
||||||
|
ttl: MEMORY_TTL
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function retrieveTorrentFiles(infoHash) {
|
function retrieveTorrentFiles(infoHash) {
|
||||||
return torrentFilesCache.get(`${TORRENT_FILES_KEY_PREFIX}:${infoHash}`)
|
return torrentFilesCache.get(`${TORRENT_FILES_KEY_PREFIX}:${infoHash}`)
|
||||||
.then((results) => {
|
.then((results) => {
|
||||||
@@ -56,16 +65,16 @@ function retrieveTorrentFiles(infoHash) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cacheWrap(key, method, options) {
|
function cacheWrap(cache, key, method, options) {
|
||||||
return cache.wrap(key, method, options);
|
return cache.wrap(key, method, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cacheWrapImdbId(key, method) {
|
function cacheWrapImdbId(key, method) {
|
||||||
return cacheWrap(`${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL });
|
return cacheWrap(remoteCache, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL });
|
||||||
}
|
}
|
||||||
|
|
||||||
function cacheWrapMetadata(id, method) {
|
function cacheWrapMetadata(id, method) {
|
||||||
return cacheWrap(`${METADATA_PREFIX}:${id}`, method, { ttl: GLOBAL_TTL });
|
return cacheWrap(memoryCache, `${METADATA_PREFIX}:${id}`, method, { ttl: GLOBAL_TTL });
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { cacheWrapImdbId, cacheWrapMetadata, retrieveTorrentFiles };
|
module.exports = { cacheWrapImdbId, cacheWrapMetadata, retrieveTorrentFiles };
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ function getMetadata(id, type = Type.SERIES) {
|
|||||||
imdbId: body.meta.imdb_id,
|
imdbId: body.meta.imdb_id,
|
||||||
title: body.meta.name,
|
title: body.meta.name,
|
||||||
year: body.meta.year,
|
year: body.meta.year,
|
||||||
|
country: body.meta.country,
|
||||||
genres: body.meta.genres,
|
genres: body.meta.genres,
|
||||||
videos: (body.meta.videos || [])
|
videos: (body.meta.videos || [])
|
||||||
.map((video) => video.imdbSeason
|
.map((video) => video.imdbSeason
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
const moment = require('moment');
|
||||||
|
const { parse } = require('parse-torrent-title');
|
||||||
const { torrentFiles } = require('../lib/torrent');
|
const { torrentFiles } = require('../lib/torrent');
|
||||||
const { escapeTitle, getMetadata, getImdbId } = require('../lib/metadata');
|
const { escapeTitle, getMetadata, getImdbId } = require('../lib/metadata');
|
||||||
const { parse } = require('parse-torrent-title');
|
|
||||||
const { Type } = require('./types');
|
const { Type } = require('./types');
|
||||||
|
|
||||||
const MIN_SIZE = 20 * 1024 * 1024; // 20 MB
|
const MIN_SIZE = 20 * 1024 * 1024; // 20 MB
|
||||||
@@ -116,7 +117,7 @@ function parseSeriesFile(file, parsedTorrentName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function decomposeEpisodes(torrent, files, metadata = { episodeCount: {} }) {
|
async function decomposeEpisodes(torrent, files, metadata = { episodeCount: {} }) {
|
||||||
if (files.every(file => !file.episodes)) {
|
if (files.every(file => !file.episodes && !file.date)) {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
// for anime type episodes are always absolute and for a single season
|
// for anime type episodes are always absolute and for a single season
|
||||||
@@ -137,12 +138,12 @@ async function decomposeEpisodes(torrent, files, metadata = { episodeCount: {} }
|
|||||||
&& sortedEpisodes.every(ep => metadata.episodeCount[div100(ep) - 1] >= mod100(ep))
|
&& sortedEpisodes.every(ep => metadata.episodeCount[div100(ep) - 1] >= mod100(ep))
|
||||||
&& files.every(file => !file.season || file.episodes.every(ep => div100(ep) === file.season))) {
|
&& files.every(file => !file.season || file.episodes.every(ep => div100(ep) === file.season))) {
|
||||||
decomposeConcatSeasonAndEpisodeFiles(torrent, files, metadata);
|
decomposeConcatSeasonAndEpisodeFiles(torrent, files, metadata);
|
||||||
}
|
} else if ((files.every(file => !file.season && file.episodes) || files.some(file => file.season && file.episodes
|
||||||
|
|
||||||
if ((files.every(file => !file.season) || files.some(file => file.season && file.episodes
|
|
||||||
&& file.episodes.every(ep => metadata.episodeCount[file.season - 1] < ep)))
|
&& file.episodes.every(ep => metadata.episodeCount[file.season - 1] < ep)))
|
||||||
&& (sortedEpisodes.length <= 1 || sortedEpisodes.slice(1).every((ep, i) => ep - sortedEpisodes[i] <= 2))) {
|
&& (sortedEpisodes.length <= 1 || sortedEpisodes.slice(1).every((ep, i) => ep - sortedEpisodes[i] <= 2))) {
|
||||||
decomposeAbsoluteEpisodeFiles(torrent, files, metadata);
|
decomposeAbsoluteEpisodeFiles(torrent, files, metadata);
|
||||||
|
} else if (files.every(file => !file.season && file.date)) {
|
||||||
|
decomposeDateEpisodeFiles(torrent, files, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
@@ -179,6 +180,39 @@ function decomposeAbsoluteEpisodeFiles(torrent, files, metadata) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decomposeDateEpisodeFiles(torrent, files, metadata) {
|
||||||
|
if (!metadata || !metadata.videos || !metadata.videos.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeZoneOffset = getTimeZoneOffset(metadata.country);
|
||||||
|
const offsetVideos = metadata.videos
|
||||||
|
.reduce((map, video) => {
|
||||||
|
const releaseDate = moment(video.released).utcOffset(timeZoneOffset).format('YYYY-MM-DD');
|
||||||
|
map[releaseDate] = video;
|
||||||
|
return map;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
files
|
||||||
|
.filter(file => file.date)
|
||||||
|
.forEach(file => {
|
||||||
|
const video = offsetVideos[file.date];
|
||||||
|
if (video) {
|
||||||
|
file.season = video.season;
|
||||||
|
file.episodes = [video.episode];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimeZoneOffset(country) {
|
||||||
|
switch (country) {
|
||||||
|
case 'USA':
|
||||||
|
return '-08:00';
|
||||||
|
default:
|
||||||
|
return '00:00';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function assignKitsuOrImdbEpisodes(files, metadata) {
|
function assignKitsuOrImdbEpisodes(files, metadata) {
|
||||||
if (!metadata || !metadata.videos || !metadata.videos.length) {
|
if (!metadata || !metadata.videos || !metadata.videos.length) {
|
||||||
return files;
|
return files;
|
||||||
|
|||||||
@@ -30,40 +30,48 @@ async function findAllFiles() {
|
|||||||
const torrent = {
|
const torrent = {
|
||||||
infoHash: '6b95e5cfde9aaa71970a14f6bb6b9de19e2cbfa1',
|
infoHash: '6b95e5cfde9aaa71970a14f6bb6b9de19e2cbfa1',
|
||||||
title: '[OMDA] Bleach + Filmes + Ovas (480p-720p x264 AAC-MP3) [rich_jc]',
|
title: '[OMDA] Bleach + Filmes + Ovas (480p-720p x264 AAC-MP3) [rich_jc]',
|
||||||
type: Type.SERIES
|
type: Type.SERIES,
|
||||||
|
imdbId: 'tt0434665'
|
||||||
};
|
};
|
||||||
const imdbId = 'tt0434665';
|
|
||||||
/* Season and concat episodes */
|
/* Season and concat episodes */
|
||||||
// const torrent = {
|
// const torrent = {
|
||||||
// infoHash: '235e8ed73b6cc9679b0842c39e17223c47b51f68',
|
// infoHash: '235e8ed73b6cc9679b0842c39e17223c47b51f68',
|
||||||
// title: 'Daria - The Complete Animated Series [2010] DVDRip',
|
// title: 'Daria - The Complete Animated Series [2010] DVDRip',
|
||||||
// type: Type.SERIES
|
// type: Type.SERIES,
|
||||||
|
// imdbId: 'tt0118298'
|
||||||
// };
|
// };
|
||||||
// const imdbId = 'tt0118298';
|
|
||||||
/* Series Season and absolute episodes */
|
/* Series Season and absolute episodes */
|
||||||
// const torrent = {
|
// const torrent = {
|
||||||
// infoHash: '16b4560beb05397c0eeb35487a997caf789243ea',
|
// infoHash: '16b4560beb05397c0eeb35487a997caf789243ea',
|
||||||
// title: 'Seinfeld - Complete Collection',
|
// title: 'Seinfeld - Complete Collection',
|
||||||
// type: Type.SERIES
|
// type: Type.SERIES,
|
||||||
|
// imdbId: 'tt0098904'
|
||||||
// };
|
// };
|
||||||
// const imdbId = 'tt0098904';
|
|
||||||
/* Series Season and episodes */
|
/* Series Season and episodes */
|
||||||
// const torrent = {
|
// const torrent = {
|
||||||
// infoHash: 'd0f120c1bbfb988eb35b648e1c78ca3e5d45ef39',
|
// infoHash: 'd0f120c1bbfb988eb35b648e1c78ca3e5d45ef39',
|
||||||
// title: 'Seinfeld Complete Series-720p WEBrip EN-SUB x264-[MULVAcoded]',
|
// title: 'Seinfeld Complete Series-720p WEBrip EN-SUB x264-[MULVAcoded]',
|
||||||
// type: Type.SERIES
|
// type: Type.SERIES,
|
||||||
|
// imdbId: 'tt0098904'
|
||||||
// };
|
// };
|
||||||
// const imdbId = 'tt0098904';
|
|
||||||
/* Anime single absolute episode */
|
/* Anime single absolute episode */
|
||||||
// const torrent = {
|
// const torrent = {
|
||||||
// infoHash: 'e81e12880980086c476aa8bfdd22bed9d41b1dfe',
|
// infoHash: 'e81e12880980086c476aa8bfdd22bed9d41b1dfe',
|
||||||
// title: '[Vision] Naruto Shippuuden - 451 (1080p x264 AAC) [rich_jc].mp4',
|
// title: '[Vision] Naruto Shippuuden - 451 (1080p x264 AAC) [rich_jc].mp4',
|
||||||
// size: 467361138,
|
// size: 467361138,
|
||||||
// type: Type.SERIES
|
// type: Type.SERIES,
|
||||||
|
// imdbId: 'tt0988824'
|
||||||
|
// };
|
||||||
|
/* Date based episode */
|
||||||
|
// const torrent = {
|
||||||
|
// infoHash: '5a8e9e64fa04e3541236f049cb6b0d35e4ca12cc',
|
||||||
|
// title: 'Jimmy.Fallon.2020.02.14.Steve.Buscemi.WEB.x264-XLF[TGx]',
|
||||||
|
// size: 618637331,
|
||||||
|
// type: Type.SERIES,
|
||||||
|
// imdbId: 'tt3444938'
|
||||||
// };
|
// };
|
||||||
// const imdbId = 'tt0988824';
|
|
||||||
|
|
||||||
return parseTorrentFiles(torrent, imdbId)
|
return parseTorrentFiles(torrent)
|
||||||
.then((files) => console.log(files));
|
.then((files) => console.log(files));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1714,7 +1714,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse-torrent-title": {
|
"parse-torrent-title": {
|
||||||
"version": "git://github.com/TheBeastLT/parse-torrent-title.git#e05b0e0121a944c1ab399e767640a0c8f9300e8e",
|
"version": "git://github.com/TheBeastLT/parse-torrent-title.git#bfa710a62818723049b39869756bb198056ddde3",
|
||||||
"from": "git://github.com/TheBeastLT/parse-torrent-title.git#master"
|
"from": "git://github.com/TheBeastLT/parse-torrent-title.git#master"
|
||||||
},
|
},
|
||||||
"parseurl": {
|
"parseurl": {
|
||||||
|
|||||||
Reference in New Issue
Block a user