浏览代码

Add switch to clean the database of old entries

Helmut Pozimski 11 年之前
父节点
当前提交
5553be395a
共有 6 个文件被更改,包括 79 次插入6 次删除
  1. 3 2
      CHANGELOG
  2. 0 1
      TODO
  3. 1 1
      outputhelper.py
  4. 39 2
      stov.py
  5. 20 0
      subscription.py
  6. 16 0
      youtube.py

+ 3 - 2
CHANGELOG

@@ -2,14 +2,15 @@
 ----
 * Added smtp authentication
 * Added notify option
+* Added "verbose" and "quiet" output modes
+* Added switch to clean the database of old video entries
 * Changed --lsvids to print the download status
-* Fixed error message printed when youtube-dl fails
 * Made the youtube-dl output shown to the user depend on the defined output level
 * Now uses youtube API version 2
 * Fixed situation when all videos fail and the output would have suggested there were no videos to be downloaded
 * Fixed a bug that lead to a duplicate subscription when a playlist was added
+* Fixed error message printed when youtube-dl fails
 * Improved output behaviour so strings will be properly encoded
-* Added "verbose" and "quiet" output modes
 
 0.2
 ----

+ 0 - 1
TODO

@@ -7,4 +7,3 @@ Long term goals:
 * Implement maxvids option
 * Improve handling of situations where a video is permanently unavailable
 * Add verbose output
-* Add option to clean database of old entries 

+ 1 - 1
outputhelper.py

@@ -33,7 +33,7 @@ def printf(string, outputlevel, descriptor="stdout", level="default"):
 			else:
 				print str(string)
 		elif level == "verbose":
-			if string is unicode:
+			if isinstance(string, unicode):
 				print string.encode("utf8")
 			elif string is str:
 				print string

+ 39 - 2
stov.py

@@ -93,6 +93,8 @@ class MyOptionParser(OptionParser):
 		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
 """
 
 parser = MyOptionParser(usage=_("Usage: %prog [options]"), prog="stov",
@@ -129,6 +131,9 @@ 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"))
 (options, arguments) = parser.parse_args()
 
 """Check if stov is run directly from command line since it shouldn't be
@@ -422,8 +427,9 @@ FROM subscriptions")
 						level=conf.outputlevel, descriptor="stderr")
 		serverconnection.quit()
 	elif videosdownloaded == 0 and videosfailed == 0:
-		printf(_("No videos to be downloaded."), outputlevel="default",
-			level=conf.outputlevel, descriptor="stdout")
+		if conf.values["notify"] == "no":
+			printf(_("No videos to be downloaded."), outputlevel="default",
+				level=conf.outputlevel, descriptor="stdout")
 	elif conf.values["notify"] == "no":
 		if videosfailed == 0:
 			printf(_("The following videos have been downloaded:\n"),
@@ -482,6 +488,37 @@ elif options.catchup is not None:
 						outputlevel="default", level=conf.outputlevel, descriptor="stderr")
 
 
+elif options.cleanup is True:
+	subscriptions_list = []
+	try:
+		database = sqlite3.connect(conf.dbpath)
+		cursor = database.cursor()
+	except sqlite3.OperationalError:
+		printf(_("Could not access the database, please check path and "
+			"permissions and try again!"), outputlevel="default",
+			level=conf.outputlevel, descriptor="stderr")
+	else:
+		cursor.execute("SELECT id,title,type,name,searchstring,directory \
+		FROM subscriptions")
+		subscriptions = cursor.fetchall()
+		database.close()
+	for element in subscriptions:
+		subscriptions_list.append(subscription.sub(id=element[0],
+		title=element[1], type=element[2], name=element[3],
+		search=element[4], directory=element[5], conf=conf))
+	for element in subscriptions_list:
+		element.CheckAndDelete()	
+	try:
+		database = sqlite3.connect(conf.dbpath)
+		cursor = database.cursor()
+	except sqlite3.OperationalError:
+		printf(_("Could not access the database, please check path and "
+			"permissions and try again!"), outputlevel="default",
+			level=conf.outputlevel, descriptor="stderr")
+	else:
+		cursor.execute("VACUUM")
+		database.close()
+
 elif options.license is True:
 	printf( """
 	stov is free software: you can redistribute it and/or modify

+ 20 - 0
subscription.py

@@ -212,3 +212,23 @@ class sub(object):
 			printf(_("None or invalid subscription type given, "
 						"please check the type option and try again"),
 				outputlevel="default", 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="default", level=self.__conf.outputlevel,
+					descriptor="stderr")

+ 16 - 0
youtube.py

@@ -84,3 +84,19 @@ and can't be created. Please check your configuration and try again"),
 
 	def AssignDBID(self, id):
 		self.__ID = id
+
+	def delete(self):
+		try:
+			self.__database = sqlite3.connect(self.__conf.dbpath)
+		except sqlite3.OperationalError:
+			printf(_("Could not connect to the database, please check settings and"
+				 "permissions and try again"), outputlevel="default",
+				level=self.__conf.outputlevel, descriptor="stderr")
+			return False
+		else:
+			self.__cursor = self.__database.cursor()
+			self.__statement = "DELETE FROM videos where id = ?"
+			self.__cursor.execute(self.__statement, (self.__ID,))
+			self.__database.commit()
+			self.__database.close()
+			return True