uploads: move thumbnail generation code to MediaFile.
* Move image thumbnail generation code to MediaFile::Image. * Move video thumbnail generation code to MediaFile::Video. * Move ugoira->webm conversion code to MediaFile::Ugoira. This separates thumbnail generation from the upload process so that it's possible to generate thumbnails outside of uploads.
This commit is contained in:
@@ -1,36 +0,0 @@
|
|||||||
module DanbooruImageResizer
|
|
||||||
module_function
|
|
||||||
|
|
||||||
# Taken from ArgyllCMS 2.0.0 (see also: https://ninedegreesbelow.com/photography/srgb-profile-comparison.html)
|
|
||||||
SRGB_PROFILE = "#{Rails.root}/config/sRGB.icm"
|
|
||||||
|
|
||||||
# http://jcupitt.github.io/libvips/API/current/libvips-resample.html#vips-thumbnail
|
|
||||||
if Vips.at_least_libvips?(8, 8)
|
|
||||||
THUMBNAIL_OPTIONS = { size: :down, linear: false, no_rotate: true, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE }
|
|
||||||
CROP_OPTIONS = { linear: false, no_rotate: true, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE, crop: :attention }
|
|
||||||
else
|
|
||||||
THUMBNAIL_OPTIONS = { size: :down, linear: false, auto_rotate: false, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE }
|
|
||||||
CROP_OPTIONS = { linear: false, auto_rotate: false, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE, crop: :attention }
|
|
||||||
end
|
|
||||||
|
|
||||||
# http://jcupitt.github.io/libvips/API/current/VipsForeignSave.html#vips-jpegsave
|
|
||||||
JPEG_OPTIONS = { background: 255, strip: true, interlace: true, optimize_coding: true }
|
|
||||||
|
|
||||||
# https://github.com/jcupitt/libvips/wiki/HOWTO----Image-shrinking
|
|
||||||
# http://jcupitt.github.io/libvips/API/current/Using-vipsthumbnail.md.html
|
|
||||||
def resize(file, width, height, resize_quality = 90)
|
|
||||||
output_file = Tempfile.new
|
|
||||||
resized_image = Vips::Image.thumbnail(file.path, width, height: height, **THUMBNAIL_OPTIONS)
|
|
||||||
resized_image.jpegsave(output_file.path, Q: resize_quality, **JPEG_OPTIONS)
|
|
||||||
|
|
||||||
output_file
|
|
||||||
end
|
|
||||||
|
|
||||||
def crop(file, width, height, resize_quality = 90)
|
|
||||||
output_file = Tempfile.new
|
|
||||||
resized_image = Vips::Image.thumbnail(file.path, width, height: height, **CROP_OPTIONS)
|
|
||||||
resized_image.jpegsave(output_file.path, Q: resize_quality, **JPEG_OPTIONS)
|
|
||||||
|
|
||||||
output_file
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -5,20 +5,20 @@ class MediaFile
|
|||||||
# delegate all File methods to `file`.
|
# delegate all File methods to `file`.
|
||||||
delegate *(File.instance_methods - MediaFile.instance_methods), to: :file
|
delegate *(File.instance_methods - MediaFile.instance_methods), to: :file
|
||||||
|
|
||||||
def self.open(file)
|
def self.open(file, **options)
|
||||||
file = Kernel.open(file, "r", binmode: true) unless file.respond_to?(:read)
|
file = Kernel.open(file, "r", binmode: true) unless file.respond_to?(:read)
|
||||||
|
|
||||||
case file_ext(file)
|
case file_ext(file)
|
||||||
when :jpg, :gif, :png
|
when :jpg, :gif, :png
|
||||||
MediaFile::Image.new(file)
|
MediaFile::Image.new(file, **options)
|
||||||
when :swf
|
when :swf
|
||||||
MediaFile::Flash.new(file)
|
MediaFile::Flash.new(file, **options)
|
||||||
when :webm, :mp4
|
when :webm, :mp4
|
||||||
MediaFile::Video.new(file)
|
MediaFile::Video.new(file, **options)
|
||||||
when :zip
|
when :zip
|
||||||
MediaFile::Ugoira.new(file)
|
MediaFile::Ugoira.new(file, **options)
|
||||||
else
|
else
|
||||||
MediaFile.new(file)
|
MediaFile.new(file, **options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class MediaFile
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(file)
|
def initialize(file, **options)
|
||||||
@file = file
|
@file = file
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -73,5 +73,29 @@ class MediaFile
|
|||||||
file.size
|
file.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_image?
|
||||||
|
file_ext.in?([:jpg, :png, :gif])
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_video?
|
||||||
|
file_ext.in?([:webm, :mp4])
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_ugoira?
|
||||||
|
file_ext == :zip
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_flash?
|
||||||
|
file_ext == :swf
|
||||||
|
end
|
||||||
|
|
||||||
|
def preview(width, height, **options)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def crop(width, height, **options)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
memoize :dimensions, :file_ext, :file_size, :md5
|
memoize :dimensions, :file_ext, :file_size, :md5
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Adapted from https://github.com/dim/ruby-imagespec/blob/f2f3ce8bb5b1b411f8658e66a891a095261d94c0/lib/image_spec/parser/swf.rb
|
# Adapted from https://github.com/dim/ruby-imagespec/blob/f2f3ce8bb5b1b411f8658e66a891a095261d94c0/lib/image_spec/parser/swf.rb
|
||||||
# License: https://github.com/dim/ruby-imagespec/blob/master/LICENSE
|
# License: https://github.com/dim/ruby-imagespec/blob/master/LICENSE
|
||||||
|
|
||||||
class MediaFile::Flash < MediaFile::Image
|
class MediaFile::Flash < MediaFile
|
||||||
def dimensions
|
def dimensions
|
||||||
# Read the entire stream into memory because the
|
# Read the entire stream into memory because the
|
||||||
# dimensions aren't stored in a standard location
|
# dimensions aren't stored in a standard location
|
||||||
|
|||||||
@@ -1,9 +1,46 @@
|
|||||||
class MediaFile::Image < MediaFile
|
class MediaFile::Image < MediaFile
|
||||||
def dimensions
|
# Taken from ArgyllCMS 2.0.0 (see also: https://ninedegreesbelow.com/photography/srgb-profile-comparison.html)
|
||||||
image.size
|
SRGB_PROFILE = "#{Rails.root}/config/sRGB.icm"
|
||||||
|
|
||||||
|
# http://jcupitt.github.io/libvips/API/current/VipsForeignSave.html#vips-jpegsave
|
||||||
|
JPEG_OPTIONS = { Q: 90, background: 255, strip: true, interlace: true, optimize_coding: true }
|
||||||
|
|
||||||
|
# http://jcupitt.github.io/libvips/API/current/libvips-resample.html#vips-thumbnail
|
||||||
|
if Vips.at_least_libvips?(8, 8)
|
||||||
|
THUMBNAIL_OPTIONS = { size: :down, linear: false, no_rotate: true, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE }
|
||||||
|
CROP_OPTIONS = { crop: :attention, linear: false, no_rotate: true, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE }
|
||||||
|
else
|
||||||
|
THUMBNAIL_OPTIONS = { size: :down, linear: false, auto_rotate: false, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE }
|
||||||
|
CROP_OPTIONS = { crop: :attention, linear: false, auto_rotate: false, export_profile: SRGB_PROFILE, import_profile: SRGB_PROFILE }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dimensions
|
||||||
|
image.size
|
||||||
|
rescue Vips::Error
|
||||||
|
[0, 0]
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://github.com/jcupitt/libvips/wiki/HOWTO----Image-shrinking
|
||||||
|
# http://jcupitt.github.io/libvips/API/current/Using-vipsthumbnail.md.html
|
||||||
|
def preview(width, height)
|
||||||
|
output_file = Tempfile.new(["image-preview", ".jpg"])
|
||||||
|
resized_image = image.thumbnail_image(width, height: height, **THUMBNAIL_OPTIONS)
|
||||||
|
resized_image.jpegsave(output_file.path, **JPEG_OPTIONS)
|
||||||
|
|
||||||
|
MediaFile::Image.new(output_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
def crop(width, height)
|
||||||
|
output_file = Tempfile.new(["image-crop", ".jpg"])
|
||||||
|
resized_image = image.thumbnail_image(width, height: height, **CROP_OPTIONS)
|
||||||
|
resized_image.jpegsave(output_file.path, **JPEG_OPTIONS)
|
||||||
|
|
||||||
|
MediaFile::Image.new(output_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def image
|
def image
|
||||||
@image ||= Vips::Image.new_from_file(file.path)
|
@image ||= Vips::Image.new_from_file(file.path, fail: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,13 +1,93 @@
|
|||||||
class MediaFile::Ugoira < MediaFile
|
class MediaFile::Ugoira < MediaFile
|
||||||
def dimensions
|
extend Memoist
|
||||||
tempfile = Tempfile.new
|
class Error < StandardError; end
|
||||||
folder = Zip::File.new(file.path)
|
attr_reader :frame_data
|
||||||
folder.first.extract(tempfile.path) { true }
|
|
||||||
|
|
||||||
image_file = MediaFile.open(tempfile)
|
def self.conversion_enabled?
|
||||||
image_file.dimensions
|
system("ffmpeg -version > /dev/null") && system("mkvmerge --version > /dev/null")
|
||||||
ensure
|
|
||||||
image_file.close
|
|
||||||
tempfile.close!
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def initialize(file, frame_data: {}, **options)
|
||||||
|
super(file, **options)
|
||||||
|
@frame_data = frame_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
file.close
|
||||||
|
zipfile.close
|
||||||
|
preview_frame.close
|
||||||
|
end
|
||||||
|
|
||||||
|
def dimensions
|
||||||
|
preview_frame.dimensions
|
||||||
|
end
|
||||||
|
|
||||||
|
def preview(width, height)
|
||||||
|
preview_frame.preview(width, height)
|
||||||
|
end
|
||||||
|
|
||||||
|
def crop(width, height)
|
||||||
|
preview_frame.crop(width, height)
|
||||||
|
end
|
||||||
|
|
||||||
|
# XXX should take width and height and resize image
|
||||||
|
def convert
|
||||||
|
raise NotImplementedError, "can't convert ugoira to webm: ffmpeg or mkvmerge not installed" unless self.class.conversion_enabled?
|
||||||
|
|
||||||
|
Dir.mktmpdir("ugoira-#{md5}") do |tmpdir|
|
||||||
|
output_file = Tempfile.new(["ugoira-conversion", ".webm"], binmode: true)
|
||||||
|
|
||||||
|
FileUtils.mkdir_p("#{tmpdir}/images")
|
||||||
|
|
||||||
|
zipfile.each do |entry|
|
||||||
|
path = File.join(tmpdir, "images", entry.name)
|
||||||
|
entry.extract(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Duplicate last frame to avoid it being displayed only for a very short amount of time.
|
||||||
|
last_file_name = zipfile.entries.last.name
|
||||||
|
last_file_name =~ /\A(\d{6})(\.\w{,4})\Z/
|
||||||
|
new_last_index = $1.to_i + 1
|
||||||
|
file_ext = $2
|
||||||
|
new_last_filename = ("%06d" % new_last_index) + file_ext
|
||||||
|
path_from = File.join(tmpdir, "images", last_file_name)
|
||||||
|
path_to = File.join(tmpdir, "images", new_last_filename)
|
||||||
|
FileUtils.cp(path_from, path_to)
|
||||||
|
|
||||||
|
delay_sum = 0
|
||||||
|
timecodes_path = File.join(tmpdir, "timecodes.tc")
|
||||||
|
File.open(timecodes_path, "w+") do |f|
|
||||||
|
f.write("# timecode format v2\n")
|
||||||
|
frame_data.each do |img|
|
||||||
|
f.write("#{delay_sum}\n")
|
||||||
|
delay_sum += (img["delay"] || img["delay_msec"])
|
||||||
|
end
|
||||||
|
f.write("#{delay_sum}\n")
|
||||||
|
f.write("#{delay_sum}\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
ext = zipfile.first.name.match(/\.(\w{,4})$/)[1]
|
||||||
|
ffmpeg_out, status = Open3.capture2e("ffmpeg -i #{tmpdir}/images/%06d.#{ext} -codec:v libvpx -crf 4 -b:v 5000k -an #{tmpdir}/tmp.webm")
|
||||||
|
raise Error, "ffmpeg failed: #{ffmpeg_out}" unless status.success?
|
||||||
|
|
||||||
|
mkvmerge_out, status = Open3.capture2e("mkvmerge -o #{output_file.path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
|
||||||
|
raise Error, "mkvmerge failed: #{mkvmerge_out}" unless status.success?
|
||||||
|
|
||||||
|
MediaFile.open(output_file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def zipfile
|
||||||
|
Zip::File.new(file.path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def preview_frame
|
||||||
|
tempfile = Tempfile.new("ugoira-preview", binmode: true)
|
||||||
|
zipfile.entries.first.extract(tempfile.path) { true } # 'true' means overwrite the existing tempfile.
|
||||||
|
MediaFile.open(tempfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
memoize :zipfile, :preview_frame
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +1,29 @@
|
|||||||
class MediaFile::Video < MediaFile
|
class MediaFile::Video < MediaFile
|
||||||
|
extend Memoist
|
||||||
|
|
||||||
def dimensions
|
def dimensions
|
||||||
[video.width, video.height]
|
[video.width, video.height]
|
||||||
end
|
end
|
||||||
|
|
||||||
def video
|
def preview(max_width, max_height)
|
||||||
@video ||= FFMPEG::Movie.new(file.path)
|
preview_frame.preview(max_width, max_height)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def crop(max_width, max_height)
|
||||||
|
preview_frame.crop(max_width, max_height)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def video
|
||||||
|
FFMPEG::Movie.new(file.path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def preview_frame
|
||||||
|
vp = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
||||||
|
video.screenshot(vp.path, seek_time: 0)
|
||||||
|
MediaFile.open(vp.path)
|
||||||
|
end
|
||||||
|
|
||||||
|
memoize :video, :preview_frame
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
class PixivUgoiraConverter
|
|
||||||
def self.enabled?
|
|
||||||
system("ffmpeg -version > /dev/null") && system("mkvmerge --version > /dev/null")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.generate_webm(ugoira_file, frame_data)
|
|
||||||
raise NotImplementedError, "can't convert ugoira to webm: ffmpeg or mkvmerge not installed" unless enabled?
|
|
||||||
|
|
||||||
folder = Zip::File.new(ugoira_file.path)
|
|
||||||
output_file = Tempfile.new(binmode: true)
|
|
||||||
write_path = output_file.path
|
|
||||||
|
|
||||||
Dir.mktmpdir do |tmpdir|
|
|
||||||
FileUtils.mkdir_p("#{tmpdir}/images")
|
|
||||||
folder.each_with_index do |file, i|
|
|
||||||
path = File.join(tmpdir, "images", file.name)
|
|
||||||
file.extract(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Duplicate last frame to avoid it being displayed only for a very short amount of time.
|
|
||||||
last_file_name = folder.to_a.last.name
|
|
||||||
last_file_name =~ /\A(\d{6})(\.\w{,4})\Z/
|
|
||||||
new_last_index = $1.to_i + 1
|
|
||||||
file_ext = $2
|
|
||||||
new_last_filename = ("%06d" % new_last_index) + file_ext
|
|
||||||
path_from = File.join(tmpdir, "images", last_file_name)
|
|
||||||
path_to = File.join(tmpdir, "images", new_last_filename)
|
|
||||||
FileUtils.cp(path_from, path_to)
|
|
||||||
|
|
||||||
delay_sum = 0
|
|
||||||
timecodes_path = File.join(tmpdir, "timecodes.tc")
|
|
||||||
File.open(timecodes_path, "w+") do |f|
|
|
||||||
f.write("# timecode format v2\n")
|
|
||||||
frame_data.each do |img|
|
|
||||||
f.write("#{delay_sum}\n")
|
|
||||||
delay_sum += (img["delay"] || img["delay_msec"])
|
|
||||||
end
|
|
||||||
f.write("#{delay_sum}\n")
|
|
||||||
f.write("#{delay_sum}\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
ext = folder.first.name.match(/\.(\w{,4})$/)[1]
|
|
||||||
ffmpeg_out, status = Open3.capture2e("ffmpeg -i #{tmpdir}/images/%06d.#{ext} -codec:v libvpx -crf 4 -b:v 5000k -an #{tmpdir}/tmp.webm")
|
|
||||||
|
|
||||||
if !status.success?
|
|
||||||
Rails.logger.error "[write_webm] ******************************"
|
|
||||||
Rails.logger.error "[write_webm] failed write_path=#{write_path}"
|
|
||||||
Rails.logger.error "[write_webm] ffmepg output:"
|
|
||||||
ffmpeg_out.split(/\n/).each do |line|
|
|
||||||
Rails.logger.error "[write_webm][ffmpeg] #{line}"
|
|
||||||
end
|
|
||||||
Rails.logger.error "[write_webm] ******************************"
|
|
||||||
end
|
|
||||||
|
|
||||||
mkvmerge_out, status = Open3.capture2e("mkvmerge -o #{write_path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
|
|
||||||
|
|
||||||
if !status.success?
|
|
||||||
Rails.logger.error "[write_webm] ******************************"
|
|
||||||
Rails.logger.error "[write_webm] failed write_path=#{write_path}"
|
|
||||||
Rails.logger.error "[write_webm] mkvmerge output:"
|
|
||||||
mkvmerge_out.split(/\n/).each do |line|
|
|
||||||
Rails.logger.error "[write_webm][mkvmerge] #{line}"
|
|
||||||
end
|
|
||||||
Rails.logger.error "[write_webm] ******************************"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
output_file
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.generate_crop(ugoira_file)
|
|
||||||
file = Tempfile.new(["ugoira-crop", ".zip"], binmode: true)
|
|
||||||
zipfile = Zip::File.new(ugoira_file.path)
|
|
||||||
zipfile.entries.first.extract(file.path) { true } # 'true' means overwrite the existing tempfile.
|
|
||||||
|
|
||||||
DanbooruImageResizer.crop(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
|
|
||||||
ensure
|
|
||||||
file&.close!
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.generate_preview(ugoira_file)
|
|
||||||
file = Tempfile.new(["ugoira-preview", ".zip"], binmode: true)
|
|
||||||
zipfile = Zip::File.new(ugoira_file.path)
|
|
||||||
zipfile.entries.first.extract(file.path) { true } # 'true' means overwrite the existing tempfile.
|
|
||||||
|
|
||||||
DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
|
|
||||||
ensure
|
|
||||||
file.close!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -25,53 +25,25 @@ class UploadService
|
|||||||
source =~ /^https?:\/\//
|
source =~ /^https?:\/\//
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_resizes(file, upload)
|
def generate_resizes(media_file)
|
||||||
if upload.is_video?
|
preview_file = media_file.preview(Danbooru.config.small_image_width, Danbooru.config.small_image_width)
|
||||||
video = FFMPEG::Movie.new(file.path)
|
crop_file = media_file.crop(Danbooru.config.small_image_width, Danbooru.config.small_image_width)
|
||||||
crop_file = generate_video_crop_for(video, Danbooru.config.small_image_width)
|
|
||||||
preview_file = generate_video_preview_for(video, Danbooru.config.small_image_width, Danbooru.config.small_image_width)
|
|
||||||
|
|
||||||
elsif upload.is_ugoira?
|
if media_file.is_ugoira?
|
||||||
preview_file = PixivUgoiraConverter.generate_preview(file)
|
sample_file = media_file.convert
|
||||||
crop_file = PixivUgoiraConverter.generate_crop(file)
|
elsif media_file.is_image? && media_file.width > Danbooru.config.large_image_width
|
||||||
sample_file = PixivUgoiraConverter.generate_webm(file, upload.context["ugoira"]["frame_data"])
|
sample_file = media_file.preview(Danbooru.config.large_image_width, nil)
|
||||||
|
else
|
||||||
elsif upload.is_image?
|
sample_file = nil
|
||||||
preview_file = DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
|
|
||||||
crop_file = DanbooruImageResizer.crop(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
|
|
||||||
if upload.image_width > Danbooru.config.large_image_width
|
|
||||||
sample_file = DanbooruImageResizer.resize(file, Danbooru.config.large_image_width, upload.image_height, 90)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
[preview_file, crop_file, sample_file]
|
[preview_file, crop_file, sample_file]
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_video_crop_for(video, width)
|
|
||||||
vp = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
|
||||||
video.screenshot(vp.path, :seek_time => 0, :resolution => "#{video.width}x#{video.height}")
|
|
||||||
crop = DanbooruImageResizer.crop(vp, width, width, 85)
|
|
||||||
vp.close
|
|
||||||
return crop
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_video_preview_for(video, width, height)
|
|
||||||
dimension_ratio = video.width.to_f / video.height
|
|
||||||
if dimension_ratio > 1
|
|
||||||
height = (width / dimension_ratio).to_i
|
|
||||||
else
|
|
||||||
width = (height * dimension_ratio).to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
output_file = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
|
||||||
video.screenshot(output_file.path, :seek_time => 0, :resolution => "#{width}x#{height}")
|
|
||||||
output_file
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_file(upload, file, original_post_id: nil)
|
def process_file(upload, file, original_post_id: nil)
|
||||||
media_file = MediaFile.open(file)
|
|
||||||
|
|
||||||
upload.file = file
|
upload.file = file
|
||||||
|
media_file = upload.media_file
|
||||||
|
|
||||||
upload.file_ext = media_file.file_ext.to_s
|
upload.file_ext = media_file.file_ext.to_s
|
||||||
upload.file_size = media_file.file_size
|
upload.file_size = media_file.file_size
|
||||||
upload.md5 = media_file.md5
|
upload.md5 = media_file.md5
|
||||||
@@ -81,7 +53,7 @@ class UploadService
|
|||||||
upload.validate!(:file)
|
upload.validate!(:file)
|
||||||
upload.tag_string = "#{upload.tag_string} #{Utils.automatic_tags(upload, file)}"
|
upload.tag_string = "#{upload.tag_string} #{Utils.automatic_tags(upload, file)}"
|
||||||
|
|
||||||
preview_file, crop_file, sample_file = Utils.generate_resizes(file, upload)
|
preview_file, crop_file, sample_file = Utils.generate_resizes(media_file)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Utils.distribute_files(file, upload, :original, original_post_id: original_post_id)
|
Utils.distribute_files(file, upload, :original, original_post_id: original_post_id)
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ class Upload < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
module FileMethods
|
module FileMethods
|
||||||
|
def media_file
|
||||||
|
@media_file ||= MediaFile.open(file, frame_data: context.to_h.dig("ugoira", "frame_data"))
|
||||||
|
end
|
||||||
|
|
||||||
def is_image?
|
def is_image?
|
||||||
%w(jpg gif png).include?(file_ext)
|
%w(jpg gif png).include?(file_ext)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ FactoryBot.define do
|
|||||||
factory(:ugoira_upload) do
|
factory(:ugoira_upload) do
|
||||||
file do
|
file do
|
||||||
f = Tempfile.new
|
f = Tempfile.new
|
||||||
IO.copy_stream("#{Rails.root}/test/fixtures/ugoira.zip", f.path)
|
IO.copy_stream("#{Rails.root}/test/files/ugoira.zip", f.path)
|
||||||
ActionDispatch::Http::UploadedFile.new(tempfile: f, filename: "ugoira.zip")
|
ActionDispatch::Http::UploadedFile.new(tempfile: f, filename: "ugoira.zip")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
7
test/files/ugoira.json
Normal file
7
test/files/ugoira.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{"file": "000000.jpg", "delay": 200},
|
||||||
|
{"file": "000001.jpg", "delay": 200},
|
||||||
|
{"file": "000002.jpg", "delay": 200},
|
||||||
|
{"file": "000003.jpg", "delay": 200},
|
||||||
|
{"file": "000004.jpg", "delay": 250}
|
||||||
|
]
|
||||||
@@ -82,4 +82,47 @@ class MediaFileTest < ActiveSupport::TestCase
|
|||||||
should "determine the correct filesize for a jpeg file" do
|
should "determine the correct filesize for a jpeg file" do
|
||||||
assert_equal(28086, MediaFile.open("test/files/test.jpg").file_size)
|
assert_equal(28086, MediaFile.open("test/files/test.jpg").file_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "#preview" do
|
||||||
|
should "generate a preview image" do
|
||||||
|
assert_equal([150, 101], MediaFile.open("test/files/test.jpg").preview(150, 150).dimensions)
|
||||||
|
assert_equal([113, 150], MediaFile.open("test/files/test.png").preview(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test.gif").preview(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test-512x512.webm").preview(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test-300x300.mp4").preview(150, 150).dimensions)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "be able to fit to width only" do
|
||||||
|
assert_equal([400, 268], MediaFile.open("test/files/test.jpg").preview(400, nil).dimensions)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "#crop" do
|
||||||
|
should "generate a cropped preview image" do
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test.jpg").crop(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test.png").crop(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test.gif").crop(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test-512x512.webm").crop(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], MediaFile.open("test/files/test-300x300.mp4").crop(150, 150).dimensions)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for a ugoira" do
|
||||||
|
setup do
|
||||||
|
skip unless MediaFile::Ugoira.conversion_enabled?
|
||||||
|
frame_data = JSON.parse(File.read("test/files/ugoira.json"))
|
||||||
|
@ugoira = MediaFile.open("test/files/ugoira.zip", frame_data: frame_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "generate a preview" do
|
||||||
|
assert_equal([60, 60], @ugoira.preview(150, 150).dimensions)
|
||||||
|
assert_equal([150, 150], @ugoira.crop(150, 150).dimensions)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "convert to a webm" do
|
||||||
|
webm = @ugoira.convert
|
||||||
|
assert_equal(:webm, webm.file_ext)
|
||||||
|
assert_equal([60, 60], webm.dimensions)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
require "test_helper"
|
|
||||||
|
|
||||||
class PixivUgoiraConverterTest < ActiveSupport::TestCase
|
|
||||||
context "An ugoira converter" do
|
|
||||||
setup do
|
|
||||||
@zipfile = upload_file("test/fixtures/ugoira.zip").tempfile
|
|
||||||
@frame_data = [
|
|
||||||
{"file" => "000000.jpg", "delay" => 200},
|
|
||||||
{"file" => "000001.jpg", "delay" => 200},
|
|
||||||
{"file" => "000002.jpg", "delay" => 200},
|
|
||||||
{"file" => "000003.jpg", "delay" => 200},
|
|
||||||
{"file" => "000004.jpg", "delay" => 250}
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
should "output to webm" do
|
|
||||||
skip "ffmpeg is not installed" unless PixivUgoiraConverter.enabled?
|
|
||||||
sample_file = PixivUgoiraConverter.generate_webm(@zipfile, @frame_data)
|
|
||||||
preview_file = PixivUgoiraConverter.generate_preview(@zipfile)
|
|
||||||
assert_operator(sample_file.size, :>, 1_000)
|
|
||||||
assert_operator(preview_file.size, :>, 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -15,8 +15,6 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
context "::Utils" do
|
context "::Utils" do
|
||||||
subject { UploadService::Utils }
|
|
||||||
|
|
||||||
context "#get_file_for_upload" do
|
context "#get_file_for_upload" do
|
||||||
context "for a non-source site" do
|
context "for a non-source site" do
|
||||||
setup do
|
setup do
|
||||||
@@ -26,10 +24,8 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "work on a jpeg" do
|
should "work on a jpeg" do
|
||||||
file = subject.get_file_for_upload(@upload)
|
file = UploadService::Utils.get_file_for_upload(@upload)
|
||||||
|
|
||||||
assert_operator(File.size(file.path), :>, 0)
|
assert_operator(File.size(file.path), :>, 0)
|
||||||
|
|
||||||
file.close
|
file.close
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -43,13 +39,9 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
should "work on an ugoira url" do
|
should "work on an ugoira url" do
|
||||||
begin
|
begin
|
||||||
file = subject.get_file_for_upload(@upload)
|
file = UploadService::Utils.get_file_for_upload(@upload)
|
||||||
|
|
||||||
assert_operator(File.size(file.path), :>, 0)
|
assert_operator(File.size(file.path), :>, 0)
|
||||||
|
|
||||||
file.close
|
file.close
|
||||||
rescue Net::OpenTimeout
|
|
||||||
skip "network problems"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -64,15 +56,12 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "work on an ugoira url" do
|
should "work on an ugoira url" do
|
||||||
skip unless PixivUgoiraConverter.enabled?
|
file = UploadService::Utils.get_file_for_upload(@upload)
|
||||||
file = subject.get_file_for_upload(@upload)
|
|
||||||
|
|
||||||
assert_not_nil(@upload.context["ugoira"])
|
assert_not_nil(@upload.context["ugoira"])
|
||||||
assert_operator(File.size(file.path), :>, 0)
|
assert_operator(File.size(file.path), :>, 0)
|
||||||
|
|
||||||
file.close
|
file.close
|
||||||
rescue Net::OpenTimeout
|
|
||||||
skip "network failure"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -84,14 +73,14 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "with an original_post_id" do
|
context "with an original_post_id" do
|
||||||
should "run" do
|
should "run" do
|
||||||
subject.expects(:distribute_files).times(3)
|
UploadService::Utils.expects(:distribute_files).times(3)
|
||||||
subject.process_file(@upload, @upload.file.tempfile, original_post_id: 12345)
|
UploadService::Utils.process_file(@upload, @upload.file.tempfile, original_post_id: 12345)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
should "run" do
|
should "run" do
|
||||||
subject.expects(:distribute_files).times(3)
|
UploadService::Utils.expects(:distribute_files).times(3)
|
||||||
subject.process_file(@upload, @upload.file.tempfile)
|
UploadService::Utils.process_file(@upload, @upload.file.tempfile)
|
||||||
assert_equal("jpg", @upload.file_ext)
|
assert_equal("jpg", @upload.file_ext)
|
||||||
assert_equal(28086, @upload.file_size)
|
assert_equal(28086, @upload.file_size)
|
||||||
assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @upload.md5)
|
assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @upload.md5)
|
||||||
@@ -99,184 +88,6 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
assert_equal(500, @upload.image_width)
|
assert_equal(500, @upload.image_width)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context ".generate_resizes" do
|
|
||||||
context "for an ugoira" do
|
|
||||||
setup do
|
|
||||||
context = UGOIRA_CONTEXT
|
|
||||||
@file = upload_file("test/fixtures/ugoira.zip")
|
|
||||||
@upload = mock
|
|
||||||
@upload.stubs(:is_video?).returns(false)
|
|
||||||
@upload.stubs(:is_ugoira?).returns(true)
|
|
||||||
@upload.stubs(:context).returns(context)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a preview and a video" do
|
|
||||||
skip unless PixivUgoiraConverter.enabled?
|
|
||||||
|
|
||||||
preview, crop, sample = subject.generate_resizes(@file, @upload)
|
|
||||||
assert_operator(File.size(preview.path), :>, 0)
|
|
||||||
assert_operator(File.size(crop.path), :>, 0)
|
|
||||||
assert_operator(File.size(sample.path), :>, 0)
|
|
||||||
assert_equal(60, MediaFile.open(preview).width)
|
|
||||||
assert_equal(60, MediaFile.open(preview).height)
|
|
||||||
assert_equal(150, MediaFile.open(crop).width)
|
|
||||||
assert_equal(150, MediaFile.open(crop).height)
|
|
||||||
preview.close
|
|
||||||
preview.unlink
|
|
||||||
sample.close
|
|
||||||
sample.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for a video" do
|
|
||||||
teardown do
|
|
||||||
@file.close
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for an mp4" do
|
|
||||||
setup do
|
|
||||||
@file = upload_file("test/files/test-300x300.mp4")
|
|
||||||
@upload = mock
|
|
||||||
@upload.stubs(:is_video?).returns(true)
|
|
||||||
@upload.stubs(:is_ugoira?).returns(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a video" do
|
|
||||||
preview, crop, sample = subject.generate_resizes(@file, @upload)
|
|
||||||
assert_operator(File.size(preview.path), :>, 0)
|
|
||||||
assert_operator(File.size(crop.path), :>, 0)
|
|
||||||
assert_equal(150, MediaFile.open(preview).width)
|
|
||||||
assert_equal(150, MediaFile.open(preview).height)
|
|
||||||
assert_equal(150, MediaFile.open(crop).width)
|
|
||||||
assert_equal(150, MediaFile.open(crop).height)
|
|
||||||
preview.close
|
|
||||||
preview.unlink
|
|
||||||
crop.close
|
|
||||||
crop.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for a webm" do
|
|
||||||
setup do
|
|
||||||
@file = upload_file("test/files/test-512x512.webm")
|
|
||||||
@upload = mock
|
|
||||||
@upload.stubs(:is_video?).returns(true)
|
|
||||||
@upload.stubs(:is_ugoira?).returns(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a video" do
|
|
||||||
preview, crop, sample = subject.generate_resizes(@file, @upload)
|
|
||||||
assert_operator(File.size(preview.path), :>, 0)
|
|
||||||
assert_operator(File.size(crop.path), :>, 0)
|
|
||||||
assert_equal(150, MediaFile.open(preview).width)
|
|
||||||
assert_equal(150, MediaFile.open(preview).height)
|
|
||||||
assert_equal(150, MediaFile.open(crop).width)
|
|
||||||
assert_equal(150, MediaFile.open(crop).height)
|
|
||||||
preview.close
|
|
||||||
preview.unlink
|
|
||||||
crop.close
|
|
||||||
crop.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for an image" do
|
|
||||||
teardown do
|
|
||||||
@file.close
|
|
||||||
end
|
|
||||||
|
|
||||||
setup do
|
|
||||||
@upload = mock
|
|
||||||
@upload.stubs(:is_video?).returns(false)
|
|
||||||
@upload.stubs(:is_ugoira?).returns(false)
|
|
||||||
@upload.stubs(:is_image?).returns(true)
|
|
||||||
@upload.stubs(:image_width).returns(1200)
|
|
||||||
@upload.stubs(:image_height).returns(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for a jpeg" do
|
|
||||||
setup do
|
|
||||||
@file = upload_file("test/files/test.jpg")
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a preview" do
|
|
||||||
preview, crop, sample = subject.generate_resizes(@file, @upload)
|
|
||||||
assert_operator(File.size(preview.path), :>, 0)
|
|
||||||
assert_operator(File.size(crop.path), :>, 0)
|
|
||||||
assert_operator(File.size(sample.path), :>, 0)
|
|
||||||
preview.close
|
|
||||||
preview.unlink
|
|
||||||
sample.close
|
|
||||||
sample.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for a png" do
|
|
||||||
setup do
|
|
||||||
@file = upload_file("test/files/test.png")
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a preview" do
|
|
||||||
preview, crop, sample = subject.generate_resizes(@file, @upload)
|
|
||||||
assert_operator(File.size(preview.path), :>, 0)
|
|
||||||
assert_operator(File.size(crop.path), :>, 0)
|
|
||||||
assert_operator(File.size(sample.path), :>, 0)
|
|
||||||
preview.close
|
|
||||||
preview.unlink
|
|
||||||
sample.close
|
|
||||||
sample.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for a gif" do
|
|
||||||
setup do
|
|
||||||
@file = upload_file("test/files/test.png")
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a preview" do
|
|
||||||
preview, crop, sample = subject.generate_resizes(@file, @upload)
|
|
||||||
assert_operator(File.size(preview.path), :>, 0)
|
|
||||||
assert_operator(File.size(crop.path), :>, 0)
|
|
||||||
assert_operator(File.size(sample.path), :>, 0)
|
|
||||||
preview.close
|
|
||||||
preview.unlink
|
|
||||||
sample.close
|
|
||||||
sample.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context ".generate_video_preview_for" do
|
|
||||||
context "for an mp4" do
|
|
||||||
setup do
|
|
||||||
@path = "test/files/test-300x300.mp4"
|
|
||||||
@video = FFMPEG::Movie.new(@path)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a video" do
|
|
||||||
sample = subject.generate_video_preview_for(@video, 100, 100)
|
|
||||||
assert_operator(File.size(sample.path), :>, 0)
|
|
||||||
sample.close
|
|
||||||
sample.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "for a webm" do
|
|
||||||
setup do
|
|
||||||
@path = "test/files/test-512x512.webm"
|
|
||||||
@video = FFMPEG::Movie.new(@path)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "generate a video" do
|
|
||||||
sample = subject.generate_video_preview_for(@video, 100, 100)
|
|
||||||
assert_operator(File.size(sample.path), :>, 0)
|
|
||||||
sample.close
|
|
||||||
sample.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context "::Preprocessor" do
|
context "::Preprocessor" do
|
||||||
@@ -302,7 +113,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "download the file" do
|
should "download the file" do
|
||||||
@service = subject.new(source: @source, referer_url: @ref)
|
@service = UploadService::Preprocessor.new(source: @source, referer_url: @ref)
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
assert_equal("preprocessed", @upload.status)
|
assert_equal("preprocessed", @upload.status)
|
||||||
assert_equal(9800, @upload.file_size)
|
assert_equal(9800, @upload.file_size)
|
||||||
@@ -321,7 +132,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
should "download the file" do
|
should "download the file" do
|
||||||
begin
|
begin
|
||||||
@service = subject.new(source: @source, referer_url: @ref)
|
@service = UploadService::Preprocessor.new(source: @source, referer_url: @ref)
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
rescue Net::OpenTimeout
|
rescue Net::OpenTimeout
|
||||||
skip "network failure"
|
skip "network failure"
|
||||||
@@ -341,9 +152,9 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "download the file" do
|
should "download the file" do
|
||||||
skip unless PixivUgoiraConverter.enabled?
|
skip unless MediaFile::Ugoira.conversion_enabled?
|
||||||
|
|
||||||
@service = subject.new(source: @source)
|
@service = UploadService::Preprocessor.new(source: @source)
|
||||||
begin
|
begin
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
rescue Net::OpenTimeout
|
rescue Net::OpenTimeout
|
||||||
@@ -364,7 +175,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "download the file" do
|
should "download the file" do
|
||||||
@service = subject.new(source: @source)
|
@service = UploadService::Preprocessor.new(source: @source)
|
||||||
begin
|
begin
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
rescue Net::OpenTimeout
|
rescue Net::OpenTimeout
|
||||||
@@ -386,7 +197,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "work for a video" do
|
should "work for a video" do
|
||||||
@service = subject.new(source: @source)
|
@service = UploadService::Preprocessor.new(source: @source)
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
assert_equal("preprocessed", @upload.status)
|
assert_equal("preprocessed", @upload.status)
|
||||||
assert_not_nil(@upload.md5)
|
assert_not_nil(@upload.md5)
|
||||||
@@ -405,7 +216,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "leave the upload in an error state" do
|
should "leave the upload in an error state" do
|
||||||
@service = subject.new(source: @source)
|
@service = UploadService::Preprocessor.new(source: @source)
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
assert_match(/error:/, @upload.status)
|
assert_match(/error:/, @upload.status)
|
||||||
end
|
end
|
||||||
@@ -413,7 +224,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "for an invalid content type" do
|
context "for an invalid content type" do
|
||||||
should "fail" do
|
should "fail" do
|
||||||
upload = subject.new(source: "http://www.example.com").start!
|
upload = UploadService::Preprocessor.new(source: "http://www.example.com").start!
|
||||||
assert_match(/\Aerror:.*File ext is invalid/, upload.status)
|
assert_match(/\Aerror:.*File ext is invalid/, upload.status)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -429,7 +240,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "overwrite the attributes" do
|
should "overwrite the attributes" do
|
||||||
@service = subject.new(source: @source, rating: 'e')
|
@service = UploadService::Preprocessor.new(source: @source, rating: 'e')
|
||||||
@upload = @service.start!
|
@upload = @service.start!
|
||||||
@service.finish!
|
@service.finish!
|
||||||
@upload.reload
|
@upload.reload
|
||||||
@@ -737,7 +548,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "a post that is replaced by a ugoira" do
|
context "a post that is replaced by a ugoira" do
|
||||||
should "save the frame data" do
|
should "save the frame data" do
|
||||||
skip "ffmpeg not installed" unless PixivUgoiraConverter.enabled?
|
skip unless MediaFile::Ugoira.conversion_enabled?
|
||||||
begin
|
begin
|
||||||
as_user { @post.replace!(replacement_url: "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") }
|
as_user { @post.replace!(replacement_url: "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364") }
|
||||||
@post.reload
|
@post.reload
|
||||||
@@ -751,8 +562,6 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
assert_equal("https://i.pximg.net/img-zip-ugoira/img/2017/04/04/08/57/38/62247364_ugoira1920x1080.zip", @post.source)
|
assert_equal("https://i.pximg.net/img-zip-ugoira/img/2017/04/04/08/57/38/62247364_ugoira1920x1080.zip", @post.source)
|
||||||
assert_equal([{"delay" => 125, "file" => "000000.jpg"}, {"delay" => 125, "file" => "000001.jpg"}], @post.pixiv_ugoira_frame_data.data)
|
assert_equal([{"delay" => 125, "file" => "000000.jpg"}, {"delay" => 125, "file" => "000001.jpg"}], @post.pixiv_ugoira_frame_data.data)
|
||||||
rescue Net::OpenTimeout
|
|
||||||
skip "Remote connection to Pixiv failed"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -760,7 +569,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
context "a post that is replaced to another file then replaced back to the original file" do
|
context "a post that is replaced to another file then replaced back to the original file" do
|
||||||
should "not delete the original files" do
|
should "not delete the original files" do
|
||||||
begin
|
begin
|
||||||
skip unless PixivUgoiraConverter.enabled?
|
skip unless MediaFile::Ugoira.conversion_enabled?
|
||||||
@post.unstub(:queue_delete_files)
|
@post.unstub(:queue_delete_files)
|
||||||
|
|
||||||
# this is called thrice to delete the file for 62247364
|
# this is called thrice to delete the file for 62247364
|
||||||
@@ -802,7 +611,7 @@ class UploadServiceTest < ActiveSupport::TestCase
|
|||||||
# swap the images between @post1 and @post2.
|
# swap the images between @post1 and @post2.
|
||||||
begin
|
begin
|
||||||
as_user do
|
as_user do
|
||||||
skip unless PixivUgoiraConverter.enabled?
|
skip unless MediaFile::Ugoira.conversion_enabled?
|
||||||
|
|
||||||
@post1.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350")
|
@post1.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247350")
|
||||||
@post2.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364")
|
@post2.replace!(replacement_url: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364")
|
||||||
|
|||||||
Reference in New Issue
Block a user