Skip to content

Commit

Permalink
refactor: rewrite isbn_lookup to use Google Books (#402)
Browse files Browse the repository at this point in the history
* refactor: rewrite isbn_lookup to use Google Books

* chore(books_controller): cleanup
  • Loading branch information
guidojw authored Nov 14, 2023
1 parent 785aa1a commit 9c43644
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 122 deletions.
55 changes: 25 additions & 30 deletions app/controllers/v1/books_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,44 @@ def isbn_lookup # rubocop:disable Metrics/AbcSize, Metrics/MethodLength

isbn = params.require(:isbn)

product = get_product(isbn)
return head :not_found if product.nil?

title = ActionView::Base.full_sanitizer.sanitize(get_title(product))
author = ActionView::Base.full_sanitizer.sanitize(product['specsTag'])
description = ActionView::Base.full_sanitizer.sanitize(product['longDescription'])
cover_photo = get_cover_photo(product)
volume = get_volume(isbn)
return head :not_found if volume.nil?

info = volume['volumeInfo']
title = ActionView::Base.full_sanitizer.sanitize(info['title'])
author = ActionView::Base.full_sanitizer.sanitize(info['authors'].to_sentence)
description = ActionView::Base.full_sanitizer.sanitize(info['description'])
cover_photo = get_cover_photo(volume['id'])
data = { title: title, author: author, description: description, isbn: isbn,
cover_photo: cover_photo }
render json: data
end

private

def get_product(query)
api_key = Rails.application.config.x.bol_com_api_key
url = "https://api.bol.com/catalog/v4/search?q=#{query}&offset=0&limit=1&dataoutput=products&apikey=#{api_key}&format=json"
def get_volume(isbn)
api_key = Rails.application.config.x.google_api_key
url = "https://www.googleapis.com/books/v1/volumes?q=isbn:#{isbn}&maxResults=1&projection=lite&key=#{api_key}"
result = HTTP.get(url).parse
return nil unless (result['totalResultSize']).positive?
return nil if result['items'].blank?

result['products'][0]
result['items'].first
end

def get_title(product)
if product['subtitle']
"#{product['title']} - #{product['subtitle']}"
else
product['title']
end
def cover_photo_sizes
%i[extra_large large medium small thumbnail small_thumbnail]
end

def get_cover_photo(product)
return nil unless product['images']

cover_photo = product['images'].find { |image| image['key'] == 'XL' }

# Pick the largest available image if no XL image available
cover_photo = product['images'].last if cover_photo.nil?

return nil unless cover_photo
def get_cover_photo(volume_id) # rubocop:disable Metrics/AbcSize
api_key = Rails.application.config.x.google_api_key
url = "https://www.googleapis.com/books/v1/volumes/#{volume_id}?fields=volumeInfo(imageLinks)&key=#{api_key}"
result = HTTP.get(url).parse
image_links = result.dig('volumeInfo', 'imageLinks')
return nil unless image_links

mime = Rack::Mime.mime_type(".#{cover_photo['url'].split('.').last}")
cover_photo = HTTP.get(cover_photo['url']).to_s
"data:#{mime};base64,#{Base64.strict_encode64(cover_photo)}"
camelized_sizes = cover_photo_sizes.map { |v| v.to_s.camelize(:lower) }
size = (camelized_sizes & image_links.keys).first
result = HTTP.get(image_links[size])
"data:#{result.content_type.mime_type};base64,#{Base64.strict_encode64(result.to_s)}"
end
end
2 changes: 1 addition & 1 deletion config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Application < Rails::Application
config.x.daily_verse_user = credentials.dig(Rails.env.to_sym, :daily_verse_user)
config.x.daily_verse_password = credentials.dig(Rails.env.to_sym, :daily_verse_password)

config.x.bol_com_api_key = credentials.dig(Rails.env.to_sym, :bol_com_api_key)
config.x.google_api_key = credentials.dig(Rails.env.to_sym, :google_api_key)

config.x.healthcheck_ids = credentials.dig(Rails.env.to_sym, :healthcheck_ids)
end
Expand Down
2 changes: 1 addition & 1 deletion config/credentials.yml.enc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
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--jloet2uepS8t1j3s--qPj9XF3FrBQmum0GR1GSKQ==
mmqv0PWHmGgqeoBEsj7A9U24mjevp5BZ7NsBGSkcy0dq/tQKpEYWs9XnW/SwjQMad6uT4AeWPUO1rZT8x98BxuAR7T0lRQdy68UXkuvyiGNwEhkn3Raa44H145tODn1FkGY1x5f7R4cTxUOBVq61TkUsaVmEioY/eIlZuPltLBOA4qkIhLlkAUZV34a4mdnJQuZgp9fhxCA8ZriKoZYX3d6ofJtIiOglaQSPmgHDq+vWR9FvD9pRf8fPFPx23WD3P9HKxJ4AaiavSsxKbmvj074Guzy2AnI3nr8B4R5uDi6GEjqlFYo9JmVnYx4YLIsr92xpakmQ5ECewlxVMfu/E+bMqS6ClVcPz1HFXrphbuaIK5oz//HYPXgzWq/bXEtTQNYfuP/fybgVVuO7S3pWwJ0UXyx2z5GWIJOnPBrH8kI0AdFeo/ixe1Ijkp8sJtiy4ciMtujrwRZNSVmIEvUXFRatpGMR6NezD3AfPYHh9kkrEJMs0p5Un4P51nJCDA2vKTLRoQmG5CypGGW/YGQCEet+hB6U8JFQ+8CIC4UaHeWN+zfFhBeW6zYTDR9JiXOnIlZtXmMdGlavKjaYRjOaW3dTHf4e/PqYRgFgGT8kLZov14weAjtUCS5nC5IR3p+VOxXbBiMvumh6uursr1CXVBDAclfMED1L+8is1UoYdltoytoNfiT2ab8dixAXiskzE8Rv7k32kSvi0gN0Gr4YiQj8G4Xx4sYbJyqHH2OJVKQg7dQ0h/6QfLase6qMtGkPwwlr8xzxqxS60vny/vtAeHk7ZEvmni8vfW56bBijNGrRD0koYZ/P/dwgIyYNijWDjYi9unCpcAz4o0QU/kxcjKhJHUc2ganROm5QvD2A8zNgJtf+4XBeue7C1mxn1Q7SnPizohag7Kuy6OLvdWpN2IkfBE8XiHtAbfYOra0jhxk7OPz4plD4GazWjf8MJ5lIQPq+Lt282YWic7VlYpfuCxOo2Es+1gWjy/pDxA0/RS+yCb8xFBwqrWTlv2afwY7fp6bPJXNGO9J8hAkhTAfN2ksQzKw1XWEYVVQ8/X5/VCdZCl8Jmpw9U3vUygJsOgjrcMvDkjPCRBK+WuWdFifp8q9Nqp+rMTl222UXOCClmeJQiODzllaMepsHnCqZ1inRq6LYoNw6aHm7AyWX0Q0zGN6tsnV58qEBvq6b2b2B5KVfj7NFQ2nXn/qvxP4vY2AhU08Q8Ebc4w94GELXl7rJmN74fJF5f4iga9j1DtUDZd8AhRfTHg6orr4UsjtibuhVpzOiX77i+Hb8HWA4kPzd7gUb+/JhUadYJ4P1treXbS2DXwNRCQFv2O2gs0dOBu6BDd5RyuTaFl+KZo2xESlK4v2kzyiq977F+wbOzn61EwKcQsb/jX1tdSL51eFWMFztKJo1ykBvskkUytN+jiFhwFEdIDkHFnhE3nX18udF+fY82aEgqUGTYbyXwXfdshX84v0NMz0pKT0olvC5ZJUTbggTqTsu4wyy7n16Hr/9Bvq/1pPpDsndOryFBsbGcWQODi6GFbGUP2u8F9YywlVFbG4y9GuiGUI2OSxlm2riMERoJaj1eimiJSstcrNzRXDkf76xe+0jXJ3TeqHDxRsC/uOlZvSU8gsS0QxnbSqO5H+8OO26wozYKRN5gr7NC1Vibw+ZfTxr6aYlPJ7EY06hh7anTTOI+cqu/xRz5jZZnF2cqdH02h6IjgxF3qzazPQa3o1m/0xckaeQfI8VnHMgQJytqnDUIUMchNlgalPI7BoAECSdgym5gNw9DYt7TeNiMqzwwoOptUTLbmlIeZWoPIzZuNLJxv1NeUz9Qzg4HYxfJuV6OnZhZdHCJ60PFpkfn9C01Ccl5qzJye4PyQdcaKl7D6/oiCZI57OpROKyqSzXJ/dw5jDGtW2YTKQY9O9Gs6HQxKn1eEqbnSrRUJkYFnJ9jPgkdPwwWuwVs1xWIJRbu9B7/PpEkkmEC98Bq7tN6mRFZ0iOWvSANRdEsxzV0nDU0wZS0lrrxInfhvnMi+I3R6eh6rri7Dxyf6jEW/j31BS8fgaeyRRuqCKBwozakZbR6X9r05kypvGTbh3UvjiNDWQhBUoYo5wBXt3jdEhUeTX8BOer3nJuXwptJMWsN/6gEziJhaPUhNg9PynPYKeHJb0gTzx1vHjnueObqmLnAwGHI4e2mTDw+2eUwVdt+p5p/tg+Aj6jTTOXc5XlfRLEhLfKaJiGb+ylvGg2pohg9rIEMbmFuVXb6krpbBrgZG3gprl31hbfYkAfup3e8ShJyfagpR0Pushxrdyou6XgRbWytXn1nEEDj2vvQTgt0OZkuDLc2gFC5H0Ok245/jl7sUtcpwILWW5j9mGSVFwIVAzPBcAf4iy++H3qphE3VKOaEqSH265MRaa8IYncjKOC8DKvTPwTfFGlFFrICKyGcgV0MrR3sSDZLlffsBGa4tI4oyX+M+79jozXpJ3kd4+z0nz0gBV0amssJRXCeC5s3qub6Jr7qdSP7PgFxAm5sSyNOsJr8P3bLusTtBYA97JmHIKqXn4JLz1gnRYQS7XrjquaarAFbSGMU7+bySnX0IUwbQ/6o2J7uz4T8czm+w4/gCN04z0osKCtY9lIq7eg9Ve+xyJkeBRoW6Nn5CdPcwHZwSUzcuGKg+nhPcU39kyVc93KcN48mTdkD8Qh3djZpoNECjNUkouLXpxqLmC6dWTeWQGK/MuOQSG9Yk14gWOzXa43BrO4OeE5HJfz3GLUVrA54hmY6TxO8gGvI3hCqO8e5kiBGppgOLVpyVFh28PWfoCKw3fj5cLgtEyZMRRMbh8sLOFQv11hhE2+Wip0ScwAdofkdpX0p4y90ZODKHX0LYPOwxItmzRAMTdgRuDrFqJQ+XqkpKo9kLsBjP2mXp9c8UkSjnHj0YSigaVe0bvgkKuSNk3vqRcfgIkXHHAw4jJCjB22xlp1v/2lsfYQRrhsKP6YSult12ALCwhl2NvgyhDS5rfVWEr3A5tueVMCCPLdjaVvBvqg4phqaa/57s9I3MoIe6d0bMWo9fmB/7+ajalKrvaJv1lMAlM9OSMWkDHHqw==--9gbBEsRvAgEatE/J--dMHKboMxI2U11ThEU7SzlA==
2 changes: 1 addition & 1 deletion spec/requests/v1/books_controller/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
let(:record_permission) { 'book.create' }
let(:request) do
VCR.use_cassette('retrieve_book_by_isbn') do
get "#{record_url}?isbn=9789065394309"
get "#{record_url}?isbn=9781784870140"
end
end

Expand Down
Loading

0 comments on commit 9c43644

Please sign in to comment.