4 from .common
import InfoExtractor
13 from ..utils
.traversal
import traverse_obj
33 'clip': '''query ($id: String!) {
34 video: getClip(clipIdentifier: $id) {
37 }''' % (_FIELDS
, _EXTRA_FIELDS
),
38 'montage': '''query ($id: String!) {
39 video: getMontage(clipIdentifier: $id) {
43 'Clips': '''query ($page: Int!, $user: String!, $game: Int) {
44 videos: clips(search: createdDate, page: $page, user: $user, mobile: false, game: $game) {
47 }''' % (_FIELDS
, _EXTRA_FIELDS
),
48 'Montages': '''query ($page: Int!, $user: String!) {
49 videos: montages(search: createdDate, page: $page, user: $user) {
53 'Mobile Clips': '''query ($page: Int!, $user: String!) {
54 videos: clips(search: createdDate, page: $page, user: $user, mobile: true) {
57 }''' % (_FIELDS
, _EXTRA_FIELDS
),
61 class AllstarBaseIE(InfoExtractor
):
63 def _parse_video_data(video_data
):
64 def media_url_or_none(path
):
65 return urljoin('https://media.allstar.gg/', path
)
67 info
= traverse_obj(video_data
, {
69 'display_id': ('shareId', {str}
),
70 'title': ('clipTitle', {str}
),
71 'url': ('clipLink', {media_url_or_none}
),
72 'thumbnails': (('clipImageThumb', 'clipImageSource'), {'url': {media_url_or_none}
}),
73 'duration': ('clipLength', {int_or_none}
),
74 'filesize': ('clipSizeBytes', {int_or_none}
),
75 'timestamp': ('createdDate', {functools
.partial(int_or_none
, scale
=1000)}),
76 'uploader': ('username', {str}
),
77 'uploader_id': ('user', '_id', {str}
),
78 'view_count': ('views', {int_or_none}
),
81 if info
.get('id') and info
.get('url'):
82 basename
= 'clip' if '/clips/' in info
['url'] else 'montage'
83 info
['webpage_url'] = f
'https://allstar.gg/{basename}?{basename}={info["id"]}'
86 'extractor_key': AllstarIE
.ie_key(),
87 'extractor': AllstarIE
.IE_NAME
,
88 'uploader_url': urljoin('https://allstar.gg/u/', info
.get('uploader_id')),
93 def _call_api(self
, query
, variables
, path
, video_id
=None, note
=None):
94 response
= self
._download
_json
(
95 'https://a1.allstar.gg/graphql', video_id
, note
=note
,
96 headers
={'content-type': 'application/json'},
97 data
=json
.dumps({'variables': variables
, 'query': query
}).encode())
99 errors
= traverse_obj(response
, ('errors', ..., 'message', {str}
))
101 raise ExtractorError('; '.join(errors
))
103 return traverse_obj(response
, path
)
106 class AllstarIE(AllstarBaseIE
):
107 _VALID_URL
= r
'https?://(?:www\.)?allstar\.gg/(?P<type>(?:clip|montage))\?(?P=type)=(?P<id>[^/?#&]+)'
110 'url': 'https://allstar.gg/clip?clip=64482c2da9eec30008a67d1b',
112 'id': '64482c2da9eec30008a67d1b',
113 'title': '4K on Inferno',
114 'url': 'md5:66befb5381eef0c9456026386c25fa55',
115 'thumbnail': r
're:https://media\.allstar\.gg/.+\.(?:png|jpg)$',
119 'filesize': 21199257,
120 'timestamp': 1682451501,
121 'uploader_id': '62b8bdfc9021052f7905882d',
122 'uploader_url': 'https://allstar.gg/u/62b8bdfc9021052f7905882d',
123 'upload_date': '20230425',
127 'url': 'https://allstar.gg/clip?clip=8LJLY4JKB',
129 'id': '64a1ec6b887f4c0008dc50b8',
130 'display_id': '8LJLY4JKB',
131 'title': 'AK-47 3K on Mirage',
132 'url': 'md5:dde224fd12f035c0e2529a4ae34c4283',
134 'thumbnail': r
're:https://media\.allstar\.gg/.+\.(?:png|jpg)$',
136 'filesize': 30175859,
137 'timestamp': 1688333419,
138 'uploader': 'cherokee',
139 'uploader_id': '62b8bdfc9021052f7905882d',
140 'uploader_url': 'https://allstar.gg/u/62b8bdfc9021052f7905882d',
141 'upload_date': '20230702',
145 'url': 'https://allstar.gg/montage?montage=643e64089da7e9363e1fa66c',
147 'id': '643e64089da7e9363e1fa66c',
148 'display_id': 'APQLGM2IMXW',
149 'title': 'cherokee Rapid Fire Snipers Montage',
150 'url': 'md5:a3ee356022115db2b27c81321d195945',
151 'thumbnail': r
're:https://media\.allstar\.gg/.+\.(?:png|jpg)$',
153 'timestamp': 1681810448,
154 'uploader': 'cherokee',
155 'uploader_id': '62b8bdfc9021052f7905882d',
156 'uploader_url': 'https://allstar.gg/u/62b8bdfc9021052f7905882d',
157 'upload_date': '20230418',
161 'url': 'https://allstar.gg/montage?montage=RILJMH6QOS',
163 'id': '64a2697372ce3703de29e868',
164 'display_id': 'RILJMH6QOS',
165 'title': 'cherokee Rapid Fire Snipers Montage',
166 'url': 'md5:d5672e6f88579730c2310a80fdbc4030',
167 'thumbnail': r
're:https://media\.allstar\.gg/.+\.(?:png|jpg)$',
169 'timestamp': 1688365434,
170 'uploader': 'cherokee',
171 'uploader_id': '62b8bdfc9021052f7905882d',
172 'uploader_url': 'https://allstar.gg/u/62b8bdfc9021052f7905882d',
173 'upload_date': '20230703',
178 def _real_extract(self
, url
):
179 query_id
, video_id
= self
._match
_valid
_url
(url
).group('type', 'id')
181 return self
._parse
_video
_data
(
183 _QUERIES
.get(query_id
), {'id': video_id
}, ('data', 'video'), video_id
))
186 class AllstarProfileIE(AllstarBaseIE
):
187 _VALID_URL
= r
'https?://(?:www\.)?allstar\.gg/(?:profile\?user=|u/)(?P<id>[^/?#&]+)'
190 'url': 'https://allstar.gg/profile?user=62b8bdfc9021052f7905882d',
192 'id': '62b8bdfc9021052f7905882d-clips',
193 'title': 'cherokee - Clips',
195 'playlist_mincount': 15
197 'url': 'https://allstar.gg/u/cherokee?game=730&view=Clips',
199 'id': '62b8bdfc9021052f7905882d-clips-730',
200 'title': 'cherokee - Clips - 730',
202 'playlist_mincount': 15
204 'url': 'https://allstar.gg/u/62b8bdfc9021052f7905882d?view=Montages',
206 'id': '62b8bdfc9021052f7905882d-montages',
207 'title': 'cherokee - Montages',
209 'playlist_mincount': 4
211 'url': 'https://allstar.gg/profile?user=cherokee&view=Mobile Clips',
213 'id': '62b8bdfc9021052f7905882d-mobile',
214 'title': 'cherokee - Mobile Clips',
216 'playlist_mincount': 1
221 def _get_page(self
, user_id
, display_id
, game
, query
, page_num
):
224 for video_data
in self
._call
_api
(
229 }, ('data', 'videos', 'data'), display_id
, f
'Downloading page {page_num}'):
230 yield self
._parse
_video
_data
(video_data
)
232 def _real_extract(self
, url
):
233 display_id
= self
._match
_id
(url
)
234 profile_data
= self
._download
_json
(
235 urljoin('https://api.allstar.gg/v1/users/profile/', display_id
), display_id
)
236 user_id
= traverse_obj(profile_data
, ('data', ('_id'), {str}
))
238 raise ExtractorError('Unable to extract the user id')
240 username
= traverse_obj(profile_data
, ('data', 'profile', ('username'), {str}
))
241 url_query
= parse_qs(url
)
242 game
= traverse_obj(url_query
, ('game', 0, {int_or_none}
))
243 query_id
= traverse_obj(url_query
, ('view', 0), default
='Clips')
245 if query_id
not in ('Clips', 'Montages', 'Mobile Clips'):
246 raise ExtractorError(f
'Unsupported playlist URL type {query_id!r}')
248 return self
.playlist_result(
251 self
._get
_page
, user_id
, display_id
, game
, _QUERIES
.get(query_id
)), self
._PAGE
_SIZE
),
252 playlist_id
=join_nonempty(user_id
, query_id
.lower().split()[0], game
),
253 playlist_title
=join_nonempty((username
or display_id
), query_id
, game
, delim
=' - '))