search_service.rb 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # frozen_string_literal: true
  2. class SearchService < BaseService
  3. QUOTE_EQUIVALENT_CHARACTERS = /[“”„«»「」『』《》]/
  4. def call(query, account, limit, options = {})
  5. @query = query&.strip&.gsub(QUOTE_EQUIVALENT_CHARACTERS, '"')
  6. @account = account
  7. @options = options
  8. @limit = limit.to_i
  9. @offset = options[:type].blank? ? 0 : options[:offset].to_i
  10. @resolve = options[:resolve] || false
  11. @following = options[:following] || false
  12. default_results.tap do |results|
  13. next if @query.blank? || @limit.zero?
  14. if url_query?
  15. results.merge!(url_resource_results) unless url_resource.nil? || @offset.positive? || (@options[:type].present? && url_resource_symbol != @options[:type].to_sym)
  16. elsif @query.present?
  17. results[:accounts] = perform_accounts_search! if account_searchable?
  18. results[:statuses] = perform_statuses_search! if status_searchable?
  19. results[:hashtags] = perform_hashtags_search! if hashtag_searchable?
  20. end
  21. end
  22. end
  23. private
  24. def perform_accounts_search!
  25. AccountSearchService.new.call(
  26. @query,
  27. @account,
  28. limit: @limit,
  29. resolve: @resolve,
  30. offset: @offset,
  31. use_searchable_text: true,
  32. following: @following,
  33. start_with_hashtag: @query.start_with?('#')
  34. )
  35. end
  36. def perform_statuses_search!
  37. StatusesSearchService.new.call(
  38. @query,
  39. @account,
  40. limit: @limit,
  41. offset: @offset,
  42. account_id: @options[:account_id],
  43. min_id: @options[:min_id],
  44. max_id: @options[:max_id]
  45. )
  46. end
  47. def perform_hashtags_search!
  48. TagSearchService.new.call(
  49. @query,
  50. limit: @limit,
  51. offset: @offset,
  52. exclude_unreviewed: @options[:exclude_unreviewed]
  53. )
  54. end
  55. def default_results
  56. { accounts: [], hashtags: [], statuses: [] }
  57. end
  58. def url_query?
  59. @resolve && %r{\Ahttps?://}.match?(@query)
  60. end
  61. def url_resource_results
  62. { url_resource_symbol => [url_resource] }
  63. end
  64. def url_resource
  65. @url_resource ||= ResolveURLService.new.call(@query, on_behalf_of: @account)
  66. end
  67. def url_resource_symbol
  68. url_resource.class.name.downcase.pluralize.to_sym
  69. end
  70. def status_searchable?
  71. Chewy.enabled? && status_search? && @account.present?
  72. end
  73. def account_searchable?
  74. account_search?
  75. end
  76. def hashtag_searchable?
  77. hashtag_search?
  78. end
  79. def account_search?
  80. @options[:type].blank? || @options[:type] == 'accounts'
  81. end
  82. def hashtag_search?
  83. @options[:type].blank? || @options[:type] == 'hashtags'
  84. end
  85. def status_search?
  86. @options[:type].blank? || @options[:type] == 'statuses'
  87. end
  88. end