@@ -1362,8 +1362,12 @@ def api_status(): # type: ignore
13621362 data = apply_privacy_substitutions (data ) # substitute everything else
13631363 substituted_targets = {}
13641364 for username , t_data in raw_targets .items ():
1365- substituted_t_data = apply_privacy_substitutions (t_data ) if isinstance (t_data , dict ) else t_data
1366- substituted_t_data ['display_name' ] = apply_privacy_substitutions (username )
1365+ if isinstance (t_data , dict ):
1366+ substituted_t_data = apply_privacy_substitutions (t_data )
1367+ substituted_t_data ['display_name' ] = apply_privacy_substitutions (username )
1368+ else :
1369+ # Non-dict target payload: pass through unchanged, can't attach display_name
1370+ substituted_t_data = t_data
13671371 substituted_targets [username ] = substituted_t_data
13681372 data ['targets' ] = substituted_targets
13691373 else :
@@ -3757,7 +3761,9 @@ def apply_privacy_substitutions(content: TPrivacyContent) -> TPrivacyContent:
37573761 """
37583762 - Recurses into dict values and list items
37593763 - For strings, performs search/replace using PRIVACY_SUBSTITIONS
3760- - Preserves dictionary keys to keep API object identity stable
3764+ - Preserves dict keys so JSON and object keys stay stable for API
3765+ consumers. Callers that display a key (e.g. terminal target tables)
3766+ must substitute it explicitly at the point of display
37613767 - Ignores invalid substitution entries to avoid runtime crashes
37623768 - Non-string primitives are returned unchanged
37633769 """
@@ -3783,10 +3789,7 @@ def apply_privacy_substitutions(content: TPrivacyContent) -> TPrivacyContent:
37833789 content_str = content_str .replace (search , replace )
37843790 return cast (TPrivacyContent , content_str )
37853791 if isinstance (content , dict ):
3786- return cast (TPrivacyContent , {
3787- apply_privacy_substitutions (k ) if isinstance (k , str ) else k : apply_privacy_substitutions (v )
3788- for k , v in content .items ()
3789- })
3792+ return cast (TPrivacyContent , {k : apply_privacy_substitutions (v ) for k , v in content .items ()})
37903793 if isinstance (content , list ):
37913794 return cast (TPrivacyContent , [apply_privacy_substitutions (item ) for item in content ])
37923795 return content
@@ -5381,6 +5384,8 @@ def generate_dashboard_targets_table(target_data):
53815384
53825385 now_ts = datetime .now ().timestamp ()
53835386 for target , data in target_data .items ():
5387+ # Substitute the displayed target name here. Dict keys stay real upstream so API consumers keep stable keys
5388+ display_target = apply_privacy_substitutions (target )
53845389 status_val = data .get ('status' , 'Unknown' )
53855390 status_style = "green" if status_val == 'OK' else "yellow" if status_val in ('Checking' , 'Starting' , 'Loading Profile' , 'Fetching Reels' ) else "blue"
53865391
@@ -5408,7 +5413,7 @@ def generate_dashboard_targets_table(target_data):
54085413 next_chk = get_squeezed_date_from_ts (next_ts , show_seconds = DASHBOARD_SHOW_CHECK_SECONDS )
54095414
54105415 table .add_row (
5411- target ,
5416+ display_target ,
54125417 visibility ,
54135418 str (data .get ('followers' ) if data .get ('followers' ) is not None else '-' ),
54145419 str (data .get ('following' ) if data .get ('following' ) is not None else '-' ),
0 commit comments