skystream-cli 1.4.2 → 1.4.4
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 +95 -61
- 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.4');
|
|
16
16
|
// Schemas
|
|
17
17
|
const pluginSchema = z.object({
|
|
18
18
|
packageName: z.string().min(5).regex(/^[a-z0-9._-]+$/),
|
|
@@ -45,12 +45,18 @@ const JS_TEMPLATE = `(function() {
|
|
|
45
45
|
*/
|
|
46
46
|
// var manifest is injected at runtime
|
|
47
47
|
|
|
48
|
+
// 1. (Optional) Register your plugin settings
|
|
49
|
+
registerSettings([
|
|
50
|
+
{ id: "quality", name: "Default Quality", type: "select", options: ["1080p", "720p"], default: "1080p" },
|
|
51
|
+
{ id: "prefer_dub", name: "Prefer Dubbed", type: "toggle", default: false }
|
|
52
|
+
]);
|
|
48
53
|
|
|
49
54
|
/**
|
|
50
55
|
* Loads the home screen categories.
|
|
51
56
|
* @param {(res: Response) => void} cb
|
|
52
57
|
*/
|
|
53
58
|
async function getHome(cb) {
|
|
59
|
+
// Example: Using solveCaptcha if needed (await solveCaptcha(siteKey, url))
|
|
54
60
|
try {
|
|
55
61
|
// Dashboard Layout:
|
|
56
62
|
// - "Trending" is a reserved category promoted to the Hero Carousel.
|
|
@@ -75,23 +81,22 @@ const JS_TEMPLATE = `(function() {
|
|
|
75
81
|
title: "Example Series (Thumb)",
|
|
76
82
|
url: \`\${manifest.baseUrl}/series\`,
|
|
77
83
|
posterUrl: \`https://placehold.co/400x600.png?text=Series+Poster\`,
|
|
78
|
-
type: "series",
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
type: "series",
|
|
85
|
+
year: 2024,
|
|
86
|
+
score: 8.5,
|
|
87
|
+
status: "ongoing", // ongoing, completed, upcoming
|
|
88
|
+
description: "This category appears as a thumbnail row.",
|
|
89
|
+
cast: [
|
|
90
|
+
new Actor({ name: "John Doe", role: "Protagonist", image: "https://..." })
|
|
91
|
+
],
|
|
81
92
|
episodes: [
|
|
82
93
|
new Episode({
|
|
83
94
|
name: "Episode 1",
|
|
84
95
|
url: \`\${manifest.baseUrl}/series/1\`,
|
|
85
96
|
season: 1,
|
|
86
97
|
episode: 1,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
new Episode({
|
|
90
|
-
name: "Episode 2",
|
|
91
|
-
url: \`\${manifest.baseUrl}/series/2\`,
|
|
92
|
-
season: 1,
|
|
93
|
-
episode: 2,
|
|
94
|
-
posterUrl: \`https://placehold.co/400x600.png?text=EP2+Poster\`
|
|
98
|
+
airDate: "2024-03-12",
|
|
99
|
+
dubStatus: "subbed" // subbed, dubbed, none
|
|
95
100
|
})
|
|
96
101
|
]
|
|
97
102
|
})
|
|
@@ -106,9 +111,10 @@ const JS_TEMPLATE = `(function() {
|
|
|
106
111
|
/**
|
|
107
112
|
* Searches for media items.
|
|
108
113
|
* @param {string} query
|
|
114
|
+
* @param {number} page
|
|
109
115
|
* @param {(res: Response) => void} cb
|
|
110
116
|
*/
|
|
111
|
-
async function search(query, cb) {
|
|
117
|
+
async function search(query, page, cb) {
|
|
112
118
|
try {
|
|
113
119
|
// Standard: Return a List of items
|
|
114
120
|
// Samples show both a movie and a series
|
|
@@ -198,7 +204,7 @@ const JS_TEMPLATE = `(function() {
|
|
|
198
204
|
data: [
|
|
199
205
|
new StreamResult({
|
|
200
206
|
url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
|
|
201
|
-
|
|
207
|
+
source: "Server [1080p]", // (optional)
|
|
202
208
|
headers: { "Referer": \`\${manifest.baseUrl}\` }, // (optional)
|
|
203
209
|
subtitles: [
|
|
204
210
|
{ url: \`\${manifest.baseUrl}/sub.vtt\`, label: "English", lang: "en" } // (optional)
|
|
@@ -409,7 +415,7 @@ program.command('validate')
|
|
|
409
415
|
count++;
|
|
410
416
|
}
|
|
411
417
|
catch (e) {
|
|
412
|
-
console.error(
|
|
418
|
+
console.error(`\u2717 ${item} invalid: ${e.message}`);
|
|
413
419
|
if (e instanceof z.ZodError) {
|
|
414
420
|
console.error(JSON.stringify(e.format(), null, 2));
|
|
415
421
|
}
|
|
@@ -493,14 +499,24 @@ program.command('test')
|
|
|
493
499
|
headers: res.headers
|
|
494
500
|
};
|
|
495
501
|
},
|
|
502
|
+
registerSettings: (schema) => {
|
|
503
|
+
console.log(' [Mock SDK]: Plugin registered settings:', JSON.stringify(schema, null, 2));
|
|
504
|
+
},
|
|
505
|
+
solveCaptcha: async (siteKey, url) => {
|
|
506
|
+
console.log(' [Mock SDK]: solveCaptcha requested for ' + url + ' with key ' + siteKey);
|
|
507
|
+
return "mock_captcha_token";
|
|
508
|
+
},
|
|
509
|
+
crypto: {
|
|
510
|
+
decryptAES: (data, key, iv) => {
|
|
511
|
+
return "decrypted(" + data + ")";
|
|
512
|
+
}
|
|
513
|
+
},
|
|
496
514
|
btoa: (s) => Buffer.from(s).toString('base64'),
|
|
497
515
|
atob: (s) => Buffer.from(s, 'base64').toString('utf8'),
|
|
498
516
|
sendMessage: async (id, arg) => {
|
|
499
517
|
if (id === 'crypto_decrypt_aes') {
|
|
500
518
|
const { data, key, iv } = JSON.parse(arg);
|
|
501
519
|
try {
|
|
502
|
-
// Standardize key and iv to correct lengths
|
|
503
|
-
// They are often passed as base64 strings
|
|
504
520
|
const decodeBuffer = (s) => {
|
|
505
521
|
return s.length % 4 === 0 && /^[A-Za-z0-9+/=]+$/.test(s) ? Buffer.from(s, 'base64') : Buffer.from(s, 'utf8');
|
|
506
522
|
};
|
|
@@ -533,41 +549,50 @@ program.command('test')
|
|
|
533
549
|
globalThis: {},
|
|
534
550
|
};
|
|
535
551
|
const entityDefs = `
|
|
552
|
+
class Actor {
|
|
553
|
+
constructor(params) {
|
|
554
|
+
Object.assign(this, params);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
class Trailer {
|
|
559
|
+
constructor(params) {
|
|
560
|
+
Object.assign(this, params);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
class NextAiring {
|
|
565
|
+
constructor(params) {
|
|
566
|
+
Object.assign(this, params);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
536
570
|
class MultimediaItem {
|
|
537
|
-
constructor(
|
|
538
|
-
this
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
this.headers = headers;
|
|
546
|
-
this.provider = provider;
|
|
571
|
+
constructor(params) {
|
|
572
|
+
Object.assign(this, {
|
|
573
|
+
type: 'movie',
|
|
574
|
+
status: 'ongoing',
|
|
575
|
+
vpnStatus: 'none',
|
|
576
|
+
isAdult: false,
|
|
577
|
+
...params
|
|
578
|
+
});
|
|
547
579
|
}
|
|
548
580
|
}
|
|
549
581
|
|
|
550
582
|
class Episode {
|
|
551
|
-
constructor(
|
|
552
|
-
this
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
this.headers = headers;
|
|
583
|
+
constructor(params) {
|
|
584
|
+
Object.assign(this, {
|
|
585
|
+
season: 0,
|
|
586
|
+
episode: 0,
|
|
587
|
+
dubStatus: 'none',
|
|
588
|
+
...params
|
|
589
|
+
});
|
|
559
590
|
}
|
|
560
591
|
}
|
|
561
592
|
|
|
562
593
|
class StreamResult {
|
|
563
|
-
constructor(
|
|
564
|
-
this
|
|
565
|
-
this.quality = quality || 'Auto';
|
|
566
|
-
this.headers = headers;
|
|
567
|
-
this.subtitles = subtitles;
|
|
568
|
-
this.drmKid = drmKid;
|
|
569
|
-
this.drmKey = drmKey;
|
|
570
|
-
this.licenseUrl = licenseUrl;
|
|
594
|
+
constructor(params) {
|
|
595
|
+
Object.assign(this, params);
|
|
571
596
|
}
|
|
572
597
|
}
|
|
573
598
|
|
|
@@ -576,7 +601,14 @@ program.command('test')
|
|
|
576
601
|
const sandbox = Object.create(null);
|
|
577
602
|
Object.assign(sandbox, context);
|
|
578
603
|
// Ensure Node globals are present
|
|
579
|
-
sandbox.
|
|
604
|
+
sandbox.atob = (str) => Buffer.from(str, 'base64').toString('binary');
|
|
605
|
+
sandbox.btoa = (str) => Buffer.from(str, 'binary').toString('base64');
|
|
606
|
+
sandbox.URL = URL;
|
|
607
|
+
sandbox.console = {
|
|
608
|
+
log: (...args) => console.log('[JS LOG]', ...args),
|
|
609
|
+
error: (...args) => console.error('[JS ERROR]', ...args),
|
|
610
|
+
warn: (...args) => console.warn('[JS WARN]', ...args),
|
|
611
|
+
};
|
|
580
612
|
sandbox.axios = axios;
|
|
581
613
|
sandbox.Buffer = Buffer;
|
|
582
614
|
sandbox.setTimeout = setTimeout;
|
|
@@ -610,21 +642,23 @@ program.command('test')
|
|
|
610
642
|
const callback = (res) => {
|
|
611
643
|
console.log('\n--- Result ---');
|
|
612
644
|
if (res && res.success === false) {
|
|
613
|
-
console.log(
|
|
614
|
-
console.log(
|
|
645
|
+
console.log('\x1b[31mStatus: FAILED\x1b[0m');
|
|
646
|
+
console.log('\x1b[31mError Code: ' + (res.errorCode || 'UNKNOWN') + '\x1b[0m');
|
|
615
647
|
if (res.message)
|
|
616
|
-
console.log(
|
|
648
|
+
console.log('\x1b[31mMessage: ' + res.message + '\x1b[0m');
|
|
617
649
|
}
|
|
618
650
|
else {
|
|
619
|
-
console.log(
|
|
651
|
+
console.log('\x1b[32mStatus: SUCCESS\x1b[0m');
|
|
620
652
|
}
|
|
621
653
|
console.log(JSON.stringify(res, null, 2));
|
|
622
654
|
};
|
|
623
655
|
try {
|
|
624
656
|
if (options.function === 'getHome')
|
|
625
657
|
await fn(callback);
|
|
658
|
+
else if (options.function === 'search')
|
|
659
|
+
await fn(options.query, 1, callback);
|
|
626
660
|
else if (!options.query || options.query.trim() === "") {
|
|
627
|
-
console.warn(
|
|
661
|
+
console.warn('\x1b[33mWarning: Function \'' + options.function + '\' usually requires a query/URL (-q), but none was provided.\x1b[0m');
|
|
628
662
|
await fn(options.query, callback);
|
|
629
663
|
}
|
|
630
664
|
else {
|
|
@@ -632,8 +666,8 @@ program.command('test')
|
|
|
632
666
|
}
|
|
633
667
|
}
|
|
634
668
|
catch (e) {
|
|
635
|
-
console.error(
|
|
636
|
-
console.error(
|
|
669
|
+
console.error('\n\x1b[31m--- CRITICAL ERROR DURING EXECUTION ---\x1b[0m');
|
|
670
|
+
console.error('\x1b[31m' + (e.stack || e.message) + '\x1b[0m\n');
|
|
637
671
|
process.exit(2);
|
|
638
672
|
}
|
|
639
673
|
});
|
|
@@ -653,27 +687,27 @@ program.command('deploy')
|
|
|
653
687
|
const catalog = [];
|
|
654
688
|
// Standardize URL: Append /dist automatically
|
|
655
689
|
const baseRaw = options.url.endsWith('/') ? options.url.slice(0, -1) : options.url;
|
|
656
|
-
const distUrl =
|
|
690
|
+
const distUrl = baseRaw + "/dist";
|
|
657
691
|
for (const item of items) {
|
|
658
692
|
const itemPath = path.join(rootDir, item);
|
|
659
693
|
const mPath = path.join(itemPath, 'plugin.json');
|
|
660
694
|
if (await fs.pathExists(mPath) && (await fs.stat(itemPath)).isDirectory()) {
|
|
661
695
|
const manifest = await fs.readJson(mPath);
|
|
662
696
|
const packageName = manifest.packageName || manifest.id || item;
|
|
663
|
-
const bundleName =
|
|
697
|
+
const bundleName = packageName + ".sky";
|
|
664
698
|
const outPath = path.join(distDir, bundleName);
|
|
665
699
|
const arch = archiver('zip', { zlib: { level: 9 } });
|
|
666
700
|
arch.pipe(fs.createWriteStream(outPath));
|
|
667
701
|
arch.file(mPath, { name: 'plugin.json' });
|
|
668
702
|
arch.file(path.join(itemPath, 'plugin.js'), { name: 'plugin.js' });
|
|
669
703
|
await arch.finalize();
|
|
670
|
-
catalog.push({ ...manifest, url:
|
|
671
|
-
console.log(
|
|
704
|
+
catalog.push({ ...manifest, url: distUrl + "/" + bundleName });
|
|
705
|
+
console.log("✓ Bundled " + manifest.packageName);
|
|
672
706
|
}
|
|
673
707
|
}
|
|
674
708
|
const finalRepo = {
|
|
675
709
|
...repo,
|
|
676
|
-
pluginLists: [
|
|
710
|
+
pluginLists: [distUrl + "/plugins.json"]
|
|
677
711
|
};
|
|
678
712
|
await fs.writeJson(repoPath, finalRepo, { spaces: 2 });
|
|
679
713
|
await fs.writeJson(path.join(distDir, 'plugins.json'), catalog, { spaces: 2 });
|
|
@@ -682,15 +716,15 @@ program.command('deploy')
|
|
|
682
716
|
if (await fs.pathExists(readmePath)) {
|
|
683
717
|
let readme = await fs.readFile(readmePath, 'utf8');
|
|
684
718
|
const placeholder = 'https://raw.githubusercontent.com/USER_NAME/REPO_NAME/main/repo.json';
|
|
685
|
-
const liveUrl =
|
|
719
|
+
const liveUrl = baseRaw + "/repo.json";
|
|
686
720
|
if (readme.includes(placeholder)) {
|
|
687
721
|
readme = readme.replace(placeholder, liveUrl);
|
|
688
722
|
await fs.writeFile(readmePath, readme);
|
|
689
|
-
console.log(
|
|
723
|
+
console.log("✓ Updated README.md with live URL");
|
|
690
724
|
}
|
|
691
725
|
}
|
|
692
|
-
console.log(
|
|
693
|
-
console.log(
|
|
694
|
-
console.log(
|
|
726
|
+
console.log("\nDeployment Complete. Assets generated in dist/");
|
|
727
|
+
console.log("\nYour Repo Link for the app:");
|
|
728
|
+
console.log("> " + baseRaw + "/repo.json");
|
|
695
729
|
});
|
|
696
730
|
program.parse();
|