ó
    ²ÃÍj2  ã                   óÆ  • S SK r S SKrS SKJr  S SKJrJrJr  S SKJ	r	  S SK
Jr  S SKJrJr  S SKJr  S SKJrJr  S S	KJrJrJrJr  S S
KJrJrJrJr  \" S\SS9r\R@                  " \5      r!S9S jr"S:S jr#S r$S;S jr%S r&S r'\RQ                  S5      \$S 5       5       r)\RQ                  SS/S9\$S 5       5       r*\RQ                  SS/S9\$S 5       5       r+\RQ                  SS/S9\$S 5       5       r,\RQ                  SS/S9\$S  5       5       r-\RQ                  S!S/S9\$S" 5       5       r.\RQ                  S#S/S9\$S$ 5       5       r/\RQ                  S%S/S9\$S& 5       5       r0\RQ                  S'S/S9\$S( 5       5       r1\RQ                  S)S/S9\$S* 5       5       r2\RQ                  S)S/S9\$S+ 5       5       r3\RQ                  S,S/S9\$S- 5       5       r4\RQ                  S.S/S0/S9\$S1 5       5       r5\RQ                  S2S/S9\$S3 5       5       r6\RQ                  S.S/S9\$S4 5       5       r7\RQ                  S5S/S9\$S6 5       5       r8\RQ                  S7S/S9\$S8 5       5       r9g)<é    N©Úwraps)Ú	BlueprintÚcurrent_appÚrequest)Údb)Úensure_fresh_token)ÚAccountÚScheduledPost)ÚValidationError)Úpublish_nowÚvalidate_post_fields)Úcreate_scheduled_postÚdelete_scheduled_postÚreschedule_postÚ
retry_post)ÚTikTokAPIErrorÚfetch_publish_statusÚget_user_infoÚlist_videosÚapiz/api/v1)Ú
url_prefixc                 ó   • SS XS.S.U4$ )NF)ÚcodeÚmessage©ÚsuccessÚdataÚerror© )r   r   Ústatuss      ÚGF:\Solutions\Thinkera\Publishers\TikTokManager\app\routes\api_routes.pyÚ	api_errorr#      s   € Ø d¸dÑ5WÑXÐZ`Ð`Ð`ó    c                 ó   • SU S S.U4$ )NTr   r    )r   r!   s     r"   Úapi_successr&      s   € Ø T°DÑ9¸6ÐAÐAr$   c                 ó0   ^ • [        T 5      U 4S j5       nU$ )zZAPI guard: a constant-time comparison of the X-API-Key (or Bearer) header against API_KEY.c                  ó®  >• [         R                  R                  SS5      nU(       d  [        SSS5      $ [        R
                  R                  S5      =(       d    SnU(       d;  [        R
                  R                  SS5      nUR                  S5      (       a  US	S  nU(       a  [        R                  " X25      (       d  [        S
SS5      $ T" U 0 UD6$ )NÚAPI_KEYÚ z+API key not configured. Set API_KEY in .envÚAPI_NOT_CONFIGUREDi÷  z	X-API-KeyÚAuthorizationzBearer é   zInvalid or missing API key.ÚUNAUTHORIZEDé‘  )	r   ÚconfigÚgetr#   r   ÚheadersÚ
startswithÚhmacÚcompare_digest)ÚargsÚkwargsÚapi_keyÚprovidedÚauthÚfs        €r"   Ú	decoratedÚ#api_key_required.<locals>.decorated    s¯   ø€ ä×$Ñ$×(Ñ(¨°BÓ7ˆÞÜÐJÐL`ÐbeÓfÐfÜ—?‘?×&Ñ& {Ó3×9°rˆÞÜ—?‘?×&Ñ& ¸Ó;ˆDØ�‰˜y×)Ñ)Ø  ˜8�Þœt×2Ò2°8×EÑEÜÐ:¸NÈCÓPÐPÙ�$Ð!˜&Ñ!Ð!r$   r   )r;   r<   s   ` r"   Úapi_key_requiredr>      s!   ø€ ä
ˆ1ƒXô"ó ð"ð Ðr$   c                 óŒ  • [         R                  R                  S5      =(       d    [         R                  R                  S5      nU(       ax  Sn [        R
                  R                  [        [        U5      5      nUc+  [        R                  R                  US9R                  5       nU(       d  S[        SSS5      4$ US4$ U (       a  S[        SS	S
5      4$ [        R                  R                  [        R                  5      R                  5       nU(       d  S[        SSS5      4$ US4$ ! [        [        4 a     NÅf = f)zÖPick the account to act on: `account_id` query param or `X-Account-Id` header (database id
or open_id). Reads fall back to the first connected account; mutations must be explicit.
Returns (account, error_response).Ú
account_idzX-Account-IdN)Úopen_idz(No account matches the given account_id.Ú
NO_ACCOUNTé”  zTThis is a mutating endpoint: pass account_id (query param) or X-Account-Id (header).ÚEXPLICIT_ACCOUNT_REQUIREDé�  z>No account connected. Connect an account via the web UI first.)r   r6   r1   r2   r   Úsessionr
   ÚintÚ	TypeErrorÚ
ValueErrorÚqueryÚ	filter_byÚfirstr#   Úorder_byÚdisplay_name)Úrequire_explicitÚvalueÚaccounts      r"   Úresolve_accountrR   0   s  € ô �L‰L×Ñ˜\Ó*×Q¬g¯o©o×.AÑ.AÀ.Ó.Q€EÞØˆð	Ü—j‘j—n‘n¤W¬c°%«jÓ9ˆGð ‰?Ü—m‘m×-Ñ-°eÐ-Ð<×BÑBÓDˆGÞØœÐ#MÈ|Ð]`ÓaÐaÐaØ˜ˆ}ÐÞØ”YØbØ'¨ó
ð 
ð 	
ô �m‰m×$Ñ$¤W×%9Ñ%9Ó:×@Ñ@ÓB€GÞØ”YÐ_ÐamÐorÓsÐsÐsØ�Dˆ=Ðøô œ:Ð&ó 	Ùð	ús   Á-D0 Ä0EÅEc                 ó  • U R                   S:X  a  [        U R                  SS5      $ U R                   S;   a  [        U R                  SS5      $ U R                   S:X  a  [        U R                  SS5      $ [        U R                  SS	5      $ )
zBMap a TikTokAPIError to the envelope with its client-safe message.rC   Ú	NOT_FOUND)r/   é“  Ú	FORBIDDENrU   i­  ÚRATE_LIMITEDÚUPSTREAM_ERRORiö  )r!   r#   r   )Úes    r"   Útiktok_error_responserZ   K   sq   € à‡x�x�3ƒÜ˜Ÿ™ K°Ó5Ð5Ø‡x�x�:ÓÜ˜Ÿ™ K°Ó5Ð5Ø‡x�x�3ƒÜ˜Ÿ™ N°CÓ8Ð8Ü�Q—Y‘YÐ 0°#Ó6Ð6r$   c                  ó<   • [         R                  " SS9=(       d    0 $ )NT)Úsilent)r   Úget_jsonr    r$   r"   Ú
_json_bodyr^   V   s   € Ü×Ò 4Ñ(×.¨BÐ.r$   z/healthc                  ó   • [        SSS.5      $ )NÚokz1.0)r!   Úversion)r&   r    r$   r"   Úhealthrb   ^   s   € ô  $°5Ñ9Ó:Ð:r$   z	/accountsÚGET)Úmethodsc                  óÔ   • [         R                  R                  [         R                  5      R	                  5       n [        U  Vs/ s H  oR                  5       PM     sn5      $ s  snf )N)r
   rJ   rM   rN   Úallr&   Úto_dict)ÚaccountsÚas     r"   Úapi_list_accountsrj   h   sH   € ô �}‰}×%Ñ%¤g×&:Ñ&:Ó;×?Ñ?ÓA€HÜ©XÓ6ªX¨Ÿ	™	ž©XÑ6Ó7Ð7ùÒ6s   ÁA%z/accounts/<int:account_db_id>c                 ó¤   • [         R                  R                  [        U 5      nU(       d  [	        SSS5      $ [        UR                  5       5      $ )NúAccount not found.rT   rC   )r   rF   r1   r
   r#   r&   rg   )Úaccount_db_idrQ   s     r"   Úapi_get_accountrn   o   s=   € ô �j‰j�n‰nœW mÓ4€GÞÜÐ-¨{¸CÓ@Ð@Ü�w—‘Ó(Ó)Ð)r$   z%/accounts/<int:account_db_id>/refreshÚPOSTc           	      ó~  • [         R                  R                  [        U 5      nU(       d  [	        SSS5      $  [        U5      n[        U5      =(       d    0 nU(       a¤  UR                  S5      =(       d    UR                  Ul        UR                  S5      =(       d    UR                  Ul        S H.  nUR                  U5      c  M  [        X[        X4   5      5        M0     [         R                  R                  5         [        UR                  5       5      $ ! [         a  n[        U5      s S nA$ S nAff = f)Nrl   rT   rC   rN   Ú
avatar_url)Úfollower_countÚfollowing_countÚlikes_countÚvideo_count)r   rF   r1   r
   r#   r	   r   rN   rq   ÚsetattrrG   Úcommitr&   rg   r   rZ   )rm   rQ   ÚtokenÚuserÚfieldrY   s         r"   Úapi_refresh_accountr{   x   sí   € ô �j‰j�n‰nœW mÓ4€GÞÜÐ-¨{¸CÓ@Ð@ð(Ü" 7Ó+ˆÜ˜UÓ#×) rˆÞØ#'§8¡8¨NÓ#;×#S¸w×?SÑ?SˆGÔ Ø!%§¡¨,Ó!7×!M¸7×;MÑ;MˆGÔÛ\�Ø—8‘8˜E“?Ó.Ü˜G¬C°±Ó,<Ö=ñ ]ô �J‰J×ÑÔÜ˜7Ÿ?™?Ó,Ó-Ð-øÜó (Ü$ QÓ'Õ'ûð(ús%   ºBD ÃAD Ä
D<Ä'
D7Ä1D<Ä7D<ÚDELETEc                 ó   • [         R                  R                  [        U 5      nU(       d  [	        SSS5      $ UR
                  n[         R                  R                  U5        [         R                  R                  5         [        SUS.5      $ )Nrl   rT   rC   T)ÚdeletedÚname)	r   rF   r1   r
   r#   rN   Údeleterw   r&   )rm   rQ   r   s      r"   Úapi_delete_accountr�   �   sh   € ô �j‰j�n‰nœW mÓ4€GÞÜÐ-¨{¸CÓ@Ð@Ø×Ñ€DÜ‡J�J×Ñ�gÔÜ‡J�J×ÑÔÜ 4°Ñ6Ó7Ð7r$   z/videosc            
      ó°  • [        5       u  pU(       a  U$ [        [        [        [        R
                  R                  SS5      5      S5      S5      n [        [        R
                  R                  SS5      5      n [        U 5      n[        XBUS9n[        U5      $ ! [        [        4 a    Sn N5f = f! [         a  n[        U5      s S nA$ S nAff = f)	NÚ	max_countÚ20é   é2   ÚcursorÚ0r   ©rƒ   r‡   )rR   ÚminÚmaxrG   r   r6   r1   rH   rI   r	   r   r&   r   rZ   )rQ   Úerrrƒ   r‡   rx   ÚresultrY   s          r"   Úapi_list_videosrŽ   �   s¼   € ô #Ó$�L€GÞ
Øˆ
Ü”CœœGŸL™L×,Ñ,¨[¸$Ó?Ó@À!ÓDÀbÓI€IðÜ”W—\‘\×%Ñ% h°Ó4Ó5ˆð(Ü" 7Ó+ˆÜ˜UÀÑGˆÜ˜6Ó"Ð"øô ”zÐ"ó ØŠðûô ó (Ü$ QÓ'Õ'ûð(ús0   Á)B Á>B6 ÂB3Â2B3Â6
CÃ 
CÃ
CÃCz/postsc                  óP  • [        SS9u  pU(       a  U$ [        5       n [        U 5      n[        U5      n[	        X4[
        R                  S   5      n[        USS9$ ! [         a!  n[        UR                  SS5      s S nA$ S nAf[         a  n[        U5      s S nA$ S nAff = f)NT©rO   ÚUPLOAD_FOLDERéÉ   ©r!   ÚINVALID_INPUTrE   )rR   r^   r	   r   r   r   r0   r&   r   r#   r   r   rZ   )rQ   rŒ   r   rx   Úfieldsr�   rY   s          r"   Úapi_create_postr–   ´   s“   € ô #°DÑ9�L€GÞ
Øˆ
Ü‹<€Dð(Ü" 7Ó+ˆÜ% dÓ+ˆÜ˜U¬K×,>Ñ,>¸Ñ,OÓPˆÜ˜6¨#Ñ.Ð.øÜó :Ü˜Ÿ™ O°SÓ9Õ9ûÜó (Ü$ QÓ'Õ'ûð(ús/    <A Á
B%Á'BÁ=B%ÂB%Â
B ÂB%Â B%z/posts/mediac                  óT  • [        SS9u  pU(       a  U$ [        R                  R                  S5      =(       d    [        R                  R                  S5      nU(       a  UR                  (       d  [        SSS5      $ [        R                  R                  5       nX#S'    [        U 5      n[        U5      n[        XE[        R                  S   5      n[        US	S
9$ ! [         a!  n[        UR                  SS5      s S nA$ S nAf[          a  n[#        U5      s S nA$ S nAff = f)NTr�   Ú
video_fileÚfileú9No video file provided. Use multipart field 'video_file'.ÚNO_FILErE   r‘   r’   r“   r”   )rR   r   Úfilesr1   Úfilenamer#   Úformrg   r	   r   r   r   r0   r&   r   r   r   rZ   )rQ   rŒ   r˜   r   rx   r•   r�   rY   s           r"   Úapi_create_media_postrŸ   Æ   së   € ô #°DÑ9�L€GÞ
Øˆ
Ü—‘×"Ñ" <Ó0×M´G·M±M×4EÑ4EÀfÓ4M€JÞ˜Z×0×0ÜÐTÐV_ÐadÓeÐeÜ�<‰<×ÑÓ!€DØ#ˆÑð(Ü" 7Ó+ˆÜ% dÓ+ˆÜ˜U¬K×,>Ñ,>¸Ñ,OÓPˆÜ˜6¨#Ñ.Ð.øÜó :Ü˜Ÿ™ O°SÓ9Õ9ûÜó (Ü$ QÓ'Õ'ûð(ús0   Â"<C Ã
D'Ã)DÃ?D'ÄD'Ä
D"ÄD'Ä"D'z/posts/<publish_id>/statusc                 ó¼   • [        5       u  pU(       a  U$  [        U5      n[        X05      n[        SU 0UE5      $ ! [         a  n[        U5      s S nA$ S nAff = f)NÚ
publish_id)rR   r	   r   r&   r   rZ   )r¡   rQ   rŒ   rx   r!   rY   s         r"   Úapi_post_statusr¢   Ü   s_   € ô #Ó$�L€GÞ
Øˆ
ð(Ü" 7Ó+ˆÜ% eÓ8ˆÜ˜L¨*Ð?¸Ð?Ó@Ð@øÜó (Ü$ QÓ'Õ'ûð(ús   —$< ¼
AÁ
AÁAÁAz
/scheduledc                  ó,  • [        5       u  pU(       a  U$ [        R                  R                  U R                  S9R                  [        R                  5      R                  5       n[        U Vs/ s H  o3R                  5       PM     sn5      $ s  snf )N)r@   )
rR   r   rJ   rK   ÚidrM   Úscheduled_atrf   r&   rg   )rQ   rŒ   ÚpostsÚps       r"   Úapi_list_scheduledr¨   î   sn   € ô #Ó$�L€GÞ
Øˆ
Ü×Ñ×)Ñ)°W·Z±ZÐ)Ð@×IÑIÌ-×JdÑJdÓe×iÑiÓk€EÜ©UÓ3ªU¨Ÿ	™	ž©UÑ3Ó4Ð4ùÒ3s   Á1Bc                  ó&  • [        SS9u  pU(       a  U$ [        5       n [        X[        R                  S   [        R                  S   S9n[        UR                  5       SS9$ ! [         a!  n[        UR                  SS	5      s S nA$ S nAff = f)
NTr�   ÚMEDIA_FOLDERÚMAX_CONTENT_LENGTH©Úupload_max_bytesr’   r“   r”   rE   )
rR   r^   r   r   r0   r&   rg   r   r#   r   )rQ   rŒ   r   ÚpostrY   s        r"   Úapi_create_scheduledr¯   ø   s…   € ô #°DÑ9�L€GÞ
Øˆ
Ü‹<€Dð:Ü$Øœ;×-Ñ-¨nÑ=Ü(×/Ñ/Ð0DÑEñ
ˆô ˜4Ÿ<™<›>°#Ñ6Ð6øÜó :Ü˜Ÿ™ O°SÓ9Õ9ûð:ús    AA% Á%
BÁ/BÂBÂBz/scheduled/mediac                  ó*  • [        SS9u  pU(       a  U$ [        R                  R                  S5      =(       d    [        R                  R                  S5      nU(       a  UR                  (       d  [        SSS5      $ [        R                  R                  5       nX#S'    [        X[        R                  S   [        R                  S	   S
9n[        UR                  5       SS9$ ! [         a!  n[        UR                  SS5      s S nA$ S nAff = f)NTr�   r˜   r™   rš   r›   rE   rª   r«   r¬   r’   r“   r”   )rR   r   rœ   r1   r�   r#   rž   rg   r   r   r0   r&   r   r   )rQ   rŒ   r˜   r   r®   rY   s         r"   Úapi_create_scheduled_mediar±   	  sÝ   € ô #°DÑ9�L€GÞ
Øˆ
Ü—‘×"Ñ" <Ó0×M´G·M±M×4EÑ4EÀfÓ4M€JÞ˜Z×0×0ÜÐTÐV_ÐadÓeÐeÜ�<‰<×ÑÓ!€DØ#ˆÑð:Ü$Øœ;×-Ñ-¨nÑ=Ü(×/Ñ/Ð0DÑEñ
ˆô ˜4Ÿ<™<›>°#Ñ6Ð6øÜó :Ü˜Ÿ™ O°SÓ9Õ9ûð:ús   Â"AC' Ã'
DÃ1DÄDÄDz/scheduled/<int:post_id>ÚPATCHÚPUTc                 ó¦  • [        SS9u  pU(       a  U$ [        R                  R                  [        U 5      nU(       a  UR
                  UR                  :w  a  [        SSS5      $ [        5       n [        X4R                  S5      5      n[        UR                  5       5      $ ! [         a!  n[        UR                  SS5      s S nA$ S nAff = f)	NTr�   ú*Scheduled post not found for this account.rT   rC   r¥   r”   rE   )rR   r   rF   r1   r   r@   r¤   r#   r^   r   r&   rg   r   r   )Úpost_idrQ   rŒ   r®   r   rY   s         r"   Úapi_reschedule_scheduledr·     s¢   € ô #°DÑ9�L€GÞ
Øˆ
Ü�:‰:�>‰>œ-¨Ó1€DÞ�4—?‘? g§j¡jÓ0ÜÐEÀ{ÐTWÓXÐXÜ‹<€Dð:Ü˜t§X¡X¨nÓ%=Ó>ˆÜ˜4Ÿ<™<›>Ó*Ð*øÜó :Ü˜Ÿ™ O°SÓ9Õ9ûð:ús   Á22B% Â%
CÂ/CÃCÃCz/scheduled/<int:post_id>/retryc                 ól  • [        SS9u  pU(       a  U$ [        R                  R                  [        U 5      nU(       a  UR
                  UR                  :w  a  [        SSS5      $ UR                  [        R                  :w  a  [        SSS5      $ [        U5        [        UR                  5       5      $ )	NTr�   rµ   rT   rC   z!Only failed posts can be retried.r”   rE   )rR   r   rF   r1   r   r@   r¤   r#   r!   ÚSTATUS_FAILEDr   r&   rg   ©r¶   rQ   rŒ   r®   s       r"   Úapi_retry_scheduledr»   /  sŠ   € ô #°DÑ9�L€GÞ
Øˆ
Ü�:‰:�>‰>œ-¨Ó1€DÞ�4—?‘? g§j¡jÓ0ÜÐEÀ{ÐTWÓXÐXØ‡{�{”m×1Ñ1Ó1ÜÐ<¸oÈsÓSÐSÜˆtÔÜ�t—|‘|“~Ó&Ð&r$   c                 ó   • [        SS9u  pU(       a  U$ [        R                  R                  [        U 5      nU(       a  UR
                  UR                  :w  a  [        SSS5      $ [        U5        [        SU S.5      $ )NTr�   rµ   rT   rC   )r~   r¤   )
rR   r   rF   r1   r   r@   r¤   r#   r   r&   rº   s       r"   Úapi_delete_scheduledr½   >  sg   € ô #°DÑ9�L€GÞ
Øˆ
Ü�:‰:�>‰>œ-¨Ó1€DÞ�4—?‘? g§j¡jÓ0ÜÐEÀ{ÐTWÓXÐXÜ˜$ÔÜ 4¨wÑ7Ó8Ð8r$   z/insights/accountc                  óà   • [        5       u  pU(       a  U$  [        U 5      n[        U5      =(       d    0 n[        U R                  US.5      $ ! [
         a  n[        U5      s S nA$ S nAff = f)N)rA   ry   )rR   r	   r   r&   rA   r   rZ   )rQ   rŒ   rx   ry   rY   s        r"   Úapi_account_insightsr¿   O  sc   € ô #Ó$�L€GÞ
Øˆ
ð(Ü" 7Ó+ˆÜ˜UÓ#×) rˆÜ w§¡ÀÑEÓFÐFøÜó (Ü$ QÓ'Õ'ûð(ús   —6A Á
A-Á
A(Á"A-Á(A-z/insights/videosc            
      óæ  • [        5       u  pU(       a  U$ [        [        [        [        R
                  R                  SS5      5      S5      S5      n [        U 5      n/ nSn[        S5       H3  n[        USUS9nUR                  US   5        US	   (       d    O	US
   nM5     UR                  S SS9  [        U R                  US U S.5      $ ! [         a  n[        U5      s S nA$ S nAff = f)NÚlimitÚ10r…   r†   r   é   r‰   ÚvideosÚhas_morer‡   c                 ó8   • [        U R                  SS5      5      $ )NÚ
view_countr   )rG   r1   )Úvs    r"   Ú<lambda>Ú api_top_videos.<locals>.<lambda>n  s   € ¤# a§e¡e¨L¸!Ó&<Ô"=r$   T)ÚkeyÚreverse)rA   rÄ   )rR   rŠ   r‹   rG   r   r6   r1   r	   Úranger   ÚextendÚsortr&   rA   r   rZ   )	rQ   rŒ   rÁ   rx   rÄ   r‡   Ú_ÚpagerY   s	            r"   Úapi_top_videosrÒ   ]  sê   € ô #Ó$�L€GÞ
Øˆ
Ü””CœŸ™×(Ñ(¨°$Ó7Ó8¸!Ó<¸bÓA€Eð(Ü" 7Ó+ˆØˆØˆÜ�q–ˆAÜ˜u°¸6ÑBˆDØ�M‰M˜$˜x™.Ô)Ø˜
×#ÙØ˜(‘^ŠFñ ð 	�‰Ñ=ÀtˆÑLÜØ—‘Ø˜V˜e�nñ
ó ð 	øô ó (Ü$ QÓ'Õ'ûð(ús   ÁA<C Ã
C0Ã
C+Ã%C0Ã+C0)ÚERRORrE   )éÈ   )F):r4   ÚloggingÚ	functoolsr   Úflaskr   r   r   Úappr   Úapp.authr	   Ú
app.modelsr
   r   Úapp.services.errorsr   Úapp.services.postsr   r   Úapp.services.scheduledr   r   r   r   Úapp.tiktok_apir   r   r   r   Ú__name__Úapi_bpÚ	getLoggerÚlogr#   r&   r>   rR   rZ   r^   Úrouterb   rj   rn   r{   r�   rŽ   r–   rŸ   r¢   r¨   r¯   r±   r·   r»   r½   r¿   rÒ   r    r$   r"   Ú<module>rä      sZ  ðÛ Û Ý ç 1Ñ 1å Ý 'ß -Ý /ß @ß lÓ l÷ó ñ 
�5˜(¨yÑ	9€à×Ò˜Ó!€ôaôBòô$ò67ò/ð ‡�ˆiÓØñ;ó ó ð;ð ‡�ˆk E 7€Ð+Øñ8ó ó ,ð8ð
 ‡�Ð-¸°w€Ð?Øñ*ó ó @ð*ð ‡�Ð5À¸x€ÐHØñ(ó ó Ið(ð& ‡�Ð-¸°z€ÐBØñ8ó ó Cð8ð ‡�ˆi % €Ð)Øñ(ó ó *ð(ð* ‡�ˆh  €Ð)Øñ(ó ó *ð(ð  ‡�ˆn v h€Ð/Øñ(ó ó 0ð(ð( ‡�Ð*°U°G€Ð<Øñ	(ó ó =ð	(ð  ‡�ˆl U G€Ð,Øñ5ó ó -ð5ð ‡�ˆl V H€Ð-Øñ:ó ó .ð:ð ‡�Ð ¨6¨(€Ð3Øñ:ó ó 4ð:ð& ‡�Ð(°7¸EÐ2B€ÐCØñ:ó ó Dð:ð ‡�Ð.¸¸€ÐAØñ
'ó ó Bð
'ð ‡�Ð(°8°*€Ð=Øñ9ó ó >ð9ð ‡�Ð!¨E¨7€Ð3Øñ	(ó ó 4ð	(ð ‡�Ð ¨5¨'€Ð2Øñ(ó ó 3ñ(r$   