@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.
- package/dist/src/client.d.ts +3 -2
- package/dist/src/client.js +11 -9
- package/dist/src/config.d.ts +3 -0
- package/dist/src/config.js +4 -1
- package/dist/src/myplex.d.ts +6 -6
- package/dist/src/myplex.js +22 -23
- package/dist/src/server.d.ts +14 -6
- package/dist/src/server.js +17 -12
- package/package.json +7 -7
package/dist/src/client.d.ts
CHANGED
|
@@ -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(
|
|
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
|
|
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'.
|
package/dist/src/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { URL, URLSearchParams } from 'url';
|
|
2
|
-
import
|
|
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(
|
|
64
|
-
const data = await this.query(this.key
|
|
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
|
|
84
|
+
async query(path, method = 'get', headers) {
|
|
84
85
|
const headersObj = this.headers(headers);
|
|
85
|
-
const response = await
|
|
86
|
+
const response = await ofetch(this.url(path).toString(), {
|
|
86
87
|
method,
|
|
87
|
-
|
|
88
|
-
timeout: { request: timeout ?? TIMEOUT },
|
|
88
|
+
timeout: this.timeout ?? TIMEOUT,
|
|
89
89
|
headers: headersObj,
|
|
90
|
-
|
|
91
|
-
|
|
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;
|
package/dist/src/config.d.ts
CHANGED
|
@@ -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;
|
package/dist/src/config.js
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/src/myplex.d.ts
CHANGED
|
@@ -9,12 +9,12 @@ import { PlexServer } from './server.js';
|
|
|
9
9
|
* and return this object.
|
|
10
10
|
*/
|
|
11
11
|
export declare class MyPlexAccount {
|
|
12
|
-
|
|
12
|
+
baseUrl: string | null;
|
|
13
13
|
username?: string;
|
|
14
|
-
|
|
14
|
+
password?: string;
|
|
15
15
|
token?: string;
|
|
16
|
-
|
|
17
|
-
|
|
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,
|
|
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
|
|
139
|
+
private baseUrl;
|
|
140
140
|
static key: string;
|
|
141
141
|
TAG: string;
|
|
142
142
|
/** Descriptive name of this resource */
|
package/dist/src/myplex.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|
138
|
-
const xml = await parseStringPromise(res.body);
|
|
138
|
+
const xml = await parseStringPromise(body);
|
|
139
139
|
return xml;
|
|
140
140
|
}
|
|
141
|
-
const res =
|
|
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
|
|
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
|
|
164
|
-
method: '
|
|
165
|
-
|
|
166
|
-
timeout: { request: TIMEOUT },
|
|
163
|
+
return ofetch(url, {
|
|
164
|
+
method: 'post',
|
|
165
|
+
timeout: TIMEOUT,
|
|
167
166
|
headers: this._headers(),
|
|
168
|
-
retry:
|
|
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
|
|
182
|
-
const data = await this.query(this.SIGNIN, 'post', undefined,
|
|
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
|
|
267
|
+
await ofetch(key, { method: 'delete', retry: 0 });
|
|
269
268
|
}
|
|
270
269
|
_loadData(data) {
|
|
271
270
|
this.name = data.name;
|
package/dist/src/server.d.ts
CHANGED
|
@@ -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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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,
|
|
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,
|
|
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
|
package/dist/src/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { URL, URLSearchParams } from 'url';
|
|
2
|
-
import
|
|
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,
|
|
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
|
|
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,
|
|
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
|
-
|
|
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:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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": "
|
|
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
|
-
"
|
|
42
|
+
"ofetch": "^1.3.4",
|
|
43
43
|
"p-any": "^4.0.0",
|
|
44
|
-
"type-fest": "^4.
|
|
45
|
-
"ws": "^8.
|
|
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.
|
|
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.
|
|
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.
|
|
71
|
+
"vitest": "1.5.2",
|
|
72
72
|
"yargs": "17.7.2"
|
|
73
73
|
},
|
|
74
74
|
"release": {
|