diff --git a/packages/wrappers/src/mediafusion.ts b/packages/wrappers/src/mediafusion.ts index 7c5b6bdd..81a66787 100644 --- a/packages/wrappers/src/mediafusion.ts +++ b/packages/wrappers/src/mediafusion.ts @@ -1,13 +1,7 @@ import { AddonDetail, ParseResult, StreamRequest } from '@aiostreams/types'; import { ParsedStream, Stream, Config } from '@aiostreams/types'; import { BaseWrapper } from './base'; -import { - addonDetails, - getTextHash, - getTimeTakenSincePoint, - Settings, - createLogger, -} from '@aiostreams/utils'; +import { addonDetails, Settings, createLogger } from '@aiostreams/utils'; const logger = createLogger('wrappers'); @@ -20,16 +14,19 @@ export class MediaFusion extends BaseWrapper { userConfig: Config, indexerTimeout?: number ) { - let url = overrideUrl - ? overrideUrl - : Settings.MEDIAFUSION_URL + (configString ? configString + '/' : ''); + let url = overrideUrl ? overrideUrl : Settings.MEDIAFUSION_URL; + const headers = + configString && !overrideUrl + ? { encoded_user_data: configString } + : undefined; super( addonName, url, addonId, userConfig, - indexerTimeout || Settings.DEFAULT_MEDIAFUSION_TIMEOUT + indexerTimeout || Settings.DEFAULT_MEDIAFUSION_TIMEOUT, + headers ); } @@ -70,40 +67,6 @@ export async function getMediafusionStreams( : undefined; const liveSearchStreams = mediafusionOptions.liveSearchStreams === 'true' ? true : false; - const cache = config.instanceCache; - - const getConfigString = async (data: any): Promise => { - const startTime = Date.now(); - const cacheKey = getTextHash(`mediafusionConfig:${JSON.stringify(data)}`); - const cachedConfig = cache ? cache.get(cacheKey) : null; - if (cachedConfig) { - logger.info(`Returning cached config string`, { - func: 'mediafusion.getConfigString', - }); - return cachedConfig; - } - try { - const encryptedStr = await _getConfigString(data); - - logger.info( - `Config encryption took ${getTimeTakenSincePoint(startTime)}`, - { - func: 'mediafusion.getConfigString', - } - ); - cache?.set(cacheKey, encryptedStr, Settings.CACHE_MEDIAFUSION_CONFIG_TTL); - return encryptedStr; - } catch (error: any) { - if (error.name === 'TimeoutError') { - throw new Error( - `Config encryption timed out after ${getTimeTakenSincePoint( - startTime - )}` - ); - } - throw new Error(`Failed to get config string: ${error.message}`); - } - }; // If overrideUrl is provided, use it to get streams and skip all other steps if (mediafusionOptions.overrideUrl) { @@ -125,13 +88,12 @@ export async function getMediafusionStreams( // if no usable services found, use mediafusion without debrid if (usableServices.length < 1) { - const configString = await getConfigString( - getMediaFusionConfig( - mediafusionOptions.filterCertificationLevels, - mediafusionOptions.filterNudity, - liveSearchStreams - ) + const configString = getConfigString( + mediafusionOptions.filterCertificationLevels, + mediafusionOptions.filterNudity, + liveSearchStreams ); + const mediafusion = new MediaFusion( configString, null, @@ -170,16 +132,15 @@ export async function getMediafusionStreams( } // get the encrypted mediafusion string - const mediafusionConfig = getMediaFusionConfig( + const mediafusionConfig = getConfigString( mediafusionOptions.filterCertificationLevels, mediafusionOptions.filterNudity, liveSearchStreams, debridService.id, debridService.credentials ); - const encryptedStr = await getConfigString(mediafusionConfig); const mediafusion = new MediaFusion( - encryptedStr, + mediafusionConfig, null, mediafusionOptions.overrideName, addonId, @@ -197,30 +158,18 @@ export async function getMediafusionStreams( throw new Error(`No enabled services found for MediaFusion`); } const promises = servicesToUse.map(async (service) => { - const mediafusionConfig = getMediaFusionConfig( + logger.info(`Getting MediaFusion streams for ${service.id}`, { + func: 'mediafusion', + }); + const encodedConfigString = getConfigString( mediafusionOptions.filterCertificationLevels, mediafusionOptions.filterNudity, liveSearchStreams, service.id, service.credentials ); - logger.info(`Getting MediaFusion streams for ${service.id}`, { - func: 'mediafusion', - }); - let encryptedStr: string = ''; - try { - encryptedStr = await getConfigString(mediafusionConfig); - if (!encryptedStr) { - throw new Error( - 'An unknown error occurred while getting config string' - ); - } - } catch (error: any) { - logger.error(`${error.message}`, { func: 'mediafusion' }); - throw new Error(error.message); - } const mediafusion = new MediaFusion( - encryptedStr, + encodedConfigString, null, mediafusionOptions.overrideName, addonId, @@ -246,7 +195,7 @@ export async function getMediafusionStreams( }; } -const getMediaFusionConfig = ( +const getConfigString = ( filterCertificationLevels?: string, filterNudity?: string, liveSearchStreams: boolean = false, @@ -263,116 +212,98 @@ const getMediaFusionConfig = ( const levels = filterNudity.split(','); nudityFilter = levels.map((level) => level.trim()); } - return { - streaming_provider: service - ? { - token: !['pikpak'].includes(service) ? credentials.apiKey : undefined, - email: credentials.email, - password: credentials.password, - service: service, - enable_watchlists_catalogs: false, - download_via_browser: false, - only_show_cached_streams: false, - } - : null, - selected_catalogs: [], - selected_resolutions: [ - '4k', - '2160p', - '1440p', - '1080p', - '720p', - '576p', - '480p', - '360p', - '240p', - null, - ], - enable_catalogs: true, - enable_imdb_metadata: false, - max_size: 'inf', - max_streams_per_resolution: '500', - torrent_sorting_priority: [ - { key: 'language', direction: 'desc' }, - { key: 'cached', direction: 'desc' }, - { key: 'resolution', direction: 'desc' }, - { key: 'quality', direction: 'desc' }, - { key: 'size', direction: 'desc' }, - { key: 'seeders', direction: 'desc' }, - { key: 'created_at', direction: 'desc' }, - ], - show_full_torrent_name: true, - show_language_country_flag: true, - nudity_filter: nudityFilter, - certification_filter: certificationFilter, - language_sorting: [ - 'English', - 'Tamil', - 'Hindi', - 'Malayalam', - 'Kannada', - 'Telugu', - 'Chinese', - 'Russian', - 'Arabic', - 'Japanese', - 'Korean', - 'Taiwanese', - 'Latino', - 'French', - 'Spanish', - 'Portuguese', - 'Italian', - 'German', - 'Ukrainian', - 'Polish', - 'Czech', - 'Thai', - 'Indonesian', - 'Vietnamese', - 'Dutch', - 'Bengali', - 'Turkish', - 'Greek', - 'Swedish', - null, - ], - quality_filter: [ - 'BluRay/UHD', - 'WEB/HD', - 'DVD/TV/SAT', - 'CAM/Screener', - 'Unknown', - ], - api_password: Settings.MEDIAFUSION_API_PASSWORD || null, - mediaflow_config: null, - rpdb_config: null, - live_search_streams: liveSearchStreams, - contribution_streams: false, - mdblist_config: null, - }; + return encodeURIComponent( + Buffer.from( + JSON.stringify({ + streaming_provider: service + ? { + token: !['pikpak'].includes(service) + ? credentials.apiKey + : undefined, + email: credentials.email, + password: credentials.password, + service: service, + enable_watchlists_catalogs: false, + download_via_browser: false, + only_show_cached_streams: false, + } + : null, + selected_catalogs: [], + selected_resolutions: [ + '4k', + '2160p', + '1440p', + '1080p', + '720p', + '576p', + '480p', + '360p', + '240p', + null, + ], + enable_catalogs: true, + enable_imdb_metadata: false, + max_size: 'inf', + max_streams_per_resolution: '500', + torrent_sorting_priority: [ + { key: 'language', direction: 'desc' }, + { key: 'cached', direction: 'desc' }, + { key: 'resolution', direction: 'desc' }, + { key: 'quality', direction: 'desc' }, + { key: 'size', direction: 'desc' }, + { key: 'seeders', direction: 'desc' }, + { key: 'created_at', direction: 'desc' }, + ], + show_full_torrent_name: true, + show_language_country_flag: true, + nudity_filter: nudityFilter, + certification_filter: certificationFilter, + language_sorting: [ + 'English', + 'Tamil', + 'Hindi', + 'Malayalam', + 'Kannada', + 'Telugu', + 'Chinese', + 'Russian', + 'Arabic', + 'Japanese', + 'Korean', + 'Taiwanese', + 'Latino', + 'French', + 'Spanish', + 'Portuguese', + 'Italian', + 'German', + 'Ukrainian', + 'Polish', + 'Czech', + 'Thai', + 'Indonesian', + 'Vietnamese', + 'Dutch', + 'Bengali', + 'Turkish', + 'Greek', + 'Swedish', + null, + ], + quality_filter: [ + 'BluRay/UHD', + 'WEB/HD', + 'DVD/TV/SAT', + 'CAM/Screener', + 'Unknown', + ], + api_password: Settings.MEDIAFUSION_API_PASSWORD || null, + mediaflow_config: null, + rpdb_config: null, + live_search_streams: liveSearchStreams, + contribution_streams: false, + mdblist_config: null, + }) + ).toString('base64') + ); }; - -async function _getConfigString(data: any): Promise { - const encryptUrl = `${Settings.MEDIAFUSION_URL}encrypt-user-data`; - const response = await fetch(encryptUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - signal: AbortSignal.timeout( - Settings.MEDIAFUSION_CONFIG_TIMEOUT || - Settings.DEFAULT_MEDIAFUSION_TIMEOUT || - Settings.DEFAULT_TIMEOUT - ), - }); - - const encryptedData = await response.json(); - if (encryptedData.status !== 'success') { - throw new Error( - `Config encryption failed: ${encryptedData.message || 'Unknown error'}` - ); - } - return encryptedData.encrypted_str; -}