alexandria-book-collection-manager 0.7.1 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +9 -0
  3. data/.gitignore +5 -2
  4. data/.hound.yml +2 -0
  5. data/.rubocop.yml +113 -45
  6. data/.rubocop_todo.yml +82 -170
  7. data/.simplecov +5 -1
  8. data/.travis.yml +45 -0
  9. data/.yardopts +1 -1
  10. data/CHANGELOG.md +60 -0
  11. data/ChangeLog.0 +33 -35
  12. data/Gemfile +6 -5
  13. data/INSTALL.md +164 -0
  14. data/README.md +52 -42
  15. data/Rakefile +95 -109
  16. data/TODO.md +9 -1
  17. data/alexandria-book-collection-manager.gemspec +52 -45
  18. data/bin/alexandria +31 -53
  19. data/doc/AUTHORS +61 -0
  20. data/doc/BUGS +31 -0
  21. data/doc/FAQ +365 -0
  22. data/doc/HACKING +19 -0
  23. data/doc/NEWS +341 -0
  24. data/doc/alexandria.1 +120 -0
  25. data/doc/cuecat_support.rdoc +67 -0
  26. data/doc/dependency_decisions.yml +80 -0
  27. data/lib/alexandria.rb +29 -37
  28. data/lib/alexandria/about.rb +52 -51
  29. data/lib/alexandria/book_providers.rb +94 -101
  30. data/lib/alexandria/book_providers/adlibris.rb +45 -85
  31. data/lib/alexandria/book_providers/amazon_aws.rb +105 -113
  32. data/lib/alexandria/book_providers/amazon_ecs_util.rb +293 -324
  33. data/lib/alexandria/book_providers/barnes_and_noble.rb +54 -53
  34. data/lib/alexandria/book_providers/douban.rb +29 -51
  35. data/lib/alexandria/book_providers/proxis.rb +42 -59
  36. data/lib/alexandria/book_providers/pseudomarc.rb +79 -99
  37. data/lib/alexandria/book_providers/siciliano.rb +68 -70
  38. data/lib/alexandria/book_providers/thalia.rb +46 -45
  39. data/lib/alexandria/book_providers/web.rb +17 -33
  40. data/lib/alexandria/book_providers/worldcat.rb +74 -102
  41. data/lib/alexandria/book_providers/z3950.rb +170 -174
  42. data/lib/alexandria/config.rb +5 -3
  43. data/lib/alexandria/console.rb +10 -21
  44. data/lib/alexandria/default_preferences.rb +37 -0
  45. data/lib/alexandria/execution_queue.rb +17 -15
  46. data/lib/alexandria/export_format.rb +47 -0
  47. data/lib/alexandria/export_library.rb +188 -302
  48. data/lib/alexandria/import_library.rb +114 -155
  49. data/lib/alexandria/import_library_csv.rb +46 -96
  50. data/lib/alexandria/library_collection.rb +79 -0
  51. data/lib/alexandria/library_sort_order.rb +45 -0
  52. data/lib/alexandria/library_store.rb +233 -0
  53. data/lib/alexandria/logging.rb +15 -19
  54. data/lib/alexandria/models/book.rb +15 -20
  55. data/lib/alexandria/models/library.rb +81 -363
  56. data/lib/alexandria/net.rb +7 -6
  57. data/lib/alexandria/preferences.rb +73 -91
  58. data/lib/alexandria/scanners.rb +4 -2
  59. data/lib/alexandria/scanners/{cuecat.rb → cue_cat.rb} +24 -20
  60. data/lib/alexandria/scanners/keyboard.rb +10 -8
  61. data/lib/alexandria/smart_library.rb +135 -171
  62. data/lib/alexandria/ui.rb +17 -15
  63. data/lib/alexandria/ui/about_dialog.rb +49 -0
  64. data/lib/alexandria/ui/{dialogs/acquire_dialog.rb → acquire_dialog.rb} +129 -152
  65. data/lib/alexandria/ui/alert_dialog.rb +64 -0
  66. data/lib/alexandria/ui/bad_isbns_dialog.rb +41 -0
  67. data/lib/alexandria/ui/{dialogs/barcode_animation.rb → barcode_animation.rb} +18 -15
  68. data/lib/alexandria/ui/{dialogs/book_properties_dialog.rb → book_properties_dialog.rb} +44 -61
  69. data/lib/alexandria/ui/{dialogs/book_properties_dialog_base.rb → book_properties_dialog_base.rb} +84 -89
  70. data/lib/alexandria/ui/builder_base.rb +9 -27
  71. data/lib/alexandria/ui/callbacks.rb +188 -186
  72. data/lib/alexandria/ui/columns.rb +2 -0
  73. data/lib/alexandria/ui/completion_models.rb +12 -23
  74. data/lib/alexandria/ui/confirm_erase_dialog.rb +33 -0
  75. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +34 -0
  76. data/lib/alexandria/ui/dndable.rb +10 -8
  77. data/lib/alexandria/ui/error_dialog.rb +25 -0
  78. data/lib/alexandria/ui/export_dialog.rb +139 -0
  79. data/lib/alexandria/ui/icons.rb +49 -65
  80. data/lib/alexandria/ui/iconview.rb +15 -13
  81. data/lib/alexandria/ui/iconview_tooltips.rb +43 -58
  82. data/lib/alexandria/ui/import_dialog.rb +157 -0
  83. data/lib/alexandria/ui/init.rb +23 -33
  84. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +36 -0
  85. data/lib/alexandria/ui/libraries_combo.rb +18 -14
  86. data/lib/alexandria/ui/listview.rb +77 -88
  87. data/lib/alexandria/ui/main_app.rb +26 -26
  88. data/lib/alexandria/ui/misc_dialogs.rb +10 -0
  89. data/lib/alexandria/ui/multi_drag_treeview.rb +30 -41
  90. data/lib/alexandria/ui/{dialogs/new_book_dialog.rb → new_book_dialog.rb} +168 -215
  91. data/lib/alexandria/ui/new_book_dialog_manual.rb +139 -0
  92. data/lib/alexandria/ui/new_provider_dialog.rb +100 -0
  93. data/lib/alexandria/ui/new_smart_library_dialog.rb +74 -0
  94. data/lib/alexandria/ui/preferences_dialog.rb +313 -0
  95. data/lib/alexandria/ui/provider_preferences_base_dialog.rb +95 -0
  96. data/lib/alexandria/ui/provider_preferences_dialog.rb +35 -0
  97. data/lib/alexandria/ui/really_delete_dialog.rb +53 -0
  98. data/lib/alexandria/ui/{sidepane.rb → sidepane_manager.rb} +62 -72
  99. data/lib/alexandria/ui/skip_entry_dialog.rb +33 -0
  100. data/lib/alexandria/ui/smart_library_properties_dialog.rb +60 -0
  101. data/lib/alexandria/ui/{dialogs/smart_library_properties_dialog_base.rb → smart_library_properties_dialog_base.rb} +96 -172
  102. data/lib/alexandria/ui/smart_library_rule_box.rb +119 -0
  103. data/lib/alexandria/ui/sound.rb +13 -13
  104. data/lib/alexandria/ui/ui_manager.rb +262 -283
  105. data/lib/alexandria/undo_manager.rb +3 -0
  106. data/lib/alexandria/version.rb +6 -19
  107. data/lib/alexandria/web_themes.rb +24 -21
  108. data/po/Makefile +2 -2
  109. data/po/cs.po +993 -880
  110. data/po/cy.po +957 -874
  111. data/po/de.po +990 -869
  112. data/po/el.po +989 -869
  113. data/po/es.po +985 -865
  114. data/po/fr.po +986 -870
  115. data/po/ga.po +907 -823
  116. data/po/gl.po +981 -865
  117. data/po/it.po +986 -868
  118. data/po/ja.po +969 -853
  119. data/po/mk.po +983 -863
  120. data/po/nb.po +979 -863
  121. data/po/nl.po +983 -864
  122. data/po/pl.po +1020 -969
  123. data/po/pt.po +988 -861
  124. data/po/pt_BR.po +984 -868
  125. data/po/ru.po +992 -873
  126. data/po/sk.po +987 -869
  127. data/po/sv.po +977 -861
  128. data/po/uk.po +975 -865
  129. data/po/zh_TW.po +976 -860
  130. data/schemas/alexandria.schemas +25 -3
  131. data/share/alexandria/glade/acquire_dialog__builder.glade +15 -12
  132. data/share/alexandria/glade/book_properties_dialog__builder.glade +171 -299
  133. data/share/alexandria/glade/main_app__builder.glade +24 -33
  134. data/share/alexandria/glade/new_book_dialog__builder.glade +27 -59
  135. data/share/alexandria/glade/preferences_dialog__builder.glade +250 -290
  136. data/share/gnome/help/alexandria/C/introduction.xml +0 -8
  137. data/share/gnome/help/alexandria/C/searching.xml +1 -1
  138. data/share/gnome/help/alexandria/C/smart-libraries.xml +2 -2
  139. data/share/gnome/help/alexandria/C/working-with-libraries.xml +1 -1
  140. data/share/gnome/help/alexandria/fr/alexandria.xml +1 -1
  141. data/share/gnome/help/alexandria/ja/introduction.xml +0 -8
  142. data/share/gnome/help/alexandria/ja/smart-libraries.xml +1 -1
  143. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +160 -0
  144. data/spec/alexandria/book_providers_spec.rb +77 -210
  145. data/spec/alexandria/book_spec.rb +16 -12
  146. data/spec/alexandria/console_spec.rb +27 -0
  147. data/spec/alexandria/export_library_spec.rb +130 -0
  148. data/spec/alexandria/library_spec.rb +130 -172
  149. data/spec/alexandria/library_store_spec.rb +37 -0
  150. data/spec/alexandria/preferences_spec.rb +46 -17
  151. data/spec/alexandria/scanners/cue_cat_spec.rb +52 -0
  152. data/spec/alexandria/smart_library_spec.rb +32 -25
  153. data/spec/alexandria/ui/about_dialog_spec.rb +14 -0
  154. data/spec/alexandria/ui/acquire_dialog_spec.rb +14 -0
  155. data/spec/alexandria/ui/alert_dialog_spec.rb +16 -0
  156. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +14 -0
  157. data/spec/alexandria/ui/book_properties_dialog_spec.rb +17 -0
  158. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +14 -0
  159. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +16 -0
  160. data/spec/alexandria/ui/error_dialog_spec.rb +14 -0
  161. data/spec/alexandria/ui/export_dialog_spec.rb +15 -0
  162. data/spec/alexandria/ui/icons_spec.rb +26 -0
  163. data/spec/alexandria/ui/iconview_spec.rb +9 -21
  164. data/spec/alexandria/ui/import_dialog_spec.rb +41 -0
  165. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +17 -0
  166. data/spec/alexandria/ui/main_app_spec.rb +8 -33
  167. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +15 -0
  168. data/spec/alexandria/ui/new_book_dialog_spec.rb +22 -0
  169. data/spec/alexandria/ui/new_provider_dialog_spec.rb +30 -0
  170. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +39 -0
  171. data/spec/alexandria/ui/preferences_dialog_spec.rb +14 -0
  172. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +34 -0
  173. data/spec/alexandria/ui/really_delete_dialog_spec.rb +16 -0
  174. data/spec/alexandria/ui/sidepane_manager_spec.rb +15 -0
  175. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +14 -0
  176. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +32 -0
  177. data/spec/alexandria/ui/sound_spec.rb +4 -2
  178. data/spec/alexandria/ui/ui_manager_spec.rb +45 -20
  179. data/spec/end_to_end/basic_run_spec.rb +57 -0
  180. data/spec/spec_helper.rb +66 -33
  181. data/tasks/setup.rb +5 -3
  182. data/tasks/spec.rake +18 -3
  183. data/util/rake/fileinstall.rb +38 -40
  184. data/util/rake/gettextgenerate.rb +15 -70
  185. data/util/rake/omfgenerate.rb +10 -10
  186. metadata +176 -60
  187. data/INSTALL.rdoc +0 -148
  188. data/dogtail/basic_run_test.py +0 -9
  189. data/lib/alexandria/book_providers/bol_it.rb +0 -160
  190. data/lib/alexandria/book_providers/deastore.rb +0 -273
  191. data/lib/alexandria/book_providers/ibs_it.rb +0 -147
  192. data/lib/alexandria/book_providers/mcu.rb +0 -169
  193. data/lib/alexandria/book_providers/renaud.rb +0 -140
  194. data/lib/alexandria/book_providers/webster_it.rb +0 -167
  195. data/lib/alexandria/ui/dialogs/about_dialog.rb +0 -59
  196. data/lib/alexandria/ui/dialogs/alert_dialog.rb +0 -70
  197. data/lib/alexandria/ui/dialogs/bad_isbns_dialog.rb +0 -43
  198. data/lib/alexandria/ui/dialogs/export_dialog.rb +0 -171
  199. data/lib/alexandria/ui/dialogs/import_dialog.rb +0 -196
  200. data/lib/alexandria/ui/dialogs/misc_dialogs.rb +0 -85
  201. data/lib/alexandria/ui/dialogs/new_book_dialog_manual.rb +0 -154
  202. data/lib/alexandria/ui/dialogs/new_smart_library_dialog.rb +0 -74
  203. data/lib/alexandria/ui/dialogs/preferences_dialog.rb +0 -578
  204. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog.rb +0 -57
  205. data/spec/alexandria/scanners/cuecat_spec.rb +0 -65
  206. data/spec/alexandria/ui/dialogs_spec.rb +0 -94
  207. data/spec/alexandria/ui/sidepane_spec.rb +0 -27
  208. data/spec/alexandria/ui/ui_utilities_spec.rb +0 -60
  209. data/spec/alexandria/utilities_spec.rb +0 -50
  210. data/tasks/dogtail.rake +0 -4
@@ -1,148 +0,0 @@
1
- = Installing Alexandria
2
-
3
- Alexandria is written in Ruby with a GTK+2/GNOME user-interface. It
4
- currently only runs on UNIX-style systems, such as GNU/Linux.
5
-
6
- Alexandria is not an easy project to build from scratch. Apart from
7
- Ruby and GNOME, it has a lot of dependencies; however, many of these
8
- are now optional as detailed below. Once the dependencies have been
9
- installed, building and installing Alexandria is relatively
10
- straightforward.
11
-
12
- [Also note that there are pre-built packages for some distros, such as
13
- Fedora and Ubuntu.]
14
-
15
- == Dependencies
16
-
17
- The {Ruby-GNOME2}[http://ruby-gnome2.sourceforge.jp/] user-interface
18
- involves a number of packages:
19
-
20
- * <tt>ruby-gtk2</tt>
21
- * <tt>ruby-goocanvas</tt>
22
- * <tt>ruby-gst</tt>
23
- * <tt>ruby-pango</tt>
24
-
25
- You should have GTK+ >= 2.22.0, and use Ruby-GNOME2 >= 0.16.0.
26
-
27
- <tt>ruby-gettext</tt>[http://ponx.s5.xrea.com/hiki/ruby-gettext.html]
28
- is required for the internationalisation of the user interface.
29
- Requires version 1.7.0 or higher.
30
-
31
- === Hpricot
32
-
33
- Alexandria uses +hpricot+[http://code.whytheluckystiff.net/hpricot] to
34
- parse the HTML from web pages for providers such as DeaStore and
35
- Siciliano. It is also used to parse the XML for the Amazon web
36
- service. You can install the +hpricot+ package natively or as a
37
- ruby gem.
38
-
39
- == HTMLEntities
40
-
41
- This is used by all website-based providers except MCU.
42
- +htmlentities+[http://htmlentities.rubyforge.org/] is used to
43
- provide more flexible HTML parsing.
44
-
45
- == Build Dependencies
46
-
47
- === Ruby Dependencies
48
-
49
- +rake+[http://rake.rubyforge.org] is required to build Alexandria from
50
- the project +Rakefile+.
51
-
52
- You also need +rubygems+[http://www.rubygems.org/] and
53
- +rspec+[http://rspec.rubyforge.org/] to run the RSpec test suite.
54
-
55
- === Native Dependencies
56
-
57
- The +gettext+[http://www.gnu.org/software/gettext] package is needed
58
- to generate the binary +mo+ files used by <tt>ruby-gettext</tt> at
59
- runtime. You also need the
60
- +intltool+[http://www.freedesktop.org/wiki/Software/intltool] package
61
- to merge translations into generated files (and to extract
62
- translatable string from xml files during development).
63
-
64
- Note that these files are pre-generated in tar.gz releases, so you'll
65
- only need them if you're building from the SVN version, or want to
66
- change the translations.
67
-
68
- === Ruby/ZOOM and Yaz
69
-
70
- For Z39.50 support and and the <b>Library of Congress</b> and
71
- <b>British Library</b> book providers you will need
72
- <tt>ruby-zoom</tt>[http://ruby-zoom.rubyforge.org], which in turn
73
- requires the non-Ruby package +yaz+[http://www.indexdata.dk/yaz].
74
-
75
- Note that if you install the recent Ruby/ZOOM as the +zoom+ gem, you
76
- will also need to install the +marc+ gem. (Older implementations of
77
- ruby-zoom contained their own implementation of MARC.)
78
-
79
- The Z39.50 Object-Orientation Model (ZOOM) is an international
80
- standard for communication between computer systems, particularly
81
- libraries and information-related systems.
82
-
83
- === image_size
84
-
85
- You will need
86
- <tt>image_size</tt>[http://rubyforge.org/projects/imagesize/] for
87
- optimizing the cover images in exported libraries.
88
-
89
- == Build and Install
90
-
91
- To build Alexandria from a subversion checkout, go to the base project
92
- directory (where the Rakefile and this INSTALL file are located) and
93
- issue the command
94
- rake build
95
- If you have downloaded a source package, this step will not usually be
96
- necessary.
97
-
98
- You must have root priveledges to install, so use +su+
99
- su -c 'rake install'
100
- or +sudo+
101
- sudo rake install
102
-
103
- Now you can check the version of the installed Alexandria
104
- alexandria --version
105
-
106
- To launch Alexandria, simply use
107
- alexandria
108
-
109
- If you wish to see more output on the console, you can use
110
- alexandria --debug
111
-
112
- === Staged installation for making packages
113
-
114
- When building a binary package (such as a deb or rpm) you will want to
115
- "install" Alexandria into a specified directory instead of the root
116
- filesystem. You should specify this as the DESTDIR environment variable
117
- and use the +install_package_staging+ task instead of +install+
118
-
119
- DESTDIR=debian/alexandria rake install_package_staging
120
-
121
- If your distribution uses a specific directory to install Ruby
122
- packages, you should also set the RUBYLIBDIR.
123
-
124
- === Installing in the home directory
125
-
126
- If you want to install Alexandria in your home directory, you should
127
- specify the PREFIX, SHARE and RUBYLIBDIR envrionment variables, and
128
- use the +install_package+ task instead of +install+.
129
-
130
- PREFIX=$HOME SHARE=$HOME/.share RUBYLIBDIR=$HOME/.rubylib rake install_package
131
-
132
- This will install the +alexandria+ program into +$HOME/bin+ (which you
133
- should add to your +PATH+), and the ruby files to your
134
- +$HOME/.rubylib+ which you should add to your +RUBYLIBDIR+ environment
135
- variable.
136
-
137
- === Uninstalling
138
-
139
- To uninstall, simply run
140
-
141
- sudo rake uninstall
142
-
143
- (or +rake uninstall_package+ if you installed in your home directory).
144
-
145
- If you specified any of the environment variables PREFIX, SHARE,
146
- RUBYLIBDIR and DESTDIR during the installation, you should use the
147
- same variables during uninstallation (or rake won't know where to look
148
- for the files it has to remove).
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env python
2
-
3
- from dogtail.tree import *
4
- from dogtail.utils import run
5
-
6
- run('bin/alexandria', appName = 'alexandria')
7
- app = root.application('alexandria')
8
- quit_item = app.menuItem('Quit')
9
- quit_item.doActionNamed('click')
@@ -1,160 +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 BOL_itProvider < GenericProvider
28
- BASE_URI = 'http://www.bol.it'.freeze
29
- CACHE_DIR = File.join(Alexandria::Library::DIR, '.bol_it_cache')
30
- REFERER = BASE_URI
31
- LOCALE = 'libri'.freeze # possible locales are: "libri", "inglesi", "video", "musica", "choco"
32
- def initialize
33
- super('BOL_it', 'BOL (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-1')
41
- req = BASE_URI + '/' + LOCALE + '/'
42
- req += case type
43
- when SEARCH_BY_ISBN
44
- 'scheda/'
45
-
46
- when SEARCH_BY_TITLE
47
- 'risultatoricerca?action=bolrisultatoricerca&skin=bol&filtro_ricerca=BOL&quick_type=Titolo&titolo='
48
-
49
- when SEARCH_BY_AUTHORS
50
- 'risultatoricerca?action=bolrisultatoricerca&skin=bol&filtro_ricerca=BOL&quick_type=Autore&titolo='
51
-
52
- when SEARCH_BY_KEYWORD
53
- 'risultatoricerca?action=bolrisultatoricerca&skin=bol&filtro_ricerca=BOL&quick_type=Parola%20chiave&titolo='
54
-
55
- else
56
- raise InvalidSearchTypeError
57
-
58
- end
59
-
60
- ## warning: this provider uses pages like http://www.bol.it/libri/scheda/ea978888584104 with 12 numbers, without the checksum
61
- criterion = 'ea' + Library.canonicalise_ean(criterion)[0..-2] + '.html' if type == SEARCH_BY_ISBN
62
- req += CGI.escape(criterion)
63
- p req if $DEBUG
64
- data = transport.get(URI.parse(req))
65
- if type == SEARCH_BY_ISBN
66
- to_book(data) # rescue raise NoResultsError
67
- else
68
- begin
69
- results = []
70
- each_book_page(data) do |code, _title|
71
- results << to_book(transport.get(URI.parse(BASE_URI + "/#{LOCALE}/scheda/ea" + code)))
72
- end
73
- return results
74
- rescue
75
- raise NoResultsError
76
- end
77
- end
78
- end
79
-
80
- def url(book)
81
- BASE_URI + "/#{LOCALE}/scheda/ea" + Library.canonicalise_ean(book.isbn)[0..-2] + '.html'
82
- end
83
-
84
- private
85
-
86
- def to_book(data)
87
- raise NoResultsError if data =~ /Scheda libro non completa \(TP null\)/
88
- data = data.encode('UTF-8')
89
-
90
- md = /<INPUT type =hidden name ="mailTitolo" value="([^"]+)/.match(data)
91
- raise 'No title' unless md
92
- title = CGI.unescape(md[1].strip)
93
-
94
- authors = []
95
- if (md = /<INPUT type =HIDDEN name ="mailAutore" value="([^"]+)/.match(data))
96
- md[1].strip.split(', ').each { |a| authors << CGI.unescape(a.strip) }
97
- end
98
-
99
- md = /<INPUT type =HIDDEN name ="mailEAN" value="([^"]+)/.match(data)
100
- raise 'No ISBN' unless md
101
- isbn = md[1].strip
102
- isbn += String(Library.ean_checksum(Library.extract_numbers(isbn)))
103
-
104
- # raise unless
105
- md = /<INPUT type =HIDDEN name ="mailEditore" value="([^"]+)/.match(data)
106
- (publisher = CGI.unescape(md[1].strip)) || md
107
-
108
- # raise unless
109
- md = /<INPUT type =HIDDEN name ="mailFormato" value="([^"]+)/.match(data)
110
- (edition = CGI.unescape(md[1].strip)) || md
111
-
112
- if (md = /#{edition}\&nbsp\;\|\&nbsp\;(\d+)\&nbsp\;\|\&nbsp\;/.match(data))
113
- nr_pages = CGI.unescape(md[1].strip)
114
- elsif (md = / (\d+) pagine \| /.match(data))
115
- nr_pages = CGI.unescape(md[1].strip)
116
- end
117
- if (nr_pages != '0') && !nr_pages.nil?
118
- edition = nr_pages + ' p., ' + edition
119
- end
120
-
121
- publish_year = nil
122
- if (md = /<INPUT type =HIDDEN name ="mailAnnoPubbl" value="([^"]+)/.match(data))
123
- publish_year = CGI.unescape(md[1].strip).to_i
124
- publish_year = nil if publish_year.zero?
125
- end
126
-
127
- cover_url = BASE_URI + '/bol/includes/tornaImmagine.jsp?cdSoc=BL&ean=' + isbn[0..11] + '&tipoOggetto=PIB&cdSito=BL' # use "FRB" instead of "PIB" for smaller images
128
- cover_filename = isbn + '.tmp'
129
- Dir.chdir(CACHE_DIR) do
130
- File.open(cover_filename, 'w') do |file|
131
- file.write open(cover_url, 'Referer' => REFERER).read
132
- end
133
- end
134
-
135
- medium_cover = CACHE_DIR + '/' + cover_filename
136
- if File.size(medium_cover) > 43 && (File.size(medium_cover) != 2382) # 2382 is the size of the fake image "copertina non disponibile"
137
- puts medium_cover + ' has non-0 size' if $DEBUG
138
- return [Book.new(title, authors, isbn, publisher, publish_year, edition), medium_cover]
139
- end
140
- puts medium_cover + ' has 0 size, removing ...' if $DEBUG
141
- File.delete(medium_cover)
142
- [Book.new(title, authors, isbn, publisher, publish_year, edition)]
143
- end
144
-
145
- def each_book_page(data)
146
- raise if data.scan(/<a href="\/#{LOCALE}\/scheda\/ea(\d+)\.html;jsessionid=[^"]+">\s*Scheda completa\s*<\/a>/) { |a| yield a }.empty?
147
- end
148
-
149
- def clean_cache
150
- # FIXME: begin ... rescue ... end?
151
- Dir.chdir(CACHE_DIR) do
152
- Dir.glob('*.tmp') do |file|
153
- puts 'removing ' + file if $DEBUG
154
- File.delete(file)
155
- end
156
- end
157
- end
158
- end
159
- end
160
- end
@@ -1,273 +0,0 @@
1
- # -*- ruby -*-
2
- #
3
- # Copyright (C) 2009 Cathal Mc Ginley
4
- # Copyright (C) 2011, 2014, 2016 Matijs van Zuijlen
5
- #
6
- # Alexandria is free software; you can redistribute it and/or
7
- # modify it under the terms of the GNU General Public License as
8
- # published by the Free Software Foundation; either version 2 of the
9
- # License, or (at your option) any later version.
10
- #
11
- # Alexandria is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
- # General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU General Public
17
- # License along with Alexandria; see the file COPYING. If not,
18
- # write to the Free Software Foundation, Inc., 51 Franklin Street,
19
- # Fifth Floor, Boston, MA 02110-1301 USA.
20
-
21
- # New DeaStore provider, taken from the Palatina MetaDataSource and
22
- # modified to fit the structure of Alexandria book providers.
23
- # (24 Feb 2009)
24
-
25
- require 'cgi'
26
- require 'alexandria/net'
27
- require 'alexandria/book_providers/web'
28
-
29
- module Alexandria
30
- class BookProviders
31
- class DeaStoreProvider < WebsiteBasedProvider
32
- include Alexandria::Logging
33
-
34
- SITE = 'http://www.deastore.com'.freeze
35
- BASE_SEARCH_URL = "#{SITE}/search/italian_books/0/%s/%s".freeze # type/term
36
-
37
- def initialize
38
- super('DeaStore', 'DeaStore (Italy)')
39
- prefs.read
40
- @agent = nil
41
- end
42
-
43
- def agent
44
- unless @agent
45
- @agent = Alexandria::WWWAgent.new
46
- @agent.language = :it
47
- end
48
- @agent
49
- end
50
-
51
- def get_book_from_search_result(result)
52
- log.debug { "Fetching book from #{result[:url]}" }
53
- html_data = agent.get(result[:url])
54
- # File.open("rsltflarn#{Time.now().usec()}.html", 'wb') do |f|
55
- # f.write(html_data.body)
56
- # end
57
- parse_result_data(html_data.body)
58
- end
59
-
60
- def search(criterion, type)
61
- begin
62
- criterion = criterion.encode('ISO-8859-1') # still needed??
63
- rescue Encoding::UndefinedConversionError
64
- log.info { "Cannot search for non-ISO-8859-1 terms at DeaStore : #{criterion}" }
65
- raise NoResultsError
66
- end
67
- html_data = agent.get(create_search_uri(type, criterion))
68
- # File.open("flarn#{Time.now().usec()}.html", 'wb') do |f|
69
- # f.write(html_data.body)
70
- # end
71
- results = parse_search_result_data(html_data.body)
72
- raise NoResultsError if results.empty?
73
-
74
- if type == SEARCH_BY_ISBN
75
- get_book_from_search_result(results.first)
76
- else
77
- results.map { |result| get_book_from_search_result(result) }
78
- end
79
- end
80
-
81
- # it isn't possible to create a URL for a book given only the ISBN...
82
- def url(_book)
83
- nil
84
- end
85
-
86
- private
87
-
88
- def create_search_uri(search_type, search_term)
89
- # bah! very, very similar to the siciliano code! refactor out this duplication
90
- (search_type_code = { SEARCH_BY_ISBN => 'isbn',
91
- SEARCH_BY_TITLE => 'title',
92
- SEARCH_BY_AUTHORS => 'author',
93
- SEARCH_BY_KEYWORD => 'keywords' }[search_type]) || 'keywords'
94
-
95
- search_term_encoded = if search_type == SEARCH_BY_ISBN
96
- Library.canonicalise_isbn(search_term) # isbn-10
97
- else
98
- CGI.escape(search_term)
99
- end
100
-
101
- uri = BASE_SEARCH_URL % [search_type_code, search_term_encoded]
102
- log.debug { uri }
103
- uri
104
- end
105
-
106
- def parse_search_result_data(html)
107
- doc = html_to_doc(html)
108
- book_search_results = []
109
-
110
- result_divs = doc.search('div.scheda_prodotto')
111
- result_divs.each do |div|
112
- begin
113
- # The layout...
114
- # a > img
115
- # div.scheda_content
116
- # a[link->productpage] title ## a.titolo_link
117
- # p (genre I think) ## !ignore
118
- # a[link->author] author ## a.info
119
- # p.editore (publisher? editor?)
120
- # p Data di pubblicazione: \n 2009
121
- # p.prezzo (price)
122
-
123
- # cover_url = ''
124
- # cover_images = div/'a/img'
125
- # unless cover_images.empty?
126
- # img = cover_images.first
127
- # image_url = img['src']
128
- # if image_url =~ /^http/
129
- # cover_url = '' # image_url
130
- # elsif image_url[0..0] != '/'
131
- # cover_url = "#{SITE}/#{image_url}"
132
- # else
133
- # cover_url = "#{SITE}#{image_url}"
134
- # end
135
- # log.debug { "Search Cover Image URL #{cover_url}" }
136
-
137
- # end
138
-
139
- content = div / 'div.scheda_content'
140
- title_link = (content / :a).first
141
- title = normalize(title_link.inner_text)
142
- link_to_description = title_link['href']
143
- lookup_url = "#{SITE}#{link_to_description}"
144
-
145
- authors = []
146
- (content / 'a.info').each do |link|
147
- authors << normalize(link.inner_text)
148
- end
149
-
150
- result = {}
151
- result[:author] = authors.first # HACK, what about multiple authors
152
- result[:title] = title
153
- result[:url] = lookup_url
154
-
155
- publishers = (content / 'p.editore')
156
- unless publishers.empty?
157
- result[:publisher] = normalize(publishers.first.inner_text)
158
- end
159
-
160
- book_search_results << result
161
- rescue => ex
162
- trace = ex.backtrace.join("\n> ")
163
- log.error { "Failed parsing DeaStore search page #{ex.message}\n#{trace}" }
164
- end
165
- end
166
- book_search_results
167
- end
168
-
169
- def parse_result_data(html)
170
- doc = html_to_doc(html)
171
- data = doc % 'div#dati_scheda'
172
- # sotto_data_hdr = doc % 'div.sotto_schede/h1.titolo_sotto[text()*="Informazioni generali"]/..'
173
- # title
174
- title_span = data % 'h1.titolo_scheda'
175
- title = normalize(title_span.inner_text)
176
- # cover
177
- cover_link = nil
178
- cover_img = data / 'a/img'
179
- unless cover_img.empty?
180
- cover_link = cover_img.first['src']
181
- end
182
- # author(s)
183
- authors = []
184
- author_span = data % 'span.int_scheda[text()*=Autore]'
185
- unless author_span
186
- author_span = data % 'span.int_scheda[text()*=cura]' # editor
187
- end
188
- if author_span
189
- author_links = author_span / 'a.info'
190
- authors = []
191
- author_links.each do |link|
192
- authors << normalize(link.inner_html)
193
- end
194
- end
195
- # if author_span
196
- # author_links = author_span/'a.info'
197
- # author_links.each do |link|
198
- # authors << normalize(link.inner_text)
199
- # end
200
- # end
201
- # publisher
202
- publisher_par = data % 'span.int_scheda[text()*=Editore]/..'
203
- publisher_link = publisher_par % 'a.info'
204
- publisher = normalize(publisher_link.inner_text)
205
- # skip 'Collana', (ummm, possibly genre information, Babelfish
206
- # says "Necklace")
207
- # format
208
- format_par = data % 'span.int_scheda[text()*=Formato]/..'
209
- format_par.inner_text =~ /:[\s]*(.+)[\s]*$/
210
- binding = normalize(Regexp.last_match[1])
211
- # year
212
- date_par = data % 'span.int_scheda[text()*=Data di pubblicazione]/..'
213
- date_par.inner_text =~ /:[\s]*([12][0-9]{3})[\s]*$/
214
- publish_year = nil
215
- if Regexp.last_match[1]
216
- publish_year = Regexp.last_match[1].to_i
217
- end
218
- isbn_spans = data / 'div.sotto/span.isbn'
219
- isbns = []
220
- isbn_spans.each do |span|
221
- span.inner_text =~ /:[\s]*(.+)[\s]*$/
222
- isbns << Regexp.last_match[1]
223
- end
224
- isbn = nil
225
- unless isbns.empty?
226
- isbn = Library.canonicalise_isbn(isbns.first)
227
- end
228
- # Editore & Imprint : as publisher info above...
229
- # pages
230
- # page_par = data % 'span.int_scheda[text()*=Pagine]/..'
231
- # if page_par
232
- # page_par.inner_text =~ /:[\s]*([0-9]+)[\s]*$/
233
- # pages = $1.to_i
234
- # end
235
- # synopsis_div = doc % 'div.sotto_schede' # exclude the first span though
236
- # book = Book.new(title, isbns.first, authors)
237
- # if publisher
238
- # book.publisher = Publisher.new(publisher)
239
- # end
240
- # if format
241
- # book.binding = CoverBinding.new(format, binding_type(format))
242
- # end
243
- # cover
244
- image_url = nil
245
- if cover_link
246
- image_url = if cover_link =~ /^http/
247
- # e.g. http://images.btol.com/ContentCafe/Jacket.aspx?\
248
- # Return=1&amp;Type=M&amp;Value=9788873641803&amp;password=\
249
- # CC70580&amp;userID=DEA40305
250
- # seems not to work, or to be blank anyway, so set to nil
251
- nil
252
- elsif cover_link[0..0] != '/'
253
- "#{SITE}/#{cover_link}"
254
- else
255
- "#{SITE}#{cover_link}"
256
- end
257
- log.debug { "Cover Image URL:: #{image_url}" }
258
- end
259
- book = Book.new(title, authors, isbn, publisher, publish_year, binding)
260
- return [book, image_url]
261
- rescue => ex
262
- trace = ex.backtrace.join("\n> ")
263
- log.error { "Failed parsing DeaStore product page #{ex.message}\n#{trace}" }
264
- return nil
265
- end
266
-
267
- def normalize(str)
268
- str = str.squeeze(' ').strip unless str.nil?
269
- str
270
- end
271
- end
272
- end
273
- end