opds_monster 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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +2 -0
- data/bin/monster +50 -0
- data/lib/opds_monster.rb +17 -0
- data/lib/opds_monster/feed.rb +33 -0
- data/lib/opds_monster/feed_item.rb +35 -0
- data/lib/opds_monster/version.rb +3 -0
- data/opds_monster.gemspec +22 -0
- metadata +90 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# OPDS MONSTER
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
OPDS Monster is a tool for downloading books from an OPDS feed. It was started on Halloween night 2011 by [Nick Rowe](http://dcxn.com). It's a treat, though, don't worry. I originally wrote this so I could easily download my [Pragmatic Programmer bookshelf](http://pragprog.com). It might also make an interesting cron job to mirror project gutenberg.
|
6
|
+
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
1. Install the gem `gem install opds_monster`
|
11
|
+
2. `monster http://example.com/feed`
|
12
|
+
|
13
|
+
This will download all of the books from the example feed to the current working directory.
|
14
|
+
|
15
|
+
|
16
|
+
## Authenticated Feeds
|
17
|
+
|
18
|
+
`monster http://pragprog.com/my_bookshelf.opds -u USER -p PASS`
|
19
|
+
|
20
|
+
Some feeds, like the Pragmatic Programmer Feed are authenticated using HTTP Basic Authentication. Adding a user and password should take care of that.
|
21
|
+
|
22
|
+
## And the rest
|
23
|
+
|
24
|
+
opds monster supports some other options too:
|
25
|
+
|
26
|
+
|
27
|
+
Usage: monster [options] feed
|
28
|
+
-u, --username USER HTTP basic authentication user name
|
29
|
+
-p, --password PASS HTTP basic authentication password
|
30
|
+
-q, --quiet Quiet Output
|
31
|
+
-h, --help Display this screen
|
32
|
+
-v, --version monster version
|
33
|
+
|
34
|
+
|
35
|
+
## Credits
|
36
|
+
Photo: [Look I'm a monster...AAAARGH! by JeHu6](http://www.flickr.com/photos/33850040@N02/3736706784/) under CC license.
|
data/Rakefile
ADDED
data/bin/monster
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
|
4
|
+
require 'opds_monster'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
optparse = OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: monster [options] feed"
|
11
|
+
|
12
|
+
opts.on( '-u', '--username USER', 'HTTP basic authentication user name' ) do |user|
|
13
|
+
options[:username] = user
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on( '-p', '--password PASS', 'HTTP basic authentication password' ) do |password|
|
17
|
+
options[:password] = password
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on( '-q', '--quiet', 'Quiet Output' ) do
|
21
|
+
options[:quiet] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
25
|
+
puts opts
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on( '-v', '--version', 'monster version' ) do
|
30
|
+
puts "opds monster version #{OpdsMonster::VERSION}"
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
optparse.parse!
|
36
|
+
|
37
|
+
abort "monster requires an opds feed url" if ARGV[0].nil?
|
38
|
+
|
39
|
+
url = ARGV[0]
|
40
|
+
feed = OpdsMonster::Feed.new(url, :username => options[:username], :password => options[:password])
|
41
|
+
feed.download_all_items do |item, success|
|
42
|
+
puts "downloaded: #{item.title}" unless options[:quiet]
|
43
|
+
end
|
44
|
+
|
45
|
+
# puts feed.items.count
|
46
|
+
# puts feed.items.count
|
47
|
+
#
|
48
|
+
# feed = Feed.new("http://bookserver.archive.org/catalog/downloads.xml", :username => '', :password => '')
|
49
|
+
# puts feed.items.count
|
50
|
+
|
data/lib/opds_monster.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'atom'
|
3
|
+
require 'curb'
|
4
|
+
|
5
|
+
require 'opds_monster/version'
|
6
|
+
require 'opds_monster/feed'
|
7
|
+
require 'opds_monster/feed_item'
|
8
|
+
|
9
|
+
|
10
|
+
# feed = OpdsMonster::Feed.new("http://pragprog.com/my_bookshelf.opds", :username => 'nixterrimus@gmail.com', :password => '6aS^7qVJej')
|
11
|
+
# puts feed.items.count
|
12
|
+
# feed.download_all_items
|
13
|
+
# puts feed.items.count
|
14
|
+
# puts feed.items.count
|
15
|
+
#
|
16
|
+
# feed = Feed.new("http://bookserver.archive.org/catalog/downloads.xml", :username => '', :password => '')
|
17
|
+
# puts feed.items.count
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module OpdsMonster
|
2
|
+
class Feed
|
3
|
+
attr_reader :feed_url
|
4
|
+
attr_accessor :feed_items
|
5
|
+
attr_accessor :username
|
6
|
+
attr_accessor :password
|
7
|
+
|
8
|
+
def initialize(feed_url, options = {})
|
9
|
+
@feed_url = feed_url
|
10
|
+
@feed_items = []
|
11
|
+
@username = options[:username]
|
12
|
+
self.password = options[:password]
|
13
|
+
end
|
14
|
+
|
15
|
+
def items
|
16
|
+
return self.feed_items unless feed_items.empty?
|
17
|
+
feed = Atom::Feed.load_feed(URI.parse(feed_url), :user => username, :pass => password)
|
18
|
+
self.feed_items = feed.each_entry.collect { |entry| FeedItem.new(entry) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def download_all_items
|
22
|
+
items.each do |item|
|
23
|
+
item.download(:username => username, :password => password)
|
24
|
+
yield item, true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def authentication_required?
|
29
|
+
username.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module OpdsMonster
|
2
|
+
class FeedItem
|
3
|
+
attr_reader :title
|
4
|
+
def initialize(atom_entry)
|
5
|
+
@title = atom_entry.title
|
6
|
+
@links = atom_entry.links
|
7
|
+
end
|
8
|
+
|
9
|
+
def download(options = {})
|
10
|
+
links_to_download.each do |link|
|
11
|
+
download_http_file(link, options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def links_to_download
|
18
|
+
@links.collect { |l| l.to_s if l.rel =~ /http:\/\/opds-spec.org\/acquisition/ }.compact!
|
19
|
+
end
|
20
|
+
|
21
|
+
def download_http_file(url, options)
|
22
|
+
c = Curl::Easy.new(url)
|
23
|
+
c.http_auth_types = :basic
|
24
|
+
c.username = options[:username]
|
25
|
+
c.password = options[:password]
|
26
|
+
c.follow_location = true
|
27
|
+
c.max_redirects = 10
|
28
|
+
c.perform
|
29
|
+
filename = url.split("/").last
|
30
|
+
open(filename, "wb") do |file|
|
31
|
+
file.write(c.body_str)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "opds_monster/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "opds_monster"
|
7
|
+
s.version = OpdsMonster::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Nick Rowe"]
|
10
|
+
s.email = ["nixterrimus@dcxn.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Download OPDS feeds}
|
13
|
+
s.description = %q{A command line tool to download opds feeds}
|
14
|
+
|
15
|
+
s.rubyforge_project = "opds_monster"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.add_dependency "ratom"
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opds_monster
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Nick Rowe
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-10-31 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: ratom
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: A command line tool to download opds feeds
|
36
|
+
email:
|
37
|
+
- nixterrimus@dcxn.com
|
38
|
+
executables:
|
39
|
+
- monster
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- Gemfile
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- bin/monster
|
50
|
+
- lib/opds_monster.rb
|
51
|
+
- lib/opds_monster/feed.rb
|
52
|
+
- lib/opds_monster/feed_item.rb
|
53
|
+
- lib/opds_monster/version.rb
|
54
|
+
- opds_monster.gemspec
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: ""
|
57
|
+
licenses: []
|
58
|
+
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project: opds_monster
|
85
|
+
rubygems_version: 1.6.2
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Download OPDS feeds
|
89
|
+
test_files: []
|
90
|
+
|