logo

youtube-dl

[mirror] Download/Watch videos from video hostersgit clone https://hacktivis.me/git/mirror/youtube-dl.git

puhutv.py (8458B)


  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. from .common import InfoExtractor
  4. from ..compat import (
  5. compat_HTTPError,
  6. compat_str,
  7. )
  8. from ..utils import (
  9. ExtractorError,
  10. int_or_none,
  11. float_or_none,
  12. parse_resolution,
  13. str_or_none,
  14. try_get,
  15. unified_timestamp,
  16. url_or_none,
  17. urljoin,
  18. )
  19. class PuhuTVIE(InfoExtractor):
  20. _VALID_URL = r'https?://(?:www\.)?puhutv\.com/(?P<id>[^/?#&]+)-izle'
  21. IE_NAME = 'puhutv'
  22. _TESTS = [{
  23. # film
  24. 'url': 'https://puhutv.com/sut-kardesler-izle',
  25. 'md5': 'a347470371d56e1585d1b2c8dab01c96',
  26. 'info_dict': {
  27. 'id': '5085',
  28. 'display_id': 'sut-kardesler',
  29. 'ext': 'mp4',
  30. 'title': 'Süt Kardeşler',
  31. 'description': 'md5:ca09da25b7e57cbb5a9280d6e48d17aa',
  32. 'thumbnail': r're:^https?://.*\.jpg$',
  33. 'duration': 4832.44,
  34. 'creator': 'Arzu Film',
  35. 'timestamp': 1561062602,
  36. 'upload_date': '20190620',
  37. 'release_year': 1976,
  38. 'view_count': int,
  39. 'tags': list,
  40. },
  41. }, {
  42. # episode, geo restricted, bypassable with --geo-verification-proxy
  43. 'url': 'https://puhutv.com/jet-sosyete-1-bolum-izle',
  44. 'only_matching': True,
  45. }, {
  46. # 4k, with subtitles
  47. 'url': 'https://puhutv.com/dip-1-bolum-izle',
  48. 'only_matching': True,
  49. }]
  50. _SUBTITLE_LANGS = {
  51. 'English': 'en',
  52. 'Deutsch': 'de',
  53. 'عربى': 'ar'
  54. }
  55. def _real_extract(self, url):
  56. display_id = self._match_id(url)
  57. info = self._download_json(
  58. urljoin(url, '/api/slug/%s-izle' % display_id),
  59. display_id)['data']
  60. video_id = compat_str(info['id'])
  61. show = info.get('title') or {}
  62. title = info.get('name') or show['name']
  63. if info.get('display_name'):
  64. title = '%s %s' % (title, info['display_name'])
  65. try:
  66. videos = self._download_json(
  67. 'https://puhutv.com/api/assets/%s/videos' % video_id,
  68. display_id, 'Downloading video JSON',
  69. headers=self.geo_verification_headers())
  70. except ExtractorError as e:
  71. if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
  72. self.raise_geo_restricted()
  73. raise
  74. urls = []
  75. formats = []
  76. for video in videos['data']['videos']:
  77. media_url = url_or_none(video.get('url'))
  78. if not media_url or media_url in urls:
  79. continue
  80. urls.append(media_url)
  81. playlist = video.get('is_playlist')
  82. if (video.get('stream_type') == 'hls' and playlist is True) or 'playlist.m3u8' in media_url:
  83. formats.extend(self._extract_m3u8_formats(
  84. media_url, video_id, 'mp4', entry_protocol='m3u8_native',
  85. m3u8_id='hls', fatal=False))
  86. continue
  87. quality = int_or_none(video.get('quality'))
  88. f = {
  89. 'url': media_url,
  90. 'ext': 'mp4',
  91. 'height': quality
  92. }
  93. video_format = video.get('video_format')
  94. is_hls = (video_format == 'hls' or '/hls/' in media_url or '/chunklist.m3u8' in media_url) and playlist is False
  95. if is_hls:
  96. format_id = 'hls'
  97. f['protocol'] = 'm3u8_native'
  98. elif video_format == 'mp4':
  99. format_id = 'http'
  100. else:
  101. continue
  102. if quality:
  103. format_id += '-%sp' % quality
  104. f['format_id'] = format_id
  105. formats.append(f)
  106. self._sort_formats(formats)
  107. creator = try_get(
  108. show, lambda x: x['producer']['name'], compat_str)
  109. content = info.get('content') or {}
  110. images = try_get(
  111. content, lambda x: x['images']['wide'], dict) or {}
  112. thumbnails = []
  113. for image_id, image_url in images.items():
  114. if not isinstance(image_url, compat_str):
  115. continue
  116. if not image_url.startswith(('http', '//')):
  117. image_url = 'https://%s' % image_url
  118. t = parse_resolution(image_id)
  119. t.update({
  120. 'id': image_id,
  121. 'url': image_url
  122. })
  123. thumbnails.append(t)
  124. tags = []
  125. for genre in show.get('genres') or []:
  126. if not isinstance(genre, dict):
  127. continue
  128. genre_name = genre.get('name')
  129. if genre_name and isinstance(genre_name, compat_str):
  130. tags.append(genre_name)
  131. subtitles = {}
  132. for subtitle in content.get('subtitles') or []:
  133. if not isinstance(subtitle, dict):
  134. continue
  135. lang = subtitle.get('language')
  136. sub_url = url_or_none(subtitle.get('url') or subtitle.get('file'))
  137. if not lang or not isinstance(lang, compat_str) or not sub_url:
  138. continue
  139. subtitles[self._SUBTITLE_LANGS.get(lang, lang)] = [{
  140. 'url': sub_url
  141. }]
  142. return {
  143. 'id': video_id,
  144. 'display_id': display_id,
  145. 'title': title,
  146. 'description': info.get('description') or show.get('description'),
  147. 'season_id': str_or_none(info.get('season_id')),
  148. 'season_number': int_or_none(info.get('season_number')),
  149. 'episode_number': int_or_none(info.get('episode_number')),
  150. 'release_year': int_or_none(show.get('released_at')),
  151. 'timestamp': unified_timestamp(info.get('created_at')),
  152. 'creator': creator,
  153. 'view_count': int_or_none(content.get('watch_count')),
  154. 'duration': float_or_none(content.get('duration_in_ms'), 1000),
  155. 'tags': tags,
  156. 'subtitles': subtitles,
  157. 'thumbnails': thumbnails,
  158. 'formats': formats
  159. }
  160. class PuhuTVSerieIE(InfoExtractor):
  161. _VALID_URL = r'https?://(?:www\.)?puhutv\.com/(?P<id>[^/?#&]+)-detay'
  162. IE_NAME = 'puhutv:serie'
  163. _TESTS = [{
  164. 'url': 'https://puhutv.com/deniz-yildizi-detay',
  165. 'info_dict': {
  166. 'title': 'Deniz Yıldızı',
  167. 'id': 'deniz-yildizi',
  168. },
  169. 'playlist_mincount': 205,
  170. }, {
  171. # a film detail page which is using same url with serie page
  172. 'url': 'https://puhutv.com/kaybedenler-kulubu-detay',
  173. 'only_matching': True,
  174. }]
  175. def _extract_entries(self, seasons):
  176. for season in seasons:
  177. season_id = season.get('id')
  178. if not season_id:
  179. continue
  180. page = 1
  181. has_more = True
  182. while has_more is True:
  183. season = self._download_json(
  184. 'https://galadriel.puhutv.com/seasons/%s' % season_id,
  185. season_id, 'Downloading page %s' % page, query={
  186. 'page': page,
  187. 'per': 40,
  188. })
  189. episodes = season.get('episodes')
  190. if isinstance(episodes, list):
  191. for ep in episodes:
  192. slug_path = str_or_none(ep.get('slugPath'))
  193. if not slug_path:
  194. continue
  195. video_id = str_or_none(int_or_none(ep.get('id')))
  196. yield self.url_result(
  197. 'https://puhutv.com/%s' % slug_path,
  198. ie=PuhuTVIE.ie_key(), video_id=video_id,
  199. video_title=ep.get('name') or ep.get('eventLabel'))
  200. page += 1
  201. has_more = season.get('hasMore')
  202. def _real_extract(self, url):
  203. playlist_id = self._match_id(url)
  204. info = self._download_json(
  205. urljoin(url, '/api/slug/%s-detay' % playlist_id),
  206. playlist_id)['data']
  207. seasons = info.get('seasons')
  208. if seasons:
  209. return self.playlist_result(
  210. self._extract_entries(seasons), playlist_id, info.get('name'))
  211. # For films, these are using same url with series
  212. video_id = info.get('slug') or info['assets'][0]['slug']
  213. return self.url_result(
  214. 'https://puhutv.com/%s-izle' % video_id,
  215. PuhuTVIE.ie_key(), video_id)