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.
Files changed (2) hide show
  1. package/dist/index.js +95 -61
  2. 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.2');
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", // Valid types: movie, series, anime, livestream
79
- description: "This category appears as a thumbnail row.", // (optional)
80
- headers: { "Referer": \`\${manifest.baseUrl}\` }, // (optional)
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
- posterUrl: \`https://placehold.co/400x600.png?text=EP1+Poster\`
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
- quality: "1080p", // (optional)
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(`✗ ${item} invalid: ${e.message}`);
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({ title, url, posterUrl, type, bannerUrl, description, episodes, headers, provider }) {
538
- this.title = title;
539
- this.url = url;
540
- this.posterUrl = posterUrl;
541
- this.type = type || 'movie';
542
- this.bannerUrl = bannerUrl;
543
- this.description = description;
544
- this.episodes = episodes;
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({ name, url, season, episode, description, posterUrl, headers }) {
552
- this.name = name;
553
- this.url = url;
554
- this.season = season || 0;
555
- this.episode = episode || 0;
556
- this.description = description;
557
- this.posterUrl = posterUrl;
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({ url, quality, headers, subtitles, drmKid, drmKey, licenseUrl }) {
564
- this.url = url;
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.console = console;
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(`\x1b[31mStatus: FAILED\x1b[0m`);
614
- console.log(`\x1b[31mError Code: ${res.errorCode || 'UNKNOWN'}\x1b[0m`);
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(`\x1b[31mMessage: ${res.message}\x1b[0m`);
648
+ console.log('\x1b[31mMessage: ' + res.message + '\x1b[0m');
617
649
  }
618
650
  else {
619
- console.log(`\x1b[32mStatus: SUCCESS\x1b[0m`);
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(`\x1b[33mWarning: Function '${options.function}' usually requires a query/URL (-q), but none was provided.\x1b[0m`);
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(`\n\x1b[31m--- CRITICAL ERROR DURING EXECUTION ---\x1b[0m`);
636
- console.error(`\x1b[31m${e.stack || e.message}\x1b[0m\n`);
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 = `${baseRaw}/dist`;
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 = `${packageName}.sky`;
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: `${distUrl}/${bundleName}` });
671
- console.log(`✓ Bundled ${manifest.packageName}`);
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: [`${distUrl}/plugins.json`]
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 = `${baseRaw}/repo.json`;
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(`✓ Updated README.md with live URL`);
723
+ console.log("✓ Updated README.md with live URL");
690
724
  }
691
725
  }
692
- console.log(`\nDeployment Complete. Assets generated in dist/`);
693
- console.log(`\nYour Repo Link for the app:`);
694
- console.log(`> ${baseRaw}/repo.json`);
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skystream-cli",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "type": "module",
5
5
  "description": "SkyStream Plugin Development Kit & Repository Manager",
6
6
  "main": "dist/index.js",