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.
- package/lib/nst-manager.js +50 -65
- package/package.json +1 -2
package/lib/nst-manager.js
CHANGED
|
@@ -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.
|
|
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 res = await this.
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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 =
|
|
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.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
canvas: 'Noise',
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
//
|
|
115
|
+
// Update language to en-US
|
|
125
116
|
try {
|
|
126
|
-
const res = await fetch(
|
|
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
|
-
|
|
147
|
-
|
|
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.
|
|
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.
|
|
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": {
|