@ctrl/plex 3.9.2 → 3.11.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.
@@ -17,6 +17,13 @@ import { Settings } from './settings.js';
17
17
  * can also create an PlexServer instance from :class:`~plexapi.myplex.MyPlexAccount`.
18
18
  */
19
19
  export class PlexServer {
20
+ baseurl;
21
+ token;
22
+ timeout;
23
+ key = '/';
24
+ _library;
25
+ _settings;
26
+ _myPlexAccount;
20
27
  constructor(baseurl, token,
21
28
  /**
22
29
  * Default request timeout in milliseconds.
@@ -26,7 +33,6 @@ export class PlexServer {
26
33
  this.baseurl = baseurl;
27
34
  this.token = token;
28
35
  this.timeout = timeout;
29
- this.key = '/';
30
36
  }
31
37
  async agents(mediaType) {
32
38
  let key = '/system/agents';
@@ -143,7 +149,7 @@ export class PlexServer {
143
149
  args.librarySectionID = librarySectionId.toString();
144
150
  }
145
151
  if (mindate !== undefined) {
146
- args['viewedAt>'] = mindate.getTime().toString();
152
+ args['viewedAt>'] = Math.floor(mindate.getTime() / 1000).toString();
147
153
  }
148
154
  args['X-Plex-Container-Start'] = '0';
149
155
  args['X-Plex-Container-Size'] = Math.min(X_PLEX_CONTAINER_SIZE, maxresults).toString();
@@ -151,14 +157,18 @@ export class PlexServer {
151
157
  let key = '/status/sessions/history/all?' + new URLSearchParams(args).toString();
152
158
  let raw = await this.query(key);
153
159
  const totalResults = raw.MediaContainer.totalSize;
154
- results = results.concat(raw.MediaContainer.Metadata);
160
+ // Filter out null/undefined items from the metadata
161
+ const validMetadata = raw.MediaContainer.Metadata?.filter(Boolean) ?? [];
162
+ results = results.concat(validMetadata);
155
163
  while (results.length <= totalResults &&
156
164
  X_PLEX_CONTAINER_SIZE === raw.MediaContainer.size &&
157
165
  maxresults > results.length) {
158
166
  args['X-Plex-Container-Start'] = (Number(args['X-Plex-Container-Start']) + Number(args['X-Plex-Container-Size'])).toString();
159
167
  key = '/status/sessions/history/all?' + new URLSearchParams(args).toString();
160
168
  raw = await this.query(key);
161
- results = results.concat(raw.MediaContainer.Metadata);
169
+ // Filter out null/undefined items from the metadata
170
+ const validMetadata = raw.MediaContainer.Metadata?.filter(item => item != null) ?? [];
171
+ results = results.concat(validMetadata);
162
172
  }
163
173
  return results;
164
174
  }
@@ -65,10 +65,12 @@ export interface HistoryMediaContainer {
65
65
  size: number;
66
66
  totalSize: number;
67
67
  offset: number;
68
- Metadata: HistoryMetadatum[];
68
+ Metadata?: Array<HistoryResult | null | undefined>;
69
69
  }
70
- export interface HistoryMetadatum {
70
+ export interface HistoryResult {
71
71
  key: string;
72
+ ratingKey: string;
73
+ historyKey: string;
72
74
  parentKey?: string;
73
75
  grandparentKey?: string;
74
76
  title: string;
@@ -84,6 +86,7 @@ export interface HistoryMetadatum {
84
86
  viewedAt: number;
85
87
  accountID: number;
86
88
  deviceID: number;
89
+ librarySectionID: string;
87
90
  }
88
91
  export interface PlaylistMediaContainer {
89
92
  size: number;
@@ -22,11 +22,8 @@ var Type;
22
22
  Type["Text"] = "text";
23
23
  })(Type || (Type = {}));
24
24
  export class Settings extends PlexObject {
25
- constructor() {
26
- super(...arguments);
27
- this._data = [];
28
- }
29
- static { this.key = '/:/prefs'; }
25
+ static key = '/:/prefs';
26
+ _data = [];
30
27
  all() {
31
28
  return Object.entries(this._settings)
32
29
  .sort((a, b) => a[0].localeCompare(b[0]))
@@ -70,10 +67,7 @@ export class Settings extends PlexObject {
70
67
  * Represents a single Plex setting
71
68
  */
72
69
  export class Setting extends PlexObject {
73
- constructor() {
74
- super(...arguments);
75
- this._setValue = null;
76
- }
70
+ _setValue = null;
77
71
  /**
78
72
  * Set a new value for this setitng. NOTE: You must call {@link Settings.save} before
79
73
  * any changes to setting values are persisted to the PlexServer.
@@ -99,11 +93,8 @@ export class Setting extends PlexObject {
99
93
  }
100
94
  }
101
95
  export class Preferences extends Setting {
102
- constructor() {
103
- super(...arguments);
104
- this.FILTER = 'preferences';
105
- }
106
- static { this.TAG = 'Preferences'; }
96
+ static TAG = 'Preferences';
97
+ FILTER = 'preferences';
107
98
  }
108
99
  // class Setting(PlexObject):
109
100
  // """ Represents a single Plex setting.
package/dist/src/video.js CHANGED
@@ -2,11 +2,8 @@ import { Playable } from './base/playable.js';
2
2
  import { fetchItem, fetchItems, findItems } from './baseFunctionality.js';
3
3
  import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Poster, Producer, Rating, Role, Similar, Writer, } from './media.js';
4
4
  class Video extends Playable {
5
- constructor() {
6
- super(...arguments);
7
- /** Hardcoded as 'video' (useful for search filters). */
8
- this.listType = 'video';
9
- }
5
+ /** Hardcoded as 'video' (useful for search filters). */
6
+ listType = 'video';
10
7
  /**
11
8
  * Returns True if this video is watched.
12
9
  */
@@ -109,12 +106,9 @@ class Video extends Playable {
109
106
  * Represents a single Movie.
110
107
  */
111
108
  export class Movie extends Video {
112
- constructor() {
113
- super(...arguments);
114
- this.TAG = 'Video';
115
- this.TYPE = 'movie';
116
- this.METADATA_TYPE = 'movie';
117
- }
109
+ TAG = 'Video';
110
+ TYPE = 'movie';
111
+ METADATA_TYPE = 'movie';
118
112
  get actors() {
119
113
  return this.roles;
120
114
  }
@@ -190,12 +184,9 @@ export class Movie extends Video {
190
184
  * Represents a single Show (including all seasons and episodes).
191
185
  */
192
186
  export class Show extends Video {
193
- constructor() {
194
- super(...arguments);
195
- this.TAG = 'Directory';
196
- this.TYPE = 'show';
197
- this.METADATA_TYPE = 'episode';
198
- }
187
+ TAG = 'Directory';
188
+ TYPE = 'show';
189
+ METADATA_TYPE = 'episode';
199
190
  /** <:class:`~plexapi.media.Similar`>): List of Similar objects. */
200
191
  // similar: List;
201
192
  /**
@@ -256,12 +247,9 @@ export class Show extends Video {
256
247
  * Represents a single Show Season (including all episodes).
257
248
  */
258
249
  export class Season extends Video {
259
- constructor() {
260
- super(...arguments);
261
- this.TAG = 'Directory';
262
- this.TYPE = 'season';
263
- this.METADATA_TYPE = 'episode';
264
- }
250
+ TAG = 'Directory';
251
+ TYPE = 'season';
252
+ METADATA_TYPE = 'episode';
265
253
  /** Returns season number */
266
254
  get seasonNumber() {
267
255
  return this.index;
@@ -290,12 +278,9 @@ export class Season extends Video {
290
278
  }
291
279
  }
292
280
  export class Episode extends Video {
293
- constructor() {
294
- super(...arguments);
295
- this.TYPE = 'episode';
296
- this.METADATA_TYPE = 'episode';
297
- }
298
- static { this.TAG = 'Video'; }
281
+ static TAG = 'Video';
282
+ TYPE = 'episode';
283
+ METADATA_TYPE = 'episode';
299
284
  /**
300
285
  * Returns this episodes season number.
301
286
  */
@@ -380,12 +365,9 @@ export class Episode extends Video {
380
365
  }
381
366
  }
382
367
  export class Clip extends Video {
383
- constructor() {
384
- super(...arguments);
385
- this.TYPE = 'clip';
386
- this.METADATA_TYPE = 'clip';
387
- }
388
- static { this.TAG = 'Video'; }
368
+ static TAG = 'Video';
369
+ TYPE = 'clip';
370
+ METADATA_TYPE = 'clip';
389
371
  _loadData(data) {
390
372
  super._loadData(data);
391
373
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl/plex",
3
- "version": "3.9.2",
3
+ "version": "3.11.0",
4
4
  "description": "plex api client in typescript using ofetch",
5
5
  "author": "Scott Cooper <scttcper@gmail.com>",
6
6
  "publishConfig": {
@@ -34,33 +34,33 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@ctrl/mac-address": "^3.1.0",
37
- "ofetch": "^1.4.1",
37
+ "ofetch": "^1.5.1",
38
38
  "p-any": "^4.0.0",
39
- "type-fest": "^5.0.1",
39
+ "type-fest": "^5.2.0",
40
40
  "ws": "^8.18.3",
41
41
  "xml2js": "^0.6.2"
42
42
  },
43
43
  "devDependencies": {
44
- "@ctrl/oxlint-config": "1.2.6",
44
+ "@ctrl/oxlint-config": "1.3.2",
45
45
  "@ctrl/video-filename-parser": "5.4.1",
46
- "@sindresorhus/tsconfig": "8.0.1",
47
- "@trivago/prettier-plugin-sort-imports": "5.2.2",
48
- "@types/node": "24.5.2",
46
+ "@sindresorhus/tsconfig": "8.1.0",
47
+ "@trivago/prettier-plugin-sort-imports": "6.0.0",
48
+ "@types/node": "24.10.1",
49
49
  "@types/ws": "8.18.1",
50
50
  "@types/xml2js": "0.4.14",
51
- "@types/yargs": "17.0.33",
52
- "@vitest/coverage-v8": "3.2.4",
51
+ "@types/yargs": "17.0.34",
52
+ "@vitest/coverage-v8": "4.0.8",
53
53
  "execa": "9.6.0",
54
- "globby": "14.1.0",
54
+ "globby": "15.0.0",
55
55
  "make-dir": "5.1.0",
56
56
  "ora": "9.0.0",
57
- "oxlint": "1.18.0",
58
- "p-retry": "7.0.0",
57
+ "oxlint": "1.28.0",
58
+ "p-retry": "7.1.0",
59
59
  "prettier": "3.6.2",
60
60
  "tsx": "4.20.6",
61
- "typedoc": "0.28.13",
62
- "typescript": "5.9.2",
63
- "vitest": "3.2.4",
61
+ "typedoc": "0.28.14",
62
+ "typescript": "5.9.3",
63
+ "vitest": "4.0.8",
64
64
  "yargs": "18.0.0"
65
65
  },
66
66
  "release": {
@@ -91,5 +91,5 @@
91
91
  "engines": {
92
92
  "node": ">=18"
93
93
  },
94
- "packageManager": "pnpm@10.17.1"
94
+ "packageManager": "pnpm@10.22.0"
95
95
  }