From 45f076eac8c5ff1a0b5c5c3eaeb990abe752f948 Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 16 Sep 2026 21:08:00 +0000 Subject: [PATCH] Deployed aec45e3 with MkDocs version: 1.6.1 --- dev/creating-a-service/index.html | 12 + dev/rest-api/dashboard/index.html | 2 +- dev/rest-api/endpoints/index.html | 53 +- dev/rest-api/errors/index.html | 2 +- dev/rest-api/quickstart/index.html | 23 +- dev/service-architecture/index.html | 10 +- objects.inv | Bin 3718 -> 3730 bytes reference/api/service/index.html | 1774 ++++++++++++++------------- search/search_index.json | 2 +- sitemap.xml | 76 +- sitemap.xml.gz | Bin 509 -> 509 bytes 11 files changed, 1043 insertions(+), 911 deletions(-) diff --git a/dev/creating-a-service/index.html b/dev/creating-a-service/index.html index 765eebf5..7d0e4a4f 100644 --- a/dev/creating-a-service/index.html +++ b/dev/creating-a-service/index.html @@ -2450,6 +2450,11 @@ Click cli entry point plus three abstract methods.

IP region codes the service requires. Empty = no geofence. unshackle treats the first entry as the main region for auto-proxy. +GEOBLOCK +tuple[str, ...] +IP region codes where the service refuses to work. Every other region is allowed. Default (). + + VAULT_TAG Optional[str] Overrides the key-vault namespace so sibling services can share one vault. Default None (use the service's own tag). @@ -2486,10 +2491,17 @@ subtitle work for services that never carry subtitles. Leave it off otherwise.GEOFENCE drives an automatic proxy: on startup, if you did not pass an explicit --proxy, the base class does a live IP check and, if your region is blocked, fetches a proxy to GEOFENCE[0] from your configured proxy providers.

+

GEOBLOCK is the negative form: the service works everywhere except the listed +regions. With no GEOFENCE to name a main region, a GEOBLOCK hit stops the run +with a "not available in your region" error; pass --proxy yourself.

class EXAMPLE(Service):
     ALIASES = ("EX", "DOMAIN")
     GEOFENCE = ("US", "UK")
     VAULT_TAG = "DIFFERENT_NAME"
+
+
+class WORLDWIDE(Service):
+    GEOBLOCK = ("GB",)
 

What Service.__init__ wires up

When you call super().__init__(ctx), the base class sets up the attributes you diff --git a/dev/rest-api/dashboard/index.html b/dev/rest-api/dashboard/index.html index c5cade86..2aac4b9d 100644 --- a/dev/rest-api/dashboard/index.html +++ b/dev/rest-api/dashboard/index.html @@ -2428,7 +2428,7 @@ limit never applies to the dashboard key, and never to /api/health. [{"tag": "EXAMPLE", "state": "staged", "error": null, "commit": "9cc230c98f13b83f6c6fe831595b9702d3ba2786", "staged_commit": "5f0aa17...", "staged_since": 1756908900.0, "sessions": 1, "jobs": 1, - "aliases": ["EXMPL"], "geofence": ["US"]}] + "aliases": ["EXMPL"], "geofence": ["US"], "geoblock": []}]

state is loaded, staged or failed. A service that failed to import keeps its error here instead of disappearing, and /status still counts it in the service total - count the diff --git a/dev/rest-api/endpoints/index.html b/dev/rest-api/endpoints/index.html index fb48849b..6a5581a8 100644 --- a/dev/rest-api/endpoints/index.html +++ b/dev/rest-api/endpoints/index.html @@ -3029,30 +3029,31 @@ "tag": "EXAMPLE", "aliases": ["EX"], "geofence": ["US"], - "title_regex": "^https?://example\\.com/.+", - "url": "https://example.com", - "help": "EXAMPLE\nAuthorization: Cookies\nSecurity: FHD@L3", - "cli_params": [ - {"name": "title", "kind": "argument", "required": true}, - { - "name": "movie", - "kind": "option", - "opts": ["-m", "--movie"], - "is_flag": true, - "default": false, - "help": "Title is a movie.", - "type": "boolean", - "multiple": false - } - ], - "needs_auth": true, - "has_search": true, - "has_drm": true, - "auth_methods": ["cookies"] - } - ], - "load_errors": [] -} + "geoblock": [], + "title_regex": "^https?://example\\.com/.+", + "url": "https://example.com", + "help": "EXAMPLE\nAuthorization: Cookies\nSecurity: FHD@L3", + "cli_params": [ + {"name": "title", "kind": "argument", "required": true}, + { + "name": "movie", + "kind": "option", + "opts": ["-m", "--movie"], + "is_flag": true, + "default": false, + "help": "Title is a movie.", + "type": "boolean", + "multiple": false + } + ], + "needs_auth": true, + "has_search": true, + "has_drm": true, + "auth_methods": ["cookies"] + } + ], + "load_errors": [] +} @@ -3079,6 +3080,10 @@ Region codes the service is geofenced to (may be empty). +geoblock +Region codes where the service refuses to work (may be empty). + + title_regex URL/ID pattern the service matches, as a string or list of strings (or null). diff --git a/dev/rest-api/errors/index.html b/dev/rest-api/errors/index.html index f0d59fd0..d0bfb68d 100644 --- a/dev/rest-api/errors/index.html +++ b/dev/rest-api/errors/index.html @@ -2553,7 +2553,7 @@ The classification is keyword-based, checked in order:

yes -geofence, region, not available in, territory +geofence, geoblock, region, not available in, territory GEOFENCE (403) no diff --git a/dev/rest-api/quickstart/index.html b/dev/rest-api/quickstart/index.html index 341b9b62..88247e82 100644 --- a/dev/rest-api/quickstart/index.html +++ b/dev/rest-api/quickstart/index.html @@ -2408,17 +2408,18 @@ "tag": "EXAMPLE", "aliases": ["EX"], "geofence": [], - "title_regex": null, - "url": "https://example.com", - "help": "EXAMPLE service documentation...", - "needs_auth": true, - "has_search": true, - "has_drm": true, - "auth_methods": ["cookies", "credentials"], - "cli_params": [] - } - ] -} + "geoblock": [], + "title_regex": null, + "url": "https://example.com", + "help": "EXAMPLE service documentation...", + "needs_auth": true, + "has_search": true, + "has_drm": true, + "auth_methods": ["cookies", "credentials"], + "cli_params": [] + } + ] +}

If the API key is missing or wrong, you get a 401 with a plain body:

401 Unauthorized
{ "status": 401, "message": "Secret Key is Invalid." }
diff --git a/dev/service-architecture/index.html b/dev/service-architecture/index.html
index 808d2b6a..2026fda5 100644
--- a/dev/service-architecture/index.html
+++ b/dev/service-architecture/index.html
@@ -2689,6 +2689,11 @@ Two kinds of members matter: class variables that give the deta
 ISO region codes the service requires; empty means no geofence. unshackle treats the first entry as the "main region" for automatic proxy selection.
 
 
+GEOBLOCK
+tuple[str, ...]
+ISO region codes where the service refuses to work; every other region is allowed. Use it for a service that works worldwide except in its home market.
+
+
 VAULT_TAG
 Optional[str]
 Overrides the key-vault namespace; defaults to the service's own tag.
@@ -2787,7 +2792,10 @@ up the objects your methods rely on:

The constructor also resolves proxies: it reads --proxy and the proxy_query and proxy_provider context params that dl derives from it, consults the per-service proxy_map, and, if GEOFENCE is set and you did not give an explicit proxy, does a live -IP check and auto-fetches a proxy to GEOFENCE[0] when it detects a geoblock. +IP check and auto-fetches a proxy to GEOFENCE[0] when it detects a geoblock. A +GEOBLOCK hit with no GEOFENCE stops the run with a "not available in your region" +error, because there is no main region to fetch a proxy for; pass --proxy yourself. +A proxy whose exit is in a GEOBLOCK region stops the run the same way. See Proxies and VPN.

TrackRequest

diff --git a/objects.inv b/objects.inv index 95830a665f559abd7cd0690bbf1a205a934027ea..6f47e8ae7979867b4f4421d0729490fad278a328 100644 GIT binary patch delta 3610 zcmV+#4(0KN9g-c8n|~5)iQP?%T2e@c8uui zPii+Aa-y_6J(?MlPDZ42N}Zb$qMWk9N+b3Z#S% zqg?9~itr`jFJA?Zkpb6m`Ht^(ruOI_xq?E+@q$G5*0hj`UYTQhA*#nkiAxso)z}`$ zl)8`=fq$K6t8Gi$G7=d!;9H8jHY9NG8mQA^+x*B64{%MN@K|$6z zOLsO8~Gm_X1Q*aY#GbywR1tQf)m_H6a~5N9(c(3GLr?`>kl@Kl{F4WM=H zv+Ytj!eWNE!13XRLT?nqME9!VW|eHbG;O*VOr1eR_h^P(U6H}N%55>$r#qD zI9mjH0*vfo&$Ud2F*WDGt+-aV5KiVeu#xpOF@HB^roScka$10|B^YduB*S#zz<)+; zi+KJX#w4&jRTAeWg6-Ir3;k`3NnrVq%yCIE%0Bhw`Q=(9RB5;pCJ>bHnIPV>VO7>O zpue54!s;r~-%wC3bq(lm$GjFB;%7nx8VU)977#y8l7MU#it$7cje)>GZ;rKQZ#y%V zkAvmvG)}$c0F_BX2s;hv0+VJ=E`NsW=pZ5R9Z`iOP9V?=D!HCs4O9vVJruemrs{7+>+j;~fbbQlY zZKeOanrSjDyuH}UKC0}gf48wb%aY(8SE3433q$X)@yg~lYM!%kEV6Nhg|9`76gbLmx?u?8h?nTuA?JoyTGyg zQYP{B`v^_?`CJgeyYD$v(~n+>w&2V&FRE}zv!^P;Seba?(44D+C44UuN}w(e2l*UG z{G456&;V)x+w}A2Qp+gB+qWz|hF-tTtus4RdFJfsST#aBil^*-Yyv*Io<| zpnnLQSgWIY>YfKUe!A_&Zh_ew!t=(Oi`@d#H;5mwoJe?jG?WHj7}TO6Z7= z)0tiz$YDkRu#9CE)cQ4G$BT2OL+-1g?70@~@u^;pvK%BpR39u@rAz~5J z`M4t89;%>N1gka>w@#G-v?uH82~LxAW&7aj>oR5VeJqJ?2kpuOKZdv9mE=~eUcXHY z+C-{crYqm6SZ~U1D?rG*xI=`67(JwZ&otJ8FI+@ z>lv>i_kS78bdLj3`)r*1TxD*ajttWMBYw!%Hu`up+d(GPjLyomtwph@6lCmsrBD+C z_sOCr7H*eFO=QV(seyXpnpMHSN_d{j^vIsX{!$dAW2Tn4VykAgNa+F z&Lh!kG*>OEiiD~$hq!L9vPY42&j>kvQ|wmr>RhHC#Jb?&dGJ-C>iPi>`LMAMyHGN( zp{kzyxG@7OB`Ob7KVaH>V zKGZw$T#YhK!)lX%B38nW?9`OMs@dRJy*#Bzsf@M}{-xfFU(GU!h=%Vf5U|T<8c@CM zP1cCM85+MtE_J2~#`}#FL_FQa50oBBZhv}qWCIDUY ziK4Esm?@Gwt5dJVz#*pGduH>Mq? zG>HDTvGYXfW)bv6_2zN(Sp8nX?|5i`xalb7hin*ocETcpX8p(a~K(SJ-tbeA`wKs3O z#9hjMKo9bfeMcqx4k|l30fCdtjzFoE za}p?Z0~2P(cDMrNVhpp%_sgV)!x(;=!}VaLS5eAXx-y;Jz%|8yf{Slk%`oWQyt=UT zU_bkTZ1yP-Ze;bm2-1&{3xBtDuNsWm$$cs@W-qs^$C&j=sxmer+zRyQ3euMg?`IOQ zNjt!!g$}p)I?7xQUw0{XE&agH(;$1(E#Pa^d?qKz+7;<-#(t6~%+ZwVVQcgHY4=JtmXU^ zkUR9d8hx^oL z<}PkmnVBo!e&hJq!GG&0As8LqrFbxQvVEpGR=a0nH}-MMly0mWzT0-nacb&~{+c6` z#^SgsMyi3pk7-o}i{&R delta 3598 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 U)gAc8+;PYG=?91Z12U_}u_Y!XkN^Mx diff --git a/reference/api/service/index.html b/reference/api/service/index.html index 3ed1916d..07eedf13 100644 --- a/reference/api/service/index.html +++ b/reference/api/service/index.html @@ -1864,6 +1864,17 @@