3 from .common
import InfoExtractor
4 from ..utils
import ExtractorError
, traverse_obj
7 class CamsodaIE(InfoExtractor
):
8 _VALID_URL
= r
'https?://www\.camsoda\.com/(?P<id>[\w-]+)'
10 'url': 'https://www.camsoda.com/lizzhopf',
14 'title': 'lizzhopf (lizzhopf) Nude on Cam. Free Live Sex Chat Room - CamSoda',
19 'skip': 'Room is offline',
22 def _real_extract(self
, url
):
23 video_id
= self
._match
_id
(url
)
24 webpage
= self
._download
_webpage
(url
, video_id
, headers
=self
.geo_verification_headers())
26 data
= self
._download
_json
(
27 f
'https://camsoda.com/api/v1/video/vtoken/{video_id}', video_id
,
28 query
={'username': f'guest_{random.randrange(10000, 99999)}
'},
29 headers=self.geo_verification_headers())
31 raise ExtractorError('Unable to find configuration
for stream
.')
32 elif data.get('private_servers
'):
33 raise ExtractorError('Model
is in private show
.', expected=True)
34 elif not data.get('stream_name
'):
35 raise ExtractorError('Model
is offline
.', expected=True)
37 stream_name = traverse_obj(data, 'stream_name
', expected_type=str)
38 token = traverse_obj(data, 'token
', expected_type=str)
41 for server in traverse_obj(data, ('edge_servers
', ...)):
42 formats = self._extract_m3u8_formats(
43 f'https
://{server}
/{stream_name}_v1
/index
.m3u8?token
={token}
',
44 video_id, ext='mp4
', m3u8_id='hls
', fatal=False, live=True)
48 self.raise_no_formats('No active streams found
', expected=True)
52 'title
': self._html_extract_title(webpage),
53 'description
': self._html_search_meta('description
', webpage, default=None),