require 'thor'
require_relative 'mastodon/media_cli'
+require_relative 'mastodon/emoji_cli'
module Mastodon
class CLI < Thor
desc 'media SUBCOMMAND ...ARGS', 'manage media files'
subcommand 'media', Mastodon::MediaCLI
+
+ desc 'emoji SUBCOMMAND ...ARGS', 'manage custom emoji'
+ subcommand 'emoji', Mastodon::EmojiCLI
end
end
--- /dev/null
+# frozen_string_literal: true
+
+require 'rubygems/package'
+require_relative '../../config/boot'
+require_relative '../../config/environment'
+require_relative 'cli_helper'
+
+# rubocop:disable Rails/Output
+
+module Mastodon
+ class EmojiCLI < Thor
+ option :prefix
+ option :suffix
+ option :overwrite, type: :boolean
+ option :unlisted, type: :boolean
+ desc 'import PATH', 'import emoji from a TAR archive at PATH'
+ long_desc <<-LONG_DESC
+ Imports custom emoji from a TAR archive specified by PATH.
+
+ Existing emoji will be skipped unless the --overwrite option
+ is provided, in which case they will be overwritten.
+
+ With the --prefix option, a prefix can be added to all
+ generated shortcodes. Likewise, the --suffix option controls
+ the suffix of all shortcodes.
+
+ With the --unlisted option, the processed emoji will not be
+ visible in the emoji picker (but still usable via other means)
+ LONG_DESC
+ def import(path)
+ imported = 0
+ skipped = 0
+ failed = 0
+
+ Gem::Package::TarReader.new(Zlib::GzipReader.open(path)) do |tar|
+ tar.each do |entry|
+ next unless entry.file? && entry.full_name.end_with?('.png')
+
+ shortcode = [options[:prefix], File.basename(entry.full_name, '.*'), options[:suffix]].compact.join
+ custom_emoji = CustomEmoji.local.find_by(shortcode: shortcode)
+
+ if custom_emoji && !options[:overwrite]
+ skipped += 1
+ next
+ end
+
+ custom_emoji ||= CustomEmoji.new(shortcode: shortcode, domain: nil)
+ custom_emoji.image = StringIO.new(entry.read)
+ custom_emoji.image_file_name = File.basename(entry.full_name)
+ custom_emoji.visible_in_picker = !options[:unlisted]
+
+ if custom_emoji.save
+ imported += 1
+ else
+ failed += 1
+ say('Failure/Error: ', :red)
+ say(entry.full_name)
+ say(' ' + custom_emoji.errors[:image].join(', '), :red)
+ end
+ end
+ end
+
+ puts
+ say("Imported #{imported}, skipped #{skipped}, failed to import #{failed}", color(imported, skipped, failed))
+ end
+
+ private
+
+ def color(green, _yellow, red)
+ if !green.zero? && red.zero?
+ :green
+ elsif red.zero?
+ :yellow
+ else
+ :red
+ end
+ end
+ end
+end
+
+# rubocop:enable Rails/Output
require_relative '../../config/boot'
require_relative '../../config/environment'
+require_relative 'cli_helper'
# rubocop:disable Rails/Output
the underlying file storage.
DESC
def remove
- time_ago = options[:days].days.ago
- queued = 0
+ time_ago = options[:days].days.ago
+ queued = 0
+ processed = 0
MediaAttachment.where.not(remote_url: '').where.not(file_file_name: nil).where('created_at < ?', time_ago).select(:id).reorder(nil).find_in_batches do |media_attachments|
if options[:background]
else
media_attachments.each do |m|
Maintenance::UncacheMediaWorker.new.perform(m)
- print '.'
+ say('.', :green, false)
+ processed += 1
end
end
end
- puts
- puts "Scheduled the deletion of #{queued} media attachments" if options[:background]
+ say
+
+ if options[:background]
+ say("Scheduled the deletion of #{queued} media attachments", :green)
+ else
+ say("Removed #{processed} media attachments", :green)
+ end
end
end
end