about summary refs log tree commit diff
path: root/app/controllers/api/v1
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/api/v1')
-rw-r--r--app/controllers/api/v1/accounts/follower_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/following_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/pins_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts_controller.rb6
-rw-r--r--app/controllers/api/v1/admin/accounts_controller.rb5
-rw-r--r--app/controllers/api/v1/admin/canonical_email_blocks_controller.rb95
-rw-r--r--app/controllers/api/v1/admin/domain_allows_controller.rb2
-rw-r--r--app/controllers/api/v1/admin/domain_blocks_controller.rb3
-rw-r--r--app/controllers/api/v1/admin/email_domain_blocks_controller.rb88
-rw-r--r--app/controllers/api/v1/admin/ip_blocks_controller.rb93
-rw-r--r--app/controllers/api/v1/featured_tags_controller.rb6
-rw-r--r--app/controllers/api/v1/filters_controller.rb2
-rw-r--r--app/controllers/api/v1/instances/domain_blocks_controller.rb23
-rw-r--r--app/controllers/api/v1/instances/extended_descriptions_controller.rb18
-rw-r--r--app/controllers/api/v1/instances/privacy_policies_controller.rb18
-rw-r--r--app/controllers/api/v1/instances_controller.rb2
-rw-r--r--app/controllers/api/v1/lists_controller.rb4
-rw-r--r--app/controllers/api/v1/statuses/translations_controller.rb29
-rw-r--r--app/controllers/api/v1/statuses_controller.rb4
-rw-r--r--app/controllers/api/v1/tags_controller.rb2
-rw-r--r--app/controllers/api/v1/trends/links_controller.rb4
-rw-r--r--app/controllers/api/v1/trends/tags_controller.rb2
22 files changed, 391 insertions, 21 deletions
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index dbb8cac5e..208e06ed6 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
-  before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
+  before_action -> { authorize_if_got_token! :read, :'read:accounts' }
   before_action :set_account
   after_action :insert_pagination_headers
 
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index 8c650570f..155ca0907 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
-  before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
+  before_action -> { authorize_if_got_token! :read, :'read:accounts' }
   before_action :set_account
   after_action :insert_pagination_headers
 
diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb
index 3915b5669..73f845c61 100644
--- a/app/controllers/api/v1/accounts/pins_controller.rb
+++ b/app/controllers/api/v1/accounts/pins_controller.rb
@@ -8,7 +8,7 @@ class Api::V1::Accounts::PinsController < Api::BaseController
   before_action :set_account
 
   def create
-    AccountPin.create!(account: current_account, target_account: @account)
+    AccountPin.find_or_create_by!(account: current_account, target_account: @account)
     render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
   end
 
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index 5537cc9b0..be84720aa 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -30,12 +30,12 @@ class Api::V1::AccountsController < Api::BaseController
     self.response_body = Oj.dump(response.body)
     self.status        = response.status
   rescue ActiveRecord::RecordInvalid => e
-    render json: ValidationErrorFormatter.new(e, :'account.username' => :username, :'invite_request.text' => :reason).as_json, status: :unprocessable_entity
+    render json: ValidationErrorFormatter.new(e, 'account.username': :username, 'invite_request.text': :reason).as_json, status: :unprocessable_entity
   end
 
   def follow
-    follow  = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, with_rate_limit: true)
-    options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify? } }, requested_map: { @account.id => false } }
+    follow  = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, languages: params.key?(:languages) ? params[:languages] : nil, with_rate_limit: true)
+    options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify?, languages: follow.languages } }, requested_map: { @account.id => false } }
 
     render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(**options)
   end
diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb
index 0dee02e94..ae7f7d076 100644
--- a/app/controllers/api/v1/admin/accounts_controller.rb
+++ b/app/controllers/api/v1/admin/accounts_controller.rb
@@ -60,14 +60,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController
   def reject
     authorize @account.user, :reject?
     DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
-    render json: @account, serializer: REST::Admin::AccountSerializer
+    render_empty
   end
 
   def destroy
     authorize @account, :destroy?
-    json = render_to_body json: @account, serializer: REST::Admin::AccountSerializer
     Admin::AccountDeletionWorker.perform_async(@account.id)
-    render json: json
+    render_empty
   end
 
   def unsensitive
diff --git a/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb b/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb
new file mode 100644
index 000000000..9ef1b3be7
--- /dev/null
+++ b/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
+  include Authorization
+  include AccountableConcern
+
+  LIMIT = 100
+
+  before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:canonical_email_blocks' }, only: [:index, :show, :test]
+  before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:canonical_email_blocks' }, except: [:index, :show, :test]
+
+  before_action :set_canonical_email_blocks, only: :index
+  before_action :set_canonical_email_blocks_from_test, only: [:test]
+  before_action :set_canonical_email_block, only: [:show, :destroy]
+
+  after_action :verify_authorized
+  after_action :insert_pagination_headers, only: :index
+
+  PAGINATION_PARAMS = %i(limit).freeze
+
+  def index
+    authorize :canonical_email_block, :index?
+    render json: @canonical_email_blocks, each_serializer: REST::Admin::CanonicalEmailBlockSerializer
+  end
+
+  def show
+    authorize @canonical_email_block, :show?
+    render json: @canonical_email_block, serializer: REST::Admin::CanonicalEmailBlockSerializer
+  end
+
+  def test
+    authorize :canonical_email_block, :test?
+    render json: @canonical_email_blocks, each_serializer: REST::Admin::CanonicalEmailBlockSerializer
+  end
+
+  def create
+    authorize :canonical_email_block, :create?
+    @canonical_email_block = CanonicalEmailBlock.create!(resource_params)
+    log_action :create, @canonical_email_block
+    render json: @canonical_email_block, serializer: REST::Admin::CanonicalEmailBlockSerializer
+  end
+
+  def destroy
+    authorize @canonical_email_block, :destroy?
+    @canonical_email_block.destroy!
+    log_action :destroy, @canonical_email_block
+    render_empty
+  end
+
+  private
+
+  def resource_params
+    params.permit(:canonical_email_hash, :email)
+  end
+
+  def set_canonical_email_blocks
+    @canonical_email_blocks = CanonicalEmailBlock.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+  end
+
+  def set_canonical_email_blocks_from_test
+    @canonical_email_blocks = CanonicalEmailBlock.matching_email(params[:email])
+  end
+
+  def set_canonical_email_block
+    @canonical_email_block = CanonicalEmailBlock.find(params[:id])
+  end
+
+  def insert_pagination_headers
+    set_pagination_headers(next_path, prev_path)
+  end
+
+  def next_path
+    api_v1_admin_canonical_email_blocks_url(pagination_params(max_id: pagination_max_id)) if records_continue?
+  end
+
+  def prev_path
+    api_v1_admin_canonical_email_blocks_url(pagination_params(min_id: pagination_since_id)) unless @canonical_email_blocks.empty?
+  end
+
+  def pagination_max_id
+    @canonical_email_blocks.last.id
+  end
+
+  def pagination_since_id
+    @canonical_email_blocks.first.id
+  end
+
+  def records_continue?
+    @canonical_email_blocks.size == limit_param(LIMIT)
+  end
+
+  def pagination_params(core_params)
+    params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
+  end
+end
diff --git a/app/controllers/api/v1/admin/domain_allows_controller.rb b/app/controllers/api/v1/admin/domain_allows_controller.rb
index 59aa807d6..0658199f0 100644
--- a/app/controllers/api/v1/admin/domain_allows_controller.rb
+++ b/app/controllers/api/v1/admin/domain_allows_controller.rb
@@ -43,7 +43,7 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
     authorize @domain_allow, :destroy?
     UnallowDomainService.new.call(@domain_allow)
     log_action :destroy, @domain_allow
-    render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer
+    render_empty
   end
 
   private
diff --git a/app/controllers/api/v1/admin/domain_blocks_controller.rb b/app/controllers/api/v1/admin/domain_blocks_controller.rb
index de8fd9d08..df5b1b3fc 100644
--- a/app/controllers/api/v1/admin/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/admin/domain_blocks_controller.rb
@@ -40,7 +40,6 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
 
   def update
     authorize @domain_block, :update?
-
     @domain_block.update(domain_block_params)
     severity_changed = @domain_block.severity_changed?
     @domain_block.save!
@@ -53,7 +52,7 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
     authorize @domain_block, :destroy?
     UnblockDomainService.new.call(@domain_block)
     log_action :destroy, @domain_block
-    render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
+    render_empty
   end
 
   private
diff --git a/app/controllers/api/v1/admin/email_domain_blocks_controller.rb b/app/controllers/api/v1/admin/email_domain_blocks_controller.rb
new file mode 100644
index 000000000..e53d0b157
--- /dev/null
+++ b/app/controllers/api/v1/admin/email_domain_blocks_controller.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
+  include Authorization
+  include AccountableConcern
+
+  LIMIT = 100
+
+  before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:email_domain_blocks' }, only: [:index, :show]
+  before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:email_domain_blocks' }, except: [:index, :show]
+  before_action :set_email_domain_blocks, only: :index
+  before_action :set_email_domain_block, only: [:show, :destroy]
+
+  after_action :verify_authorized
+  after_action :insert_pagination_headers, only: :index
+
+  PAGINATION_PARAMS = %i(
+    limit
+  ).freeze
+
+  def create
+    authorize :email_domain_block, :create?
+
+    @email_domain_block = EmailDomainBlock.create!(resource_params)
+    log_action :create, @email_domain_block
+
+    render json: @email_domain_block, serializer: REST::Admin::EmailDomainBlockSerializer
+  end
+
+  def index
+    authorize :email_domain_block, :index?
+    render json: @email_domain_blocks, each_serializer: REST::Admin::EmailDomainBlockSerializer
+  end
+
+  def show
+    authorize @email_domain_block, :show?
+    render json: @email_domain_block, serializer: REST::Admin::EmailDomainBlockSerializer
+  end
+
+  def destroy
+    authorize @email_domain_block, :destroy?
+    @email_domain_block.destroy!
+    log_action :destroy, @email_domain_block
+    render_empty
+  end
+
+  private
+
+  def set_email_domain_blocks
+    @email_domain_blocks = EmailDomainBlock.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+  end
+
+  def set_email_domain_block
+    @email_domain_block = EmailDomainBlock.find(params[:id])
+  end
+
+  def resource_params
+    params.permit(:domain)
+  end
+
+  def insert_pagination_headers
+    set_pagination_headers(next_path, prev_path)
+  end
+
+  def next_path
+    api_v1_admin_email_domain_blocks_url(pagination_params(max_id: pagination_max_id)) if records_continue?
+  end
+
+  def prev_path
+    api_v1_admin_email_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @email_domain_blocks.empty?
+  end
+
+  def pagination_max_id
+    @email_domain_blocks.last.id
+  end
+
+  def pagination_since_id
+    @email_domain_blocks.first.id
+  end
+
+  def records_continue?
+    @email_domain_blocks.size == limit_param(LIMIT)
+  end
+
+  def pagination_params(core_params)
+    params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
+  end
+end
diff --git a/app/controllers/api/v1/admin/ip_blocks_controller.rb b/app/controllers/api/v1/admin/ip_blocks_controller.rb
new file mode 100644
index 000000000..201ab6b1f
--- /dev/null
+++ b/app/controllers/api/v1/admin/ip_blocks_controller.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+class Api::V1::Admin::IpBlocksController < Api::BaseController
+  include Authorization
+  include AccountableConcern
+
+  LIMIT = 100
+
+  before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:ip_blocks' }, only: [:index, :show]
+  before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:ip_blocks' }, except: [:index, :show]
+  before_action :set_ip_blocks, only: :index
+  before_action :set_ip_block, only: [:show, :update, :destroy]
+
+  after_action :verify_authorized
+  after_action :insert_pagination_headers, only: :index
+
+  PAGINATION_PARAMS = %i(
+    limit
+  ).freeze
+
+  def create
+    authorize :ip_block, :create?
+    @ip_block = IpBlock.create!(resource_params)
+    log_action :create, @ip_block
+    render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
+  end
+
+  def index
+    authorize :ip_block, :index?
+    render json: @ip_blocks, each_serializer: REST::Admin::IpBlockSerializer
+  end
+
+  def show
+    authorize @ip_block, :show?
+    render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
+  end
+
+  def update
+    authorize @ip_block, :update?
+    @ip_block.update(resource_params)
+    log_action :update, @ip_block
+    render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
+  end
+
+  def destroy
+    authorize @ip_block, :destroy?
+    @ip_block.destroy!
+    log_action :destroy, @ip_block
+    render_empty
+  end
+
+  private
+
+  def set_ip_blocks
+    @ip_blocks = IpBlock.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+  end
+
+  def set_ip_block
+    @ip_block = IpBlock.find(params[:id])
+  end
+
+  def resource_params
+    params.permit(:ip, :severity, :comment, :expires_in)
+  end
+
+  def insert_pagination_headers
+    set_pagination_headers(next_path, prev_path)
+  end
+
+  def next_path
+    api_v1_admin_ip_blocks_url(pagination_params(max_id: pagination_max_id)) if records_continue?
+  end
+
+  def prev_path
+    api_v1_admin_ip_blocks_url(pagination_params(min_id: pagination_since_id)) unless @ip_blocks.empty?
+  end
+
+  def pagination_max_id
+    @ip_blocks.last.id
+  end
+
+  def pagination_since_id
+    @ip_blocks.first.id
+  end
+
+  def records_continue?
+    @ip_blocks.size == limit_param(LIMIT)
+  end
+
+  def pagination_params(core_params)
+    params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
+  end
+end
diff --git a/app/controllers/api/v1/featured_tags_controller.rb b/app/controllers/api/v1/featured_tags_controller.rb
index c1ead4f54..edb42a94e 100644
--- a/app/controllers/api/v1/featured_tags_controller.rb
+++ b/app/controllers/api/v1/featured_tags_controller.rb
@@ -13,12 +13,12 @@ class Api::V1::FeaturedTagsController < Api::BaseController
   end
 
   def create
-    @featured_tag = current_account.featured_tags.create!(featured_tag_params)
-    render json: @featured_tag, serializer: REST::FeaturedTagSerializer
+    featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name])
+    render json: featured_tag, serializer: REST::FeaturedTagSerializer
   end
 
   def destroy
-    @featured_tag.destroy!
+    RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
     render_empty
   end
 
diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb
index 07cd14147..149139b40 100644
--- a/app/controllers/api/v1/filters_controller.rb
+++ b/app/controllers/api/v1/filters_controller.rb
@@ -52,7 +52,7 @@ class Api::V1::FiltersController < Api::BaseController
   end
 
   def resource_params
-    params.permit(:phrase, :expires_in, :irreversible, :whole_word, context: [])
+    params.permit(:phrase, :expires_in, :irreversible, context: [])
   end
 
   def filter_params
diff --git a/app/controllers/api/v1/instances/domain_blocks_controller.rb b/app/controllers/api/v1/instances/domain_blocks_controller.rb
new file mode 100644
index 000000000..37a6906fb
--- /dev/null
+++ b/app/controllers/api/v1/instances/domain_blocks_controller.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class Api::V1::Instances::DomainBlocksController < Api::BaseController
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+
+  before_action :require_enabled_api!
+  before_action :set_domain_blocks
+
+  def index
+    expires_in 3.minutes, public: true
+    render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?))
+  end
+
+  private
+
+  def require_enabled_api!
+    head 404 unless Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?)
+  end
+
+  def set_domain_blocks
+    @domain_blocks = DomainBlock.with_user_facing_limitations.by_severity
+  end
+end
diff --git a/app/controllers/api/v1/instances/extended_descriptions_controller.rb b/app/controllers/api/v1/instances/extended_descriptions_controller.rb
new file mode 100644
index 000000000..c72e16cff
--- /dev/null
+++ b/app/controllers/api/v1/instances/extended_descriptions_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+
+  before_action :set_extended_description
+
+  def show
+    expires_in 3.minutes, public: true
+    render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer
+  end
+
+  private
+
+  def set_extended_description
+    @extended_description = ExtendedDescription.current
+  end
+end
diff --git a/app/controllers/api/v1/instances/privacy_policies_controller.rb b/app/controllers/api/v1/instances/privacy_policies_controller.rb
new file mode 100644
index 000000000..dbd69f54d
--- /dev/null
+++ b/app/controllers/api/v1/instances/privacy_policies_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+
+  before_action :set_privacy_policy
+
+  def show
+    expires_in 1.day, public: true
+    render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer
+  end
+
+  private
+
+  def set_privacy_policy
+    @privacy_policy = PrivacyPolicy.current
+  end
+end
diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb
index 5b5058a7b..913319a86 100644
--- a/app/controllers/api/v1/instances_controller.rb
+++ b/app/controllers/api/v1/instances_controller.rb
@@ -6,6 +6,6 @@ class Api::V1::InstancesController < Api::BaseController
 
   def show
     expires_in 3.minutes, public: true
-    render_with_cache json: {}, serializer: REST::InstanceSerializer, root: 'instance'
+    render_with_cache json: InstancePresenter.new, serializer: REST::V1::InstanceSerializer, root: 'instance'
   end
 end
diff --git a/app/controllers/api/v1/lists_controller.rb b/app/controllers/api/v1/lists_controller.rb
index e5ac45fef..843ca2ec2 100644
--- a/app/controllers/api/v1/lists_controller.rb
+++ b/app/controllers/api/v1/lists_controller.rb
@@ -7,6 +7,10 @@ class Api::V1::ListsController < Api::BaseController
   before_action :require_user!
   before_action :set_list, except: [:index, :create]
 
+  rescue_from ArgumentError do |e|
+    render json: { error: e.to_s }, status: 422
+  end
+
   def index
     @lists = List.where(account: current_account).all
     render json: @lists, each_serializer: REST::ListSerializer
diff --git a/app/controllers/api/v1/statuses/translations_controller.rb b/app/controllers/api/v1/statuses/translations_controller.rb
new file mode 100644
index 000000000..540b17d00
--- /dev/null
+++ b/app/controllers/api/v1/statuses/translations_controller.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class Api::V1::Statuses::TranslationsController < Api::BaseController
+  include Authorization
+
+  before_action -> { doorkeeper_authorize! :read, :'read:statuses' }
+  before_action :set_status
+  before_action :set_translation
+
+  rescue_from TranslationService::NotConfiguredError, with: :not_found
+  rescue_from TranslationService::UnexpectedResponseError, TranslationService::QuotaExceededError, TranslationService::TooManyRequestsError, with: :service_unavailable
+
+  def create
+    render json: @translation, serializer: REST::TranslationSerializer
+  end
+
+  private
+
+  def set_status
+    @status = Status.find(params[:status_id])
+    authorize @status, :show?
+  rescue Mastodon::NotPermittedError
+    not_found
+  end
+
+  def set_translation
+    @translation = TranslateStatusService.new.call(@status, content_locale)
+  end
+end
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index b2cee3e92..26ef7087a 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -66,6 +66,7 @@ class Api::V1::StatusesController < Api::BaseController
       text: status_params[:status],
       media_ids: status_params[:media_ids],
       sensitive: status_params[:sensitive],
+      language: status_params[:language],
       spoiler_text: status_params[:spoiler_text],
       poll: status_params[:poll],
       content_type: status_params[:content_type]
@@ -78,7 +79,8 @@ class Api::V1::StatusesController < Api::BaseController
     @status = Status.where(account: current_account).find(params[:id])
     authorize @status, :destroy?
 
-    @status.discard
+    @status.discard_with_reblogs
+    StatusPin.find_by(status: @status)&.destroy
     @status.account.statuses_count = @status.account.statuses_count - 1
     json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true
 
diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb
index 9e5c53330..32f71bdce 100644
--- a/app/controllers/api/v1/tags_controller.rb
+++ b/app/controllers/api/v1/tags_controller.rb
@@ -24,7 +24,7 @@ class Api::V1::TagsController < Api::BaseController
   private
 
   def set_or_create_tag
-    return not_found unless /\A(#{Tag::HASHTAG_NAME_RE})\z/.match?(params[:id])
+    return not_found unless Tag::HASHTAG_NAME_RE.match?(params[:id])
     @tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id])
   end
 end
diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb
index 1a9f918f2..8ff3b364e 100644
--- a/app/controllers/api/v1/trends/links_controller.rb
+++ b/app/controllers/api/v1/trends/links_controller.rb
@@ -28,7 +28,9 @@ class Api::V1::Trends::LinksController < Api::BaseController
   end
 
   def links_from_trends
-    Trends.links.query.allowed.in_locale(content_locale)
+    scope = Trends.links.query.allowed.in_locale(content_locale)
+    scope = scope.filtered_for(current_account) if user_signed_in?
+    scope
   end
 
   def insert_pagination_headers
diff --git a/app/controllers/api/v1/trends/tags_controller.rb b/app/controllers/api/v1/trends/tags_controller.rb
index 21adfa2a1..885a4ad7e 100644
--- a/app/controllers/api/v1/trends/tags_controller.rb
+++ b/app/controllers/api/v1/trends/tags_controller.rb
@@ -5,7 +5,7 @@ class Api::V1::Trends::TagsController < Api::BaseController
 
   after_action :insert_pagination_headers
 
-  DEFAULT_TAGS_LIMIT = 10
+  DEFAULT_TAGS_LIMIT = (ENV['MAX_TRENDING_TAGS'] || 10).to_i
 
   def index
     render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id)