spamcheck.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2017 New Vector Ltd
  3. # Copyright 2019 The Matrix.org Foundation C.I.C.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. import inspect
  17. from typing import Any, Dict, List
  18. from synapse.spam_checker_api import SpamCheckerApi
  19. MYPY = False
  20. if MYPY:
  21. import synapse.server
  22. class SpamChecker(object):
  23. def __init__(self, hs: "synapse.server.HomeServer"):
  24. self.spam_checkers = [] # type: List[Any]
  25. for module, config in hs.config.spam_checkers:
  26. # Older spam checkers don't accept the `api` argument, so we
  27. # try and detect support.
  28. spam_args = inspect.getfullargspec(module)
  29. if "api" in spam_args.args:
  30. api = SpamCheckerApi(hs)
  31. self.spam_checkers.append(module(config=config, api=api))
  32. else:
  33. self.spam_checkers.append(module(config=config))
  34. def check_event_for_spam(self, event: "synapse.events.EventBase") -> bool:
  35. """Checks if a given event is considered "spammy" by this server.
  36. If the server considers an event spammy, then it will be rejected if
  37. sent by a local user. If it is sent by a user on another server, then
  38. users receive a blank event.
  39. Args:
  40. event: the event to be checked
  41. Returns:
  42. True if the event is spammy.
  43. """
  44. for spam_checker in self.spam_checkers:
  45. if spam_checker.check_event_for_spam(event):
  46. return True
  47. return False
  48. def user_may_invite(
  49. self, inviter_userid: str, invitee_userid: str, room_id: str
  50. ) -> bool:
  51. """Checks if a given user may send an invite
  52. If this method returns false, the invite will be rejected.
  53. Args:
  54. inviter_userid: The user ID of the sender of the invitation
  55. invitee_userid: The user ID targeted in the invitation
  56. room_id: The room ID
  57. Returns:
  58. True if the user may send an invite, otherwise False
  59. """
  60. for spam_checker in self.spam_checkers:
  61. if (
  62. spam_checker.user_may_invite(inviter_userid, invitee_userid, room_id)
  63. is False
  64. ):
  65. return False
  66. return True
  67. def user_may_create_room(self, userid: str) -> bool:
  68. """Checks if a given user may create a room
  69. If this method returns false, the creation request will be rejected.
  70. Args:
  71. userid: The ID of the user attempting to create a room
  72. Returns:
  73. True if the user may create a room, otherwise False
  74. """
  75. for spam_checker in self.spam_checkers:
  76. if spam_checker.user_may_create_room(userid) is False:
  77. return False
  78. return True
  79. def user_may_create_room_alias(self, userid: str, room_alias: str) -> bool:
  80. """Checks if a given user may create a room alias
  81. If this method returns false, the association request will be rejected.
  82. Args:
  83. userid: The ID of the user attempting to create a room alias
  84. room_alias: The alias to be created
  85. Returns:
  86. True if the user may create a room alias, otherwise False
  87. """
  88. for spam_checker in self.spam_checkers:
  89. if spam_checker.user_may_create_room_alias(userid, room_alias) is False:
  90. return False
  91. return True
  92. def user_may_publish_room(self, userid: str, room_id: str) -> bool:
  93. """Checks if a given user may publish a room to the directory
  94. If this method returns false, the publish request will be rejected.
  95. Args:
  96. userid: The user ID attempting to publish the room
  97. room_id: The ID of the room that would be published
  98. Returns:
  99. True if the user may publish the room, otherwise False
  100. """
  101. for spam_checker in self.spam_checkers:
  102. if spam_checker.user_may_publish_room(userid, room_id) is False:
  103. return False
  104. return True
  105. def check_username_for_spam(self, user_profile: Dict[str, str]) -> bool:
  106. """Checks if a user ID or display name are considered "spammy" by this server.
  107. If the server considers a username spammy, then it will not be included in
  108. user directory results.
  109. Args:
  110. user_profile: The user information to check, it contains the keys:
  111. * user_id
  112. * display_name
  113. * avatar_url
  114. Returns:
  115. True if the user is spammy.
  116. """
  117. for spam_checker in self.spam_checkers:
  118. # For backwards compatibility, only run if the method exists on the
  119. # spam checker
  120. checker = getattr(spam_checker, "check_username_for_spam", None)
  121. if checker:
  122. # Make a copy of the user profile object to ensure the spam checker
  123. # cannot modify it.
  124. if checker(user_profile.copy()):
  125. return True
  126. return False