U
    <ºj» ã                
   @   s|  d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlZddlmZmZ ej ej e¡¡Zej ed¡Zej edd¡ZdZej eddd	¡Zej eddd
¡Z ej ed¡Z!ej e!d¡Z"ej eddd¡Z#ej ed¡Z$ej ed¡Z%ej ed¡Z&ej ed¡Z'ej ed¡Z(ej ed¡Z)ej edd¡Z*ej ed¡Z+ej ej ,d¡ddddddd¡Z-ej ej ,d¡dddddd¡Z.ej ed¡Z/ej ej ,d¡d d!d"d#¡Z0ej ej ,d¡d d!d"d$¡Z1ej2 3d%d&¡ 4d'¡Z5ej2 3d(d)¡Z6d*Z7d+Z8d,Z9d-d.d/d0hZ:d1Z;e:e;hB Z<d2d3d4d5d6d7œZ=ddd8œa>d9Z?e @¡ ZAe @¡ ZBe @¡ ZCe @¡ ZDe @¡ ZEd:ZFd;d<„ ZGd=d>„ ZHd?d@„ ZIdAdB„ ZJdCdD„ ZKdfdFdG„ZLdHdI„ ZMdJdK„ ZNdLdM„ ZOdNdO„ ZPdgdPdQ„ZQdhdRdS„ZRdTdU„ ZSdidWdX„ZTdjdYdZ„ZUdkd[d\„ZVd]d^„ ZWd_d`„ ZXG dadb„ dbejYjZƒZ[dcdd„ Z\e]dek�rxe\ƒ  dS )lu×   
Personal Life OS - æœ¬åœ°æœ�åŠ¡
- æ‰˜ç®¡ life-dashboard.html ç­‰é�™æ€�æ–‡ä»¶
- æ��ä¾› /sync (POST) æŽ¥æ”¶æ�¥è‡ªå¾®ä¿¡è¯»ä¹¦çš„ä¹¦ç­¾æŒ‰é’®å�Œæ­¥æ•°æ�®
- æ��ä¾› /sync.json (GET) ä¾›å·¥ä½œå�°è¯»å�–æœ€æ–°å�Œæ­¥ç»“æžœ
é    N)Úparse_qsÚurlparsez	sync.jsonú.wereadz
apikey.txtz)https://i.weread.qq.com/api/agent/gatewayÚtmpúlast_reading_note.jsonzrun_reading_auto.pyõ   è¯»ä¹¦æ”¶èŽ·u   ä¹¦ç±�ú
shelf.jsonzlearning-hot-videos.jsonzhot_video_auto.pyzai-learning-videos.jsonzai_learning_video_auto.pyzlife-data.jsonzfavorite-collections.jsonz
.favoritesZmediazsync-favorites.jsú~z.cachezcodex-runtimeszcodex-primary-runtimeZdependenciesÚnodeÚbinznode.exeZnode_modulesZAppDataZRoamingZting_enz	events.dbzconfig.jsonZWORKBUDDY_CLOUD_ORIGINzhttps://xm.cloudmall.funú/ZWORKBUDDY_READING_SYNC_TOKENzworkbuddy-reading-sync-20260910i="  é   é   ÚexerciseÚreadÚenglishÚailearnÚreadingNoteu   ðŸ’ƒu   ðŸ“–u   ðŸŽ§ZAiu   ðŸ“–ðŸª™)r   r   r   r   r   ©ÚtsÚdataé<   )u   è¯»ä¹¦æ”¶èŽ·/ä¹¦ç±�/u"   è¯»ä¹¦æ”¶èŽ·/reading-insights.jsonz.weread/tmp/shelf.jsonz".weread/tmp/last_reading_note.jsonúreading-note-status.jsonc                  C   s$   t  t jdd�¡} t j  | ¡ d¡S )Nr   ©Zhoursú%Y-%m-%d)ÚdatetimeÚtimezoneÚ	timedeltaÚnowÚstrftime)Útz8© r!   ú/opt/workbuddy/server.pyÚ_local_today_strT   s    r#   c               	   C   sd   t j t¡sdS z8ttddd��} t | ¡}W 5 Q R X t| d¡pDdƒW S  t	k
r^   Y dS X d S )NÚ Úrúutf-8©ÚencodingÚdate)
ÚosÚpathÚexistsÚLAST_NOTE_PATHÚopenÚjsonÚloadÚstrÚgetÚ	Exception©Úfr   r!   r!   r"   Ú_last_reading_note_dateY   s    r6   c               	   C   sž   t j t¡sdS zrttddd��} t | ¡}W 5 Q R X t| d¡pDdƒ}t	|t
ƒr\| d¡ng }t|phg ƒdk rvW dS |d d… W S  tk
r˜   Y dS X d S )	Nr$   r%   r&   r'   Ú	updatedAtÚvideosé   é
   )r*   r+   r,   ÚHOT_VIDEOS_PATHr.   r/   r0   r1   r2   Ú
isinstanceÚdictÚlenr3   )r5   r   Z
updated_atr8   r!   r!   r"   Ú_last_hot_video_dated   s    r?   c                    s,   ˆ pd  dd¡ d¡‰ t‡ fdd„tD ƒƒS )Nr$   ú\r   c                 3   s&   | ]}ˆ |  d ¡kpˆ  |¡V  qdS )r   N)ÚrstripÚ
startswith)Ú.0Úprefix©Úrel_pathr!   r"   Ú	<genexpr>u   s     z0_is_allowed_reading_sync_path.<locals>.<genexpr>)ÚreplaceÚlstripÚanyÚREADING_SYNC_PREFIXESrE   r!   rE   r"   Ú_is_allowed_reading_sync_paths   s    rL   c               
   C   sN  g } t j td¡t j td¡t j tddd¡t j tddd¡g}t j t¡rŠt  t¡D ]2\}}}|D ]"}|dkrrqd| t j ||¡¡ qdqVt	ƒ }|D ]´}|r”t j |¡r”t j 
|¡s¶q”t j |t¡ dd	¡}||ks”t|ƒsÞq”| |¡ zDt|d
dd��}	|	 ¡ }
W 5 Q R X |  ||
tt j |¡ƒdœ¡ W q” tk
�rF   Y q”Y q”X q”| S )Nr   zreading-insights.jsonr   r   r   r   )õ   ä¹¦ç±�æ¡£æ¡ˆ.mdúmetadata.jsonr@   r   r%   r&   r'   )r+   ÚcontentÚmtime)r*   r+   ÚjoinÚ	WORKSPACEÚREADING_NOTES_DIRr,   ÚREADING_BOOKS_DIRÚwalkÚappendÚsetÚisfileÚrelpathrH   rL   Úaddr.   r   ÚintÚgetmtimer3   )ÚfilesZ
candidatesÚrootÚ_ÚnamesÚnameÚseenr+   rF   r5   rO   r!   r!   r"   Ú_collect_reading_sync_filesx   s>    ü
ýrc   é   c              
   C   s  t jdkrddddœS tjdd�s,dddœS zÚzštƒ }|sLddd	d
œW W ¢¾S tjtt	t
 
¡ ƒ|dœdd� d¡}tjjt› d�|ddidd�}tjj|| d��}t | ¡  dd¡¡}W 5 Q R X |W W ¢@S  tk
�r } zdt|ƒdœ W Y ¢W ¢S d }~X Y nX W 5 t ¡  X d S )NÚntTz0cloud sync runs from the Windows desktop service©ÚokÚskippedÚreasonF©Zblockingu!   è¯»ä¹¦æ¡£æ¡ˆäº‘å�Œæ­¥æ­£åœ¨è¿�è¡Œ©rg   Úerrorr   )rg   rh   r]   )Útokenr7   r]   ©Úensure_asciir&   ú/api/reading-sync/importúContent-Typeúapplication/json; charset=utf-8ÚPOST©r   ÚheadersÚmethod©ÚtimeoutÚignore)r*   ra   Ú_reading_cloud_sync_lockÚacquireÚreleaserc   r/   ÚdumpsÚREADING_SYNC_TOKENr[   ÚtimeÚencodeÚurllibÚrequestÚRequestÚCLOUD_SERVER_ORIGINÚurlopenÚloadsr   Údecoder3   r1   )rx   r]   ÚpayloadÚreqÚrespÚresultÚer!   r!   r"   Úsync_reading_artifacts_to_cloud›   s:    


ýüüü 
,r�   c                     sˆ  t j t¡s4tƒ } |  d¡r(d| d< | S ddtdœS i }d}t j t¡rÊzdttdd	d
��}t 	|¡}W 5 Q R X | d¡}t
|tƒr”| ¡ r”t |¡}tt| d¡p¤dƒƒ}W n tk
rÈ   i }d}Y nX zHdd l}|jdt› d�dd�}|j|_| ¡ }| d¡ ¡ }	| ¡  W n8 tk
�rJ }
 zdt|
ƒtdœ W Y ¢S d }
~
X Y nX i }i }g }|	D ]ø}t|d �pndƒ}t d|¡�s„�q\|d d… › d|dd… › d|dd… › �}t|d �p¾dƒ}t|d �pÐdƒ}td|| ƒ}|||< |||< | ||tt|d ƒƒ||tt|d ƒƒt|d �p(dƒt|d �p8dƒt|d �pHdƒdœ	¡ �q\t| d ¡�pr| d!¡�prdƒ‰ td|d ƒ}t d"ˆ ¡�r$|t| ˆ ¡�p¤dƒk�r$||ˆ < tt| ˆ ¡�pÆdƒ|ƒ|ˆ < t‡ fd#d$„|D ƒƒ�s$| dˆ |tt|d ƒƒd|tt|d ƒƒdddd%d&œ
¡ tƒ }| d¡�rpd'd(„ |D ƒ}| d)¡�pRi   ¡ D �]\}}zt|�pndƒ}W n tk
�rŽ   d}Y nX t d"t|�p dƒ¡�rX|t| |¡�pºdƒk�rÆ�qXtt|d ƒƒ}|||< tt| |¡�pðdƒ|ƒ||< | |¡}|�r:| !tt| d¡�p"dƒ|ƒ|||d*d+œ¡ n | |||d||d,ddd*d&œ
¡ �qX|j"d-d.„ dd/� dd0tt|||||d1œ	S )2Nrg   ul   å½“å‰�æœ�åŠ¡æ— æ³•è¯»å�–æ¯�æ—¥è‹±è¯­å�¬åŠ› Windows å®¢æˆ·ç«¯æ—¥å¿—ï¼Œå·²ä½¿ç”¨äº‘ç«¯å·¥ä½œå�°å�Œæ­¥è®°å½•ã€‚ÚwarningFu=   æœªæ‰¾åˆ°æ¯�æ—¥è‹±è¯­å�¬åŠ› Windows å®¢æˆ·ç«¯æ—¥å¿— events.db)rg   rl   Ú
sourcePathr   r%   r&   r'   ZKey_User_CheckIn_InfoZplanDurationzfile:z?mode=roT)Zuria´  
            select epoch,
                   count(*) as count,
                   sum(coalesce(duration, 0)) as listenSeconds,
                   sum(coalesce(read_duration, 0)) as readSeconds,
                   min(timestamp) as firstTimestamp,
                   max(timestamp) as lastTimestamp
            from Logs
            where type = 'LISTEN_DURATION'
            group by epoch
            order by epoch desc
            Zepochr$   z\d{8}é   ú-é   r   ÚlistenSecondsÚreadSecondsr   ÚcountÚfirstTimestampÚlastTimestamp)	r)   r“   ÚlistenMinutesr”   ÚstudySecondsÚstudyMinutesr•   r–   r—   ZcheckinDateLocalZcheckinDateú\d{4}-\d{2}-\d{2}c                 3   s   | ]}|  d ¡ˆ kV  qdS )r)   N©r2   ©rC   Úitem©Zfallback_dater!   r"   rG     s     z5read_daily_english_listening_stats.<locals>.<genexpr>zcheckin-planDuration©
r)   r“   r˜   r”   r™   rš   r•   r–   r—   ÚsourceDetailc                 S   s"   i | ]}t |tƒr| d ¡|“qS ©r)   ©r<   r=   r2   r�   r!   r!   r"   Ú
<dictcomp>  s     
  z6read_daily_english_listening_stats.<locals>.<dictcomp>Ú	readTimeszlife-data-englishMinutes-merged)r“   r˜   r™   rš   r¡   é   c                 S   s   |   d¡pdS ©Nr)   r$   rœ   ©rž   r!   r!   r"   Ú<lambda>4  ó    z4read_daily_english_listening_stats.<locals>.<lambda>©ÚkeyÚreverseu.   æ¯�æ—¥è‹±è¯­å�¬åŠ› Windows å®¢æˆ·ç«¯ events.db)	rg   Úsourcer�   Z
configPathZcheckinInfoÚplanDurationMinutesr¥   ÚlistenTimesÚrecords)#r*   r+   r,   ÚDAILY_ENGLISH_EVENTS_DBÚ'read_daily_english_stats_from_life_datar2   ÚDAILY_ENGLISH_CONFIG_JSONr.   r/   r0   r<   r1   Ústripr†   r[   Úfloatr3   Úsqlite3ZconnectZRowZrow_factoryZcursorZexecuteZfetchallÚcloseÚreÚ	fullmatchÚmaxrV   ÚroundrJ   ÚinsertÚitemsÚupdateÚsort)ZfallbackZcheckin_infoZplan_durationr5   ZcfgZraw_checkinr·   ZconZcurZrowsrŒ   Ú
read_timesZlisten_timesr±   ZrowZ	raw_epochÚdate_keyZlisten_secondsZread_secondsZstudy_secondsZfallback_secondsZlife_fallbackZexisting_recordsÚsecondsÚminutesÚexistingr!   rŸ   r"   Ú"read_daily_english_listening_stats¸   sð    
ý


ÿ&,÷ (ö
2
û
ö÷rÆ   c               	   C   sf   t j t¡si S z8ttddd��} t | ¡}W 5 Q R X t|tƒrD|ni W S  t	k
r`   i  Y S X d S ©Nr%   r&   r'   )
r*   r+   r,   ÚLIFE_DATA_PATHr.   r/   r0   r<   r=   r3   r4   r!   r!   r"   Ú_load_life_data_fileB  s    rÉ   c            
      C   s`  t ƒ } t| tƒr|  d¡ni }t|tƒs,i }i }g }| ¡ D ]ø\}}t dt|pRdƒ¡sZq<t|tƒrn| d¡ng }t|tƒs~q<t	dd„ |D ƒd ƒ}t|tƒr¶t
tt| d¡p®dƒƒƒnd}|dkrÄq<|d	 }	|	||< | ||	|d|	|d
t|tƒ�rt
| d¡�pdƒndt|tƒ�r(t
| d¡�p$dƒndddœ
¡ q<|jdd„ dd� t|ƒdtd|||dœS )NÚ	dailyPlanr›   r$   Úpresetsc                 s   s*   | ]"}t |tƒr| d ¡dkr|V  qdS ©Úidr   Nr£   r�   r!   r!   r"   rG   Z  s     
  z:read_daily_english_stats_from_life_data.<locals>.<genexpr>ÚenglishMinutesr   r   r¦   ÚcompletedAtzlife-data-englishMinutesr    c                 S   s   |   d¡pdS r§   rœ   r¨   r!   r!   r"   r©   l  rª   z9read_daily_english_stats_from_life_data.<locals>.<lambda>Tr«   u,   äº‘ç«¯å·¥ä½œå�° life-data è‹±è¯­æ‰“å�¡è®°å½•é   )rg   r®   r�   r¯   r¥   r°   r±   )rÉ   r<   r=   r2   r¾   r¹   rº   r1   ÚlistÚnextr[   r¼   r¶   rV   rÀ   ÚboolrÈ   )
r   ÚdailyrÁ   r±   rÂ   ÚplanrË   ÚtaskrÄ   rÃ   r!   r!   r"   r³   M  sN    

(""ö
ùr³   c                    sv   |   di ¡}|  |g g dœ¡}|  dg ¡}|  dg ¡ dD ]6‰ t‡ fdd„|D ƒƒs:| ˆ t ˆ ˆ ¡dd	d
œ¡ q:|S )NrÊ   ©rË   ÚcustomsrË   rØ   )r   r   r   r   c                 3   s&   | ]}t |tƒo| d ¡ˆ kV  qdS ©rÍ   Nr£   r�   ©Z	preset_idr!   r"   rG   ~  s     z-_ensure_life_plan_for_date.<locals>.<genexpr>FZpreset)rÍ   ra   ÚcheckedÚtype)Ú
setdefaultrJ   rV   ÚPRESET_DISPLAY_NAMESr2   )r   rÂ   rÔ   rÕ   rË   r!   rÚ   r"   Ú_ensure_life_plan_for_datex  s    
ü
rß   c                    sÐ   |   di ¡}|  dg ¡}t|tƒs.g }||d< d|› �‰ t‡ fdd„|D ƒd ƒ}ˆ |dt|ƒddt d	t |pxt ¡ d
 d
 ¡¡t|p�t ¡ d
 ƒdœ}|rÂt|ƒt| d¡p°dƒkrÌ| 	|¡ n
| 
|¡ d S )NÚenglishLearnÚsessionsZdaily_english_listening_c                 3   s*   | ]"}t |tƒr| d ¡ˆ kr|V  qdS rÙ   r£   r�   ©Z
session_idr!   r"   rG   �  s     
  z*_upsert_english_session.<locals>.<genexpr>u   æ¯�æ—¥è‹±è¯­å�¬åŠ›u*   æ¯�æ—¥è‹±è¯­å�¬åŠ› Windows å®¢æˆ·ç«¯å�Œæ­¥zdaily-english-listeningz%H:%Méè  )rÍ   r)   ÚskillrÄ   Údetailr¬   r   Ú	timestamprÄ   r   )rÝ   r<   rÑ   rÒ   r[   r   r   Ú	localtimer2   r¿   rV   )r   rÂ   rÄ   ræ   r   rá   rÅ   rˆ   r!   râ   r"   Ú_upsert_english_sessionˆ  s(    

 ø
rè   c              
   C   s0  t jdkrddddœS tjdd�s,dddœS �zò�z°tƒ }| d	¡sP|W W �¢ÔS tƒ }d}tj 	¡  
¡ tjd
d� }| d¡p€g D �]z}t| d¡p–dƒ}t d|¡s¨q‚ztj |d¡ 
¡ |k rÄW q‚W n tk
rÞ   Y q‚Y nX tt| d¡pðdd ƒƒ}|dk�rq‚t||ƒ}tdd„ | dg ¡D ƒd ƒ}	|	�s4q‚t|	 d¡�pDdƒ}
||
kr‚||	d< d|	d< d|	d< |dk�p~t|	 d¡ƒ|	d< |	d �rº|	 d¡�sºt| d¡�p²t ¡ d ƒ|	d< |	d �rÐd |› d!�n
d |› d"�|	d#< t|||| d¡�pödƒ d}q‚|�sdd|d$œW W �¢
S tt ¡ d ƒ|d%< t d&¡|d'< ttd(d)d*��}tj||dd+d,� W 5 Q R X tjd-|idd.� d)¡}tj j!t"› d/�|d0d1id2d3�}tj j#|| d4��}t $| %¡  &d)d5¡¡}W 5 Q R X dd||d6œW W ¢@S  t'k
�r } zdt|ƒdœ W Y ¢W ¢S d }~X Y nX W 5 t ¡  X d S )7Nre   TuN   æ¯�æ—¥è‹±è¯­å�¬åŠ›å�Œæ­¥å�ªåœ¨ Windows æ¡Œé�¢æœ�åŠ¡è¯»å�–æœ¬æœºå®¢æˆ·ç«¯æ—¥å¿—rf   Frj   u'   æ¯�æ—¥è‹±è¯­å�¬åŠ›äº‘å�Œæ­¥æ­£åœ¨è¿�è¡Œrk   rg   é   )Zdaysr±   r)   r$   r›   r   r™   r   r   c                 s   s*   | ]"}t |tƒr| d ¡dkr|V  qdS rÌ   r£   r�   r!   r!   r"   rG   º  s     
  z<sync_daily_english_listening_to_life_data.<locals>.<genexpr>rË   rÎ   ZdailyEnglishListeningÚautoCheckinrÐ   ÚthresholdMinutesrÛ   rÏ   r—   rã   u   æ¯�æ—¥è‹±è¯­å�¬åŠ› õ    åˆ†é’Ÿï¼Œå·²è‡ªåŠ¨æ‰“å�¡u"    åˆ†é’Ÿï¼Œæ»¡ 5 åˆ†é’Ÿè‡ªåŠ¨æ‰“å�¡Ú
statusText)rg   ÚchangedÚstatsÚ__syncUpdatedAtú%Y-%m-%d %H:%M:%SÚ__syncSavedAtÚwr&   r'   é   ©ro   Úindentr   rn   ú/api/life-datarq   rr   rs   rt   rw   ry   )rg   rî   Úcloudrï   )(r*   ra   Ú_english_cloud_sync_lockr{   r|   rÆ   r2   rÉ   r   r   r)   r   r1   r¹   rº   ÚstrptimeÚ
ValueErrorr[   r¼   rß   rÒ   rÓ   r   rè   r   r.   rÈ   r/   Údumpr}   r€   r�   r‚   rƒ   r„   r…   r†   r   r‡   r3   )rx   rï   r   rî   ÚcutoffÚrecordrÂ   rÄ   rÕ   rÖ   Zpreviousr5   rˆ   r‰   rŠ   rø   rŒ   r!   r!   r"   Ú)sync_daily_english_listening_to_life_data¡  sr    





 &ü ,rÿ   c                  C   s.   t jdkrd S dd„ } tj| ddd� ¡  d S )Nre   c                   S   s$   t  d¡ tdd� t  d¡ q
d S )Nr9   rd   rw   éZ   )r   Úsleeprÿ   r!   r!   r!   r"   Úloopá  s    

z4start_english_listening_sync_scheduler.<locals>.loopTzenglish-listening-cloud-sync©ÚtargetZdaemonra   )r*   ra   Ú	threadingÚThreadÚstart©r  r!   r!   r"   Ú&start_english_listening_sync_schedulerÞ  s    
r	  é´   c              
   C   sH  t j t¡sdddœS tjdd�s,dddœS �z
z¦tjt	j
tgtdddd| d	�}|jpXd
 ¡ }|jpfd
 ¡ }|r‚t | ¡ d ¡nd|jdki}|jdkrºd|d< |p´|p´d|j› �|d< ||d< |rÎ||d< |W W ¢dS  tjk
� rü   dddœ Y W ¢@S  tk
�r4 } zdt|ƒdœ W Y ¢W ¢S d }~X Y nX W 5 t ¡  X d S )NFzhot_video_auto.py not foundrk   rj   u3   çƒ­é—¨è§†é¢‘æŠ“å�–æ­£åœ¨è¿�è¡Œï¼Œè¯·ç¨�å�Žå†�è¯•ã€‚Tr&   rH   ©ÚcwdÚcapture_outputÚtextr(   Úerrorsrx   r$   éÿÿÿÿrg   r   ú
exit code rl   ÚstdoutÚstderru-   çƒ­é—¨è§†é¢‘æŠ“å�–è¶…æ—¶ï¼Œè¯·ç¨�å�Žé‡�è¯•ã€‚)r*   r+   r,   ÚHOT_VIDEO_AUTO_SCRIPTÚ_hot_video_auto_lockr{   r|   Ú
subprocessÚrunÚsysÚ
executablerR   r  rµ   r  r/   r†   Ú
splitlinesÚ
returncodeÚTimeoutExpiredr3   r1   )rx   Úprocr  r  r‹   rŒ   r!   r!   r"   Úrun_hot_video_auto_jobé  s:    

ù	$

,r  c           	   
   C   sˆ  t j t¡sdddœS tjdd�s,dddœS �zJzætjtg}|d k	rX| 	dt
|ƒ› �¡ |rv| 	dtdt
|ƒƒ› �¡ tj|td	d	d
d| d�}|jp–d ¡ }|jp¤d ¡ }|rÀt | ¡ d ¡nd|jdki}|jdkrød|d< |pò|pòd|j› �|d< ||d< |�r||d< |W W ¢dS  tjk
�r<   dddœ Y W ¢@S  tk
�rt } zdt|ƒdœ W Y ¢W ¢S d }~X Y nX W 5 t ¡  X d S )NFz#ai_learning_video_auto.py not foundrk   rj   u8   AIå­¦ä¹ è§†é¢‘æŽ¨è��æ­£åœ¨ç”Ÿæˆ�ä¸­ï¼Œè¯·ç¨�å�Žå†�è¯•ã€‚z--completed-count=z--refresh-offset=r   Tr&   rH   r  r$   r  rg   r  rl   r  r  u5   AIå­¦ä¹ è§†é¢‘æŽ¨è��ç”Ÿæˆ�è¶…æ—¶ï¼Œè¯·ç¨�å�Žé‡�è¯•ã€‚)r*   r+   r,   ÚAI_LEARNING_VIDEO_AUTO_SCRIPTÚ_ai_learning_video_auto_lockr{   r|   r  r  rV   r[   r»   r  r  rR   r  rµ   r  r/   r†   r  r  r  r3   r1   )	rx   Úcompleted_countÚrefresh_offsetÚcmdr  r  r  r‹   rŒ   r!   r!   r"   Úrun_ai_learning_video_job
  sD    


ù	$

,r$  c              
   C   s’  t j t¡sddtdœS tjdd�s.dddœS �zRzîtjt	j
tgtdddd	| d
�}|jdkrzdd|j|j|jdœW W �¢S dd dœaddi}t j t¡rôz(ttddd��}t |¡}W 5 Q R X W n2 tk
rò } zdd|› �dœ}W 5 d }~X Y nX d|d< |j ¡ |d< tdd�|d< |W W ¢dS  tjk
�rF   dddœ Y W ¢@S  tk
�r~ } zdt|ƒdœ W Y ¢W ¢S d }~X Y nX W 5 t ¡  X d S )NFz'reading note generator script not found)rg   rl   Zscriptrj   u0   è¯»ä¹¦æ”¶èŽ·æ­£åœ¨ç”Ÿæˆ�ä¸­ï¼Œè¯·ç¨�å�ŽæŸ¥çœ‹ã€‚rk   Tr&   rH   r  r   u   ç”Ÿæˆ�è„šæœ¬æ‰§è¡Œå¤±è´¥)rg   rl   r  r  r  r   rg   r%   r'   u0   ç¬”è®°å·²ç”Ÿæˆ�ï¼Œä½†çŠ¶æ€�æ–‡ä»¶è¯»å�–å¤±è´¥ï¼š)rg   rŽ   r  rd   rw   Z	cloudSyncu!   ç”Ÿæˆ�è¶…æ—¶ï¼Œè¯·ç¨�å�Žé‡�è¯•ã€‚)r*   r+   r,   ÚREADING_AUTO_SCRIPTÚ_reading_auto_lockr{   r|   r  r  r  r  rR   r  r  r  Ú_readtimes_cacher-   r.   r/   r0   r3   rµ   r�   r  r1   )rx   r  Ústatus_datar5   rŒ   r!   r!   r"   Úrun_reading_auto_job0  sR    ý
ù	
û
"
,r)  c                  C   s    dd„ } t j| ddd� ¡  d S )Nc                  S   sV  z°t  t jdd�¡} t j  | ¡}|jtkr®tƒ | d¡kr®tdd�}t	j
 tdd¡}t	j|dd	� tt	j
 |d
¡ddd��.}| d| d¡› dtj|dd�› d�¡ W 5 Q R X W n” tk
�rD } ztzXt	j
 tdd¡}t	j|dd	� tt	j
 |d
¡ddd��}| d|› d�¡ W 5 Q R X W n tk
�r2   Y nX W 5 d }~X Y nX t d¡ q d S )Nr   r   r   r
  rw   r   r   T©Úexist_okzreading-auto.logÚar&   r'   ú[rñ   z] scheduled 08:00 result=Frn   Ú
ú[scheduler-error] r   )r   r   r   r   ÚhourÚREADING_AUTO_HOURr6   r   r)  r*   r+   rQ   rR   Úmakedirsr.   Úwriter/   r}   r3   r   r  ©r    r   r‹   Zlog_dirr5   rŒ   r!   r!   r"   r  a  s$    
6 z*start_reading_auto_scheduler.<locals>.loopTzreading-auto-08r  ©r  r  r  r  r!   r!   r"   Ústart_reading_auto_scheduler`  s    r6  c                  C   s    dd„ } t j| ddd� ¡  d S )Nc                  S   sR  z®t  t jdd�¡} t j  | ¡}|jtkr¬tƒ | d¡kr¬tdd�}t	j
 td¡}t	j|dd� tt	j
 |d	¡d
dd��.}| d| d¡› dtj|dd�› d�¡ W 5 Q R X W n’ tk
�r@ } zrzVt	j
 td¡}t	j|dd� tt	j
 |d	¡d
dd��}| d|› d�¡ W 5 Q R X W n tk
�r.   Y nX W 5 d }~X Y nX t d¡ q d S )Nr   r   r   r
  rw   z
.workbuddyTr*  zhot-video-auto.logr,  r&   r'   r-  rñ   z] scheduled 07:00 result=Frn   r.  r/  r   )r   r   r   r   r0  ÚHOT_VIDEO_AUTO_HOURr?   r   r  r*   r+   rQ   rR   r2  r.   r3  r/   r}   r3   r   r  r4  r!   r!   r"   r  y  s$    
6 z,start_hot_video_auto_scheduler.<locals>.loopTzhot-video-auto-07r  r5  r  r!   r!   r"   Ústart_hot_video_auto_schedulerx  s    r8  c                       sâ  e Zd Z‡ fdd„Zdd„ Zdd„ Zdd„ Zd¸d
d„Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd¹d"d#„Zd$d%„ Zd&d'„ Zdºd*d+„Zd,d-„ Zd»d/d0„Zd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ Zd9d:„ Zd;d<„ Zd=d>„ Zd?d@„ ZdAdB„ Z dCdD„ Z!dEdF„ Z"dGdH„ Z#dIdJ„ Z$dKdL„ Z%dMdN„ Z&dOdP„ Z'dQdR„ Z(dSdT„ Z)dUdV„ Z*dWdX„ Z+dYdZ„ Z,d[d\„ Z-d]d^„ Z.d_d`„ Z/dadb„ Z0dcdd„ Z1dedf„ Z2dgdh„ Z3didj„ Z4dkdl„ Z5dmdn„ Z6dodp„ Z7d¼drds„Z8dtdu„ Z9dvdw„ Z:d½dydz„Z;d{d|„ Z<d}d~„ Z=dd€„ Z>d�d‚„ Z?dƒd„„ Z@d…d†„ ZAd‡dˆ„ ZBd‰dŠ„ ZCd‹dŒ„ ZDd�dŽ„ ZEd�d�„ ZFd‘d’„ ZGd“d”„ ZHd•d–„ ZId—d˜„ ZJd™dš„ ZKd›dœ„ ZLd�dž„ ZMdŸd „ ZNd¡d¢„ ZOd¾d¤d¥„ZPd¦d§„ ZQd¨d©„ ZRdªd«„ ZSd¬d­„ ZTd®d¯„ ZUd°d±„ ZV‡ fd²d³„ZW‡ fd´dµ„ZXd¶d·„ ZY‡  ZZS )¿ÚHandlerc                    s,   t ƒ  |¡}| d¡r(d|kr(|› d�S |S )Nztext/zcharset=z; charset=utf-8)ÚsuperÚ
guess_typerB   )Úselfr+   Zcontent_type©Ú	__class__r!   r"   r;  ‘  s    
zHandler.guess_typec                 C   sV   d  t| dg ƒ¡ ¡ }d|kr*|  dd¡ d|kr>|  dd¡ d	|krR|  d
d¡ d S )Nrª   Z_headers_buffers   access-control-allow-origin:zAccess-Control-Allow-OriginÚ*s   access-control-allow-methods:zAccess-Control-Allow-MethodszGET, POST, OPTIONSs   access-control-allow-headers:zAccess-Control-Allow-Headersrq   )rQ   ÚgetattrÚlowerÚsend_header)r<  rÅ   r!   r!   r"   Ú_cors—  s    zHandler._corsc                 C   s   |   d¡ |  ¡  |  ¡  d S )NéÈ   )Úsend_responserC  Úend_headers©r<  r!   r!   r"   Ú
do_OPTIONS   s    
zHandler.do_OPTIONSc              
   C   s`   t j t¡sd S z4ttddd��}| ¡  ¡ W  5 Q R £ W S Q R X W n tk
rZ   Y d S X d S rÇ   )r*   r+   r,   ÚKEY_PATHr.   r   rµ   r3   )r<  r5   r!   r!   r"   Ú	_read_key¥  s    $zHandler._read_keyr:   c           	   
   C   s˜   |   ¡ }|stdƒ‚tjd|dœ|–dd� d¡}tjjt|d|› �dd	œd
d�}t	 
¡ }tjj|||d��"}t | ¡  d¡¡W  5 Q R £ S Q R X d S )NzWEREAD_API_KEY not configuredz1.0.4)Zskill_versionÚapi_nameFrn   r&   úBearer úapplication/json©ZAuthorizationrq   rs   rt   )rx   Úcontext)rJ  ÚRuntimeErrorr/   r}   r€   r�   r‚   rƒ   ÚGW_URLÚsslZcreate_default_contextr…   r†   r   r‡   )	r<  rK  rˆ   rx   r¬   Úbodyr‰   ZctxrŠ   r!   r!   r"   Ú_gw_post®  s    üzHandler._gw_postc              
   C   sú  | j  d¡r|  ¡  �nÞ| j  d¡r0|  ¡  �nÆ| j  d¡rH|  ¡  �n®| j  d¡r`|  ¡  �n–| j  d¡rx|  ¡  �n~| j  d¡r�|  ¡  �nf| j  d¡r¨|  ¡  �nN| j  d¡rÀ|  	¡  �n6| j  d	¡rØ|  
¡  �n| j  d
¡rð|  ¡  �n| j  d¡�r
|  ¡  �nì| j  d¡�rÜz<t| j dd¡ƒ}|�r>| j |¡nd}t | d¡¡}W nf tk
�rº } zF|  d¡ |  ¡  |  ¡  | j t dt|ƒdœ¡ d¡¡ W Y ¢d S d }~X Y nX t|tƒ�rÔ| dg ¡ng }t|tƒ�rð| dd¡nd|dœ}z0t t!ddd��}tj"||ddd� W 5 Q R X W nf tk
�r� } zF|  d¡ |  ¡  |  ¡  | j t dt|ƒdœ¡ d¡¡ W Y ¢d S d }~X Y nX |  d¡ |  ¡  |  #dd¡ |  ¡  | j t d t$|ƒd!œ¡ d¡¡ n|  d"¡ |  ¡  |  ¡  d S )#Nz/api/generate-reading-notez/api/delete-reading-noterp   z/api/hot-videos/runz/api/ai-learning-videos/runz/api/viral-video/analyzer÷   z /api/favorite-collections/importz/api/favorite-collections/loginz/api/favorite-collections/syncz!/api/favorite-collections/analyzez/syncúContent-Lengthr   ó   {}r&   é�  Frk   ÚbooksÚupdatedr$   )rY  rX  ró   r'   rô   rõ   éô  rD  rq   rr   T)rg   r•   é”  )%r+   rB   Ú_generate_reading_noteÚ_delete_reading_noteÚ_import_reading_syncÚ_run_hot_videosÚ_run_ai_learning_videosÚ_analyze_viral_videoÚ_save_life_dataÚ_import_favorite_collectionsÚ_login_favorite_collectionsÚ_sync_favorite_collectionsÚ!_analyze_favorite_collection_itemr[   ru   r2   Úrfiler   r/   r†   r‡   r3   rE  rC  rF  Úwfiler3  r}   r1   r€   r<   r=   r.   Ú	SYNC_PATHrü   rB  r>   )r<  ÚlengthrS  r   rŒ   rX  Zsnapshotr5   r!   r!   r"   Údo_POST½  sh    
"" 
"
$
zHandler.do_POSTc                 C   s*   t dd�}| j|| d¡rdndd� d S ©Nr
  rw   rg   rD  rZ  ©Ústatus)r)  Ú_json_responser2   )r<  r(  r!   r!   r"   r\  ô  s    
zHandler._generate_reading_notec              
   C   s  z|   ¡ }t| d¡pdƒ}W nB tk
r` } z$| jdd|› �dœdd� W Y ¢d S d }~X Y nX |  |¡}|sˆ| jdddœdd� d S d}tj |¡r¦t 	|¡ d	}t
ƒ |krøttj td
¡fD ]4}ztj |¡rÞt 	|¡ W qÂ tk
rô   Y qÂX qÂ|  d	||dœ¡ d S )Nr)   r$   Fõ   è¯·æ±‚æ ¼å¼�é”™è¯¯ï¼šrk   rW  rm  u   æ—¥æœŸæ ¼å¼�é”™è¯¯Tr   )rg   Údeletedr)   )Ú_read_json_bodyr1   r2   r3   ro  Ú_reading_note_file_for_dater*   r+   r,   Úremover6   r-   rQ   rR   )r<  rˆ   Údate_strrŒ   Ú	note_pathrq  Zstatus_pathr!   r!   r"   r]  ø  s0    


þzHandler._delete_reading_notec              
   C   sþ  �zº|   ¡ }t|tƒr$| d¡tkr>| jdddœdd� W d S | d¡}t|tƒsl| jdddœd	d� W d S d
}d
}|D �],}t|tƒs’|d7 }qxt| d¡p dƒ dd¡ 	d¡}| d¡}|rÒt
|ƒrÒt|tƒsÜ|d7 }qxtj tjjtf| d¡žŽ ¡}| tj t¡tj ¡�s |d7 }qxtjtj |¡dd� t|ddd��}	|	 |¡ W 5 Q R X | d¡}
z"|
�r„t |t|
ƒt|
ƒf¡ W n tk
�rœ   Y nX |d7 }qx|  d||dœ¡ W n< tk
�rø } z| jdt|ƒdœdd� W 5 d }~X Y nX d S )Nrm   FZunauthorizedrk   i“  rm  r]   zfiles must be a listrW  r   r¦   r+   r$   r@   r   rO   Tr*  ró   r&   r'   rP   )rg   Úwrittenrh   rZ  )rr  r<   r=   r2   r~   ro  rÑ   r1   rH   rI   rL   r*   r+   ÚabspathrQ   rR   ÚsplitrB   Úsepr2  Údirnamer.   r3  Úutimer[   r3   )r<  rˆ   r]   rw  rh   rž   rF   rO   r  r5   rP   rŒ   r!   r!   r"   r^    sJ    



 
 

zHandler._import_reading_syncc                 C   s*   t dd�}| j|| d¡rdndd� d S rl  )r  ro  r2   )r<  r‹   r!   r!   r"   r_  :  s    
zHandler._run_hot_videosc                 C   s²   d }d}z^|   ¡ }t|tƒr8| d¡d k	r8t| d¡ƒ}t|tƒrd| d¡d k	rdtdt| d¡ƒƒ}W n tk
r‚   d }d}Y nX td||d�}| j|| d¡r¦dndd	� d S )
Nr   ZcompletedCountZrefreshOffsetr
  )rx   r!  r"  rg   rD  rZ  rm  )	rr  r<   r=   r2   r[   r»   r3   r$  ro  )r<  r!  r"  rˆ   r‹   r!   r!   r"   r`  >  s    
zHandler._run_ai_learning_videosc                 C   s&   t  d|pdt j¡}|r"| d¡S dS )Nõ   https?://[^\sï¼Œã€‚)ï¼‰]+r$   r   )r¹   ÚsearchÚIÚgroup)r<  r  Úmatchr!   r!   r"   Ú_extract_first_urlM  s    zHandler._extract_first_urlc              	   C   s|   t j t¡sg S zNttddd��}t |¡}W 5 Q R X t|tƒrL| 	dg ¡nt|t
ƒrZ|ng W S  tk
rv   g  Y S X d S )Nr%   r&   r'   r8   )r*   r+   r,   r;   r.   r/   r0   r<   r=   r2   rÑ   r3   )r<  r5   r   r!   r!   r"   Ú_load_hot_videosQ  s    *zHandler._load_hot_videosc                 C   s:   t |pdƒ ¡  ¡ }t dd|¡}t dd|¡}| d¡S )Nr$   z
^https?://z[?#].*$r   )r1   rµ   rA  r¹   ÚsubrA   )r<  Úurlr!   r!   r"   Ú_normalize_video_url[  s    zHandler._normalize_video_urlc                 C   sf   |   |¡}|sd S |  ¡ D ]F}|   | d¡p8| d¡p8d¡}|r||ksX||ksX||kr|  S qd S )Nr…  Úlinkr$   )r†  rƒ  r2   )r<  r…  r  ÚvideoÚcurrentr!   r!   r"   Ú_match_hot_videoa  s    

zHandler._match_hot_videoúhttps://www.bilibili.com/é   c              
   C   sX   t jj|d|dddœd�}t jj||d��$}t | ¡  dd¡¡W  5 Q R £ S Q R X d S )	NzoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36z!application/json, text/plain, */*zzh-CN,zh;q=0.9,en;q=0.8)z
User-AgentZRefererZAcceptzAccept-Language)ru   rw   r&   ry   )r�   r‚   rƒ   r…   r/   r†   r   r‡   )r<  r…  Zrefererrx   r‰   rŠ   r!   r!   r"   Ú_fetch_json_urlk  s    üþ	zHandler._fetch_json_urlc                 C   sH  t |pdƒ}t d|¡}t d|¡}|rDdtj d| d¡i¡ }n(|rddtj d| d¡i¡ }ntdƒ‚|  |¡}| 	d	¡d
kr–t| 	d¡p’dƒ‚| 	d¡p¢i }| 	d¡p°i }| 	d¡p¾i }	d }
|	 	d¡�r$z8|  dtj d|	 	d¡i¡ ¡}| 	d¡pþi  	d¡}
W n t
k
�r"   d }
Y nX g }z>|  dtj d| 	d¡i¡ ¡}dd„ | 	d¡�p^g D ƒ}W n t
k
�r€   g }Y nX | 	d¡}t|tƒ�r¼t|
tƒ�r¼|
d
k�r¼t||
 dƒnd }d| 	d¡�pÐd| 	d¡�rîd| 	d¡› d�n|||| 	d¡| 	d¡|
|
||d d… �pdg|	 	d ¡�p*d| 	d!¡| 	d"¡�p@dd#d$œS )%Nr$   z(BV[0-9A-Za-z]+)z(?:/video/|av)(\d+)z.https://api.bilibili.com/x/web-interface/view?Zbvidr¦   Zaidu%   æ²¡æœ‰è¯†åˆ«åˆ° Bç«™ BV å�·æˆ– av å�·Úcoder   Úmessageu   Bç«™æŽ¥å�£æœªè¿”å›žè§†é¢‘ä¿¡æ�¯r   ÚstatÚownerZmidz)https://api.bilibili.com/x/relation/stat?ZvmidZfollowerz,https://api.bilibili.com/x/tag/archive/tags?c                 S   s    g | ]}|  d ¡r|  d ¡‘qS )Ztag_namerœ   r�   r!   r!   r"   Ú
<listcomp>–  s     
 z6Handler._fetch_bilibili_video_meta.<locals>.<listcomp>Zviewrô   õ   Bç«™Útitlezhttps://www.bilibili.com/video/r   Zliker   u   å­¦ä¹ è§†é¢‘ra   ÚdurationZdescuF   Bç«™å…¬å¼€æŽ¥å�£ï¼šæ ‡é¢˜ã€�ä½œè€…ã€�æ’­æ”¾ã€�ç‚¹èµžã€�ç²‰ä¸�ã€�æ ‡ç­¾)Úplatformr”  r…  ÚplaysZ	playCountZlikesZ	likeCountÚfansZfollowerCountZplayFanRatioÚtagsÚauthorr•  ÚdescriptionÚanalysisBasis)r1   r¹   r~  r�   ÚparseZ	urlencoder€  rP  r�  r2   r3   r<   r[   r¼   )r<  r…  r  Z
bvid_matchZ	aid_matchZapir   Úinfor�  r‘  r˜  Zrelr™  Ztag_datar—  Zratior!   r!   r"   Ú_fetch_bilibili_video_metax  sb    
ÿ
ÿ

4 ñz"Handler._fetch_bilibili_video_metac              
   C   s¦   t j dd¡ ¡ }|r|S t j tdd¡t j t j d¡dd¡fD ]^}zDt j |¡rˆt	|ddd��}| 
¡  ¡ }W 5 Q R X |rˆ|W   S W qB tk
rž   Y qBX qBdS )	NZOPENAI_API_KEYr$   z.openaizapi_key.txtr	   r%   r&   r'   )r*   Úenvironr2   rµ   r+   rQ   rR   Ú
expanduserr,   r.   r   r3   )r<  r¬   r+   r5   r!   r!   r"   Ú_openai_api_key­  s    þzHandler._openai_api_keyr$   é-   c              
   C   s‚  g }t |tƒr|ng D ]z}t |tƒs&qt| d¡p4dƒ}| d¡sDqt|ƒdkrRq| t| d¡pddƒt| d¡ptdƒ|dœ¡ t|ƒd	kr q’q|sšd S |  ¡ }|s¶d
dt|ƒdœS d|d d… › �}d|dœg}	|D ]}|	 d|d dœ¡ qØt	j
tj dd¡d|	dœgddœd
d� d¡}
tjjd|
d|› �ddœdd �}z6tjj||d!��}t	 | ¡  dd"¡¡}W 5 Q R X W n> tk
�r´ } zd
d#|› �t|ƒdœ W Y ¢S d }~X Y nX t| d$¡�pÆdƒ ¡ }|�srg }t | d%¡tƒ�rö| d%g ¡ng D ]h}t |tƒ�r(t | d&¡tƒ�r(| d&g ¡ng D ]2}t |tƒ�r,| d'¡�r,| t| d'¡ƒ¡ �q,�qúd( |¡ ¡ }d)t|ƒ|d*œS )+NÚdataUrlr$   zdata:image/i ªD ra   ZimagerÜ   )ra   rÜ   r¤  r   Ful   ç¼ºå°‘è§†è§‰æ¨¡åž‹ API Keyï¼šè¯·é…�ç½®çŽ¯å¢ƒå�˜é‡� OPENAI_API_KEYï¼Œæˆ–æŠŠ Key å†™å…¥ .openai/api_key.txtã€‚)rg   rl   Ú
imageCountue  ä½ æ˜¯çŸ­è§†é¢‘çˆ†æ¬¾æ‹†è§£åŠ©æ‰‹ã€‚è¯·å�ªæ ¹æ�®ç”¨æˆ·ä¸Šä¼ çš„æˆªå›¾/å›¾ç‰‡å’Œè¾“å…¥æ–‡æœ¬æ��å�–å�¯è§�è¯�æ�®ï¼Œä¸�è¦�ç¼–é€ çœ‹ä¸�åˆ°çš„ç”»é�¢ã€�å­—å¹•ã€�è¯„è®ºæˆ–æ•°æ�®ã€‚è¾“å‡ºä¸­æ–‡ï¼Œç»“æž„ä¸ºï¼š1. ç”»é�¢äº‹å®žï¼›2. å�¯è§�æ–‡å­—/OCRï¼›3. è§†é¢‘å�¯èƒ½ç±»åž‹ï¼›4. å�¯ç”¨äºŽæ‹†è§£çš„å†…å®¹ç»“æž„çº¿ç´¢ï¼›5. ä»�ç¼ºå°‘çš„ä¿¡æ�¯ã€‚ç”¨æˆ·è¾“å…¥æ–‡æœ¬å¦‚ä¸‹ï¼š
i°  Z
input_text)rÜ   r  Zinput_image)rÜ   Z	image_urlZOPENAI_VISION_MODELzgpt-4o-miniÚuser)ZrolerO   i„  )ZmodelÚinputZmax_output_tokensrn   r&   z#https://api.openai.com/v1/responsesrL  rM  rN  rs   rt   rw   ry   u   è§†è§‰è¯†åˆ«å¤±è´¥ï¼šZoutput_textÚoutputrO   r  r.  T)rg   r¥  Úanalysis)r<   rÑ   r=   r1   r2   rB   r>   rV   r¢  r/   r}   r*   r   r€   r�   r‚   rƒ   r…   r†   r   r‡   r3   rµ   rQ   )r<  ÚimagesZraw_textrx   Zvalidrž   Zdata_urlr¬   ÚpromptrO   rS  r‰   rŠ   r‹   rŒ   r  ÚpartsÚoutÚpartr!   r!   r"   Ú_analyze_viral_images¿  sx    

ýýÿ
ýüüþù	$,&2zHandler._analyze_viral_imagesc              
   C   s  z6|   ¡ }t|tƒr0t| d¡p,| d¡p,dƒnd}W nB tk
rx } z$| jdd|› �dœdd� W Y ¢d S d }~X Y nX |  |¡pŠ| ¡ }|  	|p–|¡}|  
|¡}t|p¬i ƒ}g }t|tƒrÐt| d	¡pÌdƒnd}	t|tƒrè| d
¡ng }
|  |
|	pø|¡}|�rš| d¡�r„| d¡�r„| d¡|d< t| d¡�p8dƒd | d¡  ¡ |d< t| d¡�pbdƒ d¡d  d¡|d< d|d< n| | d¡�p–d¡ |dk�rtz˜||  |¡–}|�r:| d¡�r:| d¡�r:| d¡|d< t| d¡�pðdƒd | d¡  ¡ |d< t| d¡�pdƒ d¡d  d¡|d< d|d< W n4 tk
�rp } z| d|› �¡ W 5 d }~X Y nX n&|dk�r�| |› d�¡ n
| d¡ |  ¡ }dd„ | ¡ D ƒ}|�rÄ| d¡ |�sÖ||g dœ}t|ƒ|d < t| d¡ƒ|d< |  d|||d!œ¡ d S )"Nr…  r  r$   Frp  rk   rW  rm  ZsupplementTextrª  rg   r©  ZimageAnalysisr›  u   

å›¾ç‰‡è¯†åˆ«ç»“æžœï¼š
rœ  u   ï¼›u   ï¼›å›¾ç‰‡è§†è§‰è¯†åˆ«TZmediaReadablerl   u*   å›¾ç‰‡å·²æ”¶åˆ°ï¼Œä½†è§†è§‰è¯†åˆ«å¤±è´¥ã€‚r“  u   Bç«™è¯¦æƒ…æŽ¥å�£è¯»å�–å¤±è´¥ï¼š)õ   æŠ–éŸ³õ	   å°�çº¢ä¹¦uÄ   è§†é¢‘è¯¦æƒ…ã€�ç”»é�¢ã€�éŸ³è½¨é€šå¸¸éœ€è¦�ç™»å½•æ€�å’Œå¹³å�°å‰�ç«¯æŽˆæ�ƒï¼›å½“å‰�æœ¬åœ°æœ�åŠ¡æ‹¿ä¸�åˆ°ä½ çš„å¹³å�°ç™»å½• Cookieï¼Œæ‰€ä»¥å�ªèƒ½ä½¿ç”¨åˆ†äº«æ–‡æœ¬å’Œæ¦œå�•å·²æŠ“åˆ°çš„å…¬å¼€å­—æ®µã€‚u3   æœªè¯†åˆ«å¹³å�°ï¼Œæ— æ³•è°ƒç”¨å¹³å�°å…¬å¼€æŽ¥å�£ã€‚c                 S   s   g | ]\}}|s|‘qS r!   r!   ©rC   ra   rg   r!   r!   r"   r’  &  s      z0Handler._analyze_viral_video.<locals>.<listcomp>uo   æœ¬æœºç¼ºå°‘ yt-dlp / ffmpeg / Whisper ä¸­çš„éƒ¨åˆ†ç»„ä»¶ï¼Œæ— æ³•ä¸‹è½½è§†é¢‘ã€�æ��å�–éŸ³é¢‘å¹¶è½¬é€�å­—ç¨¿ã€‚)r–  r…  r™  ZmatchedHotVideo)rg   rˆ  Ú
toolStatusÚlimitations)rr  r<   r=   r1   r2   r3   ro  r‚  rµ   Ú_detect_video_platformrŠ  r¯  rV   rŸ  Ú_tool_statusr¾   rÓ   )r<  rˆ   ÚrawrŒ   r…  r–  Zmatchedrˆ  r´  Zsupplement_textrª  ZvisionÚtoolsÚmissingr!   r!   r"   ra     sV    .
 *(

*($


zHandler._analyze_viral_videorD  c                 C   sF   |   |¡ |  ¡  |  dd¡ |  ¡  | j tj|dd� d¡¡ d S )Nrq   rr   Frn   r&   )	rE  rC  rB  rF  rh  r3  r/   r}   r€   )r<  rˆ   rn  r!   r!   r"   ro  /  s
    
zHandler._json_responsec                 C   s   t ƒ S ©N)rÆ   rG  r!   r!   r"   Ú_daily_english_listening_stats6  s    z&Handler._daily_english_listening_statsc                 C   s:   t  d|pd¡sd S |d d… }tj td|d|› d�¡S )Nr›   r$   r�   r   u   ä»Šæ—¥è¯»ä¹¦æ”¶èŽ·_z.md)r¹   rº   r*   r+   rQ   rR   )r<  ru  Zyearr!   r!   r"   rs  9  s    z#Handler._reading_note_file_for_datec                    sV  g ‰d‰ d‰‡ ‡fdd„}‡‡fdd„}|  ¡ D �]}| ¡ }|sP|ƒ  |ƒ  q0t |¡}t dd|¡}t dd	|¡}| d
¡rÖ|ƒ  |ƒ  |dd … }d|krÂ| dd¡\}}	d|› d|	› d�}ˆ d|› d�¡ q0| d¡�r
|ƒ  |ƒ  ˆ d|dd … › d�¡ q0| d¡�r>|ƒ  |ƒ  ˆ d|dd … › d�¡ q0| d¡�rr|ƒ  |ƒ  ˆ d|dd … › d�¡ q0t 	d|¡�r¼|ƒ  ˆ �sšˆ d ¡ d!‰ t dd"|¡}
ˆ d#|
› d$�¡ q0| d%¡�rþ|ƒ  ˆ�sâˆ d&¡ d!‰ˆ d#|dd … › d$�¡ q0|d'k�r |ƒ  |ƒ  ˆ d(¡ q0|ƒ  |ƒ  ˆ d)|› d*�¡ q0|ƒ  |ƒ  d+ 
ˆ¡S ),NFc                      s   ˆ rˆ  d¡ d‰ d S )Nz</ol>F©rV   r!   )Úin_olr­  r!   r"   Úclose_olD  s    
z+Handler._markdown_to_html.<locals>.close_olc                      s   ˆ rˆ  d¡ d‰ d S )Nz</ul>Fr¼  r!   )Úin_ulr­  r!   r"   Úclose_ulJ  s    
z+Handler._markdown_to_html.<locals>.close_ulz\*\*(.+?)\*\*z<strong>\1</strong>z	\*(.+?)\*z<em>\1</em>ú# rô   u   ï½œä½œè€…ï¼šr¦   z<span class="book-title-main">u0   </span><span class="book-title-author">ä½œè€…ï¼šz</span>z<h1>z</h1>ú## z<h2>r9   z</h2>z### z<h3>r�   z</h3>z&gt; z<blockquote>rÐ   z</blockquote>z^\d+\. z<ol>Tr$   z<li>z</li>z- z<ul>ú---z<hr>z<p>z</p>r.  )r  rµ   ÚhtmlÚescaper¹   r„  rB   ry  rV   r�  rQ   )r<  r  r¾  rÀ  r·  ÚlineZsafeÚheadingÚ
book_titlerš  Z	item_textr!   )r½  r¿  r­  r"   Ú_markdown_to_html?  sr    




zHandler._markdown_to_htmlc              	   C   sö   t t| jƒjƒ}| d¡pdgd }|  |¡}|r>tj |¡sz|  d¡ |  	¡  |  
dd¡ |  ¡  | j d d¡¡ d S t|d	dd
��}|  | ¡ ¡}W 5 Q R X dt |¡› d|› d�}|  d¡ |  	¡  |  
dd¡ |  ¡  | j | d¡¡ d S )Nr)   r$   r   r[  rq   útext/html; charset=utf-8u   <h1>è¯»ä¹¦ç¬”è®°ä¸�å­˜åœ¨</h1>r&   r%   r'   u¡   <!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ä»Šæ—¥è¯»ä¹¦æ”¶èŽ· u  </title>
<style>
body{margin:0;background:#fdf2f4;color:#4a3b3e;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;line-height:1.75}
main{max-width:860px;margin:0 auto;padding:42px 22px 72px}
h1{font-size:30px;line-height:1.25;margin:0 0 18px;color:#b55d76}
.book-title-main{display:inline;font-weight:800}
.book-title-author{display:inline-block;margin-left:14px;font-size:15px;font-weight:600;color:#9a8288;vertical-align:middle}
h2{font-size:20px;margin:34px 0 12px;color:#b55d76}
h3{font-size:16px;margin:22px 0 8px;color:#7a5961}
p{margin:10px 0}
blockquote{margin:12px 0;padding:12px 16px;border-left:4px solid #d97a94;background:#fff;border-radius:8px;box-shadow:0 2px 12px rgba(217,122,148,.10)}
ol,ul{padding-left:24px}
li{margin:8px 0}
hr{border:0;border-top:1px solid #f3d6de;margin:28px 0 14px}
a{color:#b55d76}
.back{display:inline-block;margin-bottom:20px;color:#9a8288;text-decoration:none;font-size:14px}
</style>
</head>
<body>
<main>
<a class="back" href="/life-dashboard.html">â†� è¿”å›žå·¥ä½œå�°</a>
ú
</main>
</body>
</html>rD  )r   r   r+   Úqueryr2   rs  r*   r,   rE  rC  rB  rF  rh  r3  r€   r.   rÉ  r   rÄ  rÅ  )r<  Úqsru  rv  r5   rS  Úpager!   r!   r"   Ú_serve_reading_note_view†  s,    

ûæ
z Handler._serve_reading_note_viewc                 C   s4   t |pdƒ}|r|dkrdS d|ks,d|kr0dS |S )Nr$   )Ú.z..r@   r   ©r1   )r<  r  Úcleanr!   r!   r"   Ú_safe_book_slug¸  s    zHandler._safe_book_slugc                 C   sN   |   |¡}|sd S tj tj t|d¡¡}tj t¡}| |tj ¡sJd S |S )NrM   )rÓ  r*   r+   rx  rQ   rT   rB   rz  )r<  Úslugr+   r^   r!   r!   r"   Ú_book_archive_pathÀ  s    
zHandler._book_archive_pathc           
   	   C   sv  t j t¡si i dœS z(ttddd��}t |¡}W 5 Q R X W n tk
r\   i i dœ Y S X i }i }t|t	ƒr|| 
dg ¡ng D ]ê}t| 
d¡t	ƒrž| 
d¡n|}t| 
d¡pº| 
d¡pºdƒ}t| 
d	¡pÖ| 
d	¡pÖdƒ}|r€|säq€||t| 
d
¡�p| 
d
¡�p| 
d¡�p| 
d¡�pdƒt| 
d¡�p:| 
d¡�p:dƒt| 
d¡�pR| 
d¡ƒdœ}	|	||< |	||< q€||dœS )N)ÚbyIdÚbyTitler%   r&   r'   rX  ÚbookÚbookIdr$   r”  ÚreadUpdateTimeZ
updateTimer   ÚfinishReadingÚisTop)rÙ  r”  rÚ  rÛ  rÜ  )r*   r+   r,   ÚWEREAD_SHELF_CACHE_PATHr.   r/   r0   r3   r<   r=   r2   r1   r[   rÓ   )
r<  r5   r   Úby_idZby_titlerž   rØ  Zbook_idr”  Ú
shelf_itemr!   r!   r"   Ú_load_weread_shelf_booksÊ  s0    
6û
z Handler._load_weread_shelf_booksc           
      C   s  |   |¡}|rtj |¡sd S tj tj |¡d¡}i }z4tj |¡rjt|ddd��}t |¡}W 5 Q R X W n t	k
r„   i }Y nX | 
d¡p’|}t| 
d¡tƒr®| 
d¡ng }d}|rØt|d  
d	¡pÌdƒd d
… }|�sHzRt|ddd��:}|D ].}	|	 ¡  d¡rô|  |	 ¡ ¡d d
… } �q$qôW 5 Q R X W n t	k
�rF   Y nX |t| 
d¡�pZdƒ|| 
d¡�pld| 
d¡�pzd| 
d¡t| 
d¡�pž| 
d¡�pždƒ| 
d¡d k	�rº| 
d¡nt|ƒ| 
d¡�pÎd| 
d¡�pÜd|tj |t¡dtj |¡› �t dt tj |¡¡¡dœS )NrN   r%   r&   r'   r”  Úquotesr$   r   r  r
  ú>rÙ  rš  rn  ÚprogressÚreadTsZread_tsÚ
quoteCountÚmaxQuoteCountrd   ZevidenceLimitu'   åŸºäºŽå¾®ä¿¡è¯»ä¹¦å�¯è§�æ•°æ�®æ•´ç�†ã€‚z/reading-book-view?book=rñ   )rÔ  rÙ  r”  rš  rn  rã  rä  rå  ræ  ÚsummaryÚ	quoteTextr+   ÚviewUrlÚ
modifiedAt)rÕ  r*   r+   r,   rQ   r{  r.   r/   r0   r3   r2   r<   rÑ   r1   rµ   rB   Ú_strip_markdownr[   r>   rY   rR   r�   r�  Zquoter   r   rç   r\   )
r<  rÔ  Úarchive_pathÚ	meta_pathr   r5   r”  rá  Zquote_previewrÆ  r!   r!   r"   Ú_book_archive_metaå  sP    

 òzHandler._book_archive_metac           	   	   C   s  t t| jƒjƒ}| d¡pdgd }|  |¡}|r>tj |¡sz|  d¡ |  	¡  |  
dd¡ |  ¡  | j d d¡¡ d S t|d	dd
��}|  | ¡ ¡}W 5 Q R X |  |¡}|rº| d¡n|}dt |¡› d|› d�}|  d¡ |  	¡  |  
dd¡ |  ¡  | j | d¡¡ d S )NrØ  r$   r   r[  rq   rÊ  u   <h1>ä¹¦ç±�æ¡£æ¡ˆä¸�å­˜åœ¨</h1>r&   r%   r'   r”  zŽ<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>uâ   è¯»ä¹¦æ¡£æ¡ˆ</title>
<style>
body{margin:0;background:#fdf2f4;color:#4a3b3e;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;line-height:1.75}
main{max-width:900px;margin:0 auto;padding:42px 22px 72px}
h1{font-size:30px;line-height:1.25;margin:0 0 18px;color:#b55d76}
.book-title-main{display:inline;font-weight:800}
.book-title-author{display:inline-block;margin-left:14px;font-size:15px;font-weight:600;color:#9a8288;vertical-align:middle}
h2{font-size:20px;margin:34px 0 12px;color:#b55d76}
h3{font-size:16px;margin:22px 0 8px;color:#7a5961}
p{margin:10px 0}
blockquote{margin:12px 0;padding:12px 16px;border-left:4px solid #d97a94;background:#fff;border-radius:8px;box-shadow:0 2px 12px rgba(217,122,148,.10)}
ol,ul{padding-left:24px}
li{margin:8px 0}
a{color:#b55d76}
.back{display:inline-block;margin-bottom:20px;color:#9a8288;text-decoration:none;font-size:14px}
</style>
</head>
<body>
<main>
<a class="back" href="/life-dashboard.html">â†� è¿”å›žå·¥ä½œå�°</a>
rË  rD  )r   r   r+   rÌ  r2   rÕ  r*   r,   rE  rC  rB  rF  rh  r3  r€   r.   rÉ  r   rî  rÄ  rÅ  )	r<  rÍ  rÔ  rì  r5   rS  Úmetar”  rÎ  r!   r!   r"   Ú _serve_reading_book_archive_view  s0    


ûç
z(Handler._serve_reading_book_archive_viewc              	   C   sH  g }|   ¡ }tj t¡�rt t¡D ]Þ}| d¡r4q$|  |¡}|sDq$|d  | d¡pXd¡pr|d  | d¡ppd¡}|szq$zt	| d¡pŠdƒ}W n t
k
r¨   d}Y nX |dkr´q$tt	| d	¡pÄdƒt	| d
¡pÔdƒƒ|d	< d|d< | d¡pòd|d< | |¡ q$|�r"t|dd„ d�}d|d< |jdd„ dd� |  d|dœ¡ d S )NrÐ  rÖ  rÙ  r$   r×  r”  rã  r   rä  rÚ  FÚisCurrentReadingZshelfBookIdc                 S   s   t |  d¡pdƒS )Nrä  r   ©r[   r2   r¨   r!   r!   r"   r©   [  rª   z6Handler._serve_reading_book_archives.<locals>.<lambda>)r¬   Tc                 S   s@   |   d¡rdndt|   d¡pdƒt|   d¡p.dƒ|   d¡p<dfS )Nrñ  r¦   r   rä  rã  rê  r$   ©r2   r[   r¨   r!   r!   r"   r©   ^  s
    ür«   )rg   Úarchives)rà  r*   r+   r,   rT   ÚlistdirrB   rî  r2   r[   r3   r»   rV   rÀ   ro  )r<  rô  Zshelfra   rï  rß  rã  Znewestr!   r!   r"   Ú_serve_reading_book_archivesC  s<    

0
*ù	z$Handler._serve_reading_book_archivesc              	   C   sœ   t t| jƒjƒ}| d¡pdgd }|  |¡}|r>tj |¡sV| jdddœdd� d S t	|d	d
d��}| 
¡ }W 5 Q R X |  d||  |¡|  |¡dœ¡ d S )NrØ  r$   r   Fu   ä¹¦ç±�æ¡£æ¡ˆä¸�å­˜åœ¨rk   r[  rm  r%   r&   r'   T)rg   rØ  rï  rÄ  )r   r   r+   rÌ  r2   rÕ  r*   r,   ro  r.   r   rî  rÉ  )r<  rÍ  rÔ  rì  r5   Úmarkdownr!   r!   r"   Ú_serve_reading_book_archiveh  s    
üz#Handler._serve_reading_book_archivec                 C   sJ   t  dd|¡}t  dd|¡}t  dd|¡}t  dd|¡}t  dd|¡ ¡ S )Nz^#+\s*r$   z^>\s*z	^\d+\.\s*z[*_`#]ú\s+ú ©r¹   r„  rµ   )r<  r  r!   r!   r"   rë  x  s
    zHandler._strip_markdownc              	      s   d}|D ]¼‰ zt ‡ fdd„t|ƒD ƒƒ}W n tk
rB   Y qY nX g }||d d … D ]P}| ¡ }| d¡rr qª|  |¡}|r’|dkr’| |¡ td |¡ƒdkrX qªqX|rd |¡d d	…   S q|D ]0}|  | ¡ ¡}|rÊ| d
¡sÊ|d d	…   S qÊdS )N)u   ## æ·±åº¦è§£è¯»u   ## æ ¸å¿ƒè§‚ç‚¹u   ## ä¸ªäººæ€�è€ƒõ   ## é‡‘å�¥æ‘˜å½•c                 3   s"   | ]\}}|  ¡ ˆ kr|V  qd S rº  ©rµ   ©rC   ÚirÆ  ©Zsectionr!   r"   rG   ƒ  s      z(Handler._note_summary.<locals>.<genexpr>r¦   rÂ  rÃ  rú  éx   éŒ   u   ä»Šæ—¥è¯»ä¹¦æ”¶èŽ·u   æš‚æ— æ‘˜è¦�)	rÒ   Ú	enumerateÚStopIterationrµ   rB   rë  rV   r>   rQ   )r<  ÚlinesZsectionsr  r¬  rÆ  ÚstrippedrÒ  r!   r   r"   Ú_note_summary  s.    



zHandler._note_summaryc              	      sd  d}d}|D �] ‰ zt ‡ fdd„t|ƒD ƒƒ}W n tk
rH   Y qY nX ||d d … D ]R}| ¡ }| d¡rt q®| d¡s€qZ|  |¡}|rZ| |¡sZ|d d…     S qZ||d d … D ]N}| ¡ }| d¡rØ q|  |¡}|r¾|d	kr¾| |¡s¾|d d…     S q¾q|D ]J}| ¡ }| d¡�s0�q|  |¡}|�r| |¡�s|d d…   S �qd
S )N)u   ## ä»Šæ—¥é‡‘å�¥rü  )u   é˜…è¯»æ‰“å�¡u   è¿žç»­æ‰“å�¡u	   å·²ä¿�å­˜c                 3   s"   | ]\}}|  ¡ ˆ kr|V  qd S rº  rý  rþ  r   r!   r"   rG   �  s      z&Handler._note_quote.<locals>.<genexpr>r¦   rÂ  râ  éÜ   rÃ  r$   )rÒ   r  r  rµ   rB   rë  )r<  r  Zquote_sectionsZstatus_prefixesr  rÆ  r  rÒ  r!   r   r"   Ú_note_quote˜  s>    







zHandler._note_quotec                    s  t j |¡}t d|¡}|r&| d¡nt dt t j 	|¡¡¡}t
|ddd��}| ¡ }W 5 Q R X | ¡ }t‡ fdd„|D ƒd	|› d
�ƒ}t d|¡}	|	s¦t d|¡}	|	s¶t d|¡}	|	rÄ|	 d¡nd}
|||
ˆ  |¡ˆ  |¡t j |t¡d|› �t dt t j 	|¡¡¡dœS )Nz(\d{4}-\d{2}-\d{2})r¦   r   r%   r&   r'   c                 3   s"   | ]}|  d ¡rˆ  |¡V  qdS )rÁ  N)rB   rë  )rC   rÆ  rG  r!   r"   rG   À  s     
 z%Handler._note_meta.<locals>.<genexpr>u   è¯»ä¹¦æ”¶èŽ·ï¼ˆu   ï¼‰u,   (?:ä»Šæ—¥ä¹¦ç±�|ä¹¦å��)ï¼š\s*ã€Š([^ã€‹]+)ã€‹u   â€”â€”\s*ã€Š([^ã€‹]+)ã€‹u   ã€Š([^ã€‹]+)ã€‹u   ç»¼å�ˆè¯»ä¹¦ç¬”è®°z/reading-note-view?date=rñ   )r)   r”  Ú	bookTitlerç  rè  r+   ré  rê  )r*   r+   Úbasenamer¹   r~  r€  r   r   rç   r\   r.   r   r  rÒ   r  r	  rY   rR   )r<  r+   ra   r�  ru  r5   r  r  rÇ  Zprimary_matchrÈ  r!   rG  r"   Ú
_note_meta¹  s,    ( øzHandler._note_metac                 C   sè   g }t j t¡rÂt  t¡D ]¦\}}}|D ]–}t d|¡s:q(t dt j |¡¡sPq(t j ||¡}z| 	|  
|¡¡ W q( tk
r¼ } z,| 	d|dt|ƒt j |t¡dddœ¡ W 5 d }~X Y q(X q(q|jdd„ dd	� |  d|d
œ¡ d S )Nu(   ä»Šæ—¥è¯»ä¹¦æ”¶èŽ·_\d{4}-\d{2}-\d{2}\.mdz\d{4}r$   u   è¯»å�–å¤±è´¥)r)   r”  r
  rç  r+   ré  rê  c                 S   s   |   d¡pd|   d¡pdfS )Nr)   r$   rê  rœ   r¨   r!   r!   r"   r©   è  rª   z.Handler._serve_reading_notes.<locals>.<lambda>Tr«   )rg   Únotes)r*   r+   r,   rS   rU   r¹   rº   r  rQ   rV   r  r3   r1   rY   rR   rÀ   ro  )r<  r  r^   r_   r]   ra   r+   rŒ   r!   r!   r"   Ú_serve_reading_notesÒ  s.    ù	zHandler._serve_reading_notesc              	   C   sœ   t t| jƒjƒ}| d¡pdgd }|  |¡}|r>tj |¡sV| jdddœdd� d S t	|d	d
d��}| 
¡ }W 5 Q R X |  d||  |¡|  |¡dœ¡ d S )Nr)   r$   r   Fu   è¯»ä¹¦ç¬”è®°ä¸�å­˜åœ¨rk   r[  rm  r%   r&   r'   T)rg   r)   rï  rÄ  )r   r   r+   rÌ  r2   rs  r*   r,   ro  r.   r   r  rÉ  )r<  rÍ  ru  rv  r5   r÷  r!   r!   r"   Ú_serve_reading_noteë  s    
üzHandler._serve_reading_notec              
   C   sò   ddddddg ddœ}t j t¡s0|  |¡ d S z~ttdd	d
��}t |¡}W 5 Q R X t|t	ƒrn|d|i–}n t|t
ƒr‚||–}n|ddi–}t| d¡ƒ |d< |  |¡ W n> tk
rì } z | j|dt|ƒdœ–dd� W 5 d }~X Y nX d S )NTr$   zdaily automationu;   å­¦ä¹ ç±»è§†é¢‘é›·è¾¾ï¼šAIæŠ€èƒ½ / å‰ªè¾‘æŠ€æœ¯ / AI+å‰ªè¾‘rÐ   r   )rg   r7   r®   ÚtrackÚminDailyVideosZtargetDailyVideosr8   rl   r%   r&   r'   r8   rl   z0learning-hot-videos.json format is not supportedrg   Frk   rZ  rm  )r*   r+   r,   r;   ro  r.   r/   r0   r<   rÑ   r=   rÓ   r2   r3   r1   ©r<  Zdefault_datar5   r   rŒ   r!   r!   r"   Ú_serve_hot_videosû  s0    ø




zHandler._serve_hot_videosc                 C   sø   ddddddddg ddd	œ}t j t¡s6|  |¡ d S z~ttd
dd��}t |¡}W 5 Q R X t|t	ƒrt|d|i–}n t|t
ƒrˆ||–}n|ddi–}t| d¡ƒ |d< |  |¡ W n> tk
rò } z | j|dt|ƒdœ–dd� W 5 d }~X Y nX d S )NTr$   z&daily automation via public web searchu   AIæ–°æ‰‹å�˜çŽ°å®žæ“�è·¯çº¿u'   ç¬¬1é˜¶æ®µï¼šAIåŸºç¡€ä½¿ç”¨ä¸Žæ��ç¤ºè¯�r   u^   ç”¨ ChatGPTã€�è±†åŒ…ã€�Kimi ç­‰å·¥å…·å®Œæˆ�æ¸…æ™°æ��é—®ã€�æ”¹å†™ã€�æ€»ç»“å’Œæ¨¡æ�¿åŒ–è¾“å‡ºã€‚r   )rg   r7   r®   r  ÚstageZ
stageIndexZgoalr  r8   r  rl   r%   r&   r'   r8   rl   z/ai-learning-videos.json format is not supportedrg   Frk   rZ  rm  )r*   r+   r,   ÚAI_LEARNING_VIDEOS_PATHro  r.   r/   r0   r<   rÑ   r=   rÓ   r2   r3   r1   r  r!   r!   r"   Ú_serve_ai_learning_videos  s6    õ



z!Handler._serve_ai_learning_videosc              
   C   s¶   t j t¡s$|  ddd ddœ¡ d S zRttddd��}t |¡}W 5 Q R X |  dd|t|t	ƒrj| 
dd¡nddœ¡ W n: tk
r° } z| jdt|ƒd	œd
d� W 5 d }~X Y nX d S )NTFr   )rg   r,   r   r7   r%   ú	utf-8-sigr'   rð   rk   rZ  rm  )r*   r+   r,   rÈ   ro  r.   r/   r0   r<   r=   r2   r3   r1   )r<  r5   r   rŒ   r!   r!   r"   Ú_serve_life_data6  s    üzHandler._serve_life_datac                 C   sˆ   t |tƒsdS t| d¡p„| d¡p„| d¡p„t| d¡p<dƒdkp„t| d¡pRdƒdkp„t| d¡phdƒdkp„t| d	¡p~dƒdkƒS )
NFrÛ   Ú	sleepTimerí   r•   r   ÚreadMinutesÚ	aiMinutesrÎ   )r<   r=   rÓ   r2   r¶   )r<  rÖ   r!   r!   r"   Ú_life_preset_has_valueF  s     

ÿþýüûùzHandler._life_preset_has_valuec                 C   s²  t |tƒrt |tƒsd S |  |¡r:|  |¡s:| |¡ d S |  |¡sHd S | d¡}|dkrœ| d¡s|| d¡r|| d¡|d< t| d¡p�| d¡ƒ|d< �n|dk�rvt| d¡p´dƒt| d¡pÄdƒkrð| d¡|d< | d¡rð| d¡|d< t| d¡�p| d¡ƒ|d< | d¡�r@| d	¡�r@| d	¡�s@| d	¡|d	< d
D ],}| |¡�rD| |¡�sD| |¡||< �qD�n8|dk�rXt| d¡�p�dƒt| d¡�p¢dƒk�rÒ| d¡|d< | d¡�rÒ| d¡|d< t| d¡�pè| d¡ƒ|d< | d¡�r"| d	¡�r"| d	¡�s"| d	¡|d	< d
D ],}| |¡�r&| |¡�s&| |¡||< �q&�nV|dk�r8t| d¡�prdƒt| d¡�p„dƒk�r´| d¡|d< | d¡�r´| d¡|d< t| d¡�pÊ| d¡ƒ|d< | d¡�r| d	¡�r| d	¡�s| d	¡|d	< d
D ],}| |¡�r| |¡�s| |¡||< �qnv|dk�r�tt| d¡�pTdƒt| d¡�pfdƒƒ|d< t| d¡�p†| d¡ƒ|d< nt| d¡�p¦| d¡ƒ|d< d S )NrÍ   r  r  rÛ   r   r  r   rí   rÏ   )rê   rë   r   r  r   rÎ   Zwaterr•   )r<   r=   r  r¿   r2   rÓ   r¶   r»   )r<  r  r®   Útask_idr¬   r!   r!   r"   Ú_merge_life_presetS  sb    


 
$
$
*$
*$
. zHandler._merge_life_presetc              
   C   s0  |  di ¡}t|tƒr | d¡ni }t|tƒs2d S | ¡ D �]î\}}t|tƒsPq:|  |g g dœ¡}|  dg ¡ |  dg ¡ |d }t|tƒs˜g }||d< dd„ |D ƒ}	| d¡p²g D ]Ä}
t|
tƒr´|
 d¡sÎq´ttƒ}z(tj 	t
|ƒd¡ ¡ d	krü| t¡ W n tk
�r   ttƒ}Y nX |
 d¡|k�r0q´|	 |
 d¡¡}|d k�rl| t|
ƒ¡ |d
 |	|
 d¡< q´|  ||
¡ q´t| d¡tƒ�r”|d ng }||d< dd„ |D ƒ}| d¡�p¼g D ]j}t|tƒ�sÒ�q¾| d¡�rðdt
| d¡ƒ ndt
| dd¡ƒ }||k�r¾| t|ƒ¡ | |¡ �q¾q:d S )NrÊ   r×   rË   rØ   c                 S   s,   i | ]$}t |tƒr| d ¡r| d ¡|“qS ©rÍ   r£   ©rC   Úpr!   r!   r"   r¤   –  s
     
 
  z2Handler._merge_life_daily_plan.<locals>.<dictcomp>rÍ   r   r’   r  c                 S   sP   h | ]H}t |tƒrt |tƒr8| d ¡r8dt| d ¡ƒ ndt| dd¡ƒ ’qS )rÍ   úid:úname:ra   r$   ©r<   r=   r2   r1   )rC   Úcr!   r!   r"   Ú	<setcomp>ª  s     
 z1Handler._merge_life_daily_plan.<locals>.<setcomp>r"  r#  ra   r$   )rÝ   r<   r=   r2   r¾   rÑ   rW   ÚALWAYS_DAILY_PRESET_IDSr   rú   r1   ZweekdayrZ   ÚSUNDAY_PRESET_IDr3   ÚDAILY_PRESET_IDSrV   r  )r<  ÚincomingrÅ   Zincoming_dailyZexisting_dailyrÂ   Zexisting_planZtarget_planZtarget_presetsrÞ  Zsource_taskZallowed_idsZtarget_taskZtarget_customsrb   Zcustomr¬   r!   r!   r"   Ú_merge_life_daily_plan‡  sR    



2
zHandler._merge_life_daily_planc                 C   sœ   t |tƒsd S t | d¡tƒr(| d¡ni }| ¡ D ]b}t |tƒsDq4t | d¡tƒr^| d¡ng }|D ].}t |tƒsvqf| d¡}|tkrft| |d< qfq4d S )NrÊ   rË   rÍ   ra   )r<   r=   r2   ÚvaluesrÑ   rÞ   )r<  r   rÔ   rÕ   rË   rÖ   r  r!   r!   r"   Ú_normalize_life_preset_names³  s    



z$Handler._normalize_life_preset_namesc                    sB   t ˆ tƒsdS ˆ  d¡r*dtˆ  d¡ƒ S d ‡ fdd„dD ƒ¡S )Nr$   rÍ   r"  ú|c                 3   s   | ]}t ˆ  |d ¡ƒV  qdS )r$   N)r1   r2   ©rC   Úk©Úentryr!   r"   rG   Ç  s     z(Handler._exercise_key.<locals>.<genexpr>)rÜ   r•  rÃ   r   ræ   r®   )r<   r=   r2   r1   rQ   )r<  r2  r!   r1  r"   Ú_exercise_keyÂ  s
    

zHandler._exercise_keyc                    s®  |  di ¡}|  di ¡}t|tƒr,| d¡ni }t|tƒsFi }||d< t|tƒr´| ¡ D ]Z\}}t|tƒrX|spqX|  |g ¡}t|tƒs’g }|||< |D ]}	|	r–|	|kr–| |	¡ q–qXt|tƒrÈ| d¡ni }
t|
tƒsÚd S |
 ¡ D ]Æ\}}t|tƒrâ|súqâ|  |g ¡}t|tƒ�sg }|||< t| |¡�p.g ƒ‰ ‡ ‡fdd„|D ƒ|d d …< ‡fdd„|D ƒ}|D ]B}ˆ |¡}	|	�rd|	ˆ k�rd|	|k�rd| t|ƒ¡ | 	|	¡ �qdqâd S )NÚ	exercisesZdeletedExerciseKeysc                    s   g | ]}ˆ  |¡ˆ kr|‘qS r!   ©r3  ©rC   rŒ   ©rq  r<  r!   r"   r’  æ  s      z1Handler._merge_life_exercises.<locals>.<listcomp>c                    s    h | ]}ˆ   |¡rˆ   |¡’qS r!   r5  r6  rG  r!   r"   r&  ç  s     
 z0Handler._merge_life_exercises.<locals>.<setcomp>)
rÝ   r<   r=   r2   r¾   rÑ   rV   rW   r3  rZ   )r<  r*  rÅ   Zincoming_exercisesZincoming_deletedZexisting_deletedrÂ   ÚkeysZtarget_keysr¬   Zexisting_exercisesÚentriesZtarget_entriesrb   r2  r!   r7  r"   Ú_merge_life_exercisesÉ  sF    




zHandler._merge_life_exercisesc              	   C   s‚   t |tƒsdS z6| d¡d k	r,t| d¡ƒnt| d¡p:dƒd }W n ttfk
r`   d}Y nX |dkrndS tdt |d ¡ƒS )Nr   rÃ   r•  r   r¦   )	r<   r=   r2   r¶   Ú	TypeErrorrû   r»   ÚmathZceil)r<  r2  rÃ   r!   r!   r"   Ú_exercise_minutesî  s    
6
zHandler._exercise_minutesc           
         s$  t |tƒsd S t | d¡tƒr(| d¡ni }t | d¡tƒrF| d¡ni }| ¡ D ]Ì\}}t |tƒsfqRt | d¡tƒr€| d¡ng }tdd„ |D ƒd ƒ}|d kr¢qRt | |¡tƒr¼| |¡ng }t‡ fdd„|D ƒƒ}	|	|d< |	dk�rd	|d
< d|	› d�|d< qRd|d
< | dd ¡ d|d< qRd S )Nr4  rÊ   rË   c                 s   s*   | ]"}t |tƒr| d ¡dkr|V  qdS )rÍ   r   Nr£   r   r!   r!   r"   rG     s     
  z7Handler._apply_life_exercise_presets.<locals>.<genexpr>c                 3   s   | ]}ˆ   |¡V  qd S rº  )r=  )rC   r2  rG  r!   r"   rG     s     ZexerciseMinutesr   TrÛ   u   è·³èˆž/è¿�åŠ¨ rì   rí   FrÏ   u   è·³èˆž/è¿�åŠ¨ 0 åˆ†é’Ÿ)r<   r=   r2   r¾   rÑ   rÒ   ÚsumÚpop)
r<  r   r4  rÔ   rÂ   rÕ   rË   rÖ   r9  rÄ   r!   rG  r"   Ú_apply_life_exercise_presetsù  s(    


z$Handler._apply_life_exercise_presetsc                 C   s<   |d dg i fkrdS t |tƒr&t|ƒS t |tƒr8t|ƒS dS )Nr$   r   r¦   )r<   r=   r>   rÑ   )r<  Úvaluer!   r!   r"   Ú_value_weight  s    

zHandler._value_weightc                    sj   t |tƒsg }t |tƒs|S ‡ fdd„|D ƒ}|D ]2}ˆ |ƒ}|r2||kr2| t |¡¡ | |¡ q2|S )Nc                    s   h | ]}ˆ |ƒrˆ |ƒ’qS r!   r!   r�   ©Úkey_funcr!   r"   r&    s      z-Handler._merge_unique_list.<locals>.<setcomp>)r<   rÑ   rV   ÚcopyÚdeepcopyrZ   )r<  Úincoming_listÚexisting_listrD  rb   rž   r¬   r!   rC  r"   Ú_merge_unique_list  s    

zHandler._merge_unique_listc           	         sf   |   ||ˆ ¡}‡ fdd„|pg D ƒ}t|ƒD ]4\}}ˆ |ƒ}||kr,| d¡s,t || ¡||< q,|S )Nc                    s2   i | ]*}t |tƒr| d ¡rˆ |ƒrˆ |ƒ|“qS )Ú	duplicater£   r�   rC  r!   r"   r¤   (  s   
 
 þ z4Handler._merge_learning_sessions.<locals>.<dictcomp>rJ  )rI  r  r2   rE  rF  )	r<  rG  rH  rD  ÚmergedZcorrectionsÚindexrž   r¬   r!   rC  r"   Ú_merge_learning_sessions&  s    
þz Handler._merge_learning_sessionsc                    sZ  dd„ }i ‰ g }||ƒ||ƒ D �]$}t | dd¡ƒ ¡ }|s@q ˆ  |¡}|d krf|ˆ |< | |¡ q t| d¡tƒr€| d¡ng }t| d¡tƒrž| d¡ng }	t|	ƒt|ƒk�rt |¡}
| 	¡ D ]2\}}||
ksê|
 |¡d dg fkrÆt |¡|
|< qÆ|
ˆ |< q | 	¡ D ]8\}}||k�s4| |¡d dg fk�rt |¡||< �qq ‡ fdd„|D ƒS )Nc                 S   s   dd„ | pg D ƒS )Nc                 S   sH   g | ]@}t |tƒr| d ¡r| d¡rdt| dd¡ƒkrt |¡‘qS )r”  r®   z??r$   )r<   r=   r2   r1   rE  rF  r�   r!   r!   r"   r’  5  s   


ûzIHandler._merge_true_reading_bank.<locals>.valid_items.<locals>.<listcomp>r!   )r¾   r!   r!   r"   Úvalid_items4  s    þz5Handler._merge_true_reading_bank.<locals>.valid_itemsr”  r$   Z
pageImagesc                    s   g | ]}|ˆ krˆ | ‘qS r!   r!   )rC   r”  ©Zmerged_by_titler!   r"   r’  U  s      z4Handler._merge_true_reading_bank.<locals>.<listcomp>)
r1   r2   rµ   rV   r<   rÑ   r>   rE  rF  r¾   )r<  rG  rH  rN  Úorderrž   r”  r‰  Zcurrent_imagesZitem_imagesÚbaser¬   rA  r!   rO  r"   Ú_merge_true_reading_bank3  s0    




 z Handler._merge_true_reading_bankNc                 C   sl   t |tƒsi }t |tƒs|S | ¡ D ]B\}}| |¡}|  |¡dkrTt |¡||< q$|r$|||ƒ||< q$|S )Nr   )r<   r=   r¾   r2   rB  rE  rF  )r<  Úincoming_mapÚexisting_mapZmergerr¬   Úexisting_valueÚincoming_valuer!   r!   r"   Ú_merge_map_non_destructiveW  s    


z"Handler._merge_map_non_destructivec                 C   sö   t |tƒr|d d … ng }t |tƒs(|S t|ƒD ]À\}}|s>q0|t|ƒksR|| sz|t|ƒkrj| d ¡ qRt |¡||< q0|| }t |tƒr0t |tƒr0| d¡r¼| d¡s¼| 	t |¡¡ q0t
| d¡pÊdƒt
| d¡pÚdƒkr0| 	t |¡¡ q0|S )NÚdoneÚ	checkedAtr   )r<   rÑ   r  r>   rV   rE  rF  r=   r2   r¿   r[   )r<  Zincoming_itemsZexisting_itemsr  ÚidxZexisting_itemr‰  r!   r!   r"   Ú_merge_indexed_recordsd  s$    
$zHandler._merge_indexed_recordsc           	      C   s   t |tƒrt |¡ng }t |tƒs&|S t|ƒD ]ì\}}t |tƒr.|sFq.|t|ƒkr^| g ¡ qFt || tƒstg ||< dd„ || D ƒ}|D ]Ž}t |tƒsšqŠd t	| 
dd¡ƒd t | 
d¡tƒrÌ| 
dg ¡ng ¡t	| 
dd¡ƒt	| 
d	d¡ƒg¡}||krŠ||  t |¡¡ | |¡ qŠq.|S )
Nc                 S   sn   h | ]f}t |tƒrd  t| dd¡ƒd t | d¡tƒrD| dg ¡ng ¡t| dd¡ƒt| dd¡ƒg¡’qS )r.  rY  r$   ú,ÚanswersÚcorrectÚtotal)r<   r=   rQ   r1   r2   rÑ   )rC   r,  r!   r!   r"   r&  ƒ  s   
ù$üz1Handler._merge_attempt_records.<locals>.<setcomp>r.  rY  r$   r\  r]  r^  r_  )r<   rÑ   rE  rF  r  r>   rV   r=   rQ   r1   r2   rZ   )	r<  Zincoming_attemptsZexisting_attemptsr  Z
task_indexZattemptsrb   Zattemptr¬   r!   r!   r"   Ú_merge_attempt_recordsx  s4    
ù

$üzHandler._merge_attempt_recordsÚgenericc           	      C   sì  t |tƒs|S t |tƒr|s&t |¡S t |¡}| ¡ D �]\}}| |¡}|dkrjt|ƒpbt|ƒ||< q8|dkr’tt|p|dƒt|p†dƒƒ||< q8|dkr¬|  	||¡||< q8|dkrÆ|  
||¡||< q8|  |¡dkrät |¡||< q8t |tƒ�rt |tƒ�rt|ƒt|ƒk�rt |¡||< q8t |tƒr8t |tƒr8t|ƒt|ƒkr8t |¡||< q8|dk�rèt | d¡tƒ�rèdd	„ |d D ƒ}|�rètd
d„ |D ƒƒ|d< tdd„ |D ƒƒ|d< dd	„ |D ƒ|d< t|ƒdk�oâtdd„ |D ƒƒ|d< |S )N)rX  ZpassedrY  r   )ÚtaskResultsZfirstTaskResultsZtaskAttemptsÚreadingrb  c                 S   s   g | ]}t |tƒr|‘qS r!   )r<   r=   ©rC   r%   r!   r!   r"   r’  ²  s     
 z1Handler._merge_english_record.<locals>.<listcomp>c                 s   s    | ]}t | d ¡pdƒV  qdS )r^  r   Nrò  rd  r!   r!   r"   rG   ´  s     z0Handler._merge_english_record.<locals>.<genexpr>r^  c                 s   s    | ]}t | d ¡pdƒV  qdS )r_  r   Nrò  rd  r!   r!   r"   rG   µ  s     r_  c                 S   s.   g | ]&}|  d ¡pg D ]}t|tƒr|‘qqS )Úwrongs)r2   r<   r=   )rC   r%   ró   r!   r!   r"   r’  ¶  s
       
 re  rô   c                 s   s   | ]}|  d ¡V  qdS )rX  Nrœ   rd  r!   r!   r"   rG   ·  s     rX  )r<   r=   rE  rF  r¾   r2   rÓ   r»   r[   r[  r`  rB  rÑ   r>   r>  Úall)	r<  Zincoming_recordZexisting_recordZrecord_typerK  r¬   rU  rV  Ztask_resultsr!   r!   r"   Ú_merge_english_record›  s:    



 *$$zHandler._merge_english_recordc                 C   s¦   t |tƒsdS t| d¡ƒp6t| d¡ƒp6t| d¡ƒ}|r@dS g }t | d¡tƒrn| dd„ | d¡D ƒ¡ t | d¡tƒr˜| d	d„ | d¡D ƒ¡ d
d |¡kS )NFrY  rb  ÚtaskAnswersTÚsourcesc                 s   s   | ]}|rt |ƒV  qd S rº  rÑ  ©rC   Úxr!   r!   r"   rG   Â  s      z6Handler._is_legacy_fake_bec_reading.<locals>.<genexpr>c                 s   s(   | ] }t |tƒrt| d d¡ƒV  qdS )r®   r$   N)r<   r=   r1   r2   rj  r!   r!   r"   rG   Ä  s     
 u   çœŸé¢˜é¢˜åž‹rú  )r<   r=   rÓ   r2   rÑ   ÚextendrQ   )r<  rþ   Zhas_current_answersri  r!   r!   r"   Ú_is_legacy_fake_bec_readingº  s    
*z#Handler._is_legacy_fake_bec_readingc                 C   sÄ   t |tƒsd S | d¡rd S | d¡}t |tƒs4d S | di ¡}t| ¡ ƒD ]r\}}t|ƒdk rbqL|  |¡snqL|› d�}||krŽt 	|¡||< dg g g ddg ddd	œ	||< | d
i ¡}d||< qLd S )NÚtrueReadingBankrc  ZlegacyReadingPracticez
2026-07-30z	-fake-becFr   z5fake practice removed from current strict BEC reading)	rX  rh  rb  r]  r^  r_  re  rY  ZsourceStatusÚ	checkedIn)
r<   r=   r2   rÝ   rÑ   r¾   r1   rm  rE  rF  )r<  r   rc  ZlegacyrÂ   rþ   Z
legacy_keyrÛ   r!   r!   r"   Ú_strip_legacy_fake_bec_readingÇ  s8    





÷
z&Handler._strip_legacy_fake_bec_readingc                 C   s@  |  di ¡}t|tƒr | d¡ni }t|tƒs2d S |  |¡ |  |¡ |  |  dg ¡| d¡dd„ ¡}||d< tƒ }t|tƒr‚|ng D � ]þ}t|tƒs˜q†t| d¡p¦dƒ}t| d¡p¸dƒ}	t	 
d|	t	j¡}
| d	¡sÚ|
ròt| d	¡pî|
 d
¡ƒnd}| d¡r†|dkr†| d¡�rq†| dd¡› d|› �}||k�rpt| d¡�pFdƒdkr†t|d ƒ|d< d|d< d|d< q†| |¡ |  d	|¡ q†|  | d¡| d¡¡|d< |  | d¡| d¡dd„ ¡|d< | d¡�pÔi }t|tƒ�rª|  di ¡}t|tƒ�si }||d< | ¡ D ]š\}}t|tƒ�s&�q| |¡}t|tƒ�sNt |¡||< �qt| d¡�pj| d¡�pjdƒ}t| d¡�pŠ| d¡�pŠdƒ}||k�rt |¡||< �qdD �]Š}| |¡�pÂi }t|tƒ�sÔ�q®|  |i ¡}t|tƒ�søi }|||< | ¡ D �]4\}}| |¡}|dk�r6t|ƒ�p.t|ƒ||< nþ|dk�ræt|tƒ�rR|�sbt |¡||< n‚t|tƒ�r4dd„ |D ƒ}|D ]b}t|tƒ�r€| d¡�s �q€| d¡|k�rÂ| t |¡¡ n| d¡�r€d|| d¡ d< �q€nN|d k�r|  ||d ¡||< n0|d!k�r"|  ||d!¡||< n|  |||¡||< �q �q®d S )"Nrà   rá   c              	   S   sX   t | tƒrT|  d¡r"t|  d¡ƒqV|  d¡› d|  d¡› d|  d¡› d|  d¡› �S dS )NrÍ   r)   r.  rä   r¬   ræ   r$   r$  )Úsr!   r!   r"   r©   ð  rª   z-Handler._merge_life_english.<locals>.<lambda>r¬   r$   rå   u   è§‚çœ‹\s*ç¬¬\s*(\d+)\s*Pr®  r¦   r   zbilibili-friends-bv1phynyeebx-rJ  r)   r.  rÄ   ÚduplicateOriginalMinutesTrn  ZtrueWritingBankc                 S   sF   t | tƒrB|  d¡rB|  d¡rBt|  dd¡ƒd t|  dd¡ƒ S dS )Nr®   r  r$   r.  r$  r¨   r!   r!   r"   r©     rª   ZvideoCollectionsr7   ZpagesFetchedAt)ro  Zcardsrc  ÚwritingÚtasksZspeakingro  rt  c                 S   s,   i | ]$}t |tƒr| d ¡r| d ¡|“qS r  r£   )rC   rÖ   r!   r!   r"   r¤   1  s
     
 
  z/Handler._merge_life_english.<locals>.<dictcomp>rÍ   rÛ   rc  rs  )rÝ   r<   r=   r2   rp  rM  rW   rÑ   r1   r¹   r~  r  r[   r€  rB   rZ   rR  rI  r¾   rE  rF  r¶   rÓ   rV   rg  )r<  r*  rÅ   Zincoming_englishZexisting_englishZincoming_sessionsZvideo_partsÚsessionZsession_keyrå   r�  r®  Z
dedupe_keyZexisting_video_collectionsZincoming_video_collectionsr¬   rU  rV  Zincoming_tsZexisting_tsÚfieldrT  rS  rÂ   rÞ  rÖ   r!   r!   r"   Ú_merge_life_englishæ  s®    



ý
*

þý
  






zHandler._merge_life_englishc           #      C   s’  t |tƒsd S |  | 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 | d¡tƒrè| d¡ni }| di ¡}t |tƒ�r2t |tƒ�r2|  | d¡| d¡dd„ ¡|d< t | d¡tƒ�rN| d¡ni }| di ¡}t |tƒ�ršt |tƒ�rštt| d¡�pˆdƒt| d¡�pšdƒƒ|d< |  | d¡| d¡dd„ ¡|d< dd„ | d¡�pÚg D ƒ|d< |  | d¡| d¡dd„ ¡|d< |  | d¡| d¡dd„ ¡|d< t | d¡tƒ�rD| d¡ni }| di ¡}t |tƒ�rœ| ¡ D ]2\}	}
tt| |	¡�p‚dƒt|
�pŽdƒƒ||	< �qhdD �]ú}t | |¡tƒ�rÂ| |¡ni }| |i ¡}t |tƒ�r | ¡ D �]°\}	}
|	|k�rt	 
|
¡||	< �qæ|dk�rœt | |	¡tƒ�rœt |
tƒ�rœ||	 }t| d¡�pX| d¡�pXdƒ}t|
 d¡�px|
 d¡�pxdƒ}|�r–||k�r–t	 
|
¡||	< nú|dk�ræt | |	¡tƒ�ræt |
tƒ�ræ||	 }t| d ¡�pè| d!¡�pèdƒ}t|
 d ¡�p|
 d!¡�pdƒ}||k�r&t	 
|
¡||	< np||k�ræ|
 d"¡�rd| d"¡�sd| d#¡�sdt	 
|
¡||	< n2| d"¡�ræ| d$¡�sæ|
 d$¡�ræ|
 d$¡|d$< �qæ�q t | d%¡tƒ�rº| d%¡ni }| d%i ¡}t |tƒ�rš| ¡ D �]¸\}}t |tƒ�sø�qÞ| |¡}t |tƒ�s t	 
|¡||< �qÞ|  | d&¡| d&¡d'd„ ¡|d&< t | d(¡tƒ�r^| d(¡ng }t | d(¡tƒ�r~| d(¡ng }tt d)d„ || D ƒ¡ƒ|d(< t| d¡�p²dƒ}t| d¡�pÆdƒ}||k�rö| d*¡�pè| d*¡|d*< ||d< t | d+¡tƒ�r| d+¡ng }t | d+¡tƒ�r2| d+¡ng }t|ƒt|ƒk�rVt	 
|¡|d+< d,D ]:}| |¡d-k�rZ| |¡d-k�rZt	 
| |¡¡||< �qZ�qÞt | d.¡tƒ�r¶| d.¡ni }| d.i ¡}t |tƒ�rŽt |tƒ�rŽd/|k�r d/|k�r | d/¡|d/< | d0¡�s&| d0¡�r&| d0¡|d0< | d1i ¡}t | d1¡tƒ�rN| d1¡ni } t |tƒ�rŽ|  ¡ D ]&\}!}"|  | |!¡|"d2d„ ¡||!< �qfd S )3NZmemosc                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  zmemo:r  r$   r.  Z	createdAtZ
reminderAtr$  r¨   r!   r!   r"   r©   F  rª   z5Handler._merge_life_generic_modules.<locals>.<lambda>ZfocusRecordsc              	   S   sŒ   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrˆdt|  dd¡ƒ d t|  dd¡ƒ d t|  d|  d	d¡¡ƒ d t|  d
d¡ƒ S dS )NrÍ   r"  zfocus:r)   r$   r.  r   rÄ   r•  ræ   r$  r¨   r!   r!   r"   r©   K  rª   rX  c                 S   s\   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrXdt|  dd¡ƒ d t|  dd¡ƒ S dS )NrÍ   r"  zbook:r”  r$   r.  rš  r$  r¨   r!   r!   r"   r©   P  rª   ZmoodsZsleepReminderShownc                 S   s   t | ƒpt |ƒS rº  )rÓ   )r‰  Úoldr!   r!   r"   r©   V  rª   ZreminderStateZviralVideoAnalysisÚhistoryc                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  zviral:r…  r$   r.  Z
analyzedAtr”  r$  r¨   r!   r!   r"   r©   _  rª   ÚaiLearnZcurrentIndexr   c                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  zai:r)   r$   r.  Z
topicIndexZthemer$  r¨   r!   r!   r"   r©   h  rª   c                 S   s4   g | ],}t |tƒr| d ¡s,t | d¡tƒr|‘qS )rÍ   ZcompletedVideos)r<   r=   r2   rÑ   r�   r!   r!   r"   r’  j  s
   
 
 ÿz7Handler._merge_life_generic_modules.<locals>.<listcomp>ZrecommendationHistoryc                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  zai-rec:r)   r$   r.  ÚbatchIdr  r$  r¨   r!   r!   r"   r©   q  rª   ÚmanualSessionsc                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  z
ai-manual:r)   r$   r.  rÄ   ræ   r$  r¨   r!   r!   r"   r©   v  rª   ZrecommendationRefreshCount)ÚdailyVideosÚvideoCompletionsÚhotVideoCompletionsr}  r7   r{  r$   )r~  r  ZstatusUpdatedAtZcompletedAtTsZ	completedZcancelledAtrÏ   Úcoursesrá   c                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  zcourse:r)   r$   r.  Ú	episodeIdræ   r$  r¨   r!   r!   r"   r©   ¢  rª   ZcompletedEpisodeIdsc                 S   s   g | ]}t |ƒ‘qS r!   rÑ  r�   r!   r!   r"   r’  ¦  s     ZcurrentEpisodeIdZepisodes)	r”  r‘  ZsubtitleZcoverZentryUrlZseasonIdZ
totalPartsZtotalMinutesZcatalogFetchedAt)Nr$   ZreadingAutoÚenabledZcurrentBookZinsightsc                 S   sp   t | tƒr&|  d¡r&dt|  d¡ƒ S t | tƒrldt|  dd¡ƒ d t|  dd¡ƒ d t|  dd¡ƒ S dS )	NrÍ   r"  zinsight:r)   r$   r.  ZsentenceZinsightr$  r¨   r!   r!   r"   r©   Á  rª   )r<   r=   rI  r2   rW  rÝ   r»   r[   r¾   rE  rF  r1   rM  rÑ   Úfromkeysr>   )#r<  r*  rÅ   Zexisting_viralZincoming_viralZexisting_aiZincoming_aiZexisting_refreshZincoming_refreshr¬   rA  Z	map_fieldrT  rS  r‰  Zcurrent_stampZ	old_stampZ
current_tsZold_tsZexisting_coursesZincoming_coursesZ	course_idZ
old_courseZcurrent_courseZcurrent_doneZold_doneZcurrent_episodesZold_episodesrv  Zexisting_readingZincoming_readingZincoming_insightsZexisting_insightsrÈ  Z	old_itemsr!   r!   r"   Ú_merge_life_generic_modules@  s   
ýýýýý .ýÿ
ýý ,
 
(  (  

$$ 
ý   
     ýz#Handler._merge_life_generic_modulesc              	   C   s   t |tƒr*t | d¡tƒr*|  | d¡¡ tj t¡s:|S z(ttddd��}t	 
|¡}W 5 Q R X W n tk
rz   | Y S X t |tƒsŠ|S |  ||¡ |  |¡ |  ||¡ |  |¡ |  ||¡ |  ||¡ |  |¡ |  |¡ tt| d¡pòdƒt| d¡�pdƒtt ¡ d ƒƒ|d< |S )Nrà   r%   r  r'   rð   r   rã   )r<   r=   r2   rp  r*   r+   r,   rÈ   r.   r/   r0   r3   r+  r-  r:  r@  rw  r„  Ú#_normalize_learning_session_minutesr»   r[   r   )r<  r*  r5   rÅ   r!   r!   r"   Ú_merge_life_data_for_saveÄ  s2    





ýz!Handler._merge_life_data_for_savec                    sŽ  |  d¡pi }|  d¡pi }|  d¡p(g }|  d¡p6i   d¡p@i }g }| ¡ D ]Ô}t|tƒs^qNtƒ }|  d¡ppg D ]®}	t|	tƒs‚qr|	  d¡dk�r|	  d¡�r|	  d	¡r´| |	¡ qr|	  d
¡t|	d ƒf}
|
|k�rt|	  d¡pâdƒdk�rt|	d ƒ|	d< d|	d< d|	d	< | |
¡ | |	¡ qrqN| 	¡ D �]Z\‰ }t|tƒ�rL|  d¡nd }t|t
ƒ�s`�q,tdd„ |D ƒd ƒ}tdd„ |D ƒd ƒ}|�rì‡ fdd„|D ƒ}tdd„ |D ƒƒ}|�rìtdd„ |D ƒƒ}t|t|  d¡�pÞdƒ| ƒ|d< |�r,‡ fdd„|D ƒ}tdd„ |D ƒƒ}|�r,|  d¡�p*i   d¡�p6g }tdd„ |D ƒƒ}|t‡ fdd„|D ƒƒ7 }t|t|  d¡�pxdƒ| ƒ|d< �q,d S )NrÊ   rà   rá   rz  r€  r®   )Úcoursezcourse-completer�  rJ  r)   rÄ   r   rr  TrË   c                 s   s*   | ]"}t |tƒr| d ¡dkr|V  qdS rÌ   r£   r   r!   r!   r"   rG   û  s     
  z>Handler._normalize_learning_session_minutes.<locals>.<genexpr>c                 s   s*   | ]"}t |tƒr| d ¡dkr|V  qdS )rÍ   r   Nr£   r   r!   r!   r"   rG   ü  s     
  c                    s(   g | ] }t |tƒr| d ¡ˆ kr|‘qS r¢   r£   ©rC   rq  ©rÂ   r!   r"   r’  þ  s     
  z?Handler._normalize_learning_session_minutes.<locals>.<listcomp>c                 s   s*   | ]"}|  d ¡rt|  d¡pdƒV  qdS ©rJ  rr  r   Nró  rˆ  r!   r!   r"   rG   ÿ  s     
 c                 s   s&   | ]}t d t| d¡pd ƒƒV  qdS ©r   rÄ   N©r»   r[   r2   rˆ  r!   r!   r"   rG   	  s     rÎ   c                    s   g | ]}|  d ¡ˆ kr|‘qS r¢   rœ   rˆ  r‰  r!   r"   r’  	  s      c                 s   s*   | ]"}|  d ¡rt|  d¡pdƒV  qdS rŠ  ró  rˆ  r!   r!   r"   rG   	  s     
 r|  c                 s   s&   | ]}t d t| d¡pd ƒƒV  qdS r‹  rŒ  rˆ  r!   r!   r"   rG   	  s     c                 3   s>   | ]6}t |tƒr| d ¡ˆ krtdt| d¡p0dƒƒV  qdS )r)   r   rÄ   N)r<   r=   r2   r»   r[   rˆ  r‰  r!   r"   rG   		  s     
  r  )r2   r,  r<   r=   rW   rV   r1   r[   rZ   r¾   rÑ   rÒ   r>  r»   )r<  r   rÔ   r   Zenglish_sessionsr€  Zcourse_sessionsr‡  rb   ru  r¬   rÕ   rË   Zenglish_taskZai_taskrá   rJ  ZrecordedZmanualr!   r‰  r"   r…  ß  sV    



"
"z+Handler._normalize_learning_session_minutesc              
   C   sþ   z¾|   ¡ }t|tƒr| d¡nd }t|tƒsF| jdddœdd� W d S |  |¡}t| d¡pft ¡ d ƒ|d< t d	¡|d
< t	t
ddd��}tj||ddd� W 5 Q R X |  d|d dœ¡ W n: tk
rø } z| jdt|ƒdœdd� W 5 d }~X Y nX d S )Nr   Fzdata must be an objectrk   rW  rm  rð   rã   rñ   rò   ró   r&   r'   rô   rõ   T)rg   r7   rZ  )rr  r<   r=   r2   ro  r†  r[   r   r   r.   rÈ   r/   rü   r3   r1   )r<  rˆ   r   r5   rŒ   r!   r!   r"   rb  	  s    

zHandler._save_life_datac              	   C   s0   ddddgddddgd	d
ddgddddœg dœS )NTr$   r°  r±  õ   çŸ¥è¯†æŠ€èƒ½õ   ç”Ÿæ´»ç�µæ„Ÿõ   æ�žç¬‘å¨±ä¹�õ	   æœªåˆ†ç±»õ	   ç¼–ç¨‹/AIõ   è�Œåœºæ²Ÿé€šõ   ç�†è´¢õ   å…¶ä»–çŸ¥è¯†u	   æœªå�Œæ­¥uˆ   æŠ–éŸ³/å°�çº¢ä¹¦æ”¶è—�éœ€è¦�ç™»å½•æ€�æˆ–å¯¼å‡ºçš„åˆ†äº«é“¾æŽ¥ã€‚å½“å‰�æœ¬åœ°æœ�åŠ¡å·²å‡†å¤‡å¥½å…¥åº“ã€�åˆ†ç±»ã€�è½¬å†™å’Œåˆ†æž�æµ�ç¨‹ã€‚)ÚdouyinÚxiaohongshur�  )rg   r7   ri  Z
categoriesZknowledgeSubcategoriesÚ
syncStatusr8   r!   rG  r!   r!   r"   Ú_favorite_default_data	  s    

ýõzHandler._favorite_default_datac              
   C   sØ   |   ¡ }tj t¡s|S zvttddd��}t |¡}W 5 Q R X t|t	ƒsb|d|d ddi–i–W S ||–}t| 
d¡tƒs‚g |d< d|d	< |W S  tk
rÒ } z&|d
|d dt|ƒi–dœ– W Y ¢S d }~X Y nX d S )Nr%   r&   r'   r—  r�  u3   æ”¶è—�æ•°æ�®æ ¼å¼�ä¸�æ­£ç¡®ï¼Œå·²ä½¿ç”¨ç©ºæ•°æ�®ã€‚r8   Trg   F)rg   r—  )r˜  r*   r+   r,   ÚFAVORITE_COLLECTIONS_PATHr.   r/   r0   r<   r=   r2   rÑ   r3   r1   )r<  Údefaultr5   r   rŒ   r!   r!   r"   Ú_load_favorite_data+	  s    
zHandler._load_favorite_datac              	   C   s>   t  d¡|d< ttddd��}tj||ddd� W 5 Q R X d S )	Nrñ   r7   ró   r&   r'   Frô   rõ   )r   r   r.   r™  r/   rü   )r<  r   r5   r!   r!   r"   Ú_save_favorite_data<	  s    zHandler._save_favorite_datac                 C   s   |   |  ¡ ¡ d S rº  )ro  r›  rG  r!   r!   r"   Ú_serve_favorite_collectionsA	  s    z#Handler._serve_favorite_collectionsc                 C   s6   t | j dd¡ƒ}|r"| j |¡nd}t | d¡¡S )NrU  r   rV  r&   )r[   ru   r2   rg  r   r/   r†   r‡   )r<  rj  rS  r!   r!   r"   rr  D	  s    zHandler._read_json_bodyc                 C   sL   |pd  ¡ }d|ksd|kr dS d|ks0d|kr4dS d|ksDd	|krHd
S dS )Nr$   z
douyin.comZ	iesdouyinr°  zxiaohongshu.comzxhslink.comr±  zbilibili.comzb23.tvr“  u   æœªçŸ¥å¹³å�°)rA  )r<  r  rA  r!   r!   r"   rµ  I	  s    zHandler._detect_video_platformc                 C   sb   t  d|pd¡}ddddddd	d
dddddg}|D ]"}||p>dkr2||kr2| |¡ q2|d d… S )Nu   #([^#\sï¼Œã€‚,.!ï¼�?ï¼Ÿ]+)r$   ÚAIõ   ç¼–ç¨‹õ   è�Œåœºõ   æ²Ÿé€šr“  õ   åŸºé‡‘õ   çœ�é’±õ   å®¶å±…õ   ç©¿æ�­õ   ç¾Žé£Ÿõ   æ�žç¬‘õ   æ®µå­�u   å® ç‰©r   )r¹   ÚfindallrV   )r<  r  r™  ÚkeywordsÚkeywordr!   r!   r"   Ú_extract_favorite_tagsS	  s    zHandler._extract_favorite_tagsc                 C   sZ   t  dd|pd¡}t  dd|¡}t  dd|¡}t  dd|¡ d¡}|sN|pLd}|d d	… S )
Nzhttps?://\S+rú  r$   u   #[^#\sï¼Œã€‚,.!ï¼�?ï¼Ÿ]+z^[\d.:\sA-Za-z@/]+rù  u    ï¼Œã€‚,.!ï¼�?ï¼Ÿõ   æœªå‘½å��æ”¶è—�è§†é¢‘r   rû  )r<  r  r…  r”  r!   r!   r"   Ú_clean_favorite_title[	  s    zHandler._clean_favorite_titlec                    s  |› dd  |¡› �‰ dddddddd	d
dddddddg}dddddddg}dddddddd d!d"g
}t‡ fd#d$„|D ƒƒrÊt‡ fd%d$„d&D ƒƒr’d'S t‡ fd(d$„d)D ƒƒr¬d*S t‡ fd+d$„d,D ƒƒrÆd-S d.S t‡ fd/d$„|D ƒƒräd0S t‡ fd1d$„|D ƒƒrþd2S d3S )4Nrú  rž  rŸ  õ   ä»£ç �ÚPythonÚCursoru   æ•ˆçŽ‡u   æ•™ç¨‹u   å­¦ä¹ r   r¡  õ   è¡¨è¾¾r“  r¢  õ   è‚¡ç¥¨õ   å­˜é’±u   å‰¯ä¸šr§  r¨  u   æ²™é›•u   å“ˆå“ˆu   ç¦»è°±u   æ•´æ´»u   å¨±ä¹�u   ç”Ÿæ´»r¤  r¥  r¦  u   æ—…è¡Œu   æ”¶çº³u   å�šé¥­u   ç�µæ„Ÿu   è£…ä¿®u   æŠ¤è‚¤c                 3   s   | ]}|ˆ kV  qd S rº  r!   r/  ©r  r!   r"   rG   i	  s     z3Handler._classify_favorite_video.<locals>.<genexpr>c                 3   s   | ]}|ˆ kV  qd S rº  r!   r/  rµ  r!   r"   rG   j	  s     )rž  rŸ  r¯  r°  r±  u   è±†åŒ…ZCoze)r�  r‘  c                 3   s   | ]}|ˆ kV  qd S rº  r!   r/  rµ  r!   r"   rG   l	  s     )r   r¡  r²  u   æ±‡æŠ¥u   é�¢è¯•)r�  r’  c                 3   s   | ]}|ˆ kV  qd S rº  r!   r/  rµ  r!   r"   rG   n	  s     )r“  r¢  r³  r´  r£  u   æŠ•èµ„)r�  r“  )r�  r”  c                 3   s   | ]}|ˆ kV  qd S rº  r!   r/  rµ  r!   r"   rG   q	  s     )r�  r$   c                 3   s   | ]}|ˆ kV  qd S rº  r!   r/  rµ  r!   r"   rG   s	  s     )rŽ  r$   )r�  r$   )rQ   rJ   )r<  r”  r™  Z	knowledgeZfunnyZlifer!   rµ  r"   Ú_classify_favorite_videod	  s"    $z Handler._classify_favorite_videoc                 C   sà   |  d¡pd}|  d¡pd}|  d¡p(d}|  d¡p6d}d |  d	¡pHg ¡}|rT|n|› d
|› �}|dkrŠd|r|d| d nd› �}d}	n,|dkrœd}d}	n|dkr®d}d}	nd}d}	|  |¡d d… pÊd}
|
||	t d¡dœS )Nr”  r­  Ú
transcriptr$   Úcategoryr�  Úsubcategoryu   ã€�r™  rú  r�  ur   è¿™æ�¡å†…å®¹é€‚å�ˆæ²‰æ·€ä¸ºä¸€å¼ çŸ¥è¯†å�¡ç‰‡ï¼Œé‡�ç‚¹å…³æ³¨â€œé—®é¢˜ã€�æ–¹æ³•ã€�ä¾‹å­�ã€�è¡ŒåŠ¨â€�å››å±‚ç»“æž„ã€‚u	   å­�ç±»ï¼šu   ã€‚uW   æ��ç‚¼ 3 ä¸ªå�¯æ‰§è¡Œæ­¥éª¤ï¼Œå¹¶æŠŠå…¶ä¸­æœ€å®¹æ˜“å½“å¤©å®žè·µçš„ä¸€æ­¥åŠ å…¥å¾…åŠžã€‚rŽ  uu   è¿™æ�¡å†…å®¹çš„ä»·å€¼åœ¨äºŽåœºæ™¯å�¯å�‘ï¼Œé€‚å�ˆè®°å½•è§¦å�‘ç�µæ„Ÿçš„ç”»é�¢ã€�ç‰©å“�ã€�åœ°ç‚¹æˆ–ç”Ÿæ´»æ–¹å¼�é€‰æ‹©ã€‚uE   æ‹†å‡ºå�¯å¤�ç”¨å…ƒç´ ï¼šåœºæ™¯ã€�é¢„ç®—ã€�å‡†å¤‡ç‰©ã€�æ›¿ä»£æ–¹æ¡ˆã€‚r�  ux   è¿™æ�¡å†…å®¹ä¸»è¦�ä¾�é� æƒ…ç»ªé‡Šæ”¾å’Œå��å·®åˆ¶é€ è®°å¿†ç‚¹ï¼Œé€‚å�ˆåˆ†æž�åŒ…è¢±é“ºåž«ã€�èŠ‚å¥�å�œé¡¿å’Œç»“å°¾å��è½¬ã€‚uQ   è®°å½•ç¬‘ç‚¹å…¬å¼�ï¼šé“ºåž«å¯¹è±¡ã€�é¢„æœŸæ–¹å�‘ã€�å��å·®åŠ¨ä½œã€�ç»“å°¾å›žæ‰£ã€‚uZ   å½“å‰�ä¿¡æ�¯è¾ƒå°‘ï¼Œå»ºè®®å…ˆè¡¥å……æ ‡é¢˜ã€�æ ‡ç­¾æˆ–é€�å­—ç¨¿ï¼Œå†�å�šæ›´ç²¾ç¡®å½’ç±»ã€‚uT   å…ˆåˆ¤æ–­å®ƒæ˜¯çŸ¥è¯†ã€�ç�µæ„Ÿè¿˜æ˜¯å¨±ä¹�ï¼Œå†�å†³å®šæ˜¯å�¦æ”¶è—�è¿›é•¿æœŸå�ˆé›†ã€‚r
  u   æš‚æ— å�¯åˆ†æž�æ–‡æœ¬ã€‚rñ   )rç  ZcontentInsightZactionSuggestionr7   )r2   rQ   rë  r   r   )r<  rž   r”  r·  r¸  r¹  r™  ZmaterialZfocusÚactionrç  r!   r!   r"   Ú_favorite_analysisw	  s.    üzHandler._favorite_analysisc                 C   sÒ  �zŽ|   ¡ }t|tƒr"| dd¡nd}t d| ¡ ¡}|  ¡ }dd„ | dg ¡D ƒ}g }|D ]Þ}| ¡ }|snq\t d|¡}|s€q\| 	d¡}	|	|kr”q\|  
|¡}
|  ||	¡}|  ||
¡\}}d	tt ¡ d
 ƒ› dt| dg ¡ƒt|ƒ › �|  |	¡||	|||
t d¡dddi dœ}|  |¡|d< d|d< | |¡ | |	¡ q\|| dg ¡ |d< |�rndt|ƒ› d�|d d< |  |¡ |  dt|ƒ|dœ¡ W n< tk
�rÌ } z| jdt|ƒdœdd� W 5 d }~X Y nX d S )Nr  r$   z\n{2,}|\r?\n(?=.*https?://)c                 S   s    h | ]}|  d ¡r|  d ¡’qS ©r…  rœ   r�   r!   r!   r"   r&  ˜	  s     
 z7Handler._import_favorite_collections.<locals>.<setcomp>r8   r}  r   Úfav_rã   r_   rñ   õ	   å¾…è½¬å†™õ	   å¾…åˆ†æž�)rÍ   r–  r”  r…  r¸  r¹  r™  ÚcollectedAtÚtranscriptStatusr·  ÚanalysisStatusr©  r©  õ   å·²ç”Ÿæˆ�åˆ�æ­¥åˆ†æž�rÂ  u
   å·²å¯¼å…¥ u:    æ�¡æ”¶è—�é“¾æŽ¥ï¼Œå¹¶å®Œæˆ�è‡ªåŠ¨åˆ†ç±»ä¸Žåˆ�æ­¥åˆ†æž�ã€‚r—  r�  T)rg   Úaddedr   Frk   rZ  rm  )rr  r<   r=   r2   r¹   ry  rµ   r›  r~  r€  r¬  r®  r¶  r[   r   r>   rµ  r   r»  rV   rZ   rœ  ro  r3   r1   )r<  rˆ   r·  Zsnippetsr   Úexisting_urlsrÄ  ZsnippetZ	url_matchr…  r™  r”  r¸  r¹  rž   rŒ   r!   r!   r"   rc  ’	  sX    

.ô

z$Handler._import_favorite_collectionsc                 C   s   t j t¡rtS t d¡S )Nr
   )r*   r+   r,   ÚNODE_EXEÚshutilÚwhichrG  r!   r!   r"   Ú_node_commandÁ	  s    zHandler._node_commandc                 C   sT   t j ¡ }g }t j t¡r$| t¡ | d¡r<| |d ¡ |rPt j 	|¡|d< |S )NZ	NODE_PATH)
r*   r   rE  r+   r,   ÚNODE_MODULESrV   r2   ÚpathseprQ   )r<  ÚenvÚpathsr!   r!   r"   Ú	_node_envÆ	  s    


zHandler._node_envr   c           	      C   s®   |  dd¡}|  d¡p |  d|¡}|  |¡}|  ||¡\}}dtt ¡ d ƒ› d|› �|  d¡ph|  |¡|||||t d¡d	dd
i |  d¡pŽddœ}|  |¡|d< d|d< |S )Nr…  r$   r”  r½  rã   r_   r–  rñ   r¾  r¿  r®   z
login-sync)rÍ   r–  r”  r…  r¸  r¹  r™  rÀ  rÁ  r·  rÂ  r©  r®   r©  rÃ  rÂ  )	r2   r®  r¬  r¶  r[   r   rµ  r   r»  )	r<  Zraw_itemrL  r…  r”  r™  r¸  r¹  rž   r!   r!   r"   Ú_favorite_item_from_syncÑ	  s*    
óz Handler._favorite_item_from_syncc              	   C   sŒ   dd„ |  dg ¡D ƒ}g }|D ]P}|  d¡}|r||kr:q|  |t|  dg ¡ƒt|ƒ ¡}| |¡ | |¡ q|rˆ||  dg ¡ |d< |S )Nc                 S   s    h | ]}|  d ¡r|  d ¡’qS r¼  rœ   r�   r!   r!   r"   r&  ê	  s     
 z1Handler._merge_favorite_videos.<locals>.<setcomp>r8   r…  )r2   rÏ  r>   rV   rZ   )r<  r   Z
raw_videosrÅ  rÄ  r·  r…  rž   r!   r!   r"   Ú_merge_favorite_videosé	  s    
 
zHandler._merge_favorite_videosc              
   C   s4  z|   ¡ }W n tk
r$   i }Y nX t|tƒr<| dd¡nd}|  ¡ }|sd| jdddœdd� d S tj 	t
¡sˆ| jdddœdd� d S �zhtjtd	d
� tj td¡}tj|d	d
� tj td¡}t|ddd��$}| dt d¡› d|› d�¡ W 5 Q R X d}tj 	|¡�s$t d¡�p"t d¡}|�sD| jdddœdd� W d S g }|dk�r\| d¡ |dk�rp| d¡ tj|d|› �ddf|•ttjtjtjdk�r¤tjnd d!� |  ¡ }	d"d"d#t d¡d$œ|	d%< |  |	¡ |  d	|	|	d% d& d'œ¡ W n< tk
�r. }
 z| jdt|
ƒdœdd� W 5 d }
~
X Y nX d S )(Nr–  rf  Fu/   æœªæ‰¾åˆ° Node.jsï¼Œæ— æ³•æ‰“å¼€ç™»å½•çª—å�£ã€‚rk   rZ  rm  u   sync-favorites.js ä¸�å­˜åœ¨ã€‚Tr*  zbrowser-profilez	login.logr,  r&   r'   z
[rñ   z] open login chrome r.  z5C:\Program Files\Google\Chrome\Application\chrome.exeÚchromez
chrome.exeu.   æœªæ‰¾åˆ° Chromeï¼Œæ— æ³•æ‰“å¼€ç™»å½•çª—å�£ã€‚)rf  r•  zhttps://www.douyin.com/)rf  r–  zhttps://www.xiaohongshu.com/z--user-data-dir=z--remote-debugging-port=9223z--new-windowre   r   )r  r  r  Zcreationflagsu   ç™»å½•çª—å�£å·²æ‰“å¼€u¡   å·²æ‰“å¼€ç‹¬ç«‹ Chrome ç™»å½•çª—å�£ã€‚è¯·æ‰«ç �ç™»å½•æŠ–éŸ³å’Œå°�çº¢ä¹¦ï¼›ç™»å½•å®Œæˆ�å�Žå…³é—­è¿™ä¸ªç™»å½•çª—å�£ï¼Œå†�å›žåˆ°å·¥ä½œå�°ç‚¹å‡»â€œå�Œæ­¥æ”¶è—�â€�ã€‚©r•  r–  r�  r7   r—  r�  )rg   r   r�  )rr  r3   r<   r=   r2   rÉ  ro  r*   r+   r,   ÚFAVORITE_SYNC_SCRIPTr2  ÚFAVORITE_LOG_DIRrQ   r.   r3  r   r   rÇ  rÈ  rV   r  ÚPopenrR   ZDEVNULLra   ZCREATE_NEW_PROCESS_GROUPr›  rœ  r1   )r<  rˆ   r–  r
   Zprofile_dirZlog_pathZlog_filerÑ  Zurlsr   rŒ   r!   r!   r"   rd  ÷	  s^    
(



ûü

z#Handler._login_favorite_collectionsc           
   
   C   s8  |   ¡ }|  ¡ }|sXdddt d¡dœ|d< |  |¡ | jd||d d dœd	d
� d S �ztj|tddgt	ddddd|  
¡ d�}|jpŠd ¡ }|ržt |¡nd|jp¨dg g dœ}|  || d¡pÄg ¡}| d¡pÔg }dd„ |D ƒ}| di ¡ dd¡| di ¡ dd¡dt|ƒ› d�t d¡dœ|d< | d¡�rLd| d¡› �|d d< |  |¡ |  t|ƒd kt|ƒ||d!œ¡ W nº tjk
�rÐ   d"d"d#t d¡dœ|d< |  |¡ | jd||d d dœd$d
� Y nd tk
�r2 }	 zDddt|	ƒt d¡dœ|d< |  |¡ | jd|t|	ƒdœd	d
� W 5 d }	~	X Y nX d S )%Nu   å�Œæ­¥å¤±è´¥u8   æœªæ‰¾åˆ° Node.jsï¼Œæ— æ³•å�¯åŠ¨æµ�è§ˆå™¨å�Œæ­¥è„šæœ¬ã€‚rñ   rÒ  r—  Fr�  )rg   r   rl   rZ  rm  Úsyncrf  Tr&   rH   r
  )r  r  r  r(   r  rx   rÌ  r$   u   å�Œæ­¥è„šæœ¬æ— è¾“å‡º)rg   rl   Ústatusesr8   r8   r×  c                 S   s"   i | ]}t |tƒr| d ¡|“qS )r–  r£   rˆ  r!   r!   r"   r¤   E
  s     
  z6Handler._sync_favorite_collections.<locals>.<dictcomp>r°  u   æœªè¿”å›žçŠ¶æ€�r±  u   å�Œæ­¥å®Œæˆ�ï¼Œæ–°å¢ž uf    æ�¡æ”¶è—�ã€‚è‹¥æ–°å¢žä¸º 0ï¼Œè¯·ç¡®è®¤ç™»å½•çª—å�£é‡Œå·²ç»�è¿›å…¥æ”¶è—�é¡µå¹¶èƒ½çœ‹åˆ°æ”¶è—�å†…å®¹ã€‚rl   u   å�Œæ­¥è„šæœ¬å¼‚å¸¸ï¼šr   )rg   rÄ  r‹   r   u   å�Œæ­¥è¶…æ—¶uZ   å�Œæ­¥è¶…è¿‡ 3 åˆ†é’Ÿæœªå®Œæˆ�ã€‚è¯·ç¡®è®¤ç™»å½•çª—å�£æ²¡æœ‰å�¡åœ¨éªŒè¯�ç �æˆ–æ�ƒé™�é¡µã€‚iø  )rÉ  r›  r   r   rœ  ro  r  r  rÓ  rR   rÎ  r  rµ   r/   r†   r  rÐ  r2   r>   r  r3   r1   )
r<  r
   r   r  r  r‹   rÄ  r×  Z
status_maprŒ   r!   r!   r"   re  )
  sh    ü


ø
"ü

$ü

"ü

z"Handler._sync_favorite_collectionsc                 C   s*   t t d¡ƒt t d¡ƒt t d¡ƒdœS )Núyt-dlpÚffmpegÚwhisper)ZytDlprÙ  Z
whisperCli)rÓ   rÇ  rÈ  rG  r!   r!   r"   r¶  c
  s    ýzHandler._tool_statusc                    sh  t jtdd� t dd| d¡p.ttt ¡ ƒƒ¡‰ t j	 
tˆ d ¡}tjddd	d
d|| dd¡gtddddddd� t j	 
tˆ d ¡}t j	 |¡sº‡ fdd„t  t¡D ƒ}|r¶|d n|}t j	 |¡sÎtdƒ‚tjd|dddddddtg
tddddddd� t j	 |¡d d  }t j	 |¡�s&td!ƒ‚t|d"ddd#��(}| ¡  ¡ t j	 |t¡fW  5 Q R £ S Q R X d S )$NTr*  z[^a-zA-Z0-9_-]r_   rÍ   z.%(ext)srØ  z-xz--audio-formatZmp3z-or…  r$   r&   rH   r
  )r  r  r  r(   r  rx   Zcheckz.mp3c                    s(   g | ] }|  ˆ d  ¡rtj t|¡‘qS )rÐ  )rB   r*   r+   rQ   ÚFAVORITE_MEDIA_DIR)rC   ra   ©rQ  r!   r"   r’  z
  s      z=Handler._transcribe_favorite_with_whisper.<locals>.<listcomp>r   u0   éŸ³é¢‘æ��å�–å¤±è´¥ï¼šæœªæ‰¾åˆ°è¾“å‡ºéŸ³é¢‘æ–‡ä»¶rÚ  z
--languageZChinesez--modelrQ  z--output_formatZtxtz--output_diriX  z.txtu/   Whisper å·²è¿�è¡Œï¼Œä½†æœªæ‰¾åˆ°é€�å­—ç¨¿æ–‡ä»¶r%   )r(   r  )r*   r2  rÛ  r¹   r„  r2   r1   r[   r   r+   rQ   r  r  rR   r,   rõ  rP  Úsplitextr.   r   rµ   rY   )r<  rž   Z
output_tplZ
audio_pathZmatchesÚtranscript_pathr5   r!   rÜ  r"   Ú!_transcribe_favorite_with_whisperj
  sD    $ø
ø
z)Handler._transcribe_favorite_with_whisperc           	   
      sÆ  �z‚|   ¡ }t|tƒr"| dd¡nd‰ |  ¡ }t‡ fdd„| dg ¡D ƒd ƒ}|sl| jdddœd	d
� W d S |  ¡ }dd„ | ¡ D ƒ}|r¦| d¡s¦d|d< d|d< n‚zD| d¡sØd|d< |  	|¡\}}||d< ||d< d|d< d|d< W n< t
k
�r& } zd|d< d|› d�|d< W 5 d }~X Y nX |  |¡|d< d|d< ||d d< | d¡�rZdnd|d d< |  |¡ |  d ||d!œ¡ W n< t
k
�rÀ } z| jdt|ƒdœd"d
� W 5 d }~X Y nX d S )#NrÍ   r$   c                 3   s    | ]}|  d ¡ˆ kr|V  qdS rÙ   rœ   )rC   Úv©Zitem_idr!   r"   rG   “
  s      z<Handler._analyze_favorite_collection_item.<locals>.<genexpr>r8   Fu   æ”¶è—�è§†é¢‘ä¸�å­˜åœ¨rk   r[  rm  c                 S   s   g | ]\}}|s|‘qS r!   r!   r²  r!   r!   r"   r’  ˜
  s      z=Handler._analyze_favorite_collection_item.<locals>.<listcomp>r·  u   ç¼ºå°‘è½¬å†™ç»„ä»¶rÁ  u“   éœ€è¦�å®‰è£… yt-dlpã€�ffmpeg å’Œ Whisper å�Žæ‰�èƒ½ä»Žå¹³å�°é“¾æŽ¥æ��å�–éŸ³é¢‘å¹¶è½¬é€�å­—ç¨¿ã€‚å½“å‰�å·²å…ˆåŸºäºŽæ ‡é¢˜/æ ‡ç­¾å®Œæˆ�å†…å®¹åˆ†æž�ã€‚ZtranscriptNoteu	   è½¬å†™ä¸­ZtranscriptPathu	   å·²è½¬å†™u-   å·²æ��å�–éŸ³é¢‘å¹¶å®Œæˆ� Whisper é€�å­—ç¨¿ã€‚u   è½¬å†™å¤±è´¥u'   éŸ³é¢‘æ��å�–æˆ– Whisper è½¬å†™å¤±è´¥ï¼šu7   ã€‚å½“å‰�å·²å…ˆåŸºäºŽæ ‡é¢˜/æ ‡ç­¾å®Œæˆ�å†…å®¹åˆ†æž�ã€‚r©  u	   å·²åˆ†æž�rÂ  r³  u	   é€�å­—ç¨¿u   æ ‡é¢˜/æ ‡ç­¾ZtranscriptBasisT)rg   rž   r   rZ  )rr  r<   r=   r2   r›  rÒ   ro  r¶  r¾   rß  r3   r»  rœ  r1   )	r<  rˆ   r   rž   r¸  r¹  r·  rÞ  rŒ   r!   rá  r"   rf  Ž
  s@     

"
z)Handler._analyze_favorite_collection_itemc              
      sZ  t | jƒj}|dkr |  ¡  �n6|dkr4|  ¡  �n"|dkrH|  ¡  �n|dkr\|  ¡  �nú|dkrp|  ¡  �næ|dkr„|  ¡  �nÒ|dkr˜|  ¡  �n¾|dkr¬|  	¡  �nª|d	krÀ|  
¡  �n–|d
krÔ|  ¡  �n‚|dk�rd|  d¡ |  ¡  |  dd¡ |  ¡  tj t¡�rDttddd��}| j | ¡  d¡¡ W 5 Q R X n| j t dg i¡ d¡¡ �nò| j d¡�r‚zœt ¡ }td d k	�r¦|td  tk �r¦td }n| jdddidd�}||dœa|  d¡ |  ¡  |  dd¡ |  ¡  | j tjd|dœdd� d¡¡ W np tk
�r~ } zP|  d¡ |  ¡  |  dd¡ |  ¡  | j tjdt |ƒd œdd� d¡¡ W 5 d }~X Y nX nÔ| j d!¡�r¸|  !¡ }| j"|| #d"¡�r®dnd#d$� nž| j d%¡�rL|  d¡ |  ¡  |  dd¡ |  ¡  tj t$¡�r,tt$ddd��}| j | ¡  d¡¡ W 5 Q R X n| j t dd&d œ¡ d¡¡ n
t%ƒ  &¡  d S )'Nz/api/hot-videosz/api/ai-learning-videosr÷   z/api/favorite-collectionsz/api/reading-notez/api/reading-notesz/api/reading-book-archivesz/api/reading-book-archivez/reading-note-viewz/reading-book-viewz
/sync.jsonrD  rq   rr   r%   r&   r'   rX  z/api/weread-readtimesr   r   z/readdata/detailÚmodeZweeklyr   rw   r   T)rg   r   Frn   rk   z/api/daily-english-listeningrg   rZ  rm  z/api/last-reading-noteznot generated yet)'r   r+   r  r  r  r�  r  r  rö  rø  rÏ  rð  rE  rC  rB  rF  r*   r,   ri  r.   rh  r3  r   r€   r/   r}   rB   r   r'  Ú_READTIMES_TTLrT  r3   r1   r»  ro  r2   r-   r:  Údo_GET)r<  Zreq_pathr5   r   r   rŒ   r‹   r=  r!   r"   rä  ±
  sz    

"  


&
: 
" zHandler.do_GETc                    s"   |   dd¡ |  ¡  tƒ  ¡  d S )NzCache-Controlzno-store)rB  rC  r:  rF  rG  r=  r!   r"   rF  õ
  s    zHandler.end_headersc                 G   s   d S rº  r!   )r<  ZfmtÚargsr!   r!   r"   Úlog_messageú
  s    zHandler.log_message)r:   )r‹  rŒ  )r$   r£  )rD  )N)ra  )r   )[Ú__name__Ú
__module__Ú__qualname__r;  rC  rH  rJ  rT  rk  r\  r]  r^  r_  r`  r‚  rƒ  r†  rŠ  r�  rŸ  r¢  r¯  ra  ro  r»  rs  rÉ  rÏ  rÓ  rÕ  rà  rî  rð  rö  rø  rë  r  r	  r  r  r  r  r  r  r  r  r+  r-  r3  r:  r=  r@  rB  rI  rM  rR  rW  r[  r`  rg  rm  rp  rw  r„  r†  r…  rb  r˜  r›  rœ  r�  rr  rµ  r¬  r®  r¶  r»  rc  rÉ  rÎ  rÏ  rÐ  rd  re  r¶  rß  rf  rä  rF  ræ  Ú__classcell__r!   r!   r=  r"   r9  �  s°   		
7'


5
A/
G2
+3%!4,%	$
#
Z -
	/
2:$#Dr9  c               	   C   s  t j t¡s:ttddd��} tjdg i| dd� W 5 Q R X t j t¡sxttddd��} tjt 	t¡| ddd� W 5 Q R X t  
t¡ tƒ  tƒ  tƒ  t jd	krÆtjtd
dd� ¡  tjtd
dd� ¡  d
tj_t dtft¡�}tdt› �ƒ | ¡  W 5 Q R X d S )Nró   r&   r'   rX  Frn   rô   rõ   re   Tzreading-cloud-sync-startupr  zenglish-cloud-sync-startupr$   z4Personal Life OS server running at http://localhost:)r*   r+   r,   ri  r.   r/   rü   r™  r9  r˜  ÚchdirrR   r8  r6  r	  ra   r  r  r�   r  rÿ   ÚsocketserverZThreadingTCPServerZallow_reuse_addressÚPORTÚprintZserve_forever)r5   Zhttpdr!   r!   r"   Úmainþ
  s"    "

rï  Ú__main__)rd   )r   )rd   )r
  )r
  Nr   )r
  )^Ú__doc__Zhttp.serverZhttprì  rE  rÄ  r/   r<  r*   r¹   rR  r  r  r   rÇ  r   r  Zurllib.parser�   Zurllib.requestr   r   r+   r{  rx  Ú__file__rR   rQ   ri  rI  rQ  r-   r%  rS   rT   rÝ  r;   r  r  r  rÈ   r™  rÛ  rÓ  r¡  rÆ  rÊ  rÔ  r²   r´   r   r2   rA   r„   r~   rí  r7  r1  r'  r(  r)  rÞ   r'  rã  ZLockr&  r  r   rz   rù   rK   r#   r6   r?   rL   rc   r�   rÆ   rÉ   r³   rß   rè   rÿ   r	  r  r$  r)  r6  r8  ÚserverZSimpleHTTPRequestHandlerr9  rï  rç  r!   r!   r!   r"   Ú<module>   sÊ   " 
û	
	#
 +

=
!
&
0                ~
