configuration.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. # This file is part of stov, written by Helmut Pozimski in 2012.
  2. #
  3. # stov is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, version 2 of the License.
  6. #
  7. # stov is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License
  13. # along with stov. If not, see <http://www.gnu.org/licenses/>.
  14. # -*- coding: utf8 -*-
  15. import os
  16. import gettext
  17. import sys
  18. import sqlite3
  19. import subprocess
  20. from outputhelper import printf
  21. class conf(object):
  22. def __init__(self):
  23. """Constructor
  24. Constructs the conf object with some reasonable default values which should
  25. work on most systems, existence of a local mail server is assumed.
  26. """
  27. self.values = {
  28. "database": "stov.sqlite",
  29. "downloaddir": str(os.environ['HOME']) + "/stov",
  30. "maxvideos": "25",
  31. "mailhost": "localhost",
  32. "mailto": "root",
  33. "mailfrom": "stov@localhost",
  34. "smtpport": "25",
  35. "auth_needed": "no",
  36. "user_name": "",
  37. "password": "",
  38. "youtube-dl": "",
  39. "notify": "yes",
  40. "config_version": "6",
  41. "db_version": "2",
  42. "videocodec": "h264",
  43. "maxresolution": "1080p",
  44. "maxfails": "50"
  45. }
  46. self.__explanations = {
  47. "database": _("the name of your database file"),
  48. "downloaddir": _("the directory where downloaded videos are saved"),
  49. "maxvideos": _("the maximum number of videos to retrieve for each subscription"),
  50. "mailhost": _("the host of your mail server"),
  51. "mailto": _("the address used for notifications"),
  52. "mailfrom": _("the sender address of notification e-mails"),
  53. "smtpport": _("the port to use on your mail server"),
  54. "auth_needed": _("if your mail server requires authentication"),
  55. "user_name": _("the user name used to authenticate to your mail server"),
  56. "password": _("the password used to authenticate to your mail server"),
  57. "youtube-dl": _("the path to your youtube-dl installation"),
  58. "notify": _("if you want to be notified via e-mail about new videos"),
  59. "videocodec": _("which video codec you prefer (h264, webm or flv)"),
  60. "maxresolution": _("which resolution you prefer (360p, 480p, 720p or 1080p)"),
  61. }
  62. self.dbpath = str(os.environ['HOME']) + "/.stov/" + self.values["database"]
  63. self.outputlevel = "default"
  64. def WriteConfig(self):
  65. """Writes the configuration from the dictionary into the configuration file
  66. for stov. The configuration is written into the home directory of the user
  67. by default.
  68. """
  69. try:
  70. printf(_("Opening configuration file"),
  71. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  72. self.configfile = open(str(os.environ['HOME']) + "/.stov/stov.config", "w")
  73. except IOError, os.error:
  74. printf(_("Configuration could not be written, please"
  75. " check that the configuration directory exists and is writable"),
  76. outputlevel="default", level=self.outputlevel, descriptor="stderr")
  77. else:
  78. for key in self.values.iterkeys():
  79. printf(_("Writing value for %s" % key.upper()),
  80. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  81. self.configfile.write(key.upper() + "=" + self.values[key] + "\n")
  82. self.configfile.close()
  83. def CreateDB(self):
  84. """Creates the database structure if it doesn't exist already."""
  85. try:
  86. self.__database = sqlite3.connect(self.dbpath)
  87. except sqlite3.OperationalError:
  88. printf(_("The database could not be created, please "
  89. "check that the configuration directory exists and is writable"),
  90. outputlevel = "default", level=self.outputlevel, descriptor="stderr")
  91. else:
  92. self.__dbcursor = self.__database.cursor()
  93. printf(_("Creating table subscriptions"),
  94. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  95. self.__dbcursor.execute("""CREATE TABLE subscriptions (
  96. id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  97. title TEXT,
  98. name TEXT,
  99. type TEXT,
  100. searchstring TEXT,
  101. directory TEXT
  102. );""")
  103. printf(_("Creating table videos"),
  104. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  105. self.__dbcursor.execute("""CREATE TABLE videos (
  106. id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  107. title TEXT,
  108. description TEXT,
  109. ytid TEXT,
  110. subscription_id INTEGER,
  111. downloaded INT,
  112. failcnt INT DEFAULT 0
  113. );""")
  114. self.__database.commit()
  115. self.__database.close()
  116. def Initialize(self):
  117. """Creates the necessary directory for the stov configuration and calls the
  118. internal methods to create the database and the configuration file.
  119. """
  120. try:
  121. printf(_("Creating hidden directory in home for configuration and database"),
  122. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  123. os.mkdir(str(os.environ['HOME']) + "/.stov", 0750)
  124. except os.error:
  125. printf(_("Configuration directory could not be created, "
  126. "please check that your home directory exists and is writable"),
  127. outputlevel="default", level=self.outputlevel, descriptor="stderr")
  128. else:
  129. printf(_("Looking for youtube-dl file"),
  130. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  131. self.values["youtube-dl"] = subprocess.Popen(["which", "youtube-dl"],
  132. stdout=subprocess.PIPE).communicate()[0].strip()
  133. self.WriteConfig()
  134. self.CreateDB()
  135. def ReadConfig(self):
  136. """Reads the existing configuration file and places the values in the
  137. dictionary. Existing values (such as default values) are overwritten.
  138. """
  139. try:
  140. printf(_("Opening config file for reading"),
  141. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  142. self.configfile = open(str(os.environ['HOME']) + "/.stov/stov.config", "r")
  143. except IOError:
  144. printf(_("Configuration could not be "
  145. "read, please check that the configuration file exists and is readable"),
  146. outputlevel="default", level=self.outputlevel, descriptor="stderr")
  147. for lines in self.configfile:
  148. printf(_("Reading line %s" % lines.strip()),
  149. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  150. self.tmpline = lines.strip()
  151. self.tmplist = self.tmpline.split("=")
  152. self.values[self.tmplist[0].lower()] = self.tmplist[1]
  153. self.configfile.close()
  154. self.dbpath = str(os.environ['HOME']) + "/.stov/" + self.values["database"]
  155. def CheckConfig(self):
  156. """Checks if the configuration is up-to-date with the running
  157. stov version.
  158. """
  159. printf(_("Checking current and running configuration version"),
  160. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  161. try:
  162. self.__currentversion = int(self.values["config_version"])
  163. except ValueError:
  164. printf(_("Invalid config version read"), outputlevel="default",
  165. level=self.outputlevel, descriptor="stderr")
  166. self.values["config_version"] = "0"
  167. self.__currentdbversion = self.values["db_version"]
  168. self.ReadConfig()
  169. printf(_("Found running version: " + self.values["config_version"] + "\n" +
  170. "Current version: " + str(self.__currentversion)),
  171. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  172. if self.values["config_version"] == "0" \
  173. or int(self.values["config_version"]) < self.__currentversion:
  174. self.values["config_version"] = str(self.__currentversion)
  175. return False
  176. else:
  177. self.values["config_version"] = str(self.__currentversion)
  178. return True
  179. def UpdateConfig(self):
  180. """Update the configuration to the latest version"""
  181. self.__versionbuffer = self.values["config_version"]
  182. self.ReadConfig()
  183. self.values["config_version"] = self.__versionbuffer
  184. self.WriteConfig()
  185. def CheckDB(self):
  186. """Checks the database if it is up-to-date"""
  187. printf(_("Checking current and running database version."),
  188. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  189. self.values["db_version"] = "0"
  190. self.ReadConfig()
  191. printf(_("Found running database version: " + self.values["db_version"] +
  192. "\n" + "Current version: " + str(self.__currentversion)),
  193. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  194. if self.values["db_version"] == "0" or \
  195. int(self.values["db_version"]) < int(self.__currentdbversion):
  196. self.values["db_version"] = str(self.__currentversion)
  197. return False
  198. else:
  199. self.values["db_version"] = str(self.__currentversion)
  200. return True
  201. def UpdateDB(self):
  202. """Performs database changes that need to be done"""
  203. self.ReadConfig()
  204. if int(self.values["db_version"]) == 1:
  205. try:
  206. self.__database = sqlite3.connect(self.dbpath)
  207. except sqlite3.OperationalError:
  208. printf(_("The database could not be updated, please "
  209. "check that the configuration directory exists and is writable"),
  210. outputlevel = "default", level=self.outputlevel, descriptor="stderr")
  211. else:
  212. self.__dbcursor = self.__database.cursor()
  213. self.__dbcursor.execute("ALTER TABLE videos add column failcnt int DEFAULT 0;")
  214. self.__database.commit()
  215. self.__database.close()
  216. self.ReadConfig()
  217. self.values["db_version"] = "2"
  218. self.WriteConfig()
  219. else:
  220. pass
  221. def GetYoutubeParameter(self):
  222. """Determines which itag value results from codec and resolution settings
  223. and returns it
  224. """
  225. printf(_("Trying to determine the itag value for youtube-dl from your"
  226. " quality and codec settings"),
  227. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  228. itag_value = 0
  229. if self.values["videocodec"] == "flv":
  230. if self.values["maxresolution"] == "240p":
  231. itag_value = 5
  232. elif self.values["maxresolution"] == "270p":
  233. itag_value = 6
  234. elif self.values["maxresolution"] == "360p":
  235. itag_value = 34
  236. elif self.values["maxresolution"] == "480p":
  237. itag_value = 35
  238. elif self.values["videocodec"] == "webm":
  239. if self.values["maxresolution"] == "360p":
  240. itag_value = 43
  241. elif self.values["maxresolution"] == "480p":
  242. itag_value = 44
  243. elif self.values["maxresolution"] == "720p":
  244. itag_value = 45
  245. elif self.values["maxresolution"] == "1080p":
  246. itag_value = 46
  247. elif self.values["videocodec"] == "h264":
  248. if self.values["maxresolution"] == "360p":
  249. itag_value = 18
  250. elif self.values["maxresolution"] == "720p":
  251. itag_value = 22
  252. elif self.values["maxresolution"] == "1080p":
  253. itag_value = 37
  254. elif self.values["maxresolution"] == "3072p":
  255. itag_value = 38
  256. printf(_("Found value: %s" % itag_value),
  257. outputlevel="verbose", level=self.outputlevel, descriptor="stderr")
  258. return itag_value
  259. def assist(self):
  260. """ Ask the user to set all required configuration parameters """
  261. printf(_("This assistant will help you to perform the initial configuration"
  262. " of stov. \nThe default value will be displayed in brackets.\n"
  263. "Please specify now :\n"), outputlevel="default", level=self.outputlevel,
  264. descriptor="stdout")
  265. for value in self.__explanations:
  266. printf(_(self.__explanations[value] + " [" + self.values[value] + "]: "),
  267. outputlevel="default", level=self.outputlevel,
  268. descriptor="stdout")
  269. self.__user_input = raw_input()
  270. if self.__user_input != "":
  271. self.values[value] = self.__user_input
  272. self.dbpath = str(os.environ['HOME']) + "/.stov/" + self.values["database"]
  273. self.Initialize()
  274. printf(_("Writing initial configuration according to your input, have fun!"),
  275. outputlevel="default", level=self.outputlevel, descriptor="stdout")