@ctrl/plex 1.5.3 → 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.
- package/README.md +3 -2
- package/dist/src/alert.d.ts +12 -0
- package/dist/src/alert.js +29 -0
- package/dist/src/alert.types.d.ts +59 -0
- package/dist/src/alert.types.js +1 -0
- package/dist/{base → src/base}/partialPlexObject.d.ts +18 -12
- package/dist/{base → src/base}/partialPlexObject.js +29 -23
- package/dist/{base → src/base}/playable.d.ts +2 -2
- package/dist/src/base/playable.js +8 -0
- package/dist/{base → src/base}/plexObject.d.ts +8 -1
- package/dist/{base → src/base}/plexObject.js +21 -18
- package/dist/{baseFunctionality.d.ts → src/baseFunctionality.d.ts} +17 -1
- package/dist/{baseFunctionality.js → src/baseFunctionality.js} +7 -15
- package/dist/{client.d.ts → src/client.d.ts} +2 -2
- package/dist/{client.js → src/client.js} +12 -20
- package/dist/src/client.types.js +1 -0
- package/dist/src/config.js +35 -0
- package/dist/src/exceptions.d.ts +20 -0
- package/dist/src/exceptions.js +40 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.js +11 -0
- package/dist/{library.d.ts → src/library.d.ts} +207 -21
- package/dist/{library.js → src/library.js} +348 -132
- package/dist/{library.types.d.ts → src/library.types.d.ts} +59 -1
- package/dist/src/library.types.js +1 -0
- package/dist/{media.d.ts → src/media.d.ts} +16 -4
- package/dist/{media.js → src/media.js} +42 -49
- package/dist/src/media.types.d.ts +7 -0
- package/dist/src/media.types.js +1 -0
- package/dist/{myplex.d.ts → src/myplex.d.ts} +16 -6
- package/dist/{myplex.js → src/myplex.js} +71 -57
- package/dist/src/myplex.types.js +10 -0
- package/dist/src/playlist.d.ts +75 -0
- package/dist/src/playlist.js +142 -0
- package/dist/src/playlist.types.d.ts +17 -0
- package/dist/src/playlist.types.js +1 -0
- package/dist/{search.d.ts → src/search.d.ts} +4 -3
- package/dist/{search.js → src/search.js} +13 -19
- package/dist/src/search.types.js +1 -0
- package/dist/{server.d.ts → src/server.d.ts} +22 -10
- package/dist/{server.js → src/server.js} +65 -50
- package/dist/src/server.types.js +1 -0
- package/dist/src/settings.d.ts +79 -0
- package/dist/src/settings.js +160 -0
- package/dist/{util.d.ts → src/util.d.ts} +2 -1
- package/dist/{util.js → src/util.js} +8 -12
- package/dist/{video.d.ts → src/video.d.ts} +38 -60
- package/dist/{video.js → src/video.js} +109 -92
- package/dist/{video.types.d.ts → src/video.types.d.ts} +1 -1
- package/dist/src/video.types.js +6 -0
- package/package.json +46 -44
- package/dist/base/playable.js +0 -12
- package/dist/client.types.js +0 -2
- package/dist/config.js +0 -41
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -23
- package/dist/library.types.js +0 -2
- package/dist/myplex.types.js +0 -13
- package/dist/playlist.d.ts +0 -7
- package/dist/playlist.js +0 -19
- package/dist/search.types.js +0 -2
- package/dist/server.types.js +0 -2
- package/dist/video.types.js +0 -9
- /package/dist/{client.types.d.ts → src/client.types.d.ts} +0 -0
- /package/dist/{config.d.ts → src/config.d.ts} +0 -0
- /package/dist/{myplex.types.d.ts → src/myplex.types.d.ts} +0 -0
- /package/dist/{search.types.d.ts → src/search.types.d.ts} +0 -0
- /package/dist/{server.types.d.ts → src/server.types.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChapterSource, MediaTagData } from './video.types';
|
|
1
|
+
import { ChapterSource, MarkerData, MediaTagData } from './video.types.js';
|
|
2
2
|
export interface LibraryRootResponse {
|
|
3
3
|
size: number;
|
|
4
4
|
allowSync: boolean;
|
|
@@ -107,6 +107,9 @@ export interface MovieData {
|
|
|
107
107
|
Role?: MediaTag[];
|
|
108
108
|
Similar?: MediaTagData[];
|
|
109
109
|
Producer?: MediaTagData[];
|
|
110
|
+
Extras?: ExtrasData[];
|
|
111
|
+
Guid?: Guid[];
|
|
112
|
+
Marker?: MarkerData[];
|
|
110
113
|
}
|
|
111
114
|
export interface MediaTag {
|
|
112
115
|
tag: string;
|
|
@@ -118,6 +121,9 @@ export interface Media {
|
|
|
118
121
|
videoProfile: string;
|
|
119
122
|
Part: Part[];
|
|
120
123
|
}
|
|
124
|
+
export interface Guid {
|
|
125
|
+
id: string;
|
|
126
|
+
}
|
|
121
127
|
export interface Part {
|
|
122
128
|
id: number;
|
|
123
129
|
key: string;
|
|
@@ -189,3 +195,55 @@ export interface CollectionData {
|
|
|
189
195
|
maxYear: string;
|
|
190
196
|
minYear: string;
|
|
191
197
|
}
|
|
198
|
+
export interface ExtrasData {
|
|
199
|
+
ratingKey: string;
|
|
200
|
+
key: string;
|
|
201
|
+
guid: string;
|
|
202
|
+
type: string;
|
|
203
|
+
title: string;
|
|
204
|
+
titleSort: string;
|
|
205
|
+
summary: string;
|
|
206
|
+
index: number;
|
|
207
|
+
thumb: string;
|
|
208
|
+
subtype: string;
|
|
209
|
+
duration: number;
|
|
210
|
+
addedAt: number;
|
|
211
|
+
extraType: number;
|
|
212
|
+
Media: ExtrasMedia[];
|
|
213
|
+
}
|
|
214
|
+
export interface ExtrasMedia {
|
|
215
|
+
id: number;
|
|
216
|
+
duration: number;
|
|
217
|
+
bitrate: number;
|
|
218
|
+
width: number;
|
|
219
|
+
height: number;
|
|
220
|
+
aspectRatio: number;
|
|
221
|
+
audioCodec: string;
|
|
222
|
+
videoCodec: string;
|
|
223
|
+
videoResolution: string;
|
|
224
|
+
container: string;
|
|
225
|
+
optimizedForStreaming: number;
|
|
226
|
+
protocol: string;
|
|
227
|
+
premium: boolean;
|
|
228
|
+
Part: Array<{
|
|
229
|
+
id: number;
|
|
230
|
+
duration: number;
|
|
231
|
+
container: string;
|
|
232
|
+
key: string;
|
|
233
|
+
Stream: ExtrasStream[];
|
|
234
|
+
}>;
|
|
235
|
+
}
|
|
236
|
+
interface ExtrasStream {
|
|
237
|
+
id: number;
|
|
238
|
+
streamType: number;
|
|
239
|
+
codec: string;
|
|
240
|
+
index: number;
|
|
241
|
+
bitrate?: number;
|
|
242
|
+
height?: number;
|
|
243
|
+
width?: number;
|
|
244
|
+
displayTitle: string;
|
|
245
|
+
extendedDisplayTitle: string;
|
|
246
|
+
selected?: boolean;
|
|
247
|
+
channels?: number;
|
|
248
|
+
}
|
|
249
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PlexObject } from './base/plexObject';
|
|
2
|
-
import { ChapterData, MarkerData, MediaData, MediaPartData, MediaPartStreamData } from './video.types';
|
|
1
|
+
import { PlexObject } from './base/plexObject.js';
|
|
2
|
+
import { ChapterData, MarkerData, MediaData, MediaPartData, MediaPartStreamData } from './video.types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Base class for media tags used for filtering and searching your library
|
|
5
5
|
* items or navigating the metadata of media items in your library. Tags are
|
|
@@ -67,7 +67,6 @@ export declare class MediaPart extends PlexObject {
|
|
|
67
67
|
file: string;
|
|
68
68
|
id: number;
|
|
69
69
|
indexes: string;
|
|
70
|
-
key: string;
|
|
71
70
|
size: number;
|
|
72
71
|
optimizedForStreaming: boolean;
|
|
73
72
|
syncItemId: string;
|
|
@@ -134,7 +133,7 @@ export declare class Producer extends MediaTag {
|
|
|
134
133
|
export declare class Marker extends MediaTag {
|
|
135
134
|
static TAG: "Marker";
|
|
136
135
|
FILTER: "marker";
|
|
137
|
-
type: 'intro';
|
|
136
|
+
type: 'intro' | 'credits';
|
|
138
137
|
startTimeOffset: number;
|
|
139
138
|
endTimeOffset: number;
|
|
140
139
|
protected _loadData(data: MarkerData): void;
|
|
@@ -167,4 +166,17 @@ export declare class Optimized extends PlexObject {
|
|
|
167
166
|
targetTagID: any;
|
|
168
167
|
protected _loadData(data: any): void;
|
|
169
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Base class for guid tags used only for Guids, as they contain only a string identifier
|
|
171
|
+
*/
|
|
172
|
+
declare class GuidTag extends PlexObject {
|
|
173
|
+
/**
|
|
174
|
+
* The guid for external metadata sources (e.g. IMDB, TMDB, TVDB). ex - imdb://tt3222784
|
|
175
|
+
*/
|
|
176
|
+
id: string;
|
|
177
|
+
protected _loadData(data: any): void;
|
|
178
|
+
}
|
|
179
|
+
export declare class Guid extends GuidTag {
|
|
180
|
+
static TAG: "Guid";
|
|
181
|
+
}
|
|
170
182
|
export {};
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Optimized = exports.Collection = exports.Chapter = exports.Marker = exports.Producer = exports.Similar = exports.Director = exports.Writer = exports.Country = exports.Genre = exports.Role = exports.MediaPartStream = exports.MediaPart = exports.Media = void 0;
|
|
4
|
-
const plexObject_1 = require("./base/plexObject");
|
|
1
|
+
import { PlexObject } from './base/plexObject.js';
|
|
5
2
|
/**
|
|
6
3
|
* Base class for media tags used for filtering and searching your library
|
|
7
4
|
* items or navigating the metadata of media items in your library. Tags are
|
|
8
5
|
* the construct used for things such as Country, Director, Genre, etc.
|
|
9
6
|
*/
|
|
10
|
-
class MediaTag extends
|
|
7
|
+
class MediaTag extends PlexObject {
|
|
11
8
|
// async items(): Promise<any[]> {
|
|
12
9
|
// if (!this.key) {
|
|
13
10
|
// throw new Error(`Key is not defined for this tag: ${this.tag}`);
|
|
@@ -21,7 +18,8 @@ class MediaTag extends plexObject_1.PlexObject {
|
|
|
21
18
|
this.tag = data.tag;
|
|
22
19
|
}
|
|
23
20
|
}
|
|
24
|
-
class Media extends
|
|
21
|
+
export class Media extends PlexObject {
|
|
22
|
+
static { this.TAG = 'Media'; }
|
|
25
23
|
_loadData(data) {
|
|
26
24
|
this.aspectRatio = data.aspectRatio;
|
|
27
25
|
this.audioChannels = data.audioChannels;
|
|
@@ -40,11 +38,9 @@ class Media extends plexObject_1.PlexObject {
|
|
|
40
38
|
this.parts = data.Part.map(part => new MediaPart(this.server, part, undefined, this));
|
|
41
39
|
}
|
|
42
40
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class MediaPart extends plexObject_1.PlexObject {
|
|
41
|
+
export class MediaPart extends PlexObject {
|
|
42
|
+
static { this.TAG = 'Part'; }
|
|
46
43
|
_loadData(data) {
|
|
47
|
-
var _a, _b;
|
|
48
44
|
this.container = data.container;
|
|
49
45
|
this.duration = data.duration;
|
|
50
46
|
this.file = data.file;
|
|
@@ -55,12 +51,11 @@ class MediaPart extends plexObject_1.PlexObject {
|
|
|
55
51
|
this.videoProfile = data.videoProfile;
|
|
56
52
|
this.exists = data.exists;
|
|
57
53
|
this.streams =
|
|
58
|
-
|
|
54
|
+
data.Stream?.map(stream => new MediaPartStream(this.server, stream, undefined, this)) ?? [];
|
|
59
55
|
}
|
|
60
56
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class MediaPartStream extends plexObject_1.PlexObject {
|
|
57
|
+
export class MediaPartStream extends PlexObject {
|
|
58
|
+
static { this.TAG = 'Stream'; }
|
|
64
59
|
_loadData(data) {
|
|
65
60
|
this.id = data.id;
|
|
66
61
|
this.codec = data.codec;
|
|
@@ -71,120 +66,109 @@ class MediaPartStream extends plexObject_1.PlexObject {
|
|
|
71
66
|
this.streamType = data.streamType;
|
|
72
67
|
}
|
|
73
68
|
}
|
|
74
|
-
exports.MediaPartStream = MediaPartStream;
|
|
75
|
-
MediaPartStream.TAG = 'Stream';
|
|
76
69
|
/**
|
|
77
70
|
* Represents a single Role (actor/actress) media tag.
|
|
78
71
|
*/
|
|
79
|
-
class Role extends MediaTag {
|
|
72
|
+
export class Role extends MediaTag {
|
|
80
73
|
constructor() {
|
|
81
74
|
super(...arguments);
|
|
82
75
|
this.FILTER = 'role';
|
|
83
76
|
}
|
|
77
|
+
static { this.TAG = 'Role'; }
|
|
84
78
|
}
|
|
85
|
-
exports.Role = Role;
|
|
86
|
-
Role.TAG = 'Role';
|
|
87
79
|
/**
|
|
88
80
|
* Represents a single Genre media tag.
|
|
89
81
|
*/
|
|
90
|
-
class Genre extends MediaTag {
|
|
82
|
+
export class Genre extends MediaTag {
|
|
91
83
|
constructor() {
|
|
92
84
|
super(...arguments);
|
|
93
85
|
this.FILTER = 'genre';
|
|
94
86
|
}
|
|
87
|
+
static { this.TAG = 'Genre'; }
|
|
95
88
|
}
|
|
96
|
-
exports.Genre = Genre;
|
|
97
|
-
Genre.TAG = 'Genre';
|
|
98
89
|
/**
|
|
99
90
|
* Represents a single Country media tag.
|
|
100
91
|
*/
|
|
101
|
-
class Country extends MediaTag {
|
|
92
|
+
export class Country extends MediaTag {
|
|
102
93
|
constructor() {
|
|
103
94
|
super(...arguments);
|
|
104
95
|
this.FILTER = 'country';
|
|
105
96
|
}
|
|
97
|
+
static { this.TAG = 'Country'; }
|
|
106
98
|
}
|
|
107
|
-
exports.Country = Country;
|
|
108
|
-
Country.TAG = 'Country';
|
|
109
99
|
/**
|
|
110
100
|
* Represents a single Writer media tag.
|
|
111
101
|
*/
|
|
112
|
-
class Writer extends MediaTag {
|
|
102
|
+
export class Writer extends MediaTag {
|
|
113
103
|
constructor() {
|
|
114
104
|
super(...arguments);
|
|
115
105
|
this.FILTER = 'writer';
|
|
116
106
|
}
|
|
107
|
+
static { this.TAG = 'Writer'; }
|
|
117
108
|
}
|
|
118
|
-
exports.Writer = Writer;
|
|
119
|
-
Writer.TAG = 'Writer';
|
|
120
109
|
/**
|
|
121
110
|
* Represents a single Director media tag.
|
|
122
111
|
*/
|
|
123
|
-
class Director extends MediaTag {
|
|
112
|
+
export class Director extends MediaTag {
|
|
124
113
|
constructor() {
|
|
125
114
|
super(...arguments);
|
|
126
115
|
this.FILTER = 'director';
|
|
127
116
|
}
|
|
117
|
+
static { this.TAG = 'Director'; }
|
|
128
118
|
}
|
|
129
|
-
|
|
130
|
-
Director.TAG = 'Director';
|
|
131
|
-
class Similar extends MediaTag {
|
|
119
|
+
export class Similar extends MediaTag {
|
|
132
120
|
constructor() {
|
|
133
121
|
super(...arguments);
|
|
134
122
|
this.FILTER = 'similar';
|
|
135
123
|
}
|
|
124
|
+
static { this.TAG = 'Similar'; }
|
|
136
125
|
}
|
|
137
|
-
|
|
138
|
-
Similar.TAG = 'Similar';
|
|
139
|
-
class Producer extends MediaTag {
|
|
126
|
+
export class Producer extends MediaTag {
|
|
140
127
|
constructor() {
|
|
141
128
|
super(...arguments);
|
|
142
129
|
this.FILTER = 'producer';
|
|
143
130
|
}
|
|
131
|
+
static { this.TAG = 'Producer'; }
|
|
144
132
|
}
|
|
145
|
-
|
|
146
|
-
Producer.TAG = 'Producer';
|
|
147
|
-
class Marker extends MediaTag {
|
|
133
|
+
export class Marker extends MediaTag {
|
|
148
134
|
constructor() {
|
|
149
135
|
super(...arguments);
|
|
150
136
|
this.FILTER = 'marker';
|
|
151
137
|
}
|
|
138
|
+
static { this.TAG = 'Marker'; }
|
|
152
139
|
_loadData(data) {
|
|
153
140
|
this.type = data.type;
|
|
154
141
|
this.startTimeOffset = data.startTimeOffset;
|
|
155
142
|
this.endTimeOffset = data.endTimeOffset;
|
|
156
143
|
}
|
|
157
144
|
}
|
|
158
|
-
exports.Marker = Marker;
|
|
159
|
-
Marker.TAG = 'Marker';
|
|
160
145
|
/**
|
|
161
146
|
* Represents a single Chapter media tag.
|
|
162
147
|
*/
|
|
163
|
-
class Chapter extends MediaTag {
|
|
148
|
+
export class Chapter extends MediaTag {
|
|
164
149
|
constructor() {
|
|
165
150
|
super(...arguments);
|
|
166
151
|
this.FILTER = 'chapter';
|
|
167
152
|
}
|
|
153
|
+
static { this.TAG = 'Chapter'; }
|
|
168
154
|
_loadData(data) {
|
|
169
155
|
this.startTimeOffset = data.startTimeOffset;
|
|
170
156
|
this.endTimeOffset = data.endTimeOffset;
|
|
171
157
|
this.thumb = data.thumb;
|
|
172
158
|
}
|
|
173
159
|
}
|
|
174
|
-
exports.Chapter = Chapter;
|
|
175
|
-
Chapter.TAG = 'Chapter';
|
|
176
160
|
/**
|
|
177
161
|
* Represents a single Collection media tag.
|
|
178
162
|
*/
|
|
179
|
-
class Collection extends MediaTag {
|
|
163
|
+
export class Collection extends MediaTag {
|
|
180
164
|
constructor() {
|
|
181
165
|
super(...arguments);
|
|
182
166
|
this.FILTER = 'collection';
|
|
183
167
|
}
|
|
168
|
+
static { this.TAG = 'Collection'; }
|
|
184
169
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
class Optimized extends plexObject_1.PlexObject {
|
|
170
|
+
export class Optimized extends PlexObject {
|
|
171
|
+
static { this.TAG = 'Item'; }
|
|
188
172
|
_loadData(data) {
|
|
189
173
|
this.id = data.id;
|
|
190
174
|
this.composite = data.composite;
|
|
@@ -194,5 +178,14 @@ class Optimized extends plexObject_1.PlexObject {
|
|
|
194
178
|
this.targetTagID = data.targetTagID;
|
|
195
179
|
}
|
|
196
180
|
}
|
|
197
|
-
|
|
198
|
-
|
|
181
|
+
/**
|
|
182
|
+
* Base class for guid tags used only for Guids, as they contain only a string identifier
|
|
183
|
+
*/
|
|
184
|
+
class GuidTag extends PlexObject {
|
|
185
|
+
_loadData(data) {
|
|
186
|
+
this.id = data.id;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export class Guid extends GuidTag {
|
|
190
|
+
static { this.TAG = 'Guid'; }
|
|
191
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { PlexObject } from './base/plexObject.js';
|
|
2
|
+
import { Connection, Device, ResourcesResponse } from './myplex.types.js';
|
|
3
|
+
import { PlexServer } from './server.js';
|
|
4
4
|
/**
|
|
5
5
|
* MyPlex account and profile information. This object represents the data found Account on
|
|
6
6
|
* the myplex.tv servers at the url https://plex.tv/users/account. You may create this object
|
|
@@ -10,9 +10,9 @@ import { PlexObject } from './base/plexObject';
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class MyPlexAccount {
|
|
12
12
|
private readonly baseUrl;
|
|
13
|
-
username?: string
|
|
13
|
+
username?: string;
|
|
14
14
|
private readonly password?;
|
|
15
|
-
token?: string
|
|
15
|
+
token?: string;
|
|
16
16
|
private readonly timeout;
|
|
17
17
|
private readonly server?;
|
|
18
18
|
static key: string;
|
|
@@ -82,7 +82,7 @@ export declare class MyPlexAccount {
|
|
|
82
82
|
* @param timeout timeout in seconds on initial connect to myplex
|
|
83
83
|
* @param server not often available
|
|
84
84
|
*/
|
|
85
|
-
constructor(baseUrl?: string | null, username?: string
|
|
85
|
+
constructor(baseUrl?: string | null, username?: string, password?: string, token?: string, timeout?: number, server?: PlexServer);
|
|
86
86
|
/**
|
|
87
87
|
* Returns a new :class:`~server.PlexServer` or :class:`~client.PlexClient` object.
|
|
88
88
|
* Often times there is more than one address specified for a server or client.
|
|
@@ -96,6 +96,11 @@ export declare class MyPlexAccount {
|
|
|
96
96
|
*/
|
|
97
97
|
resource(name: string): Promise<MyPlexResource>;
|
|
98
98
|
resources(): Promise<MyPlexResource[]>;
|
|
99
|
+
/**
|
|
100
|
+
* @param name Name to match against.
|
|
101
|
+
* @param clientId clientIdentifier to match against.
|
|
102
|
+
*/
|
|
103
|
+
device(name?: string, clientId?: string): Promise<MyPlexDevice>;
|
|
99
104
|
/**
|
|
100
105
|
* Returns a list of all :class:`~plexapi.myplex.MyPlexDevice` objects connected to the server.
|
|
101
106
|
*/
|
|
@@ -218,5 +223,10 @@ export declare class MyPlexDevice extends PlexObject {
|
|
|
218
223
|
lastSeenAt: Date;
|
|
219
224
|
/** List of connection URIs for the device. */
|
|
220
225
|
connections?: string[];
|
|
226
|
+
connect(): Promise<PlexServer>;
|
|
227
|
+
/**
|
|
228
|
+
* Remove this device from your account
|
|
229
|
+
*/
|
|
230
|
+
delete(): Promise<void>;
|
|
221
231
|
protected _loadData(data: Device): void;
|
|
222
232
|
}
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const url_1 = require("url");
|
|
9
|
-
const p_any_1 = __importDefault(require("p-any"));
|
|
10
|
-
const config_1 = require("./config");
|
|
11
|
-
const server_1 = require("./server");
|
|
12
|
-
const plexObject_1 = require("./base/plexObject");
|
|
13
|
-
const xml2js_1 = require("xml2js");
|
|
1
|
+
import { URL, URLSearchParams } from 'url';
|
|
2
|
+
import got from 'got';
|
|
3
|
+
import pAny from 'p-any';
|
|
4
|
+
import { parseStringPromise } from 'xml2js';
|
|
5
|
+
import { PlexObject } from './base/plexObject.js';
|
|
6
|
+
import { BASE_HEADERS, TIMEOUT } from './config.js';
|
|
7
|
+
import { PlexServer } from './server.js';
|
|
14
8
|
/**
|
|
15
9
|
* MyPlex account and profile information. This object represents the data found Account on
|
|
16
10
|
* the myplex.tv servers at the url https://plex.tv/users/account. You may create this object
|
|
@@ -18,7 +12,8 @@ const xml2js_1 = require("xml2js");
|
|
|
18
12
|
* method provided at :class:`~plexapi.server.PlexServer.myPlexAccount()` which will create
|
|
19
13
|
* and return this object.
|
|
20
14
|
*/
|
|
21
|
-
class MyPlexAccount {
|
|
15
|
+
export class MyPlexAccount {
|
|
16
|
+
static { this.key = 'https://plex.tv/api/v2/user'; }
|
|
22
17
|
/**
|
|
23
18
|
*
|
|
24
19
|
* @param username Your MyPlex username
|
|
@@ -28,7 +23,7 @@ class MyPlexAccount {
|
|
|
28
23
|
* @param timeout timeout in seconds on initial connect to myplex
|
|
29
24
|
* @param server not often available
|
|
30
25
|
*/
|
|
31
|
-
constructor(baseUrl = null, username, password, token, timeout =
|
|
26
|
+
constructor(baseUrl = null, username, password, token, timeout = TIMEOUT, server) {
|
|
32
27
|
this.baseUrl = baseUrl;
|
|
33
28
|
this.username = username;
|
|
34
29
|
this.password = password;
|
|
@@ -94,6 +89,18 @@ class MyPlexAccount {
|
|
|
94
89
|
const data = await this.query(MyPlexResource.key);
|
|
95
90
|
return data.map(device => new MyPlexResource(this, device, this.baseUrl));
|
|
96
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* @param name Name to match against.
|
|
94
|
+
* @param clientId clientIdentifier to match against.
|
|
95
|
+
*/
|
|
96
|
+
async device(name = '', clientId) {
|
|
97
|
+
const devices = await this.devices();
|
|
98
|
+
const device = devices.find(device => device.name?.toLowerCase() === name.toLowerCase() || device.clientIdentifier === clientId);
|
|
99
|
+
if (!device) {
|
|
100
|
+
throw new Error('Unable to find device');
|
|
101
|
+
}
|
|
102
|
+
return device;
|
|
103
|
+
}
|
|
97
104
|
/**
|
|
98
105
|
* Returns a list of all :class:`~plexapi.myplex.MyPlexDevice` objects connected to the server.
|
|
99
106
|
*/
|
|
@@ -117,18 +124,18 @@ class MyPlexAccount {
|
|
|
117
124
|
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
|
118
125
|
requestHeaders.Authorization = `Basic ${credentials}`;
|
|
119
126
|
}
|
|
120
|
-
const promise =
|
|
127
|
+
const promise = got({
|
|
121
128
|
method,
|
|
122
|
-
url: new
|
|
129
|
+
url: new URL(url),
|
|
123
130
|
headers: requestHeaders,
|
|
124
|
-
timeout:
|
|
125
|
-
username,
|
|
126
|
-
password,
|
|
127
|
-
retry: 0,
|
|
131
|
+
timeout: { request: timeout ?? TIMEOUT },
|
|
132
|
+
...(username ? { username } : {}),
|
|
133
|
+
...(password ? { password } : {}),
|
|
134
|
+
retry: { limit: 0 },
|
|
128
135
|
});
|
|
129
136
|
if (url.includes('xml')) {
|
|
130
137
|
const res = await promise;
|
|
131
|
-
const xml = await
|
|
138
|
+
const xml = await parseStringPromise(res.body);
|
|
132
139
|
return xml;
|
|
133
140
|
}
|
|
134
141
|
const res = await promise.json();
|
|
@@ -141,29 +148,29 @@ class MyPlexAccount {
|
|
|
141
148
|
*/
|
|
142
149
|
async claimToken() {
|
|
143
150
|
const url = 'https://plex.tv/api/claim/token.json';
|
|
144
|
-
const response = await this.query(url, 'get', undefined,
|
|
151
|
+
const response = await this.query(url, 'get', undefined, TIMEOUT);
|
|
145
152
|
return response.token;
|
|
146
153
|
}
|
|
147
154
|
/**
|
|
148
155
|
* @param token pass token from claimToken
|
|
149
156
|
*/
|
|
150
157
|
async claimServer(token) {
|
|
151
|
-
const params = new
|
|
158
|
+
const params = new URLSearchParams({
|
|
152
159
|
token,
|
|
153
|
-
...
|
|
160
|
+
...BASE_HEADERS,
|
|
154
161
|
});
|
|
155
162
|
const url = `${this.baseUrl}/myplex/claim?${params.toString()}`;
|
|
156
|
-
return
|
|
163
|
+
return got({
|
|
157
164
|
method: 'POST',
|
|
158
165
|
url,
|
|
159
|
-
timeout:
|
|
166
|
+
timeout: { request: TIMEOUT },
|
|
160
167
|
headers: this._headers(),
|
|
161
|
-
retry: 0,
|
|
168
|
+
retry: { limit: 0 },
|
|
162
169
|
});
|
|
163
170
|
}
|
|
164
171
|
_headers() {
|
|
165
172
|
const headers = {
|
|
166
|
-
...
|
|
173
|
+
...BASE_HEADERS,
|
|
167
174
|
'Content-type': 'application/json',
|
|
168
175
|
};
|
|
169
176
|
if (this.token) {
|
|
@@ -176,7 +183,6 @@ class MyPlexAccount {
|
|
|
176
183
|
return data.user;
|
|
177
184
|
}
|
|
178
185
|
_loadData(user) {
|
|
179
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
180
186
|
// Attempt to prevent token from being logged accidentally
|
|
181
187
|
Object.defineProperty(this, 'token', {
|
|
182
188
|
enumerable: false,
|
|
@@ -194,21 +200,19 @@ class MyPlexAccount {
|
|
|
194
200
|
this.username = user.username;
|
|
195
201
|
this.title = user.title;
|
|
196
202
|
this.locale = user.locale;
|
|
197
|
-
this.mailingListStatus =
|
|
203
|
+
this.mailingListStatus = user.mailingListStatus ?? 'inactive';
|
|
198
204
|
this.mailingListActive = user.mailingListActive;
|
|
199
205
|
this.queueEmail = user.queueEmail;
|
|
200
206
|
this.thumb = user.thumb;
|
|
201
207
|
this.scrobbleTypes = user.scrobbleTypes;
|
|
202
208
|
this.restricted = user.restricted;
|
|
203
|
-
this.subscriptionActive =
|
|
204
|
-
this.subscriptionStatus =
|
|
205
|
-
this.subscriptionPlan =
|
|
206
|
-
this.subscriptionFeatures =
|
|
209
|
+
this.subscriptionActive = user.subscription?.active ?? null;
|
|
210
|
+
this.subscriptionStatus = user.subscription?.status?.toLowerCase() ?? 'inactive';
|
|
211
|
+
this.subscriptionPlan = user.subscription?.plan ?? null;
|
|
212
|
+
this.subscriptionFeatures = user.subscription?.features ?? [];
|
|
207
213
|
this.entitlements = user.entitlements;
|
|
208
214
|
}
|
|
209
215
|
}
|
|
210
|
-
exports.MyPlexAccount = MyPlexAccount;
|
|
211
|
-
MyPlexAccount.key = 'https://plex.tv/api/v2/user';
|
|
212
216
|
/**
|
|
213
217
|
* Connects to the specified cls with url and token
|
|
214
218
|
*/
|
|
@@ -221,7 +225,8 @@ async function connect(cls, url, token, timeout) {
|
|
|
221
225
|
* This object represents resources connected to your Plex server that can provide
|
|
222
226
|
* content such as Plex Media Servers, iPhone or Android clients, etc.
|
|
223
227
|
*/
|
|
224
|
-
class MyPlexResource {
|
|
228
|
+
export class MyPlexResource {
|
|
229
|
+
static { this.key = 'https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1'; }
|
|
225
230
|
constructor(account, data, baseUrl = null) {
|
|
226
231
|
this.account = account;
|
|
227
232
|
this.baseUrl = baseUrl;
|
|
@@ -255,19 +260,18 @@ class MyPlexResource {
|
|
|
255
260
|
// TODO: switch between PlexServer and PlexClient
|
|
256
261
|
// Try connecting to all known resource connections in parellel, but
|
|
257
262
|
// only return the first server (in order) that provides a response.
|
|
258
|
-
const promises = attemptUrls.map(async (url) => connect((...args) => new
|
|
259
|
-
const result = await
|
|
263
|
+
const promises = attemptUrls.map(async (url) => connect((...args) => new PlexServer(...args), url, this.accessToken, timeout));
|
|
264
|
+
const result = await pAny(promises);
|
|
260
265
|
return result;
|
|
261
266
|
}
|
|
262
267
|
/** Remove this device from your account */
|
|
263
268
|
async delete() {
|
|
264
|
-
const key = `https://plex.tv/api/servers/${this.clientIdentifier}?X-Plex-Client-Identifier=${
|
|
265
|
-
await
|
|
269
|
+
const key = `https://plex.tv/api/servers/${this.clientIdentifier}?X-Plex-Client-Identifier=${BASE_HEADERS['X-Plex-Client-Identifier']}&X-Plex-Token=${this.accessToken}`;
|
|
270
|
+
await got.delete(key, { retry: { limit: 0 } });
|
|
266
271
|
}
|
|
267
272
|
_loadData(data) {
|
|
268
|
-
var _a, _b, _c;
|
|
269
273
|
this.name = data.name;
|
|
270
|
-
this.accessToken =
|
|
274
|
+
this.accessToken = data.accessToken ?? '';
|
|
271
275
|
this.owned = data.owned;
|
|
272
276
|
this.clientIdentifier = data.clientIdentifier;
|
|
273
277
|
this.createdAt = new Date(data.createdAt);
|
|
@@ -282,12 +286,10 @@ class MyPlexResource {
|
|
|
282
286
|
this.product = data.product;
|
|
283
287
|
this.productVersion = data.productVersion;
|
|
284
288
|
this.connections =
|
|
285
|
-
|
|
289
|
+
data.connections?.map(connection => new ResourceConnection(connection)) ?? [];
|
|
286
290
|
}
|
|
287
291
|
}
|
|
288
|
-
|
|
289
|
-
MyPlexResource.key = 'https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1';
|
|
290
|
-
class ResourceConnection {
|
|
292
|
+
export class ResourceConnection {
|
|
291
293
|
constructor(data) {
|
|
292
294
|
this.TAG = 'Connection';
|
|
293
295
|
this._loadData(data);
|
|
@@ -301,16 +303,31 @@ class ResourceConnection {
|
|
|
301
303
|
this.httpuri = `http://${data.address}:${data.port}`;
|
|
302
304
|
}
|
|
303
305
|
}
|
|
304
|
-
exports.ResourceConnection = ResourceConnection;
|
|
305
306
|
/**
|
|
306
307
|
* This object represents resources connected to your Plex server that provide
|
|
307
308
|
* playback ability from your Plex Server, iPhone or Android clients, Plex Web,
|
|
308
309
|
* this API, etc. The raw xml for the data presented here can be found at:
|
|
309
310
|
* https://plex.tv/devices.xml
|
|
310
311
|
*/
|
|
311
|
-
class MyPlexDevice extends
|
|
312
|
+
export class MyPlexDevice extends PlexObject {
|
|
313
|
+
static { this.TAG = 'Device'; }
|
|
314
|
+
static { this.key = 'https://plex.tv/devices.xml'; }
|
|
315
|
+
async connect() {
|
|
316
|
+
// TODO: switch between PlexServer and PlexClient
|
|
317
|
+
// Try connecting to all known resource connections in parellel, but
|
|
318
|
+
// only return the first server (in order) that provides a response.
|
|
319
|
+
const promises = (this.connections ?? []).map(async (url) => connect((...args) => new PlexServer(...args), url, this.token));
|
|
320
|
+
const result = await pAny(promises);
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Remove this device from your account
|
|
325
|
+
*/
|
|
326
|
+
async delete() {
|
|
327
|
+
const key = `https://plex.tv/devices/${this.id}.xml`;
|
|
328
|
+
await this.server.query(key, 'delete');
|
|
329
|
+
}
|
|
312
330
|
_loadData(data) {
|
|
313
|
-
var _a;
|
|
314
331
|
this.name = data.$.name;
|
|
315
332
|
this.publicAddress = data.$.publicAddress;
|
|
316
333
|
this.product = data.$.product;
|
|
@@ -332,11 +349,8 @@ class MyPlexDevice extends plexObject_1.PlexObject {
|
|
|
332
349
|
});
|
|
333
350
|
this.screenResolution = data.$.screenResolution;
|
|
334
351
|
this.screenDensity = data.$.screenDensity;
|
|
335
|
-
this.createdAt = new Date(data.$.createdAt);
|
|
336
|
-
this.lastSeenAt = new Date(data.$.lastSeenAt);
|
|
337
|
-
this.connections =
|
|
352
|
+
this.createdAt = new Date(parseInt(data.$.createdAt, 10));
|
|
353
|
+
this.lastSeenAt = new Date(parseInt(data.$.lastSeenAt, 10));
|
|
354
|
+
this.connections = data.Connection?.map(connection => connection.$.uri);
|
|
338
355
|
}
|
|
339
356
|
}
|
|
340
|
-
exports.MyPlexDevice = MyPlexDevice;
|
|
341
|
-
MyPlexDevice.TAG = 'Device';
|
|
342
|
-
MyPlexDevice.key = 'https://plex.tv/devices.xml';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export var Status;
|
|
2
|
+
(function (Status) {
|
|
3
|
+
Status["Online"] = "online";
|
|
4
|
+
Status["Offline"] = "offline";
|
|
5
|
+
})(Status || (Status = {}));
|
|
6
|
+
export var Protocol;
|
|
7
|
+
(function (Protocol) {
|
|
8
|
+
Protocol["HTTP"] = "http";
|
|
9
|
+
Protocol["HTTPS"] = "https";
|
|
10
|
+
})(Protocol || (Protocol = {}));
|