+
    Ki%  c                   s   ^ RI t ^ RIt^ RIHtHt ^ RIHt ^ RIHt ^ RI	H
t
HtHtHtHt ^ RIHtHtHt ^ RIHt ^ RIHt ^ R	IHt ^ R
IHt ]P6                  R,           t]! 4       t]! 4       t]! 4       tRs R t! ! R R4      t"R# )i    N)ListOptional)settings)read_api_key)add_categoryadd_game_to_categoryget_all_games_categoriesget_categoriesremove_category_from_game)add_game	get_gamesget_games_where)Game)NotificationSource)http)loggerz/api/users/libraryFc                 s    \         # )zSTrue if the library is syncing now; attempting to sync again will do nothing if so.)_IS_LOCAL_LIBRARY_SYNCING     =/usr/lib/python3.14/site-packages/lutris/util/library_sync.pyis_local_library_syncingr      s
    
 %$r   c                   s   a  ] tR t^#t o R tRR ltRR ltR tV 3R lR ltR t	R	 t
V 3R
 lR ltR tRR ltRV 3R lR lltR tRtV tR# )LibrarySyncerc                s|    V P                  4       V n        V P                  R R7      V n        \        4       V n        R# )TreverseN)_load_categories
categoriescategory_idsr   games_categories)selfs   &r   __init__ZLibrarySyncer.__init__$   s3    //1 11$1? 8 :r   c                s    V'       d   RMRpV'       d   RMRp\        4        Uu/ uF  qDV,          WC,          bK  	  up# u upi )zHCreate a mapping of category ID to name or name to ID if reverse is usednameid)r   )r   r   ZkeyZvalueZr   &&   r   r   ZLibrarySyncer._load_categories)   s:    fTV*8*:;*:Q# *:;;;s   A Nc           	     s    \        4       pV'       g   R# \        pV'       d   VRV,          ,          p\        P                  ! VRRRRVR,          ,           /R7      # )	zDReturn a request object and ensures authentication to the Lutris APINz	?since=%szContent-Typezapplication/jsonZAuthorizationzToken Ztoken)Zheaders)r   LIBRARY_URLr   ZRequest)r   sinceZcredentialsZurl   &&  r   _get_requestZLibrarySyncer._get_request/   sT    "n;&&C|| 2K,@!@
 	
r   c                s    VR,          VR,          ;'       g    RVR,          ;'       g    RVR,          ;'       g    R3# )z:Create a unique-ish key used to discriminate between gamesslugrunner platformservicer   )r   game   &&r   _make_game_keyZLibrarySyncer._make_game_key?   sC     LN  b""O!!r	
 	
r   c                s0   < V ^8  d   QhRS[ S[,          /# )   return)r   r   Zformat__classdict__   "r   __annotate__LibrarySyncer.__annotate__H   s     $ $ $r   c                sj   RVR,          /pR F  pW,          '       g   K  W,          W#&   K  	  \        R/ VB p\        V4      ^ 8X  d!   \        P                  ! RVR,          4       R# \        V4      ^8  d!   \        P                  ! RVR,          4       R# V^ ,          p\	        VR,          4      # )z/Return a Game instance from a remote API recordr%   zNo game found for %sNzMore than one game found for %sr   )r&   r(   r)   r   )r   Zlenr   errorr   )r   remote_gameZ
conditionsZcond_keyZpga_gamer    r   	_get_gameZLibrarySyncer._get_gameH   s    k&12
9H$$'2'<
$ : #0Z0x=ALL/V1DEx=1LL:K<OPA;HTN##r   c                sT   \         P                  ! RVR,          4       \        VR,          VR,          VR,          VR,          VR,          VR,          VR,          VR	,          ^ R
7	      pVR,           F0  pV P                  V4       \	        W P
                  V,          4       K2  	  R# )z,Create a new local game from a remote recordz	Create %sr%   r   r&   r(   
lastplayedplaytimer)   
service_id)	r   r%   r&   r(   r7   r8   r)   r9   Z	installedr   N)r   Zinfor	   _ensure_categoryr   r   )r   r5   Zgame_idcategoryr#   r   _create_new_gameZLibrarySyncer._create_new_gameX   s    KV!45V$V$x( ,"<0 ,	*"<0

 $L11H!!(+ *;*;H*EF 2r   c                s    WP                   P                  4       9  d:   \        V4       V P                  4       V n         V P                  RR7      V n        R# R# )zCMake sure a given category exists in the database, create it if notTr   N)r   Zvaluesr   r   r   )r   r;   r+   r   r:   ZLibrarySyncer._ensure_categoryj   sH    ??1133""335DO $ 5 5d 5 CD 4r   c                s&   < V ^8  d   QhRS[ RS[/# )r-   r*   r5   )r   Zdictr/   r1   r   r2   r3   q   s     
K 
Kt 
K$ 
Kr   c                s:   VP                  4       pVR,          pV F2  pWT9  g   K  \        VP                  V P                  V,          4       K4  	  V FC  pWS9  g   K  V P	                  V4       \        VP                  V P                  V,          4       KE  	  R# )z%Update the categories of a local gamer   N)r   r   r   r   r:   r   )r   r*   r5   Zgame_categoriesZremote_categoriesr;   s   &&&   r   _update_categoriesZ LibrarySyncer._update_categoriesq   s}    %)%8%8%:'2<'@'H0)$''43D3DX3NO ( *H.%%h/$TWWd.?.?.IJ *r   c                s   V P                   P                  VR,          . 4       Uu. uF  q P                  V,          NK  	  ppRVR,          RVR,          RVR,          ;'       g    RRVR,          ;'       g    RRRVR,          ;'       g    ^ ,          R	VR	,          ;'       g    ^ R
VR
,          ;'       g    RRVR,          ;'       g    RRV/	# u upi )z<Serialize DB game entry to a payload compatible with the APIr   r   r%   r&   r'   r(   r8   z%0.5fr7   r)   r9   r   )r   Zgetr   )r   db_gameZcat_idr   r#   r   _db_game_to_apiZLibrarySyncer._db_game_to_api}   s    <@<Q<Q<U<UV]^bVceg<hi<h&oof--<h
iGFOGFOgh'--2
+11r7:#6#;#;!<',/441wy)//R',/552*

 
	
 js   Cc                s    . pV F_  pVR,          ;'       g    ^ pVR,          ;'       g    ^ pV'       d   WR8  d	   Wb8  d   K?  VP                  V P                  V4      4       Ka  	  V# )zKSerialize a collection of games to API format, optionally filtering by dater7   installed_at)Zappendr?   )r   Zdb_gamesr"   Zpayloadr>   r7   r@   s   &&&    r   _db_games_to_apiZLibrarySyncer._db_games_to_api   sc    G .33!J">277aL+0DNN4//89   r   c                s$   < V ^8  d   QhRS[ RR/# )r-   forcer.   N)Zboolr/   r1   r   r2   r3      s     H- H- H- H-r   c                sj   \         '       d   R# V'       g=   \        P                  ! R4      '       d!   \        \        P                  ! R4      4      pMRp\	        4       pV P                  V4      pV P                  W2R7      pV P                  V4      pV'       g   R# \        P                  4        Rp Rs  VP                  \        P                  ! V4      P                  4       R7       \'        4       p	\'        4       p
/ p\'        4       pT FX  pT P)                  T4      pY9   d   T
P+                  T4       T	P+                  T4       YT&   TP+                  TR,          4       KZ  	  TP                   EF,  pT P)                  T4      pTT
9   d   \        P,                  ! R	T4       K5  TT9   d   T P/                  T4      pT'       g   KW  RpTR
,          TP0                  8  d   TR
,          Tn        RpTR,          TP2                  8  d   TR,          Tn        Rp\'        TR,          4      \'        TP5                  4       4      8w  d   T P7                  Y4       T'       d   RpTP9                  4        EK  EK  TR,          T9   d   EK  T P;                  T4       RpEK/  	  \        P<                  ! R\        \>        P>                  ! 4       4      4       Rs \"        P                  4        T'       d   \$        P                  4        R# R#   \        P                   dW   p\        P                   ! RT4        Rp?Rs \"        P                  4        T'       d   \$        P                  4        R# R# Rp?ii ; i  Rs \"        P                  4        T'       d   \$        P                  4        i i ; i)z_Sync task to send recent changes to the server and sync back server changes to the local clientNZlast_library_sync_at)r"   FTZdataz*Could not send local library to server: %sr%   zDuplicate game %s, not syncing.r8   r7   r   ) r   r   Zread_settingZintr
   rA   r$   LOCAL_LIBRARY_SYNCINGZfireZpostjsondumpsencoder   	HTTPErrorr   r4   LOCAL_LIBRARY_SYNCEDLOCAL_LIBRARY_UPDATEDZsetr,   ZaddZwarningr6   r8   r7   r   r=   Zsaver<   Zwrite_settingtime)r   rB   r"   Z	all_gamesZlocal_libraryZlocal_library_updatesrequestZany_local_changesexZlibrary_keysZduplicate_keysZlibrary_mapZlibrary_slugsr*   Zlibrary_keyr5   Z
remote_keyZchangeds   &&                r   sync_local_libraryZ LibrarySyncer.sync_local_library   s    %$../EFF--.DEFEEK	--i8 $ 5 5i 5 M##E*""$!3	-(,%$**-B"C"J"J"LM 5L UNKEM%"11$7."&&{3  -+/K(!!$v,/ &  '||!00=
/NN#DjQ,>>+6D #G":.>(3J(?"&"<04??B*5l*C"&;|45T=P=P=R9SS//B,0)		  #6*m; ))+6(,%3  ,6 ""#93tyy{;KL(-% %%' %**, !] >> I2NT ).% %%' %**, !]X ).% %%' %**, !sE   4M= 74L +CM= 
BM= %A4M= M:$M5;M= 5M::M= =5N2c                sH   V P                  4       pV'       g   R#  VP                  \        P                  ! V P	                  V4      4      P                  4       R7       VP                  #   \        P                   d"   p\        P                  ! T4        Rp?R# Rp?ii ; i)z3Task to delete a game entry from the remote libraryNrC   )
r$   ZdeleterE   rF   rA   rG   r   rH   r   r4   )r   ZgamesrL   rM   r#   r   delete_from_remote_libraryZ(LibrarySyncer.delete_from_remote_library   sw    ##%	NN

4+@+@+G H O O QNR || ~~ 	LL	s   AA+ +B! BB!)r   r   r   )F)N)Z__name__Z
__module__Z__qualname__Z__firstlineno__r   r   r$   r,   r6   r<   r:   r=   r?   rA   rN   rO   Z__static_attributes__Z__classdictcell__)r0   s   @r   r   r   #   s\     ;
<
 
$ $ G$D
K 
K

H- H-T
 
r   r   )#rE   rK   Ztypingr    r   Zlutrisr   Z
lutris.apir   Zlutris.database.categoriesr   r   r   r   r   Zlutris.database.gamesr	   r
   r   Zlutris.gamer   Zlutris.gui.widgetsr   Zlutris.utilr   Zlutris.util.logr   ZSITE_URLr!   rD   rI   rJ   r   r   r   r   r   r   <module>rP      sv      !  #  G F  1  ""66*, )+ *, ! %I Ir   