bercow 0.0.1

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.
@@ -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/>
@@ -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
@@ -0,0 +1 @@
1
+ require 'bach/version'
@@ -0,0 +1,3 @@
1
+ module Bercow
2
+ VERSION = '0.0.1'
3
+ end
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: []