diff --git a/addon/addon.js b/addon/addon.js
index 5854b27..a2dbd0e 100644
--- a/addon/addon.js
+++ b/addon/addon.js
@@ -1,11 +1,12 @@
const Bottleneck = require('bottleneck');
const { addonBuilder } = require('stremio-addon-sdk');
const { Type } = require('./lib/types');
-const { dummyManifest, DefaultProviders } = require('./lib/manifest');
+const { dummyManifest } = require('./lib/manifest');
const { cacheWrapStream } = require('./lib/cache');
const { toStreamInfo, applyStaticInfo } = require('./lib/streamInfo');
const repository = require('./lib/repository');
const applySorting = require('./lib/sort');
+const applyFilters = require('./lib/filter');
const { applyMochs, getMochCatalog, getMochItemMeta } = require('./moch/moch');
const CACHE_MAX_AGE = process.env.CACHE_MAX_AGE || 4 * 60 * 60; // 4 hours in seconds
@@ -13,7 +14,6 @@ const CACHE_MAX_AGE_EMPTY = 30 * 60; // 30 minutes
const STALE_REVALIDATE_AGE = 4 * 60 * 60; // 4 hours
const STALE_ERROR_AGE = 7 * 24 * 60 * 60; // 7 days
-const defaultProviders = DefaultProviders.map(provider => provider.toLowerCase());
const builder = new addonBuilder(dummyManifest());
const limiter = new Bottleneck({
maxConcurrent: process.env.LIMIT_MAX_CONCURRENT || 20,
@@ -30,7 +30,7 @@ builder.defineStreamHandler((args) => {
.then(records => records
.sort((a, b) => b.torrent.seeders - a.torrent.seeders || b.torrent.uploadDate - a.torrent.uploadDate)
.map(record => toStreamInfo(record)))))
- .then(streams => filterByProvider(streams, args.extra.providers || defaultProviders))
+ .then(streams => applyFilters(streams, args.extra))
.then(streams => applySorting(streams, args.extra))
.then(streams => applyStaticInfo(streams))
.then(streams => applyMochs(streams, args.extra))
@@ -111,15 +111,4 @@ async function movieRecordsHandler(args) {
return Promise.resolve([]);
}
-function filterByProvider(streams, providers) {
- if (!providers || !providers.length) {
- return streams;
- }
- return streams.filter(stream => {
- const match = stream.title.match(/⚙.* ([^ \n]+)/);
- const provider = match && match[1].toLowerCase();
- return providers.includes(provider);
- })
-}
-
module.exports = builder.getInterface();
diff --git a/addon/lib/configuration.js b/addon/lib/configuration.js
index ef4df8d..a83a291 100644
--- a/addon/lib/configuration.js
+++ b/addon/lib/configuration.js
@@ -1,3 +1,8 @@
+const { DebridOptions } = require('../moch/options');
+const { QualityFilter } = require('./filter');
+
+const keysToSplit = ['providers', QualityFilter.key, DebridOptions.key];
+
function parseConfiguration(configuration) {
const configValues = configuration.split('|')
.reduce((map, next) => {
@@ -7,12 +12,9 @@ function parseConfiguration(configuration) {
}
return map;
}, {});
- if (configValues.providers) {
- configValues.providers = configValues.providers.split(',').map(provider => provider.toLowerCase());
- }
- if (configValues.debridoptions) {
- configValues.debridoptions = configValues.debridoptions.split(',').map(option => option.toLowerCase());
- }
+ keysToSplit
+ .filter(key => configValues[key])
+ .filter(key => configValues[key] = configValues[key].split(',').map(provider => provider.toLowerCase()))
return configValues;
}
diff --git a/addon/lib/filter.js b/addon/lib/filter.js
new file mode 100644
index 0000000..4b1ffe8
--- /dev/null
+++ b/addon/lib/filter.js
@@ -0,0 +1,114 @@
+const Providers = [
+ 'YTS',
+ 'EZTV',
+ 'RARBG',
+ '1337x',
+ 'ThePirateBay',
+ 'KickassTorrents',
+ 'TorrentGalaxy',
+ 'Rutor',
+ 'HorribleSubs',
+ 'NyaaSi',
+ 'NyaaPantsu'
+];
+const QualityFilter = {
+ key: 'qualityfilter',
+ options: [
+ {
+ key: "4k",
+ label: "4k",
+ items: ["4k"],
+ test(quality) {
+ return this.items.includes(quality);
+ }
+ },
+ {
+ key: "1080p",
+ label: "1080p",
+ items: ["1080p"],
+ test(quality) {
+ return this.items.includes(quality)
+ }
+ },
+ {
+ key: "720p",
+ label: "720p",
+ items: ["720p"],
+ test(quality) {
+ return this.items.includes(quality)
+ }
+ },
+ {
+ key: "480p",
+ label: "480p",
+ items: ["480p"],
+ test(quality) {
+ return this.items.includes(quality)
+ }
+ },
+ {
+ key: "sd",
+ label: "SD",
+ items: ["DVDRip", "HDRip", "BDRip", "BRRip", "BluRay", "WED-DL", "WEBRip", "HDTV", "DivX", "XviD"],
+ test(quality) {
+ return this.items.includes(quality)
+ }
+ },
+ {
+ key: "scr",
+ label: "Screener",
+ items: ["SCR"],
+ test(quality) {
+ return this.items.includes(quality)
+ }
+ },
+ {
+ key: "cam",
+ label: "Cam",
+ items: ["CAM", "TeleSync", "TeleCine"],
+ test(quality) {
+ return this.items.includes(quality)
+ }
+ },
+ {
+ key: "unknown",
+ label: "Unknown",
+ test(quality) {
+ return !quality
+ }
+ }
+ ]
+};
+const defaultProviderKeys = Providers.map(provider => provider.toLowerCase());
+
+function applyFilters(streams, config) {
+ return filterByQuality(filterByProvider(streams, config), config);
+}
+
+function filterByProvider(streams, config) {
+ const providers = config.providers || defaultProviderKeys;
+ if (!providers || !providers.length) {
+ return streams;
+ }
+ return streams.filter(stream => {
+ const match = stream.title.match(/⚙.* ([^ \n]+)/);
+ const provider = match && match[1].toLowerCase();
+ return providers.includes(provider);
+ })
+}
+
+function filterByQuality(streams, config) {
+ const filters = config[QualityFilter.key];
+ if (!filters) {
+ return streams;
+ }
+ const filterOptions = QualityFilter.options.filter(option => filters.includes(option.key));
+ return streams.filter(stream => {
+ const streamQuality = stream.name.split('\n')[1];
+ return !filterOptions.some(option => option.test(streamQuality));
+ });
+}
+
+module.exports = applyFilters;
+module.exports.Providers = Providers;
+module.exports.QualityFilter = QualityFilter;
\ No newline at end of file
diff --git a/addon/lib/landingTemplate.js b/addon/lib/landingTemplate.js
index 038fee5..d031c9d 100644
--- a/addon/lib/landingTemplate.js
+++ b/addon/lib/landingTemplate.js
@@ -180,14 +180,16 @@ button:active {
box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
}
`;
-const { Providers } = require('./manifest');
+const { Providers } = require('./filter');
const { SortOptions } = require('./sort');
+const { QualityFilter } = require('./filter');
const { DebridOptions } = require('../moch/options');
const { MochOptions } = require('../moch/moch');
function landingTemplate(manifest, config = {}) {
const providers = config.providers || [];
- const sort = config.sort || SortOptions.options.qualitySeeders.key;
+ const sort = config[SortOptions.key] || SortOptions.options.qualitySeeders.key;
+ const qualityFilters = config[QualityFilter.key] || [];
const limit = config.limit || '';
const debridProvider = Object.keys(MochOptions).find(mochKey => config[mochKey]);
@@ -212,6 +214,9 @@ function landingTemplate(manifest, config = {}) {
const sortOptionsHTML = Object.values(SortOptions.options)
.map((option, i) => ``)
.join('\n');
+ const qualityFiltersHTML = Object.values(QualityFilter.options)
+ .map(option => ``)
+ .join('\n');
const debridProvidersHTML = Object.values(MochOptions)
.map(moch => ``)
.join('\n');
@@ -267,6 +272,11 @@ function landingTemplate(manifest, config = {}) {
${sortOptionsHTML}
+
+
+
@@ -318,6 +328,11 @@ function landingTemplate(manifest, config = {}) {
onChange: () => generateInstallLink()
});
$('#iProviders').multiselect('select', [${providers.map(provider => '"' + provider + '"')}]);
+ $('#iQualityFilter').multiselect({
+ nonSelectedText: 'None',
+ onChange: () => generateInstallLink()
+ });
+ $('#iQualityFilter').multiselect('select', [${qualityFilters.map(filter => '"' + filter + '"')}]);
$('#iDebridOptions').multiselect({
nonSelectedText: 'None',
onChange: () => generateInstallLink()
@@ -355,6 +370,7 @@ function landingTemplate(manifest, config = {}) {
function generateInstallLink() {
const providersValue = $('#iProviders').val().join(',') || '';
+ const qualityFilterValue = $('#iQualityFilter').val().join(',') || '';
const sortValue = $('#iSort').val() || '';
const limitValue = $('#iLimit').val() || '';
@@ -367,6 +383,7 @@ function landingTemplate(manifest, config = {}) {
const providers = providersValue.length && providersValue;
+ const qualityFilters = qualityFilterValue.length && qualityFilterValue;
const sort = sortValue !== '${SortOptions.options.qualitySeeders.key}' && sortValue;
const limit = /^[1-9][0-9]*$/.test(limitValue) && limitValue;
@@ -380,6 +397,7 @@ function landingTemplate(manifest, config = {}) {
['providers', providers],
['${SortOptions.key}', sort],
['limit', limit],
+ ['${QualityFilter.key}', qualityFilters],
['${DebridOptions.key}', debridOptions],
['${MochOptions.realdebrid.key}', realDebrid],
['${MochOptions.premiumize.key}', premiumize],
diff --git a/addon/lib/manifest.js b/addon/lib/manifest.js
index 89a6973..be36f96 100644
--- a/addon/lib/manifest.js
+++ b/addon/lib/manifest.js
@@ -1,20 +1,8 @@
const { MochOptions } = require('../moch/moch');
+const { Providers } = require('./filter');
const { showDebridCatalog } = require('../moch/options');
const { Type } = require('./types');
-const Providers = [
- 'YTS',
- 'EZTV',
- 'RARBG',
- '1337x',
- 'ThePirateBay',
- 'KickassTorrents',
- 'TorrentGalaxy',
- 'Rutor',
- 'HorribleSubs',
- 'NyaaSi',
- 'NyaaPantsu'
-];
const DefaultProviders = Providers
const CatalogMochs = Object.values(MochOptions).filter(moch => moch.catalog);
@@ -31,7 +19,7 @@ function manifest(config = {}) {
const mochsDesc = enabledMochs ? ` and ${enabledMochs} enabled` : '';
return {
id: 'com.stremio.torrentio.addon',
- version: '0.0.9',
+ version: '0.0.10',
name: 'Torrentio',
description: 'Provides torrent streams from scraped torrent providers.'
+ ` Currently supports ${enabledProvidersDesc}${mochsDesc}.`
@@ -86,4 +74,4 @@ function getResources(config) {
return [streamResource];
}
-module.exports = { manifest, dummyManifest, Providers, DefaultProviders };
\ No newline at end of file
+module.exports = { manifest, dummyManifest };
\ No newline at end of file
diff --git a/addon/lib/streamInfo.js b/addon/lib/streamInfo.js
index 4a279a1..d1f822e 100644
--- a/addon/lib/streamInfo.js
+++ b/addon/lib/streamInfo.js
@@ -60,7 +60,7 @@ function toStreamInfo(record) {
function getQuality(record, torrentInfo, fileInfo) {
const resolution = fileInfo.resolution || torrentInfo.resolution || record.torrent.resolution;
const source = fileInfo.source || torrentInfo.source;
- if (['CAM', 'TeleSync'].includes(source)) {
+ if (['CAM', 'TeleSync', 'TeleCine'].includes(source)) {
return source;
}
return resolution || source;
diff --git a/addon/package-lock.json b/addon/package-lock.json
index 382d1d6..919fb64 100644
--- a/addon/package-lock.json
+++ b/addon/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "stremio-torrentio",
- "version": "1.0.9",
+ "version": "1.0.10",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/addon/package.json b/addon/package.json
index 85f1125..565ace3 100644
--- a/addon/package.json
+++ b/addon/package.json
@@ -1,6 +1,6 @@
{
"name": "stremio-torrentio",
- "version": "1.0.9",
+ "version": "1.0.10",
"main": "addon.js",
"scripts": {
"start": "node index.js"