123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- # This file is part of stov, written by Helmut Pozimski 2012-2017.
- #
- # stov is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, version 2 of the License.
- #
- # stov is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with stov. If not, see <http://www.gnu.org/licenses/>.
- # -*- coding: utf8 -*-
- """This file takes care of reading, storing and updating the configuration of
- stov, the configuration file is expected to be in json format and reside in
- ~/.stov/stov.json.
- """
- import os
- import json
- import logging
- from lib_stov import stov_exceptions
- LOGGER = logging.getLogger("stov")
- class Conf(object):
- """This class is used to create the object which is responsible for all
- configuration operations.
- """
- def __init__(self):
- """Constructor
- Constructs the conf object with some reasonable default values which
- should work on most systems, existence of a local mail server is
- assumed.
- """
- self.values = {
- "database": "stov.sqlite",
- "downloaddir": str(os.environ['HOME']) + "/stov",
- "maxvideos": "25",
- "mailhost": "localhost",
- "mailto": "root",
- "mailfrom": "stov@localhost",
- "smtpport": "25",
- "auth_needed": "no",
- "user_name": "",
- "password": "",
- "youtube-dl": "",
- "notify": "yes",
- "config_version": "9",
- "db_version": "6",
- "videocodec": "mp4",
- "maxresolution": "1080p",
- "maxfails": 50,
- "check_title": "no"
- }
- self.__explanations = {
- "database": _("the name of your database file"),
- "downloaddir": _("the directory where downloaded videos are "
- "saved"),
- "maxvideos": _("the maximum number of videos to retrieve for each "
- "subscription"),
- "mailhost": _("the host name of your mail server"),
- "mailto": _("the address used for notifications"),
- "mailfrom": _("the sender address of notification e-mails"),
- "smtpport": _("the port to use on your mail server"),
- "auth_needed": _("if your mail server requires authentication"),
- "user_name": _("the user name used to authenticate to your mail "
- "server"),
- "password": _("the password used to authenticate to your mail "
- "server"),
- "youtube-dl": _("the path to your youtube-dl installation"),
- "notify": _("if you want to be notified via e-mail about new "
- "videos"),
- "videocodec": _("which video codec you prefer (h264, webm or "
- "flv)"),
- "maxresolution": _("which resolution you prefer (360p, 480p, 720p "
- "or 1080p)"),
- "check_title": _("if you want to compare the title of a video "
- "with the subscription search string")
- }
- self.dbpath = str(os.environ['HOME']) + "/.stov/" + \
- self.values["database"]
- self.outputlevel = "default"
- def write_config(self):
- """Writes the configuration from the dictionary into the configuration
- file for stov. The configuration is written into the home directory of
- the user by default.
- """
- LOGGER.debug(_("Writing configuration file."))
- try:
- configfile = open(str(os.environ['HOME']) +
- "/.stov/stov.json", "w")
- except IOError:
- raise stov_exceptions.ConfigFileWriteErrorException()
- else:
- json.dump(self.values, configfile, indent=0)
- configfile.close()
- def initialize(self):
- """Creates the necessary directory for the stov configuration and
- calls the internal methods to create the database and the
- configuration file.
- """
- LOGGER.debug(_("Creating stov configuration directory"))
- try:
- os.mkdir(str(os.environ['HOME']) + "/.stov", 0o750)
- except os.error:
- raise stov_exceptions.DirectoryCreationFailedException()
- else:
- self.write_config()
- def read_old_config(self):
- """Reads the existing plain text configuration file and places the
- values in the dictionary. Existing values (such as default values)
- are overwritten.
- """
- LOGGER.debug(_("Opening old configuration file to convert it to "
- "json"))
- try:
- configfile = open(str(os.environ['HOME']) +
- "/.stov/stov.config", "r")
- except IOError:
- raise stov_exceptions.ConfigFileReadErrorException()
- for lines in configfile:
- tmpline = lines.strip()
- tmplist = tmpline.split("=")
- self.values[tmplist[0].lower()] = tmplist[1]
- configfile.close()
- self.dbpath = str(os.environ['HOME']) + "/.stov/" + \
- self.values["database"]
- def read_config(self):
- """Reads the existing json configuration files and loads the values in
- the dictionary.
- """
- LOGGER.debug(_("Opening configuration file"))
- try:
- configfile = open(str(os.environ['HOME']) + "/.stov/stov.json",
- "r")
- except IOError:
- raise stov_exceptions.ConfigFileReadErrorException()
- else:
- self.values.update(json.load(configfile))
- configfile.close()
- def check_config(self):
- """Checks if the configuration is up-to-date with the running
- stov version.
- """
- try:
- current_version = int(self.values["config_version"])
- except ValueError:
- raise stov_exceptions.InvalidConfigurationVersionException()
- self.values["config_version"] = "0"
- self.read_config()
- if self.values["config_version"] == "0" \
- or int(self.values["config_version"]) < current_version:
- self.values["config_version"] = str(current_version)
- return False
- else:
- self.values["config_version"] = current_version
- return True
- def update_config(self):
- """Update the configuration to the latest version"""
- version_buffer = self.values["config_version"]
- self.read_config()
- self.values["config_version"] = version_buffer
- self.write_config()
- def check_db(self):
- """Checks the database if it is up-to-date"""
- currentdbversion = int(self.values["db_version"])
- self.values["db_version"] = "0"
- self.read_config()
- if self.values["db_version"] == "0" or \
- int(self.values["db_version"]) <\
- int(currentdbversion):
- self.values["db_version"] = str(currentdbversion)
- return False
- else:
- self.values["db_version"] = str(currentdbversion)
- return True
- def get_youtube_parameter(self):
- """Determines which itag value results from codec and resolution
- settings and returns it
- """
- itag_value = 0
- if self.values["videocodec"] == "flv":
- if self.values["maxresolution"] == "240p":
- itag_value = 5
- elif self.values["maxresolution"] == "270p":
- itag_value = 6
- elif self.values["maxresolution"] == "360p":
- itag_value = 34
- elif self.values["maxresolution"] == "480p":
- itag_value = 35
- elif self.values["videocodec"] == "webm":
- if self.values["maxresolution"] == "360p":
- itag_value = 43
- elif self.values["maxresolution"] == "480p":
- itag_value = 44
- elif self.values["maxresolution"] == "720p":
- itag_value = 45
- elif self.values["maxresolution"] == "1080p":
- itag_value = 46
- elif self.values["videocodec"] == "mp4":
- if self.values["maxresolution"] == "360p":
- itag_value = 18
- elif self.values["maxresolution"] == "720p":
- itag_value = 22
- elif self.values["maxresolution"] == "1080p":
- itag_value = 37
- elif self.values["maxresolution"] == "3072p":
- itag_value = 38
- if itag_value:
- return itag_value
- else:
- LOGGER.debug(_("Could not determine an itag value "
- "from the configuration"))
- return 38
- def assist(self):
- """ Ask the user to set all required configuration parameters """
- print(_("This assistant will help you to perform the initial "
- "configuration of stov. \nThe default value will be "
- "displayed in brackets.\n"
- "Please specify now :\n"))
- for value in self.__explanations:
- print(self.__explanations[value] + " [" + self.values[value] +
- "]:" +
- " ")
- user_input = input()
- if user_input != "":
- self.values[value] = user_input
- self.dbpath = str(os.environ['HOME']) + "/.stov/" + \
- self.values["database"]
- def migrate_config(self):
- """Migrates the configuration from the old plain text config to
- the new and shiny json configuration file.
- """
- try:
- self.read_old_config()
- self.write_config()
- except stov_exceptions.ConfigFileReadErrorException:
- raise stov_exceptions.ConfigurationMigrationFailed()
- except stov_exceptions.ConfigFileWriteErrorException:
- raise stov_exceptions.ConfigurationMigrationFailed
- else:
- os.remove(str(os.environ['HOME']) + "/.stov/stov.config")
- def configure_logging(self, verbose=False, quiet=False):
- """
- Sets up logging for stov and returns a logger object
- :param verbose: whether to use verbose mode
- :type verbose: bool
- :param quiet: whether to use quiet mode
- :type quiet: bool
- :return: logger object
- :rtype: logging.Logger
- """
- logger = logging.getLogger("stov")
- # verbose takes precedence
- if verbose:
- logger.setLevel(logging.DEBUG)
- self.outputlevel = "verbose"
- elif quiet:
- logger.setLevel(logging.ERROR)
- self.outputlevel = "quiet"
- else:
- logger.setLevel(logging.INFO)
- console_handler = logging.StreamHandler()
- logger.addHandler(console_handler)
- return logger
|