12
12
import re
13
13
from urllib .parse import urljoin , urlparse
14
14
15
+ from streamlink .exceptions import NoStreamsError
15
16
from streamlink .plugin import Plugin , pluginmatcher
16
17
from streamlink .plugin .api import validate
17
18
from streamlink .stream .dash import DASHStream
26
27
27
28
@pluginmatcher (
28
29
name = "default" ,
29
- pattern = re .compile (r"https?://(?:www\.)?vimeo\.com/.+" ),
30
+ pattern = re .compile (r"https?://(?:www\.)?vimeo\.com/(?!event/).+" ),
31
+ )
32
+ @pluginmatcher (
33
+ name = "event" ,
34
+ pattern = re .compile (r"https?://(?:www\.)?vimeo\.com/event/(?P<event_id>\d+)" ),
30
35
)
31
36
@pluginmatcher (
32
37
name = "player" ,
35
40
class Vimeo (Plugin ):
36
41
VIEWER_URL = "https://vimeo.com/_next/viewer"
37
42
OEMBED_URL = "https://vimeo.com/api/oembed.json"
43
+ EVENT_EMBED_URL = "https://vimeo.com/event/{id}/embed"
38
44
39
45
@staticmethod
40
46
def _schema_config (config ):
@@ -110,15 +116,19 @@ def _get_dash_url(self, url):
110
116
111
117
def _query_player (self ):
112
118
return self .session .http .get (self .url , schema = validate .Schema (
113
- re .compile (r"playerConfig\s*=\s*({.+?})\s*var" ),
119
+ validate .parse_html (),
120
+ validate .xml_xpath_string (".//script[contains(text(),'window.playerConfig')][1]/text()" ),
114
121
validate .none_or_all (
115
- validate .get (1 ),
116
- validate .parse_json (),
117
- validate .transform (self ._schema_config ),
122
+ re .compile (r"^\s*window\.playerConfig\s*=\s*(?P<json>{.+?})\s*$" ),
123
+ validate .none_or_all (
124
+ validate .get ("json" ),
125
+ validate .parse_json (),
126
+ validate .transform (self ._schema_config ),
127
+ ),
118
128
),
119
129
))
120
130
121
- def _query_api (self ):
131
+ def _get_config_url (self ):
122
132
jwt , api_url = self .session .http .get (
123
133
self .VIEWER_URL ,
124
134
schema = validate .Schema (
@@ -135,10 +145,13 @@ def _query_api(self):
135
145
params = {"url" : self .url },
136
146
schema = validate .Schema (
137
147
validate .parse_json (),
138
- {"uri" : str },
148
+ {validate . optional ( "uri" ) : str },
139
149
validate .get ("uri" ),
140
150
),
141
151
)
152
+ if not uri :
153
+ return
154
+
142
155
player_config_url = urljoin (update_scheme ("https://" , api_url ), uri )
143
156
config_url = self .session .http .get (
144
157
player_config_url ,
@@ -151,6 +164,38 @@ def _query_api(self):
151
164
),
152
165
)
153
166
167
+ return config_url
168
+
169
+ def _get_config_url_event (self ):
170
+ return self .session .http .get (
171
+ self .EVENT_EMBED_URL .format (id = self .match ["event_id" ]),
172
+ schema = validate .Schema (
173
+ validate .parse_html (),
174
+ validate .xml_xpath_string (".//script[contains(text(),'var htmlString')][1]/text()" ),
175
+ validate .none_or_all (
176
+ re .compile (r"var htmlString\s*=\s*`(?P<html>.+?)`;" , re .DOTALL ),
177
+ validate .none_or_all (
178
+ validate .get ("html" ),
179
+ validate .parse_html (),
180
+ validate .xml_xpath_string (".//*[@data-config-url][1]/@data-config-url" ),
181
+ ),
182
+ ),
183
+ ),
184
+ )
185
+
186
+ def _query_api (self ):
187
+ config_url = ""
188
+ if self .matches ["event" ]:
189
+ log .debug ("Getting event config_url" )
190
+ config_url = self ._get_config_url_event ()
191
+ if not config_url :
192
+ log .debug ("Getting config_url" )
193
+ config_url = self ._get_config_url ()
194
+
195
+ if not config_url :
196
+ log .error ("The content is not available" )
197
+ raise NoStreamsError
198
+
154
199
return self .session .http .get (config_url , schema = validate .Schema (
155
200
validate .parse_json (),
156
201
validate .transform (self ._schema_config ),
0 commit comments