1+ import json
2+ import requests
3+ import os
4+ import datetime
5+ import time
6+ from urllib .parse import urlparse
7+
8+
9+ # Function to convert Discord snowflake ID to timestamp
10+ def snowflake_to_timestamp (snowflake ):
11+ try :
12+ discord_epoch = 1420070400000
13+ timestamp = ((int (snowflake ) >> 22 ) + discord_epoch ) // 1000
14+ return timestamp
15+ except (ValueError , TypeError ):
16+ return int (datetime .datetime .now ().timestamp ())
17+
18+
19+ # Function to load existing database
20+ def load_database (file_path ):
21+ try :
22+ print (f"Loading database from { file_path } ..." )
23+ with open (file_path , 'r' ) as file :
24+ return json .load (file )
25+ except FileNotFoundError :
26+ print (f"Database file not found. Creating new database." )
27+ return {}
28+ except json .JSONDecodeError :
29+ print (f"Error parsing database file. Creating new database." )
30+ return {}
31+
32+
33+ # Function to save updated database
34+ def save_database (file_path , data ):
35+ directory = os .path .dirname (file_path )
36+ if not os .path .exists (directory ):
37+ print (f"Creating directory: { directory } " )
38+ os .makedirs (directory )
39+
40+ print (f"Saving database to { file_path } ..." )
41+ with open (file_path , 'w' ) as file :
42+ json .dump (data , file , indent = 4 )
43+ print (f"Database saved successfully." )
44+
45+
46+ # Function to ensure all entries have all required fields
47+ def normalize_entry (entry ):
48+ required_fields = ["INVITE_URL" , "FOUND_ON" , "SERVER_ID" , "REASON" ]
49+ for field in required_fields :
50+ if field not in entry :
51+ entry [field ] = "UNKNOWN"
52+ return entry
53+
54+
55+ # Function to convert old format to new format
56+ def convert_database_format (old_database ):
57+ print ("Converting database to new format..." )
58+ new_database = {}
59+ count = 1
60+ processed_urls = set ()
61+
62+ for url , data in old_database .items ():
63+ normalized_url = url .lower ()
64+ if normalized_url in processed_urls :
65+ continue
66+
67+ new_entry = {
68+ "INVITE_URL" : url ,
69+ "FOUND_ON" : data .get ("FOUND_ON" , "UNKNOWN" ),
70+ "SERVER_ID" : data .get ("SERVER_ID" , "UNKNOWN" ),
71+ "REASON" : data .get ("REASON" , "UNKNOWN" )
72+ }
73+
74+ new_database [f"DISCORD_SERVER_{ count } " ] = normalize_entry (new_entry )
75+ processed_urls .add (normalized_url )
76+ count += 1
77+
78+ print (f"Converted { count - 1 } entries to new format." )
79+ return new_database
80+
81+
82+ # Function to extract invite code from URL
83+ def extract_invite_code (url ):
84+ try :
85+ parts = url .lower ().split ("/" )
86+ return parts [- 1 ] if parts [- 1 ] else ""
87+ except :
88+ return ""
89+
90+
91+ # Function to check if invite code already exists in database
92+ def invite_code_exists_in_database (invite_code , database ):
93+ if not invite_code :
94+ return False
95+ invite_code = invite_code .lower ()
96+ for entry_data in database .values ():
97+ url = entry_data .get ("INVITE_URL" , "" ).lower ()
98+ existing_code = extract_invite_code (url )
99+ if existing_code == invite_code :
100+ return True
101+ return False
102+
103+
104+ # Function to renumber all database entries sequentially
105+ def renumber_database (database ):
106+ print ("Renumbering database entries sequentially..." )
107+ new_database = {}
108+ count = 1
109+ for _ , entry in database .items ():
110+ new_database [f"DISCORD_SERVER_{ count } " ] = entry
111+ count += 1
112+ print (f"Renumbered { len (new_database )} entries." )
113+ return new_database
114+
115+
116+ # Main function to fetch and process data
117+ def update_discord_servers_database ():
118+ start_time = time .time ()
119+ print ("Starting Discord server database update..." )
120+
121+ api_url = "https://api.phish.gg/servers/all"
122+ db_file_path = "../Database-Files/Filter-Database/Discord-Servers.json"
123+
124+ database = load_database (db_file_path )
125+
126+ # Check if old format
127+ is_old_format = any (key .startswith ("http" ) for key in database .keys ())
128+ if is_old_format :
129+ database = convert_database_format (database )
130+
131+ # Normalize entries
132+ print ("Normalizing existing entries..." )
133+ for key , entry in database .items ():
134+ database [key ] = normalize_entry (entry )
135+
136+ # Fetch from API
137+ print (f"Fetching data from { api_url } ..." )
138+ try :
139+ response = requests .get (api_url )
140+ response .raise_for_status ()
141+ servers = response .json ()
142+ print (f"Successfully fetched data: { len (servers )} servers found." )
143+ except requests .RequestException as e :
144+ print (f"Error fetching data from API: { e } " )
145+ return
146+
147+ new_entries_data = []
148+ print ("Processing server data..." )
149+ for server in servers :
150+ server_id = server .get ("serverID" , "UNKNOWN" )
151+ invite_code = server .get ("invite" , "" )
152+ reason = server .get ("reason" , "UNKNOWN" )
153+
154+ if not invite_code :
155+ continue
156+
157+ if invite_code_exists_in_database (invite_code , database ):
158+ continue
159+
160+ found_on = snowflake_to_timestamp (server_id ) if server_id != "UNKNOWN" else int (datetime .datetime .now ().timestamp ())
161+ url = f"https://discord.com/invite/{ invite_code } "
162+
163+ new_entries_data .append ({
164+ "INVITE_URL" : url ,
165+ "FOUND_ON" : found_on ,
166+ "SERVER_ID" : server_id ,
167+ "REASON" : reason
168+ })
169+
170+ # Track existing invite codes
171+ existing_invite_codes = {
172+ extract_invite_code (entry .get ("INVITE_URL" , "" ))
173+ for entry in database .values ()
174+ }
175+
176+ for entry_data in new_entries_data :
177+ invite_code = extract_invite_code (entry_data ["INVITE_URL" ])
178+ if invite_code in existing_invite_codes :
179+ continue
180+
181+ highest_num = max (
182+ [int (k .split ("_" )[- 1 ]) for k in database if k .startswith ("DISCORD_SERVER_" )],
183+ default = 0
184+ )
185+ new_key = f"DISCORD_SERVER_{ highest_num + 1 } "
186+ database [new_key ] = entry_data
187+ existing_invite_codes .add (invite_code )
188+
189+ database = renumber_database (database )
190+ save_database (db_file_path , database )
191+
192+ end_time = time .time ()
193+ print (f"Database update completed in { end_time - start_time :.2f} seconds." )
194+ print (f"Added { len (new_entries_data )} new entries." )
195+ print (f"Total entries in database: { len (database )} " )
196+
197+
198+ if __name__ == "__main__" :
199+ update_discord_servers_database ()
0 commit comments