about summary refs log tree commit diff
path: root/app/serializers
diff options
context:
space:
mode:
Diffstat (limited to 'app/serializers')
-rw-r--r--app/serializers/activitypub/accept_follow_serializer.rb6
-rw-r--r--app/serializers/activitypub/activity_serializer.rb8
-rw-r--r--app/serializers/activitypub/actor_serializer.rb60
-rw-r--r--app/serializers/activitypub/block_serializer.rb6
-rw-r--r--app/serializers/activitypub/delete_serializer.rb29
-rw-r--r--app/serializers/activitypub/follow_serializer.rb6
-rw-r--r--app/serializers/activitypub/like_serializer.rb6
-rw-r--r--app/serializers/activitypub/note_serializer.rb36
-rw-r--r--app/serializers/activitypub/reject_follow_serializer.rb6
-rw-r--r--app/serializers/activitypub/undo_announce_serializer.rb19
-rw-r--r--app/serializers/activitypub/undo_block_serializer.rb6
-rw-r--r--app/serializers/activitypub/undo_follow_serializer.rb6
-rw-r--r--app/serializers/activitypub/undo_like_serializer.rb6
-rw-r--r--app/serializers/activitypub/update_serializer.rb6
-rw-r--r--app/serializers/initial_state_serializer.rb3
-rw-r--r--app/serializers/oembed_serializer.rb18
-rw-r--r--app/serializers/rest/instance_serializer.rb16
-rw-r--r--app/serializers/rest/status_serializer.rb16
-rw-r--r--app/serializers/web/notification_serializer.rb169
19 files changed, 394 insertions, 34 deletions
diff --git a/app/serializers/activitypub/accept_follow_serializer.rb b/app/serializers/activitypub/accept_follow_serializer.rb
index ce900bc78..3e23591a5 100644
--- a/app/serializers/activitypub/accept_follow_serializer.rb
+++ b/app/serializers/activitypub/accept_follow_serializer.rb
@@ -1,10 +1,14 @@
 # frozen_string_literal: true
 
 class ActivityPub::AcceptFollowSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
 
   has_one :object, serializer: ActivityPub::FollowSerializer
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.target_account), '#accepts/follows/', object.id].join
+  end
+
   def type
     'Accept'
   end
diff --git a/app/serializers/activitypub/activity_serializer.rb b/app/serializers/activitypub/activity_serializer.rb
index 69e2160c5..349495e84 100644
--- a/app/serializers/activitypub/activity_serializer.rb
+++ b/app/serializers/activitypub/activity_serializer.rb
@@ -6,11 +6,11 @@ class ActivityPub::ActivitySerializer < ActiveModel::Serializer
   has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer
 
   def id
-    [ActivityPub::TagManager.instance.uri_for(object), '/activity'].join
+    [ActivityPub::TagManager.instance.activity_uri_for(object)].join
   end
 
   def type
-    object.reblog? ? 'Announce' : 'Create'
+    announce? ? 'Announce' : 'Create'
   end
 
   def actor
@@ -24,4 +24,8 @@ class ActivityPub::ActivitySerializer < ActiveModel::Serializer
   def cc
     ActivityPub::TagManager.instance.cc(object)
   end
+
+  def announce?
+    object.reblog?
+  end
 end
diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb
index f5e626d73..a11178f5b 100644
--- a/app/serializers/activitypub/actor_serializer.rb
+++ b/app/serializers/activitypub/actor_serializer.rb
@@ -4,11 +4,41 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
   include RoutingHelper
 
   attributes :id, :type, :following, :followers,
-             :inbox, :outbox, :preferred_username,
-             :name, :summary, :icon, :image
+             :inbox, :outbox,
+             :preferred_username, :name, :summary,
+             :url, :manually_approves_followers
 
   has_one :public_key, serializer: ActivityPub::PublicKeySerializer
 
+  class ImageSerializer < ActiveModel::Serializer
+    include RoutingHelper
+
+    attributes :type, :url
+
+    def type
+      'Image'
+    end
+
+    def url
+      full_asset_url(object.url(:original))
+    end
+  end
+
+  class EndpointsSerializer < ActiveModel::Serializer
+    include RoutingHelper
+
+    attributes :shared_inbox
+
+    def shared_inbox
+      inbox_url
+    end
+  end
+
+  has_one :endpoints, serializer: EndpointsSerializer
+
+  has_one :icon,  serializer: ImageSerializer, if: :avatar_exists?
+  has_one :image, serializer: ImageSerializer, if: :header_exists?
+
   def id
     account_url(object)
   end
@@ -26,13 +56,17 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
   end
 
   def inbox
-    nil
+    account_inbox_url(object)
   end
 
   def outbox
     account_outbox_url(object)
   end
 
+  def endpoints
+    object
+  end
+
   def preferred_username
     object.username
   end
@@ -46,14 +80,30 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
   end
 
   def icon
-    full_asset_url(object.avatar.url(:original))
+    object.avatar
   end
 
   def image
-    full_asset_url(object.header.url(:original))
+    object.header
   end
 
   def public_key
     object
   end
+
+  def url
+    short_account_url(object)
+  end
+
+  def avatar_exists?
+    object.avatar.exists?
+  end
+
+  def header_exists?
+    object.header.exists?
+  end
+
+  def manually_approves_followers
+    object.locked
+  end
 end
diff --git a/app/serializers/activitypub/block_serializer.rb b/app/serializers/activitypub/block_serializer.rb
index a001b213b..b3bd9f868 100644
--- a/app/serializers/activitypub/block_serializer.rb
+++ b/app/serializers/activitypub/block_serializer.rb
@@ -1,9 +1,13 @@
 # frozen_string_literal: true
 
 class ActivityPub::BlockSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
   attribute :virtual_object, key: :object
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#blocks/', object.id].join
+  end
+
   def type
     'Block'
   end
diff --git a/app/serializers/activitypub/delete_serializer.rb b/app/serializers/activitypub/delete_serializer.rb
index 77098b1b0..87a43b95d 100644
--- a/app/serializers/activitypub/delete_serializer.rb
+++ b/app/serializers/activitypub/delete_serializer.rb
@@ -1,8 +1,29 @@
 # frozen_string_literal: true
 
 class ActivityPub::DeleteSerializer < ActiveModel::Serializer
-  attributes :type, :actor
-  attribute :virtual_object, key: :object
+  class TombstoneSerializer < ActiveModel::Serializer
+    attributes :id, :type, :atom_uri
+
+    def id
+      ActivityPub::TagManager.instance.uri_for(object)
+    end
+
+    def type
+      'Tombstone'
+    end
+
+    def atom_uri
+      ::TagManager.instance.uri_for(object)
+    end
+  end
+
+  attributes :id, :type, :actor
+
+  has_one :object, serializer: TombstoneSerializer
+
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object), '#delete'].join
+  end
 
   def type
     'Delete'
@@ -11,8 +32,4 @@ class ActivityPub::DeleteSerializer < ActiveModel::Serializer
   def actor
     ActivityPub::TagManager.instance.uri_for(object.account)
   end
-
-  def virtual_object
-    ActivityPub::TagManager.instance.uri_for(object)
-  end
 end
diff --git a/app/serializers/activitypub/follow_serializer.rb b/app/serializers/activitypub/follow_serializer.rb
index 1953a2d7b..86c9992fe 100644
--- a/app/serializers/activitypub/follow_serializer.rb
+++ b/app/serializers/activitypub/follow_serializer.rb
@@ -1,9 +1,13 @@
 # frozen_string_literal: true
 
 class ActivityPub::FollowSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
   attribute :virtual_object, key: :object
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#follows/', object.id].join
+  end
+
   def type
     'Follow'
   end
diff --git a/app/serializers/activitypub/like_serializer.rb b/app/serializers/activitypub/like_serializer.rb
index 4226913f5..c1a7ff6f6 100644
--- a/app/serializers/activitypub/like_serializer.rb
+++ b/app/serializers/activitypub/like_serializer.rb
@@ -1,9 +1,13 @@
 # frozen_string_literal: true
 
 class ActivityPub::LikeSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
   attribute :virtual_object, key: :object
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#likes/', object.id].join
+  end
+
   def type
     'Like'
   end
diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb
index 4c13f8e59..d42f54263 100644
--- a/app/serializers/activitypub/note_serializer.rb
+++ b/app/serializers/activitypub/note_serializer.rb
@@ -3,7 +3,9 @@
 class ActivityPub::NoteSerializer < ActiveModel::Serializer
   attributes :id, :type, :summary, :content,
              :in_reply_to, :published, :url,
-             :attributed_to, :to, :cc, :sensitive
+             :attributed_to, :to, :cc, :sensitive,
+             :atom_uri, :in_reply_to_atom_uri,
+             :conversation
 
   has_many :media_attachments, key: :attachment
   has_many :virtual_tags, key: :tag
@@ -25,7 +27,13 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer
   end
 
   def in_reply_to
-    ActivityPub::TagManager.instance.uri_for(object.thread) if object.reply?
+    return unless object.reply?
+
+    if object.thread.uri.nil? || object.thread.uri.start_with?('http')
+      ActivityPub::TagManager.instance.uri_for(object.thread)
+    else
+      object.thread.url
+    end
   end
 
   def published
@@ -52,6 +60,30 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer
     object.mentions + object.tags
   end
 
+  def atom_uri
+    return unless object.local?
+
+    ::TagManager.instance.uri_for(object)
+  end
+
+  def in_reply_to_atom_uri
+    return unless object.reply?
+
+    ::TagManager.instance.uri_for(object.thread)
+  end
+
+  def conversation
+    if object.conversation.uri?
+      object.conversation.uri
+    else
+      TagManager.instance.unique_tag(object.conversation.created_at, object.conversation.id, 'Conversation')
+    end
+  end
+
+  def local?
+    object.account.local?
+  end
+
   class MediaAttachmentSerializer < ActiveModel::Serializer
     include RoutingHelper
 
diff --git a/app/serializers/activitypub/reject_follow_serializer.rb b/app/serializers/activitypub/reject_follow_serializer.rb
index 28584d627..7814f4f57 100644
--- a/app/serializers/activitypub/reject_follow_serializer.rb
+++ b/app/serializers/activitypub/reject_follow_serializer.rb
@@ -1,10 +1,14 @@
 # frozen_string_literal: true
 
 class ActivityPub::RejectFollowSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
 
   has_one :object, serializer: ActivityPub::FollowSerializer
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.target_account), '#rejects/follows/', object.id].join
+  end
+
   def type
     'Reject'
   end
diff --git a/app/serializers/activitypub/undo_announce_serializer.rb b/app/serializers/activitypub/undo_announce_serializer.rb
new file mode 100644
index 000000000..839847e22
--- /dev/null
+++ b/app/serializers/activitypub/undo_announce_serializer.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ActivityPub::UndoAnnounceSerializer < ActiveModel::Serializer
+  attributes :id, :type, :actor
+
+  has_one :object, serializer: ActivityPub::ActivitySerializer
+
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#announces/', object.id, '/undo'].join
+  end
+
+  def type
+    'Undo'
+  end
+
+  def actor
+    ActivityPub::TagManager.instance.uri_for(object.account)
+  end
+end
diff --git a/app/serializers/activitypub/undo_block_serializer.rb b/app/serializers/activitypub/undo_block_serializer.rb
index f71faa729..2f43d8402 100644
--- a/app/serializers/activitypub/undo_block_serializer.rb
+++ b/app/serializers/activitypub/undo_block_serializer.rb
@@ -1,10 +1,14 @@
 # frozen_string_literal: true
 
 class ActivityPub::UndoBlockSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
 
   has_one :object, serializer: ActivityPub::BlockSerializer
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#blocks/', object.id, '/undo'].join
+  end
+
   def type
     'Undo'
   end
diff --git a/app/serializers/activitypub/undo_follow_serializer.rb b/app/serializers/activitypub/undo_follow_serializer.rb
index fe91f5f1c..e5b7f143d 100644
--- a/app/serializers/activitypub/undo_follow_serializer.rb
+++ b/app/serializers/activitypub/undo_follow_serializer.rb
@@ -1,10 +1,14 @@
 # frozen_string_literal: true
 
 class ActivityPub::UndoFollowSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
 
   has_one :object, serializer: ActivityPub::FollowSerializer
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#follows/', object.id, '/undo'].join
+  end
+
   def type
     'Undo'
   end
diff --git a/app/serializers/activitypub/undo_like_serializer.rb b/app/serializers/activitypub/undo_like_serializer.rb
index db9cd1d0d..25f4ccaae 100644
--- a/app/serializers/activitypub/undo_like_serializer.rb
+++ b/app/serializers/activitypub/undo_like_serializer.rb
@@ -1,10 +1,14 @@
 # frozen_string_literal: true
 
 class ActivityPub::UndoLikeSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
 
   has_one :object, serializer: ActivityPub::LikeSerializer
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object.account), '#likes/', object.id, '/undo'].join
+  end
+
   def type
     'Undo'
   end
diff --git a/app/serializers/activitypub/update_serializer.rb b/app/serializers/activitypub/update_serializer.rb
index 322305da8..ebc667d96 100644
--- a/app/serializers/activitypub/update_serializer.rb
+++ b/app/serializers/activitypub/update_serializer.rb
@@ -1,10 +1,14 @@
 # frozen_string_literal: true
 
 class ActivityPub::UpdateSerializer < ActiveModel::Serializer
-  attributes :type, :actor
+  attributes :id, :type, :actor
 
   has_one :object, serializer: ActivityPub::ActorSerializer
 
+  def id
+    [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.updated_at.to_i].join
+  end
+
   def type
     'Update'
   end
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index 0191948b1..32ffcc688 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -19,7 +19,6 @@ class InitialStateSerializer < ActiveModel::Serializer
       store[:boost_modal]    = object.current_account.user.setting_boost_modal
       store[:delete_modal]   = object.current_account.user.setting_delete_modal
       store[:auto_play_gif]  = object.current_account.user.setting_auto_play_gif
-      store[:system_font_ui] = object.current_account.user.setting_system_font_ui
     end
 
     store
@@ -34,6 +33,8 @@ class InitialStateSerializer < ActiveModel::Serializer
       store[:default_sensitive] = object.current_account.user.setting_default_sensitive
     end
 
+    store[:text] = object.text if object.text
+
     store
   end
 
diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb
index 78376d253..bd05da585 100644
--- a/app/serializers/oembed_serializer.rb
+++ b/app/serializers/oembed_serializer.rb
@@ -21,7 +21,7 @@ class OEmbedSerializer < ActiveModel::Serializer
   end
 
   def author_url
-    account_url(object.account)
+    short_account_url(object.account)
   end
 
   def provider_name
@@ -37,13 +37,15 @@ class OEmbedSerializer < ActiveModel::Serializer
   end
 
   def html
-    tag :iframe,
-        src: embed_account_stream_entry_url(object.account, object),
-        style: 'width: 100%; overflow: hidden',
-        frameborder: '0',
-        scrolling: 'no',
-        width: width,
-        height: height
+    attributes = {
+      src: embed_short_account_status_url(object.account, object),
+      class: 'mastodon-embed',
+      style: 'max-width: 100%; border: none;',
+      width: width,
+      height: height,
+    }
+
+    content_tag :iframe, nil, attributes
   end
 
   def width
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
index 8e32f9cb3..a97137909 100644
--- a/app/serializers/rest/instance_serializer.rb
+++ b/app/serializers/rest/instance_serializer.rb
@@ -2,7 +2,7 @@
 
 class REST::InstanceSerializer < ActiveModel::Serializer
   attributes :uri, :title, :description, :email,
-             :version, :urls
+             :version, :urls, :stats
 
   def uri
     Rails.configuration.x.local_domain
@@ -24,7 +24,21 @@ class REST::InstanceSerializer < ActiveModel::Serializer
     Mastodon::Version.to_s
   end
 
+  def stats
+    {
+      user_count: instance_presenter.user_count,
+      status_count: instance_presenter.status_count,
+      domain_count: instance_presenter.domain_count,
+    }
+  end
+
   def urls
     { streaming_api: Rails.configuration.x.streaming_api_base_url }
   end
+
+  private
+
+  def instance_presenter
+    @instance_presenter ||= InstancePresenter.new
+  end
 end
diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb
index 246b12a90..298a3bb40 100644
--- a/app/serializers/rest/status_serializer.rb
+++ b/app/serializers/rest/status_serializer.rb
@@ -8,6 +8,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
   attribute :favourited, if: :current_user?
   attribute :reblogged, if: :current_user?
   attribute :muted, if: :current_user?
+  attribute :pinned, if: :pinnable?
 
   belongs_to :reblog, serializer: REST::StatusSerializer
   belongs_to :application
@@ -57,6 +58,21 @@ class REST::StatusSerializer < ActiveModel::Serializer
     end
   end
 
+  def pinned
+    if instance_options && instance_options[:relationships]
+      instance_options[:relationships].pins_map[object.id] || false
+    else
+      current_user.account.pinned?(object)
+    end
+  end
+
+  def pinnable?
+    current_user? &&
+      current_user.account_id == object.account_id &&
+      !object.reblog? &&
+      %w(public unlisted).include?(object.visibility)
+  end
+
   class ApplicationSerializer < ActiveModel::Serializer
     attributes :name, :website
   end
diff --git a/app/serializers/web/notification_serializer.rb b/app/serializers/web/notification_serializer.rb
new file mode 100644
index 000000000..e5524fe7a
--- /dev/null
+++ b/app/serializers/web/notification_serializer.rb
@@ -0,0 +1,169 @@
+# frozen_string_literal: true
+
+class Web::NotificationSerializer < ActiveModel::Serializer
+  include RoutingHelper
+  include StreamEntriesHelper
+
+  class DataSerializer < ActiveModel::Serializer
+    include RoutingHelper
+    include StreamEntriesHelper
+    include ActionView::Helpers::SanitizeHelper
+
+    attributes :content, :nsfw, :url, :actions,
+               :access_token, :message, :dir
+
+    def content
+      decoder.decode(strip_tags(body))
+    end
+
+    def dir
+      rtl?(body) ? 'rtl' : 'ltr'
+    end
+
+    def nsfw
+      return if object.target_status.nil?
+      object.target_status.spoiler_text.presence
+    end
+
+    def url
+      case object.type
+      when :mention
+        web_url("statuses/#{object.target_status.id}")
+      when :follow
+        web_url("accounts/#{object.from_account.id}")
+      when :favourite
+        web_url("statuses/#{object.target_status.id}")
+      when :reblog
+        web_url("statuses/#{object.target_status.id}")
+      end
+    end
+
+    def actions
+      return @actions if defined?(@actions)
+
+      @actions = []
+
+      if object.type == :mention
+        @actions << expand_action if collapsed?
+        @actions << favourite_action
+        @actions << reblog_action if rebloggable?
+      end
+
+      @actions
+    end
+
+    def access_token
+      return if actions.empty?
+      current_push_subscription.access_token
+    end
+
+    def message
+      I18n.t('push_notifications.group.title')
+    end
+
+    private
+
+    def body
+      case object.type
+      when :mention
+        object.target_status.text
+      when :follow
+        object.from_account.note
+      when :favourite
+        object.target_status.text
+      when :reblog
+        object.target_status.text
+      end
+    end
+
+    def decoder
+      @decoder ||= HTMLEntities.new
+    end
+
+    def expand_action
+      {
+        title: I18n.t('push_notifications.mention.action_expand'),
+        icon: full_asset_url('web-push-icon_expand.png', skip_pipeline: true),
+        todo: 'expand',
+        action: 'expand',
+      }
+    end
+
+    def favourite_action
+      {
+        title: I18n.t('push_notifications.mention.action_favourite'),
+        icon: full_asset_url('web-push-icon_favourite.png', skip_pipeline: true),
+        todo: 'request',
+        method: 'POST',
+        action: "/api/v1/statuses/#{object.target_status.id}/favourite",
+      }
+    end
+
+    def reblog_action
+      {
+        title: I18n.t('push_notifications.mention.action_boost'),
+        icon: full_asset_url('web-push-icon_reblog.png', skip_pipeline: true),
+        todo: 'request',
+        method: 'POST',
+        action: "/api/v1/statuses/#{object.target_status.id}/reblog",
+      }
+    end
+
+    def collapsed?
+      !object.target_status.nil? && (object.target_status.sensitive? || object.target_status.spoiler_text.present?)
+    end
+
+    def rebloggable?
+      !object.target_status.nil? && !object.target_status.hidden?
+    end
+  end
+
+  attributes :title, :image, :badge, :tag,
+             :timestamp, :icon
+
+  has_one :data, serializer: DataSerializer
+
+  def title
+    case object.type
+    when :mention
+      I18n.t('push_notifications.mention.title', name: name)
+    when :follow
+      I18n.t('push_notifications.follow.title', name: name)
+    when :favourite
+      I18n.t('push_notifications.favourite.title', name: name)
+    when :reblog
+      I18n.t('push_notifications.reblog.title', name: name)
+    end
+  end
+
+  def image
+    return if object.target_status.nil? || object.target_status.media_attachments.empty?
+    full_asset_url(object.target_status.media_attachments.first.file.url(:small))
+  end
+
+  def badge
+    full_asset_url('badge.png', skip_pipeline: true)
+  end
+
+  def tag
+    object.id
+  end
+
+  def timestamp
+    object.created_at
+  end
+
+  def icon
+    object.from_account.avatar_static_url
+  end
+
+  def data
+    object
+  end
+
+  private
+
+  def name
+    display_name(object.from_account)
+  end
+end