friends_of_friends_source.rb 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. # frozen_string_literal: true
  2. class AccountSuggestions::FriendsOfFriendsSource < AccountSuggestions::Source
  3. def get(account, limit: DEFAULT_LIMIT)
  4. source_query(account, limit: limit)
  5. .map { |id, _frequency, _followers_count| [id, key] }
  6. end
  7. def source_query(account, limit: DEFAULT_LIMIT)
  8. Account.find_by_sql([<<~SQL.squish, { id: account.id, limit: limit }]).map { |row| [row.id, row.frequency, row.followers_count] }
  9. WITH first_degree AS (
  10. SELECT target_account_id
  11. FROM follows
  12. JOIN accounts AS target_accounts ON follows.target_account_id = target_accounts.id
  13. WHERE account_id = :id
  14. AND NOT target_accounts.hide_collections
  15. )
  16. SELECT accounts.id, COUNT(*) AS frequency, account_stats.followers_count as followers_count
  17. FROM accounts
  18. JOIN follows ON follows.target_account_id = accounts.id
  19. JOIN account_stats ON account_stats.account_id = accounts.id
  20. LEFT OUTER JOIN follow_recommendation_mutes ON follow_recommendation_mutes.target_account_id = accounts.id AND follow_recommendation_mutes.account_id = :id
  21. WHERE follows.account_id IN (SELECT * FROM first_degree)
  22. AND NOT EXISTS (SELECT 1 FROM blocks b WHERE b.target_account_id = follows.target_account_id AND b.account_id = :id)
  23. AND NOT EXISTS (SELECT 1 FROM blocks b WHERE b.target_account_id = :id AND b.account_id = follows.target_account_id)
  24. AND NOT EXISTS (SELECT 1 FROM mutes m WHERE m.target_account_id = follows.target_account_id AND m.account_id = :id)
  25. AND (accounts.domain IS NULL OR NOT EXISTS (SELECT 1 FROM account_domain_blocks b WHERE b.account_id = :id AND b.domain = accounts.domain))
  26. AND NOT EXISTS (SELECT 1 FROM follows f WHERE f.target_account_id = follows.target_account_id AND f.account_id = :id)
  27. AND follows.target_account_id <> :id
  28. AND accounts.discoverable
  29. AND accounts.suspended_at IS NULL
  30. AND accounts.silenced_at IS NULL
  31. AND accounts.moved_to_account_id IS NULL
  32. AND accounts.memorial = FALSE
  33. AND follow_recommendation_mutes.target_account_id IS NULL
  34. GROUP BY accounts.id, account_stats.id
  35. ORDER BY frequency DESC, account_stats.followers_count ASC
  36. LIMIT :limit
  37. SQL
  38. end
  39. private
  40. def key
  41. :friends_of_friends
  42. end
  43. end