mirror of
https://github.com/Viren070/AIOStreams.git
synced 2025-12-01 23:14:04 +01:00
feat: add easynews and easynews+ addons
This commit is contained in:
@@ -6,6 +6,23 @@ export function formatSize(bytes: number): string {
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
export function formatDuration(durationInMs: number): string {
|
||||
const seconds = Math.floor(durationInMs / 1000);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
|
||||
const formattedSeconds = seconds % 60;
|
||||
const formattedMinutes = minutes % 60;
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}h:${formattedMinutes}m:${formattedSeconds}s`;
|
||||
} else if (formattedSeconds > 0) {
|
||||
return `${formattedMinutes}m:${formattedSeconds}s`;
|
||||
} else {
|
||||
return `${formattedMinutes}m`;
|
||||
}
|
||||
}
|
||||
|
||||
export function languageToEmoji(language: string): string | undefined {
|
||||
return languageEmojiMap[language.toLowerCase()];
|
||||
}
|
||||
|
||||
@@ -17,3 +17,15 @@ export function extractSizeInBytes(string: string, k: number): number {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function extractDurationInMs(string: string): number {
|
||||
const durationPattern = /(?:(\d+)h:)?(?:(\d+)m:)?(\d+)s/;
|
||||
const match = string.match(durationPattern);
|
||||
if (!match) return 0;
|
||||
|
||||
const hours = parseInt(match[1] || '0');
|
||||
const minutes = parseInt(match[2] || '0');
|
||||
const seconds = parseInt(match[3]);
|
||||
|
||||
return (hours * 60 * 60 + minutes * 60 + seconds) * 1000;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface ParsedStream extends ParsedNameData {
|
||||
usenet?: {
|
||||
age?: string;
|
||||
};
|
||||
duration?: number;
|
||||
url?: string;
|
||||
externalUrl?: string;
|
||||
indexers?: string;
|
||||
|
||||
@@ -203,6 +203,78 @@ export const addonDetails: AddonDetail[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Easynews',
|
||||
id: 'easynews',
|
||||
requiresService: true,
|
||||
supportedServices: ['easynews'],
|
||||
options: [
|
||||
{
|
||||
id: 'overrideName',
|
||||
required: false,
|
||||
label: 'Override Addon Name',
|
||||
description:
|
||||
"Override the name of the addon that shows up in the results. Leave it empty to use the default name of 'Easynews'.",
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
id: 'overrideUrl',
|
||||
required: false,
|
||||
label: 'Override URL',
|
||||
description:
|
||||
'Override the URL used to fetch streams from the Easynews addon. By default, the URL is generated based on the username and password provided for the Easynews service. Use this option to override the URL with a custom URL.',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
id: 'indexerTimeout',
|
||||
required: false,
|
||||
label: 'Override Indexer Timeout',
|
||||
description:
|
||||
'The timeout for fetching streams from the Easynews addon in milliseconds. This is the time in milliseconds that the addon will wait for a response from Easynews before timing out. Leave it empty to use the recommended timeout.',
|
||||
type: 'number',
|
||||
constraints: {
|
||||
min: Settings.MIN_TIMEOUT,
|
||||
max: Settings.MAX_TIMEOUT,
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Easynews Plus',
|
||||
id: 'easynewsplus',
|
||||
requiresService: true,
|
||||
supportedServices: ['easynews'],
|
||||
options: [
|
||||
{
|
||||
id: 'overrideName',
|
||||
required: false,
|
||||
label: 'Override Addon Name',
|
||||
description:
|
||||
"Override the name of the addon that shows up in the results. Leave it empty to use the default name of 'Easynews Plus'.",
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
id: 'overrideUrl',
|
||||
required: false,
|
||||
label: 'Override URL',
|
||||
description:
|
||||
'Override the URL used to fetch streams from the Easynews Plus addon. By default, the URL is generated based on the username and password provided for the Easynews service. Use this option to override the URL with a custom URL.',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
id: 'indexerTimeout',
|
||||
required: false,
|
||||
label: 'Override Indexer Timeout',
|
||||
description:
|
||||
'The timeout for fetching streams from the Easynews Plus addon in milliseconds. This is the time in milliseconds that the addon will wait for a response from Easynews Plus before timing out. Leave it empty to use the recommended timeout.',
|
||||
type: 'number',
|
||||
constraints: {
|
||||
min: Settings.MIN_TIMEOUT,
|
||||
max: Settings.MAX_TIMEOUT,
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Stremio GDrive',
|
||||
id: 'gdrive',
|
||||
|
||||
@@ -18,6 +18,8 @@ export class Settings {
|
||||
public static readonly MEDIAFUSION_URL = process.env.MEDIAFUSION_URL ?? 'https://mediafusion.elfhosted.com/';
|
||||
public static readonly TORRENTIO_URL = process.env.TORRENTIO_URL ?? 'https://torrentio.strem.fun/';
|
||||
public static readonly TORBOX_STREMIO_URL = process.env.TORBOX_STREMIO_URL ?? 'https://stremio.torbox.app/';
|
||||
public static readonly EASYNEWS_URL = process.env.EASYNEWS_URL ?? 'https://ea627ddf0ee7-easynews.baby-beamup.club/';
|
||||
public static readonly EASYNEWS_PLUS_URL = process.env.EASYNEWS_PLUS_URL ?? 'https://b89262c192b0-stremio-easynews-addon.baby-beamup.club/';
|
||||
public static readonly MAX_ADDONS = process.env.MAX_ADDONS ? parseInt(process.env.MAX_ADDONS) : 15;
|
||||
public static readonly MAX_MOVIE_SIZE = process.env.MAX_MOVIE_SIZE ? parseInt(process.env.MAX_MOVIE_SIZE) : 150000000000; // 150GB
|
||||
public static readonly MAX_EPISODE_SIZE = process.env.MAX_EPISODE_SIZE ? parseInt(process.env.MAX_EPISODE_SIZE) : 15000000000; // 15GB
|
||||
@@ -28,6 +30,8 @@ export class Settings {
|
||||
public static readonly DEFAULT_TORBOX_TIMEOUT = process.env.DEFAULT_TORBOX_TIMEOUT ? parseInt(process.env.DEFAULT_TORBOX_TIMEOUT) : 15000;
|
||||
public static readonly DEFAULT_COMET_TIMEOUT = process.env.DEFAULT_COMET_TIMEOUT ? parseInt(process.env.DEFAULT_COMET_TIMEOUT) : 15000;
|
||||
public static readonly DEFAULT_MEDIAFUSION_TIMEOUT = process.env.DEFAULT_MEDIAFUSION_TIMEOUT ? parseInt(process.env.DEFAULT_MEDIAFUSION_TIMEOUT) : 15000;
|
||||
public static readonly DEFAULT_EASYNEWS_TIMEMOUT = process.env.DEFAULT_EASYNEWS_TIMEMOUT ? parseInt(process.env.DEFAULT_EASYNEWS_TIMEMOUT) : 15000;
|
||||
public static readonly DEFAULT_EASYNEWS_PLUS_TIMEMOUT = process.env.DEFAULT_EASYNEWS_PLUS_TIMEMOUT ? parseInt(process.env.DEFAULT_EASYNEWS_PLUS_TIMEMOUT) : 15000;
|
||||
public static readonly SHOW_DIE = process.env.SHOW_DIE ? process.env.SHOW_DIE === 'true' : true;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ export class BaseWrapper {
|
||||
provider?: ParsedStream['provider'],
|
||||
seeders?: number,
|
||||
usenetAge?: string,
|
||||
indexer?: string
|
||||
indexer?: string,
|
||||
duration?: number
|
||||
): ParsedStream {
|
||||
return {
|
||||
...parsedInfo,
|
||||
@@ -118,6 +119,7 @@ export class BaseWrapper {
|
||||
age: usenetAge,
|
||||
},
|
||||
indexers: indexer,
|
||||
duration: duration,
|
||||
stream: {
|
||||
subtitles: stream.subtitles,
|
||||
behaviorHints: {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import { AddonDetail, ParsedNameData, StreamRequest } from '@aiostreams/types';
|
||||
import { parseFilename, extractSizeInBytes, extractDurationInMs } from '@aiostreams/parser';
|
||||
import { ParsedStream, Stream, Config } from '@aiostreams/types';
|
||||
import { BaseWrapper } from './base';
|
||||
import { addonDetails, serviceDetails } from '@aiostreams/utils';
|
||||
import { Settings } from '@aiostreams/utils';
|
||||
|
||||
|
||||
export class Easynews extends BaseWrapper {
|
||||
constructor(
|
||||
configString: string | null,
|
||||
overrideUrl: string | null,
|
||||
indexerTimeout: number = Settings.DEFAULT_EASYNEWS_TIMEMOUT,
|
||||
addonName: string = 'Easynews',
|
||||
addonId: string,
|
||||
) {
|
||||
let url = overrideUrl
|
||||
? overrideUrl
|
||||
: Settings.EASYNEWS_URL +
|
||||
(configString ? configString + '/' : '');
|
||||
|
||||
super(addonName, url, indexerTimeout, addonId);
|
||||
}
|
||||
|
||||
protected parseStream(stream: Stream): ParsedStream {
|
||||
const [filename, sizeString, durationString] = stream.description?.split('\n') || [];
|
||||
|
||||
const parsedFilename: ParsedNameData = parseFilename(
|
||||
filename || stream.description || ''
|
||||
);
|
||||
const sizeInBytes = stream.description
|
||||
? extractSizeInBytes(sizeString, 1024)
|
||||
: undefined;
|
||||
|
||||
const provider = {
|
||||
id: 'easynews',
|
||||
cached: true,
|
||||
}
|
||||
|
||||
const durationInMs = extractDurationInMs(durationString || '');
|
||||
|
||||
const parsedStream: ParsedStream = this.createParsedResult(
|
||||
parsedFilename,
|
||||
stream,
|
||||
filename,
|
||||
sizeInBytes,
|
||||
provider,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
durationInMs
|
||||
);
|
||||
return parsedStream;
|
||||
}
|
||||
}
|
||||
|
||||
const getEasynewsConfigString = (username: string, password: string) => {
|
||||
return `%7B%22username%22%3A%22${username}%22%2C%22password%22%3A%22${password}%22%7D`
|
||||
};
|
||||
|
||||
export async function getEasynewsStreams(
|
||||
config: Config,
|
||||
easynewsOptions: {
|
||||
overrideName?: string;
|
||||
overrideUrl?: string;
|
||||
indexerTimeout?: string;
|
||||
},
|
||||
streamRequest: StreamRequest,
|
||||
addonId: string,
|
||||
): Promise<ParsedStream[]> {
|
||||
|
||||
// look for the 'easynews' id in the services array and destructure the username and password
|
||||
// if we cant find it, throw an error
|
||||
const easynewsService = serviceDetails.find((service) => service.id === 'easynews');
|
||||
if (!easynewsService) {
|
||||
throw new Error('Easynews service not found');
|
||||
}
|
||||
|
||||
// check for the presence of the username and password in teh easynewsService.credentials object
|
||||
// if not found, throw an error
|
||||
const credentails = config.services.find((service) => service.id === 'easynews')?.credentials;
|
||||
if (!credentails || !credentails.username || !credentails.password) {
|
||||
throw new Error('Easynews credentials not found');
|
||||
}
|
||||
|
||||
const easynewsConfigString = getEasynewsConfigString(credentails.username, credentails.password);
|
||||
|
||||
const easynews = new Easynews(
|
||||
easynewsConfigString,
|
||||
easynewsOptions.overrideUrl ?? null,
|
||||
easynewsOptions.indexerTimeout ? parseInt(easynewsOptions.indexerTimeout) : undefined,
|
||||
easynewsOptions.overrideName,
|
||||
addonId
|
||||
);
|
||||
|
||||
const streams = await easynews.getParsedStreams(streamRequest);
|
||||
return streams;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { AddonDetail, ParsedNameData, StreamRequest } from '@aiostreams/types';
|
||||
import { parseFilename, extractSizeInBytes, extractDurationInMs } from '@aiostreams/parser';
|
||||
import { ParsedStream, Stream, Config } from '@aiostreams/types';
|
||||
import { BaseWrapper } from './base';
|
||||
import { addonDetails, serviceDetails } from '@aiostreams/utils';
|
||||
import { Settings } from '@aiostreams/utils';
|
||||
|
||||
|
||||
export class EasynewsPlus extends BaseWrapper {
|
||||
constructor(
|
||||
configString: string | null,
|
||||
overrideUrl: string | null,
|
||||
indexerTimeout: number = Settings.DEFAULT_EASYNEWS_PLUS_TIMEMOUT,
|
||||
addonName: string = 'Easynews Plus',
|
||||
addonId: string,
|
||||
) {
|
||||
let url = overrideUrl
|
||||
? overrideUrl
|
||||
: Settings.EASYNEWS_PLUS_URL +
|
||||
(configString ? configString + '/' : '');
|
||||
|
||||
super(addonName, url, indexerTimeout, addonId);
|
||||
}
|
||||
|
||||
protected parseStream(stream: Stream): ParsedStream {
|
||||
const [filename, durationString, sizeString] = stream.description?.split('\n') || [];
|
||||
|
||||
const parsedFilename: ParsedNameData = parseFilename(
|
||||
filename || stream.description || ''
|
||||
);
|
||||
const sizeInBytes = stream.behaviorHints?.videoSize
|
||||
? stream.behaviorHints.videoSize
|
||||
: sizeString
|
||||
? extractSizeInBytes(sizeString, 1024)
|
||||
: undefined;
|
||||
|
||||
const provider = {
|
||||
id: 'easynews',
|
||||
cached: true,
|
||||
}
|
||||
|
||||
const durationInMs = extractDurationInMs(durationString || '');
|
||||
|
||||
const parsedStream: ParsedStream = this.createParsedResult(
|
||||
parsedFilename,
|
||||
stream,
|
||||
filename,
|
||||
sizeInBytes,
|
||||
provider,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
durationInMs
|
||||
);
|
||||
return parsedStream;
|
||||
}
|
||||
}
|
||||
|
||||
const getEasynewsPlusConfigString = (username: string, password: string) => {
|
||||
return `%7B%22username%22%3A%22${username}%22%2C%22password%22%3A%22${password}%22%2C%22sort1%22%3A%22Size%22%2C%22sort1Direction%22%3A%22Descending%22%2C%22sort2%22%3A%22Relevance%22%2C%22sort2Direction%22%3A%22Descending%22%2C%22sort3%22%3A%22Date%20%26%20Time%22%2C%22sort3Direction%22%3A%22Descending%22%7D`
|
||||
};
|
||||
|
||||
export async function getEasynewsPlusStreams(
|
||||
config: Config,
|
||||
easynewsPlusOptions: {
|
||||
overrideName?: string;
|
||||
overrideUrl?: string;
|
||||
indexerTimeout?: string;
|
||||
},
|
||||
streamRequest: StreamRequest,
|
||||
addonId: string,
|
||||
): Promise<ParsedStream[]> {
|
||||
|
||||
// look for the 'easynews' id in the services array and destructure the username and password
|
||||
// if we cant find it, throw an error
|
||||
const easynewsService = serviceDetails.find((service) => service.id === 'easynews');
|
||||
if (!easynewsService) {
|
||||
throw new Error('Easynews service not found');
|
||||
}
|
||||
|
||||
// check for the presence of the username and password in teh easynewsService.credentials object
|
||||
// if not found, throw an error
|
||||
const credentails = config.services.find((service) => service.id === 'easynews')?.credentials;
|
||||
if (!credentails || !credentails.username || !credentails.password) {
|
||||
throw new Error('Easynews credentials not found');
|
||||
}
|
||||
|
||||
const easynewsPlusConfigString = getEasynewsPlusConfigString(credentails.username, credentails.password);
|
||||
|
||||
const easynews = new EasynewsPlus(
|
||||
easynewsPlusConfigString,
|
||||
easynewsPlusOptions.overrideUrl ?? null,
|
||||
easynewsPlusOptions.indexerTimeout ? parseInt(easynewsPlusOptions.indexerTimeout) : undefined,
|
||||
easynewsPlusOptions.overrideName,
|
||||
addonId
|
||||
);
|
||||
|
||||
const streams = await easynews.getParsedStreams(streamRequest);
|
||||
return streams;
|
||||
}
|
||||
Reference in New Issue
Block a user