channel-worker 1.6.5 → 1.6.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.
@@ -187,9 +187,12 @@ class CommandPoller {
187
187
  // Auto-create Nstbrowser profile if not exists
188
188
  await this.nst.ensureProfile(nst_profile_id, { os: os || 'windows' });
189
189
 
190
- // Use Content Creator extension path (separate from channel-manager-ext)
191
- const baseExtPath = this.config.content_creator_ext_path || '';
192
- if (!baseExtPath) throw new Error('content_creator_ext_path not configured in worker config.');
190
+ // Auto-download Content Creator extension if not present
191
+ const path = require('path');
192
+ const os_mod = require('os');
193
+ const defaultCCExtPath = path.join(os_mod.homedir(), 'content-creator-ext');
194
+ const baseExtPath = this.config.content_creator_ext_path || defaultCCExtPath;
195
+ await this._ensureContentCreatorExt(baseExtPath);
193
196
 
194
197
  let extensionPath = baseExtPath;
195
198
 
@@ -201,11 +204,7 @@ class CommandPoller {
201
204
  const uniqueExtPath = baseExtPath + '-' + nst_profile_id + '-' + ts;
202
205
  try {
203
206
  fs.mkdirSync(uniqueExtPath, { recursive: true });
204
- const files = fs.readdirSync(baseExtPath);
205
- for (const f of files) {
206
- const src = path.join(baseExtPath, f);
207
- if (fs.statSync(src).isFile()) fs.copyFileSync(src, path.join(uniqueExtPath, f));
208
- }
207
+ fs.cpSync(baseExtPath, uniqueExtPath, { recursive: true });
209
208
  // Write Veo3-specific config.json
210
209
  fs.writeFileSync(path.join(uniqueExtPath, 'config.json'), JSON.stringify({
211
210
  channelManagerApi: 'https://api.channel.tunasm.art',
@@ -247,6 +246,70 @@ class CommandPoller {
247
246
  }
248
247
  }
249
248
 
249
+ async _ensureContentCreatorExt(extPath) {
250
+ const fs = require('fs');
251
+ const path = require('path');
252
+ const os = require('os');
253
+ const { execSync } = require('child_process');
254
+
255
+ // Check if already downloaded
256
+ const manifestPath = path.join(extPath, 'manifest.json');
257
+ if (fs.existsSync(manifestPath)) {
258
+ // Check for updates
259
+ try {
260
+ const local = JSON.parse(fs.readFileSync(manifestPath, 'utf8')).version;
261
+ const res = await this.api.request('GET', '/cc-extension-download/version');
262
+ const remote = res?.version;
263
+ if (remote && local && remote === local) {
264
+ console.log(`[commands] CC extension up to date (v${local})`);
265
+ return;
266
+ }
267
+ console.log(`[commands] CC extension update: ${local} → ${remote}`);
268
+ } catch {
269
+ console.log('[commands] CC extension exists, skip version check');
270
+ return;
271
+ }
272
+ }
273
+
274
+ console.log(`[commands] Downloading Content Creator extension to ${extPath}...`);
275
+ const tmpArchive = path.join(os.tmpdir(), `content-creator-ext-${Date.now()}.tar.gz`);
276
+ const tmpExtract = path.join(os.tmpdir(), `content-creator-ext-new-${Date.now()}`);
277
+
278
+ try {
279
+ // Download zip from API
280
+ const url = `${this.api.baseUrl}/cc-extension-download/zip`;
281
+ const res = await fetch(url, { headers: { 'x-worker-token': this.api.workerToken } });
282
+ if (!res.ok) throw new Error(`Download failed: ${res.status}`);
283
+ const buffer = Buffer.from(await res.arrayBuffer());
284
+ fs.writeFileSync(tmpArchive, buffer);
285
+
286
+ // Extract
287
+ fs.mkdirSync(tmpExtract, { recursive: true });
288
+ execSync(`tar -xzf "${tmpArchive}" -C "${tmpExtract}"`, { timeout: 30000 });
289
+
290
+ // Tar extracts into subfolder — find it (could be content-creator or content-creator-ext)
291
+ const subdirs = fs.readdirSync(tmpExtract).filter(f => fs.statSync(path.join(tmpExtract, f)).isDirectory());
292
+ const sourceDir = subdirs.length === 1 ? path.join(tmpExtract, subdirs[0]) : tmpExtract;
293
+
294
+ // Replace extension dir
295
+ if (fs.existsSync(extPath)) {
296
+ fs.rmSync(extPath, { recursive: true, force: true });
297
+ }
298
+ fs.mkdirSync(extPath, { recursive: true });
299
+ const files = fs.readdirSync(sourceDir);
300
+ for (const f of files) {
301
+ const src = path.join(sourceDir, f);
302
+ const dest = path.join(extPath, f);
303
+ if (fs.statSync(src).isFile()) fs.copyFileSync(src, dest);
304
+ else if (fs.statSync(src).isDirectory()) fs.cpSync(src, dest, { recursive: true });
305
+ }
306
+ console.log(`[commands] CC extension downloaded to ${extPath}`);
307
+ } finally {
308
+ try { fs.unlinkSync(tmpArchive); } catch {}
309
+ try { fs.rmSync(tmpExtract, { recursive: true, force: true }); } catch {}
310
+ }
311
+ }
312
+
250
313
  async handleScanFacebookPages(command) {
251
314
  const { profile_id } = command.payload || {};
252
315
  console.log(`[commands] Scan Facebook pages — launching profile: ${profile_id}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "1.6.5",
3
+ "version": "1.6.7",
4
4
  "description": "Channel Manager worker daemon — runs on remote machines to execute video pipeline jobs",
5
5
  "main": "lib/daemon.js",
6
6
  "bin": {