channel-worker 1.3.2 → 1.3.4

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.
Files changed (2) hide show
  1. package/lib/nst-manager.js +50 -65
  2. package/package.json +1 -2
@@ -1,26 +1,26 @@
1
- let NstBrowserV2;
2
- try {
3
- NstBrowserV2 = require('nstbrowser-sdk-node').NstBrowserV2;
4
- } catch {
5
- // SDK not installed
6
- }
7
-
8
1
  class NstManager {
9
2
  constructor(apiKey, options = {}) {
10
- if (!NstBrowserV2) {
11
- throw new Error('nstbrowser-sdk-node not installed. Run: npm install -g nstbrowser-sdk-node');
12
- }
13
3
  this.apiKey = apiKey;
14
- this.client = new NstBrowserV2(apiKey, {
15
- timeout: options.timeout || 60000,
16
- apiAddress: options.apiAddress || 'http://localhost:8848/api/v2',
4
+ this.baseUrl = options.apiAddress || 'http://localhost:8848/api/v2';
5
+ }
6
+
7
+ async api(path, options = {}) {
8
+ const url = path.startsWith('http') ? path : `${this.baseUrl}${path}`;
9
+ const res = await fetch(url, {
10
+ ...options,
11
+ headers: {
12
+ 'x-api-key': this.apiKey,
13
+ 'Content-Type': 'application/json',
14
+ ...options.headers,
15
+ },
17
16
  });
17
+ return res.json();
18
18
  }
19
19
 
20
20
  // Get all running browsers
21
21
  async getRunningBrowsers() {
22
22
  try {
23
- const res = await this.client.browsers().getBrowsers('running');
23
+ const res = await this.api('/browsers/running');
24
24
  return res?.data || [];
25
25
  } catch (err) {
26
26
  console.error(`[nst] Error getting running browsers:`, err.message);
@@ -37,28 +37,19 @@ class NstManager {
37
37
  // Find profile by name, return profileId
38
38
  async findProfile(name) {
39
39
  try {
40
- // Try SDK first
41
- const res = await this.client.profiles().getProfiles({ keyword: name });
42
- let profiles = [];
43
- if (res?.data?.docs && Array.isArray(res.data.docs)) {
44
- profiles = res.data.docs;
45
- } else if (Array.isArray(res?.data)) {
46
- profiles = res.data;
40
+ let allProfiles = [];
41
+ let page = 1;
42
+ while (true) {
43
+ const res = await this.api(`/profiles/?keyword=${encodeURIComponent(name)}&page=${page}&limit=100`);
44
+ const docs = res?.data?.docs || res?.data || [];
45
+ allProfiles = allProfiles.concat(docs);
46
+ const totalPages = res?.data?.totalPage || res?.data?.totalPages || 1;
47
+ if (page >= totalPages || docs.length === 0) break;
48
+ page++;
47
49
  }
48
-
49
- const match = profiles.find(p => p.name?.toLowerCase() === name.toLowerCase());
50
+ console.log(`[nst] Search for "${name}": found ${allProfiles.length} profiles [${allProfiles.map(p => p.name).join(', ')}]`);
51
+ const match = allProfiles.find(p => p.name?.toLowerCase() === name.toLowerCase());
50
52
  if (match) return match.profileId || match._id;
51
-
52
- // Fallback: fetch profiles via local API with exact name search
53
- const rawRes = await fetch(`http://localhost:8848/api/v2/profiles/?keyword=${encodeURIComponent(name)}&limit=100`, {
54
- headers: { 'x-api-key': this.apiKey },
55
- });
56
- const rawData = await rawRes.json();
57
- const allProfiles = rawData?.data?.docs || rawData?.data || [];
58
- console.log(`[nst] Fallback search for "${name}": found ${allProfiles.length} profiles`);
59
- const fallback = allProfiles.find(p => p.name?.toLowerCase() === name.toLowerCase());
60
- if (fallback) return fallback.profileId || fallback._id;
61
-
62
53
  return null;
63
54
  } catch (err) {
64
55
  console.error(`[nst] Error finding profile "${name}":`, err.message);
@@ -75,22 +66,19 @@ class NstManager {
75
66
  }
76
67
 
77
68
  console.log(`[nst] WARNING: Profile "${name}" NOT FOUND — creating new profile...`);
78
- const res = await this.client.profiles().createProfile({
79
- name,
80
- platform: 'Windows',
81
- kernelMilestone: '132',
82
- fingerprint: {
83
- flags: {
84
- audio: 'Noise',
85
- canvas: 'Noise',
86
- fonts: 'Masked',
87
- gpu: 'Allow',
88
- webgl: 'Noise',
69
+ const res = await this.api('/profiles', {
70
+ method: 'POST',
71
+ body: JSON.stringify({
72
+ name,
73
+ platform: 'Windows',
74
+ kernelMilestone: '132',
75
+ fingerprint: {
76
+ flags: { audio: 'Noise', canvas: 'Noise', fonts: 'Masked', gpu: 'Allow', webgl: 'Noise' },
77
+ hardwareConcurrency: 8,
78
+ deviceMemory: 8,
79
+ language: 'en-US',
89
80
  },
90
- hardwareConcurrency: 8,
91
- deviceMemory: 8,
92
- language: 'en-US',
93
- },
81
+ }),
94
82
  });
95
83
 
96
84
  const profileId = res?.data?.profileId || res?.data?._id;
@@ -104,7 +92,10 @@ class NstManager {
104
92
  async setProxy(profileId, proxyUrl) {
105
93
  if (!proxyUrl) return;
106
94
  console.log(`[nst] Setting proxy for ${profileId}: ${proxyUrl}`);
107
- await this.client.profiles().updateProfileProxy(profileId, { url: proxyUrl });
95
+ await this.api(`/profiles/${profileId}/proxy`, {
96
+ method: 'PATCH',
97
+ body: JSON.stringify({ url: proxyUrl }),
98
+ });
108
99
  console.log(`[nst] Proxy set`);
109
100
  }
110
101
 
@@ -115,15 +106,15 @@ class NstManager {
115
106
  profileId = await this.ensureProfile(profileIdOrName);
116
107
  }
117
108
 
118
- // If already running, skip — don't restart
109
+ // If already running, skip
119
110
  if (await this.isProfileRunning(profileId)) {
120
111
  console.log(`[nst] Profile ${profileId} already running — skipping`);
121
112
  return { profileId, alreadyRunning: true };
122
113
  }
123
114
 
124
- // Ensure profile language is en-US to prevent auto-translate
115
+ // Update language to en-US
125
116
  try {
126
- const res = await fetch(`http://localhost:8848/api/v2/profiles/${profileId}`, {
117
+ const res = await fetch(`${this.baseUrl}/profiles/${profileId}`, {
127
118
  method: 'PATCH',
128
119
  headers: { 'Content-Type': 'application/json', 'x-api-key': this.apiKey },
129
120
  body: JSON.stringify({ fingerprint: { language: 'en-US' } }),
@@ -141,12 +132,10 @@ class NstManager {
141
132
  const connectConfig = {
142
133
  headless: false,
143
134
  autoClose: false,
144
- };
145
-
146
- // Disable Chrome auto-translate
147
- connectConfig.args = {
148
- '--lang': 'en-US',
149
- '--disable-features': 'Translate',
135
+ args: {
136
+ '--lang': 'en-US',
137
+ '--disable-features': 'Translate',
138
+ },
150
139
  };
151
140
 
152
141
  if (options.extensionPath) {
@@ -156,11 +145,7 @@ class NstManager {
156
145
  }
157
146
 
158
147
  console.log(`[nst] Connecting browser for profile: ${profileId}`);
159
-
160
- // SDK uses axios which serializes nested objects as config[key]=value
161
- // But Nstbrowser API expects ?config=<JSON-string>
162
- // Workaround: call the API directly with fetch instead of SDK
163
- const apiUrl = `http://localhost:8848/api/v2/connect/${profileId}?config=${encodeURIComponent(JSON.stringify(connectConfig))}`;
148
+ const apiUrl = `${this.baseUrl}/connect/${profileId}?config=${encodeURIComponent(JSON.stringify(connectConfig))}`;
164
149
  const rawRes = await fetch(apiUrl, { headers: { 'x-api-key': this.apiKey } });
165
150
  const res = await rawRes.json();
166
151
  if (res.err) throw new Error(res.msg || 'Failed to connect browser');
@@ -178,7 +163,7 @@ class NstManager {
178
163
  }
179
164
 
180
165
  console.log(`[nst] Stopping browser for profile: ${profileId}`);
181
- await this.client.browsers().stopBrowser(profileId);
166
+ await this.api(`/browsers/${profileId}/stop`, { method: 'PUT' });
182
167
  console.log(`[nst] Browser stopped`);
183
168
  }
184
169
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
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": {
@@ -16,7 +16,6 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "node-fetch": "^3.3.2",
19
- "nstbrowser-sdk-node": "^0.1.1",
20
19
  "ws": "^8.18.0"
21
20
  },
22
21
  "engines": {