@ctrl/plex 3.1.0 → 3.3.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/media.d.ts +42 -0
- package/dist/src/media.js +49 -0
- package/dist/src/server.d.ts +4 -1
- package/dist/src/server.js +2 -1
- package/dist/src/video.d.ts +22 -1
- package/dist/src/video.js +33 -1
- package/package.json +1 -1
package/dist/src/media.d.ts
CHANGED
|
@@ -200,4 +200,46 @@ export declare class Rating extends PlexObject {
|
|
|
200
200
|
value: number;
|
|
201
201
|
protected _loadData(data: any): void;
|
|
202
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Base class for all Art, Poster, and Theme objects.
|
|
205
|
+
*/
|
|
206
|
+
declare abstract class BaseResource extends PlexObject {
|
|
207
|
+
/**
|
|
208
|
+
* The source of the resource. 'local' for local files (e.g. theme.mp3),
|
|
209
|
+
*/
|
|
210
|
+
provider: string;
|
|
211
|
+
/**
|
|
212
|
+
* Unique key identifying the resource.
|
|
213
|
+
*/
|
|
214
|
+
ratingKey: string;
|
|
215
|
+
/**
|
|
216
|
+
* True if the resource is currently selected.
|
|
217
|
+
*/
|
|
218
|
+
selected: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* The URL to retrieve the resource thumbnail.
|
|
221
|
+
*/
|
|
222
|
+
thumb: string;
|
|
223
|
+
select(): Promise<any>;
|
|
224
|
+
resourceFilepath(): string;
|
|
225
|
+
protected _loadData(data: any): void;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Represents a single Art object.
|
|
229
|
+
*/
|
|
230
|
+
export declare class Art extends BaseResource {
|
|
231
|
+
static TAG: string;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Represents a single Poster object.
|
|
235
|
+
*/
|
|
236
|
+
export declare class Poster extends BaseResource {
|
|
237
|
+
static TAG: string;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Represents a single Theme object.
|
|
241
|
+
*/
|
|
242
|
+
export declare class Theme extends BaseResource {
|
|
243
|
+
static TAG: string;
|
|
244
|
+
}
|
|
203
245
|
export {};
|
package/dist/src/media.js
CHANGED
|
@@ -200,3 +200,52 @@ export class Rating extends PlexObject {
|
|
|
200
200
|
this.value = data.value;
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Base class for all Art, Poster, and Theme objects.
|
|
205
|
+
*/
|
|
206
|
+
class BaseResource extends PlexObject {
|
|
207
|
+
async select() {
|
|
208
|
+
const key = this.key.slice(0, -1);
|
|
209
|
+
const params = new URLSearchParams();
|
|
210
|
+
params.append('url', this.ratingKey);
|
|
211
|
+
return this.server.query(`${key}?${params.toString()}`, 'put');
|
|
212
|
+
}
|
|
213
|
+
resourceFilepath() {
|
|
214
|
+
if (this.ratingKey.startsWith('media://')) {
|
|
215
|
+
return `Media/localhost/${this.ratingKey.split('://')[1]}`;
|
|
216
|
+
}
|
|
217
|
+
const parent = this.parent?.deref();
|
|
218
|
+
if (this.ratingKey.startsWith('metadata://') && parent) {
|
|
219
|
+
return `${parent.metadataDirectory}/Contents/_combined/${this.ratingKey.split('://')[1]}`;
|
|
220
|
+
}
|
|
221
|
+
if (this.ratingKey.startsWith('upload://') && parent) {
|
|
222
|
+
return `${parent.metadataDirectory}/Uploads/${this.ratingKey.split('://')[1]}`;
|
|
223
|
+
}
|
|
224
|
+
return this.ratingKey;
|
|
225
|
+
}
|
|
226
|
+
_loadData(data) {
|
|
227
|
+
this.key = data.key;
|
|
228
|
+
this.provider = data.provider;
|
|
229
|
+
this.ratingKey = data.ratingKey;
|
|
230
|
+
this.selected = data.selected;
|
|
231
|
+
this.thumb = data.thumb;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Represents a single Art object.
|
|
236
|
+
*/
|
|
237
|
+
export class Art extends BaseResource {
|
|
238
|
+
static { this.TAG = 'Art'; }
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Represents a single Poster object.
|
|
242
|
+
*/
|
|
243
|
+
export class Poster extends BaseResource {
|
|
244
|
+
static { this.TAG = 'Photo'; }
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Represents a single Theme object.
|
|
248
|
+
*/
|
|
249
|
+
export class Theme extends BaseResource {
|
|
250
|
+
static { this.TAG = 'Theme'; }
|
|
251
|
+
}
|
package/dist/src/server.d.ts
CHANGED
|
@@ -172,7 +172,10 @@ export declare class PlexServer {
|
|
|
172
172
|
* @param method
|
|
173
173
|
* @param headers
|
|
174
174
|
*/
|
|
175
|
-
query<T = any>(path: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete',
|
|
175
|
+
query<T = any>(path: string, method?: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete', options?: {
|
|
176
|
+
headers?: Record<string, string>;
|
|
177
|
+
body?: Uint8Array;
|
|
178
|
+
}, username?: string, password?: string): Promise<T>;
|
|
176
179
|
/**
|
|
177
180
|
* Returns a list of media items from watched history. If there are many results, they will
|
|
178
181
|
* be fetched from the server in batches of X_PLEX_CONTAINER_SIZE amounts. If you're only
|
package/dist/src/server.js
CHANGED
|
@@ -99,7 +99,7 @@ export class PlexServer {
|
|
|
99
99
|
* @param method
|
|
100
100
|
* @param headers
|
|
101
101
|
*/
|
|
102
|
-
async query(path, method = 'get',
|
|
102
|
+
async query(path, method = 'get', options = {}, username, password) {
|
|
103
103
|
const requestHeaders = this._headers();
|
|
104
104
|
if (username && password) {
|
|
105
105
|
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
|
@@ -113,6 +113,7 @@ export class PlexServer {
|
|
|
113
113
|
method,
|
|
114
114
|
headers: requestHeaders,
|
|
115
115
|
timeout: this.timeout ?? TIMEOUT,
|
|
116
|
+
body: options.body,
|
|
116
117
|
retry: 0,
|
|
117
118
|
responseType: 'json',
|
|
118
119
|
});
|
package/dist/src/video.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { URL } from 'url';
|
|
3
3
|
import { Playable } from './base/playable.js';
|
|
4
4
|
import { ExtrasData, FullShowData, MovieData, ShowData } from './library.types.js';
|
|
5
|
-
import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Producer, Rating, Role, Similar, Writer } from './media.js';
|
|
5
|
+
import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Poster, Producer, Rating, Role, Similar, Writer } from './media.js';
|
|
6
6
|
import { ChapterSource, EpisodeMetadata, FullMovieResponse } from './video.types.js';
|
|
7
7
|
export type VideoType = Movie | Show;
|
|
8
8
|
declare abstract class Video extends Playable {
|
|
@@ -24,6 +24,14 @@ declare abstract class Video extends Playable {
|
|
|
24
24
|
viewCount?: number;
|
|
25
25
|
art?: string;
|
|
26
26
|
grandparentArt?: string;
|
|
27
|
+
/**
|
|
28
|
+
* BlurHash string for artwork image.
|
|
29
|
+
*/
|
|
30
|
+
artBlurHash?: string;
|
|
31
|
+
/**
|
|
32
|
+
* BlurHash string for thumbnail image.
|
|
33
|
+
*/
|
|
34
|
+
thumbBlurHash?: string;
|
|
27
35
|
/**
|
|
28
36
|
* Returns True if this video is watched.
|
|
29
37
|
*/
|
|
@@ -44,6 +52,19 @@ declare abstract class Video extends Playable {
|
|
|
44
52
|
markUnwatched(): Promise<void>;
|
|
45
53
|
rate(rate: number): Promise<void>;
|
|
46
54
|
extras(): Promise<Extra[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Returns list of available Poster objects.
|
|
57
|
+
*/
|
|
58
|
+
posters(): Promise<Poster[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Set the poster for a Plex object.
|
|
61
|
+
* @param poster The poster object to select.
|
|
62
|
+
*/
|
|
63
|
+
setPoster(poster: Poster): Promise<this>;
|
|
64
|
+
/**
|
|
65
|
+
* I haven't tested this yet. It may not work.
|
|
66
|
+
*/
|
|
67
|
+
uploadPoster(url?: string, file?: Uint8Array): Promise<void>;
|
|
47
68
|
protected _loadData(data: MovieData | ShowData | EpisodeMetadata): void;
|
|
48
69
|
}
|
|
49
70
|
/**
|
package/dist/src/video.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Playable } from './base/playable.js';
|
|
2
2
|
import { fetchItem, fetchItems, findItems } from './baseFunctionality.js';
|
|
3
|
-
import { Chapter, Collection, Country, Director, Genre, Guid, Marker, Media, Producer, Rating, Role, Similar, Writer, } from './media.js';
|
|
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
5
|
constructor() {
|
|
6
6
|
super(...arguments);
|
|
@@ -53,6 +53,35 @@ class Video extends Playable {
|
|
|
53
53
|
const data = await this.server.query(this._detailsKey);
|
|
54
54
|
return findItems(data.MediaContainer.Metadata[0].Extras?.Metadata, undefined, Extra, this.server, this);
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns list of available Poster objects.
|
|
58
|
+
*/
|
|
59
|
+
async posters() {
|
|
60
|
+
return fetchItems(this.server, `/library/metadata/${this.ratingKey}/posters`, undefined, Poster);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Set the poster for a Plex object.
|
|
64
|
+
* @param poster The poster object to select.
|
|
65
|
+
*/
|
|
66
|
+
async setPoster(poster) {
|
|
67
|
+
await poster.select();
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* I haven't tested this yet. It may not work.
|
|
72
|
+
*/
|
|
73
|
+
async uploadPoster(url, file) {
|
|
74
|
+
if (url) {
|
|
75
|
+
const key = `/library/metadata/${this.ratingKey}/posters?url=${encodeURIComponent(url)}`;
|
|
76
|
+
await this.server.query(key, 'post');
|
|
77
|
+
}
|
|
78
|
+
else if (file) {
|
|
79
|
+
const key = `/library/metadata/${this.ratingKey}/posters`;
|
|
80
|
+
await this.server.query(key, 'post', {
|
|
81
|
+
body: file,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
56
85
|
_loadData(data) {
|
|
57
86
|
this.key = data.key;
|
|
58
87
|
this.ratingKey = data.ratingKey;
|
|
@@ -71,6 +100,9 @@ class Video extends Playable {
|
|
|
71
100
|
this.titleSort = data.titleSort ?? this.title;
|
|
72
101
|
this.viewCount = data.viewCount;
|
|
73
102
|
this.playlistItemID = data.playlistItemID;
|
|
103
|
+
// todo: update one of them with this property
|
|
104
|
+
this.artBlurHash = data.artBlurHash;
|
|
105
|
+
this.thumbBlurHash = data.thumbBlurHash;
|
|
74
106
|
}
|
|
75
107
|
}
|
|
76
108
|
/**
|