[grilo-plugins] lua-factory: Add iTunes Podcast source



commit 271fae4639b7b57b6d7d3fe7d8c6eca70fa50891
Author: Bastien Nocera <hadess hadess net>
Date:   Sat Apr 9 15:20:01 2016 +0200

    lua-factory: Add iTunes Podcast source
    
    A source to browse and search iTunes podcasts.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=764816

 src/lua-factory/sources/Makefile.am                |   13 +-
 .../sources/grl-itunes-podcast.gresource.xml       |    6 +
 src/lua-factory/sources/grl-itunes-podcast.lua     |  222 ++++++++++++++++++++
 src/lua-factory/sources/itunes-podcast.png         |  Bin 0 -> 542588 bytes
 4 files changed, 238 insertions(+), 3 deletions(-)
---
diff --git a/src/lua-factory/sources/Makefile.am b/src/lua-factory/sources/Makefile.am
index ad3d49b..4d304a7 100644
--- a/src/lua-factory/sources/Makefile.am
+++ b/src/lua-factory/sources/Makefile.am
@@ -22,7 +22,9 @@ lua_sources_DATA =                                    \
        grl-pocket.lua                                  \
        grl-pocket.gresource                            \
        grl-appletrailers.lua                           \
-       grl-appletrailers.gresource
+       grl-appletrailers.gresource                     \
+       grl-itunes-podcast.lua                          \
+       grl-itunes-podcast.gresource
 
 lua_sourcesdir = $(datadir)/$(LUA_FACTORY_SOURCE_LOCATION)
 
@@ -41,12 +43,16 @@ grl-pocket.gresource: grl-pocket.gresource.xml
 grl-appletrailers.gresource: grl-appletrailers.gresource.xml
        $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $(srcdir)/grl-appletrailers.gresource.xml
 
+grl-itunes-podcast.gresource: grl-itunes-podcast.gresource.xml
+       $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $(srcdir)/grl-itunes-podcast.gresource.xml
+
 CLEANFILES =                                           \
        grl-euronews.gresource                          \
        grl-guardianvideos.gresource                    \
        grl-radiofrance.gresource                       \
        grl-pocket.gresource                            \
-       grl-appletrailers.gresource
+       grl-appletrailers.gresource                     \
+       grl-itunes-podcast.gresource
 
 EXTRA_DIST +=                                          \
        $(lua_sources_DATA)                             \
@@ -59,6 +65,7 @@ EXTRA_DIST +=                                         \
        guardianvideos.svg                              \
        radiofrance.png                                 \
        trailers.svg                                    \
-       pocket.svg
+       pocket.svg                                      \
+       itunes-podcast.png
 
 -include $(top_srcdir)/git.mk
diff --git a/src/lua-factory/sources/grl-itunes-podcast.gresource.xml 
b/src/lua-factory/sources/grl-itunes-podcast.gresource.xml
new file mode 100644
index 0000000..1a6340a
--- /dev/null
+++ b/src/lua-factory/sources/grl-itunes-podcast.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/grilo/plugins/itunes-podcast">
+    <file compressed="false">itunes-podcast.png</file>
+  </gresource>
+</gresources>
diff --git a/src/lua-factory/sources/grl-itunes-podcast.lua b/src/lua-factory/sources/grl-itunes-podcast.lua
new file mode 100644
index 0000000..4bac1ec
--- /dev/null
+++ b/src/lua-factory/sources/grl-itunes-podcast.lua
@@ -0,0 +1,222 @@
+--[[
+ * Copyright (C) 2016 Grilo Project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+--]]
+
+-- API Documentation available at:
+-- https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/
+
+-- Browse URL, will return a URL to be parsed by totem-pl-parser
+ITUNES_PODCAST_URL = 'https://itunes.apple.com/%s/rss/toppodcasts/limit=%d/json'
+-- Search URL, will return the URL to an RSS feed
+ITUNES_SEARCH_PODCAST_URL = 'https://itunes.apple.com/search?term=%s&entity=podcast&country=%s&limit=%d'
+-- The web service will not return more than 200 items
+MAX_ITEMS = 200
+
+---------------------------
+-- Source initialization --
+---------------------------
+
+source = {
+  id = "grl-itunes-podcast",
+  name = "iTunes Podcast",
+  description = "iTunes Podcast",
+  supported_keys = { 'artist', 'thumbnail', 'id', 'title', 'region',
+                     'external-url', 'genre', 'modification-date',
+                     'mime-type', 'description' },
+  config_keys = {
+    optional = { 'country' },
+  },
+  -- From http://www.powerpresspodcast.com/wp-content/uploads/2016/02/itunes-podcast-app-logo.png
+  icon = 'resource:///org/gnome/grilo/plugins/itunes-podcast/itunes-podcast.png',
+  tags = { 'podcast', 'net:internet' },
+}
+
+-- Global table to store config data
+ldata = {}
+
+------------------
+-- Source utils --
+------------------
+
+-- Valid countries are listed at
+-- 
https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Appendices/AppStoreTerritories.html
+--
+-- io.input("AppStoreTerritories.html")
+-- t = io.read("*all")
+-- table = t:match('TableHeading_TableRow_TableCell.-<td  scope="row">(.-)</table>')
+-- io.write ('countries = { ')
+-- for i in table:gmatch('<p>([A-Z][A-Z])</p>') do
+--     io.write ('"' .. i .. '"')
+--     io.write (', ')
+-- end
+-- io.write ('}\n')
+
+countries = { "AE", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BE", "BF", "BG", "BH", 
"BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BW", "BY", "BZ", "CA", "CG", "CH", "CL", "CN", "CO", "CR", "CV", 
"CY", "CZ", "DE", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "ES", "FI", "FJ", "FM", "FR", "GB", "GD", "GH", 
"GM", "GR", "GT", "GW", "GY", "HK", "HN", "HR", "HU", "ID", "IE", "IL", "IN", "IS", "IT", "JM", "JO", "JP", 
"KE", "KG", "KH", "KN", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LK", "LR", "LT", "LU", "LV", "MD", "MG", 
"MK", "ML", "MN", "MO", "MR", "MS", "MT", "MU", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", 
"NP", "NZ", "OM", "PA", "PE", "PG", "PH", "PK", "PL", "PT", "PW", "PY", "QA", "RO", "RU", "SA", "SB", "SC", 
"SE", "SG", "SI", "SK", "SL", "SN", "SR", "ST", "SV", "SZ", "TC", "TD", "TH", "TJ", "TM", "TN", "TR", "TT", 
"TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VG", "VN", "YE", "ZA", "ZW", }
+
+function grl_source_init(configs)
+  ldata.country = 'US'
+
+  if not configs.country then
+    return true
+  end
+
+  for i in countries do
+    if configs.country ~= i then
+      ldata.country = i
+      return true
+    end
+  end
+
+  grl.warning ('Invalid Podcast territory "' .. configs.country .. '"')
+
+  return false
+end
+
+---------------------------------
+-- Handlers of Grilo functions --
+---------------------------------
+
+function grl_source_browse(media_id)
+  local count = grl.get_options("count")
+  local skip = grl.get_options("skip")
+
+  if skip + count > MAX_ITEMS then
+    grl.callback()
+    return
+  end
+
+  local url = string.format(ITUNES_PODCAST_URL, ldata.country, skip + count)
+  grl.debug ("Fetching URL: " .. url .. " (count: " .. count .. " skip: " .. skip .. ")")
+  grl.fetch(url, fetch_browse_results_cb)
+end
+
+function grl_source_search(text)
+  local count = grl.get_options("count")
+  local skip = grl.get_options("skip")
+
+  if skip + count > MAX_ITEMS then
+    grl.callback()
+    return
+  end
+
+  text = string.gsub(text, " ", "+")
+
+  local url = string.format(ITUNES_SEARCH_PODCAST_URL, text, ldata.country, skip + count)
+  grl.debug ("Fetching URL: " .. url .. " (count: " .. count .. " skip: " .. skip .. " text: " .. text .. 
")")
+  grl.fetch(url, fetch_search_results_cb)
+end
+
+---------------
+-- Utilities --
+---------------
+
+function fetch_browse_results_cb(results)
+  local count = grl.get_options("count")
+  local skip = grl.get_options("skip")
+
+  if not results then
+    grl.callback()
+    return
+  end
+
+  local json = grl.lua.json.string_to_table(results)
+  if not json or not json.feed or not json.feed.entry then
+    grl.callback()
+    return
+  end
+
+  for i, result in ipairs(json.feed.entry) do
+    if skip > 0 then
+      skip = skip - 1
+    elseif count > 0 then
+      local media = {}
+
+      media.genre = result.category.attributes.label
+      media.id = result.id.attributes["im:id"]
+      media.artist = result["im:artist"].label
+      media.thumbnail = {}
+      for j, image in ipairs(result["im:image"]) do
+        -- FIXME sort images with the biggest first
+        table.insert(media.thumbnail, image.label)
+      end
+      if result["im:releaseDate"] then
+        media.modification_date = result["im:releaseDate"].label
+      else
+        print (grl.lua.inspect (result))
+      end
+      if result.summary then media.description = result.summary.label end
+      media.title = result.title.label
+      media.external_url = result.link.attributes.href
+
+      count = count - 1
+      grl.debug ('Sending out media ' .. media.id .. ' (external url: ' .. media.external_url .. ' left: ' 
.. count .. ')')
+      grl.callback(media, count)
+    end
+  end
+
+  if count > 0 then
+    grl.callback()
+  end
+end
+
+function fetch_search_results_cb(results)
+  local count = grl.get_options("count")
+  local skip = grl.get_options("skip")
+
+  if not results then
+    grl.callback()
+    return
+  end
+
+  local json = grl.lua.json.string_to_table(results)
+  if not json or json.resultCount < 1 then
+    grl.callback()
+    return
+  end
+
+  for i, result in ipairs(json.results) do
+    if skip > 0 then
+      skip = skip - 1
+    elseif count > 0 then
+      local media = {}
+
+      media.artist = result.artistName
+      media.thumbnail = {}
+      if result.artworkUrl600 then table.insert(media.thumbnail, result.artworkUrl600) end
+      if result.artworkUrl100 then table.insert(media.thumbnail, result.artworkUrl100) end
+      if result.artworkUrl60 then table.insert(media.thumbnail, result.artworkUrl60) end
+      if result.artworkUrl30 then table.insert(media.thumbnail, result.artworkUrl30) end
+      media.id = result.collectionId
+      media.title = result.collectionName
+      media.region = result.country
+      media.url = result.feedUrl
+      media.genre = result.genres
+      media.modification_date = result.releaseDate
+      media.mime_type = 'application/rss+xml'
+
+      count = count - 1
+      grl.debug ('Sending out media ' .. media.id .. ' (feed url: ' .. media.url .. ' left: ' .. count .. 
')')
+      grl.callback(media, count)
+    end
+  end
+
+  if count > 0 then
+    grl.callback()
+  end
+end
diff --git a/src/lua-factory/sources/itunes-podcast.png b/src/lua-factory/sources/itunes-podcast.png
new file mode 100644
index 0000000..bdf9455
Binary files /dev/null and b/src/lua-factory/sources/itunes-podcast.png differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]