# frozen_string_literal: true class Chat::Api::ChatChatablesController < Chat::Api def index params.require(:filter) filter = params[:filter].downcase memberships = Chat::ChatChannelMembershipManager.all_for_user(current_user) public_channels = Chat::ChatChannelFetcher.secured_public_channels( guardian, memberships, filter: filter, status: :open, ) users = User.joins(:user_option).where.not(id: current_user.id) if !Chat.allowed_group_ids.include?(Group::AUTO_GROUPS[:everyone]) users = users .joins(:groups) .where(groups: { id: Chat.allowed_group_ids }) .or(users.joins(:groups).staff) end users = users.where(user_option: { chat_enabled: true }) like_filter = "%#{filter}%" if SiteSetting.prioritize_username_in_ux || !SiteSetting.enable_names users = users.where("users.username_lower ILIKE ?", like_filter) else users = users.where( "LOWER(users.name) ILIKE ? OR users.username_lower ILIKE ?", like_filter, like_filter, ) end users = users.limit(25).uniq direct_message_channels = if users.count > 0 # FIXME: investigate the cost of this query ChatChannel .includes(chatable: :users) .joins(direct_message: :direct_message_users) .group(1) .having( "ARRAY[?] <@ ARRAY_AGG(user_id) AND ARRAY[?] && ARRAY_AGG(user_id)", [current_user.id], users.map(&:id), ) else [] end user_ids_with_channel = [] direct_message_channels.each do |dm_channel| user_ids = dm_channel.chatable.users.map(&:id) user_ids_with_channel.concat(user_ids) if user_ids.count < 3 end users_without_channel = users.filter { |u| !user_ids_with_channel.include?(u.id) } if current_user.username.downcase.start_with?(filter) # We filtered out the current user for the query earlier, but check to see # if they should be included, and add. users_without_channel << current_user end render_serialized( { public_channels: public_channels, direct_message_channels: direct_message_channels, users: users_without_channel, memberships: memberships, }, ChatChannelSearchSerializer, root: false, ) end end