+
    i                         R t ^ RIt^ RIt^ RIt^ RIt^ RIHtHt ^ RIH	t	H
t
HtHt ^RIHt RtRtRtR^R	^R
^</tR^R	^R
^
/tR R ltR R ltR R ltR R ltRR R lltR R ltRR R lltRR R lltR# )zHacker News search via Algolia API (free, no auth required).

Uses hn.algolia.com/api/v1 for story discovery and comment enrichment.
No API key needed - just HTTP calls via stdlib urllib.
N)ThreadPoolExecutoras_completed)AnyDictListOptional)httpz$https://hn.algolia.com/api/v1/searchz,https://hn.algolia.com/api/v1/search_by_datez#https://hn.algolia.com/api/v1/itemsquickdefaultdeepc                $    V ^8  d   QhR\         /# )   msgstr)formats   "V/Users/bowang/.openclaw/workspace/skills/last30days-official/scripts/lib/hackernews.py__annotate__r   !   s      c     c                    \         P                  P                  4       '       dD   \         P                  P                  RV  R24       \         P                  P	                  4        R# R# )zHLog to stderr (only in TTY mode to avoid cluttering Claude Code output).z[HN] 
N)sysstderrisattywriteflush)r   s   &r   _logr   !   sD    
zz

5R)

 r   c                0    V ^8  d   QhR\         R\        /# )r   date_strreturn)r   int)r   s   "r   r   r   (   s      C C r   c                   V P                  R4      p\        V^ ,          4      \        V^,          4      \        V^,          4      rCp^ RIp^ RIpVP                  W#WFP                  P
                  R7      p\        VP                  4       4      # )z8Convert YYYY-MM-DD to Unix timestamp (start of day UTC).-N)tzinfo)splitr    calendardatetimetimezoneutc	timestamp)r   partsyearmonthdayr%   r&   dts   &       r   _date_to_unixr/   (   sk    NN3E58}c%(mSq]D			44E4E4I4I		JBr||~r   c                0    V ^8  d   QhR\         R\        /# )r   tsr   )r    r   )r   s   "r   r   r   2   s     # #c #c #r   c                    ^ RI pVP                   P                  WP                  P                  R7      pVP	                  R4      # )z%Convert Unix timestamp to YYYY-MM-DD.N)tzz%Y-%m-%d)r&   fromtimestampr'   r(   strftime)r1   r&   r.   s   &  r   _unix_to_dater6   2   s9    				(	(0A0A0E0E	(	FB;;z""r   c                0    V ^8  d   QhR\         R\         /# )r   textr   r   )r   s   "r   r   r   9   s      c c r   c                    ^ RI p\        P                  ! V 4      p VP                  RRV 4      p VP                  RRV 4      p V P	                  4       # )z9Strip HTML tags and decode entities from HN comment text.Nz<p>r   z<[^>]+> )rehtmlunescapesubstrip)r8   r;   s   & r   _strip_htmlr@   9   sC    ==D66&$%D66*b$'D::<r   c                v    V ^8  d   QhR\         R\         R\         R\         R\        \         \        3,          /# )r   topic	from_dateto_datedepthr   )r   r   r   )r   s   "r   r   r   B   sB     - --- - 	-
 
#s(^-r   c           
     r   \         P                  V\         R,          4      p\        V4      p\        V4      R,           p\        RV  RV RV R24       RV RR	R
RV RV 2R\	        V4      /p^ RIHp \         RV! V4       2p	 \        P                  ! RV	^R7      p
T
P                  R. 4      p\        R\        T4       R24       T
#   \        P                   d(   p\        RT 24       R. R\	        T4      /u Rp?# Rp?i\         d(   p\        RT 24       R. R\	        T4      /u Rp?# Rp?ii ; i)zSearch Hacker News via Algolia API.

Args:
    topic: Search topic
    from_date: Start date (YYYY-MM-DD)
    to_date: End date (YYYY-MM-DD)
    depth: 'quick', 'default', or 'deep'

Returns:
    Dict with Algolia response (contains 'hits' list).
r
   iQ zSearching for 'z	' (since z, count=)querytagsstorynumericFilterszcreated_at_i>z,created_at_i<hitsPerPage)	urlencode?GETtimeoutzSearch failed: hitserrorNzFound z stories)DEPTH_CONFIGgetr/   r   r   urllib.parserM   ALGOLIA_SEARCH_URLr   request	HTTPError	Exceptionlen)rB   rC   rD   rE   countfrom_tsto_tsparamsrM   urlresponseerR   s   &&&&         r   search_hackernewsrc   B   sA   " UL$;<EI&G'"U*E?5'9+XeWA	FG 	M'.Hs5z	F ' )F"3!4
5C-<<sB7 <<#D6#d)H	%&O >> -qc"#GSV,, -qc"#GSV,,-s6   C
 
D6D;D6D6D6D1+D61D6c                    V ^8  d   QhR\         \        \        3,          R\        \         \        \        3,          ,          /# )r   ra   r   )r   r   r   r   )r   s   "r   r   r   r   s/     , ,S#X ,4S#X;O ,r   c                   V P                  R. 4      p. p\        V4       EFa  w  r4VP                  RR4      pVP                  R4      ;'       g    ^ pVP                  R4      ;'       g    ^ pVP                  R4      pRp	V'       d   \        V4      p	VP                  R4      ;'       g    Rp
R	V 2p\        R
RVR,          ,
          4      p\	        R\
        P                  ! V4      ^(,          4      p\	        RVR,          V,           R,           4      pVP                  RVRVP                  RR4      RV
RVRVP                  RR4      RV	RRVRV/R\        V^4      RRVP                  RR4      R,           2/	4       EKd  	  V# )zmParse Algolia response into normalized item dicts.

Returns:
    List of item dicts ready for normalization.
rR   objectIDr:   pointsnum_commentscreated_at_iNr`   z%https://news.ycombinator.com/item?id=g333333?g      ?g{Gz?g?gffffff?g?	object_idtitlehn_urlauthordate
engagement	relevancewhy_relevantzHN story about rB   :N<   N)	rU   	enumerater6   maxminmathlog1pappendround)ra   rR   itemsihitrj   rg   rh   ri   r   article_urlrl   
rank_scoreengagement_boostrp   s   &              r   parse_hackernews_responser   r   s    <<#DED/GGJ+	"''aww~.33!ww~.$\2H ggen**8D cQX./
sDJJv$6$;<Z#-0@@3FG	SWWWb);fcggh+H& y!,ocgggw.G.L-MN
 	) "F Lr   c                ^    V ^8  d   QhR\         R\        R\        \         \        3,          /# )r   rj   max_commentsr   )r   r    r   r   )r   s   "r   r   r      s.     *@ *@C *@s *@4S> *@r   c                L   \          RV  2p \        P                  ! RV^R7      pTP                  R	. 4      pT Uu. uF7  pTP                  R
4      '       g   K  TP                  R4      '       g   K5  TNK9  	  ppTP                  R RR7       . p. p	TRT  F  p\        TP                  R
R4      4      p
\        T
4      R8  d   T
R,          R,           MT
pTP                  RTP                  RR4      R
TRTP                  R4      ;'       g    ^ /4       T
P                  R4      ^ ,          P                  R4      ^ ,          R,          pT'       g   K  T	P                  T4       K  	  RTRT	/#   \         d"   p\	        RT  RT 24       R. R. /u Rp?# Rp?ii ; iu upi )zFetch top-level comments for a story from Algolia items endpoint.

Args:
    object_id: HN story ID
    max_comments: Max comments to return

Returns:
    Dict with 'comments' list and 'comment_insights' list.
/rO   rP   zFailed to fetch comments for z: commentscomment_insightsNchildrenr8   rm   c                 8    V P                  R 4      ;'       g    ^ # )rg   rU   )cs   &r   <lambda>&_fetch_item_comments.<locals>.<lambda>   s    QUU8_%9%9%9r   Tkeyreverser:   i,  :Ni,  Nz...rg   z. r   :N   N)ALGOLIA_ITEM_URLr   rX   rZ   r   rU   sortr@   r[   rx   r$   )rj   r   r`   datarb   r   r   real_commentsr   insightsr8   excerptfirst_sentences   &&           r   _fetch_item_commentsr      s    a	{
+C8||E33
 xx
B'H a55= 	
UU8_ 	
8   94HHH=L)155,-(+D	C$t*u$TaeeHb)GaeeHo**
 	 D)!,2248;DA>OON+ * "4h??9  8,YKr!=>B 2B778s.   E2 F!F!3F!2F=FFFc          	          V ^8  d   QhR\         \        \        \        3,          ,          R\        R\         \        \        \        3,          ,          /# )r   rz   rE   r   )r   r   r   r   )r   s   "r   r   r      s@     / /S#X// 
$sCx./r   c           
       a  S '       g   S # \         P                  V\         R,          4      p\        \        \	        S 4      4      V 3R lRR7      pVRV p\        R\	        V4       R24       \        ^R7      ;_uu_ 4       pV Uu/ uF(  pVP                  \        S V,          R	,          4      VbK*  	  pp\        V4       FD  pWx,          p VP                  ^R
7      p	V	R,          S V,          R&   V	R,          S V,          R&   KF  	  RRR4       S # u upi   \         d    . S T,          R&   . S T,          R&    K}  i ; i  + '       g   i     S # ; i)zFetch comments for top N stories by points.

Args:
    items: Parsed HN items
    depth: Research depth (controls how many to enrich)

Returns:
    Items with top_comments and comment_insights added.
r
   c                 V   < SV ,          P                  R / 4      P                  R^ 4      # )ro   rg   r   )r{   rz   s   &r   r   $enrich_top_stories.<locals>.<lambda>   s!    eAhll<4881Er   Tr   NzEnriching top z stories with comments)max_workersrj   rP   r   top_commentsr   )ENRICH_LIMITSrU   sortedranger[   r   r   submitr   r   resultrZ   )
rz   rE   limit	by_points	to_enrichexecutoridxfuturesfuturer   s
   f&        r   enrich_top_storiesr      s`    e]9%=>E c%jEI
 &5!I>#i.))?	@A		*	*h !

 !	 OO$c
;'  ! 	 
 #7+F/C4r2-3J-?c
>*178J1Kc
-. , 
+& L%
  4-/c
>*13c
-.4 
+	*& LsB   E.D5E8DEE#E 	<E?E 	 EE	)r
   )   )__doc__r<   rv   r   timeconcurrent.futuresr   r   typingr   r   r   r   r:   r   rW   ALGOLIA_SEARCH_BY_DATE_URLr   rT   r   r   r/   r6   r@   rc   r   r   r    r   r   <module>r      s      
  ? , , ; K 8  Rr
B Qq
B#-`,^*@Z/ /r   