123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- #! /usr/bin/env python3
- # -*- coding: utf8 -*-
- # stov - a program to subscribe to channels and users from youtube
- # and download the videos automatically
- #
- # written by Helmut Pozimski 2012-2015
- #
- # This program 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.
- #
- # This program 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 this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor,
- # Boston, MA 02110-1301, USA.
- """This is the main script of stov, it can be directly called and glues
- everything together, performing all the actions a user wants.
- """
- import sys
- import gettext
- import os
- import smtplib
- import subprocess
- import signal
- import socket
- import logging
- from email.mime.multipart import MIMEMultipart
- from email.mime.text import MIMEText
- from optparse import OptionParser
- from lib_stov import subscription
- from lib_stov import configuration
- from lib_stov import stov_exceptions
- from lib_stov import database
- # Setup the logger to log messages to stdout and stderr
- LOGGER = logging.getLogger("stov")
- LOGGER.setLevel(logging.DEBUG)
- CONSOLE_HANDLER = logging.StreamHandler()
- LOGGER.addHandler(CONSOLE_HANDLER)
- # Determine the path where the stov files are for localization
- LOCALE_PATH = os.path.join(sys.path[0] + "/locale")
- if gettext.find("stov", LOCALE_PATH) is None:
- BASE_PATH = os.path.split(sys.path[0])[0]
- if "share" in BASE_PATH:
- LOCALE_PATH = os.path.join(BASE_PATH, "locale")
- else:
- LOCALE_PATH = os.path.join(BASE_PATH, "share/locale")
- # Initialize gettext to support translation of the program
- try:
- TRANS = gettext.translation("stov", LOCALE_PATH)
- except IOError:
- gettext.install("stov")
- if os.environ["LANG"] != "C" and os.environ["LANGUAGE"] != "C":
- print(_("The translation files could not be found, localization "
- "won't be available"), file=sys.stderr)
- else:
- TRANS.install()
- # Define a handler for signals sent to the program
- def sighandler(signum, frame):
- """Handler function for signals caught by stov."""
- if signum == 2:
- print(_("STRG+C has been pressed, quitting..."), file=sys.stderr)
- elif signum == 15:
- print(_("Received SIGTERM, quitting..."), file=sys.stderr)
- os.killpg(os.getpid(), 1)
- os.remove("/tmp/stov.lock")
- sys.exit(0)
- signal.signal(signal.SIGTERM, sighandler)
- signal.signal(signal.SIGINT, sighandler)
- # Overwrite the default OptionParser class so error messages
- # can be localized
- class MyOptionParser(OptionParser):
- """Custom class overriding the OptionParser class."""
- def error(self, parser_msg):
- if "invalid integer" in parser_msg:
- print(_("option %s requires an integer value")
- % parser_msg.split()[1], file=sys.stderr)
- self.exit()
- elif "an argument" in parser_msg:
- print(_("option %s requires an argument") % parser_msg.split()[0],
- file=sys.stderr)
- self.exit()
- elif "no such" in parser_msg:
- print(_("invalid option %s") % parser_msg.split()[3],
- file=sys.stderr)
- self.exit()
- else:
- print(parser_msg, file=sys.stderr)
- self.exit()
- PARSER = MyOptionParser(usage=_("Usage: %prog [options]"), prog="stov",
- add_help_option=True, conflict_handler="resolve")
- PARSER.add_option("-h", "--help", action="store_true", dest="help",
- help=_("show this help message and exit"))
- PARSER.add_option("-a", "--add", dest="add", action="store_true",
- help=_("Add a new subscription (requires either \
- --search, --channel or --playlist)"))
- PARSER.add_option("-p", "--playlist", dest="playlist",
- help=_("Add a new Playlist subscription (requires add)"))
- PARSER.add_option("-l", "--lssubs", action="store_true", dest="list",
- help=_("List the currently available subscriptions"))
- PARSER.add_option("-r", "--remove", type="int", dest="deleteid",
- help=_("remove a subscription"))
- PARSER.add_option("-u", "--update", action="store_true", dest="update",
- help=_("update the information about the available videos"))
- PARSER.add_option("-d", "--download", action="store_true", dest="download",
- help=_("download all available videos which haven't already "
- "been downloaded"))
- PARSER.add_option("-s", "--search", dest="searchparameter",
- help=_("optionally add a search string to a new channel "
- "subscription or create a new search subscription "
- "(requires --add)"))
- PARSER.add_option("-l", "--lsvids", type="int", dest="subscriptionid",
- help=_("Print all videos from a subscription"))
- PARSER.add_option("-c", "--catchup", dest="catchup",
- help=_("Mark all videos from one channel as read \
- (requires subscription-id as argument)"))
- PARSER.add_option("-c", "--channel", dest="channel",
- help=_("specify a channel for a new subscription "
- "(requires --add)"))
- PARSER.add_option("-l", "--license", dest="license", action="store_true",
- help=_("show the license of the program"))
- PARSER.add_option("-v", "--version", dest="version", action="store_true",
- help=_("show the current running version number"))
- PARSER.add_option("-q", "--quiet", dest="quiet", action="store_true",
- help=_("Suppress all output"))
- PARSER.add_option("-v", "--verbose", dest="verbose", action="store_true",
- help=_("Be verbose and print also diagnostical messages"))
- PARSER.add_option("-c", "--clean-database", dest="cleanup",
- action="store_true", help=_("Clean the database of entries "
- "no longer listed in the current"
- " API response"))
- PARSER.add_option("-e", "--enable", type="int", dest="enableid",
- help=_("enables the subscription with the provided ID"))
- PARSER.add_option("--disable", type="int", dest="disableid",
- help=_("disables the subscription with the provided ID"))
- (OPTIONS, ARGUMENTS) = PARSER.parse_args()
- # Check if stov is run directly from command line since it shouldn't be
- # loaded as a module
- if __name__ != "__main__":
- print("This file should not be imported as a module"
- "please run it directly from command line")
- sys.exit(1)
- # Check which outputlevel is defined and save it to a temporary variable
- # accordingly. Output generated before this will be printed to stdout
- # regardless of the user defined setting
- if OPTIONS.verbose is True and OPTIONS.quiet is True:
- print(_("--quiet and --verbose can't be defined at the same time, "
- "exiting."), file=sys.stderr)
- sys.exit(1)
- elif OPTIONS.verbose is True:
- OUTPUT_LEVEL = "verbose"
- LOGGER.setLevel(logging.DEBUG)
- elif OPTIONS.quiet is True:
- OUTPUT_LEVEL = "quiet"
- LOGGER.setLevel(logging.ERROR)
- else:
- OUTPUT_LEVEL = "default"
- LOGGER.setLevel(logging.INFO)
- # Create the lock file which is used to determine if another instance is
- # already running by chance, the program shouldn't be run in this case since
- # we want to prevent concurent access to the database.
- if os.access("/tmp/stov.lock", os.F_OK):
- try:
- LOCK_FILE = open("/tmp/stov.lock", "r")
- except IOError:
- LOGGER.error(_("The lock file could not be opened, please check that "
- "it exists and is readable, quitting now"))
- sys.exit(1)
- OLD_PID = LOCK_FILE.read().strip()
- if os.access("/proc/" + OLD_PID, os.F_OK):
- LOGGER.error(_("The lock file already exists, probably another "
- "instance of this program is already running\n"
- "if you are sure this is not the case, delete it"
- " manually and try again!"))
- sys.exit(1)
- LOCK_FILE.close()
- if os.access("/proc/" + OLD_PID, os.F_OK) is not True:
- try:
- os.remove("/tmp/stov.lock")
- except os.error:
- LOGGER.error(_("The old lock file could not be deleted!"))
- try:
- LOCK_FILE = open("/tmp/stov.lock", "w")
- LOCK_FILE.write(str(os.getpid()))
- LOCK_FILE.close()
- except IOError:
- LOGGER.error(_("The lock file could not be created, please check that /tmp"
- " is writable and properly configured, quitting now."))
- sys.exit(1)
- # Check if the configuration directory exists and is writeable. If it
- # doesnt, create it using the configuration class.
- if os.access(os.environ['HOME'] + "/.stov", os.F_OK & os.W_OK) is not True:
- LOGGER.info(_("This seems to be the first time you run the programm, do "
- "you want to run the interactive assistant? (yes/no)"))
- CONF = configuration.Conf()
- TEMP_INPUT = input()
- if TEMP_INPUT == "yes":
- CONF.assist()
- try:
- CONF.initialize()
- except stov_exceptions.ConfigFileWriteErrorException as error:
- LOGGER.error(error)
- else:
- LOGGER.info(_("Writing initial configuration according to your "
- "input, have fun!"))
- else:
- LOGGER.info(_("Writing initial configuration according to default"
- " values."))
- LOGGER.debug(_("Creating hidden directory in home for configuration"
- " and database."))
- try:
- CONF.initialize()
- except stov_exceptions.DirectoryCreationFailedException as error:
- LOGGER.error(error)
- except stov_exceptions.ConfigFileWriteErrorException as error:
- LOGGER.error(error)
- else:
- CONF = configuration.Conf()
- if os.access(str(os.environ['HOME']) + "/.stov/stov.config", os.F_OK):
- LOGGER.debug(_("Migrating configuration from plain text to json."))
- CONF.migrate_config()
- try:
- LOGGER.debug(_("Comparing current and running configuration version."))
- CHECK_RESULT = CONF.check_config()
- except stov_exceptions.ConfigFileReadErrorException as error:
- LOGGER.error(error)
- sys.exit(1)
- except stov_exceptions.InvalidConfigurationVersionException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- if not CHECK_RESULT:
- LOGGER.info(_("Your configuration needs to be updated, performing"
- " update now."))
- try:
- CONF.update_config()
- except stov_exceptions.ConfigFileReadErrorException as error:
- LOGGER.error(error)
- sys.exit(1)
- except stov_exceptions.ConfigFileWriteErrorException as error:
- LOGGER.error(error)
- sys.exit(1)
- # Create the initial connection to the database
- if os.access(CONF.dbpath, os.F_OK):
- try:
- DB = database.Db(path=CONF.dbpath, version=CONF.values["db_version"])
- except stov_exceptions.DBConnectionFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- try:
- DB = database.Db(path=CONF.dbpath, version=CONF.values["db_version"])
- except stov_exceptions.DBConnectionFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- try:
- DB.populate()
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.debug(_("Created initial database tables."))
- try:
- LOGGER.debug(_("Comparing current and running database version."))
- if not CONF.check_db():
- LOGGER.info(_("Your database needs to be updated, performing update "
- "now."))
- DB.update()
- CONF.values["db_version"] = DB.get_version()
- LOGGER.debug("Opening configuration file.")
- try:
- CONF.write_config()
- except stov_exceptions.ConfigFileWriteErrorException as error:
- LOGGER.error(error)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- # Check which outputlevel is defined and update the configuration object
- # accordingly.
- CONF.outputlevel = OUTPUT_LEVEL
- # youtube-dl is really a dependency but the program will run with limited
- # functionality without it so we need to check that here
- if CONF.values["youtube-dl"] == "":
- YOUTUBE_DL_PATH = subprocess.Popen(["which", "youtube-dl"],
- stdout=subprocess.PIPE)\
- .communicate()[0]
- CONF.values["youtube-dl"] = YOUTUBE_DL_PATH.strip()
- if os.access(CONF.values["youtube-dl"], os.F_OK & os.R_OK & os.X_OK):
- LOGGER.info(_("Found youtube-dl, writing it's path to the "
- "configuration file."))
- LOGGER.debug("Opening configuration file.")
- try:
- CONF.write_config()
- except stov_exceptions.ConfigFileWriteErrorException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.error(_("Could not find youtube-dl, it either does not exist, "
- "is not readable or not executable. Please note that "
- "youtube-dl is not needed for the program to run but "
- "is needed to use the download option which won't work "
- "otherwise. If youtube-dl isn't found automatically, "
- "you may also enter the path to it in the configuration"
- " file."))
- # Variable to save the text that is later sent as e-mail
- MAIL_CONTENT = []
- """Check which options are given on the command line and
- run the corresponding code
- """
- if OPTIONS.add is True:
- if OPTIONS.channel is not None and OPTIONS.searchparameter is None:
- NEW_SUBSCRIPTION = subscription.Sub(subscription_type="channel",
- name=OPTIONS.channel, conf=CONF)
- elif OPTIONS.channel is not None and OPTIONS.searchparameter is not None:
- NEW_SUBSCRIPTION = subscription.Sub(subscription_type="channel",
- name=OPTIONS.channel,
- search=OPTIONS.searchparameter,
- conf=CONF)
- elif OPTIONS.channel is None and OPTIONS.searchparameter is not None:
- NEW_SUBSCRIPTION = subscription.Sub(subscription_type="search",
- name=_("Search_"),
- search=OPTIONS.searchparameter,
- conf=CONF)
- elif OPTIONS.playlist is not None:
- if OPTIONS.searchparameter is not None:
- LOGGER.error(_("Playlists do not support searching, the search "
- "option will be ignored!"))
- NEW_SUBSCRIPTION = subscription.Sub(subscription_type="playlist",
- name=OPTIONS.playlist,
- conf=CONF)
- else:
- LOGGER.error(_("None or invalid subscription type given, please check "
- "the type option and try again."))
- sys.exit(1)
- try:
- SUBSCRIPTION_ID = DB.insert_subscription(NEW_SUBSCRIPTION.add_sub())
- NEW_SUBSCRIPTION.set_id(SUBSCRIPTION_ID)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.debug(_("Subscription sucessfully inserted into database."))
- try:
- NEW_SUBSCRIPTION.update_data()
- except stov_exceptions.YoutubeAPITimeoutException as error:
- LOGGER.error(error)
- except stov_exceptions.NoDataFromYoutubeAPIException as error:
- LOGGER.error(error)
- for video in NEW_SUBSCRIPTION.parsed_response.videos:
- if not DB.video_in_database(video.ytid):
- if NEW_SUBSCRIPTION.check_string_match(video):
- try:
- DB.insert_video(video, NEW_SUBSCRIPTION.get_id())
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.debug(_("Video %s successfully inserted into "
- "database."), video.title)
- LOGGER.info(_("New subscription ") + NEW_SUBSCRIPTION.get_title()
- + _(" successfully added"))
- elif OPTIONS.list is True:
- LIST_OF_SUBSCRIPTIONS = DB.get_subscriptions(CONF)
- SUB_STATE = None
- if len(LIST_OF_SUBSCRIPTIONS) != 0:
- LOGGER.info(_("ID Title"))
- for sub in LIST_OF_SUBSCRIPTIONS:
- if not sub.disabled:
- SUB_STATE = _("enabled")
- elif sub.disabled:
- SUB_STATE = _("disabled")
- LOGGER.info(str(sub.get_id()) + " " + sub.get_title()
- + " (%s)" % SUB_STATE)
- else:
- LOGGER.info(_("No subscriptions added yet, add one!"))
- elif OPTIONS.deleteid is not None:
- try:
- DELETE_ID = int(OPTIONS.deleteid)
- except ValueError:
- LOGGER.error(_("Invalid option, please use the ID of the subscription "
- "you want to delete as parameter for the remove "
- "option."))
- else:
- try:
- DB.delete_subscription(DELETE_ID)
- except stov_exceptions.SubscriptionNotFoundException as error:
- LOGGER.error(error)
- sys.exit(1)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.info(_("Subscription deleted successfully!"))
- elif OPTIONS.update is True:
- SUBSCRIPTIONS_LIST = DB.get_subscriptions(CONF)
- for element in SUBSCRIPTIONS_LIST:
- VIDEOS = DB.get_videos(element.get_id(), CONF)
- element.gather_videos(VIDEOS)
- try:
- element.update_data()
- except stov_exceptions.YoutubeAPITimeoutException as error:
- LOGGER.error(error)
- except stov_exceptions.NoDataFromYoutubeAPIException as error:
- LOGGER.error(error)
- for video in element.parsed_response.videos:
- if not DB.video_in_database(video.ytid):
- if element.check_string_match(video):
- try:
- DB.insert_video(video, element.get_id())
- except stov_exceptions.DBWriteAccessFailedException as \
- error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.debug(_("Video %s successfully inserted into "
- "database."), video.title)
- elif OPTIONS.download is True:
- SUBSCRIPTIONS_LIST = DB.get_subscriptions(CONF)
- LOGGER.debug(_("Trying to determine the itag value for youtube-dl from"
- " your quality and codec settings."))
- ITAG_VALUE = CONF.get_youtube_parameter()
- LOGGER.debug(_("Found value: %s."), ITAG_VALUE)
- if ITAG_VALUE == 0:
- LOGGER.debug(_("Codec and resolution could not be determined, using "
- "maximum possible value."))
- ITAG_VALUE = 38
- VIDEOS_DOWNLOADED = 0
- VIDEOS_FAILED = 0
- for element in SUBSCRIPTIONS_LIST:
- VIDEOS = DB.get_videos(element.get_id(), CONF)
- element.gather_videos(VIDEOS)
- try:
- element.download_videos(ITAG_VALUE)
- except stov_exceptions.SubscriptionDisabledException as error:
- LOGGER.debug(error)
- for entry in element.downloaded_videos:
- DB.update_video_download_status(entry.get_id(), 1)
- MAIL_CONTENT.append(entry.title)
- VIDEOS_DOWNLOADED = len(MAIL_CONTENT)
- VIDEOS_FAILED = VIDEOS_FAILED + element.failed_videos_count
- for video in element.failed_videos:
- try:
- DB.update_video_fail_count(video.failcnt, video.get_id())
- if video.failcnt >= int(CONF.values["maxfails"]):
- DB.disable_failed_video(video.get_id())
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- if VIDEOS_DOWNLOADED > 0 and CONF.values["notify"] == "yes":
- MAIL_TEXT = ""
- MSG = MIMEMultipart()
- if VIDEOS_DOWNLOADED == 1:
- MSG["Subject"] = _("Downloaded %i new video") % VIDEOS_DOWNLOADED
- MAIL_TEXT = _("The following episode has been downloaded by stov: "
- "\n\n")
- else:
- MSG["Subject"] = _("Downloaded %i new videos") % VIDEOS_DOWNLOADED
- MAIL_TEXT = _("The following episodes have been downloaded by "
- "stov: \n\n")
- MSG["From"] = "stov <%s>" % CONF.values["mailfrom"]
- MSG["To"] = "<%s>" % CONF.values["mailto"]
- for line in MAIL_CONTENT:
- MAIL_TEXT += line + "\n"
- MSG_TEXT = MIMEText(MAIL_TEXT.encode("utf8"), _charset="utf8")
- MSG.attach(MSG_TEXT)
- SERVER_CONNECTION = smtplib.SMTP()
- try:
- if sys.version_info >= (3, 0):
- SERVER_CONNECTION.connect(CONF.values["mailhost"],
- CONF.values["smtpport"])
- else:
- SERVER_CONNECTION.connect(str(CONF.values["mailhost"]),
- str(CONF.values["smtpport"]))
- except (smtplib.SMTPConnectError, smtplib.SMTPServerDisconnected,
- socket.error):
- LOGGER.error(_("Could not connect to the smtp server, please check"
- " your settings!"))
- LOGGER.error(MAIL_TEXT)
- else:
- try:
- SERVER_CONNECTION.starttls()
- except smtplib.SMTPException:
- LOGGER.debug(_("TLS not available, proceeding unencrypted."))
- if CONF.values["auth_needed"] == "yes":
- try:
- SERVER_CONNECTION.login(CONF.values["user_name"],
- CONF.values["password"])
- except smtplib.SMTPAuthenticationError:
- LOGGER.error(_("Authentication failed, please check user "
- "name and password!"))
- except smtplib.SMTPException:
- LOGGER.error(_("Could not authenticate, server probably "
- "does not support authentication!"))
- try:
- SERVER_CONNECTION.sendmail(CONF.values["mailfrom"],
- CONF.values["mailto"],
- MSG.as_string())
- except smtplib.SMTPRecipientsRefused:
- LOGGER.error(_("The server refused the recipient address, "
- "please check your settings."))
- except smtplib.SMTPSenderRefused:
- LOGGER.error(_("The server refused the sender address, "
- "please check your settings."))
- SERVER_CONNECTION.quit()
- elif VIDEOS_DOWNLOADED == 0 and VIDEOS_FAILED == 0:
- if CONF.values["notify"] == "no":
- LOGGER.info(_("There are no videos to be downloaded."))
- elif CONF.values["notify"] == "no":
- if VIDEOS_FAILED == 0:
- LOGGER.info(_("The following videos have been downloaded:\n"))
- for i in MAIL_CONTENT:
- LOGGER.info(i)
- else:
- if CONF.values["notify"] != "yes":
- LOGGER.error(_("Could not determine how you want to be informed "
- "about new videos, please check the notify "
- "parameter in your configuration."))
- elif OPTIONS.subscriptionid is not None:
- try:
- DATA = DB.get_subscription(OPTIONS.subscriptionid)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- if DATA:
- SUBSCRIPTION = subscription.Sub(subscription_id=DATA[0][0],
- title=DATA[0][1],
- subscription_type=DATA[0][2],
- name=DATA[0][3],
- search=DATA[0][4],
- directory=DATA[0][5],
- disabled=DATA[0][6], conf=CONF)
- VIDEOS = DB.get_videos(SUBSCRIPTION.get_id(), CONF)
- SUBSCRIPTION.gather_videos(VIDEOS)
- VIDEO_LIST = SUBSCRIPTION.print_videos()
- for video in VIDEO_LIST:
- LOGGER.info(video)
- else:
- LOGGER.error(_("Invalid subscription, please check the list and "
- "try again."))
- elif OPTIONS.catchup is not None:
- try:
- SUB_DATA = DB.get_subscription_title(OPTIONS.catchup)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- if SUB_DATA != []:
- try:
- DB.mark_video_downloaded(OPTIONS.catchup)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- else:
- LOGGER.error(_("The subscription could not be updated, "
- "please check if the ID given is correct."))
- elif OPTIONS.cleanup is True:
- SUBSCRIPTION_LIST = DB.get_subscriptions(CONF)
- for element in SUBSCRIPTION_LIST:
- VIDEOS = DB.get_videos(element.get_id(), CONF)
- element.check_and_delete(VIDEOS)
- for delete_video in element.ToDelete:
- LOGGER.debug(_("Deleting video %s from "
- "database"), delete_video.title)
- try:
- DB.delete_video(delete_video.get_id())
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- try:
- DB.vacuum()
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- elif OPTIONS.enableid is not None:
- SUBSCRIPTION_STATE = DB.get_subscription(OPTIONS.enableid)
- try:
- if int(SUBSCRIPTION_STATE[0][6]) == 0:
- LOGGER.error(_("The subscription ID %s is already enabled."),
- OPTIONS.enableid)
- elif int(SUBSCRIPTION_STATE[0][6]) == 1:
- try:
- DB.change_subscription_state(OPTIONS.enableid, 0)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.info(_("Enabled subscription ID %s."), OPTIONS.enableid)
- except IndexError:
- LOGGER.error(_("Could not find the subscription with ID %s, "
- "please check and try again."), OPTIONS.enableid)
- elif OPTIONS.disableid is not None:
- SUBSCRIPTION_STATE = DB.get_subscription(OPTIONS.disableid)
- try:
- if int(SUBSCRIPTION_STATE[0][6]) == 1:
- LOGGER.error(_("Subscription ID %s is already disabled."),
- OPTIONS.disableid)
- elif int(SUBSCRIPTION_STATE[0][6]) == 0:
- try:
- DB.change_subscription_state(OPTIONS.disableid, 1)
- except stov_exceptions.DBWriteAccessFailedException as error:
- LOGGER.error(error)
- sys.exit(1)
- else:
- LOGGER.info(_("Disabled subscription ID %s."),
- OPTIONS.disableid)
- except IndexError:
- LOGGER.error(_("Could not find the subscription with ID %s, please"
- " check and try again."), OPTIONS.disableid)
- elif OPTIONS.license is True:
- LOGGER.info("""
- 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/>.""")
- elif OPTIONS.version is True:
- LOGGER.info("0.9.3")
- else:
- PARSER.print_help()
- # Remove the lock file and end the program so it can be run again
- try:
- os.remove("/tmp/stov.lock")
- sys.exit(0)
- except os.error:
- LOGGER.error(_("Could not delete the lock file. Please check what "
- "went wrong and clean up manually!"))
- sys.exit(1)
|