about summary refs log tree commit diff
path: root/app/lib
diff options
context:
space:
mode:
Diffstat (limited to 'app/lib')
-rw-r--r--app/lib/activitypub/activity/create.rb49
-rw-r--r--app/lib/activitypub/adapter.rb14
-rw-r--r--app/lib/activitypub/case_transform.rb4
-rw-r--r--app/lib/command_tag/command/status_tools.rb14
-rw-r--r--app/lib/command_tag/processor.rb15
-rw-r--r--app/lib/formatter.rb18
6 files changed, 95 insertions, 19 deletions
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 69480ccf6..9ab60107b 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -85,7 +85,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     @params   = {}
 
     unless @status.nil?
-      process_status_update_params
+      reblog_uri.blank? ? process_status_update_params : process_reblog_update_params
       process_tags
       process_audience
 
@@ -95,7 +95,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
       return @status
     end
 
-    process_status_params
+    reblog_uri.blank? ? process_status_params : process_reblog_params
     process_tags
     process_audience
 
@@ -128,6 +128,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
         language: detected_language,
         spoiler_text: converted_object_type? ? '' : (text_from_summary || ''),
         title: text_from_title,
+        reblog: reblogged_status,
         created_at: @object['published'],
         override_timestamps: @options[:override_timestamps],
         reply: @object['inReplyTo'].present?,
@@ -155,6 +156,40 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     end
   end
 
+  def process_reblog_params
+    @params = begin
+      {
+        uri: object_uri,
+        url: object_url || object_uri,
+        account: @account,
+        text: text_from_content || '',
+        language: detected_language,
+        spoiler_text: converted_object_type? ? '' : (text_from_summary || ''),
+        title: text_from_title,
+        reblog: reblogged_status,
+        created_at: @object['published'],
+        override_timestamps: @options[:override_timestamps],
+        reply: @object['inReplyTo'].present?,
+        sensitive: @object['sensitive'] || false,
+        visibility: visibility_from_audience,
+        thread: replied_to_status,
+      }
+    end
+  end
+
+  def process_reblog_update_params
+    @params = begin
+      {
+        text: text_from_content || '',
+        language: detected_language,
+        spoiler_text: converted_object_type? ? '' : (text_from_summary || ''),
+        title: text_from_title,
+        sensitive: @object['sensitive'] || false,
+        visibility: visibility_from_audience,
+      }
+    end
+  end
+
   def process_audience
     (as_array(audience_to) + as_array(audience_cc)).uniq.each do |audience|
       next if audience == ActivityPub::TagManager::COLLECTIONS[:public]
@@ -459,6 +494,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     value_or_id(@object['inReplyTo'])
   end
 
+  def reblogged_status
+    FetchRemoteStatusService.new.call(reblog_uri) if reblog_uri.present?
+  end
+
+  def reblog_uri
+    return @reblog_uri if defined?(@reblog_uri)
+
+    @reblog_uri = @object['reblog'].presence || @object['_misskey_quote'].presence
+  end
+
   def text_from_content
     return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || object_uri].join(' ')) if converted_object_type?
 
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
index 107b93b44..33fa47d63 100644
--- a/app/lib/activitypub/adapter.rb
+++ b/app/lib/activitypub/adapter.rb
@@ -8,15 +8,17 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
 
   CONTEXT_EXTENSION_MAP = {
     direct_message: { 'litepub': 'http://litepub.social/ns#', 'directMessage': 'litepub:directMessage' },
-    edited: { 'mp' => 'http://the.monsterpit.net/ns#', 'edited' => 'mp:edited' },
-    require_dereference: { 'mp' => 'http://the.monsterpit.net/ns#', 'requireDereference' => 'mp:requireDereference' },
-    show_replies: { 'mp' => 'http://the.monsterpit.net/ns#', 'showReplies' => 'mp:showReplies' },
-    show_unlisted: { 'mp' => 'http://the.monsterpit.net/ns#', 'showUnlisted' => 'mp:showUnlisted' },
-    private: { 'mp' => 'http://the.monsterpit.net/ns#', 'private' => 'mp:private' },
-    require_auth: { 'mp' => 'http://the.monsterpit.net/ns#', 'requireAuth' => 'mp:requireAuth' },
+    edited: { 'mp' => 'https://the.monsterpit.net/ns#', 'edited' => 'mp:edited' },
+    require_dereference: { 'mp' => 'https://the.monsterpit.net/ns#', 'requireDereference' => 'mp:requireDereference' },
+    show_replies: { 'mp' => 'https://the.monsterpit.net/ns#', 'showReplies' => 'mp:showReplies' },
+    show_unlisted: { 'mp' => 'https://the.monsterpit.net/ns#', 'showUnlisted' => 'mp:showUnlisted' },
+    private: { 'mp' => 'https://the.monsterpit.net/ns#', 'private' => 'mp:private' },
+    require_auth: { 'mp' => 'https://the.monsterpit.net/ns#', 'requireAuth' => 'mp:requireAuth' },
     metadata: { 'mp' => 'https://the.monsterpit.net/ns#', 'metadata' => { '@id' => 'mp:metadata', '@type' => '@id' } },
     server_metadata: { 'mp' => 'https://the.monsterpit.net/ns#', 'serverMetadata' => { '@id' => 'mp:serverMetadata', '@type' => '@id' } },
     root: { 'mp' => 'https://the.monsterpit.net/ns#', 'root' => { '@id' => 'mp:root', '@type' => '@id' } },
+    reblog: { 'mp' => 'https://the.monsterpit.net/ns#', 'reblog' => { '@id' => 'mp:reblog', '@type' => '@id' },
+              'misskey' => 'https://misskey.io/ns#', '_misskey_quote' => { '@id' => 'misskey:_misskey_quote', '@type' => '@id' } },
     manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' },
     sensitive: { 'sensitive' => 'as:sensitive' },
     hashtag: { 'Hashtag' => 'as:Hashtag' },
diff --git a/app/lib/activitypub/case_transform.rb b/app/lib/activitypub/case_transform.rb
index 7f716f862..7f31fabda 100644
--- a/app/lib/activitypub/case_transform.rb
+++ b/app/lib/activitypub/case_transform.rb
@@ -14,8 +14,10 @@ module ActivityPub::CaseTransform
       when String
         camel_lower_cache[value] ||= if value.start_with?('_:')
                                        '_:' + value.gsub(/\A_:/, '').underscore.camelize(:lower)
-                                     else
+                                     elsif value != '_misskey_quote'
                                        value.underscore.camelize(:lower)
+                                     else
+                                       value
                                      end
       else value
       end
diff --git a/app/lib/command_tag/command/status_tools.rb b/app/lib/command_tag/command/status_tools.rb
index 1cdb90e4a..5cc11dde2 100644
--- a/app/lib/command_tag/command/status_tools.rb
+++ b/app/lib/command_tag/command/status_tools.rb
@@ -1,5 +1,19 @@
 # frozen_string_literal: true
 module CommandTag::Command::StatusTools
+  def handle_boost_once_at_start(args)
+    return unless @parent.present? && StatusPolicy.new(@account, @parent).reblog?
+
+    status = ReblogService.new.call(
+      @account, @parent,
+      visibility: @status.visibility,
+      spoiler_text: args.join(' ').presence || @status.spoiler_text
+    )
+  end
+
+  alias handle_reblog_at_start handle_boost_once_at_start
+  alias handle_rb_at_start handle_boost_once_at_start
+  alias handle_rt_at_start handle_boost_once_at_start
+
   def handle_article_before_save(args)
     return unless author_of_status? && args.present?
 
diff --git a/app/lib/command_tag/processor.rb b/app/lib/command_tag/processor.rb
index 2c33b5f83..9edcb58ba 100644
--- a/app/lib/command_tag/processor.rb
+++ b/app/lib/command_tag/processor.rb
@@ -12,6 +12,12 @@
 
 require_relative 'commands'
 
+class CommandTag::Break < Mastodon::Error
+  def initialize(msg = 'A handler stopped execution.')
+    super
+  end
+end
+
 class CommandTag::Processor
   include Redisable
   include ImgProxyHelper
@@ -83,6 +89,8 @@ class CommandTag::Processor
 
     execute_statements(:at_end)
     all_handlers!(:shutdown)
+  rescue CommandTag::Break
+    nil
   rescue StandardError => e
     @status.update(published: false)
     @status.destroy
@@ -247,6 +255,13 @@ class CommandTag::Processor
     @status.destroy
   end
 
+  def replace_status!(new_status)
+    return if new_status.blank?
+
+    destroy_status!
+    @status = new_status
+  end
+
   def normalize(text)
     text.to_s.strip.downcase
   end
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 5559ddb73..6673f4b4b 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -32,15 +32,8 @@ class Formatter
   include ActionView::Helpers::TextHelper
 
   def format(status, **options)
-    if status.reblog?
-      prepend_reblog = status.reblog.account.acct
-      status         = status.proper
-    else
-      prepend_reblog = false
-    end
-
     summary = nil
-    raw_content = status.text
+    raw_content = status.proper.text
     summary_mode = false
 
     if status.title.present?
@@ -56,8 +49,13 @@ class Formatter
     return '' if raw_content.blank?
     return format_remote_content(raw_content, status.emojis, summary: summary, **options) unless status.local?
 
-    html = raw_content
-    html = "RT @#{prepend_reblog} #{html}" if prepend_reblog
+    if status.reblog?
+      html = "🔁 @#{status.reblog.account.acct}\n🔗 #{ActivityPub::TagManager.instance.url_for(status.reblog)}"
+      html += "\nℹ️ #{status.reblog.spoiler_text}" if status.reblog.spoiler_text.present?
+    else
+      html = raw_content
+    end
+
     html = "📄 #{html}" if summary_mode
     return html if options[:plaintext]