Ë
     Lj‚  ã                   ó  — d Z ddlZddlZddlZddlmZ ddlmZmZ ddlm	Z	  e
ej                  d«      rej                  j                  d¬«        e	e«      j                  «       j                  Zed	z  Zed
z  Zg d¢Z ej(                  dej*                  «      Z ej(                  dej*                  «      ZdZdededz  fd„Zdee   deee   ef   fd„Zdedeeef   dz  fd„Z dedefd„Z!d„ Z"e#dk(  r e"«        yy)u!  Build insta_mapping.json from insta_meta.json.

Input: insta_meta.json â€” list of {thread_id, thread_name (YYYY/MM/DD),
created_at_ts, caption, image_urls[]}.

Output: insta_mapping.json â€” keyed by week (YYMMDD_YYMMDD), then by day
(MON-FRI), with lunch/dinner arrays of {thread_id, caption, image_urls}.

Lunch/dinner classification:
1. Drop near-duplicate posts (same caption + created_at within 5s) â€” Discord
   bot occasionally double-publishes on RESUME / connection wobble.
2. Classify each post by caption keywords (English Discord translations +
   Korean originals). Posts tagged 'lunch' go to lunch[]; 'dinner' go to
   dinner[]. Unknown captions fall back to created_at ordering against the
   remaining empty slot.
3. After all entries placed, any 3rd+ entry per day goes to 'extra'.
é    N)Údefaultdict)ÚdatetimeÚ	timedelta)ÚPathÚreconfigureúutf-8©Úencodingzinsta_meta.jsonzinsta_mapping.json)ÚMONÚTUEÚWEDÚTHUÚFRIÚSATÚSUNux   today'?s lunch|lunch menu|lunchtime|today'?s lunch special|ì˜¤ëŠ˜ ì �ì‹¬|ì �ì‹¬ ë©”ë‰´|ì �ì‹¬ ìŠ¤íŽ˜ì…œ|ì˜¤ëŠ˜ì�˜ ì �ì‹¬ul   tonight'?s|dinner|evening menu|ì˜¤ëŠ˜ ì €ë…�|ì €ë…� ë©”ë‰´|ì €ë…� ìŠ¤íŽ˜ì…œ|ì˜¤ëŠ˜ì�˜ ì €ë…�|today'?s dinneriˆ  ÚcaptionÚreturnc                 ób   — | syt         j                  | «      ryt        j                  | «      ryy)z7Return 'lunch' / 'dinner' / None based on caption text.NÚlunchÚdinner)ÚLUNCH_KWÚsearchÚ	DINNER_KW)r   s    ú+C:\fearx-photos\sync\build_insta_mapping.pyÚclassify_mealr   6   s+   € áØÜ‡��wÔØÜ×Ñ˜Ô ØØó    Úentriesc           	      óž  — g }d}| D ]Á  }|j                  d«      xs dj                  «       }t        |j                  d«      xs d«      }d}|D ]^  }|j                  d«      xs dj                  «       |k(  sŒ*t        t        |j                  d«      xs d«      |z
  «      t        k  sŒ\d} n |r|dz  }Œ±|j                  |«       ŒÃ ||fS )z§Drop later entries that share caption with an earlier entry within DUP_WINDOW_MS.

    Returns (kept, dropped_count). Entries assumed sorted by created_at_ts asc.
    r   r   Ú Úcreated_at_tsFTé   )ÚgetÚstripÚintÚabsÚDUP_WINDOW_MSÚappend)r   ÚkeptÚdroppedÚeÚcapÚtsÚis_dupÚprevs           r   Údedupe_caption_dupesr/   A   sÑ   € ð
 €DØ€GÛˆØ�u‰u�YÓÒ% 2×,Ñ,Ó.ˆÜ�—‘�Ó'Ò,¨1Ó-ˆØˆÛˆDØ—‘˜Ó#Ò) r×0Ñ0Ó2°cÓ9¼cÄ#ÀdÇhÁhÈÓF_ÒFdÐcdÓBeÐhjÑBjÓ>kÔo|Ó>|Ø�Ùð ñ Ø�q‰LˆGØØ�‰�A�ð ð �ˆ=Ðr   Údate_strc                 ó  — t        j                  | d«      j                  «       }|j                  «       }|dk\  ry|t	        |¬«      z
  }|t	        d¬«      z   }|j                  d«      › d|j                  d«      › �}t        |   }||fS )uC   '2026/04/22' â†’ ('260420_260424', 'WED'). Returns None if Sat/Sun.z%Y/%m/%dé   N)Údaysé   z%y%m%dÚ_)r   ÚstrptimeÚdateÚweekdayr   ÚstrftimeÚ	DAY_NAMES)r0   Údr8   ÚmondayÚfridayÚweek_keyÚday_names          r   Údate_to_weekr@   W   s‰   € ä×Ñ˜( JÓ/×4Ñ4Ó6€AØ�i‰i‹k€GØ�!‚|ØØ” Ô(Ñ(€FØ”i QÔ'Ñ'€FØ—/‘/ (Ó+Ð,¨A¨f¯o©o¸hÓ.GÐ-HÐI€HÜ˜Ñ!€HØ�XÐÐr   r*   c                 óP   — | d   | d   | d   | j                  d«      xs g | d   dœS )NÚ	thread_idr   Ú
image_urlsÚ
video_urlsÚcreated_at_kst)rB   r   rC   rD   Ú	posted_at)r"   )r*   s    r   Ú_entry_payloadrG   d   s;   € à�{‘^Ø�Y‘<Ø˜‘oØ—e‘e˜LÓ)Ò/¨RØÐ'Ñ(ñð r   c            	      ó(
  — t         j                  «       s7t        dt         › �t        j                  ¬«       t        j
                  d«       t        j                  t         j                  d¬«      «      } t        dt        | «      › dt         j                  › �«       | D �ch c]1  }t        |j                  dd	«      «      j                  d
«      r|d   ’Œ3 }}t        | «      }| D �cg c]A  }t        |j                  dd	«      «      j                  d
«      s|j                  d«      |v s|‘ŒC } }|t        | «      z
  }|rt        d|› d�«       t        t        «      }| D ]  }||d      j!                  |«       Œ i }g }g }d}	g }
t#        |j%                  «       «      D �]ñ  \  }}t'        |«      }|s|j!                  |«       Œ&|\  }}|j)                  d„ ¬«       t+        |«      \  }}|	|z  }	||vri ||<   |||   vrg g g dœ||   |<   ||   |   }g }|D ]™  }t-        |j                  d«      xs d	«      }|dv r#||   s||   j!                  t/        |«      «       ŒH|dv r=|d   j!                  t/        |«      «       |j!                  |t        |d   «      f«       Œ‰|j!                  |«       Œ› |D ]Ø  }|d   sH|d   j!                  t/        |«      «       |
j!                  |d|j                  d«      xs d	d d f«       ŒP|d   sH|d   j!                  t/        |«      «       |
j!                  |d|j                  d«      xs d	d d f«       Œ�|d   j!                  t/        |«      «       |j!                  |t        |d   «      f«       ŒÚ �Œô t0        j3                  t        j4                  |dd¬«      d¬«       t        d«       t        dt        |«      › �«       t        dt        |«      › �|d d «       t        d|	› �«       t        d t        |
«      › �|
d d «       t        d!t        |«      › �|d d «       t        d"t0        › �«       t        d#«       t#        |«      D ]œ  }g }t6        d d D ]l  }||   j                  |i «      }t        |j                  d«      xs g «      }t        |j                  d«      xs g «      }|j!                  |› d$|› d%|› �«       Œn t        d&|› d&d'j9                  |«      › �«       Œž y c c}w c c}w )(Nznot found: )Úfiler!   r   r	   zloaded z entries from rB   r   Úinsta_Úthread_namezdedupe (cross-source): dropped z4 Discord entries that duplicate Playwright originalsr   c                 ó   — | d   S )Nr    © )Úxs    r   Ú<lambda>zmain.<locals>.<lambda>•   s	   €  1 _Ò#5r   )Úkey)r   r   Úextrar   )r   r   rQ   r   é(   r   Fé   )Úensure_asciiÚindentz
=== summary ===z  weeks covered: z  weekend dates skipped: r2   z#  same-caption duplicates dropped: z'  unknown-caption fallback placements: z  extras (3rd+ on same day): z
  output: z
=== per-week ===Ú:Ú/z  Ú )ÚMETAÚis_fileÚprintÚsysÚstderrÚexitÚjsonÚloadsÚ	read_textÚlenÚnameÚstrr"   Ú
startswithr   Úlistr'   ÚsortedÚitemsr@   Úsortr/   r   rG   ÚOUTÚ
write_textÚdumpsr:   Újoin)Údatar*   Úpw_datesÚbeforeÚcross_droppedÚby_dateÚmappingÚweekend_skippedÚ
extras_logÚsame_caption_dropsÚfallback_logr0   r   Úwk_dayr>   r?   r)   Úday_slotÚunknownsÚmealÚwkÚ	day_statsr;   ÚslotsÚlÚdis                             r   Úmainr�   n   sü  € Ü�<‰<Œ>Ü�œD˜6Ð"¬¯©Õ4Ü�‰�ŒÜ�:‰:”d—n‘n¨g�nÓ6Ó7€DÜ	ˆG”C˜“I�;˜n¬T¯Y©Y¨KÐ
8Ô9ñ +/ó E©$ QÜ�q—u‘u˜[¨"Ó-Ó.×9Ñ9¸(ÔCð �-Ó ¨$€Hð Eä�‹Y€FÙó ;‘t�!Ü˜AŸE™E +¨rÓ2Ó3×>Ñ>¸xÔHØŸ™˜mÓ,°Ñ8ò �t€Dð ;ð œS ›YÑ&€MÙÜÐ/°¨Ð>rÐsÔtäœ$Ó€GÛˆØ��-Ñ Ñ!×(Ñ(¨Õ+ð ð €GØ!#€OØ(*€JØÐØ/1€Lä# G§M¡M£O×4Ñˆ�'Ü˜hÓ'ˆÙØ×"Ñ" 8Ô,ØØ#Ñˆ�(à�‰Ñ5ˆÔ6ä/°Ó8Ñˆ�Ø˜gÑ%Ðà˜7Ñ"Ø "ˆG�HÑØ˜7 8Ñ,Ñ,Ø46À"ÈrÑ*RˆG�HÑ˜hÑ'Ø˜8Ñ$ XÑ.ˆð  "ˆÛˆAÜ  §¡ yÓ!1Ò!7°RÓ8ˆDØÐ*Ñ*°8¸D²>Ø˜‘×%Ñ%¤n°QÓ&7Õ8ØÐ,Ñ,à˜Ñ!×(Ñ(¬¸Ó):Ô;Ø×!Ñ! 8¬S°¸'Ñ1BÓ-CÐ"DÕEà—‘ Õ"ð ó ˆAØ˜GÒ$Ø˜Ñ!×(Ñ(¬¸Ó):Ô;Ø×#Ñ# X¨w¸¿¹¸yÓ9IÒ9OÈRÐQTÐRTÐ8UÐ$VÕWØ˜hÒ'Ø˜Ñ"×)Ñ)¬.¸Ó*;Ô<Ø×#Ñ# X¨x¸!¿%¹%À	Ó:JÒ:PÈbÐRUÐSUÐ9VÐ$WÕXà˜Ñ!×(Ñ(¬¸Ó):Ô;Ø×!Ñ! 8¬S°¸'Ñ1BÓ-CÐ"DÕEò ðA 5ôV ‡N�N”4—:‘:˜g°EÀ!ÔDÈw€NÔWä	ÐÔÜ	Ðœc '›l˜^Ð
,Ô-Ü	Ð%¤c¨/Ó&:Ð%;Ð
<¸oÈbÈqÐ>QÔRÜ	Ð/Ð0BÐ/CÐ
DÔEÜ	Ð3´C¸Ó4EÐ3FÐ
GÈÐVXÐWXÐIYÔZÜ	Ð)¬#¨j«/Ð):Ð
;¸ZÈÈ¸^ÔLÜ	ˆJ”s�eÐ
Ôä	Ð
ÔÜ�WŽoˆØˆ	Ü˜2˜A“ˆAØ˜B‘K—O‘O A rÓ*ˆEÜ�E—I‘I˜gÓ&Ò,¨"Ó-ˆAÜ�U—Y‘Y˜xÓ(Ò.¨BÓ/ˆBØ×Ñ ˜s ! A 3 a¨ t˜_Õ-ð	 ô
 	��2�$�b˜Ÿ™ )Ó,Ð-Ð.Õ/ñ ùòUEùò;s   Â!6T
Ã(ATÚ__main__)$Ú__doc__r_   Úrer\   Úcollectionsr   r   r   Úpathlibr   ÚhasattrÚstdoutr   Ú__file__ÚresolveÚparentÚHERErY   rj   r:   ÚcompileÚ
IGNORECASEr   r   r&   rd   r   rf   ÚdictÚtupler$   r/   r@   rG   r�   Ú__name__rM   r   r   Ú<module>r’      sB  ðñó" Û 	Û 
Ý #ß (Ý á
ˆ3�:‰:�}Ô%Ø‡J�J×Ñ GÐÔ,áˆHƒ~×ÑÓ×&Ñ&€ØÐÑ€Ø
Ð!Ñ!€â=€	ð ˆ2�:‰:ðFà‡M�Mó€ð
 ˆB�J‰JðVà‡M�Mó€	ð €ð˜3ð  3¨¡:ó ð $ t¡*ð °°t¸D±zÀ3°Ñ1Gó ð,
˜3ð 
 5¨¨c¨¡?°TÑ#9ó 
ð�dð ˜tó ò]0ð@ ˆzÒÙ…Fð r   