123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- # This file is part of stov, written by Helmut Pozimski 2012-2021.
- #
- # 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 json
- import logging
- import os
- from lib_stov import stov_exceptions
- LOGGER = logging.getLogger("stov")
- class Conf:
- """This class is used to create the object which is responsible for all
- configuration operations.
- """
- _instance = None
- 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": "10",
- "db_version": "6",
- "video_codec": "mp4",
- "video_height": "1080",
- "audio_quality": "bestaudio",
- "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"),
- "video_codec": _("which video codec you prefer (h264, webm or "
- "flv)"),
- "video_height": _("sets the height of the video to download (e.g."
- " 1080 for 1920x180)"),
- "audio_quality": _("sets the requested audio quality "
- "(e.g. bestaudio)"),
- "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 __new__(cls, *args, **kwargs):
- if not Conf._instance:
- Conf._instance = super(Conf, cls).__new__(cls)
- return Conf._instance
- @staticmethod
- def get_instance():
- """
- Returns the singleton instance of the object
- :return: Conf object
- :rtype: lib_stov.configuration.Conf
- """
- return Conf._instance
- 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 as exc:
- raise stov_exceptions.ConfigFileWriteErrorException() from exc
- 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 as exc:
- raise stov_exceptions.DirectoryCreationFailedException() from exc
- 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 as exc:
- raise stov_exceptions.ConfigFileReadErrorException() from exc
- 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 as exc:
- raise stov_exceptions.ConfigFileReadErrorException() from exc
- 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 as exc:
- raise stov_exceptions.InvalidConfigurationVersionException() \
- from exc
- 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
- 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"""
- current_db_version = 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(current_db_version):
- self.values["db_version"] = str(current_db_version)
- return False
- self.values["db_version"] = str(current_db_version)
- return True
- 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 as exc:
- raise stov_exceptions.ConfigurationMigrationFailed() from exc
- except stov_exceptions.ConfigFileWriteErrorException as exc:
- raise stov_exceptions.ConfigurationMigrationFailed from exc
- 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
- def get_value(self, identifier):
- """
- Returns the value for the specified identifier
- :param identifier: the identifier in the value dictionary
- :return:
- """
- return self.values[identifier]
|