bercow 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +31 -0
- data/bin/bercow +93 -0
- data/lib/bercow.rb +1 -0
- data/lib/bercow/version.rb +3 -0
- metadata +74 -0
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Bercow
|
2
|
+
|
3
|
+
Convert an RSS feed to a Podcast suitable for subscribing to in iTunes.
|
4
|
+
|
5
|
+
## Installing
|
6
|
+
|
7
|
+
You need to setup [King](https://github.com/craigw/king) and the dependencies
|
8
|
+
for that.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
I make a few assumptions for this example:
|
13
|
+
|
14
|
+
* That King is running at `http://10.0.1.200:4567/`.
|
15
|
+
* That your mp3 files will be hosted under `http://example.com/media/`.
|
16
|
+
* That your RSS feed is available at `http://blog.example.com/rss.xml`.
|
17
|
+
|
18
|
+
Run Bercow like this:
|
19
|
+
|
20
|
+
bercow \
|
21
|
+
--king http://10.0.1.200:4567/ \
|
22
|
+
--host http://example.com/media/ \
|
23
|
+
--rss http://blog.example.com/rss.xml \
|
24
|
+
--cache /var/www/example.com/htdocs/media
|
25
|
+
|
26
|
+
Obviously you'll need to put your own locations in for these options.
|
27
|
+
|
28
|
+
|
29
|
+
## Authors
|
30
|
+
|
31
|
+
Craig R Webster <http://barkingiguana.com/>
|
data/bin/bercow
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require "getoptlong"
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'cgi'
|
8
|
+
|
9
|
+
options = {}
|
10
|
+
argv = GetoptLong.new(
|
11
|
+
[ "--broker", "-b", GetoptLong::OPTIONAL_ARGUMENT ],
|
12
|
+
[ "--rss", "-r", GetoptLong::REQUIRED_ARGUMENT ],
|
13
|
+
[ "--cache", "-c", GetoptLong::OPTIONAL_ARGUMENT ],
|
14
|
+
[ "--host", "-h", GetoptLong::REQUIRED_ARGUMENT ],
|
15
|
+
[ "--king", "-k", GetoptLong::OPTIONAL_ARGUMENT ],
|
16
|
+
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ]
|
17
|
+
)
|
18
|
+
argv.each do |option, value|
|
19
|
+
options['broker'] = value if option == '--broker'
|
20
|
+
options['rss'] = value if option == '--rss'
|
21
|
+
options['cache'] = value if option == '--cache'
|
22
|
+
options['host'] = value if option == '--host'
|
23
|
+
options['king'] = value if option == '--king'
|
24
|
+
options['verbose'] = true if option == '--verbose'
|
25
|
+
end
|
26
|
+
options['broker'] ||= 'stomp://127.0.0.1:61613'
|
27
|
+
options['king'] ||= 'http://127.0.0.1:4567/'
|
28
|
+
options['cache'] ||= File.expand_path('../tmp/cache', File.basename(__FILE__))
|
29
|
+
|
30
|
+
unless File.exists? options['cache']
|
31
|
+
puts "The cache directory does not exist: #{options['cache']}"
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
|
35
|
+
remove_nodes = %w{
|
36
|
+
content:encoded
|
37
|
+
wfw:commentRss
|
38
|
+
slash:comments
|
39
|
+
description
|
40
|
+
category
|
41
|
+
}
|
42
|
+
|
43
|
+
rss = Nokogiri::XML open(options['rss']).read
|
44
|
+
items = rss.xpath '//channel/item'
|
45
|
+
items.to_a.each do |item|
|
46
|
+
item_link = item.xpath(".//link").to_a[0]
|
47
|
+
item_url = item_link.inner_text.to_s
|
48
|
+
article = CGI.escape item_url
|
49
|
+
url = URI.parse item_url
|
50
|
+
cache_key = Digest::SHA1.hexdigest item_url
|
51
|
+
file_dir = [ url.host, *(cache_key.scan(/(.)/)[0..3]) ].inject(options['cache']) { |a, e|
|
52
|
+
dir = File.join a, e
|
53
|
+
Dir.mkdir dir unless File.exists? dir
|
54
|
+
dir
|
55
|
+
}
|
56
|
+
file_path = File.join file_dir, cache_key + '.mp3'
|
57
|
+
url_path = file_path.gsub /^#{options['cache']}\//, ''
|
58
|
+
file_url = "#{options['host']}#{url_path}"
|
59
|
+
guid = item.xpath(".//guid").to_a[0]
|
60
|
+
guid.content = file_url
|
61
|
+
guid['isPermaLink'] = 'true'
|
62
|
+
remove_nodes.each do |node|
|
63
|
+
item.xpath(node).remove
|
64
|
+
end
|
65
|
+
enclosure = Nokogiri::XML::Node.new 'enclosure', rss
|
66
|
+
enclosure['url'] = file_url
|
67
|
+
enclosure['type'] = "audio/mpeg"
|
68
|
+
item << enclosure
|
69
|
+
next if File.exists? file_path
|
70
|
+
print "Encoding #{item_url}... " if options['verbose']
|
71
|
+
mp3 = open(options['king'] + 'read?url=' + article).read
|
72
|
+
File.open file_path, 'w+' do |f|
|
73
|
+
f.print mp3
|
74
|
+
end
|
75
|
+
puts "#{file_path}" if options['verbose']
|
76
|
+
end
|
77
|
+
|
78
|
+
rss.root.add_namespace_definition 'itunes', 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
79
|
+
|
80
|
+
rss_host = URI.parse(options['rss']).host
|
81
|
+
rss_url = "#{options['host']}#{rss_host}/rss.xml"
|
82
|
+
reference = rss.xpath("//channel/atom:link[@rel = 'self']").to_a[0]
|
83
|
+
reference['href'] = rss_url
|
84
|
+
|
85
|
+
rss_feed = File.join options['cache'], rss_host, 'rss.xml'
|
86
|
+
File.open rss_feed, 'w+' do |f|
|
87
|
+
f.print rss.to_s
|
88
|
+
end
|
89
|
+
|
90
|
+
if options['verbose']
|
91
|
+
iptc_url = rss_url.gsub /^http/, 'iptc'
|
92
|
+
puts "iTunes users can subscribe at #{iptc_url}"
|
93
|
+
end
|
data/lib/bercow.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bach/version'
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bercow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Craig R Webster
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-08 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: stomp
|
16
|
+
requirement: &70179254038080 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70179254038080
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: nokogiri
|
27
|
+
requirement: &70179254030200 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70179254030200
|
36
|
+
description: ''
|
37
|
+
email:
|
38
|
+
- craig@barkingiguana.com
|
39
|
+
executables:
|
40
|
+
- bercow
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- lib/bercow/version.rb
|
45
|
+
- lib/bercow.rb
|
46
|
+
- bin/bercow
|
47
|
+
- README.md
|
48
|
+
homepage:
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements:
|
67
|
+
- A broker capable of talking Stomp
|
68
|
+
- A King server
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.8.10
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: ''
|
74
|
+
test_files: []
|