1 from .common
import InfoExtractor
2 from ..compat
import compat_b64decode
15 class DaftsexIE(InfoExtractor
):
16 _VALID_URL
= r
'https?://(?:www\.)?daft\.sex/watch/(?P<id>-?\d+_\d+)'
18 'url': 'https://daft.sex/watch/-35370899_456246186',
19 'md5': '64c04ef7b4c7b04b308f3b0c78efe7cd',
21 'id': '-35370899_456246186',
23 'title': 'just relaxing',
24 'description': 'just relaxing – Watch video Watch video in high quality',
25 'upload_date': '20201113',
26 'timestamp': 1605261911,
27 'thumbnail': r
're:^https?://.*\.jpg$',
33 'url': 'https://daft.sex/watch/-156601359_456242791',
35 'id': '-156601359_456242791',
37 'title': 'Skye Blue - Dinner And A Show',
38 'description': 'Skye Blue - Dinner And A Show - Watch video Watch video in high quality',
39 'upload_date': '20200916',
40 'timestamp': 1600250735,
41 'thumbnail': 'https://psv153-1.crazycloud.ru/videos/-156601359/456242791/thumb.jpg?extra=i3D32KaBbBFf9TqDRMAVmQ',
43 'skip': 'deleted / private'
46 def _real_extract(self
, url
):
47 video_id
= self
._match
_id
(url
)
48 webpage
= self
._download
_webpage
(url
, video_id
)
49 title
= self
._html
_search
_meta
('name', webpage
, 'title')
50 timestamp
= unified_timestamp(self
._html
_search
_meta
('uploadDate', webpage
, 'Upload Date', default
=None))
51 description
= self
._html
_search
_meta
('description', webpage
, 'Description', default
=None)
53 duration
= parse_duration(self
._search
_regex
(
54 r
'Duration: ((?:[0-9]{2}:){0,2}[0-9]{2})',
55 webpage
, 'duration', fatal
=False))
56 views
= parse_count(self
._search
_regex
(
58 webpage
, 'views', fatal
=False))
60 player_hash
= self
._search
_regex
(
61 r
'DaxabPlayer\.Init\({[\s\S]*hash:\s*"([0-9a-zA-Z_\-]+)"[\s\S]*}',
62 webpage
, 'player hash')
63 player_color
= self
._search
_regex
(
64 r
'DaxabPlayer\.Init\({[\s\S]*color:\s*"([0-9a-z]+)"[\s\S]*}',
65 webpage
, 'player color', fatal
=False) or ''
67 embed_page
= self
._download
_webpage
(
68 'https://dxb.to/player/%s?color=%s' % (player_hash
, player_color
),
69 video_id
, headers
={'Referer': url
})
70 video_params
= self
._parse
_json
(
72 r
'window\.globParams\s*=\s*({[\S\s]+})\s*;\s*<\/script>',
73 embed_page
, 'video parameters'),
74 video_id
, transform_source
=js_to_json
)
76 server_domain
= 'https://%s' % compat_b64decode(video_params
['server'][::-1]).decode('utf-8')
78 cdn_files
= traverse_obj(video_params
, ('video', 'cdn_files')) or {}
81 for format_id
, format_data
in cdn_files
.items():
82 ext
, height
= format_id
.split('_')
84 'format_id': format_id
,
85 'url': f
'{server_domain}/videos/{video_id.replace("_", "/")}/{height}.mp4?extra={format_data.split(".")[-1]}',
86 'height': int_or_none(height
),
94 'description': description
,
96 'thumbnail': try_get(video_params
, lambda vi
: 'https:' + compat_b64decode(vi
['video']['thumb']).decode('utf-8')),
97 'timestamp': timestamp
,
102 items
= self
._download
_json
(
103 f
'{server_domain}/method/video.get/{video_id}', video_id
,
104 headers
={'Referer': url
}, query
={
105 'token': video_params
['video']['access_token'],
107 'ckey': video_params
['c_key'],
108 'credentials': video_params
['video']['credentials'],
109 })['response']['items']
112 raise ExtractorError('Video is not available', video_id
=video_id
, expected
=True)
116 for f_id
, f_url
in item
.get('files', {}).items():
117 if f_id
== 'external':
118 return self
.url_result(f_url
)
119 ext
, height
= f_id
.split('_')
120 height_extra_key
= traverse_obj(video_params
, ('video', 'partial', 'quality', height
))
123 'format_id': f
'{height}p',
124 'url': f
'{server_domain}/{f_url[8:]}&videos={video_id}&extra_key={height_extra_key}',
125 'height': int_or_none(height
),
130 for k
, v
in item
.items():
131 if k
.startswith('photo_') and v
:
132 width
= k
.replace('photo_', '')
136 'width': int_or_none(width
),
143 'comment_count': int_or_none(item
.get('comments')),
144 'description': description
,
145 'duration': duration
,
146 'thumbnails': thumbnails
,
147 'timestamp': timestamp
,