bookscan 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Yoshihiro TAKAHARA
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,54 @@
1
+ = bookscan
2
+
3
+ This is a scraper of Bookscan (http://www.bookscan.co.jp) Service.This is *NOT* a official software of Bookscan.
4
+
5
+ == Install
6
+
7
+ sudo gem install bookscan
8
+
9
+ == Usage
10
+
11
+ bookscan [global options] command [command options]
12
+
13
+ === GlobalOptions
14
+
15
+ * --debug
16
+ * --help
17
+
18
+ === Commands
19
+
20
+ * help [command]
21
+ * login
22
+ * logout
23
+ * update [-a,--all] [-g,--group=HASH]
24
+ * download [--dry-run] [-g,--group=HASH] [-d,--directory=DIR] [-t,--tuned=TYPE] _id_|all
25
+ * tune [--dry-run] _id_|all _type_
26
+ * list
27
+ * tuned
28
+ * tuning
29
+ * groups
30
+
31
+ == Depends
32
+
33
+ === gems
34
+
35
+ * highline > 1.6
36
+ * mechanize >= 1.0
37
+ * keystorage > 0.1
38
+
39
+
40
+ == Contributing to bookscan
41
+
42
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
43
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
44
+ * Fork the project
45
+ * Start a feature/bugfix branch
46
+ * Commit and push until you are happy with your contribution
47
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
48
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
49
+
50
+ == Copyright
51
+
52
+ Copyright (c) 2011 Yoshihiro TAKAHARA. See LICENSE.txt for
53
+ further details.
54
+
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "bookscan"
16
+ gem.homepage = "http://github.com/tumf/bookscan"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{BookScan Scraper}
19
+ gem.description = %Q{This is a scraper of BookScan (http://www.bookscan.co.jp/) Service.This is *NOT* a official software of BookScan.}
20
+ gem.email = "y.takahara@gmail.com"
21
+ gem.authors = ["Yoshihiro TAKAHARA"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ gem.add_runtime_dependency 'mutter'
25
+ gem.add_runtime_dependency 'keystorage', '> 0.1'
26
+ gem.add_runtime_dependency 'mechanize', '> 1.0.0'
27
+ gem.add_runtime_dependency 'highline', '> 1.6'
28
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'rake/testtask'
33
+ Rake::TestTask.new(:test) do |test|
34
+ test.libs << 'lib' << 'test'
35
+ test.pattern = 'test/**/test_*.rb'
36
+ test.verbose = true
37
+ end
38
+
39
+ require 'rcov/rcovtask'
40
+ Rcov::RcovTask.new do |test|
41
+ test.libs << 'test'
42
+ test.pattern = 'test/**/test_*.rb'
43
+ test.verbose = true
44
+ end
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/rdoctask'
49
+ Rake::RDocTask.new do |rdoc|
50
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "bookscan #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
data/bin/bookscan ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:set fileencoding=utf-8:
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
4
+ require 'bookscan/cli'
5
+ Bookscan::CLI::run(ARGV)
6
+ exit
7
+
8
+ require 'optparse'
9
+
10
+
11
+ require 'rubygems'
12
+ require 'highline'
13
+ require 'mutter'
14
+
15
+ require 'moat';include Moat
16
+
17
+ load_passwords
18
+
19
+ Moat::SITES[@site] = {:username => username, :password => password }
20
+ show_credentials_for(@site) if @generated
21
+ save_passwords
22
+
23
+
data/lib/bookscan.rb ADDED
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Bookscan
3
+ BSURL = "http://system.bookscan.co.jp"
4
+ TUNE_TYPES = ["ipad","iphone","kindle3","kindledx","android","sonyreader","nook","jpg"]
5
+ TUNED_PATTERN = /((iphone|ipad|kindle3|kindledx|android|sonyreader|nook|jpg)_([^>%]*\.pdf))/
6
+ end
@@ -0,0 +1,158 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "rubygems"
3
+ require "mechanize"
4
+
5
+ require "bookscan"
6
+ require "bookscan/groups"
7
+ require "bookscan/book"
8
+
9
+ module Bookscan
10
+ class Agent < Mechanize
11
+ def initialize
12
+ super
13
+ max_history = 0
14
+ end
15
+
16
+ def getr path
17
+ get(BSURL + path)
18
+ end
19
+
20
+ def login id,password
21
+ getr("/login.php")
22
+ form = page.forms[0]
23
+ form.fields.find{|f| f.name == "email" }.value = id
24
+ form.fields.find{|f| f.name == "password" }.value = password
25
+ submit(form)
26
+ end
27
+
28
+ def login?
29
+ getr("/mypage.php")
30
+ /さんのおかげです/ =~ page.body # => OK
31
+ end
32
+
33
+ def logout
34
+ getr("/history.php?logout=1")
35
+ end
36
+
37
+ def tuned
38
+ bs = Books.new
39
+ getr("/tunelablist.php")
40
+ page.search("td").each do |td|
41
+ if TUNED_PATTERN =~ td.to_s
42
+ a = td.at("a")
43
+ book = Book.new
44
+ book.title = $1
45
+ book.url = a.attributes["href"].value.to_s
46
+ book.group_url = "/tunelablist.php"
47
+ bs << book
48
+ end
49
+ end
50
+ bs
51
+ end
52
+
53
+ def tuning
54
+ bs = Books.new
55
+ getr("/tunelabnowlist.php")
56
+ page.search("td").each do |td|
57
+ if TUNED_PATTERN =~ td.to_s
58
+ book = Book.new
59
+ book.title = $1
60
+ book.group_url = "/tunelabnowlist.php"
61
+ bs << book
62
+ end
63
+ end
64
+ bs
65
+ end
66
+
67
+ def tune book,type
68
+ getr(book.group_url)
69
+ page.search("a[@class=downloading]").each do |u|
70
+ if u.text == "変換" and
71
+ /_#{book.isbn}/ =~ u.attributes["href"].value.to_s
72
+ click(u)
73
+ page.forms.first["optimize_type"] = type;
74
+ page.forms.first["cover_flg"] = "1";
75
+ page.forms.first.submit
76
+ puts "tune %s " % [book.title]
77
+ return true
78
+ end
79
+ end
80
+ end
81
+
82
+ def groups
83
+ r = Groups.new
84
+ getr("/history.php")
85
+ page.search("table.table5").each do |table|
86
+ if /依頼したもの一覧/ =~ table.to_s
87
+ table.search("tr").each do |tr|
88
+ if /決済完了/ =~ tr.to_s
89
+ g = Group.new
90
+ g.import(tr)
91
+ r << g
92
+ end
93
+ end
94
+ end
95
+ end
96
+ r
97
+ end
98
+
99
+ def group_urls
100
+ getr("/history.php")
101
+ urls = Array.new
102
+ page.search("a/@href").each do |url|
103
+ urls << "/" + url if(/bookdetail/ =~ url)
104
+ end
105
+ urls
106
+ end
107
+
108
+ def books group
109
+ bs = Books.new
110
+ getr(group.url)
111
+ page.search("a[@class=downloading]").each do |u|
112
+ next if u.text == "PDFダウンロード" or
113
+ u.text == "変換"
114
+ book = Book.new
115
+ book.title = u.text.to_s
116
+ book.url = u.attributes["href"].value.to_s
117
+ book.group_url = group.url
118
+ bs << book
119
+ end
120
+ bs
121
+ end
122
+
123
+ def allbooks
124
+ books = Books.new
125
+ group_urls.each do |url|
126
+ getr(url)
127
+ page.search("a[@class=downloading]").each do |u|
128
+ next if u.text == "PDFダウンロード" or
129
+ u.text == "変換"
130
+ book = Book.new
131
+ book.title = u.text.to_s
132
+ book.url = u.attributes["href"].value.to_s
133
+ book.group_url = url
134
+ books[book.isbn] = book
135
+ end
136
+ end
137
+ books
138
+ end
139
+
140
+ def download(url,path)
141
+ get(url)
142
+ page.save(path)
143
+ end
144
+
145
+ def download2 isbn,type,dir
146
+ getr("/tunelablist.php")
147
+ page.search("a[@class=download]").each do |a|
148
+ if /^#{type}_.*_#{isbn}.*\.pdf$/ =~ a.text
149
+ click(a)
150
+ path = dir + "/" + a.text
151
+ puts "Download %s" % [path]
152
+ page.save(path)
153
+ end
154
+ end
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'digest/md5'
4
+ require 'rubygems'
5
+ require 'mutter'
6
+
7
+ require 'bookscan'
8
+ module Bookscan
9
+ class Books < Array
10
+ def to_s
11
+ table = Mutter::Table.new(:delimiter => '|') do
12
+ column :style => :green
13
+ column :width => 60
14
+ end
15
+
16
+ each do |b|
17
+ table << [b.id,b.title]
18
+ end
19
+ table.to_s if length > 0
20
+ end
21
+
22
+ def ids
23
+ a = Array.new
24
+ each do |b|
25
+ a << b.id
26
+ end
27
+ a
28
+ end
29
+
30
+ def by_id(book_id)
31
+ each do |b|
32
+ return b if b.id == book_id
33
+ end
34
+ end
35
+
36
+ def has?(book_id)
37
+ each do |b|
38
+ return true if b.id == book_id
39
+ end
40
+ false
41
+ end
42
+ end
43
+
44
+ class Book
45
+ attr_accessor :url,:title,:group_url
46
+
47
+ def to_s
48
+ @title
49
+ end
50
+
51
+ def filename
52
+ return @title if isbn
53
+ if /(.*)\.pdf$/ =~ @title
54
+ return $1 + "_" + id + ".pdf"
55
+ end
56
+ raise "Can't make filename"
57
+ end
58
+
59
+ def tune_type
60
+ if TUNED_PATTERN =~ title
61
+ return $2
62
+ end
63
+ nil
64
+ end
65
+
66
+ def isbn
67
+ return $1 if /_([0-9a-zA-Z]+)_s\.pdf$/ =~ @title
68
+ return $1 if /_([0-9a-zA-Z]+)\.pdf$/ =~ @title
69
+ end
70
+
71
+ def id
72
+ return isbn if isbn
73
+ title = @title
74
+ if TUNED_PATTERN =~ title
75
+ title = $3
76
+ end
77
+ title.gsub!(/_s\.pdf$/,".pdf")
78
+ Digest::MD5.hexdigest(title).to_s[1,10]
79
+ end
80
+
81
+ end
82
+ end
83
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'pstore'
4
+
5
+ module Bookscan
6
+ class Cache < PStore
7
+
8
+ def groups
9
+ gs = nil
10
+ transaction do |ps|
11
+ gs = ps["groups"]
12
+ end
13
+ raise "No groups in cache. Exceute 'bookscan update' first." unless gs
14
+ gs
15
+ end
16
+
17
+ def tuned
18
+ ts = nil
19
+ transaction do |ps|
20
+ ts = ps["tuned"]
21
+ end
22
+ ts
23
+ end
24
+
25
+ def books(group)
26
+ groups.each do |g|
27
+ return g.books if g.hash == group.hash
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'optparse'
4
+ require 'bookscan/commands'
5
+
6
+ module Bookscan
7
+ class CLI
8
+ def initialize
9
+ @options = Hash.new
10
+ @options[:debug] = false
11
+ end
12
+
13
+ def execute(argv)
14
+ begin
15
+ @opt = OptionParser.new
16
+ @opt.on('--help', 'show this message') { usage;exit }
17
+ @opt.on('--debug', 'debug mode') { @options[:debug] = true }
18
+ cmd_argv = @opt.order!(argv)
19
+ cmd = cmd_argv.shift
20
+ Commands.new(cmd_argv,@options).send(cmd)
21
+ rescue =>e
22
+ puts e
23
+ usage
24
+ raise e if @options[:debug]
25
+ end
26
+ end
27
+
28
+ def usage(e=nil)
29
+ puts @opt
30
+ end
31
+
32
+ class << self
33
+ def run(argv)
34
+ self.new.execute(argv)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require "rubygems"
4
+ require "highline/import"
5
+
6
+ require "keystorage"
7
+
8
+ require "bookscan"
9
+ require "bookscan/agent"
10
+ require "bookscan/cache"
11
+
12
+ module Bookscan
13
+ class Commands
14
+ def initialize(cmd_options,options)
15
+ @options = options
16
+ @command_options = cmd_options
17
+ @agent = Agent.new
18
+ @cache_file = ENV['HOME']+"/.bookscan.cache"
19
+ @cache = Cache.new(@cache_file)
20
+ end
21
+
22
+ def login
23
+ email = ask('Enter email: ') do |q|
24
+ q.validate = /\w+/
25
+ end
26
+
27
+ ok = false
28
+ while(!ok)
29
+ password = ask("Enter your password: ") do |q|
30
+ q.validate = /\w+/
31
+ q.echo = false
32
+ end
33
+
34
+ @agent.login(email,password)
35
+ if @agent.login? # => OK
36
+ ok = true
37
+ Keystorage.set("bookscan",email,password)
38
+ puts "login OK"
39
+ else
40
+ puts "password mismatch"
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ def logout
47
+ Keystorage.delete("bookscan")
48
+ end
49
+
50
+ def start
51
+ return true if @agent.login?
52
+ email = Keystorage.list("bookscan").shift
53
+ if email
54
+ @agent.login(email,Keystorage.get("bookscan",email))
55
+ unless @agent.login?
56
+ login
57
+ end
58
+ else
59
+ login
60
+ end
61
+ end
62
+
63
+ def update
64
+ start
65
+ all = false
66
+ hash = false
67
+
68
+ opt = OptionParser.new
69
+ opt.on('-a','--all', 'update all cache') do
70
+ all = true
71
+ end
72
+ opt.on('-g HASH','--group=HASH', 'update group') do |v|
73
+ hash = v
74
+ end
75
+ opt.parse!(@command_options)
76
+
77
+ gs = @agent.groups
78
+ if all
79
+ gs.each_index do |index|
80
+ gs[index].books = @agent.books(gs[index])
81
+ end
82
+ elsif hash
83
+ i = gs.to_index(hash)
84
+ gs[i].books = @agent.books(gs[i]) if gs[i]
85
+ else
86
+ gs.each_index do |index|
87
+ gs[index].books = @cache.books(gs[index])
88
+ end
89
+ end
90
+ ts = @agent.tuned
91
+
92
+ @cache.transaction do |cache|
93
+ cache["groups"] = gs
94
+ cache["tuned"] = ts
95
+ end
96
+ end
97
+
98
+ def groups
99
+ gs = @cache.groups
100
+ puts gs.to_s
101
+ end
102
+
103
+ def list
104
+ gs = @cache.groups
105
+
106
+ opt = OptionParser.new
107
+ hash = nil
108
+ opt.on('-g HASH','--group=HASH', 'group hash') do |v|
109
+ hash = v
110
+ end
111
+ opt.parse!(@command_options)
112
+
113
+ unless hash
114
+ puts gs.to_s
115
+ hash = ask('Enter hash: ',gs.hashes) do |q|
116
+ q.validate = /\w+/
117
+ q.readline = true
118
+ end
119
+ end
120
+
121
+ g = gs.by_hash(hash)
122
+ puts g.books.to_s
123
+ end
124
+
125
+ def ask_tuned_book_id(book_id,type)
126
+ unless type
127
+ type = ask('Enter tune type: ',TUNE_TYPES) do |q|
128
+ q.validate = /\w+/
129
+ q.readline = true
130
+ end
131
+ end
132
+ ts = @cache.tuned
133
+ ts.collect! do |i|
134
+ i if i.tune_type == type
135
+ end.compact!
136
+ raise "No tuned in cache. Exceute 'bookscan update' first." unless ts.length > 0
137
+ unless book_id
138
+ puts ts.to_s
139
+ book_id = ask('Enter book id: ',ts.ids) do |q|
140
+ q.validate = /\w+/
141
+ q.readline = true
142
+ end
143
+ end
144
+ ts.by_id(book_id)
145
+ end
146
+
147
+ def ask_book_id(book_id,hash)
148
+ gs = @cache.groups
149
+ unless book_id
150
+ unless hash
151
+ puts gs.to_s
152
+ hash = ask('Enter hash: ',gs.hashes) do |q|
153
+ q.validate = /\w+/
154
+ q.readline = true
155
+ end
156
+ g = gs.by_hash(hash)
157
+
158
+ puts g.books.to_s
159
+
160
+ book_id = ask('Enter book id: ',g.books.ids) do |q|
161
+ q.validate = /\w+/
162
+ q.readline = true
163
+ end
164
+
165
+ end
166
+ end
167
+ gs.book(book_id)
168
+ end
169
+
170
+ def download
171
+ opt = OptionParser.new
172
+ directory = "."
173
+ hash = nil
174
+ type = nil
175
+ opt.on('-d DIR','--directory=DIR', 'download directory') do |v|
176
+ directory = v
177
+ end
178
+ opt.on('-g HASH','--group=HASH', 'group hash') do |v|
179
+ hash = v
180
+ end
181
+ opt.on('-t TYPE','--tuned=TYPE', 'download tuned') do |v|
182
+ type = v
183
+ end
184
+ opt.parse!(@command_options)
185
+ book_id = @command_options.shift
186
+ if type
187
+ book = ask_tuned_book_id(book_id,type)
188
+ else
189
+ book = ask_book_id(book_id,hash)
190
+ end
191
+
192
+ # download
193
+ start
194
+ path = directory + "/" +book.filename
195
+ puts "download: " + path
196
+ @agent.download(book.url,path)
197
+ end
198
+
199
+ def tune
200
+ opt = OptionParser.new
201
+ hash = nil
202
+ opt.on('-g HASH','--group=HASH', 'group hash') do |v|
203
+ hash = v
204
+ end
205
+ opt.parse!(@command_options)
206
+ book_id = @command_options.shift
207
+ type = @command_options.shift
208
+ book = ask_book_id(book_id,hash)
209
+ unless type
210
+ type = ask('Enter tune type: ',TUNE_TYPES) do |q|
211
+ q.validate = /\w+/
212
+ q.readline = true
213
+ end
214
+ end
215
+
216
+ # tune
217
+ start
218
+ @agent.tuning
219
+ @agent.tune(book,type)
220
+ end
221
+
222
+ def tuning
223
+ start
224
+ books = @agent.tuning
225
+ puts books.to_s
226
+ end
227
+
228
+ def tuned
229
+ puts @cache.tuned.to_s
230
+ end
231
+
232
+ end
233
+ end
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'bookscan/book'
4
+ module Bookscan
5
+ class Group
6
+ attr_reader :hash,:date,:num,:price,:payment
7
+ attr_accessor :books
8
+
9
+ def initialize
10
+ @books = Books.new
11
+ end
12
+
13
+ def to_a
14
+ if completed?
15
+ @status = "完了"
16
+ else
17
+ @status = "未完了"
18
+ end
19
+ [@hash,@date,@num,@price,@payment,@status]
20
+ end
21
+
22
+ def url
23
+ "/bookdetail.php?hash=" + @hash
24
+ end
25
+
26
+ def import(tr)
27
+ a = Array.new
28
+ tr.search("td").each do |td|
29
+ a << td.text.to_s
30
+ end
31
+ if /hash=(.+)/ =~ tr.at("a/@href")
32
+ @hash = $1
33
+ end
34
+ # puts url
35
+
36
+ @date = a[0]
37
+ @num = a[1]
38
+ @price = a[2]
39
+ @payment = a[3]
40
+ @is_completed = true
41
+ if a[6] == "未完了"
42
+ @is_completed = false
43
+ end
44
+ end
45
+
46
+ def completed?
47
+ @is_completed
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'rubygems'
4
+ require 'mutter'
5
+ require 'bookscan/group'
6
+ module Bookscan
7
+ class Groups < Array
8
+ def hashes
9
+ h = Array.new
10
+ each do |group|
11
+ h << group.hash
12
+ end
13
+ h
14
+ end
15
+
16
+ def by_hash(hash)
17
+ i = to_index(hash)
18
+ at(i) if i
19
+ end
20
+
21
+ def to_index(hash)
22
+ each_index do |i|
23
+ return i if hash == at(i).hash
24
+ end
25
+ end
26
+
27
+ def to_s
28
+ table = Mutter::Table.new(:delimiter => '|') do
29
+ column :style => :green
30
+ column
31
+ column
32
+ column
33
+ column
34
+ column
35
+ end
36
+ # table << ["#","Date","num","price","status"]
37
+ each do |group|
38
+ table << group.to_a
39
+ end
40
+ table.to_s if length > 0
41
+ end
42
+
43
+ def book(book_id)
44
+ each do |g|
45
+ return g.books.by_id(book_id) if g.books.has?(book_id)
46
+ end
47
+ end
48
+
49
+ end
50
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'bookscan'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestBookscan < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bookscan
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ version: 0.1.2
11
+ platform: ruby
12
+ authors:
13
+ - Yoshihiro TAKAHARA
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-18 00:00:00 +09:00
19
+ default_executable: bookscan
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :development
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ requirement: *id001
33
+ prerelease: false
34
+ name: shoulda
35
+ - !ruby/object:Gem::Dependency
36
+ type: :development
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ hash: 23
43
+ segments:
44
+ - 1
45
+ - 0
46
+ - 0
47
+ version: 1.0.0
48
+ requirement: *id002
49
+ prerelease: false
50
+ name: bundler
51
+ - !ruby/object:Gem::Dependency
52
+ type: :development
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ hash: 7
59
+ segments:
60
+ - 1
61
+ - 5
62
+ - 2
63
+ version: 1.5.2
64
+ requirement: *id003
65
+ prerelease: false
66
+ name: jeweler
67
+ - !ruby/object:Gem::Dependency
68
+ type: :development
69
+ version_requirements: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirement: *id004
79
+ prerelease: false
80
+ name: rcov
81
+ - !ruby/object:Gem::Dependency
82
+ type: :runtime
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirement: *id005
93
+ prerelease: false
94
+ name: mutter
95
+ - !ruby/object:Gem::Dependency
96
+ type: :runtime
97
+ version_requirements: &id006 !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">"
101
+ - !ruby/object:Gem::Version
102
+ hash: 9
103
+ segments:
104
+ - 0
105
+ - 1
106
+ version: "0.1"
107
+ requirement: *id006
108
+ prerelease: false
109
+ name: keystorage
110
+ - !ruby/object:Gem::Dependency
111
+ type: :runtime
112
+ version_requirements: &id007 !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">"
116
+ - !ruby/object:Gem::Version
117
+ hash: 23
118
+ segments:
119
+ - 1
120
+ - 0
121
+ - 0
122
+ version: 1.0.0
123
+ requirement: *id007
124
+ prerelease: false
125
+ name: mechanize
126
+ - !ruby/object:Gem::Dependency
127
+ type: :runtime
128
+ version_requirements: &id008 !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ">"
132
+ - !ruby/object:Gem::Version
133
+ hash: 3
134
+ segments:
135
+ - 1
136
+ - 6
137
+ version: "1.6"
138
+ requirement: *id008
139
+ prerelease: false
140
+ name: highline
141
+ description: This is a scraper of BookScan (http://www.bookscan.co.jp/) Service.This is *NOT* a official software of BookScan.
142
+ email: y.takahara@gmail.com
143
+ executables:
144
+ - bookscan
145
+ extensions: []
146
+
147
+ extra_rdoc_files:
148
+ - LICENSE.txt
149
+ - README.rdoc
150
+ files:
151
+ - Gemfile
152
+ - LICENSE.txt
153
+ - README.rdoc
154
+ - Rakefile
155
+ - VERSION
156
+ - bin/bookscan
157
+ - lib/bookscan.rb
158
+ - lib/bookscan/agent.rb
159
+ - lib/bookscan/book.rb
160
+ - lib/bookscan/cache.rb
161
+ - lib/bookscan/cli.rb
162
+ - lib/bookscan/commands.rb
163
+ - lib/bookscan/group.rb
164
+ - lib/bookscan/groups.rb
165
+ - test/helper.rb
166
+ - test/test_bookscan.rb
167
+ has_rdoc: true
168
+ homepage: http://github.com/tumf/bookscan
169
+ licenses:
170
+ - MIT
171
+ post_install_message:
172
+ rdoc_options: []
173
+
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ hash: 3
182
+ segments:
183
+ - 0
184
+ version: "0"
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ hash: 3
191
+ segments:
192
+ - 0
193
+ version: "0"
194
+ requirements: []
195
+
196
+ rubyforge_project:
197
+ rubygems_version: 1.4.2
198
+ signing_key:
199
+ specification_version: 3
200
+ summary: BookScan Scraper
201
+ test_files:
202
+ - test/helper.rb
203
+ - test/test_bookscan.rb