channel-worker 1.3.3 → 1.3.5
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/lib/nst-manager.js +54 -80
- package/package.json +1 -2
package/lib/nst-manager.js
CHANGED
|
@@ -1,29 +1,36 @@
|
|
|
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.
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const rawRes = await fetch(`${this.baseUrl}/browsers/running`, {
|
|
24
|
+
headers: { 'x-api-key': this.apiKey },
|
|
25
|
+
});
|
|
26
|
+
const text = await rawRes.text();
|
|
27
|
+
try {
|
|
28
|
+
const data = JSON.parse(text);
|
|
29
|
+
return data?.data || [];
|
|
30
|
+
} catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
} catch {
|
|
27
34
|
return [];
|
|
28
35
|
}
|
|
29
36
|
}
|
|
@@ -37,36 +44,19 @@ class NstManager {
|
|
|
37
44
|
// Find profile by name, return profileId
|
|
38
45
|
async findProfile(name) {
|
|
39
46
|
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;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const match = profiles.find(p => p.name?.toLowerCase() === name.toLowerCase());
|
|
50
|
-
if (match) return match.profileId || match._id;
|
|
51
|
-
|
|
52
|
-
// Fallback: fetch ALL profiles via local API (paginate if needed)
|
|
53
47
|
let allProfiles = [];
|
|
54
48
|
let page = 1;
|
|
55
49
|
while (true) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
const rawData = await rawRes.json();
|
|
60
|
-
const docs = rawData?.data?.docs || rawData?.data || [];
|
|
50
|
+
const res = await this.api(`/profiles/?keyword=${encodeURIComponent(name)}&page=${page}&limit=100`);
|
|
51
|
+
const docs = res?.data?.docs || res?.data || [];
|
|
61
52
|
allProfiles = allProfiles.concat(docs);
|
|
62
|
-
const totalPages =
|
|
53
|
+
const totalPages = res?.data?.totalPage || res?.data?.totalPages || 1;
|
|
63
54
|
if (page >= totalPages || docs.length === 0) break;
|
|
64
55
|
page++;
|
|
65
56
|
}
|
|
66
|
-
console.log(`[nst]
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
69
|
-
|
|
57
|
+
console.log(`[nst] Search for "${name}": found ${allProfiles.length} profiles [${allProfiles.map(p => p.name).join(', ')}]`);
|
|
58
|
+
const match = allProfiles.find(p => p.name?.toLowerCase() === name.toLowerCase());
|
|
59
|
+
if (match) return match.profileId || match._id;
|
|
70
60
|
return null;
|
|
71
61
|
} catch (err) {
|
|
72
62
|
console.error(`[nst] Error finding profile "${name}":`, err.message);
|
|
@@ -83,22 +73,19 @@ class NstManager {
|
|
|
83
73
|
}
|
|
84
74
|
|
|
85
75
|
console.log(`[nst] WARNING: Profile "${name}" NOT FOUND — creating new profile...`);
|
|
86
|
-
const res = await this.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
canvas: 'Noise',
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
const res = await this.api('/profiles', {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
body: JSON.stringify({
|
|
79
|
+
name,
|
|
80
|
+
platform: 'Windows',
|
|
81
|
+
kernelMilestone: '132',
|
|
82
|
+
fingerprint: {
|
|
83
|
+
flags: { audio: 'Noise', canvas: 'Noise', fonts: 'Masked', gpu: 'Allow', webgl: 'Noise' },
|
|
84
|
+
hardwareConcurrency: 8,
|
|
85
|
+
deviceMemory: 8,
|
|
86
|
+
language: 'en-US',
|
|
97
87
|
},
|
|
98
|
-
|
|
99
|
-
deviceMemory: 8,
|
|
100
|
-
language: 'en-US',
|
|
101
|
-
},
|
|
88
|
+
}),
|
|
102
89
|
});
|
|
103
90
|
|
|
104
91
|
const profileId = res?.data?.profileId || res?.data?._id;
|
|
@@ -112,7 +99,10 @@ class NstManager {
|
|
|
112
99
|
async setProxy(profileId, proxyUrl) {
|
|
113
100
|
if (!proxyUrl) return;
|
|
114
101
|
console.log(`[nst] Setting proxy for ${profileId}: ${proxyUrl}`);
|
|
115
|
-
await this.
|
|
102
|
+
await this.api(`/profiles/${profileId}/proxy`, {
|
|
103
|
+
method: 'PATCH',
|
|
104
|
+
body: JSON.stringify({ url: proxyUrl }),
|
|
105
|
+
});
|
|
116
106
|
console.log(`[nst] Proxy set`);
|
|
117
107
|
}
|
|
118
108
|
|
|
@@ -123,23 +113,13 @@ class NstManager {
|
|
|
123
113
|
profileId = await this.ensureProfile(profileIdOrName);
|
|
124
114
|
}
|
|
125
115
|
|
|
126
|
-
// If already running, skip
|
|
116
|
+
// If already running, skip
|
|
127
117
|
if (await this.isProfileRunning(profileId)) {
|
|
128
118
|
console.log(`[nst] Profile ${profileId} already running — skipping`);
|
|
129
119
|
return { profileId, alreadyRunning: true };
|
|
130
120
|
}
|
|
131
121
|
|
|
132
|
-
//
|
|
133
|
-
try {
|
|
134
|
-
const res = await fetch(`http://localhost:8848/api/v2/profiles/${profileId}`, {
|
|
135
|
-
method: 'PATCH',
|
|
136
|
-
headers: { 'Content-Type': 'application/json', 'x-api-key': this.apiKey },
|
|
137
|
-
body: JSON.stringify({ fingerprint: { language: 'en-US' } }),
|
|
138
|
-
});
|
|
139
|
-
if (!res.ok) console.warn(`[nst] Could not update profile language: ${res.status}`);
|
|
140
|
-
} catch (err) {
|
|
141
|
-
console.warn(`[nst] Could not update profile language:`, err.message);
|
|
142
|
-
}
|
|
122
|
+
// Language set via --lang arg in connectConfig, no need to update profile
|
|
143
123
|
|
|
144
124
|
// Set proxy before launch
|
|
145
125
|
if (options.proxy) {
|
|
@@ -149,12 +129,10 @@ class NstManager {
|
|
|
149
129
|
const connectConfig = {
|
|
150
130
|
headless: false,
|
|
151
131
|
autoClose: false,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
'--lang': 'en-US',
|
|
157
|
-
'--disable-features': 'Translate',
|
|
132
|
+
args: {
|
|
133
|
+
'--lang': 'en-US',
|
|
134
|
+
'--disable-features': 'Translate',
|
|
135
|
+
},
|
|
158
136
|
};
|
|
159
137
|
|
|
160
138
|
if (options.extensionPath) {
|
|
@@ -164,11 +142,7 @@ class NstManager {
|
|
|
164
142
|
}
|
|
165
143
|
|
|
166
144
|
console.log(`[nst] Connecting browser for profile: ${profileId}`);
|
|
167
|
-
|
|
168
|
-
// SDK uses axios which serializes nested objects as config[key]=value
|
|
169
|
-
// But Nstbrowser API expects ?config=<JSON-string>
|
|
170
|
-
// Workaround: call the API directly with fetch instead of SDK
|
|
171
|
-
const apiUrl = `http://localhost:8848/api/v2/connect/${profileId}?config=${encodeURIComponent(JSON.stringify(connectConfig))}`;
|
|
145
|
+
const apiUrl = `${this.baseUrl}/connect/${profileId}?config=${encodeURIComponent(JSON.stringify(connectConfig))}`;
|
|
172
146
|
const rawRes = await fetch(apiUrl, { headers: { 'x-api-key': this.apiKey } });
|
|
173
147
|
const res = await rawRes.json();
|
|
174
148
|
if (res.err) throw new Error(res.msg || 'Failed to connect browser');
|
|
@@ -186,7 +160,7 @@ class NstManager {
|
|
|
186
160
|
}
|
|
187
161
|
|
|
188
162
|
console.log(`[nst] Stopping browser for profile: ${profileId}`);
|
|
189
|
-
await this.
|
|
163
|
+
await this.api(`/browsers/${profileId}/stop`, { method: 'PUT' });
|
|
190
164
|
console.log(`[nst] Browser stopped`);
|
|
191
165
|
}
|
|
192
166
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "channel-worker",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
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": {
|