mirror of
https://github.com/Viren070/AIOStreams.git
synced 2025-12-01 23:14:04 +01:00
@@ -0,0 +1,183 @@
|
||||
import {
|
||||
Addon,
|
||||
Option,
|
||||
ParsedStream,
|
||||
ParsedFile,
|
||||
Stream,
|
||||
UserData,
|
||||
} from '../db';
|
||||
import { Preset, baseOptions } from './preset';
|
||||
import { constants, Env, HTTP_STREAM_TYPE, LIVE_STREAM_TYPE } from '../utils';
|
||||
import { FileParser, StreamParser } from '../parser';
|
||||
|
||||
class AStreamStreamParser extends StreamParser {
|
||||
protected override getParsedFile(
|
||||
stream: Stream,
|
||||
parsedStream: ParsedStream
|
||||
): ParsedFile | undefined {
|
||||
const parsed =
|
||||
typeof stream.language === 'string'
|
||||
? FileParser.parse(stream.language)
|
||||
: undefined;
|
||||
if (!parsed) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...parsed,
|
||||
title: undefined,
|
||||
};
|
||||
}
|
||||
protected override getIndexer(
|
||||
stream: Stream,
|
||||
currentParsedStream: ParsedStream
|
||||
): string | undefined {
|
||||
const indexer = super.getIndexer(stream, currentParsedStream);
|
||||
if (indexer && typeof indexer === 'string') {
|
||||
try {
|
||||
return new URL(indexer).hostname;
|
||||
} catch {}
|
||||
}
|
||||
return indexer;
|
||||
}
|
||||
protected override getFilename(
|
||||
stream: Stream,
|
||||
currentParsedStream: ParsedStream
|
||||
): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
protected override getMessage(
|
||||
stream: Stream,
|
||||
currentParsedStream: ParsedStream
|
||||
): string | undefined {
|
||||
if (stream.language === 'vostfr') return 'VOSTFR';
|
||||
}
|
||||
protected getStreamType(
|
||||
stream: Stream,
|
||||
service: ParsedStream['service'],
|
||||
currentParsedStream: ParsedStream
|
||||
): ParsedStream['type'] {
|
||||
return constants.HTTP_STREAM_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
export class AStreamPreset extends Preset {
|
||||
static override getParser(): typeof StreamParser {
|
||||
return AStreamStreamParser;
|
||||
}
|
||||
|
||||
static override get METADATA() {
|
||||
const supportedResources = [
|
||||
constants.CATALOG_RESOURCE,
|
||||
constants.META_RESOURCE,
|
||||
constants.STREAM_RESOURCE,
|
||||
];
|
||||
|
||||
const options: Option[] = [
|
||||
...baseOptions(
|
||||
'AStream',
|
||||
supportedResources,
|
||||
Env.DEFAULT_ASTREAM_TIMEOUT
|
||||
),
|
||||
{
|
||||
id: 'language',
|
||||
name: 'Language',
|
||||
description: 'Language of the streams',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'Tout / Both', value: 'Tout' },
|
||||
{ label: 'VOSTFR / French Subtitles Only', value: 'VOSTFR' },
|
||||
{ label: 'VF / French Dub Only', value: 'VF' },
|
||||
],
|
||||
default: 'Tout',
|
||||
},
|
||||
{
|
||||
id: 'tmdbEnabled',
|
||||
name: 'Activate TMDB Metadata (Recommended)',
|
||||
description:
|
||||
'Replaces images and descriptions with TMDB images (Requires a TMDB API Key to be provided in the services menu)',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
id: 'tmdbEpisodeMapping',
|
||||
name: 'TMDB Episode Mapping (Recommended)',
|
||||
description:
|
||||
'Use TMDB titles and descriptions instead of AStream ones (Requires a TMDB API Key to be provided in the services menu)',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
ID: 'astream',
|
||||
NAME: 'AStream',
|
||||
LOGO: `https://raw.githubusercontent.com/Dydhzo/astream/refs/heads/main/astream/assets/astream-logo.jpg`,
|
||||
URL: Env.ASTREAM_URL,
|
||||
TIMEOUT: Env.DEFAULT_ASTREAM_TIMEOUT || Env.DEFAULT_TIMEOUT,
|
||||
USER_AGENT: Env.DEFAULT_ASTREAM_USER_AGENT || Env.DEFAULT_USER_AGENT,
|
||||
SUPPORTED_SERVICES: [],
|
||||
DESCRIPTION: "Addon non officiel pour accéder au contenu d'Anime-Sama",
|
||||
OPTIONS: options,
|
||||
SUPPORTED_STREAM_TYPES: [HTTP_STREAM_TYPE],
|
||||
SUPPORTED_RESOURCES: supportedResources,
|
||||
};
|
||||
}
|
||||
|
||||
static async generateAddons(
|
||||
userData: UserData,
|
||||
options: Record<string, any>
|
||||
): Promise<Addon[]> {
|
||||
return [this.generateAddon(userData, options)];
|
||||
}
|
||||
|
||||
private static generateAddon(
|
||||
userData: UserData,
|
||||
options: Record<string, any>
|
||||
): Addon {
|
||||
return {
|
||||
name: options.name || this.METADATA.NAME,
|
||||
manifestUrl: this.generateManifestUrl(userData, options),
|
||||
enabled: true,
|
||||
library: false,
|
||||
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>
|
||||
): string {
|
||||
if (options.url?.endsWith('/manifest.json')) {
|
||||
return options.url;
|
||||
}
|
||||
const url = (options.url || this.METADATA.URL).replace(/\/$/, '');
|
||||
|
||||
if (
|
||||
(options.tmdbEnabled || options.tmdbEpisodeMapping) &&
|
||||
!userData.tmdbApiKey
|
||||
) {
|
||||
throw new Error(
|
||||
`${this.METADATA.NAME} requires a TMDB API Key to use TMDB features. Please provide it in the services menu. `
|
||||
);
|
||||
}
|
||||
|
||||
const config = {
|
||||
language: options.language || 'Tout',
|
||||
languageOrder: 'VF,VOSTFR',
|
||||
tmdbApiKey: userData.tmdbApiKey,
|
||||
tmdbEnabled: options.tmdbEnabled,
|
||||
tmdbEpisodeMapping: options.tmdbEpisodeMapping,
|
||||
};
|
||||
|
||||
return `${url}/${this.base64EncodeJSON(config)}/manifest.json`;
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ import { ContentDeepDivePreset } from './contentDeepDive';
|
||||
import { AICompanionPreset } from './aiCompanion';
|
||||
import { GoogleOAuth } from '../builtins/gdrive/api';
|
||||
import { TorBoxSearchPreset } from './torboxSearch';
|
||||
import { AStreamPreset } from './aStream';
|
||||
import { Env } from '../utils/env';
|
||||
|
||||
let PRESET_LIST: string[] = [
|
||||
@@ -76,6 +77,7 @@ let PRESET_LIST: string[] = [
|
||||
'dmm-cast',
|
||||
'nuvio-streams',
|
||||
'webstreamr',
|
||||
'astream',
|
||||
'streamasia',
|
||||
Env.BUILTIN_GDRIVE_CLIENT_ID && Env.BUILTIN_GDRIVE_CLIENT_SECRET
|
||||
? 'stremio-gdrive'
|
||||
@@ -184,6 +186,8 @@ export class PresetManager {
|
||||
return NuvioStreamsPreset;
|
||||
case 'webstreamr':
|
||||
return WebStreamrPreset;
|
||||
case 'astream':
|
||||
return AStreamPreset;
|
||||
case 'streaming-catalogs':
|
||||
return StreamingCatalogsPreset;
|
||||
case 'anime-catalogs':
|
||||
|
||||
@@ -1383,6 +1383,19 @@ export const Env = cleanEnv(process.env, {
|
||||
desc: 'Default AI Companion user agent',
|
||||
}),
|
||||
|
||||
ASTREAM_URL: url({
|
||||
default: 'https://astream.stremiofr.com',
|
||||
desc: 'AStream URL',
|
||||
}),
|
||||
DEFAULT_ASTREAM_TIMEOUT: num({
|
||||
default: undefined,
|
||||
desc: 'Default AStream timeout',
|
||||
}),
|
||||
DEFAULT_ASTREAM_USER_AGENT: userAgent({
|
||||
default: undefined,
|
||||
desc: 'Default AStream user agent',
|
||||
}),
|
||||
|
||||
BUILTIN_STREMTHRU_URL: url({
|
||||
default: 'https://stremthru.13377001.xyz',
|
||||
desc: 'Builtin StremThru URL',
|
||||
|
||||
Reference in New Issue
Block a user