@@ -280,8 +280,6 @@ def read_analytics_file(package_status_id, package_id, link, session):
280280
281281 if analytics_file_name :
282282
283- is_partial = False
284-
285283 compute_time_per_line = []
286284 for line in TextIOWrapper (zip .open (analytics_file_name )):
287285
@@ -426,7 +424,20 @@ def read_analytics_file(package_status_id, package_id, link, session):
426424
427425 compute_time_per_line .append (time .time () - compute_time_per_line_start )
428426
429- print (f'Average compute time per line: { sum (compute_time_per_line ) / len (compute_time_per_line )} ' )
427+ # When the user un-ticks "Activity history" in Discord's export
428+ # request form, Discord still ships an analytics file path but
429+ # the file is empty. Don't error — keep is_partial=True (the
430+ # default) and let the rest of the worker produce what it can:
431+ # owner profile, servers, DMs, payments, per-channel message
432+ # totals from CSVs are all still useful. The frontend reads
433+ # package_is_partial from the SQLite to know which screens to
434+ # render as N/A. Asking the user to re-export would mean a
435+ # ~30-day round-trip, so degrading gracefully is the kinder UX.
436+ if analytics_line_count > 0 :
437+ is_partial = False
438+ print (f'Average compute time per line: { sum (compute_time_per_line ) / len (compute_time_per_line )} ' )
439+ else :
440+ print ('Analytics file is empty — keeping is_partial=True; activity-driven stats will be N/A on the client.' )
430441
431442 print (f'Analytics data: { time .time () - start } ' )
432443 print (f'Session logs: { len (session_logs )} ' )
0 commit comments