123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- #
- # This file is part of stov, written by Helmut Pozimski 2012-2014.
- #
- # 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 -*-
- from __future__ import unicode_literals
- import sys
- import gettext
- import sqlite3
- import ssl
- if sys.version_info >= (3,):
- import urllib.request as urllib2
- else:
- import urllib2
- from lib_stov import youtubeAPI
- from lib_stov import youtube
- from lib_stov.outputhelper import printf
- class sub(object):
- def __init__(self, type, name, conf, search="", id=0, title="", directory="",
- disabled=0):
- self.__ID = id
- self.__title = title
- self.__type = type
- self.__name = name
- self.__search = search
- self.__directory = directory
- self.__APIURL = ""
- self.__conf = conf
- self.DownloadedVideos = []
- self.FailedVideos = 0
- if int(disabled) == 0:
- self.__disabled = False
- elif int(disabled) == 1:
- self.__disabled = True
- if self.__name != "delete":
- self.__ConstructAPIURL()
- def GetTitle(self):
- return self.__title
- def Delete(self):
- """Deletes all videos from the subscription from the database and deletes
- the subscription itself once it's done.
- """
- try:
- self.__connection = sqlite3.connect(self.__conf.dbpath)
- except sqlite3.OperationalError:
- printf(_("Could not write to database, subscription "
- "was NOT deleted. Please check permissions and try again."),
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- else:
- self.__cursor = self.__connection.cursor()
- self.__checkquery = "SELECT * FROM subscriptions WHERE id=?"
- self.__checkresult = self.__cursor.execute(self.__checkquery, (self.__ID,))
- if self.__checkresult.fetchall() == []:
- printf(_("The subscription could not be found and was therefore "
- "not deleted"), outputlevel="default", level=self.__conf.outputlevel,
- descriptor="stderr")
- self.__connection.close()
- return False
- else:
- self.__deletevideos = "DELETE FROM videos WHERE subscription_id=?"
- self.__cursor.execute(self.__deletevideos, (self.__ID,))
- self.__deletesubscription = "DELETE FROM subscriptions WHERE id=?"
- self.__cursor.execute(self.__deletesubscription, (self.__ID,))
- self.__connection.commit()
- self.__connection.close()
- printf(_("Subscription deleted successfully!"), outputlevel="default",
- level=self.__conf.outputlevel, descriptor="stdout")
- return True
- def UpdateVideos(self):
- """Retrieves the current videos from the youtube API and adds them
- to the database if they where not already added earlier
- """
- if self.__disabled is False:
- if self.__ParseAPIData() is True:
- self.__processed = []
- try:
- self.__connection = sqlite3.connect(self.__conf.dbpath)
- self.__cursor = self.__connection.cursor()
- except sqlite3.OperationalError:
- printf(_("Could not write to database, "
- "new video was NOT added! Please check permissions and try again."),
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- for i in self.__ParsedResponse.videos:
- printf(_('Checking if video "%s" exists in the database') % i.title,
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__ytid = i.ytid
- if self.__search != "" and self.__conf.values["check_title"] == "yes":
- if self.__search not in i.title:
- printf(_("You have requested title checking and the title of the video "
- "does not match with the search string, ignoring it"),
- outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stderr")
- continue
- self.__videoquery = "SELECT id FROM videos WHERE ytid=?"
- self.__cursor.execute(self.__videoquery, (self.__ytid,))
- self.__tmpid = self.__cursor.fetchall()
- if self.__tmpid == []:
- printf(_("Video %s not found in database, inserting...") % i.title,
- outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stderr")
- self.__query = "INSERT INTO videos (title, description, \
- ytid, subscription_id, downloaded) VALUES (?, ?, ?, ?, ?)"
- self.__data = (i.title, i.description, self.__ytid, self.__ID, 0)
- self.__cursor.execute(self.__query, self.__data)
- self.__connection.commit()
- self.__connection.close()
- else:
- printf(_("Subscription %s is disabled, it will not be updated")
- % self.__title, outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stderr")
- def GetVideos(self):
- """Retrieves all videos in the subscription from the database and saves
- them in an the internal list so they can be accessed by the object
- """
- self.__videos = []
- try:
- self.__connection = sqlite3.connect(self.__conf.dbpath)
- self.__cursor = self.__connection.cursor()
- except sqlite3.OperationalError:
- printf(_("Could not access database. "
- "Please check permissions and try again."),
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- printf(_("Getting all videos for subscription %s from database")
- % self.__title, outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stderr")
- self.__videoquerybysubscription = "SELECT id, title, description, \
- ytid, downloaded, failcnt FROM videos WHERE subscription_id=?"
- self.__cursor.execute(self.__videoquerybysubscription, (self.__ID,))
- self.__videodata = self.__cursor.fetchall()
- for i in self.__videodata:
- printf(_("Got video %s") % i[1],
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__videos.append(youtube.video(id=i[0],
- title=i[1], description=i[2], ytid=i[3],
- downloaded=i[4], failcount=i[5], conf=self.__conf))
- self.__connection.close()
- def DownloadVideos(self, itag_value):
- """Uses the DownloadVideo method of the video object to download all
- videos contained in the subscription and adds them to the list of
- downloaded videos if the download succeeds.
- """
- if self.__disabled is False:
- for video in self.__videos:
- if video.downloaded == 0:
- if video.DownloadVideo(self.__directory, itag_value) is True:
- self.DownloadedVideos.append(video.title)
- else:
- self.FailedVideos = self.FailedVideos + 1
- else:
- printf(_("Subscription %s is disabled, videos will not be downloaded")
- % self.__title, outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stderr")
- """Prints a list of all videos contained in the subscription"""
- def PrintVideos(self):
- printf(_("Videos in subscription ") + self.__title + ":\n",
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stdout")
- for i in self.__videos:
- if i.downloaded == 0:
- printf(i.title + _(" (pending)"), outputlevel="default",
- level=self.__conf.outputlevel, descriptor="stdout")
- elif i.downloaded == 1:
- printf(i.title + _(" (downloaded)"), outputlevel="default",
- level=self.__conf.outputlevel, descriptor="stdout")
- elif i.downloaded == -1:
- printf(i.title + _(" (failed)"), outputlevel="default",
- level=self.__conf.outputlevel, descriptor="stdout")
- def AddSub(self):
- """Adds a new subscription to the database"""
- if self.__ParseAPIData() is True:
- try:
- self.__connection = sqlite3.connect(self.__conf.dbpath)
- except sqlite3.OperationalError:
- printf(_("Could not write to database, new "
- "subscription was NOT added! Please check permissions and try again."),
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- else:
- self.__cursor = self.__connection.cursor()
- self.__title = self.__ParsedResponse.title
- printf(_("Found subscription title %s") % self.__title,
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__directory = self.__name + "_" + self.__search.replace(" ", "_")
- printf(_("Directory: %s") % self.__directory,
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__query = "INSERT INTO subscriptions (title, type, searchstring, \
- directory, name, disabled) VALUES (?, ?, ?, ?, ?, ?)"
- self.__data = (self.__title, self.__type, self.__search,
- self.__directory, self.__name, 0)
- printf(_("Writing subscription info into database..."),
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__cursor.execute(self.__query, self.__data)
- self.__connection.commit()
- self.__query = "SELECT id from subscriptions where title=?"
- self.__data = (self.__title, )
- self.__cursor.execute(self.__query, self.__data)
- self.__ID = self.__cursor.fetchone()
- self.__ID = self.__ID[0]
- printf(_("Subscription got internal ID %s") % self.__ID,
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__connection.close()
- return True
- else:
- return False
- def __ParseAPIData(self):
- """Retrieves the youtube API data and parses them so they can be used
- by the object
- """
- try:
- printf(_("Updating subscription %s") % self.__name,
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- printf(_("Connectiong to youtube API."),
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__ConnectAPI = urllib2.urlopen(self.__APIURL, timeout=30)
- printf(_("Connection established, reading data."),
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- self.__APIResponse = self.__ConnectAPI.read()
- self.__ConnectAPI.close()
- except urllib2.HTTPError:
- printf(_("Could not get API data, maybe the API "
- "is down or you have given wrong parameters"
- ", please check and try again!"),
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- return False
- except ssl.SSLError:
- printf(_("The API Request timed out for subscription %s, "
- "please try again later") % self.__title,
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- return False
- else:
- printf(_("Parsing youtube API response."),
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- parser = youtubeAPI.Parser(self.__APIResponse)
- self.__ParsedResponse = parser.parse()
- return True
- def __ConstructAPIURL(self):
- """Constructs the API URL which is used to retrieve API data"""
- if self.__type == "channel":
- self.__APIURL = "https://gdata.youtube.com/feeds/api/users/"\
- + urllib2.quote(self.__name) + "/uploads/" + "?v=2"\
- + "&max-results=%s" % self.__conf.values["maxvideos"]
- if self.__search != "":
- self.__APIURL = self.__APIURL + "&q=" + "%22"\
- + urllib2.quote(self.__search) + "%22"
- elif self.__type == "search":
- self.__APIURL = "http://gdata.youtube.com/feeds/api/videos?q="\
- + urllib2.quote(self.__search) + "&v=2"\
- + "&max-results=%s" % self.__conf.values["maxvideos"]
- elif self.__type == "playlist":
- self.__APIURL = "https://gdata.youtube.com/feeds/api/playlists/"\
- + "%20" + urllib2.quote(self.__name) + "%20" + "?v=2"\
- + "&max-results=%s" % self.__conf.values["maxvideos"]
- else:
- printf(_("None or invalid subscription type given, "
- "please check the type option and try again"),
- outputlevel="default", level=self.__conf.outputlevel, descriptor="stderr")
- printf(_("Constructed the following API URL: %s") % self.__APIURL,
- outputlevel="verbose", level=self.__conf.outputlevel, descriptor="stderr")
- def CheckAndDelete(self):
- """Checks if a video still exists in the current API response and deletes
- it if it doesn't
- """
- self.__ParseAPIData()
- self.GetVideos()
- self.__id_list = []
- for entry in self.__ParsedResponse.videos:
- self.__id_list.append(entry.ytid)
- for item in self.__videos:
- if item.ytid not in self.__id_list:
- if item.delete() is True:
- printf(_("Video %s deleted from the database!") % item.title,
- outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stdout")
- else:
- printf(_("Videos %s could not be deleted from the database"),
- outputlevel="verbose", level=self.__conf.outputlevel,
- descriptor="stderr")
|