@@ -61,6 +61,58 @@ def count_sentiments(contents):
6161 sentiments .append (score )
6262 return sum (sentiments ) / len (sentiments ) if len (sentiments ) > 0 else 0
6363
64+ def find_user_root (zip_namelist ):
65+ """
66+ Find the root path for user.json in the package.
67+ This handles cases where the folder might be translated (e.g., 'Compte/user.json' in French).
68+ """
69+ # Look for any direct user.json file in the root of a folder
70+ user_path = next ((name for name in zip_namelist if re .match (r'^[^/]+/user\.json$' , name )), None )
71+ if user_path :
72+ return user_path .split ('/' )[0 ]
73+ return None
74+
75+ def find_messages_root (zip_namelist ):
76+ """
77+ Find the root path for Messages folder in the package.
78+ This handles cases where the folder might be translated.
79+ """
80+ # Find any channel.json inside a numbered folder
81+ sample = next ((name for name in zip_namelist if re .search (r'/c?[0-9]{16,32}/channel\.json$' , name )), None )
82+ if sample :
83+ # Remove the channel ID and file name to get the root
84+ segments = sample .split ('/' )
85+ return '/' .join (segments [:- 2 ])
86+ return None
87+
88+ def find_servers_root (zip_namelist ):
89+ """
90+ Find the root path for Servers folder in the package.
91+ This handles cases where the folder might be translated.
92+ """
93+ # Find guild.json or index.json that contains server data
94+ sample = next ((name for name in zip_namelist if re .search (r'/[0-9]{16,32}/guild\.json$' , name )), None )
95+ if sample :
96+ # Remove the guild ID and file name to get the root
97+ segments = sample .split ('/' )
98+ return '/' .join (segments [:- 2 ])
99+
100+ # Try to find the index.json file in any folder that might be for servers
101+ server_index = next ((name for name in zip_namelist if name .endswith ('/index.json' )
102+ and not (name .startswith ('Messages/' ) or name .startswith ('messages/' ))), None )
103+ if server_index :
104+ return '/' .join (server_index .split ('/' )[:- 1 ])
105+
106+ return None
107+
108+ def find_analytics_file (zip_namelist ):
109+ """
110+ Find the analytics file in the package.
111+ This handles cases where the folder might be translated.
112+ """
113+ # Look for any JSON file in a folder that could be analytics
114+ return next ((name for name in zip_namelist if re .search (r'/analytics.*\.json$' , name )), None )
115+
64116app = Celery (config_source = 'celeryconfig' )
65117
66118def download_file (package_status_id , package_id , link , session ):
@@ -156,9 +208,14 @@ def read_analytics_file(package_status_id, package_id, link, session):
156208 All this data will be useful to parse more complex things later.
157209 '''
158210
159- user_path = 'Account/user.json'
160- if user_path not in zip .namelist () and 'account/user.json' in zip .namelist ():
161- user_path = 'account/user.json'
211+ user_path = find_user_root (zip .namelist ())
212+ if not user_path :
213+ # Fallback to traditional paths
214+ user_path = 'Account/user.json'
215+ if user_path not in zip .namelist () and 'account/user.json' in zip .namelist ():
216+ user_path = 'account/user.json'
217+ else :
218+ user_path = f'{ user_path } /user.json'
162219 user_content = zip .open (user_path )
163220 user_json = orjson .loads (user_content .read ())
164221 user_data = {
@@ -194,7 +251,7 @@ def read_analytics_file(package_status_id, package_id, link, session):
194251 We read it line by line (each line is a JSON object).
195252 '''
196253
197- analytics_file_name = next (( name for name in zip .namelist () if ( name . startswith ( 'Activity/analytics' ) or name . startswith ( 'activity/analytics' )) and name . endswith ( '.json' )), None )
254+ analytics_file_name = find_analytics_file ( zip .namelist ())
198255
199256 if analytics_file_name :
200257
@@ -354,9 +411,15 @@ def read_analytics_file(package_status_id, package_id, link, session):
354411 This will be used later to get the guild name from the guild_id.
355412 '''
356413
357- server_path = 'Servers/index.json'
358- if server_path not in zip .namelist () and 'servers/index.json' in zip .namelist ():
359- server_path = 'servers/index.json'
414+ namelist = zip .namelist ()
415+ servers_root = find_servers_root (namelist )
416+ if not servers_root :
417+ server_path = 'Servers/index.json'
418+ if server_path not in namelist and 'servers/index.json' in namelist :
419+ server_path = 'servers/index.json'
420+ else :
421+ server_path = f'{ servers_root } /index.json'
422+
360423 server_content = zip .open (server_path )
361424 server_json = orjson .loads (server_content .read ())
362425 for guild_id in server_json :
@@ -370,9 +433,14 @@ def read_analytics_file(package_status_id, package_id, link, session):
370433 This will be used later to get the channel name from the channel_id (or to check whether it is a DM or a Guild Channel).
371434 '''
372435
373- message_index_path = 'Messages/index.json'
374- if message_index_path not in zip .namelist () and 'messages/index.json' in zip .namelist ():
375- message_index_path = 'messages/index.json'
436+ messages_root = find_messages_root (namelist )
437+ if not messages_root :
438+ message_index_path = 'Messages/index.json'
439+ if message_index_path not in namelist and 'messages/index.json' in namelist :
440+ message_index_path = 'messages/index.json'
441+ else :
442+ message_index_path = f'{ messages_root } /index.json'
443+
376444 message_index_content = zip .open (message_index_path )
377445 message_index_json = orjson .loads (message_index_content .read ())
378446 for channel_id in message_index_json :
@@ -404,7 +472,14 @@ def read_analytics_file(package_status_id, package_id, link, session):
404472 compute_times = []
405473 compute_1_times = []
406474 compute_2_times = []
407- channel_json_files = [file_name for file_name in namelist if (file_name .startswith ('Messages/' ) or file_name .startswith ('messages/' )) and file_name .endswith ('channel.json' )]
475+
476+ # If we have a messages root path, use it for more precise filtering
477+ if messages_root :
478+ channel_json_files = [file_name for file_name in namelist if file_name .startswith (f'{ messages_root } /' ) and file_name .endswith ('channel.json' )]
479+ else :
480+ # Fallback to checking any potential messages folders
481+ channel_json_files = [file_name for file_name in namelist if (file_name .startswith ('Messages/' ) or file_name .startswith ('messages/' )) and file_name .endswith ('channel.json' )]
482+
408483 print (f'Found { len (channel_json_files )} channel files' )
409484 for channel_json_file in channel_json_files :
410485 read_time_start = time .time ()
@@ -415,14 +490,28 @@ def read_analytics_file(package_status_id, package_id, link, session):
415490 channel_json = orjson .loads (channel_content .read ())
416491 read_time_diff = time .time () - read_time_start
417492 read_json_times .append (read_time_diff )
418- channel_id = re .match (r'(?:Messages|messages)\/c?([0-9]{16,32})\/' , channel_json_file ).group (1 )
419- # new package includes 'c' before the channel id
420- is_new_package = channel_json_file .startswith ('Messages/c' ) or channel_json_file .startswith ('messages/c' )
421- read_time_start = time .time ()
422- messages_folder = 'Messages' if channel_json_file .startswith ('Messages/' ) else 'messages'
423- ch_msgs_file_name = f'{ messages_folder } /{ "c" if is_new_package else "" } { channel_id } /messages.json'
493+
494+ # Extract channel ID with a more flexible regex pattern that handles any path structure
495+ channel_id_match = re .search (r'/c?([0-9]{16,32})/' , channel_json_file )
496+ if not channel_id_match :
497+ continue
498+
499+ channel_id = channel_id_match .group (1 )
500+
501+ # Determine if 'c' prefix is used before channel IDs
502+ channel_path_parts = channel_json_file .split ('/' )
503+ channel_dir = channel_path_parts [- 2 ] # Get the directory containing channel.json
504+ is_new_package = channel_dir .startswith ('c' )
505+
506+ # Get the path up to the numbered directory
507+ base_path = '/' .join (channel_path_parts [:- 2 ])
508+
509+ # Construct message file path based on the channel file path structure
510+ ch_msgs_file_name = f'{ base_path } /{ "c" if is_new_package else "" } { channel_id } /messages.json'
424511 if ch_msgs_file_name not in namelist :
425512 continue
513+
514+ read_time_start = time .time ()
426515 message_content = zip .open (ch_msgs_file_name )
427516 read_time_diff = time .time () - read_time_start
428517 read_channel_times .append (read_time_diff )
0 commit comments