75 lines
3.1 KiB
Ruby
75 lines
3.1 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
class E621ThumbnailJob < ApplicationJob
|
||
|
queue_as :default
|
||
|
|
||
|
def perform(entry)
|
||
|
infile = Tempfile.new(%W[e621-thumbnail-#{entry.stripped_md5} .webm])
|
||
|
outfile = Tempfile.new(%W[e621-thumbnail-#{entry.stripped_md5} .#{entry.filetype}])
|
||
|
cutfile = Tempfile.new(%W[e621-thumbnail-#{entry.stripped_md5} .cut.webm])
|
||
|
palettefile = Tempfile.new(%W[e621-thumbnail-#{entry.stripped_md5} .palette.png])
|
||
|
Timeout.timeout(1000) do
|
||
|
infile.binmode
|
||
|
HTTParty.get("https://static1.e621.net/data/#{entry.stripped_md5[0..1]}/#{entry.stripped_md5[2..3]}/#{entry.stripped_md5}.webm", stream_body: true) do |fragment|
|
||
|
infile.write(fragment)
|
||
|
end
|
||
|
duration = `ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 #{infile.path}`.to_f
|
||
|
offset = duration > 10 ? rand(0..(duration - 10)) : duration / 2
|
||
|
if entry.filetype == "gif"
|
||
|
`ffmpeg -y -i #{infile.path} -ss #{offset} -t 3 -c:v copy -an #{cutfile.path} 1>&2`
|
||
|
`ffmpeg -y -i #{cutfile.path} -filter_complex "[0:v] palettegen" #{palettefile.path} 1>&2`
|
||
|
`ffmpeg -y -i #{cutfile.path} -i #{palettefile.path} -filter_complex "[0:v][1:v] paletteuse" #{outfile.path} 1>&2`
|
||
|
else
|
||
|
`ffmpeg -y -i #{infile.path} -ss #{offset} -vframes 1 #{outfile.path} 1>&2`
|
||
|
end
|
||
|
ImageOptim.new.optimize_image!(outfile.path)
|
||
|
StorageManager::E621Thumbnails.upload("#{entry.stripped_md5}.#{entry.filetype}", outfile.read)
|
||
|
entry.update!(status: "complete")
|
||
|
execute_webhook(entry, title: "Thumbnail Generated (#{entry.filetype})")
|
||
|
end
|
||
|
rescue Timeout::Error
|
||
|
entry.update!(status: "timeout")
|
||
|
execute_webhook(entry, title: "Thumbnail Generation Timed Out (#{entry.filetype})", error: true)
|
||
|
rescue StandardError => e
|
||
|
code = Requests::Pastebin.default.create(title: "E621 Thumbnail Generation Error (#{entry.stripped_md5})", content: "#{e}\n#{e.backtrace&.join("\n") || ''}")
|
||
|
entry.update!(status: "error", error_code: code)
|
||
|
execute_webhook(entry, title: "Thumbnail Generation Errored (#{entry.filetype})", body: "Backtrace: https://passtebin.com/#{code}", error: true)
|
||
|
raise(e)
|
||
|
ensure
|
||
|
[infile, outfile, palettefile, cutfile].each do |file|
|
||
|
file&.close
|
||
|
file&.unlink
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def execute_webhook(entry, title:, body: "", error: false)
|
||
|
if error
|
||
|
entry.update(expires_at: 5.minutes.from_now)
|
||
|
E621ThumbnailErrorCleanupJob.set(wait: 5.minutes).perform_later(entry)
|
||
|
end
|
||
|
thumb = {}
|
||
|
if entry.complete?
|
||
|
thumb = {
|
||
|
thumbnail: {
|
||
|
url: entry.url,
|
||
|
},
|
||
|
}
|
||
|
end
|
||
|
Websites.config.e621_thumbnails_webhook.execute({
|
||
|
embeds: [
|
||
|
{
|
||
|
title: title,
|
||
|
description: <<~DESC,
|
||
|
Key: ##{entry.api_key_id} (`#{entry.api_key.application_name}`)
|
||
|
Post: [##{entry.post_id}](https://e621.net/posts/#{entry.post_id})
|
||
|
#{body}
|
||
|
DESC
|
||
|
color: error ? 0xDC143C : 0x008000,
|
||
|
timestamp: Time.now.iso8601,
|
||
|
**thumb,
|
||
|
},
|
||
|
],
|
||
|
})
|
||
|
end
|
||
|
end
|