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