@dupecom/botcha-cloudflare 0.3.0 → 0.3.1

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 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAYL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAOtB,KAAK,QAAQ,GAAG;IACd,UAAU,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,iBAAiB,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,GAAG;cAAwB,QAAQ;eAAa,SAAS;yCAAK,CAAC;AAuvBrE,eAAe,GAAG,CAAC;AAGnB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAYL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAOtB,KAAK,QAAQ,GAAG;IACd,UAAU,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,iBAAiB,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,GAAG;cAAwB,QAAQ;eAAa,SAAS;yCAAK,CAAC;AAs3BrE,eAAe,GAAG,CAAC;AAGnB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -67,44 +67,178 @@ async function requireJWT(c, next) {
67
67
  await next();
68
68
  }
69
69
  // ============ ROOT & INFO ============
70
+ // Detect if request is from a bot/agent vs human browser
71
+ function isBot(c) {
72
+ const accept = c.req.header('accept') || '';
73
+ const userAgent = c.req.header('user-agent') || '';
74
+ // Bots typically request JSON or have specific user agents
75
+ if (accept.includes('application/json'))
76
+ return true;
77
+ if (userAgent.includes('curl'))
78
+ return true;
79
+ if (userAgent.includes('httpie'))
80
+ return true;
81
+ if (userAgent.includes('wget'))
82
+ return true;
83
+ if (userAgent.includes('python'))
84
+ return true;
85
+ if (userAgent.includes('node'))
86
+ return true;
87
+ if (userAgent.includes('axios'))
88
+ return true;
89
+ if (userAgent.includes('fetch'))
90
+ return true;
91
+ if (userAgent.includes('bot'))
92
+ return true;
93
+ if (userAgent.includes('anthropic'))
94
+ return true;
95
+ if (userAgent.includes('openai'))
96
+ return true;
97
+ if (userAgent.includes('claude'))
98
+ return true;
99
+ if (userAgent.includes('gpt'))
100
+ return true;
101
+ // If no user agent at all, probably a bot
102
+ if (!userAgent)
103
+ return true;
104
+ return false;
105
+ }
106
+ // ASCII art landing page for humans (plain text, terminal-style)
107
+ function getHumanLanding(version) {
108
+ return `
109
+ ╔══════════════════════════════════════════════════════════════╗
110
+ ║ ║
111
+ ║ ██████╗ ██████╗ ████████╗ ██████╗██╗ ██╗ █████╗ ║
112
+ ║ ██╔══██╗██╔═══██╗╚══██╔══╝██╔════╝██║ ██║██╔══██╗ ║
113
+ ║ ██████╔╝██║ ██║ ██║ ██║ ███████║███████║ ║
114
+ ║ ██╔══██╗██║ ██║ ██║ ██║ ██╔══██║██╔══██║ ║
115
+ ║ ██████╔╝╚██████╔╝ ██║ ╚██████╗██║ ██║██║ ██║ ║
116
+ ║ ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ║
117
+ ║ ║
118
+ ║ Prove you're a bot. Humans need not apply. ║
119
+ ║ ║
120
+ ╠══════════════════════════════════════════════════════════════╣
121
+ ║ ║
122
+ ║ This site is for AI agents and bots, not humans. ║
123
+ ║ ║
124
+ ║ If you're a developer, point your bot here: ║
125
+ ║ ║
126
+ ║ curl https://botcha.ai/v1/challenges ║
127
+ ║ ║
128
+ ║ Or install the SDK: ║
129
+ ║ ║
130
+ ║ npm install @dupecom/botcha ║
131
+ ║ ║
132
+ ║ GitHub: https://github.com/dupe-com/botcha ║
133
+ ║ npm: https://npmjs.com/package/@dupecom/botcha ║
134
+ ║ ║
135
+ ╠══════════════════════════════════════════════════════════════╣
136
+ ║ v${version} https://botcha.ai ║
137
+ ╚══════════════════════════════════════════════════════════════╝
138
+ `;
139
+ }
70
140
  app.get('/', (c) => {
141
+ const version = c.env.BOTCHA_VERSION || '0.3.0';
142
+ // If it's a human browser, show plain text ASCII art
143
+ if (!isBot(c)) {
144
+ return c.text(getHumanLanding(version), 200, {
145
+ 'Content-Type': 'text/plain; charset=utf-8',
146
+ });
147
+ }
148
+ // For bots/agents, return comprehensive JSON documentation
71
149
  return c.json({
72
150
  name: 'BOTCHA',
73
- version: c.env.BOTCHA_VERSION || '0.2.0',
151
+ version,
74
152
  runtime: 'cloudflare-workers',
75
153
  tagline: 'Prove you are a bot. Humans need not apply.',
154
+ description: 'BOTCHA is a reverse CAPTCHA - computational challenges that only AI agents can solve. Use it to protect your APIs from humans and verify bot authenticity.',
155
+ quickstart: {
156
+ step1: 'GET /v1/challenges to receive a challenge',
157
+ step2: 'Solve the SHA256 hash problems within 500ms',
158
+ step3: 'POST your answers to verify',
159
+ step4: 'Receive a JWT token for authenticated access',
160
+ example: 'curl https://botcha.ai/v1/challenges',
161
+ },
76
162
  endpoints: {
77
- '/': 'API info',
78
- '/health': 'Health check',
79
- '/v1/challenges': 'Generate challenge (GET) or verify (POST) - hybrid by default',
80
- '/v1/challenges?type=speed': 'Speed-only challenge (SHA256 in 500ms)',
81
- '/v1/challenges?type=standard': 'Standard challenge (puzzle solving)',
82
- '/v1/hybrid': 'Hybrid challenge - speed + reasoning combined (GET/POST)',
83
- '/v1/reasoning': 'Reasoning-only challenge - LLM questions (GET/POST)',
84
- '/v1/token': 'Get challenge for JWT token flow (GET)',
85
- '/v1/token/verify': 'Verify challenge and get JWT (POST)',
86
- '/v1/challenge/stream': 'SSE streaming challenge (interactive flow)',
87
- '/v1/challenge/stream/:session': 'SSE session actions (POST: go/solve)',
88
- '/agent-only': 'Protected endpoint (requires JWT)',
89
- '/badge/:id': 'Badge verification page (HTML)',
90
- '/badge/:id/image': 'Badge image (SVG)',
91
- '/api/badge/:id': 'Badge verification (JSON)',
163
+ challenges: {
164
+ 'GET /v1/challenges': 'Get hybrid challenge (speed + reasoning) - DEFAULT',
165
+ 'GET /v1/challenges?type=speed': 'Get speed-only challenge (SHA256 in <500ms)',
166
+ 'GET /v1/challenges?type=standard': 'Get standard puzzle challenge',
167
+ 'POST /v1/challenges/:id/verify': 'Verify challenge solution',
168
+ },
169
+ specialized: {
170
+ 'GET /v1/hybrid': 'Get hybrid challenge (speed + reasoning)',
171
+ 'POST /v1/hybrid': 'Verify hybrid challenge',
172
+ 'GET /v1/reasoning': 'Get reasoning-only challenge (LLM questions)',
173
+ 'POST /v1/reasoning': 'Verify reasoning challenge',
174
+ },
175
+ streaming: {
176
+ 'GET /v1/challenge/stream': 'SSE streaming challenge (interactive, real-time)',
177
+ 'POST /v1/challenge/stream/:session': 'Send actions to streaming session',
178
+ },
179
+ authentication: {
180
+ 'GET /v1/token': 'Get challenge for JWT token flow',
181
+ 'POST /v1/token/verify': 'Verify challenge and receive JWT token',
182
+ 'GET /agent-only': 'Protected endpoint (requires Bearer token)',
183
+ },
184
+ badges: {
185
+ 'GET /badge/:id': 'Badge verification page (HTML)',
186
+ 'GET /badge/:id/image': 'Badge image (SVG)',
187
+ 'GET /api/badge/:id': 'Badge verification (JSON)',
188
+ },
189
+ info: {
190
+ 'GET /': 'This documentation (JSON for bots, ASCII for humans)',
191
+ 'GET /health': 'Health check endpoint',
192
+ },
92
193
  },
93
- defaultChallenge: 'hybrid',
94
- rateLimit: {
95
- free: '100 challenges/hour/IP',
96
- headers: ['X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-RateLimit-Reset'],
194
+ challengeTypes: {
195
+ speed: {
196
+ description: 'Compute SHA256 hashes of 5 numbers in under 500ms',
197
+ difficulty: 'Only bots can solve this fast enough',
198
+ timeLimit: '500ms',
199
+ },
200
+ reasoning: {
201
+ description: 'Answer 3 questions requiring AI reasoning capabilities',
202
+ difficulty: 'Requires LLM-level comprehension',
203
+ timeLimit: '30s',
204
+ },
205
+ hybrid: {
206
+ description: 'Combines speed AND reasoning challenges',
207
+ difficulty: 'The ultimate bot verification',
208
+ timeLimit: 'Speed: 500ms, Reasoning: 30s',
209
+ },
97
210
  },
98
211
  authentication: {
99
- flow: 'GET /v1/token → solve challenge → POST /v1/token/verify → Bearer token',
212
+ flow: [
213
+ '1. GET /v1/token - receive challenge',
214
+ '2. Solve the challenge',
215
+ '3. POST /v1/token/verify - submit solution',
216
+ '4. Receive JWT token (valid 1 hour)',
217
+ '5. Use: Authorization: Bearer <token>',
218
+ ],
100
219
  tokenExpiry: '1 hour',
101
220
  usage: 'Authorization: Bearer <token>',
102
221
  },
103
- discovery: {
222
+ rateLimit: {
223
+ free: '100 challenges/hour/IP',
224
+ headers: ['X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-RateLimit-Reset'],
225
+ },
226
+ sdk: {
227
+ npm: 'npm install @dupecom/botcha',
228
+ cloudflare: 'npm install @dupecom/botcha-cloudflare',
229
+ usage: "import { BotchaClient } from '@dupecom/botcha/client'",
230
+ },
231
+ links: {
232
+ github: 'https://github.com/dupe-com/botcha',
233
+ npm: 'https://www.npmjs.com/package/@dupecom/botcha',
234
+ npmCloudflare: 'https://www.npmjs.com/package/@dupecom/botcha-cloudflare',
104
235
  openapi: 'https://botcha.ai/openapi.json',
105
236
  aiPlugin: 'https://botcha.ai/.well-known/ai-plugin.json',
106
- npm: 'https://www.npmjs.com/package/@dupecom/botcha-cloudflare',
107
- github: 'https://github.com/i8ramin/botcha',
237
+ },
238
+ contributing: {
239
+ repo: 'https://github.com/dupe-com/botcha',
240
+ issues: 'https://github.com/dupe-com/botcha/issues',
241
+ pullRequests: 'https://github.com/dupe-com/botcha/pulls',
108
242
  },
109
243
  });
110
244
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dupecom/botcha-cloudflare",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "BOTCHA for Cloudflare Workers - Prove you're a bot. Humans need not apply.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",