mirror of
https://github.com/Viren070/AIOStreams.git
synced 2025-12-01 23:14:04 +01:00
feat: add sootio preset
This commit is contained in:
@@ -644,6 +644,10 @@ PRUNE_MAX_DAYS=-1
|
||||
# FORCE_STREMTHRU_TORZ_PORT=
|
||||
# FORCE_STREMTHRU_TORZ_PROTOCOL=
|
||||
|
||||
# --------- Sootio ---------
|
||||
# SOOTIO_URL=https://sootio.elfhosted.com
|
||||
# DEFAULT_SOOTIO_TIMEOUT=
|
||||
|
||||
# --------- EASYNEWS+ ADDON ---------
|
||||
# EASYNEWS_PLUS_URL=https://b89262c192b0-stremio-easynews-addon.baby-beamup.club/
|
||||
# DEFAULT_EASYNEWS_PLUS_TIMEOUT=
|
||||
|
||||
@@ -63,6 +63,7 @@ import { JackettPreset } from './jackett.js';
|
||||
import { NZBHydraPreset } from './nzbhydra.js';
|
||||
import { KnabenPreset } from './knaben.js';
|
||||
import { BitmagnetPreset } from './bitmagnet.js';
|
||||
import { SootioPreset } from './sootio.js';
|
||||
|
||||
let PRESET_LIST: string[] = [
|
||||
'custom',
|
||||
@@ -74,6 +75,7 @@ let PRESET_LIST: string[] = [
|
||||
'mediafusion',
|
||||
'stremthruTorz',
|
||||
'stremthruStore',
|
||||
'sootio',
|
||||
'zilean',
|
||||
'knaben',
|
||||
Env.BUILTIN_BITMAGNET_URL ? 'bitmagnet' : '',
|
||||
@@ -272,6 +274,8 @@ export class PresetManager {
|
||||
return KnabenPreset;
|
||||
case 'bitmagnet':
|
||||
return BitmagnetPreset;
|
||||
case 'sootio':
|
||||
return SootioPreset;
|
||||
default:
|
||||
throw new Error(`Preset ${id} not found`);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
import {
|
||||
Addon,
|
||||
Option,
|
||||
UserData,
|
||||
Resource,
|
||||
Stream,
|
||||
ParsedStream,
|
||||
} from '../db/index.js';
|
||||
import { baseOptions, Preset } from './preset.js';
|
||||
import { createLogger, Env, getSimpleTextHash } from '../utils/index.js';
|
||||
import { constants, ServiceId } from '../utils/index.js';
|
||||
import { StreamParser } from '../parser/index.js';
|
||||
|
||||
class SootioStreamParser extends StreamParser {
|
||||
protected override getInLibrary(
|
||||
stream: Stream,
|
||||
currentParsedStream: ParsedStream
|
||||
): boolean {
|
||||
return stream.description?.includes('[Cloud]') ?? false;
|
||||
}
|
||||
protected override getIndexer(
|
||||
stream: Stream,
|
||||
currentParsedStream: ParsedStream
|
||||
): string | undefined {
|
||||
return /[☁️💾][^|]*\|\s*(.*)$/s.exec(stream.description || '')?.[1];
|
||||
}
|
||||
}
|
||||
|
||||
export class SootioPreset extends Preset {
|
||||
static override getParser(): typeof StreamParser {
|
||||
return SootioStreamParser;
|
||||
}
|
||||
|
||||
static override get METADATA() {
|
||||
const supportedServices: ServiceId[] = [
|
||||
constants.REALDEBRID_SERVICE,
|
||||
constants.OFFCLOUD_SERVICE,
|
||||
];
|
||||
|
||||
const supportedResources = [
|
||||
constants.STREAM_RESOURCE,
|
||||
constants.CATALOG_RESOURCE,
|
||||
];
|
||||
|
||||
const options: Option[] = [
|
||||
...baseOptions(
|
||||
'Sootio',
|
||||
supportedResources,
|
||||
Env.DEFAULT_SOOTIO_TIMEOUT,
|
||||
Env.SOOTIO_URL
|
||||
),
|
||||
{
|
||||
id: 'services',
|
||||
name: 'Services',
|
||||
description:
|
||||
'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
|
||||
type: 'multi-select',
|
||||
required: false,
|
||||
showInNoobMode: false,
|
||||
options: supportedServices.map((service) => ({
|
||||
value: service,
|
||||
label: constants.SERVICE_DETAILS[service].name,
|
||||
})),
|
||||
default: undefined,
|
||||
emptyIsUndefined: true,
|
||||
},
|
||||
{
|
||||
id: 'socials',
|
||||
name: '',
|
||||
description: '',
|
||||
type: 'socials',
|
||||
socials: [
|
||||
{
|
||||
id: 'github',
|
||||
url: 'https://github.com/sooti/stremio-addon-debrid-search',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
ID: 'sootio',
|
||||
NAME: 'Sootio',
|
||||
LOGO: `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cdefs%3E%3ClinearGradient id='grad' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' style='stop-color:%2364ffda;stop-opacity:1' /%3E%3Cstop offset='100%25' style='stop-color:%2300A7B5;stop-opacity:1' /%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23grad)' d='M50,5 C74.85,5 95,25.15 95,50 C95,74.85 74.85,95 50,95 C35,95 22.33,87.6 15,76 C25,85 40,85 50,80 C60,75 65,65 65,50 C65,35 55,25 40,25 C25,25 15,40 15,50 C15,55 16,60 18,64 C8.5,58 5,45 5,50 C5,25.15 25.15,5 50,5 Z'/%3E%3C/svg%3E`,
|
||||
URL: Env.SOOTIO_URL[0],
|
||||
TIMEOUT: Env.DEFAULT_SOOTIO_TIMEOUT || Env.DEFAULT_TIMEOUT,
|
||||
USER_AGENT: Env.DEFAULT_SOOTIO_USER_AGENT || Env.DEFAULT_USER_AGENT,
|
||||
SUPPORTED_SERVICES: supportedServices,
|
||||
DESCRIPTION: 'Debrid addon.',
|
||||
OPTIONS: options,
|
||||
SUPPORTED_STREAM_TYPES: [constants.DEBRID_STREAM_TYPE],
|
||||
SUPPORTED_RESOURCES: supportedResources,
|
||||
};
|
||||
}
|
||||
|
||||
static async generateAddons(
|
||||
userData: UserData,
|
||||
options: Record<string, any>
|
||||
): Promise<Addon[]> {
|
||||
if (options?.url?.endsWith('/manifest.json')) {
|
||||
return [this.generateAddon(userData, options, undefined)];
|
||||
}
|
||||
|
||||
const usableServices = this.getUsableServices(userData, options.services);
|
||||
|
||||
if (!usableServices || usableServices.length === 0) {
|
||||
throw new Error(
|
||||
`${this.METADATA.NAME} requires at least one usable service, but none were found. Please enable at least one of the following services: ${this.METADATA.SUPPORTED_SERVICES.join(
|
||||
', '
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
let addons = usableServices.map((service) => {
|
||||
return this.generateAddon(userData, options, service.id);
|
||||
});
|
||||
|
||||
return addons;
|
||||
}
|
||||
|
||||
private static generateAddon(
|
||||
userData: UserData,
|
||||
options: Record<string, any>,
|
||||
serviceId?: ServiceId
|
||||
): Addon {
|
||||
return {
|
||||
name: options.name || this.METADATA.NAME,
|
||||
identifier: serviceId
|
||||
? `${constants.SERVICE_DETAILS[serviceId].shortName}`
|
||||
: undefined,
|
||||
displayIdentifier: serviceId
|
||||
? `${constants.SERVICE_DETAILS[serviceId].shortName}`
|
||||
: undefined,
|
||||
manifestUrl: this.generateManifestUrl(userData, options, serviceId),
|
||||
enabled: true,
|
||||
resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
|
||||
timeout: options.timeout || this.METADATA.TIMEOUT,
|
||||
preset: {
|
||||
id: '',
|
||||
type: this.METADATA.ID,
|
||||
options: options,
|
||||
},
|
||||
headers: {
|
||||
'User-Agent': this.METADATA.USER_AGENT,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private static generateManifestUrl(
|
||||
userData: UserData,
|
||||
options: Record<string, any>,
|
||||
serviceId?: ServiceId
|
||||
) {
|
||||
const url = (options.url || this.METADATA.URL).replace(/\/$/, '');
|
||||
if (url.endsWith('/manifest.json')) {
|
||||
return url;
|
||||
}
|
||||
if (!serviceId) {
|
||||
throw new Error(
|
||||
`${this.METADATA.NAME} requires at least one usable service, but none were found. Please enable at least one of the following services: ${this.METADATA.SUPPORTED_SERVICES.join(
|
||||
', '
|
||||
)}`
|
||||
);
|
||||
}
|
||||
const serviceNameMap: Partial<Record<ServiceId, string>> = {
|
||||
realdebrid: 'RealDebrid',
|
||||
offcloud: 'OffCloud',
|
||||
};
|
||||
const config = {
|
||||
DebridProvider: serviceNameMap[serviceId],
|
||||
DebridApiKey: this.getServiceCredential(serviceId, userData),
|
||||
};
|
||||
return `${url}/${this.urlEncodeJSON(config)}/manifest.json`;
|
||||
}
|
||||
}
|
||||
@@ -1185,6 +1185,19 @@ export const Env = cleanEnv(process.env, {
|
||||
desc: 'Default StreamFusion StremThru URL',
|
||||
}),
|
||||
|
||||
SOOTIO_URL: urlOrUrlList({
|
||||
default: ['https://sootio.elfhosted.com'],
|
||||
desc: 'Sootio URL',
|
||||
}),
|
||||
DEFAULT_SOOTIO_TIMEOUT: num({
|
||||
default: undefined,
|
||||
desc: 'Default Sootio timeout',
|
||||
}),
|
||||
DEFAULT_SOOTIO_USER_AGENT: userAgent({
|
||||
default: undefined,
|
||||
desc: 'Default Sootio user agent',
|
||||
}),
|
||||
|
||||
// DMM Cast settings
|
||||
DEFAULT_DMM_CAST_TIMEOUT: num({
|
||||
default: undefined,
|
||||
|
||||
Reference in New Issue
Block a user