mirror of
				https://github.com/PC-Admin/matrix-moderation-tool.git
				synced 2025-10-31 18:20:30 -04:00 
			
		
		
		
	add ipinfo function for determining an accounts country of origin, add multiple whois and query account functions
This commit is contained in:
		| @@ -4,6 +4,8 @@ | |||||||
| homeserver_url = "matrix.example.org" | homeserver_url = "matrix.example.org" | ||||||
| base_url = "example.org" | base_url = "example.org" | ||||||
| access_token = "" | access_token = "" | ||||||
|  | # ipinfo.io token | ||||||
|  | ipinfo_token = "" | ||||||
| # rdlist specific | # rdlist specific | ||||||
| rdlist_bot_username = "mod_team" | rdlist_bot_username = "mod_team" | ||||||
| ########################################################################### | ########################################################################### | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ if length_access_token == 0: | |||||||
|  |  | ||||||
| pass_token = False | pass_token = False | ||||||
| while pass_token == False: | while pass_token == False: | ||||||
| 	menu_input = input('\nPlease select one of the following options:\n#### User Account Commands ####\n1) Deactivate a user account.\n2) Deactivate multiple user accounts.\n3) Create a user account.\n4) Create multiple user accounts.\n5) Reset a users password.\n6) Whois user account.\n7) Whois multiple user accounts.\n8) List room memberships of user.\n9) Promote a user to server admin.\n10) List all user accounts.\n11) Quarantine all media a users uploaded.\n#### Room Commands ####\n12) List details of a room.\n13) Export the state events of a target room.\n14) List rooms in public directory.\n15) Remove a room from the public directory.\n16) Remove multiple rooms from the public directory.\n17) Redact a room event. (Like abusive avatars or display names.) \n18) List/Download all media in a room.\n19) Download media from multiple rooms.\n20) Quarantine all media in a room.\n21) Shutdown a room.\n22) Shutdown multiple rooms.\n23) Delete a room.\n24) Delete multiple rooms.\n25) Purge the event history of a room to a specific timestamp.\n26) Purge the event history of multiple rooms to a specific timestamp.\n#### Server Commands ####\n27) Delete and block a specific media. (Like an abusive avatar.) \n28) Purge remote media repository up to a certain date.\n29) Prepare database for copying events of multiple rooms.\n#### rdlist ####\n30) Block all rooms with specific rdlist tags.\n34) Block all rooms with recommended rdlist tags.\n(\'q\' or \'e\') Exit.\n\n') | 	menu_input = input('\nPlease select one of the following options:\n#### User Account Commands ####\n1) Deactivate a user account.\n2) Deactivate multiple user accounts.\n3) Create a user account.\n4) Create multiple user accounts.\n5) Reset a users password.\n6) Whois user account.\n7) Whois multiple user accounts.\n8) Query user account.\n9) Query multiple user accounts.\n10) List room memberships of user.\n11) Promote a user to server admin.\n12) List all user accounts.\n13) Quarantine all media a users uploaded.\n#### Room Commands ####\n14) List details of a room.\n15) Export the state events of a target room.\n16) List rooms in public directory.\n17) Remove a room from the public directory.\n18) Remove multiple rooms from the public directory.\n19) Redact a room event. (Like abusive avatars or display names.) \n20) List/Download all media in a room.\n21) Download media from multiple rooms.\n22) Quarantine all media in a room.\n23) Shutdown a room.\n24) Shutdown multiple rooms.\n25) Delete a room.\n26) Delete multiple rooms.\n27) Purge the event history of a room to a specific timestamp.\n28) Purge the event history of multiple rooms to a specific timestamp.\n#### Server Commands ####\n29) Delete and block a specific media. (Like an abusive avatar.) \n30) Purge remote media repository up to a certain date.\n31) Prepare database for copying events of multiple rooms.\n#### rdlist ####\n32) Block all rooms with specific rdlist tags.\n34) Block all rooms with recommended rdlist tags.\n#### ipinfo.io ####\n40) Analyse a users country of origin.\n41) Analyse multiple users country of origin.\n(\'q\' or \'e\') Exit.\n\n') | ||||||
| 	if menu_input == "1": | 	if menu_input == "1": | ||||||
| 		user_commands.deactivate_account('') | 		user_commands.deactivate_account('') | ||||||
| 	elif menu_input == "2": | 	elif menu_input == "2": | ||||||
| @@ -41,60 +41,68 @@ while pass_token == False: | |||||||
| 		user_commands.create_account('','') | 		user_commands.create_account('','') | ||||||
| 	elif menu_input == "4": | 	elif menu_input == "4": | ||||||
| 		user_commands.create_multiple_accounts() | 		user_commands.create_multiple_accounts() | ||||||
| 	elif menu_input == "6": | 	elif menu_input == "5": | ||||||
| 		user_commands.reset_password('','') | 		user_commands.reset_password('','') | ||||||
| 	elif menu_input == "6": | 	elif menu_input == "6": | ||||||
| 		user_commands.whois_account('') | 		user_commands.whois_account('') | ||||||
| 	elif menu_input == "7": | 	elif menu_input == "7": | ||||||
| 		user_commands.whois_multiple_accounts() | 		user_commands.whois_multiple_accounts() | ||||||
| 	elif menu_input == "8": | 	elif menu_input == "8": | ||||||
| 		user_commands.list_joined_rooms('') | 		user_commands.query_account() | ||||||
| 	elif menu_input == "9": | 	elif menu_input == "9": | ||||||
| 		user_commands.set_user_server_admin('') | 		user_commands.query_multiple_accounts() | ||||||
| 	elif menu_input == "10": | 	elif menu_input == "10": | ||||||
| 		user_commands.list_accounts() | 		user_commands.list_joined_rooms('') | ||||||
| 	elif menu_input == "11": | 	elif menu_input == "11": | ||||||
| 		user_commands.quarantine_users_media() | 		user_commands.set_user_server_admin('') | ||||||
| 	elif menu_input == "12": | 	elif menu_input == "12": | ||||||
| 		room_commands.list_room_details('') | 		user_commands.list_accounts() | ||||||
| 	elif menu_input == "13": | 	elif menu_input == "13": | ||||||
| 		room_commands.export_room_state('') | 		user_commands.quarantine_users_media() | ||||||
| 	elif menu_input == "14": | 	elif menu_input == "14": | ||||||
| 		room_commands.list_directory_rooms() | 		room_commands.list_room_details('') | ||||||
| 	elif menu_input == "15": | 	elif menu_input == "15": | ||||||
| 		room_commands.remove_room_from_directory('') | 		room_commands.export_room_state('') | ||||||
| 	elif menu_input == "16": | 	elif menu_input == "16": | ||||||
| 		room_commands.remove_multiple_rooms_from_directory() | 		room_commands.list_directory_rooms() | ||||||
| 	elif menu_input == "17": | 	elif menu_input == "17": | ||||||
| 		room_commands.redact_room_event() | 		room_commands.remove_room_from_directory('') | ||||||
| 	elif menu_input == "18": | 	elif menu_input == "18": | ||||||
| 		room_commands.list_and_download_media_in_room('','','','./') | 		room_commands.remove_multiple_rooms_from_directory() | ||||||
| 	elif menu_input == "19": | 	elif menu_input == "19": | ||||||
| 		room_commands.download_media_from_multiple_rooms() | 		room_commands.redact_room_event() | ||||||
| 	elif menu_input == "20": | 	elif menu_input == "20": | ||||||
| 		room_commands.quarantine_media_in_room() | 		room_commands.list_and_download_media_in_room('','','','./') | ||||||
| 	elif menu_input == "21": | 	elif menu_input == "21": | ||||||
| 		room_commands.shutdown_room('','','','','','') | 		room_commands.download_media_from_multiple_rooms() | ||||||
| 	elif menu_input == "22": | 	elif menu_input == "22": | ||||||
| 		room_commands.shutdown_multiple_rooms() | 		room_commands.quarantine_media_in_room() | ||||||
| 	elif menu_input == "23": | 	elif menu_input == "23": | ||||||
| 		room_commands.delete_room('') | 		room_commands.shutdown_room('','','','','','') | ||||||
| 	elif menu_input == "24": | 	elif menu_input == "24": | ||||||
| 		room_commands.delete_multiple_rooms() | 		room_commands.shutdown_multiple_rooms() | ||||||
| 	elif menu_input == "25": | 	elif menu_input == "25": | ||||||
| 		room_commands.purge_room_to_timestamp('','') | 		room_commands.delete_room('') | ||||||
| 	elif menu_input == "26": | 	elif menu_input == "26": | ||||||
| 		room_commands.purge_multiple_rooms_to_timestamp() | 		room_commands.delete_multiple_rooms() | ||||||
| 	elif menu_input == "27": | 	elif menu_input == "27": | ||||||
| 		server_commands.delete_block_media() | 		room_commands.purge_room_to_timestamp('','') | ||||||
| 	elif menu_input == "28": | 	elif menu_input == "28": | ||||||
| 		server_commands.purge_remote_media_repo() | 		room_commands.purge_multiple_rooms_to_timestamp() | ||||||
| 	elif menu_input == "29": | 	elif menu_input == "29": | ||||||
| 		server_commands.prepare_database_copy_of_multiple_rooms() | 		server_commands.delete_block_media() | ||||||
| 	elif menu_input == "30": | 	elif menu_input == "30": | ||||||
|  | 		server_commands.purge_remote_media_repo() | ||||||
|  | 	elif menu_input == "31": | ||||||
|  | 		server_commands.prepare_database_copy_of_multiple_rooms() | ||||||
|  | 	elif menu_input == "32": | ||||||
| 		rdlist_commands.block_all_rooms_with_rdlist_tags(False,'','','','','') | 		rdlist_commands.block_all_rooms_with_rdlist_tags(False,'','','','','') | ||||||
| 	elif menu_input == "34": | 	elif menu_input == "34": | ||||||
| 		rdlist_commands.block_recommended_rdlist_tags() | 		rdlist_commands.block_recommended_rdlist_tags() | ||||||
|  | 	elif menu_input == "40": | ||||||
|  | 		user_commands.analyse_account_ip('') | ||||||
|  | 	elif menu_input == "41": | ||||||
|  | 		user_commands.analyse_multiple_account_ips() | ||||||
| 	elif menu_input == "q" or menu_input == "Q" or menu_input == "e" or menu_input == "E": | 	elif menu_input == "q" or menu_input == "Q" or menu_input == "e" or menu_input == "E": | ||||||
| 		print("\nExiting...\n") | 		print("\nExiting...\n") | ||||||
| 		pass_token = True | 		pass_token = True | ||||||
|   | |||||||
							
								
								
									
										173
									
								
								user_commands.py
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								user_commands.py
									
									
									
									
									
								
							| @@ -1,9 +1,11 @@ | |||||||
|  |  | ||||||
|  | import os | ||||||
| import requests | import requests | ||||||
| import json | import json | ||||||
| import time | import time | ||||||
| import csv | import csv | ||||||
| import hardcoded_variables | import hardcoded_variables | ||||||
|  | import socket | ||||||
|  |  | ||||||
| def parse_username(username): | def parse_username(username): | ||||||
| 	tail_end = ':' + hardcoded_variables.base_url | 	tail_end = ':' + hardcoded_variables.base_url | ||||||
| @@ -183,7 +185,7 @@ def set_user_server_admin(preset_username): | |||||||
| # Example: | # 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 | # $ 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): | def whois_account(preset_username, output_file=None): | ||||||
| 	if preset_username == '': | 	if preset_username == '': | ||||||
| 		username = input("\nPlease enter the username you wish to whois: ") | 		username = input("\nPlease enter the username you wish to whois: ") | ||||||
| 	elif preset_username != '': | 	elif preset_username != '': | ||||||
| @@ -196,10 +198,17 @@ def whois_account(preset_username): | |||||||
| 	print("\n" + url + "\n") | 	print("\n" + url + "\n") | ||||||
| 	response = requests.get(url, verify=True) | 	response = requests.get(url, verify=True) | ||||||
|  |  | ||||||
|  | 	output_text = "" | ||||||
| 	if response.status_code == 200: | 	if response.status_code == 200: | ||||||
| 		print(response.text + "\n") | 		output_text = response.text + "\n" | ||||||
| 	else: | 	else: | ||||||
| 		print(f"Error retrieving account info: {response.status_code}, {response.text}\n") | 		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) | ||||||
|  |  | ||||||
| 	return response.text | 	return response.text | ||||||
|  |  | ||||||
| @@ -207,24 +216,110 @@ def whois_account(preset_username): | |||||||
| # $ curl -kXGET https://matrix.perthchat.org/_matrix/client/r0/admin/whois/@PC-Admin:perthchat.org?access_token=ACCESS_TOKEN | # $ curl -kXGET https://matrix.perthchat.org/_matrix/client/r0/admin/whois/@PC-Admin:perthchat.org?access_token=ACCESS_TOKEN | ||||||
|  |  | ||||||
| def whois_multiple_accounts(): | def whois_multiple_accounts(): | ||||||
| 	print("Whois multiple user accounts selected") |     print("Whois multiple user accounts selected") | ||||||
| 	user_list_location = input("\nPlease enter the path of the file containing a newline seperated list of Matrix usernames: ") |     user_list_location = input("\nPlease enter the path of the file containing a newline seperated list of Matrix usernames: ") | ||||||
| 	with open(user_list_location, newline='') as f: |     with open(user_list_location, newline='') as f: | ||||||
| 		reader = csv.reader(f) |         reader = csv.reader(f) | ||||||
| 		data = list(reader) |         data = list(reader) | ||||||
| 		print(len(data)) |         print(len(data)) | ||||||
| 	whois_confirmation = input("\n" + str(data) + "\n\nAre you sure you want to whois all of these users? y/n?\n") |  | ||||||
| 	if whois_confirmation == "y" or whois_confirmation == "Y" or whois_confirmation == "yes" or whois_confirmation == "Yes":   |     print("\n" + str(data)) | ||||||
| 		x = 0 |  | ||||||
| 		while x <= (len(data) - 1): |     output_file = None | ||||||
| 			print(data[x][0]) |     if len(data) > 10: | ||||||
| 			query_account(data[x][0]) |         file_confirmation = input("\nThere are more than 10 users. Would you like to save the output to a file? y/n?\n") | ||||||
| 			list_joined_rooms(data[x][0]) |         if file_confirmation.lower() in ("y", "yes"): | ||||||
| 			x += 1 |             output_file = input("\nPlease enter the desired output file path:\n") | ||||||
| 			#print(x) |  | ||||||
| 			time.sleep(1) |     whois_confirmation = input("\n\nAre you sure you want to whois all of these users? y/n?\n") | ||||||
| 	if whois_confirmation == "n" or whois_confirmation == "N" or whois_confirmation == "no" or whois_confirmation == "No": |  | ||||||
| 		print("\nExiting...\n") |     if whois_confirmation.lower() in ("y", "yes"):   | ||||||
|  |         x = 0 | ||||||
|  |         while x <= (len(data) - 1): | ||||||
|  |             output = whois_account(data[x][0]) | ||||||
|  |  | ||||||
|  |             # if output file is specified, append to file | ||||||
|  |             if output_file: | ||||||
|  |                 with open(output_file, 'a') as f: | ||||||
|  |                     f.write(output + "\n") | ||||||
|  |             x += 1 | ||||||
|  |             time.sleep(1) | ||||||
|  |  | ||||||
|  |     if whois_confirmation.lower() in ("n", "no"): | ||||||
|  |         print("\nExiting...\n") | ||||||
|  |  | ||||||
|  |     if output_file and os.path.isfile(output_file): | ||||||
|  |         print(f"Output saved to {output_file}") | ||||||
|  |  | ||||||
|  | def is_valid_ipv4(ip): | ||||||
|  |     try: | ||||||
|  |         socket.inet_pton(socket.AF_INET, ip) | ||||||
|  |     except socket.error:  # not a valid address | ||||||
|  |         return False | ||||||
|  |     return True | ||||||
|  |  | ||||||
|  | def analyse_account_ip(preset_username): | ||||||
|  |     if not preset_username: | ||||||
|  |         preset_username = input("\nPlease enter a username to analyse their country of origin: ") | ||||||
|  |     user_info = whois_account(preset_username=preset_username) | ||||||
|  |  | ||||||
|  |     data = json.loads(user_info) | ||||||
|  |      | ||||||
|  |     user_id = data['user_id'] | ||||||
|  |     #print(f'user_id: {user_id}') | ||||||
|  |     device_data = data['devices'] | ||||||
|  |     #print(f'device_data: {device_data}') | ||||||
|  |  | ||||||
|  |     countries = [] | ||||||
|  |     for device_id, device_info in device_data.items(): | ||||||
|  |         for session in device_info['sessions']: | ||||||
|  |             for connection in session['connections']: | ||||||
|  |                 ip = connection['ip'] | ||||||
|  |                 if is_valid_ipv4(ip): | ||||||
|  |                     res = requests.get(f"https://ipinfo.io/{ip}",  | ||||||
|  |                                        headers={"Authorization": f"Bearer {hardcoded_variables.ipinfo_token}"}) | ||||||
|  |                     if res.status_code == 200: | ||||||
|  |                         country = res.json().get('country') | ||||||
|  |                         countries.append(country) | ||||||
|  |  | ||||||
|  |     print(f"User: {user_id} from Countries: {countries}") | ||||||
|  |     return(f"User: {user_id} from Countries: {countries}") | ||||||
|  |  | ||||||
|  | def analyse_multiple_account_ips(): | ||||||
|  |     print("Analyse multiple user IPs selected") | ||||||
|  |     user_list_location = input("\nPlease enter the path of the file containing a newline seperated list of Matrix usernames: ") | ||||||
|  |     with open(user_list_location, newline='') as f: | ||||||
|  |         reader = csv.reader(f) | ||||||
|  |         data = list(reader) | ||||||
|  |         print(len(data)) | ||||||
|  |  | ||||||
|  |     print("\n" + str(data)) | ||||||
|  |  | ||||||
|  |     output_file = None | ||||||
|  |     if len(data) > 10: | ||||||
|  |         file_confirmation = input("\nThere are more than 10 users. Would you like to save the output to a file? y/n?\n") | ||||||
|  |         if file_confirmation.lower() in ("y", "yes"): | ||||||
|  |             output_file = input("\nPlease enter the desired output file path:\n") | ||||||
|  |  | ||||||
|  |     analyse_confirmation = input("\n\nAre you sure you want to analyse the IP of all of these users? y/n?\n") | ||||||
|  |  | ||||||
|  |     if analyse_confirmation.lower() in ("y", "yes"):   | ||||||
|  |         x = 0 | ||||||
|  |         while x <= (len(data) - 1): | ||||||
|  |             output = analyse_account_ip(data[x][0]) | ||||||
|  |  | ||||||
|  |             # if output file is specified, append to file | ||||||
|  |             if output_file: | ||||||
|  |                 with open(output_file, 'a') as f: | ||||||
|  |                     f.write(output + "\n") | ||||||
|  |             x += 1 | ||||||
|  |             time.sleep(1) | ||||||
|  |  | ||||||
|  |     if analyse_confirmation.lower() in ("n", "no"): | ||||||
|  |         print("\nExiting...\n") | ||||||
|  |  | ||||||
|  |     if output_file and os.path.isfile(output_file): | ||||||
|  |         print(f"Output saved to {output_file}") | ||||||
|  |  | ||||||
| def list_joined_rooms(preset_username): | def list_joined_rooms(preset_username): | ||||||
| 	if preset_username == '': | 	if preset_username == '': | ||||||
| @@ -299,6 +394,42 @@ def query_account(preset_username): | |||||||
| # Example: | # Example: | ||||||
| # $ curl -kX GET https://matrix.perthchat.org/_synapse/admin/v2/users/@billybob:perthchat.org?access_token=ACCESS_TOKEN | # $ curl -kX GET https://matrix.perthchat.org/_synapse/admin/v2/users/@billybob:perthchat.org?access_token=ACCESS_TOKEN | ||||||
|  |  | ||||||
|  | def query_multiple_accounts(): | ||||||
|  |     print("Query multiple user accounts selected") | ||||||
|  |     user_list_location = input("\nPlease enter the path of the file containing a newline seperated list of Matrix usernames: ") | ||||||
|  |     with open(user_list_location, newline='') as f: | ||||||
|  |         reader = csv.reader(f) | ||||||
|  |         data = list(reader) | ||||||
|  |         print(len(data)) | ||||||
|  |  | ||||||
|  |     print("\n" + str(data)) | ||||||
|  |  | ||||||
|  |     output_file = None | ||||||
|  |     if len(data) > 10: | ||||||
|  |         file_confirmation = input("\nThere are more than 10 users. Would you like to save the output to a file? y/n?\n") | ||||||
|  |         if file_confirmation.lower() in ("y", "yes"): | ||||||
|  |             output_file = input("\nPlease enter the desired output file path:\n") | ||||||
|  |  | ||||||
|  |     query_confirmation = input("\n\nAre you sure you want to query all of these users? y/n?\n") | ||||||
|  |  | ||||||
|  |     if query_confirmation.lower() in ("y", "yes"):   | ||||||
|  |         x = 0 | ||||||
|  |         while x <= (len(data) - 1): | ||||||
|  |             output = query_account(data[x][0]) | ||||||
|  |  | ||||||
|  |             # if output file is specified, append to file | ||||||
|  |             if output_file: | ||||||
|  |                 with open(output_file, 'a') as f: | ||||||
|  |                     f.write(output + "\n") | ||||||
|  |             x += 1 | ||||||
|  |             time.sleep(1) | ||||||
|  |  | ||||||
|  |     if query_confirmation.lower() in ("n", "no"): | ||||||
|  |         print("\nExiting...\n") | ||||||
|  |  | ||||||
|  |     if output_file and os.path.isfile(output_file): | ||||||
|  |         print(f"Output saved to {output_file}") | ||||||
|  |  | ||||||
| def quarantine_users_media(): | def quarantine_users_media(): | ||||||
| 	username = input("\nPlease enter the username of the user who's media you want to quarantine: ") | 	username = input("\nPlease enter the username of the user who's media you want to quarantine: ") | ||||||
| 	username = parse_username(username) | 	username = parse_username(username) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user