Skip to content

Commit

Permalink
Background the mailgun attachment job
Browse files Browse the repository at this point in the history
  • Loading branch information
parterburn committed Jan 29, 2024
1 parent 14bb271 commit c154ee8
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 49 deletions.
8 changes: 4 additions & 4 deletions app/controllers/entries_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
70 changes: 66 additions & 4 deletions app/jobs/image_collage_job.rb
Original file line number Diff line number Diff line change
@@ -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
47 changes: 6 additions & 41 deletions app/lib/email_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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?

Expand Down

0 comments on commit c154ee8

Please sign in to comment.