sni-cli 1.2.1__tar.gz → 1.2.3__tar.gz

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.
Files changed (45) hide show
  1. {sni_cli-1.2.1 → sni_cli-1.2.3}/PKG-INFO +18 -14
  2. {sni_cli-1.2.1 → sni_cli-1.2.3}/README.md +17 -13
  3. {sni_cli-1.2.1 → sni_cli-1.2.3}/pyproject.toml +1 -1
  4. sni_cli-1.2.3/sni/__init__.py +1 -0
  5. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/cli.py +20 -10
  6. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/allanime.py +54 -15
  7. sni_cli-1.2.3/worker/README.md +133 -0
  8. sni_cli-1.2.1/sni/__init__.py +0 -1
  9. {sni_cli-1.2.1 → sni_cli-1.2.3}/.gitignore +0 -0
  10. {sni_cli-1.2.1 → sni_cli-1.2.3}/LICENSE +0 -0
  11. {sni_cli-1.2.1 → sni_cli-1.2.3}/install.ps1 +0 -0
  12. {sni_cli-1.2.1 → sni_cli-1.2.3}/install.sh +0 -0
  13. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/__main__.py +0 -0
  14. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/config.py +0 -0
  15. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/exceptions.py +0 -0
  16. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/logger.py +0 -0
  17. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/player.py +0 -0
  18. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/__init__.py +0 -0
  19. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/base.py +0 -0
  20. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/cache.py +0 -0
  21. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/extractors/__init__.py +0 -0
  22. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/extractors/megacloud.py +0 -0
  23. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/extractors/vixcloud.py +0 -0
  24. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/registry.py +0 -0
  25. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/__init__.py +0 -0
  26. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/app.py +0 -0
  27. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/bridge.py +0 -0
  28. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/__init__.py +0 -0
  29. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/help.py +0 -0
  30. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/history.py +0 -0
  31. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/home.py +0 -0
  32. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/player.py +0 -0
  33. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/widgets/__init__.py +0 -0
  34. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/widgets/ascii_art.py +0 -0
  35. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/widgets/info_box.py +0 -0
  36. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/ui.py +0 -0
  37. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/watch_history.py +0 -0
  38. {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/wizard.py +0 -0
  39. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/__init__.py +0 -0
  40. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/conftest.py +0 -0
  41. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_allanime_captcha.py +0 -0
  42. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_cache.py +0 -0
  43. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_config.py +0 -0
  44. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_exceptions.py +0 -0
  45. {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_providers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sni-cli
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Stream Ninja Interface — terminal-based anime streaming CLI + TUI
5
5
  Project-URL: Homepage, https://github.com/sundeepyt2/SNI
6
6
  Project-URL: Source, https://github.com/sundeepyt2/SNI
@@ -380,26 +380,30 @@ echo 'cf_clearance=...;' > ~/.config/sni/allanime_cookies.txt
380
380
  sni play "one piece" --cookie 'cf_clearance=...;'
381
381
  ```
382
382
 
383
- ### Option 2 — Cloudflare Worker (last resort for VPN/shared IPs that are permanently captcha-walled AND cookies + public proxies don't work)
383
+ ### Option 2 — Self-hosted proxy worker (last resort for VPN/shared IPs that are permanently captcha-walled AND cookies + public proxies don't work)
384
384
 
385
- This is the most powerful bypass it proxies AllAnime API requests through Cloudflare's own IPs, which AllAnime rarely challenges. Only set this up if Option 1 fails AND SNI's built-in proxy fallback doesn't work for you.
385
+ SNI ships with ready-to-deploy proxy worker code in the [`worker/`](worker/) directory. The worker proxies AllAnime API requests through a clean IP (the platform's IP), which AllAnime's edge doesn't flag. **Three deployment platforms are supported all have free tiers, none require a credit card:**
386
386
 
387
- **Deploy via Cloudflare** (free, requires a Cloudflare account):
387
+ | Platform | Difficulty | Setup time | Why pick this |
388
+ |---|---|---|---|
389
+ | **Deno Deploy** | Easiest | ~2 min | Most reliable as of 2026; playground = no GitHub repo needed |
390
+ | **Vercel Edge Functions** | Easy | ~3 min | Good if you already use Vercel |
391
+ | **Cloudflare Workers** | Hard right now | ~5 min | Known dashboard deploy bugs; use only if others fail |
388
392
 
389
- 1. Go to https://dash.cloudflare.com Workers & Pages Create
390
- 2. Paste the contents of [`cf-worker/worker.js`](https://github.com/smithmx20/XAN/blob/main/cf-worker/worker.js) from the XAN repo
391
- 3. Deploy, copy the worker URL (e.g. `https://xan-proxy.you.workers.dev`)
392
- 4. Save it to SNI:
393
+ **Full step-by-step instructions for all three platforms are in [`worker/README.md`](worker/README.md).**
394
+
395
+ Quick Deno Deploy setup (recommended):
396
+
397
+ 1. Go to https://dash.deno.com → sign in with GitHub → "New Project" → "Playground"
398
+ 2. Paste the contents of [`worker/proxy.deno.js`](worker/proxy.deno.js) → click "Save & Deploy"
399
+ 3. Copy the URL (e.g. `https://your-project.deno.dev`)
400
+ 4. Save to SNI:
393
401
 
394
402
  ```bash
395
- sni config --update allanime_cf_worker_url='https://xan-proxy.you.workers.dev'
403
+ sni config --update allanime_cf_worker_url='https://your-project.deno.dev'
396
404
  ```
397
405
 
398
- **Can't create a Cloudflare account?** Deploy the same `worker.js` code to any of these alternative platforms (all have free tiers, none require a credit card):
399
-
400
- - **Deno Deploy** (https://dash.deno.com) — free, no card required, fastest setup. Wrap the worker's `fetch` handler in a `Deno.serve()` call.
401
- - **Vercel Edge Functions** (https://vercel.com) — free tier. Adapt the handler to Vercel's `export default function handler(req: Request)` signature.
402
- - **Netlify Functions** (https://netlify.com) — free tier. Convert to Netlify's `exports.handler` format.
406
+ 5. Try: `sni play "one piece"`
403
407
 
404
408
  The worker code is platform-agnostic — it's just a `fetch` handler that proxies a request. The only thing that changes between platforms is the entry-point wrapper.
405
409
 
@@ -327,26 +327,30 @@ echo 'cf_clearance=...;' > ~/.config/sni/allanime_cookies.txt
327
327
  sni play "one piece" --cookie 'cf_clearance=...;'
328
328
  ```
329
329
 
330
- ### Option 2 — Cloudflare Worker (last resort for VPN/shared IPs that are permanently captcha-walled AND cookies + public proxies don't work)
330
+ ### Option 2 — Self-hosted proxy worker (last resort for VPN/shared IPs that are permanently captcha-walled AND cookies + public proxies don't work)
331
331
 
332
- This is the most powerful bypass it proxies AllAnime API requests through Cloudflare's own IPs, which AllAnime rarely challenges. Only set this up if Option 1 fails AND SNI's built-in proxy fallback doesn't work for you.
332
+ SNI ships with ready-to-deploy proxy worker code in the [`worker/`](worker/) directory. The worker proxies AllAnime API requests through a clean IP (the platform's IP), which AllAnime's edge doesn't flag. **Three deployment platforms are supported all have free tiers, none require a credit card:**
333
333
 
334
- **Deploy via Cloudflare** (free, requires a Cloudflare account):
334
+ | Platform | Difficulty | Setup time | Why pick this |
335
+ |---|---|---|---|
336
+ | **Deno Deploy** | Easiest | ~2 min | Most reliable as of 2026; playground = no GitHub repo needed |
337
+ | **Vercel Edge Functions** | Easy | ~3 min | Good if you already use Vercel |
338
+ | **Cloudflare Workers** | Hard right now | ~5 min | Known dashboard deploy bugs; use only if others fail |
335
339
 
336
- 1. Go to https://dash.cloudflare.com Workers & Pages Create
337
- 2. Paste the contents of [`cf-worker/worker.js`](https://github.com/smithmx20/XAN/blob/main/cf-worker/worker.js) from the XAN repo
338
- 3. Deploy, copy the worker URL (e.g. `https://xan-proxy.you.workers.dev`)
339
- 4. Save it to SNI:
340
+ **Full step-by-step instructions for all three platforms are in [`worker/README.md`](worker/README.md).**
341
+
342
+ Quick Deno Deploy setup (recommended):
343
+
344
+ 1. Go to https://dash.deno.com → sign in with GitHub → "New Project" → "Playground"
345
+ 2. Paste the contents of [`worker/proxy.deno.js`](worker/proxy.deno.js) → click "Save & Deploy"
346
+ 3. Copy the URL (e.g. `https://your-project.deno.dev`)
347
+ 4. Save to SNI:
340
348
 
341
349
  ```bash
342
- sni config --update allanime_cf_worker_url='https://xan-proxy.you.workers.dev'
350
+ sni config --update allanime_cf_worker_url='https://your-project.deno.dev'
343
351
  ```
344
352
 
345
- **Can't create a Cloudflare account?** Deploy the same `worker.js` code to any of these alternative platforms (all have free tiers, none require a credit card):
346
-
347
- - **Deno Deploy** (https://dash.deno.com) — free, no card required, fastest setup. Wrap the worker's `fetch` handler in a `Deno.serve()` call.
348
- - **Vercel Edge Functions** (https://vercel.com) — free tier. Adapt the handler to Vercel's `export default function handler(req: Request)` signature.
349
- - **Netlify Functions** (https://netlify.com) — free tier. Convert to Netlify's `exports.handler` format.
353
+ 5. Try: `sni play "one piece"`
350
354
 
351
355
  The worker code is platform-agnostic — it's just a `fetch` handler that proxies a request. The only thing that changes between platforms is the entry-point wrapper.
352
356
 
@@ -9,7 +9,7 @@ build-backend = "hatchling.build"
9
9
  # just `sni` (defined below in [project.scripts]), so users run `sni play`,
10
10
  # `sni tui`, etc. — only `pip install sni-cli` differs from the bare name.
11
11
  name = "sni-cli"
12
- version = "1.2.1"
12
+ version = "1.2.3"
13
13
  description = "Stream Ninja Interface — terminal-based anime streaming CLI + TUI"
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.10"
@@ -0,0 +1 @@
1
+ __version__ = "1.2.3"
@@ -142,6 +142,8 @@ async def _search(
142
142
  results.append((provider_name, hits))
143
143
  except CaptchaRequiredError:
144
144
  raise # let the caller print the helpful panel
145
+ except ProviderError:
146
+ raise # let the caller print the error
145
147
  except Exception as e:
146
148
  logger.exception(f"Search failed for '{query}' with provider '{provider_name}'")
147
149
  typer.echo(f"Search failed: {type(e).__name__}: {e}")
@@ -192,6 +194,9 @@ async def _play(
192
194
  except CaptchaRequiredError as e:
193
195
  _print_captcha_help(e)
194
196
  return
197
+ except ProviderError as e:
198
+ typer.echo(f"Error: {e}")
199
+ return
195
200
  if not results:
196
201
  typer.echo("No results found.")
197
202
  return
@@ -257,6 +262,9 @@ async def _watch(
257
262
  except CaptchaRequiredError as e:
258
263
  _print_captcha_help(e)
259
264
  return
265
+ except ProviderError as e:
266
+ typer.echo(f"Error: {e}")
267
+ return
260
268
  if not results:
261
269
  typer.echo("No results found.")
262
270
  return
@@ -305,6 +313,9 @@ async def _search_cmd(
305
313
  except CaptchaRequiredError as e:
306
314
  _print_captcha_help(e)
307
315
  raise typer.Exit(code=1)
316
+ except ProviderError as e:
317
+ typer.echo(f"Error: {e}")
318
+ raise typer.Exit(code=1)
308
319
 
309
320
  if not results:
310
321
  typer.echo("No results found.")
@@ -518,17 +529,16 @@ def config(
518
529
  " sni config --update allanime_cookies='cf_clearance=...;'\n"
519
530
  " Or write to file (easier to refresh):\n"
520
531
  f" echo 'cf_clearance=...;' > {DEFAULT_COOKIES_PATH}\n\n"
521
- "[bold yellow]Option 2 - Cloudflare Worker[/bold yellow]\n"
532
+ "[bold yellow]Option 2 - Self-hosted proxy worker[/bold yellow]\n"
522
533
  "[bold yellow](last resort for VPN/shared IPs):[/bold yellow]\n"
523
- " Deploy the XAN CF Worker (free, requires Cloudflare account):\n"
524
- " 1. https://dash.cloudflare.com -> Workers & Pages -> Create\n"
525
- " 2. Paste XAN/cf-worker/worker.js from the XAN repo\n"
526
- " 3. Deploy, copy the worker URL\n"
527
- " 4. sni config --update allanime_cf_worker_url='https://your-worker.workers.dev'\n"
528
- " Can't create a Cloudflare account? Deploy the same worker.js to:\n"
529
- " - Deno Deploy (https://dash.deno.com) - free, no card required\n"
530
- " - Vercel Edge Functions (https://vercel.com) - free tier\n"
531
- " - Netlify Functions (https://netlify.com) - free tier\n",
534
+ " SNI ships worker code in the worker/ directory. Deploy to ANY of:\n"
535
+ " - Deno Deploy (recommended): https://dash.deno.com -> Playground\n"
536
+ " Paste worker/proxy.deno.js -> Save & Deploy. ~2 min, no card.\n"
537
+ " - Vercel Edge Functions: https://vercel.com (3 min)\n"
538
+ " - Cloudflare Workers: https://dash.cloudflare.com (5 min, flaky)\n"
539
+ " See worker/README.md in the repo for full step-by-step.\n"
540
+ " Then save the URL:\n"
541
+ " sni config --update allanime_cf_worker_url='https://your-deployment'\n",
532
542
  title="AllAnime captcha bypass",
533
543
  border_style="cyan",
534
544
  ))
@@ -58,8 +58,8 @@ USER_AGENT = (
58
58
  REFERER = "https://youtu-chan.com"
59
59
  ORIGIN = "https://youtu-chan.com"
60
60
 
61
- REQUEST_TIMEOUT = 15.0
62
- CLOCK_TIMEOUT = 20.0
61
+ REQUEST_TIMEOUT = 30.0 # increased from 15s — proxy connections can be slow
62
+ CLOCK_TIMEOUT = 30.0
63
63
 
64
64
  # Regex used by the embed scraper to pull HLS / MP4 URLs out of HTML pages.
65
65
  # Mirrors XAN's scrapeEmbedPage regexes.
@@ -146,6 +146,44 @@ def _is_captcha_response(resp: httpx.Response) -> bool:
146
146
  return "just a moment" in body_start or "cf-mitigated" in resp.headers
147
147
 
148
148
 
149
+ def _wrap_fallback_error(last_error: Optional[Exception], endpoint: str) -> Exception:
150
+ """Wrap a network/captcha error in a user-friendly ProviderError.
151
+
152
+ If the last error was already a CaptchaRequiredError, return it as-is
153
+ (it already has a helpful hint). If it was a network error (ConnectTimeout,
154
+ ReadTimeout, etc.), wrap it in a ProviderError with a clear message
155
+ explaining that SNI couldn't reach AllAnime and suggesting fixes.
156
+ """
157
+ if last_error is None:
158
+ return CaptchaRequiredError(f"AllAnime {endpoint} failed with no specific error")
159
+
160
+ if isinstance(last_error, CaptchaRequiredError):
161
+ return last_error
162
+
163
+ # Network errors (ConnectTimeout, ReadTimeout, ConnectError, etc.)
164
+ if isinstance(last_error, (httpx.TimeoutException, httpx.HTTPError)):
165
+ err_name = type(last_error).__name__
166
+ return ProviderError(
167
+ f"SNI could not connect to AllAnime ({err_name} on {endpoint}).\n\n"
168
+ f"This is a NETWORK issue, not a captcha. SNI tried direct + proxy.cors.sh "
169
+ f"but couldn't reach any of them.\n\n"
170
+ f"Possible causes:\n"
171
+ f" 1. Your internet is down or unstable\n"
172
+ f" 2. Your ISP/firewall blocks api.allanime.day or proxy.cors.sh\n"
173
+ f" 3. Your DNS can't resolve these hosts\n"
174
+ f" 4. You're on a restrictive network (school/work/country firewall)\n\n"
175
+ f"Try:\n"
176
+ f" - Check your internet: curl -I https://api.allanime.day\n"
177
+ f" - Try a different network (mobile hotspot, VPN)\n"
178
+ f" - If on a VPN, try WITHOUT it (some VPNs are blocked)\n"
179
+ f" - Check DNS: nslookup api.allanime.day\n"
180
+ f" - Try again in a few minutes (temporary outage)"
181
+ )
182
+
183
+ # Any other exception — wrap it
184
+ return ProviderError(f"AllAnime {endpoint} failed: {type(last_error).__name__}: {last_error}")
185
+
186
+
149
187
  class AllAnimeProvider(Provider):
150
188
  name = "allanime"
151
189
  domain = "allanime.day"
@@ -161,12 +199,11 @@ class AllAnimeProvider(Provider):
161
199
 
162
200
  # Free public CORS proxies that support POST + JSON bodies. SNI tries
163
201
  # each one in order when the direct request to api.allanime.day is
164
- # captcha-walled. proxy.cors.sh is the most reliable as of 2026; the
165
- # others are kept as backup in case cors.sh ever rate-limits or goes
166
- # down. Format: a format string with a single {url} placeholder.
202
+ # captcha-walled. As of 2026, most public CORS proxies have shut down
203
+ # or block POST. proxy.cors.sh is the only reliable one left.
204
+ # Format: a format string with a single {url} placeholder.
167
205
  PUBLIC_PROXIES = [
168
206
  "https://proxy.cors.sh/{url}",
169
- "https://thingproxy.freeboard.io/fetch/{url}",
170
207
  ]
171
208
 
172
209
  def __init__(self, cookies: str = "", cf_worker_url: str = ""):
@@ -205,8 +242,8 @@ class AllAnimeProvider(Provider):
205
242
  Fallback order:
206
243
  1. Direct request to api.allanime.day (fastest when not captcha-walled)
207
244
  2. Each public CORS proxy in PUBLIC_PROXIES (no user config needed)
208
- 3. CF Worker (only if user configured allanime_cf_worker_url — but
209
- CF Workers are GET-only, so this raises a clear error instead)
245
+ 3. CF Worker (if user configured allanime_cf_worker_url — the v3
246
+ worker in worker/proxy.js supports POST)
210
247
 
211
248
  CaptchaRequiredError is raised only when ALL fallbacks fail.
212
249
  """
@@ -218,6 +255,12 @@ class AllAnimeProvider(Provider):
218
255
  fallbacks: List[tuple] = [("direct", self.GRAPHQL_URL)]
219
256
  for i in range(len(self.PUBLIC_PROXIES)):
220
257
  fallbacks.append(("proxy", self._proxy_url(i, self.GRAPHQL_URL)))
258
+ if self.cf_worker_url:
259
+ # CF Worker v3 supports POST — body is forwarded as-is
260
+ fallbacks.append(("worker", _build_cf_worker_url(
261
+ self.cf_worker_url, self.GRAPHQL_URL,
262
+ extra_headers={"Referer": self.REFERER, "Origin": self.ORIGIN},
263
+ )))
221
264
 
222
265
  # If a proxy previously worked, try it first (skip the dead direct)
223
266
  if self._working_proxy_idx is not None:
@@ -269,10 +312,8 @@ class AllAnimeProvider(Provider):
269
312
  )
270
313
  return raw
271
314
 
272
- # All fallbacks failed
273
- raise last_error or CaptchaRequiredError(
274
- "All AllAnime API fallbacks failed for /api/graphql",
275
- )
315
+ # All fallbacks failed — wrap the error in a user-friendly message
316
+ raise _wrap_fallback_error(last_error, "/api/graphql")
276
317
 
277
318
  async def _get_persisted(self, variables: dict) -> dict:
278
319
  """GET /api?variables=...&extensions=persistedQuery...
@@ -349,9 +390,7 @@ class AllAnimeProvider(Provider):
349
390
  )
350
391
  return raw
351
392
 
352
- raise last_error or CaptchaRequiredError(
353
- "All AllAnime API fallbacks failed for /api persisted query",
354
- )
393
+ raise _wrap_fallback_error(last_error, "/api persisted query")
355
394
 
356
395
  def _check_graphql_errors(self, raw: dict) -> None:
357
396
  """Inspect a parsed GraphQL response for errors, raising the right
@@ -0,0 +1,133 @@
1
+ # SNI Stream Proxy — Self-Hostable Captcha Bypass
2
+
3
+ This directory contains the proxy worker code that SNI uses as a fallback when your IP is captcha-walled on `api.allanime.day`. The worker is a simple JavaScript `fetch` handler that proxies requests through a clean IP (the platform's IP, not yours), which AllAnime's Cloudflare edge doesn't flag.
4
+
5
+ ## When you need this
6
+
7
+ You need this **only** if ALL of these are true:
8
+
9
+ 1. `sni play "one piece"` fails with `NEED_CAPTCHA` or `ConnectTimeout`
10
+ 2. `curl -I https://api.allanime.day` times out or returns 403 from your machine
11
+ 3. `curl -I https://proxy.cors.sh` also times out (SNI's built-in public proxy fallback doesn't work for you)
12
+
13
+ If any of those work, you don't need this — SNI's built-in fallbacks already cover you.
14
+
15
+ ## Three deployment options (all free, no credit card required)
16
+
17
+ Pick **one**. All three run the same JavaScript code (slightly different entry-point wrappers).
18
+
19
+ | Platform | Free tier | Signup difficulty | Setup time |
20
+ |---|---|---|---|
21
+ | **Deno Deploy** | 1M req/month | Easy (GitHub login) | ~2 min |
22
+ | **Vercel Edge Functions** | 1M req/month | Easy (GitHub login) | ~3 min |
23
+ | **Cloudflare Workers** | 100K req/day | Hard right now (deploy bugs) | ~5 min |
24
+
25
+ **If you can't create a Cloudflare Worker (the Hello World project won't deploy), use Deno Deploy instead — it's the most reliable as of 2026.**
26
+
27
+ ---
28
+
29
+ ## Option 1: Deno Deploy (recommended — most reliable)
30
+
31
+ 1. Go to https://dash.deno.com → Sign in with GitHub
32
+ 2. Click **"New Project"**
33
+ 3. Click **"Playground"** (top-right, lets you paste code directly — no GitHub repo needed)
34
+ 4. Delete the default code, paste the entire contents of [`proxy.deno.js`](./proxy.deno.js) from this directory
35
+ 5. Click **"Save & Deploy"**
36
+ 6. You'll get a URL like `https://your-project.deno.dev` — copy it
37
+ 7. Test it in your browser: visit `https://your-project.deno.dev/` — you should see `{"ok":true,"service":"sni-stream-proxy",...}`
38
+ 8. Save it to SNI:
39
+
40
+ ```bash
41
+ sni config --update allanime_cf_worker_url='https://your-project.deno.dev'
42
+ ```
43
+
44
+ 9. Try SNI: `sni play "one piece"`
45
+
46
+ ---
47
+
48
+ ## Option 2: Vercel Edge Functions
49
+
50
+ 1. Go to https://vercel.com → Sign in with GitHub
51
+ 2. Click **"Add New"** → **"Project"**
52
+ 3. Click **"Create New Project"** → under "No Framework", click **"Browse all templates"** → pick **"Blank"**
53
+ 4. Name your project, click **"Deploy"** (this creates an empty project)
54
+ 5. Once deployed, click **"Continue to Dashboard"** → **"Code"** tab → **"Files"** tab
55
+ 6. Create a new folder called `api` and a file inside it called `proxy.js`
56
+ 7. Paste the entire contents of [`api/proxy.js`](./api/proxy.js) into that file
57
+ 8. Click **"Commit"** → **"Commit & Deploy"**
58
+ 9. Once redeployed, your URL will be `https://your-project.vercel.app/api/proxy` — copy it
59
+ 10. Test it in your browser: visit `https://your-project.vercel.app/api/proxy` — you should see `{"ok":true,...}`
60
+ 11. Save it to SNI:
61
+
62
+ ```bash
63
+ sni config --update allanime_cf_worker_url='https://your-project.vercel.app/api/proxy'
64
+ ```
65
+
66
+ 12. Try SNI: `sni play "one piece"`
67
+
68
+ ---
69
+
70
+ ## Option 3: Cloudflare Workers
71
+
72
+ Use this only if Deno Deploy and Vercel both fail for you.
73
+
74
+ 1. Go to https://dash.cloudflare.com → sign up / sign in
75
+ 2. Left sidebar → **"Workers & Pages"** → **"Create"** → **"Create Worker"**
76
+ 3. Give it a name (e.g. `sni-proxy`) → click **"Deploy"**
77
+ 4. Click **"Edit code"** (top-right)
78
+ 5. Delete the default code, paste the entire contents of [`proxy.js`](./proxy.js) from this directory
79
+ 6. Click **"Deploy"** (top-right)
80
+ 7. Your URL will be `https://sni-proxy.<your-subdomain>.workers.dev` — copy it
81
+ 8. Test it in your browser: visit the URL — you should see `{"ok":true,...}`
82
+ 9. Save it to SNI:
83
+
84
+ ```bash
85
+ sni config --update allanime_cf_worker_url='https://sni-proxy.your-subdomain.workers.dev'
86
+ ```
87
+
88
+ 10. Try SNI: `sni play "one piece"`
89
+
90
+ **If the "Hello World" project won't deploy:** This is a known Cloudflare dashboard bug. Try:
91
+ - Use a different browser (Chrome instead of Firefox, or vice versa)
92
+ - Disable ad-blockers / privacy extensions
93
+ - Try incognito mode
94
+ - Wait 30 minutes and retry (sometimes it's a transient outage)
95
+ - **Or just use Deno Deploy instead** (Option 1) — it's more reliable right now
96
+
97
+ ---
98
+
99
+ ## How it works
100
+
101
+ SNI's `AllAnimeProvider` tries these in order when fetching anime data:
102
+
103
+ 1. **Direct request** to `api.allanime.day` — fastest, works for most users
104
+ 2. **proxy.cors.sh** (built-in public proxy) — automatic fallback, no setup needed
105
+ 3. **Your self-hosted worker** (this directory) — last resort, only used if you configured `allanime_cf_worker_url`
106
+ 4. **CF Worker** (Cloudflare's own IPs) — same as #3, just deployed on Cloudflare specifically
107
+
108
+ The worker:
109
+ - Accepts GET and POST requests
110
+ - Proxies them to the target URL with proper headers (Referer, Origin, User-Agent)
111
+ - Only allows requests to a hardcoded list of AllAnime-related hosts (security: prevents abuse)
112
+ - Streams the response body back (supports large video files)
113
+
114
+ ## Security
115
+
116
+ The worker has a hardcoded allowlist of hosts it will proxy (`ALLOWED_HOSTS` in the code). It will refuse to proxy requests to any other host. This prevents someone from using your worker as an open proxy for arbitrary traffic.
117
+
118
+ ## Verification
119
+
120
+ After configuring your worker URL, verify SNI can use it:
121
+
122
+ ```bash
123
+ # Should print the version
124
+ sni --version
125
+
126
+ # Should search successfully (using your worker if direct fails)
127
+ sni search "one piece"
128
+
129
+ # Should play successfully
130
+ sni play "one piece"
131
+ ```
132
+
133
+ If you still get `NEED_CAPTCHA` or `ConnectTimeout`, run `sni config --cookie-info` for more options or open an issue at https://github.com/sundeepyt2/SNI/issues
@@ -1 +0,0 @@
1
- __version__ = "1.2.1"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes