]>
Commit | Line | Data |
---|---|---|
89f383c4 HTL |
1 | import functools |
2 | ||
920134b2 | 3 | from .common import InfoExtractor |
89f383c4 HTL |
4 | from ..utils import ( |
5 | OnDemandPagedList, | |
9c92b803 | 6 | float_or_none, |
89f383c4 HTL |
7 | traverse_obj, |
8 | unified_strdate, | |
9 | ) | |
920134b2 AG |
10 | |
11 | ||
12 | class GronkhIE(InfoExtractor): | |
0d95d8b0 | 13 | _VALID_URL = r'https?://(?:www\.)?gronkh\.tv/(?:watch/)?streams?/(?P<id>\d+)' |
920134b2 AG |
14 | |
15 | _TESTS = [{ | |
0d95d8b0 MC |
16 | 'url': 'https://gronkh.tv/streams/657', |
17 | 'info_dict': { | |
18 | 'id': '657', | |
19 | 'ext': 'mp4', | |
20 | 'title': 'H.O.R.D.E. - DAS ZWEiTE ZEiTALTER 🎲 Session 1', | |
21 | 'view_count': int, | |
22 | 'thumbnail': 'https://01.cdn.vod.farm/preview/9e2555d3a23bf4e5c5b7c6b3b70a9d84.jpg', | |
9c92b803 | 23 | 'upload_date': '20221111', |
24 | 'chapters': 'count:3', | |
25 | 'duration': 31463, | |
0d95d8b0 MC |
26 | }, |
27 | 'params': {'skip_download': True} | |
28 | }, { | |
920134b2 AG |
29 | 'url': 'https://gronkh.tv/stream/536', |
30 | 'info_dict': { | |
31 | 'id': '536', | |
32 | 'ext': 'mp4', | |
33 | 'title': 'GTV0536, 2021-10-01 - MARTHA IS DEAD #FREiAB1830 !FF7 !horde !archiv', | |
0d95d8b0 | 34 | 'view_count': int, |
920134b2 | 35 | 'thumbnail': 'https://01.cdn.vod.farm/preview/6436746cce14e25f751260a692872b9b.jpg', |
9c92b803 | 36 | 'upload_date': '20211001', |
37 | 'duration': 32058, | |
920134b2 AG |
38 | }, |
39 | 'params': {'skip_download': True} | |
375d9360 S |
40 | }, { |
41 | 'url': 'https://gronkh.tv/watch/stream/546', | |
42 | 'only_matching': True, | |
920134b2 AG |
43 | }] |
44 | ||
45 | def _real_extract(self, url): | |
46 | id = self._match_id(url) | |
47 | data_json = self._download_json(f'https://api.gronkh.tv/v1/video/info?episode={id}', id) | |
48 | m3u8_url = self._download_json(f'https://api.gronkh.tv/v1/video/playlist?episode={id}', id)['playlist_url'] | |
49 | formats, subtitles = self._extract_m3u8_formats_and_subtitles(m3u8_url, id) | |
50 | if data_json.get('vtt_url'): | |
51 | subtitles.setdefault('en', []).append({ | |
52 | 'url': data_json['vtt_url'], | |
53 | 'ext': 'vtt', | |
54 | }) | |
920134b2 AG |
55 | return { |
56 | 'id': id, | |
57 | 'title': data_json.get('title'), | |
58 | 'view_count': data_json.get('views'), | |
59 | 'thumbnail': data_json.get('preview_url'), | |
60 | 'upload_date': unified_strdate(data_json.get('created_at')), | |
61 | 'formats': formats, | |
62 | 'subtitles': subtitles, | |
9c92b803 | 63 | 'duration': float_or_none(data_json.get('source_length')), |
64 | 'chapters': traverse_obj(data_json, ( | |
65 | 'chapters', lambda _, v: float_or_none(v['offset']) is not None, { | |
66 | 'title': 'title', | |
67 | 'start_time': ('offset', {float_or_none}), | |
68 | })) or None, | |
920134b2 | 69 | } |
89f383c4 HTL |
70 | |
71 | ||
72 | class GronkhFeedIE(InfoExtractor): | |
73 | _VALID_URL = r'https?://(?:www\.)?gronkh\.tv(?:/feed)?/?(?:#|$)' | |
74 | IE_NAME = 'gronkh:feed' | |
75 | ||
76 | _TESTS = [{ | |
77 | 'url': 'https://gronkh.tv/feed', | |
78 | 'info_dict': { | |
79 | 'id': 'feed', | |
80 | }, | |
81 | 'playlist_count': 16, | |
82 | }, { | |
83 | 'url': 'https://gronkh.tv', | |
84 | 'only_matching': True, | |
85 | }] | |
86 | ||
87 | def _entries(self): | |
88 | for type_ in ('recent', 'views'): | |
89 | info = self._download_json( | |
90 | f'https://api.gronkh.tv/v1/video/discovery/{type_}', 'feed', note=f'Downloading {type_} API JSON') | |
91 | for item in traverse_obj(info, ('discovery', ...)) or []: | |
92 | yield self.url_result(f'https://gronkh.tv/watch/stream/{item["episode"]}', GronkhIE, item.get('title')) | |
93 | ||
94 | def _real_extract(self, url): | |
95 | return self.playlist_result(self._entries(), 'feed') | |
96 | ||
97 | ||
98 | class GronkhVodsIE(InfoExtractor): | |
99 | _VALID_URL = r'https?://(?:www\.)?gronkh\.tv/vods/streams/?(?:#|$)' | |
100 | IE_NAME = 'gronkh:vods' | |
101 | ||
102 | _TESTS = [{ | |
103 | 'url': 'https://gronkh.tv/vods/streams', | |
104 | 'info_dict': { | |
105 | 'id': 'vods', | |
106 | }, | |
107 | 'playlist_mincount': 150, | |
108 | }] | |
109 | _PER_PAGE = 25 | |
110 | ||
111 | def _fetch_page(self, page): | |
112 | items = traverse_obj(self._download_json( | |
113 | 'https://api.gronkh.tv/v1/search', 'vods', query={'offset': self._PER_PAGE * page, 'first': self._PER_PAGE}, | |
114 | note=f'Downloading stream video page {page + 1}'), ('results', 'videos', ...)) | |
115 | for item in items or []: | |
116 | yield self.url_result(f'https://gronkh.tv/watch/stream/{item["episode"]}', GronkhIE, item['episode'], item.get('title')) | |
117 | ||
118 | def _real_extract(self, url): | |
119 | entries = OnDemandPagedList(functools.partial(self._fetch_page), self._PER_PAGE) | |
120 | return self.playlist_result(entries, 'vods') |