das_catalog 0.0.2
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/LICENSE +20 -0
- data/README.md +65 -0
- data/bin/das_catalog_sync +24 -0
- data/lib/das_catalog/downloader.rb +18 -0
- data/lib/das_catalog/feed.rb +11 -0
- data/lib/das_catalog/screencast.rb +30 -0
- data/lib/das_catalog/screencast_data.rb +43 -0
- data/lib/das_catalog/std_logger.rb +21 -0
- data/lib/das_catalog/store.rb +19 -0
- data/lib/das_catalog/version.rb +3 -0
- data/lib/das_catalog.rb +55 -0
- data/spec/das_catalog_spec.rb +7 -0
- data/spec/das_downloader_spec.rb +6 -0
- data/spec/das_feed_spec.rb +8 -0
- data/spec/das_screencast_data_spec.rb +52 -0
- data/spec/das_screencast_spec.rb +77 -0
- data/spec/das_std_logger_spec.rb +35 -0
- data/spec/das_store_spec.rb +21 -0
- data/spec/spec_helper.rb +22 -0
- metadata +139 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Brendon Murphy
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
Das Catalog
|
2
|
+
===========
|
3
|
+
|
4
|
+
The Das Catalog gem - used for downloading screencasts from the [Destroy All Software screencasts catalog](https://www.destroyallsoftware.com/screencasts). Uses the rss feed plus Mechanize to log you in and then download unsaved movies to a local directory.
|
5
|
+
|
6
|
+
This gem is in not linked to Destroy All Software or endorsed by Gary Bernhardt. I just like his stuff.
|
7
|
+
|
8
|
+
Requirements
|
9
|
+
------------
|
10
|
+
|
11
|
+
I've written and only run the gem on Ruby 1.9.2. YMMV, but 1.8.x will definitely blow up.
|
12
|
+
|
13
|
+
The gem also expects that wget exists in your path, as it uses it for downloaded the movie file.
|
14
|
+
|
15
|
+
Installation
|
16
|
+
------------
|
17
|
+
|
18
|
+
Install the gem
|
19
|
+
|
20
|
+
$ gem install das_catalog
|
21
|
+
|
22
|
+
Usage
|
23
|
+
-----
|
24
|
+
|
25
|
+
Run from the command line:
|
26
|
+
|
27
|
+
$ das_catalog_sync
|
28
|
+
|
29
|
+
It will prompt your for some settings (username, password, storage directory) and then be off and running.
|
30
|
+
|
31
|
+
Stored Configuration
|
32
|
+
--------------------
|
33
|
+
|
34
|
+
If you don't provide configuration, `das_catalog_sync` will prompt you for configuration values when you run it.
|
35
|
+
|
36
|
+
However, you can persist a full or partial config in ~/.das_catalog.yml as such:
|
37
|
+
|
38
|
+
---
|
39
|
+
username: your_username
|
40
|
+
password: your_password
|
41
|
+
downloads_directory: /Users/programmer/Movies/DAS
|
42
|
+
|
43
|
+
If you wish to exclude any config, leave it out and `das_catalog_sync` will prompt your for it at runtime.
|
44
|
+
|
45
|
+
Basic Process
|
46
|
+
-------------
|
47
|
+
|
48
|
+
The steps by which the gem works are fairly simple:
|
49
|
+
|
50
|
+
1. Fetch the rss feed to see what is in the catalog
|
51
|
+
2. Use Mechanize to log in at the DAS sign in page
|
52
|
+
3. Find links in the feed that have not been downloaded yet
|
53
|
+
4. Construct a download link, and grab the location header from the redirect (the movie on S3)
|
54
|
+
5. Offload the download to wget for efficient processing
|
55
|
+
|
56
|
+
TODO
|
57
|
+
----
|
58
|
+
* Finish missing spec coverage (mostly in DasCatalog toplevel namespace)
|
59
|
+
* Hook up Aruba for bin testing
|
60
|
+
* Switch bin to [GLI](https://github.com/davetron5000/gli)?
|
61
|
+
* CLI interface for tracking if you've watched a specific screencast
|
62
|
+
* Make missing directory automatically
|
63
|
+
* better wget detection/warnings
|
64
|
+
* Lighten some dependencies (feed fetching, highline, etc)
|
65
|
+
* Better cli access to modify the underlying pstore
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'highline/import'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", File.dirname(__FILE__))
|
7
|
+
|
8
|
+
require 'das_catalog'
|
9
|
+
|
10
|
+
config_file = File.expand_path("~/.das_catalog.yml")
|
11
|
+
|
12
|
+
config = if File.exists?(config_file)
|
13
|
+
YAML.load_file(config_file)
|
14
|
+
else
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
|
18
|
+
DasCatalog.configure do |c|
|
19
|
+
c.username = config["username"] || ask("Enter your DAS username: ") { |q| q.echo = true }
|
20
|
+
c.password = config["password"] || ask("Enter your DAS password: ") { |q| q.echo = "*" }
|
21
|
+
c.downloads_directory = config["downloads_directory"] || ask("Enter your DAS downloads directory: ") { |q| q.echo = "*" }
|
22
|
+
end
|
23
|
+
|
24
|
+
DasCatalog.sync
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module DasCatalog
|
4
|
+
# TODO spec this
|
5
|
+
class Downloader
|
6
|
+
def self.process(screencast)
|
7
|
+
# Mechanize was choking on large file downloads and keeps them in memory,
|
8
|
+
# outsource to wget
|
9
|
+
agent = DasCatalog.agent
|
10
|
+
agent.redirect_ok = false
|
11
|
+
result = agent.get screencast.download_link
|
12
|
+
url = result.header["location"]
|
13
|
+
url =~ /^http.+?([^\/]+\.mov)\?/
|
14
|
+
output_filename = $1
|
15
|
+
`wget --quiet #{Shellwords.escape url} -O #{DasCatalog.downloads_directory}/#{output_filename}`
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DasCatalog
|
2
|
+
class Screencast
|
3
|
+
extend Forwardable
|
4
|
+
include LoggerAccess
|
5
|
+
|
6
|
+
attr_reader :screencast_data
|
7
|
+
def_delegators :@screencast_data, :watched?, :downloaded?, :download_link
|
8
|
+
|
9
|
+
def initialize(screencast_data)
|
10
|
+
@screencast_data = screencast_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.for_link(link)
|
14
|
+
new ScreencastData.for_link(link)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
screencast_data.link
|
19
|
+
end
|
20
|
+
|
21
|
+
def download
|
22
|
+
return false if screencast_data.downloaded?
|
23
|
+
log.info "Starting download of #{self}"
|
24
|
+
Downloader.process(self)
|
25
|
+
screencast_data.downloaded
|
26
|
+
log.info "Finished download of #{self}"
|
27
|
+
screencast_data.save
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module DasCatalog
|
2
|
+
class ScreencastData
|
3
|
+
attr_reader :link, :watched, :downloaded
|
4
|
+
|
5
|
+
def initialize(link)
|
6
|
+
@link = link
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.for_link(link)
|
10
|
+
Store.find(link) or new(link)
|
11
|
+
end
|
12
|
+
|
13
|
+
alias :id :link
|
14
|
+
|
15
|
+
def download_link
|
16
|
+
"#{link}/download"
|
17
|
+
end
|
18
|
+
|
19
|
+
def downloaded
|
20
|
+
@downloaded = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def downloaded?
|
24
|
+
@downloaded
|
25
|
+
end
|
26
|
+
|
27
|
+
def watched
|
28
|
+
@watched = true
|
29
|
+
end
|
30
|
+
|
31
|
+
def unwatched
|
32
|
+
@watched = false
|
33
|
+
end
|
34
|
+
|
35
|
+
def watched?
|
36
|
+
@watched
|
37
|
+
end
|
38
|
+
|
39
|
+
def save
|
40
|
+
Store.store(self)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'delegate'
|
3
|
+
|
4
|
+
module DasCatalog
|
5
|
+
class StdLogger < DelegateClass(::Logger)
|
6
|
+
def initialize
|
7
|
+
@logger = ::Logger.new(STDOUT)
|
8
|
+
super(@logger)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module LoggerAccess
|
13
|
+
def self.included(klass)
|
14
|
+
klass.extend(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def log
|
18
|
+
DasCatalog.logger
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'pstore'
|
2
|
+
|
3
|
+
module DasCatalog
|
4
|
+
class Store
|
5
|
+
def self.find(id)
|
6
|
+
store = PStore.new(DasCatalog.tracker_file)
|
7
|
+
store.transaction(true) do
|
8
|
+
store[id]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.store(screencast_data)
|
13
|
+
store = PStore.new(DasCatalog.tracker_file)
|
14
|
+
store.transaction do
|
15
|
+
store[screencast_data.id] = screencast_data
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/das_catalog.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
|
3
|
+
module DasCatalog
|
4
|
+
SIGN_IN_URL = "https://www.destroyallsoftware.com/screencasts/users/sign_in"
|
5
|
+
|
6
|
+
# TODO spec this
|
7
|
+
class << self
|
8
|
+
attr_accessor :username
|
9
|
+
attr_accessor :password
|
10
|
+
attr_accessor :downloads_directory
|
11
|
+
|
12
|
+
attr_writer :logger
|
13
|
+
def logger
|
14
|
+
@logger ||= StdLogger.new
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_writer :tracker_file
|
18
|
+
def tracker_file
|
19
|
+
@tracker_file ||= File.expand_path("~/.das_tracker.pstore")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.configure
|
24
|
+
yield self
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO spec this
|
28
|
+
def self.agent
|
29
|
+
@agent ||= begin
|
30
|
+
agent = Mechanize.new
|
31
|
+
page = agent.get SIGN_IN_URL
|
32
|
+
form = page.forms.first
|
33
|
+
form['user[email]'] = username
|
34
|
+
form['user[password]'] = password
|
35
|
+
agent.submit form
|
36
|
+
agent
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO spec this
|
41
|
+
def self.sync
|
42
|
+
feed = Feed.get
|
43
|
+
feed.entries.each do |entry|
|
44
|
+
sc = Screencast.for_link(entry.url)
|
45
|
+
sc.download
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
require_relative "das_catalog/downloader"
|
51
|
+
require_relative "das_catalog/feed"
|
52
|
+
require_relative "das_catalog/std_logger"
|
53
|
+
require_relative "das_catalog/screencast"
|
54
|
+
require_relative "das_catalog/screencast_data"
|
55
|
+
require_relative "das_catalog/store"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe DasCatalog::ScreencastData do
|
4
|
+
let(:link) { "https://www.destroyallsoftware.com/screencasts/catalog/statistics-over-git-repositories" }
|
5
|
+
subject { DasCatalog::ScreencastData.new(link) }
|
6
|
+
|
7
|
+
it "creates a download link by appending download to the link" do
|
8
|
+
subject.download_link.must_equal("#{link}/download")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the link as the id" do
|
12
|
+
subject.id.must_equal link
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't report as downloaded if it hasn't been" do
|
16
|
+
refute subject.downloaded?
|
17
|
+
end
|
18
|
+
|
19
|
+
it "reports as downloaded if downloaded" do
|
20
|
+
subject.downloaded
|
21
|
+
assert subject.downloaded?
|
22
|
+
end
|
23
|
+
|
24
|
+
it "reports as watched if watched" do
|
25
|
+
subject.watched
|
26
|
+
assert subject.watched?
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can be unwatched" do
|
30
|
+
subject.unwatched
|
31
|
+
refute subject.watched?
|
32
|
+
end
|
33
|
+
|
34
|
+
it "saves by passing itself to the tracker" do
|
35
|
+
DasCatalog::Store.expects(:store).with(subject)
|
36
|
+
subject.save
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "getting the screencast data for a given link" do
|
40
|
+
it "creates a new screencast data if one doeesn't already exist" do
|
41
|
+
skip "needs new_record?"
|
42
|
+
scd = DasCatalog::ScreencastData.for_link(link)
|
43
|
+
assert scd.new_record?
|
44
|
+
end
|
45
|
+
|
46
|
+
it "finds the screencast data if already persisted" do
|
47
|
+
DasCatalog::Store.expects(:find).with(link).returns(subject)
|
48
|
+
DasCatalog::ScreencastData.for_link(link).must_equal(subject)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe DasCatalog::Screencast do
|
4
|
+
let(:link) { "https://www.destroyallsoftware.com/screencasts/catalog/statistics-over-git-repositories" }
|
5
|
+
let(:screencast_data) { sd = mock("ScreencastData"); sd.stubs(:link).returns(link); sd }
|
6
|
+
subject { DasCatalog::Screencast.new(screencast_data) }
|
7
|
+
|
8
|
+
it "is created from screencast data" do
|
9
|
+
screencast = DasCatalog::Screencast.new(screencast_data)
|
10
|
+
screencast.screencast_data.must_equal(screencast_data)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "contains screencast data" do
|
14
|
+
assert subject.screencast_data
|
15
|
+
end
|
16
|
+
|
17
|
+
it "is converting to a string that is the link" do
|
18
|
+
subject.to_s.must_equal link
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can be created for a given link" do
|
22
|
+
screencast_data = mock()
|
23
|
+
DasCatalog::ScreencastData.expects(:for_link).with(link).returns(screencast_data)
|
24
|
+
DasCatalog::Screencast.for_link(link).screencast_data.must_equal screencast_data
|
25
|
+
end
|
26
|
+
|
27
|
+
it "delegates to the screencast data for watched?" do
|
28
|
+
screencast_data.stubs(:watched?).returns(false, true)
|
29
|
+
refute subject.watched?
|
30
|
+
assert subject.watched?
|
31
|
+
end
|
32
|
+
|
33
|
+
it "delegates to the screencast data for downloaded?" do
|
34
|
+
screencast_data.stubs(:downloaded?).returns(false, true)
|
35
|
+
refute subject.downloaded?
|
36
|
+
assert subject.downloaded?
|
37
|
+
end
|
38
|
+
|
39
|
+
it "delegates to the screencast data for download link" do
|
40
|
+
screencast_data.stubs(:download_link).returns("http://example.com/path")
|
41
|
+
subject.download_link.must_equal "http://example.com/path"
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "downloading" do
|
45
|
+
before do
|
46
|
+
DasCatalog::Downloader.stubs(:process)
|
47
|
+
screencast_data.stubs(:save)
|
48
|
+
screencast_data.stubs(:downloaded?)
|
49
|
+
screencast_data.stubs(:downloaded)
|
50
|
+
end
|
51
|
+
|
52
|
+
context "for a screencast that hasn't been downloaded" do
|
53
|
+
it "occurs by sending itself to the downloader for processing" do
|
54
|
+
DasCatalog::Downloader.expects(:process).with(subject)
|
55
|
+
subject.download
|
56
|
+
end
|
57
|
+
|
58
|
+
it "marks the screencast data downloaded" do
|
59
|
+
screencast_data.expects(:downloaded)
|
60
|
+
subject.download
|
61
|
+
end
|
62
|
+
|
63
|
+
it "saves the screencast data" do
|
64
|
+
screencast_data.expects(:save)
|
65
|
+
subject.download
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "for a screencast that hasn't been downloaded" do
|
70
|
+
it "returns false" do
|
71
|
+
screencast_data.expects(:downloaded?).returns(true)
|
72
|
+
refute subject.download
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe DasCatalog::StdLogger do
|
4
|
+
it "creates a standard ruby logger to STDOUT" do
|
5
|
+
::Logger.expects(:new).with(STDOUT)
|
6
|
+
DasCatalog::StdLogger.new
|
7
|
+
end
|
8
|
+
|
9
|
+
[:fatal, :error, :warn, :info, :debug].each do |log_method|
|
10
|
+
it "delegates #{log_method} to the contained logger" do
|
11
|
+
logger = DasCatalog::StdLogger.new
|
12
|
+
assert_respond_to(logger, log_method)
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "the logger mixin" do
|
18
|
+
let(:klass) { Class.new }
|
19
|
+
|
20
|
+
before do
|
21
|
+
DasCatalog.logger = mock("Logger")
|
22
|
+
klass.send(:include, DasCatalog::LoggerAccess)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "adds a log class method to grab the DasCatalog.logger" do
|
26
|
+
assert klass.respond_to?(:log)
|
27
|
+
klass.log.must_equal(DasCatalog.logger)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "also adds a log instance method" do
|
31
|
+
assert klass.new.respond_to?(:log)
|
32
|
+
klass.log.must_equal(DasCatalog.logger)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe DasCatalog::Store do
|
4
|
+
let(:link) { "https://www.destroyallsoftware.com/screencasts/catalog/statistics-over-git-repositories" }
|
5
|
+
let(:id) { link }
|
6
|
+
let(:screencast_data) { scd = mock(); scd.stubs(:id).returns(id); scd }
|
7
|
+
|
8
|
+
it "tracks in the file specified in config" do
|
9
|
+
DasCatalog::Store.store(screencast_data)
|
10
|
+
assert File.exists?(DasCatalog.tracker_file.path)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can find the screencast by the id" do
|
14
|
+
DasCatalog::Store.store(screencast_data)
|
15
|
+
assert DasCatalog::Store.find(id)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is nil if the screencast is not found" do
|
19
|
+
refute DasCatalog::Store.find(id)
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
gem "minitest"
|
2
|
+
require 'minitest/spec'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/pride'
|
5
|
+
require 'mocha'
|
6
|
+
require 'fakefs/safe'
|
7
|
+
require 'fileutils'
|
8
|
+
require 'tempfile'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
require_relative '../lib/das_catalog'
|
12
|
+
|
13
|
+
alias :context :describe
|
14
|
+
|
15
|
+
null_logger = ::Logger.new("/dev/null")
|
16
|
+
|
17
|
+
MiniTest::Spec.add_setup_hook do
|
18
|
+
DasCatalog.configure do |c|
|
19
|
+
c.tracker_file = Tempfile.new("das_tracker")
|
20
|
+
c.logger = null_logger
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: das_catalog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brendon Murphy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-17 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: feedzirra
|
16
|
+
requirement: &2153475280 !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: *2153475280
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mechanize
|
27
|
+
requirement: &2153473140 !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: *2153473140
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: highline
|
38
|
+
requirement: &2153472680 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2153472680
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: minitest
|
49
|
+
requirement: &2153472260 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2153472260
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: mocha
|
60
|
+
requirement: &2153471700 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2153471700
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fakefs
|
71
|
+
requirement: &2153471140 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2153471140
|
80
|
+
description: Download screencasts from Destroy All Software catalog. Uses the rss
|
81
|
+
feed plus Mechanize to log you in and then download new movies to your local drive.
|
82
|
+
email: xternal1+github@gmail.com
|
83
|
+
executables:
|
84
|
+
- das_catalog_sync
|
85
|
+
extensions: []
|
86
|
+
extra_rdoc_files: []
|
87
|
+
files:
|
88
|
+
- lib/das_catalog/downloader.rb
|
89
|
+
- lib/das_catalog/feed.rb
|
90
|
+
- lib/das_catalog/screencast.rb
|
91
|
+
- lib/das_catalog/screencast_data.rb
|
92
|
+
- lib/das_catalog/std_logger.rb
|
93
|
+
- lib/das_catalog/store.rb
|
94
|
+
- lib/das_catalog/version.rb
|
95
|
+
- lib/das_catalog.rb
|
96
|
+
- bin/das_catalog_sync
|
97
|
+
- README.md
|
98
|
+
- LICENSE
|
99
|
+
- spec/das_catalog_spec.rb
|
100
|
+
- spec/das_downloader_spec.rb
|
101
|
+
- spec/das_feed_spec.rb
|
102
|
+
- spec/das_screencast_data_spec.rb
|
103
|
+
- spec/das_screencast_spec.rb
|
104
|
+
- spec/das_std_logger_spec.rb
|
105
|
+
- spec/das_store_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
homepage:
|
108
|
+
licenses: []
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 1.8.11
|
128
|
+
signing_key:
|
129
|
+
specification_version: 3
|
130
|
+
summary: Download screencasts from Destroy All Software catalog
|
131
|
+
test_files:
|
132
|
+
- spec/das_catalog_spec.rb
|
133
|
+
- spec/das_downloader_spec.rb
|
134
|
+
- spec/das_feed_spec.rb
|
135
|
+
- spec/das_screencast_data_spec.rb
|
136
|
+
- spec/das_screencast_spec.rb
|
137
|
+
- spec/das_std_logger_spec.rb
|
138
|
+
- spec/das_store_spec.rb
|
139
|
+
- spec/spec_helper.rb
|