@scrypted/server 0.0.116 → 0.0.118

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.

Potentially problematic release.


This version of @scrypted/server might be problematic. Click here for more details.

Files changed (54) hide show
  1. package/.vscode/launch.json +1 -0
  2. package/dist/http-interfaces.js +11 -4
  3. package/dist/http-interfaces.js.map +1 -1
  4. package/dist/level.js.map +1 -1
  5. package/dist/plugin/media.js +3 -3
  6. package/dist/plugin/media.js.map +1 -1
  7. package/dist/plugin/plugin-console.js.map +1 -1
  8. package/dist/plugin/plugin-device.js +13 -3
  9. package/dist/plugin/plugin-device.js.map +1 -1
  10. package/dist/plugin/plugin-host-api.js +2 -2
  11. package/dist/plugin/plugin-host-api.js.map +1 -1
  12. package/dist/plugin/plugin-host.js +110 -235
  13. package/dist/plugin/plugin-host.js.map +1 -1
  14. package/dist/plugin/plugin-lazy-remote.js.map +1 -1
  15. package/dist/plugin/plugin-remote-worker.js +253 -0
  16. package/dist/plugin/plugin-remote-worker.js.map +1 -0
  17. package/dist/plugin/plugin-remote.js +38 -14
  18. package/dist/plugin/plugin-remote.js.map +1 -1
  19. package/dist/plugin/plugin-repl.js.map +1 -1
  20. package/dist/plugin/system.js +7 -5
  21. package/dist/plugin/system.js.map +1 -1
  22. package/dist/rpc.js +2 -1
  23. package/dist/rpc.js.map +1 -1
  24. package/dist/runtime.js +5 -4
  25. package/dist/runtime.js.map +1 -1
  26. package/dist/scrypted-main.js +3 -437
  27. package/dist/scrypted-main.js.map +1 -1
  28. package/dist/scrypted-plugin-main.js +8 -0
  29. package/dist/scrypted-plugin-main.js.map +1 -0
  30. package/dist/scrypted-server-main.js +448 -0
  31. package/dist/scrypted-server-main.js.map +1 -0
  32. package/package.json +5 -4
  33. package/python/media.py +1 -12
  34. package/python/plugin-remote.py +15 -7
  35. package/python/rpc.py +1 -1
  36. package/src/http-interfaces.ts +12 -5
  37. package/src/level.ts +0 -2
  38. package/src/plugin/media.ts +3 -3
  39. package/src/plugin/plugin-api.ts +9 -1
  40. package/src/plugin/plugin-console.ts +0 -1
  41. package/src/plugin/plugin-device.ts +10 -3
  42. package/src/plugin/plugin-host-api.ts +2 -2
  43. package/src/plugin/plugin-host.ts +121 -264
  44. package/src/plugin/plugin-http.ts +2 -2
  45. package/src/plugin/plugin-lazy-remote.ts +1 -1
  46. package/src/plugin/plugin-remote-worker.ts +272 -0
  47. package/src/plugin/plugin-remote.ts +45 -16
  48. package/src/plugin/plugin-repl.ts +0 -1
  49. package/src/plugin/system.ts +8 -6
  50. package/src/rpc.ts +3 -1
  51. package/src/runtime.ts +5 -4
  52. package/src/scrypted-main.ts +3 -508
  53. package/src/scrypted-plugin-main.ts +6 -0
  54. package/src/scrypted-server-main.ts +516 -0
@@ -0,0 +1,448 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const path_1 = __importDefault(require("path"));
7
+ const process_1 = __importDefault(require("process"));
8
+ const http_1 = __importDefault(require("http"));
9
+ const https_1 = __importDefault(require("https"));
10
+ const express_1 = __importDefault(require("express"));
11
+ const body_parser_1 = __importDefault(require("body-parser"));
12
+ const net_1 = __importDefault(require("net"));
13
+ const runtime_1 = require("./runtime");
14
+ const level_1 = __importDefault(require("./level"));
15
+ const db_types_1 = require("./db-types");
16
+ const server_settings_1 = require("./server-settings");
17
+ const crypto_1 = __importDefault(require("crypto"));
18
+ const cookie_parser_1 = __importDefault(require("cookie-parser"));
19
+ const axios_1 = __importDefault(require("axios"));
20
+ const query_string_1 = __importDefault(require("query-string"));
21
+ const rpc_1 = require("./rpc");
22
+ const fs_1 = __importDefault(require("fs"));
23
+ const mkdirp_1 = __importDefault(require("mkdirp"));
24
+ const source_map_support_1 = require("source-map-support");
25
+ const http_auth_1 = __importDefault(require("http-auth"));
26
+ const semver_1 = __importDefault(require("semver"));
27
+ const info_1 = require("./services/info");
28
+ const addresses_1 = require("./addresses");
29
+ const sleep_1 = require("./sleep");
30
+ const cert_1 = require("./cert");
31
+ const plugin_error_1 = require("./plugin/plugin-error");
32
+ const plugin_volume_1 = require("./plugin/plugin-volume");
33
+ if (!semver_1.default.gte(process_1.default.version, '16.0.0')) {
34
+ throw new Error('"node" version out of date. Please update node to v16 or higher.');
35
+ }
36
+ process_1.default.on('unhandledRejection', error => {
37
+ if (error?.constructor !== rpc_1.RPCResultError && error?.constructor !== plugin_error_1.PluginError) {
38
+ throw error;
39
+ }
40
+ console.warn('unhandled rejection of RPC Result', error);
41
+ });
42
+ function listenServerPort(env, port, server) {
43
+ server.listen(port);
44
+ server.on('error', (e) => {
45
+ console.error(`Failed to listen on port ${port}. It may be in use.`);
46
+ console.error(`Use the environment variable ${env} to change the port.`);
47
+ throw e;
48
+ });
49
+ }
50
+ (0, source_map_support_1.install)({
51
+ environment: 'node',
52
+ });
53
+ let workerInspectPort = undefined;
54
+ async function doconnect() {
55
+ return new Promise((resolve, reject) => {
56
+ const target = net_1.default.connect(workerInspectPort);
57
+ target.once('error', reject);
58
+ target.once('connect', () => resolve(target));
59
+ });
60
+ }
61
+ const debugServer = net_1.default.createServer(async (socket) => {
62
+ if (!workerInspectPort) {
63
+ socket.destroy();
64
+ return;
65
+ }
66
+ for (let i = 0; i < 10; i++) {
67
+ try {
68
+ const target = await doconnect();
69
+ socket.pipe(target).pipe(socket);
70
+ const destroy = () => {
71
+ socket.destroy();
72
+ target.destroy();
73
+ };
74
+ socket.on('error', destroy);
75
+ target.on('error', destroy);
76
+ socket.on('close', destroy);
77
+ target.on('close', destroy);
78
+ return;
79
+ }
80
+ catch (e) {
81
+ await (0, sleep_1.sleep)(500);
82
+ }
83
+ }
84
+ console.warn('debugger connect timed out');
85
+ socket.destroy();
86
+ });
87
+ listenServerPort('SCRYPTED_DEBUG_PORT', server_settings_1.SCRYPTED_DEBUG_PORT, debugServer);
88
+ const app = (0, express_1.default)();
89
+ // parse application/x-www-form-urlencoded
90
+ app.use(body_parser_1.default.urlencoded({ extended: false }));
91
+ // parse application/json
92
+ app.use(body_parser_1.default.json());
93
+ // parse some custom thing into a Buffer
94
+ app.use(body_parser_1.default.raw({ type: 'application/zip', limit: 100000000 }));
95
+ async function start() {
96
+ const volumeDir = (0, plugin_volume_1.getScryptedVolume)();
97
+ mkdirp_1.default.sync(volumeDir);
98
+ const dbPath = path_1.default.join(volumeDir, 'scrypted.db');
99
+ const db = (0, level_1.default)(dbPath);
100
+ await db.open();
101
+ if (process_1.default.env.SCRYPTED_RESET_ALL_USERS === 'true') {
102
+ await db.removeAll(db_types_1.ScryptedUser);
103
+ }
104
+ let certSetting = await db.tryGet(db_types_1.Settings, 'certificate');
105
+ if (certSetting?.value?.version !== cert_1.CURRENT_SELF_SIGNED_CERTIFICATE_VERSION) {
106
+ const cert = (0, cert_1.createSelfSignedCertificate)();
107
+ certSetting = new db_types_1.Settings();
108
+ certSetting._id = 'certificate';
109
+ certSetting.value = cert;
110
+ certSetting = await db.upsert(certSetting);
111
+ }
112
+ const basicAuth = http_auth_1.default.basic({
113
+ realm: 'Scrypted',
114
+ }, async (username, password, callback) => {
115
+ const user = await db.tryGet(db_types_1.ScryptedUser, username);
116
+ if (!user) {
117
+ callback(false);
118
+ return;
119
+ }
120
+ const salted = user.salt + password;
121
+ const hash = crypto_1.default.createHash('sha256');
122
+ hash.update(salted);
123
+ const sha = hash.digest().toString('hex');
124
+ callback(sha === user.passwordHash || password === user.token);
125
+ });
126
+ const keys = certSetting.value;
127
+ const httpsServerOptions = process_1.default.env.SCRYPTED_HTTPS_OPTIONS_FILE
128
+ ? JSON.parse(fs_1.default.readFileSync(process_1.default.env.SCRYPTED_HTTPS_OPTIONS_FILE).toString())
129
+ : {};
130
+ const mergedHttpsServerOptions = Object.assign({
131
+ key: keys.serviceKey,
132
+ cert: keys.certificate
133
+ }, httpsServerOptions);
134
+ const secure = https_1.default.createServer(mergedHttpsServerOptions, app);
135
+ listenServerPort('SCRYPTED_SECURE_PORT', server_settings_1.SCRYPTED_SECURE_PORT, secure);
136
+ const insecure = http_1.default.createServer(app);
137
+ listenServerPort('SCRYPTED_INSECURE_PORT', server_settings_1.SCRYPTED_INSECURE_PORT, insecure);
138
+ // legacy secure port 9443 is now in use by portainer.
139
+ let shownLegacyPortAlert = false;
140
+ const legacySecure = https_1.default.createServer(mergedHttpsServerOptions, (req, res) => {
141
+ if (!shownLegacyPortAlert) {
142
+ const core = scrypted.findPluginDevice('@scrypted/core');
143
+ if (core) {
144
+ const logger = scrypted.getDeviceLogger(core);
145
+ shownLegacyPortAlert = true;
146
+ const host = (req.headers.host || 'localhost').split(':')[0];
147
+ const newUrl = `https://${host}:${server_settings_1.SCRYPTED_SECURE_PORT}`;
148
+ logger.log('a', `Due to a port conflict with Portainer, the default Scrypted URL has changed to ${newUrl}`);
149
+ }
150
+ }
151
+ app(req, res);
152
+ });
153
+ legacySecure.listen(9443);
154
+ legacySecure.on('error', () => {
155
+ // can ignore.
156
+ });
157
+ // use a hash of the private key as the cookie secret.
158
+ app.use((0, cookie_parser_1.default)(crypto_1.default.createHash('sha256').update(certSetting.value.serviceKey).digest().toString('hex')));
159
+ app.all('*', async (req, res, next) => {
160
+ // this is a trap for all auth.
161
+ // only basic auth will fail with 401. it is up to the endpoints to manage
162
+ // lack of login from cookie auth.
163
+ const { login_user_token } = req.signedCookies;
164
+ if (login_user_token) {
165
+ const userTokenParts = login_user_token.split('#');
166
+ const username = userTokenParts[0];
167
+ const timestamp = parseInt(userTokenParts[1]);
168
+ if (timestamp + 86400000 < Date.now()) {
169
+ console.warn('login expired');
170
+ return next();
171
+ }
172
+ const user = await db.tryGet(db_types_1.ScryptedUser, username);
173
+ if (!user) {
174
+ console.warn('login not found');
175
+ return next();
176
+ }
177
+ res.locals.username = username;
178
+ }
179
+ next();
180
+ });
181
+ // allow basic auth to deploy plugins
182
+ app.all('/web/component/*', (req, res, next) => {
183
+ if (req.protocol === 'https' && req.headers.authorization && req.headers.authorization.toLowerCase()?.indexOf('basic') !== -1) {
184
+ const basicChecker = basicAuth.check((req) => {
185
+ res.locals.username = req.user;
186
+ next();
187
+ });
188
+ // this automatically handles unauthorized.
189
+ basicChecker(req, res);
190
+ return;
191
+ }
192
+ next();
193
+ });
194
+ // verify all plugin related requests have some sort of auth
195
+ app.all('/web/component/*', (req, res, next) => {
196
+ if (!res.locals.username) {
197
+ res.status(401);
198
+ res.send('Not Authorized');
199
+ return;
200
+ }
201
+ next();
202
+ });
203
+ console.log('#######################################################');
204
+ console.log(`Scrypted Server (Local) : https://localhost:${server_settings_1.SCRYPTED_SECURE_PORT}/`);
205
+ for (const address of (0, addresses_1.getAddresses)()) {
206
+ console.log(`Scrypted Server (Remote) : https://${address}:${server_settings_1.SCRYPTED_SECURE_PORT}/`);
207
+ }
208
+ console.log(`Version: : ${await new info_1.Info().getVersion()}`);
209
+ console.log('#######################################################');
210
+ console.log('Chrome Users: You may need to type "thisisunsafe" into');
211
+ console.log(' the window to bypass the warning. There');
212
+ console.log(' may be no button to continue, type the');
213
+ console.log(' letters "thisisunsafe" and it will proceed.');
214
+ console.log('#######################################################');
215
+ console.log('Scrypted insecure http service port:', server_settings_1.SCRYPTED_INSECURE_PORT);
216
+ console.log('Ports can be changed with environment variables.');
217
+ console.log('https: $SCRYPTED_SECURE_PORT');
218
+ console.log('http : $SCRYPTED_INSECURE_PORT');
219
+ console.log('Certificate can be modified via tls.createSecureContext options in');
220
+ console.log('JSON file located at SCRYPTED_HTTPS_OPTIONS_FILE environment variable:');
221
+ console.log('export SCRYPTED_HTTPS_OPTIONS_FILE=/path/to/options.json');
222
+ console.log('https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions');
223
+ console.log('#######################################################');
224
+ const scrypted = new runtime_1.ScryptedRuntime(db, insecure, secure, app);
225
+ await scrypted.start();
226
+ app.get(['/web/component/script/npm/:pkg', '/web/component/script/npm/@:owner/:pkg'], async (req, res) => {
227
+ const { owner, pkg } = req.params;
228
+ let endpoint = pkg;
229
+ if (owner)
230
+ endpoint = `@${owner}/${endpoint}`;
231
+ try {
232
+ const response = await (0, axios_1.default)(`https://registry.npmjs.org/${endpoint}`);
233
+ res.send(response.data);
234
+ }
235
+ catch (e) {
236
+ res.status(500);
237
+ res.end();
238
+ }
239
+ });
240
+ app.post(['/web/component/script/install/:pkg', '/web/component/script/install/@:owner/:pkg', '/web/component/script/install/@:owner/:pkg/:tag'], async (req, res) => {
241
+ const { owner, pkg, tag } = req.params;
242
+ let endpoint = pkg;
243
+ if (owner)
244
+ endpoint = `@${owner}/${endpoint}`;
245
+ try {
246
+ const plugin = await scrypted.installNpm(endpoint, tag);
247
+ res.send({
248
+ id: scrypted.findPluginDevice(plugin.pluginId)._id,
249
+ });
250
+ }
251
+ catch (e) {
252
+ res.status(500);
253
+ res.end();
254
+ }
255
+ });
256
+ app.get('/web/component/script/search', async (req, res) => {
257
+ try {
258
+ const query = query_string_1.default.stringify({
259
+ text: req.query.text,
260
+ });
261
+ const response = await (0, axios_1.default)(`https://registry.npmjs.org/-/v1/search?${query}`);
262
+ res.send(response.data);
263
+ }
264
+ catch (e) {
265
+ res.status(500);
266
+ res.end();
267
+ }
268
+ });
269
+ app.post('/web/component/script/setup', async (req, res) => {
270
+ const npmPackage = req.query.npmPackage;
271
+ const plugin = await db.tryGet(db_types_1.Plugin, npmPackage) || new db_types_1.Plugin();
272
+ plugin._id = npmPackage;
273
+ plugin.packageJson = req.body;
274
+ await db.upsert(plugin);
275
+ res.send('ok');
276
+ });
277
+ app.post('/web/component/script/deploy', async (req, res) => {
278
+ const npmPackage = req.query.npmPackage;
279
+ const plugin = await db.tryGet(db_types_1.Plugin, npmPackage);
280
+ if (!plugin) {
281
+ res.status(500);
282
+ res.send(`npm package ${npmPackage} not found`);
283
+ return;
284
+ }
285
+ plugin.zip = req.body.toString('base64');
286
+ await db.upsert(plugin);
287
+ const noRebind = req.query['no-rebind'] !== undefined;
288
+ if (!noRebind)
289
+ await scrypted.installPlugin(plugin);
290
+ res.send('ok');
291
+ });
292
+ app.post('/web/component/script/debug', async (req, res) => {
293
+ const npmPackage = req.query.npmPackage;
294
+ const plugin = await db.tryGet(db_types_1.Plugin, npmPackage);
295
+ if (!plugin) {
296
+ res.status(500);
297
+ res.send(`npm package ${npmPackage} not found`);
298
+ return;
299
+ }
300
+ const waitDebug = new Promise((resolve, reject) => {
301
+ setTimeout(() => reject(new Error('timed out waiting for debug session')), 30000);
302
+ debugServer.on('connection', resolve);
303
+ });
304
+ workerInspectPort = Math.round(Math.random() * 10000) + 30000;
305
+ try {
306
+ await scrypted.installPlugin(plugin, {
307
+ waitDebug,
308
+ inspectPort: workerInspectPort,
309
+ });
310
+ }
311
+ catch (e) {
312
+ res.status(500);
313
+ res.send(e.toString());
314
+ return;
315
+ }
316
+ res.send({
317
+ workerInspectPort,
318
+ });
319
+ });
320
+ app.get('/logout', (req, res) => {
321
+ res.clearCookie('login_user_token');
322
+ res.send({});
323
+ });
324
+ app.post('/login', async (req, res) => {
325
+ const hasLogin = await db.getCount(db_types_1.ScryptedUser) > 0;
326
+ const { username, password, change_password } = req.body;
327
+ const timestamp = Date.now();
328
+ const maxAge = 86400000;
329
+ if (hasLogin) {
330
+ const user = await db.tryGet(db_types_1.ScryptedUser, username);
331
+ if (!user) {
332
+ res.send({
333
+ error: 'User does not exist.',
334
+ hasLogin,
335
+ });
336
+ return;
337
+ }
338
+ const salted = user.salt + password;
339
+ const hash = crypto_1.default.createHash('sha256');
340
+ hash.update(salted);
341
+ const sha = hash.digest().toString('hex');
342
+ if (user.passwordHash !== sha) {
343
+ res.send({
344
+ error: 'Incorrect password.',
345
+ hasLogin,
346
+ });
347
+ return;
348
+ }
349
+ const login_user_token = `${username}#${timestamp}`;
350
+ res.cookie('login_user_token', login_user_token, {
351
+ maxAge,
352
+ secure: true,
353
+ signed: true,
354
+ httpOnly: true,
355
+ });
356
+ if (change_password) {
357
+ user.salt = crypto_1.default.randomBytes(64).toString('base64');
358
+ user.passwordHash = crypto_1.default.createHash('sha256').update(user.salt + change_password).digest().toString('hex');
359
+ user.passwordDate = timestamp;
360
+ await db.upsert(user);
361
+ }
362
+ res.send({
363
+ username,
364
+ expiration: maxAge,
365
+ });
366
+ return;
367
+ }
368
+ const user = new db_types_1.ScryptedUser();
369
+ user._id = username;
370
+ user.salt = crypto_1.default.randomBytes(64).toString('base64');
371
+ user.passwordHash = crypto_1.default.createHash('sha256').update(user.salt + password).digest().toString('hex');
372
+ user.passwordDate = timestamp;
373
+ await db.upsert(user);
374
+ const login_user_token = `${username}#${timestamp}`;
375
+ res.cookie('login_user_token', login_user_token, {
376
+ maxAge,
377
+ secure: true,
378
+ signed: true,
379
+ httpOnly: true,
380
+ });
381
+ res.send({
382
+ username,
383
+ expiration: maxAge,
384
+ });
385
+ });
386
+ app.get('/login', async (req, res) => {
387
+ if (req.protocol === 'https' && req.headers.authorization) {
388
+ const username = await new Promise(resolve => {
389
+ const basicChecker = basicAuth.check((req) => {
390
+ resolve(req.user);
391
+ });
392
+ // this automatically handles unauthorized.
393
+ basicChecker(req, res);
394
+ });
395
+ const user = await db.tryGet(db_types_1.ScryptedUser, username);
396
+ if (!user.token) {
397
+ user.token = crypto_1.default.randomBytes(16).toString('hex');
398
+ await db.upsert(user);
399
+ }
400
+ res.send({
401
+ username,
402
+ token: user.token,
403
+ });
404
+ return;
405
+ }
406
+ const hasLogin = await db.getCount(db_types_1.ScryptedUser) > 0;
407
+ const { login_user_token } = req.signedCookies;
408
+ if (!login_user_token) {
409
+ res.send({
410
+ error: 'Not logged in.',
411
+ hasLogin,
412
+ });
413
+ return;
414
+ }
415
+ const userTokenParts = login_user_token.split('#');
416
+ const username = userTokenParts[0];
417
+ const timestamp = parseInt(userTokenParts[1]);
418
+ if (timestamp + 86400000 < Date.now()) {
419
+ res.send({
420
+ error: 'Login expired.',
421
+ hasLogin,
422
+ });
423
+ return;
424
+ }
425
+ const user = await db.tryGet(db_types_1.ScryptedUser, username);
426
+ if (!user) {
427
+ res.send({
428
+ error: 'User not found.',
429
+ hasLogin,
430
+ });
431
+ return;
432
+ }
433
+ if (timestamp < user.passwordDate) {
434
+ res.send({
435
+ error: 'Login invalid. Password has changed.',
436
+ hasLogin,
437
+ });
438
+ return;
439
+ }
440
+ res.send({
441
+ expiration: 86400000 - (Date.now() - timestamp),
442
+ username,
443
+ });
444
+ });
445
+ app.get('/', (_req, res) => res.redirect('/endpoint/@scrypted/core/public/'));
446
+ }
447
+ start();
448
+ //# sourceMappingURL=scrypted-server-main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrypted-server-main.js","sourceRoot":"","sources":["../src/scrypted-server-main.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@scrypted/server",
3
- "version": "0.0.116",
3
+ "version": "0.0.118",
4
4
  "description": "",
5
5
  "dependencies": {
6
- "@scrypted/sdk": "^0.0.133",
6
+ "@mapbox/node-pre-gyp": "^1.0.5",
7
+ "@scrypted/ffmpeg": "^1.0.4",
8
+ "@scrypted/sdk": "^0.0.134",
7
9
  "adm-zip": "^0.5.3",
8
10
  "axios": "^0.21.1",
9
11
  "body-parser": "^1.19.0",
@@ -13,6 +15,7 @@
13
15
  "express": "^4.17.1",
14
16
  "http-auth": "^4.1.9",
15
17
  "level": "^6.0.1",
18
+ "linkfs": "^2.1.0",
16
19
  "lodash": "^4.17.21",
17
20
  "memfs": "^3.2.2",
18
21
  "mkdirp": "^1.0.4",
@@ -31,11 +34,9 @@
31
34
  },
32
35
  "optionalDependencies": {
33
36
  "@koush/wrtc": "^0.5.2",
34
- "ffmpeg-for-homebridge": "^0.0.9",
35
37
  "mdns": "^2.7.2"
36
38
  },
37
39
  "devDependencies": {
38
- "@mapbox/node-pre-gyp": "^1.0.5",
39
40
  "@types/adm-zip": "^0.4.33",
40
41
  "@types/cookie-parser": "^1.4.2",
41
42
  "@types/debug": "^4.1.5",
package/python/media.py CHANGED
@@ -1,18 +1,7 @@
1
1
  from __future__ import annotations
2
2
  import scrypted_python.scrypted_sdk
3
- from scrypted_python.scrypted_sdk.types import MediaObject, ScryptedInterfaceProperty
4
- from collections.abc import Mapping
5
- from genericpath import exists
6
- import asyncio
7
- import json
8
- import aiofiles
3
+ from scrypted_python.scrypted_sdk.types import MediaObject
9
4
  import os
10
- from typing_extensions import TypedDict
11
- import base64
12
- from os import sys
13
- import time
14
- import zipfile
15
- import subprocess
16
5
  from typing import Any
17
6
 
18
7
  class MediaObjectRemote:
@@ -13,15 +13,15 @@ import json
13
13
  from asyncio.events import AbstractEventLoop
14
14
  import asyncio
15
15
  import rpc
16
- from genericpath import exists
17
16
  from collections.abc import Mapping
18
- from scrypted_python.scrypted_sdk.types import DeviceManifest, MediaManager, MediaObject, ScryptedInterfaceProperty
17
+ from scrypted_python.scrypted_sdk.types import DeviceManifest, MediaManager, ScryptedInterfaceProperty
19
18
  import scrypted_python.scrypted_sdk
20
19
  from asyncio.futures import Future
21
20
  from asyncio.streams import StreamReader, StreamWriter
22
21
  import os
23
22
  from os import sys
24
23
  import platform
24
+ import shutil
25
25
 
26
26
  class SystemDeviceState(TypedDict):
27
27
  lastEventTime: int
@@ -156,11 +156,19 @@ class PluginRemote:
156
156
  nativeId, *values, sep=sep, end=end, flush=flush), self.loop)
157
157
 
158
158
  async def loadZip(self, packageJson, zipData, options=None):
159
- zipPath = options['filename']
159
+ zipPath: str
160
160
 
161
- f = open(zipPath, 'wb')
162
- f.write(zipData)
163
- f.close()
161
+ if isinstance(zipData, str):
162
+ zipPath = (options and options.get('filename', None)) or zipData
163
+ if zipPath != zipData:
164
+ shutil.copyfile(zipData, zipPath)
165
+ else:
166
+ zipPath = options['filename']
167
+ f = open(zipPath, 'wb')
168
+ f.write(zipData)
169
+ f.close()
170
+
171
+ zipData = None
164
172
 
165
173
  zip = zipfile.ZipFile(zipPath)
166
174
 
@@ -278,7 +286,7 @@ async def readLoop(loop, peer, reader):
278
286
  asyncio.run_coroutine_threadsafe(peer.handleMessage(message), loop)
279
287
  except Exception as e:
280
288
  print('read loop error', e)
281
- pass
289
+ sys.exit()
282
290
 
283
291
 
284
292
  async def async_main(loop: AbstractEventLoop):
package/python/rpc.py CHANGED
@@ -308,8 +308,8 @@ class RpcPeer:
308
308
 
309
309
  result['result'] = self.serialize(value, False)
310
310
  except Exception as e:
311
- print('failure', method, e)
312
311
  tb = traceback.format_exc()
312
+ print('failure', method, e, tb)
313
313
  self.createErrorResult(
314
314
  result, type(e).__name__, str(e), tb)
315
315
 
@@ -1,10 +1,17 @@
1
1
  import { HttpResponse, HttpResponseOptions } from "@scrypted/sdk/types";
2
2
  import { Response } from "express";
3
3
  import mime from "mime";
4
- import AdmZip from "adm-zip";
4
+ import { PROPERTY_PROXY_ONEWAY_METHODS } from "./rpc";
5
+ import { join as pathJoin } from 'path';
6
+ import fs from 'fs';
5
7
 
6
- export function createResponseInterface(res: Response, zip: AdmZip): HttpResponse {
8
+ export function createResponseInterface(res: Response, unzippedDir: string): HttpResponse {
7
9
  class HttpResponseImpl implements HttpResponse {
10
+ [PROPERTY_PROXY_ONEWAY_METHODS] = [
11
+ 'send',
12
+ 'sendFile',
13
+ ];
14
+
8
15
  send(body: string): void;
9
16
  send(body: string, options: HttpResponseOptions): void;
10
17
  send(body: Buffer): void;
@@ -35,13 +42,13 @@ export function createResponseInterface(res: Response, zip: AdmZip): HttpRespons
35
42
  if (!res.getHeader('Content-Type'))
36
43
  res.contentType(mime.lookup(path));
37
44
 
38
- const data = zip.getEntry(`fs/${path}`)?.getData();
39
- if (!data) {
45
+ const filePath = pathJoin(unzippedDir, 'fs', path);
46
+ if (!fs.existsSync(filePath)) {
40
47
  res.status(404);
41
48
  res.end();
42
49
  return;
43
50
  }
44
- res.send(data);
51
+ res.sendFile(filePath);
45
52
  }
46
53
  }
47
54
 
package/src/level.ts CHANGED
@@ -5,8 +5,6 @@
5
5
  // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
6
6
  // TypeScript Version: 2.3
7
7
 
8
- import { asyncFilter } from "./asynciterable-utils";
9
-
10
8
  export interface AbstractOptions {
11
9
  // wtf is this?
12
10
  readonly [k: string]: any;
@@ -7,7 +7,7 @@ import { once } from 'events';
7
7
  import fs from 'fs';
8
8
  import tmp from 'tmp';
9
9
  import os from 'os';
10
- import pathToFfmpeg from 'ffmpeg-for-homebridge';
10
+ import { getInstalledFfmpeg } from '@scrypted/ffmpeg'
11
11
  import { ffmpegLogInitialOutput } from "../media-helpers";
12
12
 
13
13
  function addBuiltins(console: Console, mediaManager: MediaManager) {
@@ -94,7 +94,7 @@ function addBuiltins(console: Console, mediaManager: MediaManager) {
94
94
  })
95
95
  const to = setTimeout(() => {
96
96
  console.log('ffmpeg stream to image convesion timed out.');
97
- cp.kill();
97
+ cp.kill('SIGKILL');
98
98
  }, 10000);
99
99
  await once(cp, 'exit');
100
100
  clearTimeout(to);
@@ -133,7 +133,7 @@ export abstract class MediaManagerBase implements MediaManager {
133
133
  return f;
134
134
 
135
135
  const defaultPath = os.platform() === 'win32' ? 'ffmpeg.exe' : 'ffmpeg';
136
- return pathToFfmpeg || defaultPath;
136
+ return getInstalledFfmpeg() || defaultPath;
137
137
  }
138
138
 
139
139
  getConverters(): BufferConverter[] {