require "manifique" require "down" module AppCatalogManager class UpdateMetadata < AppCatalogManagerService def initialize(app:) @app = app end def call agent = Manifique::Agent.new(url: @app.url) metadata = agent.fetch_metadata @app.name = metadata.name [:name, :short_name, :description, :theme_color, :background_color, :display, :start_url, :scope, :share_target, :icons].each do |prop| @app.metadata[prop] = metadata.send(prop) if prop end @app.save! # TODO move icon downloads to separate, async job if icon = metadata.select_icon(sizes: "256x256") || icon = metadata.select_icon(sizes: "192x192") attach_remote_image(:icon, icon) # TODO elsif get whatever is available end if apple_touch_icon = metadata.select_icon(purpose: "apple-touch-icon") attach_remote_image(:apple_touch_icon, apple_touch_icon) end rescue Manifique::Error => e msg = "Fetching web app manifest failed for #{e.url}: #{e.type}" Rails.logger.warn(msg) Sentry.capture_message(msg) if Setting.sentry_enabled? false end def attach_remote_image(attachment_name, icon) if icon['src'].start_with?("http") download_url = icon['src'] else download_url = "#{@app.url}/#{icon["src"].gsub(/^\//,'')}" end filename = "#{attachment_name}-#{Time.now.to_i}.png" key = "web_apps/#{@app.id}/icons/#{filename}" begin tempfile = Down.download(download_url) @app.send(attachment_name).attach(key: key, io: tempfile, filename: filename) rescue Down::NotFound msg = "Download of \"#{attachment_name}\" failed: NotFound error for #{download_url}" Rails.logger.warn(msg) Sentry.capture_message(msg) rescue => e Rails.logger.warn "Saving attachment \"#{attachment_name}\" failed: \"#{e.message}\"" Sentry.capture_exception(e) if Setting.sentry_enabled? end end end end