From c83a746b7a8aca02f77365e28fc73d3c8550ef72 Mon Sep 17 00:00:00 2001 From: Nischaldoescode Date: Thu, 30 Apr 2026 22:50:53 +0530 Subject: [PATCH 1/4] feat: adds videasy --- src/providers/videasy/decryptor.ts | 63 ++++++++ src/providers/videasy/videasy.ts | 208 +++++++++++++++++++++++++ src/providers/videasy/videasy.types.ts | 60 +++++++ 3 files changed, 331 insertions(+) create mode 100644 src/providers/videasy/decryptor.ts create mode 100644 src/providers/videasy/videasy.ts create mode 100644 src/providers/videasy/videasy.types.ts diff --git a/src/providers/videasy/decryptor.ts b/src/providers/videasy/decryptor.ts new file mode 100644 index 0000000..c1ac02d --- /dev/null +++ b/src/providers/videasy/decryptor.ts @@ -0,0 +1,63 @@ +// decryptor.ts +// calls enc-dec.app to decrypt videasy's encrypted blob. +// the blob is plain text hex returned directly from api.videasy.net. +// enc-dec.app handles the wasm/cryptojs decryption server-side. + +const DEC_API = 'https://enc-dec.app/api/dec-videasy'; + +// response shape from enc-dec.app +interface DecApiResponse { + status: number; + result: { + sources: Array<{ quality?: string; url: string; type?: string }>; + subtitles: Array<{ url: string; lang?: string; language?: string }>; + }; +} + +export interface DecryptedPayload { + sources: Array<{ quality?: string; url: string; type?: string }>; + subtitles: Array<{ url: string; lang?: string; language?: string }>; +} + +// simple in-memory cache: key = `${tmdbId}:${blobHash}`, value = decrypted payload +// avoids re-calling the api for the same blob within a server session +const cache = new Map(); + +function blobKey(tmdbId: string, blob: string): string { + // soo i think it's better to use first 32 chars of blob as a cheap fingerprint as blobs are unique per request + return `${tmdbId}:${blob.slice(0, 32)}`; +} + +export async function decryptResponse( + blob: string, + tmdbId: string +): Promise { + if (!blob || blob.length < 10) return null; + + const key = blobKey(tmdbId, blob); + if (cache.has(key)) return cache.get(key)!; + + try { + const res = await fetch(DEC_API, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: blob, id: tmdbId }), + }); + + if (!res.ok) return null; + + const json = (await res.json()) as DecApiResponse; + + if (json.status !== 200 || !json.result?.sources) return null; + + const payload: DecryptedPayload = { + sources: json.result.sources ?? [], + subtitles: json.result.subtitles ?? [], + }; + + cache.set(key, payload); + return payload; + } catch { + return null; + } +} \ No newline at end of file diff --git a/src/providers/videasy/videasy.ts b/src/providers/videasy/videasy.ts new file mode 100644 index 0000000..8517d34 --- /dev/null +++ b/src/providers/videasy/videasy.ts @@ -0,0 +1,208 @@ +import { BaseProvider } from '@omss/framework'; +import type { + ProviderCapabilities, + ProviderMediaObject, + ProviderResult +} from '@omss/framework'; +import type { VideasyServer } from './videasy.types.js';; +import { decryptResponse } from './decryptor.js'; + +/** + * all known api endpoints. mb-flix is the primary english source. + * endpoints like meine, overflix, cuevana serve other languages. + * hdmovie returns sources where the "quality" field is actually + * a language label ("Hindi", "English") rather than a resolution. + * those which are commented do not work + */ + +const VIDEASY_SERVERS: readonly VideasyServer[] = [ + // { name: 'primesrcme', url: 'https://api.videasy.net/primesrcme/sources-with-title' }, + // { name: 'm4uhd', url: 'https://api.videasy.net/m4uhd/sources-with-title' }, + // { name: 'meine-de', url: 'https://api.videasy.net/meine/sources-with-title', language: 'german' }, + // { name: 'meine-it', url: 'https://api.videasy.net/meine/sources-with-title', language: 'italian' }, + // { name: 'meine-fr', url: 'https://api.videasy.net/meine/sources-with-title', language: 'french' }, + { name: 'mb-flix', url: 'https://api.videasy.net/mb-flix/sources-with-title' }, + { name: '1movies', url: 'https://api.videasy.net/1movies/sources-with-title' }, + { name: 'cdn', url: 'https://api.videasy.net/cdn/sources-with-title' }, + { name: 'superflix', url: 'https://api.videasy.net/superflix/sources-with-title' }, +] as const; + +export class VideasyProvider extends BaseProvider { + readonly id = 'Videasy'; + readonly name = 'Videasy'; + readonly enabled = true; + readonly BASE_URL = 'https://api.videasy.net'; + readonly HEADERS = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', + Accept: 'application/json, */*; q=0.01', + Referer: 'https://player.videasy.net/', + Origin: 'https://player.videasy.net', + }; + + readonly capabilities: ProviderCapabilities = { + supportedContentTypes: ['movies', 'tv'], + }; + + async getMovieSources(media: ProviderMediaObject): Promise { + return this.getSources(media); + } + + async getTVSources(media: ProviderMediaObject): Promise { + return this.getSources(media); + } + + // fans out to all servers in parallel, merges results + private async getSources(media: ProviderMediaObject): Promise { + const results = await Promise.allSettled( + VIDEASY_SERVERS.map(server => this.fetchFromServer(server, media)) + ); + + const sources: ProviderResult['sources'] = []; + const subtitles: ProviderResult['subtitles'] = []; + const diagnostics: ProviderResult['diagnostics'] = []; + let failCount = 0; + + for (const result of results) { + if (result.status === 'rejected' || !result.value) { + failCount++; + continue; + } + sources.push(...result.value.sources); + subtitles.push(...result.value.subtitles); + } + + if (failCount > 0 && sources.length > 0) { + diagnostics.push({ + code: 'PARTIAL_SCRAPE', + message: `${failCount} of ${VIDEASY_SERVERS.length} videasy servers did not return results`, + field: '', + severity: 'warning', + }); + } + + if (sources.length === 0) { + return this.emptyResult('all videasy servers returned no sources', media); + } + + return { sources, subtitles, diagnostics }; + } + + // I have added a small identification of error in case in future we have some problem + // if the error has all capital then it proly mean that they shifted their encryption and all + // if it's small and has same then we might have to change a bit let's say api url ?. + // suppose the small invalid response indicates that they might have changed their setup + // while the capital indicates that the response might be short not enough, hope it helps. + + // fetches one server, reads plain text blob, decrypts via enc-dec.app + private async fetchFromServer( + server: VideasyServer, + media: ProviderMediaObject + ): Promise { + const params = this.buildParams(server, media); + const url = `${server.url}?${new URLSearchParams(params as Record)}`; + const response = await fetch(url, { headers: this.HEADERS }); + + if (!response.ok) { + return this.emptyResult('invalid response', media); + } + + // api returns plain text hex blob, not json + const blob = await response.text(); + + if (!blob || blob.length < 10) { + return this.emptyResult('INVALID RESPONSE', media); + } + + const decrypted = await decryptResponse(blob, String(media.tmdbId)); + + if (!decrypted || decrypted.sources.length === 0) { + return this.emptyResult('Unable to Decode', media); + } + + const sources: ProviderResult['sources'] = decrypted.sources + .filter(s => !!s?.url) + .map(s => ({ + url: this.createProxyUrl(s.url, this.HEADERS), + type: this.detectType(s.url, s.type), + quality: this.normalizeQuality(s.quality), + audioTracks: [{ language: this.resolveLanguage(server), label: this.resolveLanguageLabel(server) }], + provider: { id: this.id, name: this.name }, + })); + + const subtitles: ProviderResult['subtitles'] = decrypted.subtitles + .filter(s => !!s?.url) + .map(s => ({ + url: this.createProxyUrl(s.url, {}), + label: s.lang ?? s.language ?? 'Unknown', + format: 'vtt' as const, + })); + + return { sources, subtitles, diagnostics: [] }; + } + + // builds query params — title passed as plain string, URLSearchParams handles encoding + private buildParams(server: VideasyServer, media: ProviderMediaObject): Record { + const base: Record = { + title: media.title ?? '', // no encodeURIComponent — URLSearchParams does it + mediaType: media.type === 'movie' ? 'movie' : 'tv', + tmdbId: String(media.tmdbId), + imdbId: media.imdbId ?? '', + episodeId: String(media.type === 'tv' ? (media.e ?? 1) : 1), + seasonId: String(media.type === 'tv' ? (media.s ?? 1) : 1), + }; + + if (media.type === 'movie') { + base.year = String(media.releaseYear ?? ''); + } + + if (server.language) { + base.language = server.language; + } + + return base; + } + + // detects stream type from url extension and api hint + private detectType(url: string, hint?: string): 'hls' | 'mp4' { + const lower = (hint ?? '').toLowerCase(); + if (lower.includes('hls') || lower.includes('m3u8') || url.toLowerCase().includes('.m3u8')) { + return 'hls'; + } + return 'mp4'; + } + + // guards against language labels being passed as quality (e.g. "Hindi") + private normalizeQuality(raw?: string): string { + if (!raw) return 'unknown'; + return /^\d{3,4}p$|^4K$|^8K$|^HD$|^SD$/i.test(raw.trim()) ? raw.trim() : 'unknown'; + } + + private resolveLanguage(server: VideasyServer): string { + if (!server.language) return 'en'; + const map: Record = { german: 'de', italian: 'it', french: 'fr' }; + return map[server.language] ?? 'en'; + } + + private resolveLanguageLabel(server: VideasyServer): string { + if (!server.language) return 'English'; + const map: Record = { german: 'German', italian: 'Italian', french: 'French' }; + return map[server.language] ?? 'English'; + } + + private emptyResult(message: string, _media: ProviderMediaObject): ProviderResult { + return { + sources: [], + subtitles: [], + diagnostics: [{ code: 'PROVIDER_ERROR', message: `${this.name}: ${message}`, field: '', severity: 'error' }], + }; + } + + async healthCheck(): Promise { + try { + const res = await fetch(this.BASE_URL, { method: 'HEAD', headers: this.HEADERS }); + return res.status < 500; + } catch { + return false; + } + } +} \ No newline at end of file diff --git a/src/providers/videasy/videasy.types.ts b/src/providers/videasy/videasy.types.ts new file mode 100644 index 0000000..41664a1 --- /dev/null +++ b/src/providers/videasy/videasy.types.ts @@ -0,0 +1,60 @@ +/** + * raw response from the api.videasy.net sources-with-title endpoint. + * the data field is an encrypted string when isEncrypted is true. + */ +export interface VideasyEncryptedResponse { + data: string; + isEncrypted?: boolean; +} + +/** + * decrypted payload shape from api.videasy.net. + */ +export interface VideasyDecryptedPayload { + sources: VideasyRawSource[]; + subtitles?: VideasyRawSubtitle[]; +} + +/** + * individual source entry from the decrypted videasy payload. + * the quality field is actually a language/audio label on some endpoints + * (e.g. "Hindi", "English") rather than a resolution. + */ +export interface VideasyRawSource { + url: string; + quality?: string; + type?: string; +} + +/** + * subtitle entry from the decrypted videasy payload. + */ +export interface VideasyRawSubtitle { + url: string; + label?: string; + language?: string; + lang?: string; +} + +/** + * shape of the params sent to each api.videasy.net endpoint. + */ +export interface VideasyApiParams { + title: string; + mediaType: 'movie' | 'tv'; + totalSeasons?: number; + episodeId: number; + seasonId: number; + tmdbId: string | number; + imdbId?: string; + language?: string; +} + +/** + * one configured api endpoint with its base url and optional language override. + */ +export interface VideasyServer { + readonly name: string; + readonly url: string; + readonly language?: string; +} \ No newline at end of file From 592f80772e5f81698c9938872b5388d4fc43b830 Mon Sep 17 00:00:00 2001 From: Nischaldoescode Date: Thu, 30 Apr 2026 22:52:37 +0530 Subject: [PATCH 2/4] feat: adds videasy(forgot to ran format) --- src/providers/videasy/decryptor.ts | 6 +- src/providers/videasy/videasy.ts | 110 ++++++++++++++++++------- src/providers/videasy/videasy.types.ts | 2 +- 3 files changed, 84 insertions(+), 34 deletions(-) diff --git a/src/providers/videasy/decryptor.ts b/src/providers/videasy/decryptor.ts index c1ac02d..f203de6 100644 --- a/src/providers/videasy/decryptor.ts +++ b/src/providers/videasy/decryptor.ts @@ -41,7 +41,7 @@ export async function decryptResponse( const res = await fetch(DEC_API, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ text: blob, id: tmdbId }), + body: JSON.stringify({ text: blob, id: tmdbId }) }); if (!res.ok) return null; @@ -52,7 +52,7 @@ export async function decryptResponse( const payload: DecryptedPayload = { sources: json.result.sources ?? [], - subtitles: json.result.subtitles ?? [], + subtitles: json.result.subtitles ?? [] }; cache.set(key, payload); @@ -60,4 +60,4 @@ export async function decryptResponse( } catch { return null; } -} \ No newline at end of file +} diff --git a/src/providers/videasy/videasy.ts b/src/providers/videasy/videasy.ts index 8517d34..a3df4ec 100644 --- a/src/providers/videasy/videasy.ts +++ b/src/providers/videasy/videasy.ts @@ -4,7 +4,7 @@ import type { ProviderMediaObject, ProviderResult } from '@omss/framework'; -import type { VideasyServer } from './videasy.types.js';; +import type { VideasyServer } from './videasy.types.js'; import { decryptResponse } from './decryptor.js'; /** @@ -21,10 +21,19 @@ const VIDEASY_SERVERS: readonly VideasyServer[] = [ // { name: 'meine-de', url: 'https://api.videasy.net/meine/sources-with-title', language: 'german' }, // { name: 'meine-it', url: 'https://api.videasy.net/meine/sources-with-title', language: 'italian' }, // { name: 'meine-fr', url: 'https://api.videasy.net/meine/sources-with-title', language: 'french' }, - { name: 'mb-flix', url: 'https://api.videasy.net/mb-flix/sources-with-title' }, - { name: '1movies', url: 'https://api.videasy.net/1movies/sources-with-title' }, - { name: 'cdn', url: 'https://api.videasy.net/cdn/sources-with-title' }, - { name: 'superflix', url: 'https://api.videasy.net/superflix/sources-with-title' }, + { + name: 'mb-flix', + url: 'https://api.videasy.net/mb-flix/sources-with-title' + }, + { + name: '1movies', + url: 'https://api.videasy.net/1movies/sources-with-title' + }, + { name: 'cdn', url: 'https://api.videasy.net/cdn/sources-with-title' }, + { + name: 'superflix', + url: 'https://api.videasy.net/superflix/sources-with-title' + } ] as const; export class VideasyProvider extends BaseProvider { @@ -33,14 +42,15 @@ export class VideasyProvider extends BaseProvider { readonly enabled = true; readonly BASE_URL = 'https://api.videasy.net'; readonly HEADERS = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', Accept: 'application/json, */*; q=0.01', Referer: 'https://player.videasy.net/', - Origin: 'https://player.videasy.net', + Origin: 'https://player.videasy.net' }; readonly capabilities: ProviderCapabilities = { - supportedContentTypes: ['movies', 'tv'], + supportedContentTypes: ['movies', 'tv'] }; async getMovieSources(media: ProviderMediaObject): Promise { @@ -52,9 +62,11 @@ export class VideasyProvider extends BaseProvider { } // fans out to all servers in parallel, merges results - private async getSources(media: ProviderMediaObject): Promise { + private async getSources( + media: ProviderMediaObject + ): Promise { const results = await Promise.allSettled( - VIDEASY_SERVERS.map(server => this.fetchFromServer(server, media)) + VIDEASY_SERVERS.map((server) => this.fetchFromServer(server, media)) ); const sources: ProviderResult['sources'] = []; @@ -76,12 +88,15 @@ export class VideasyProvider extends BaseProvider { code: 'PARTIAL_SCRAPE', message: `${failCount} of ${VIDEASY_SERVERS.length} videasy servers did not return results`, field: '', - severity: 'warning', + severity: 'warning' }); } if (sources.length === 0) { - return this.emptyResult('all videasy servers returned no sources', media); + return this.emptyResult( + 'all videasy servers returned no sources', + media + ); } return { sources, subtitles, diagnostics }; @@ -120,35 +135,43 @@ export class VideasyProvider extends BaseProvider { } const sources: ProviderResult['sources'] = decrypted.sources - .filter(s => !!s?.url) - .map(s => ({ + .filter((s) => !!s?.url) + .map((s) => ({ url: this.createProxyUrl(s.url, this.HEADERS), type: this.detectType(s.url, s.type), quality: this.normalizeQuality(s.quality), - audioTracks: [{ language: this.resolveLanguage(server), label: this.resolveLanguageLabel(server) }], - provider: { id: this.id, name: this.name }, + audioTracks: [ + { + language: this.resolveLanguage(server), + label: this.resolveLanguageLabel(server) + } + ], + provider: { id: this.id, name: this.name } })); const subtitles: ProviderResult['subtitles'] = decrypted.subtitles - .filter(s => !!s?.url) - .map(s => ({ + .filter((s) => !!s?.url) + .map((s) => ({ url: this.createProxyUrl(s.url, {}), label: s.lang ?? s.language ?? 'Unknown', - format: 'vtt' as const, + format: 'vtt' as const })); return { sources, subtitles, diagnostics: [] }; } // builds query params — title passed as plain string, URLSearchParams handles encoding - private buildParams(server: VideasyServer, media: ProviderMediaObject): Record { + private buildParams( + server: VideasyServer, + media: ProviderMediaObject + ): Record { const base: Record = { - title: media.title ?? '', // no encodeURIComponent — URLSearchParams does it + title: media.title ?? '', // no encodeURIComponent — URLSearchParams does it mediaType: media.type === 'movie' ? 'movie' : 'tv', tmdbId: String(media.tmdbId), imdbId: media.imdbId ?? '', episodeId: String(media.type === 'tv' ? (media.e ?? 1) : 1), - seasonId: String(media.type === 'tv' ? (media.s ?? 1) : 1), + seasonId: String(media.type === 'tv' ? (media.s ?? 1) : 1) }; if (media.type === 'movie') { @@ -165,7 +188,11 @@ export class VideasyProvider extends BaseProvider { // detects stream type from url extension and api hint private detectType(url: string, hint?: string): 'hls' | 'mp4' { const lower = (hint ?? '').toLowerCase(); - if (lower.includes('hls') || lower.includes('m3u8') || url.toLowerCase().includes('.m3u8')) { + if ( + lower.includes('hls') || + lower.includes('m3u8') || + url.toLowerCase().includes('.m3u8') + ) { return 'hls'; } return 'mp4'; @@ -174,35 +201,58 @@ export class VideasyProvider extends BaseProvider { // guards against language labels being passed as quality (e.g. "Hindi") private normalizeQuality(raw?: string): string { if (!raw) return 'unknown'; - return /^\d{3,4}p$|^4K$|^8K$|^HD$|^SD$/i.test(raw.trim()) ? raw.trim() : 'unknown'; + return /^\d{3,4}p$|^4K$|^8K$|^HD$|^SD$/i.test(raw.trim()) + ? raw.trim() + : 'unknown'; } private resolveLanguage(server: VideasyServer): string { if (!server.language) return 'en'; - const map: Record = { german: 'de', italian: 'it', french: 'fr' }; + const map: Record = { + german: 'de', + italian: 'it', + french: 'fr' + }; return map[server.language] ?? 'en'; } private resolveLanguageLabel(server: VideasyServer): string { if (!server.language) return 'English'; - const map: Record = { german: 'German', italian: 'Italian', french: 'French' }; + const map: Record = { + german: 'German', + italian: 'Italian', + french: 'French' + }; return map[server.language] ?? 'English'; } - private emptyResult(message: string, _media: ProviderMediaObject): ProviderResult { + private emptyResult( + message: string, + _media: ProviderMediaObject + ): ProviderResult { return { sources: [], subtitles: [], - diagnostics: [{ code: 'PROVIDER_ERROR', message: `${this.name}: ${message}`, field: '', severity: 'error' }], + diagnostics: [ + { + code: 'PROVIDER_ERROR', + message: `${this.name}: ${message}`, + field: '', + severity: 'error' + } + ] }; } async healthCheck(): Promise { try { - const res = await fetch(this.BASE_URL, { method: 'HEAD', headers: this.HEADERS }); + const res = await fetch(this.BASE_URL, { + method: 'HEAD', + headers: this.HEADERS + }); return res.status < 500; } catch { return false; } } -} \ No newline at end of file +} diff --git a/src/providers/videasy/videasy.types.ts b/src/providers/videasy/videasy.types.ts index 41664a1..3109b07 100644 --- a/src/providers/videasy/videasy.types.ts +++ b/src/providers/videasy/videasy.types.ts @@ -57,4 +57,4 @@ export interface VideasyServer { readonly name: string; readonly url: string; readonly language?: string; -} \ No newline at end of file +} From 96315478b2e66c0de5f36e60f2f978ea64dfaf57 Mon Sep 17 00:00:00 2001 From: Nischaldoescode Date: Fri, 1 May 2026 00:02:55 +0530 Subject: [PATCH 3/4] Updated the servers list --- src/providers/videasy/videasy.ts | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/providers/videasy/videasy.ts b/src/providers/videasy/videasy.ts index a3df4ec..d4d4754 100644 --- a/src/providers/videasy/videasy.ts +++ b/src/providers/videasy/videasy.ts @@ -21,20 +21,18 @@ const VIDEASY_SERVERS: readonly VideasyServer[] = [ // { name: 'meine-de', url: 'https://api.videasy.net/meine/sources-with-title', language: 'german' }, // { name: 'meine-it', url: 'https://api.videasy.net/meine/sources-with-title', language: 'italian' }, // { name: 'meine-fr', url: 'https://api.videasy.net/meine/sources-with-title', language: 'french' }, - { - name: 'mb-flix', - url: 'https://api.videasy.net/mb-flix/sources-with-title' - }, - { - name: '1movies', - url: 'https://api.videasy.net/1movies/sources-with-title' - }, - { name: 'cdn', url: 'https://api.videasy.net/cdn/sources-with-title' }, - { - name: 'superflix', - url: 'https://api.videasy.net/superflix/sources-with-title' - } -] as const; + // { name: 'overflix', url: 'https://api2.videasy.net/overflix/sources-with-title', language: 'english' }, + // { name: 'visioncine', url: 'https://api.videasy.net/visioncine/sources-with-title', language: 'english' }, + // { name: 'hdmovie', url: 'https://api.videasy.net/hdmovie/sources-with-title', language: 'english' }, + // { name: 'primewire', url: 'https://api2.videasy.net/primewire/sources-with-title', language: 'english' }, + + { name: 'cuevana', url: 'https://api2.videasy.net/cuevana/sources-with-title', language: 'english' }, + { name: 'mb-flix', url: 'https://api.videasy.net/mb-flix/sources-with-title', language: 'english' }, + { name: '1movies', url: 'https://api.videasy.net/1movies/sources-with-title', language: 'english' }, + { name: 'cdn', url: 'https://api.videasy.net/cdn/sources-with-title', language: 'english' }, + { name: 'superflix', url: 'https://api.videasy.net/superflix/sources-with-title', language: 'english' }, + { name: 'lamovie', url: 'https://api.videasy.net/lamovie/sources-with-title', language: 'english' } + ] as const; export class VideasyProvider extends BaseProvider { readonly id = 'Videasy'; From 5e0526231779f88aa418ac8250439ab1da84d139 Mon Sep 17 00:00:00 2001 From: Nischaldoescode Date: Fri, 1 May 2026 00:03:42 +0530 Subject: [PATCH 4/4] Updated the servers list(2), ran: npm format --- src/providers/videasy/videasy.ts | 38 ++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/providers/videasy/videasy.ts b/src/providers/videasy/videasy.ts index d4d4754..f932e25 100644 --- a/src/providers/videasy/videasy.ts +++ b/src/providers/videasy/videasy.ts @@ -26,13 +26,37 @@ const VIDEASY_SERVERS: readonly VideasyServer[] = [ // { name: 'hdmovie', url: 'https://api.videasy.net/hdmovie/sources-with-title', language: 'english' }, // { name: 'primewire', url: 'https://api2.videasy.net/primewire/sources-with-title', language: 'english' }, - { name: 'cuevana', url: 'https://api2.videasy.net/cuevana/sources-with-title', language: 'english' }, - { name: 'mb-flix', url: 'https://api.videasy.net/mb-flix/sources-with-title', language: 'english' }, - { name: '1movies', url: 'https://api.videasy.net/1movies/sources-with-title', language: 'english' }, - { name: 'cdn', url: 'https://api.videasy.net/cdn/sources-with-title', language: 'english' }, - { name: 'superflix', url: 'https://api.videasy.net/superflix/sources-with-title', language: 'english' }, - { name: 'lamovie', url: 'https://api.videasy.net/lamovie/sources-with-title', language: 'english' } - ] as const; + { + name: 'cuevana', + url: 'https://api2.videasy.net/cuevana/sources-with-title', + language: 'english' + }, + { + name: 'mb-flix', + url: 'https://api.videasy.net/mb-flix/sources-with-title', + language: 'english' + }, + { + name: '1movies', + url: 'https://api.videasy.net/1movies/sources-with-title', + language: 'english' + }, + { + name: 'cdn', + url: 'https://api.videasy.net/cdn/sources-with-title', + language: 'english' + }, + { + name: 'superflix', + url: 'https://api.videasy.net/superflix/sources-with-title', + language: 'english' + }, + { + name: 'lamovie', + url: 'https://api.videasy.net/lamovie/sources-with-title', + language: 'english' + } +] as const; export class VideasyProvider extends BaseProvider { readonly id = 'Videasy';