1+ import json
2+ import time
3+ from datetime import datetime
4+
5+ # Constants
6+ JSON_FILE_PATH = "../Database-Files/Edit-Database/Compromised-Discord-Accounts.json"
7+
8+
9+ # ======================
10+ # Utility Functions
11+ # ======================
12+
13+ def print_header (title ):
14+ """Print a formatted header for tool sections."""
15+ print (f"\n { '=' * 50 } " )
16+ print (f"{ title .upper ():^50} " )
17+ print (f"{ '=' * 50 } \n " )
18+
19+
20+ def log_message (message ):
21+ """Print formatted log messages with timestamp."""
22+ print (f"[{ datetime .now ().strftime ('%Y-%m-%d %H:%M:%S' )} ] { message } " )
23+
24+
25+ # ======================
26+ # Tool Functions
27+ # ======================
28+
29+ def chronological_case_sorter ():
30+ """Sort cases chronologically by FOUND_ON date (Tool-02)."""
31+ print_header ("chronological case sorter" )
32+
33+ # Load existing data from the JSON file
34+ log_message ("Loading JSON data..." )
35+ try :
36+ with open (JSON_FILE_PATH , "r" , encoding = "utf-8" ) as file :
37+ data = json .load (file )
38+ except FileNotFoundError :
39+ log_message ("JSON file not found. Exiting." )
40+ return
41+ except Exception as e :
42+ log_message (f"Error loading JSON file: { str (e )} " )
43+ return
44+
45+ # Convert data into a list of tuples (key, value) and sort by date
46+ log_message ("Sorting cases by date..." )
47+ date_count = 0
48+ unknown_dates = 0
49+
50+ def parse_date (account ):
51+ nonlocal date_count , unknown_dates
52+ date_str = account .get ("FOUND_ON" , "Unknown" )
53+ if date_str == "Unknown" :
54+ unknown_dates += 1
55+ return datetime .min # Assign minimum date for unknown values
56+ try :
57+ date_count += 1
58+ return datetime .strptime (date_str , "%Y-%m-%d" )
59+ except ValueError :
60+ unknown_dates += 1
61+ return datetime .min
62+
63+ sorted_data = dict (sorted (data .items (), key = lambda item : parse_date (item [1 ])))
64+
65+ # Print sorting statistics
66+ log_message (f"Total dates found: { date_count + unknown_dates } " )
67+ log_message (f"Dates sorted: { date_count } " )
68+ log_message (f"Unknown dates: { unknown_dates } " )
69+
70+ # Write the sorted data back to the JSON file
71+ log_message ("Saving sorted JSON data..." )
72+ try :
73+ with open (JSON_FILE_PATH , "w" , encoding = "utf-8" ) as file :
74+ json .dump (sorted_data , file , indent = 4 , ensure_ascii = False )
75+ log_message ("Sorting complete." )
76+ except Exception as e :
77+ log_message (f"Error saving JSON file: { str (e )} " )
78+
79+
80+ def case_number_normalizer ():
81+ """Normalize case numbers and account keys (Tool-03)."""
82+ print_header ("case number normalizer" )
83+
84+ def get_current_timestamp ():
85+ return datetime .now ().strftime ("%Y-%m-%d %H:%M:%S" )
86+
87+ log_message (f"Starting to fix account numbers in the file: { JSON_FILE_PATH } " )
88+
89+ try :
90+ with open (JSON_FILE_PATH , "r" , encoding = "utf-8" ) as f :
91+ data = json .load (f )
92+ log_message ("Successfully loaded the data from the file." )
93+ except Exception as e :
94+ log_message (f"Error loading the file: { e } " )
95+ return
96+
97+ total_accounts = len (data )
98+ updated_count = 0
99+ updated_data = {}
100+
101+ # Iterate through the accounts and update both the keys and the CASE_NUMBER
102+ for index , (old_key , account ) in enumerate (data .items (), start = 1 ):
103+ # Generate the new key (e.g., ACCOUNT_NUMBER_1, ACCOUNT_NUMBER_2, etc.)
104+ new_key = f"ACCOUNT_NUMBER_{ index } "
105+
106+ # Remove the 'ACCOUNT_NUMBER_' field if it exists
107+ if "ACCOUNT_NUMBER_" in account :
108+ del account ["ACCOUNT_NUMBER_" ]
109+
110+ # Update the 'CASE_NUMBER' field
111+ if account ["CASE_NUMBER" ] != str (index ): # If the CASE_NUMBER is incorrect
112+ updated_count += 1
113+ account ["CASE_NUMBER" ] = str (index )
114+
115+ # Add the updated account data with the new key to the updated_data dictionary
116+ updated_data [new_key ] = account
117+
118+ try :
119+ with open (JSON_FILE_PATH , "w" , encoding = "utf-8" ) as f :
120+ json .dump (updated_data , f , indent = 4 , ensure_ascii = False )
121+ log_message ("Successfully saved the corrected data back to the file." )
122+ except Exception as e :
123+ log_message (f"Error saving the file: { e } " )
124+ return
125+
126+ log_message (f"Found { total_accounts } accounts in the file." )
127+ log_message (f"{ updated_count } accounts were updated." )
128+
129+
130+ # ======================
131+ # Main Menu
132+ # ======================
133+
134+ def display_menu ():
135+ """Display the main menu and get user choice."""
136+ print ("\n " + "=" * 50 )
137+ print ("CASE MANAGEMENT TOOL" .center (50 ))
138+ print ("=" * 50 )
139+ print ("\n Main Menu:" )
140+ print ("1. Run All Tools (Full Processing)" )
141+ print ("2. Chronological Case Sorter" )
142+ print ("3. Case Number Normalizer" )
143+ print ("4. Exit" )
144+
145+ while True :
146+ choice = input ("\n Enter your choice (1-4): " )
147+ if choice .isdigit () and 1 <= int (choice ) <= 4 :
148+ return int (choice )
149+ print ("Invalid input. Please enter a number between 1 and 4." )
150+
151+
152+ def main ():
153+ """Main function to run the combined tool."""
154+ while True :
155+ choice = display_menu ()
156+
157+ if choice == 1 : # Run all tools
158+ print_header ("running all tools" )
159+ chronological_case_sorter ()
160+ case_number_normalizer ()
161+ print_header ("all tools completed" )
162+ elif choice == 2 :
163+ chronological_case_sorter ()
164+ elif choice == 3 :
165+ case_number_normalizer ()
166+ elif choice == 4 :
167+ print ("\n Exiting the program. Goodbye!" )
168+ break
169+
170+ input ("\n Press Enter to return to the main menu..." )
171+
172+
173+ if __name__ == "__main__" :
174+ main ()
0 commit comments