1
1
"""Utils for Meeting and Import_video module."""
2
2
import json
3
+ import os
3
4
import requests
4
5
import shutil
5
6
42
43
),
43
44
)
44
45
46
+ VIDEOS_DIR = getattr (settings , "VIDEOS_DIR" , "videos" )
47
+
45
48
46
49
def secure_request_for_upload (request ):
47
50
"""Check that the request is correct for uploading a recording.
@@ -55,7 +58,7 @@ def secure_request_for_upload(request):
55
58
# Source_url and recording_name are necessary
56
59
if request .POST .get ("source_url" ) == "" or request .POST .get ("recording_name" ) == "" :
57
60
msg = {}
58
- msg ["error" ] = _ ("Impossible to upload to Pod the video" )
61
+ msg ["error" ] = _ ("Unable to upload the video to Pod " )
59
62
msg ["message" ] = _ ("No URL found / No recording name" )
60
63
msg ["proposition" ] = _ (
61
64
"Try changing the record type or address for this recording"
@@ -81,20 +84,15 @@ def parse_remote_file(session, source_html_url):
81
84
if response .status_code != 200 :
82
85
msg = {}
83
86
msg ["error" ] = _ (
84
- "The HTML file for this recording was not found on the BBB server."
87
+ "The HTML file for this recording was not found on the server."
85
88
)
86
89
# If we want to display the 404/500... page to the user
87
90
# msg["message"] = response.content.decode("utf-8")
88
91
msg ["message" ] = _ ("Error number: %s" ) % response .status_code
89
92
raise ValueError (msg )
90
93
91
94
# Parse the BBB video HTML file
92
- parser = video_parser ()
93
- # Manage the encoding
94
- if response .encoding == "ISO-8859-1" :
95
- parser .feed (response .text .encode ("ISO-8859-1" ).decode ("utf-8" ))
96
- else :
97
- parser .feed (response .text )
95
+ parser = create_parser (response )
98
96
99
97
# Video file found
100
98
if parser .video_check :
@@ -111,12 +109,17 @@ def parse_remote_file(session, source_html_url):
111
109
# Returns the name of the video (if necessary, title is parser.title)
112
110
return parser .video_file
113
111
else :
114
- msg = {}
115
- msg ["error" ] = _ (
116
- "The video file for this recording was not found in the HTML file."
117
- )
118
- msg ["message" ] = _ ("No video file found." )
119
- raise ValueError (msg )
112
+ msg = ""
113
+ # Useful tips for Pod links
114
+ if (
115
+ source_html_url .find ("/video/" ) != - 1
116
+ or source_html_url .find ("/media/videos/" ) != - 1
117
+ ):
118
+ msg = _ (
119
+ "In the case of a video from a Pod platform, please enter "
120
+ "the source file address, available in the video edition."
121
+ )
122
+ raise ValueError ("<div role='alert' class='alert alert-info'>%s</div>" % msg )
120
123
except Exception as exc :
121
124
msg = {}
122
125
msg ["error" ] = _ (
@@ -126,6 +129,16 @@ def parse_remote_file(session, source_html_url):
126
129
raise ValueError (msg )
127
130
128
131
132
+ def create_parser (response ):
133
+ """Parse the BBB video HTML file and manage its encoding."""
134
+ parser = video_parser ()
135
+ if response .encoding == "ISO-8859-1" :
136
+ parser .feed (response .text .encode ("ISO-8859-1" ).decode ("utf-8" ))
137
+ else :
138
+ parser .feed (response .text )
139
+ return parser
140
+
141
+
129
142
def manage_recording_url (source_url , video_file_add ):
130
143
"""Generate the BBB video URL.
131
144
@@ -136,7 +149,7 @@ def manage_recording_url(source_url, video_file_add):
136
149
video_file_add (String): Name of the video file to add to the URL
137
150
138
151
Returns:
139
- String: good URL of a BBB recording video
152
+ String: good URL of a BBB recording video or of the video file
140
153
"""
141
154
try :
142
155
bbb_playback_video = "/video/"
@@ -201,7 +214,7 @@ def manage_download(session, source_url, video_file_add, dest_file):
201
214
202
215
203
216
def download_video_file (session , source_video_url , dest_file ):
204
- """Download BBB video file.
217
+ """Download video file.
205
218
206
219
Args:
207
220
session (Session) : session useful to achieve requests (and keep cookies between)
@@ -220,7 +233,7 @@ def download_video_file(session, source_video_url, dest_file):
220
233
raise ValueError (
221
234
_ (
222
235
"The video file for this recording "
223
- "was not found on the BBB server."
236
+ "was not found on the server."
224
237
)
225
238
)
226
239
@@ -281,10 +294,13 @@ def check_file_exists(source_url):
281
294
Returns:
282
295
Boolean: file exists (True) or not (False)
283
296
"""
284
- response = requests .head (source_url , timeout = 2 )
285
- if response .status_code < 400 :
286
- return True
287
- else :
297
+ try :
298
+ response = requests .head (source_url , timeout = 2 )
299
+ if response .status_code < 400 :
300
+ return True
301
+ else :
302
+ return False
303
+ except Exception :
288
304
return False
289
305
290
306
@@ -297,12 +313,18 @@ def verify_video_exists_and_size(video_url):
297
313
Raises:
298
314
ValueError: exception raised if no video found in this URL or video oversized
299
315
"""
300
- response = requests .head (video_url , timeout = 2 )
301
- if response .status_code < 400 :
302
- # Video file size
303
- size = int (response .headers .get ("Content-Length" , "0" ))
304
- check_video_size (size )
305
- else :
316
+ try :
317
+ response = requests .head (video_url , timeout = 2 )
318
+ if response .status_code < 400 :
319
+ # Video file size
320
+ size = int (response .headers .get ("Content-Length" , "0" ))
321
+ check_video_size (size )
322
+ else :
323
+ msg = {}
324
+ msg ["error" ] = _ ("No video file found." )
325
+ msg ["message" ] = _ ("No video file found for this address." )
326
+ raise ValueError (msg )
327
+ except Exception :
306
328
msg = {}
307
329
msg ["error" ] = _ ("No video file found." )
308
330
msg ["message" ] = _ ("No video file found for this address." )
@@ -329,6 +351,149 @@ def check_video_size(video_size):
329
351
raise ValueError (msg )
330
352
331
353
354
+ def check_source_url (source_url ): # noqa: C901
355
+ """Check the source URL to identify the used platform.
356
+
357
+ Platforms managed :
358
+ - Mediacad platform (Médiathèque académique) : rewrite source URL if required
359
+ and manage JSON API.
360
+ """
361
+ base_url = ""
362
+ media_id = ""
363
+ format = ""
364
+ url_api_video = ""
365
+ source_video_url = ""
366
+ platform = ""
367
+ platform_type = None
368
+ # Source URL array
369
+ array_url = source_url .split ('/' )
370
+ # Parse for parameters
371
+ url = urlparse (source_url )
372
+ if url .query :
373
+ query = parse_qs (url .query , keep_blank_values = True )
374
+
375
+ try :
376
+ if source_url .find ("/download.php?t=" ) != - 1 and url .query :
377
+ # Mediacad direct video link (with ##format## in: mp4, source, webm)
378
+ # ##mediacadBaseUrl##/download.php?t=##token##&e=##format##&m=##mediaId##
379
+ base_url = source_url [:source_url .find ("/download.php?t=" )]
380
+ media_id = query ["m" ][0 ]
381
+ format = query ["e" ][0 ].replace ("source" , "mp4" )
382
+ # Force to download mp4 file if source
383
+ source_video_url = source_url .replace ("&e=source" , "&e=mp4" )
384
+ platform = "Mediacad"
385
+ elif (
386
+ source_url .find ("/d/d" ) != - 1
387
+ and source_url .find ("/default/media/display/m" ) != - 1
388
+ ):
389
+ # Mediacad direct video link (with ##format## in: mp4, source, webm)
390
+ # ##mediacadBaseUrl##/default/media/display/m/##mediaId##/e/##format##/d/d
391
+ base_url = source_url [:source_url .find ("/default/media/display/m/" )]
392
+ media_id = array_url [- 5 ]
393
+ format = array_url [- 3 ].replace ("source" , "mp4" )
394
+ # Force to download mp4 file if source
395
+ source_video_url = source_url .replace ("/e/source" , "/e/mp4" )
396
+ platform = "Mediacad"
397
+ elif source_url .find ("/d/m/e" ) != - 1 :
398
+ # Mediacad direct video link (with ##format## in: mp4, source, webm)
399
+ # ##mediacadBaseUrl##/m/##mediaId##/d/m/e/##format##
400
+ base_url = source_url [:source_url .find ("/m/" )]
401
+ media_id = array_url [- 5 ]
402
+ format = array_url [- 1 ].replace ("source" , "mp4" )
403
+ source_video_url = source_url .replace ("/e/source" , "/e/mp4" )
404
+ platform = "Mediacad"
405
+ elif source_url .find ("/default/media/display/" ) != - 1 :
406
+ # Mediacad page link
407
+ # ##mediacadBaseUrl##/default/media/display/m/##mediaId##
408
+ # ##mediacadBaseUrl##/default/media/display/page/1/sort/date/m/##mediaId##
409
+ base_url = source_url [:source_url .find ("/default/media/display/" )]
410
+ media_id = array_url [- 1 ]
411
+ format = "mp4"
412
+ source_video_url = source_url + "/e/mp4/d/d"
413
+ platform = "Mediacad"
414
+ elif source_url .find ("/m/" ) != - 1 :
415
+ # Mediacad page link
416
+ # ##mediacadBaseUrl##/m/##mediaId##
417
+ base_url = source_url [:source_url .find ("/m/" )]
418
+ media_id = array_url [- 1 ]
419
+ format = "mp4"
420
+ # Download possible on all Mediacad platform with such an URL
421
+ source_video_url = "%s/default/media/display/m/%s/e/mp4/d/d" % (
422
+ base_url , media_id
423
+ )
424
+ platform = "Mediacad"
425
+
426
+ # Platform's URL identified
427
+ if platform == "Mediacad" :
428
+ # Mediacad API (JSON format) is available at :
429
+ # ##mediacadBaseUrl##/default/media/display/m/##mediaId##/d/j
430
+ url_api_video = "%s/default/media/display/m/%s/d/j" % (base_url , media_id )
431
+ # Platform type
432
+ platform_type = TypeSourceURL (
433
+ platform ,
434
+ source_video_url ,
435
+ format ,
436
+ url_api_video
437
+ )
438
+
439
+ return platform_type
440
+ except Exception as exc :
441
+ msg = {}
442
+ msg ["error" ] = _ (
443
+ "The video file for this recording was not found."
444
+ )
445
+ msg ["message" ] = mark_safe (str (exc ))
446
+ raise ValueError (msg )
447
+
448
+
449
+ def define_dest_file (request , id , extension ):
450
+ """ Define standard destination filename for an external recording."""
451
+ # Set a discriminant
452
+ discrim = dt .now ().strftime ("%Y%m%d%H%M%S" )
453
+ dest_file = os .path .join (
454
+ settings .MEDIA_ROOT ,
455
+ VIDEOS_DIR ,
456
+ request .user .owner .hashkey ,
457
+ os .path .basename ("%s-%s.%s" % (discrim , id , extension )),
458
+ )
459
+ os .makedirs (os .path .dirname (dest_file ), exist_ok = True )
460
+ return dest_file
461
+
462
+
463
+ def define_dest_path (request , id , extension ):
464
+ """ Define standard destination path for an external recording."""
465
+ # Set a discriminant
466
+ discrim = dt .now ().strftime ("%Y%m%d%H%M%S" )
467
+ dest_path = os .path .join (
468
+ VIDEOS_DIR ,
469
+ request .user .owner .hashkey ,
470
+ os .path .basename ("%s-%s.%s" % (discrim , id , extension )),
471
+ )
472
+ return dest_path
473
+
474
+
475
+ class TypeSourceURL :
476
+ """Manage external recording source URL.
477
+
478
+ Define context, and platform used, about a source URL.
479
+ """
480
+ # Source URL type, like Mediacad, Pod...
481
+ type = ""
482
+ # Source video file URL
483
+ url = ""
484
+ # Video extension (mp4, webm...)
485
+ extension = ""
486
+ # API URL if supplied
487
+ api_url = ""
488
+
489
+ def __init__ (self , type , url , extension , api_url ):
490
+ """Initialize."""
491
+ self .type = type
492
+ self .url = url
493
+ self .extension = extension
494
+ self .api_url = api_url
495
+
496
+
332
497
class video_parser (HTMLParser ):
333
498
"""Useful to parse the BBB Web page and search for video file.
334
499
0 commit comments