podcastinator 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|