Ë
    Ì
âi‰h  ã                   óN  — d Z ddlZddlZddlmZ ddlmZmZmZm	Z	 ddl
mZ e G d„ d«      «       Ze G d„ d	«      «       Z G d
„ d«      Zedk(  rV ee«      j"                  j"                  j"                  Z e ee«      «      Zej+                  «       Zej/                  e«       yy)zT
API Analyzer - Analyzes backend API endpoints and compares with frontend API calls
é    N)ÚPath)ÚDictÚListÚSetÚTuple)Ú	dataclassc                   ó:   — e Zd ZU dZeed<   eed<   eed<   eed<   y)ÚAPIEndpointzRepresents an API endpointÚpathÚmethodÚfileÚlineN©Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚstrÚ__annotations__Úint© ó    ú7/home/factor_ks/STREAMA2026/tests/utils/api_analyzer.pyr
   r
      s   … á$Ø
ƒIØƒKØ
ƒIØ
„Ir   r
   c                   ó:   — e Zd ZU dZeed<   eed<   eed<   eed<   y)ÚAPICallz"Represents an API call in frontendr   r   r   r   Nr   r   r   r   r   r      s   … á,Ø
ƒIØƒKØ
ƒIØ
„Ir   r   c                   ó>  — e Zd ZdZdefd„Zdeeee   f   fd„Z	de
dee   fd„Zdeeee   f   fd„Zd	e
dee   fd
„Zdeeef   fd„Zdee   fd„Zdeeee   f   defd„Zdee   fd„Zdee   fd„Zdee   fd„Zdee   fd„Zdefd„Zdefd„Zdeeef   fd„Zy)ÚAPIAnalyzerz>Analyzes API endpoints and frontend calls to detect mismatchesÚproject_dirc                 óº   — t        |«      | _        | j                  dz  dz  dz  | _        | j                  dz  dz  | _        | j                  dz  dz  dz  | _        y )	NÚbackendÚappÚapiÚfrontendÚsrcÚtestsÚutilsz.api_baseline.json)r   r   Úbackend_api_dirÚfrontend_src_dirÚbaseline_file)Úselfr   s     r   Ú__init__zAPIAnalyzer.__init__    sb   € Ü Ó,ˆÔØ#×/Ñ/°)Ñ;¸eÑCÀeÑKˆÔØ $× 0Ñ 0°:Ñ =ÀÑ EˆÔØ!×-Ñ-°Ñ7¸'ÑAÐDXÑXˆÕr   Úreturnc                 ó8  — i }| j                   j                  «       s|S | j                   j                  d«      D ]e  }|j                  dk(  rŒ| j	                  |«      }|D ]=  }|j
                  |vrg ||j
                  <   ||j
                     j                  |«       Œ? Œg | j                  dz  dz  dz  }|j                  «       rS| j	                  |«      }|D ]=  }|j
                  |vrg ||j
                  <   ||j
                     j                  |«       Œ? |S )z2Analyze backend API files to extract all endpointsz*.pyz__init__.pyr    r!   zmain.py)r'   ÚexistsÚglobÚnameÚ_extract_endpointsr   Úappendr   )r*   Ú	endpointsÚapi_fileÚfile_endpointsÚendpointÚ	main_files         r   Úanalyze_backend_endpointsz%APIAnalyzer.analyze_backend_endpoints&   s   € àˆ	à×#Ñ#×*Ñ*Ô,ØÐð ×,Ñ,×1Ñ1°&Ó9ò 	:ˆHØ�}‰} Ò-Øà!×4Ñ4°XÓ>ˆNØ*ò :�Ø—=‘=¨	Ñ1Ø/1�I˜hŸm™mÑ,Ø˜(Ÿ-™-Ñ(×/Ñ/°Õ9ñ:ð	:ð ×$Ñ$ yÑ0°5Ñ8¸9ÑDˆ	Ø×ÑÔØ!×4Ñ4°YÓ?ˆNØ*ò :�Ø—=‘=¨	Ñ1Ø/1�I˜hŸm™mÑ,Ø˜(Ÿ-™-Ñ(×/Ñ/°Õ9ð:ð
 Ðr   r4   c                 ó   — g }	 t        |dd¬«      5 }|j                  «       }ddd«       d}t        j                  |«      }|r|j	                  d«      nd}d}t        j
                  ||«      D ]¡  }	|	j	                  d«      j                  «       }
|	j	                  d	«      }|r|› |› �n|}|d|	j                  «        j                  d
«      dz   }|j                  t        ||
t        |j                  | j                  «      «      |¬«      «       Œ£ d}t        j
                  ||«      D ]™  }	|	j	                  d«      j                  «       }
|	j	                  d	«      }|}|d|	j                  «        j                  d
«      dz   }|j                  t        ||
t        |j                  | j                  «      «      |¬«      «       Œ› |S # 1 sw Y   �Œ©xY w# t        $ r}t        d|› d|› �«       g cY d}~S d}~ww xY w)z-Extract API endpoints from a backend API fileÚrúutf-8©ÚencodingNz;router\s*=\s*APIRouter\(.*?prefix\s*=\s*["\']([^"\']+)["\']é   Ú z?@router\.(get|post|put|delete|patch)\s*\(\s*["\']([^"\']*)["\']é   Ú
©r   r   r   r   z<@app\.(get|post|put|delete|patch)\s*\(\s*["\']([^"\']*)["\']úError analyzing ú: )ÚopenÚreadÚreÚsearchÚgroupÚfinditerÚupperÚstartÚcountr2   r
   r   Úrelative_tor   Ú	ExceptionÚprint)r*   r4   r3   ÚfÚcontentÚprefix_patternÚprefix_matchÚprefixÚrouter_patternÚmatchr   r   Ú	full_pathÚline_numÚapp_patternÚes                   r   r1   zAPIAnalyzer._extract_endpointsC   sï  € àˆ	ð2	Ü�h ¨gÔ6ð #¸!ØŸ&™&›(�÷#ð \ˆNÜŸ9™9 ^°WÓ=ˆLÙ.:�\×'Ñ'¨Ô*ÀˆFð
 `ˆNäŸ™ ^°WÓ=ò �ØŸ™ Q›×-Ñ-Ó/�Ø—{‘{ 1“~�á17˜v˜h t fÑ-¸T�	Ø" > E§K¡K£MÐ2×8Ñ8¸Ó>ÀÑB�à× Ñ ¤Ø"Ø!Ü˜X×1Ñ1°$×2BÑ2BÓCÓDØ!ô	"õ ðð  ZˆKäŸ™ [°'Ó:ò �ØŸ™ Q›×-Ñ-Ó/�Ø—{‘{ 1“~�à �	Ø" > E§K¡K£MÐ2×8Ñ8¸Ó>ÀÑB�à× Ñ ¤Ø"Ø!Ü˜X×1Ñ1°$×2BÑ2BÓCÓDØ!ô	"õ ðð Ð÷[#ñ #ûô^ ò 	ÜÐ$ X J¨b°°Ð4Ô5Ø�Iûð	ús4   „G ’G
£F&G Ç
GÇG Ç	G=Ç G8Ç2G=Ç8G=c                 ór  — i }| j                   j                  «       s|S | j                   j                  d«      D ]n  }|j                  j	                  d«      rŒ| j                  |«      }|D ]:  }|j                  › d|j                  › �}||vrg ||<   ||   j                  |«       Œ< Œp | j                   j                  d«      D ]n  }|j                  j	                  d«      rŒ| j                  |«      }|D ]:  }|j                  › d|j                  › �}||vrg ||<   ||   j                  |«       Œ< Œp |S )z/Analyze frontend files to extract all API callsú*.tsú.d.tsú:ú*.tsx)	r(   r.   Úrglobr0   ÚendswithÚ_extract_api_callsr   r   r2   )r*   ÚcallsÚfrontend_fileÚ
file_callsÚcallÚkeys         r   Úanalyze_frontend_callsz"APIAnalyzer.analyze_frontend_calls{   sK  € àˆà×$Ñ$×+Ñ+Ô-ØˆLð "×2Ñ2×8Ñ8¸Ó@ò 		(ˆMØ×!Ñ!×*Ñ*¨7Ô3Øà×0Ñ0°Ó?ˆJØ"ò (�ØŸ™˜ Q t§y¡y kÐ2�Ø˜eÑ#Ø!#�E˜#‘JØ�c‘
×!Ñ! $Õ'ñ	(ð		(ð "×2Ñ2×8Ñ8¸ÓAò 		(ˆMØ×!Ñ!×*Ñ*¨7Ô3Øà×0Ñ0°Ó?ˆJØ"ò (�ØŸ™˜ Q t§y¡y kÐ2�Ø˜eÑ#Ø!#�E˜#‘JØ�c‘
×!Ñ! $Õ'ñ	(ð		(ð ˆr   re   c                 ó¬  — g }	 t        |dd¬«      5 }|j                  «       }ddd«       d}t        j                  |«      D ]—  }|j	                  d«      j                  «       }|j	                  d«      }|d|j                  «        j                  d«      dz   }	|j                  t        ||t        |j                  | j                  «      «      |	¬	«      «       Œ™ d
}
t        j                  |
|t        j                  «      D ]—  }|j	                  d«      }|j	                  d«      j                  «       }|d|j                  «        j                  d«      dz   }	|j                  t        ||t        |j                  | j                  «      «      |	¬	«      «       Œ™ |S # 1 sw Y   �ŒxY w# t        $ r}t        d|› d|› �«       g cY d}~S d}~ww xY w)z&Extract API calls from a frontend filer:   r;   r<   NzE(?:axios|api)\.(get|post|put|delete|patch)\s*\(\s*["\']([^"\']+)["\']r>   r@   rA   rB   zWfetch\s*\(\s*["\']([^"\']+)["\'].*?method\s*:\s*["\']?(GET|POST|PUT|DELETE|PATCH)["\']?rC   rD   )rE   rF   rG   rJ   rI   rK   rL   rM   r2   r   r   rN   r   ÚDOTALLrO   rP   )r*   re   rd   rQ   rR   Úaxios_patternrW   r   r   rY   Úfetch_patternr[   s               r   rc   zAPIAnalyzer._extract_api_callsœ   s­  € àˆð(	Ü�m S°7Ô;ð #¸qØŸ&™&›(�÷#ð eˆMÜŸ™ ]°GÓ<ò 
�ØŸ™ Q›×-Ñ-Ó/�Ø—{‘{ 1“~�Ø" > E§K¡K£MÐ2×8Ñ8¸Ó>ÀÑB�à—‘œWØØ!Ü˜]×6Ñ6°t×7GÑ7GÓHÓIØ!ô	õ ð
ð wˆMÜŸ™ ]°G¼R¿Y¹YÓGò 
�Ø—{‘{ 1“~�ØŸ™ Q›×-Ñ-Ó/�Ø" > E§K¡K£MÐ2×8Ñ8¸Ó>ÀÑB�à—‘œWØØ!Ü˜]×6Ñ6°t×7GÑ7GÓHÓIØ!ô	õ ð
ð ˆL÷G#ñ #ûôJ ò 	ÜÐ$ ] O°2°a°SÐ9Ô:Ø�Iûð	ús4   „F- ’F £E<F- Æ F*Æ%F- Æ-	GÆ6GÇGÇGc           	      óÊ  — | j                  «       }| j                  «       }g g g dœ}t        «       }|j                  «       D ],  \  }}|D ]"  }|j	                  |j
                  › d|› �«       Œ$ Œ. t        «       }|j                  «       D ]  \  }	}
|j	                  |	«       Œ |D ]S  }||vsŒ|j                  dd«      \  }}||   D ]/  }|d   j                  |||j                  |j                  dœ«       Œ1 ŒU |D ]c  }||vsŒ|j                  dd«      \  }}||   D ]?  }|j
                  |k(  sŒ|d   j                  |||j                  |j                  dœ«       ŒA Œe |S )z-Compare backend endpoints with frontend calls)Úmissing_backend_endpointsÚunused_backend_endpointsÚmismatched_methodsr_   r>   ro   rB   rp   )
r8   ri   ÚsetÚitemsÚaddr   Úsplitr2   r   r   )r*   Úbackend_endpointsÚfrontend_callsÚdifferencesÚbackend_setr   r3   r6   Úfrontend_setrh   rd   Úcall_keyr   rg   Úendpoint_keys                  r   Úcompare_apiszAPIAnalyzer.compare_apisÊ   s¨  € à ×:Ñ:Ó<ÐØ×4Ñ4Ó6ˆð *,Ø(*Ø"$ñ
ˆô “eˆØ0×6Ñ6Ó8ò 	=‰OˆD�)Ø%ò =�Ø—‘ 8§?¡?Ð"3°1°T°FÐ ;Õ<ñ=ð	=ô
 “uˆØ(×.Ñ.Ó0ò 	"‰JˆC�Ø×Ñ˜SÕ!ð	"ð %ò 		ˆHØ˜{Ò*Ø'Ÿ~™~¨c°1Ó5‘�˜Ø*¨8Ñ4ò �DØÐ ;Ñ<×CÑCØ $Ø"(Ø $§	¡	Ø $§	¡	ñ	Eõ ñð		ð (ò 
	ˆLØ <Ò/Ø+×1Ñ1°#°qÓ9‘�˜Ø 1°$Ñ 7ò �HØ—‘¨&Ó0Ø#Ð$>Ñ?×FÑFØ$(Ø&,Ø$,§M¡MØ$,§M¡Mñ	Hõ ñð
	ð Ðr   c                 ód  — | j                   j                  «       s
t        «       S 	 t        | j                   dd¬«      5 }t	        j
                  |«      }t        |j                  dg «      «      cddd«       S # 1 sw Y   yxY w# t        $ r"}t        d|› �«       t        «       cY d}~S d}~ww xY w)z-Load cached baseline endpoints from JSON filer:   r;   r<   r3   NzError loading baseline: )	r)   r.   rr   rE   ÚjsonÚloadÚgetrO   rP   )r*   rQ   Úbaseline_datar[   s       r   Úload_baselinezAPIAnalyzer.load_baselineû   s“   € à×!Ñ!×(Ñ(Ô*Ü“5ˆLð	Ü�d×(Ñ(¨#¸Ô@ð ?ÀAÜ $§	¡	¨!£�Ü˜=×,Ñ,¨[¸"Ó=Ó>÷?÷ ?ò ?ûô ò 	ÜÐ,¨Q¨CÐ0Ô1Ü“5�Lûð	ús:   ¦B ¾0A8Á.	B Á8BÁ=B ÂB Â	B/ÂB*Â$B/Â*B/r3   c                 ó´  — 	 t        «       }|j                  «       D ],  \  }}|D ]"  }|j                  |j                  › d|› �«       Œ$ Œ. t	        t        |«      «      | j                  «       dœ}t        | j                  dd¬«      5 }t        j                  ||d¬«       ddd«       y	# 1 sw Y   y	xY w# t        $ r}t        d
|› �«       Y d}~yd}~ww xY w)z'Save current endpoints to baseline filer_   )r3   Ú
updated_atÚwr;   r<   r@   )ÚindentNTzError saving baseline: F)rr   rs   rt   r   ÚsortedÚlistÚ_get_timestamprE   r)   r   ÚdumprO   rP   )	r*   r3   Úendpoint_keysr   Úendpoint_listr6   r‚   rQ   r[   s	            r   Úsave_baselinezAPIAnalyzer.save_baseline  sÞ   € ð	Ü›EˆMØ'0§¡Ó'8ò CÑ#��mØ -ò C�HØ!×%Ñ%¨¯©Ð(9¸¸4¸&Ð&AÕBñCðCô
 $¤D¨Ó$7Ó8Ø"×1Ñ1Ó3ñˆMô
 �d×(Ñ(¨#¸Ô@ð 6ÀAÜ—	‘	˜-¨°1Õ5÷6ð ÷6ð ûÜò 	ÜÐ+¨A¨3Ð/Ô0Üûð	ús6   ‚BB6 ÂB*Â!B6 Â*B3Â/B6 Â3B6 Â6	CÂ?CÃCc           	      ó¦  — | j                  «       }| j                  «       }t        «       }|j                  «       D ],  \  }}|D ]"  }|j	                  |j
                  › d|› �«       Œ$ Œ. ||z
  }g }|D ][  }	|	j                  dd«      \  }
}||   D ]<  }|j
                  |
k(  sŒ|j                  ||
|j                  |j                  dœ«       Œ> Œ] |S )z;Compare current endpoints with baseline and detect new onesr_   r>   rB   )
r8   rƒ   rr   rs   rt   r   ru   r2   r   r   )r*   Úcurrent_endpointsÚbaseline_endpointsÚcurrent_setr   r�   r6   Únew_endpointsÚresultr|   r   s              r   Údetect_new_endpointsz APIAnalyzer.detect_new_endpoints  sò   € à ×:Ñ:Ó<ÐØ!×/Ñ/Ó1Ðä“eˆØ#4×#:Ñ#:Ó#<ò 	=ÑˆD�-Ø)ò =�Ø—‘ 8§?¡?Ð"3°1°T°FÐ ;Õ<ñ=ð	=ð $Ð&8Ñ8ˆàˆØ)ò 		ˆLØ'×-Ñ-¨c°1Ó5‰LˆF�DØ-¨dÑ3ò �Ø—?‘? fÓ,Ø—M‘MØ $Ø"(Ø (§¡Ø (§¡ñ	#õ ñð		ð ˆr   c                 óJ  — | j                  «       }| j                  «       }t        «       }|j                  «       D ],  \  }}|D ]"  }|j	                  |j
                  › d|› �«       Œ$ Œ. ||z
  }g }|D ]-  }	|	j                  dd«      \  }
}|j                  ||
dddœ«       Œ/ |S )z?Compare current endpoints with baseline and detect removed onesr_   r>   Úbaseliner   rB   )r8   rƒ   rr   rs   rt   r   ru   r2   )r*   r�   r‘   r’   r   r�   r6   Úremoved_endpointsr”   r|   r   s              r   Údetect_removed_endpointsz$APIAnalyzer.detect_removed_endpoints7  sÊ   € à ×:Ñ:Ó<ÐØ!×/Ñ/Ó1Ðä“eˆØ#4×#:Ñ#:Ó#<ò 	=ÑˆD�-Ø)ò =�Ø—‘ 8§?¡?Ð"3°1°T°FÐ ;Õ<ñ=ð	=ð /°Ñ<ÐàˆØ-ò 	ˆLØ'×-Ñ-¨c°1Ó5‰LˆF�DØ�M‰MØØ Ø"Øñ	õ ð	ð ˆr   c                 ó�  — | j                   dz  }| j                   dz  }|j                  «       s
t        «       S t        «       }i dd“dd“dd“dd	“d
d“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“ddddddddddddddœ¥}ddddddddddœ	}t        «       }|j                  d«      D ]9  }|j                  j                  d «      rŒ|j                  |j                  «       Œ; t        «       }|j                  «       rM|j                  d!«      D ]9  }	|	j                  j                  d «      rŒ|j                  |	j                  «       Œ; |j                  «       D ]'  \  }
}||v sŒd"D ]  }|j                  |› d#|
› �«       Œ Œ) |j                  «       D ]'  \  }
}||v sŒd"D ]  }|j                  |› d#|
› �«       Œ Œ) |S )$z'Get coverage based on service existenceÚservicesÚcontextsz/api/streamsÚstreamServicez/api/streams/{stream_id}z!/api/streams/{stream_id}/commentsÚcommentServicez/api/streams/{stream_id}/chatÚchatServicez/api/commentsz	/api/tagsÚ
tagServicez/api/tags/streams/{stream_id}z&/api/tags/streams/{stream_id}/{tag_id}z
/api/usersÚuserServicez/api/users/mez/api/users/me/watch-historyÚwatchHistoryServicez'/api/users/me/watch-history/{stream_id}z./api/users/me/watch-history/stream/{stream_id}z/api/admin/usersÚadminServicez/api/admin/users/{user_id}z/api/admin/users/{user_id}/rolez#/api/admin/users/{user_id}/activateÚsettingsService)z%/api/admin/users/{user_id}/deactivatez/api/admin/statsz/api/admin/backupz/api/admin/backup/{filename}z/api/admin/backup/createz/api/admin/backup/uploadz$/api/admin/backup/restore/{filename}z /api/admin/backup/restore/statusz/api/settingsz/api/settings/{key}z/api/settings/bulkz/api/settings/upload-faviconz/api/settings/upload-logoÚAuthContext)	z	/api/authz/api/auth/mez/api/auth/loginz/api/auth/registerz/api/auth/logoutz/api/auth/refreshz/api/auth/twitch/loginz/api/auth/twitch/callbackz/api/auth/twitch/unlinkr]   r^   r`   )ÚGETÚPOSTÚPUTÚDELETEÚPATCHr_   )	r(   r.   rr   r/   r0   rb   rt   Ústemrs   )r*   Úservice_dirÚcontexts_dirÚcoveredÚservice_mappingÚauth_mappingÚexisting_servicesÚservice_fileÚexisting_contextsÚcontext_filer6   Úservice_namer   Úcontext_names                 r   Ú_get_service_coveragez!APIAnalyzer._get_service_coverageO  s±  € à×+Ñ+¨jÑ8ˆØ×,Ñ,¨zÑ9ˆØ×!Ñ!Ô#Ü“5ˆLä“%ˆð
Ø˜Oð
à&¨ð
ð 0Ð1Að
ð ,¨]ð	
ð
 Ð-ð
ð ˜ð
ð ,¨\ð
ð 5°lð
ð ˜-ð
ð ˜]ð
ð *Ð+@ð
ð 6Ð7Lð
ð =Ð>Sð
ð  ð
ð )¨.ð
ð  .¨~ð!
ð" 2°>ð#
ð$ 6DØ .Ø!/Ø,:Ø(6Ø(6Ø4BØ0>Ø.Ø#4Ø"3Ø,=Ø):ò=
ˆðF 'Ø)Ø,Ø"/Ø -Ø!.Ø&3Ø)6Ø'4ñ

ˆô  ›EÐØ'×,Ñ,¨VÓ4ò 	5ˆLØ× Ñ ×)Ñ)¨'Ô2ØØ×!Ñ! ,×"3Ñ"3Õ4ð	5ô  ›EÐØ×ÑÔ Ø ,× 1Ñ 1°'Ó :ò 9�Ø×$Ñ$×-Ñ-¨gÔ6ØØ!×%Ñ% l×&7Ñ&7Õ8ð9ð '6×&;Ñ&;Ó&=ò 	8Ñ"ˆH�lØÐ0Ò0àGò 8�FØ—K‘K 6 (¨!¨H¨:Ð 6Õ7ñ8ð	8ð '3×&8Ñ&8Ó&:ò 	8Ñ"ˆH�lØÐ0Ò0àGò 8�FØ—K‘K 6 (¨!¨H¨:Ð 6Õ7ñ8ð	8ð ˆr   c                 ó   — h d£}|S )zVGet endpoints that are intentionally unused (internal features, background jobs, etc.)>C   úGET:/úGET:/api/eventsúGET:/api/healthúGET:/api/auth/meúGET:/api/settingsúGET:/api/admin/usersúGET:/api/permissionsúPOST:/api/auth/loginúGET:/api/admin/backupúPOST:/api/auth/logoutúPOST:/api/auth/refreshúGET:/api/settings/{key}úGET:/api/streams/latestúGET:/api/streams/randomúGET:/api/streams/searchúPOST:/api/auth/registerúPOST:/api/settings/bulkúPUT:/api/settings/{key}úGET:/api/streams/popularúGET:/api/auth/twitch/loginúGET:/api/permissions/adminúGET:/api/permissions/publicúGET:/api/streams/{stream_id}úPOST:/api/auth/twitch/unlinkúPUT:/api/streams/{stream_id}úGET:/api/auth/twitch/callbackúPOST:/api/admin/backup/createúPOST:/api/admin/backup/uploadúGET:/api/admin/users/{user_id}úGET:/api/permissions/protectedúPOST:/api/settings/upload-logoúDELETE:/api/streams/{stream_id}úGET:/api/users/me/watch-historyúPOST:/api/streams/twitch-importú GET:/api/admin/backup/{filename}ú!DELETE:/api/admin/users/{user_id}ú!GET:/api/streams/{stream_id}/chatú!GET:/api/tags/streams/{stream_id}ú!POST:/api/settings/upload-faviconú"POST:/api/streams/{stream_id}/playú#DELETE:/api/admin/backup/{filename}ú#PUT:/api/admin/users/{user_id}/roleú$GET:/api/admin/backup/restore/statusú$POST:/api/streams/{stream_id}/uploadú%GET:/api/streams/{stream_id}/commentsú%POST:/api/streams/{stream_id}/processú%PUT:/api/streams/{stream_id}/metadataú&POST:/api/streams/{stream_id}/commentsú'PUT:/api/admin/users/{user_id}/activateú)POST:/api/admin/backup/restore/{filename}ú)POST:/api/streams/{stream_id}/chat/uploadú)POST:/api/streams/{stream_id}/re-downloadú)PUT:/api/admin/users/{user_id}/deactivateú+POST:/api/tags/streams/{stream_id}/{tag_id}ú+PUT:/api/users/me/watch-history/{stream_id}ú-DELETE:/api/tags/streams/{stream_id}/{tag_id}ú-GET:/api/streams/{stream_id}/chat/proxy-imageú.DELETE:/api/users/me/watch-history/{stream_id}ú.GET:/api/streams/{stream_id}/download-progressú.POST:/api/streams/{stream_id}/import-chat-jsonú/GET:/api/streams/{stream_id}/thumbnail-progressú0GET:/api/streams/{stream_id}/processing-progressú1POST:/api/streams/{stream_id}/generate-thumbnailsú2GET:/api/users/me/watch-history/stream/{stream_id}ú2PUT:/api/streams/{stream_id}/comments/{comment_id}ú5DELETE:/api/streams/{stream_id}/comments/{comment_id}ú7GET:/api/streams/{stream_id}/thumbnail/{segment_number}r   )r*   Úintentionally_unuseds     r   Ú#_get_intentionally_unused_endpointsz/APIAnalyzer._get_intentionally_unused_endpoints¦  s   € òg 
ÐðR $Ð#r   c                 óä  — | j                  «       }| j                  «       }| j                  «       }| j                  «       }| j	                  «       }t        d„ |j                  «       D «       «      }t        d„ |j                  «       D «       «      }t        «       }|j                  «       D ],  \  }	}
|
D ]"  }|j                  |j                  › d|	› �«       Œ$ Œ. t        «       }|j                  «       D ]  \  }}|j                  |«       Œ | j                  «       }||z  }| j                  «       }||z  }||z
  }||z
  }||z
  }|d   D �cg c]  }|d   › d|d   › �|vr|‘Œ }}|d   D �cg c]  }|d   › d|d   › �|v r|‘Œ }}i d|“d|“d	t        |«      “d
|dkD  rt        t        |«      |z  dz  d«      nd“dt        |«      “d|dkD  rt        t        |«      |z  dz  d«      nd“dt        |«      “d|dkD  rt        t        |«      |z  dz  d«      nd“dt        |«      “dt        |«      “dt        |«      “dt        t!        |«      «      “d|“d|“d|d   “d|“d|“S c c}w c c}w )z3Generate comprehensive endpoint coverage statisticsc              3   ó2   K  — | ]  }t        |«      –— Œ y ­w©N©Úlen)Ú.0r3   s     r   ú	<genexpr>z@APIAnalyzer.generate_endpoint_coverage_report.<locals>.<genexpr>  s   è ø€ ÒW¨yœC 	ŸNÑWùó   ‚c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr   r  )r  rd   s     r   r  z@APIAnalyzer.generate_endpoint_coverage_report.<locals>.<genexpr>  s   è ø€ Ò"S°%¤3 u§:Ñ"Sùr  r_   rp   r   r   Útotal_backend_endpointsÚtotal_frontend_callsÚcovered_countÚcovered_percentager   éd   r>   Úunused_countÚunused_percentageÚintentionally_unused_countÚintentionally_unused_percentageÚmissing_countÚnew_endpoints_countÚremoved_endpoints_countÚcovered_endpointsÚunused_endpointsÚintentionally_unused_endpointsÚmissing_endpointsro   r“   r˜   )r8   ri   r}   r•   r™   ÚsumÚvaluesrr   rs   rt   r   r·   rý   r  Úroundrˆ   r‰   )r*   rv   rw   rx   r“   r˜   Útotal_backendr  ry   r   r3   r6   rz   rh   rd   Úservice_setrü   r  r  r  ÚepÚfiltered_unusedÚintentionally_unused_lists                          r   Ú!generate_endpoint_coverage_reportz-APIAnalyzer.generate_endpoint_coverage_report  sd  € à ×:Ñ:Ó<ÐØ×4Ñ4Ó6ˆØ×'Ñ'Ó)ˆØ×1Ñ1Ó3ˆØ ×9Ñ9Ó;Ðô ÑWÐ<M×<TÑ<TÓ<VÔWÓWˆÜ"Ñ"S¸>×;PÑ;PÓ;RÔ"SÓSÐô “eˆØ0×6Ñ6Ó8ò 	=‰OˆD�)Ø%ò =�Ø—‘ 8§?¡?Ð"3°1°T°FÐ ;Õ<ñ=ð	=ô “uˆØ(×.Ñ.Ó0ò 	"‰JˆC�Ø×Ñ˜SÕ!ð	"ð ×0Ñ0Ó2ˆØ# kÑ1ˆð  $×GÑGÓIÐà'¨,Ñ6ÐØ&¨Ñ5Ðà+Ð.BÑBÐØ(¨;Ñ6Ðð %Ð%?Ñ@ö
ØØ�X‘,�˜q  F¡ Ð-Ð5IÑIò ð
ˆð 
ð %Ð%?Ñ@ö%
ØØ�X‘,�˜q  F¡ Ð-Ð1EÑEò ð%
Ð!ð %
ð

Ø% }ð
à"Ð$8ð
ð œSÐ!2Ó3ð
ð !Ð\iÐlmÒ\m¤%¬Ð,=Ó(>ÀÑ(NÐQTÑ(TÐVWÔ"XÐstð	
ð
 œCÐ 0Ó1ð
ð  ÐZgÐjkÒZk¤¤sÐ+;Ó'<¸}Ñ'LÈsÑ'RÐTUÔ!VÐqrð
ð )¬#Ð.BÓ*Cð
ð .ÐlyÐ|}Òl}¬u´SÐ9MÓ5NÐQ^Ñ5^ÐadÑ5dÐfgÔ/hð  DEð
ð œSÐ!2Ó3ð
ð "¤3 }Ó#5ð
ð &¤sÐ+<Ó'=ð
ð  ¤¬Ð->Ó(?Ó!@ð
ð  ð
ð -Ð.Gð
ð   Ð-HÑ!Ið
ð  ˜]ð!
ð"  Ð!2ð#
ð 	
ùò
ùò%
s   ÅI(Å.I-c                 óL   — ddl m } |j                  «       j                  d«      S )zGet current timestampr   )Údatetimez%Y-%m-%d %H:%M:%S)r!  ÚnowÚstrftime)r*   r!  s     r   rŠ   zAPIAnalyzer._get_timestampV  s   € å%Ø�|‰|‹~×&Ñ&Ð':Ó;Ð;r   rx   c                 ó  — t        d«       t        d«       t        d«       | j                  «       }|d   rOt        d«       t        |d   d„ ¬«      D ]0  }t        d|d   › d	|d
   › �«       t        d|d   › d|d   › �«       Œ2 |d   D �cg c]  }|d   › d|d
   › �|vr|‘Œ }}|rLt        d«       t        |d„ ¬«      D ]0  }t        d|d   › d	|d
   › �«       t        d|d   › d|d   › �«       Œ2 |d   D �cg c]  }|d   › d|d
   › �|v r|‘Œ }}|rLt        d«       t        |d„ ¬«      D ]0  }t        d|d   › d	|d
   › �«       t        d|d   › d|d   › �«       Œ2 |d   s|st        d«       t        d«       yc c}w c c}w )z0Print a human-readable report of API differencesz<============================================================zAPI Analysis Reportro   zE
Missing Backend Endpoints (called from frontend but not in backend):c                 ó   — | d   | d   fS ©Nr   r   r   ©Úxs    r   ú<lambda>z*APIAnalyzer.print_report.<locals>.<lambda>e  s   € ÐXYÐZbÑXcÐefÐgmÑenÐWo€ r   )rh   z  r   Ú r   z    Called in: r   r_   r   rp   zD
Unused Backend Endpoints (in backend but not called from frontend):c                 ó   — | d   | d   fS r&  r   r'  s    r   r)  z*APIAnalyzer.print_report.<locals>.<lambda>q  s   € ¸qÀ¹{ÈAÈfÉIÐ>V€ r   z    Defined in: zE
Intentionally Unused Endpoints (internal features, background jobs):c                 ó   — | d   | d   fS r&  r   r'  s    r   r)  z*APIAnalyzer.print_report.<locals>.<lambda>}  s   € ÈÈ8ÉÐVWÐX^ÑV_ÐH`€ r   u@   
âœ“ All frontend API calls have corresponding backend endpointsN)rP   rý   rˆ   )r*   rx   rü   Úitemr  Úunused_filteredr  s          r   Úprint_reportzAPIAnalyzer.print_report[  s  € äˆhŒÜÐ#Ô$ÜˆhŒà#×GÑGÓIÐàÐ2Ò3ÜÐZÔ[Ü˜{Ð+FÑGÑMoÔpò G�Ü˜˜4 ™>Ð*¨!¨D°©L¨>Ð:Ô;Ü˜¨¨V© ~°Q°t¸F±|°nÐEÕFðGð %Ð%?Ñ@ö
ØØ�X‘,�˜q  F¡ Ð-Ð5IÑIò ð
ˆð 
ñ
 ÜÐYÔZÜ˜Ñ4VÔWò H�Ü˜˜4 ™>Ð*¨!¨D°©L¨>Ð:Ô;ÜÐ(¨¨f©¨°a¸¸V¹°~ÐFÕGðHð %Ð%?Ñ@ö%
ØØ�X‘,�˜q  F¡ Ð-Ð1EÑEò ð%
Ð!ð %
ñ
 %ÜÐZÔ[ÜÐ8Ñ>`Ôaò H�Ü˜˜4 ™>Ð*¨!¨D°©L¨>Ð:Ô;ÜÐ(¨¨f©¨°a¸¸V¹°~ÐFÕGðHð Ð6Ò7ÁÜÐUÔVäˆh�ùò5
ùò%
s   ÂFÃ<FN)r   r   r   r   r   r+   r   r   r
   r8   r   r1   r   ri   rc   r}   r   rƒ   ÚboolrŽ   r•   r™   r·   rý   r  rŠ   r/  r   r   r   r   r      s6  „ ÙHðY Có Yð¨4°°T¸+Ñ5FÐ0FÑ+Gó ð:6¨4ð 6°D¸Ñ4Eó 6ðp¨¨S°$°w±-Ð-?Ñ(@ó ðB,°ð ,¸¸g¹ó ,ð\/˜d 3¨ 9™oó /ðb˜s 3™xó ð t¨C°°kÑ1BÐ,BÑ'Cð Èó ð* d¨4¡jó ð4¨$¨t©*ó ð0U s¨3¡xó Uðnk$°S¸±Xó k$ðZA
°4ó A
ðF< ó <ð
)¨¨S°$¨Y©ô )r   r   Ú__main__)r   rG   r   Úpathlibr   Útypingr   r   r   r   Údataclassesr   r
   r   r   r   Ú__file__Úparentr   r   Úanalyzerr}   rx   r/  r   r   r   ú<module>r8     s²   ðñó 
Û Ý ß )Ó )Ý !ð ÷ð ó ðð ÷ð ó ð÷g	ñ g	ðT ˆzÒá�x“.×'Ñ'×.Ñ.×5Ñ5€KÙ™3˜{Ó+Ó,€Hà×'Ñ'Ó)€KØ×Ñ˜+Õ&ð r   