@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,11 +1,12 @@
1
- /// <reference types="node" />
1
+ /// <reference types="node" resolution-mode="require"/>
2
2
  import { URL, URLSearchParams } from 'url';
3
- import { HistoryMetadatum } from './server.types';
4
- import { Library, Hub } from './library';
5
- import { Optimized } from './media';
6
- import { Agent, SEARCHTYPES } from './search';
7
- import { PlexClient } from './client';
8
- import { MyPlexAccount } from './myplex';
3
+ import { PlexClient } from './client.js';
4
+ import { Hub, Library } from './library.js';
5
+ import { Optimized } from './media.js';
6
+ import { MyPlexAccount } from './myplex.js';
7
+ import { Agent, SEARCHTYPES } from './search.js';
8
+ import { HistoryMetadatum } from './server.types.js';
9
+ import { Settings } from './settings.js';
9
10
  /**
10
11
  * This is the main entry point to interacting with a Plex server. It allows you to
11
12
  * list connected clients, browse your library sections and perform actions such as
@@ -16,7 +17,7 @@ import { MyPlexAccount } from './myplex';
16
17
  export declare class PlexServer {
17
18
  readonly baseurl: string;
18
19
  readonly token: string;
19
- readonly timeout?: number | undefined;
20
+ readonly timeout?: number;
20
21
  key: string;
21
22
  /** True if server allows camera upload */
22
23
  allowCameraUpload: boolean;
@@ -51,7 +52,7 @@ export declare class PlexServer {
51
52
  */
52
53
  hubSearch: boolean;
53
54
  /** Unique ID for this server (looks like an md5) */
54
- machineIdentifier: string;
55
+ machineIdentifier?: string;
55
56
  /**
56
57
  * True if `multiusers <https!://support.plex.tv/hc/en-us/articles/200250367-Multi-User-Support>`_ are enabled.
57
58
  */
@@ -128,8 +129,9 @@ export declare class PlexServer {
128
129
  /** Unknown */
129
130
  pushNotifications: boolean;
130
131
  _library?: Library;
132
+ _settings?: Settings;
131
133
  private _myPlexAccount?;
132
- constructor(baseurl: string, token: string, timeout?: number | undefined);
134
+ constructor(baseurl: string, token: string, timeout?: number);
133
135
  agents(mediaType?: number | string): Promise<Agent[]>;
134
136
  connect(): Promise<void>;
135
137
  /**
@@ -175,6 +177,7 @@ export declare class PlexServer {
175
177
  * @param librarySectionId request history for a specific library section ID.
176
178
  */
177
179
  history(maxresults?: number, mindate?: Date, ratingKey?: number | string, accountId?: number | string, librarySectionId?: number | string): Promise<HistoryMetadatum[]>;
180
+ settings(): Promise<Settings>;
178
181
  /**
179
182
  * Returns a :class:`~plexapi.myplex.MyPlexAccount` object using the same
180
183
  * token to access this server. If you are not the owner of this PlexServer
@@ -189,6 +192,15 @@ export declare class PlexServer {
189
192
  * if either includeToken is True or TODO: CONFIG.log.show_secrets is 'true'.
190
193
  */
191
194
  url(key: string, includeToken?: boolean, params?: URLSearchParams): URL;
195
+ /**
196
+ * Build the Plex Web URL for the object.
197
+ * @param base The base URL before the fragment (``#!``).
198
+ * Default is https://app.plex.tv/desktop.
199
+ * @param endpoint The Plex Web URL endpoint.
200
+ * None for server, 'playlist' for playlists, 'details' for all other media types.
201
+ */
202
+ _buildWebURL(base?: string, endpoint?: string, params?: URLSearchParams): string;
203
+ _uriRoot(): string;
192
204
  private _headers;
193
205
  private _loadData;
194
206
  /**
@@ -1,18 +1,13 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.PlexServer = void 0;
7
- const got_1 = __importDefault(require("got"));
8
- const url_1 = require("url");
9
- const config_1 = require("./config");
10
- const library_1 = require("./library");
11
- const baseFunctionality_1 = require("./baseFunctionality");
12
- const media_1 = require("./media");
13
- const search_1 = require("./search");
14
- const client_1 = require("./client");
15
- const myplex_1 = require("./myplex");
1
+ import { URL, URLSearchParams } from 'url';
2
+ import got from 'got';
3
+ import { fetchItem, fetchItems } from './baseFunctionality.js';
4
+ import { PlexClient } from './client.js';
5
+ import { BASE_HEADERS, TIMEOUT, X_PLEX_CONTAINER_SIZE } from './config.js';
6
+ import { Hub, Library } from './library.js';
7
+ import { Optimized } from './media.js';
8
+ import { MyPlexAccount } from './myplex.js';
9
+ import { Agent, SEARCHTYPES } from './search.js';
10
+ import { Settings } from './settings.js';
16
11
  /**
17
12
  * This is the main entry point to interacting with a Plex server. It allows you to
18
13
  * list connected clients, browse your library sections and perform actions such as
@@ -20,7 +15,7 @@ const myplex_1 = require("./myplex");
20
15
  * server, or simply want to access your server with your username and password, you
21
16
  * can also create an PlexServer instance from :class:`~plexapi.myplex.MyPlexAccount`.
22
17
  */
23
- class PlexServer {
18
+ export class PlexServer {
24
19
  constructor(baseurl, token, timeout) {
25
20
  this.baseurl = baseurl;
26
21
  this.token = token;
@@ -32,7 +27,7 @@ class PlexServer {
32
27
  if (mediaType) {
33
28
  key += `?mediaType=${mediaType}`;
34
29
  }
35
- return baseFunctionality_1.fetchItems(this, key, undefined, search_1.Agent, this);
30
+ return fetchItems(this, key, undefined, Agent, this);
36
31
  }
37
32
  async connect() {
38
33
  const data = await this.query(this.key, undefined, undefined, this.timeout);
@@ -53,13 +48,13 @@ class PlexServer {
53
48
  return this._library;
54
49
  }
55
50
  try {
56
- const data = await this.query(library_1.Library.key);
57
- this._library = new library_1.Library(this, data.MediaContainer);
51
+ const data = await this.query(Library.key);
52
+ this._library = new Library(this, data.MediaContainer);
58
53
  }
59
- catch (_a) {
54
+ catch {
60
55
  // TODO: validate error type, also TODO figure out how this is used
61
56
  const data = await this.query('/library/sections/');
62
- this._library = new library_1.Library(this, data.MediaContainer);
57
+ this._library = new Library(this, data.MediaContainer);
63
58
  }
64
59
  return this._library;
65
60
  }
@@ -81,13 +76,13 @@ class PlexServer {
81
76
  async search(query, mediatype, limit) {
82
77
  const params = { query };
83
78
  if (mediatype) {
84
- params.section = search_1.SEARCHTYPES[mediatype].toString();
79
+ params.section = SEARCHTYPES[mediatype].toString();
85
80
  }
86
81
  if (limit) {
87
82
  params.limit = limit.toString();
88
83
  }
89
- const key = '/hubs/search?' + new url_1.URLSearchParams(params).toString();
90
- const hubs = await baseFunctionality_1.fetchItems(this, key, undefined, library_1.Hub, this);
84
+ const key = '/hubs/search?' + new URLSearchParams(params).toString();
85
+ const hubs = await fetchItems(this, key, undefined, Hub, this);
91
86
  return hubs;
92
87
  }
93
88
  /**
@@ -107,14 +102,14 @@ class PlexServer {
107
102
  requestHeaders.Authorization = `Basic ${credentials}`;
108
103
  }
109
104
  const url = this.url(path);
110
- const response = await got_1.default({
105
+ const response = await got({
111
106
  method,
112
107
  url,
113
108
  headers: requestHeaders,
114
- timeout: timeout !== null && timeout !== void 0 ? timeout : config_1.TIMEOUT,
115
- username,
116
- password,
117
- retry: 0,
109
+ timeout: { request: timeout ?? TIMEOUT },
110
+ ...(username ? { username } : {}),
111
+ ...(password ? { password } : {}),
112
+ retry: { limit: 0 },
118
113
  }).json();
119
114
  return response;
120
115
  }
@@ -144,23 +139,30 @@ class PlexServer {
144
139
  args['viewedAt>'] = mindate.getTime().toString();
145
140
  }
146
141
  args['X-Plex-Container-Start'] = '0';
147
- args['X-Plex-Container-Size'] = Math.min(config_1.X_PLEX_CONTAINER_SIZE, maxresults).toString();
142
+ args['X-Plex-Container-Size'] = Math.min(X_PLEX_CONTAINER_SIZE, maxresults).toString();
148
143
  let results = [];
149
- let key = '/status/sessions/history/all?' + new url_1.URLSearchParams(args).toString();
144
+ let key = '/status/sessions/history/all?' + new URLSearchParams(args).toString();
150
145
  let raw = await this.query(key);
151
146
  const totalResults = raw.MediaContainer.totalSize;
152
147
  results = results.concat(raw.MediaContainer.Metadata);
153
148
  while (results.length <= totalResults &&
154
- config_1.X_PLEX_CONTAINER_SIZE === raw.MediaContainer.size &&
149
+ X_PLEX_CONTAINER_SIZE === raw.MediaContainer.size &&
155
150
  maxresults > results.length) {
156
151
  args['X-Plex-Container-Start'] = (Number(args['X-Plex-Container-Start']) + Number(args['X-Plex-Container-Size'])).toString();
157
- key = '/status/sessions/history/all?' + new url_1.URLSearchParams(args).toString();
152
+ key = '/status/sessions/history/all?' + new URLSearchParams(args).toString();
158
153
  // eslint-disable-next-line no-await-in-loop
159
154
  raw = await this.query(key);
160
155
  results = results.concat(raw.MediaContainer.Metadata);
161
156
  }
162
157
  return results;
163
158
  }
159
+ async settings() {
160
+ if (!this._settings) {
161
+ const data = await this.query(Settings.key);
162
+ this._settings = new Settings(this, data.MediaContainer.Setting);
163
+ }
164
+ return this._settings;
165
+ }
164
166
  // TODO: not sure if this works
165
167
  // /**
166
168
  // * Returns a list of all playlist objects saved on the server.
@@ -178,38 +180,37 @@ class PlexServer {
178
180
  */
179
181
  myPlexAccount() {
180
182
  if (!this._myPlexAccount) {
181
- this._myPlexAccount = new myplex_1.MyPlexAccount(this.baseurl, undefined, undefined, this.token, this.timeout, this);
183
+ this._myPlexAccount = new MyPlexAccount(this.baseurl, undefined, undefined, this.token, this.timeout, this);
182
184
  }
183
185
  return this._myPlexAccount;
184
186
  }
185
187
  // Returns list of all :class:`~plexapi.client.PlexClient` objects connected to server.
186
188
  async clients() {
187
- var _a, _b;
188
189
  const items = [];
189
190
  const response = await this.query('/clients');
190
- if (((_a = response.MediaContainer) === null || _a === void 0 ? void 0 : _a.Server) === undefined) {
191
+ if (response.MediaContainer?.Server === undefined) {
191
192
  return [];
192
193
  }
193
194
  const shouldFetchPorts = response.MediaContainer.Server.some(server => server.port === null || server.port === undefined);
194
- let ports;
195
+ let ports = {};
195
196
  if (shouldFetchPorts) {
196
197
  ports = await this._myPlexClientPorts();
197
198
  }
198
199
  for (const server of response.MediaContainer.Server) {
199
- let port = server.port;
200
+ let { port } = server;
200
201
  if (!port) {
201
202
  // TODO: print warning about doing weird port stuff
202
- port = (_b = ports) === null || _b === void 0 ? void 0 : _b[server.machineIdentifier];
203
+ port = Number(ports?.[server.machineIdentifier]);
203
204
  }
204
205
  const baseurl = `http://${server.host}:${port}`;
205
- items.push(new client_1.PlexClient({ baseurl, token: this.token, server: this, data: server }));
206
+ items.push(new PlexClient({ baseurl, token: this.token, server: this, data: server }));
206
207
  }
207
208
  return items;
208
209
  }
209
210
  /** Returns list of all :class:`~plexapi.media.Optimized` objects connected to server. */
210
211
  async optimizedItems() {
211
- const backgroundProcessing = await baseFunctionality_1.fetchItem(this, '/playlists?type=42');
212
- const items = await baseFunctionality_1.fetchItems(this, backgroundProcessing.key, undefined, media_1.Optimized, this);
212
+ const backgroundProcessing = await fetchItem(this, '/playlists?type=42');
213
+ const items = await fetchItems(this, backgroundProcessing.key, undefined, Optimized, this);
213
214
  return items;
214
215
  }
215
216
  /**
@@ -220,18 +221,34 @@ class PlexServer {
220
221
  if (!this.baseurl) {
221
222
  throw new Error('PlexClient object missing baseurl.');
222
223
  }
223
- const url = new url_1.URL(key, this.baseurl);
224
+ const url = new URL(key, this.baseurl);
224
225
  if (this.token && includeToken) {
225
- const searchParams = new url_1.URLSearchParams(params);
226
+ const searchParams = new URLSearchParams(params);
226
227
  searchParams.append('X-Plex-Token', this.token);
227
228
  url.search = searchParams.toString();
228
229
  return url;
229
230
  }
230
231
  return url;
231
232
  }
233
+ /**
234
+ * Build the Plex Web URL for the object.
235
+ * @param base The base URL before the fragment (``#!``).
236
+ * Default is https://app.plex.tv/desktop.
237
+ * @param endpoint The Plex Web URL endpoint.
238
+ * None for server, 'playlist' for playlists, 'details' for all other media types.
239
+ */
240
+ _buildWebURL(base = 'https://app.plex.tv/desktop/', endpoint, params) {
241
+ if (endpoint) {
242
+ return `${base}#!/server/${this.machineIdentifier}/${endpoint}?${params?.toString()}`;
243
+ }
244
+ return `${base}#!/media/${this.machineIdentifier}/com.plexapp.plugins.library?${params?.toString()}`;
245
+ }
246
+ _uriRoot() {
247
+ return `server://${this.machineIdentifier}/com.plexapp.plugins.library`;
248
+ }
232
249
  _headers() {
233
250
  const headers = {
234
- ...config_1.BASE_HEADERS,
251
+ ...BASE_HEADERS,
235
252
  'Content-type': 'application/json',
236
253
  };
237
254
  if (this.token) {
@@ -292,16 +309,14 @@ class PlexServer {
292
309
  * See python plex issue #126: Make PlexServer.clients() more user friendly.
293
310
  */
294
311
  async _myPlexClientPorts() {
295
- var _a;
296
- let ports = {};
312
+ const ports = {};
297
313
  const account = this.myPlexAccount();
298
314
  const devices = await account.devices();
299
315
  for (const device of devices) {
300
- if ((_a = device.connections) === null || _a === void 0 ? void 0 : _a.length) {
301
- ports[device.clientIdentifier] = new url_1.URL('http://172.17.0.2:32400').port;
316
+ if (device.connections?.length) {
317
+ ports[device.clientIdentifier] = new URL('http://172.17.0.2:32400').port;
302
318
  }
303
319
  }
304
320
  return ports;
305
321
  }
306
322
  }
307
- exports.PlexServer = PlexServer;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ import { PlexObject } from './base/plexObject.js';
2
+ export interface SettingResponse {
3
+ id: string;
4
+ label: string;
5
+ summary: string;
6
+ type: Type;
7
+ default: boolean | number | string;
8
+ value: boolean | number | string;
9
+ hidden: boolean;
10
+ advanced: boolean;
11
+ group: SettingsGroup;
12
+ }
13
+ declare enum SettingsGroup {
14
+ Butler = "butler",
15
+ Channels = "channels",
16
+ Dlna = "dlna",
17
+ Empty = "",
18
+ Extras = "extras",
19
+ General = "general",
20
+ Library = "library",
21
+ Network = "network",
22
+ Transcoder = "transcoder"
23
+ }
24
+ declare enum Type {
25
+ Bool = "bool",
26
+ Double = "double",
27
+ Int = "int",
28
+ Text = "text"
29
+ }
30
+ export declare class Settings extends PlexObject {
31
+ static key: string;
32
+ _settings: Record<string, Setting>;
33
+ _data: SettingResponse[];
34
+ all(): Setting[];
35
+ get(id: string): Setting;
36
+ /**
37
+ * Save any outstanding settnig changes to the PlexServer. This
38
+ * performs a full reload() of Settings after complete.
39
+ */
40
+ save(): Promise<void>;
41
+ _loadData(data: SettingResponse[]): void;
42
+ }
43
+ /**
44
+ * Represents a single Plex setting
45
+ */
46
+ export declare class Setting extends PlexObject {
47
+ /** Setting id (or name). */
48
+ id: string;
49
+ /** Short description of what this setting is. */
50
+ label: string;
51
+ /** Long description of what this setting is. */
52
+ summary: string;
53
+ /** Setting type (text, int, double, bool). */
54
+ type: string;
55
+ /** Default value for this setting. */
56
+ default: string | boolean | number;
57
+ /** Current value for this setting. */
58
+ value: string | boolean | number;
59
+ /** True if this is a hidden setting. */
60
+ hidden: boolean;
61
+ /** True if this is an advanced setting. */
62
+ advanced: boolean;
63
+ /** Group name this setting is categorized as. */
64
+ group: string;
65
+ /** List or dictionary of valis values for this setting. */
66
+ enumValues: any[] | any;
67
+ _setValue: string | boolean | number | null;
68
+ /**
69
+ * Set a new value for this setitng. NOTE: You must call {@link Settings.save} before
70
+ * any changes to setting values are persisted to the PlexServer.
71
+ */
72
+ set(value: string | boolean | number): void;
73
+ _loadData(data: SettingResponse): void;
74
+ }
75
+ export declare class Preferences extends Setting {
76
+ static TAG: "Preferences";
77
+ FILTER: "preferences";
78
+ }
79
+ export {};
@@ -0,0 +1,160 @@
1
+ import { URLSearchParams } from 'url';
2
+ import { PlexObject } from './base/plexObject.js';
3
+ import { NotFound } from './exceptions.js';
4
+ import { lowerFirst } from './util.js';
5
+ var SettingsGroup;
6
+ (function (SettingsGroup) {
7
+ SettingsGroup["Butler"] = "butler";
8
+ SettingsGroup["Channels"] = "channels";
9
+ SettingsGroup["Dlna"] = "dlna";
10
+ SettingsGroup["Empty"] = "";
11
+ SettingsGroup["Extras"] = "extras";
12
+ SettingsGroup["General"] = "general";
13
+ SettingsGroup["Library"] = "library";
14
+ SettingsGroup["Network"] = "network";
15
+ SettingsGroup["Transcoder"] = "transcoder";
16
+ })(SettingsGroup || (SettingsGroup = {}));
17
+ var Type;
18
+ (function (Type) {
19
+ Type["Bool"] = "bool";
20
+ Type["Double"] = "double";
21
+ Type["Int"] = "int";
22
+ Type["Text"] = "text";
23
+ })(Type || (Type = {}));
24
+ export class Settings extends PlexObject {
25
+ constructor() {
26
+ super(...arguments);
27
+ this._data = [];
28
+ }
29
+ static { this.key = '/:/prefs'; }
30
+ all() {
31
+ return Object.entries(this._settings)
32
+ .sort((a, b) => a[0].localeCompare(b[0]))
33
+ .map(x => x[1]);
34
+ }
35
+ get(id) {
36
+ const lowerId = lowerFirst(id);
37
+ if (this._settings[lowerId]) {
38
+ return this._settings[lowerId];
39
+ }
40
+ throw new NotFound(`Invalid setting id: ${id}`);
41
+ }
42
+ /**
43
+ * Save any outstanding settnig changes to the PlexServer. This
44
+ * performs a full reload() of Settings after complete.
45
+ */
46
+ async save() {
47
+ const params = new URLSearchParams();
48
+ for (const setting of this.all()) {
49
+ if (setting._setValue !== null) {
50
+ params.append('setting.id', JSON.stringify(setting._setValue));
51
+ }
52
+ }
53
+ const url = `${this.key}?${params.toString()}`;
54
+ await this.server.query(url, 'put');
55
+ }
56
+ _loadData(data) {
57
+ this._data = data;
58
+ this._settings = this._settings ?? {};
59
+ for (const elem of data) {
60
+ const id = lowerFirst(elem.id);
61
+ if (this._settings[id]) {
62
+ this._settings[id]._loadData(elem);
63
+ continue;
64
+ }
65
+ this._settings[id] = new Setting(this.server, elem, this.initpath);
66
+ }
67
+ }
68
+ }
69
+ /**
70
+ * Represents a single Plex setting
71
+ */
72
+ export class Setting extends PlexObject {
73
+ constructor() {
74
+ super(...arguments);
75
+ this._setValue = null;
76
+ }
77
+ /**
78
+ * Set a new value for this setitng. NOTE: You must call {@link Settings.save} before
79
+ * any changes to setting values are persisted to the PlexServer.
80
+ */
81
+ set(value) {
82
+ if (typeof value !== typeof this.value) {
83
+ throw new Error('Invalid type');
84
+ }
85
+ this._setValue = value;
86
+ }
87
+ _loadData(data) {
88
+ // this._setValue = None
89
+ this.id = data.id;
90
+ this.label = data.label;
91
+ this.summary = data.summary;
92
+ this.type = data.type;
93
+ this.default = data.default;
94
+ this.value = data.value;
95
+ this.hidden = data.hidden;
96
+ this.advanced = data.advanced;
97
+ this.group = data.group;
98
+ // this.enumValues = this._getEnumValues(data);
99
+ }
100
+ }
101
+ export class Preferences extends Setting {
102
+ constructor() {
103
+ super(...arguments);
104
+ this.FILTER = 'preferences';
105
+ }
106
+ static { this.TAG = 'Preferences'; }
107
+ }
108
+ // class Setting(PlexObject):
109
+ // """ Represents a single Plex setting.
110
+ // _bool_cast = lambda x: True if x == 'true' or x == '1' else False
111
+ // _bool_str = lambda x: str(x).lower()
112
+ // _str = lambda x: str(x).encode('utf-8')
113
+ // TYPES = {
114
+ // 'bool': {'type': bool, 'cast': _bool_cast, 'tostr': _bool_str},
115
+ // 'double': {'type': float, 'cast': float, 'tostr': _str},
116
+ // 'int': {'type': int, 'cast': int, 'tostr': _str},
117
+ // 'text': {'type': str, 'cast': _str, 'tostr': _str},
118
+ // }
119
+ // def _loadData(self, data):
120
+ // """ Load attribute values from Plex XML response. """
121
+ // this._setValue = None
122
+ // this.id = data.('id')
123
+ // this.label = data.('label')
124
+ // this.summary = data.('summary')
125
+ // this.type = data.('type')
126
+ // this.default = this._cast(data.('default'))
127
+ // this.value = this._cast(data.('value'))
128
+ // this.hidden = utils.cast(bool, data.('hidden'))
129
+ // this.advanced = utils.cast(bool, data.('advanced'))
130
+ // this.group = data.('group')
131
+ // this.enumValues = this._getEnumValues(data)
132
+ // def _cast(self, value):
133
+ // """ Cast the specific value to the type of this setting. """
134
+ // if this.type != 'enum':
135
+ // value = utils.cast(this.TYPES.get(this.type)['cast'], value)
136
+ // return value
137
+ // def _getEnumValues(self, data):
138
+ // """ Returns a list of dictionary of valis value for this setting. """
139
+ // enumstr = data.('enumValues')
140
+ // if not enumstr:
141
+ // return None
142
+ // if ':' in enumstr:
143
+ // return {this._cast(k): v for k, v in [kv.split(':') for kv in enumstr.split('|')]}
144
+ // return enumstr.split('|')
145
+ // def set(self, value):
146
+ // """ Set a new value for this setitng. NOTE: You must call plex.settings.save() for before
147
+ // any changes to setting values are persisted to the :class:`~plexapi.server.PlexServer`.
148
+ // """
149
+ // # check a few things up front
150
+ // if not isinstance(value, this.TYPES[this.type]['type']):
151
+ // badtype = type(value).__name__
152
+ // raise BadRequest('Invalid value for %s: a %s is required, not %s' % (this.id, this.type, badtype))
153
+ // if this.enumValues and value not in this.enumValues:
154
+ // raise BadRequest('Invalid value for %s: %s not in %s' % (this.id, value, list(this.enumValues)))
155
+ // # store value off to the side until we call settings.save()
156
+ // tostr = this.TYPES[this.type]['tostr']
157
+ // this._setValue = tostr(value)
158
+ // def toUrl(self):
159
+ // """Helper for urls"""
160
+ // return '%s=%s' % (this.id, this._value or this.value)
@@ -1,4 +1,4 @@
1
- import type { Section } from './library';
1
+ import type { Section } from './library.js';
2
2
  export interface MediaContainer<T> {
3
3
  MediaContainer: T;
4
4
  }
@@ -17,3 +17,4 @@ export declare function getAgentIdentifier(section: Section, agent: string): Pro
17
17
  /** Simple tag helper for editing a object. */
18
18
  export declare function tagHelper(tag: string, items: string[], locked?: boolean, remove?: boolean): Record<string, string | number>;
19
19
  export declare function ltrim(x: string, characters: string[]): string;
20
+ export declare function lowerFirst(str: string): string;
@@ -1,17 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ltrim = exports.tagHelper = exports.getAgentIdentifier = exports.rsplit = void 0;
4
- function rsplit(str, sep, maxsplit) {
5
- var split = str.split(sep);
1
+ export function rsplit(str, sep, maxsplit) {
2
+ const split = str.split(sep);
6
3
  return maxsplit ? [split.slice(0, -maxsplit).join(sep)].concat(split.slice(-maxsplit)) : split;
7
4
  }
8
- exports.rsplit = rsplit;
9
5
  /**
10
6
  * Return the full agent identifier from a short identifier, name, or confirm full identifier.
11
7
  * @param section
12
8
  * @param agent
13
9
  */
14
- async function getAgentIdentifier(section, agent) {
10
+ export async function getAgentIdentifier(section, agent) {
15
11
  const agents = [];
16
12
  for (const ag of await section.agents()) {
17
13
  const identifiers = [ag.identifier, ag.shortIdentifier, ag.name];
@@ -22,9 +18,8 @@ async function getAgentIdentifier(section, agent) {
22
18
  }
23
19
  throw new Error(`Couldnt find "${agent}" in agents list (${agents.join(', ')})`);
24
20
  }
25
- exports.getAgentIdentifier = getAgentIdentifier;
26
21
  /** Simple tag helper for editing a object. */
27
- function tagHelper(tag, items, locked = true, remove = false) {
22
+ export function tagHelper(tag, items, locked = true, remove = false) {
28
23
  const data = {};
29
24
  if (remove) {
30
25
  const tagname = `${tag}[].tag.tag-`;
@@ -40,8 +35,7 @@ function tagHelper(tag, items, locked = true, remove = false) {
40
35
  data[`${tag}.locked`] = locked ? 1 : 0;
41
36
  return data;
42
37
  }
43
- exports.tagHelper = tagHelper;
44
- function ltrim(x, characters) {
38
+ export function ltrim(x, characters) {
45
39
  let start = 0;
46
40
  while (characters.includes(x[start])) {
47
41
  start += 1;
@@ -49,4 +43,6 @@ function ltrim(x, characters) {
49
43
  const end = x.length - 1;
50
44
  return x.substr(start, end);
51
45
  }
52
- exports.ltrim = ltrim;
46
+ export function lowerFirst(str) {
47
+ return str.charAt(0).toUpperCase() + str.slice(1);
48
+ }