logo

youtube-dl

[mirror] Download/Watch videos from video hostersgit clone https://hacktivis.me/git/mirror/youtube-dl.git

box.py (3795B)


  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. import json
  4. import re
  5. from .common import InfoExtractor
  6. from ..utils import (
  7. determine_ext,
  8. parse_iso8601,
  9. # try_get,
  10. update_url_query,
  11. )
  12. class BoxIE(InfoExtractor):
  13. _VALID_URL = r'https?://(?:[^.]+\.)?app\.box\.com/s/(?P<shared_name>[^/]+)/file/(?P<id>\d+)'
  14. _TEST = {
  15. 'url': 'https://mlssoccer.app.box.com/s/0evd2o3e08l60lr4ygukepvnkord1o1x/file/510727257538',
  16. 'md5': '1f81b2fd3960f38a40a3b8823e5fcd43',
  17. 'info_dict': {
  18. 'id': '510727257538',
  19. 'ext': 'mp4',
  20. 'title': 'Garber St. Louis will be 28th MLS team +scarving.mp4',
  21. 'uploader': 'MLS Video',
  22. 'timestamp': 1566320259,
  23. 'upload_date': '20190820',
  24. 'uploader_id': '235196876',
  25. }
  26. }
  27. def _real_extract(self, url):
  28. shared_name, file_id = re.match(self._VALID_URL, url).groups()
  29. webpage = self._download_webpage(url, file_id)
  30. request_token = self._parse_json(self._search_regex(
  31. r'Box\.config\s*=\s*({.+?});', webpage,
  32. 'Box config'), file_id)['requestToken']
  33. access_token = self._download_json(
  34. 'https://app.box.com/app-api/enduserapp/elements/tokens', file_id,
  35. 'Downloading token JSON metadata',
  36. data=json.dumps({'fileIDs': [file_id]}).encode(), headers={
  37. 'Content-Type': 'application/json',
  38. 'X-Request-Token': request_token,
  39. 'X-Box-EndUser-API': 'sharedName=' + shared_name,
  40. })[file_id]['read']
  41. shared_link = 'https://app.box.com/s/' + shared_name
  42. f = self._download_json(
  43. 'https://api.box.com/2.0/files/' + file_id, file_id,
  44. 'Downloading file JSON metadata', headers={
  45. 'Authorization': 'Bearer ' + access_token,
  46. 'BoxApi': 'shared_link=' + shared_link,
  47. 'X-Rep-Hints': '[dash]', # TODO: extract `hls` formats
  48. }, query={
  49. 'fields': 'authenticated_download_url,created_at,created_by,description,extension,is_download_available,name,representations,size'
  50. })
  51. title = f['name']
  52. query = {
  53. 'access_token': access_token,
  54. 'shared_link': shared_link
  55. }
  56. formats = []
  57. # for entry in (try_get(f, lambda x: x['representations']['entries'], list) or []):
  58. # entry_url_template = try_get(
  59. # entry, lambda x: x['content']['url_template'])
  60. # if not entry_url_template:
  61. # continue
  62. # representation = entry.get('representation')
  63. # if representation == 'dash':
  64. # TODO: append query to every fragment URL
  65. # formats.extend(self._extract_mpd_formats(
  66. # entry_url_template.replace('{+asset_path}', 'manifest.mpd'),
  67. # file_id, query=query))
  68. authenticated_download_url = f.get('authenticated_download_url')
  69. if authenticated_download_url and f.get('is_download_available'):
  70. formats.append({
  71. 'ext': f.get('extension') or determine_ext(title),
  72. 'filesize': f.get('size'),
  73. 'format_id': 'download',
  74. 'url': update_url_query(authenticated_download_url, query),
  75. })
  76. self._sort_formats(formats)
  77. creator = f.get('created_by') or {}
  78. return {
  79. 'id': file_id,
  80. 'title': title,
  81. 'formats': formats,
  82. 'description': f.get('description') or None,
  83. 'uploader': creator.get('name'),
  84. 'timestamp': parse_iso8601(f.get('created_at')),
  85. 'uploader_id': creator.get('id'),
  86. }