From b3e65978b4a60bede5d5c9dc68daa1e5b5888a7a Mon Sep 17 00:00:00 2001 From: Darius Kazemi Date: Tue, 30 Apr 2019 15:29:28 -0700 Subject: [PATCH] Support locally cached inline images in Articles --- app/lib/activitypub/activity.rb | 4 +- app/lib/activitypub/activity/create.rb | 53 ++++++++++++++++++++++++++ app/lib/formatter.rb | 5 +++ app/lib/sanitize_config.rb | 3 +- 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 66b5763a9..9b4a88382 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -4,8 +4,8 @@ class ActivityPub::Activity include JsonLdHelper include Redisable - SUPPORTED_TYPES = %w(Note Question).freeze - CONVERTED_TYPES = %w(Image Video Article Page).freeze + SUPPORTED_TYPES = %w(Note Question Article).freeze + CONVERTED_TYPES = %w(Image Video Page).freeze def initialize(json, account, **options) @json = json diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 00f0dd42d..1e47de2d9 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -30,6 +30,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @mentions = [] @params = {} + process_inline_images if @object['content'].present? && @object['type'] == 'Article' process_status_params process_tags process_audience @@ -73,6 +74,56 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end end + class Handler < ::Ox::Sax + attr_reader :srcs + attr_reader :alts + def initialize(block) + @stack = [] + @srcs = [] + @alts = {} + end + + def start_element(element_name) + @stack << [element_name, {}] + end + + def end_element(element_name) + self_name, self_attributes = @stack[-1] + if self_name == :img && !self_attributes[:src].nil? + @srcs << self_attributes[:src] + @alts[self_attributes[:src]] = self_attributes[:alt] + end + @stack.pop + end + + def attr(attribute_name, attribute_value) + _name, attributes = @stack.last + attributes[attribute_name] = attribute_value + end + end + + def process_inline_images + proc = Proc.new { |name| puts name } + handler = Handler.new(proc) + Ox.sax_parse(handler, @object['content']) + handler.srcs.each do |src| + if skip_download? + @object['content'].gsub!(src, '') + next + end + + media_attachment = MediaAttachment.create(account: @account, remote_url: src, description: handler.alts[src], focus: nil) + media_attachment.file_remote_url = src + media_attachment.save + if unsupported_media_type?(media_attachment.file.content_type) + @object['content'].gsub!(src, '') + media_attachment.delete + else + @object['content'].gsub!(src, media_attachment.file.url(:small)) + end + end + end + def process_audience (as_array(@object['to']) + as_array(@object['cc'])).uniq.each do |audience| next if audience == ActivityPub::TagManager::COLLECTIONS[:public] @@ -310,6 +361,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def text_from_content return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || @object['id']].join(' ')) if converted_object_type? + return Formatter.instance.format_article(@object['content']) if @object['content'].present? && @object['type'] == 'Article' + if @object['content'].present? @object['content'] elsif content_language_map? diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 8a1aad41a..9c2c0cd29 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -90,6 +90,11 @@ class Formatter html.html_safe # rubocop:disable Rails/OutputSafety end + def format_article(text) + text = text.gsub(/>\n+<") + text.html_safe # rubocop:disable Rails/OutputSafety + end + def linkify(text) html = encode_and_link_urls(text) html = simple_format(html, {}, sanitize: false) diff --git a/app/lib/sanitize_config.rb b/app/lib/sanitize_config.rb index fa2d0784b..c157fc16a 100644 --- a/app/lib/sanitize_config.rb +++ b/app/lib/sanitize_config.rb @@ -34,13 +34,14 @@ class Sanitize end MASTODON_STRICT ||= freeze_config( - elements: %w(p br span a abbr del pre blockquote code b strong i em h1 h2 h3 h4 h5 ul ol li), + elements: %w(p br span a abbr del pre blockquote code b strong i em h1 h2 h3 h4 h5 ul ol li img), attributes: { 'a' => %w(href rel class title), 'span' => %w(class), 'abbr' => %w(title), 'blockquote' => %w(cite), + 'img' => %w(src alt), }, add_attributes: {