podcastinator 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -2
- data/README.md +83 -13
- data/Rakefile +6 -0
- data/lib/podcastinator.rb +10 -2
- data/lib/podcastinator/feed.rb +34 -116
- data/lib/podcastinator/file_feed.rb +127 -0
- data/lib/podcastinator/generator.rb +25 -21
- data/lib/podcastinator/version.rb +1 -1
- data/podcastinator.gemspec +1 -0
- data/test/generated_feed_test.rb +140 -0
- data/test/test_helper.rb +4 -0
- metadata +22 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b5bfc40a9fcbf90998ad87bd51065215167794a
|
4
|
+
data.tar.gz: 729c1266623feb119fb563cd7c7807979f5c4f7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf095930b829c63823ae434e0537a6870de2583038c7a423607850263dc9f0ec36396b70a69dc93065c6f383f81bcb15172bb020a935cbbde7a2ad6d726add81
|
7
|
+
data.tar.gz: 8a15339a01f3c093be0e9c97745f276bb7eee9ec5f0607ec48f44dd85c97df23ada009f9dc69b3789327f70dcad5e4197b0d71b23c39d6215e1dd353ba56193d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
��ƖJ���K�����2��
|
2
|
+
�bl��iB)���v��o� F�֏^'��F`�ZA�I�bUӭ��
|
data/README.md
CHANGED
@@ -18,28 +18,98 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
Create a Feed object with items
|
22
22
|
|
23
|
-
|
23
|
+
```ruby
|
24
|
+
feed =
|
25
|
+
Podcastinator::Feed.new({
|
26
|
+
:author => "Mr. Bob Example",
|
27
|
+
:copyright => "Copyright 2001 Bob Example Inc",
|
28
|
+
:description => "This is Bob's podcast. Do not mess with Bob.",
|
29
|
+
:image_url => "http://example.com/podcast.png",
|
30
|
+
:keywords => [ "bob", "example" ],
|
31
|
+
:language => "English",
|
32
|
+
:owner_name => "Bob Example",
|
33
|
+
:owner_email => "bob@example.com",
|
34
|
+
:subtitle => "Don't mess with the bob.",
|
35
|
+
:title => "Bob's EXTREME Podcast",
|
36
|
+
:url => "http://example.com/podcast.xml",
|
37
|
+
|
38
|
+
:items => [{
|
39
|
+
:author => "Sue Example",
|
40
|
+
:duration => "127",
|
41
|
+
:file_size => "92812",
|
42
|
+
:filename => "episode-128.mp3",
|
43
|
+
:guid => "http://example.com/episodes/128.html",
|
44
|
+
:image_url => "http://example.com/episodes/128.png",
|
45
|
+
:keywords => [ "sue", "example" ],
|
46
|
+
:mime_type => "audio/mp3",
|
47
|
+
:subtitle => "Sue's episode, it's great!",
|
48
|
+
:summary => "This episode is dedicated to Sue.",
|
49
|
+
:time => Time.parse("April 21, 2010 6:24pm CDT").utc,
|
50
|
+
:title => "Episode 128",
|
51
|
+
:url => "http://example.com/episodes/128.mp3",
|
52
|
+
}, {
|
53
|
+
:author => "Ms. Sue Example",
|
54
|
+
:duration => "256",
|
55
|
+
:file_size => "92912",
|
56
|
+
:filename => "episode-129.mp3",
|
57
|
+
:guid => "http://example.com/episodes/129.html",
|
58
|
+
:image_url => "http://example.com/episodes/129.png",
|
59
|
+
:keywords => [ "sue", "example", "two" ],
|
60
|
+
:mime_type => "audio/mp3",
|
61
|
+
:subtitle => "Sue's second episode, it's great!",
|
62
|
+
:summary => "This second episode is dedicated to Sue.",
|
63
|
+
:time => Time.parse("April 22, 2010 6:24pm CDT").utc,
|
64
|
+
:title => "Episode 129",
|
65
|
+
:url => "http://example.com/episodes/129.mp3",
|
66
|
+
}],
|
67
|
+
})
|
68
|
+
```
|
24
69
|
|
25
|
-
|
70
|
+
Then extract the XML from the feed object
|
26
71
|
|
27
72
|
```ruby
|
28
|
-
|
29
|
-
def initialize(options = {})
|
30
|
-
super
|
31
|
-
@items_hash = options[:items_hash]
|
32
|
-
end
|
33
|
-
def items
|
34
|
-
end
|
35
|
-
end
|
73
|
+
xml = feed.to_xml
|
36
74
|
```
|
37
75
|
|
38
|
-
|
76
|
+
The XML generator can accept any object that responds to the following methods:
|
77
|
+
|
78
|
+
```
|
79
|
+
author
|
80
|
+
copyright
|
81
|
+
description
|
82
|
+
image_url
|
83
|
+
items
|
84
|
+
keywords
|
85
|
+
language
|
86
|
+
owner_name
|
87
|
+
owner_email
|
88
|
+
subtitle
|
89
|
+
title
|
90
|
+
url
|
91
|
+
```
|
92
|
+
|
93
|
+
The `items` value should be an array of objects that respond to the following methods:
|
94
|
+
|
95
|
+
```
|
96
|
+
author
|
97
|
+
duration
|
98
|
+
file_size
|
99
|
+
guid
|
100
|
+
image_url
|
101
|
+
keywords
|
102
|
+
mime_type
|
103
|
+
subtitle
|
104
|
+
summary
|
105
|
+
time
|
106
|
+
title
|
107
|
+
url
|
108
|
+
```
|
39
109
|
|
40
110
|
## Contributing
|
41
111
|
|
42
|
-
1. Fork it ( https://github.com/
|
112
|
+
1. Fork it ( https://github.com/alexmchale/podcastinator/fork )
|
43
113
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
44
114
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
45
115
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/Rakefile
CHANGED
data/lib/podcastinator.rb
CHANGED
@@ -19,8 +19,16 @@ require "podcastinator/generator"
|
|
19
19
|
module Podcastinator
|
20
20
|
|
21
21
|
def self.start(options = self.parse_cli_options)
|
22
|
-
feed = Podcastinator::
|
23
|
-
|
22
|
+
feed = Podcastinator::FileFeed.new(options)
|
23
|
+
xml = Podcastinator::Generator.new(feed).to_xml
|
24
|
+
|
25
|
+
if options[:output]
|
26
|
+
File.open(options[:output], "w") do |f|
|
27
|
+
f.puts(xml)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
puts xml
|
31
|
+
end
|
24
32
|
end
|
25
33
|
|
26
34
|
def self.parse_cli_options
|
data/lib/podcastinator/feed.rb
CHANGED
@@ -2,152 +2,70 @@ module Podcastinator
|
|
2
2
|
|
3
3
|
class Feed
|
4
4
|
|
5
|
-
|
6
|
-
title
|
7
|
-
url
|
8
|
-
description
|
9
|
-
language
|
10
|
-
copyright
|
11
|
-
subtitle
|
5
|
+
FIELDS = %i(
|
12
6
|
author
|
7
|
+
copyright
|
8
|
+
description
|
13
9
|
image_url
|
14
|
-
keywords
|
15
|
-
owner
|
16
10
|
items
|
17
|
-
|
11
|
+
keywords
|
12
|
+
language
|
13
|
+
owner_name
|
14
|
+
owner_email
|
15
|
+
subtitle
|
16
|
+
title
|
17
|
+
url
|
18
18
|
)
|
19
19
|
|
20
|
+
FIELDS.each { |field| attr_reader field }
|
21
|
+
|
20
22
|
def initialize(options = {})
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@description = options[:description]
|
25
|
-
@language = options[:language]
|
26
|
-
@copyright = options[:copyright]
|
27
|
-
@subtitle = options[:subtitle]
|
28
|
-
@author = options[:author]
|
29
|
-
@image_url = options[:image_url]
|
30
|
-
@keywords = options[:keywords]
|
31
|
-
@owner = Owner.build(options[:owner_name], options[:owner_email])
|
32
|
-
end
|
23
|
+
FIELDS.each do |field|
|
24
|
+
instance_variable_set("@#{ field }", options[field] || options[field.to_s])
|
25
|
+
end
|
33
26
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
if @items.kind_of? Array
|
28
|
+
@items.map! do |item|
|
29
|
+
if item.kind_of? Hash
|
30
|
+
Item.new(item)
|
31
|
+
else
|
32
|
+
item
|
39
33
|
end
|
40
34
|
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class Owner < Struct.new(:name, :email)
|
44
|
-
|
45
|
-
def self.build(name, email)
|
46
|
-
new(name, email) if name.present? || email.present?
|
47
35
|
end
|
48
|
-
|
49
36
|
end
|
50
37
|
|
51
38
|
class Item
|
52
39
|
|
53
|
-
|
40
|
+
FIELDS = %i(
|
54
41
|
author
|
55
|
-
|
42
|
+
duration
|
43
|
+
file_size
|
44
|
+
guid
|
56
45
|
image_url
|
57
|
-
|
46
|
+
keywords
|
47
|
+
mime_type
|
58
48
|
subtitle
|
49
|
+
summary
|
59
50
|
time
|
60
51
|
title
|
61
52
|
url
|
62
|
-
file_size
|
63
|
-
mime_type
|
64
|
-
duration
|
65
53
|
)
|
66
54
|
|
67
|
-
|
68
|
-
@feed = feed
|
69
|
-
@filename = filename
|
70
|
-
@local_filename = File.join(feed.local_path, filename)
|
71
|
-
@url = "#{ feed.url }/#{ URI.escape @filename.to_s }".gsub("//", "/")
|
55
|
+
FIELDS.each { |field| attr_reader field }
|
72
56
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
else
|
77
|
-
feed.image_url
|
78
|
-
end
|
79
|
-
|
80
|
-
TagLib::FileRef.open(local_filename) do |fileref|
|
81
|
-
tag = fileref.tag
|
82
|
-
|
83
|
-
@title = tag.title
|
84
|
-
@author = tag.artist
|
85
|
-
@album = tag.album
|
86
|
-
@track = if tag.track.present? && tag.track != 0 then tag.to_s.track[/^\d+/] end
|
87
|
-
@subtitle = if author.present? && @track.present? then %[#{ album } ##{ track }] end
|
88
|
-
@duration = fileref.audio_properties.length
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def mime_type
|
93
|
-
case File.extname(filename).downcase
|
94
|
-
when ".mp3" then "audio/mpeg"
|
95
|
-
else raise UnknownMimeType, "podcastinator can't handle #{ filename }"
|
57
|
+
def initialize(options = {})
|
58
|
+
FIELDS.each do |field|
|
59
|
+
instance_variable_set("@#{ field }", options[field] || options[field.to_s])
|
96
60
|
end
|
97
61
|
end
|
98
62
|
|
99
|
-
def guid
|
100
|
-
md5 = Digest::MD5.new
|
101
|
-
|
102
|
-
File.open(local_filename, 'rb') do |io|
|
103
|
-
while (buf = io.read(4096)) && (buf.length > 0)
|
104
|
-
md5.update(buf)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
md5.to_s
|
109
|
-
end
|
110
|
-
|
111
63
|
def is_guid_permalink?
|
64
|
+
URI.parse(@guid).kind_of?(URI::HTTP)
|
65
|
+
rescue URI::InvalidURIError
|
112
66
|
false
|
113
67
|
end
|
114
68
|
|
115
|
-
def time
|
116
|
-
@time || File.mtime(local_filename)
|
117
|
-
end
|
118
|
-
|
119
|
-
def keywords
|
120
|
-
[]
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.mime_types
|
124
|
-
{
|
125
|
-
"mp3" => "audio/mpeg",
|
126
|
-
}
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.globs
|
130
|
-
mime_types.keys.map { |ext| "**/*.#{ ext }" }
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.build(feed, files)
|
134
|
-
files.map do |filename|
|
135
|
-
title, subtitle, author, time, image_url = nil
|
136
|
-
|
137
|
-
TagLib::FileRef.open(local_filename) do |fileref|
|
138
|
-
tag = fileref.tag
|
139
|
-
|
140
|
-
title = tag.title
|
141
|
-
author = tag.artist
|
142
|
-
album = tag.album
|
143
|
-
track = if tag.track.present? && tag.track != 0 then tag.to_s.track[/^\d+/] end
|
144
|
-
subtitle = if album.present? && track.present? then %[#{ album } ##{ track }] end
|
145
|
-
end
|
146
|
-
|
147
|
-
new(feed, filename, title, subtitle, author, time, image_url)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
69
|
end
|
152
70
|
|
153
71
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Podcastinator
|
2
|
+
|
3
|
+
class FileFeed < Feed
|
4
|
+
|
5
|
+
attr_reader :local_path
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
super
|
9
|
+
|
10
|
+
@local_path = options[:local_path]
|
11
|
+
end
|
12
|
+
|
13
|
+
def items
|
14
|
+
@items ||=
|
15
|
+
Dir.chdir(local_path) do
|
16
|
+
Dir[*FileItem.globs].uniq.map do |filename|
|
17
|
+
FileItem.new(self, filename)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class FileItem < Item
|
23
|
+
|
24
|
+
attr_reader *%i(
|
25
|
+
author
|
26
|
+
filename
|
27
|
+
image_url
|
28
|
+
local_filename
|
29
|
+
subtitle
|
30
|
+
time
|
31
|
+
title
|
32
|
+
url
|
33
|
+
file_size
|
34
|
+
mime_type
|
35
|
+
duration
|
36
|
+
summary
|
37
|
+
)
|
38
|
+
|
39
|
+
def initialize(feed, filename)
|
40
|
+
@feed = feed
|
41
|
+
@filename = filename
|
42
|
+
@local_filename = File.join(feed.local_path, filename)
|
43
|
+
@url = "#{ feed.url }/#{ URI.escape @filename.to_s }".gsub("//", "/")
|
44
|
+
|
45
|
+
@image_url =
|
46
|
+
if File.file? File.join(feed.local_path, "#{ filename }.jpg")
|
47
|
+
"#{ @url }.jpg"
|
48
|
+
else
|
49
|
+
feed.image_url
|
50
|
+
end
|
51
|
+
|
52
|
+
TagLib::FileRef.open(local_filename) do |fileref|
|
53
|
+
tag = fileref.tag
|
54
|
+
|
55
|
+
@title = tag.title
|
56
|
+
@author = tag.artist
|
57
|
+
@album = tag.album
|
58
|
+
@track = if tag.track.present? && tag.track != 0 then tag.to_s.track[/^\d+/] end
|
59
|
+
@subtitle = if author.present? && @track.present? then %[#{ album } ##{ track }] end
|
60
|
+
@duration = fileref.audio_properties.length
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def mime_type
|
65
|
+
case File.extname(filename).downcase
|
66
|
+
when ".mp3" then "audio/mpeg"
|
67
|
+
else raise UnknownMimeType, "podcastinator can't handle #{ filename }"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def guid
|
72
|
+
md5 = Digest::MD5.new
|
73
|
+
|
74
|
+
File.open(local_filename, 'rb') do |io|
|
75
|
+
while (buf = io.read(4096)) && (buf.length > 0)
|
76
|
+
md5.update(buf)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
md5.to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
def is_guid_permalink?
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
def time
|
88
|
+
@time || File.mtime(local_filename)
|
89
|
+
end
|
90
|
+
|
91
|
+
def keywords
|
92
|
+
[]
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.mime_types
|
96
|
+
{
|
97
|
+
"mp3" => "audio/mpeg",
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.globs
|
102
|
+
mime_types.keys.map { |ext| "**/*.#{ ext }" }
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.build(feed, files)
|
106
|
+
files.map do |filename|
|
107
|
+
title, subtitle, author, time, image_url = nil
|
108
|
+
|
109
|
+
TagLib::FileRef.open(local_filename) do |fileref|
|
110
|
+
tag = fileref.tag
|
111
|
+
|
112
|
+
title = tag.title
|
113
|
+
author = tag.artist
|
114
|
+
album = tag.album
|
115
|
+
track = if tag.track.present? && tag.track != 0 then tag.to_s.track[/^\d+/] end
|
116
|
+
subtitle = if album.present? && track.present? then %[#{ album } ##{ track }] end
|
117
|
+
end
|
118
|
+
|
119
|
+
new(feed, filename, title, subtitle, author, time, image_url)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
@@ -13,25 +13,25 @@ module Podcastinator
|
|
13
13
|
xml.rss("xmlns:itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd", "version" => "2.0") do
|
14
14
|
xml.channel do
|
15
15
|
# Required channel attributes
|
16
|
-
xml.title
|
17
|
-
xml.link
|
18
|
-
xml.description
|
19
|
-
xml["itunes"].summary
|
16
|
+
xml.title(feed.title)
|
17
|
+
xml.link(feed.url)
|
18
|
+
xml.description(feed.description)
|
19
|
+
xml["itunes"].summary(feed.description)
|
20
20
|
xml["itunes"].image(href: feed.image_url)
|
21
|
-
xml.generator
|
21
|
+
xml.generator("Podcastinator #{ Podcastinator::VERSION }")
|
22
22
|
|
23
23
|
# Optional channel attributes
|
24
|
-
xml.language
|
25
|
-
xml.copyright
|
26
|
-
xml.subtitle
|
27
|
-
xml.author
|
28
|
-
xml["itunes"].keywords feed.keywords.join(",") if feed.keywords
|
24
|
+
xml.language(feed.language) if feed.language
|
25
|
+
xml.copyright(feed.copyright) if feed.copyright
|
26
|
+
xml.subtitle(feed.subtitle) if feed.subtitle
|
27
|
+
xml.author(feed.author) if feed.author
|
28
|
+
xml["itunes"].keywords([ feed.keywords ].flatten.compact.join(",")) if feed.keywords
|
29
29
|
|
30
30
|
# Owner details
|
31
|
-
if feed.
|
31
|
+
if feed.owner_name || feed.owner_email
|
32
32
|
xml["itunes"].owner do
|
33
|
-
xml["itunes"].name
|
34
|
-
xml["itunes"].email
|
33
|
+
xml["itunes"].name(feed.owner_name)
|
34
|
+
xml["itunes"].email(feed.owner_email)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -42,16 +42,16 @@ module Podcastinator
|
|
42
42
|
# Channel items
|
43
43
|
feed.items.each do |item|
|
44
44
|
xml.item do
|
45
|
-
xml.title
|
46
|
-
xml["itunes"].author
|
47
|
-
xml["itunes"].subtitle
|
48
|
-
xml["itunes"].summary
|
49
|
-
xml["itunes"].image(href:
|
45
|
+
xml.title(item.title)
|
46
|
+
xml["itunes"].author(item.author)
|
47
|
+
xml["itunes"].subtitle(item.subtitle) if item.subtitle
|
48
|
+
xml["itunes"].summary(item.summary) if item.summary
|
49
|
+
xml["itunes"].image(href: item.image_url || feed.image_url)
|
50
50
|
xml.enclosure(url: item.url, length: item.file_size, type: item.mime_type)
|
51
51
|
xml.guid(item.guid, isPermaLink: item.is_guid_permalink?)
|
52
|
-
xml.pubDate item.time.iso8601
|
53
|
-
xml["itunes"].duration
|
54
|
-
xml["itunes"].keywords item.keywords.join(",") if item.keywords
|
52
|
+
xml.pubDate(if item.time.respond_to?(:iso8601) then item.time.iso8601 else item.time.to_s end)
|
53
|
+
xml["itunes"].duration(item.duration.to_i)
|
54
|
+
xml["itunes"].keywords([ item.keywords ].flatten.compact.join(",")) if item.keywords
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -63,6 +63,10 @@ module Podcastinator
|
|
63
63
|
xml_builder.to_xml
|
64
64
|
end
|
65
65
|
|
66
|
+
def self.to_xml(feed)
|
67
|
+
new(feed).to_xml
|
68
|
+
end
|
69
|
+
|
66
70
|
end
|
67
71
|
|
68
72
|
end
|
data/podcastinator.gemspec
CHANGED
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GeneratedFeedTest < Minitest::Test
|
4
|
+
|
5
|
+
def test_empty_fields
|
6
|
+
feed =
|
7
|
+
Podcastinator::Feed.new({
|
8
|
+
:items => [
|
9
|
+
Podcastinator::Feed::Item.new({
|
10
|
+
}),
|
11
|
+
]
|
12
|
+
})
|
13
|
+
|
14
|
+
expected_xml = <<-XML.gsub(/^\s{6}/, "")
|
15
|
+
<?xml version="1.0"?>
|
16
|
+
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
|
17
|
+
<channel>
|
18
|
+
<title/>
|
19
|
+
<link/>
|
20
|
+
<description/>
|
21
|
+
<itunes:summary/>
|
22
|
+
<itunes:image href=""/>
|
23
|
+
<generator>Podcastinator #{ Podcastinator::VERSION }</generator>
|
24
|
+
<item>
|
25
|
+
<title/>
|
26
|
+
<itunes:author/>
|
27
|
+
<itunes:image href=""/>
|
28
|
+
<enclosure url="" length="" type=""/>
|
29
|
+
<guid isPermaLink="false"/>
|
30
|
+
<pubDate/>
|
31
|
+
<itunes:duration>0</itunes:duration>
|
32
|
+
</item>
|
33
|
+
</channel>
|
34
|
+
</rss>
|
35
|
+
XML
|
36
|
+
|
37
|
+
generated_xml = Podcastinator::Generator.new(feed).to_xml
|
38
|
+
|
39
|
+
assert_equal expected_xml.strip, generated_xml.strip
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_all_fields
|
43
|
+
feed =
|
44
|
+
Podcastinator::Feed.new({
|
45
|
+
:author => "Mr. Bob Example",
|
46
|
+
:copyright => "Copyright 2001 Bob Example Inc",
|
47
|
+
:description => "This is Bob's podcast. Do not mess with Bob.",
|
48
|
+
:image_url => "http://example.com/podcast.png",
|
49
|
+
:keywords => [ "bob", "example" ],
|
50
|
+
:language => "English",
|
51
|
+
:owner_name => "Bob Example",
|
52
|
+
:owner_email => "bob@example.com",
|
53
|
+
:subtitle => "Don't mess with the bob.",
|
54
|
+
:title => "Bob's EXTREME Podcast",
|
55
|
+
:url => "http://example.com/podcast.xml",
|
56
|
+
|
57
|
+
:items => [{
|
58
|
+
:author => "Sue Example",
|
59
|
+
:duration => "127",
|
60
|
+
:file_size => "92812",
|
61
|
+
:filename => "episode-128.mp3",
|
62
|
+
:guid => "http://example.com/episodes/128.html",
|
63
|
+
:image_url => "http://example.com/episodes/128.png",
|
64
|
+
:keywords => [ "sue", "example" ],
|
65
|
+
:mime_type => "audio/mp3",
|
66
|
+
:subtitle => "Sue's episode, it's great!",
|
67
|
+
:summary => "This episode is dedicated to Sue.",
|
68
|
+
:time => Time.parse("April 21, 2010 6:24pm CDT").utc,
|
69
|
+
:title => "Episode 128",
|
70
|
+
:url => "http://example.com/episodes/128.mp3",
|
71
|
+
}, {
|
72
|
+
:author => "Ms. Sue Example",
|
73
|
+
:duration => "256",
|
74
|
+
:file_size => "92912",
|
75
|
+
:filename => "episode-129.mp3",
|
76
|
+
:guid => "http://example.com/episodes/129.html",
|
77
|
+
:image_url => "http://example.com/episodes/129.png",
|
78
|
+
:keywords => [ "sue", "example", "two" ],
|
79
|
+
:mime_type => "audio/mp3",
|
80
|
+
:subtitle => "Sue's second episode, it's great!",
|
81
|
+
:summary => "This second episode is dedicated to Sue.",
|
82
|
+
:time => Time.parse("April 22, 2010 6:24pm CDT").utc,
|
83
|
+
:title => "Episode 129",
|
84
|
+
:url => "http://example.com/episodes/129.mp3",
|
85
|
+
}],
|
86
|
+
})
|
87
|
+
|
88
|
+
expected_xml = <<-XML.gsub(/^\s{6}/, "")
|
89
|
+
<?xml version="1.0"?>
|
90
|
+
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
|
91
|
+
<channel>
|
92
|
+
<title>Bob's EXTREME Podcast</title>
|
93
|
+
<link>http://example.com/podcast.xml</link>
|
94
|
+
<description>This is Bob's podcast. Do not mess with Bob.</description>
|
95
|
+
<itunes:summary>This is Bob's podcast. Do not mess with Bob.</itunes:summary>
|
96
|
+
<itunes:image href="http://example.com/podcast.png"/>
|
97
|
+
<generator>Podcastinator #{ Podcastinator::VERSION }</generator>
|
98
|
+
<language>English</language>
|
99
|
+
<copyright>Copyright 2001 Bob Example Inc</copyright>
|
100
|
+
<subtitle>Don't mess with the bob.</subtitle>
|
101
|
+
<author>Mr. Bob Example</author>
|
102
|
+
<itunes:keywords>bob,example</itunes:keywords>
|
103
|
+
<itunes:owner>
|
104
|
+
<itunes:name>Bob Example</itunes:name>
|
105
|
+
<itunes:email>bob@example.com</itunes:email>
|
106
|
+
</itunes:owner>
|
107
|
+
<item>
|
108
|
+
<title>Episode 128</title>
|
109
|
+
<itunes:author>Sue Example</itunes:author>
|
110
|
+
<itunes:subtitle>Sue's episode, it's great!</itunes:subtitle>
|
111
|
+
<itunes:summary>This episode is dedicated to Sue.</itunes:summary>
|
112
|
+
<itunes:image href="http://example.com/episodes/128.png"/>
|
113
|
+
<enclosure url="http://example.com/episodes/128.mp3" length="92812" type="audio/mp3"/>
|
114
|
+
<guid isPermaLink="true">http://example.com/episodes/128.html</guid>
|
115
|
+
<pubDate>2010-04-21T23:24:00Z</pubDate>
|
116
|
+
<itunes:duration>127</itunes:duration>
|
117
|
+
<itunes:keywords>sue,example</itunes:keywords>
|
118
|
+
</item>
|
119
|
+
<item>
|
120
|
+
<title>Episode 129</title>
|
121
|
+
<itunes:author>Ms. Sue Example</itunes:author>
|
122
|
+
<itunes:subtitle>Sue's second episode, it's great!</itunes:subtitle>
|
123
|
+
<itunes:summary>This second episode is dedicated to Sue.</itunes:summary>
|
124
|
+
<itunes:image href="http://example.com/episodes/129.png"/>
|
125
|
+
<enclosure url="http://example.com/episodes/129.mp3" length="92912" type="audio/mp3"/>
|
126
|
+
<guid isPermaLink="true">http://example.com/episodes/129.html</guid>
|
127
|
+
<pubDate>2010-04-22T23:24:00Z</pubDate>
|
128
|
+
<itunes:duration>256</itunes:duration>
|
129
|
+
<itunes:keywords>sue,example,two</itunes:keywords>
|
130
|
+
</item>
|
131
|
+
</channel>
|
132
|
+
</rss>
|
133
|
+
XML
|
134
|
+
|
135
|
+
generated_xml = Podcastinator::Generator.new(feed).to_xml
|
136
|
+
|
137
|
+
assert_equal expected_xml.strip, generated_xml.strip
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: podcastinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex McHale
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
2Aa+tn7z9Ygivb+IdwitCXQvFHxKDtL4oDy/tbnByulZuuZsWz3FNO/U3YDk7ZnY
|
31
31
|
Y9/a+THXdusIEEFRYgFvTJo3zjcsl9tL
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2014-09
|
33
|
+
date: 2014-10-09 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: nokogiri
|
@@ -102,6 +102,20 @@ dependencies:
|
|
102
102
|
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: '10.3'
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: minitest
|
107
|
+
requirement: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '5.4'
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '5.4'
|
105
119
|
description: A ruby library for generating podcast feeds from a source or via an API.
|
106
120
|
email:
|
107
121
|
- alex@anticlever.com
|
@@ -119,9 +133,12 @@ files:
|
|
119
133
|
- lib/podcastinator.rb
|
120
134
|
- lib/podcastinator/extensions.rb
|
121
135
|
- lib/podcastinator/feed.rb
|
136
|
+
- lib/podcastinator/file_feed.rb
|
122
137
|
- lib/podcastinator/generator.rb
|
123
138
|
- lib/podcastinator/version.rb
|
124
139
|
- podcastinator.gemspec
|
140
|
+
- test/generated_feed_test.rb
|
141
|
+
- test/test_helper.rb
|
125
142
|
homepage: http://github.com/alexmchale/podcastinator
|
126
143
|
licenses:
|
127
144
|
- MIT
|
@@ -146,5 +163,6 @@ rubygems_version: 2.2.2
|
|
146
163
|
signing_key:
|
147
164
|
specification_version: 4
|
148
165
|
summary: A ruby library for generating podcast feeds.
|
149
|
-
test_files:
|
150
|
-
|
166
|
+
test_files:
|
167
|
+
- test/generated_feed_test.rb
|
168
|
+
- test/test_helper.rb
|
metadata.gz.sig
CHANGED
Binary file
|