3 from .common
import InfoExtractor
13 class BannedVideoIE(InfoExtractor
):
14 _VALID_URL
= r
'https?://(?:www\.)?banned\.video/watch\?id=(?P<id>[0-f]{24})'
16 'url': 'https://banned.video/watch?id=5e7a859644e02200c6ef5f11',
17 'md5': '14b6e81d41beaaee2215cd75c6ed56e4',
19 'id': '5e7a859644e02200c6ef5f11',
21 'title': 'China Discovers Origin of Corona Virus: Issues Emergency Statement',
22 'thumbnail': r
're:^https?://(?:www\.)?assets\.infowarsmedia.com/images/',
23 'description': 'md5:560d96f02abbebe6c6b78b47465f6b28',
24 'upload_date': '20200324',
25 'timestamp': 1585087895,
29 _GRAPHQL_GETMETADATA_QUERY
= '''
30 query GetVideoAndComments($id: String!) {
50 getVideoComments(id: $id, limit: 999999, offset: 0) {
65 _GRAPHQL_GETCOMMENTSREPLIES_QUERY
= '''
66 query GetCommentReplies($id: String!) {
67 getCommentReplies(id: $id, limit: 999999, offset: 0) {
83 'GetVideoAndComments': _GRAPHQL_GETMETADATA_QUERY
,
84 'GetCommentReplies': _GRAPHQL_GETCOMMENTSREPLIES_QUERY
,
87 def _call_api(self
, video_id
, id_var
, operation
, note
):
88 return self
._download
_json
(
89 'https://api.infowarsmedia.com/graphql', video_id
, note
=note
,
91 'Content-Type': 'application/json; charset=utf-8',
93 'variables': {'id': id_var
},
94 'operationName': operation
,
95 'query': self
._GRAPHQL
_QUERIES
[operation
],
96 }).encode('utf8')).get('data')
98 def _get_comments(self
, video_id
, comments
, comment_data
):
100 for comment
in comment_data
.copy():
101 comment_id
= comment
.get('_id')
102 if comment
.get('replyCount') > 0:
103 reply_json
= self
._call
_api
(
104 video_id
, comment_id
, 'GetCommentReplies',
105 f
'Downloading replies for comment {comment_id}')
106 for reply
in reply_json
.get('getCommentReplies'):
107 yield self
._parse
_comment
(reply
, comment_id
)
110 def _parse_comment(comment_data
, parent
):
112 'id': comment_data
.get('_id'),
113 'text': comment_data
.get('content'),
114 'author': try_get(comment_data
, lambda x
: x
['user']['username']),
115 'author_id': try_get(comment_data
, lambda x
: x
['user']['_id']),
116 'timestamp': unified_timestamp(comment_data
.get('createdAt')),
118 'like_count': try_get(comment_data
, lambda x
: x
['voteCount']['positive']),
121 def _real_extract(self
, url
):
122 video_id
= self
._match
_id
(url
)
123 video_json
= self
._call
_api
(video_id
, video_id
, 'GetVideoAndComments', 'Downloading video metadata')
124 video_info
= video_json
['getVideo']
125 is_live
= video_info
.get('live')
126 comments
= [self
._parse
_comment
(comment
, 'root') for comment
in video_json
.get('getVideoComments')]
129 'format_id': 'direct',
131 'url': video_info
.get('directUrl'),
133 }] if url_or_none(video_info
.get('directUrl')) else []
134 if video_info
.get('streamUrl'):
135 formats
.extend(self
._extract
_m
3u8_formats
(
136 video_info
.get('streamUrl'), video_id
, 'mp4',
137 entry_protocol
='m3u8_native', m3u8_id
='hls', live
=True))
141 'title': video_info
.get('title')[:-1],
144 'description': video_info
.get('summary'),
145 'channel': try_get(video_info
, lambda x
: x
['channel']['title']),
146 'channel_id': try_get(video_info
, lambda x
: x
['channel']['_id']),
147 'view_count': int_or_none(video_info
.get('playCount')),
148 'thumbnail': url_or_none(video_info
.get('largeImage')),
149 'duration': float_or_none(video_info
.get('videoDuration')),
150 'timestamp': unified_timestamp(video_info
.get('createdAt')),
151 'tags': [tag
.get('name') for tag
in video_info
.get('tags')],
152 'availability': self
._availability
(is_unlisted
=video_info
.get('unlisted')),
153 'comments': comments
,
154 '__post_extractor': self
.extract_comments(video_id
, comments
, video_json
.get('getVideoComments')),