From b81aa5757ba300b1aad8ad226c1dd1f5e447ee9a Mon Sep 17 00:00:00 2001
From: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Date: Sun, 25 Oct 2020 20:46:34 -0400
Subject: [PATCH] Temporary fix for streaming error.

---
 .../api/v1/timelines/public_controller.rb     | 49 ++++++++++++++-----
 app/models/status.rb                          |  6 +++
 2 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
index 8529c6a7a3..28ac96304b 100644
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ b/app/controllers/api/v1/timelines/public_controller.rb
@@ -25,24 +25,47 @@ class Api::V1::Timelines::PublicController < Api::BaseController
     cache_collection(public_statuses, Status)
   end
 
+  # TODO: uncomment and fix below code and comment out the two public_* methods below this.
+  # This version is the improved version from fedibird but causes an Invalid token error on streaming when used.
+  # Once this code is uncommented then as_public_timeline can be removed from app/models/status.rb as well.
+  #
+  # def public_statuses
+  #   public_feed.get(
+  #     limit_param(DEFAULT_STATUSES_LIMIT),
+  #     params[:max_id],
+  #     params[:since_id],
+  #     params[:min_id]
+  #   )
+  # end
+
+  # def public_feed
+  #   PublicFeed.new(
+  #     current_account,
+  #     local: truthy_param?(:local),
+  #     remote: truthy_param?(:remote),
+  #     domain: params[:domain],
+  #     only_media: truthy_param?(:only_media),
+  #     application: doorkeeper_token&.application
+  #   )
+  # end
+
   def public_statuses
-    public_feed.get(
+    statuses = public_timeline_statuses.paginate_by_id(
       limit_param(DEFAULT_STATUSES_LIMIT),
-      params[:max_id],
-      params[:since_id],
-      params[:min_id]
+      params_slice(:max_id, :since_id, :min_id)
     )
+
+    if truthy_param?(:only_media)
+      # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids.
+      status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id)
+      statuses.where(id: status_ids)
+    else
+      statuses
+    end
   end
 
-  def public_feed
-    PublicFeed.new(
-      current_account,
-      local: truthy_param?(:local),
-      remote: truthy_param?(:remote),
-      domain: params[:domain],
-      only_media: truthy_param?(:only_media),
-      application: doorkeeper_token&.application
-    )
+  def public_timeline_statuses
+    Status.as_public_timeline(current_account, truthy_param?(:remote) ? :remote : truthy_param?(:local))
   end
 
   def insert_pagination_headers
diff --git a/app/models/status.rb b/app/models/status.rb
index 2e97f3584e..b294b72805 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -359,6 +359,12 @@ class Status < ApplicationRecord
       %w(text/plain text/markdown)
     end
 
+    def as_public_timeline(account = nil, local_only = false)
+      query = timeline_scope(local_only).without_replies
+
+      apply_timeline_filters(query, account, [:local, true].include?(local_only))
+    end
+
     def favourites_map(status_ids, account_id)
       Favourite.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |f, h| h[f.status_id] = true }
     end
-- 
GitLab