Make itunes compatible optional (#1411)

* Make itunes compatible optional

in generated xml

* Add tests + migration

* Description change

as per comment
This commit is contained in:
Irfan Charania 2016-04-30 13:44:09 -07:00 committed by Andrew Cantino
parent 01596c7ff1
commit 50aff67a8a
3 changed files with 148 additions and 4 deletions

View file

@ -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 \\<channel\\> 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 \\<ttl\\> 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']
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<rss version="2.0" #{xml_namespace}>
<channel>
<atom:link href=#{feed_url(secret: params['secret'], format: :xml).encode(xml: :attr)} rel="self" type="application/rss+xml" />
<atom:icon>#{feed_icon.encode(xml: :text)}</atom:icon>

View file

@ -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

View file

@ -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+/, '')
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<atom:link href="https://yoursite.com/users/#{agent.user.id}/web_requests/#{agent.id}/secret1.xml" rel="self" type="application/rss+xml"/>
<atom:icon>https://yoursite.com/favicon.ico</atom:icon>
@ -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+/, '')
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" >
<channel>
<atom:link href="https://yoursite.com/users/#{agent.user.id}/web_requests/#{agent.id}/secret1.xml" rel="self" type="application/rss+xml"/>
<atom:icon>https://yoursite.com/favicon.ico</atom:icon>