neocities/workers/screenshot_worker.rb

105 lines
No EOL
3.3 KiB
Ruby

require 'RMagick'
require 'timeout'
require 'securerandom'
require 'thread'
require 'open3'
# Don't judge - Ruby handling of timeouts is a joke..
module Phantomjs
def self.run(*args, &block)
pid = nil
stdin, stdout, stderr, wait_thr = nil
begin
Timeout::timeout(50) do
stdin, stdout, stderr, wait_thr = Open3.popen3(path, *args)
pid = wait_thr.pid
wait_thr.join
return stdout.read
end
# :nocov:
rescue Timeout::Error
stdin.close
stdout.close
stderr.close
Process.kill 'QUIT', pid
raise Timeout::Error
end
# :nocov:
end
end
class ScreenshotWorker
SCREENSHOTS_PATH = Site::SCREENSHOTS_ROOT
include Sidekiq::Worker
sidekiq_options queue: :screenshots, retry: 3, backtrace: true
def perform(username, path)
path = "/#{path}" unless path[0] == '/'
screenshot = Tempfile.new 'neocities_screenshot'
screenshot.close
screenshot_output_path = screenshot.path+'.png'
begin
f = Screencap::Fetcher.new("http://#{username}.neocities.org#{path}")
f.fetch(
output: screenshot_output_path,
width: 1280,
height: 960
)
rescue Timeout::Error
# :nocov:
puts "#{username}/#{path} is timing out, discontinuing"
site = Site[username: username]
site.update is_crashing: true
# Don't enable until we know it works well.
=begin
if site.email
EmailWorker.perform_async({
from: 'web@neocities.org',
to: site.email,
subject: "[NeoCities] The web page \"#{path}\" on your site (#{username}.neocities.org) is slow",
body: "Hi there! This is an automated email to inform you that we're having issues loading your site to take a "+
"screenshot. It is possible that this is an error specific to our screenshot program, but it is much more "+
"likely that your site is too slow to be used with browsers. We don't want Neocities sites crashing browsers, "+
"so we're taking steps to inform you and see if you can resolve the issue. "+
"We may have to de-list your web site from being viewable in our browse page if it is not resolved shortly. "+
"We will review the site manually before taking this step, so don't worry if your site is fine and we made "+
"a mistake."+
"\n\nOur best,\n- Neocities"
})
end
=end
return
# :nocov:
end
img_list = Magick::ImageList.new
img_list.from_blob File.read(screenshot_output_path)
screenshot.unlink
File.unlink screenshot_output_path
img_list.new_image(img_list.first.columns, img_list.first.rows) { self.background_color = "white" }
img = img_list.reverse.flatten_images
user_screenshots_path = File.join SCREENSHOTS_PATH, username
screenshot_path = File.join user_screenshots_path, File.dirname(path)
FileUtils.mkdir_p screenshot_path unless Dir.exists?(screenshot_path)
Site::SCREENSHOT_RESOLUTIONS.each do |res|
width, height = res.split('x').collect {|r| r.to_i}
if width == height
new_img = img.crop_resized width, height, Magick::NorthGravity
else
new_img = img.scale width, height
end
new_img.write(File.join(user_screenshots_path, "#{path}.#{res}.jpg")) {
self.quality = 90
}
end
end
end