iobroker.assistant 1.4.6 → 1.4.7

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.
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FFMPEG_STATIC_RELEASE = void 0;
37
+ exports.ffmpegStaticAsset = ffmpegStaticAsset;
38
+ exports.ffmpegStaticPath = ffmpegStaticPath;
39
+ exports.downloadFfmpegStatic = downloadFfmpegStatic;
40
+ /**
41
+ * A static ffmpeg for hosts without one: the binaries of ffmpeg-static (github.com/eugeneware/ffmpeg-static),
42
+ * downloaded on request ("Download ffmpeg" on the Voice tab) into the instance data dir.
43
+ *
44
+ * Deliberately not the npm package: its install script downloads 20-30 MB for every installation of the adapter,
45
+ * also where nobody uses voice, and newer npm versions no longer run install scripts without asking - then the
46
+ * binary is silently missing. The release and the SHA-256 of every file are pinned here, so a replaced file is
47
+ * refused instead of executed.
48
+ */
49
+ const node_crypto_1 = require("node:crypto");
50
+ const fs = __importStar(require("node:fs"));
51
+ const path = __importStar(require("node:path"));
52
+ const node_stream_1 = require("node:stream");
53
+ const promises_1 = require("node:stream/promises");
54
+ const node_zlib_1 = require("node:zlib");
55
+ /** The ffmpeg-static release. The binaries are newer than its name (Linux arm64: ffmpeg 7.0.2). */
56
+ exports.FFMPEG_STATIC_RELEASE = 'b6.1.1';
57
+ const BASE_URL = `https://github.com/eugeneware/ffmpeg-static/releases/download/${exports.FFMPEG_STATIC_RELEASE}`;
58
+ /** SHA-256 of the gzipped binaries, as GitHub reports them for the release. Key = `<platform>-<arch>` of Node. */
59
+ const ASSETS = {
60
+ 'darwin-arm64': '8923876afa8db5585022d7860ec7e589af192f441c56793971276d450ed3bbfa',
61
+ 'darwin-x64': '929b375c1182d956c51f7ac25e0b2b0411fb01f6f407aa15c9758efeb4242106',
62
+ 'linux-arm': '64b115a12f0ab77c277e3c418aae8b40ef881e75e746a0e2d066a206b9bc5172',
63
+ 'linux-arm64': '754a678672298bc68156adff58aa7385a592c2b30b1d0ae8750c45c915c4bac0',
64
+ 'linux-ia32': '169b27c078a8ecedb814cac67afccf15a9868d63e9d74ef86088adefaa500d00',
65
+ 'linux-x64': 'bfe8a8fc511530457b528c48d77b5737527b504a3797a9bc4866aeca69c2dffa',
66
+ 'win32-x64': '8883a3dffbd0a16cf4ef95206ea05283f78908dbfb118f73c83f4951dcc06d77',
67
+ };
68
+ /**
69
+ * The file for this machine, or `null` if ffmpeg-static has none (e.g. Windows on ARM, FreeBSD).
70
+ *
71
+ * @param platform Node's `process.platform`
72
+ * @param arch Node's `process.arch`
73
+ */
74
+ function ffmpegStaticAsset(platform = process.platform, arch = process.arch) {
75
+ const key = `${platform}-${arch}`;
76
+ return ASSETS[key] ? { name: `ffmpeg-${key}.gz`, sha256: ASSETS[key] } : null;
77
+ }
78
+ /**
79
+ * Where the downloaded binary lives.
80
+ *
81
+ * @param dataDir the instance data dir
82
+ * @param platform Node's `process.platform`
83
+ */
84
+ function ffmpegStaticPath(dataDir, platform = process.platform) {
85
+ return path.join(dataDir, 'ffmpeg', platform === 'win32' ? 'ffmpeg.exe' : 'ffmpeg');
86
+ }
87
+ /**
88
+ * Download, check and unpack the static ffmpeg into `<dataDir>/ffmpeg/`. Replaces an older download.
89
+ *
90
+ * @param dataDir the instance data dir
91
+ * @param options logger; the rest is for tests
92
+ * @returns the path of the binary
93
+ */
94
+ async function downloadFfmpegStatic(dataDir, options = {}) {
95
+ const platform = options.platform ?? process.platform;
96
+ const asset = options.asset === undefined ? ffmpegStaticAsset(platform) : options.asset;
97
+ if (!asset) {
98
+ throw new Error(`there is no ffmpeg download for ${process.platform}-${process.arch} - install ffmpeg yourself and enter its path`);
99
+ }
100
+ const url = `${options.baseUrl ?? BASE_URL}/${asset.name}`;
101
+ const dest = ffmpegStaticPath(dataDir, platform);
102
+ const tmp = `${dest}.part`;
103
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
104
+ const res = await fetch(url, { signal: AbortSignal.timeout(options.timeoutMs ?? 10 * 60_000) });
105
+ if (!res.ok || !res.body) {
106
+ throw new Error(`download of ${url} failed: HTTP ${res.status}`);
107
+ }
108
+ const size = Number(res.headers.get('content-length')) || 0;
109
+ options.log?.info(`Downloading ffmpeg (${asset.name}${size ? `, ${(size / 1e6).toFixed(1)} MB` : ''}) …`);
110
+ // The hash is taken over the gzipped bytes - that is what GitHub publishes.
111
+ const hash = (0, node_crypto_1.createHash)('sha256');
112
+ const tap = new node_stream_1.Transform({
113
+ transform(chunk, _encoding, done) {
114
+ hash.update(chunk);
115
+ done(null, chunk);
116
+ },
117
+ });
118
+ try {
119
+ await (0, promises_1.pipeline)(node_stream_1.Readable.fromWeb(res.body), tap, (0, node_zlib_1.createGunzip)(), fs.createWriteStream(tmp, { mode: 0o755 }));
120
+ const actual = hash.digest('hex');
121
+ if (actual !== asset.sha256) {
122
+ throw new Error(`${asset.name} has the wrong checksum (${actual}) - not used`);
123
+ }
124
+ if (platform !== 'win32') {
125
+ fs.chmodSync(tmp, 0o755);
126
+ }
127
+ fs.rmSync(dest, { force: true });
128
+ fs.renameSync(tmp, dest);
129
+ }
130
+ catch (e) {
131
+ fs.rmSync(tmp, { force: true });
132
+ throw e;
133
+ }
134
+ options.log?.info(`ffmpeg saved to ${dest}`);
135
+ return dest;
136
+ }
137
+ //# sourceMappingURL=ffmpegStatic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffmpegStatic.js","sourceRoot":"","sources":["../../../src/lib/voice/ffmpegStatic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A static ffmpeg for hosts without one: the binaries of ffmpeg-static (github.com/eugeneware/ffmpeg-static),\n * downloaded on request (\"Download ffmpeg\" on the Voice tab) into the instance data dir.\n *\n * Deliberately not the npm package: its install script downloads 20-30 MB for every installation of the adapter,\n * also where nobody uses voice, and newer npm versions no longer run install scripts without asking - then the\n * binary is silently missing. The release and the SHA-256 of every file are pinned here, so a replaced file is\n * refused instead of executed.\n */\nimport { createHash } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable, Transform } from 'node:stream';\nimport type { ReadableStream as WebReadableStream } from 'node:stream/web';\nimport { pipeline } from 'node:stream/promises';\nimport { createGunzip } from 'node:zlib';\n\nimport type { VoiceLogger } from './download';\n\n/** The ffmpeg-static release. The binaries are newer than its name (Linux arm64: ffmpeg 7.0.2). */\nexport const FFMPEG_STATIC_RELEASE = 'b6.1.1';\n\nconst BASE_URL = `https://github.com/eugeneware/ffmpeg-static/releases/download/${FFMPEG_STATIC_RELEASE}`;\n\n/** SHA-256 of the gzipped binaries, as GitHub reports them for the release. Key = `<platform>-<arch>` of Node. */\nconst ASSETS: Record<string, string> = {\n 'darwin-arm64': '8923876afa8db5585022d7860ec7e589af192f441c56793971276d450ed3bbfa',\n 'darwin-x64': '929b375c1182d956c51f7ac25e0b2b0411fb01f6f407aa15c9758efeb4242106',\n 'linux-arm': '64b115a12f0ab77c277e3c418aae8b40ef881e75e746a0e2d066a206b9bc5172',\n 'linux-arm64': '754a678672298bc68156adff58aa7385a592c2b30b1d0ae8750c45c915c4bac0',\n 'linux-ia32': '169b27c078a8ecedb814cac67afccf15a9868d63e9d74ef86088adefaa500d00',\n 'linux-x64': 'bfe8a8fc511530457b528c48d77b5737527b504a3797a9bc4866aeca69c2dffa',\n 'win32-x64': '8883a3dffbd0a16cf4ef95206ea05283f78908dbfb118f73c83f4951dcc06d77',\n};\n\n/** A file of the release: its name and the SHA-256 of the gzipped content. */\nexport interface FfmpegAsset {\n name: string;\n sha256: string;\n}\n\n/**\n * The file for this machine, or `null` if ffmpeg-static has none (e.g. Windows on ARM, FreeBSD).\n *\n * @param platform Node's `process.platform`\n * @param arch Node's `process.arch`\n */\nexport function ffmpegStaticAsset(\n platform: string = process.platform,\n arch: string = process.arch,\n): FfmpegAsset | null {\n const key = `${platform}-${arch}`;\n return ASSETS[key] ? { name: `ffmpeg-${key}.gz`, sha256: ASSETS[key] } : null;\n}\n\n/**\n * Where the downloaded binary lives.\n *\n * @param dataDir the instance data dir\n * @param platform Node's `process.platform`\n */\nexport function ffmpegStaticPath(dataDir: string, platform: string = process.platform): string {\n return path.join(dataDir, 'ffmpeg', platform === 'win32' ? 'ffmpeg.exe' : 'ffmpeg');\n}\n\n/** Options of {@link downloadFfmpegStatic} - besides the logger only for tests. */\nexport interface FfmpegDownloadOptions {\n log?: VoiceLogger;\n /** Release URL without the file name */\n baseUrl?: string;\n /** Instead of the file for this machine */\n asset?: FfmpegAsset | null;\n platform?: string;\n timeoutMs?: number;\n}\n\n/**\n * Download, check and unpack the static ffmpeg into `<dataDir>/ffmpeg/`. Replaces an older download.\n *\n * @param dataDir the instance data dir\n * @param options logger; the rest is for tests\n * @returns the path of the binary\n */\nexport async function downloadFfmpegStatic(dataDir: string, options: FfmpegDownloadOptions = {}): Promise<string> {\n const platform = options.platform ?? process.platform;\n const asset = options.asset === undefined ? ffmpegStaticAsset(platform) : options.asset;\n if (!asset) {\n throw new Error(\n `there is no ffmpeg download for ${process.platform}-${process.arch} - install ffmpeg yourself and enter its path`,\n );\n }\n const url = `${options.baseUrl ?? BASE_URL}/${asset.name}`;\n const dest = ffmpegStaticPath(dataDir, platform);\n const tmp = `${dest}.part`;\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n\n const res = await fetch(url, { signal: AbortSignal.timeout(options.timeoutMs ?? 10 * 60_000) });\n if (!res.ok || !res.body) {\n throw new Error(`download of ${url} failed: HTTP ${res.status}`);\n }\n const size = Number(res.headers.get('content-length')) || 0;\n options.log?.info(`Downloading ffmpeg (${asset.name}${size ? `, ${(size / 1e6).toFixed(1)} MB` : ''}) …`);\n\n // The hash is taken over the gzipped bytes - that is what GitHub publishes.\n const hash = createHash('sha256');\n const tap = new Transform({\n transform(chunk: Buffer, _encoding, done): void {\n hash.update(chunk);\n done(null, chunk);\n },\n });\n try {\n await pipeline(\n Readable.fromWeb(res.body as WebReadableStream),\n tap,\n createGunzip(),\n fs.createWriteStream(tmp, { mode: 0o755 }),\n );\n const actual = hash.digest('hex');\n if (actual !== asset.sha256) {\n throw new Error(`${asset.name} has the wrong checksum (${actual}) - not used`);\n }\n if (platform !== 'win32') {\n fs.chmodSync(tmp, 0o755);\n }\n fs.rmSync(dest, { force: true });\n fs.renameSync(tmp, dest);\n } catch (e) {\n fs.rmSync(tmp, { force: true });\n throw e;\n }\n options.log?.info(`ffmpeg saved to ${dest}`);\n return dest;\n}\n"]}