You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

354 lines
13 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. #!/usr/bin/env python2
  2. # -*- coding: utf-8 -*-
  3. """Youtubedlg module to handle settings. """
  4. from __future__ import unicode_literals
  5. import json
  6. import os.path
  7. from .utils import (
  8. encode_tuple,
  9. decode_tuple,
  10. check_path
  11. )
  12. class OptionsManager(object):
  13. """Handles youtubedlg options.
  14. This class is responsible for storing and retrieving the options.
  15. Attributes:
  16. SETTINGS_FILENAME (string): Filename of the settings file.
  17. SENSITIVE_KEYS (tuple): Contains the keys that we don't want
  18. to store on the settings file. (SECURITY ISSUES).
  19. Args:
  20. config_path (string): Absolute path where OptionsManager
  21. should store the settings file.
  22. Note:
  23. See load_default() method for available options.
  24. Example:
  25. Access the options using the 'options' variable.
  26. opt_manager = OptionsManager('.')
  27. opt_manager.options['save_path'] = '~/Downloads'
  28. """
  29. SETTINGS_FILENAME = 'settings.json'
  30. SENSITIVE_KEYS = ('sudo_password', 'password', 'video_password')
  31. def __init__(self, config_path):
  32. self.config_path = config_path
  33. self.settings_file = os.path.join(config_path, self.SETTINGS_FILENAME)
  34. self.options = dict()
  35. self.load_default()
  36. self.load_from_file()
  37. def load_default(self):
  38. """Load the default options.
  39. Note:
  40. This method is automatically called by the constructor.
  41. Options Description:
  42. save_path (string): Path where youtube-dl should store the
  43. downloaded file. Default is $HOME.
  44. video_format (string): Video format to download.
  45. When this options is set to '0' youtube-dl will choose
  46. the best video format available for the given URL.
  47. second_video_format (string): Video format to mix with the first
  48. one (-f 18+17).
  49. to_audio (boolean): If True youtube-dl will post process the
  50. video file.
  51. keep_video (boolen): If True youtube-dl will keep the video file
  52. after post processing it.
  53. audio_format (string): Audio format of the post processed file.
  54. Available values are "mp3", "wav", "aac", "m4a", "vorbis".
  55. audio_quality (string): Audio quality of the post processed file.
  56. Available values are "9", "5", "0". The lowest the value the
  57. better the quality.
  58. restrict_filenames (boolean): If True youtube-dl will restrict
  59. the downloaded file filename to ASCII characters only.
  60. output_format (string): This option sets the downloaded file
  61. output template. Available values are 'id', 'title', 'custom'
  62. 'id' -> '%(id)s.%(ext)s'
  63. 'title' -> '%(title)s.%(ext)s'
  64. 'custom' -> Use 'output_template' as output template.
  65. output_template (string): Can be any output template supported
  66. by youtube-dl.
  67. playlist_start (int): Playlist index to start downloading.
  68. playlist_end (int): Playlist index to stop downloading.
  69. max_downloads (int): Maximum number of video files to download
  70. from the given playlist.
  71. min_filesize (float): Minimum file size of the video file.
  72. If the video file is smaller than the given size then
  73. youtube-dl will abort the download process.
  74. max_filesize (float): Maximum file size of the video file.
  75. If the video file is larger than the given size then
  76. youtube-dl will abort the download process.
  77. min_filesize_unit (string): Minimum file size unit.
  78. Available values: '', 'k', 'm', 'g', 'y', 'p', 'e', 'z', 'y'.
  79. max_filesize_unit (string): Maximum file size unit.
  80. See 'min_filesize_unit' option for available values.
  81. write_subs (boolean): If True youtube-dl will try to download
  82. the subtitles file for the given URL.
  83. write_all_subs (boolean): If True youtube-dl will try to download
  84. all the available subtitles files for the given URL.
  85. write_auto_subs (boolean): If True youtube-dl will try to download
  86. the automatic subtitles file for the given URL.
  87. embed_subs (boolean): If True youtube-dl will merge the subtitles
  88. file with the video. (ONLY mp4 files).
  89. subs_lang (string): Language of the subtitles file to download.
  90. Needs 'write_subs' option.
  91. ignore_errors (boolean): If True youtube-dl will ignore the errors
  92. and continue the download process.
  93. open_dl_dir (boolean): If True youtube-dlg will open the
  94. destination folder after download process has been completed.
  95. write_description (boolean): If True youtube-dl will write video
  96. description to a .description file.
  97. write_info (boolean): If True youtube-dl will write video
  98. metadata to a .info.json file.
  99. write_thumbnail (boolean): If True youtube-dl will write
  100. thumbnail image to disk.
  101. retries (int): Number of youtube-dl retries.
  102. user_agent (string): Specify a custom user agent for youtube-dl.
  103. referer (string): Specify a custom referer to use if the video
  104. access is restricted to one domain.
  105. proxy (string): Use the specified HTTP/HTTPS proxy.
  106. shutdown (boolean): If True youtube-dlg will turn the computer
  107. off after the download process has been completed.
  108. sudo_password (string): SUDO password for the shutdown process if
  109. the user does not have elevated privileges.
  110. username (string): Username to login with.
  111. password (string): Password to login with.
  112. video_password (string): Video password for the given URL.
  113. youtubedl_path (string): Absolute path to the youtube-dl binary.
  114. Default is the self.config_path. You can change this option
  115. to point on /usr/local/bin etc.. if you want to use the
  116. youtube-dl binary on your system. This is also the directory
  117. where youtube-dlg will auto download the youtube-dl if not
  118. exists so you should make sure you have write access if you
  119. want to update the youtube-dl binary from within youtube-dlg.
  120. cmd_args (string): String that contains extra youtube-dl options
  121. seperated by spaces.
  122. enable_log (boolean): If True youtube-dlg will enable
  123. the LogManager. See main() function under __init__().
  124. log_time (boolean): See logmanager.LogManager add_time attribute.
  125. workers_number (int): Number of download workers that download manager
  126. will spawn. Must be greater than zero.
  127. locale_name (string): Locale name (e.g. ru_RU).
  128. main_win_size (tuple): Main window size (width, height).
  129. If window becomes to small the program will reset its size.
  130. See _settings_are_valid method MIN_FRAME_SIZE.
  131. opts_win_size (tuple): Options window size (width, height).
  132. If window becomes to small the program will reset its size.
  133. See _settings_are_valid method MIN_FRAME_SIZE.
  134. """
  135. self.options = {
  136. 'save_path': os.path.expanduser('~'),
  137. 'video_format': '0',
  138. 'second_video_format': '0',
  139. 'to_audio': False,
  140. 'keep_video': False,
  141. 'audio_format': 'mp3',
  142. 'audio_quality': '5',
  143. 'restrict_filenames': False,
  144. 'output_format': 'title',
  145. 'output_template': '%(uploader)s/%(title)s.%(ext)s',
  146. 'playlist_start': 1,
  147. 'playlist_end': 0,
  148. 'max_downloads': 0,
  149. 'min_filesize': 0,
  150. 'max_filesize': 0,
  151. 'min_filesize_unit': '',
  152. 'max_filesize_unit': '',
  153. 'write_subs': False,
  154. 'write_all_subs': False,
  155. 'write_auto_subs': False,
  156. 'embed_subs': False,
  157. 'subs_lang': 'en',
  158. 'ignore_errors': True,
  159. 'open_dl_dir': True,
  160. 'write_description': False,
  161. 'write_info': False,
  162. 'write_thumbnail': False,
  163. 'retries': 10,
  164. 'user_agent': '',
  165. 'referer': '',
  166. 'proxy': '',
  167. 'shutdown': False,
  168. 'sudo_password': '',
  169. 'username': '',
  170. 'password': '',
  171. 'video_password': '',
  172. 'youtubedl_path': self.config_path,
  173. 'cmd_args': '',
  174. 'enable_log': True,
  175. 'log_time': False,
  176. 'workers_number': 3,
  177. 'locale_name': 'en_US',
  178. 'main_win_size': (700, 490),
  179. 'opts_win_size': (640, 270)
  180. }
  181. def load_from_file(self):
  182. """Load options from settings file. """
  183. if not os.path.exists(self.settings_file):
  184. return
  185. with open(self.settings_file, 'rb') as settings_file:
  186. try:
  187. options = json.load(settings_file)
  188. if self._settings_are_valid(options):
  189. self.options = options
  190. except:
  191. self.load_default()
  192. def save_to_file(self):
  193. """Save options to settings file. """
  194. check_path(self.config_path)
  195. with open(self.settings_file, 'wb') as settings_file:
  196. options = self._get_options()
  197. json.dump(options,
  198. settings_file,
  199. indent=4,
  200. separators=(',', ': '))
  201. def _settings_are_valid(self, settings_dictionary):
  202. """Check settings.json dictionary.
  203. Args:
  204. settings_dictionary (dictionary): Options dictionary loaded
  205. from the settings file. See load_from_file() method.
  206. Returns:
  207. True if settings.json dictionary is valid, else False.
  208. """
  209. VALID_VIDEO_FORMAT = ('0', '17', '36', '5', '34', '35', '43', '44', '45',
  210. '46', '18', '22', '37', '38', '160', '133', '134', '135', '136','137',
  211. '264', '138', '242', '243', '244', '247', '248', '271', '272', '82',
  212. '83', '84', '85', '100', '101', '102', '139', '140', '141', '171', '172')
  213. VALID_AUDIO_FORMAT = ('mp3', 'wav', 'aac', 'm4a', 'vorbis')
  214. VALID_AUDIO_QUALITY = ('0', '5', '9')
  215. VALID_OUTPUT_FORMAT = ('title', 'id', 'custom')
  216. VALID_FILESIZE_UNIT = ('', 'k', 'm', 'g', 't', 'p', 'e', 'z', 'y')
  217. VALID_SUB_LANGUAGE = ('en', 'gr', 'pt', 'fr', 'it', 'ru', 'es', 'de')
  218. MIN_FRAME_SIZE = 100
  219. # Decode string formatted tuples back to normal tuples
  220. settings_dictionary['main_win_size'] = decode_tuple(settings_dictionary['main_win_size'])
  221. settings_dictionary['opts_win_size'] = decode_tuple(settings_dictionary['opts_win_size'])
  222. for key in self.options:
  223. if key not in settings_dictionary:
  224. return False
  225. if type(self.options[key]) != type(settings_dictionary[key]):
  226. return False
  227. # Check if each key has a valid value
  228. rules_dict = {
  229. 'video_format': VALID_VIDEO_FORMAT,
  230. 'second_video_format': VALID_VIDEO_FORMAT,
  231. 'audio_format': VALID_AUDIO_FORMAT,
  232. 'audio_quality': VALID_AUDIO_QUALITY,
  233. 'output_format': VALID_OUTPUT_FORMAT,
  234. 'min_filesize_unit': VALID_FILESIZE_UNIT,
  235. 'max_filesize_unit': VALID_FILESIZE_UNIT,
  236. 'subs_lang': VALID_SUB_LANGUAGE
  237. }
  238. for key, valid_list in rules_dict.items():
  239. if settings_dictionary[key] not in valid_list:
  240. return False
  241. # Check workers number value
  242. if settings_dictionary['workers_number'] < 1:
  243. return False
  244. # Check main-options frame size
  245. for size in settings_dictionary['main_win_size']:
  246. if size < MIN_FRAME_SIZE:
  247. return False
  248. for size in settings_dictionary['opts_win_size']:
  249. if size < MIN_FRAME_SIZE:
  250. return False
  251. return True
  252. def _get_options(self):
  253. """Return options dictionary without SENSITIVE_KEYS. """
  254. temp_options = self.options.copy()
  255. for key in self.SENSITIVE_KEYS:
  256. temp_options[key] = ''
  257. # Encode normal tuples to string formatted tuples
  258. temp_options['main_win_size'] = encode_tuple(temp_options['main_win_size'])
  259. temp_options['opts_win_size'] = encode_tuple(temp_options['opts_win_size'])
  260. return temp_options