Skip to content

Commit

Permalink
Updates and only support GVS context by default
Browse files Browse the repository at this point in the history
  • Loading branch information
coletdjnz committed Jan 24, 2025
1 parent a5dd5dc commit 65fe2ab
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 19 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Changed

- Support new PO Token context requested by yt-dlp.
- Support new PO Token context requested by yt-dlp. By default, providers only support "gvs" PO Token context for backwards compatibility.

## [0.2.0]

Expand Down
8 changes: 4 additions & 4 deletions examples/getpot_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class ExampleGetPOTProviderRH(GetPOTProvider): # ⚠ The class name must end in
# Supported Innertube clients, as defined in yt_dlp.extractor.youtube.INNERTUBE_CLIENTS
_SUPPORTED_CLIENTS = ('web', 'web_embedded', 'web_music')

# Support PO Token contexts. "gvs" (Google Video Server) or "player". Default is "gvs".
# _SUPPORTED_CONTEXTS = ('gvs', 'player')

# Optional: Define the version of the provider. Shown in debug output for debugging purposes.
VERSION = '0.0.1'

Expand All @@ -27,15 +30,12 @@ class ExampleGetPOTProviderRH(GetPOTProvider): # ⚠ The class name must end in
# You can get the proxies for the request with `self._get_proxies(request)`

# Optional
def _validate_get_pot(self, client: str, ydl: YoutubeDL, data_sync_id=None, context=None, **kwargs):
def _validate_get_pot(self, client: str, ydl: YoutubeDL, data_sync_id=None, **kwargs):
# ℹ️ If you need to validate the request before making the request to the external source, do it here.
# Raise yt_dlp.networking.exceptions.UnsupportedRequest if the request is not valid.
if data_sync_id:
raise UnsupportedRequest('Fetching PO Token for accounts is not supported')

if context != 'gvs':
raise UnsupportedRequest('Only GVS PO Tokens are supported')

# ℹ️ Implement this method
def _get_pot(self, client: str, ydl: YoutubeDL, visitor_data=None, data_sync_id=None, player_url=None, context=None, video_id=None, **kwargs) -> str:
# You should use the ydl instance to make requests where possible,
Expand Down
9 changes: 8 additions & 1 deletion tests/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,16 @@ def test_validate_supported_clients(self):
with YoutubeDL() as ydl, ExampleProviderRH(logger=FakeLogger()) as provider:
provider.validate(Request('get-pot:', extensions={'getpot': {'client': 'web'}, 'ydl': ydl}))

with pytest.raises(UnsupportedRequest, match=r'^Client android is not supported$'):
with pytest.raises(UnsupportedRequest, match=r'^Client "android" is not supported. Supported clients: web$'):
provider.validate(Request('get-pot:', extensions={'getpot': {'client': 'android'}, 'ydl': ydl}))

def test_validate_supported_contexts(self):
with YoutubeDL() as ydl, ExampleProviderRH(logger=FakeLogger()) as provider:
provider.validate(Request('get-pot:', extensions={'getpot': {'client': 'web', 'context': 'gvs'}, 'ydl': ydl}))

with pytest.raises(UnsupportedRequest, match=r'^PO Token context "player" is not supported. Supported contexts: gvs$'):
provider.validate(Request('get-pot:', extensions={'getpot': {'client': 'web', 'context': 'player'}, 'ydl': ydl}))

@pytest.mark.parametrize('extensions', [
{'getpot': 'invalid'},
{'getpot': {'visitor_data': 'xyz'}},
Expand Down
17 changes: 16 additions & 1 deletion yt_dlp_plugins/extractor/getpot.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class GetPOTProvider(RequestHandler, abc.ABC):
# Supported Innertube clients, as defined in yt_dlp.extractor.youtube.INNERTUBE_CLIENTS
_SUPPORTED_CLIENTS = ()

# Support PO Token contexts. "gvs" (Google Video Server) is the default for backwards compatibility.
_SUPPORTED_CONTEXTS = ['gvs']

# Version of the provider. Shown in debug output for debugging purposes.
VERSION = None

Expand Down Expand Up @@ -93,7 +96,11 @@ def _validate(self, request: Request):
client = pot_request.pop('client')

if client not in self._SUPPORTED_CLIENTS:
raise UnsupportedRequest(f'Client {client} is not supported')
raise UnsupportedRequest(f'Client "{client}" is not supported. Supported clients: {", ".join(self._SUPPORTED_CLIENTS)}')

context = pot_request.get('context')
if context and self._SUPPORTED_CONTEXTS and context not in self._SUPPORTED_CONTEXTS:
raise UnsupportedRequest(f'PO Token context "{context}" is not supported. Supported contexts: {", ".join(self._SUPPORTED_CONTEXTS)}')

self._validate_get_pot(
client=client,
Expand All @@ -119,9 +126,11 @@ def _validate_get_pot(
ydl: YoutubeDL,
visitor_data=None,
data_sync_id=None,
session_index=None,
player_url=None,
context=None,
video_id=None,
ytcfg=None,
**kwargs
):
"""
Expand All @@ -130,9 +139,11 @@ def _validate_get_pot(
:param ydl: YoutubeDL instance.
:param visitor_data: Visitor Data.
:param data_sync_id: Data Sync ID. Only provided if yt-dlp is running with an account.
:param session_index: Session Index.
:param player_url: Player URL. Only provided if the client is BotGuard based (requires JS player).
:param context: PO Token context. "gvs" or "player".
:param video_id: Video ID.
:param ytcfg: The ytcfg yt-dlp will use for the client to make Innertube requests.
:param kwargs: Additional arguments that may be passed in the future.
:raises UnsupportedRequest: If the request is unsupported.
"""
Expand All @@ -144,9 +155,11 @@ def _get_pot(
ydl: YoutubeDL,
visitor_data=None,
data_sync_id=None,
session_index=None,
player_url=None,
context=None,
video_id=None,
ytcfg=None,
**kwargs
) -> str:
"""
Expand All @@ -155,9 +168,11 @@ def _get_pot(
:param ydl: YoutubeDL instance.
:param visitor_data: Visitor Data.
:param data_sync_id: Data Sync ID. Only provided if yt-dlp is running with an account.
:param session_index: Session Index.
:param player_url: Player URL. Only provided if the client is BotGuard based (requires JS player).
:param context: PO Token context. "gvs" or "player".
:param video_id: Video ID.
:param ytcfg: The ytcfg yt-dlp will use for the client to make Innertube requests.
:param kwargs: Additional arguments that may be passed in the future.
:returns: PO Token
:raises RequestError: If the request fails.
Expand Down
12 changes: 0 additions & 12 deletions yt_dlp_plugins/extractor/getpot_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,13 @@ def set_downloader(self, downloader: YoutubeDL):
def _fetch_po_token(
self,
client,
visitor_data=None,
data_sync_id=None,
player_url=None,
context=None,
video_id=None,
**kwargs
):
# use any existing implementation
pot = super()._fetch_po_token(
client=client,
visitor_data=visitor_data,
data_sync_id=data_sync_id,
player_url=player_url,
context=context,
video_id=video_id,
**kwargs
)

Expand All @@ -61,11 +53,7 @@ def _fetch_po_token(

params = {
'client': client,
'visitor_data': visitor_data,
'data_sync_id': data_sync_id,
'player_url': player_url,
'context': context,
'video_id': video_id,
**kwargs
}

Expand Down

0 comments on commit 65fe2ab

Please sign in to comment.