subscription.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #
  2. # This file is part of stov, written by Helmut Pozimski 2012-2014.
  3. #
  4. # stov is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, version 2 of the License.
  7. #
  8. # stov is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with stov. If not, see <http://www.gnu.org/licenses/>.
  15. # -*- coding: utf8 -*-
  16. from __future__ import unicode_literals
  17. import sys
  18. import ssl
  19. if sys.version_info >= (3,):
  20. import urllib.request as urllib2
  21. else:
  22. import urllib2
  23. from lib_stov import youtubeAPI
  24. from lib_stov import youtube
  25. from lib_stov import stov_exceptions
  26. class sub(object):
  27. def __init__(self, type, name, conf, search="", id=0, title="", directory="",
  28. disabled=0):
  29. self.__ID = id
  30. self.__title = title
  31. self.__type = type
  32. self.__name = name
  33. self.__search = search
  34. self.__directory = directory
  35. self.__APIURL = ""
  36. self.__conf = conf
  37. self.DownloadedVideos = []
  38. self.FailedVideosCount = 0
  39. self.FailedVideos = []
  40. self.ToDelete = []
  41. self.__video_list = []
  42. self.parsed_response = None
  43. self.__id_list = []
  44. if int(disabled) == 0:
  45. self.__disabled = False
  46. elif int(disabled) == 1:
  47. self.__disabled = True
  48. self.__ConstructAPIURL()
  49. def GetTitle(self):
  50. return self.__title
  51. def GetId(self):
  52. return self.__ID
  53. def SetID(self, id):
  54. self.__ID = id
  55. def CheckStringMatch(self, video):
  56. """Checks if the subscription is enabled and the video matches the
  57. search string defined for the subscription"""
  58. if self.__disabled is False:
  59. if self.__search != "" and self.__conf.values["check_title"] == "yes":
  60. if self.__search in video.title:
  61. return True
  62. else:
  63. return False
  64. else:
  65. return True
  66. else:
  67. return False
  68. def GatherVideos(self, video_data):
  69. """Gathers all videos in the subscription and saves
  70. them in an the internal list so they can be accessed by the object
  71. """
  72. for i in video_data:
  73. self.__video_list.append(youtube.video(id=i[0],
  74. title=i[1], description=i[2], ytid=i[3],
  75. downloaded=i[4], failcount=i[5], conf=self.__conf))
  76. def DownloadVideos(self, itag_value):
  77. """Uses the DownloadVideo method of the video object to download all
  78. videos contained in the subscription and adds them to the list of
  79. downloaded videos if the download succeeds.
  80. """
  81. if self.__disabled is False:
  82. for video in self.__video_list:
  83. if video.downloaded == 0:
  84. if video.DownloadVideo(self.__directory, itag_value) is True:
  85. self.DownloadedVideos.append(video)
  86. else:
  87. self.FailedVideosCount = self.FailedVideosCount + 1
  88. self.FailedVideos.append(video)
  89. else:
  90. raise stov_exceptions.SubscriptionDisabledException(self.__title)
  91. def PrintVideos(self):
  92. """Prepares a human readable list of all videos contained
  93. in the subscription.
  94. """
  95. for i in self.__video_list:
  96. video_list = []
  97. if i.downloaded == 0:
  98. video_list.append(i.title + _(" (pending)"))
  99. elif i.downloaded == 1:
  100. video_list.append(i.title + _(" (downloaded)"))
  101. elif i.downloaded == -1:
  102. video_list.append(i.title + _(" (failed)"))
  103. return video_list
  104. def AddSub(self):
  105. """Adds a new subscription to the database"""
  106. self.ParseAPIData()
  107. self.__title = self.parsed_response.title
  108. self.__directory = self.__name + "_" + self.__search.replace(" ", "_")
  109. data = (self.__title, self.__type, self.__search, self.__directory,
  110. self.__name, 0)
  111. return data
  112. def ParseAPIData(self):
  113. """Retrieves the youtube API data and parses them so they can be used
  114. by the object
  115. """
  116. try:
  117. self.__ConnectAPI = urllib2.urlopen(self.__APIURL, timeout=30)
  118. self.__APIResponse = self.__ConnectAPI.read()
  119. self.__ConnectAPI.close()
  120. except urllib2.HTTPError:
  121. raise stov_exceptions.NoDataFromYoutubeAPIException()
  122. except ssl.SSLError:
  123. raise stov_exceptions.YoutubeAPITimeoutException(self.__title)
  124. else:
  125. parser = youtubeAPI.Parser(self.__APIResponse)
  126. self.parsed_response = parser.parse()
  127. def __ConstructAPIURL(self):
  128. """Constructs the API URL which is used to retrieve API data"""
  129. if self.__type == "channel":
  130. self.__APIURL = "https://gdata.youtube.com/feeds/api/users/" \
  131. + urllib2.quote(self.__name) + "/uploads/" + "?v=2" \
  132. + "&max-results=%s" % self.__conf.values["maxvideos"]
  133. if self.__search != "":
  134. self.__APIURL = self.__APIURL + "&q=" + "%22" \
  135. + urllib2.quote(self.__search) + "%22"
  136. elif self.__type == "search":
  137. self.__APIURL = "http://gdata.youtube.com/feeds/api/videos?q=" \
  138. + urllib2.quote(self.__search) + "&v=2" \
  139. + "&max-results=%s" % self.__conf.values["maxvideos"]
  140. elif self.__type == "playlist":
  141. self.__APIURL = "https://gdata.youtube.com/feeds/api/playlists/" \
  142. + "%20" + urllib2.quote(self.__name) + "%20" + "?v=2" \
  143. + "&max-results=%s" % self.__conf.values["maxvideos"]
  144. def CheckAndDelete(self, videos):
  145. """Checks if a video still exists in the current API response and deletes
  146. it if it doesn't
  147. """
  148. self.ParseAPIData()
  149. self.GatherVideos(videos)
  150. for entry in self.parsed_response.videos:
  151. self.__id_list.append(entry.ytid)
  152. for item in self.__video_list:
  153. if item.ytid not in self.__id_list:
  154. self.ToDelete.append(item)