DEV: Remove gifsicle dependency (#10357)

DEV: Remove gifsicle dependency (#10357)

Dependency on gifsicle, allow_animated_avatars and allow_animated_thumbnails site settings were all removed. Animated GIF images are still allowed, but the generated optimized images are no longer animated for those (which were used for avatars and thumbnails).

The added ‘animated’ is populated by extracting information using FastImage. This field was used to selectively reoptimize old animations. This process happens in the background.

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3eb5f26..8e4c2b6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -65,7 +65,7 @@ jobs:
         if: env.BUILD_TYPE != 'LINT'
         run: |
           sudo apt-get update
-          sudo apt-get -yqq install postgresql-client libpq-dev gifsicle jpegoptim optipng jhead
+          sudo apt-get -yqq install postgresql-client libpq-dev jpegoptim optipng jhead
           wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/master/image/base/install-pngquant | sudo sh
 
       - name: Update imagemagick
diff --git a/app/assets/javascripts/discourse/tests/helpers/site-settings.js b/app/assets/javascripts/discourse/tests/helpers/site-settings.js
index ba52f3f..d84b53e 100644
--- a/app/assets/javascripts/discourse/tests/helpers/site-settings.js
+++ b/app/assets/javascripts/discourse/tests/helpers/site-settings.js
@@ -63,7 +63,6 @@ const ORIGINAL_SETTINGS = {
   max_image_height: 500,
   allow_profile_backgrounds: true,
   allow_uploaded_avatars: true,
-  allow_animated_avatars: false,
   tl1_requires_read_posts: 30,
   enable_long_polling: true,
   polling_interval: 3000,
diff --git a/app/controllers/user_avatars_controller.rb b/app/controllers/user_avatars_controller.rb
index be91188..583fc81 100644
--- a/app/controllers/user_avatars_controller.rb
+++ b/app/controllers/user_avatars_controller.rb
@@ -189,7 +189,7 @@ class UserAvatarsController < ApplicationController
     return if !upload
     return upload if upload.extension == "svg"
 
-    upload.get_optimized_image(size, size, allow_animation: SiteSetting.allow_animated_avatars)
+    upload.get_optimized_image(size, size)
     # TODO decide if we want to detach here
   end
 
diff --git a/app/jobs/regular/create_avatar_thumbnails.rb b/app/jobs/regular/create_avatar_thumbnails.rb
index 540c580..51988a4 100644
--- a/app/jobs/regular/create_avatar_thumbnails.rb
+++ b/app/jobs/regular/create_avatar_thumbnails.rb
@@ -14,12 +14,7 @@ module Jobs
       return unless upload = Upload.find_by(id: upload_id)
 
       Discourse.avatar_sizes.each do |size|
-        OptimizedImage.create_for(
-          upload,
-          size,
-          size,
-          allow_animation: SiteSetting.allow_animated_avatars
-        )
+        OptimizedImage.create_for(upload, size, size)
       end
     end
 
diff --git a/app/jobs/scheduled/update_animated_uploads.rb b/app/jobs/scheduled/update_animated_uploads.rb
new file mode 100644
index 0000000..2938911
--- /dev/null
+++ b/app/jobs/scheduled/update_animated_uploads.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Jobs
+  class UpdateAnimatedUploads < ::Jobs::Scheduled
+    every 1.hour
+
+    MAX_PROCESSED_GIF_IMAGES ||= 200
+
+    def execute(args)
+      Upload
+        .where("extension = 'gif' OR (extension IS NULL AND original_filename LIKE '%.gif')")
+        .where(animated: nil)
+        .limit(MAX_PROCESSED_GIF_IMAGES)
+        .each do |upload|
+        uri = Discourse.store.path_for(upload) || upload.url
+        upload.update!(animated: FastImage.animated?(uri))
+        upload.optimized_images.destroy_all if upload.animated
+      end
+
+      nil
+    end
+  end
+end
diff --git a/app/models/optimized_image.rb b/app/models/optimized_image.rb
index 589cc5f..42a62b9 100644
--- a/app/models/optimized_image.rb
+++ b/app/models/optimized_image.rb
@@ -234,20 +234,6 @@ class OptimizedImage < ActiveRecord::Base
     })
   end
 
-  def self.resize_instructions_animated(from, to, dimensions, opts = {})
-    ensure_safe_paths!(from, to)
-    resize_method = opts[:scale_image] ? "scale" : "resize-fit"
-
-    %W{
-      gifsicle
-      --colors=#{opts[:colors] || 256}
-      --#{resize_method} #{dimensions}
-      --optimize=3
-      --output #{to}
-      #{from}
-    }
-  end
-
   def self.crop_instructions(from, to, dimensions, opts = {})
     ensure_safe_paths!(from, to)
 
@@ -270,19 +256,6 @@ class OptimizedImage < ActiveRecord::Base
     }
   end
 
-  def self.crop_instructions_animated(from, to, dimensions, opts = {})
-    ensure_safe_paths!(from, to)
-
-    %W{
-      gifsicle
-      --crop 0,0+#{dimensions}
-      --colors=#{opts[:colors] || 256}
-      --optimize=3
-      --output #{to}
-      #{from}
-    }
-  end
-
   def self.downsize_instructions(from, to, dimensions, opts = {})
     ensure_safe_paths!(from, to)
 
@@ -302,10 +275,6 @@ class OptimizedImage < ActiveRecord::Base
     }
   end
 
-  def self.downsize_instructions_animated(from, to, dimensions, opts = {})
-    resize_instructions_animated(from, to, dimensions, opts)
-  end
-
   def self.resize(from, to, width, height, opts = {})
     optimize("resize", from, to, "#{width}x#{height}", opts)
   end
@@ -322,10 +291,6 @@ class OptimizedImage < ActiveRecord::Base
   def self.optimize(operation, from, to, dimensions, opts = {})
     method_name = "#{operation}_instructions"
 
-    if !!opts[:allow_animation] && (from =~ /\.GIF$/i)
-      method_name += "_animated"
-    end
-
     instructions = self.public_send(method_name.to_sym, from, to, dimensions, opts)
     convert_with(instructions, to, opts)
   end
diff --git a/app/models/upload.rb b/app/models/upload.rb
index 36fc6da..27d8825 100644
--- a/app/models/upload.rb
+++ b/app/models/upload.rb
@@ -78,7 +78,6 @@ class Upload < ActiveRecord::Base
   def create_thumbnail!(width, height, opts = nil)
     return unless SiteSetting.create_thumbnails?
     opts ||= {}
-    opts[:allow_animation] = SiteSetting.allow_animated_thumbnails
 
     if get_optimized_image(width, height, opts)
       save(validate: false)
@@ -86,7 +85,9 @@ class Upload < ActiveRecord::Base
   end
 
   # this method attempts to correct old incorrect extensions
-  def get_optimized_image(width, height, opts)
+  def get_optimized_image(width, height, opts = nil)
+    opts ||= {}
+
     if (!extension || extension.length == 0)
       fix_image_extension
     end
@@ -461,11 +462,12 @@ end
 #  secure                 :boolean          default(FALSE), not null
 #  access_control_post_id :bigint
 #  original_sha1          :string
-#  verified               :boolean
 #  verification_status    :integer          default(1), not null
+#  animated               :boolean
 #
 # Indexes
 #
+#  idx_uploads_on_verification_status       (verification_status)
 #  index_uploads_on_access_control_post_id  (access_control_post_id)
 #  index_uploads_on_etag                    (etag)
 #  index_uploads_on_extension               (lower((extension)::text))
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 2ef198f..16455b5 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -2000,8 +2000,6 @@ en:
     logout_redirect: "Location to redirect browser to after logout (eg: https://example.com/logout)"
 
     allow_uploaded_avatars: "Allow users to upload custom profile pictures."
-    allow_animated_avatars: "Allow users to use animated gif profile pictures. WARNING: run the avatars:refresh rake task after changing this setting."
-    allow_animated_thumbnails: "Generates animated thumbnails of animated gifs."
     default_avatars: "URLs to avatars that will be used by default for new users until they change them."
     automatically_download_gravatars: "Download Gravatars for users upon account creation or email change."
     digest_topics: "The maximum number of popular topics to display in the email summary."
diff --git a/config/site_settings.yml b/config/site_settings.yml
index 42722d9..0483fed 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -1308,10 +1308,6 @@ files:
   allow_uploaded_avatars:
     client: true
     default: true
-  allow_animated_avatars:
-    client: true
-    default: false
-  allow_animated_thumbnails: true
   default_avatars:
     default: ""
     type: url_list
diff --git a/db/migrate/20200707183007_add_animated_to_uploads.rb b/db/migrate/20200707183007_add_animated_to_uploads.rb

[... diff too long, it was truncated ...]

GitHub sha: 43e52a7d

This commit appears in #10357 which was approved by ZogStriP. It was merged by nbianca.