@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.
Files changed (52) hide show
  1. package/package.json +3 -2
  2. package/src/config.js +10 -85
  3. package/src/sdk.d.ts +94 -121
  4. package/src/sdk.js +82 -78
  5. package/src/sources/111477.js +88 -100
  6. package/src/sources/123anime.js +120 -56
  7. package/src/sources/3eyedraven.js +82 -135
  8. package/src/sources/cinecat.js +37 -18
  9. package/src/sources/cinemaarmy.js +179 -180
  10. package/src/sources/cinesrc.js +401 -397
  11. package/src/sources/cno.js +101 -94
  12. package/src/sources/dulo.js +134 -149
  13. package/src/sources/flaxmovies.js +114 -105
  14. package/src/sources/frost.js +38 -29
  15. package/src/sources/fsonline.js +95 -47
  16. package/src/sources/hdhub.js +43 -36
  17. package/src/sources/hexa.js +60 -53
  18. package/src/sources/hyper.js +42 -35
  19. package/src/sources/kickassanime.js +117 -124
  20. package/src/sources/kisskh.js +114 -59
  21. package/src/sources/lmscript.js +72 -70
  22. package/src/sources/lookmovie.js +80 -79
  23. package/src/sources/movenerds.js +74 -124
  24. package/src/sources/movy.js +197 -209
  25. package/src/sources/net79.js +59 -55
  26. package/src/sources/peestream.js +126 -138
  27. package/src/sources/pengu.js +46 -49
  28. package/src/sources/pstream.js +73 -67
  29. package/src/sources/purstream.js +96 -104
  30. package/src/sources/rivestream.js +182 -176
  31. package/src/sources/rivo.js +58 -53
  32. package/src/sources/streamaggregator.js +114 -128
  33. package/src/sources/thugtv.js +70 -62
  34. package/src/sources/vidapi.js +122 -114
  35. package/src/sources/vidcore.js +14 -122
  36. package/src/sources/vidfast.js +14 -122
  37. package/src/sources/vidlink.js +78 -27
  38. package/src/sources/vidup.js +14 -122
  39. package/src/sources/vidvault.js +133 -187
  40. package/src/sources/vidy.js +192 -187
  41. package/src/sources/vidzee.js +189 -183
  42. package/src/sources/vixsrc.js +123 -113
  43. package/src/sources/watchout.js +60 -46
  44. package/src/sources/xdownloader.js +127 -128
  45. package/src/sources/yapgrid.js +68 -62
  46. package/src/sources/yastream.js +35 -29
  47. package/src/subtitles.js +105 -122
  48. package/src/utils/helpers.js +586 -247
  49. package/src/sources/bcine.js +0 -202
  50. package/src/sources/cinezo.js +0 -55
  51. package/src/sources/vidora.js +0 -62
  52. package/src/sources/vidrock.js +0 -145
@@ -1,181 +1,180 @@
1
- import crypto from "crypto";
2
- import { Session, ClientIdentifier, initTLS, destroyTLS } from "node-tls-client";
3
-
4
- const BASE_URL = "https://cinema.army";
5
- const API_BASE = "https://cinema.army/api";
6
-
7
- const XOR_KEY = "f16a6b92fcd6eed3e9476297f893f2505c32f79bc6efef9b6c95496aa5914548";
8
- const HMAC_KEY = "a2cfc9eaa2a3690b5d4f6b5f958dbdeae52a097283d375bd253ee7c7062524f5";
9
-
10
- const UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
11
-
12
- const SERVERS = [
13
- { key: "cookiebakers", method: "POST", label: "CookieBakers" },
14
- { key: "tcloud", method: "GET", label: "TCloud" },
15
- { key: "ipcloud", method: "GET", label: "IPcloud" },
16
- { key: "dcloud", method: "GET", label: "Dcloud" },
17
- ];
18
-
19
- let tlsInitialized = false;
20
- let session = null;
21
-
22
- async function ensureSession() {
23
- if (!tlsInitialized) {
24
- await initTLS();
25
- tlsInitialized = true;
26
- }
27
- if (!session) {
28
- session = new Session({
29
- clientIdentifier: ClientIdentifier.chrome_131,
30
- timeout: 15000,
31
- insecureSkipVerify: false,
32
- });
33
- }
34
- return session;
35
- }
36
-
37
- function getHeaders(token, id, isTv, s, e) {
38
- const referer = isTv
39
- ? `${BASE_URL}/watch?id=${id}&type=tv&season=${s}&episode=${e}`
40
- : `${BASE_URL}/watch?id=${id}&type=movie`;
41
-
42
- return {
43
- "User-Agent": UA,
44
- "Accept": "application/json",
45
- "Accept-Language": "en-US,en;q=0.9",
46
- "Accept-Encoding": "gzip, deflate, br",
47
- "Cache-Control": "no-cache",
48
- "Pragma": "no-cache",
49
- "Referer": referer,
50
- "Origin": BASE_URL,
51
- "Sec-Ch-Ua": '"Chromium";v="131", "Not_A Brand";v="24"',
52
- "Sec-Ch-Ua-Mobile": "?0",
53
- "Sec-Ch-Ua-Platform": '"Windows"',
54
- "Sec-Fetch-Dest": "empty",
55
- "Sec-Fetch-Mode": "cors",
56
- "Sec-Fetch-Site": "same-origin",
57
- "Priority": "u=1, i",
58
- "X-Stream-Token": token,
59
- };
60
- }
61
-
62
- function generateToken(id) {
63
- try {
64
- const minute = Math.floor(Date.now() / 1000 / 60);
65
- return crypto
66
- .createHmac("sha256", HMAC_KEY)
67
- .update(`${id}:${minute}`)
68
- .digest("hex");
69
- } catch {
70
- return "";
71
- }
72
- }
73
-
74
- function decryptStreamUrl(encoded) {
75
- if (!encoded) return "";
76
- if (encoded.startsWith("http://") || encoded.startsWith("https://")) return encoded;
77
- try {
78
- const decoded = Buffer.from(encoded, "base64").toString("binary");
79
- let out = "";
80
- for (let i = 0; i < decoded.length; i++) {
81
- out += String.fromCharCode(
82
- decoded.charCodeAt(i) ^ XOR_KEY.charCodeAt(i % XOR_KEY.length)
83
- );
84
- }
85
- return out;
86
- } catch {
87
- return encoded;
88
- }
89
- }
90
-
91
- export async function getStream(args) {
92
- const { id, s = null, e = null } = args;
93
- const isTv = s != null && e != null;
94
-
95
- const token = generateToken(id);
96
- const headers = getHeaders(token, id, isTv, s, e);
97
-
98
- const sess = await ensureSession();
99
-
100
- const requests = SERVERS.map(server => {
101
- const path = isTv
102
- ? `/${server.key}/tv/${id}/${s}/${e}`
103
- : `/${server.key}/movie/${id}`;
104
- return { url: `${API_BASE}${path}`, server };
105
- });
106
-
107
- const results = await Promise.allSettled(
108
- requests.map(async ({ url, server }) => {
109
- try {
110
- const res = server.method === "POST"
111
- ? await sess.post(url, { headers })
112
- : await sess.get(url, { headers });
113
-
114
- if (res.status !== 200) {
115
- if (process.env.DEBUG_CAUSE) {
116
- console.error(`[CinemaArmy ${server.key}] HTTP ${res.status}`);
117
- }
118
- return null;
119
- }
120
-
121
- const text = await res.text();
122
- let data;
123
- try {
124
- data = JSON.parse(text);
125
- } catch {
126
- return null;
127
- }
128
-
129
- const encrypted = data?.stream?.url;
130
- if (!encrypted) return null;
131
-
132
- const streamUrl = decryptStreamUrl(encrypted);
133
- if (!streamUrl || !/^https?:\/\//.test(streamUrl)) return null;
134
-
135
- return {
136
- url: streamUrl,
137
- headers: {
138
- "User-Agent": UA,
139
- Referer: `${BASE_URL}/`,
140
- Origin: BASE_URL,
141
- },
142
- server: `CinemaArmy (${server.label})`,
143
- quality: "1080p",
144
- type: streamUrl.includes(".m3u8") ? "hls" : "mp4",
145
- };
146
- } catch (err) {
147
- if (process.env.DEBUG_CAUSE) {
148
- console.error(`[CinemaArmy ${server.key}] ${err.message}`);
149
- if (err.cause) {
150
- console.error(` cause.code: ${err.cause.code || "n/a"}`);
151
- console.error(` cause.message: ${err.cause.message || err.cause}`);
152
- }
153
- }
154
- return null;
155
- }
156
- })
157
- );
158
-
159
- const allUrls = results
160
- .filter(r => r.status === "fulfilled" && r.value)
161
- .map(r => r.value);
162
-
163
- if (!allUrls.length) return null;
164
-
165
- return { allUrls };
166
- }
167
-
168
- export async function cleanup() {
169
- if (session) {
170
- try {
171
- await session.close();
172
- } catch { }
173
- session = null;
174
- }
175
- if (tlsInitialized) {
176
- try {
177
- await destroyTLS();
178
- } catch { }
179
- tlsInitialized = false;
180
- }
1
+ import crypto from 'node:crypto';
2
+ import { ClientIdentifier, destroyTLS, initTLS, Session } from 'node-tls-client';
3
+
4
+ const BASE_URL = 'https://cinema.army';
5
+ const API_BASE = `${BASE_URL}/api`;
6
+ const HMAC_KEY = 'a2cfc9eaa2a3690b5d4f6b5f958dbdeae52a097283d375bd253ee7c7062524f5';
7
+ const XOR_KEY = 'f16a6b92fcd6eed3e9476297f893f2505c32f79bc6efef9b6c95496aa5914548';
8
+ const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
9
+
10
+ const SERVERS = [
11
+ { key: 'cookiebakers', label: 'CookieBakers', method: 'POST' },
12
+ { key: 'tcloud', label: 'TCloud', method: 'POST' },
13
+ { key: 'ipcloud', label: 'IPCloud', method: 'POST' },
14
+ { key: 'dcloud', label: 'DCloud', method: 'POST' },
15
+ { key: 'tidb', label: 'TIDB', method: 'POST' },
16
+ ];
17
+
18
+ let tlsInitialized = false;
19
+ let session = null;
20
+
21
+ async function ensureSession() {
22
+ if (!tlsInitialized) {
23
+ await initTLS();
24
+ tlsInitialized = true;
25
+ }
26
+ if (!session) {
27
+ session = new Session({
28
+ clientIdentifier: ClientIdentifier.chrome_131,
29
+ timeout: 15000,
30
+ insecureSkipVerify: false,
31
+ });
32
+ }
33
+ return session;
34
+ }
35
+
36
+ function getHeaders(token, id, isTv, s, e) {
37
+ const referer = isTv
38
+ ? `${BASE_URL}/watch?id=${id}&type=tv&season=${s}&episode=${e}`
39
+ : `${BASE_URL}/watch?id=${id}&type=movie`;
40
+
41
+ return {
42
+ 'User-Agent': UA,
43
+ Accept: 'application/json',
44
+ 'Accept-Language': 'en-US,en;q=0.9',
45
+ 'Accept-Encoding': 'gzip, deflate, br',
46
+ 'Cache-Control': 'no-cache',
47
+ Pragma: 'no-cache',
48
+ Referer: referer,
49
+ Origin: BASE_URL,
50
+ 'Sec-Ch-Ua': '"Chromium";v="131", "Not_A Brand";v="24"',
51
+ 'Sec-Ch-Ua-Mobile': '?0',
52
+ 'Sec-Ch-Ua-Platform': '"Windows"',
53
+ 'Sec-Fetch-Dest': 'empty',
54
+ 'Sec-Fetch-Mode': 'cors',
55
+ 'Sec-Fetch-Site': 'same-origin',
56
+ Priority: 'u=1, i',
57
+ 'X-Stream-Token': token,
58
+ };
59
+ }
60
+
61
+ function generateToken(id) {
62
+ try {
63
+ const minute = Math.floor(Date.now() / 1000 / 60);
64
+ return crypto
65
+ .createHmac('sha256', HMAC_KEY)
66
+ .update(`${id}:${minute}`)
67
+ .digest('hex');
68
+ } catch {
69
+ return '';
70
+ }
71
+ }
72
+
73
+ function decryptStreamUrl(encoded) {
74
+ if (!encoded) return '';
75
+ if (encoded.startsWith('http://') || encoded.startsWith('https://')) return encoded;
76
+ try {
77
+ const decoded = Buffer.from(encoded, 'base64').toString('binary');
78
+ let out = '';
79
+ for (let i = 0; i < decoded.length; i++) {
80
+ out += String.fromCharCode(
81
+ decoded.charCodeAt(i) ^ XOR_KEY.charCodeAt(i % XOR_KEY.length)
82
+ );
83
+ }
84
+ return out;
85
+ } catch {
86
+ return encoded;
87
+ }
88
+ }
89
+
90
+ export async function getStream(args) {
91
+ const { id, s, e } = args || {};
92
+ const isTv = s != null && e != null;
93
+
94
+ const token = generateToken(id);
95
+ const headers = getHeaders(token, id, isTv, s, e);
96
+
97
+ const sess = await ensureSession();
98
+
99
+ const requests = SERVERS.map(server => {
100
+ const path = isTv
101
+ ? `/${server.key}/tv/${id}/${s}/${e}`
102
+ : `/${server.key}/movie/${id}`;
103
+ return { url: `${API_BASE}${path}`, server };
104
+ });
105
+
106
+ const results = await Promise.allSettled(
107
+ requests.map(async ({ url, server }) => {
108
+ try {
109
+ const res = server.method === 'POST'
110
+ ? await sess.post(url, { headers, body: '' })
111
+ : await sess.get(url, { headers });
112
+
113
+ if (res?.status !== 200) return null;
114
+
115
+ const rawBody = typeof res.text === 'function' ? await res.text() : res.body;
116
+
117
+ let data;
118
+ try {
119
+ data = typeof rawBody === 'object' && rawBody !== null ? rawBody : JSON.parse(rawBody);
120
+ } catch (err) {
121
+ return null;
122
+ }
123
+
124
+ const encrypted = data?.stream?.url;
125
+ if (!encrypted) {
126
+ return null;
127
+ }
128
+
129
+ const streamUrl = decryptStreamUrl(encrypted);
130
+
131
+ if (!streamUrl || !/^https?:\/\//.test(streamUrl)) {
132
+ return null;
133
+ }
134
+
135
+ return {
136
+ url: streamUrl,
137
+ headers: {
138
+ 'User-Agent': UA,
139
+ Referer: `${BASE_URL}/`,
140
+ Origin: BASE_URL,
141
+ },
142
+ server: `CinemaArmy (${server.label})`,
143
+ quality: '1080p',
144
+ type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
145
+ };
146
+ } catch (err) {
147
+ return null;
148
+ }
149
+ })
150
+ );
151
+
152
+ const allUrls = results
153
+ .filter(r => r.status === 'fulfilled' && r.value)
154
+ .map(r => r.value);
155
+
156
+ if (!allUrls.length) {
157
+ return null;
158
+ }
159
+
160
+ return {
161
+ url: allUrls[0].url,
162
+ headers: allUrls[0].headers,
163
+ allUrls,
164
+ };
165
+ }
166
+
167
+ export async function cleanup() {
168
+ if (session) {
169
+ try {
170
+ await session.close();
171
+ } catch { }
172
+ session = null;
173
+ }
174
+ if (tlsInitialized) {
175
+ try {
176
+ await destroyTLS();
177
+ } catch { }
178
+ tlsInitialized = false;
179
+ }
181
180
  }