1 # frozen_string_literal: true
3 class StatusesController
< ApplicationController
4 include SignatureAuthentication
9 DESCENDANTS_DEPTH_LIMIT
= 20
13 before_action
:set_account
14 before_action
:set_status
15 before_action
:set_instance_presenter
16 before_action
:set_link_headers
17 before_action
:check_account_suspension
18 before_action
:redirect_to_original, only
: [:show]
19 before_action
:set_referrer_policy_header, only
: [:show]
20 before_action
:set_cache_headers
23 respond_to
do |format
|
25 @body_classes = 'with-modals'
30 render
'stream_entries/show'
34 skip_session!
unless @stream_entry.hidden
?
36 render_cached_json(['activitypub', 'note', @status], content_type
: 'application/activity+json
', public: !@stream_entry.hidden
?) do
37 ActiveModelSerializers
::SerializableResource.new(@status, serializer
: ActivityPub
::NoteSerializer, adapter
: ActivityPub
::Adapter)
46 render_cached_json(['activitypub', 'activity', @status], content_type
: 'application/activity+json
', public: !@stream_entry.hidden
?) do
47 ActiveModelSerializers
::SerializableResource.new(@status, serializer
: ActivityPub
::ActivitySerializer, adapter
: ActivityPub
::Adapter)
52 raise ActiveRecord
::RecordNotFound if @status.hidden
?
55 expires_in
180, public
: true
56 response
.headers
['X-Frame-Options'] = 'ALLOWALL'
57 @autoplay = ActiveModel
::Type::Boolean.new
.cast(params
[:autoplay])
59 render
'stream_entries/embed', layout
: 'embedded'
64 def create_descendant_thread(depth
, statuses
)
65 if depth
< DESCENDANTS_DEPTH_LIMIT
66 { statuses
: statuses
}
68 next_status
= statuses
.pop
69 { statuses
: statuses
, next_status
: next_status
}
74 @account = Account
.find_local!
(params
[:account_username])
78 @ancestors = @status.reply
? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT
, current_account
), Status
) : []
79 @next_ancestor = @ancestors.size
< ANCESTORS_LIMIT
? nil : @ancestors.shift
83 @max_descendant_thread_id = params
[:max_descendant_thread_id]&.to_i
84 @since_descendant_thread_id = params
[:since_descendant_thread_id]&.to_i
86 descendants
= cache_collection(
90 @max_descendant_thread_id,
91 @since_descendant_thread_id,
92 DESCENDANTS_DEPTH_LIMIT
97 @descendant_threads = []
99 if descendants
.present
?
100 statuses
= [descendants
.first
]
103 descendants
.drop(1).each_with_index
do |descendant
, index
|
104 if descendants
[index
].id
== descendant
.in_reply_to_id
106 statuses
<< descendant
108 @descendant_threads << create_descendant_thread(depth
, statuses
)
110 @descendant_threads.reverse_each
do |descendant_thread
|
111 statuses
= descendant_thread
[:statuses]
113 index
= statuses
.find_index
do |thread_status
|
114 thread_status
.id
== descendant
.in_reply_to_id
118 depth +
= index
- statuses
.size
122 depth
-= statuses
.size
125 statuses
= [descendant
]
129 @descendant_threads << create_descendant_thread(depth
, statuses
)
132 @max_descendant_thread_id = @descendant_threads.pop
[:statuses].first
.id
if descendants
.size
>= DESCENDANTS_LIMIT
136 response
.headers
['Link'] = LinkHeader
.new(
138 [account_stream_entry_url(@account, @status.stream_entry
, format
: 'atom'), [%w(rel alternate
), %w(type application
/atom+xml
)]],
139 [ActivityPub
::TagManager.instance
.uri_for(@status), [%w(rel alternate
), %w(type application
/activity+json
)]],
145 @status = @account.statuses
.find(params
[:id])
146 @stream_entry = @status.stream_entry
147 @type = @stream_entry.activity_type
.downcase
149 authorize
@status, :show?
150 rescue Mastodon
::NotPermittedError
151 # Reraise in order to get a 404
152 raise ActiveRecord
::RecordNotFound
155 def set_instance_presenter
156 @instance_presenter = InstancePresenter
.new
159 def check_account_suspension
160 gone
if @account.suspended
?
163 def redirect_to_original
164 redirect_to
::TagManager.instance
.url_for(@status.reblog
) if @status.reblog
?
167 def set_referrer_policy_header
168 return if @status.public_visibility
? || @status.unlisted_visibility
?
169 response
.headers
['Referrer-Policy'] = 'origin'