@deadair/plugin-sdk 0.8.3 → 0.9.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/dist/index.js CHANGED
@@ -53,6 +53,12 @@ var JSON_SAFE_PAYLOAD_TYPES = [
53
53
  "NewsFeedDescriptor",
54
54
  "NewsQuery",
55
55
  "NewsItem",
56
+ "PodcastShow",
57
+ "PodcastAudio",
58
+ "PodcastEpisode",
59
+ "PodcastEpisodesQuery",
60
+ "PodcastDirectoryQuery",
61
+ "PodcastDirectoryEntry",
56
62
  "SimilarArtist",
57
63
  "ArtistTrack",
58
64
  "SearchQuery",
@@ -87,6 +93,7 @@ var BOUNDARY_METHOD_TYPES = [
87
93
  "MixerProvider",
88
94
  "ChartsProvider",
89
95
  "NewsProvider",
96
+ "PodcastProvider",
90
97
  "SimilarityProvider",
91
98
  "SearchProvider",
92
99
  "WeatherProvider",
@@ -599,6 +606,18 @@ function parseFeed(xml) {
599
606
  if (title !== void 0) feed.title = title;
600
607
  const homeUrl = readLink(channel.link);
601
608
  if (homeUrl !== void 0) feed.homeUrl = homeUrl;
609
+ const description = plainText2(channel.description ?? channel.summary ?? channel.subtitle);
610
+ if (description !== void 0) feed.description = description;
611
+ const author = readAuthor(channel.author);
612
+ if (author !== void 0) feed.author = author;
613
+ const imageUrl = readImage(channel.image);
614
+ if (imageUrl !== void 0) feed.imageUrl = imageUrl;
615
+ const language = text(channel.language);
616
+ if (language !== void 0) feed.language = language;
617
+ const categories = readCategories(channel.category);
618
+ if (categories.length > 0) feed.categories = categories;
619
+ const explicit = readExplicit(channel.explicit);
620
+ if (explicit !== void 0) feed.explicit = explicit;
602
621
  return feed;
603
622
  }
604
623
  __name(parseFeed, "parseFeed");
@@ -632,6 +651,18 @@ function readItem(entry) {
632
651
  if (publishedAt !== void 0) item.publishedAt = publishedAt;
633
652
  if (author !== void 0) item.author = author;
634
653
  if (categories.length > 0) item.categories = categories;
654
+ const enclosure = readEnclosure(entry.enclosure) ?? readEnclosure(entry.link);
655
+ if (enclosure !== void 0) item.enclosure = enclosure;
656
+ const durationMs = readDuration(entry.duration);
657
+ if (durationMs !== void 0) item.durationMs = durationMs;
658
+ const imageUrl = readImage(entry.image);
659
+ if (imageUrl !== void 0) item.imageUrl = imageUrl;
660
+ const explicit = readExplicit(entry.explicit);
661
+ if (explicit !== void 0) item.explicit = explicit;
662
+ const season = readOrdinal(entry.season);
663
+ if (season !== void 0) item.season = season;
664
+ const episode = readOrdinal(entry.episode);
665
+ if (episode !== void 0) item.episode = episode;
635
666
  return item;
636
667
  }
637
668
  __name(readItem, "readItem");
@@ -668,15 +699,91 @@ function readAuthor(value) {
668
699
  __name(readAuthor, "readAuthor");
669
700
  function readCategories(value) {
670
701
  const seen = /* @__PURE__ */ new Set();
671
- for (const candidate of asArray(value)) {
672
- const name = typeof candidate === "string" ? trimmed(candidate) : isRecord(candidate) ? text(candidate["@_term"]) ?? text(candidate["#text"]) : void 0;
673
- if (name !== void 0) seen.add(name);
674
- }
702
+ const visit = /* @__PURE__ */ __name((candidates) => {
703
+ for (const candidate of candidates) {
704
+ const name = typeof candidate === "string" ? trimmed(candidate) : isRecord(candidate) ? text(candidate["@_term"]) ?? text(candidate["@_text"]) ?? text(candidate["#text"]) : void 0;
705
+ if (name !== void 0) seen.add(name);
706
+ if (isRecord(candidate)) visit(asArray(candidate.category));
707
+ }
708
+ }, "visit");
709
+ visit(asArray(value));
675
710
  return [
676
711
  ...seen
677
712
  ];
678
713
  }
679
714
  __name(readCategories, "readCategories");
715
+ function readEnclosure(value) {
716
+ const found = [];
717
+ for (const candidate of asArray(value)) {
718
+ if (!isRecord(candidate)) continue;
719
+ const rel = text(candidate["@_rel"]);
720
+ const isAtomLink = candidate["@_href"] !== void 0;
721
+ if (isAtomLink && rel !== "enclosure") continue;
722
+ const url = webAddress(text(candidate["@_url"]) ?? text(candidate["@_href"]));
723
+ if (url === void 0) continue;
724
+ const enclosure = {
725
+ url
726
+ };
727
+ const type = text(candidate["@_type"])?.toLowerCase();
728
+ if (type !== void 0) enclosure.type = type;
729
+ const lengthBytes = positiveWhole(text(candidate["@_length"]));
730
+ if (lengthBytes !== void 0) enclosure.lengthBytes = lengthBytes;
731
+ found.push(enclosure);
732
+ }
733
+ return found.find((enclosure) => enclosure.type?.startsWith("audio/") === true) ?? found[0];
734
+ }
735
+ __name(readEnclosure, "readEnclosure");
736
+ function readDuration(value) {
737
+ const raw = text(asArray(value)[0]);
738
+ if (raw === void 0) return void 0;
739
+ const parts = raw.split(":").map((part) => part.trim());
740
+ if (parts.length > 3) return void 0;
741
+ if (!parts.every((part, at) => (at === parts.length - 1 ? /^\d+(\.\d+)?$/ : /^\d+$/).test(part))) return void 0;
742
+ if (parts.slice(1).some((part) => Number(part) >= 60)) return void 0;
743
+ const seconds = parts.reduce((total, part) => total * 60 + Number(part), 0);
744
+ const ms = Math.round(seconds * 1e3);
745
+ return Number.isFinite(ms) && ms > 0 ? ms : void 0;
746
+ }
747
+ __name(readDuration, "readDuration");
748
+ function readImage(value) {
749
+ const candidates = asArray(value);
750
+ for (const candidate of candidates) {
751
+ if (isRecord(candidate)) {
752
+ const href = webAddress(text(candidate["@_href"]));
753
+ if (href !== void 0) return href;
754
+ }
755
+ }
756
+ for (const candidate of candidates) {
757
+ const url = isRecord(candidate) ? webAddress(text(candidate.url)) : webAddress(text(candidate));
758
+ if (url !== void 0) return url;
759
+ }
760
+ return void 0;
761
+ }
762
+ __name(readImage, "readImage");
763
+ function readExplicit(value) {
764
+ const raw = text(asArray(value)[0])?.toLowerCase();
765
+ if (raw === "yes" || raw === "true" || raw === "explicit") return true;
766
+ if (raw === "no" || raw === "false" || raw === "clean") return false;
767
+ return void 0;
768
+ }
769
+ __name(readExplicit, "readExplicit");
770
+ var readOrdinal = /* @__PURE__ */ __name((value) => positiveWhole(text(asArray(value)[0])), "readOrdinal");
771
+ function positiveWhole(raw) {
772
+ if (raw === void 0 || !/^\d+$/.test(raw)) return void 0;
773
+ const parsed = Number(raw);
774
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
775
+ }
776
+ __name(positiveWhole, "positiveWhole");
777
+ function webAddress(raw) {
778
+ if (raw === void 0) return void 0;
779
+ try {
780
+ const { protocol } = new URL(raw);
781
+ return protocol === "http:" || protocol === "https:" ? raw : void 0;
782
+ } catch {
783
+ return void 0;
784
+ }
785
+ }
786
+ __name(webAddress, "webAddress");
680
787
  function plainText2(value) {
681
788
  const raw = text(value);
682
789
  return raw === void 0 ? void 0 : plainText(raw, FEED_SUMMARY_MAX_CHARS);
@@ -704,6 +811,13 @@ var trimmed = /* @__PURE__ */ __name((value) => value.trim().length === 0 ? void
704
811
  function text(value) {
705
812
  if (typeof value === "string") return trimmed(value);
706
813
  if (typeof value === "number" || typeof value === "boolean") return String(value);
814
+ if (Array.isArray(value)) {
815
+ for (const candidate of value) {
816
+ const found = text(candidate);
817
+ if (found !== void 0) return found;
818
+ }
819
+ return void 0;
820
+ }
707
821
  if (isRecord(value)) return text(value["#text"]);
708
822
  return void 0;
709
823
  }
@@ -880,6 +994,7 @@ var configFieldControlSchema = z.enum([
880
994
  var configFieldOptionSourceSchema = z.enum([
881
995
  "station.newsCategories",
882
996
  "station.newsFeeds",
997
+ "station.podcastShows",
883
998
  "intl.timeZones",
884
999
  "plugins.speech",
885
1000
  "plugins.llm",
@@ -1032,6 +1147,7 @@ var PLUGIN_CAPABILITY_ANALYSIS = "analysis";
1032
1147
  var PLUGIN_CAPABILITY_MIXER = "mixer";
1033
1148
  var PLUGIN_CAPABILITY_CHARTS = "charts";
1034
1149
  var PLUGIN_CAPABILITY_NEWS = "news";
1150
+ var PLUGIN_CAPABILITY_PODCAST = "podcast";
1035
1151
  var PLUGIN_CAPABILITY_SIMILARITY = "similarity";
1036
1152
  var PLUGIN_CAPABILITY_SEARCH = "search";
1037
1153
  var PLUGIN_CAPABILITY_WEATHER = "weather";
@@ -1048,6 +1164,7 @@ var KNOWN_PLUGIN_CAPABILITIES = [
1048
1164
  PLUGIN_CAPABILITY_MIXER,
1049
1165
  PLUGIN_CAPABILITY_CHARTS,
1050
1166
  PLUGIN_CAPABILITY_NEWS,
1167
+ PLUGIN_CAPABILITY_PODCAST,
1051
1168
  PLUGIN_CAPABILITY_SIMILARITY,
1052
1169
  PLUGIN_CAPABILITY_SEARCH,
1053
1170
  PLUGIN_CAPABILITY_WEATHER,
@@ -1097,6 +1214,7 @@ export {
1097
1214
  PLUGIN_CAPABILITY_MIXER,
1098
1215
  PLUGIN_CAPABILITY_NEWS,
1099
1216
  PLUGIN_CAPABILITY_OAUTH,
1217
+ PLUGIN_CAPABILITY_PODCAST,
1100
1218
  PLUGIN_CAPABILITY_SCROBBLE,
1101
1219
  PLUGIN_CAPABILITY_SEARCH,
1102
1220
  PLUGIN_CAPABILITY_SIMILARITY,