3 from .common
import InfoExtractor
4 from ..networking
import PUTRequest
5 from ..networking
.exceptions
import HTTPError
6 from ..utils
import ExtractorError
, clean_html
, int_or_none
9 class PlayPlusTVIE(InfoExtractor
):
10 _VALID_URL
= r
'https?://(?:www\.)?playplus\.(?:com|tv)/VOD/(?P<project_id>[0-9]+)/(?P<id>[0-9a-f]{32})'
12 'url': 'https://www.playplus.tv/VOD/7572/db8d274a5163424e967f35a30ddafb8e',
13 'md5': 'd078cb89d7ab6b9df37ce23c647aef72',
15 'id': 'db8d274a5163424e967f35a30ddafb8e',
17 'title': 'CapĂtulo 179 - Final',
18 'description': 'md5:01085d62d8033a1e34121d3c3cabc838',
19 'timestamp': 1529992740,
20 'upload_date': '20180626',
22 'skip': 'Requires account credential',
24 _NETRC_MACHINE
= 'playplustv'
25 _GEO_COUNTRIES
= ['BR']
29 def _call_api(self
, resource
, video_id
=None, query
=None):
30 return self
._download
_json
('https://api.playplus.tv/api/media/v2/get' + resource
, video_id
, headers
={
31 'Authorization': 'Bearer ' + self
._token
,
34 def _perform_login(self
, username
, password
):
36 'https://api.playplus.tv/api/web/login', json
.dumps({
40 'Content-Type': 'application/json; charset=utf-8',
44 self
._token
= self
._download
_json
(req
, None)['token']
45 except ExtractorError
as e
:
46 if isinstance(e
.cause
, HTTPError
) and e
.cause
.status
== 401:
47 raise ExtractorError(self
._parse
_json
(
48 e
.cause
.response
.read(), None)['errorMessage'], expected
=True)
51 self
._profile
= self
._call
_api
('Profiles')['list'][0]['_id']
53 def _real_initialize(self
):
55 self
.raise_login_required(method
='password')
57 def _real_extract(self
, url
):
58 project_id
, media_id
= self
._match
_valid
_url
(url
).groups()
59 media
= self
._call
_api
(
61 'profileId': self
._profile
,
62 'projectId': project_id
,
65 title
= media
['title']
68 for f
in media
.get('files', []):
72 file_info
= f
.get('fileInfo') or {}
75 'width': int_or_none(file_info
.get('width')),
76 'height': int_or_none(file_info
.get('height')),
80 for thumb
in media
.get('thumbs', []):
81 thumb_url
= thumb
.get('url')
86 'width': int_or_none(thumb
.get('width')),
87 'height': int_or_none(thumb
.get('height')),
94 'thumbnails': thumbnails
,
95 'description': clean_html(media
.get('description')) or media
.get('shortDescription'),
96 'timestamp': int_or_none(media
.get('publishDate'), 1000),
97 'view_count': int_or_none(media
.get('numberOfViews')),
98 'comment_count': int_or_none(media
.get('numberOfComments')),
99 'tags': media
.get('tags'),