rubypodder 0.1.0
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.
- data/MIT-LICENSE +20 -0
- data/README +69 -0
- data/Rakefile +27 -0
- data/bin/rubypodder +2 -0
- data/lib/rubypodder.rb +113 -0
- data/tests/tc_rubypodder.rb +199 -0
- metadata +57 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 Lex Miller
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
= rubypodder - A podcast aggregator without an interface
|
2
|
+
|
3
|
+
This package contains rubypodder, a simple podcast receiver
|
4
|
+
inspired by bashpodder (http://linc.homeunix.org:8080/scripts/bashpodder/).
|
5
|
+
|
6
|
+
== Download
|
7
|
+
|
8
|
+
The latest version of rubypodder can be found at
|
9
|
+
|
10
|
+
http://rubyforge.org/projects/rubypodder/
|
11
|
+
|
12
|
+
== Installation
|
13
|
+
|
14
|
+
Place the rubypodder gem in your local repository and install with
|
15
|
+
the following:
|
16
|
+
|
17
|
+
gem install rubypodder
|
18
|
+
|
19
|
+
== Quick Start
|
20
|
+
|
21
|
+
Type
|
22
|
+
|
23
|
+
rubypodder
|
24
|
+
|
25
|
+
When it finishes, you should see a ~/.rubypodder directory.
|
26
|
+
This should contain an example rp.conf configuration file with a feed in
|
27
|
+
it to get you started. If there were any podcasts to download in the feed
|
28
|
+
they will be in a directory named after the date (e.g. 2007-01-20).
|
29
|
+
You can see what happened by looking in rp.log.
|
30
|
+
|
31
|
+
== Running the rubypodder Test Suite
|
32
|
+
|
33
|
+
If you wish to run the unit tests that come with rubypodder:
|
34
|
+
|
35
|
+
gem check rubypodder --test
|
36
|
+
|
37
|
+
A message will be given if any of the tests fail.
|
38
|
+
|
39
|
+
=== Uninstallation
|
40
|
+
|
41
|
+
To uninstall the rubypodder gem use:
|
42
|
+
|
43
|
+
gem uninstall rubypodder
|
44
|
+
|
45
|
+
== Configuration
|
46
|
+
|
47
|
+
Create a file +~/.rubypodder/rp.conf+ containing podcast feeds, one per line.
|
48
|
+
|
49
|
+
== Usage
|
50
|
+
|
51
|
+
Type
|
52
|
+
|
53
|
+
rubypodder
|
54
|
+
|
55
|
+
and if there are any podcast episodes from your feeds that have not yet
|
56
|
+
been downloaded, they will be downloaded into a "date" directory such as
|
57
|
+
+~/.rubypodder/2007-01-18/+
|
58
|
+
|
59
|
+
A good idea is to use +crontab -e+ and add a line like
|
60
|
+
+0 5 * * * rubypodder+
|
61
|
+
which will set up a cron job which will do
|
62
|
+
this regularly.
|
63
|
+
|
64
|
+
== License
|
65
|
+
|
66
|
+
rubypodder is available under an MIT-style license.
|
67
|
+
|
68
|
+
:include: MIT-LICENSE
|
69
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
Gem::manage_gems
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
spec = Gem::Specification.new do |s|
|
5
|
+
s.platform = Gem::Platform::RUBY
|
6
|
+
s.name = "rubypodder"
|
7
|
+
s.version = "0.1.0"
|
8
|
+
s.author = "Lex Miller"
|
9
|
+
s.email = "lex.miller @nospam@ gmail.com"
|
10
|
+
s.summary = "A podcast aggregator without an interface"
|
11
|
+
s.files = FileList['lib/*.rb', 'tests/*', 'Rakefile'].to_a
|
12
|
+
s.require_path = "lib"
|
13
|
+
s.bindir = "bin"
|
14
|
+
s.executables = ["rubypodder"]
|
15
|
+
s.default_executable = "rubypodder"
|
16
|
+
s.autorequire = "rubypodder"
|
17
|
+
s.add_dependency("rio")
|
18
|
+
s.test_files = Dir.glob('tests/*.rb')
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = ["README", "MIT-LICENSE"]
|
21
|
+
end
|
22
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
23
|
+
pkg.need_tar = true
|
24
|
+
end
|
25
|
+
task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
|
26
|
+
puts "generated latest version"
|
27
|
+
end
|
data/bin/rubypodder
ADDED
data/lib/rubypodder.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'rss/1.0'
|
2
|
+
require 'rss/2.0'
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rio'
|
7
|
+
require 'logger'
|
8
|
+
require 'ftools'
|
9
|
+
|
10
|
+
class File
|
11
|
+
|
12
|
+
def self.touch(fn)
|
13
|
+
File.open(fn, "w").close unless File.exist?(fn)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class RubyPodder
|
19
|
+
|
20
|
+
attr_reader :conf_file, :log_file, :done_file, :date_dir
|
21
|
+
|
22
|
+
def initialize(file_base="~/.rubypodder/rp")
|
23
|
+
@file_base = File.expand_path(file_base)
|
24
|
+
@rp_dir = File.dirname(@file_base)
|
25
|
+
@conf_file = @file_base + ".conf"
|
26
|
+
@log_file = @file_base + ".log"
|
27
|
+
@done_file = @file_base + ".done"
|
28
|
+
create_default_config_file
|
29
|
+
@log = Logger.new(@log_file)
|
30
|
+
File.touch @done_file
|
31
|
+
@date_dir = create_date_dir
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_default_config_file
|
35
|
+
expanded_path = File.expand_path(@conf_file)
|
36
|
+
return if File.exists?(expanded_path)
|
37
|
+
make_dirname(expanded_path)
|
38
|
+
rio(expanded_path) < "http://downloads.bbc.co.uk/rmhttp/downloadtrial/radio4/thenowshow/rss.xml"
|
39
|
+
end
|
40
|
+
|
41
|
+
def make_dirname(full_filename)
|
42
|
+
dirname = File.dirname(full_filename)
|
43
|
+
File.makedirs dirname
|
44
|
+
end
|
45
|
+
|
46
|
+
def date_string(time)
|
47
|
+
time.strftime("%Y-%m-%d")
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_date_dir
|
51
|
+
date_dir = @rp_dir + "/" + date_string(Time.now)
|
52
|
+
File.makedirs date_dir
|
53
|
+
date_dir
|
54
|
+
end
|
55
|
+
|
56
|
+
def read_feeds
|
57
|
+
IO.readlines(@conf_file).each {|l| l.chomp!}
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_rss(rss_source)
|
61
|
+
RSS::Parser.parse(rss_source, false)
|
62
|
+
end
|
63
|
+
|
64
|
+
def dest_file_name(url)
|
65
|
+
@date_dir + "/" + File.basename(URI.parse(url).path)
|
66
|
+
end
|
67
|
+
|
68
|
+
def record_download(url)
|
69
|
+
rio(@done_file) << "#{url}\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
def already_downloaded(url)
|
73
|
+
url_regexp = Regexp.new(url)
|
74
|
+
File.open(@done_file).grep(url_regexp).length > 0
|
75
|
+
end
|
76
|
+
|
77
|
+
def download(url)
|
78
|
+
return if already_downloaded(url)
|
79
|
+
@log.info(" Downloading: #{url}")
|
80
|
+
file_name = dest_file_name(url)
|
81
|
+
rio(file_name) < rio(url)
|
82
|
+
record_download(url)
|
83
|
+
end
|
84
|
+
|
85
|
+
def remove_dir_if_empty(dirname)
|
86
|
+
begin
|
87
|
+
Dir.rmdir(dirname)
|
88
|
+
rescue SystemCallError
|
89
|
+
@log.info("#{dirname} has contents, not removed")
|
90
|
+
else
|
91
|
+
@log.info("#{dirname} was empty, removed")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def run
|
96
|
+
@log.info("Starting")
|
97
|
+
read_feeds.each do |url|
|
98
|
+
http_body = rio(url).contents
|
99
|
+
rss = parse_rss(http_body)
|
100
|
+
@log.info("Channel: #{rss.channel.title}")
|
101
|
+
rss.items.each do |item|
|
102
|
+
download(item.enclosure.url)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
remove_dir_if_empty(@date_dir)
|
106
|
+
@log.info("Finished")
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
if $0 == __FILE__
|
112
|
+
RubyPodder.new.run
|
113
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rubypodder'
|
4
|
+
|
5
|
+
class TC_RubyPodder < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
system("rm -rf " + "/tmp/test_rp.conf")
|
9
|
+
system("rm -rf " + "/tmp/test_rp.done")
|
10
|
+
File.open("/tmp/test_rp.conf", "w") do |file|
|
11
|
+
file.write("http://downloads.bbc.co.uk/rmhttp/downloadtrial/radio4/thenowshow/rss.xml\n")
|
12
|
+
file.write("http://www.guardian.co.uk/podcasts/comedy/rickygervais/mp3.xml")
|
13
|
+
end
|
14
|
+
@subdir = "/tmp/subdir"
|
15
|
+
system("rm -rf " + @subdir)
|
16
|
+
@rp = RubyPodder.new("/tmp/test_rp")
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
system("rm -rf " + "/tmp/test_rp.conf")
|
21
|
+
system("rm -rf " + "/tmp/test_rp.done")
|
22
|
+
system("rm -rf " + "/tmp/test_rp.log")
|
23
|
+
system("rm -rf " + "/tmp/#{@rp.date_string(Time.now)}")
|
24
|
+
system("rm -rf " + @subdir)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_initialize_with_test_config_file
|
29
|
+
assert_kind_of(RubyPodder, @rp)
|
30
|
+
assert_equal("/tmp/test_rp.conf", @rp.conf_file)
|
31
|
+
assert_equal("/tmp/test_rp.log", @rp.log_file)
|
32
|
+
assert_equal("/tmp/test_rp.done", @rp.done_file)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_initialize_with_default_config_file
|
36
|
+
ENV['HOME'] = "/tmp"
|
37
|
+
@rp = RubyPodder.new()
|
38
|
+
assert_kind_of(RubyPodder, @rp)
|
39
|
+
assert_equal(ENV['HOME'] + "/.rubypodder/rp.conf", @rp.conf_file)
|
40
|
+
assert_equal(ENV['HOME'] + "/.rubypodder/rp.log", @rp.log_file)
|
41
|
+
assert_equal(ENV['HOME'] + "/.rubypodder/rp.done", @rp.done_file)
|
42
|
+
system("rm -rf " + "/tmp/.rubypodder")
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_initialize_with_absent_config_file
|
46
|
+
file_base = "/tmp/test_rp"
|
47
|
+
file_conf = file_base + ".conf"
|
48
|
+
system("rm -rf " + file_conf)
|
49
|
+
@rp = RubyPodder.new(file_base)
|
50
|
+
assert(File.exists?(file_conf))
|
51
|
+
system("rm -rf " + file_conf)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_make_dirname_one_subdir
|
55
|
+
filename = @subdir + "/file"
|
56
|
+
@rp.make_dirname(filename)
|
57
|
+
assert(File.exists?(@subdir))
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_make_dirname_many_subdir
|
61
|
+
subsubdirs = "/subsubdir/subsubsubdir"
|
62
|
+
filename = @subdir + subsubdirs + "/file"
|
63
|
+
@rp.make_dirname(filename)
|
64
|
+
assert(File.exists?(@subdir + subsubdirs))
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_date_string
|
68
|
+
t = Time.gm(2006,"dec",18,21,0,0)
|
69
|
+
date_string = @rp.date_string(t)
|
70
|
+
assert_equal(date_string, "2006-12-18")
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_initialize_with_absent_config_file_dir
|
74
|
+
file_base = @subdir + "/test_rp"
|
75
|
+
file_conf = file_base + ".conf"
|
76
|
+
@rp = RubyPodder.new(file_base)
|
77
|
+
assert(File.exists?(file_conf))
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_initialize_creates_date_dir
|
81
|
+
file_base = @subdir + "/test_rp"
|
82
|
+
@rp = RubyPodder.new(file_base)
|
83
|
+
date_dir = @subdir + "/" + @rp.date_string(Time.now)
|
84
|
+
assert_equal(date_dir, @rp.date_dir)
|
85
|
+
assert(File.exists?(date_dir), "Subdirectory #{date_dir} not created")
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_read_feeds
|
89
|
+
feed_list = @rp.read_feeds
|
90
|
+
assert_kind_of(Array, feed_list)
|
91
|
+
assert_equal(2, feed_list.length)
|
92
|
+
assert_equal("http://downloads.bbc.co.uk/rmhttp/downloadtrial/radio4/thenowshow/rss.xml", feed_list[0])
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_parse_rss
|
96
|
+
#rss_source = IO.read("test_feed.xml")
|
97
|
+
rss_source = <<-END_OF_STRING
|
98
|
+
<?xml version="1.0" encoding="utf-8"?>
|
99
|
+
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
|
100
|
+
<channel>
|
101
|
+
<lastBuildDate>Fri, 27 Oct 2006 16:50:15 +0100</lastBuildDate>
|
102
|
+
<title>The Ricky Gervais Show</title>
|
103
|
+
<itunes:author>Guardian Unlimited</itunes:author>
|
104
|
+
<link>http://www.guardian.co.uk/rickygervais</link>
|
105
|
+
<generator>Podcast Maker v1.2.4 - http://www.potionfactory.com/podcastmaker</generator>
|
106
|
+
<description>Ricky Gervais, Steve Merchant and Karl Pilkington are back yada yada</description>
|
107
|
+
<itunes:subtitle />
|
108
|
+
<itunes:summary>Ricky Gervais, Steve Merchant and Karl Pilkington are back yada yada</itunes:summary>
|
109
|
+
<language>en</language>
|
110
|
+
<copyright>Ricky Gervais, Steve Merchant, Karl Pilkington</copyright>
|
111
|
+
<itunes:owner>
|
112
|
+
<itunes:name>Glyn Hughes</itunes:name>
|
113
|
+
<itunes:email>glyn@rickygervais.com</itunes:email>
|
114
|
+
</itunes:owner>
|
115
|
+
<image>
|
116
|
+
<url>http://podcast.rickygervais.com/gu_p123_300_144.jpg</url>
|
117
|
+
<title>The Ricky Gervais Show</title>
|
118
|
+
<link>http://www.guardian.co.uk/rickygervais</link>
|
119
|
+
<width>144</width>
|
120
|
+
<height>144</height>
|
121
|
+
</image>
|
122
|
+
<itunes:image href="http://podcast.rickygervais.com/gu_p123_300.jpg" />
|
123
|
+
<category>Comedy</category>
|
124
|
+
<itunes:category text="Comedy" />
|
125
|
+
<itunes:keywords>Ricky, Gervais, Steve, Merchant, Karl, Pilkington</itunes:keywords>
|
126
|
+
<itunes:explicit>yes</itunes:explicit>
|
127
|
+
<item>
|
128
|
+
<title>The Podfather Part I - Halloween</title>
|
129
|
+
<itunes:author>Guardian Unlimited</itunes:author>
|
130
|
+
<description>The first of three specials from Ricky, Steve and Karl yada yada</description>
|
131
|
+
<itunes:subtitle>The first of three specials from Ricky, Steve and Karl yada yada</itunes:subtitle>
|
132
|
+
<itunes:summary />
|
133
|
+
<enclosure type="audio/mpeg" url="http://podcast.rickygervais.com/guspecials_halloween.mp3" length="15723925" />
|
134
|
+
<guid>http://podcast.rickygervais.com/guspecials_halloween.mp3</guid>
|
135
|
+
<pubDate>Tue, 31 Oct 2006 00:00:01 +0000</pubDate>
|
136
|
+
<category>Comedy</category>
|
137
|
+
<itunes:explicit>yes</itunes:explicit>
|
138
|
+
<itunes:duration>00:37:22</itunes:duration>
|
139
|
+
<itunes:keywords>Ricky, Gervais, Steve, Merchant, Karl, Pilkington</itunes:keywords>
|
140
|
+
</item>
|
141
|
+
</channel>
|
142
|
+
</rss>
|
143
|
+
END_OF_STRING
|
144
|
+
rss = @rp.parse_rss(rss_source)
|
145
|
+
assert_equal(1, rss.items.length)
|
146
|
+
assert_equal("http://podcast.rickygervais.com/guspecials_halloween.mp3", rss.items[0].enclosure.url)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_dest_file_name(url)
|
150
|
+
correct_dest_file_name = @rp.date_dir + "/" + "podcast.mp3"
|
151
|
+
dest_file_name = @rp.dest_file_name("http://www.podcast.com/podcast.mp3")
|
152
|
+
assert_equal(correct_dest_file_name, dest_file_name)
|
153
|
+
dest_file_name = @rp.dest_file_name("http://www.podcast.com/subdir/podcast.mp3")
|
154
|
+
assert_equal(correct_dest_file_name, dest_file_name)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_download
|
158
|
+
@rp.download("http://www.google.com/index.html")
|
159
|
+
dest_file = @rp.date_dir + "/" + "index.html"
|
160
|
+
assert(File.exists?(dest_file))
|
161
|
+
assert(File.open(dest_file).grep(/google/))
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_download_recorded
|
165
|
+
@rp.download("http://www.google.com/index.html")
|
166
|
+
assert(File.exists?(@rp.done_file))
|
167
|
+
assert(File.open(@rp.done_file).grep(/^http:\/\/www.google.com\/index.html$/))
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_already_downloaded
|
171
|
+
url1 = "http://www.google.com/index.html"
|
172
|
+
assert(!@rp.already_downloaded(url1), "url1 should not be already downloaded before download of url1")
|
173
|
+
@rp.download(url1)
|
174
|
+
assert(@rp.already_downloaded(url1), "url1 should be already downloaded after download of url1")
|
175
|
+
url2 = "http://www.google.co.nz/index.html"
|
176
|
+
@rp.download(url2)
|
177
|
+
assert(@rp.already_downloaded(url2), "url2 should be already downloaded after download of url2")
|
178
|
+
assert(@rp.already_downloaded(url1), "url1 should still be already downloaded after download of url2")
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_download_omits_done_items
|
182
|
+
@rp.download("http://www.google.com/index.html")
|
183
|
+
dest_file = @rp.date_dir + "/" + "index.html"
|
184
|
+
system("rm -rf " + dest_file)
|
185
|
+
@rp.download("http://www.google.com/index.html")
|
186
|
+
assert(!File.exists?(dest_file))
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_remove_dir_if_empty
|
190
|
+
system("mkdir -p " + @subdir)
|
191
|
+
@rp.remove_dir_if_empty(@subdir)
|
192
|
+
assert(!File.exists?(@subdir))
|
193
|
+
system("mkdir -p " + @subdir)
|
194
|
+
system("touch " + @subdir + "/fish")
|
195
|
+
@rp.remove_dir_if_empty(@subdir)
|
196
|
+
assert(File.exists?(@subdir))
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: rubypodder
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-01-20 00:00:00 +13:00
|
8
|
+
summary: A podcast aggregator without an interface
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: lex.miller @nospam@ gmail.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: rubypodder
|
16
|
+
default_executable: rubypodder
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Lex Miller
|
31
|
+
files:
|
32
|
+
- lib/rubypodder.rb
|
33
|
+
- tests/tc_rubypodder.rb
|
34
|
+
- Rakefile
|
35
|
+
- README
|
36
|
+
- MIT-LICENSE
|
37
|
+
test_files:
|
38
|
+
- tests/tc_rubypodder.rb
|
39
|
+
rdoc_options: []
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README
|
42
|
+
- MIT-LICENSE
|
43
|
+
executables:
|
44
|
+
- rubypodder
|
45
|
+
extensions: []
|
46
|
+
requirements: []
|
47
|
+
dependencies:
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rio
|
50
|
+
version_requirement:
|
51
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
52
|
+
requirements:
|
53
|
+
-
|
54
|
+
- ">"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.0.0
|
57
|
+
version:
|