account_statuses_filter.rb 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # frozen_string_literal: true
  2. class AccountStatusesFilter
  3. KEYS = %i(
  4. pinned
  5. tagged
  6. only_media
  7. exclude_replies
  8. exclude_reblogs
  9. ).freeze
  10. attr_reader :params, :account, :current_account
  11. def initialize(account, current_account, params = {})
  12. @account = account
  13. @current_account = current_account
  14. @params = params
  15. end
  16. def results
  17. scope = initial_scope
  18. scope.merge!(pinned_scope) if pinned?
  19. scope.merge!(only_media_scope) if only_media?
  20. scope.merge!(no_replies_scope) if exclude_replies?
  21. scope.merge!(no_reblogs_scope) if exclude_reblogs?
  22. scope.merge!(hashtag_scope) if tagged?
  23. scope
  24. end
  25. private
  26. def initial_scope
  27. if suspended?
  28. Status.none
  29. elsif anonymous?
  30. account.statuses.where(visibility: %i(public unlisted))
  31. elsif author?
  32. account.statuses.all # NOTE: #merge! does not work without the #all
  33. elsif blocked?
  34. Status.none
  35. else
  36. filtered_scope
  37. end
  38. end
  39. def filtered_scope
  40. scope = account.statuses.left_outer_joins(:mentions)
  41. scope.merge!(scope.where(visibility: follower? ? %i(public unlisted private) : %i(public unlisted)).or(scope.where(mentions: { account_id: current_account.id })).group(Status.arel_table[:id]))
  42. scope.merge!(filtered_reblogs_scope) if reblogs_may_occur?
  43. scope
  44. end
  45. def filtered_reblogs_scope
  46. Status.left_outer_joins(:reblog).where(reblog_of_id: nil).or(Status.where.not(reblogs_statuses: { account_id: current_account.excluded_from_timeline_account_ids }))
  47. end
  48. def only_media_scope
  49. Status.joins(:media_attachments).merge(account.media_attachments.reorder(nil)).group(Status.arel_table[:id])
  50. end
  51. def no_replies_scope
  52. Status.without_replies
  53. end
  54. def no_reblogs_scope
  55. Status.without_reblogs
  56. end
  57. def pinned_scope
  58. account.pinned_statuses.group(Status.arel_table[:id], StatusPin.arel_table[:created_at])
  59. end
  60. def hashtag_scope
  61. tag = Tag.find_normalized(params[:tagged])
  62. if tag
  63. Status.tagged_with(tag.id)
  64. else
  65. Status.none
  66. end
  67. end
  68. def suspended?
  69. account.suspended?
  70. end
  71. def anonymous?
  72. current_account.nil?
  73. end
  74. def author?
  75. current_account.id == account.id
  76. end
  77. def blocked?
  78. account.blocking?(current_account) || (current_account.domain.present? && account.domain_blocking?(current_account.domain))
  79. end
  80. def follower?
  81. current_account.following?(account)
  82. end
  83. def reblogs_may_occur?
  84. !exclude_reblogs? && !only_media? && !tagged?
  85. end
  86. def pinned?
  87. truthy_param?(:pinned)
  88. end
  89. def only_media?
  90. truthy_param?(:only_media)
  91. end
  92. def exclude_replies?
  93. truthy_param?(:exclude_replies)
  94. end
  95. def exclude_reblogs?
  96. truthy_param?(:exclude_reblogs)
  97. end
  98. def tagged?
  99. params[:tagged].present?
  100. end
  101. def truthy_param?(key)
  102. ActiveModel::Type::Boolean.new.cast(params[key])
  103. end
  104. end