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.

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