diff --git a/app/chewy/accounts_index.rb b/app/chewy/accounts_index.rb index 4ef383c12..cbfcfa1c3 100644 --- a/app/chewy/accounts_index.rb +++ b/app/chewy/accounts_index.rb @@ -35,6 +35,8 @@ class AccountsIndex < Chewy::Index field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content' end + field :actor_type, type: 'keyword', analyzer: 'content' + field :following_count, type: 'long', value: ->(account) { account.following.local.count } field :followers_count, type: 'long', value: ->(account) { account.followers.local.count } field :subscribing_count, type: 'long', value: ->(account) { account.subscribing.local.count } diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb index 3061fcb7e..0730a92a5 100644 --- a/app/controllers/api/v1/accounts/search_controller.rb +++ b/app/controllers/api/v1/accounts/search_controller.rb @@ -18,6 +18,7 @@ class Api::V1::Accounts::SearchController < Api::BaseController limit: limit_param(DEFAULT_ACCOUNTS_LIMIT), resolve: truthy_param?(:resolve), following: truthy_param?(:following), + group_only: truthy_param?(:group_only), offset: params[:offset] ) end diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index eeca1ea06..f22264bb7 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -451,9 +451,11 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => }), params: { - q: token.slice(1), + q: token.replace(/^@@?/, ''), resolve: false, limit: 4, + following: token.startsWith('@@'), + group_only: token.startsWith('@@'), }, }).then(response => { dispatch(importFetchedAccounts(response.data)); diff --git a/app/models/account.rb b/app/models/account.rb index 1585a054d..7826faad3 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -443,9 +443,13 @@ class Account < ApplicationRecord DeliveryFailureTracker.without_unavailable(urls) end - def search_for(terms, limit = 10, offset = 0) + def search_for(terms, limit = 10, group = false, offset = 0) textsearch, query = generate_query_for_search(terms) + sql_where_group = <<-SQL if group + AND accounts.actor_type = 'Group' + SQL + sql = <<-SQL.squish SELECT accounts.*, @@ -454,6 +458,7 @@ class Account < ApplicationRecord WHERE #{query} @@ #{textsearch} AND accounts.suspended_at IS NULL AND accounts.moved_to_account_id IS NULL + #{sql_where_group} ORDER BY rank DESC LIMIT ? OFFSET ? SQL @@ -463,9 +468,13 @@ class Account < ApplicationRecord records end - def advanced_search_for(terms, account, limit = 10, following = false, offset = 0) + def advanced_search_for(terms, account, limit = 10, following = false, group = false, offset = 0) textsearch, query = generate_query_for_search(terms) + sql_where_group = <<-SQL if group + AND accounts.actor_type = 'Group' + SQL + if following sql = <<-SQL.squish WITH first_degree AS ( @@ -484,6 +493,7 @@ class Account < ApplicationRecord AND #{query} @@ #{textsearch} AND accounts.suspended_at IS NULL AND accounts.moved_to_account_id IS NULL + #{sql_where_group} GROUP BY accounts.id ORDER BY rank DESC LIMIT ? OFFSET ? @@ -500,6 +510,7 @@ class Account < ApplicationRecord WHERE #{query} @@ #{textsearch} AND accounts.suspended_at IS NULL AND accounts.moved_to_account_id IS NULL + #{sql_where_group} GROUP BY accounts.id ORDER BY rank DESC LIMIT ? OFFSET ? diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb index 6fe4b6593..10a77c411 100644 --- a/app/services/account_search_service.rb +++ b/app/services/account_search_service.rb @@ -61,11 +61,11 @@ class AccountSearchService < BaseService end def advanced_search_results - Account.advanced_search_for(terms_for_query, account, limit_for_non_exact_results, options[:following], offset) + Account.advanced_search_for(terms_for_query, account, limit_for_non_exact_results, options[:following], options[:group_only], offset) end def simple_search_results - Account.search_for(terms_for_query, limit_for_non_exact_results, offset) + Account.search_for(terms_for_query, limit_for_non_exact_results, options[:group_only], offset) end def from_elasticsearch @@ -80,6 +80,9 @@ class AccountSearchService < BaseService elsif following_ids.any? should_clauses << { terms: { id: following_ids, boost: 100 } } end + if options[:group_only] + must_clauses << { term: { actor_type: 'group' } } + end end query = { bool: { must: must_clauses, should: should_clauses } }