@ctrl/plex 3.7.0 → 3.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.
@@ -1,3 +1,4 @@
1
+ import type { Section } from '../library.js';
1
2
  import { SearchResult } from '../search.js';
2
3
  import { PlexObject } from './plexObject.js';
3
4
  export declare abstract class PartialPlexObject extends PlexObject {
@@ -100,7 +101,7 @@ export declare abstract class PartialPlexObject extends PlexObject {
100
101
  * @param mindate Min datetime to return results from.
101
102
  */
102
103
  history(maxresults?: number, mindate?: Date): Promise<import("../server.types.js").HistoryMetadatum[]>;
103
- section(): Promise<import("../library.js").Section>;
104
+ section(): Promise<Section>;
104
105
  /**
105
106
  * Delete a media element. This has to be enabled under settings > server > library in plex webui.
106
107
  */
@@ -1,3 +1,5 @@
1
+ import type { PlayQueue as PlayQueueType } from '../playqueue.js';
2
+ import type { CreatePlayQueueOptions } from '../playqueue.types.js';
1
3
  import { PartialPlexObject } from './partialPlexObject.js';
2
4
  /**
3
5
  * This is a general place to store functions specific to media that is Playable.
@@ -19,4 +21,11 @@ export declare abstract class Playable extends PartialPlexObject {
19
21
  viewedAt: any;
20
22
  /** (int): Playlist item ID (only populated for :class:`~plexapi.playlist.Playlist` items). */
21
23
  playlistItemID?: number;
24
+ /**
25
+ * Returns a new PlayQueue from this media item.
26
+ *
27
+ * @param options Options for creating the PlayQueue
28
+ * @returns New PlayQueue instance
29
+ */
30
+ createPlayQueue(options?: CreatePlayQueueOptions): Promise<PlayQueueType>;
22
31
  }
@@ -1,3 +1,4 @@
1
+ import { PlayQueue } from '../playqueue.js';
1
2
  import { PartialPlexObject } from './partialPlexObject.js';
2
3
  /**
3
4
  * This is a general place to store functions specific to media that is Playable.
@@ -5,4 +6,13 @@ import { PartialPlexObject } from './partialPlexObject.js';
5
6
  * Albums which are all not playable.
6
7
  */
7
8
  export class Playable extends PartialPlexObject {
9
+ /**
10
+ * Returns a new PlayQueue from this media item.
11
+ *
12
+ * @param options Options for creating the PlayQueue
13
+ * @returns New PlayQueue instance
14
+ */
15
+ async createPlayQueue(options = {}) {
16
+ return PlayQueue.create(this.server, this, options);
17
+ }
8
18
  }
@@ -6,7 +6,9 @@ export * from './library.js';
6
6
  export * from './media.js';
7
7
  export * from './myplex.js';
8
8
  export * from './playlist.js';
9
+ export * from './playqueue.js';
9
10
  export * from './server.js';
10
11
  export * from './video.js';
12
+ export * from './audio.js';
11
13
  export { X_PLEX_IDENTIFIER } from './config.js';
12
14
  export { SearchResult, Agent, SEARCHTYPES } from './search.js';
package/dist/src/index.js CHANGED
@@ -5,7 +5,9 @@ export * from './library.js';
5
5
  export * from './media.js';
6
6
  export * from './myplex.js';
7
7
  export * from './playlist.js';
8
+ export * from './playqueue.js';
8
9
  export * from './server.js';
9
10
  export * from './video.js';
11
+ export * from './audio.js';
10
12
  export { X_PLEX_IDENTIFIER } from './config.js';
11
13
  export { SearchResult, Agent, SEARCHTYPES } from './search.js';
@@ -1,13 +1,14 @@
1
1
  import type { Class } from 'type-fest';
2
2
  import { PartialPlexObject } from './base/partialPlexObject.js';
3
3
  import { PlexObject } from './base/plexObject.js';
4
+ import { Album, Artist, Track } from './audio.js';
4
5
  import type { CollectionData, LibraryRootResponse, Location, SectionsDirectory } from './library.types.js';
5
6
  import { Playlist } from './playlist.js';
6
7
  import { type Agent, type SEARCHTYPES } from './search.js';
7
8
  import type { SearchResult } from './search.types.js';
8
9
  import type { PlexServer } from './server.js';
9
- import { Movie, Show, type VideoType } from './video.js';
10
- export type Section = MovieSection | ShowSection;
10
+ import { Movie, Show } from './video.js';
11
+ export type Section = MovieSection | ShowSection | MusicSection;
11
12
  export declare class Library {
12
13
  private readonly server;
13
14
  static key: string;
@@ -198,7 +199,7 @@ export declare class Library {
198
199
  }
199
200
  type Libtype = keyof typeof SEARCHTYPES;
200
201
  interface SearchArgs {
201
- [key: string]: number | string | boolean | string[];
202
+ [key: string]: number | string | boolean | string[] | Record<string, string | number | boolean>;
202
203
  /** General string query to search for. Partial string matches are allowed. */
203
204
  title: string;
204
205
  /** A string of comma separated sort fields or a list of sort fields in the format ``column:dir``. */
@@ -221,11 +222,14 @@ interface SearchArgs {
221
222
  * Return only results that have duplicates.
222
223
  */
223
224
  duplicate: number;
225
+ /** Advanced filters object used by music searches. */
226
+ filters?: Record<string, string | number | boolean>;
224
227
  }
228
+ export type SectionType = Movie | Show | Artist | Album | Track;
225
229
  /**
226
230
  * Base class for a single library section.
227
231
  */
228
- export declare abstract class LibrarySection<SectionVideoType = VideoType> extends PlexObject {
232
+ export declare abstract class LibrarySection<SType = SectionType> extends PlexObject {
229
233
  static ALLOWED_FILTERS: string[];
230
234
  static ALLOWED_SORT: string[];
231
235
  static BOOLEAN_FILTERS: string[];
@@ -261,16 +265,16 @@ export declare abstract class LibrarySection<SectionVideoType = VideoType> exten
261
265
  /** Unique id for this section (32258d7c-3e6c-4ac5-98ad-bad7a3b78c63) */
262
266
  uuid: string;
263
267
  CONTENT_TYPE: string;
264
- readonly VIDEO_TYPE: Class<SectionVideoType>;
268
+ readonly SECTION_TYPE: Class<SType>;
265
269
  _filterTypes?: FilteringType[];
266
270
  _fieldTypes?: FilteringFieldType[];
267
- all(sort?: string): Promise<SectionVideoType[]>;
271
+ all(sort?: string): Promise<SType[]>;
268
272
  agents(): Promise<Agent[]>;
269
273
  /**
270
274
  * @param title Title of the item to return.
271
275
  * @returns the media item with the specified title.
272
276
  */
273
- get(title: string): Promise<SectionVideoType>;
277
+ get(title: string): Promise<SType>;
274
278
  /**
275
279
  * Returns the media item with the specified external IMDB, TMDB, or TVDB ID.
276
280
  * Note: This search uses a PlexAPI operator so performance may be slow. All items from the
@@ -296,7 +300,7 @@ export declare abstract class LibrarySection<SectionVideoType = VideoType> exten
296
300
  * result2 = guidLookup['tmdb://1399']
297
301
  * result3 = guidLookup['tvdb://121361']
298
302
  */
299
- getGuid(guid: string): Promise<SectionVideoType>;
303
+ getGuid(guid: string): Promise<SType>;
300
304
  /**
301
305
  * Returns the Plex Web URL for the library.
302
306
  *
@@ -316,7 +320,7 @@ export declare abstract class LibrarySection<SectionVideoType = VideoType> exten
316
320
  * TLDR: This is untested but seems to work. Use library section search when you can.
317
321
  * @param args Search using a number of different attributes
318
322
  */
319
- search<T = SectionVideoType>(args?: Partial<SearchArgs>, Cls?: any): Promise<T[]>;
323
+ search<C = SType>(args?: Partial<SearchArgs>, Cls?: Class<C>): Promise<C[]>;
320
324
  /**
321
325
  * Run an analysis on all of the items in this library section.
322
326
  * See :func:`~plexapi.base.PlexPartialObject.analyze` for more details.
@@ -361,7 +365,7 @@ export declare abstract class LibrarySection<SectionVideoType = VideoType> exten
361
365
  * Returns a list of playlists from this library section.
362
366
  */
363
367
  playlists(): Promise<Playlist[]>;
364
- collections(args?: Record<string, number | string | boolean>): Promise<Collections<SectionVideoType>[]>;
368
+ collections(args?: Record<string, number | string | boolean>): Promise<Collections<SType>[]>;
365
369
  /**
366
370
  * Returns a list of available Folders for this library section.
367
371
  */
@@ -405,7 +409,7 @@ export declare class MovieSection extends LibrarySection<Movie> {
405
409
  static TAG: string;
406
410
  METADATA_TYPE: string;
407
411
  CONTENT_TYPE: string;
408
- readonly VIDEO_TYPE: typeof Movie;
412
+ readonly SECTION_TYPE: typeof Movie;
409
413
  }
410
414
  export declare class ShowSection extends LibrarySection<Show> {
411
415
  static TYPE: string;
@@ -414,7 +418,7 @@ export declare class ShowSection extends LibrarySection<Show> {
414
418
  static TAG: string;
415
419
  METADATA_TYPE: string;
416
420
  CONTENT_TYPE: string;
417
- readonly VIDEO_TYPE: typeof Show;
421
+ readonly SECTION_TYPE: typeof Show;
418
422
  /**
419
423
  * Returns a list of recently added episodes from this library section.
420
424
  *
@@ -422,6 +426,40 @@ export declare class ShowSection extends LibrarySection<Show> {
422
426
  */
423
427
  recentlyAdded(args: any, libtype?: string, maxresults?: number): Promise<Show[]>;
424
428
  }
429
+ export declare class MusicSection extends LibrarySection<Track> {
430
+ static TYPE: string;
431
+ static TAG: string;
432
+ METADATA_TYPE: string;
433
+ CONTENT_TYPE: string;
434
+ readonly SECTION_TYPE: typeof Track;
435
+ /** Returns a list of Album objects in this section. */
436
+ albums(): Promise<Album[]>;
437
+ /**
438
+ * Returns the music stations Hub for this section, if available.
439
+ * TODO: Investigate how to return actual station items (Playlists?) from the Hub.
440
+ */
441
+ stations(): Promise<Hub | undefined>;
442
+ /** Search for an artist. */
443
+ searchArtists(args?: Partial<SearchArgs>): Promise<Artist[]>;
444
+ /** Search for an album. */
445
+ searchAlbums(args?: Partial<SearchArgs>): Promise<Album[]>;
446
+ /** Search for a track. */
447
+ searchTracks(args?: Partial<SearchArgs>): Promise<Track[]>;
448
+ /** Returns a list of recently added artists from this library section. */
449
+ recentlyAddedArtists(maxresults?: number): Promise<Artist[]>;
450
+ /** Returns a list of recently added albums from this library section. */
451
+ recentlyAddedAlbums(maxresults?: number): Promise<Album[]>;
452
+ /** Returns a list of recently added tracks from this library section. */
453
+ recentlyAddedTracks(maxresults?: number): Promise<Track[]>;
454
+ /**
455
+ * Returns a list of tracks from this library section that are part of a sonic adventure.
456
+ * IDs should be of a track; other IDs will return an empty list or an error.
457
+ * @param start The Track or ID of the first track in the sonic adventure.
458
+ * @param end The Track or ID of the last track in the sonic adventure.
459
+ * @returns A list of tracks that are part of a sonic adventure.
460
+ */
461
+ sonicAdventure(start: Track | number, end: Track | number): Promise<Track[]>;
462
+ }
425
463
  /** Represents a single Hub (or category) in the PlexServer search */
426
464
  export declare class Hub extends PlexObject {
427
465
  static TAG: string;
@@ -446,7 +484,7 @@ export declare class Folder extends PlexObject {
446
484
  subfolders(): Promise<Folder[]>;
447
485
  protected _loadData(data: any): void;
448
486
  }
449
- export declare class Collections<CollectionVideoType = VideoType> extends PartialPlexObject {
487
+ export declare class Collections<CollectionVideoType = SectionType> extends PartialPlexObject {
450
488
  static TAG: string;
451
489
  TYPE: string;
452
490
  guid: string;
@@ -1,6 +1,7 @@
1
1
  import { URLSearchParams } from 'url';
2
2
  import { PartialPlexObject } from './base/partialPlexObject.js';
3
3
  import { PlexObject } from './base/plexObject.js';
4
+ import { Album, Artist, Track } from './audio.js';
4
5
  import { fetchItem, fetchItems, findItems } from './baseFunctionality.js';
5
6
  import { NotFound } from './exceptions.js';
6
7
  import { Playlist } from './playlist.js';
@@ -19,8 +20,11 @@ export class Library {
19
20
  const key = '/library/sections';
20
21
  const elems = await this.server.query(key);
21
22
  const sections = [];
23
+ if (!elems.MediaContainer.Directory) {
24
+ return sections;
25
+ }
22
26
  for (const elem of elems.MediaContainer.Directory) {
23
- for (const cls of [MovieSection, ShowSection]) {
27
+ for (const cls of [MovieSection, ShowSection, MusicSection]) {
24
28
  if (cls.TYPE === elem.type) {
25
29
  // eslint-disable-next-line new-cap
26
30
  const instance = new cls(this.server, elem, key);
@@ -281,7 +285,7 @@ export class LibrarySection extends PlexObject {
281
285
  sortStr = `?sort=${sort}`;
282
286
  }
283
287
  const key = `/library/sections/${this.key}/all${sortStr}`;
284
- const items = await fetchItems(this.server, key, undefined, this.VIDEO_TYPE, this);
288
+ const items = await fetchItems(this.server, key, undefined, this.SECTION_TYPE, this);
285
289
  return items;
286
290
  }
287
291
  async agents() {
@@ -294,7 +298,7 @@ export class LibrarySection extends PlexObject {
294
298
  async get(title) {
295
299
  const key = `/library/sections/${this.key}/all?includeGuids=1&title=${title}`;
296
300
  const data = await fetchItem(this.server, key, { title__iexact: title });
297
- return new this.VIDEO_TYPE(this.server, data, key, this);
301
+ return new this.SECTION_TYPE(this.server, data, key, this);
298
302
  }
299
303
  /**
300
304
  * Returns the media item with the specified external IMDB, TMDB, or TVDB ID.
@@ -355,7 +359,7 @@ export class LibrarySection extends PlexObject {
355
359
  * TLDR: This is untested but seems to work. Use library section search when you can.
356
360
  * @param args Search using a number of different attributes
357
361
  */
358
- async search(args = {}, Cls = this.VIDEO_TYPE) {
362
+ async search(args = {}, Cls) {
359
363
  const params = new URLSearchParams();
360
364
  for (const [key, value] of Object.entries(args)) {
361
365
  let strValue;
@@ -374,7 +378,8 @@ export class LibrarySection extends PlexObject {
374
378
  params.append('type', searchType(args.libtype).toString());
375
379
  }
376
380
  const key = `/library/sections/${this.key}/all?${params.toString()}`;
377
- const data = await fetchItems(this.server, key, undefined, Cls, this);
381
+ const ClsToUse = Cls ?? this.SECTION_TYPE;
382
+ const data = await fetchItems(this.server, key, undefined, ClsToUse, this);
378
383
  return data;
379
384
  }
380
385
  /**
@@ -467,7 +472,7 @@ export class LibrarySection extends PlexObject {
467
472
  async collections(args = {}) {
468
473
  const collections = await this.search({ ...args, libtype: 'collection' }, Collections);
469
474
  collections.forEach(collection => {
470
- collection.VIDEO_TYPE = this.VIDEO_TYPE;
475
+ collection.VIDEO_TYPE = this.SECTION_TYPE;
471
476
  });
472
477
  return collections;
473
478
  }
@@ -573,7 +578,7 @@ export class MovieSection extends LibrarySection {
573
578
  super(...arguments);
574
579
  this.METADATA_TYPE = 'movie';
575
580
  this.CONTENT_TYPE = 'video';
576
- this.VIDEO_TYPE = Movie;
581
+ this.SECTION_TYPE = Movie;
577
582
  }
578
583
  static { this.TYPE = 'movie'; }
579
584
  static { this.ALLOWED_FILTERS = [
@@ -615,7 +620,7 @@ export class ShowSection extends LibrarySection {
615
620
  super(...arguments);
616
621
  this.METADATA_TYPE = 'episode';
617
622
  this.CONTENT_TYPE = 'video';
618
- this.VIDEO_TYPE = Show;
623
+ this.SECTION_TYPE = Show;
619
624
  }
620
625
  static { this.TYPE = 'show'; }
621
626
  static { this.ALLOWED_FILTERS = [
@@ -670,6 +675,66 @@ export class ShowSection extends LibrarySection {
670
675
  return this.search({ libtype, maxresults, sort: 'episode.addedAt:desc', ...args });
671
676
  }
672
677
  }
678
+ export class MusicSection extends LibrarySection {
679
+ constructor() {
680
+ super(...arguments);
681
+ this.METADATA_TYPE = 'track';
682
+ this.CONTENT_TYPE = 'audio';
683
+ this.SECTION_TYPE = Track;
684
+ }
685
+ static { this.TYPE = 'artist'; }
686
+ static { this.TAG = 'Directory'; }
687
+ /** Returns a list of Album objects in this section. */
688
+ async albums() {
689
+ const key = `/library/sections/${this.key}/albums`;
690
+ return fetchItems(this.server, key, undefined, Album, this);
691
+ }
692
+ /**
693
+ * Returns the music stations Hub for this section, if available.
694
+ * TODO: Investigate how to return actual station items (Playlists?) from the Hub.
695
+ */
696
+ async stations() {
697
+ const hubs = await this.hubs();
698
+ return hubs.find(hub => hub.hubIdentifier === 'hub.music.stations');
699
+ }
700
+ /** Search for an artist. */
701
+ async searchArtists(args = {}) {
702
+ return this.search({ ...args, libtype: 'artist' }, Artist);
703
+ }
704
+ /** Search for an album. */
705
+ async searchAlbums(args = {}) {
706
+ return this.search({ ...args, libtype: 'album' }, Album);
707
+ }
708
+ /** Search for a track. */
709
+ async searchTracks(args = {}) {
710
+ return this.search({ ...args, libtype: 'track' }, Track);
711
+ }
712
+ /** Returns a list of recently added artists from this library section. */
713
+ async recentlyAddedArtists(maxresults = 50) {
714
+ return this.search({ maxresults, sort: 'addedAt:desc', libtype: 'artist' }, Artist);
715
+ }
716
+ /** Returns a list of recently added albums from this library section. */
717
+ async recentlyAddedAlbums(maxresults = 50) {
718
+ return this.search({ maxresults, sort: 'addedAt:desc', libtype: 'album' }, Album);
719
+ }
720
+ /** Returns a list of recently added tracks from this library section. */
721
+ async recentlyAddedTracks(maxresults = 50) {
722
+ return this.search({ maxresults, sort: 'addedAt:desc', libtype: 'track' }, Track);
723
+ }
724
+ /**
725
+ * Returns a list of tracks from this library section that are part of a sonic adventure.
726
+ * IDs should be of a track; other IDs will return an empty list or an error.
727
+ * @param start The Track or ID of the first track in the sonic adventure.
728
+ * @param end The Track or ID of the last track in the sonic adventure.
729
+ * @returns A list of tracks that are part of a sonic adventure.
730
+ */
731
+ async sonicAdventure(start, end) {
732
+ const startID = typeof start === 'number' ? start : start.ratingKey;
733
+ const endID = typeof end === 'number' ? end : end.ratingKey;
734
+ const key = `/library/sections/${this.key}/computePath?startID=${startID}&endID=${endID}`;
735
+ return fetchItems(this.server, key, undefined, Track, this);
736
+ }
737
+ }
673
738
  /** Represents a single Hub (or category) in the PlexServer search */
674
739
  export class Hub extends PlexObject {
675
740
  static { this.TAG = 'Hub'; }
@@ -231,6 +231,26 @@ export declare class Collection extends MediaTag {
231
231
  static TAG: "Collection";
232
232
  FILTER: "collection";
233
233
  }
234
+ /** Represents a single Label media tag. */
235
+ export declare class Label extends MediaTag {
236
+ static TAG: "Label";
237
+ FILTER: "label";
238
+ }
239
+ /** Represents a single Style media tag. */
240
+ export declare class Style extends MediaTag {
241
+ static TAG: "Style";
242
+ FILTER: "style";
243
+ }
244
+ /** Represents a single Format media tag. */
245
+ export declare class Format extends MediaTag {
246
+ static TAG: "Format";
247
+ FILTER: "format";
248
+ }
249
+ /** Represents a single Subformat media tag. */
250
+ export declare class Subformat extends MediaTag {
251
+ static TAG: "Subformat";
252
+ FILTER: "subformat";
253
+ }
234
254
  export declare class Optimized extends PlexObject {
235
255
  static TAG: string;
236
256
  id: string;
@@ -380,4 +400,29 @@ export declare class AudioStream extends MediaPartStream {
380
400
  setSelected(): Promise<void>;
381
401
  protected _loadData(data: any): void;
382
402
  }
403
+ /** Represents a single Image media tag. */
404
+ export declare class Image extends PlexObject {
405
+ static TAG: "Image";
406
+ /** The alt text for the image. */
407
+ alt?: string;
408
+ /** The type of image (e.g. coverPoster, background, snapshot). */
409
+ type?: string;
410
+ /** The API URL (/library/metadata/<ratingKey>/thumb/<thumbid>). */
411
+ url?: string;
412
+ protected _loadData(data: any): void;
413
+ }
414
+ /** Represents a single Field. */
415
+ export declare class Field extends PlexObject {
416
+ static TAG: "Field";
417
+ /** True if the field is locked. */
418
+ locked: boolean;
419
+ /** The name of the field. */
420
+ name: string;
421
+ protected _loadData(data: any): void;
422
+ }
423
+ /** Represents a single Mood media tag. */
424
+ export declare class Mood extends MediaTag {
425
+ static TAG: "Mood";
426
+ FILTER: "mood";
427
+ }
383
428
  export {};
package/dist/src/media.js CHANGED
@@ -256,6 +256,38 @@ export class Collection extends MediaTag {
256
256
  }
257
257
  static { this.TAG = 'Collection'; }
258
258
  }
259
+ /** Represents a single Label media tag. */
260
+ export class Label extends MediaTag {
261
+ constructor() {
262
+ super(...arguments);
263
+ this.FILTER = 'label';
264
+ }
265
+ static { this.TAG = 'Label'; }
266
+ }
267
+ /** Represents a single Style media tag. */
268
+ export class Style extends MediaTag {
269
+ constructor() {
270
+ super(...arguments);
271
+ this.FILTER = 'style';
272
+ }
273
+ static { this.TAG = 'Style'; }
274
+ }
275
+ /** Represents a single Format media tag. */
276
+ export class Format extends MediaTag {
277
+ constructor() {
278
+ super(...arguments);
279
+ this.FILTER = 'format';
280
+ }
281
+ static { this.TAG = 'Format'; }
282
+ }
283
+ /** Represents a single Subformat media tag. */
284
+ export class Subformat extends MediaTag {
285
+ constructor() {
286
+ super(...arguments);
287
+ this.FILTER = 'subformat';
288
+ }
289
+ static { this.TAG = 'Subformat'; }
290
+ }
259
291
  export class Optimized extends PlexObject {
260
292
  static { this.TAG = 'Item'; }
261
293
  // TODO: Implement items()
@@ -402,3 +434,30 @@ export class AudioStream extends MediaPartStream {
402
434
  this.startRamp = data.startRamp;
403
435
  }
404
436
  }
437
+ /** Represents a single Image media tag. */
438
+ export class Image extends PlexObject {
439
+ static { this.TAG = 'Image'; }
440
+ _loadData(data) {
441
+ this.alt = data.alt;
442
+ this.type = data.type;
443
+ // Assuming server.url is needed to make this a complete URL
444
+ this.url = data.url ? this.server.url(data.url, true)?.toString() : undefined;
445
+ }
446
+ }
447
+ /** Represents a single Field. */
448
+ export class Field extends PlexObject {
449
+ static { this.TAG = 'Field'; }
450
+ _loadData(data) {
451
+ // Convert potential string '1' or '0' to boolean
452
+ this.locked = data.locked === '1' || data.locked === true;
453
+ this.name = data.name;
454
+ }
455
+ }
456
+ /** Represents a single Mood media tag. */
457
+ export class Mood extends MediaTag {
458
+ constructor() {
459
+ super(...arguments);
460
+ this.FILTER = 'mood';
461
+ }
462
+ static { this.TAG = 'Mood'; }
463
+ }
@@ -110,12 +110,14 @@ export class MyPlexAccount {
110
110
  if (this.token) {
111
111
  Object.defineProperty(this, 'token', {
112
112
  enumerable: false,
113
+ configurable: true,
113
114
  value: this.token,
114
115
  });
115
116
  }
116
117
  if (this.password) {
117
118
  Object.defineProperty(this, 'password', {
118
119
  enumerable: false,
120
+ configurable: true,
119
121
  value: this.password,
120
122
  });
121
123
  }
@@ -249,6 +251,7 @@ export class MyPlexAccount {
249
251
  // Attempt to prevent token from being logged accidentally
250
252
  Object.defineProperty(this, 'token', {
251
253
  enumerable: false,
254
+ configurable: true,
252
255
  value: user.authToken,
253
256
  });
254
257
  this.authenticationToken = this.token;
@@ -406,6 +409,7 @@ export class MyPlexDevice extends PlexObject {
406
409
  // Attempt to prevent token from being logged accidentally
407
410
  Object.defineProperty(this, 'token', {
408
411
  enumerable: false,
412
+ configurable: true,
409
413
  value: data.$.token,
410
414
  });
411
415
  this.screenResolution = data.$.screenResolution;
@@ -1,13 +1,13 @@
1
1
  import { Playable } from './base/playable.js';
2
- import type { Section } from './library.js';
2
+ import type { Section, SectionType } from './library.js';
3
3
  import type { PlaylistResponse } from './playlist.types.js';
4
4
  import type { PlexServer } from './server.js';
5
- import { Episode, Movie, type VideoType } from './video.js';
5
+ import { Episode, Movie } from './video.js';
6
6
  interface CreateRegularPlaylistOptions {
7
7
  /** True to create a smart playlist */
8
8
  smart?: false;
9
9
  /** Regular playlists only */
10
- items?: VideoType[];
10
+ items?: SectionType[];
11
11
  }
12
12
  interface CreateSmartPlaylistOptions {
13
13
  /** True to create a smart playlist */
@@ -0,0 +1,105 @@
1
+ import type { Playable } from './base/playable.js';
2
+ import { PlexObject } from './base/plexObject.js';
3
+ import type { Playlist } from './playlist.js';
4
+ import type { AddPlayQueueItemOptions, CreatePlayQueueOptions, GetPlayQueueOptions, MovePlayQueueItemOptions, PlayQueueResponse } from './playqueue.types.js';
5
+ import type { PlexServer } from './server.js';
6
+ /**
7
+ * Control a PlayQueue.
8
+ *
9
+ * A PlayQueue is a linear list of media items that can be played in sequence.
10
+ * It represents the current playback queue and supports operations like adding,
11
+ * removing, and reordering items.
12
+ */
13
+ export declare class PlayQueue extends PlexObject {
14
+ static TAG: string;
15
+ static TYPE: string;
16
+ /** PlayQueue identifier */
17
+ identifier: string;
18
+ /** Media tag prefix path */
19
+ mediaTagPrefix: string;
20
+ /** Media tag version number */
21
+ mediaTagVersion: number;
22
+ /** Unique ID of the PlayQueue */
23
+ playQueueID: number;
24
+ /** ID of the last added item, defines where "Up Next" region starts */
25
+ playQueueLastAddedItemID?: number;
26
+ /** The queue item ID of the currently selected item */
27
+ playQueueSelectedItemID: number;
28
+ /** The offset of the selected item in the PlayQueue */
29
+ playQueueSelectedItemOffset: number;
30
+ /** ID of the currently selected item, matches ratingKey */
31
+ playQueueSelectedMetadataItemID: number;
32
+ /** True if the PlayQueue is shuffled */
33
+ playQueueShuffled: boolean;
34
+ /** Original URI used to create the PlayQueue */
35
+ playQueueSourceURI: string;
36
+ /** Total number of items in the PlayQueue */
37
+ playQueueTotalCount: number;
38
+ /** Version of the PlayQueue, increments on changes */
39
+ playQueueVersion: number;
40
+ /** Total size of the PlayQueue (alias for playQueueTotalCount) */
41
+ size: number;
42
+ /** Media object for the currently selected item */
43
+ selectedItem?: Playable;
44
+ /** Cache of PlayQueue items */
45
+ private _items;
46
+ /** Raw data from server */
47
+ private _data;
48
+ /**
49
+ * Retrieve an existing PlayQueue by identifier.
50
+ */
51
+ static get(server: PlexServer, playQueueID: number, options?: GetPlayQueueOptions): Promise<PlayQueue>;
52
+ /**
53
+ * Create and return a new PlayQueue.
54
+ */
55
+ static create(server: PlexServer, items: Playable | Playable[] | Playlist, options?: CreatePlayQueueOptions): Promise<PlayQueue>;
56
+ /**
57
+ * Create and return a new PlayQueue from a station key.
58
+ * This is a convenience method for radio stations.
59
+ */
60
+ static fromStationKey(server: PlexServer, key: string): Promise<PlayQueue>;
61
+ /**
62
+ * Get items in the PlayQueue.
63
+ */
64
+ get items(): Playable[];
65
+ /**
66
+ * Get item at specific index.
67
+ */
68
+ getItem(index: number): Playable | null;
69
+ /**
70
+ * Get the length of the PlayQueue.
71
+ */
72
+ get length(): number;
73
+ /**
74
+ * Check if the PlayQueue contains the provided media item.
75
+ */
76
+ contains(media: Playable): boolean;
77
+ /**
78
+ * Get a similar object from this PlayQueue.
79
+ * Useful for looking up playQueueItemIDs using items from the Library.
80
+ */
81
+ getQueueItem(item: Playable): Playable;
82
+ /**
83
+ * Append an item to the "Up Next" section of the PlayQueue.
84
+ */
85
+ addItem(item: Playable | Playlist, options?: AddPlayQueueItemOptions): Promise<PlayQueue>;
86
+ /**
87
+ * Move an item to the beginning of the PlayQueue.
88
+ * If 'after' is provided, the item will be placed immediately after the specified item.
89
+ */
90
+ moveItem(item: Playable, options?: MovePlayQueueItemOptions): Promise<PlayQueue>;
91
+ /**
92
+ * Remove an item from the PlayQueue.
93
+ */
94
+ removeItem(item: Playable, refresh?: boolean): Promise<PlayQueue>;
95
+ /**
96
+ * Remove all items from the PlayQueue.
97
+ */
98
+ clear(): Promise<PlayQueue>;
99
+ /**
100
+ * Refresh the PlayQueue from the Plex server.
101
+ */
102
+ refresh(): Promise<void>;
103
+ protected _loadData(data: PlayQueueResponse): void;
104
+ private _invalidateCacheAndLoadData;
105
+ }