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.
- {sni_cli-1.2.1 → sni_cli-1.2.3}/PKG-INFO +18 -14
- {sni_cli-1.2.1 → sni_cli-1.2.3}/README.md +17 -13
- {sni_cli-1.2.1 → sni_cli-1.2.3}/pyproject.toml +1 -1
- sni_cli-1.2.3/sni/__init__.py +1 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/cli.py +20 -10
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/allanime.py +54 -15
- sni_cli-1.2.3/worker/README.md +133 -0
- sni_cli-1.2.1/sni/__init__.py +0 -1
- {sni_cli-1.2.1 → sni_cli-1.2.3}/.gitignore +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/LICENSE +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/install.ps1 +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/install.sh +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/__main__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/config.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/exceptions.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/logger.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/player.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/__init__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/base.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/cache.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/extractors/__init__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/extractors/megacloud.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/extractors/vixcloud.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/providers/registry.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/__init__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/app.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/bridge.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/__init__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/help.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/history.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/home.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/screens/player.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/widgets/__init__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/widgets/ascii_art.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/tui/widgets/info_box.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/ui.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/watch_history.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/sni/wizard.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/__init__.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/conftest.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_allanime_captcha.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_cache.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_config.py +0 -0
- {sni_cli-1.2.1 → sni_cli-1.2.3}/tests/test_exceptions.py +0 -0
- {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.
|
|
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 —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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://
|
|
403
|
+
sni config --update allanime_cf_worker_url='https://your-project.deno.dev'
|
|
396
404
|
```
|
|
397
405
|
|
|
398
|
-
|
|
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 —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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://
|
|
350
|
+
sni config --update allanime_cf_worker_url='https://your-project.deno.dev'
|
|
343
351
|
```
|
|
344
352
|
|
|
345
|
-
|
|
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.
|
|
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 -
|
|
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
|
-
"
|
|
524
|
-
"
|
|
525
|
-
"
|
|
526
|
-
"
|
|
527
|
-
"
|
|
528
|
-
"
|
|
529
|
-
"
|
|
530
|
-
"
|
|
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 =
|
|
62
|
-
CLOCK_TIMEOUT =
|
|
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.
|
|
165
|
-
#
|
|
166
|
-
#
|
|
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 (
|
|
209
|
-
|
|
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
|
|
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
|
|
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
|
sni_cli-1.2.1/sni/__init__.py
DELETED
|
@@ -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
|
|
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
|