beast-agent 1.7.0 → 1.9.0

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.
@@ -1,292 +0,0 @@
1
- 'use strict';
2
-
3
- /* ---------- Obscura entegrasyonu ----------
4
- Obscura (github.com/h4ckf0r0day/obscura): Rust tabanlı stealth headless
5
- tarayıcı — anti-detect + V8 JS + gerçek rendering, Chromium'suz.
6
- Beast kullanımı:
7
- 1) Kurulum: releases'taki Windows stealth zip'i %APPDATA%\beast\obscura'ya
8
- açılır (obscura.exe + obscura-worker.exe). İlk açılışta OTOMATİK kurulur.
9
- 2) Arama: `obscura fetch https://html.duckduckgo.com/html/?q=...` çıktısı
10
- DDG sonuç ayrıştırıcısıyla results'a döner — web_search zincirinin
11
- sıralı bir motoru (Ayarlar → Web Arama'dan sıra değiştirilebilir). */
12
-
13
- const fs = require('fs');
14
- const os = require('os');
15
- const path = require('path');
16
- const https = require('https');
17
- const { execFile, spawn } = require('child_process');
18
-
19
- const RELEASE_BASE = 'https://github.com/h4ckf0r0day/obscura/releases/latest/download/';
20
- const WINDOWS_ZIP = 'obscura-x86_64-windows-stealth.zip';
21
- const MAX_ZIP_BYTES = 250 * 1024 * 1024;
22
- const FETCH_TIMEOUT_MS = 25000;
23
- /* content-length gelmezse yüzde tahmini için yaklaşık boyut (stealth zip ≈74 MB) */
24
- const EST_ZIP_BYTES = 74 * 1024 * 1024;
25
-
26
- /* Beast Agent PAKETİNE gömülü zip (vendor/) — varsa HİÇ indirme yapılmaz */
27
- function bundledZip() {
28
- const p = path.join(__dirname, '..', '..', 'vendor', 'obscura.zip');
29
- try { return fs.existsSync(p) ? p : null; } catch { return null; }
30
- }
31
-
32
- function obscuraDir() {
33
- const base = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
34
- return path.join(base, 'beast', 'obscura');
35
- }
36
-
37
- function obscuraExe() {
38
- return path.join(obscuraDir(), 'obscura.exe');
39
- }
40
-
41
- function obscuraInstalled() {
42
- try { return fs.existsSync(obscuraExe()); } catch { return false; }
43
- }
44
-
45
- /* kurulan varyant işareti: stealth zip'te --stealth bayrağı geçerli */
46
- function markVariant(v) {
47
- try { fs.writeFileSync(path.join(obscuraDir(), 'variant.txt'), String(v || 'stealth') + '\n', 'utf8'); } catch {}
48
- }
49
-
50
- function readVariant() {
51
- try { return String(fs.readFileSync(path.join(obscuraDir(), 'variant.txt'), 'utf8')).trim() || 'stealth'; } catch { return 'stealth'; }
52
- }
53
-
54
- /* bina sağ mı: --help 10 sn içinde cevap veriyor mu (oturum başına tek deneme) */
55
- let _okProbe = null;
56
- function obscuraOk() {
57
- if (!obscuraInstalled()) return Promise.resolve(false);
58
- if (_okProbe) return _okProbe;
59
- _okProbe = new Promise((resolve) => {
60
- try {
61
- execFile(obscuraExe(), ['--help'], { timeout: 10000, windowsHide: true }, (err) => resolve(!err));
62
- } catch {
63
- resolve(false);
64
- }
65
- });
66
- return _okProbe;
67
- }
68
-
69
- function httpsDownload(url, redirectsLeft = 5, signal, onProgress) {
70
- return new Promise((resolve, reject) => {
71
- const req = https.get(url, { headers: { 'User-Agent': 'BeastAgent/1.0 (+obscura bootstrap)' } }, (res) => {
72
- if ([301, 302, 303, 307, 308].includes(res.statusCode) && res.headers.location && redirectsLeft > 0) {
73
- res.resume();
74
- return resolve(httpsDownload(new URL(res.headers.location, url).toString(), redirectsLeft - 1, signal, onProgress));
75
- }
76
- if (res.statusCode !== 200) {
77
- res.resume();
78
- return reject(new Error(`indirme başarısız: HTTP ${res.statusCode}`));
79
- }
80
- const total = Number(res.headers['content-length']) || EST_ZIP_BYTES;
81
- const chunks = [];
82
- let size = 0;
83
- let lastPct = -1;
84
- const tick = () => {
85
- /* yüzdeyi INDIRME fazının %1-88 aralığına map et; %1'lik adımda bildir */
86
- const pct = 1 + Math.min(88, Math.floor((size / total) * 88));
87
- if (typeof onProgress === 'function' && pct !== lastPct) {
88
- lastPct = pct;
89
- try { onProgress({ pct, phase: 'indiriliyor', loaded: size, total }); } catch {}
90
- }
91
- };
92
- res.on('data', (c) => {
93
- size += c.length;
94
- if (size > MAX_ZIP_BYTES) {
95
- req.destroy(new Error('dosya çok büyük'));
96
- return;
97
- }
98
- chunks.push(c);
99
- tick();
100
- });
101
- res.on('end', () => {
102
- tick();
103
- resolve(Buffer.concat(chunks));
104
- });
105
- res.on('error', reject);
106
- });
107
- req.on('error', reject);
108
- if (signal) {
109
- if (signal.aborted) return reject(new Error('iptal'));
110
- signal.addEventListener('abort', () => req.destroy(new Error('iptal')), { once: true });
111
- }
112
- });
113
- }
114
-
115
- function psExpand(zipPath, destDir) {
116
- return new Promise((resolve) => {
117
- const cmd = `Expand-Archive -LiteralPath "${zipPath}" -DestinationPath "${destDir}" -Force`;
118
- const child = spawn(
119
- 'powershell.exe',
120
- ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', cmd],
121
- { windowsHide: true }
122
- );
123
- let err = '';
124
- const finish = (ok) => {
125
- clearTimeout(timer);
126
- resolve(ok);
127
- };
128
- const timer = setTimeout(() => {
129
- try { spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true }); } catch {}
130
- finish(false);
131
- }, 180000);
132
- child.stderr.setEncoding('utf8');
133
- child.stderr.on('data', (d) => { err += d; });
134
- child.on('error', () => finish(false));
135
- child.on('close', (code) => finish(code === 0 && !/Expand-Archive :/i.test(err)));
136
- });
137
- }
138
-
139
- /* Obscura'yı kur / güncelle. SIRA: pakete gömülü vendor zip'i (network YOK,
140
- anında) → yoksa GitHub'dan indir. onProgress({pct, phase}). */
141
- async function installObscura(signal, onProgress) {
142
- const tick = (pct, phase) => {
143
- if (typeof onProgress === 'function') {
144
- try { onProgress({ pct, phase: phase || 'indiriliyor' }); } catch {}
145
- }
146
- };
147
- try {
148
- tick(0, 'hazırlanıyor');
149
- const dest = obscuraDir();
150
- fs.mkdirSync(dest, { recursive: true });
151
- const bundled = bundledZip();
152
- let ok = false;
153
- if (bundled) {
154
- /* PAKET İÇİ kurulum — indirme yok, saniyeler sürer */
155
- tick(30, 'kuruluyor');
156
- ok = await psExpand(bundled, dest);
157
- tick(97, 'doğrulanıyor');
158
- } else {
159
- const zipPath = path.join(os.tmpdir(), 'beast-obscura.zip');
160
- const buf = await httpsDownload(RELEASE_BASE + WINDOWS_ZIP, 5, signal, onProgress);
161
- tick(89, 'kuruluyor');
162
- fs.writeFileSync(zipPath, buf);
163
- tick(90, 'kuruluyor');
164
- ok = await psExpand(zipPath, dest);
165
- try { fs.unlinkSync(zipPath); } catch {}
166
- tick(97, 'doğrulanıyor');
167
- }
168
- if (!ok || !obscuraInstalled()) {
169
- return { ok: false, error: 'obscura kurulumu başarısız (zip açılamadı)' };
170
- }
171
- markVariant('stealth');
172
- _okProbe = null; /* yeniden doğrula */
173
- const good = await obscuraOk();
174
- tick(good ? 100 : 98, good ? 'tamamlandı' : 'doğrulanıyor');
175
- return { ok: good, dir: dest, error: good ? null : 'obscura.exe doğrulanamadı' };
176
- } catch (e) {
177
- return { ok: false, error: String((e && e.message) || e) };
178
- }
179
- }
180
-
181
- /* obscura fetch — sayfa HTML'i (abort ile süreç kesilir) */
182
- function obscuraFetchHtml(url, signal, timeoutMs = FETCH_TIMEOUT_MS) {
183
- return new Promise((resolve, reject) => {
184
- const args = ['fetch', url, '--dump', 'html', '--quiet', '--timeout', '20'];
185
- if (readVariant() === 'stealth') args.push('--stealth');
186
- let settled = false;
187
- const finish = (err, html) => {
188
- if (settled) return;
189
- settled = true;
190
- clearTimeout(timer);
191
- if (signal) signal.removeEventListener('abort', onAbort);
192
- err ? reject(err) : resolve(String(html || ''));
193
- };
194
- let child = null;
195
- const onAbort = () => {
196
- try {
197
- if (child && child.pid) spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true });
198
- } catch {}
199
- finish(new Error('obscura fetch iptal edildi'));
200
- };
201
- const timer = setTimeout(() => {
202
- try {
203
- if (child && child.pid) spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true });
204
- } catch {}
205
- finish(new Error('obscura fetch zaman aşımı'));
206
- }, timeoutMs);
207
- if (signal) {
208
- if (signal.aborted) return finish(new Error('iptal'));
209
- signal.addEventListener('abort', onAbort, { once: true });
210
- }
211
- try {
212
- child = execFile(
213
- obscuraExe(),
214
- args,
215
- { timeout: timeoutMs, windowsHide: true, maxBuffer: 8 * 1024 * 1024 },
216
- (err, stdout) => finish(err, stdout)
217
- );
218
- } catch (e) {
219
- finish(e);
220
- }
221
- });
222
- }
223
-
224
- /* lite.duckduckgo sonuç ayrıştırıcı (tablo düzeni, result-link çıpaları) */
225
- function parseDdgLite(html, limit = 8) {
226
- const out = [];
227
- const re = /<a\s+[^>]*class="[^"]*result-link[^"]*"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/g;
228
- let m;
229
- while ((m = re.exec(String(html || ''))) && out.length < limit) {
230
- let href = m[1] || '';
231
- try {
232
- const u = new URL(href, 'https://duckduckgo.com');
233
- const uddg = u.searchParams.get('uddg');
234
- href = uddg ? decodeURIComponent(uddg) : u.toString();
235
- } catch {}
236
- const title = String(m[2] || '').replace(/<[^>]+>/g, '').trim();
237
- if (!title || !/^https?:\/\//i.test(href)) continue;
238
- if (out.some((r) => r.url === href)) continue;
239
- out.push({ title, url: href, snippet: '' });
240
- }
241
- return out;
242
- }
243
-
244
- /* Obscura arama motoru: DDG html (önce) → DDG lite (yedek), stealth ile.
245
- Döndüremiyorsa null — zincir sıradaki motora geçer. */
246
- async function obscuraSearch(query, { maxResults = 8, signal } = {}) {
247
- const q = String(query || '').trim().slice(0, 400);
248
- if (!q || !obscuraInstalled()) return null;
249
- const cap = Math.max(1, Math.min(12, Number(maxResults) || 8));
250
- const targets = [
251
- 'https://html.duckduckgo.com/html/?q=' + encodeURIComponent(q),
252
- 'https://lite.duckduckgo.com/lite/?q=' + encodeURIComponent(q),
253
- ];
254
- for (const url of targets) {
255
- let html = '';
256
- try {
257
- html = await obscuraFetchHtml(url, signal);
258
- } catch {
259
- continue;
260
- }
261
- if (!html) continue;
262
- let results = [];
263
- const { parseDdgResults } = require('./tools'); /* döngüsel require — çağrı anında */
264
- if (/result__a/.test(html)) results = parseDdgResults(html, cap);
265
- if (!results.length) results = parseDdgLite(html, cap);
266
- if (results.length) {
267
- return {
268
- ok: true,
269
- engine: 'obscura',
270
- query: q,
271
- count: results.length,
272
- results: results.map((r) => ({ ...r, engine: 'obscura' })),
273
- };
274
- }
275
- }
276
- return null;
277
- }
278
-
279
- module.exports = {
280
- ENGINE: 'obscura',
281
- RELEASE_BASE,
282
- WINDOWS_ZIP,
283
- bundledZip,
284
- obscuraDir,
285
- obscuraExe,
286
- obscuraInstalled,
287
- obscuraOk,
288
- installObscura,
289
- obscuraFetchHtml,
290
- obscuraSearch,
291
- parseDdgLite,
292
- };