alexandria-book-collection-manager 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/.rubocop.yml +45 -27
- data/.rubocop_todo.yml +127 -86
- data/.simplecov +1 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +5 -0
- data/ChangeLog.0 +33 -35
- data/Gemfile +2 -2
- data/INSTALL.md +152 -0
- data/Rakefile +12 -10
- data/alexandria-book-collection-manager.gemspec +5 -5
- data/bin/alexandria +2 -1
- data/doc/AUTHORS +61 -0
- data/doc/BUGS +31 -0
- data/doc/FAQ +369 -0
- data/doc/HACKING +19 -0
- data/doc/NEWS +341 -0
- data/doc/alexandria.1 +120 -0
- data/doc/cuecat_support.rdoc +67 -0
- data/doc/dependency_decisions.yml +61 -0
- data/lib/alexandria.rb +2 -0
- data/lib/alexandria/about.rb +7 -6
- data/lib/alexandria/book_providers.rb +6 -6
- data/lib/alexandria/book_providers/adlibris.rb +9 -14
- data/lib/alexandria/book_providers/amazon_aws.rb +29 -33
- data/lib/alexandria/book_providers/amazon_ecs_util.rb +10 -14
- data/lib/alexandria/book_providers/barnes_and_noble.rb +9 -11
- data/lib/alexandria/book_providers/deastore.rb +12 -20
- data/lib/alexandria/book_providers/douban.rb +9 -15
- data/lib/alexandria/book_providers/mcu.rb +26 -13
- data/lib/alexandria/book_providers/proxis.rb +9 -15
- data/lib/alexandria/book_providers/pseudomarc.rb +15 -27
- data/lib/alexandria/book_providers/renaud.rb +18 -9
- data/lib/alexandria/book_providers/siciliano.rb +8 -9
- data/lib/alexandria/book_providers/thalia.rb +6 -6
- data/lib/alexandria/book_providers/web.rb +2 -0
- data/lib/alexandria/book_providers/worldcat.rb +6 -7
- data/lib/alexandria/book_providers/z3950.rb +19 -10
- data/lib/alexandria/config.rb +4 -2
- data/lib/alexandria/console.rb +2 -0
- data/lib/alexandria/execution_queue.rb +2 -2
- data/lib/alexandria/export_library.rb +14 -18
- data/lib/alexandria/import_library.rb +8 -16
- data/lib/alexandria/import_library_csv.rb +5 -52
- data/lib/alexandria/logging.rb +4 -6
- data/lib/alexandria/models/book.rb +2 -0
- data/lib/alexandria/models/library.rb +10 -20
- data/lib/alexandria/net.rb +2 -0
- data/lib/alexandria/preferences.rb +10 -14
- data/lib/alexandria/scanners.rb +2 -0
- data/lib/alexandria/scanners/cuecat.rb +4 -2
- data/lib/alexandria/scanners/keyboard.rb +2 -0
- data/lib/alexandria/smart_library.rb +4 -3
- data/lib/alexandria/ui.rb +2 -0
- data/lib/alexandria/ui/builder_base.rb +2 -0
- data/lib/alexandria/ui/callbacks.rb +8 -12
- data/lib/alexandria/ui/columns.rb +2 -0
- data/lib/alexandria/ui/completion_models.rb +2 -0
- data/lib/alexandria/ui/dialogs/about_dialog.rb +3 -1
- data/lib/alexandria/ui/dialogs/acquire_dialog.rb +11 -17
- data/lib/alexandria/ui/dialogs/alert_dialog.rb +2 -0
- data/lib/alexandria/ui/dialogs/bad_isbns_dialog.rb +10 -2
- data/lib/alexandria/ui/dialogs/barcode_animation.rb +2 -0
- data/lib/alexandria/ui/dialogs/book_properties_dialog.rb +5 -9
- data/lib/alexandria/ui/dialogs/book_properties_dialog_base.rb +3 -3
- data/lib/alexandria/ui/dialogs/export_dialog.rb +3 -3
- data/lib/alexandria/ui/dialogs/import_dialog.rb +2 -2
- data/lib/alexandria/ui/dialogs/misc_dialogs.rb +6 -4
- data/lib/alexandria/ui/dialogs/new_book_dialog.rb +22 -31
- data/lib/alexandria/ui/dialogs/new_book_dialog_manual.rb +3 -3
- data/lib/alexandria/ui/dialogs/new_smart_library_dialog.rb +3 -3
- data/lib/alexandria/ui/dialogs/preferences_dialog.rb +8 -18
- data/lib/alexandria/ui/dialogs/smart_library_properties_dialog.rb +2 -0
- data/lib/alexandria/ui/dialogs/smart_library_properties_dialog_base.rb +4 -6
- data/lib/alexandria/ui/dndable.rb +4 -2
- data/lib/alexandria/ui/icons.rb +3 -3
- data/lib/alexandria/ui/iconview.rb +3 -3
- data/lib/alexandria/ui/iconview_tooltips.rb +4 -6
- data/lib/alexandria/ui/init.rb +2 -0
- data/lib/alexandria/ui/libraries_combo.rb +2 -0
- data/lib/alexandria/ui/listview.rb +15 -12
- data/lib/alexandria/ui/main_app.rb +2 -0
- data/lib/alexandria/ui/multi_drag_treeview.rb +2 -0
- data/lib/alexandria/ui/sidepane.rb +8 -6
- data/lib/alexandria/ui/sound.rb +2 -0
- data/lib/alexandria/ui/ui_manager.rb +37 -43
- data/lib/alexandria/undo_manager.rb +2 -0
- data/lib/alexandria/version.rb +5 -3
- data/lib/alexandria/web_themes.rb +2 -0
- data/spec/alexandria/book_providers_spec.rb +12 -49
- data/spec/alexandria/book_spec.rb +4 -2
- data/spec/alexandria/library_spec.rb +2 -0
- data/spec/alexandria/preferences_spec.rb +2 -0
- data/spec/alexandria/scanners/cuecat_spec.rb +2 -0
- data/spec/alexandria/smart_library_spec.rb +3 -1
- data/spec/alexandria/ui/dialogs_spec.rb +2 -0
- data/spec/alexandria/ui/iconview_spec.rb +2 -0
- data/spec/alexandria/ui/main_app_spec.rb +2 -0
- data/spec/alexandria/ui/sidepane_spec.rb +2 -0
- data/spec/alexandria/ui/sound_spec.rb +2 -0
- data/spec/alexandria/ui/ui_manager_spec.rb +2 -0
- data/spec/alexandria/ui/ui_utilities_spec.rb +2 -0
- data/spec/alexandria/utilities_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- data/tasks/dogtail.rake +2 -0
- data/tasks/setup.rb +3 -1
- data/tasks/spec.rake +2 -0
- data/util/rake/fileinstall.rb +6 -12
- data/util/rake/gettextgenerate.rb +9 -64
- data/util/rake/omfgenerate.rb +3 -3
- metadata +21 -37
- data/INSTALL.rdoc +0 -148
- data/lib/alexandria/book_providers/bol_it.rb +0 -160
- data/lib/alexandria/book_providers/ibs_it.rb +0 -147
- data/lib/alexandria/book_providers/webster_it.rb +0 -167
@@ -1,147 +0,0 @@
|
|
1
|
-
# Copyright (C) 2005-2006 Claudio Belotti
|
2
|
-
# Copyright (C) 2014, 2016 Matijs van Zuijlen
|
3
|
-
#
|
4
|
-
# Alexandria is free software; you can redistribute it and/or
|
5
|
-
# modify it under the terms of the GNU General Public License as
|
6
|
-
# published by the Free Software Foundation; either version 2 of the
|
7
|
-
# License, or (at your option) any later version.
|
8
|
-
#
|
9
|
-
# Alexandria is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
-
# General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public
|
15
|
-
# License along with Alexandria; see the file COPYING. If not,
|
16
|
-
# write to the Free Software Foundation, Inc., 51 Franklin Street,
|
17
|
-
# Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
-
|
19
|
-
require 'fileutils'
|
20
|
-
require 'net/http'
|
21
|
-
require 'open-uri'
|
22
|
-
# require 'cgi'
|
23
|
-
|
24
|
-
module Alexandria
|
25
|
-
class BookProviders
|
26
|
-
class IBS_itProvider < GenericProvider
|
27
|
-
BASE_URI = 'http://www.internetbookshop.it'.freeze
|
28
|
-
CACHE_DIR = File.join(Alexandria::Library::DIR, '.ibs_it_cache')
|
29
|
-
REFERER = BASE_URI
|
30
|
-
def initialize
|
31
|
-
super('IBS_it', 'Internet Bookshop (Italy)')
|
32
|
-
FileUtils.mkdir_p(CACHE_DIR) unless File.exist?(CACHE_DIR)
|
33
|
-
# no preferences for the moment
|
34
|
-
at_exit { clean_cache }
|
35
|
-
end
|
36
|
-
|
37
|
-
def search(criterion, type)
|
38
|
-
criterion = criterion.encode('ISO-8859-1')
|
39
|
-
req = BASE_URI + '/ser/'
|
40
|
-
req += case type
|
41
|
-
when SEARCH_BY_ISBN
|
42
|
-
'serdsp.asp?isbn='
|
43
|
-
|
44
|
-
when SEARCH_BY_TITLE
|
45
|
-
'serpge.asp?Type=keyword&T='
|
46
|
-
|
47
|
-
when SEARCH_BY_AUTHORS
|
48
|
-
'serpge.asp?Type=keyword&A='
|
49
|
-
|
50
|
-
when SEARCH_BY_KEYWORD
|
51
|
-
'serpge.asp?Type=keyword&S='
|
52
|
-
|
53
|
-
else
|
54
|
-
raise InvalidSearchTypeError
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
req += CGI.escape(criterion)
|
59
|
-
p req if $DEBUG
|
60
|
-
data = transport.get(URI.parse(req))
|
61
|
-
if type == SEARCH_BY_ISBN
|
62
|
-
to_book(data) # rescue raise NoResultsError
|
63
|
-
else
|
64
|
-
begin
|
65
|
-
results = []
|
66
|
-
each_book_page(data) do |code, _title|
|
67
|
-
results << to_book(transport.get(URI.parse('http://www.internetbookshop.it/ser/serdsp.asp?cc=' + code)))
|
68
|
-
end
|
69
|
-
return results
|
70
|
-
rescue
|
71
|
-
raise NoResultsError
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def url(book)
|
77
|
-
'http://www.internetbookshop.it/ser/serdsp.asp?isbn=' + book.isbn
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def to_book(data)
|
83
|
-
raise NoResultsError if data =~ /<b>Il libro che hai cercato non è presente nel nostro catalogo<\/b><br>/
|
84
|
-
data = data.encode('UTF-8')
|
85
|
-
|
86
|
-
md = />Titolo<\/td><td valign="top" class="lbarrasup">([^<]+)/.match(data)
|
87
|
-
raise 'No title' unless md
|
88
|
-
title = CGI.unescape(md[1].strip)
|
89
|
-
|
90
|
-
authors = []
|
91
|
-
if (md = /<b>Autore<\/b><\/td>.+<b>([^<]+)/.match(data))
|
92
|
-
md[0].strip.gsub(/<.*?>|Autore/m, ' ').split('; ').each { |a| authors << CGI.unescape(a.strip) }
|
93
|
-
end
|
94
|
-
|
95
|
-
md = /<input type=\"hidden\" name=\"isbn\" value=\"([^"]+)\">/i.match(data)
|
96
|
-
raise 'No ISBN' unless md
|
97
|
-
isbn = md[1].strip
|
98
|
-
|
99
|
-
# raise "No publisher" unless
|
100
|
-
md = /<b>Editore<\/b><\/td>.+<b>([^<]+)/.match(data)
|
101
|
-
(publisher = CGI.unescape(md[1].strip)) || md
|
102
|
-
|
103
|
-
# raise "No edition" unless
|
104
|
-
md = /Dati<\/b><\/td><td valign="top">([^<]+)/.match(data)
|
105
|
-
(edition = CGI.unescape(md[1].strip)) || md
|
106
|
-
|
107
|
-
publish_year = nil
|
108
|
-
if (md = /Anno<\/b><\/td><td valign="top">([^<]+)/.match(data))
|
109
|
-
publish_year = CGI.unescape(md[1].strip).to_i
|
110
|
-
publish_year = nil if publish_year.zero?
|
111
|
-
end
|
112
|
-
|
113
|
-
md = /src="http:\/\/giotto.ibs.it\/cop\/copt13.asp\?f=(\d+)">/.match(data)
|
114
|
-
cover_url = 'http://giotto.ibs.it/cop/copt13.asp?f=' + md[1] # use copa13.asp, copt13.asp, copj13.asp, for small, medium, big image
|
115
|
-
cover_filename = isbn + '.tmp'
|
116
|
-
Dir.chdir(CACHE_DIR) do
|
117
|
-
File.open(cover_filename, 'w') do |file|
|
118
|
-
file.write open(cover_url, 'Referer' => REFERER).read
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
medium_cover = CACHE_DIR + '/' + cover_filename
|
123
|
-
if File.size(medium_cover) > 0 && (File.size(medium_cover) != 1822) # 1822 is the size of the fake image "copertina non disponibile"
|
124
|
-
puts medium_cover + ' has non-0 size' if $DEBUG
|
125
|
-
return [Book.new(title, authors, isbn, publisher, publish_year, edition), medium_cover]
|
126
|
-
end
|
127
|
-
puts medium_cover + ' has 0 size, removing ...' if $DEBUG
|
128
|
-
File.delete(medium_cover)
|
129
|
-
[Book.new(title, authors, isbn, publisher, publish_year, edition)]
|
130
|
-
end
|
131
|
-
|
132
|
-
def each_book_page(data)
|
133
|
-
raise if data.scan(/<a href="http:\/\/www.internetbookshop.it\/ser\/serdsp.asp\?shop=1&cc=([\w\d]+)"><b>([^<]+)/) { |a| yield a }.empty?
|
134
|
-
end
|
135
|
-
|
136
|
-
def clean_cache
|
137
|
-
# FIXME: begin ... rescue ... end?
|
138
|
-
Dir.chdir(CACHE_DIR) do
|
139
|
-
Dir.glob('*.tmp') do |file|
|
140
|
-
puts 'removing ' + file if $DEBUG
|
141
|
-
File.delete(file)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
@@ -1,167 +0,0 @@
|
|
1
|
-
# Copyright (C) 2007 Marco Costantini
|
2
|
-
# Copyright (C) 2014, 2016 Matijs van Zuijlen
|
3
|
-
# based on ibs_it.rb by Claudio Belotti
|
4
|
-
#
|
5
|
-
# Alexandria is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU General Public License as
|
7
|
-
# published by the Free Software Foundation; either version 2 of the
|
8
|
-
# License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# Alexandria is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU General Public
|
16
|
-
# License along with Alexandria; see the file COPYING. If not,
|
17
|
-
# write to the Free Software Foundation, Inc., 51 Franklin Street,
|
18
|
-
# Fifth Floor, Boston, MA 02110-1301 USA.
|
19
|
-
|
20
|
-
require 'fileutils'
|
21
|
-
require 'net/http'
|
22
|
-
require 'open-uri'
|
23
|
-
# require 'cgi'
|
24
|
-
|
25
|
-
module Alexandria
|
26
|
-
class BookProviders
|
27
|
-
class Webster_itProvider < GenericProvider
|
28
|
-
BASE_URI = 'http://www.libreriauniversitaria.it'.freeze # also "http://www.webster.it"
|
29
|
-
CACHE_DIR = File.join(Alexandria::Library::DIR, '.webster_it_cache')
|
30
|
-
REFERER = BASE_URI
|
31
|
-
LOCALE = 'BIT'.freeze # used only for search by title/author/keyword. possible are: "BIT", "BUS", "BUK", "BDE", "MIT"
|
32
|
-
def initialize
|
33
|
-
super('Webster_it', 'Webster (Italy)')
|
34
|
-
FileUtils.mkdir_p(CACHE_DIR) unless File.exist?(CACHE_DIR)
|
35
|
-
# no preferences for the moment
|
36
|
-
at_exit { clean_cache }
|
37
|
-
end
|
38
|
-
|
39
|
-
def search(criterion, type)
|
40
|
-
criterion = criterion.encode('ISO-8859-15')
|
41
|
-
req = BASE_URI + '/'
|
42
|
-
req += case type
|
43
|
-
when SEARCH_BY_ISBN
|
44
|
-
'isbn/' # "#{LOCALE}/"
|
45
|
-
|
46
|
-
when SEARCH_BY_TITLE
|
47
|
-
"c_search.php?noinput=1&shelf=#{LOCALE}&title_query="
|
48
|
-
|
49
|
-
when SEARCH_BY_AUTHORS
|
50
|
-
"c_search.php?noinput=1&shelf=#{LOCALE}&author_query="
|
51
|
-
|
52
|
-
when SEARCH_BY_KEYWORD
|
53
|
-
"c_search.php?noinput=1&shelf=#{LOCALE}&subject_query="
|
54
|
-
|
55
|
-
else
|
56
|
-
raise InvalidSearchTypeError
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
req += CGI.escape(criterion)
|
61
|
-
p req if $DEBUG
|
62
|
-
data = transport.get(URI.parse(req))
|
63
|
-
if type == SEARCH_BY_ISBN
|
64
|
-
to_book(data) # rescue raise NoResultsError
|
65
|
-
else
|
66
|
-
begin
|
67
|
-
results = []
|
68
|
-
each_book_page(data) do |code, _title|
|
69
|
-
results << to_book(transport.get(URI.parse(BASE_URI + "/#{LOCALE}/" + code)))
|
70
|
-
end
|
71
|
-
return results
|
72
|
-
rescue
|
73
|
-
raise NoResultsError
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def url(book)
|
79
|
-
BASE_URI + '/isbn/' + book.isbn
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
def to_book(data)
|
85
|
-
raise NoResultsError if data =~ /<font color="\#ffffff"><b>Prodotto non esistente<\/b><\/font>/
|
86
|
-
data = data.encode('UTF-8')
|
87
|
-
|
88
|
-
md = /<li><span class="product_label">Titolo:<\/span><span class="product_text"> ([^<]+)/.match(data)
|
89
|
-
raise unless md
|
90
|
-
title = CGI.unescape(md[1].strip)
|
91
|
-
if (md = /<span class="product_heading_volume">([^<]+)/.match(data))
|
92
|
-
title += ' ' + CGI.unescape(md[1].strip)
|
93
|
-
end
|
94
|
-
|
95
|
-
authors = []
|
96
|
-
if (md = /<li><span class="product_label">Autor[ei]:<\/span> <span class="product_text">(<a href="[^>]+">([^<]+)<\/a>,? ?)+<\/span><li>/.match(data))
|
97
|
-
this = CGI.unescape(md[0].strip)
|
98
|
-
authors = this.scan(/<a href="[^>]+">([^<]+)<\/a>,?/)
|
99
|
-
authors = authors.map { |author| author[0] }
|
100
|
-
# puts this
|
101
|
-
# md[1].strip.split(', ').each { |a| authors << CGI.unescape(a.strip) }
|
102
|
-
end
|
103
|
-
|
104
|
-
md = /<li><span class="product_label">ISBN:<\/span> <span class="product_text">([^<]+)/.match(data)
|
105
|
-
raise unless md
|
106
|
-
isbn = Library.canonicalise_ean(md[1].strip)
|
107
|
-
|
108
|
-
# raise unless
|
109
|
-
md = /<li><span class="product_label">Editore:<\/span> <span class="product_text"><a href="[^>]+>([^<]+)/.match(data)
|
110
|
-
(publisher = CGI.unescape(md[1].strip)) || md
|
111
|
-
|
112
|
-
edition = if (md = /<li><span class="product_label">Pagine:<\/span> <span class="product_text">([^<]+)/.match(data))
|
113
|
-
CGI.unescape(md[1].strip) + ' p.'
|
114
|
-
end
|
115
|
-
|
116
|
-
publish_year = nil
|
117
|
-
if (md = /<li><span class="product_label">Data di Pubblicazione:<\/span> <span class="product_text">([^<]+)/.match(data))
|
118
|
-
publish_year = CGI.unescape(md[1].strip)[-4..-1].to_i
|
119
|
-
publish_year = nil if publish_year.zero?
|
120
|
-
end
|
121
|
-
|
122
|
-
if data =~ /javascript:popImage/ && (md = /<img border="0" alt="[^"]+" src="([^"]+)/.match(data))
|
123
|
-
cover_url = BASE_URI + md[1].strip
|
124
|
-
# use "p" instead of "g" for smaller image
|
125
|
-
cover_url[-5] = 112 if cover_url[-5] == 103
|
126
|
-
|
127
|
-
cover_filename = isbn + '.tmp'
|
128
|
-
Dir.chdir(CACHE_DIR) do
|
129
|
-
begin
|
130
|
-
cover_data = open(cover_url, 'Referer' => REFERER).read
|
131
|
-
rescue OpenURI::HTTPError
|
132
|
-
cover_data = nil
|
133
|
-
end
|
134
|
-
if cover_data
|
135
|
-
File.open(cover_filename, 'w') do |file|
|
136
|
-
file.write cover_data
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
medium_cover = CACHE_DIR + '/' + cover_filename
|
142
|
-
if File.size(medium_cover) > 0
|
143
|
-
puts medium_cover + ' has non-0 size' if $DEBUG
|
144
|
-
return [Book.new(title, authors, isbn, publisher, publish_year, edition), medium_cover]
|
145
|
-
end
|
146
|
-
puts medium_cover + ' has 0 size, removing ...' if $DEBUG
|
147
|
-
File.delete(medium_cover)
|
148
|
-
end
|
149
|
-
[Book.new(title, authors, isbn, publisher, publish_year, edition)]
|
150
|
-
end
|
151
|
-
|
152
|
-
def each_book_page(data)
|
153
|
-
raise if data.scan(/<tr ><td width="10%" align="center""> <a href="#{LOCALE}\/([^\/]+)/) { |a| yield a }.empty?
|
154
|
-
end
|
155
|
-
|
156
|
-
def clean_cache
|
157
|
-
# FIXME: begin ... rescue ... end?
|
158
|
-
Dir.chdir(CACHE_DIR) do
|
159
|
-
Dir.glob('*.tmp') do |file|
|
160
|
-
puts 'removing ' + file if $DEBUG
|
161
|
-
File.delete(file)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|