@paa1997/metho 1.0.0 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paa1997/metho",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Automated recon pipeline: subfinder → gau → filter → katana → findsomething",
5
5
  "type": "module",
6
6
  "bin": {
package/src/gui.html CHANGED
@@ -71,6 +71,14 @@
71
71
  text-transform: none; letter-spacing: 0; font-weight: 400;
72
72
  }
73
73
  .skip-checks input[type="checkbox"] { accent-color: #7c3aed; width: 15px; height: 15px; }
74
+ .input-with-btn { display: flex; gap: 8px; }
75
+ .input-with-btn input { flex: 1; }
76
+ .btn-browse {
77
+ background: #2a2a4a; color: #ccc; border: 1px solid #3a3a5a; border-radius: 6px;
78
+ padding: 9px 14px; font-size: 12px; font-weight: 600; cursor: pointer;
79
+ transition: all 0.15s; white-space: nowrap;
80
+ }
81
+ .btn-browse:hover { background: #7c3aed; color: #fff; border-color: #7c3aed; }
74
82
  .actions { display: flex; gap: 12px; margin-top: 18px; align-items: center; }
75
83
  .btn {
76
84
  padding: 10px 28px; border: none; border-radius: 6px;
@@ -269,7 +277,10 @@
269
277
  </div>
270
278
  <div class="form-group">
271
279
  <label>Output Directory</label>
272
- <input type="text" id="outputDir" placeholder="./metho-results" value="./metho-results">
280
+ <div class="input-with-btn">
281
+ <input type="text" id="outputDir" placeholder="./metho-results" value="./metho-results">
282
+ <button class="btn-browse" onclick="browseFolder()">Browse</button>
283
+ </div>
273
284
  </div>
274
285
  <div class="form-group">
275
286
  <label>FindSomething Script (optional override)</label>
@@ -363,6 +374,16 @@ function getStepNum(name) {
363
374
  return null;
364
375
  }
365
376
 
377
+ async function browseFolder() {
378
+ try {
379
+ const resp = await fetch('/browse-folder');
380
+ const data = await resp.json();
381
+ if (data.path) {
382
+ document.getElementById('outputDir').value = data.path;
383
+ }
384
+ } catch { /* dialog cancelled or unavailable */ }
385
+ }
386
+
366
387
  function esc(str) {
367
388
  const d = document.createElement('div');
368
389
  d.textContent = str;
package/src/server.js CHANGED
@@ -165,6 +165,18 @@ export function startServer(port = 3000) {
165
165
  return res.end(JSON.stringify({ ok: true }));
166
166
  }
167
167
 
168
+ // GET /browse-folder → open native folder picker dialog
169
+ if (method === 'GET' && url === '/browse-folder') {
170
+ try {
171
+ const folder = await openFolderDialog();
172
+ res.writeHead(200, { 'Content-Type': 'application/json' });
173
+ return res.end(JSON.stringify({ path: folder }));
174
+ } catch (err) {
175
+ res.writeHead(200, { 'Content-Type': 'application/json' });
176
+ return res.end(JSON.stringify({ path: null, error: err.message }));
177
+ }
178
+ }
179
+
168
180
  // GET /file?path=... → read result file
169
181
  if (method === 'GET' && url === '/file') {
170
182
  const fullUrl = new URL(req.url, `http://localhost:${port}`);
@@ -259,3 +271,28 @@ function openBrowser(url) {
259
271
  : `xdg-open "${url}"`;
260
272
  exec(cmd, () => {});
261
273
  }
274
+
275
+ function openFolderDialog() {
276
+ return new Promise((resolve, reject) => {
277
+ let cmd;
278
+ if (process.platform === 'win32') {
279
+ cmd = 'powershell -Command "Add-Type -AssemblyName System.Windows.Forms; $f = New-Object System.Windows.Forms.FolderBrowserDialog; $f.Description = \'Select output directory\'; if ($f.ShowDialog() -eq \'OK\') { $f.SelectedPath } else { \'\' }"';
280
+ } else if (process.platform === 'darwin') {
281
+ cmd = "osascript -e 'POSIX path of (choose folder with prompt \"Select output directory\")'";
282
+ } else {
283
+ // Linux — try zenity, fall back to kdialog
284
+ cmd = 'zenity --file-selection --directory --title="Select output directory" 2>/dev/null || kdialog --getexistingdirectory ~ 2>/dev/null';
285
+ }
286
+
287
+ exec(cmd, { timeout: 60000 }, (err, stdout) => {
288
+ const path = (stdout || '').trim();
289
+ if (err && !path) {
290
+ return reject(new Error('Dialog cancelled or unavailable'));
291
+ }
292
+ if (!path) {
293
+ return reject(new Error('No folder selected'));
294
+ }
295
+ resolve(path);
296
+ });
297
+ });
298
+ }
@@ -1,10 +1,9 @@
1
- import { dirname, join } from 'path';
2
- import { fileURLToPath } from 'url';
1
+ import { join } from 'path';
2
+ import { homedir } from 'os';
3
3
  import { TOOLS, STEP_TOOLS } from './registry.js';
4
4
  import { isBinaryAvailable, attemptInstall, installToLocal, isProjectDiscoveryHttpx } from './installer.js';
5
5
 
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const LOCAL_BIN_DIR = join(__dirname, '..', '..', 'bin', 'tools');
6
+ const LOCAL_BIN_DIR = join(homedir(), '.metho', 'bin');
8
7
 
9
8
  // Resolved binary paths — maps tool name to full path (or just the name if on PATH)
10
9
  const resolvedPaths = {};