@vyla-entertainment/sdk 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +1 -1
- package/src/config.js +38 -0
- package/src/sources/braflix.js +80 -0
- package/src/sources/zenox.js +108 -0
package/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# vyla-entertainment/sdk
|
|
2
|
+
|
|
2
3
|
The Vyla SDK (@vyla-entertainment/sdk) is a server-side JavaScript/TypeScript package that provides direct access to Vyla's stream resolvers, health probes, download resolvers, and subtitle providers.
|
|
3
4
|
|
|
4
5
|
## Installing
|
|
@@ -11,7 +12,7 @@ npm install @vyla-entertainment/sdk
|
|
|
11
12
|
pnpm install @vyla-entertainment/sdk
|
|
12
13
|
```
|
|
13
14
|
|
|
14
|
-
View our full documentation at https://
|
|
15
|
+
View our full documentation at https://vyla.cc/sdk
|
|
15
16
|
|
|
16
17
|
# [DMCA](https://vyla.cc/misc/project/DMCA)
|
|
17
18
|
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -94,6 +94,25 @@ export const SOURCES = [
|
|
|
94
94
|
}],
|
|
95
95
|
},
|
|
96
96
|
|
|
97
|
+
{
|
|
98
|
+
key: 'braflix',
|
|
99
|
+
label: 'Braflix',
|
|
100
|
+
sourceFile: 'braflix',
|
|
101
|
+
proxyParam: 'bf',
|
|
102
|
+
timeout: 25000,
|
|
103
|
+
jitter: 500,
|
|
104
|
+
retries: 2,
|
|
105
|
+
multiUrl: true,
|
|
106
|
+
skipProxy: true,
|
|
107
|
+
cdnHeaders: [{
|
|
108
|
+
pattern: /braflix\.dev/i,
|
|
109
|
+
headers: {
|
|
110
|
+
Referer: 'https://braflix.dev/',
|
|
111
|
+
Origin: 'https://braflix.dev',
|
|
112
|
+
},
|
|
113
|
+
}],
|
|
114
|
+
},
|
|
115
|
+
|
|
97
116
|
{
|
|
98
117
|
key: 'castle',
|
|
99
118
|
label: 'Castle',
|
|
@@ -725,6 +744,25 @@ export const SOURCES = [
|
|
|
725
744
|
multiUrl: true,
|
|
726
745
|
},
|
|
727
746
|
|
|
747
|
+
{
|
|
748
|
+
key: 'zenox',
|
|
749
|
+
label: 'Zenox',
|
|
750
|
+
sourceFile: 'zenox',
|
|
751
|
+
proxyParam: 'zx',
|
|
752
|
+
timeout: 25000,
|
|
753
|
+
jitter: 500,
|
|
754
|
+
retries: 2,
|
|
755
|
+
multiUrl: true,
|
|
756
|
+
skipProxy: true,
|
|
757
|
+
cdnHeaders: [{
|
|
758
|
+
pattern: /zenox\.lol|hls-m3u8\.lol/i,
|
|
759
|
+
headers: {
|
|
760
|
+
Referer: 'https://zenox.lol/',
|
|
761
|
+
Origin: 'https://zenox.lol',
|
|
762
|
+
},
|
|
763
|
+
}],
|
|
764
|
+
},
|
|
765
|
+
|
|
728
766
|
];
|
|
729
767
|
|
|
730
768
|
export const HEALTH_PROBE_ID = '155';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const BASE_URL = 'https://braflix.dev';
|
|
2
|
+
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36';
|
|
3
|
+
|
|
4
|
+
const HEADERS = {
|
|
5
|
+
Origin: BASE_URL,
|
|
6
|
+
Referer: `${BASE_URL}/`,
|
|
7
|
+
'User-Agent': UA,
|
|
8
|
+
Accept: 'application/json, text/plain, */*',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const PLAYBACK_HEADERS = {
|
|
12
|
+
Origin: BASE_URL,
|
|
13
|
+
Referer: `${BASE_URL}/`,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function getStream(args) {
|
|
17
|
+
const { id, s, e } = args || {};
|
|
18
|
+
const idNum = parseInt(id, 10);
|
|
19
|
+
if (!idNum) return null;
|
|
20
|
+
|
|
21
|
+
const isTv = s != null && e != null;
|
|
22
|
+
const targetSeason = isTv ? (s || 1) : 1;
|
|
23
|
+
const targetEpisode = isTv ? (e || 1) : 1;
|
|
24
|
+
|
|
25
|
+
const path = isTv
|
|
26
|
+
? `/api/play/tv/${idNum}/${targetSeason}/${targetEpisode}`
|
|
27
|
+
: `/api/play/movie/${idNum}`;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
31
|
+
headers: HEADERS,
|
|
32
|
+
signal: AbortSignal.timeout(10000),
|
|
33
|
+
});
|
|
34
|
+
if (!res.ok) return null;
|
|
35
|
+
const data = await res.json();
|
|
36
|
+
|
|
37
|
+
if (data?.status !== 'ready' || !data.result?.file?.stream) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const rawStreamPath = data.result.file.stream;
|
|
42
|
+
const fullStreamUrl = rawStreamPath.startsWith('http')
|
|
43
|
+
? rawStreamPath
|
|
44
|
+
: `${BASE_URL}${rawStreamPath}`;
|
|
45
|
+
|
|
46
|
+
const qualityRaw = String(data.result.source?.quality || '1080,720,480');
|
|
47
|
+
const qualityParts = qualityRaw.split(',').map(q => q.trim()).filter(Boolean);
|
|
48
|
+
const maxQ = qualityParts.reduce((acc, curr) => {
|
|
49
|
+
const num = parseInt(curr, 10);
|
|
50
|
+
return num > acc ? num : acc;
|
|
51
|
+
}, 0);
|
|
52
|
+
|
|
53
|
+
const quality = maxQ > 0 ? `${maxQ}p` : 'Auto';
|
|
54
|
+
const qualitySummary = qualityParts.length > 0
|
|
55
|
+
? qualityParts.map(q => `${q}p`).join('/')
|
|
56
|
+
: 'DASH';
|
|
57
|
+
|
|
58
|
+
const streamType = fullStreamUrl.includes('.mpd')
|
|
59
|
+
? 'dash'
|
|
60
|
+
: fullStreamUrl.includes('.m3u8')
|
|
61
|
+
? 'hls'
|
|
62
|
+
: 'dash';
|
|
63
|
+
|
|
64
|
+
const allUrls = [{
|
|
65
|
+
url: fullStreamUrl,
|
|
66
|
+
server: `Braflix - DASH (${qualitySummary})`,
|
|
67
|
+
quality,
|
|
68
|
+
type: streamType,
|
|
69
|
+
headers: PLAYBACK_HEADERS,
|
|
70
|
+
}];
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
url: fullStreamUrl,
|
|
74
|
+
headers: PLAYBACK_HEADERS,
|
|
75
|
+
allUrls,
|
|
76
|
+
};
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const BASE_URL = 'https://zenox.lol';
|
|
2
|
+
const API_URL = `${BASE_URL}/api/v1/playback/session`;
|
|
3
|
+
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36';
|
|
4
|
+
|
|
5
|
+
const HEADERS = {
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
Origin: BASE_URL,
|
|
8
|
+
Referer: `${BASE_URL}/`,
|
|
9
|
+
'User-Agent': UA,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const PLAYBACK_HEADERS = {
|
|
13
|
+
Origin: BASE_URL,
|
|
14
|
+
Referer: `${BASE_URL}/`,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function fetchServerStream(payload, srv) {
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(API_URL, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: HEADERS,
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
...payload,
|
|
24
|
+
serverIndex: srv.index,
|
|
25
|
+
serverName: srv.name,
|
|
26
|
+
}),
|
|
27
|
+
signal: AbortSignal.timeout(6000),
|
|
28
|
+
});
|
|
29
|
+
if (!res.ok) return null;
|
|
30
|
+
const data = await res.json();
|
|
31
|
+
if (
|
|
32
|
+
!data?.success ||
|
|
33
|
+
!data?.streamUrl ||
|
|
34
|
+
data.streamUrl.includes('/primary/') ||
|
|
35
|
+
data.serverName?.toLowerCase() === 'primary'
|
|
36
|
+
) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const streamUrl = data.streamUrl.startsWith('http')
|
|
41
|
+
? data.streamUrl
|
|
42
|
+
: `${BASE_URL}${data.streamUrl}`;
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
url: streamUrl,
|
|
46
|
+
server: `Zenox - ${data.serverName || srv.name}`,
|
|
47
|
+
quality: 'Auto',
|
|
48
|
+
type: streamUrl.includes('.m3u8') ? 'hls' : (streamUrl.includes('.mpd') ? 'dash' : 'mp4'),
|
|
49
|
+
headers: PLAYBACK_HEADERS,
|
|
50
|
+
};
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function getStream(args) {
|
|
57
|
+
const { id, s, e, title, year, imdbId } = args || {};
|
|
58
|
+
const idNum = parseInt(id, 10);
|
|
59
|
+
if (!idNum) return null;
|
|
60
|
+
|
|
61
|
+
const isTv = s != null && e != null;
|
|
62
|
+
const payload = {
|
|
63
|
+
mediaId: idNum,
|
|
64
|
+
mediaType: isTv ? 'tv' : 'movie',
|
|
65
|
+
season: isTv ? (parseInt(s, 10) || 1) : 1,
|
|
66
|
+
episode: isTv ? (parseInt(e, 10) || 1) : 1,
|
|
67
|
+
title: title || '',
|
|
68
|
+
year: String(year || ''),
|
|
69
|
+
imdbId: imdbId || '',
|
|
70
|
+
autoUseCommunity: false,
|
|
71
|
+
isManualSwitch: true,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const activeServers = [
|
|
75
|
+
{ name: 'Vbot', index: 1 },
|
|
76
|
+
{ name: 'Temporary', index: 1 },
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const results = await Promise.allSettled(
|
|
80
|
+
activeServers.map(srv => fetchServerStream(payload, srv))
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const allUrls = [];
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
|
|
86
|
+
for (const r of results) {
|
|
87
|
+
if (r.status === 'fulfilled' && r.value?.url && !seen.has(r.value.url)) {
|
|
88
|
+
seen.add(r.value.url);
|
|
89
|
+
allUrls.push(r.value);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!allUrls.length) {
|
|
94
|
+
const delta = await fetchServerStream(payload, { name: 'Delta', index: 0 });
|
|
95
|
+
if (delta?.url && !seen.has(delta.url)) {
|
|
96
|
+
seen.add(delta.url);
|
|
97
|
+
allUrls.push(delta);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!allUrls.length) return null;
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
url: allUrls[0].url,
|
|
105
|
+
headers: allUrls[0].headers,
|
|
106
|
+
allUrls,
|
|
107
|
+
};
|
|
108
|
+
}
|