diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py
index 5a907718d6..0a13fca9a4 100644
--- a/synapse/events/spamcheck.py
+++ b/synapse/events/spamcheck.py
@@ -15,6 +15,7 @@
# limitations under the License.
import inspect
+from typing import Dict
from synapse.spam_checker_api import SpamCheckerApi
@@ -125,3 +126,29 @@ class SpamChecker(object):
return True
return self.spam_checker.user_may_publish_room(userid, room_id)
+
+ def check_username_for_spam(self, user_profile: Dict[str, str]) -> bool:
+ """Checks if a user ID or display name are considered "spammy" by this server.
+
+ If the server considers a username spammy, then it will not be included in
+ user directory results.
+
+ Args:
+ user_profile: The user information to check, it contains the keys:
+ * user_id
+ * display_name
+ * avatar_url
+
+ Returns:
+ True if the user is spammy.
+ """
+ if self.spam_checker is None:
+ return False
+
+ # For backwards compatibility, if the method does not exist on the spam checker, fallback to not interfering.
+ checker = getattr(self.spam_checker, "check_username_for_spam", None)
+ if not checker:
+ return False
+ # Make a copy of the user profile object to ensure the spam checker
+ # cannot modify it.
+ return checker(user_profile.copy())
diff --git a/synapse/handlers/user_directory.py b/synapse/handlers/user_directory.py
index 81aa58dc8c..722760c59d 100644
--- a/synapse/handlers/user_directory.py
+++ b/synapse/handlers/user_directory.py
@@ -52,6 +52,7 @@ class UserDirectoryHandler(StateDeltasHandler):
self.is_mine_id = hs.is_mine_id
self.update_user_directory = hs.config.update_user_directory
self.search_all_users = hs.config.user_directory_search_all_users
+ self.spam_checker = hs.get_spam_checker()
# The current position in the current_state_delta stream
self.pos = None
@@ -65,7 +66,7 @@ class UserDirectoryHandler(StateDeltasHandler):
# we start populating the user directory
self.clock.call_later(0, self.notify_new_event)
- def search_users(self, user_id, search_term, limit):
+ async def search_users(self, user_id, search_term, limit):
"""Searches for users in directory
Returns:
@@ -82,7 +83,16 @@ class UserDirectoryHandler(StateDeltasHandler):
]
}
"""
- return self.store.search_user_dir(user_id, search_term, limit)
+ results = await self.store.search_user_dir(user_id, search_term, limit)
+
+ # Remove any spammy users from the results.
+ results["results"] = [
+ user
+ for user in results["results"]
+ if not self.spam_checker.check_username_for_spam(user)
+ ]
+
+ return results
def notify_new_event(self):
"""Called when there may be more deltas to process
|