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!   ú4/opt/workbuddy/server.py.tmp-syncfix-20260928-180551Ú_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±   Ú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    r7  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/  r0  r   )r   r   r   r   r1  ÚHOT_VIDEO_AUTO_HOURr?   r   r  r*   r+   rQ   rR   r3  r.   r4  r/   r}   r3   r   r  r5  r!   r!   r"   r  y  s$    
6 z,start_hot_video_auto_scheduler.<locals>.loopTzhot-video-auto-07r  r6  r	  r!   r!   r"   Ústart_hot_video_auto_schedulerx  s    r9  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_responserD  Ú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)rK  ÚRuntimeErrorr/   r}   r€   r�   r‚   rƒ   ÚGW_URLÚsslZcreate_default_contextr…   r†   r   r‡   )	r=  rL  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$   )rZ  rY  rô   r'   rõ   rö   éô  rE  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   rF  rD  rG  Úwfiler4  r}   r1   r€   r<   r=   r.   Ú	SYNC_PATHrý   rC  r>   )r=  ÚlengthrT  r   rŒ   rY  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   rE  r[  ©Ú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   rX  rn  u   æ—¥æœŸæ ¼å¼�é”™è¯¯Tr   )rg   Údeletedr)   )Ú_read_json_bodyr1   r2   r3   rp  Ú_reading_note_file_for_dater*   r+   r,   Úremover6   r-   rQ   rR   )r=  rˆ   Údate_strrŒ   Ú	note_pathrr  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“  rn  r]   zfiles must be a listrX  r   r¦   r+   r$   r@   r   rO   Tr+  rô   r&   r'   rP   )rg   Úwrittenrh   r[  )rs  r<   r=   r2   r~   rp  rÒ   r1   rH   rI   rL   r*   r+   ÚabspathrQ   rR   ÚsplitrB   Úsepr3  Údirnamer.   r4  Úutimer[   r3   )r=  rˆ   r]   rx  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 rm  )r  rp  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   rE  r[  rn  )	rs  r<   r=   r2   r[   r»   r3   r%  rp  )r=  r"  r#  rˆ   r‹   r!   r!   r"   ra  >  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µ   rB  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�  rQ  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/responsesrM  rN  rO  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   rT  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$   Frq  rk   rX  rn  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)rs  r<   r=   r1   r2   r3   rp  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"   rb     sV    .
 *(

*($


zHandler._analyze_viral_videorE  c                 C   sF   |   |¡ |  ¡  |  dd¡ |  ¡  | j tj|dd� d¡¡ d S )Nrq   rr   Frn   r&   )	rF  rD  rC  rG  ri  r4  r/   r}   r€   )r=  rˆ   ro  r!   r!   r"   rp  /  s
    
zHandler._json_responsec                 C   s   t ƒ S ©N)rÇ   rH  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=  rv  Zyearr!   r!   r"   rt  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   rz  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>rE  )r   r   r+   Úqueryr2   rt  r*   r,   rF  rD  rC  rG  ri  r4  r€   r.   rÊ  r   rÅ  rÆ  )r=  Úqsrv  rw  r5   rT  Ú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+   ry  rQ   rT   rB   r{  )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'   rY  Ú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›  ro  ÚprogressÚreadTsZread_tsÚ
quoteCountÚmaxQuoteCountrd   ZevidenceLimitu'   åŸºäºŽå¾®ä¿¡è¯»ä¹¦å�¯è§�æ•°æ�®æ•´ç�†ã€‚z/reading-book-view?book=rò   )rÕ  rÚ  r•  r›  ro  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Ì  rE  )r   r   r+   rÍ  r2   rÖ  r*   r,   rF  rD  rC  rG  ri  r4  r€   r.   rÊ  r   rï  rÅ  rÆ  )	r=  rÎ  rÕ  rí  r5   rT  Ú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À   rp  )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\  rn  r%   r&   r'   T)rg   rÙ  rð  rÅ  )r   r   r+   rÍ  r2   rÖ  r*   r,   rp  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Ç  rH  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‚  rv  r5   r  r  rÈ  Zprimary_matchrÉ  r!   rH  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À   rp  )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\  rn  r%   r&   r'   T)rg   r)   rð  rÅ  )r   r   r+   rÍ  r2   rt  r*   r,   rp  r.   r   r  rÊ  )r=  rÎ  rv  rw  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   r[  rn  )r*   r+   r,   r;   rp  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   r[  rn  )r*   r+   r,   ÚAI_LEARNING_VIDEOS_PATHrp  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   r[  rn  )r*   r+   r,   rÉ   rp  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=  r3  r!   r2  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!   ©r4  ©rC   rŒ   ©rr  r=  r!   r"   r“  æ  s      z1Handler._merge_life_exercises.<locals>.<listcomp>c                    s    h | ]}ˆ   |¡rˆ   |¡’qS r!   r6  r7  rH  r!   r"   r'  ç  s     
 z0Handler._merge_life_exercises.<locals>.<setcomp>)
rÞ   r<   r=   r2   r¾   rÒ   rV   rW   r4  rZ   )r=  r+  rÆ   Zincoming_exercisesZincoming_deletedZexisting_deletedrÃ   ÚkeysZtarget_keysr¬   Zexisting_exercisesÚentriesZtarget_entriesrb   r3  r!   r8  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=  r3  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 )Nr5  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   r3  rH  r!   r"   rG     s     ZexerciseMinutesr   TrÜ   u   è·³èˆž/è¿�åŠ¨ rí   rî   FrÐ   u   è·³èˆž/è¿�åŠ¨ 0 åˆ†é’Ÿ)r<   r=   r2   r¾   rÒ   rÓ   ÚsumÚpop)
r=  r   r5  rÕ   rÃ   rÖ   rÌ   r×   r:  rÅ   r!   rH  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_listrE  rb   rž   r¬   r!   rD  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�   rD  r!   r"   r¤   (  s   
 
 þ z4Handler._merge_learning_sessions.<locals>.<dictcomp>rK  )rJ  r  r2   rF  rG  )	r=  rH  rI  rE  ÚmergedZcorrectionsÚindexrž   r¬   r!   rD  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   rF  rG  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>   rF  rG  r¾   )r=  rH  rI  rO  Úorderrž   r•  rŠ  Zcurrent_imagesZitem_imagesÚbaser¬   rB  r!   rP  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   rC  rF  rG  )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   rF  rG  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/  rZ  r$   ú,ÚanswersÚcorrectÚtotal)r<   r=   rQ   r1   r2   rÒ   )rC   r-  r!   r!   r"   r'  ƒ  s   
ù$üz1Handler._merge_attempt_records.<locals>.<setcomp>r/  rZ  r$   r]  r^  r_  r`  )r<   rÒ   rF  rG  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)rY  ZpassedrZ  r   )ÚtaskResultsZfirstTaskResultsZtaskAttemptsÚreadingrc  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ó  re  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ó  re  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
       
 rf  rõ   c                 s   s   | ]}|  d ¡V  qdS )rY  Nrœ   re  r!   r!   r"   rG   ·  s     rY  )r<   r=   rF  rG  r¾   r2   rÔ   r»   r[   r\  ra  rC  rÒ   r>   r?  Úall)	r=  Zincoming_recordZexisting_recordZrecord_typerL  r¬   rV  rW  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 )NFrZ  rc  Ú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   rk  r!   r!   r"   rG   Ä  s     
 u   çœŸé¢˜é¢˜åž‹rû  )r<   r=   rÔ   r2   rÒ   ÚextendrQ   )r=  rÿ   Zhas_current_answersrj  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ÚtrueReadingBankrd  ZlegacyReadingPracticez
2026-07-30z	-fake-becFr   z5fake practice removed from current strict BEC reading)	rY  ri  rc  r^  r_  r`  rf  rZ  ZsourceStatusÚ	checkedIn)
r<   r=   r2   rÞ   rÒ   r¾   r1   rn  rF  rG  )r=  r   rd  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-rK  r)   r/  rÅ   ÚduplicateOriginalMinutesTro  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)rp  Zcardsrd  ÚwritingÚtasksZspeakingrp  ru  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Ü   rd  rt  )rÞ   r<   r=   r2   rq  rN  rW   rÒ   r1   r¹   r  r€  r[   r�  rB   rZ   rS  rJ  r¾   rF  rG  r¶   rÔ   rV   rh  )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¬   rV  rW  Zincoming_tsZexisting_tsÚfieldrU  rT  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ª   rY  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=   rJ  r2   rX  rÞ   r»   r[   r¾   rF  rG  r1   rN  rÒ   Úfromkeysr>   )#r=  r+  rÆ   Zexisting_viralZincoming_viralZexisting_aiZincoming_aiZexisting_refreshZincoming_refreshr¬   rB  Z	map_fieldrU  rT  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_episodesrw  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   rq  r*   r+   r,   rÉ   r.   r/   r0   r3   r,  r.  r;  rA  rx  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â   r{  r�  r®   )Úcoursezcourse-completer‚  rK  r)   rÅ   r   rs  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   rr  ©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 ©rK  rs  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   rv  r¬   rÖ   rÌ   Zenglish_taskZai_taskrâ   rK  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   rX  rn  rñ   rä   rò   ró   rô   r&   r'   rõ   rö   T)rg   r7   r[  )rs  r<   r=   r2   rp  r‡  r[   r   r   r.   rÉ   r/   rý   r3   r1   )r=  rˆ   r   r5   rŒ   r!   r!   r"   rc  	  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   rj  Z
categoriesZknowledgeSubcategoriesÚ
syncStatusr8   r!   rH  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»  )rp  rœ  rH  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 )NrV  r   rW  r&   )r[   ru   r2   rh  r   r/   r†   r‡   )r=  rk  rT  r!   r!   r"   rs  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   æœªçŸ¥å¹³å�°)rB  )r=  r  rB  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!   r0  ©r  r!   r"   rG   i	  s     z3Handler._classify_favorite_video.<locals>.<genexpr>c                 3   s   | ]}|ˆ kV  qd S r»  r!   r0  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!   r0  r¶  r!   r"   rG   l	  s     )r¡  r¢  r³  u   æ±‡æŠ¥u   é�¢è¯•)rŽ  r“  c                 3   s   | ]}|ˆ kV  qd S r»  r!   r0  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!   r0  r¶  r!   r"   rG   q	  s     )r�  r$   c                 3   s   | ]}|ˆ kV  qd S r»  r!   r0  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   r[  rn  )rs  r<   r=   r2   r¹   rz  rµ   rœ  r  r�  r­  r¯  r·  r[   r   r>   r¶  r   r¼  rV   rZ   r�  rp  r3   r1   )r=  rˆ   r¸  Zsnippetsr   Úexisting_urlsrÅ  ZsnippetZ	url_matchr†  rš  r•  r¹  rº  rž   rŒ   r!   r!   r"   rd  ’	  sX    

.ô

z$Handler._import_favorite_collectionsc                 C   s   t j t¡rtS t d¡S )Nr
   )r*   r+   r,   ÚNODE_EXEÚshutilÚwhichrH  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¡  rF  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_itemrM  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—  rg  Fu/   æœªæ‰¾åˆ° Node.jsï¼Œæ— æ³•æ‰“å¼€ç™»å½•çª—å�£ã€‚rk   r[  rn  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ï¼Œæ— æ³•æ‰“å¼€ç™»å½•çª—å�£ã€‚)rg  r–  zhttps://www.douyin.com/)rg  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�  )rs  r3   r<   r=   r2   rÊ  rp  r*   r+   r,   ÚFAVORITE_SYNC_SCRIPTr3  ÚFAVORITE_LOG_DIRrQ   r.   r4  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"   re  ÷	  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   r[  rn  Úsyncrg  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�  rp  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"   rf  )
  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É  rH  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   ©rR  r!   r"   r“  z
  s      z=Handler._transcribe_favorite_with_whisper.<locals>.<listcomp>r   u0   éŸ³é¢‘æ��å�–å¤±è´¥ï¼šæœªæ‰¾åˆ°è¾“å‡ºéŸ³é¢‘æ–‡ä»¶rÛ  z
--languageZChinesez--modelrR  z--output_formatZtxtz--output_diriX  z.txtu/   Whisper å·²è¿�è¡Œï¼Œä½†æœªæ‰¾åˆ°é€�å­—ç¨¿æ–‡ä»¶r%   )r(   r  )r*   r3  rÜ  r¹   r…  r2   r1   r[   r   r+   rQ   r  r  rR   r,   rö  rQ  Ú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\  rn  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   r[  )rs  r<   r=   r2   rœ  rÓ   rp  r·  r¾   rà  r3   r¼  r�  r1   )	r=  rˆ   r   rž   r¹  rº  r¸  rß  rŒ   r!   râ  r"   rg  Ž
  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.jsonrE  rq   rr   r%   r&   r'   rY  z/api/weread-readtimesr   r   z/readdata/detailÚmodeZweeklyr   rw   r   T)rg   r   Frn   rk   z/api/daily-english-listeningrg   r[  rn  z/api/last-reading-noteznot generated yet)'r   r+   r  r  r  rž  r  r  r÷  rù  rÐ  rñ  rF  rD  rC  rG  r*   r,   rj  r.   ri  r4  r   r€   r/   r}   rB   r   r(  Ú_READTIMES_TTLrU  r3   r1   r¼  rp  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)rC  rD  r;  rG  rH  r>  r!   r"   rG  õ
  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¤  )rE  )N)rb  )r   )[Ú__name__Ú
__module__Ú__qualname__r<  rD  rI  rK  rU  rl  r]  r^  r_  r`  ra  rƒ  r„  r‡  r‹  rŽ  r   r£  r°  rb  rp  r¼  rt  rÊ  rÐ  rÔ  rÖ  rá  rï  rñ  r÷  rù  rì  r  r
  r  r  r  r  r  r  r  r  r,  r.  r4  r;  r>  rA  rC  rJ  rN  rS  rX  r\  ra  rh  rn  rq  rx  r…  r‡  r†  rc  r™  rœ  r�  rž  rs  r¶  r­  r¯  r·  r¼  rd  rÊ  rÏ  rÐ  rÑ  re  rf  r·  rà  rg  rå  rG  rç  Ú__classcell__r!   r!   r>  r"   r:  �  s°   		
7'


5
A/
G2
+3%!4,%	$
#
Z -
	/
2:$#Dr:  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'   rY  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,   rj  r.   r/   rý   rš  r:  r™  ÚchdirrR   r9  r7  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í  rF  rÅ  r/   r=  r*   r¹   rS  r  r  r   rÈ  r   r  Zurllib.parser�   Zurllib.requestr   r   r+   r|  ry  Ú__file__rR   rQ   rj  rJ  rR  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î  r8  r2  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*  r7  r9  ZserverZSimpleHTTPRequestHandlerr:  rð  rè  r!   r!   r!   r"   Ú<module>   sÊ   " 
û	
	#
 +

=
!
&
0                ~
