@redseat/api 0.0.1
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 +132 -0
- package/agents.md +275 -0
- package/client.md +288 -0
- package/dist/auth.d.ts +5 -0
- package/dist/auth.js +10 -0
- package/dist/client.d.ts +32 -0
- package/dist/client.js +157 -0
- package/dist/crypto.d.ts +36 -0
- package/dist/crypto.js +164 -0
- package/dist/encryption.d.ts +73 -0
- package/dist/encryption.js +238 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/interfaces.d.ts +311 -0
- package/dist/interfaces.js +38 -0
- package/dist/library.d.ts +231 -0
- package/dist/library.js +589 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.js +33 -0
- package/dist/upload.d.ts +16 -0
- package/dist/upload.js +28 -0
- package/encryption.md +533 -0
- package/libraries.md +1652 -0
- package/package.json +50 -0
- package/server.md +196 -0
- package/test.md +291 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform encryption/decryption functions
|
|
3
|
+
* Supports the same formats as src/lib/crypt.ts
|
|
4
|
+
*/
|
|
5
|
+
import { getCryptoSubtle, getCryptoRandomValues, uint8ArrayFromBase64Url, arrayBufferToBase64, base64ToBase64Url, } from './crypto';
|
|
6
|
+
// Salt constants matching existing implementation
|
|
7
|
+
const TEXT_SALT = 'a1209660b32cca003630cb963f730b54';
|
|
8
|
+
const FILE_SALT = 'e5709660b22ab0803630cb963f703b83';
|
|
9
|
+
/**
|
|
10
|
+
* Derive a CryptoKey from a passphrase using PBKDF2
|
|
11
|
+
* @param passPhrase - The passphrase to derive the key from
|
|
12
|
+
* @param type - 'text' for text encryption, 'file' for file encryption
|
|
13
|
+
* @returns A CryptoKey suitable for AES-CBC encryption/decryption
|
|
14
|
+
*/
|
|
15
|
+
export async function deriveKey(passPhrase, type) {
|
|
16
|
+
const crypto = getCryptoSubtle();
|
|
17
|
+
const saltB64 = type === 'text' ? TEXT_SALT : FILE_SALT;
|
|
18
|
+
const saltBuffer = uint8ArrayFromBase64Url(saltB64);
|
|
19
|
+
const passphraseKey = new TextEncoder().encode(passPhrase);
|
|
20
|
+
// Import the passphrase as a key for PBKDF2
|
|
21
|
+
const keyMaterial = await crypto.importKey('raw', passphraseKey, {
|
|
22
|
+
name: 'PBKDF2',
|
|
23
|
+
}, false, ['deriveBits', 'deriveKey']);
|
|
24
|
+
// Derive the actual encryption key
|
|
25
|
+
// Normalize saltBuffer to ensure it's a proper BufferSource
|
|
26
|
+
const salt = saltBuffer instanceof Uint8Array ? new Uint8Array(saltBuffer) : saltBuffer;
|
|
27
|
+
return await crypto.deriveKey({
|
|
28
|
+
name: 'PBKDF2',
|
|
29
|
+
salt: salt,
|
|
30
|
+
iterations: 1000,
|
|
31
|
+
hash: 'SHA-1',
|
|
32
|
+
}, keyMaterial, {
|
|
33
|
+
name: 'AES-CBC',
|
|
34
|
+
length: 256,
|
|
35
|
+
}, false, ['encrypt', 'decrypt']);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generate a random 16-byte IV (Initialization Vector)
|
|
39
|
+
*/
|
|
40
|
+
export function getRandomIV() {
|
|
41
|
+
const getRandomValues = getCryptoRandomValues();
|
|
42
|
+
return getRandomValues(new Uint8Array(16));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Encrypt a text string
|
|
46
|
+
* Returns format: `${base64ToBase64Url(IV)}.${base64ToBase64Url(encryptedData)}`
|
|
47
|
+
*/
|
|
48
|
+
export async function encryptText(key, text) {
|
|
49
|
+
const crypto = getCryptoSubtle();
|
|
50
|
+
const iv = getRandomIV();
|
|
51
|
+
const textData = new TextEncoder().encode(text);
|
|
52
|
+
// Normalize iv to ensure it's a proper BufferSource
|
|
53
|
+
const ivBuffer = new Uint8Array(iv);
|
|
54
|
+
const encrypted = await crypto.encrypt({
|
|
55
|
+
name: 'AES-CBC',
|
|
56
|
+
iv: ivBuffer,
|
|
57
|
+
}, key, textData);
|
|
58
|
+
const ivB64 = base64ToBase64Url(arrayBufferToBase64(iv));
|
|
59
|
+
const encryptedB64 = base64ToBase64Url(arrayBufferToBase64(encrypted));
|
|
60
|
+
return `${ivB64}.${encryptedB64}`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decrypt a text string
|
|
64
|
+
* Expects format: `${base64ToBase64Url(IV)}.${base64ToBase64Url(encryptedData)}`
|
|
65
|
+
* Or can accept IV separately
|
|
66
|
+
*/
|
|
67
|
+
export async function decryptText(key, encryptedText, iv) {
|
|
68
|
+
const crypto = getCryptoSubtle();
|
|
69
|
+
let extractedIv;
|
|
70
|
+
let encryptedData;
|
|
71
|
+
if (iv) {
|
|
72
|
+
extractedIv = iv;
|
|
73
|
+
encryptedData = encryptedText;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const parts = encryptedText.split('.');
|
|
77
|
+
if (parts.length !== 2) {
|
|
78
|
+
throw new Error('Invalid encrypted text format. Expected format: IV.encryptedData');
|
|
79
|
+
}
|
|
80
|
+
extractedIv = uint8ArrayFromBase64Url(parts[0]);
|
|
81
|
+
encryptedData = parts[1];
|
|
82
|
+
}
|
|
83
|
+
const encryptedBuffer = uint8ArrayFromBase64Url(encryptedData);
|
|
84
|
+
// Normalize iv and buffer to ensure they're proper BufferSource
|
|
85
|
+
const ivBuffer = extractedIv instanceof Uint8Array ? new Uint8Array(extractedIv) : extractedIv;
|
|
86
|
+
const bufferSource = encryptedBuffer instanceof Uint8Array ? new Uint8Array(encryptedBuffer) : encryptedBuffer;
|
|
87
|
+
const decrypted = await crypto.decrypt({
|
|
88
|
+
name: 'AES-CBC',
|
|
89
|
+
iv: ivBuffer,
|
|
90
|
+
}, key, bufferSource);
|
|
91
|
+
return new TextDecoder('utf-8').decode(decrypted);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Encrypt a buffer (ArrayBuffer or Uint8Array)
|
|
95
|
+
*/
|
|
96
|
+
export async function encryptBuffer(key, iv, buffer) {
|
|
97
|
+
const crypto = getCryptoSubtle();
|
|
98
|
+
// Normalize iv and buffer to ensure they're proper BufferSource
|
|
99
|
+
const ivBuffer = iv instanceof Uint8Array ? new Uint8Array(iv) : iv;
|
|
100
|
+
const bufferSource = buffer instanceof Uint8Array ? new Uint8Array(buffer) : buffer;
|
|
101
|
+
return await crypto.encrypt({
|
|
102
|
+
name: 'AES-CBC',
|
|
103
|
+
iv: ivBuffer,
|
|
104
|
+
}, key, bufferSource);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Decrypt a buffer (ArrayBuffer or Uint8Array)
|
|
108
|
+
*/
|
|
109
|
+
export async function decryptBuffer(key, iv, buffer) {
|
|
110
|
+
const crypto = getCryptoSubtle();
|
|
111
|
+
// Normalize iv and buffer to ensure they're proper BufferSource
|
|
112
|
+
const ivBuffer = iv instanceof Uint8Array ? new Uint8Array(iv) : iv;
|
|
113
|
+
const bufferSource = buffer instanceof Uint8Array ? new Uint8Array(buffer) : buffer;
|
|
114
|
+
return await crypto.decrypt({
|
|
115
|
+
name: 'AES-CBC',
|
|
116
|
+
iv: ivBuffer,
|
|
117
|
+
}, key, bufferSource);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Encrypt a file with thumbnail and metadata
|
|
121
|
+
* Structure: [16 bytes IV][4 bytes thumb size][4 bytes info size][32 bytes thumb mime][256 bytes file mime][T bytes encrypted thumb][I bytes encrypted info][encrypted file data]
|
|
122
|
+
*/
|
|
123
|
+
export async function encryptFile(key, options) {
|
|
124
|
+
const iv = getRandomIV();
|
|
125
|
+
// Encrypt thumbnail and file buffer
|
|
126
|
+
const encThumb = await encryptBuffer(key, iv, options.thumb);
|
|
127
|
+
const encBuffer = await encryptBuffer(key, iv, options.buffer);
|
|
128
|
+
// Create metadata buffers
|
|
129
|
+
const thumbMimeBuffer = stringToArrayBuffer(options.thumbMime, 32);
|
|
130
|
+
const fileMimeBuffer = stringToArrayBuffer(options.mime, 256);
|
|
131
|
+
// Create the encrypted file structure
|
|
132
|
+
// Use big-endian to match toBytesInt32 behavior (false = big-endian in DataView API)
|
|
133
|
+
const thumbSizeBytes = new ArrayBuffer(4);
|
|
134
|
+
new DataView(thumbSizeBytes).setInt32(0, encThumb.byteLength, false); // big-endian (false = big-endian)
|
|
135
|
+
const infoSizeBytes = new ArrayBuffer(4);
|
|
136
|
+
new DataView(infoSizeBytes).setInt32(0, 0, false); // info size is 0, big-endian
|
|
137
|
+
// Combine all parts
|
|
138
|
+
const totalLength = 16 + 4 + 4 + 32 + 256 + encThumb.byteLength + 0 + encBuffer.byteLength;
|
|
139
|
+
const result = new Uint8Array(totalLength);
|
|
140
|
+
let offset = 0;
|
|
141
|
+
// IV (16 bytes)
|
|
142
|
+
result.set(new Uint8Array(iv), offset);
|
|
143
|
+
offset += 16;
|
|
144
|
+
// Thumb size (4 bytes)
|
|
145
|
+
result.set(new Uint8Array(thumbSizeBytes), offset);
|
|
146
|
+
offset += 4;
|
|
147
|
+
// Info size (4 bytes)
|
|
148
|
+
result.set(new Uint8Array(infoSizeBytes), offset);
|
|
149
|
+
offset += 4;
|
|
150
|
+
// Thumb mime (32 bytes)
|
|
151
|
+
result.set(new Uint8Array(thumbMimeBuffer), offset);
|
|
152
|
+
offset += 32;
|
|
153
|
+
// File mime (256 bytes)
|
|
154
|
+
result.set(new Uint8Array(fileMimeBuffer), offset);
|
|
155
|
+
offset += 256;
|
|
156
|
+
// Encrypted thumb
|
|
157
|
+
result.set(new Uint8Array(encThumb), offset);
|
|
158
|
+
offset += encThumb.byteLength;
|
|
159
|
+
// Encrypted file data
|
|
160
|
+
result.set(new Uint8Array(encBuffer), offset);
|
|
161
|
+
// Encrypt filename
|
|
162
|
+
const binaryFilename = new TextEncoder().encode(options.filename);
|
|
163
|
+
const encFilename = await encryptBuffer(key, iv, binaryFilename);
|
|
164
|
+
const filenameB64 = base64ToBase64Url(arrayBufferToBase64(encFilename));
|
|
165
|
+
return {
|
|
166
|
+
filename: filenameB64,
|
|
167
|
+
ivb64: arrayBufferToBase64(iv),
|
|
168
|
+
thumbsize: encThumb.byteLength,
|
|
169
|
+
blob: result.buffer,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Decrypt a file buffer
|
|
174
|
+
* Extracts and decrypts the file data from the encrypted file structure
|
|
175
|
+
*/
|
|
176
|
+
export async function decryptFile(key, buffer) {
|
|
177
|
+
const crypto = getCryptoSubtle();
|
|
178
|
+
const dv = new DataView(buffer, 0);
|
|
179
|
+
const iv = buffer.slice(0, 16);
|
|
180
|
+
// Read thumb size (handle endianness - try big-endian first since we write big-endian, then little-endian for backward compatibility)
|
|
181
|
+
let targetThumbSize = dv.getInt32(16, false); // big-endian (default, matches toBytesInt32)
|
|
182
|
+
if (targetThumbSize > 999999 || targetThumbSize < 0) {
|
|
183
|
+
targetThumbSize = dv.getInt32(16, true); // little-endian fallback for backward compatibility
|
|
184
|
+
}
|
|
185
|
+
const infoSize = dv.getInt32(20, false); // big-endian (default, matches toBytesInt32)
|
|
186
|
+
// Calculate offset to encrypted file data
|
|
187
|
+
const fileDataOffset = 16 + 4 + 4 + 32 + 256 + targetThumbSize + infoSize;
|
|
188
|
+
const encryptedFileData = buffer.slice(fileDataOffset);
|
|
189
|
+
return await crypto.decrypt({
|
|
190
|
+
name: 'AES-CBC',
|
|
191
|
+
iv: iv,
|
|
192
|
+
}, key, encryptedFileData);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Decrypt a file thumbnail
|
|
196
|
+
* Extracts and decrypts the thumbnail from the encrypted file structure
|
|
197
|
+
*/
|
|
198
|
+
export async function decryptFileThumb(key, buffer) {
|
|
199
|
+
const crypto = getCryptoSubtle();
|
|
200
|
+
const dv = new DataView(buffer, 0);
|
|
201
|
+
const iv = buffer.slice(0, 16);
|
|
202
|
+
// Read thumb size (big-endian first to match toBytesInt32, then little-endian fallback)
|
|
203
|
+
let thumbSize = dv.getInt32(16, false); // big-endian (matches toBytesInt32 which uses false)
|
|
204
|
+
if (thumbSize > 999999 || thumbSize < 0) {
|
|
205
|
+
thumbSize = dv.getInt32(16, true); // little-endian fallback for backward compatibility
|
|
206
|
+
}
|
|
207
|
+
// If thumbSize is 0, return empty buffer
|
|
208
|
+
if (thumbSize === 0) {
|
|
209
|
+
return new ArrayBuffer(0);
|
|
210
|
+
}
|
|
211
|
+
// Encrypted thumb starts after: IV (16) + thumbSize (4) + infoSize (4) + thumbMime (32) + fileMime (256) = 312
|
|
212
|
+
const thumbOffset = 16 + 4 + 4 + 32 + 256;
|
|
213
|
+
const encryptedThumb = buffer.slice(thumbOffset, thumbOffset + thumbSize);
|
|
214
|
+
return await crypto.decrypt({
|
|
215
|
+
name: 'AES-CBC',
|
|
216
|
+
iv: iv,
|
|
217
|
+
}, key, encryptedThumb);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Encrypt a filename
|
|
221
|
+
* Returns base64url encoded encrypted filename
|
|
222
|
+
*/
|
|
223
|
+
export async function encryptFilename(key, filename, iv) {
|
|
224
|
+
const binaryFilename = new TextEncoder().encode(filename);
|
|
225
|
+
const encFilename = await encryptBuffer(key, iv, binaryFilename);
|
|
226
|
+
return base64ToBase64Url(arrayBufferToBase64(encFilename));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Helper function to convert string to ArrayBuffer with fixed length
|
|
230
|
+
*/
|
|
231
|
+
function stringToArrayBuffer(str, length) {
|
|
232
|
+
const buffer = new ArrayBuffer(length);
|
|
233
|
+
const view = new Uint8Array(buffer);
|
|
234
|
+
const encoder = new TextEncoder();
|
|
235
|
+
const encoded = encoder.encode(str);
|
|
236
|
+
view.set(encoded.slice(0, length));
|
|
237
|
+
return buffer;
|
|
238
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
export declare enum FileTypes {
|
|
2
|
+
directory = "directory",
|
|
3
|
+
photo = "photo",
|
|
4
|
+
video = "video",
|
|
5
|
+
archive = "archive",
|
|
6
|
+
album = "album",
|
|
7
|
+
channel = "channel",
|
|
8
|
+
other = "other"
|
|
9
|
+
}
|
|
10
|
+
export interface SerieInMedia {
|
|
11
|
+
id: string;
|
|
12
|
+
season?: number;
|
|
13
|
+
episode?: number;
|
|
14
|
+
episodeTo?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface IFile {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
size: number;
|
|
21
|
+
type: FileTypes;
|
|
22
|
+
mimetype: string;
|
|
23
|
+
modified: number;
|
|
24
|
+
created: number;
|
|
25
|
+
added: number;
|
|
26
|
+
starred?: any;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
phash?: string;
|
|
30
|
+
thumbhash?: string;
|
|
31
|
+
acodecs?: string[];
|
|
32
|
+
achan?: number[];
|
|
33
|
+
vcodecs?: string[];
|
|
34
|
+
fps?: number;
|
|
35
|
+
bitrate?: number;
|
|
36
|
+
colorSpace?: string;
|
|
37
|
+
icc?: string;
|
|
38
|
+
mp?: number;
|
|
39
|
+
focal?: number;
|
|
40
|
+
iso?: number;
|
|
41
|
+
fNumber?: number;
|
|
42
|
+
sspeed?: string;
|
|
43
|
+
orientation?: number;
|
|
44
|
+
duration?: any;
|
|
45
|
+
progress?: number;
|
|
46
|
+
thumb?: any;
|
|
47
|
+
rating?: number;
|
|
48
|
+
tags?: {
|
|
49
|
+
id: string;
|
|
50
|
+
conf?: number;
|
|
51
|
+
}[];
|
|
52
|
+
people?: {
|
|
53
|
+
id: string;
|
|
54
|
+
conf?: number;
|
|
55
|
+
}[];
|
|
56
|
+
series?: SerieInMedia[];
|
|
57
|
+
movie?: string;
|
|
58
|
+
long?: number;
|
|
59
|
+
lat?: number;
|
|
60
|
+
params?: any;
|
|
61
|
+
iv?: string;
|
|
62
|
+
pages?: number;
|
|
63
|
+
thumbv?: number;
|
|
64
|
+
thumbsize?: number;
|
|
65
|
+
model?: string;
|
|
66
|
+
originalId?: string;
|
|
67
|
+
}
|
|
68
|
+
export declare enum LibraryTypes {
|
|
69
|
+
'Photos' = "photos",
|
|
70
|
+
'Shows' = "shows",
|
|
71
|
+
'Movies' = "movies",
|
|
72
|
+
'IPTV' = "iptv"
|
|
73
|
+
}
|
|
74
|
+
export declare enum LibrarySources {
|
|
75
|
+
'Path' = "PathProvider",
|
|
76
|
+
'Virtual' = "VirtualProvider",
|
|
77
|
+
'Plugin' = "PluginProvider"
|
|
78
|
+
}
|
|
79
|
+
export declare enum LibraryRole {
|
|
80
|
+
none = "none",
|
|
81
|
+
display = "display",
|
|
82
|
+
read = "read",
|
|
83
|
+
write = "write",
|
|
84
|
+
share = "share",
|
|
85
|
+
admin = "admin"
|
|
86
|
+
}
|
|
87
|
+
export interface ILibrary {
|
|
88
|
+
id?: string;
|
|
89
|
+
name: string;
|
|
90
|
+
type: LibraryTypes;
|
|
91
|
+
source?: LibrarySources;
|
|
92
|
+
roles?: LibraryRole[];
|
|
93
|
+
crypt?: boolean;
|
|
94
|
+
hidden?: boolean;
|
|
95
|
+
status?: string;
|
|
96
|
+
}
|
|
97
|
+
export interface ITag {
|
|
98
|
+
id?: string;
|
|
99
|
+
name: string;
|
|
100
|
+
parent?: string;
|
|
101
|
+
path?: string;
|
|
102
|
+
count?: number;
|
|
103
|
+
starred?: boolean;
|
|
104
|
+
hidden?: boolean;
|
|
105
|
+
alt?: string[];
|
|
106
|
+
generated?: boolean;
|
|
107
|
+
waiting?: boolean;
|
|
108
|
+
}
|
|
109
|
+
export declare enum LinkType {
|
|
110
|
+
'profile' = "profile",
|
|
111
|
+
'post' = "post",
|
|
112
|
+
'other' = "other"
|
|
113
|
+
}
|
|
114
|
+
export interface IPerson {
|
|
115
|
+
id?: string;
|
|
116
|
+
name: string;
|
|
117
|
+
alt?: string[];
|
|
118
|
+
socials?: {
|
|
119
|
+
id: string;
|
|
120
|
+
type: LinkType | undefined;
|
|
121
|
+
platform: string;
|
|
122
|
+
}[];
|
|
123
|
+
posterv?: number;
|
|
124
|
+
portrait?: boolean;
|
|
125
|
+
birthday?: number;
|
|
126
|
+
waiting?: boolean;
|
|
127
|
+
generated?: boolean;
|
|
128
|
+
}
|
|
129
|
+
export interface ISerie {
|
|
130
|
+
id?: string;
|
|
131
|
+
name: string;
|
|
132
|
+
alt?: string[];
|
|
133
|
+
tags?: string[];
|
|
134
|
+
people?: string[];
|
|
135
|
+
year?: number;
|
|
136
|
+
poster?: boolean;
|
|
137
|
+
imdb?: string;
|
|
138
|
+
slug?: string;
|
|
139
|
+
tmdb?: number;
|
|
140
|
+
trakt?: number;
|
|
141
|
+
tvdb?: number;
|
|
142
|
+
otherids?: string;
|
|
143
|
+
status?: string;
|
|
144
|
+
imdbRating?: number;
|
|
145
|
+
imdbVotes?: number;
|
|
146
|
+
images?: {
|
|
147
|
+
poster?: string;
|
|
148
|
+
background?: string;
|
|
149
|
+
};
|
|
150
|
+
posterv?: number;
|
|
151
|
+
backgroundv?: number;
|
|
152
|
+
cardv?: number;
|
|
153
|
+
waiting?: boolean;
|
|
154
|
+
}
|
|
155
|
+
export interface IEpisode {
|
|
156
|
+
id?: string;
|
|
157
|
+
serie: string;
|
|
158
|
+
name: string;
|
|
159
|
+
season?: number;
|
|
160
|
+
number?: number;
|
|
161
|
+
abs?: number;
|
|
162
|
+
overview?: string;
|
|
163
|
+
airdate?: number;
|
|
164
|
+
duration?: number;
|
|
165
|
+
type?: string;
|
|
166
|
+
alt?: string[];
|
|
167
|
+
imdb?: string;
|
|
168
|
+
slug?: string;
|
|
169
|
+
tmdb?: number;
|
|
170
|
+
trakt?: number;
|
|
171
|
+
tvdb?: number;
|
|
172
|
+
otherids?: string;
|
|
173
|
+
modified?: number;
|
|
174
|
+
watched?: number;
|
|
175
|
+
images?: {
|
|
176
|
+
poster?: string;
|
|
177
|
+
background?: string;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export interface IMovie {
|
|
181
|
+
id?: string;
|
|
182
|
+
name: string;
|
|
183
|
+
year?: number;
|
|
184
|
+
}
|
|
185
|
+
export interface IServer {
|
|
186
|
+
id: string;
|
|
187
|
+
name: string;
|
|
188
|
+
url: string;
|
|
189
|
+
port?: number;
|
|
190
|
+
}
|
|
191
|
+
export interface MediaRequest {
|
|
192
|
+
sort?: string;
|
|
193
|
+
order?: 'ASC' | 'DESC';
|
|
194
|
+
tags?: string[];
|
|
195
|
+
people?: string[];
|
|
196
|
+
series?: string[];
|
|
197
|
+
movies?: string[];
|
|
198
|
+
minSize?: number;
|
|
199
|
+
maxSize?: number;
|
|
200
|
+
pageKey?: string;
|
|
201
|
+
limit?: number;
|
|
202
|
+
}
|
|
203
|
+
export interface IBackup {
|
|
204
|
+
id: string;
|
|
205
|
+
name: string;
|
|
206
|
+
path: string;
|
|
207
|
+
password?: string;
|
|
208
|
+
library: string;
|
|
209
|
+
source: string;
|
|
210
|
+
plugin?: string;
|
|
211
|
+
credentials?: string;
|
|
212
|
+
credentialsName?: string;
|
|
213
|
+
schedule: string;
|
|
214
|
+
filter?: MediaRequest;
|
|
215
|
+
last?: number;
|
|
216
|
+
size?: number;
|
|
217
|
+
}
|
|
218
|
+
export interface IBackupFile {
|
|
219
|
+
backup: string;
|
|
220
|
+
library: string;
|
|
221
|
+
file: string;
|
|
222
|
+
id?: string;
|
|
223
|
+
path?: string;
|
|
224
|
+
hash?: string;
|
|
225
|
+
sourcehash?: string;
|
|
226
|
+
size?: number;
|
|
227
|
+
added: number;
|
|
228
|
+
modified: number;
|
|
229
|
+
iv?: string;
|
|
230
|
+
thumbsize?: number;
|
|
231
|
+
infoSize?: number;
|
|
232
|
+
error?: string;
|
|
233
|
+
}
|
|
234
|
+
export interface ExternalImage {
|
|
235
|
+
url: string;
|
|
236
|
+
type: string;
|
|
237
|
+
}
|
|
238
|
+
export interface IChannel {
|
|
239
|
+
id: string;
|
|
240
|
+
name: string;
|
|
241
|
+
series: string[];
|
|
242
|
+
lang?: string;
|
|
243
|
+
versions: IChannelVersion[];
|
|
244
|
+
type?: FileTypes;
|
|
245
|
+
}
|
|
246
|
+
export interface IChannelVersion {
|
|
247
|
+
id: string;
|
|
248
|
+
name: string;
|
|
249
|
+
source: string;
|
|
250
|
+
quality?: string;
|
|
251
|
+
description?: string;
|
|
252
|
+
}
|
|
253
|
+
export interface UnassignedFace {
|
|
254
|
+
id: string;
|
|
255
|
+
media: string;
|
|
256
|
+
box: any;
|
|
257
|
+
confidence: number;
|
|
258
|
+
}
|
|
259
|
+
export interface UnassignedFacesResponse {
|
|
260
|
+
faces: UnassignedFace[];
|
|
261
|
+
total: number;
|
|
262
|
+
}
|
|
263
|
+
export interface Cluster {
|
|
264
|
+
id: string;
|
|
265
|
+
faces: UnassignedFace[];
|
|
266
|
+
representativeFace: UnassignedFace;
|
|
267
|
+
}
|
|
268
|
+
export interface AssignFacesRequest {
|
|
269
|
+
faceIds: string[];
|
|
270
|
+
personId: string;
|
|
271
|
+
}
|
|
272
|
+
export interface AssignFacesResponse {
|
|
273
|
+
assigned: number;
|
|
274
|
+
}
|
|
275
|
+
export interface CreatePersonFromClusterRequest {
|
|
276
|
+
name?: string;
|
|
277
|
+
}
|
|
278
|
+
export interface CreatePersonFromClusterResponse {
|
|
279
|
+
person: IPerson;
|
|
280
|
+
}
|
|
281
|
+
export interface SplitClusterRequest {
|
|
282
|
+
faceIds?: string[];
|
|
283
|
+
}
|
|
284
|
+
export interface SplitClusterResponse {
|
|
285
|
+
newClusters: Cluster[];
|
|
286
|
+
}
|
|
287
|
+
export interface UnassignFaceRequest {
|
|
288
|
+
reason?: string;
|
|
289
|
+
}
|
|
290
|
+
export interface UnassignFaceResponse {
|
|
291
|
+
unassigned: number;
|
|
292
|
+
}
|
|
293
|
+
export interface DeleteFaceResponse {
|
|
294
|
+
deleted: number;
|
|
295
|
+
}
|
|
296
|
+
export interface AssignedFace extends UnassignedFace {
|
|
297
|
+
person: IPerson;
|
|
298
|
+
}
|
|
299
|
+
export interface MergePeopleRequest {
|
|
300
|
+
sourcePersonId: string;
|
|
301
|
+
targetPersonId: string;
|
|
302
|
+
}
|
|
303
|
+
export interface MergePeopleResponse {
|
|
304
|
+
merged: boolean;
|
|
305
|
+
}
|
|
306
|
+
export interface ClusterFacesResponse {
|
|
307
|
+
clusters: number;
|
|
308
|
+
}
|
|
309
|
+
export interface IChannelUpdate {
|
|
310
|
+
[key: string]: any;
|
|
311
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export var FileTypes;
|
|
2
|
+
(function (FileTypes) {
|
|
3
|
+
FileTypes["directory"] = "directory";
|
|
4
|
+
FileTypes["photo"] = "photo";
|
|
5
|
+
FileTypes["video"] = "video";
|
|
6
|
+
FileTypes["archive"] = "archive";
|
|
7
|
+
FileTypes["album"] = "album";
|
|
8
|
+
FileTypes["channel"] = "channel";
|
|
9
|
+
FileTypes["other"] = "other";
|
|
10
|
+
})(FileTypes || (FileTypes = {}));
|
|
11
|
+
export var LibraryTypes;
|
|
12
|
+
(function (LibraryTypes) {
|
|
13
|
+
LibraryTypes["Photos"] = "photos";
|
|
14
|
+
LibraryTypes["Shows"] = "shows";
|
|
15
|
+
LibraryTypes["Movies"] = "movies";
|
|
16
|
+
LibraryTypes["IPTV"] = "iptv";
|
|
17
|
+
})(LibraryTypes || (LibraryTypes = {}));
|
|
18
|
+
export var LibrarySources;
|
|
19
|
+
(function (LibrarySources) {
|
|
20
|
+
LibrarySources["Path"] = "PathProvider";
|
|
21
|
+
LibrarySources["Virtual"] = "VirtualProvider";
|
|
22
|
+
LibrarySources["Plugin"] = "PluginProvider";
|
|
23
|
+
})(LibrarySources || (LibrarySources = {}));
|
|
24
|
+
export var LibraryRole;
|
|
25
|
+
(function (LibraryRole) {
|
|
26
|
+
LibraryRole["none"] = "none";
|
|
27
|
+
LibraryRole["display"] = "display";
|
|
28
|
+
LibraryRole["read"] = "read";
|
|
29
|
+
LibraryRole["write"] = "write";
|
|
30
|
+
LibraryRole["share"] = "share";
|
|
31
|
+
LibraryRole["admin"] = "admin";
|
|
32
|
+
})(LibraryRole || (LibraryRole = {}));
|
|
33
|
+
export var LinkType;
|
|
34
|
+
(function (LinkType) {
|
|
35
|
+
LinkType["profile"] = "profile";
|
|
36
|
+
LinkType["post"] = "post";
|
|
37
|
+
LinkType["other"] = "other";
|
|
38
|
+
})(LinkType || (LinkType = {}));
|