From feca66d9d5e6194a83602f031f72e9517c73fc09 Mon Sep 17 00:00:00 2001 From: Viren070 Date: Thu, 1 May 2025 19:12:40 +0100 Subject: [PATCH] feat: add folderName property, show in gdrive and torrentio formats. deprecate stream.name, add stream.filename and stream.folderName closes #147 --- packages/formatters/src/custom.ts | 5 ++ packages/formatters/src/gdrive.ts | 7 +- packages/formatters/src/torrentio.ts | 4 +- packages/types/src/types.ts | 1 + packages/wrappers/src/base.ts | 100 ++++++++++++++------------- packages/wrappers/src/dmmCast.ts | 8 +-- packages/wrappers/src/mediafusion.ts | 11 ++- packages/wrappers/src/torbox.ts | 13 ++-- packages/wrappers/src/torrentio.ts | 19 ++++- 9 files changed, 102 insertions(+), 66 deletions(-) diff --git a/packages/formatters/src/custom.ts b/packages/formatters/src/custom.ts index 639bdea7..1d06230d 100644 --- a/packages/formatters/src/custom.ts +++ b/packages/formatters/src/custom.ts @@ -70,7 +70,10 @@ export type ParseValue = { showDie: boolean | null; }; stream?: { + /** @deprecated Use filename instead */ name: string | null; + filename: string | null; + folderName: string | null; size: number | null; personal: boolean | null; quality: string | null; @@ -117,7 +120,9 @@ const convertStreamToParseValue = (stream: ParsedStream): ParseValue => { showDie: Settings.SHOW_DIE, }, stream: { + filename: stream.filename || null, name: stream.filename || null, + folderName: stream.folderName || null, size: stream.size || null, personal: stream.personal !== undefined ? stream.personal : null, quality: stream.quality === 'Unknown' ? null : stream.quality, diff --git a/packages/formatters/src/gdrive.ts b/packages/formatters/src/gdrive.ts index f3066cd2..93fc85c0 100644 --- a/packages/formatters/src/gdrive.ts +++ b/packages/formatters/src/gdrive.ts @@ -93,10 +93,11 @@ export function gdriveFormat( description += '\n'; } - if (!minimalistic && stream.filename) { - description += stream.filename ? `📄 ${stream.filename}` : '📄 Unknown'; - description += '\n'; + if (!minimalistic && (stream.filename || stream.folderName)) { + description += stream.folderName ? `📁 ${stream.folderName}\n` : ''; + description += stream.filename ? `📄 ${stream.filename}\n` : '📄 Unknown\n'; } + if (stream.message) { description += `📢 ${stream.message}`; } diff --git a/packages/formatters/src/torrentio.ts b/packages/formatters/src/torrentio.ts index 4c7f8413..ac9b70eb 100644 --- a/packages/formatters/src/torrentio.ts +++ b/packages/formatters/src/torrentio.ts @@ -35,8 +35,8 @@ export function torrentioFormat(stream: ParsedStream): { description += `\n${stream.message}`; } - if (stream.filename) { - description += `\n${stream.filename}`; + if (stream.filename || stream.folderName) { + description += `\n${stream.folderName}/${stream.filename}`; } if ( stream.size || diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index 4c76e803..dafe467b 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -22,6 +22,7 @@ export interface ParsedStream extends ParsedNameData { name: string; }; filename?: string; + folderName?: string; message?: string; size?: number; provider?: { diff --git a/packages/wrappers/src/base.ts b/packages/wrappers/src/base.ts index b04a507d..077bfb9f 100644 --- a/packages/wrappers/src/base.ts +++ b/packages/wrappers/src/base.ts @@ -235,68 +235,73 @@ export class BaseWrapper { } } - protected createParsedResult( - parsedInfo: ParsedNameData, - stream: Stream, - filename?: string, - size?: number, - provider?: ParsedStream['provider'], - seeders?: number, - usenetAge?: string, - indexer?: string, - duration?: number, - personal?: boolean, - infoHash?: string, - message?: string - ): ParseResult { + protected createParsedResult(data: { + parsedInfo: ParsedNameData; + stream: Stream; + filename?: string; + folderName?: string; + size?: number; + provider?: ParsedStream['provider']; + seeders?: number; + usenetAge?: string; + indexer?: string; + duration?: number; + personal?: boolean; + infoHash?: string; + message?: string; + }): ParseResult { + if (data.folderName === data.filename) { + data.folderName = undefined; + } return { type: 'stream', result: { - ...parsedInfo, + ...data.parsedInfo, proxied: false, - message: message, + message: data.message, addon: { name: this.addonName, id: this.addonId }, - filename: filename, - size: size, - url: stream.url, - externalUrl: stream.externalUrl, - _infoHash: infoHash, + filename: data.filename, + folderName: data.folderName, + size: data.size, + url: data.stream.url, + externalUrl: data.stream.externalUrl, + _infoHash: data.infoHash, torrent: { - infoHash: stream.infoHash, - fileIdx: stream.fileIdx, - sources: stream.sources, - seeders: seeders, + infoHash: data.stream.infoHash, + fileIdx: data.stream.fileIdx, + sources: data.stream.sources, + seeders: data.seeders, }, - provider: provider, + provider: data.provider, usenet: { - age: usenetAge, + age: data.usenetAge, }, - indexers: indexer, - duration: duration, - personal: personal, - type: stream.infoHash + indexers: data.indexer, + duration: data.duration, + personal: data.personal, + type: data.stream.infoHash ? 'p2p' - : usenetAge + : data.usenetAge ? 'usenet' - : provider + : data.provider ? 'debrid' - : stream.url?.endsWith('.m3u8') + : data.stream.url?.endsWith('.m3u8') ? 'live' : 'unknown', stream: { - subtitles: stream.subtitles, + subtitles: data.stream.subtitles, behaviorHints: { - countryWhitelist: stream.behaviorHints?.countryWhitelist, - notWebReady: stream.behaviorHints?.notWebReady, + countryWhitelist: data.stream.behaviorHints?.countryWhitelist, + notWebReady: data.stream.behaviorHints?.notWebReady, proxyHeaders: - stream.behaviorHints?.proxyHeaders?.request || - stream.behaviorHints?.proxyHeaders?.response + data.stream.behaviorHints?.proxyHeaders?.request || + data.stream.behaviorHints?.proxyHeaders?.response ? { - request: stream.behaviorHints?.proxyHeaders?.request, - response: stream.behaviorHints?.proxyHeaders?.response, + request: data.stream.behaviorHints?.proxyHeaders?.request, + response: data.stream.behaviorHints?.proxyHeaders?.response, } : undefined, - videoHash: stream.behaviorHints?.videoHash, + videoHash: data.stream.behaviorHints?.videoHash, }, }, }, @@ -406,19 +411,18 @@ export class BaseWrapper { // if its a p2p result, it is not from a debrid service provider = undefined; } - return this.createParsedResult( + return this.createParsedResult({ parsedInfo, stream, filename, size, provider, - seeders ? parseInt(seeders) : undefined, - undefined, + seeders: seeders ? parseInt(seeders) : undefined, indexer, duration, - stream.personal, - stream.infoHash || this.extractInfoHash(stream.url || '') - ); + personal: stream.personal, + infoHash: stream.infoHash || this.extractInfoHash(stream.url || ''), + }); } protected parseServiceData( diff --git a/packages/wrappers/src/dmmCast.ts b/packages/wrappers/src/dmmCast.ts index ce9f1d49..4ef58bfe 100644 --- a/packages/wrappers/src/dmmCast.ts +++ b/packages/wrappers/src/dmmCast.ts @@ -56,12 +56,12 @@ export class DMMCast extends BaseWrapper { ? this.extractSizeInBytes(stream.title.split('\n').pop()!, 1024) : 0; - const parseResult: ParseResult = this.createParsedResult( - parsedFilename, + const parseResult: ParseResult = this.createParsedResult({ + parsedInfo: parsedFilename, stream, filename, - sizeInBytes - ); + size: sizeInBytes, + }); if (parseResult.type === 'stream') { parseResult.result.message = message; } diff --git a/packages/wrappers/src/mediafusion.ts b/packages/wrappers/src/mediafusion.ts index d4fb59e4..d7cfd000 100644 --- a/packages/wrappers/src/mediafusion.ts +++ b/packages/wrappers/src/mediafusion.ts @@ -36,7 +36,16 @@ export class MediaFusion extends BaseWrapper { result: stream.description, }; } - return super.parseStream(stream); + const parseResult = super.parseStream(stream); + if (parseResult.type === 'stream' && parseResult.result) { + const torrentNameRegex = /📂\s*(.+)/; + const description = stream.description || stream.title; + const match = torrentNameRegex.exec(description || ''); + if (match && match[1].trim() !== parseResult.result.filename) { + parseResult.result.folderName = match[1].trim(); + } + } + return parseResult; } } diff --git a/packages/wrappers/src/torbox.ts b/packages/wrappers/src/torbox.ts index 98e5c7e9..2f7c7198 100644 --- a/packages/wrappers/src/torbox.ts +++ b/packages/wrappers/src/torbox.ts @@ -80,20 +80,19 @@ export class Torbox extends BaseWrapper { cached: stream.is_cached !== undefined ? stream.is_cached : true, }; - const parsedStream: ParseResult = this.createParsedResult( - parsedFilename, + const parsedStream: ParseResult = this.createParsedResult({ + parsedInfo: parsedFilename, stream, filename, size, provider, seeders, - age, - source, - undefined, + usenetAge: age, + indexer: source, personal, infoHash, - message - ); + message, + }); return parsedStream; } diff --git a/packages/wrappers/src/torrentio.ts b/packages/wrappers/src/torrentio.ts index 8eab65d3..050b2501 100644 --- a/packages/wrappers/src/torrentio.ts +++ b/packages/wrappers/src/torrentio.ts @@ -1,4 +1,9 @@ -import { AddonDetail, StreamRequest } from '@aiostreams/types'; +import { + AddonDetail, + ParseResult, + Stream, + StreamRequest, +} from '@aiostreams/types'; import { ParsedStream, Config } from '@aiostreams/types'; import { BaseWrapper } from './base'; import { addonDetails, createLogger } from '@aiostreams/utils'; @@ -30,6 +35,18 @@ export class Torrentio extends BaseWrapper { } ); } + + protected parseStream(stream: Stream): ParseResult { + const parseResult = super.parseStream(stream); + if (parseResult.type === 'stream' && parseResult.result) { + const description = stream.description || stream.title; + const folderName = description?.split('\n')?.[0]; + if (folderName !== parseResult.result.filename) { + parseResult.result.folderName = folderName; + } + } + return parseResult; + } } export async function getTorrentioStreams(