]> cat aescling's git repositories - mastodon.git/blob - app/controllers/accounts_controller.rb
Merge branch 'main' into glitch-soc/merge-upstream
[mastodon.git] / app / controllers / accounts_controller.rb
1 # frozen_string_literal: true
2
3 class AccountsController < ApplicationController
4 PAGE_SIZE = 20
5 PAGE_SIZE_MAX = 200
6
7 include AccountControllerConcern
8 include SignatureAuthentication
9
10 before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
11 before_action :set_cache_headers
12 before_action :set_body_classes
13
14 skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
15 skip_before_action :require_functional!, unless: :whitelist_mode?
16
17 def show
18 respond_to do |format|
19 format.html do
20 use_pack 'public'
21 expires_in 0, public: true unless user_signed_in?
22
23 @pinned_statuses = []
24 @endorsed_accounts = @account.endorsed_accounts.to_a.sample(4)
25 @featured_hashtags = @account.featured_tags.order(statuses_count: :desc)
26
27 if current_account && @account.blocking?(current_account)
28 @statuses = []
29 return
30 end
31
32 @pinned_statuses = cached_filtered_status_pins if show_pinned_statuses?
33 @statuses = cached_filtered_status_page
34 @rss_url = rss_url
35
36 unless @statuses.empty?
37 @older_url = older_url if @statuses.last.id > filtered_statuses.last.id
38 @newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
39 end
40 end
41
42 format.rss do
43 expires_in 1.minute, public: true
44
45 limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE
46 @statuses = filtered_statuses.without_reblogs.limit(limit)
47 @statuses = cache_collection(@statuses, Status)
48 render xml: RSS::AccountSerializer.render(@account, @statuses, params[:tag])
49 end
50
51 format.json do
52 expires_in 3.minutes, public: !(authorized_fetch_mode? && signed_request_account.present?)
53 render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter
54 end
55 end
56 end
57
58 private
59
60 def set_body_classes
61 @body_classes = 'with-modals'
62 end
63
64 def show_pinned_statuses?
65 [replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
66 end
67
68 def filtered_pinned_statuses
69 @account.pinned_statuses.not_local_only.where(visibility: [:public, :unlisted])
70 end
71
72 def filtered_statuses
73 default_statuses.tap do |statuses|
74 statuses.merge!(hashtag_scope) if tag_requested?
75 statuses.merge!(only_media_scope) if media_requested?
76 statuses.merge!(no_replies_scope) unless replies_requested?
77 end
78 end
79
80 def default_statuses
81 @account.statuses.not_local_only.where(visibility: [:public, :unlisted])
82 end
83
84 def only_media_scope
85 Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id)
86 end
87
88 def no_replies_scope
89 Status.without_replies
90 end
91
92 def hashtag_scope
93 tag = Tag.find_normalized(params[:tag])
94
95 if tag
96 Status.tagged_with(tag.id)
97 else
98 Status.none
99 end
100 end
101
102 def username_param
103 params[:username]
104 end
105
106 def skip_temporary_suspension_response?
107 request.format == :json
108 end
109
110 def rss_url
111 if tag_requested?
112 short_account_tag_url(@account, params[:tag], format: 'rss')
113 else
114 short_account_url(@account, format: 'rss')
115 end
116 end
117
118 def older_url
119 pagination_url(max_id: @statuses.last.id)
120 end
121
122 def newer_url
123 pagination_url(min_id: @statuses.first.id)
124 end
125
126 def pagination_url(max_id: nil, min_id: nil)
127 if tag_requested?
128 short_account_tag_url(@account, params[:tag], max_id: max_id, min_id: min_id)
129 elsif media_requested?
130 short_account_media_url(@account, max_id: max_id, min_id: min_id)
131 elsif replies_requested?
132 short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
133 else
134 short_account_url(@account, max_id: max_id, min_id: min_id)
135 end
136 end
137
138 def media_requested?
139 request.path.split('.').first.end_with?('/media') && !tag_requested?
140 end
141
142 def replies_requested?
143 request.path.split('.').first.end_with?('/with_replies') && !tag_requested?
144 end
145
146 def tag_requested?
147 request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
148 end
149
150 def cached_filtered_status_pins
151 cache_collection(
152 filtered_pinned_statuses,
153 Status
154 )
155 end
156
157 def cached_filtered_status_page
158 cache_collection_paginated_by_id(
159 filtered_statuses,
160 Status,
161 PAGE_SIZE,
162 params_slice(:max_id, :min_id, :since_id)
163 )
164 end
165
166 def params_slice(*keys)
167 params.slice(*keys).permit(*keys)
168 end
169 end
This page took 0.112162 seconds and 5 git commands to generate.