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 95830a66..6f47e8ae 100644 Binary files a/objects.inv and b/objects.inv differ 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 @@