123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- #! /usr/bin/env python
- # -*- coding: utf8 -*-
- #stov - a program to subscribe to channels and users from youtube
- # and download the videos automatically
- #
- # written by Helmut Pozimski 2012-2014
- #
- # 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.
- from __future__ import unicode_literals
- from __future__ import print_function
- 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:
- if sys.version_info >= (3, 0):
- trans.install()
- else:
- trans.install(unicode=True)
- """Define a handler for signals sent to the program"""
- def sighandler(signum, frame):
- 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):
- 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()
- """Process the given options and parameters,
- add: Add a new subscription (which can be a search, channel or
- playlist)
- channel: with add, specify the name of the channel or user
- lssubs: List the currently available subscriptions
- remove: remove a subscription
- update: update the information about the available videos
- download: download all available videos which haven't already been
- downloaded
- search: optionally add a search string to a new subscription or
- create a search subscription with add
- playlist: with add, subscribe to a youtube playlist
- catchup: Mark all videos in a subscription as downloaded
- version: Print version number
- quiet: Suppress all output
- verbose: Print normal output + diagnostical messages
- clean-database: Clean the database of old entries, meaning videos that
- are no longer present in the current API response of youtube
- enable: enables a previously disabled subscription
- disable: disables a previously enabled subscription
- """
- 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)
- """Variable to determine if the exit code should be success or not"""
- exit_status = True
- """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:
- outputlevel = "verbose"
- logger.setLevel(logging.DEBUG)
- elif options.quiet is True:
- outputlevel = "quiet"
- logger.setLevel(logging.ERROR)
- else:
- outputlevel = "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:
- lockfile = 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)
- oldpid = lockfile.read().strip()
- if os.access("/proc/" + oldpid, 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)
- lockfile.close()
- if os.access("/proc/" + oldpid, 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:
- lockfile = open("/tmp/stov.lock", "w")
- lockfile.write(str(os.getpid()))
- lockfile.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()
- if sys.version_info >= (3, 0):
- temp_input = input()
- else:
- # noinspection PyCompatibility
- temp_input = raw_input()
- if temp_input == "yes":
- conf.assist()
- try:
- conf.Initialize()
- except stov_exceptions.ConfigFileWriteErrorException as e:
- logger.error(e)
- 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 e:
- logger.error(e)
- except stov_exceptions.ConfigFileWriteErrorException as e:
- logger.error(e)
- 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.CheckConfig()
- except stov_exceptions.ConfigFileReadErrorException as e:
- logger.error(e)
- sys.exit(1)
- except stov_exceptions.InvalidConfigurationVersionException as e:
- logger.error(e)
- sys.exit(1)
- else:
- if check_result is not True:
- logger.info(_("Your configuration needs to be updated, performing"
- " update now."))
- try:
- conf.UpdateConfig()
- except stov_exceptions.ConfigFileReadErrorException as e:
- logger.error(e)
- sys.exit(1)
- except stov_exceptions.ConfigFileWriteErrorException as e:
- logger.error(e)
- 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 e:
- logger.error(e)
- sys.exit(1)
- else:
- try:
- db = database.db(path=conf.dbpath, version=conf.values["db_version"])
- except stov_exceptions.DBConnectionFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- try:
- db.Populate()
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- logger.debug(_("Created initial database tables."))
- try:
- logger.debug(_("Comparing current and running database version."))
- if conf.CheckDB() is not True:
- logger.info(_("Your database needs to be updated, performing"
- " update now."))
- db.Update()
- conf.values["db_version"] = db.GetVersion()
- logger.debug("Opening configuration file.")
- try:
- conf.WriteConfig()
- except stov_exceptions.ConfigFileWriteErrorException as e:
- logger.error(e)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- """Check which outputlevel is defined and update the configuration object
- accordingly.
- """
- conf.outputlevel = outputlevel
- """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.WriteConfig()
- except stov_exceptions.ConfigFileWriteErrorException as e:
- logger.error(e)
- 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"""
- mailcontent = []
- """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:
- NewSubscription = subscription.sub(type="channel",
- name=options.channel, conf=conf)
- elif options.channel is not None and options.searchparameter is not None:
- NewSubscription = subscription.sub(type="channel",
- name=options.channel,
- search=options.searchparameter,
- conf=conf)
- elif options.channel is None and options.searchparameter is not None:
- NewSubscription = subscription.sub(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!"))
- NewSubscription = subscription.sub(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:
- id = db.InsertSubscription(NewSubscription.AddSub())
- NewSubscription.SetID(id)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- logger.debug(_("Subscription sucessfully inserted into database."))
- try:
- NewSubscription.update_data()
- except stov_exceptions.YoutubeAPITimeoutException as e:
- logger.error(e)
- except stov_exceptions.NoDataFromYoutubeAPIException as e:
- logger.error(e)
- for video in NewSubscription.parsed_response.videos:
- if not db.VideoInDatabase(video.ytid):
- if NewSubscription.CheckStringMatch(video):
- try:
- db.InsertVideo(video, NewSubscription.GetId())
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- logger.debug(_("Video %s successfully inserted into "
- "database.") % video.title)
- logger.info(_("New subscription ") + NewSubscription.GetTitle()
- + _(" successfully added"))
- elif options.list is True:
- Listofsubscriptions = db.GetSubscriptions(conf)
- sub_state = None
- if len(Listofsubscriptions) != 0:
- logger.info(_("ID Title"))
- for sub in Listofsubscriptions:
- if not sub.disabled:
- sub_state = _("enabled")
- elif sub.disabled:
- sub_state = _("disabled")
- logger.info(str(sub.GetId()) + " " + sub.GetTitle()
- + " (%s)" % sub_state)
- else:
- logger.info(_("No subscriptions added yet, add one!"))
- elif options.deleteid is not None:
- try:
- DeleteID = 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.DeleteSubscription(DeleteID)
- except stov_exceptions.SubscriptionNotFoundException as e:
- logger.error(e)
- sys.exit(1)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- logger.info(_("Subscription deleted successfully!"))
- elif options.update is True:
- listofsubscriptions = db.GetSubscriptions(conf)
- for element in listofsubscriptions:
- try:
- element.update_data()
- except stov_exceptions.YoutubeAPITimeoutException as e:
- logger.error(e)
- except stov_exceptions.NoDataFromYoutubeAPIException as e:
- logger.error(e)
- for video in element.parsed_response.videos:
- if not db.VideoInDatabase(video.ytid):
- if element.CheckStringMatch(video):
- try:
- db.InsertVideo(video, element.GetId())
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- logger.debug(_("Video %s successfully inserted into "
- "database.") % video.title)
- elif options.download is True:
- listofsubscriptions = db.GetSubscriptions(conf)
- logger.debug(_("Trying to determine the itag value for youtube-dl from"
- " your quality and codec settings."))
- itag_value = conf.GetYoutubeParameter()
- 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
- videosdownloaded = 0
- videosfailed = 0
- for element in listofsubscriptions:
- videos = db.GetVideos(element.GetId(), conf)
- element.GatherVideos(videos)
- try:
- element.DownloadVideos(itag_value)
- except stov_exceptions.SubscriptionDisabledException as e:
- logger.debug(e)
- for entry in element.DownloadedVideos:
- db.UpdateVideoDownloadStatus(entry.GetID(), 1)
- mailcontent.append(entry.title)
- videosdownloaded = len(mailcontent)
- videosfailed = videosfailed + element.FailedVideosCount
- for video in element.FailedVideos:
- try:
- db.UpdateVideoFailCount(video.failcnt, video.GetID())
- if video.failcnt >= int(conf.values["maxfails"]):
- db.DisableFailedVideo(video.GetID())
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- if videosdownloaded > 0 and conf.values["notify"] == "yes":
- MailText = ""
- msg = MIMEMultipart()
- if videosdownloaded == 1:
- msg["Subject"] = _("Downloaded %i new video") % videosdownloaded
- MailText = _("The following episode has been downloaded by stov: "
- "\n\n")
- else:
- msg["Subject"] = _("Downloaded %i new videos") % videosdownloaded
- MailText = _("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 mailcontent:
- MailText += line + "\n"
- msgtext = MIMEText(MailText.encode("utf8"), _charset="utf8")
- msg.attach(msgtext)
- serverconnection = smtplib.SMTP()
- try:
- if sys.version_info >= (3, 0):
- serverconnection.connect(conf.values["mailhost"],
- conf.values["smtpport"])
- else:
- serverconnection.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(MailText)
- else:
- try:
- serverconnection.starttls()
- except smtplib.SMTPException:
- logger.debug(_("TLS not available, proceeding unencrypted."))
- if conf.values["auth_needed"] == "yes":
- try:
- serverconnection.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:
- serverconnection.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."))
- serverconnection.quit()
- elif videosdownloaded == 0 and videosfailed == 0:
- if conf.values["notify"] == "no":
- logger.info(_("There are no videos to be downloaded."))
- elif conf.values["notify"] == "no":
- if videosfailed == 0:
- logger.info(_("The following videos have been downloaded:\n"))
- for i in mailcontent:
- 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.GetSubscription(options.subscriptionid)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- if Data:
- Subscription = subscription.sub(id=Data[0][0], title=Data[0][1],
- type=Data[0][2], name=Data[0][3],
- search=Data[0][4],
- directory=Data[0][5],
- disabled=Data[0][6], conf=conf)
- videos = db.GetVideos(Subscription.GetId(), conf)
- Subscription.GatherVideos(videos)
- video_list = Subscription.PrintVideos()
- 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.GetSubscriptionTitle(options.catchup)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- else:
- if sub_data != []:
- try:
- db.MarkVideosDownloaded(options.catchup)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- else:
- logger.error(_("The subscription could not be updated, "
- "please check if the ID given is correct."))
- elif options.cleanup is True:
- subscriptions_list = db.GetSubscriptions(conf)
- for element in subscriptions_list:
- videos = db.GetVideos(element.GetId(), conf)
- element.CheckAndDelete(videos)
- for delete_video in element.ToDelete:
- logger.debug(_("Deleting video %s from "
- "database") % delete_video.title)
- try:
- db.DeleteVideo(delete_video.GetID())
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- try:
- db.Vacuum()
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- sys.exit(1)
- elif options.enableid is not None:
- subscription_state = db.GetSubscription(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.ChangeSubscriptionState(options.enableid, 0)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- 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.GetSubscription(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.ChangeSubscriptionState(options.disableid, 1)
- except stov_exceptions.DBWriteAccessFailedException as e:
- logger.error(e)
- 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-wip")
- else:
- parser.print_help()
- """Remove the lock file and end the program so it can be run again"""
- try:
- os.remove("/tmp/stov.lock")
- if exit_status is True:
- sys.exit(0)
- else:
- sys.exit(1)
- except os.error:
- logger.error(_("Could not delete the lock file. Please check what "
- "went wrong and clean up manually!"))
|