Add emoji reactions to note object
This commit is contained in:
parent
cf35497935
commit
b12778caeb
9 changed files with 141 additions and 3 deletions
77
app/controllers/activitypub/emoji_reactions_controller.rb
Normal file
77
app/controllers/activitypub/emoji_reactions_controller.rb
Normal 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
|
21
app/controllers/emoji_reactions_controller.rb
Normal file
21
app/controllers/emoji_reactions_controller.rb
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Reference in a new issue