-
Notifications
You must be signed in to change notification settings - Fork 1
/
convert.rb
executable file
·239 lines (193 loc) · 5.87 KB
/
convert.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#!/usr/bin/env ruby
# FIXME doesn't detect duplicates when ISBN10/ISBN13 conflict
require 'amazon_product'
require 'term/ansicolor'
require 'pp'
require 'date'
require 'optparse'
require './config.rb'
class Color
extend Term::ANSIColor
end
def prepare_request(locale='de')
req = AmazonProduct[locale]
req.configure do |c|
c.key = $access_key_id
c.secret = $secret_access_key
c.tag = $affiliate_tag
end
req
end
def get_attrs_from_isbn(isbn)
request_locales = $locales.clone
while locale = request_locales.shift
puts "Looking up ISBN #{isbn} in the #{locale} locale..."
req_options = { 'IdType' => 'ISBN',
'SearchIndex' => 'All',
'ResponseGroup' => 'Large'}
req = prepare_request(locale)
resp = req.find(isbn, req_options)
if resp.has_errors? then
pp resp.errors if $debug
status_message("No valid response received.", :warn)
next
end
resp.to_hash
resp = resp["Item"][0]['ItemAttributes']
pp resp if $debug
# store this for reference
resp['__AmazonLocale'] = locale
resp['__Author'] = []
if resp.has_key?('Author') then
resp['__Author'] << resp['Author']
elsif resp.has_key?('Creator') then
# resp['Creator'] can be an array of creators
if resp['Creator'].class == Hash
resp['Creator'] = [resp['Creator']]
end
resp['Creator'].each do |creator|
if creator['Role'] == 'Editor' || creator['Role'] == 'Herausgeber'
resp['__Author'] << creator['__content__'] + ' (Hrsg.)'
end
end
end
resp['__Author'] = resp['__Author'].flatten.join(', ')
if resp['__Author'].empty?
status_message("No author information found.", :warn)
next
end
unless resp.has_key?('Title') &&
resp.has_key?('Publisher') &&
resp.has_key?('PublicationDate')
status_message("A required key is missing from the response.", :warn)
next
end
begin
resp['__PublicationYear'] = Date.parse(resp['PublicationDate']).year
rescue ArgumentError
# TODO try to parse the date before failing for this locale
# check for a date in the format of 2005-12 or 2005
regex = /^([[:digit:]]{4})(-[[:digit:]]{1,2})?$/
if match = regex.match(resp['PublicationDate'])
resp['__PublicationYear'] = match[1]
else
status_message("The returned date is not valid.", :warn)
next
end
end
# all tests passed
return resp
end
status_message("Locales exhausted; no valid information found.", :err)
false
end
def status_message(message,level)
colors = {:info => Color.blue, :warn => Color.yellow, :success => Color.green, :err => Color.red}
color = colors[level]
puts color + "*** " + Color.clear + message
print "\a" if level == :err
end
# We don't use the amazon provided ISBN because
# it isn't reliably contained in the response
def dokuwiki_line(item, isbn, *comment)
comment.unshift(DateTime.now.to_s)
comment = comment.join(' - ')
# Dokuwiki apparently does not support escaping pipe
# symbols, so we just delete them
author = item['__Author'].delete('|')
title = item['Title'].delete('|')
publisher = item['Publisher'].delete('|')
line = "| #{author} "
line << "| #{title} "
line << "| #{publisher} "
line << "| #{item['__PublicationYear']} "
line << "| #{isbn} "
# the ugli dokuwiki part begins
line << "<html><!-- #{comment} --></html> |"
end
# append a line to a file
def write_line(line)
open('dokuwiki.txt', 'a') { |f|
# newline
f.puts
# no newline
f.print line
}
end
def normalize_isbn(isbn)
isbn.strip.delete('-')
end
def read_file
isbn_list = []
filename = 'dokuwiki.txt'
return [] unless File.file?(filename)
open(filename, 'r') { |f|
while line = f.gets
line.strip!
# check whether this is a table row
next unless line[0] == '|'
line[0] = ''
isbn = line.split('|').last.match(/^[[:space:]]*([[[:digit:]]-]*)/)[1]
isbn = normalize_isbn(isbn)
next if isbn.empty?
isbn_list << normalize_isbn(isbn)
end
}
status_message("Read #{isbn_list.length} entries from file.", :success)
isbn_list
end
def isbn_exists?(isbn)
$isbn_list.include?(isbn)
end
def print_item(item)
puts " Title: #{item['Title']}"
puts " Author: #{item['__Author']}"
puts " Publisher: #{item['Publisher']}"
puts " Publication Year: #{item['__PublicationYear']}"
end
### OPTION PARSING
no_save = no_read = false
OptionParser.new do |opts|
opts.banner = "Usage: convert.rb [options]"
opts.on("-d", "Enable debug output") do |v|
$debug = true
end
opts.on("-n", "Don't save to file") do |v|
no_save = true
end
opts.on("-b", "--blind", "Don't read input file") do |v|
no_read = true
end
end.parse!
$isbn_list = []
$isbn_list = read_file unless no_read
# amazon locales are tried in this order until a useful result is found
# $locales = ['us', 'de']
$locales = ['de', 'us']
puts "\nCERTAIN CONTENT THAT APPEARS IN THIS APPLICATION COMES FROM AMAZON EU S.à.r.l. THIS CONTENT IS PROVIDED ‘AS IS’ AND IS SUBJECT TO CHANGE OR REMOVAL AT ANY TIME.\n"
while true
pp $isbn_list if $debug
print "\n[Press RETURN to quit]\nISBN to lookup: "
isbn = normalize_isbn(STDIN.gets)
puts
break if isbn.empty?
if isbn_exists? isbn
status_message( 'This ISBN already exists in our library -- skipping',
:info)
next
end
next unless item = get_attrs_from_isbn(isbn)
pp item if $debug
status_message("Got a result", :success)
print_item item
puts ""
unless no_save then
status_message("Adding this book to the library.", :info)
write_line( dokuwiki_line(item,
isbn,
"Amazon Locale: #{item['__AmazonLocale']}"))
$isbn_list << isbn
else
status_message("Saving to file disabled - doing nothing", :info)
end
end