diff --git a/app/controllers/entries_controller.rb b/app/controllers/entries_controller.rb index 6c7ac395..df440f50 100644 --- a/app/controllers/entries_controller.rb +++ b/app/controllers/entries_controller.rb @@ -101,7 +101,7 @@ def create if params[:entry][:image].present? if @existing_entry.image_url_cdn.present? || params[:entry][:image].count > 1 image_urls = collage_from_attachments(Array(params[:entry][:image])) - ImageCollageJob.perform_later(@existing_entry.id, image_urls) + ImageCollageJob.perform_later(@existing_entry.id, urls: image_urls) elsif params[:entry][:image].present? @existing_entry.image = params[:entry][:image].first end @@ -117,7 +117,7 @@ def create @entry = current_user.entries.create(entry_params) if params[:entry][:image].present? && params[:entry][:image].count > 1 image_urls = collage_from_attachments(params[:entry][:image]) - ImageCollageJob.perform_later(@entry.id, image_urls) + ImageCollageJob.perform_later(@entry.id, urls: image_urls) elsif params[:entry][:image].present? @entry.image = params[:entry][:image].first end @@ -155,7 +155,7 @@ def update if params[:entry][:image].present? if @existing_entry.image_url_cdn.present? || params[:entry][:image].count > 1 image_urls = collage_from_attachments(Array(params[:entry][:image])) - ImageCollageJob.perform_later(@existing_entry.id, image_urls) + ImageCollageJob.perform_later(@existing_entry.id, urls: image_urls) else @existing_entry.image = params[:entry][:image] end @@ -182,7 +182,7 @@ def update if @entry.update(update_params) if params[:entry][:image].present? && params[:entry][:image].size > 1 image_urls = collage_from_attachments(params[:entry][:image]) - ImageCollageJob.perform_later(@entry.id, image_urls) + ImageCollageJob.perform_later(@entry.id, urls: image_urls) elsif params[:entry][:image].present? @entry.image = params[:entry][:image].first @entry.save diff --git a/app/jobs/image_collage_job.rb b/app/jobs/image_collage_job.rb index e04b1ae6..950e344e 100644 --- a/app/jobs/image_collage_job.rb +++ b/app/jobs/image_collage_job.rb @@ -1,20 +1,82 @@ class ImageCollageJob < ActiveJob::Base queue_as :default - def perform(entry_id, urls) + def perform(entry_id, urls: nil, message_id: nil) entry = Entry.where(id: entry_id).first + @message_id = message_id return nil unless entry.present? entry.update(filepicker_url: "https://dabble-me.s3.amazonaws.com/uploading.png") - existing_url = entry&.image_url_cdn == "https://dabble-me.s3.amazonaws.com/uploading.png" ? nil : entry&.image_url_cdn + @existing_url = entry&.image_url_cdn == "https://dabble-me.s3.amazonaws.com/uploading.png" ? nil : entry&.image_url_cdn - filestack_collage_url = collage_from_urls(urls + [existing_url]) + if @message_id.present? + filestack_collage_url = collage_from_mailgun_attachments + else + filestack_collage_url = collage_from_urls(urls + [@existing_url]) + end entry.update(remote_image_url: filestack_collage_url, filepicker_url: nil) end + def collage_from_mailgun_attachments + return unless @message_id.present? + + last_message = nil + message = nil + 5.times do + connection = Faraday.new(url: "https://api.mailgun.net") do |f| + f.request :json + f.response :json + f.request :authorization, :basic, 'api', ENV['MAILGUN_API_KEY'] + f.options.timeout = 120 + f.options.open_timeout = 120 + end + resp = connection.get("/v3/#{ENV['SMTP_DOMAIN']}/events?pretty=yes&event=accepted&ascending=no&limit=1&message-id=#{@message_id}") + last_message = resp.body&.dig("items", 0) if resp.success? + break if last_message.present? + sleep 10 + end + return unless last_message.present? + + message = nil + 5.times do + message_url = URI.parse(last_message["storage"]["url"]) + msg_conn = Faraday.new("https://#{message_url.host}") do |f| + f.options.timeout = 120 + f.options.open_timeout = 120 + f.request :json + f.response :json + f.request :authorization, :basic, 'api', ENV['MAILGUN_API_KEY'] + end + response = msg_conn.get(message_url.path) + message = response.body if response.success? + break if message.present? + sleep 10 + end + return unless message.present? && message["recipients"].to_s.include?(@user.user_key) || message["from"].to_s.include?(@user.email) + + attachment_urls = message["attachments"].map do |att| + next unless att["content-type"]&.downcase.in?(['image/gif', 'image/jpeg', 'image/jpg', 'application/octet-stream', 'image/webp', 'image/png', 'image/heic', 'image/heif']) + next unless att["size"].to_i > 20_000 + + att["url"].gsub("://", "://api:#{ENV['MAILGUN_API_KEY']}@") + end.compact + return nil unless attachment_urls.any? + + collage_from_urls(attachment_urls + [@existing_url]) + end + def collage_from_urls(urls) + return nil unless urls.present? + + urls.reject! { |url| url&.include?("googleusercontent.com/mail-sig/") } urls.compact! - "https://process.filestackapi.com/#{ENV['FILESTACK_API_KEY']}/collage=a:true,i:auto,f:[#{urls[1..-1].map(&:inspect).join(',')}],w:1200,h:1200,m:10/#{CGI.escape(urls.first)}" + + if urls.size == 1 && urls.first.starts_with?("http") + urls.first + elsif urls.any? + first_url = urls.first.include?("%40") ? urls.first : CGI.escape(urls.first) # don't escape if already escaped + "https://process.filestackapi.com/#{ENV['FILESTACK_API_KEY']}/collage=a:true,i:auto,f:[#{urls[1..-1].map(&:inspect).join(',')}],w:1200,h:1200,m:10/#{first_url}" + end end end diff --git a/app/lib/email_processor.rb b/app/lib/email_processor.rb index 79c5cec8..8f2d23b9 100644 --- a/app/lib/email_processor.rb +++ b/app/lib/email_processor.rb @@ -62,7 +62,7 @@ def process end if valid_attachments.size > 1 - best_attachment_url = collage_from_mailgun_attachments + best_attachment_url = "mailgun_collage:#{@message_id}" elsif valid_attachments.any? best_attachment = valid_attachments.first end @@ -123,13 +123,15 @@ def process if existing_entry.image_url_cdn.blank? if best_attachment.present? existing_entry.image = best_attachment + elsif best_attachment_url.present? && best_attachment_url.starts_with?("mailgun_collage:") + ImageCollageJob.perform_later(existing_entry.id, message_id: best_attachment_url.gsub("mailgun_collage:", "")) elsif best_attachment_url.present? existing_entry.remote_image_url = best_attachment_url end elsif existing_entry.image_url_cdn.present? if best_attachment.present? image_urls = collage_from_attachments([best_attachment]) - ImageCollageJob.perform_later(existing_entry.id, image_urls) + ImageCollageJob.perform_later(existing_entry.id, urls: image_urls) elsif best_attachment_url.present? existing_entry.update(filepicker_url: "https://dabble-me.s3.amazonaws.com/uploading.png") existing_image = existing_entry.image_url_cdn == "https://dabble-me.s3.amazonaws.com/uploading.png" ? nil : existing_entry.image_url_cdn @@ -155,6 +157,8 @@ def process entry = @user.entries.create!(date: date, inspiration_id: inspiration_id, body: @body, original_email_body: @raw_body) if best_attachment.present? entry.image = best_attachment + elsif best_attachment_url.present? && best_attachment_url.starts_with?("mailgun_collage:") + ImageCollageJob.perform_later(entry.id, message_id: best_attachment_url.gsub("mailgun_collage:", "")) elsif best_attachment_url.present? entry.update(filepicker_url: "https://dabble-me.s3.amazonaws.com/uploading.png") entry.remote_image_url = best_attachment_url @@ -360,45 +364,6 @@ def clean_html_version(html) to_utf8(html) end - def collage_from_mailgun_attachments - return unless @message_id.present? - - last_message = nil - connection = Faraday.new(url: "https://api.mailgun.net") do |f| - f.request :json - f.response :json - f.request :authorization, :basic, 'api', ENV['MAILGUN_API_KEY'] - f.options.timeout = 20 - f.options.open_timeout = 20 - end - resp = connection.get("/v3/#{ENV['SMTP_DOMAIN']}/events?pretty=yes&event=accepted&ascending=no&limit=1&message-id=#{@message_id}") - last_message = resp.body&.dig("items", 0) if resp.success? - return unless last_message.present? - - message = nil - message_url = URI.parse(last_message["storage"]["url"]) - msg_conn = Faraday.new("https://#{message_url.host}") do |f| - f.options.timeout = 20 - f.options.open_timeout = 20 - f.request :json - f.response :json - f.request :authorization, :basic, 'api', ENV['MAILGUN_API_KEY'] - end - response = msg_conn.get(message_url.path) - message = response.body if response.success? - return unless message.present? && message["recipients"].to_s.include?(@user.user_key) || message["from"].to_s.include?(@user.email) - - attachment_urls = message["attachments"].map do |att| - next unless att["content-type"]&.downcase.in?(['image/gif', 'image/jpeg', 'image/jpg', 'application/octet-stream', 'image/webp', 'image/png', 'image/heic', 'image/heif']) - next unless att["size"].to_i > 20_000 - - att["url"].gsub("://", "://api:#{ENV['MAILGUN_API_KEY']}@") - end.compact - return nil unless attachment_urls.any? - - collage_from_urls(attachment_urls) - end - def collage_from_attachments(attachments, existing_image_url: nil) return nil unless attachments.present?