diff --git a/app/controllers/api/v1/timelines/link_controller.rb b/app/controllers/api/v1/timelines/link_controller.rb new file mode 100644 index 0000000000..b65df23ab2 --- /dev/null +++ b/app/controllers/api/v1/timelines/link_controller.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +class Api::V1::Timelines::LinkController < Api::BaseController + before_action :set_preview_card + before_action :set_statuses + + after_action :insert_pagination_headers, unless: -> { @statuses.empty? } + + def show + cache_if_unauthenticated! + render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) + end + + private + + def set_preview_card + @preview_card = PreviewCard.joins(:trend).merge(PreviewCardTrend.allowed).find_by!(url: params[:url]) + end + + def set_statuses + @statuses = @preview_card.nil? ? [] : cache_collection(link_timeline_statuses, Status) + end + + def link_timeline_statuses + link_feed.get( + limit_param(DEFAULT_STATUSES_LIMIT), + params[:max_id], + params[:since_id], + params[:min_id] + ) + end + + def link_feed + LinkFeed.new(@preview_card, current_account) + end + + def insert_pagination_headers + set_pagination_headers(next_path, prev_path) + end + + def pagination_params(core_params) + params.slice(:local, :limit, :only_media).permit(:local, :limit, :only_media).merge(core_params) + end + + def next_path + api_v1_timelines_link_url params[:id], pagination_params(max_id: pagination_max_id) + end + + def prev_path + api_v1_timelines_link_url params[:id], pagination_params(min_id: pagination_since_id) + end + + def pagination_max_id + @statuses.last.id + end + + def pagination_since_id + @statuses.first.id + end +end diff --git a/app/models/link_feed.rb b/app/models/link_feed.rb new file mode 100644 index 0000000000..78db597b84 --- /dev/null +++ b/app/models/link_feed.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class LinkFeed < PublicFeed + # @param [PreviewCard] preview_card + # @param [Account] account + def initialize(preview_card, account) + @preview_card = preview_card + super(account) + end + + # @param [Integer] limit + # @param [Integer] max_id + # @param [Integer] since_id + # @param [Integer] min_id + # @return [Array] + def get(limit, max_id = nil, since_id = nil, min_id = nil) + scope = public_scope + + scope.merge!(discoverable) + scope.merge!(attached_to_preview_card) + + scope.cache_ids.to_a_paginated_by_id(limit, max_id: max_id, since_id: since_id, min_id: min_id) + end + + private + + def attached_to_preview_card + Status.joins(:preview_cards_statuses).where(preview_cards_statuses: { preview_card_id: @preview_card.id }) + end + + def discoverable + Account.discoverable + end +end diff --git a/config/routes/api.rb b/config/routes/api.rb index 19c583b3e1..068ca87c2c 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -39,6 +39,7 @@ namespace :api, format: false do namespace :timelines do resource :home, only: :show, controller: :home resource :public, only: :show, controller: :public + resource :link, only: :show, controller: :link resources :tag, only: :show resources :list, only: :show end