From 50aff67a8a9773d2c5da62d8baec9e14430d3bef Mon Sep 17 00:00:00 2001 From: Irfan Charania Date: Sat, 30 Apr 2016 13:44:09 -0700 Subject: [PATCH] Make itunes compatible optional (#1411) * Make itunes compatible optional in generated xml * Add tests + migration * Description change as per comment --- app/models/agents/data_output_agent.rb | 19 ++- ..._namespace_option_to_data_output_agents.rb | 17 +++ spec/models/agents/data_output_agent_spec.rb | 116 +++++++++++++++++- 3 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20160423163416_add_xml_namespace_option_to_data_output_agents.rb diff --git a/app/models/agents/data_output_agent.rb b/app/models/agents/data_output_agent.rb index 8f4c9856..29ac95d8 100644 --- a/app/models/agents/data_output_agent.rb +++ b/app/models/agents/data_output_agent.rb @@ -24,6 +24,8 @@ module Agents * `template` - A JSON object representing a mapping between item output keys and incoming event values. Use [Liquid](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid) to format the values. Values of the `link`, `title`, `description` and `icon` keys will be put into the \\ section of RSS output. Value of the `self` key will be used as URL for this feed itself, which is useful when you serve it via reverse proxy. The `item` key will be repeated for every Event. The `pubDate` key for each item will have the creation time of the Event unless given. * `events_to_show` - The number of events to output in RSS or JSON. (default: `40`) * `ttl` - A value for the \\ element in RSS output. (default: `60`) + * `ns_media` - Add [yahoo media namespace](https://en.wikipedia.org/wiki/Media_RSS) in output xml + * `ns_itunes` - Add [itunes compatible namespace](http://lists.apple.com/archives/syndication-dev/2005/Nov/msg00002.html) in output xml * `push_hubs` - Set to a list of PubSubHubbub endpoints you want to publish an update to every time this agent receives an event. (default: none) Popular hubs include [Superfeedr](https://pubsubhubbub.superfeedr.com/) and [Google](https://pubsubhubbub.appspot.com/). Note that publishing updates will make your feed URL known to the public, so if you want to keep it secret, set up a reverse proxy to serve your feed via a safe URL and specify it in `template.self`. If you'd like to output RSS tags with attributes, such as `enclosure`, use something like the following in your `template`: @@ -68,7 +70,8 @@ module Agents "description" => "Secret hovertext: {{hovertext}}", "link" => "{{url}}" } - } + }, + "ns_media" => "true" } end @@ -156,6 +159,18 @@ module Agents interpolated['template']['description'].presence || "A feed of Events received by the '#{name}' Huginn Agent" end + def xml_namespace + namespaces = ['xmlns:atom="http://www.w3.org/2005/Atom"'] + + if (boolify(interpolated['ns_media'])) + namespaces << 'xmlns:media="http://search.yahoo.com/mrss/"' + end + if (boolify(interpolated['ns_itunes'])) + namespaces << 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"' + end + namespaces.join(' ') + end + def push_hubs interpolated['push_hubs'].presence || [] end @@ -214,7 +229,7 @@ module Agents return [<<-XML, 200, 'text/xml'] - + #{feed_icon.encode(xml: :text)} diff --git a/db/migrate/20160423163416_add_xml_namespace_option_to_data_output_agents.rb b/db/migrate/20160423163416_add_xml_namespace_option_to_data_output_agents.rb new file mode 100644 index 00000000..5e0b0c70 --- /dev/null +++ b/db/migrate/20160423163416_add_xml_namespace_option_to_data_output_agents.rb @@ -0,0 +1,17 @@ +class AddXmlNamespaceOptionToDataOutputAgents < ActiveRecord::Migration + def up + Agents::DataOutputAgent.find_each do |agent| + agent.options['ns_media'] = 'true' + agent.options['ns_itunes'] = 'true' + agent.save!(validate: false) + end + end + + def down + Agents::DataOutputAgent.find_each do |agent| + agent.options.delete 'ns_media' + agent.options.delete 'ns_itunes' + agent.save!(validate: false) + end + end +end \ No newline at end of file diff --git a/spec/models/agents/data_output_agent_spec.rb b/spec/models/agents/data_output_agent_spec.rb index 16d00c35..5b9e3f5c 100644 --- a/spec/models/agents/data_output_agent_spec.rb +++ b/spec/models/agents/data_output_agent_spec.rb @@ -153,7 +153,7 @@ describe Agents::DataOutputAgent do expect(content_type).to eq('text/xml') expect(content.gsub(/\s+/, '')).to eq Utils.unindent(<<-XML).gsub(/\s+/, '') - + https://yoursite.com/favicon.ico @@ -294,6 +294,118 @@ describe Agents::DataOutputAgent do expect(Nokogiri(content).at('/rss/channel/atom:icon/text()').text).to eq('https://somesite.com/icon.png') end end + + describe "with media namespace not set" do + before do + agent.options['ns_media'] = nil + agent.save! + end + + it "can output RSS" do + stub(agent).feed_link { "https://yoursite.com" } + content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml') + expect(status).to eq(200) + expect(content_type).to eq('text/xml') + + doc = Nokogiri(content) + namespaces = doc.collect_namespaces + expect(namespaces).not_to include("xmlns:media") + end + end + + describe "with media namespace set true" do + before do + agent.options['ns_media'] = 'true' + agent.save! + end + + it "can output RSS" do + stub(agent).feed_link { "https://yoursite.com" } + content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml') + expect(status).to eq(200) + expect(content_type).to eq('text/xml') + + doc = Nokogiri(content) + namespaces = doc.collect_namespaces + expect(namespaces).to include( + "xmlns:media" => 'http://search.yahoo.com/mrss/' + ) + end + end + + describe "with media namespace set false" do + before do + agent.options['ns_media'] = 'false' + agent.save! + end + + it "can output RSS" do + stub(agent).feed_link { "https://yoursite.com" } + content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml') + expect(status).to eq(200) + expect(content_type).to eq('text/xml') + + doc = Nokogiri(content) + namespaces = doc.collect_namespaces + expect(namespaces).not_to include("xmlns:media") + end + end + + describe "with itunes namespace not set" do + before do + agent.options['ns_itunes'] = nil + agent.save! + end + + it "can output RSS" do + stub(agent).feed_link { "https://yoursite.com" } + content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml') + expect(status).to eq(200) + expect(content_type).to eq('text/xml') + + doc = Nokogiri(content) + namespaces = doc.collect_namespaces + expect(namespaces).not_to include("xmlns:itunes") + end + end + + describe "with itunes namespace set true" do + before do + agent.options['ns_itunes'] = 'true' + agent.save! + end + + it "can output RSS" do + stub(agent).feed_link { "https://yoursite.com" } + content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml') + expect(status).to eq(200) + expect(content_type).to eq('text/xml') + + doc = Nokogiri(content) + namespaces = doc.collect_namespaces + expect(namespaces).to include( + "xmlns:itunes" => 'http://www.itunes.com/dtds/podcast-1.0.dtd' + ) + end + end + + describe "with itunes namespace set false" do + before do + agent.options['ns_itunes'] = 'false' + agent.save! + end + + it "can output RSS" do + stub(agent).feed_link { "https://yoursite.com" } + content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml') + expect(status).to eq(200) + expect(content_type).to eq('text/xml') + + doc = Nokogiri(content) + namespaces = doc.collect_namespaces + expect(namespaces).not_to include("xmlns:itunes") + end + end end describe "outputting nesting" do @@ -392,7 +504,7 @@ describe Agents::DataOutputAgent do expect(content_type).to eq('text/xml') expect(content.gsub(/\s+/, '')).to eq Utils.unindent(<<-XML).gsub(/\s+/, '') - + https://yoursite.com/favicon.ico