mirror of
https://github.com/PC-Admin/matrix-moderation-tool.git
synced 2024-12-19 07:00:27 -05:00
add function to return list of all or just local members of a room. silence a lot of functions terminal output. adjust incident reports module to handle sending 1 email per homeserver with all offending users, rooms and tag details combined. allow automatic generation of reports for all users when blocking rdlist tags. just block unknown rooms instead of block+purge. collect list of all local users present in rdlist rooms for batch reporting/deactivation. add statistics about rdlist blocking. divide room states/details into both dms and larger rooms. add save_to_file boolean to state export module to avoid writing it to file, also pass variable to customise file location.
This commit is contained in:
parent
a61a4e88af
commit
dbb9821a5c
@ -9,10 +9,10 @@ ipinfo_token = "" # Leave blank to disable ipinfo.io lookups
|
||||
# rdlist specific
|
||||
rdlist_bot_username = "mod_team" # The username to perform automated room shutdowns
|
||||
rdlist_recommended_tags = ['hub_room_links', 'hub_room_trade', 'preban', 'degen_misc', 'beastiality', 'degen_porn', 'gore', 'snuff', 'degen_larp', 'hub_room_sussy', 'bot_spam', 'cfm', 'jailbait', 'bot_porn', 'toddlercon', 'loli', 'csam', 'tfm', 'degen_meet', 'stylized_3d_loli', '3d_loli']
|
||||
# report generator
|
||||
# User report generator
|
||||
report_folder = "./reports" # Reports folder name
|
||||
testing_mode = True # For testing this report generator, set this to True
|
||||
# email settings
|
||||
# Incident report email settings
|
||||
smtp_user = "abuse@matrix.example.org"
|
||||
smtp_password = "strong-stmp-password"
|
||||
smtp_server = "smtp.provider.org"
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
import json
|
||||
import user_commands
|
||||
import room_commands
|
||||
import server_commands
|
||||
@ -35,21 +36,21 @@ while pass_token == False:
|
||||
print("\n----------------------------------------------")
|
||||
print("\n#### User Account Commands ####\t\t\t#### Room Commands ####")
|
||||
print("1) Deactivate a user account.\t\t\t20) List details of a room.")
|
||||
print("2) Deactivate multiple user accounts.\t\t21) Export the state events of a target room.")
|
||||
print("3) Create a user account.\t\t\t22) List rooms in public directory.")
|
||||
print("4) Create multiple user accounts.\t\t23) Remove a room from the public directory.")
|
||||
print("5) Reset a users password.\t\t\t24) Remove multiple rooms from the public directory.")
|
||||
print("6) Whois user account.\t\t\t\t25) Redact a room event.")
|
||||
print("7) Whois multiple user accounts.\t\t26) List/Download all media in a room.")
|
||||
print("8) Query user account.\t\t\t\t27) Download media from multiple rooms.")
|
||||
print("9) Query multiple user accounts.\t\t28) Quarantine all media in a room.")
|
||||
print("10) List room memberships of user.\t\t29) Shutdown a room.")
|
||||
print("11) Promote a user to server admin.\t\t30) Shutdown multiple rooms.")
|
||||
print("12) List all user accounts.\t\t\t31) Delete a room.")
|
||||
print("13) Quarantine all media a users uploaded.\t32) Delete multiple rooms.")
|
||||
print("14) Collect account data.\t\t\t33) Purge the event history of a room to a specific timestamp.")
|
||||
print("15) List account pushers.\t\t\t34) Purge the event history of multiple rooms to a specific timestamp.")
|
||||
print("16) Get rate limit of a user account.")
|
||||
print("2) Deactivate multiple user accounts.\t\t21) List the members of a room.")
|
||||
print("3) Create a user account.\t\t\t22) Export the state events of a target room.")
|
||||
print("4) Create multiple user accounts.\t\t23) List rooms in public directory.")
|
||||
print("5) Reset a users password.\t\t\t24) Remove a room from the public directory.")
|
||||
print("6) Whois user account.\t\t\t\t25) Remove multiple rooms from the public directory.")
|
||||
print("7) Whois multiple user accounts.\t\t26) Redact a room event.")
|
||||
print("8) Query user account.\t\t\t\t27) List/Download all media in a room.")
|
||||
print("9) Query multiple user accounts.\t\t28) Download media from multiple rooms.")
|
||||
print("10) List room memberships of user.\t\t29) Quarantine all media in a room.")
|
||||
print("11) Promote a user to server admin.\t\t30) Shutdown a room.")
|
||||
print("12) List all user accounts.\t\t\t31) Shutdown multiple rooms.")
|
||||
print("13) Quarantine all media a users uploaded.\t32) Delete a room.")
|
||||
print("14) Collect account data.\t\t\t33) Delete multiple rooms.")
|
||||
print("15) List account pushers.\t\t\t34) Purge the event history of a room to a specific timestamp.")
|
||||
print("16) Get rate limit of a user account.\t\t35) Purge the event history of multiple rooms to a specific timestamp.")
|
||||
print("17) Set rate limit of a user account.")
|
||||
print("18) Delete rate limit of a user account.")
|
||||
print("19) Check if user account exists.")
|
||||
@ -58,7 +59,7 @@ while pass_token == False:
|
||||
print("41) Purge remote media repository up to a certain date.\t\t71) Decrypt user report .zip file.")
|
||||
print("42) Prepare database for copying events of multiple rooms.\t72) Lookup homeserver admin contact email.")
|
||||
print("\t\t\t\t\t\t\t\t73) Send a test email.")
|
||||
print("#### rdlist ####\t\t\t\t\t\t74) Send a test incident report to yourself.")
|
||||
print("#### rdlist ####\t\t\t\t\t\t74) Send test incident reports to yourself.")
|
||||
print("50) Block all rooms with specific rdlist tags.")
|
||||
print("51) Block all rooms with recommended rdlist tags.")
|
||||
print("\n#### ipinfo.io ####")
|
||||
@ -77,23 +78,28 @@ while pass_token == False:
|
||||
elif menu_input == "5":
|
||||
user_commands.reset_password('','')
|
||||
elif menu_input == "6":
|
||||
user_commands.whois_account('')
|
||||
whois_account_dict = user_commands.whois_account('')
|
||||
print(json.dumps(whois_account_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "7":
|
||||
user_commands.whois_multiple_accounts()
|
||||
elif menu_input == "8":
|
||||
user_commands.query_account()
|
||||
query_account_dict = user_commands.query_account()
|
||||
print(json.dumps(query_account_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "9":
|
||||
user_commands.query_multiple_accounts()
|
||||
elif menu_input == "10":
|
||||
user_commands.list_joined_rooms('')
|
||||
joined_rooms_dict = user_commands.list_joined_rooms('')
|
||||
print(json.dumps(joined_rooms_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "11":
|
||||
user_commands.set_user_server_admin('')
|
||||
set_user_server_admin_dict = user_commands.set_user_server_admin('')
|
||||
print(json.dumps(set_user_server_admin_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "12":
|
||||
user_commands.list_accounts()
|
||||
elif menu_input == "13":
|
||||
user_commands.quarantine_users_media()
|
||||
elif menu_input == "14":
|
||||
user_commands.collect_account_data('')
|
||||
account_data_dict = user_commands.collect_account_data('')
|
||||
print(json.dumps(account_data_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "15":
|
||||
user_commands.list_account_pushers('')
|
||||
elif menu_input == "16":
|
||||
@ -103,36 +109,44 @@ while pass_token == False:
|
||||
elif menu_input == "18":
|
||||
user_commands.delete_rate_limit()
|
||||
elif menu_input == "19":
|
||||
user_commands.check_user_account_exists('')
|
||||
user_account_exists = user_commands.check_user_account_exists('')
|
||||
if user_account_exists == True:
|
||||
print("\nUser account exists.\n")
|
||||
elif user_account_exists == False:
|
||||
print("\nUser account does not exist.\n")
|
||||
elif menu_input == "20":
|
||||
room_commands.list_room_details('')
|
||||
room_details_dict = room_commands.list_room_details('')
|
||||
print(json.dumps(room_details_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "21":
|
||||
room_commands.export_room_state('')
|
||||
room_members_dict = room_commands.get_room_members('',False)
|
||||
print(json.dumps(room_members_dict, indent=4, sort_keys=True))
|
||||
elif menu_input == "22":
|
||||
room_commands.list_directory_rooms()
|
||||
room_commands.export_room_state('','',True)
|
||||
elif menu_input == "23":
|
||||
room_commands.remove_room_from_directory('')
|
||||
room_commands.public_directory_rooms()
|
||||
elif menu_input == "24":
|
||||
room_commands.remove_multiple_rooms_from_directory()
|
||||
room_commands.remove_room_from_directory('')
|
||||
elif menu_input == "25":
|
||||
room_commands.redact_room_event()
|
||||
room_commands.remove_multiple_rooms_from_directory()
|
||||
elif menu_input == "26":
|
||||
room_commands.list_and_download_media_in_room('','','','./')
|
||||
room_commands.redact_room_event()
|
||||
elif menu_input == "27":
|
||||
room_commands.download_media_from_multiple_rooms()
|
||||
room_commands.list_and_download_media_in_room('','','','./')
|
||||
elif menu_input == "28":
|
||||
room_commands.quarantine_media_in_room()
|
||||
room_commands.download_media_from_multiple_rooms()
|
||||
elif menu_input == "29":
|
||||
room_commands.shutdown_room('','','','','','')
|
||||
room_commands.quarantine_media_in_room()
|
||||
elif menu_input == "30":
|
||||
room_commands.shutdown_multiple_rooms()
|
||||
room_commands.shutdown_room('','','','','','')
|
||||
elif menu_input == "31":
|
||||
room_commands.delete_room('')
|
||||
room_commands.shutdown_multiple_rooms()
|
||||
elif menu_input == "32":
|
||||
room_commands.delete_multiple_rooms()
|
||||
room_commands.delete_room('')
|
||||
elif menu_input == "33":
|
||||
room_commands.purge_room_to_timestamp('','')
|
||||
room_commands.delete_multiple_rooms()
|
||||
elif menu_input == "34":
|
||||
room_commands.purge_room_to_timestamp('','')
|
||||
elif menu_input == "35":
|
||||
room_commands.purge_multiple_rooms_to_timestamp()
|
||||
elif menu_input == "40":
|
||||
server_commands.delete_block_media()
|
||||
@ -141,7 +155,7 @@ while pass_token == False:
|
||||
elif menu_input == "42":
|
||||
server_commands.prepare_database_copy_of_multiple_rooms()
|
||||
elif menu_input == "50":
|
||||
rdlist_commands.block_all_rooms_with_rdlist_tags(False,'','','','','')
|
||||
rdlist_commands.block_all_rooms_with_rdlist_tags(False,'','','')
|
||||
elif menu_input == "51":
|
||||
rdlist_commands.block_recommended_rdlist_tags()
|
||||
elif menu_input == "60":
|
||||
@ -157,10 +171,10 @@ while pass_token == False:
|
||||
elif menu_input == "73":
|
||||
report_commands.test_send_email()
|
||||
elif menu_input == "74":
|
||||
report_commands.test_send_incident_report()
|
||||
report_commands.test_send_incident_reports()
|
||||
elif menu_input == "q" or menu_input == "Q" or menu_input == "e" or menu_input == "E":
|
||||
print("\nExiting...\n")
|
||||
pass_token = True
|
||||
else:
|
||||
print("\nIncorrect input detected, please select a number from 1 to 41!\n")
|
||||
print("\nIncorrect input detected, please select a number from 1 to 74!\n")
|
||||
|
||||
|
@ -7,6 +7,7 @@ import string
|
||||
import time
|
||||
import user_commands
|
||||
import room_commands
|
||||
import report_commands
|
||||
import hardcoded_variables
|
||||
|
||||
#rdlist_bot_username = hardcoded_variables.rdlist_bot_username
|
||||
@ -16,7 +17,7 @@ def sync_rdlist():
|
||||
os.makedirs(rdlist_dir, exist_ok=True)
|
||||
# Check if the rdlist repo has already been cloned
|
||||
if os.path.isdir("./rdlist/.git"):
|
||||
print("rdlist repo already cloned...")
|
||||
print("\nrdlist repo already cloned...")
|
||||
os.chdir("./rdlist/")
|
||||
# Update git remote references and get status
|
||||
subprocess.run(["git", "remote", "update"], check=True)
|
||||
@ -36,31 +37,78 @@ def sync_rdlist():
|
||||
print("Cloning rdlist repo...")
|
||||
subprocess.run(["git", "clone", "ssh://gitea@code.glowers.club:1488/loj/rdlist.git"], check=True)
|
||||
|
||||
def block_all_rooms_with_rdlist_tags(rdlist_use_recommended,preset_user_ID,preset_new_room_name,preset_message,preset_purge_choice,preset_block_choice):
|
||||
# def build_incident_report(users_list):
|
||||
# # Git clone the rdlist repo to ./rdlist/
|
||||
# sync_rdlist()
|
||||
|
||||
# # Load the summaries JSON file
|
||||
# summaries_path = os.path.join("rdlist", "dist", "summaries.json")
|
||||
# with open(summaries_path, 'r') as file:
|
||||
# data = json.load(file)
|
||||
|
||||
|
||||
# return incidents_dict
|
||||
|
||||
# # Example of the data structure we're trying to build/transform:
|
||||
# # users_list = ["@billybob:matrix.org", "@johndoe:matrix.org", "@pedobear:perthchat.org", "@randomcreep:perthchat.org", "@fatweeb:grin.hu"]
|
||||
# #
|
||||
# # becomes:
|
||||
# #
|
||||
# # incidents_dict = {
|
||||
# # f"@billybob:matrix.org": {
|
||||
# # "!dummyid1:matrix.org": ["csam", "lolicon", "beastiality"],
|
||||
# # "!dummyid2:matrix.org": ["csam", "anarchy"]
|
||||
# # },
|
||||
# # f"@johndoe:matrix.org": {
|
||||
# # "!dummyid3:matrix.org": ["csam", "lolicon", "toddlercon"],
|
||||
# # "!dummyid4:matrix.org": ["csam", "terrorism"]
|
||||
# # },
|
||||
# # f"@pedobear:perthchat.org": {
|
||||
# # "!dummyid5:matrix.org": ["csam", "lolicon", "jailbait"],
|
||||
# # "!dummyid6:matrix.org": ["csam", "hub_links"]
|
||||
# # },
|
||||
# # f"@randomcreep:perthchat.org": {
|
||||
# # "!dummyid7:matrix.org": ["csam", "jailbait"],
|
||||
# # "!dummyid8:matrix.org": ["csam", "pre_ban"]
|
||||
# # },
|
||||
# # f"@fatweeb:grin.hu": {
|
||||
# # "!dummyid9:matrix.org": ["csam", "lolicon"],
|
||||
# # "!dummyid10:matrix.org": ["csam", "degen"]
|
||||
# # }
|
||||
# # }
|
||||
|
||||
def block_all_rooms_with_rdlist_tags(rdlist_use_recommended,preset_user_ID,preset_new_room_name,preset_message):
|
||||
# Git clone the rdlist repo to ./rdlist/
|
||||
sync_rdlist()
|
||||
|
||||
if rdlist_use_recommended == True:
|
||||
# Take input from the user and convert it to a list
|
||||
# Use the hardcoded recommended tags
|
||||
blocked_tags = hardcoded_variables.rdlist_recommended_tags
|
||||
print("\nUsing recommended rdlist tags. Rooms matching the following tags will be blocked and purged:\n\n" + str(hardcoded_variables.rdlist_recommended_tags))
|
||||
print(f"\nUsing recommended rdlist tags. Rooms matching the following tags will be purged and/or blocked:\n{hardcoded_variables.rdlist_recommended_tags}")
|
||||
|
||||
elif rdlist_use_recommended == False:
|
||||
# After the git repo has been cloned/pulled, open the file and read it into a string
|
||||
with open(os.path.join("rdlist", "lib", "docs", "tags.md"), 'r') as file:
|
||||
data = file.readlines()
|
||||
|
||||
# Print ./rdlist/lib/docs/tags.md README file for the user
|
||||
print("\nPrinting details about the current tags in rdlist:\n")
|
||||
for line in data:
|
||||
print(line, end='') # Print the contents of the file
|
||||
|
||||
# Take input from the user and convert it to a list
|
||||
print("\nPlease enter a space seperated list of tags you wish to block:\n")
|
||||
blocked_tags = input().split()
|
||||
print('')
|
||||
|
||||
# Load the summaries JSON file
|
||||
summaries_path = os.path.join("rdlist", "dist", "summaries.json")
|
||||
with open(summaries_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
|
||||
# Create an empty list to store all the room_ids
|
||||
all_room_ids = []
|
||||
|
||||
# Iterate over blocked_tags
|
||||
for tag in blocked_tags:
|
||||
# Filter the data to keep only the entries where the tag appears in the "tags" list
|
||||
@ -73,8 +121,51 @@ def block_all_rooms_with_rdlist_tags(rdlist_use_recommended,preset_user_ID,prese
|
||||
if rdlist_use_recommended == False:
|
||||
# Print the tag and corresponding room_ids
|
||||
print(f"Tag: {tag}\nRoom IDs: {room_ids}\n")
|
||||
|
||||
# Deduplicate the list of all room_ids
|
||||
all_room_ids = list(set(all_room_ids))
|
||||
|
||||
# Examine these room_ids for local users
|
||||
all_local_users = []
|
||||
all_remote_users = []
|
||||
for room_id in all_room_ids:
|
||||
joined_local_members = room_commands.get_room_members(room_id, True)
|
||||
all_local_users.extend(joined_local_members)
|
||||
joined_remote_members = room_commands.get_room_members(room_id, False)
|
||||
all_remote_users.extend(joined_remote_members)
|
||||
|
||||
# Deduplicate the list of all local users
|
||||
all_local_users = list(set(all_local_users))
|
||||
#print("all_local_users: " + str(all_local_users))
|
||||
|
||||
# If there's at least 1 local user detected, ask the admin if they want to generate a user report for every user found in rdlist rooms
|
||||
if len(all_local_users) > 0:
|
||||
print(f"\nWARNING! The following local users are current members of rooms tagged in rdlist: {all_local_users}")
|
||||
generate_user_report_confirmation = input("\nDo you want to generate a user report file for each of these users? y/n? ")
|
||||
if generate_user_report_confirmation.lower() in ['y', 'yes', 'Y', 'Yes']:
|
||||
for user_id in all_local_users:
|
||||
report_commands.generate_user_report(user_id)
|
||||
elif generate_user_report_confirmation.lower() in ['n', 'no', 'N', 'No']:
|
||||
print("\nSkipping user report generation...\n")
|
||||
elif len(all_local_users) == 0:
|
||||
print(f"\nNo local users were found in rdlist rooms.")
|
||||
|
||||
# Deduplicate the list of all remote users
|
||||
all_remote_users = list(set(all_remote_users))
|
||||
all_remote_users = [user for user in all_remote_users if user not in all_local_users]
|
||||
#print("all_remote_users: " + str(all_remote_users))
|
||||
|
||||
# Ask the admin if they would like to mail off an incident report for every remote user found in rdlist rooms
|
||||
# if len(all_remote_users) > 0:
|
||||
# print(f"\nThe following remote users are current members of rooms tagged in rdlist: {all_remote_users}")
|
||||
# send_incident_report_confirmation = input("\nDo you want to send an incident report to the abuse email address for each of these users? y/n? ")
|
||||
# if send_incident_report_confirmation.lower() in ['y', 'yes', 'Y', 'Yes']:
|
||||
# build_incident_report(all_remote_users)
|
||||
# #for user_id in all_remote_users:
|
||||
# # report_commands.send_incident_report(user_id)
|
||||
# elif send_incident_report_confirmation.lower() in ['n', 'no', 'N', 'No']:
|
||||
# print("\nSkipping incident report generation...\n")
|
||||
|
||||
# Ask the user if they wish to block and purge all these rooms, then collect shutdown parameters
|
||||
if preset_user_ID == '':
|
||||
user_ID = input("\nPlease enter the local username that will create a 'muted violation room' for your users (Example: michael): ")
|
||||
@ -88,47 +179,84 @@ def block_all_rooms_with_rdlist_tags(rdlist_use_recommended,preset_user_ID,prese
|
||||
message = input("\nPlease enter the shutdown message that will be displayed to users: ")
|
||||
elif preset_message != '':
|
||||
message = preset_message
|
||||
if preset_purge_choice == '':
|
||||
purge_choice = input("\nDo you want to purge the room? (This deletes all the room history from your database.) y/n? ")
|
||||
elif preset_purge_choice != '':
|
||||
purge_choice = preset_purge_choice
|
||||
if preset_block_choice == '':
|
||||
block_choice = input("\nDo you want to block the room? (This prevents your server users re-entering the room.) y/n? ")
|
||||
elif preset_block_choice != '':
|
||||
block_choice = preset_block_choice
|
||||
|
||||
# Ask the user if they wish to block and purge all these rooms
|
||||
shutdown_confirmation = input("\nNumber of rooms being shutdown: " + str(len(all_room_ids)) + "\n\nAre you sure you want to shutdown these rooms? y/n? ")
|
||||
shutdown_confirmation = input("\nNumber of rdlist rooms being shutdown: " + str(len(all_room_ids)) + "\n\nAre you sure you want to shutdown these rooms? y/n? ")
|
||||
|
||||
total_list_kicked_users = []
|
||||
num_rooms_blocked = 0
|
||||
|
||||
#print(f"all_room_ids: {all_room_ids}")
|
||||
if shutdown_confirmation.lower() in ['y', 'yes', 'Y', 'Yes']:
|
||||
for room_id in all_room_ids:
|
||||
room_commands.shutdown_room(room_id, user_ID, new_room_name, message, purge_choice, block_choice)
|
||||
print(f"\n\nShutting down room: {room_id}")
|
||||
room_state_dict = room_commands.export_room_state(room_id, "", False)
|
||||
#print(f"\nroom_state_dict: {room_state_dict}")
|
||||
if "Room not found" in room_state_dict.get('error', ''):
|
||||
list_kicked_users = room_commands.shutdown_room(room_id, user_ID, new_room_name, message, False, True)
|
||||
else:
|
||||
list_kicked_users = room_commands.shutdown_room(room_id, user_ID, new_room_name, message, True, True)
|
||||
num_rooms_blocked += 1
|
||||
total_list_kicked_users.extend(list_kicked_users)
|
||||
time.sleep(5)
|
||||
elif shutdown_confirmation.lower() in ['n', 'no', 'N', 'No']:
|
||||
print("\nSkipping these files...\n")
|
||||
return
|
||||
else:
|
||||
print("\nInvalid input, skipping these files...\n")
|
||||
return
|
||||
|
||||
# Deduplicate the list of all kicked users
|
||||
total_list_kicked_users = list(set(total_list_kicked_users))
|
||||
|
||||
# Print the list of all kicked users
|
||||
print(f"\n\nList of all kicked users: {total_list_kicked_users}\n")
|
||||
|
||||
# Return the list of all kicked users
|
||||
return num_rooms_blocked, total_list_kicked_users
|
||||
|
||||
def block_recommended_rdlist_tags():
|
||||
# Check if user account already exists
|
||||
account_query = user_commands.query_account(hardcoded_variables.rdlist_bot_username)
|
||||
|
||||
# Generate random password
|
||||
preset_password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(20))
|
||||
|
||||
# If user is not found, create it
|
||||
if 'User not found' in account_query:
|
||||
# Create user account
|
||||
user_commands.create_account(hardcoded_variables.rdlist_bot_username, preset_password)
|
||||
else:
|
||||
print("Account already exists.")
|
||||
print(f"\n@{hardcoded_variables.rdlist_bot_username}:{hardcoded_variables.base_url} account already exists. Resetting account password.")
|
||||
user_commands.reset_password(hardcoded_variables.rdlist_bot_username, preset_password)
|
||||
|
||||
# Promote bot user to server admin
|
||||
print(f"\nEnsuring @{hardcoded_variables.rdlist_bot_username}:{hardcoded_variables.base_url} account is a server admin.")
|
||||
user_commands.set_user_server_admin(hardcoded_variables.rdlist_bot_username)
|
||||
|
||||
# Define default valies for shutdown_room()
|
||||
preset_new_room_name = 'POLICY VIOLATION'
|
||||
preset_message = 'THIS ROOM VIOLATES SERVER POLICIES'
|
||||
preset_purge_choice = 'y'
|
||||
preset_block_choice = 'y'
|
||||
|
||||
# Block all rooms with recommended tag set
|
||||
block_all_rooms_with_rdlist_tags(True, hardcoded_variables.rdlist_bot_username, preset_new_room_name, preset_message, preset_purge_choice, preset_block_choice)
|
||||
num_rooms_blocked, total_list_kicked_users = block_all_rooms_with_rdlist_tags(True, hardcoded_variables.rdlist_bot_username, preset_new_room_name, preset_message)
|
||||
|
||||
# Print user login details
|
||||
print("\n\nUser login details for your moderator account:\n")
|
||||
print("\n\nRoom shutdowns completed!\n\nUser login details for your moderator account:\n")
|
||||
print("Username: " + hardcoded_variables.rdlist_bot_username)
|
||||
print("Password: " + preset_password)
|
||||
|
||||
# Print statistics for the admin
|
||||
print(f"\nPrint rdlist statistics:")
|
||||
print(f"\nNumber of rooms blocked/purged: {num_rooms_blocked}")
|
||||
print(f"Number of local users located in rdlist rooms and kicked: {len(total_list_kicked_users)}")
|
||||
print(f"\nThe following users were current members of rooms tagged in rdlist: {total_list_kicked_users}")
|
||||
|
||||
# Ask admin if they want to deactivate all the accounts that were kicked from rdlist rooms
|
||||
deactivate_confirmation = input("\nDo you want to also deactivate all these accounts that were kicked from rdlist rooms? y/n? ")
|
||||
if deactivate_confirmation.lower() in ['y', 'yes', 'Y', 'Yes']:
|
||||
for user_id in total_list_kicked_users:
|
||||
user_commands.deactivate_account(user_id)
|
||||
print(f"\nThese accounts have been deactivated.")
|
||||
elif deactivate_confirmation.lower() in ['n', 'no', 'N', 'No']:
|
||||
print("\nSkipping account deactivations...\n")
|
@ -54,6 +54,11 @@ def encrypt_user_folder(user_report_folder, username):
|
||||
# Delete the original zip file
|
||||
os.remove(zip_file_name)
|
||||
|
||||
# Write the password to a file
|
||||
password_file = open(zip_file_name + ".aes" + ".password", "w")
|
||||
password_file.write(strong_password)
|
||||
password_file.close()
|
||||
|
||||
# You can return the password if you need to use it later, or you can directly print it here
|
||||
return strong_password, zip_file_name + ".aes"
|
||||
|
||||
@ -65,10 +70,11 @@ def generate_user_report(preset_username):
|
||||
username = user_commands.parse_username(preset_username)
|
||||
|
||||
# Check if user exists
|
||||
if user_commands.check_user_account_exists(username) == True:
|
||||
print("\nUser exists, continuing with report generation.")
|
||||
if user_commands.check_user_account_exists(username) == False:
|
||||
print("\nUser does not exist, exiting report generation.")
|
||||
return
|
||||
|
||||
elif user_commands.check_user_account_exists(username) == True:
|
||||
print(f"\nGenerating user report for {username}...")
|
||||
# If report_folder ends in a slash, remove it
|
||||
report_folder = get_report_folder()
|
||||
|
||||
@ -117,34 +123,51 @@ def generate_user_report(preset_username):
|
||||
ipinfo_file.write(json.dumps(ipinfo, indent=4, sort_keys=True))
|
||||
ipinfo_file.close()
|
||||
|
||||
# For each room the user is in, get the room state and write to ./report/username/room_states/
|
||||
room_states_folder = user_report_folder + "room_states/"
|
||||
if os.path.exists(room_states_folder) == False:
|
||||
os.mkdir(room_states_folder)
|
||||
# Prepare folder structures
|
||||
room_folder = user_report_folder + "rooms/"
|
||||
dm_folder = user_report_folder + "dms/"
|
||||
details_folder = "details/"
|
||||
states_folder = "states/"
|
||||
|
||||
# For each room the user is in, get the room state and write to ./report/username/rooms/states/
|
||||
room_states_folder = room_folder + states_folder
|
||||
if not os.path.exists(room_states_folder):
|
||||
os.makedirs(room_states_folder, exist_ok=True)
|
||||
|
||||
# For each room the user is in, get the room details and write to ./report/username/rooms/details/
|
||||
room_details_folder = room_folder + details_folder
|
||||
if not os.path.exists(room_details_folder):
|
||||
os.makedirs(room_details_folder, exist_ok=True)
|
||||
|
||||
# For DM, get the state and write to ./report/username/dms/states/
|
||||
dm_states_folder = dm_folder + states_folder
|
||||
if not os.path.exists(dm_states_folder):
|
||||
os.makedirs(dm_states_folder, exist_ok=True)
|
||||
|
||||
# For DM, get the details and write to ./report/username/dms/details/
|
||||
dm_details_folder = dm_folder + details_folder
|
||||
if not os.path.exists(dm_details_folder):
|
||||
os.makedirs(dm_details_folder, exist_ok=True)
|
||||
|
||||
room_list = joined_rooms_dict.get('joined_rooms', [])
|
||||
|
||||
count = 0
|
||||
for room in room_list:
|
||||
count += 1
|
||||
room = room.split(" ")[0]
|
||||
room_commands.export_room_state(room, room_states_folder)
|
||||
if count > 4 and hardcoded_variables.testing_mode == True:
|
||||
break
|
||||
|
||||
# For each room the user is in, get the room details and write to ./report/username/room_details/
|
||||
room_details_folder = user_report_folder + "room_details/"
|
||||
if os.path.exists(room_details_folder) == False:
|
||||
os.mkdir(room_details_folder)
|
||||
|
||||
count = 0
|
||||
for room in room_list:
|
||||
count += 1
|
||||
room = room.split(" ")[0]
|
||||
room_details = room_commands.list_room_details(room)
|
||||
|
||||
# Check the room conditions to select the proper output folders
|
||||
if room_details['joined_members'] == 2 and room_details['public'] == False:
|
||||
room_details_file = open(dm_details_folder + room + ".json", "w")
|
||||
state_events = room_commands.export_room_state(room, dm_states_folder, True)
|
||||
else:
|
||||
room_details_file = open(room_details_folder + room + ".json", "w")
|
||||
room_details_file.write(str(room_details))
|
||||
state_events = room_commands.export_room_state(room, room_states_folder, True)
|
||||
|
||||
room_details_file.write(json.dumps(room_details, indent=4, sort_keys=True))
|
||||
room_details_file.close()
|
||||
|
||||
if count > 4 and hardcoded_variables.testing_mode == True:
|
||||
break
|
||||
|
||||
@ -155,7 +178,7 @@ def generate_user_report(preset_username):
|
||||
encrypted_zip_file_size = os.path.getsize(encrypted_zip_file_name) / 1000000
|
||||
|
||||
# Print the password and the encrypted .zip file name
|
||||
print("\nReport generated successfully on user: \"" + username + "\"\n\nYou can send this .zip file and password when reporting a user to law enforcement.")
|
||||
print("Report generated successfully on user: \"" + username + "\"\n\nYou can send this .zip file and password when reporting a user to law enforcement.")
|
||||
print("\nPassword: " + strong_password)
|
||||
print("Encrypted .zip file location: " + encrypted_zip_file_name)
|
||||
print("Encrypted .zip file size: " + str(encrypted_zip_file_size) + " MB\n")
|
||||
@ -268,41 +291,29 @@ def test_send_email():
|
||||
else:
|
||||
print("\nFailed to send email.")
|
||||
|
||||
def send_incident_report(full_username, room_id, rdlist_tags):
|
||||
# First extract the baseurl from the username, for example '@billybob:matrix.org' becomes 'matrix.org'
|
||||
baseurl = full_username.split(":")[1]
|
||||
|
||||
# Use the lookup function to get the admin's email
|
||||
if hardcoded_variables.testing_mode == True:
|
||||
admin_email_dict = {hardcoded_variables.base_url: [hardcoded_variables.report_return_email]}
|
||||
print("admin_email_dict: " + str(admin_email_dict))
|
||||
from_whois = True
|
||||
elif hardcoded_variables.testing_mode == False:
|
||||
admin_email_dict, from_whois = lookup_homeserver_admin_email(baseurl)
|
||||
|
||||
# If no admin emails are found, return False
|
||||
if not admin_email_dict or baseurl not in admin_email_dict:
|
||||
print(f"Unable to find any admin emails for {baseurl}")
|
||||
return False
|
||||
|
||||
# Prepare the incident report email content
|
||||
email_subject = f"Incident Report for user: {full_username}"
|
||||
def prepare_email_content(user_dict, from_whois, baseurl):
|
||||
email_content = f"""Dear Administrator,
|
||||
|
||||
We regret to inform you that your user {full_username} has been involved in an incident in the following room: {room_id}
|
||||
We regret to inform you that there have been incidents involving the following users in your homeserver:
|
||||
"""
|
||||
|
||||
In that room they were exposed to the following content: {', '.join(rdlist_tags)}
|
||||
for full_username, room_dict in user_dict.items():
|
||||
email_content += f"\nUser: {full_username}\n"
|
||||
for room_id, rdlist_tags in room_dict.items():
|
||||
email_content += f"Is in the room {room_id}, this room has been flagged with the following rdlist tags:\n{', '.join(rdlist_tags)}\n"
|
||||
|
||||
email_content += f"""
|
||||
|
||||
We request your immediate attention to this matter. It is recommended that you:
|
||||
- Generate a report on this user's account and send it to law enforcement.
|
||||
- Block and purge this room from your homeserver.
|
||||
- Deactivate this users account.
|
||||
- Generate a report on these users' accounts and send it to law enforcement.
|
||||
- Block and purge these rooms from your homeserver.
|
||||
- Deactivate these users' accounts.
|
||||
|
||||
All of these actions can be done automatically using this moderation tool:
|
||||
https://github.com/PC-Admin/matrix-moderation-tool
|
||||
|
||||
**********************************************************************
|
||||
THIS EMAIL IS UNMONITORED, PLEASE DO NOT REPLY TO IT
|
||||
\tTHIS EMAIL IS UNMONITORED, PLEASE DO NOT REPLY TO IT
|
||||
**********************************************************************
|
||||
|
||||
To contact us please email {hardcoded_variables.report_return_email}.
|
||||
@ -314,10 +325,9 @@ Incident Report Team
|
||||
https://{hardcoded_variables.base_url}
|
||||
"""
|
||||
|
||||
# If email address is collected from WHOIS data, append an extra paragraph
|
||||
if from_whois:
|
||||
email_content += f"""\n\n**********************************************************************
|
||||
ATTENTION DOMAIN REGISTRAR, YOUR ACTION IS REQUIRED HERE
|
||||
\tATTENTION DOMAIN REGISTRAR, YOUR ACTION IS REQUIRED HERE
|
||||
**********************************************************************
|
||||
\nThis email is intended for the owner of the domain {baseurl}, but they have not published their email address.
|
||||
\nAs the recipient of this email, you have a legal obligation to ensure that this email reaches them.
|
||||
@ -325,51 +335,93 @@ ATTENTION DOMAIN REGISTRAR, YOUR ACTION IS REQUIRED HERE
|
||||
https://github.com/matrix-org/matrix-spec-proposals/pull/1929
|
||||
"""
|
||||
|
||||
# Confidentiality warning
|
||||
confidentiality_warning = """\n\n**********************************************************************
|
||||
WARNING! CONFIDENTIALITY NOTICE!
|
||||
\nThis email message and any attached files may contain information
|
||||
that is confidential and subject of legal privilege intended only for
|
||||
use by the individual or entity to whom they are addressed. If you
|
||||
are not the intended recipient or the person responsible for
|
||||
delivering the message to the intended recipient be advised that you
|
||||
have received this message in error and that any use, copying,
|
||||
circulation, forwarding, printing or publication of this message or
|
||||
attached files is strictly forbidden, as is the disclosure of the
|
||||
information contained therein. If you have received this message in
|
||||
error, please notify the sender immediately and delete it from your
|
||||
inbox.
|
||||
confidentiality_warning = f"""\n\n**********************************************************************
|
||||
\t\tATTENTION! CONFIDENTIALITY NOTICE!
|
||||
\nThis electronic mail and any files linked to it may hold information
|
||||
that is privileged, confidential, and intended exclusively for the use of
|
||||
the designated recipient or entity. If you're not the expected recipient or
|
||||
the individual tasked with delivering the electronic mail to the intended recipient,
|
||||
be aware that you've received this mail in error. Any utilization, duplication,
|
||||
distribution, forwarding, printing, or publicizing of this email or the attached files
|
||||
is strictly prohibited, as is revealing the information contained within.
|
||||
If you've received this email in error, please promptly inform the sender and
|
||||
remove it from your electronic mailbox.
|
||||
\n**********************************************************************
|
||||
"""
|
||||
|
||||
# Append the confidentiality warning
|
||||
email_content += confidentiality_warning
|
||||
return email_content
|
||||
|
||||
# Prepare the email attachments. This can be modified based on what you want to attach.
|
||||
email_attachments = []
|
||||
|
||||
# Loop over each admin email address and send them the email
|
||||
def send_incident_report(incidents_dict):
|
||||
success = True
|
||||
homeserver_dict = {}
|
||||
|
||||
# Aggregate incidents by homeserver.
|
||||
for full_username, room_dict in incidents_dict.items():
|
||||
baseurl = full_username.split(":")[1]
|
||||
|
||||
if baseurl not in homeserver_dict:
|
||||
homeserver_dict[baseurl] = {}
|
||||
homeserver_dict[baseurl][full_username] = room_dict
|
||||
|
||||
print("homeserver_dict: " + str(homeserver_dict))
|
||||
# Prepare and send one email per homeserver, including all users and rooms.
|
||||
for baseurl, user_dict in homeserver_dict.items():
|
||||
if hardcoded_variables.testing_mode == True:
|
||||
admin_email_dict = {baseurl: [hardcoded_variables.report_return_email]}
|
||||
print("admin_email_dict: " + str(admin_email_dict))
|
||||
from_whois = True
|
||||
elif hardcoded_variables.testing_mode == False:
|
||||
admin_email_dict, from_whois = lookup_homeserver_admin_email(baseurl)
|
||||
|
||||
if not admin_email_dict or baseurl not in admin_email_dict:
|
||||
print(f"Unable to find any admin emails for {baseurl}")
|
||||
success = False
|
||||
continue
|
||||
|
||||
# Prepare and send one email per homeserver, including all users and rooms.
|
||||
for email_address in admin_email_dict[baseurl]:
|
||||
email_subject = f"Incident Report for users from {baseurl}"
|
||||
email_content = prepare_email_content(user_dict, from_whois, baseurl)
|
||||
|
||||
email_attachments = []
|
||||
if not send_email(email_address, email_subject, email_content, email_attachments):
|
||||
print(f"Failed to send email to {email_address}")
|
||||
success = False
|
||||
|
||||
return success
|
||||
|
||||
def test_send_incident_report():
|
||||
# Preset the parameters
|
||||
full_username = f"@billybob:{hardcoded_variables.base_url}"
|
||||
room_id = "!dummyid:matrix.org"
|
||||
rdlist_tags = ["csam", "lolicon", "beastiality"]
|
||||
def test_send_incident_reports():
|
||||
incidents_dict = {
|
||||
f"@billybob:matrix.org": {
|
||||
"!dummyid1:matrix.org": ["csam", "lolicon", "beastiality"],
|
||||
"!dummyid2:matrix.org": ["csam", "anarchy"]
|
||||
},
|
||||
f"@johndoe:matrix.org": {
|
||||
"!dummyid3:matrix.org": ["csam", "lolicon", "toddlercon"],
|
||||
"!dummyid4:matrix.org": ["csam", "terrorism"]
|
||||
},
|
||||
f"@pedobear:perthchat.org": {
|
||||
"!dummyid5:matrix.org": ["csam", "lolicon", "jailbait"],
|
||||
"!dummyid6:matrix.org": ["csam", "hub_links"]
|
||||
},
|
||||
f"@randomcreep:perthchat.org": {
|
||||
"!dummyid7:matrix.org": ["csam", "jailbait"],
|
||||
"!dummyid8:matrix.org": ["csam", "pre_ban"]
|
||||
},
|
||||
f"@fatweeb:grin.hu": {
|
||||
"!dummyid9:matrix.org": ["csam", "lolicon"],
|
||||
"!dummyid10:matrix.org": ["csam", "degen"]
|
||||
}
|
||||
}
|
||||
|
||||
# Try to send the incident report
|
||||
try:
|
||||
if hardcoded_variables.testing_mode == True:
|
||||
print("\nWARNING: TESTING MODE ENABLED, SENDING EMAIL TO: " + hardcoded_variables.report_return_email + "\n")
|
||||
if send_incident_report(full_username, room_id, rdlist_tags):
|
||||
print("\nIncident report successfully sent.")
|
||||
if send_incident_report(incidents_dict):
|
||||
print("\nIncident reports successfully sent.")
|
||||
else:
|
||||
print("\nFailed to send the incident report.")
|
||||
print("\nFailed to send the incident reports.")
|
||||
except Exception as e:
|
||||
print(f"\nFailed to send incident report: {e}")
|
||||
print(f"\nFailed to send incident reports: {e}")
|
||||
|
118
room_commands.py
118
room_commands.py
@ -21,18 +21,53 @@ def list_room_details(preset_internal_ID):
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/rooms/{internal_ID}"
|
||||
headers = {"Authorization": f"Bearer {hardcoded_variables.access_token}"}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, headers=headers, verify=True)
|
||||
|
||||
room_details_dict = json.loads(response.text)
|
||||
print(json.dumps(room_details_dict, indent=4, sort_keys=True))
|
||||
|
||||
return room_details_dict
|
||||
|
||||
# Example
|
||||
# $ curl -kXGET 'https://matrix.perthchat.org/_synapse/admin/v1/rooms/!OeqILBxiHahidSQQoC:matrix.org?access_token=ACCESS_TOKEN'
|
||||
|
||||
def export_room_state(preset_internal_ID, preset_directory):
|
||||
def get_room_members(preset_internal_ID, local_only):
|
||||
if preset_internal_ID == '':
|
||||
internal_ID = input("\nEnter the internal id of the room you wish to query (Example: !OLkDvaYjpNrvmwnwdj:matrix.org): ")
|
||||
elif preset_internal_ID != '':
|
||||
internal_ID = preset_internal_ID
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/rooms/{internal_ID}/members"
|
||||
headers = {"Authorization": f"Bearer {hardcoded_variables.access_token}"}
|
||||
|
||||
response = requests.get(url, headers=headers, verify=True)
|
||||
|
||||
room_members_dict = json.loads(response.text)
|
||||
|
||||
# Print room_members_dict for debugging
|
||||
#print("room_members_dict: " + json.dumps(room_members_dict, indent=4, sort_keys=True))
|
||||
|
||||
# Check if the 'members' key is in the response
|
||||
if 'members' in room_members_dict:
|
||||
# List of all members
|
||||
room_members = room_members_dict['members']
|
||||
|
||||
if local_only:
|
||||
# Filter to get only local members
|
||||
room_members = [member for member in room_members if member.split(':')[1] == hardcoded_variables.base_url]
|
||||
|
||||
else:
|
||||
# If 'members' key is not found, return an empty dictionary
|
||||
room_members = {}
|
||||
|
||||
# Print room_members for debugging
|
||||
#print("room_members: " + str(room_members))
|
||||
return room_members
|
||||
|
||||
# Example
|
||||
# $ curl -kXGET 'https://matrix.perthchat.org/_synapse/admin/v1/rooms/!OeqILBxiHahidSQQoC:matrix.org/members?access_token=ACCESS_TOKEN'
|
||||
|
||||
# This function returns the state of a room as output and optionally writes it to a json file
|
||||
def export_room_state(preset_internal_ID, preset_directory, save_to_file):
|
||||
# record the current directory location
|
||||
current_directory = os.getcwd()
|
||||
|
||||
@ -46,21 +81,28 @@ def export_room_state(preset_internal_ID, preset_directory):
|
||||
elif preset_directory != '':
|
||||
room_dir = preset_directory
|
||||
|
||||
os.makedirs(room_dir, exist_ok=True)
|
||||
|
||||
unix_time = int(time.time())
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/rooms/{internal_ID}/state"
|
||||
headers = {"Authorization": f"Bearer {hardcoded_variables.access_token}"}
|
||||
filename = os.path.join(room_dir, f"{internal_ID}_state_{unix_time}.json")
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, headers=headers, verify=True)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
f.write(response.text)
|
||||
|
||||
state_events_dict = json.loads(response.text)
|
||||
|
||||
# If save_to_file is True, write the output to a file
|
||||
if save_to_file == True:
|
||||
if "Room not found" not in state_events_dict.get('error', ''):
|
||||
# If save_to_file is True, create the directory if it doesn't exist
|
||||
os.makedirs(room_dir, exist_ok=True)
|
||||
# Define the filename and write to it
|
||||
unix_time = int(time.time())
|
||||
filename = os.path.join(room_dir, f"{internal_ID}_state_{unix_time}.json")
|
||||
#print(f"Writing room state events to {filename}")
|
||||
with open(filename, 'w') as f:
|
||||
f.write(json.dumps(state_events_dict, indent=4, sort_keys=True))
|
||||
elif "Room not found" in state_events_dict.get('error', ''):
|
||||
print("Room not found, skipping write to file...")
|
||||
|
||||
return state_events_dict
|
||||
|
||||
# Example
|
||||
@ -69,11 +111,11 @@ def export_room_state(preset_internal_ID, preset_directory):
|
||||
# See
|
||||
# https://matrix-org.github.io/synapse/latest/admin_api/rooms.html#room-state-api
|
||||
|
||||
def list_directory_rooms():
|
||||
def public_directory_rooms():
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_matrix/client/r0/publicRooms"
|
||||
headers = {"Authorization": f"Bearer {hardcoded_variables.access_token}"}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, headers=headers, verify=True)
|
||||
output = response.text
|
||||
|
||||
@ -82,6 +124,10 @@ def list_directory_rooms():
|
||||
|
||||
print(json.dumps(output, indent=4, sort_keys=True))
|
||||
|
||||
public_room_directories_dict = json.loads(response.text)
|
||||
|
||||
return public_room_directories_dict
|
||||
|
||||
# Example
|
||||
# $ curl -kXGET https://matrix.perthchat.org/_matrix/client/r0/publicRooms?access_token=ACCESS_TOKEN
|
||||
|
||||
@ -94,7 +140,7 @@ def remove_room_from_directory(preset_internal_ID):
|
||||
headers = {"Authorization": f"Bearer {hardcoded_variables.access_token}"}
|
||||
data = {"visibility": "private"}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.put(url, headers=headers, json=data, verify=True)
|
||||
|
||||
print(response.text)
|
||||
@ -127,7 +173,7 @@ def list_and_download_media_in_room(preset_internal_ID, preset_print_file_list_c
|
||||
internal_ID = preset_internal_ID
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/room/{internal_ID}/media"
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
|
||||
response = requests.get(url, headers=headers, verify=True)
|
||||
media_list_output = response.text
|
||||
@ -268,41 +314,33 @@ def shutdown_room(preset_internal_ID,preset_user_ID,preset_new_room_name,preset_
|
||||
|
||||
username = parse_username(user_ID)
|
||||
|
||||
if purge_choice == "y" or purge_choice == "Y" or purge_choice == "yes" or purge_choice == "Yes":
|
||||
if purge_choice == "y" or purge_choice == "Y" or purge_choice == "yes" or purge_choice == "Yes" or purge_choice == True:
|
||||
purge_choice = "true"
|
||||
elif purge_choice == "n" or purge_choice == "N" or purge_choice == "no" or purge_choice == "No":
|
||||
elif purge_choice == "n" or purge_choice == "N" or purge_choice == "no" or purge_choice == "No" or purge_choice == False:
|
||||
purge_choice = "false"
|
||||
else:
|
||||
print("Input invalid! exiting.")
|
||||
return
|
||||
|
||||
if block_choice == "y" or block_choice == "Y" or block_choice == "yes" or block_choice == "Yes":
|
||||
if block_choice == "y" or block_choice == "Y" or block_choice == "yes" or block_choice == "Yes" or block_choice == True:
|
||||
block_choice = "true"
|
||||
elif block_choice == "n" or block_choice == "N" or block_choice == "no" or block_choice == "No":
|
||||
elif block_choice == "n" or block_choice == "N" or block_choice == "no" or block_choice == "No" or block_choice == False:
|
||||
block_choice = "false"
|
||||
else:
|
||||
print("Input invalid! exiting.")
|
||||
return
|
||||
|
||||
# First export the state events of the room to examine them later or import them to rdlist
|
||||
room_status = export_room_state(internal_ID)
|
||||
|
||||
# Convert the string to a dictionary
|
||||
room_status_dict = json.loads(room_status)
|
||||
|
||||
if "Room not found" not in room_status_dict.get('error', ''):
|
||||
print(f"Exported room state events to file, this data can be useful for profiling a room after you've blocked/purged it: ./state_events{internal_ID}_state.json")
|
||||
|
||||
headers = {"Authorization": f"Bearer {hardcoded_variables.access_token}"}
|
||||
data = {
|
||||
"new_room_user_id": f"@{username}:{hardcoded_variables.base_url}",
|
||||
"room_name": new_room_name,
|
||||
"message": message,
|
||||
"block": block_choice,
|
||||
"purge": purge_choice
|
||||
"block": bool(block_choice),
|
||||
"purge": bool(purge_choice)
|
||||
}
|
||||
delete_room_url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v2/rooms/{internal_ID}"
|
||||
response = requests.delete(delete_room_url, headers=headers, json=data, verify=True)
|
||||
#print(response.text)
|
||||
|
||||
status = "null"
|
||||
count = 0
|
||||
@ -314,21 +352,27 @@ def shutdown_room(preset_internal_ID,preset_user_ID,preset_new_room_name,preset_
|
||||
sleep_time *= 2
|
||||
check_status_url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v2/rooms/{internal_ID}/delete_status"
|
||||
status_response = requests.get(check_status_url, headers=headers, verify=True)
|
||||
#print(f"status_response: {status_response.text}")
|
||||
output_json = status_response.json()
|
||||
#print(f"output_json: {output_json}")
|
||||
status = output_json["results"][0]["status"]
|
||||
print(f"status: {status}")
|
||||
#print(f"status: {status}")
|
||||
if status != "complete":
|
||||
print(f"Sleeping for {sleep_time} seconds...")
|
||||
|
||||
if status == "complete":
|
||||
print(f"{internal_ID} has been successfully shutdown!")
|
||||
list_kicked_users = []
|
||||
if str(output_json["results"][0]["shutdown_room"]["kicked_users"]) != '[]':
|
||||
print("List of kicked users:")
|
||||
for entry in output_json["results"][0]["shutdown_room"]["kicked_users"]:
|
||||
list_kicked_users.append(entry)
|
||||
print(entry)
|
||||
print("")
|
||||
else:
|
||||
print("The room was not found.")
|
||||
print(f"Failed to shutdown {internal_ID}!")
|
||||
list_kicked_users = []
|
||||
|
||||
return list_kicked_users
|
||||
|
||||
# Example:
|
||||
#$ curl -H "Authorization: Bearer ACCESS_TOKEN" --data '{ "new_room_user_id": "@PC-Admin:perthchat.org", "room_name": "VIOLATION ROOM", "message": "YOU HAVE BEEN NAUGHTY!", "block": true, "purge": true }' -X DELETE 'https://matrix.perthchat.org/_synapse/admin/v2/rooms/!yUykDcYIEtrbSxOyPD:perthchat.org'
|
||||
@ -357,7 +401,15 @@ def shutdown_multiple_rooms():
|
||||
preset_new_room_name = input("\nPlease enter the room name of the muted violation room your users will be sent to: ")
|
||||
preset_message = input("\nPlease enter the shutdown message that will be displayed to users: ")
|
||||
preset_purge_choice = input("\n Do you want to purge these rooms? (This deletes all the room history from your database.) y/n? ")
|
||||
if preset_purge_choice.lower() in ["y", "yes", "Y", "Yes"]:
|
||||
preset_purge_choice = True
|
||||
elif preset_purge_choice.lower() in ["n", "no", "N", "No"]:
|
||||
preset_purge_choice = False
|
||||
preset_block_choice = input("\n Do you want to block these rooms? (This prevents your server users re-entering the room.) y/n? ")
|
||||
if preset_block_choice.lower() in ["y", "yes", "Y", "Yes"]:
|
||||
preset_block_choice = True
|
||||
elif preset_block_choice.lower() in ["n", "no", "N", "No"]:
|
||||
preset_block_choice = False
|
||||
# Get the directory of the current script
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
room_list_data = []
|
||||
|
@ -87,7 +87,7 @@ def create_account(preset_username, preset_password):
|
||||
"password": user_password
|
||||
}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.put(url, headers=headers, data=json.dumps(data), verify=True)
|
||||
|
||||
if response.status_code == 201:
|
||||
@ -97,7 +97,9 @@ def create_account(preset_username, preset_password):
|
||||
else:
|
||||
print(f"Error creating account: {response.status_code}, {response.text}")
|
||||
|
||||
return response.text
|
||||
create_account_dict = json.loads(response.text)
|
||||
|
||||
return create_account_dict
|
||||
|
||||
# Example:
|
||||
# $ curl -kX PUT -H 'Content-Type: application/json' -d '{"password": "user_password","admin": false,"deactivated": false}' https://matrix.perthchat.org/_synapse/admin/v2/users/@billybob:perthchat.org?access_token=ACCESS_TOKEN
|
||||
@ -136,16 +138,16 @@ def reset_password(preset_username, preset_password):
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
data = {'new_password': password, 'logout_devices': True}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
|
||||
response = requests.post(url, headers=headers, data=json.dumps(data), verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.text)
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
print(f"Error resetting password: {response.status_code}, {response.text}")
|
||||
|
||||
return response.text
|
||||
reset_password_dict = json.loads(response.text)
|
||||
|
||||
return reset_password_dict
|
||||
|
||||
# Example:
|
||||
# $ curl -X POST -H 'Content-Type: application/json' -d '{"new_password": "dogpoo", "logout_devices": true}' https://matrix.perthchat.org/_synapse/admin/v1/reset_password/@dogpoo:perthchat.org?access_token=ACCESS_TOKEN
|
||||
@ -172,20 +174,20 @@ def set_user_server_admin(preset_username):
|
||||
"admin": server_admin_result
|
||||
}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.put(url, headers=headers, data=json.dumps(data), verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print("Successfully set user as server admin.")
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
print(f"Error setting user as server admin: {response.status_code}, {response.text}")
|
||||
|
||||
return response.text
|
||||
set_user_server_admin_dict = json.loads(response.text)
|
||||
|
||||
return set_user_server_admin_dict
|
||||
|
||||
# Example:
|
||||
# $ curl -kX POST -H 'Content-Type: application/json' -d '{"admin": "true"}' https://matrix.perthchat.org/_synapse/admin/v2/users/@dogpoo:perthchat.org?access_token=ACCESS_TOKEN
|
||||
|
||||
def whois_account(preset_username, output_file=None):
|
||||
def whois_account(preset_username):
|
||||
if preset_username == '':
|
||||
username = input("\nPlease enter the username you wish to whois: ")
|
||||
elif preset_username != '':
|
||||
@ -195,20 +197,11 @@ def whois_account(preset_username, output_file=None):
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_matrix/client/r0/admin/whois/@{username}:{hardcoded_variables.base_url}"
|
||||
url += f"?access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
output_text = ""
|
||||
if response.status_code == 200:
|
||||
output_text = response.text + "\n"
|
||||
else:
|
||||
output_text = f"Error retrieving account info: {response.status_code}, {response.text}\n"
|
||||
|
||||
if output_file:
|
||||
with open(output_file, 'a') as f:
|
||||
f.write(output_text)
|
||||
else:
|
||||
print(output_text)
|
||||
if response.status_code != 200:
|
||||
print(f"Error retrieving account info: {response.status_code}, {response.text}\n")
|
||||
|
||||
whois_account_dict = json.loads(response.text)
|
||||
|
||||
@ -265,9 +258,7 @@ def list_joined_rooms(preset_username):
|
||||
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.text + "\n")
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
print(f"Error querying joined rooms: {response.status_code}, {response.text}")
|
||||
|
||||
joined_rooms_dict = json.loads(response.text)
|
||||
@ -317,12 +308,10 @@ def query_account(preset_username):
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v2/users/@{username}:{hardcoded_variables.base_url}?access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.text)
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
print(f"Error querying account: {response.status_code}, {response.text}")
|
||||
|
||||
query_account_dict = json.loads(response.text)
|
||||
@ -394,12 +383,10 @@ def collect_account_data(preset_username):
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/users/@{username}:{hardcoded_variables.base_url}/accountdata?access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.text)
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
print(f"Error querying account: {response.status_code}, {response.text}")
|
||||
|
||||
account_data_dict = json.loads(response.text)
|
||||
@ -418,12 +405,10 @@ def list_account_pushers(preset_username):
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/users/@{username}:{hardcoded_variables.base_url}/pushers?access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print(response.text)
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
print(f"Error querying account: {response.status_code}, {response.text}")
|
||||
|
||||
pusher_data_dict = json.loads(response.text)
|
||||
@ -438,7 +423,7 @@ def get_rate_limit():
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/users/@{username}:{hardcoded_variables.base_url}/override_ratelimit?access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
@ -465,7 +450,7 @@ def set_rate_limit():
|
||||
"burst_count": int(burst_count)
|
||||
}
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
|
||||
response = requests.post(url, headers=headers, data=json.dumps(data), verify=True)
|
||||
|
||||
@ -484,7 +469,7 @@ def delete_rate_limit():
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/users/@{username}:{hardcoded_variables.base_url}/override_ratelimit?access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.delete(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
@ -506,15 +491,15 @@ def check_user_account_exists(preset_username):
|
||||
|
||||
url = f"https://{hardcoded_variables.homeserver_url}/_synapse/admin/v1/username_available?username={username}&access_token={hardcoded_variables.access_token}"
|
||||
|
||||
print("\n" + url + "\n")
|
||||
#print("\n" + url + "\n")
|
||||
response = requests.get(url, verify=True)
|
||||
|
||||
if response.status_code == 200:
|
||||
print("User ID is available.")
|
||||
return True
|
||||
elif response.status_code == 400:
|
||||
print(f"User ID already taken.")
|
||||
#print("User ID is available.")
|
||||
return False
|
||||
elif response.status_code == 400:
|
||||
#print(f"User ID already exists.")
|
||||
return True
|
||||
else:
|
||||
print(f"Error querying account: {response.status_code}, {response.text}")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user