您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

176 行
5.3 KiB

  1. #!/usr/bin/env python
  2. # Copyright 2021 The Matrix.org Foundation C.I.C.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import argparse
  16. import sys
  17. import time
  18. from datetime import datetime
  19. from typing import List
  20. import attr
  21. from synapse.config._base import RootConfig, find_config_files, read_config_files
  22. from synapse.config.database import DatabaseConfig
  23. from synapse.storage.database import DatabasePool, LoggingTransaction, make_conn
  24. from synapse.storage.engines import create_engine
  25. class ReviewConfig(RootConfig):
  26. "A config class that just pulls out the database config"
  27. config_classes = [DatabaseConfig]
  28. @attr.s(auto_attribs=True)
  29. class UserInfo:
  30. user_id: str
  31. creation_ts: int
  32. emails: List[str] = attr.Factory(list)
  33. private_rooms: List[str] = attr.Factory(list)
  34. public_rooms: List[str] = attr.Factory(list)
  35. ips: List[str] = attr.Factory(list)
  36. def get_recent_users(txn: LoggingTransaction, since_ms: int) -> List[UserInfo]:
  37. """Fetches recently registered users and some info on them."""
  38. sql = """
  39. SELECT name, creation_ts FROM users
  40. WHERE
  41. ? <= creation_ts
  42. AND deactivated = 0
  43. """
  44. txn.execute(sql, (since_ms / 1000,))
  45. user_infos = [UserInfo(user_id, creation_ts) for user_id, creation_ts in txn]
  46. for user_info in user_infos:
  47. user_info.emails = DatabasePool.simple_select_onecol_txn(
  48. txn,
  49. table="user_threepids",
  50. keyvalues={"user_id": user_info.user_id, "medium": "email"},
  51. retcol="address",
  52. )
  53. sql = """
  54. SELECT room_id, canonical_alias, name, join_rules
  55. FROM local_current_membership
  56. INNER JOIN room_stats_state USING (room_id)
  57. WHERE user_id = ? AND membership = 'join'
  58. """
  59. txn.execute(sql, (user_info.user_id,))
  60. for room_id, canonical_alias, name, join_rules in txn:
  61. if join_rules == "public":
  62. user_info.public_rooms.append(canonical_alias or name or room_id)
  63. else:
  64. user_info.private_rooms.append(canonical_alias or name or room_id)
  65. user_info.ips = DatabasePool.simple_select_onecol_txn(
  66. txn,
  67. table="user_ips",
  68. keyvalues={"user_id": user_info.user_id},
  69. retcol="ip",
  70. )
  71. return user_infos
  72. def main():
  73. parser = argparse.ArgumentParser()
  74. parser.add_argument(
  75. "-c",
  76. "--config-path",
  77. action="append",
  78. metavar="CONFIG_FILE",
  79. help="The config files for Synapse.",
  80. required=True,
  81. )
  82. parser.add_argument(
  83. "-s",
  84. "--since",
  85. metavar="duration",
  86. help="Specify how far back to review user registrations for, defaults to 7d (i.e. 7 days).",
  87. default="7d",
  88. )
  89. parser.add_argument(
  90. "-e",
  91. "--exclude-emails",
  92. action="store_true",
  93. help="Exclude users that have validated email addresses",
  94. )
  95. parser.add_argument(
  96. "-u",
  97. "--only-users",
  98. action="store_true",
  99. help="Only print user IDs that match.",
  100. )
  101. config = ReviewConfig()
  102. config_args = parser.parse_args(sys.argv[1:])
  103. config_files = find_config_files(search_paths=config_args.config_path)
  104. config_dict = read_config_files(config_files)
  105. config.parse_config_dict(
  106. config_dict,
  107. )
  108. since_ms = time.time() * 1000 - config.parse_duration(config_args.since)
  109. exclude_users_with_email = config_args.exclude_emails
  110. include_context = not config_args.only_users
  111. for database_config in config.database.databases:
  112. if "main" in database_config.databases:
  113. break
  114. engine = create_engine(database_config.config)
  115. with make_conn(database_config, engine, "review_recent_signups") as db_conn:
  116. user_infos = get_recent_users(db_conn.cursor(), since_ms)
  117. for user_info in user_infos:
  118. if exclude_users_with_email and user_info.emails:
  119. continue
  120. if include_context:
  121. print_public_rooms = ""
  122. if user_info.public_rooms:
  123. print_public_rooms = "(" + ", ".join(user_info.public_rooms[:3])
  124. if len(user_info.public_rooms) > 3:
  125. print_public_rooms += ", ..."
  126. print_public_rooms += ")"
  127. print("# Created:", datetime.fromtimestamp(user_info.creation_ts))
  128. print("# Email:", ", ".join(user_info.emails) or "None")
  129. print("# IPs:", ", ".join(user_info.ips))
  130. print(
  131. "# Number joined public rooms:",
  132. len(user_info.public_rooms),
  133. print_public_rooms,
  134. )
  135. print("# Number joined private rooms:", len(user_info.private_rooms))
  136. print("#")
  137. print(user_info.user_id)
  138. if include_context:
  139. print()
  140. if __name__ == "__main__":
  141. main()