@ctrl/plex 2.1.0 → 3.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.
@@ -67,6 +67,7 @@ export declare class PlexClient {
67
67
  platform?: string;
68
68
  platformVersion?: string;
69
69
  title?: string;
70
+ timeout: number;
70
71
  constructor(options?: PlexOptions);
71
72
  /**
72
73
  * Alias of reload as any subsequent requests to this client will be
@@ -74,7 +75,7 @@ export declare class PlexClient {
74
75
  * populated from a PlexServer.
75
76
  * @param timeout
76
77
  */
77
- connect(timeout?: number): Promise<void>;
78
+ connect(): Promise<void>;
78
79
  /**
79
80
  * @alias PlexClient.connect
80
81
  */
@@ -89,7 +90,7 @@ export declare class PlexClient {
89
90
  * @param headers
90
91
  * @param timeout
91
92
  */
92
- query<T>(path: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', headers?: Record<string, string>, timeout?: number): Promise<T>;
93
+ query<T>(path: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', headers?: Record<string, string>): Promise<T>;
93
94
  /**
94
95
  * Build a URL string with proper token argument. Token will be appended to the URL
95
96
  * if either includeToken is True or TODO: CONFIG.log.show_secrets is 'true'.
@@ -1,5 +1,5 @@
1
1
  import { URL, URLSearchParams } from 'url';
2
- import got from 'got';
2
+ import { ofetch } from 'ofetch';
3
3
  import { BASE_HEADERS, TIMEOUT } from './config.js';
4
4
  /**
5
5
  * Main class for interacting with a Plex client. This class can connect
@@ -53,6 +53,7 @@ export class PlexClient {
53
53
  }
54
54
  this._baseurl = options.baseurl ?? 'http://localhost:32400';
55
55
  this._token = options.token ?? null;
56
+ this.timeout = options.timeout ?? TIMEOUT;
56
57
  }
57
58
  /**
58
59
  * Alias of reload as any subsequent requests to this client will be
@@ -60,8 +61,8 @@ export class PlexClient {
60
61
  * populated from a PlexServer.
61
62
  * @param timeout
62
63
  */
63
- async connect(timeout) {
64
- const data = await this.query(this.key, undefined, undefined, timeout);
64
+ async connect() {
65
+ const data = await this.query(this.key);
65
66
  this._loadData(data.MediaContainer.Player);
66
67
  }
67
68
  /**
@@ -80,15 +81,15 @@ export class PlexClient {
80
81
  * @param headers
81
82
  * @param timeout
82
83
  */
83
- async query(path, method = 'get', headers, timeout) {
84
+ async query(path, method = 'get', headers) {
84
85
  const headersObj = this.headers(headers);
85
- const response = await got({
86
+ const response = await ofetch(this.url(path).toString(), {
86
87
  method,
87
- url: this.url(path),
88
- timeout: { request: timeout ?? TIMEOUT },
88
+ timeout: this.timeout ?? TIMEOUT,
89
89
  headers: headersObj,
90
- retry: { limit: 0 },
91
- }).json();
90
+ responseType: 'json',
91
+ retry: 0,
92
+ });
92
93
  return response;
93
94
  }
94
95
  /**
@@ -128,6 +129,7 @@ export class PlexClient {
128
129
  const headersObj = {
129
130
  ...BASE_HEADERS,
130
131
  ...headers,
132
+ accept: 'application/json',
131
133
  };
132
134
  if (this._token) {
133
135
  headersObj['X-Plex-Token'] = this._token;
@@ -1,5 +1,8 @@
1
1
  export declare const PROJECT = "PlexAPI";
2
2
  export declare const VERSION = "3.3.0";
3
+ /**
4
+ * Default timeout for requests in milliseconds.
5
+ */
3
6
  export declare const TIMEOUT = 30000;
4
7
  export declare const X_PLEX_CONTAINER_SIZE = 100;
5
8
  export declare const X_PLEX_ENABLE_FAST_CONNECT: false;
@@ -7,7 +7,10 @@ import { getMAC, parseMAC } from '@ctrl/mac-address';
7
7
  // PlexAPI Settings
8
8
  export const PROJECT = 'PlexAPI';
9
9
  export const VERSION = '3.3.0';
10
- export const TIMEOUT = 30000;
10
+ /**
11
+ * Default timeout for requests in milliseconds.
12
+ */
13
+ export const TIMEOUT = 30_000;
11
14
  export const X_PLEX_CONTAINER_SIZE = 100;
12
15
  export const X_PLEX_ENABLE_FAST_CONNECT = false;
13
16
  // Plex Header Configuation
@@ -9,12 +9,12 @@ import { PlexServer } from './server.js';
9
9
  * and return this object.
10
10
  */
11
11
  export declare class MyPlexAccount {
12
- private readonly baseUrl;
12
+ baseUrl: string | null;
13
13
  username?: string;
14
- private readonly password?;
14
+ password?: string;
15
15
  token?: string;
16
- private readonly timeout;
17
- private readonly server?;
16
+ timeout: number;
17
+ server?: PlexServer;
18
18
  static key: string;
19
19
  FRIENDINVITE: string;
20
20
  HOMEUSERCREATE: string;
@@ -115,7 +115,7 @@ export declare class MyPlexAccount {
115
115
  * @param headers
116
116
  * @param timeout
117
117
  */
118
- query<T = any>(url: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', headers?: any, timeout?: number, username?: string, password?: string): Promise<T>;
118
+ query<T = any>(url: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', headers?: any, username?: string, password?: string): Promise<T>;
119
119
  /**
120
120
  * Returns a str, a new "claim-token", which you can use to register your new Plex Server instance to your account.
121
121
  * @link https://hub.docker.com/r/plexinc/pms-docker/
@@ -136,7 +136,7 @@ export declare class MyPlexAccount {
136
136
  */
137
137
  export declare class MyPlexResource {
138
138
  readonly account: MyPlexAccount;
139
- private readonly baseUrl;
139
+ private baseUrl;
140
140
  static key: string;
141
141
  TAG: string;
142
142
  /** Descriptive name of this resource */
@@ -1,5 +1,5 @@
1
- import { URL, URLSearchParams } from 'url';
2
- import got from 'got';
1
+ import { URLSearchParams } from 'url';
2
+ import { ofetch } from 'ofetch';
3
3
  import pAny from 'p-any';
4
4
  import { parseStringPromise } from 'xml2js';
5
5
  import { PlexObject } from './base/plexObject.js';
@@ -64,8 +64,7 @@ export class MyPlexAccount {
64
64
  */
65
65
  async connect() {
66
66
  if (!this.token) {
67
- // log('Logging in with username', { username: this.username });
68
- const data = await this._signin(this.username, this.password, this.timeout);
67
+ const data = await this._signin(this.username, this.password);
69
68
  this._loadData(data);
70
69
  return this;
71
70
  }
@@ -118,27 +117,28 @@ export class MyPlexAccount {
118
117
  * @param headers
119
118
  * @param timeout
120
119
  */
121
- async query(url, method = 'get', headers, timeout, username, password) {
120
+ async query(url, method = 'get', headers, username, password) {
122
121
  const requestHeaders = this._headers();
123
122
  if (username && password) {
124
123
  const credentials = Buffer.from(`${username}:${password}`).toString('base64');
125
124
  requestHeaders.Authorization = `Basic ${credentials}`;
126
125
  }
127
- const promise = got({
126
+ if (!url.includes('xml')) {
127
+ requestHeaders.accept = 'application/json';
128
+ }
129
+ const body = await ofetch(url, {
128
130
  method,
129
- url: new URL(url),
130
131
  headers: requestHeaders,
131
- timeout: { request: timeout ?? TIMEOUT },
132
- ...(username ? { username } : {}),
133
- ...(password ? { password } : {}),
134
- retry: { limit: 0 },
132
+ timeout: this.timeout ?? TIMEOUT,
133
+ retry: 0,
134
+ parseResponse: res => res,
135
+ // Can't seem to pass responseType
135
136
  });
136
137
  if (url.includes('xml')) {
137
- const res = await promise;
138
- const xml = await parseStringPromise(res.body);
138
+ const xml = await parseStringPromise(body);
139
139
  return xml;
140
140
  }
141
- const res = await promise.json();
141
+ const res = JSON.parse(body);
142
142
  return res;
143
143
  }
144
144
  /**
@@ -148,7 +148,7 @@ export class MyPlexAccount {
148
148
  */
149
149
  async claimToken() {
150
150
  const url = 'https://plex.tv/api/claim/token.json';
151
- const response = await this.query(url, 'get', undefined, TIMEOUT);
151
+ const response = await this.query(url, 'get', undefined);
152
152
  return response.token;
153
153
  }
154
154
  /**
@@ -160,12 +160,11 @@ export class MyPlexAccount {
160
160
  ...BASE_HEADERS,
161
161
  });
162
162
  const url = `${this.baseUrl}/myplex/claim?${params.toString()}`;
163
- return got({
164
- method: 'POST',
165
- url,
166
- timeout: { request: TIMEOUT },
163
+ return ofetch(url, {
164
+ method: 'post',
165
+ timeout: TIMEOUT,
167
166
  headers: this._headers(),
168
- retry: { limit: 0 },
167
+ retry: 0,
169
168
  });
170
169
  }
171
170
  _headers() {
@@ -178,8 +177,8 @@ export class MyPlexAccount {
178
177
  }
179
178
  return headers;
180
179
  }
181
- async _signin(username, password, timeout) {
182
- const data = await this.query(this.SIGNIN, 'post', undefined, timeout, username, password);
180
+ async _signin(username, password) {
181
+ const data = await this.query(this.SIGNIN, 'post', undefined, username, password);
183
182
  return data.user;
184
183
  }
185
184
  _loadData(user) {
@@ -265,7 +264,7 @@ export class MyPlexResource {
265
264
  /** Remove this device from your account */
266
265
  async delete() {
267
266
  const key = `https://plex.tv/api/servers/${this.clientIdentifier}?X-Plex-Client-Identifier=${BASE_HEADERS['X-Plex-Client-Identifier']}&X-Plex-Token=${this.accessToken}`;
268
- await got.delete(key, { retry: { limit: 0 } });
267
+ await ofetch(key, { method: 'delete', retry: 0 });
269
268
  }
270
269
  _loadData(data) {
271
270
  this.name = data.name;
@@ -15,9 +15,13 @@ import { Settings } from './settings.js';
15
15
  * can also create an PlexServer instance from :class:`~plexapi.myplex.MyPlexAccount`.
16
16
  */
17
17
  export declare class PlexServer {
18
- readonly baseurl: string;
19
- readonly token: string;
20
- readonly timeout?: number;
18
+ baseurl: string;
19
+ token: string;
20
+ /**
21
+ * Default request timeout in milliseconds.
22
+ * @default 30000
23
+ */
24
+ timeout: number;
21
25
  key: string;
22
26
  /** True if server allows camera upload */
23
27
  allowCameraUpload: boolean;
@@ -131,7 +135,12 @@ export declare class PlexServer {
131
135
  _library?: Library;
132
136
  _settings?: Settings;
133
137
  private _myPlexAccount?;
134
- constructor(baseurl: string, token: string, timeout?: number);
138
+ constructor(baseurl: string, token: string,
139
+ /**
140
+ * Default request timeout in milliseconds.
141
+ * @default 30000
142
+ */
143
+ timeout?: number);
135
144
  agents(mediaType?: number | string): Promise<Agent[]>;
136
145
  connect(): Promise<void>;
137
146
  /**
@@ -162,9 +171,8 @@ export declare class PlexServer {
162
171
  * @param path
163
172
  * @param method
164
173
  * @param headers
165
- * @param timeout
166
174
  */
167
- query<T = any>(path: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', headers?: any, timeout?: number, username?: string, password?: string): Promise<T>;
175
+ query<T = any>(path: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', headers?: any, username?: string, password?: string): Promise<T>;
168
176
  /**
169
177
  * Returns a list of media items from watched history. If there are many results, they will
170
178
  * be fetched from the server in batches of X_PLEX_CONTAINER_SIZE amounts. If you're only
@@ -1,5 +1,5 @@
1
1
  import { URL, URLSearchParams } from 'url';
2
- import got from 'got';
2
+ import { ofetch } from 'ofetch';
3
3
  import { fetchItem, fetchItems } from './baseFunctionality.js';
4
4
  import { PlexClient } from './client.js';
5
5
  import { BASE_HEADERS, TIMEOUT, X_PLEX_CONTAINER_SIZE } from './config.js';
@@ -16,7 +16,12 @@ import { Settings } from './settings.js';
16
16
  * can also create an PlexServer instance from :class:`~plexapi.myplex.MyPlexAccount`.
17
17
  */
18
18
  export class PlexServer {
19
- constructor(baseurl, token, timeout) {
19
+ constructor(baseurl, token,
20
+ /**
21
+ * Default request timeout in milliseconds.
22
+ * @default 30000
23
+ */
24
+ timeout = TIMEOUT) {
20
25
  this.baseurl = baseurl;
21
26
  this.token = token;
22
27
  this.timeout = timeout;
@@ -30,7 +35,7 @@ export class PlexServer {
30
35
  return fetchItems(this, key, undefined, Agent, this);
31
36
  }
32
37
  async connect() {
33
- const data = await this.query(this.key, undefined, undefined, this.timeout);
38
+ const data = await this.query(this.key);
34
39
  this._loadData(data.MediaContainer);
35
40
  // Attempt to prevent token from being logged accidentally
36
41
  if (this.token) {
@@ -93,24 +98,24 @@ export class PlexServer {
93
98
  * @param path
94
99
  * @param method
95
100
  * @param headers
96
- * @param timeout
97
101
  */
98
- async query(path, method = 'get', headers, timeout, username, password) {
102
+ async query(path, method = 'get', headers, username, password) {
99
103
  const requestHeaders = this._headers();
100
104
  if (username && password) {
101
105
  const credentials = Buffer.from(`${username}:${password}`).toString('base64');
102
106
  requestHeaders.Authorization = `Basic ${credentials}`;
103
107
  }
104
108
  const url = this.url(path);
105
- const response = await got({
109
+ if (!url.toString().includes('xml')) {
110
+ requestHeaders.accept = 'application/json';
111
+ }
112
+ const response = await ofetch(url.toString(), {
106
113
  method,
107
- url,
108
114
  headers: requestHeaders,
109
- timeout: { request: timeout ?? TIMEOUT },
110
- ...(username ? { username } : {}),
111
- ...(password ? { password } : {}),
112
- retry: { limit: 0 },
113
- }).json();
115
+ timeout: this.timeout ?? TIMEOUT,
116
+ retry: 0,
117
+ responseType: 'json',
118
+ });
114
119
  return response;
115
120
  }
116
121
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl/plex",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "plex api client in typescript",
5
5
  "author": "Scott Cooper <scttcper@gmail.com>",
6
6
  "publishConfig": {
@@ -39,15 +39,15 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@ctrl/mac-address": "^3.0.3",
42
- "got": "^13.0.0",
42
+ "ofetch": "^1.3.4",
43
43
  "p-any": "^4.0.0",
44
- "type-fest": "^4.16.0",
45
- "ws": "^8.16.0",
44
+ "type-fest": "^4.17.0",
45
+ "ws": "^8.17.0",
46
46
  "xml2js": "^0.6.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@biomejs/biome": "1.7.1",
50
- "@ctrl/eslint-config-biome": "2.6.5",
50
+ "@ctrl/eslint-config-biome": "2.6.7",
51
51
  "@sindresorhus/tsconfig": "5.0.0",
52
52
  "@types/lodash": "4.17.0",
53
53
  "@types/micromatch": "4.0.7",
@@ -55,7 +55,7 @@
55
55
  "@types/ws": "8.5.10",
56
56
  "@types/xml2js": "0.4.14",
57
57
  "@types/yargs": "17.0.32",
58
- "@vitest/coverage-v8": "1.5.0",
58
+ "@vitest/coverage-v8": "1.5.2",
59
59
  "delay": "6.0.0",
60
60
  "eslint": "8.57.0",
61
61
  "execa": "8.0.1",
@@ -68,7 +68,7 @@
68
68
  "ts-node": "10.9.2",
69
69
  "typedoc": "0.25.13",
70
70
  "typescript": "5.4.5",
71
- "vitest": "1.5.0",
71
+ "vitest": "1.5.2",
72
72
  "yargs": "17.7.2"
73
73
  },
74
74
  "release": {