skystream-cli 1.4.5 → 1.4.7
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/dist/index.js +55 -45
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ const program = new Command();
|
|
|
12
12
|
program
|
|
13
13
|
.name('skystream')
|
|
14
14
|
.description('SkyStream Plugin Development Kit CLI (Sky Gen 2)')
|
|
15
|
-
.version('1.4.
|
|
15
|
+
.version('1.4.7');
|
|
16
16
|
// Schemas
|
|
17
17
|
const pluginSchema = z.object({
|
|
18
18
|
packageName: z.string().min(5).regex(/^[a-z0-9._-]+$/),
|
|
@@ -163,7 +163,13 @@ const JS_TEMPLATE = `(function() {
|
|
|
163
163
|
],
|
|
164
164
|
nextAiring: new NextAiring({ episode: 5, season: 1, airDate: "2024-04-01" }),
|
|
165
165
|
recommendations: [
|
|
166
|
-
new MultimediaItem({ title: "Similar Show", url: \`\${manifest.baseUrl}/similar\`, posterUrl: "
|
|
166
|
+
new MultimediaItem({ title: "Similar Show", url: \`\${manifest.baseUrl}/similar\`, posterUrl: "https://placehold.co/400x600", type: "series" })
|
|
167
|
+
],
|
|
168
|
+
playbackPolicy: "none", // 'none' | 'VPN Recommended' | 'torrent' | 'externalPlayerOnly' | 'internalPlayerOnly'
|
|
169
|
+
syncData: { "my_service_id": "12345" }, // Optional: external metadata sync
|
|
170
|
+
streams: [
|
|
171
|
+
// Optional: "Instant Load" - bypass loadStreams by providing links here
|
|
172
|
+
new StreamResult({ url: "https://example.com/movie.mp4", source: "Instant High" })
|
|
167
173
|
],
|
|
168
174
|
headers: { "Referer": \`\${manifest.baseUrl}\` },
|
|
169
175
|
episodes: [
|
|
@@ -174,7 +180,8 @@ const JS_TEMPLATE = `(function() {
|
|
|
174
180
|
episode: 1,
|
|
175
181
|
description: "Episode summary...",
|
|
176
182
|
posterUrl: \`https://placehold.co/400x600.png?text=Episode+Poster\`,
|
|
177
|
-
headers: { "Referer": \`\${manifest.baseUrl}\` }
|
|
183
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` },
|
|
184
|
+
streams: [] // Optional: "Instant Load" for episodes
|
|
178
185
|
}),
|
|
179
186
|
new Episode({
|
|
180
187
|
name: "Episode 2",
|
|
@@ -200,25 +207,19 @@ const JS_TEMPLATE = `(function() {
|
|
|
200
207
|
*/
|
|
201
208
|
async function loadStreams(url, cb) {
|
|
202
209
|
try {
|
|
203
|
-
// Standard: Return a List of stream
|
|
210
|
+
// Standard: Return a List of stream objects
|
|
204
211
|
cb({
|
|
205
212
|
success: true,
|
|
206
213
|
data: [
|
|
207
214
|
new StreamResult({
|
|
208
215
|
url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
|
|
209
|
-
source: "
|
|
210
|
-
headers: { "Referer": \`\${manifest.baseUrl}\` }
|
|
211
|
-
subtitles: [
|
|
212
|
-
{ url: \`\${manifest.baseUrl}/sub.vtt\`, label: "English", lang: "en" } // (optional)
|
|
213
|
-
],
|
|
214
|
-
drmKid: "kid_value", // (optional)
|
|
215
|
-
drmKey: "key_value", // (optional)
|
|
216
|
-
licenseUrl: "https://license-server.com" // (optional)
|
|
216
|
+
source: "Direct Quality",
|
|
217
|
+
headers: { "Referer": \`\${manifest.baseUrl}\` }
|
|
217
218
|
})
|
|
218
219
|
]
|
|
219
220
|
});
|
|
220
221
|
} catch (e) {
|
|
221
|
-
cb({ success: false, errorCode: "STREAM_ERROR", message:
|
|
222
|
+
cb({ success: false, errorCode: "STREAM_ERROR", message: String(e) });
|
|
222
223
|
}
|
|
223
224
|
}
|
|
224
225
|
|
|
@@ -447,6 +448,7 @@ program.command('test')
|
|
|
447
448
|
const manifest = await fs.readJson(manifestPath);
|
|
448
449
|
const jsContent = await fs.readFile(jsPath, 'utf8');
|
|
449
450
|
console.log(`\n--- Testing ${manifest.packageName} -> ${options.function} ---`);
|
|
451
|
+
const preferences = {};
|
|
450
452
|
const context = {
|
|
451
453
|
manifest,
|
|
452
454
|
console: {
|
|
@@ -455,11 +457,16 @@ program.command('test')
|
|
|
455
457
|
},
|
|
456
458
|
http_get: async (url, headers, cb) => {
|
|
457
459
|
try {
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
+
const finalHeaders = { ...(headers || {}) };
|
|
461
|
+
if (!Object.keys(finalHeaders).some(k => k.toLowerCase() === 'user-agent')) {
|
|
462
|
+
finalHeaders['User-Agent'] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36";
|
|
463
|
+
}
|
|
464
|
+
const res = await axios.get(url, { headers: finalHeaders });
|
|
465
|
+
const body = typeof res.data === 'string' ? res.data : JSON.stringify(res.data);
|
|
466
|
+
const response = { status: res.status, statusCode: res.status, body, headers: res.headers };
|
|
460
467
|
if (cb)
|
|
461
|
-
cb(
|
|
462
|
-
return
|
|
468
|
+
cb(response);
|
|
469
|
+
return response;
|
|
463
470
|
}
|
|
464
471
|
catch (e) {
|
|
465
472
|
const res = { status: e.response?.status || 500, statusCode: e.response?.status || 500, body: e.response?.data || e.message, headers: e.response?.headers || {} };
|
|
@@ -470,11 +477,16 @@ program.command('test')
|
|
|
470
477
|
},
|
|
471
478
|
http_post: async (url, headers, body, cb) => {
|
|
472
479
|
try {
|
|
473
|
-
const
|
|
474
|
-
|
|
480
|
+
const finalHeaders = { ...(headers || {}) };
|
|
481
|
+
if (!Object.keys(finalHeaders).some(k => k.toLowerCase() === 'user-agent')) {
|
|
482
|
+
finalHeaders['User-Agent'] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36";
|
|
483
|
+
}
|
|
484
|
+
const res = await axios.post(url, body, { headers: finalHeaders });
|
|
485
|
+
const resBody = typeof res.data === 'string' ? res.data : JSON.stringify(res.data);
|
|
486
|
+
const response = { status: res.status, statusCode: res.status, body: resBody, headers: res.headers };
|
|
475
487
|
if (cb)
|
|
476
|
-
cb(
|
|
477
|
-
return
|
|
488
|
+
cb(response);
|
|
489
|
+
return response;
|
|
478
490
|
}
|
|
479
491
|
catch (e) {
|
|
480
492
|
const res = { status: e.response?.status || 500, statusCode: e.response?.status || 500, body: e.response?.data || e.message, headers: e.response?.headers || {} };
|
|
@@ -483,39 +495,32 @@ program.command('test')
|
|
|
483
495
|
return res;
|
|
484
496
|
}
|
|
485
497
|
},
|
|
486
|
-
_fetch: async (url) => {
|
|
487
|
-
try {
|
|
488
|
-
const res = await axios.get(url);
|
|
489
|
-
return typeof res.data === 'string' ? res.data : JSON.stringify(res.data);
|
|
490
|
-
}
|
|
491
|
-
catch (e) {
|
|
492
|
-
throw new Error(`HTTP Error ${e.response?.status || 500} fetching ${url}`);
|
|
493
|
-
}
|
|
494
|
-
},
|
|
495
|
-
fetch: async (url) => {
|
|
496
|
-
const res = await axios.get(url);
|
|
497
|
-
return {
|
|
498
|
-
status: res.status,
|
|
499
|
-
statusCode: res.status,
|
|
500
|
-
body: typeof res.data === 'string' ? res.data : JSON.stringify(res.data),
|
|
501
|
-
headers: res.headers
|
|
502
|
-
};
|
|
503
|
-
},
|
|
504
498
|
registerSettings: (schema) => {
|
|
505
499
|
console.log(' [Mock SDK]: Plugin registered settings:', JSON.stringify(schema, null, 2));
|
|
506
500
|
},
|
|
501
|
+
getPreference: (key) => {
|
|
502
|
+
return preferences[key] || null;
|
|
503
|
+
},
|
|
504
|
+
setPreference: (key, value) => {
|
|
505
|
+
preferences[key] = value;
|
|
506
|
+
return true;
|
|
507
|
+
},
|
|
507
508
|
solveCaptcha: async (siteKey, url) => {
|
|
508
509
|
console.log(' [Mock SDK]: solveCaptcha requested for ' + url + ' with key ' + siteKey);
|
|
509
510
|
return "mock_captcha_token";
|
|
510
511
|
},
|
|
511
|
-
crypto: {
|
|
512
|
-
decryptAES: (data, key, iv) => {
|
|
513
|
-
return "decrypted(" + data + ")";
|
|
514
|
-
}
|
|
515
|
-
},
|
|
516
512
|
btoa: (s) => Buffer.from(s).toString('base64'),
|
|
517
513
|
atob: (s) => Buffer.from(s, 'base64').toString('utf8'),
|
|
518
514
|
sendMessage: async (id, arg) => {
|
|
515
|
+
if (id === 'get_preference') {
|
|
516
|
+
const { key } = JSON.parse(arg);
|
|
517
|
+
return preferences[key] || null;
|
|
518
|
+
}
|
|
519
|
+
if (id === 'set_preference') {
|
|
520
|
+
const { key, value } = JSON.parse(arg);
|
|
521
|
+
preferences[key] = value;
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
519
524
|
if (id === 'crypto_decrypt_aes') {
|
|
520
525
|
const { data, key, iv } = JSON.parse(arg);
|
|
521
526
|
try {
|
|
@@ -550,6 +555,7 @@ program.command('test')
|
|
|
550
555
|
},
|
|
551
556
|
globalThis: {},
|
|
552
557
|
};
|
|
558
|
+
context.globalThis = context;
|
|
553
559
|
const entityDefs = `
|
|
554
560
|
class Actor {
|
|
555
561
|
constructor(params) {
|
|
@@ -574,8 +580,10 @@ program.command('test')
|
|
|
574
580
|
Object.assign(this, {
|
|
575
581
|
type: 'movie',
|
|
576
582
|
status: 'ongoing',
|
|
577
|
-
|
|
583
|
+
playbackPolicy: 'none',
|
|
578
584
|
isAdult: false,
|
|
585
|
+
streams: [],
|
|
586
|
+
syncData: {},
|
|
579
587
|
...params
|
|
580
588
|
});
|
|
581
589
|
}
|
|
@@ -587,6 +595,8 @@ program.command('test')
|
|
|
587
595
|
season: 0,
|
|
588
596
|
episode: 0,
|
|
589
597
|
dubStatus: 'none',
|
|
598
|
+
playbackPolicy: 'none',
|
|
599
|
+
streams: [],
|
|
590
600
|
...params
|
|
591
601
|
});
|
|
592
602
|
}
|