PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Coherence-0.6.6.2/coherence/backends/miroguide_storage.py

#
Python | 248 lines | 182 code | 52 blank | 14 comment | 18 complexity | 165a30e08a6f245dcb10f246ee1314fe MD5 | raw file
  1. # Licensed under the MIT license
  2. # http://opensource.org/licenses/mit-license.php
  3. # Coherence backend presenting the content of the MIRO Guide catalog for on-line videos
  4. #
  5. # The APi is described on page:
  6. # https://develop.participatoryculture.org/trac/democracy/wiki/MiroGuideApi
  7. # Copyright 2009, Jean-Michel Sizun
  8. # Copyright 2009 Frank Scholz <coherence@beebits.net>
  9. import urllib
  10. from coherence.upnp.core import utils
  11. from coherence.upnp.core import DIDLLite
  12. from coherence.backend import BackendStore, BackendItem, Container, LazyContainer, \
  13. AbstractBackendStore
  14. from coherence.backends.youtube_storage import TestVideoProxy
  15. class VideoItem(BackendItem):
  16. def __init__(self, name, description, url, thumbnail_url, store):
  17. self.name = name
  18. self.duration = None
  19. self.size = None
  20. self.mimetype = "video"
  21. self.url = None
  22. self.video_url = url
  23. self.thumbnail_url = thumbnail_url
  24. self.description = description
  25. self.date = None
  26. self.item = None
  27. self.location = TestVideoProxy(self.video_url, hash(self.video_url),
  28. store.proxy_mode,
  29. store.cache_directory, store.cache_maxsize,store.buffer_size
  30. )
  31. def get_item(self):
  32. if self.item == None:
  33. upnp_id = self.get_id()
  34. upnp_parent_id = self.parent.get_id()
  35. self.item = DIDLLite.VideoItem(upnp_id, upnp_parent_id, self.name)
  36. self.item.description = self.description
  37. self.item.date = self.date
  38. if self.thumbnail_url is not None:
  39. self.item.icon = self.thumbnail_url
  40. self.item.albumArtURI = self.thumbnail_url
  41. res = DIDLLite.Resource(self.url, 'http-get:*:%s:*' % self.mimetype)
  42. res.duration = self.duration
  43. res.size = self.size
  44. self.item.res.append(res)
  45. return self.item
  46. def get_path(self):
  47. return self.url
  48. def get_id(self):
  49. return self.storage_id
  50. class MiroGuideStore(AbstractBackendStore):
  51. logCategory = 'miroguide_store'
  52. implements = ['MediaServer']
  53. description = ('Miro Guide', 'connects to the MIRO Guide service and exposes the podcasts catalogued by the service. ', None)
  54. options = [{'option':'name', 'text':'Server Name:', 'type':'string','default':'my media','help': 'the name under this MediaServer shall show up with on other UPnP clients'},
  55. {'option':'version','text':'UPnP Version:','type':'int','default':2,'enum': (2,1),'help': 'the highest UPnP version this MediaServer shall support','level':'advance'},
  56. {'option':'uuid','text':'UUID Identifier:','type':'string','help':'the unique (UPnP) identifier for this MediaServer, usually automatically set','level':'advance'},
  57. {'option':'language','text':'Language:','type':'string', 'default':'English'},
  58. {'option':'refresh','text':'Refresh period','type':'string'},
  59. {'option':'proxy_mode','text':'Proxy mode:','type':'string', 'enum': ('redirect','proxy','cache','buffered')},
  60. {'option':'buffer_size','text':'Buffering size:','type':'int'},
  61. {'option':'cache_directory','text':'Cache directory:','type':'dir', 'group':'Cache'},
  62. {'option':'cache_maxsize','text':'Cache max size:','type':'int', 'group':'Cache'},
  63. ]
  64. def __init__(self, server, **kwargs):
  65. AbstractBackendStore.__init__(self, server, **kwargs)
  66. self.name = kwargs.get('name','MiroGuide')
  67. self.language = kwargs.get('language','English')
  68. self.refresh = int(kwargs.get('refresh',60))*60
  69. self.proxy_mode = kwargs.get('proxy_mode', 'redirect')
  70. self.cache_directory = kwargs.get('cache_directory', '/tmp/coherence-cache')
  71. try:
  72. if self.proxy_mode != 'redirect':
  73. os.mkdir(self.cache_directory)
  74. except:
  75. pass
  76. self.cache_maxsize = kwargs.get('cache_maxsize', 100000000)
  77. self.buffer_size = kwargs.get('buffer_size', 750000)
  78. rootItem = Container(None, self.name)
  79. self.set_root_item(rootItem)
  80. categoriesItem = Container(rootItem, "All by Categories")
  81. rootItem.add_child(categoriesItem)
  82. languagesItem = Container(rootItem, "All by Languages")
  83. rootItem.add_child(languagesItem)
  84. self.appendLanguage("Recent Videos", self.language, rootItem, sort='-age', count=15)
  85. self.appendLanguage("Top Rated", self.language, rootItem, sort='rating', count=15)
  86. self.appendLanguage("Most Popular", self.language, rootItem, sort='-popular', count=15)
  87. def gotError(error):
  88. print "ERROR: %s" % error
  89. def gotCategories(result):
  90. if result is None:
  91. print "Unable to retrieve list of categories"
  92. return
  93. data,header = result
  94. categories = eval(data) # FIXME add some checks to avoid code injection
  95. for category in categories:
  96. name = category['name'].encode('ascii', 'strict')
  97. category_url = category['url'].encode('ascii', 'strict')
  98. self.appendCategory(name, name, categoriesItem)
  99. categories_url = "https://www.miroguide.com/api/list_categories"
  100. d1 = utils.getPage(categories_url)
  101. d1.addCallbacks(gotCategories, gotError)
  102. def gotLanguages(result):
  103. if result is None:
  104. print "Unable to retrieve list of languages"
  105. return
  106. data,header = result
  107. languages = eval(data) # FIXME add some checks to avoid code injection
  108. for language in languages:
  109. name = language['name'].encode('ascii', 'strict')
  110. language_url = language['url'].encode('ascii', 'strict')
  111. self.appendLanguage(name, name, languagesItem)
  112. languages_url = "https://www.miroguide.com/api/list_languages"
  113. d2 = utils.getPage(languages_url)
  114. d2.addCallbacks(gotLanguages, gotError)
  115. self.init_completed()
  116. def __repr__(self):
  117. return self.__class__.__name__
  118. def appendCategory( self, name, category_id, parent):
  119. item = LazyContainer(parent, name, category_id, self.refresh, self.retrieveChannels, filter="category", filter_value=category_id, per_page=100)
  120. parent.add_child(item, external_id=category_id)
  121. def appendLanguage( self, name, language_id, parent, sort='name', count=0):
  122. item = LazyContainer(parent, name, language_id, self.refresh, self.retrieveChannels, filter="language", filter_value=language_id, per_page=100, sort=sort, count=count)
  123. parent.add_child(item, external_id=language_id)
  124. def appendChannel(self, name, channel_id, parent):
  125. item = LazyContainer(parent, name, channel_id, self.refresh, self.retrieveChannelItems, channel_id=channel_id)
  126. parent.add_child(item, external_id=channel_id)
  127. def upnp_init(self):
  128. self.current_connection_id = None
  129. if self.server:
  130. self.server.connection_manager_server.set_variable(
  131. 0, 'SourceProtocolInfo',
  132. ['http-get:*:%s:*' % 'video/'], #FIXME put list of all possible video mimetypes
  133. default=True)
  134. self.wmc_mapping = {'15': self.get_root_id()}
  135. def retrieveChannels (self, parent, filter, filter_value, per_page=100, offset=0, count=0, sort='name'):
  136. filter_value = urllib.quote(filter_value.encode("utf-8"))
  137. limit = count
  138. if (count == 0):
  139. limit = per_page
  140. uri = "https://www.miroguide.com/api/get_channels?limit=%d&offset=%d&filter=%s&filter_value=%s&sort=%s" % (limit, offset, filter, filter_value, sort)
  141. #print uri
  142. d = utils.getPage(uri)
  143. def gotChannels(result):
  144. if result is None:
  145. print "Unable to retrieve channel for category %s" % category_id
  146. return
  147. data,header = result
  148. channels = eval(data)
  149. for channel in channels:
  150. publisher = channel['publisher']
  151. description = channel['description']
  152. url = channel['url']
  153. hi_def = channel['hi_def']
  154. thumbnail_url = channel['thumbnail_url']
  155. postal_code = channel['postal_code']
  156. id = channel['id']
  157. website_url = channel['website_url']
  158. name = channel['name']
  159. self.appendChannel(name, id, parent)
  160. if ((count == 0) and (len(channels) >= per_page)):
  161. #print "reached page limit (%d)" % len(channels)
  162. parent.childrenRetrievingNeeded = True
  163. def gotError(error):
  164. print "ERROR: %s" % error
  165. d.addCallbacks(gotChannels, gotError)
  166. return d
  167. def retrieveChannelItems (self, parent, channel_id):
  168. uri = "https://www.miroguide.com/api/get_channel?id=%s" % channel_id
  169. d = utils.getPage(uri)
  170. def gotItems(result):
  171. if result is None:
  172. print "Unable to retrieve items for channel %s" % channel_id
  173. return
  174. data,header = result
  175. channel = eval(data)
  176. items = []
  177. if (channel.has_key('item')):
  178. items = channel['item']
  179. for item in items:
  180. #print "item:",item
  181. url = item['url']
  182. description = item['description']
  183. #print "description:", description
  184. name = item['name']
  185. thumbnail_url = None
  186. if (channel.has_key('thumbnail_url')):
  187. #print "Thumbnail:", channel['thumbnail_url']
  188. thumbnail_url = channel['thumbnail_url']
  189. #size = size['size']
  190. item = VideoItem(name, description, url, thumbnail_url, self)
  191. item.parent = parent
  192. parent.add_child(item, external_id=url)
  193. def gotError(error):
  194. print "ERROR: %s" % error
  195. d.addCallbacks(gotItems, gotError)
  196. return d