@dupecom/botcha-cli 0.1.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.
- package/README.md +102 -0
- package/bin/botcha.js +2 -0
- package/dist/commands/benchmark.d.ts +8 -0
- package/dist/commands/benchmark.d.ts.map +1 -0
- package/dist/commands/benchmark.js +89 -0
- package/dist/commands/benchmark.js.map +1 -0
- package/dist/commands/headers.d.ts +7 -0
- package/dist/commands/headers.d.ts.map +1 -0
- package/dist/commands/headers.js +68 -0
- package/dist/commands/headers.js.map +1 -0
- package/dist/commands/solve.d.ts +8 -0
- package/dist/commands/solve.d.ts.map +1 -0
- package/dist/commands/solve.js +78 -0
- package/dist/commands/solve.js.map +1 -0
- package/dist/commands/test.d.ts +7 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +80 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/output.d.ts +26 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +107 -0
- package/dist/lib/output.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# @dupecom/botcha-cli
|
|
2
|
+
|
|
3
|
+
> CLI tool for testing and debugging BOTCHA-protected endpoints
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @dupecom/botcha-cli
|
|
9
|
+
# or use directly with npx
|
|
10
|
+
npx botcha <command>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### Test an Endpoint
|
|
16
|
+
|
|
17
|
+
Check if an endpoint is BOTCHA-protected and test verification:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
botcha test https://api.example.com/agent-only
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Options:
|
|
24
|
+
- `--json` - Output as JSON
|
|
25
|
+
- `-v, --verbose` - Show detailed output
|
|
26
|
+
- `-q, --quiet` - Minimal output
|
|
27
|
+
|
|
28
|
+
### Solve Challenges
|
|
29
|
+
|
|
30
|
+
Solve a specific challenge type:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Get a token
|
|
34
|
+
botcha solve token --url https://botcha.ai/v1/token
|
|
35
|
+
|
|
36
|
+
# Solve a speed challenge
|
|
37
|
+
botcha solve speed --url https://botcha.ai/api/speed-challenge
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
- `--url <url>` - URL to solve challenge from (required)
|
|
42
|
+
- `--json` - Output as JSON
|
|
43
|
+
- `-v, --verbose` - Show detailed output
|
|
44
|
+
- `-q, --quiet` - Minimal output
|
|
45
|
+
|
|
46
|
+
### Benchmark
|
|
47
|
+
|
|
48
|
+
Test performance and reliability:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
botcha benchmark https://api.example.com/agent-only --iterations 100
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Options:
|
|
55
|
+
- `-n, --iterations <number>` - Number of iterations (default: 10)
|
|
56
|
+
- `--json` - Output as JSON
|
|
57
|
+
- `-v, --verbose` - Show each iteration result
|
|
58
|
+
- `-q, --quiet` - Minimal output
|
|
59
|
+
|
|
60
|
+
### Check Headers
|
|
61
|
+
|
|
62
|
+
Inspect BOTCHA headers on any URL:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
botcha headers https://botcha.ai/api
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Options:
|
|
69
|
+
- `--json` - Output as JSON
|
|
70
|
+
- `-v, --verbose` - Show all headers (not just BOTCHA)
|
|
71
|
+
- `-q, --quiet` - Minimal output
|
|
72
|
+
|
|
73
|
+
## Examples
|
|
74
|
+
|
|
75
|
+
### CI/CD Integration
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
# GitHub Actions
|
|
79
|
+
- name: Test BOTCHA Protection
|
|
80
|
+
run: |
|
|
81
|
+
npx botcha test ${{ env.API_URL }}/protected
|
|
82
|
+
npx botcha benchmark ${{ env.API_URL }}/protected --iterations 10
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Debugging
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# See detailed information about challenge solving
|
|
89
|
+
botcha test https://api.example.com/endpoint --verbose
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Scripting
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Get token and use in other commands
|
|
96
|
+
TOKEN=$(botcha solve token --url https://botcha.ai/v1/token --json | jq -r '.token')
|
|
97
|
+
curl -H "Authorization: Bearer $TOKEN" https://botcha.ai/agent-only
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT
|
package/bin/botcha.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../../src/commands/benchmark.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AASD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6F5F"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Benchmark command - Test performance and reliability
|
|
3
|
+
*/
|
|
4
|
+
import { BotchaClient } from '@dupecom/botcha/client';
|
|
5
|
+
import { Output } from '../lib/output.js';
|
|
6
|
+
export async function benchmarkCommand(url, options) {
|
|
7
|
+
const output = new Output(options);
|
|
8
|
+
const iterations = options.iterations || 10;
|
|
9
|
+
output.header(`\n🏃 Running ${iterations} iterations...\n`);
|
|
10
|
+
const client = new BotchaClient({ baseUrl: new URL(url).origin });
|
|
11
|
+
const results = [];
|
|
12
|
+
const startTime = Date.now();
|
|
13
|
+
for (let i = 0; i < iterations; i++) {
|
|
14
|
+
const spinner = output.spinner(`Iteration ${i + 1}/${iterations}...`);
|
|
15
|
+
const iterStart = Date.now();
|
|
16
|
+
try {
|
|
17
|
+
const response = await client.fetch(url);
|
|
18
|
+
const timeMs = Date.now() - iterStart;
|
|
19
|
+
results.push({
|
|
20
|
+
iteration: i + 1,
|
|
21
|
+
success: response.ok,
|
|
22
|
+
timeMs,
|
|
23
|
+
});
|
|
24
|
+
spinner.stop();
|
|
25
|
+
if (options.verbose) {
|
|
26
|
+
const status = response.ok ? '✅' : '❌';
|
|
27
|
+
output.info(`${status} Iteration ${i + 1}: ${timeMs}ms (${response.status})`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const timeMs = Date.now() - iterStart;
|
|
32
|
+
results.push({
|
|
33
|
+
iteration: i + 1,
|
|
34
|
+
success: false,
|
|
35
|
+
timeMs,
|
|
36
|
+
error: error instanceof Error ? error.message : String(error),
|
|
37
|
+
});
|
|
38
|
+
spinner.stop();
|
|
39
|
+
if (options.verbose) {
|
|
40
|
+
output.error(`❌ Iteration ${i + 1}: ${error instanceof Error ? error.message : String(error)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const totalTime = Date.now() - startTime;
|
|
45
|
+
const successCount = results.filter(r => r.success).length;
|
|
46
|
+
const successRate = (successCount / iterations) * 100;
|
|
47
|
+
const times = results.filter(r => r.success).map(r => r.timeMs);
|
|
48
|
+
if (times.length === 0) {
|
|
49
|
+
output.error('All iterations failed!');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const avgTime = times.reduce((a, b) => a + b, 0) / times.length;
|
|
53
|
+
const minTime = Math.min(...times);
|
|
54
|
+
const maxTime = Math.max(...times);
|
|
55
|
+
// Calculate P95
|
|
56
|
+
const sortedTimes = [...times].sort((a, b) => a - b);
|
|
57
|
+
const p95Index = Math.ceil(sortedTimes.length * 0.95) - 1;
|
|
58
|
+
const p95Time = sortedTimes[p95Index] || sortedTimes[sortedTimes.length - 1];
|
|
59
|
+
if (options.json) {
|
|
60
|
+
output.json({
|
|
61
|
+
url,
|
|
62
|
+
iterations,
|
|
63
|
+
successRate,
|
|
64
|
+
successCount,
|
|
65
|
+
failureCount: iterations - successCount,
|
|
66
|
+
avgTimeMs: Math.round(avgTime),
|
|
67
|
+
minTimeMs: minTime,
|
|
68
|
+
maxTimeMs: maxTime,
|
|
69
|
+
p95TimeMs: p95Time,
|
|
70
|
+
totalTimeMs: totalTime,
|
|
71
|
+
requestsPerSec: (iterations / (totalTime / 1000)).toFixed(2),
|
|
72
|
+
results,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.log('\n' + '─'.repeat(50));
|
|
77
|
+
output.header('Results:');
|
|
78
|
+
output.section('Success Rate', `${successRate.toFixed(1)}% (${successCount}/${iterations})`);
|
|
79
|
+
output.section('Avg Time', `${Math.round(avgTime)}ms`);
|
|
80
|
+
output.section('Min Time', `${minTime}ms`);
|
|
81
|
+
output.section('Max Time', `${maxTime}ms`);
|
|
82
|
+
output.section('P95 Time', `${p95Time}ms`);
|
|
83
|
+
console.log();
|
|
84
|
+
output.section('Total Time', `${(totalTime / 1000).toFixed(2)}s`);
|
|
85
|
+
output.section('Requests/sec', (iterations / (totalTime / 1000)).toFixed(2));
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.js","sourceRoot":"","sources":["../../src/commands/benchmark.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/commands/headers.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmExF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headers command - Show BOTCHA headers from a URL
|
|
3
|
+
*/
|
|
4
|
+
import { Output, formatUrl } from '../lib/output.js';
|
|
5
|
+
export async function headersCommand(url, options) {
|
|
6
|
+
const output = new Output(options);
|
|
7
|
+
output.header(`\n🔍 Fetching headers from ${formatUrl(url)}...\n`);
|
|
8
|
+
try {
|
|
9
|
+
const response = await fetch(url, {
|
|
10
|
+
method: 'HEAD',
|
|
11
|
+
});
|
|
12
|
+
const botchaHeaders = {};
|
|
13
|
+
const allHeaders = {};
|
|
14
|
+
response.headers.forEach((value, key) => {
|
|
15
|
+
allHeaders[key] = value;
|
|
16
|
+
if (key.toLowerCase().startsWith('x-botcha-')) {
|
|
17
|
+
botchaHeaders[key] = value;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
if (options.json) {
|
|
21
|
+
output.json({
|
|
22
|
+
url,
|
|
23
|
+
statusCode: response.status,
|
|
24
|
+
botchaHeaders,
|
|
25
|
+
allHeaders: options.verbose ? allHeaders : undefined,
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (Object.keys(botchaHeaders).length === 0) {
|
|
30
|
+
output.warn('No BOTCHA headers found');
|
|
31
|
+
if (options.verbose) {
|
|
32
|
+
console.log('\nAll headers:');
|
|
33
|
+
for (const [key, value] of Object.entries(allHeaders)) {
|
|
34
|
+
console.log(` ${key}: ${value}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
output.success('BOTCHA headers found:');
|
|
40
|
+
console.log();
|
|
41
|
+
for (const [key, value] of Object.entries(botchaHeaders)) {
|
|
42
|
+
console.log(` ${key}: ${value}`);
|
|
43
|
+
}
|
|
44
|
+
if (options.verbose) {
|
|
45
|
+
console.log('\nAll headers:');
|
|
46
|
+
for (const [key, value] of Object.entries(allHeaders)) {
|
|
47
|
+
if (!key.toLowerCase().startsWith('x-botcha-')) {
|
|
48
|
+
console.log(` ${key}: ${value}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (options.json) {
|
|
56
|
+
output.json({
|
|
57
|
+
url,
|
|
58
|
+
success: false,
|
|
59
|
+
error: error instanceof Error ? error.message : String(error),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
output.error(`Failed to fetch headers: ${error instanceof Error ? error.message : String(error)}`);
|
|
64
|
+
}
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/commands/headers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solve.d.ts","sourceRoot":"","sources":["../../src/commands/solve.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ErF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solve command - Solve BOTCHA challenges and output tokens
|
|
3
|
+
*/
|
|
4
|
+
import { BotchaClient } from '@dupecom/botcha/client';
|
|
5
|
+
import { Output } from '../lib/output.js';
|
|
6
|
+
export async function solveCommand(type, options) {
|
|
7
|
+
const output = new Output(options);
|
|
8
|
+
if (!options.url) {
|
|
9
|
+
output.error('--url is required');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const client = new BotchaClient({ baseUrl: new URL(options.url).origin });
|
|
13
|
+
const startTime = Date.now();
|
|
14
|
+
try {
|
|
15
|
+
switch (type.toLowerCase()) {
|
|
16
|
+
case 'speed': {
|
|
17
|
+
output.debug('Solving speed challenge...');
|
|
18
|
+
const { id, answers } = await client.solveChallenge();
|
|
19
|
+
const solveTime = Date.now() - startTime;
|
|
20
|
+
if (options.json) {
|
|
21
|
+
output.json({
|
|
22
|
+
type: 'speed',
|
|
23
|
+
challengeId: id,
|
|
24
|
+
answers,
|
|
25
|
+
solveTimeMs: solveTime,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
output.success(`Solved in ${solveTime}ms!`);
|
|
30
|
+
output.section('Challenge ID', id);
|
|
31
|
+
output.section('Answers', answers.length);
|
|
32
|
+
if (options.verbose) {
|
|
33
|
+
console.log('\nAnswers:', answers);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case 'token': {
|
|
39
|
+
output.debug('Getting token...');
|
|
40
|
+
const token = await client.getToken();
|
|
41
|
+
const solveTime = Date.now() - startTime;
|
|
42
|
+
if (options.json) {
|
|
43
|
+
output.json({
|
|
44
|
+
type: 'token',
|
|
45
|
+
token,
|
|
46
|
+
solveTimeMs: solveTime,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
output.success(`Token acquired in ${solveTime}ms!`);
|
|
51
|
+
console.log('\nToken:');
|
|
52
|
+
console.log(token);
|
|
53
|
+
console.log('\nUse with:');
|
|
54
|
+
console.log(` Authorization: Bearer ${token}`);
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
default:
|
|
59
|
+
output.error(`Unknown challenge type: ${type}`);
|
|
60
|
+
output.info('Supported types: speed, token');
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (options.json) {
|
|
66
|
+
output.json({
|
|
67
|
+
type,
|
|
68
|
+
success: false,
|
|
69
|
+
error: error instanceof Error ? error.message : String(error),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
output.error(`Solve failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
74
|
+
}
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=solve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solve.js","sourceRoot":"","sources":["../../src/commands/solve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFlF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test command - Check if URL is BOTCHA-protected and test verification
|
|
3
|
+
*/
|
|
4
|
+
import { BotchaClient } from '@dupecom/botcha/client';
|
|
5
|
+
import { Output, formatUrl } from '../lib/output.js';
|
|
6
|
+
export async function testCommand(url, options) {
|
|
7
|
+
const output = new Output(options);
|
|
8
|
+
output.header(`\n🔍 Testing ${formatUrl(url)}...\n`);
|
|
9
|
+
const client = new BotchaClient({ baseUrl: new URL(url).origin });
|
|
10
|
+
const startTime = Date.now();
|
|
11
|
+
try {
|
|
12
|
+
// First, make a request to see if BOTCHA is required
|
|
13
|
+
output.debug('Making initial request...');
|
|
14
|
+
const response = await client.fetch(url);
|
|
15
|
+
const totalTime = Date.now() - startTime;
|
|
16
|
+
// Check for BOTCHA headers
|
|
17
|
+
const botchaHeaders = {};
|
|
18
|
+
response.headers.forEach((value, key) => {
|
|
19
|
+
if (key.toLowerCase().startsWith('x-botcha-')) {
|
|
20
|
+
botchaHeaders[key] = value;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const hasBotcha = Object.keys(botchaHeaders).length > 0;
|
|
24
|
+
if (options.json) {
|
|
25
|
+
const result = {
|
|
26
|
+
url,
|
|
27
|
+
protected: hasBotcha,
|
|
28
|
+
statusCode: response.status,
|
|
29
|
+
success: response.ok,
|
|
30
|
+
headers: botchaHeaders,
|
|
31
|
+
totalTimeMs: totalTime,
|
|
32
|
+
};
|
|
33
|
+
output.json(result);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (hasBotcha) {
|
|
37
|
+
output.success('BOTCHA Detected!');
|
|
38
|
+
if (botchaHeaders['x-botcha-version']) {
|
|
39
|
+
output.section('Version', botchaHeaders['x-botcha-version']);
|
|
40
|
+
}
|
|
41
|
+
if (botchaHeaders['x-botcha-methods']) {
|
|
42
|
+
output.section('Methods', botchaHeaders['x-botcha-methods']);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
output.warn('No BOTCHA protection detected');
|
|
47
|
+
}
|
|
48
|
+
console.log();
|
|
49
|
+
if (response.ok) {
|
|
50
|
+
output.success(`Access Granted! (${response.status})`);
|
|
51
|
+
output.timing('Total Time', totalTime);
|
|
52
|
+
// Try to show response body
|
|
53
|
+
const contentType = response.headers.get('content-type') || '';
|
|
54
|
+
if (contentType.includes('application/json')) {
|
|
55
|
+
const data = await response.json();
|
|
56
|
+
console.log('\nResponse:');
|
|
57
|
+
console.log(JSON.stringify(data, null, 2));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
output.error(`Access Denied! (${response.status} ${response.statusText})`);
|
|
62
|
+
output.timing('Total Time', totalTime);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (options.json) {
|
|
68
|
+
output.json({
|
|
69
|
+
url,
|
|
70
|
+
success: false,
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
output.error(`Test failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
76
|
+
}
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQrD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,OAAoB;IACjE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnC,MAAM,CAAC,MAAM,CAAC,gBAAgB,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAErD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,qDAAqD;QACrD,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAEzC,2BAA2B;QAC3B,MAAM,aAAa,GAA2B,EAAE,CAAC;QACjD,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAa,EAAE,GAAW,EAAE,EAAE;YACtD,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC9C,aAAa,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAExD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG;gBACb,GAAG;gBACH,SAAS,EAAE,SAAS;gBACpB,UAAU,EAAE,QAAQ,CAAC,MAAM;gBAC3B,OAAO,EAAE,QAAQ,CAAC,EAAE;gBACpB,OAAO,EAAE,aAAa;gBACtB,WAAW,EAAE,SAAS;aACvB,CAAC;YACF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;YAEnC,IAAI,aAAa,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACtC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,IAAI,aAAa,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACtC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,CAAC,OAAO,CAAC,oBAAoB,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;YAEvC,4BAA4B;YAC5B,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC/D,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC;YAC3E,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IAEH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC;gBACV,GAAG;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* BOTCHA CLI - Test, debug, and interact with BOTCHA from the command line
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { testCommand } from './commands/test.js';
|
|
7
|
+
import { solveCommand } from './commands/solve.js';
|
|
8
|
+
import { benchmarkCommand } from './commands/benchmark.js';
|
|
9
|
+
import { headersCommand } from './commands/headers.js';
|
|
10
|
+
const program = new Command();
|
|
11
|
+
program
|
|
12
|
+
.name('botcha')
|
|
13
|
+
.description('CLI tool for testing and debugging BOTCHA-protected endpoints')
|
|
14
|
+
.version('0.1.0');
|
|
15
|
+
// Test command
|
|
16
|
+
program
|
|
17
|
+
.command('test <url>')
|
|
18
|
+
.description('Check if URL is BOTCHA-protected and test verification')
|
|
19
|
+
.option('--json', 'Output as JSON')
|
|
20
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
21
|
+
.option('-q, --quiet', 'Minimal output')
|
|
22
|
+
.action(testCommand);
|
|
23
|
+
// Solve command
|
|
24
|
+
program
|
|
25
|
+
.command('solve <type>')
|
|
26
|
+
.description('Solve a BOTCHA challenge (types: speed, token)')
|
|
27
|
+
.requiredOption('--url <url>', 'URL to solve challenge from')
|
|
28
|
+
.option('--json', 'Output as JSON')
|
|
29
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
30
|
+
.option('-q, --quiet', 'Minimal output')
|
|
31
|
+
.action(solveCommand);
|
|
32
|
+
// Benchmark command
|
|
33
|
+
program
|
|
34
|
+
.command('benchmark <url>')
|
|
35
|
+
.description('Test performance and reliability')
|
|
36
|
+
.option('-n, --iterations <number>', 'Number of iterations to run', '10')
|
|
37
|
+
.option('--json', 'Output as JSON')
|
|
38
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
39
|
+
.option('-q, --quiet', 'Minimal output')
|
|
40
|
+
.action((url, options) => {
|
|
41
|
+
benchmarkCommand(url, {
|
|
42
|
+
...options,
|
|
43
|
+
iterations: parseInt(options.iterations, 10),
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
// Headers command
|
|
47
|
+
program
|
|
48
|
+
.command('headers <url>')
|
|
49
|
+
.description('Show BOTCHA headers from a URL')
|
|
50
|
+
.option('--json', 'Output as JSON')
|
|
51
|
+
.option('-v, --verbose', 'Show all headers')
|
|
52
|
+
.option('-q, --quiet', 'Minimal output')
|
|
53
|
+
.action(headersCommand);
|
|
54
|
+
// Parse and execute
|
|
55
|
+
program.parse();
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,+DAA+D,CAAC;KAC5E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,eAAe;AACf,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC;KACvC,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,gBAAgB;AAChB,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,gDAAgD,CAAC;KAC7D,cAAc,CAAC,aAAa,EAAE,6BAA6B,CAAC;KAC5D,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC;KACvC,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,oBAAoB;AACpB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,2BAA2B,EAAE,6BAA6B,EAAE,IAAI,CAAC;KACxE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC;KACvC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;IACvB,gBAAgB,CAAC,GAAG,EAAE;QACpB,GAAG,OAAO;QACV,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;KAC7C,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,kBAAkB;AAClB,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC;KAC3C,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC;KACvC,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,oBAAoB;AACpB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface OutputOptions {
|
|
2
|
+
json?: boolean;
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
quiet?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class Output {
|
|
7
|
+
private options;
|
|
8
|
+
constructor(options?: OutputOptions);
|
|
9
|
+
private suppressNonJson;
|
|
10
|
+
success(message: string): void;
|
|
11
|
+
error(message: string): void;
|
|
12
|
+
info(message: string): void;
|
|
13
|
+
warn(message: string): void;
|
|
14
|
+
debug(message: string): void;
|
|
15
|
+
header(message: string): void;
|
|
16
|
+
section(label: string, value: string | number): void;
|
|
17
|
+
json(data: unknown): void;
|
|
18
|
+
table(headers: string[], rows: string[][]): void;
|
|
19
|
+
spinner(message: string): {
|
|
20
|
+
stop: (finalMessage?: string) => void;
|
|
21
|
+
};
|
|
22
|
+
timing(label: string, ms: number): void;
|
|
23
|
+
}
|
|
24
|
+
export declare function formatUrl(url: string): string;
|
|
25
|
+
export declare function formatHeaders(headers: Record<string, string>): void;
|
|
26
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,MAAM;IACL,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE,aAAkB;IAE/C,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK5B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKpD,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIzB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI;IAiBhD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;IA4BnE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;CAMxC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAOnE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal output utilities with colored and formatted output
|
|
3
|
+
*/
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
export class Output {
|
|
6
|
+
options;
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
suppressNonJson() {
|
|
11
|
+
return Boolean(this.options.quiet || this.options.json);
|
|
12
|
+
}
|
|
13
|
+
success(message) {
|
|
14
|
+
if (this.suppressNonJson())
|
|
15
|
+
return;
|
|
16
|
+
console.log(chalk.green('✅'), message);
|
|
17
|
+
}
|
|
18
|
+
error(message) {
|
|
19
|
+
if (this.suppressNonJson())
|
|
20
|
+
return;
|
|
21
|
+
console.error(chalk.red('❌'), message);
|
|
22
|
+
}
|
|
23
|
+
info(message) {
|
|
24
|
+
if (this.suppressNonJson())
|
|
25
|
+
return;
|
|
26
|
+
console.log(chalk.blue('ℹ️ '), message);
|
|
27
|
+
}
|
|
28
|
+
warn(message) {
|
|
29
|
+
if (this.suppressNonJson())
|
|
30
|
+
return;
|
|
31
|
+
console.warn(chalk.yellow('⚠️ '), message);
|
|
32
|
+
}
|
|
33
|
+
debug(message) {
|
|
34
|
+
if (this.suppressNonJson() || !this.options.verbose)
|
|
35
|
+
return;
|
|
36
|
+
console.log(chalk.gray('DEBUG:'), message);
|
|
37
|
+
}
|
|
38
|
+
header(message) {
|
|
39
|
+
if (this.suppressNonJson())
|
|
40
|
+
return;
|
|
41
|
+
console.log(chalk.bold.cyan(message));
|
|
42
|
+
}
|
|
43
|
+
section(label, value) {
|
|
44
|
+
if (this.suppressNonJson())
|
|
45
|
+
return;
|
|
46
|
+
console.log(` ${chalk.dim(label)}: ${value}`);
|
|
47
|
+
}
|
|
48
|
+
json(data) {
|
|
49
|
+
console.log(JSON.stringify(data, null, 2));
|
|
50
|
+
}
|
|
51
|
+
table(headers, rows) {
|
|
52
|
+
if (this.suppressNonJson())
|
|
53
|
+
return;
|
|
54
|
+
const colWidths = headers.map((h, i) => {
|
|
55
|
+
const values = [h, ...rows.map(r => r[i] || '')];
|
|
56
|
+
return Math.max(...values.map(v => v.length));
|
|
57
|
+
});
|
|
58
|
+
const formatRow = (row) => {
|
|
59
|
+
return row.map((cell, i) => cell.padEnd(colWidths[i])).join(' ');
|
|
60
|
+
};
|
|
61
|
+
console.log(chalk.bold(formatRow(headers)));
|
|
62
|
+
console.log(chalk.dim('─'.repeat(colWidths.reduce((a, b) => a + b + 2, 0))));
|
|
63
|
+
rows.forEach(row => console.log(formatRow(row)));
|
|
64
|
+
}
|
|
65
|
+
spinner(message) {
|
|
66
|
+
if (this.suppressNonJson()) {
|
|
67
|
+
return { stop: () => { } };
|
|
68
|
+
}
|
|
69
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
70
|
+
let i = 0;
|
|
71
|
+
let stopped = false;
|
|
72
|
+
const interval = setInterval(() => {
|
|
73
|
+
if (!stopped) {
|
|
74
|
+
process.stdout.write(`\r${chalk.cyan(frames[i])} ${message}`);
|
|
75
|
+
i = (i + 1) % frames.length;
|
|
76
|
+
}
|
|
77
|
+
}, 80);
|
|
78
|
+
return {
|
|
79
|
+
stop: (finalMessage) => {
|
|
80
|
+
stopped = true;
|
|
81
|
+
clearInterval(interval);
|
|
82
|
+
process.stdout.write('\r' + ' '.repeat(message.length + 2) + '\r');
|
|
83
|
+
if (finalMessage) {
|
|
84
|
+
console.log(finalMessage);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
timing(label, ms) {
|
|
90
|
+
if (this.suppressNonJson())
|
|
91
|
+
return;
|
|
92
|
+
const color = ms < 100 ? chalk.green : ms < 500 ? chalk.yellow : chalk.red;
|
|
93
|
+
console.log(` ${chalk.dim(label)}: ${color(`${ms}ms`)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function formatUrl(url) {
|
|
97
|
+
return chalk.underline.blue(url);
|
|
98
|
+
}
|
|
99
|
+
export function formatHeaders(headers) {
|
|
100
|
+
console.log(chalk.bold('\nHeaders:'));
|
|
101
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
102
|
+
if (key.toLowerCase().startsWith('x-botcha-')) {
|
|
103
|
+
console.log(` ${chalk.cyan(key)}: ${value}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dupecom/botcha-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tool for testing and debugging BOTCHA-protected endpoints",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"botcha": "./bin/botcha.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"bin",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsx src/index.ts",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"botcha",
|
|
23
|
+
"cli",
|
|
24
|
+
"bot",
|
|
25
|
+
"ai",
|
|
26
|
+
"agent",
|
|
27
|
+
"testing",
|
|
28
|
+
"debug"
|
|
29
|
+
],
|
|
30
|
+
"author": "Ramin <ramin@dupe.com>",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/i8ramin/botcha"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://botcha.ai",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@dupecom/botcha": "^0.4.1",
|
|
39
|
+
"chalk": "^5.3.0",
|
|
40
|
+
"commander": "^12.1.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20.19.0",
|
|
44
|
+
"tsx": "^4.7.0",
|
|
45
|
+
"typescript": "^5.3.0"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
}
|
|
50
|
+
}
|