@vyla-entertainment/sdk 1.20.0 → 1.21.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/package.json +3 -2
- package/src/config.js +10 -85
- package/src/sdk.d.ts +94 -121
- package/src/sdk.js +82 -78
- package/src/sources/111477.js +88 -100
- package/src/sources/123anime.js +120 -56
- package/src/sources/3eyedraven.js +82 -135
- package/src/sources/cinecat.js +37 -18
- package/src/sources/cinemaarmy.js +179 -180
- package/src/sources/cinesrc.js +401 -397
- package/src/sources/cno.js +101 -94
- package/src/sources/dulo.js +134 -149
- package/src/sources/flaxmovies.js +114 -105
- package/src/sources/frost.js +38 -29
- package/src/sources/fsonline.js +95 -47
- package/src/sources/hdhub.js +43 -36
- package/src/sources/hexa.js +60 -53
- package/src/sources/hyper.js +42 -35
- package/src/sources/kickassanime.js +117 -124
- package/src/sources/kisskh.js +114 -59
- package/src/sources/lmscript.js +72 -70
- package/src/sources/lookmovie.js +80 -79
- package/src/sources/movenerds.js +74 -124
- package/src/sources/movy.js +197 -209
- package/src/sources/net79.js +59 -55
- package/src/sources/peestream.js +126 -138
- package/src/sources/pengu.js +46 -49
- package/src/sources/pstream.js +73 -67
- package/src/sources/purstream.js +96 -104
- package/src/sources/rivestream.js +182 -176
- package/src/sources/rivo.js +58 -53
- package/src/sources/streamaggregator.js +114 -128
- package/src/sources/thugtv.js +70 -62
- package/src/sources/vidapi.js +122 -114
- package/src/sources/vidcore.js +14 -122
- package/src/sources/vidfast.js +14 -122
- package/src/sources/vidlink.js +78 -27
- package/src/sources/vidup.js +14 -122
- package/src/sources/vidvault.js +133 -187
- package/src/sources/vidy.js +192 -187
- package/src/sources/vidzee.js +189 -183
- package/src/sources/vixsrc.js +123 -113
- package/src/sources/watchout.js +60 -46
- package/src/sources/xdownloader.js +127 -128
- package/src/sources/yapgrid.js +68 -62
- package/src/sources/yastream.js +35 -29
- package/src/subtitles.js +105 -122
- package/src/utils/helpers.js +586 -247
- package/src/sources/bcine.js +0 -202
- package/src/sources/cinezo.js +0 -55
- package/src/sources/vidora.js +0 -62
- package/src/sources/vidrock.js +0 -145
package/src/sources/111477.js
CHANGED
|
@@ -1,101 +1,89 @@
|
|
|
1
|
-
import { getUA } from '../utils/helpers.js';
|
|
2
|
-
|
|
3
|
-
const SERVICE_ORIGIN = 'https://st.111477.xyz';
|
|
4
|
-
|
|
5
|
-
function generateManifestBaseUrl(
|
|
6
|
-
let config = 'https://a.111477.xyz/::sort=file-desc::limit=3';
|
|
7
|
-
if (
|
|
8
|
-
config += `::tmdb=${
|
|
9
|
-
}
|
|
10
|
-
const b64 = Buffer.from(config, 'utf8')
|
|
11
|
-
.toString('base64')
|
|
12
|
-
.replace(/\+/g, '-')
|
|
13
|
-
.replace(/\//g, '_')
|
|
14
|
-
.replace(/=+$/, '');
|
|
15
|
-
return `${SERVICE_ORIGIN}/config/${b64}`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (allUrls.length > 0) break;
|
|
90
|
-
}
|
|
91
|
-
} catch { }
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (allUrls.length === 0) return null;
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
url: allUrls[0].url,
|
|
98
|
-
allUrls,
|
|
99
|
-
headers: allUrls[0].headers,
|
|
100
|
-
};
|
|
1
|
+
import { getUA, resolveImdbId, resolveTmdbKey } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const SERVICE_ORIGIN = 'https://st.111477.xyz';
|
|
4
|
+
|
|
5
|
+
function generateManifestBaseUrl(apiKey) {
|
|
6
|
+
let config = 'https://a.111477.xyz/::sort=file-desc::limit=3';
|
|
7
|
+
if (apiKey) {
|
|
8
|
+
config += `::tmdb=${apiKey}`;
|
|
9
|
+
}
|
|
10
|
+
const b64 = Buffer.from(config, 'utf8')
|
|
11
|
+
.toString('base64')
|
|
12
|
+
.replace(/\+/g, '-')
|
|
13
|
+
.replace(/\//g, '_')
|
|
14
|
+
.replace(/=+$/, '');
|
|
15
|
+
return `${SERVICE_ORIGIN}/config/${b64}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function getStream(args) {
|
|
19
|
+
const { id, s, e, sdk } = args || {};
|
|
20
|
+
const isTv = s != null && e != null;
|
|
21
|
+
const apiKey = resolveTmdbKey(args, sdk);
|
|
22
|
+
const ua = getUA();
|
|
23
|
+
|
|
24
|
+
const imdbId = await resolveImdbId(id, isTv, apiKey);
|
|
25
|
+
const targetIds = [];
|
|
26
|
+
|
|
27
|
+
if (imdbId && imdbId.startsWith('tt')) {
|
|
28
|
+
targetIds.push(imdbId);
|
|
29
|
+
}
|
|
30
|
+
targetIds.push(`tmdb:${id}`);
|
|
31
|
+
|
|
32
|
+
const addonBase = generateManifestBaseUrl(apiKey);
|
|
33
|
+
const seenUrls = new Set();
|
|
34
|
+
const allUrls = [];
|
|
35
|
+
|
|
36
|
+
const headers = {
|
|
37
|
+
'User-Agent': ua,
|
|
38
|
+
Accept: 'application/json, text/plain, */*',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
for (const targetId of targetIds) {
|
|
42
|
+
const endpoint = isTv
|
|
43
|
+
? `${addonBase}/stream/series/${targetId}:${s || 1}:${e || 1}.json`
|
|
44
|
+
: `${addonBase}/stream/movie/${targetId}.json`;
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(endpoint, {
|
|
48
|
+
headers,
|
|
49
|
+
signal: AbortSignal.timeout(12000),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!res.ok) continue;
|
|
53
|
+
const data = await res.json();
|
|
54
|
+
|
|
55
|
+
if (Array.isArray(data?.streams) && data.streams.length > 0) {
|
|
56
|
+
for (const item of data.streams) {
|
|
57
|
+
if (!item || typeof item !== 'object') continue;
|
|
58
|
+
const streamUrl = String(item.url || '').trim();
|
|
59
|
+
if (!streamUrl || !streamUrl.startsWith('http') || seenUrls.has(streamUrl)) continue;
|
|
60
|
+
|
|
61
|
+
seenUrls.add(streamUrl);
|
|
62
|
+
|
|
63
|
+
const rawTitle = item.title ? String(item.title).trim() : '';
|
|
64
|
+
const rawName = item.name ? String(item.name).trim() : '111477';
|
|
65
|
+
const label = rawTitle || rawName;
|
|
66
|
+
|
|
67
|
+
allUrls.push({
|
|
68
|
+
url: streamUrl,
|
|
69
|
+
label,
|
|
70
|
+
server: label,
|
|
71
|
+
quality: 'Auto',
|
|
72
|
+
type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
|
|
73
|
+
headers,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (allUrls.length > 0) break;
|
|
78
|
+
}
|
|
79
|
+
} catch { }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (allUrls.length === 0) return null;
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
url: allUrls[0].url,
|
|
86
|
+
headers: allUrls[0].headers,
|
|
87
|
+
allUrls,
|
|
88
|
+
};
|
|
101
89
|
}
|
package/src/sources/123anime.js
CHANGED
|
@@ -1,57 +1,121 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
1
|
+
import { fetchJson, getTmdbMetadata, resolveTmdbKey, USER_AGENT } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const BASE_URL = 'https://123animehub.cc';
|
|
4
|
+
const CDN_ORIGIN = 'https://play2.echovideo.ru';
|
|
5
|
+
|
|
6
|
+
async function resolveSlug(id, s, e, titles) {
|
|
7
|
+
const keywords = [];
|
|
8
|
+
for (const title of titles) {
|
|
9
|
+
const t = title.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
10
|
+
if (!keywords.includes(t)) keywords.push(t);
|
|
11
|
+
const words = title.split(/[\s:]+/).filter(w => w.length > 2);
|
|
12
|
+
if (words.length >= 2) {
|
|
13
|
+
const short = words.slice(0, 3).join(' ').toLowerCase();
|
|
14
|
+
if (!keywords.includes(short)) keywords.push(short);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const slugCandidates = [];
|
|
19
|
+
for (const keyword of keywords) {
|
|
20
|
+
try {
|
|
21
|
+
const data = await fetchJson(`${BASE_URL}/ajax/film/search?keyword=${encodeURIComponent(keyword)}&_=${Date.now()}`, {
|
|
22
|
+
headers: {
|
|
23
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
24
|
+
Referer: `${BASE_URL}/`,
|
|
25
|
+
Accept: 'application/json',
|
|
26
|
+
'User-Agent': USER_AGENT,
|
|
27
|
+
},
|
|
28
|
+
signal: AbortSignal.timeout(8000),
|
|
29
|
+
});
|
|
30
|
+
let html = data.html || '';
|
|
31
|
+
let idx = 0;
|
|
32
|
+
while ((idx = html.indexOf('href="/anime/', idx)) !== -1) {
|
|
33
|
+
const start = idx + 13;
|
|
34
|
+
const end = html.indexOf('"', start);
|
|
35
|
+
const slug = html.slice(start, end);
|
|
36
|
+
if (!slugCandidates.includes(slug)) slugCandidates.push(slug);
|
|
37
|
+
idx = end;
|
|
38
|
+
}
|
|
39
|
+
} catch { }
|
|
40
|
+
if (slugCandidates.length) break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const slug of slugCandidates) {
|
|
44
|
+
try {
|
|
45
|
+
const data = await fetchJson(`${BASE_URL}/ajax/episode/info?epr=${encodeURIComponent(s ? `${slug}/${s}/${e}` : `${slug}/1`)}&ts=1&_=${Date.now()}`, {
|
|
46
|
+
headers: {
|
|
47
|
+
Referer: `${BASE_URL}/anime/${slug}`,
|
|
48
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
49
|
+
Accept: 'application/json, text/javascript, */*; q=0.01',
|
|
50
|
+
'User-Agent': USER_AGENT,
|
|
51
|
+
},
|
|
52
|
+
signal: AbortSignal.timeout(10000),
|
|
53
|
+
});
|
|
54
|
+
if (data?.target) return data.target;
|
|
55
|
+
} catch { }
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function getStream(args) {
|
|
61
|
+
const { id, s, e, sdk } = args || {};
|
|
62
|
+
const isTv = s != null && e != null;
|
|
63
|
+
if (!s) return null;
|
|
64
|
+
|
|
65
|
+
const apiKey = resolveTmdbKey(args, sdk);
|
|
66
|
+
const meta = await getTmdbMetadata(id, isTv, apiKey);
|
|
67
|
+
if (!meta?.isAnime) return null;
|
|
68
|
+
|
|
69
|
+
const target = await resolveSlug(id, s, e, meta.titles || []);
|
|
70
|
+
if (!target) return null;
|
|
71
|
+
|
|
72
|
+
const embedMatch = target.match(/\/embed-[^/]+\/([A-Za-z0-9+/=]+)$/);
|
|
73
|
+
if (!embedMatch) return null;
|
|
74
|
+
|
|
75
|
+
const origin = new URL(target).origin;
|
|
76
|
+
try {
|
|
77
|
+
const embedRes = await fetch(target, {
|
|
78
|
+
headers: { 'User-Agent': USER_AGENT },
|
|
79
|
+
signal: AbortSignal.timeout(10000),
|
|
80
|
+
});
|
|
81
|
+
if (!embedRes.ok) return null;
|
|
82
|
+
|
|
83
|
+
const setCookie = embedRes.headers.get('set-cookie');
|
|
84
|
+
const data = await fetchJson(`${origin}/hs/getSources?id=${embedMatch[1]}`, {
|
|
85
|
+
headers: {
|
|
86
|
+
Referer: target,
|
|
87
|
+
Accept: '*/*',
|
|
88
|
+
'User-Agent': USER_AGENT,
|
|
89
|
+
...(setCookie ? { Cookie: setCookie.split(';')[0].trim() } : {}),
|
|
90
|
+
},
|
|
91
|
+
signal: AbortSignal.timeout(10000),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const streamUrl = typeof data.sources === 'string' && data.sources.length
|
|
95
|
+
? data.sources
|
|
96
|
+
: (Array.isArray(data.sources) && data.sources.length ? (data.sources[0].file || data.sources[0].src || data.sources[0].url) : null);
|
|
97
|
+
|
|
98
|
+
if (!streamUrl) return null;
|
|
99
|
+
|
|
100
|
+
const headers = {
|
|
101
|
+
Referer: `${CDN_ORIGIN}/`,
|
|
102
|
+
Origin: CDN_ORIGIN,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const allUrls = [{
|
|
106
|
+
url: streamUrl,
|
|
107
|
+
server: '123Anime',
|
|
108
|
+
quality: 'Auto',
|
|
109
|
+
type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
|
|
110
|
+
headers,
|
|
111
|
+
}];
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
url: streamUrl,
|
|
115
|
+
headers,
|
|
116
|
+
allUrls,
|
|
117
|
+
};
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
57
121
|
}
|
|
@@ -1,136 +1,83 @@
|
|
|
1
|
-
import { getUA } from
|
|
2
|
-
|
|
3
|
-
const BASE_URL =
|
|
4
|
-
const API_BASE =
|
|
5
|
-
|
|
6
|
-
function
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!res.ok) {
|
|
85
|
-
if (process.env.DEBUG_CAUSE) {
|
|
86
|
-
console.error(`[3eyedraven] HTTP ${res.status} for ${url}`);
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const data = await res.json();
|
|
92
|
-
const stream = data?.stream;
|
|
93
|
-
if (!stream?.url) {
|
|
94
|
-
if (process.env.DEBUG_CAUSE) {
|
|
95
|
-
console.error(`[3eyedraven] No stream.url in response for ${url}`);
|
|
96
|
-
}
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const streamUrl = absolute(stream.url);
|
|
101
|
-
if (!/^https?:\/\//.test(streamUrl)) return null;
|
|
102
|
-
|
|
103
|
-
const subtitles = (stream.subtitles || [])
|
|
104
|
-
.map(sub => {
|
|
105
|
-
const subUrl = absolute(sub.url);
|
|
106
|
-
if (!subUrl) return null;
|
|
107
|
-
return {
|
|
108
|
-
label: sub.label || sub.language || "Subtitle",
|
|
109
|
-
file: subUrl,
|
|
110
|
-
type: "vtt",
|
|
111
|
-
source: "3eyedraven",
|
|
112
|
-
};
|
|
113
|
-
})
|
|
114
|
-
.filter(Boolean);
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
url: streamUrl,
|
|
118
|
-
headers: {
|
|
119
|
-
"User-Agent": getUA(),
|
|
120
|
-
Referer: `${BASE_URL}/`,
|
|
121
|
-
Origin: BASE_URL,
|
|
122
|
-
},
|
|
123
|
-
server: "3eyedraven",
|
|
124
|
-
quality: "1080p",
|
|
125
|
-
type: stream.format === "hls" ? "hls" : "mp4",
|
|
126
|
-
subtitles,
|
|
127
|
-
skipProxy: true,
|
|
128
|
-
};
|
|
129
|
-
} catch (err) {
|
|
130
|
-
if (process.env.DEBUG_CAUSE) {
|
|
131
|
-
console.error(`[3eyedraven] fetch error for ${url}:`, err.message);
|
|
132
|
-
if (err.cause) console.error(" cause:", err.cause.code, err.cause.message);
|
|
133
|
-
}
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
1
|
+
import { getTmdbMetadata, getUA, resolveTmdbKey, slugify } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const BASE_URL = 'https://3eyedraven.watch';
|
|
4
|
+
const API_BASE = 'https://3eyedraven.watch/api';
|
|
5
|
+
|
|
6
|
+
function absolute(url) {
|
|
7
|
+
if (!url) return '';
|
|
8
|
+
if (/^https?:\/\//.test(url)) return url;
|
|
9
|
+
return `${BASE_URL}${url.startsWith('/') ? '' : '/'}${url}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function getStream(args) {
|
|
13
|
+
const { id, s, e, sdk } = args || {};
|
|
14
|
+
const isTv = s != null && e != null;
|
|
15
|
+
const apiKey = resolveTmdbKey(args, sdk);
|
|
16
|
+
|
|
17
|
+
const meta = await getTmdbMetadata(id, isTv, apiKey);
|
|
18
|
+
const title = meta?.title;
|
|
19
|
+
if (!title) return null;
|
|
20
|
+
|
|
21
|
+
const identifier = `${slugify(title)}-${id}`;
|
|
22
|
+
const url = isTv
|
|
23
|
+
? `${API_BASE}/stream/${identifier}?season=${s}&episode=${e}`
|
|
24
|
+
: `${API_BASE}/stream/${identifier}`;
|
|
25
|
+
|
|
26
|
+
const headers = {
|
|
27
|
+
'User-Agent': getUA(),
|
|
28
|
+
Accept: 'application/json',
|
|
29
|
+
Referer: `${BASE_URL}/`,
|
|
30
|
+
Origin: BASE_URL,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const res = await fetch(url, {
|
|
35
|
+
headers,
|
|
36
|
+
signal: AbortSignal.timeout(15000),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) return null;
|
|
39
|
+
|
|
40
|
+
const data = await res.json();
|
|
41
|
+
const stream = data?.stream;
|
|
42
|
+
if (!stream?.url) return null;
|
|
43
|
+
|
|
44
|
+
const streamUrl = absolute(stream.url);
|
|
45
|
+
if (!/^https?:\/\//.test(streamUrl)) return null;
|
|
46
|
+
|
|
47
|
+
const subtitles = (stream.subtitles || [])
|
|
48
|
+
.map(sub => {
|
|
49
|
+
const subUrl = absolute(sub.url);
|
|
50
|
+
if (!subUrl) return null;
|
|
51
|
+
return {
|
|
52
|
+
label: sub.label || sub.language || 'Subtitle',
|
|
53
|
+
file: subUrl,
|
|
54
|
+
type: 'vtt',
|
|
55
|
+
source: '3eyedraven',
|
|
56
|
+
};
|
|
57
|
+
})
|
|
58
|
+
.filter(Boolean);
|
|
59
|
+
|
|
60
|
+
const allUrls = [{
|
|
61
|
+
url: streamUrl,
|
|
62
|
+
headers,
|
|
63
|
+
server: '3eyedraven',
|
|
64
|
+
quality: '1080p',
|
|
65
|
+
type: stream.format === 'hls' ? 'hls' : 'mp4',
|
|
66
|
+
subtitles,
|
|
67
|
+
skipProxy: true,
|
|
68
|
+
}];
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
url: streamUrl,
|
|
72
|
+
headers,
|
|
73
|
+
server: '3eyedraven',
|
|
74
|
+
quality: '1080p',
|
|
75
|
+
type: stream.format === 'hls' ? 'hls' : 'mp4',
|
|
76
|
+
subtitles,
|
|
77
|
+
skipProxy: true,
|
|
78
|
+
allUrls,
|
|
79
|
+
};
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
136
83
|
}
|
package/src/sources/cinecat.js
CHANGED
|
@@ -1,19 +1,38 @@
|
|
|
1
|
-
import { fetchJson } from '../utils/helpers.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { fetchJson } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const BASE_URL = 'https://zcdn.bluevelvet.space';
|
|
4
|
+
|
|
5
|
+
export async function getStream(args) {
|
|
6
|
+
const { id, s, e } = args || {};
|
|
7
|
+
const isTv = s != null && e != null;
|
|
8
|
+
|
|
9
|
+
const url = isTv
|
|
10
|
+
? `${BASE_URL}/cdn?tmdb=${id}&type=tv&season=${s}&episode=${e}`
|
|
11
|
+
: `${BASE_URL}/cdn?tmdb=${id}&type=movie`;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetchJson(url);
|
|
15
|
+
if (!res || !res.ready || !res.url) return null;
|
|
16
|
+
|
|
17
|
+
const headers = {
|
|
18
|
+
Referer: `${BASE_URL}/`,
|
|
19
|
+
Origin: BASE_URL,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const allUrls = [{
|
|
23
|
+
url: res.url,
|
|
24
|
+
server: 'CineCat',
|
|
25
|
+
quality: 'Auto',
|
|
26
|
+
type: res.url.includes('.m3u8') ? 'hls' : 'mp4',
|
|
27
|
+
headers,
|
|
28
|
+
}];
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
url: res.url,
|
|
32
|
+
headers,
|
|
33
|
+
allUrls,
|
|
34
|
+
};
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
19
38
|
}
|