]> jfr.im git - yt-dlp.git/commitdiff
[extractor/zaiko] ZaikoETicket: Add extractor (#7347)
authorMozi <redacted>
Tue, 20 Jun 2023 04:22:36 +0000 (12:22 +0800)
committerGitHub <redacted>
Tue, 20 Jun 2023 04:22:36 +0000 (04:22 +0000)
Authored by: pzhlkj6612

yt_dlp/extractor/_extractors.py
yt_dlp/extractor/zaiko.py

index 7e1fa4a0d1e960f95a83d322a7397dba3ef15439..ff659a7a29f3df9504f5b61561c1dbad0e9d7dc7 100644 (file)
 from .youporn import YouPornIE
 from .yourporn import YourPornIE
 from .yourupload import YourUploadIE
-from .zaiko import ZaikoIE
+from .zaiko import (
+    ZaikoIE,
+    ZaikoETicketIE,
+)
 from .zapiks import ZapiksIE
 from .zattoo import (
     BBVTVIE,
index 59fc64c5a94beffcfb20b179f6dc8a23fb1ade1d..84cee4445e1984fa19158e5f3c2fd8932802f62a 100644 (file)
@@ -1,3 +1,5 @@
+import base64
+
 from .common import InfoExtractor
 from ..utils import (
     ExtractorError,
@@ -5,12 +7,33 @@
     int_or_none,
     str_or_none,
     traverse_obj,
+    try_call,
     unescapeHTML,
     url_or_none,
 )
 
 
-class ZaikoIE(InfoExtractor):
+class ZaikoBaseIE(InfoExtractor):
+    def _download_real_webpage(self, url, video_id):
+        webpage, urlh = self._download_webpage_handle(url, video_id)
+        final_url = urlh.geturl()
+        if 'zaiko.io/login' in final_url:
+            self.raise_login_required()
+        elif '/_buy/' in final_url:
+            raise ExtractorError('Your account does not have tickets to this event', expected=True)
+        return webpage
+
+    def _parse_vue_element_attr(self, name, string, video_id):
+        page_elem = self._search_regex(rf'(<{name}[^>]+>)', string, name)
+        attrs = {}
+        for key, value in extract_attributes(page_elem).items():
+            if key.startswith(':'):
+                attrs[key[1:]] = self._parse_json(
+                    value, video_id, transform_source=unescapeHTML, fatal=False)
+        return attrs
+
+
+class ZaikoIE(ZaikoBaseIE):
     _VALID_URL = r'https?://(?:[\w-]+\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
     _TESTS = [{
         'url': 'https://zaiko.io/event/324868/stream/20571/20571',
@@ -30,24 +53,10 @@ class ZaikoIE(InfoExtractor):
         'params': {'skip_download': 'm3u8'},
     }]
 
-    def _parse_vue_element_attr(self, name, string, video_id):
-        page_elem = self._search_regex(rf'(<{name}[^>]+>)', string, name)
-        attrs = {}
-        for key, value in extract_attributes(page_elem).items():
-            if key.startswith(':'):
-                attrs[key[1:]] = self._parse_json(
-                    value, video_id, transform_source=unescapeHTML, fatal=False)
-        return attrs
-
     def _real_extract(self, url):
         video_id = self._match_id(url)
 
-        webpage, urlh = self._download_webpage_handle(url, video_id)
-        final_url = urlh.geturl()
-        if 'zaiko.io/login' in final_url:
-            self.raise_login_required()
-        elif '/_buy/' in final_url:
-            raise ExtractorError('Your account does not have tickets to this event', expected=True)
+        webpage = self._download_real_webpage(url, video_id)
         stream_meta = self._parse_vue_element_attr('stream-page', webpage, video_id)
 
         player_page = self._download_webpage(
@@ -90,3 +99,32 @@ def _real_extract(self, url):
                 'thumbnail': ('poster_url', {url_or_none}),
             })),
         }
+
+
+class ZaikoETicketIE(ZaikoBaseIE):
+    _VALID_URL = r'https?://(?:www.)?zaiko\.io/account/eticket/(?P<id>[\w=-]{49})'
+    _TESTS = [{
+        'url': 'https://zaiko.io/account/eticket/TZjMwMzQ2Y2EzMXwyMDIzMDYwNzEyMTMyNXw1MDViOWU2Mw==',
+        'playlist_count': 1,
+        'info_dict': {
+            'id': 'f30346ca31-20230607121325-505b9e63',
+            'title': 'ZAIKO STREAMING TEST',
+            'thumbnail': 'https://media.zkocdn.net/pf_1/1_3wdyjcjyupseatkwid34u',
+        },
+        'skip': 'Only available with the ticketholding account',
+    }]
+
+    def _real_extract(self, url):
+        ticket_id = self._match_id(url)
+        ticket_id = try_call(
+            lambda: base64.urlsafe_b64decode(ticket_id[1:]).decode().replace('|', '-')) or ticket_id
+
+        webpage = self._download_real_webpage(url, ticket_id)
+        eticket = self._parse_vue_element_attr('eticket', webpage, ticket_id)
+
+        return self.playlist_result(
+            [self.url_result(stream, ZaikoIE) for stream in traverse_obj(eticket, ('streams', ..., 'url'))],
+            ticket_id, **traverse_obj(eticket, ('ticket-details', {
+                'title': 'event_name',
+                'thumbnail': 'event_img_url',
+            })))