comer_de_tapas 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +41 -0
- data/DEVELOPMENT.md +15 -0
- data/LICENSE +21 -0
- data/README.md +81 -0
- data/Rakefile +11 -0
- data/bin/comer_de_tapas +5 -0
- data/comer_de_tapas.gemspec +29 -0
- data/lib/comer_de_tapas/cli.rb +33 -0
- data/lib/comer_de_tapas/client.rb +207 -0
- data/lib/comer_de_tapas/constants.rb +12 -0
- data/lib/comer_de_tapas/fetcher.rb +16 -0
- data/lib/comer_de_tapas/subscription.rb +65 -0
- data/lib/comer_de_tapas/version.rb +3 -0
- data/lib/comer_de_tapas.rb +9 -0
- data/test/cli_test.rb +12 -0
- data/test/client_test.rb +7 -0
- data/test/fetcher_test.rb +7 -0
- data/test/subscription_test.rb +6 -0
- data/test/test_helper.rb +11 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 52d7624ee230325d84d34d1d7dbed242eff3f67c
|
4
|
+
data.tar.gz: 821ec2bcb59323e569227d7996bf751a77e09a2b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0e13a238ba77729967bafa0c02f20f5352f0bf0b243bcecaee12249163504c463110d9ad4c26fe8e1a98e4ecfefa3b034e159308d9772d938fd99a33414215b1
|
7
|
+
data.tar.gz: 524d6b69a68edbeac46176d4ec624cfdb2a36bd9fc0488c4cc5822f9a31581ace50d1da03d8a365af02440a6e90673e9426acac33e66153ebdcc57b8d52366bd
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
## Contributing
|
2
|
+
|
3
|
+
**Everyone** is encouraged to help improve this project.
|
4
|
+
|
5
|
+
Ways to contribute:
|
6
|
+
|
7
|
+
* by reporting bugs
|
8
|
+
* by suggesting new features
|
9
|
+
* by writing or editing documentation
|
10
|
+
* by writing code (**no patch is too small**: fix typos, add comments, clean up
|
11
|
+
inconsistent whitespace)
|
12
|
+
* by refactoring code
|
13
|
+
* by fixing [issues][]
|
14
|
+
* by reviewing patches
|
15
|
+
|
16
|
+
[issues]: https://github.com/juanitofatas/comer_de_tapas/issues
|
17
|
+
|
18
|
+
## Submit an Issue
|
19
|
+
|
20
|
+
We use the [GitHub issue tracker][issues] to track bugs and features. Before
|
21
|
+
submitting a bug report or feature request, check to make sure it hasn't
|
22
|
+
already been submitted. When submitting a bug report, please include a [Gist][]
|
23
|
+
that includes a stack trace and any details that may be necessary to reproduce
|
24
|
+
the bug, including your gem version, Ruby version, and operating system.
|
25
|
+
Ideally, a bug report should include a pull request with failing specs.
|
26
|
+
|
27
|
+
[gist]: https://gist.github.com/
|
28
|
+
|
29
|
+
## Submit a Pull Request
|
30
|
+
|
31
|
+
1. [Fork the repository.][fork]
|
32
|
+
2. [Create a topic branch.][branch]
|
33
|
+
3. Add tests for your unimplemented feature or bug fix.
|
34
|
+
4. Implement your feature or bug fix.
|
35
|
+
5. Run `rake test`. If your tests pass, go to step 6.
|
36
|
+
6. Add, commit, and push your changes.
|
37
|
+
7. [Submit a pull request.][pr]
|
38
|
+
|
39
|
+
[fork]: http://help.github.com/fork-a-repo/
|
40
|
+
[branch]: http://learn.github.com/p/branching.html
|
41
|
+
[pr]: http://help.github.com/send-pull-requests/
|
data/DEVELOPMENT.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Juanito Fatas
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
Comer de Tapas
|
2
|
+
==============
|
3
|
+
|
4
|
+
[Ruby Tapas](http://www.rubytapas.com/) Downloader episodes for subscribers.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
$ gem install comer_de_tapas
|
10
|
+
|
11
|
+
Preparation
|
12
|
+
-----------
|
13
|
+
|
14
|
+
$ comer_de_tapas init
|
15
|
+
|
16
|
+
This will create a directory `~/.rubytapas` And a yaml `~/.rubytapas/.credentials`.
|
17
|
+
|
18
|
+
Please fill in your subscription information in `~/.rubytapas/.credentials`.
|
19
|
+
|
20
|
+
Example:
|
21
|
+
|
22
|
+
```yaml
|
23
|
+
---
|
24
|
+
credentials:
|
25
|
+
- email: foo@example.com
|
26
|
+
- password: password
|
27
|
+
- save_path: ~/Downloads
|
28
|
+
```
|
29
|
+
|
30
|
+
If you want to save all Ruby Tapas episodes in your home folder. Please write it explicily as: `/Users/YOUR-USER-NAME`, please do not write `~`, because in Ruby, `~` considered as `nil` in YAML.
|
31
|
+
|
32
|
+
Usage
|
33
|
+
-----
|
34
|
+
|
35
|
+
$ comer_de_tapas download
|
36
|
+
|
37
|
+
Will fetch all episodes, then start to download it.
|
38
|
+
|
39
|
+
By default it will save a `~/.rubytapas/episodes.json`, to cache all episode attachment links for 3 days.
|
40
|
+
|
41
|
+
Why 3 days? Because normally our Chef Avdi ships new episode in 3.75 days on average.
|
42
|
+
|
43
|
+
But if Avdi ships within < 3 days, you can force it to get latest episodes:
|
44
|
+
|
45
|
+
$ comer_de_tapas download --force # or `-f`.
|
46
|
+
|
47
|
+
Command References
|
48
|
+
------------------
|
49
|
+
|
50
|
+
| command | purpose | Options |
|
51
|
+
| ----------------------------- | ----------------------------------|---------|
|
52
|
+
| comer_de_tapas init | Initialize ComerDeTapas. | |
|
53
|
+
| comer_de_tapas download | Download episodes. | `-f` |
|
54
|
+
| comer_de_tapas version | Display version of Comer de Tapas | |
|
55
|
+
|
56
|
+
Similar Tools
|
57
|
+
-------------
|
58
|
+
|
59
|
+
* [bf4/downloader](https://github.com/bf4/downloader)
|
60
|
+
* [leafac/ruby-tapas-downloader](https://github.com/leafac/ruby-tapas-downloader)
|
61
|
+
* [xpepper/download_rubytapas.rb](https://gist.github.com/xpepper/5872399)
|
62
|
+
* [ebarendt/tapas](https://github.com/ebarendt/tapas)
|
63
|
+
* [YaronWittenstein/next-rubytapas](https://github.com/YaronWittenstein/next-rubytapas)
|
64
|
+
* [cibernox/rubytapas_downloader](https://github.com/cibernox/rubytapas_downloader)
|
65
|
+
|
66
|
+
Questions
|
67
|
+
---------
|
68
|
+
|
69
|
+
Feel free to [open an issue](https://github.com/juanitofatas/comer_de_tapas/issues/new).
|
70
|
+
|
71
|
+
Development
|
72
|
+
-----------
|
73
|
+
|
74
|
+
Please see [DEVELOPMENT](/DEVELOPMENT.md) and [CONTRIBUTING](/CONTRIBUTING.md).
|
75
|
+
|
76
|
+
If you like this small tool, please give it a tweet!
|
77
|
+
|
78
|
+
License
|
79
|
+
-------
|
80
|
+
|
81
|
+
MIT License. Please see [LICENSE](/LICENSE).
|
data/Rakefile
ADDED
data/bin/comer_de_tapas
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "comer_de_tapas/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "comer_de_tapas"
|
8
|
+
spec.version = ComerDeTapas::VERSION
|
9
|
+
spec.authors = ["Juanito Fatas"]
|
10
|
+
spec.email = ["katehuang0320@gmail.com"]
|
11
|
+
spec.summary = %q{Ruby Tapas Episode Downloader.}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = "https://github.com/juanitofatas/comer_de_tapas"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = %w[CONTRIBUTING.md DEVELOPMENT.md LICENSE README.md Rakefile comer_de_tapas.gemspec]
|
17
|
+
spec.files += Dir.glob("lib/**/*.rb")
|
18
|
+
spec.files += Dir.glob("bin/**/*")
|
19
|
+
spec.files += Dir.glob("test/**/*")
|
20
|
+
|
21
|
+
spec.executables = ["comer_de_tapas"]
|
22
|
+
spec.test_files = Dir.glob("test/**/*")
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_dependency "thor"
|
26
|
+
spec.add_dependency "http", ">= 0.6"
|
27
|
+
spec.add_dependency "nokogiri"
|
28
|
+
spec.add_dependency "celluloid-io"
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module ComerDeTapas
|
4
|
+
class CLI < Thor
|
5
|
+
def initialize(*)
|
6
|
+
@client = Client.new
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'version', 'Show version'
|
11
|
+
def version
|
12
|
+
say VERSION
|
13
|
+
end
|
14
|
+
map %w[-v --version] => :version
|
15
|
+
|
16
|
+
desc 'init', 'Create config folder and files'
|
17
|
+
def init
|
18
|
+
@client.init!
|
19
|
+
say 'Please fill in your subscription info in ~/.rubytapas/.credentials'
|
20
|
+
end
|
21
|
+
|
22
|
+
# -f, --force, options[:force] => true, otherwise nil.
|
23
|
+
desc 'download', 'Download RubyTapas episodes'
|
24
|
+
method_option 'force', :aliases => '-f', type: :boolean, desc: 'Force download.'
|
25
|
+
def download
|
26
|
+
@client.fetch_episodes!(options[:force])
|
27
|
+
@client.prepare_save_folder!
|
28
|
+
@client.authenticate
|
29
|
+
@client.load_episodes
|
30
|
+
@client.download_all_tapas!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'http'
|
2
|
+
require 'json'
|
3
|
+
require 'pathname'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module ComerDeTapas
|
7
|
+
class Client
|
8
|
+
|
9
|
+
# Initialize comer de tapas
|
10
|
+
# $ mkdir -p ~/.rubytapas/
|
11
|
+
# $ touch ~/.rubytapas/.credentials
|
12
|
+
def init!
|
13
|
+
if File.exist?(RUBYTAPAS_DIR) && File.exist?(CREDENTIAL_FILE)
|
14
|
+
abort 'Credentials found. type `comer_de_tapas download` to download.'
|
15
|
+
end
|
16
|
+
create_rubytapas_files!
|
17
|
+
puts '~/.rubytapas/.credentials folder and file has been created.'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Fetch latest feed on rubytapas.dpdcart.com
|
21
|
+
# Parse it to episode, save episodes data as json to ~/.rubytapas.json
|
22
|
+
def fetch_episodes! force=nil
|
23
|
+
return puts 'Use cached episode data.' if fresh? && force.nil?
|
24
|
+
puts 'Fetching episodes...'
|
25
|
+
get_feed_with_basic_auth
|
26
|
+
save_feed_data parse_xml_feed
|
27
|
+
puts 'Episodes successfully fetched.'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Create user specified folder: credentials[:save_path]
|
31
|
+
def prepare_save_folder!
|
32
|
+
return puts "#{save_folder} found." if File.exist? save_folder
|
33
|
+
|
34
|
+
FileUtils.mkdir_p save_folder.expand_path
|
35
|
+
puts "#{save_folder} created."
|
36
|
+
end
|
37
|
+
|
38
|
+
# Authenticate and return Cookie
|
39
|
+
def authenticate
|
40
|
+
@cookie ||= HTTP.post(LOGIN_URL, form_params).headers['Set-Cookie']
|
41
|
+
end
|
42
|
+
|
43
|
+
# Load episodes json from EPISODES_JSON_FILE
|
44
|
+
def load_episodes
|
45
|
+
@episodes ||= JSON.parse(File.read EPISODES_JSON_FILE)
|
46
|
+
end
|
47
|
+
|
48
|
+
# User spefified folder to save episodes.
|
49
|
+
# @return [Pathname]
|
50
|
+
def save_folder
|
51
|
+
Pathname credentials[:save_path]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Download episode in parallel using Actors
|
55
|
+
# Powered by Celluloid::IO
|
56
|
+
def download_all_tapas!
|
57
|
+
episodes.each do |episode|
|
58
|
+
FileUtils.cd(save_folder.expand_path) do
|
59
|
+
episode_title = episode['title']
|
60
|
+
puts "Downloading Epsiode #{episode_title}..."
|
61
|
+
|
62
|
+
episode_folder = save_folder.join(sanitized episode_title).expand_path
|
63
|
+
|
64
|
+
FileUtils.mkdir_p episode_folder unless File.exist? episode_folder
|
65
|
+
|
66
|
+
FileUtils.cd episode_folder do
|
67
|
+
fetcher = Fetcher.new
|
68
|
+
file_and_links = episode['links']
|
69
|
+
downloadables = find_downloadables file_and_links
|
70
|
+
|
71
|
+
if downloadables.all? &:nil?
|
72
|
+
puts 'Already downloaded, skip.'
|
73
|
+
next
|
74
|
+
end
|
75
|
+
|
76
|
+
download_parallelly! downloadables
|
77
|
+
puts "Episode #{episode_title} content all saved."
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
attr_reader :feed_xml, :cookie, :episodes
|
86
|
+
|
87
|
+
# Download episode all attachments
|
88
|
+
# compact to remove attachment that already downloaded
|
89
|
+
# @param [Array] downloadables
|
90
|
+
def download_parallelly! downloadables
|
91
|
+
downloadables.compact.each do |file, future|
|
92
|
+
response = future.value.to_s
|
93
|
+
puts "Downloading #{file}..."
|
94
|
+
IO.write file, response
|
95
|
+
puts "#{file} saved."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Find episode's attachment that has not been downloaded
|
100
|
+
# @param [Array] file_and_links
|
101
|
+
def find_downloadables file_and_links
|
102
|
+
file_and_links.map do |file_and_link|
|
103
|
+
next if File.exist? file_and_link['filename']
|
104
|
+
|
105
|
+
q, v = file_and_link['link'].split('?').last.split('=')
|
106
|
+
[file_and_link['filename'], fetcher.future.fetch(DOWNLOAD_URL, cookie, { q => v })]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# mkdir -p ~/.rubytapas
|
111
|
+
# touch ~/.rubytapas/.credentials
|
112
|
+
def create_rubytapas_files!
|
113
|
+
FileUtils.mkdir_p RUBYTAPAS_DIR
|
114
|
+
FileUtils.touch CREDENTIAL_FILE
|
115
|
+
IO.write CREDENTIAL_FILE, credential_template
|
116
|
+
end
|
117
|
+
|
118
|
+
# Use to create empty credential file
|
119
|
+
def credential_template
|
120
|
+
require 'yaml'
|
121
|
+
{"credentials"=>[{"email"=>nil}, {"password"=>nil}, {"save_path"=>nil}]}.to_yaml
|
122
|
+
end
|
123
|
+
|
124
|
+
# Get raw feed data (XML), RSS
|
125
|
+
def get_feed_with_basic_auth
|
126
|
+
puts 'Authorizing...'
|
127
|
+
@feed_xml = HTTP.auth(:basic, authenticate_params).get(FEED_URL).body.to_s
|
128
|
+
puts 'Authroized.'
|
129
|
+
end
|
130
|
+
|
131
|
+
# Params for basic authentication
|
132
|
+
def authenticate_params
|
133
|
+
{ user: credentials[:email], pass: credentials[:password] }
|
134
|
+
end
|
135
|
+
|
136
|
+
# RubyTapas subscription credentials (~/.rubytapas/.credentials)
|
137
|
+
# @return [Hash]
|
138
|
+
def credentials
|
139
|
+
Subscription.new.to_h
|
140
|
+
end
|
141
|
+
|
142
|
+
# Parse raw feed data (XML), retrive episode's title and links.
|
143
|
+
# @return [Array<Hash>]
|
144
|
+
def parse_xml_feed
|
145
|
+
puts 'Parsing Episodes...'
|
146
|
+
require 'nokogiri'
|
147
|
+
items = Nokogiri::XML(feed_xml).xpath('//item')
|
148
|
+
|
149
|
+
epsiode_data = items.map do |item|
|
150
|
+
children = item.children
|
151
|
+
|
152
|
+
title = (children / 'title').first.child.content
|
153
|
+
description = (children / 'description').first.child.content
|
154
|
+
|
155
|
+
links = Nokogiri::HTML(description).css('ul li a')
|
156
|
+
|
157
|
+
{ title: title, links: attachments(links) }
|
158
|
+
end
|
159
|
+
|
160
|
+
puts 'Episodes parsed successfully.'
|
161
|
+
|
162
|
+
return epsiode_data
|
163
|
+
end
|
164
|
+
|
165
|
+
# Given links, parse to
|
166
|
+
# { filename: "123.rb", "/subscriber/download?file_id=34567" }
|
167
|
+
# @return [Array<Hash>]
|
168
|
+
def attachments links
|
169
|
+
links.each_with_object([]) do |link, episode|
|
170
|
+
if link['href'] =~ /rubytapas.dpdcart.com\/subscriber\/download/
|
171
|
+
episode << { filename: link.content, link: link['href'].gsub(/#{BASE_URL}/, '') }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Write episodes data to ~/.rubytapas/episodes.json
|
177
|
+
def save_feed_data feed
|
178
|
+
puts 'Saving episodes data to ~/.rubytapas/episodes.json...'
|
179
|
+
IO.write EPISODES_JSON_FILE, feed.to_json
|
180
|
+
puts 'Saved.'
|
181
|
+
end
|
182
|
+
|
183
|
+
# Return each episode's folder name
|
184
|
+
def sanitized title
|
185
|
+
dasherize_file_name(title)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Before: 999 Array.first, Foo::Bar, Class<<self
|
189
|
+
# After: 999-array-first-foo-bar-class<<self
|
190
|
+
def dasherize_file_name file_name
|
191
|
+
file_name.downcase.gsub('<', '<').gsub(/[^\w<>#?!$]+/, '-')
|
192
|
+
end
|
193
|
+
|
194
|
+
# Form params to post for HTTP
|
195
|
+
# @return [Hash]
|
196
|
+
def form_params
|
197
|
+
{ form: { username: credentials[:email], password: credentials[:password] } }
|
198
|
+
end
|
199
|
+
|
200
|
+
# If the episodes json was made of 259_200.seconds.ago (3 days)
|
201
|
+
# @return [Boolean] true if episodes.json creation time < 3 days
|
202
|
+
def fresh?
|
203
|
+
return false unless File.exist? EPISODES_JSON_FILE
|
204
|
+
Time.now - File.ctime(EPISODES_JSON_FILE) < 259_200
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module ComerDeTapas
|
4
|
+
BASE_URL = 'https://rubytapas.dpdcart.com'
|
5
|
+
DOWNLOAD_URL = BASE_URL + '/subscriber/download'
|
6
|
+
LOGIN_URL = BASE_URL + '/subscriber/login'
|
7
|
+
FEED_URL = BASE_URL + '/feed'
|
8
|
+
|
9
|
+
RUBYTAPAS_DIR = Pathname.new(ENV['HOME']).join('.rubytapas')
|
10
|
+
EPISODES_JSON_FILE = RUBYTAPAS_DIR.join('episodes.json')
|
11
|
+
CREDENTIAL_FILE = RUBYTAPAS_DIR.join('.credentials')
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'celluloid/io'
|
2
|
+
|
3
|
+
module ComerDeTapas
|
4
|
+
class Fetcher
|
5
|
+
include Celluloid::IO
|
6
|
+
|
7
|
+
# Fetch url with given cookie, and query string (optional)
|
8
|
+
# @param [String] url
|
9
|
+
# @param cookie
|
10
|
+
# @option query [Hash]
|
11
|
+
def fetch url, cookie, query={}
|
12
|
+
require 'http'
|
13
|
+
HTTP.with('Cookie' => cookie).get(url, ssl_socket_class: Celluloid::IO::SSLSocket, params: query)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ComerDeTapas
|
2
|
+
class Subscription
|
3
|
+
CredentialYamlNotExist = Class.new StandardError
|
4
|
+
CredentialYamlKeyError = Class.new StandardError
|
5
|
+
CredentialYamlValueError = Class.new StandardError
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
raise CredentialYamlNotExist, 'Please run `comer_de_tapas init` first' unless File.exist? CREDENTIAL_FILE
|
9
|
+
|
10
|
+
set_subscription_data if subscription_data_valid?
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Hash] User's Ruby Tapas credential information
|
14
|
+
def to_h
|
15
|
+
{ email: email, password: password, save_path: save_path }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :email, :password, :save_path
|
21
|
+
|
22
|
+
# Load ~/.rubytapas/.credentials yaml
|
23
|
+
def load_credential_data
|
24
|
+
require 'yaml'
|
25
|
+
@credential_yaml ||= YAML.load_file CREDENTIAL_FILE
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if ~/.rubytapas/.credentials files are filled and corrected.
|
29
|
+
def subscription_data_valid?
|
30
|
+
# empty credential file's size is about 50-55.
|
31
|
+
# 65 is when you have a very short email, password, and save_path.
|
32
|
+
# So when you filled in data, probably will > 65.
|
33
|
+
if File.size(CREDENTIAL_FILE) < 65
|
34
|
+
puts "Did you fill in your subscription data in #{CREDENTIAL_FILE}?"
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
credential_data_valid?(get_validate load_credential_data)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Check if credential data valid?
|
42
|
+
def credential_data_valid? data
|
43
|
+
data.each do |hash|
|
44
|
+
hash.each do |k,v|
|
45
|
+
raise CredentialYamlKeyError, "Valid yaml keys: #{KEYS.join(' ,')}." unless %w(email password save_path).include? k
|
46
|
+
raise CredentialYamlValueError, "Please fill value for this one: #{k}" if v.nil?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get credential data from loaded yaml for validation.
|
54
|
+
def get_validate data
|
55
|
+
data.values.flatten
|
56
|
+
end
|
57
|
+
|
58
|
+
# Set subscription data from ~/.rubytapas/.credentials yaml
|
59
|
+
def set_subscription_data
|
60
|
+
@email ||= load_credential_data['credentials'][0]['email']
|
61
|
+
@password ||= load_credential_data['credentials'][1]['password']
|
62
|
+
@save_path ||= load_credential_data['credentials'][2]['save_path']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/test/cli_test.rb
ADDED
data/test/client_test.rb
ADDED
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: comer_de_tapas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Juanito Fatas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: http
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: celluloid-io
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Ruby Tapas Episode Downloader.
|
70
|
+
email:
|
71
|
+
- katehuang0320@gmail.com
|
72
|
+
executables:
|
73
|
+
- comer_de_tapas
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- CONTRIBUTING.md
|
78
|
+
- DEVELOPMENT.md
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/comer_de_tapas
|
83
|
+
- comer_de_tapas.gemspec
|
84
|
+
- lib/comer_de_tapas.rb
|
85
|
+
- lib/comer_de_tapas/cli.rb
|
86
|
+
- lib/comer_de_tapas/client.rb
|
87
|
+
- lib/comer_de_tapas/constants.rb
|
88
|
+
- lib/comer_de_tapas/fetcher.rb
|
89
|
+
- lib/comer_de_tapas/subscription.rb
|
90
|
+
- lib/comer_de_tapas/version.rb
|
91
|
+
- test/cli_test.rb
|
92
|
+
- test/client_test.rb
|
93
|
+
- test/fetcher_test.rb
|
94
|
+
- test/subscription_test.rb
|
95
|
+
- test/test_helper.rb
|
96
|
+
homepage: https://github.com/juanitofatas/comer_de_tapas
|
97
|
+
licenses:
|
98
|
+
- MIT
|
99
|
+
metadata: {}
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 2.3.0
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Ruby Tapas Episode Downloader.
|
120
|
+
test_files:
|
121
|
+
- test/cli_test.rb
|
122
|
+
- test/client_test.rb
|
123
|
+
- test/fetcher_test.rb
|
124
|
+
- test/subscription_test.rb
|
125
|
+
- test/test_helper.rb
|
126
|
+
has_rdoc:
|