Add emoji reactions to note object

This commit is contained in:
noellabo 2022-04-13 10:33:23 +09:00
parent cf35497935
commit b12778caeb
9 changed files with 141 additions and 3 deletions

View file

@ -0,0 +1,77 @@
# frozen_string_literal: true
class ActivityPub::EmojiReactionsController < ActivityPub::BaseController
include SignatureVerification
include Authorization
include AccountOwnedConcern
EMOJI_REACTIONS_LIMIT = 60
before_action :require_signature!, if: :authorized_fetch_mode?
before_action :set_status
before_action :set_cache_headers
before_action :set_emoji_reactions
def index
expires_in 0, public: public_fetch_mode?
render json: emoji_reactions_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json', skip_activities: true
end
private
def pundit_user
signed_request_account
end
def set_status
@status = @account.statuses.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def set_emoji_reactions
@emoji_reactions = @status.emoji_reactions
@emoji_reactions = @emoji_reactions.paginate_by_min_id(EMOJI_REACTIONS_LIMIT, params[:min_id])
end
def records_continue?
@emoji_reactions.size == EMOJI_REACTIONS_LIMIT
end
def emoji_reactions_collection_presenter
page = ActivityPub::CollectionPresenter.new(
id: ActivityPub::TagManager.instance.emoji_reactions_uri_for(@status, page_params),
type: :unordered,
part_of: ActivityPub::TagManager.instance.emoji_reactions_uri_for(@status),
next: next_page,
items: @emoji_reactions.map { |emoji_reaction| emoji_reaction.uri.blank? ? emoji_reaction : emoji_reaction.uri }
)
return page if page_requested?
ActivityPub::CollectionPresenter.new(
id: ActivityPub::TagManager.instance.emoji_reactions_uri_for(@status),
type: :unordered,
first: page
)
end
def page_requested?
truthy_param?(:page)
end
def next_page
if records_continue?
ActivityPub::TagManager.instance.emoji_reactions_uri_for(
@status,
page: true,
min_id: @emoji_reactions&.last&.id,
)
end
end
def page_params
params_slice(:min_id).merge(page: true)
end
end

View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
class EmojiReactionsController < ApplicationController
before_action :set_emoji_reaction
before_action :set_cache_headers
def show
respond_to do |format|
format.json do
expires_in 3.minutes, public: true
render_with_cache json: @emoji_reaction, content_type: 'application/activity+json', serializer: ActivityPub::EmojiReactionSerializer, adapter: ActivityPub::Adapter
end
end
end
private
def set_emoji_reaction
@emoji_reaction = EmojiReaction.local.find(params[:id])
end
end

View file

@ -28,6 +28,7 @@ module ContextHelper
expiry: { 'fedibird' => 'http://fedibird.com/ns#', 'expiry' => 'fedibird:expiry' }, expiry: { 'fedibird' => 'http://fedibird.com/ns#', 'expiry' => 'fedibird:expiry' },
other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' }, other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' },
references: { 'fedibird' => 'http://fedibird.com/ns#', 'references' => { '@id' => "fedibird:references", '@type' => '@id' } }, references: { 'fedibird' => 'http://fedibird.com/ns#', 'references' => { '@id' => "fedibird:references", '@type' => '@id' } },
emoji_reactions: { 'fedibird' => 'http://fedibird.com/ns#', 'emojiReactions' => { '@id' => "fedibird:emojiReactions", '@type' => '@id' } },
is_cat: { 'misskey' => 'https://misskey-hub.net/ns#', 'isCat' => 'misskey:isCat' }, is_cat: { 'misskey' => 'https://misskey-hub.net/ns#', 'isCat' => 'misskey:isCat' },
vcard: { 'vcard' => 'http://www.w3.org/2006/vcard/ns#' }, vcard: { 'vcard' => 'http://www.w3.org/2006/vcard/ns#' },
}.freeze }.freeze

View file

@ -47,6 +47,8 @@ class ActivityPub::TagManager
end end
when :emoji when :emoji
emoji_url(target) emoji_url(target)
when :emoji_reaction
emoji_reaction_url(target)
when :conversation when :conversation
context_url(target) context_url(target)
end end
@ -78,6 +80,12 @@ class ActivityPub::TagManager
account_status_references_url(target.account, target, page_params) account_status_references_url(target.account, target, page_params)
end end
def emoji_reactions_uri_for(target, page_params = nil)
raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?
account_status_emoji_reactions_url(target.account, target, page_params)
end
# Primary audience of a status # Primary audience of a status
# Public statuses go out to primarily the public collection # Public statuses go out to primarily the public collection
# Unlisted and private statuses go out primarily to the followers collection # Unlisted and private statuses go out primarily to the followers collection

View file

@ -26,6 +26,9 @@ class EmojiReaction < ApplicationRecord
has_one :notification, as: :activity, dependent: :destroy has_one :notification, as: :activity, dependent: :destroy
scope :local, -> { where(uri: nil) }
scope :remote, -> { where.not(uri: nil) }
validates :name, presence: true validates :name, presence: true
validates_with EmojiReactionValidator validates_with EmojiReactionValidator
@ -37,6 +40,10 @@ class EmojiReaction < ApplicationRecord
true true
end end
def object_type
:emoji_reaction
end
private private
def queue_publish def queue_publish

View file

@ -7,7 +7,7 @@ class ActivityPub::EmojiReactionSerializer < ActivityPub::Serializer
has_one :custom_emoji ,key: :tag, serializer: ActivityPub::EmojiSerializer, unless: -> { object.custom_emoji.nil? } has_one :custom_emoji ,key: :tag, serializer: ActivityPub::EmojiSerializer, unless: -> { object.custom_emoji.nil? }
def id def id
[ActivityPub::TagManager.instance.uri_for(object.account), '#emoji_reactions/', object.id].join ActivityPub::TagManager.instance.uri_for(object)
end end
def type def type

View file

@ -7,8 +7,25 @@ class ActivityPub::EmojiSerializer < ActivityPub::Serializer
attributes :id, :type, :name, :updated attributes :id, :type, :name, :updated
has_one :icon, serializer: ActivityPub::ImageSerializer has_one :icon
class RemoteImageSerializer < ActivityPub::ImageSerializer
def url
object.instance.image_remote_url
end
end
def self.serializer_for(model, options)
case model.class.name
when 'Paperclip::Attachment'
if model.instance.local?
ActivityPub::ImageSerializer
else
RemoteImageSerializer
end
end
end
def id def id
ActivityPub::TagManager.instance.uri_for(object) ActivityPub::TagManager.instance.uri_for(object)
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class ActivityPub::NoteSerializer < ActivityPub::Serializer class ActivityPub::NoteSerializer < ActivityPub::Serializer
context_extensions :atom_uri, :conversation, :sensitive, :voters_count, :quote_uri, :expiry, :references context_extensions :atom_uri, :conversation, :sensitive, :voters_count, :quote_uri, :expiry, :references, :emoji_reactions
attributes :id, :type, :summary, attributes :id, :type, :summary,
:in_reply_to, :published, :url, :in_reply_to, :published, :url,
@ -22,6 +22,7 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local? has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local?
has_one :references, serializer: ActivityPub::CollectionSerializer, if: :local? has_one :references, serializer: ActivityPub::CollectionSerializer, if: :local?
has_one :emoji_reactions, if: -> { object.local? && object.emoji_reaction? }
has_many :poll_options, key: :one_of, if: :poll_and_not_multiple? has_many :poll_options, key: :one_of, if: :poll_and_not_multiple?
has_many :poll_options, key: :any_of, if: :poll_and_multiple? has_many :poll_options, key: :any_of, if: :poll_and_multiple?
@ -85,6 +86,10 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
) )
end end
def emoji_reactions
ActivityPub::TagManager.instance.emoji_reactions_uri_for(object)
end
def language? def language?
object.language.present? object.language.present?
end end

View file

@ -71,6 +71,7 @@ Rails.application.routes.draw do
resources :replies, only: [:index], module: :activitypub resources :replies, only: [:index], module: :activitypub
resources :references, only: [:index], module: :activitypub resources :references, only: [:index], module: :activitypub
resources :emoji_reactions, only: [:index], module: :activitypub
end end
resources :followers, only: [:index], controller: :follower_accounts resources :followers, only: [:index], controller: :follower_accounts
@ -183,6 +184,7 @@ Rails.application.routes.draw do
resources :tags, only: [:show] resources :tags, only: [:show]
resources :emojis, only: [:show] resources :emojis, only: [:show]
resources :emoji_reactions, only: [:show]
resources :invites, only: [:index, :create, :destroy] resources :invites, only: [:index, :create, :destroy]
resources :filters, except: [:show] resources :filters, except: [:show]
resource :relationships, only: [:show, :update] resource :relationships, only: [:show, :update]