include top seeded entries only for non foreign provider by default
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
const Bottleneck = require('bottleneck');
|
const Bottleneck = require('bottleneck');
|
||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
const { addonBuilder } = require('stremio-addon-sdk');
|
const { addonBuilder } = require('stremio-addon-sdk');
|
||||||
|
const { Providers } = require('../addon/lib/filter')
|
||||||
const { createManifest, genres } = require('./lib/manifest');
|
const { createManifest, genres } = require('./lib/manifest');
|
||||||
const { getMetas } = require('./lib/metadata');
|
const { getMetas } = require('./lib/metadata');
|
||||||
const { cacheWrapCatalog, cacheWrapIds } = require('./lib/cache');
|
const { cacheWrapCatalog, cacheWrapIds } = require('./lib/cache');
|
||||||
@@ -17,19 +18,23 @@ const limiter = new Bottleneck({
|
|||||||
highWater: process.env.LIMIT_QUEUE_SIZE || 50,
|
highWater: process.env.LIMIT_QUEUE_SIZE || 50,
|
||||||
strategy: Bottleneck.strategy.OVERFLOW
|
strategy: Bottleneck.strategy.OVERFLOW
|
||||||
});
|
});
|
||||||
|
const defaultProviders = Providers.options
|
||||||
|
.filter(provider => !provider.foreign)
|
||||||
|
.map(provider => provider.label)
|
||||||
|
.sort();
|
||||||
|
|
||||||
builder.defineCatalogHandler((args) => {
|
builder.defineCatalogHandler((args) => {
|
||||||
const offset = parseInt(args.extra.skip || '0', 10);
|
const offset = parseInt(args.extra.skip || '0', 10);
|
||||||
const genre = args.extra.genre || 'default';
|
const genre = args.extra.genre || 'default';
|
||||||
const catalog = manifest.catalogs.find(c => c.id === args.id);
|
const catalog = manifest.catalogs.find(c => c.id === args.id);
|
||||||
|
const providers = defaultProviders;
|
||||||
console.log(`Incoming catalog ${args.id} request with genre=${genre} and skip=${offset}`)
|
console.log(`Incoming catalog ${args.id} request with genre=${genre} and skip=${offset}`)
|
||||||
if (!catalog) {
|
if (!catalog) {
|
||||||
return Promise.reject(`No catalog found for with id: ${args.id}`)
|
return Promise.reject(`No catalog found for with id: ${args.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cacheKey = `${args.id}|${genre}|${dateKey()}|${offset}`
|
const cacheKey = createCacheKey(catalog.id, providers, genre, offset);
|
||||||
return limiter.schedule(() => cacheWrapCatalog(cacheKey, () => getCatalog(catalog, genre, offset)))
|
return limiter.schedule(() => cacheWrapCatalog(cacheKey, () => getCatalog(catalog, providers, genre, offset)))
|
||||||
.then(metas => ({
|
.then(metas => ({
|
||||||
metas: metas,
|
metas: metas,
|
||||||
cacheMaxAge: CACHE_MAX_AGE,
|
cacheMaxAge: CACHE_MAX_AGE,
|
||||||
@@ -39,23 +44,24 @@ builder.defineCatalogHandler((args) => {
|
|||||||
.catch(error => Promise.reject(`Failed retrieving catalog ${args.id}: ${JSON.stringify(error)}`));
|
.catch(error => Promise.reject(`Failed retrieving catalog ${args.id}: ${JSON.stringify(error)}`));
|
||||||
})
|
})
|
||||||
|
|
||||||
async function getCursor(catalog, genre, offset) {
|
async function getCursor(catalog, providers, genre, offset) {
|
||||||
if (offset === 0) {
|
if (offset === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const previousCacheKey = `${catalog.id}|${genre}|${dateKey()}|${offset - catalog.pageSize}`;
|
const previousOffset = offset - catalog.pageSize;
|
||||||
|
const previousCacheKey = createCacheKey(catalog.id, providers, genre, previousOffset);
|
||||||
return cacheWrapCatalog(previousCacheKey, () => Promise.reject("cursor not found"))
|
return cacheWrapCatalog(previousCacheKey, () => Promise.reject("cursor not found"))
|
||||||
.then(metas => metas[metas.length - 1])
|
.then(metas => metas[metas.length - 1])
|
||||||
.then(meta => meta.id.replace('kitsu:', ''))
|
.then(meta => meta.id.replace('kitsu:', ''))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCatalog(catalog, genre, offset) {
|
async function getCatalog(catalog, providers, genre, offset) {
|
||||||
const cursor = await getCursor(catalog, genre, offset)
|
const cursor = await getCursor(catalog, providers, genre, offset)
|
||||||
const startDate = getStartDate(genre)?.toISOString();
|
const startDate = getStartDate(genre)?.toISOString();
|
||||||
const endDate = getEndDate(genre)?.toISOString();
|
const endDate = getEndDate(genre)?.toISOString();
|
||||||
const cacheKey = `${catalog.id}|${genre}|${dateKey()}`
|
const cacheKey = createCacheKey(catalog.id, providers, genre);
|
||||||
|
|
||||||
return cacheWrapIds(cacheKey, () => repository.getIds(catalog.type, startDate, endDate))
|
return cacheWrapIds(cacheKey, () => repository.getIds(providers, catalog.type, startDate, endDate))
|
||||||
.then(ids => ids.slice(ids.indexOf(cursor) + 1))
|
.then(ids => ids.slice(ids.indexOf(cursor) + 1))
|
||||||
.then(ids => getMetas(ids, catalog.type))
|
.then(ids => getMetas(ids, catalog.type))
|
||||||
.then(metas => metas.slice(0, catalog.pageSize));
|
.then(metas => metas.slice(0, catalog.pageSize));
|
||||||
@@ -85,8 +91,9 @@ function getEndDate(genre) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dateKey() {
|
function createCacheKey(catalogId, providers, genre, offset) {
|
||||||
return moment().format('YYYY-MM-DD')
|
const dateKey = moment().format('YYYY-MM-DD');
|
||||||
|
return [catalogId, providers.join(','), genre, dateKey, offset].filter(x => x !== undefined).join('|');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = builder.getInterface();
|
module.exports = builder.getInterface();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const DATABASE_URI = process.env.DATABASE_URI;
|
|||||||
|
|
||||||
const database = new Sequelize(DATABASE_URI, { logging: false });
|
const database = new Sequelize(DATABASE_URI, { logging: false });
|
||||||
|
|
||||||
async function getIds(type, startDate, endDate) {
|
async function getIds(providers, type, startDate, endDate) {
|
||||||
const idName = type === Type.ANIME ? 'kitsuId' : 'imdbId';
|
const idName = type === Type.ANIME ? 'kitsuId' : 'imdbId';
|
||||||
const episodeCondition = type === Type.SERIES
|
const episodeCondition = type === Type.SERIES
|
||||||
? 'AND files."imdbSeason" IS NOT NULL AND files."imdbEpisode" IS NOT NULL'
|
? 'AND files."imdbSeason" IS NOT NULL AND files."imdbEpisode" IS NOT NULL'
|
||||||
@@ -13,9 +13,12 @@ async function getIds(type, startDate, endDate) {
|
|||||||
const dateCondition = startDate && endDate
|
const dateCondition = startDate && endDate
|
||||||
? `AND "uploadDate" BETWEEN '${startDate}' AND '${endDate}'`
|
? `AND "uploadDate" BETWEEN '${startDate}' AND '${endDate}'`
|
||||||
: ''
|
: ''
|
||||||
|
const providersCondition = providers && providers.length
|
||||||
|
? `AND provider in (${providers.map(it => `'${it}'`).join(',')})`
|
||||||
|
: ''
|
||||||
const query = `SELECT files."${idName}"
|
const query = `SELECT files."${idName}"
|
||||||
FROM (SELECT torrents."infoHash", torrents.seeders FROM torrents
|
FROM (SELECT torrents."infoHash", torrents.seeders FROM torrents
|
||||||
WHERE seeders > 0 AND type = '${type}' ${dateCondition}
|
WHERE seeders > 0 AND type = '${type}' ${providersCondition} ${dateCondition}
|
||||||
) as torrents
|
) as torrents
|
||||||
JOIN files ON torrents."infoHash" = files."infoHash"
|
JOIN files ON torrents."infoHash" = files."infoHash"
|
||||||
WHERE files."${idName}" IS NOT NULL ${episodeCondition}
|
WHERE files."${idName}" IS NOT NULL ${episodeCondition}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ router.get('/:configuration/:resource/:type/:id/:extra?.json', (req, res, next)
|
|||||||
staleError: 'stale-if-error'
|
staleError: 'stale-if-error'
|
||||||
};
|
};
|
||||||
const cacheControl = Object.keys(cacheHeaders)
|
const cacheControl = Object.keys(cacheHeaders)
|
||||||
.map(prop => resp[prop] && cacheHeaders[prop] + '=' + resp[prop])
|
.map(prop => Number.isInteger(resp[prop]) && cacheHeaders[prop] + '=' + resp[prop])
|
||||||
.filter(val => !!val).join(', ');
|
.filter(val => !!val).join(', ');
|
||||||
|
|
||||||
res.setHeader('Cache-Control', `${cacheControl}, public`);
|
res.setHeader('Cache-Control', `${cacheControl}, public`);
|
||||||
|
|||||||
Reference in New Issue
Block a user