statuses_controller.rb 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # frozen_string_literal: true
  2. class Api::V1::StatusesController < Api::BaseController
  3. include Authorization
  4. before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
  5. before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy]
  6. before_action :require_user!, except: [:show, :context]
  7. before_action :set_status, only: [:show, :context]
  8. before_action :set_thread, only: [:create]
  9. override_rate_limit_headers :create, family: :statuses
  10. override_rate_limit_headers :update, family: :statuses
  11. # This API was originally unlimited, pagination cannot be introduced without
  12. # breaking backwards-compatibility. Arbitrarily high number to cover most
  13. # conversations as quasi-unlimited, it would be too much work to render more
  14. # than this anyway
  15. CONTEXT_LIMIT = 4_096
  16. def show
  17. @status = cache_collection([@status], Status).first
  18. render json: @status, serializer: REST::StatusSerializer
  19. end
  20. def context
  21. ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(CONTEXT_LIMIT, current_account)
  22. descendants_results = @status.descendants(CONTEXT_LIMIT, current_account)
  23. loaded_ancestors = cache_collection(ancestors_results, Status)
  24. loaded_descendants = cache_collection(descendants_results, Status)
  25. @context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
  26. statuses = [@status] + @context.ancestors + @context.descendants
  27. render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
  28. end
  29. def create
  30. @status = PostStatusService.new.call(
  31. current_user.account,
  32. text: status_params[:status],
  33. thread: @thread,
  34. media_ids: status_params[:media_ids],
  35. sensitive: status_params[:sensitive],
  36. spoiler_text: status_params[:spoiler_text],
  37. visibility: status_params[:visibility],
  38. language: status_params[:language],
  39. scheduled_at: status_params[:scheduled_at],
  40. application: doorkeeper_token.application,
  41. poll: status_params[:poll],
  42. idempotency: request.headers['Idempotency-Key'],
  43. with_rate_limit: true
  44. )
  45. render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
  46. end
  47. def update
  48. @status = Status.where(account: current_account).find(params[:id])
  49. authorize @status, :update?
  50. UpdateStatusService.new.call(
  51. @status,
  52. current_account.id,
  53. text: status_params[:status],
  54. media_ids: status_params[:media_ids],
  55. sensitive: status_params[:sensitive],
  56. language: status_params[:language],
  57. spoiler_text: status_params[:spoiler_text],
  58. poll: status_params[:poll]
  59. )
  60. render json: @status, serializer: REST::StatusSerializer
  61. end
  62. def destroy
  63. @status = Status.where(account: current_account).find(params[:id])
  64. authorize @status, :destroy?
  65. @status.discard_with_reblogs
  66. StatusPin.find_by(status: @status)&.destroy
  67. @status.account.statuses_count = @status.account.statuses_count - 1
  68. json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true
  69. RemovalWorker.perform_async(@status.id, { 'redraft' => true })
  70. render json: json
  71. end
  72. private
  73. def set_status
  74. @status = Status.find(params[:id])
  75. authorize @status, :show?
  76. rescue Mastodon::NotPermittedError
  77. not_found
  78. end
  79. def set_thread
  80. @thread = Status.find(status_params[:in_reply_to_id]) if status_params[:in_reply_to_id].present?
  81. authorize(@thread, :show?) if @thread.present?
  82. rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
  83. render json: { error: I18n.t('statuses.errors.in_reply_not_found') }, status: 404
  84. end
  85. def status_params
  86. params.permit(
  87. :status,
  88. :in_reply_to_id,
  89. :sensitive,
  90. :spoiler_text,
  91. :visibility,
  92. :language,
  93. :scheduled_at,
  94. media_ids: [],
  95. poll: [
  96. :multiple,
  97. :hide_totals,
  98. :expires_in,
  99. options: [],
  100. ]
  101. )
  102. end
  103. def pagination_params(core_params)
  104. params.slice(:limit).permit(:limit).merge(core_params)
  105. end
  106. end