@ctrl/plex 1.5.2 → 2.0.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 (68) hide show
  1. package/README.md +3 -2
  2. package/dist/src/alert.d.ts +12 -0
  3. package/dist/src/alert.js +29 -0
  4. package/dist/src/alert.types.d.ts +59 -0
  5. package/dist/src/alert.types.js +1 -0
  6. package/dist/{base → src/base}/partialPlexObject.d.ts +18 -12
  7. package/dist/{base → src/base}/partialPlexObject.js +32 -23
  8. package/dist/{base → src/base}/playable.d.ts +2 -2
  9. package/dist/src/base/playable.js +8 -0
  10. package/dist/{base → src/base}/plexObject.d.ts +8 -1
  11. package/dist/{base → src/base}/plexObject.js +21 -18
  12. package/dist/{baseFunctionality.d.ts → src/baseFunctionality.d.ts} +17 -1
  13. package/dist/{baseFunctionality.js → src/baseFunctionality.js} +7 -15
  14. package/dist/{client.d.ts → src/client.d.ts} +2 -2
  15. package/dist/{client.js → src/client.js} +12 -20
  16. package/dist/src/client.types.js +1 -0
  17. package/dist/src/config.js +35 -0
  18. package/dist/src/exceptions.d.ts +20 -0
  19. package/dist/src/exceptions.js +40 -0
  20. package/dist/src/index.d.ts +12 -0
  21. package/dist/src/index.js +11 -0
  22. package/dist/{library.d.ts → src/library.d.ts} +207 -21
  23. package/dist/{library.js → src/library.js} +349 -133
  24. package/dist/{library.types.d.ts → src/library.types.d.ts} +71 -1
  25. package/dist/src/library.types.js +1 -0
  26. package/dist/{media.d.ts → src/media.d.ts} +16 -4
  27. package/dist/{media.js → src/media.js} +42 -49
  28. package/dist/src/media.types.d.ts +7 -0
  29. package/dist/src/media.types.js +1 -0
  30. package/dist/{myplex.d.ts → src/myplex.d.ts} +16 -6
  31. package/dist/{myplex.js → src/myplex.js} +71 -57
  32. package/dist/src/myplex.types.js +10 -0
  33. package/dist/src/playlist.d.ts +75 -0
  34. package/dist/src/playlist.js +142 -0
  35. package/dist/src/playlist.types.d.ts +17 -0
  36. package/dist/src/playlist.types.js +1 -0
  37. package/dist/{search.d.ts → src/search.d.ts} +5 -4
  38. package/dist/{search.js → src/search.js} +16 -20
  39. package/dist/src/search.types.js +1 -0
  40. package/dist/{server.d.ts → src/server.d.ts} +22 -10
  41. package/dist/{server.js → src/server.js} +65 -50
  42. package/dist/src/server.types.js +1 -0
  43. package/dist/src/settings.d.ts +79 -0
  44. package/dist/src/settings.js +160 -0
  45. package/dist/{util.d.ts → src/util.d.ts} +2 -1
  46. package/dist/{util.js → src/util.js} +8 -12
  47. package/dist/{video.d.ts → src/video.d.ts} +39 -61
  48. package/dist/{video.js → src/video.js} +110 -93
  49. package/dist/{video.types.d.ts → src/video.types.d.ts} +1 -1
  50. package/dist/src/video.types.js +6 -0
  51. package/package.json +46 -44
  52. package/dist/base/playable.js +0 -12
  53. package/dist/client.types.js +0 -2
  54. package/dist/config.js +0 -41
  55. package/dist/index.d.ts +0 -8
  56. package/dist/index.js +0 -23
  57. package/dist/library.types.js +0 -2
  58. package/dist/myplex.types.js +0 -13
  59. package/dist/playlist.d.ts +0 -7
  60. package/dist/playlist.js +0 -19
  61. package/dist/search.types.js +0 -2
  62. package/dist/server.types.js +0 -2
  63. package/dist/video.types.js +0 -9
  64. /package/dist/{client.types.d.ts → src/client.types.d.ts} +0 -0
  65. /package/dist/{config.d.ts → src/config.d.ts} +0 -0
  66. /package/dist/{myplex.types.d.ts → src/myplex.types.d.ts} +0 -0
  67. /package/dist/{search.types.d.ts → src/search.types.d.ts} +0 -0
  68. /package/dist/{server.types.d.ts → src/server.types.d.ts} +0 -0
@@ -1,40 +1,29 @@
1
- /// <reference types="node" />
1
+ /// <reference types="node" resolution-mode="require"/>
2
2
  import { URL } from 'url';
3
- import { Playable } from './base/playable';
4
- import { MovieData, ShowData } from './library.types';
5
- import { PlexServer } from './server';
6
- import { Director, Country, Writer, Chapter, Collection, Genre, Role, Media, Similar, Producer, Marker } from './media';
7
- import { FullMovieResponse, ChapterSource, EpisodeMetadata } from './video.types';
8
- export declare type VideoType = Movie | Show;
3
+ import { Playable } from './base/playable.js';
4
+ import { ExtrasData, FullShowData, MovieData, ShowData } from './library.types.js';
5
+ import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Producer, Role, Similar, Writer } from './media.js';
6
+ import { ChapterSource, EpisodeMetadata, FullMovieResponse } from './video.types.js';
7
+ export type VideoType = Movie | Show;
9
8
  declare abstract class Video extends Playable {
10
- server: PlexServer;
11
- /** API URL (/library/metadata/<ratingkey>) */
12
- key: string;
13
9
  /** Datetime this item was added to the library. */
14
10
  addedAt: Date;
15
11
  /** Datetime item was last accessed. */
16
12
  lastViewedAt?: Date;
17
13
  /** Hardcoded as 'video' (useful for search filters). */
18
14
  listType: "video";
19
- /** Unique key identifying this item. */
20
- ratingKey: string;
21
15
  /** Summary of the artist, track, or album. */
22
16
  summary: string;
23
17
  /** URL to thumbnail image. */
24
18
  thumb: string;
25
- /** Artist, Album or Track title. (Jason Mraz, We Sing, Lucky, etc.) */
26
- title: string;
27
19
  /** Title to use when sorting (defaults to title). */
28
20
  titleSort?: string;
29
- /** 'artist', 'album', or 'track'. */
30
- type: string;
31
21
  /** Datetime this item was updated. */
32
22
  updatedAt?: Date;
33
23
  /** Count of times this item was accessed. */
34
24
  viewCount?: number;
35
25
  art?: string;
36
26
  grandparentArt?: string;
37
- constructor(server: PlexServer, data: MovieData | EpisodeMetadata, initpath: string, parent?: any);
38
27
  /**
39
28
  * Returns True if this video is watched.
40
29
  */
@@ -54,6 +43,7 @@ declare abstract class Video extends Playable {
54
43
  */
55
44
  markUnwatched(): Promise<void>;
56
45
  rate(rate: number): Promise<void>;
46
+ extras(): Promise<Extra[]>;
57
47
  protected _loadData(data: MovieData | ShowData | EpisodeMetadata): void;
58
48
  }
59
49
  /**
@@ -63,9 +53,6 @@ export declare class Movie extends Video {
63
53
  TAG: string;
64
54
  TYPE: string;
65
55
  METADATA_TYPE: string;
66
- /** Key to movie artwork (/library/metadata/<ratingkey>/art/<artid>) */
67
- art: string;
68
- librarySectionID?: number;
69
56
  /** Audience rating (usually from Rotten Tomatoes). */
70
57
  audienceRating?: number;
71
58
  /** Key to audience rating image (rottentomatoes://image.rating.spilled) */
@@ -78,8 +65,8 @@ export declare class Movie extends Video {
78
65
  duration: number;
79
66
  /** Original title, often the foreign title (転々; 엽기적인 그녀). */
80
67
  originalTitle?: string;
81
- /** Datetime movie was released. */
82
- originallyAvailableAt: Date;
68
+ /** YYYY-MM-DD movie was released. */
69
+ originallyAvailableAt: string;
83
70
  /** Primary extra key (/library/metadata/66351). */
84
71
  primaryExtraKey: string;
85
72
  /** Movie rating (7.9; 9.8; 8.1). */
@@ -94,8 +81,6 @@ export declare class Movie extends Video {
94
81
  userRating?: number;
95
82
  /** View offset in milliseconds. */
96
83
  viewOffset: number;
97
- /** Year movie was released. */
98
- year: number;
99
84
  /** Plex GUID (com.plexapp.agents.imdb://tt4302938?lang=en) */
100
85
  guid: string;
101
86
  directors: Director[];
@@ -108,8 +93,18 @@ export declare class Movie extends Video {
108
93
  roles: Role[];
109
94
  similar: Similar[];
110
95
  media: Media[];
96
+ guids: Guid[];
97
+ markers: Marker[];
111
98
  get actors(): Role[];
112
99
  locations(): Promise<string[]>;
100
+ /**
101
+ * Returns True if this movie has an intro marker
102
+ */
103
+ hasIntroMarker(): Promise<boolean>;
104
+ /**
105
+ * Returns True if this movie has a credits marker
106
+ */
107
+ hasCreditsMarker(): Promise<boolean>;
113
108
  protected _loadData(data: MovieData): void;
114
109
  protected _loadFullData(data: FullMovieResponse): void;
115
110
  }
@@ -120,8 +115,6 @@ export declare class Show extends Video {
120
115
  TAG: string;
121
116
  TYPE: string;
122
117
  METADATA_TYPE: string;
123
- /** Key to show artwork (/library/metadata/<ratingkey>/art/<artid>) */
124
- art: string;
125
118
  /** Key to banner artwork (/library/metadata/<ratingkey>/art/<artid>) */
126
119
  banner: string;
127
120
  /** Unknown. */
@@ -147,8 +140,6 @@ export declare class Show extends Video {
147
140
  theme: string;
148
141
  /** Unknown. */
149
142
  viewedLeafCount: number;
150
- /** Year the show was released. */
151
- year: number;
152
143
  /** List of genre objects. */
153
144
  genres: Genre[];
154
145
  /** List of role objects. */
@@ -163,7 +154,7 @@ export declare class Show extends Video {
163
154
  seasons(query?: Record<string, string | number>): Promise<Season[]>;
164
155
  episodes(query?: Record<string, string | number>): Promise<Episode[]>;
165
156
  protected _loadData(data: ShowData): void;
166
- protected _loadFullData(data: ShowData): void;
157
+ protected _loadFullData(data: FullShowData): void;
167
158
  }
168
159
  /**
169
160
  * Represents a single Show Season (including all episodes).
@@ -195,24 +186,16 @@ export declare class Season extends Video {
195
186
  protected _loadData(data: ShowData): void;
196
187
  protected _loadFullData(data: ShowData): void;
197
188
  }
198
- declare class Episode extends Video {
189
+ export declare class Episode extends Video {
199
190
  static TAG: string;
200
191
  TYPE: string;
201
192
  METADATA_TYPE: string;
202
- /**
203
- * Name of this Episode
204
- */
205
- title: string;
206
- /** Key to episode artwork (/library/metadata/<ratingkey>/art/<artid>) */
207
- art: string;
208
193
  /** Unknown (media). */
209
194
  chapterSource?: string;
210
195
  /** Content rating (PG-13; NR; TV-G). */
211
196
  contentRating: string;
212
197
  /** Duration of episode in milliseconds. */
213
198
  duration: number;
214
- /** Key to this episodes :class:`~plexapi.video.Show` artwork. */
215
- grandparentArt: string;
216
199
  /** Key to this episodes :class:`~plexapi.video.Show`. */
217
200
  grandparentKey: string;
218
201
  /** Unique key for this episodes :class:`~plexapi.video.Show`. */
@@ -243,35 +226,12 @@ declare class Episode extends Video {
243
226
  rating: number;
244
227
  /** View offset in milliseconds. */
245
228
  viewOffset?: number;
246
- /** Year episode was released. */
247
- year: number;
248
229
  writers: Writer[];
249
230
  directors: Director[];
250
231
  media: Media[];
251
232
  collections: Collection[];
252
233
  chapters: Chapter[];
253
234
  markers: Marker[];
254
- protected _INCLUDES: {
255
- checkFiles: number;
256
- includeAllConcerts: number;
257
- includeBandwidths: number;
258
- includeChapters: number;
259
- includeChildren: number;
260
- includeConcerts: number;
261
- includeExternalMedia: number;
262
- includeExtras: number;
263
- includeFields: string;
264
- includeGeolocation: number;
265
- includeLoudnessRamps: number;
266
- includeMarkers: number;
267
- includeOnDeck: number;
268
- includePopularLeaves: number;
269
- includePreferences: number;
270
- includeRelated: number;
271
- includeRelatedCount: number;
272
- includeReviews: number;
273
- includeStations: number;
274
- };
275
235
  /**
276
236
  * Returns this episodes season number.
277
237
  */
@@ -284,9 +244,27 @@ declare class Episode extends Video {
284
244
  * Returns True if this episode has an intro marker
285
245
  */
286
246
  hasIntroMarker(): Promise<boolean>;
247
+ /**
248
+ * Returns True if this episode has a credits marker
249
+ */
250
+ hasCreditsMarker(): Promise<boolean>;
287
251
  protected _loadData(data: EpisodeMetadata): void;
288
252
  protected _loadFullData(data: {
289
253
  Metadata: EpisodeMetadata[];
290
254
  }): void;
291
255
  }
256
+ export declare class Clip extends Video {
257
+ static TAG: string;
258
+ TYPE: string;
259
+ METADATA_TYPE: string;
260
+ protected _loadData(data: any): void;
261
+ protected _loadFullData(data: any): void;
262
+ }
263
+ /**
264
+ * Represents a single Extra (trailer, behindTheScenes, etc).
265
+ */
266
+ export declare class Extra extends Clip {
267
+ protected _loadData(data: ExtrasData): void;
268
+ protected _loadFullData(data: any): void;
269
+ }
292
270
  export {};
@@ -1,13 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Season = exports.Show = exports.Movie = void 0;
4
- const playable_1 = require("./base/playable");
5
- const baseFunctionality_1 = require("./baseFunctionality");
6
- const media_1 = require("./media");
7
- class Video extends playable_1.Playable {
8
- constructor(server, data, initpath, parent) {
9
- super(server, data, initpath, parent);
10
- this.server = server;
1
+ import { Playable } from './base/playable.js';
2
+ import { fetchItem, fetchItems, findItems } from './baseFunctionality.js';
3
+ import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Producer, Role, Similar, Writer, } from './media.js';
4
+ class Video extends Playable {
5
+ constructor() {
6
+ super(...arguments);
11
7
  /** Hardcoded as 'video' (useful for search filters). */
12
8
  this.listType = 'video';
13
9
  }
@@ -25,13 +21,11 @@ class Video extends playable_1.Playable {
25
21
  * the most specific thumbnail for that item.
26
22
  */
27
23
  get thumbUrl() {
28
- var _a, _b;
29
- const thumb = (_b = (_a = this.thumb) !== null && _a !== void 0 ? _a : this.parentThumb) !== null && _b !== void 0 ? _b : this.granparentThumb;
24
+ const thumb = this.thumb ?? this.parentThumb ?? this.granparentThumb;
30
25
  return this.server.url(thumb, true);
31
26
  }
32
27
  get artUrl() {
33
- var _a;
34
- const art = (_a = this.art) !== null && _a !== void 0 ? _a : this.grandparentArt;
28
+ const art = this.art ?? this.grandparentArt;
35
29
  return this.server.url(art, true);
36
30
  }
37
31
  /**
@@ -55,30 +49,34 @@ class Video extends playable_1.Playable {
55
49
  await this.server.query(key);
56
50
  await this.reload();
57
51
  }
52
+ async extras() {
53
+ const data = await this.server.query(this._detailsKey);
54
+ return findItems(data.MediaContainer.Metadata[0].Extras?.Metadata, undefined, Extra, this.server, this);
55
+ }
58
56
  _loadData(data) {
59
- var _a, _b;
60
- this.addedAt = new Date(data.addedAt * 1000);
61
- this.librarySectionID = data.librarySectionID;
62
- this.lastViewedAt = data.lastViewedAt
63
- ? new Date(data.lastViewedAt * 1000)
64
- : undefined;
65
- this.updatedAt = data.lastViewedAt ? new Date(data.updatedAt * 1000) : undefined;
66
57
  this.key = data.key;
67
58
  this.ratingKey = data.ratingKey;
68
- this.viewCount = (_a = data.viewCount) !== null && _a !== void 0 ? _a : 0;
69
59
  this.title = data.title;
70
60
  this.summary = data.summary;
71
61
  this.thumb = data.thumb;
72
62
  this.title = data.title;
73
- this.titleSort = (_b = data.titleSort) !== null && _b !== void 0 ? _b : this.title;
74
63
  this.type = data.type;
64
+ this.librarySectionID = data.librarySectionID;
65
+ this.addedAt = new Date(data.addedAt * 1000);
66
+ this.lastViewedAt = data.lastViewedAt
67
+ ? new Date(data.lastViewedAt * 1000)
68
+ : undefined;
69
+ this.updatedAt = data.lastViewedAt ? new Date(data.updatedAt * 1000) : undefined;
70
+ this.viewCount = data.viewCount ?? 0;
71
+ this.titleSort = data.titleSort ?? this.title;
75
72
  this.viewCount = data.viewCount;
73
+ this.playlistItemID = data.playlistItemID;
76
74
  }
77
75
  }
78
76
  /**
79
77
  * Represents a single Movie.
80
78
  */
81
- class Movie extends Video {
79
+ export class Movie extends Video {
82
80
  constructor() {
83
81
  super(...arguments);
84
82
  this.TAG = 'Video';
@@ -89,15 +87,31 @@ class Movie extends Video {
89
87
  return this.roles;
90
88
  }
91
89
  async locations() {
92
- var _a, _b;
93
90
  if (!this.isFullObject) {
94
91
  await this.reload();
95
92
  }
96
- const parts = ((_b = (_a = this.media) === null || _a === void 0 ? void 0 : _a.map(media => media.parts)) !== null && _b !== void 0 ? _b : []).flat();
93
+ const parts = (this.media?.map(media => media.parts) ?? []).flat();
97
94
  return parts.map(part => part.file);
98
95
  }
96
+ /**
97
+ * Returns True if this movie has an intro marker
98
+ */
99
+ async hasIntroMarker() {
100
+ if (!this.isFullObject) {
101
+ await this.reload();
102
+ }
103
+ return this.markers.some(marker => marker.type === 'intro');
104
+ }
105
+ /**
106
+ * Returns True if this movie has a credits marker
107
+ */
108
+ async hasCreditsMarker() {
109
+ if (!this.isFullObject) {
110
+ await this.reload();
111
+ }
112
+ return this.markers.some(marker => marker.type === 'credits');
113
+ }
99
114
  _loadData(data) {
100
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
101
115
  super._loadData(data);
102
116
  this.art = data.art;
103
117
  this.audienceRating = data.audienceRating;
@@ -107,45 +121,42 @@ class Movie extends Video {
107
121
  this.duration = data.duration;
108
122
  this.guid = data.guid;
109
123
  this.originalTitle = data.originalTitle;
110
- this.originallyAvailableAt = new Date(data.originallyAvailableAt);
124
+ this.originallyAvailableAt = data.originallyAvailableAt;
111
125
  this.primaryExtraKey = data.primaryExtraKey;
112
126
  this.rating = data.rating;
113
127
  this.ratingImage = data.ratingImage;
114
128
  this.studio = data.studio;
115
129
  this.tagline = data.tagline;
116
130
  this.userRating = data.userRating;
117
- this.viewOffset = (_a = data.viewOffset) !== null && _a !== void 0 ? _a : 0;
131
+ this.viewOffset = data.viewOffset ?? 0;
118
132
  this.year = data.year;
119
133
  this.librarySectionID = data.librarySectionID;
120
- this.directors =
121
- (_c = (_b = data.Director) === null || _b === void 0 ? void 0 : _b.map(data => new media_1.Director(this.server, data, undefined, this))) !== null && _c !== void 0 ? _c : [];
122
- this.countries =
123
- (_e = (_d = data.Country) === null || _d === void 0 ? void 0 : _d.map(data => new media_1.Country(this.server, data, undefined, this))) !== null && _e !== void 0 ? _e : [];
124
- this.writers = (_g = (_f = data.Writer) === null || _f === void 0 ? void 0 : _f.map(data => new media_1.Writer(this.server, data, undefined, this))) !== null && _g !== void 0 ? _g : [];
134
+ this.directors = data.Director?.map(d => new Director(this.server, d, undefined, this)) ?? [];
135
+ this.countries = data.Country?.map(d => new Country(this.server, d, undefined, this)) ?? [];
136
+ this.writers = data.Writer?.map(d => new Writer(this.server, d, undefined, this)) ?? [];
125
137
  this.collections =
126
- (_j = (_h = data.Collection) === null || _h === void 0 ? void 0 : _h.map(data => new media_1.Collection(this.server, data, undefined, this))) !== null && _j !== void 0 ? _j : [];
127
- this.roles = (_l = (_k = data.Role) === null || _k === void 0 ? void 0 : _k.map(data => new media_1.Role(this.server, data, undefined, this))) !== null && _l !== void 0 ? _l : [];
128
- this.similar = (_o = (_m = data.Similar) === null || _m === void 0 ? void 0 : _m.map(data => new media_1.Similar(this.server, data, undefined, this))) !== null && _o !== void 0 ? _o : [];
129
- this.genres = (_q = (_p = data.Genre) === null || _p === void 0 ? void 0 : _p.map(data => new media_1.Genre(this.server, data, undefined, this))) !== null && _q !== void 0 ? _q : [];
130
- this.producers =
131
- (_s = (_r = data.Producer) === null || _r === void 0 ? void 0 : _r.map(data => new media_1.Producer(this.server, data, undefined, this))) !== null && _s !== void 0 ? _s : [];
132
- this.media = (_u = (_t = data.Media) === null || _t === void 0 ? void 0 : _t.map(data => new media_1.Media(this.server, data, undefined, this))) !== null && _u !== void 0 ? _u : [];
138
+ data.Collection?.map(d => new Collection(this.server, d, undefined, this)) ?? [];
139
+ this.roles = data.Role?.map(d => new Role(this.server, d, undefined, this)) ?? [];
140
+ this.similar = data.Similar?.map(d => new Similar(this.server, d, undefined, this)) ?? [];
141
+ this.genres = data.Genre?.map(d => new Genre(this.server, d, undefined, this)) ?? [];
142
+ this.producers = data.Producer?.map(d => new Producer(this.server, d, undefined, this)) ?? [];
143
+ this.media = data.Media?.map(d => new Media(this.server, d, undefined, this)) ?? [];
144
+ this.guids = data.Guid?.map(d => new Guid(this.server, d, undefined, this)) ?? [];
145
+ this.markers = data.Marker?.map(d => new Marker(this.server, d, undefined, this)) ?? [];
133
146
  }
134
147
  _loadFullData(data) {
135
- var _a, _b, _c;
136
148
  const metadata = data.Metadata[0];
137
149
  this._loadData(metadata);
138
150
  this.librarySectionID = metadata.librarySectionID;
139
- this.chapters = (_a = metadata.Chapter) === null || _a === void 0 ? void 0 : _a.map(chapter => new media_1.Chapter(this.server, chapter));
151
+ this.chapters = metadata.Chapter?.map(chapter => new Chapter(this.server, chapter));
140
152
  this.collections =
141
- (_c = (_b = metadata.Collection) === null || _b === void 0 ? void 0 : _b.map(collection => new media_1.Collection(this.server, collection, undefined, this))) !== null && _c !== void 0 ? _c : [];
153
+ metadata.Collection?.map(collection => new Collection(this.server, collection, undefined, this)) ?? [];
142
154
  }
143
155
  }
144
- exports.Movie = Movie;
145
156
  /**
146
157
  * Represents a single Show (including all seasons and episodes).
147
158
  */
148
- class Show extends Video {
159
+ export class Show extends Video {
149
160
  constructor() {
150
161
  super(...arguments);
151
162
  this.TAG = 'Directory';
@@ -176,17 +187,16 @@ class Show extends Video {
176
187
  // }
177
188
  async seasons(query) {
178
189
  const key = `/library/metadata/${this.ratingKey}/children?excludeAllLeaves=1`;
179
- return baseFunctionality_1.fetchItems(this.server, key, query, Season, this);
190
+ return fetchItems(this.server, key, query, Season, this);
180
191
  }
181
192
  async episodes(query) {
182
193
  const key = `/library/metadata/${this.ratingKey}/allLeaves`;
183
- const episodes = await baseFunctionality_1.fetchItems(this.server, key, query);
194
+ const episodes = await fetchItems(this.server, key, query);
184
195
  return episodes.map(episode => new Episode(this.server, episode, key, this));
185
196
  }
186
197
  _loadData(data) {
187
- var _a, _b, _c, _d, _e;
188
198
  super._loadData(data);
189
- this.key = ((_a = data.key) !== null && _a !== void 0 ? _a : '').replace('/children', '');
199
+ this.key = (data.key ?? '').replace('/children', '');
190
200
  this.art = data.art;
191
201
  this.banner = data.banner;
192
202
  this.childCount = data.childCount;
@@ -202,18 +212,17 @@ class Show extends Video {
202
212
  this.theme = data.theme;
203
213
  this.viewedLeafCount = data.viewedLeafCount;
204
214
  this.year = data.year;
205
- this.genres = (_c = (_b = data.Genre) === null || _b === void 0 ? void 0 : _b.map(genre => new media_1.Genre(this.server, genre))) !== null && _c !== void 0 ? _c : [];
206
- this.roles = (_e = (_d = data.Role) === null || _d === void 0 ? void 0 : _d.map(role => new media_1.Role(this.server, role))) !== null && _e !== void 0 ? _e : [];
215
+ this.genres = data.Genre?.map(genre => new Genre(this.server, genre)) ?? [];
216
+ this.roles = data.Role?.map(role => new Role(this.server, role)) ?? [];
207
217
  }
208
218
  _loadFullData(data) {
209
- this._loadData(data);
219
+ this._loadData(data.Metadata[0]);
210
220
  }
211
221
  }
212
- exports.Show = Show;
213
222
  /**
214
223
  * Represents a single Show Season (including all episodes).
215
224
  */
216
- class Season extends Video {
225
+ export class Season extends Video {
217
226
  constructor() {
218
227
  super(...arguments);
219
228
  this.TAG = 'Directory';
@@ -233,7 +242,7 @@ class Season extends Video {
233
242
  */
234
243
  async episodes(query) {
235
244
  const key = `/library/metadata/${this.ratingKey}/children`;
236
- const episodes = await baseFunctionality_1.fetchItems(this.server, key, query);
245
+ const episodes = await fetchItems(this.server, key, query);
237
246
  return episodes.map(episode => new Episode(this.server, episode, key, this));
238
247
  }
239
248
  _loadData(data) {
@@ -247,34 +256,13 @@ class Season extends Video {
247
256
  this._loadData(data);
248
257
  }
249
258
  }
250
- exports.Season = Season;
251
- class Episode extends Video {
259
+ export class Episode extends Video {
252
260
  constructor() {
253
261
  super(...arguments);
254
262
  this.TYPE = 'episode';
255
263
  this.METADATA_TYPE = 'episode';
256
- this._INCLUDES = {
257
- checkFiles: 1,
258
- includeAllConcerts: 1,
259
- includeBandwidths: 1,
260
- includeChapters: 1,
261
- includeChildren: 1,
262
- includeConcerts: 1,
263
- includeExternalMedia: 1,
264
- includeExtras: 1,
265
- includeFields: 'thumbBlurHash,artBlurHash',
266
- includeGeolocation: 1,
267
- includeLoudnessRamps: 1,
268
- includeMarkers: 1,
269
- includeOnDeck: 1,
270
- includePopularLeaves: 1,
271
- includePreferences: 1,
272
- includeRelated: 1,
273
- includeRelatedCount: 1,
274
- includeReviews: 1,
275
- includeStations: 1,
276
- };
277
264
  }
265
+ static { this.TAG = 'Video'; }
278
266
  /**
279
267
  * Returns this episodes season number.
280
268
  */
@@ -291,16 +279,15 @@ class Episode extends Video {
291
279
  return `s${seasonNumber}e${episodeNumber}`;
292
280
  }
293
281
  async season() {
294
- const data = await baseFunctionality_1.fetchItem(this.server, this.parentKey);
282
+ const data = await fetchItem(this.server, this.parentKey);
295
283
  return new Season(this.server, data, this.parentKey, this);
296
284
  }
297
285
  async show() {
298
- const data = await baseFunctionality_1.fetchItem(this.server, this.grandparentKey);
286
+ const data = await fetchItem(this.server, this.grandparentKey);
299
287
  return new Show(this.server, data, this.grandparentKey, this);
300
288
  }
301
289
  locations() {
302
- var _a, _b;
303
- const parts = ((_b = (_a = this.media) === null || _a === void 0 ? void 0 : _a.map(media => media.parts)) !== null && _b !== void 0 ? _b : []).flat();
290
+ const parts = (this.media?.map(media => media.parts) ?? []).flat();
304
291
  return parts.map(part => part.file);
305
292
  }
306
293
  /**
@@ -312,8 +299,16 @@ class Episode extends Video {
312
299
  }
313
300
  return this.markers.some(marker => marker.type === 'intro');
314
301
  }
302
+ /**
303
+ * Returns True if this episode has a credits marker
304
+ */
305
+ async hasCreditsMarker() {
306
+ if (!this.isFullObject) {
307
+ await this.reload();
308
+ }
309
+ return this.markers.some(marker => marker.type === 'credits');
310
+ }
315
311
  _loadData(data) {
316
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
317
312
  super._loadData(data);
318
313
  this.key = (data.key || '').replace('/children', '');
319
314
  this.title = data.title;
@@ -339,18 +334,40 @@ class Episode extends Video {
339
334
  this.rating = data.rating;
340
335
  this.viewOffset = data.viewOffset;
341
336
  this.year = data.year;
342
- this.directors =
343
- (_b = (_a = data.Director) === null || _a === void 0 ? void 0 : _a.map(data => new media_1.Director(this.server, data, undefined, this))) !== null && _b !== void 0 ? _b : [];
344
- this.writers = (_d = (_c = data.Writer) === null || _c === void 0 ? void 0 : _c.map(data => new media_1.Writer(this.server, data, undefined, this))) !== null && _d !== void 0 ? _d : [];
345
- this.media = (_e = data.Media) === null || _e === void 0 ? void 0 : _e.map(data => new media_1.Media(this.server, data, undefined, this));
337
+ this.directors = data.Director?.map(d => new Director(this.server, d, undefined, this)) ?? [];
338
+ this.writers = data.Writer?.map(d => new Writer(this.server, d, undefined, this)) ?? [];
339
+ this.media = data.Media?.map(d => new Media(this.server, d, undefined, this));
346
340
  this.collections =
347
- (_g = (_f = data.Collection) === null || _f === void 0 ? void 0 : _f.map(data => new media_1.Collection(this.server, data, undefined, this))) !== null && _g !== void 0 ? _g : [];
348
- this.chapters =
349
- (_j = (_h = data.Chapter) === null || _h === void 0 ? void 0 : _h.map(data => new media_1.Chapter(this.server, data, undefined, this))) !== null && _j !== void 0 ? _j : [];
350
- this.markers = (_l = (_k = data.Marker) === null || _k === void 0 ? void 0 : _k.map(data => new media_1.Marker(this.server, data, undefined, this))) !== null && _l !== void 0 ? _l : [];
341
+ data.Collection?.map(d => new Collection(this.server, d, undefined, this)) ?? [];
342
+ this.chapters = data.Chapter?.map(d => new Chapter(this.server, d, undefined, this)) ?? [];
343
+ this.markers = data.Marker?.map(d => new Marker(this.server, d, undefined, this)) ?? [];
344
+ }
345
+ _loadFullData(data) {
346
+ this._loadData(data.Metadata[0]);
347
+ }
348
+ }
349
+ export class Clip extends Video {
350
+ constructor() {
351
+ super(...arguments);
352
+ this.TYPE = 'clip';
353
+ this.METADATA_TYPE = 'clip';
354
+ }
355
+ static { this.TAG = 'Video'; }
356
+ _loadData(data) {
357
+ super._loadData(data);
358
+ }
359
+ _loadFullData(data) {
360
+ this._loadData(data.Metadata[0]);
361
+ }
362
+ }
363
+ /**
364
+ * Represents a single Extra (trailer, behindTheScenes, etc).
365
+ */
366
+ export class Extra extends Clip {
367
+ _loadData(data) {
368
+ super._loadData(data);
351
369
  }
352
370
  _loadFullData(data) {
353
371
  this._loadData(data.Metadata[0]);
354
372
  }
355
373
  }
356
- Episode.TAG = 'Video';
@@ -113,7 +113,7 @@ export interface ChapterData extends MediaTagData {
113
113
  filter?: string;
114
114
  }
115
115
  export interface MarkerData extends MediaTagData {
116
- type: 'intro';
116
+ type: 'intro' | 'credits';
117
117
  startTimeOffset: number;
118
118
  endTimeOffset: number;
119
119
  }
@@ -0,0 +1,6 @@
1
+ export var ChapterSource;
2
+ (function (ChapterSource) {
3
+ ChapterSource["Agent"] = "agent";
4
+ ChapterSource["Media"] = "media";
5
+ ChapterSource["Mixed"] = "mixed";
6
+ })(ChapterSource || (ChapterSource = {}));