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.

417 lines
15 KiB

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