From a4c6b5639dbe5f209ece75c0a6f04e38ba8ae433 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Fri, 7 Aug 2020 17:26:14 -0500 Subject: [PATCH] Updated sorting in groups controllers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Updated: - sorting in groups controllers --- .../timelines/group_collection_controller.rb | 65 +++++++--- .../api/v1/timelines/group_controller.rb | 119 +++++++++++++++--- 2 files changed, 150 insertions(+), 34 deletions(-) diff --git a/app/controllers/api/v1/timelines/group_collection_controller.rb b/app/controllers/api/v1/timelines/group_collection_controller.rb index ead367cf..2c334275 100644 --- a/app/controllers/api/v1/timelines/group_collection_controller.rb +++ b/app/controllers/api/v1/timelines/group_collection_controller.rb @@ -28,6 +28,8 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController return @collection_type end + private + def set_sort_type @sort_type = 'newest' @sort_type = params[:sort_by] if [ @@ -39,12 +41,14 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController 'top_yearly', 'top_all_time', ].include? params[:sort_by] + + if @collection_type === 'featured' && (@sort_type == 'newest' || @sort_type == 'recent') + @sort_type = 'top_today' + end return @sort_type end - private - def set_statuses @statuses = cached_group_collection_statuses end @@ -59,8 +63,10 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController @groupIds = [] if @collection_type == 'featured' @groupIds = Group.where(is_featured: true, is_archived: false).limit(100).all.pluck(:id) - elsif @collection_type == 'member' + elsif @collection_type == 'member' && !current_user.nil? @groupIds = current_user.account.groups.pluck(:id) + else + return [] end date_limit = 30.days.ago @@ -80,8 +86,10 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController if @sort_type == 'newest' statuses = Status.where( group: @groupIds, reply: false - ).paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id)) - .reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } + ).paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } elsif @sort_type == 'recent' statuses = Status.where( group: @groupIds, reply: false @@ -112,21 +120,42 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController end end else - statuses = Status.as_group_collection_timeline(@groupIds).paginate_by_id( - limit_param(DEFAULT_STATUSES_LIMIT), - params_slice(:max_id, :since_id, :min_id) - ) + if @sort_type == 'newest' + statuses = Status.where( + group: @groupIds, reply: false + ).paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id)) + elsif @sort_type == 'recent' + statuses = Status.where( + group: @groupIds, reply: false + ).joins(:status_stat).where( + 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0' + ).order('status_stats.updated_at DESC').paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time'].include? @sort_type + if @sort_type == 'top_all_time' + statuses = Status.unscoped.where( + group: @groupIds, reply: false + ).joins(:status_stat).order(top_order) + .paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + else + statuses = Status.unscoped.where( + group: @groupIds, reply: false + ).where( + 'statuses.created_at > ?', date_limit + ).joins(:status_stat).order(top_order).paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + end + end end - # statuses = query - - # if truthy_param?(:only_media) && current_account - # # `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 + statuses end def insert_pagination_headers diff --git a/app/controllers/api/v1/timelines/group_controller.rb b/app/controllers/api/v1/timelines/group_controller.rb index 3ff0e11c..5a4310d6 100644 --- a/app/controllers/api/v1/timelines/group_controller.rb +++ b/app/controllers/api/v1/timelines/group_controller.rb @@ -2,6 +2,7 @@ class Api::V1::Timelines::GroupController < Api::BaseController before_action :set_group + before_action :set_sort_type before_action :set_statuses after_action :insert_pagination_headers, unless: -> { @statuses.empty? } @@ -18,6 +19,21 @@ class Api::V1::Timelines::GroupController < Api::BaseController private + def set_sort_type + @sort_type = 'newest' + @sort_type = params[:sort_by] if [ + 'newest', + 'recent', + 'top_today', + 'top_weekly', + 'top_monthly', + 'top_yearly', + 'top_all_time', + ].include? params[:sort_by] + + return @sort_type + end + def set_group @group = Group.where(id: params[:id], is_archived: false).first end @@ -32,26 +48,97 @@ class Api::V1::Timelines::GroupController < Api::BaseController def group_statuses statuses = nil + + date_limit = 30.days.ago + top_order = 'status_stats.favourites_count DESC, status_stats.reblogs_count DESC, status_stats.replies_count DESC' + + if @sort_type == 'top_today' + date_limit = 24.hours.ago + elsif @sort_type == 'top_weekly' + date_limit = 7.days.ago + elsif @sort_type == 'top_monthly' + date_limit = 30.days.ago + elsif @sort_type == 'top_yearly' + date_limit = 1.year.ago + end + if current_account - statuses = group_timeline_statuses.paginate_by_id( - limit_param(DEFAULT_STATUSES_LIMIT), - params_slice(:max_id, :since_id, :min_id) - ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } + if @sort_type == 'newest' + statuses = Status.where( + group: @group, reply: false + ).paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } + elsif @sort_type == 'recent' + statuses = Status.where( + group: @group, reply: false + ).joins(:status_stat).where( + 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0' + ).order('status_stats.updated_at DESC').paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } + elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time'].include? @sort_type + if @sort_type == 'top_all_time' + statuses = Status.unscoped.where( + group: @group, reply: false + ).joins(:status_stat).order(top_order) + .paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } + else + statuses = Status.unscoped.where( + group: @group, reply: false + ).where( + 'statuses.created_at > ?', date_limit + ).joins(:status_stat).order(top_order).paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) } + end + end else - statuses = group_timeline_statuses.limit(DEFAULT_STATUSES_LIMIT) + if @sort_type == 'newest' + statuses = Status.where( + group: @group, reply: false + ).paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + elsif @sort_type == 'recent' + statuses = Status.where( + group: @group, reply: false + ).joins(:status_stat).where( + 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0' + ).order('status_stats.updated_at DESC').paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time'].include? @sort_type + if @sort_type == 'top_all_time' + statuses = Status.unscoped.where( + group: @group, reply: false + ).joins(:status_stat).order(top_order) + .paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + else + statuses = Status.unscoped.where( + group: @group, reply: false + ).where( + 'statuses.created_at > ?', date_limit + ).joins(:status_stat).order(top_order).paginate_by_id( + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + end + end end - if truthy_param?(:only_media) && current_account - # `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 group_timeline_statuses - Status.as_group_timeline(@group) + statuses end def insert_pagination_headers