daftsex.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. from .common import InfoExtractor
  2. from ..compat import compat_b64decode
  3. from ..utils import (
  4. int_or_none,
  5. js_to_json,
  6. parse_count,
  7. parse_duration,
  8. traverse_obj,
  9. try_get,
  10. unified_timestamp,
  11. )
  12. class DaftsexIE(InfoExtractor):
  13. _VALID_URL = r'https?://(?:www\.)?daftsex\.com/watch/(?P<id>-?\d+_\d+)'
  14. _TESTS = [{
  15. 'url': 'https://daftsex.com/watch/-35370899_456246186',
  16. 'md5': 'd95135e6cea2d905bea20dbe82cda64a',
  17. 'info_dict': {
  18. 'id': '-35370899_456246186',
  19. 'ext': 'mp4',
  20. 'title': 'just relaxing',
  21. 'description': 'just relaxing - Watch video Watch video in high quality',
  22. 'upload_date': '20201113',
  23. 'timestamp': 1605261911,
  24. 'thumbnail': r're:https://[^/]+/impf/-43BuMDIawmBGr3GLcZ93CYwWf2PBv_tVWoS1A/dnu41DnARU4\.jpg\?size=800x450&quality=96&keep_aspect_ratio=1&background=000000&sign=6af2c26ff4a45e55334189301c867384&type=video_thumb',
  25. },
  26. }, {
  27. 'url': 'https://daftsex.com/watch/-156601359_456242791',
  28. 'info_dict': {
  29. 'id': '-156601359_456242791',
  30. 'ext': 'mp4',
  31. 'title': 'Skye Blue - Dinner And A Show',
  32. 'description': 'Skye Blue - Dinner And A Show - Watch video Watch video in high quality',
  33. 'upload_date': '20200916',
  34. 'timestamp': 1600250735,
  35. 'thumbnail': 'https://psv153-1.crazycloud.ru/videos/-156601359/456242791/thumb.jpg?extra=i3D32KaBbBFf9TqDRMAVmQ',
  36. },
  37. }]
  38. def _real_extract(self, url):
  39. video_id = self._match_id(url)
  40. webpage = self._download_webpage(url, video_id)
  41. title = self._html_search_meta('name', webpage, 'title')
  42. timestamp = unified_timestamp(self._html_search_meta('uploadDate', webpage, 'Upload Date', default=None))
  43. description = self._html_search_meta('description', webpage, 'Description', default=None)
  44. duration = parse_duration(self._search_regex(
  45. r'Duration: ((?:[0-9]{2}:){0,2}[0-9]{2})',
  46. webpage, 'duration', fatal=False))
  47. views = parse_count(self._search_regex(
  48. r'Views: ([0-9 ]+)',
  49. webpage, 'views', fatal=False))
  50. player_hash = self._search_regex(
  51. r'DaxabPlayer\.Init\({[\s\S]*hash:\s*"([0-9a-zA-Z_\-]+)"[\s\S]*}',
  52. webpage, 'player hash')
  53. player_color = self._search_regex(
  54. r'DaxabPlayer\.Init\({[\s\S]*color:\s*"([0-9a-z]+)"[\s\S]*}',
  55. webpage, 'player color', fatal=False) or ''
  56. embed_page = self._download_webpage(
  57. 'https://daxab.com/player/%s?color=%s' % (player_hash, player_color),
  58. video_id, headers={'Referer': url})
  59. video_params = self._parse_json(
  60. self._search_regex(
  61. r'window\.globParams\s*=\s*({[\S\s]+})\s*;\s*<\/script>',
  62. embed_page, 'video parameters'),
  63. video_id, transform_source=js_to_json)
  64. server_domain = 'https://%s' % compat_b64decode(video_params['server'][::-1]).decode('utf-8')
  65. cdn_files = traverse_obj(video_params, ('video', 'cdn_files')) or {}
  66. if cdn_files:
  67. formats = []
  68. for format_id, format_data in cdn_files.items():
  69. ext, height = format_id.split('_')
  70. formats.append({
  71. 'format_id': format_id,
  72. 'url': f'{server_domain}/videos/{video_id.replace("_", "/")}/{height}.mp4?extra={format_data.split(".")[-1]}',
  73. 'height': int_or_none(height),
  74. 'ext': ext,
  75. })
  76. return {
  77. 'id': video_id,
  78. 'title': title,
  79. 'formats': formats,
  80. 'description': description,
  81. 'duration': duration,
  82. 'thumbnail': try_get(video_params, lambda vi: 'https:' + compat_b64decode(vi['video']['thumb']).decode('utf-8')),
  83. 'timestamp': timestamp,
  84. 'view_count': views,
  85. 'age_limit': 18,
  86. }
  87. item = self._download_json(
  88. f'{server_domain}/method/video.get/{video_id}', video_id,
  89. headers={'Referer': url}, query={
  90. 'token': video_params['video']['access_token'],
  91. 'videos': video_id,
  92. 'ckey': video_params['c_key'],
  93. 'credentials': video_params['video']['credentials'],
  94. })['response']['items'][0]
  95. formats = []
  96. for f_id, f_url in item.get('files', {}).items():
  97. if f_id == 'external':
  98. return self.url_result(f_url)
  99. ext, height = f_id.split('_')
  100. height_extra_key = traverse_obj(video_params, ('video', 'partial', 'quality', height))
  101. if height_extra_key:
  102. formats.append({
  103. 'format_id': f'{height}p',
  104. 'url': f'{server_domain}/{f_url[8:]}&videos={video_id}&extra_key={height_extra_key}',
  105. 'height': int_or_none(height),
  106. 'ext': ext,
  107. })
  108. thumbnails = []
  109. for k, v in item.items():
  110. if k.startswith('photo_') and v:
  111. width = k.replace('photo_', '')
  112. thumbnails.append({
  113. 'id': width,
  114. 'url': v,
  115. 'width': int_or_none(width),
  116. })
  117. return {
  118. 'id': video_id,
  119. 'title': title,
  120. 'formats': formats,
  121. 'comment_count': int_or_none(item.get('comments')),
  122. 'description': description,
  123. 'duration': duration,
  124. 'thumbnails': thumbnails,
  125. 'timestamp': timestamp,
  126. 'view_count': views,
  127. 'age_limit': 18,
  128. }