
    \Sj8;                       d Z ddlm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c mZ ddlmZmZmZ ddlmZ ddlmZ  ed      Z ej0                         Zedz  Zed	z  Zd
Zedz  ZddddZddddZd#dZ d$dZ!d%d&dZ"d'd(dZ#d Z$d)dZ%d*d+dZ&d Z'd,dZ(d Z)d Z*d-d.dZ+d Z,d  Z-d! Z.e/d"k(  r e.        yy)/zData collector for the JARVIS morning briefing.

The cron job runs this script first and injects stdout into an LLM prompt.
The script intentionally returns compact JSON context, not polished prose.
    )annotationsN)datetime	timedeltatimezone)Path)ZoneInfoEurope/Zurichz(.hermes/assets/Gesundheit/health_data.dbz.todoist_tokenzfriday.uplink@gmail.comz.hermes/secrets/gog_keyring.envzWindisch AGg46<G@g oo @namelatlonStein AGghsG@g o@c                 4    t        j                  t              S )N)r   nowTZ     H/home/agent/.hermes/repos/HealthManager/scripts/cron/morning_briefing.py	now_localr       s    <<r   c                    t         j                  j                  dd      j                         } | r| S t        j                         st        dt               t        j                         j                  dz  rt        dt               t        j                  d      j                         D ]  }|j                         }|r|j                  d      r'|j                  d	      r|d
d  j                         }|j                  d      \  }}}|sc|j                         dk(  sw|j                         j                  d      j                  d      }|s|c S  t        dt               )NGOG_KEYRING_PASSWORD z-Missing gog keyring secret environment file: ?   z/Unsafe permissions on gog keyring secret file: utf-8)encoding#zexport    ="'z)GOG_KEYRING_PASSWORD missing or empty in )osenvirongetstripGOG_SECRET_ENVis_fileRuntimeErrorstatst_mode	read_text
splitlines
startswith	partition)valueraw_linelinekeysep	raw_valuesecrets          r   load_gog_keyring_passwordr5   $   s:   JJNN126<<>E!!#J>JZ[\\$$u,L^L\]^^",,g,>IIK 
~~ts+??9%8>>#D"nnS1S)399;"88__&,,S177<F
 B>BRS
TTr   c                &   t         j                  j                  | |xs ddi      }t         j                  j                  ||      5 }t	        j
                  |j                         j                  dd            cd d d        S # 1 sw Y   y xY w)N
User-AgentJARVIS-MorningBriefing/1.0headerstimeoutr   replace)errors)urllibrequestRequesturlopenjsonloadsreaddecode)urlr<   r:   reqrs        r   	http_jsonrJ   :   sw    
..
 
 g.e,Hd9e
 
fC			W		5 Fzz!&&(//')/DEF F Fs   	4BBc                    	 t        j                  | dd||      }|j                  |j                  |j                  fS # t
        $ r}ddt        |      fcY d }~S d }~ww xY w)NT)textcapture_outputr<   envi  r   )
subprocessrun
returncodestdoutstderr	Exceptionstr)cmdr<   rN   pes        r   rP   rP   @   sW    NN3T$UXY||QXXqxx// BAs   <? 	A AA A c                 v   t         j                  j                  t        d   t        d   dddddd      } i 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!d"d#d$d%d&d'd(d)d*d+d,d-d.}	 t	        d/| z         }|j                  d0i       }|j                  d1i       }|j                  d2i       }|j                  d3g       }g }g }t               j                         j                         }	t        |      D ]  \  }
}t        |      j                  |	      s!t        t        |      d4d5       }t        |      d4d6 |j                  d7      xs d g|
   |j                  d8      xs d g|
   |j                  d9      xs d g|
   |j                  |j                  d:      xs d g|
   d;      d<}d=|cxk  rd>k  rn n|j                  |       d=|cxk  rd?k  sn |j                  |        t        |D cg c]  }|j                  d@      xs d	 c}xs d	g      }t        dA   |j                  |j                  d:      dB      |j                  dC      |j                  dD      |j                  dE      |j                  d9      |j                  dF      xs d gd	   |j                  dG      xs d gd	   |j                  dH      xs d gd	   |||j                  dI      xs d;gd	   dJd  |j                  dK      xs d;gd	   dJd  dLS c c}w # t        $ r}dMt        |      icY d }~S d }~ww xY w)NNr   r   zbtemperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m,precipitationzRtemperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10mzYtemperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max,sunrise,sunsetr	      )latitude	longitudecurrenthourlydailyr   forecast_daysr   sonnigzmeist sonnig   u   teils bewölkt   u   bewölkt-   Nebel0   	Reifnebel3   zleichter Nieselregen5   Nieselregen7   zstarker Nieselregen=   zleichter Regenr   RegenA   zstarker RegenG   zleichter SchneeI   SchneeK   zstarker SchneeP   zleichte SchauerQ   Schauerzstarke SchauerGewitterzGewitter/Hagelzstarkes Gewitter/Hagel)R   _   `   c   z'https://api.open-meteo.com/v1/forecast?r]   r_   r^   time         precipitation_probabilityprecipitationwind_speed_10mweather_coder   )r{   precip_prob	precip_mmwind	condition   	      r   r   	unbekannttemperature_2mapparent_temperaturerelative_humidity_2mtemperature_2m_mintemperature_2m_maxprecipitation_sumsunrisesunset)locationr   temperature_cfeels_like_chumidity_pctwind_kmhtoday_min_ctoday_max_cprecip_sum_mmmax_precip_probability_pctcommute_windowr   r   error)r?   parse	urlencodeWINDISCHrJ   r#   r   date	isoformat	enumeraterU   r,   intappendmaxrT   )paramscodesdcurr_   r^   timescommutedaytodayithourrowxmax_rain_probrX   s                    r   weatherr   H   s   \\##UOe_wfl#% F	8()+;=>

G&(*@BDm 	! $&'7 :<W GI/ 		  "8	 .01A	 DFGX	
 	I
 ,AQWoE*!?&HIeeIr"gr"x$

62&  ",,.e$ 	 DAqq6$$U+s1vb}%DAr" &

+F G QD6STU$jj9CdVQG$45?$C"YY

>(B(Ltfa'PRTUC D~A~s#DB

3	  D1QUU=16Q6DKL (377>#:KH WW%56GG$:;GG$:; 01!II&:;EvqI!II&:;EvqI#ii(;<FJ*7%		),4a8=yy*2rdA6rs;
 	
 E   !Q  !s8   3E-L !L  LC6L L 	L8!L3-L83L8c                    | sy | j                  d      r| d d dz   } 	 t        j                  |       j                  t              S # t
        $ r Y y w xY w)NZz+00:00)endswithr   fromisoformat
astimezoner   rT   r   s    r   parse_dtr      sV    zz#crFX%%a(33B77 s   'A 	AAc                Z   t         j                  j                         }	 t               |d<   t        ddt        ddddt        |       d	d
ddgd|      \  }}}|dk7  s|j                         s|j                         xs d| g g dS 	 t        j                  |      }|j                  dt        |t              r|ng       }t               j!                         }	|	t#        d      z   }
g g d}|D ]  }|j                  d      xs i j                  d      xs$ |j                  d      xs i j                  d      }|j                  d      xs i j                  d      xs$ |j                  d      xs i j                  d      }d|j                  d      xs i v}|st%        |      nd }|r'	 t'        j(                  |      j!                         }d}n2|r|j!                         n|	}|r|j+                  d      n
t        |      }||j                  dd      |j                  dd      |j                  d      xs dd d  ||r|j-                         n|t%        |      rt%        |      j-                         n|d!}||	k(  r|d"   j/                  |       ||
k(  s|d#   j/                  |        |D ]  }||   j1                  d$ %        |S # t        $ r}t        |      g g dcY d }~S d }~ww xY w# t        $ r}d| g g dcY d }~S d }~ww xY w# t        $ r |	}Y Uw xY w)&Nr   )r   r   tomorrowgogz-acalendareventsz--allz--daysz--max30z--jsonz
--no-input<   )r<   rN   r   z	gog exit zcalendar json parse: rZ   days)r   r   startdateTimer   endu
   ganztägigz%H:%Msummaryz(ohne Titel)r   r   descriptioni,  )r{   r   r   r   all_day	start_isoend_isor   r   c                &    | j                  dd      S )Nr{   99:99r#   r   s    r   <lambda>z!calendar_events.<locals>.<lambda>   s    QUU67%; r   r1   )r!   r"   copyr5   r'   rU   rP   GOG_ACCOUNTr$   rC   rD   rT   r#   
isinstancelistr   r   r   r   r   r   strftimer   r   sort)r   rN   excrcouterrrawrX   evsr   r   resultev	start_rawend_rawr   r   r   time_sitemks                        r   calendar_eventsr      s   
**//
C@&?&A"# t[*h3t9V]_cemo{sLBS 
Qwciik8)B4(82SUVVSjjo ''(:c4#8Cb
ACKEya((Hr*F ,VVG_*//
;bw@USU?Z?Z[a?b	66%=&B++J7\BFF5M<OR;T;TU[;\RVVG_%:;+2#**95::< "F %

5A05U^^G,3y>Fvvi8z2.FF=17R#>.3*8@8Ix(224w
 :7O""4((]:%%d+5,6  =q	;<=MY  @SBB??@  S04rrRRS  sM   K 	K< 1#L	K9 K4.K94K9<	LLLLL*)L*c                    t         j                         sddiS t         j                         j                         } t        j
                  j                  ddd|  i      }	 t        j
                  j                  |d      5 }t        j                  |j                         j                               }d d d        j                  d	t        |t               r|ng       }t#               j%                         }|t'        d
      z   }g g g g g d}|D ]2  }	|	j                  d      r|	j                  d      xs i j                  d      }
|	j                  dd      |	j                  d      |
|	j                  d      d}|
r	 t)        j*                  |
d d       j%                         }|r||k  r|d   j-                  |       ||k(  r|d   j-                  |       ||k(  r|d   j-                  |       |s||cxk  r|t'        d      z   k  sn 	|d   j-                  |       |d   j-                  |       5 |D ])  }||   j/                  d        ||   d |dv rdnd  ||<   + t1        |D 	cg c]  }	|	j                  d      r|	 c}	      |d!<   |S # 1 sw Y   xY w# t        $ r}dt        |      icY d }~S d }~ww xY w# t        $ r d }Y :w xY wc c}	w )"Nr   zTodoist token fehltz$https://api.todoist.com/api/v1/tasksAuthorizationzBearer r9      r;   resultsrZ   r   )overduer   r   next_7_days
no_due_topcheckedduer   contentr   priority
project_id)r   r   r   r   
   r   r   r   r   r   r   c                V    | j                  d      xs d| j                  d      xs dfS )Nr   9999r   r   r   r   s    r   r   ztodoist.<locals>.<lambda>   s'    quuU|'=vquuZ?P?UTU&V r   r   )r   r         
total_open)TODOIST_TOKENexistsr*   r$   r?   r@   rA   rB   rC   rD   rE   rF   rT   rU   r#   r   r   r   r   r   r   r   r   r   len)tokenrH   rI   r   rX   tasksr   r   bucketsr   r   r   ddr   s                 r   todoistr     s   !.//##%++-E
..
 
 !GRaelmrlsctQu
 
vC!^^##C#4 	.

1668??,-A	. EE)*Q"5Q2>EKEya((Hrr"\^_G /55uuU|!r&&v.55B/QUU:=NWZjkjojop|j}~++CH5::< b5j	"))$/u ''-x
#**40?eiQ.?&???&--d3L!((.'/(  H
VWQZ Fa+?&?QG
H  E Jqy9I JKGLNA	. 	. !Q  !   !KsT   "!J3 2J&5J3 &K?K(K(&J0+J3 3	K<KKKK%$K%c                    t         j                  j                  | dddd      }	 t        d|z   d      }|r6|d   j	                  d	      t        |d   d
         t        |d   d         dS 	 y # t        $ r Y y w xY w)NrC   rZ   ch)qformatlimitcountrycodesz+https://nominatim.openstreetmap.org/search?   r;   r   display_namer   r   r
   )r?   r   r   rJ   r#   floatrT   )placer  arrs      r   geocoder     s    UfqZ^_`AEISUVFJJ~6uSVE]?S\abefgbhinbo\pqq    s   AA0 0	A<;A<c           	     H   	 d| d    d| d    d|d    d|d    d	}t        |d      }|j                  d	      xs i gd
   }t        |j                  dd
      dz  d      t        |j                  dd
      dz        dS # t        $ r}dt	        |      icY d }~S d }~ww xY w)Nz1https://router.project-osrm.org/route/v1/driving/r   ,r   ;z.?overview=false&alternatives=false&steps=false   r;   routesr   distancei  rZ   durationr   )distance_kmduration_min_no_trafficr   )rJ   r#   roundrT   rU   )origindestrG   r   routerX   s         r   
osrm_router     s    !A&-PQRXY^R_Q``abfglbmannoptuzp{o|  }k  lc2&x(RD!,$UYYz1%=%DaHejkpktktu  BC  lD  GI  lI  fJ  K  	K !Q  !s   A>B 	B!
BB!B!c                   | j                  dg       D ]  }|j                  d      xs dj                         |j                  d      xs dj                         sLg d}t        fd|D              rf|j                  dd      d	k  s|t	              }|sd
|j                  d       |d<   |c S  t        t              }d|d<   |S )Nr   r   r   r   )
homeofficeteamszoomonlinetelefonwindischc              3  N   K   | ]  }|d z   z   j                         v   yw) N)lower).0r   locr   s     r   	<genexpr>z%choose_destination.<locals>.<genexpr>
  s(     ?aqS3Y(//11?s   "%r{   r   z12:00zerster externer Termin: reasonzStandard Arbeitsweg)r#   r$   r&  anyr  dictSTEIN_AG)r   r   badgr   r(  r   s        @@r   choose_destinationr0    s    jj"% vvj!'R..066)$*113N?3??66&'"g-A 8	9J8KL( 	XA'AhKHr   c                   	 t         j                  j                  | ddi      }t         j                  j                  |d      5 }|j	                         }d d d        t        j                        }g }|j                  d      d | D ]  }|j                  d      xs dj                         }|j                  d	      xs dj                         }	|j                  d
      xs dj                         }
|so|j                  t        j                  dd|      |	|
d        |S # 1 sw Y   xY w# t        $ r g cY S w xY w)Nr7   r8   r9   r  r;   z.//itemtitler   linkpubDatez\s+r%  )r2  r3  	published)r?   r@   rA   rB   rE   ET
fromstringfindallfindtextr$   r   resubrT   )rG   	max_itemsrH   rI   xmlrootitemsr   r2  r3  pubs              r   	rss_itemsrA    s'   nn$$S<A]2^$_^^##C#4 	&&(C	}}S!LL+JY7 	dD]]7+1r88:EMM&)/R668D==+1r88:Crvvfc5'A4^abc	d 	 	  	s1   AD3 D'B!D3 9-D3 'D0,D3 3E Ec            	         ddd}  | dd      t        dd      xs	  | dd      t        dd      xs	  | dd       | d	d       | d
d       | dd      dS )N   c                `    t         j                  j                  |       }t        d| d|      S )Nz%https://news.google.com/rss/search?q=z&hl=de-CH&gl=CH&ceid=CH:de)r?   r   
quote_plusrA  )querynr  s      r   google_newsznews.<locals>.google_news)  s/    LL##E*@C]^`abbr   zBrugg Windisch Aargau heutez$https://www.srf.ch/news/bnf/rss/1646r   zSchweiz Nachrichten heutez$https://www.srf.ch/news/bnf/rss/1003zWelt Nachrichten heuteu%   Künstliche Intelligenz AI News heutez"Bitcoin Ethereum Krypto News heutez)Stau Aargau A1 A3 Brugg Baden Frick heute)local_brugg_windischswitzerlandworldaicryptotraffic_incidentsrC  )rF  rU   rG  r   )rA  )rH  s    r   newsrP  (  ss    c !,,I1 M !GKz{[vxyOzA1EqUmopIqA1EBAF()TVWX r   c                 X   g d d} t         j                         s| S 	 t        j                  t               }t        j                  |_        t               j                         t        d      z
  j                         }	 |j                  d|f      D cg c]  }t        |       c}| d<   	 |j                  d      j                         d   | d<   |j                          | S c c}w # t        $ r Y Hw xY w# t        $ r Y 1w xY w# t        $ r}t        |      | d	<   Y d }~| S d }~ww xY w)
N)recent_symptomsopen_lab_reviewsr   r   zSELECT datum, symptom, koerperbereich, intensitaet, notizen FROM symptom_log WHERE datum>=? ORDER BY datum DESC, id DESC LIMIT 6rR  zUSELECT count(*) FROM laborwerte_staging WHERE status IN ('zur_pruefung','extrahiert')r   rS  r   )	HEALTH_DBr   sqlite3connectRowrow_factoryr   r   r   r   executer,  rT   fetchonecloserU   )r   consincerI   rX   s        r   health_contextr^  6  s>    d
;C
ooi(!++!!#iQ&77BBD	7:{{ S  V[  U]8 &!d1g &C!"
	&)kk  3J  'K  'T  'T  'V  WX  'YC"# 			 J&  		  		  1vGJsl   A!D ?C) C$&C) -%C8 D $C) )	C52D 4C55D 8	DD DD 	D)D$$D)c                 t   t               } t        d      }t        |      }t        t        |      }| j                         | j                         j                         g d| j                            t               |t               t        ||ddt        j                  j                  t        d         z   dz   t        j                  j                  |j                  d      xs |j                  d      xs d	      z   d
t               t               g dd
}t!        t#        j$                  |dd             y )Nrb   r   )MontagDienstagMittwoch
DonnerstagFreitagSamstagSonntagzcOSRM-Fahrzeit ohne Live-Verkehr; Stau-/Unfallhinweise werden aus News/Traffic-Meldungen abgeleitet.z https://www.google.com/maps/dir/r   /r*  r   )r  destinationr  notegoogle_maps_url)uC   Strukturiere als kompaktes deutsches Morgen-Briefing für Telegram.u   Berücksichtige Termine, Todoist-Pendenzen, Gesprächs-Follow-ups, Chancen/Risiken, Wetter, Arbeitsweg/Verkehr, News, KI/Crypto und proaktive Tipps.zHWenn Datenquelle fehlt: kurz transparent markieren, nicht halluzinieren.)
generated_atr   
weekday_deweather_windischr   r  r   healthrP  briefing_requirementsF)ensure_asciiindent)r   r   r0  r  r   r   r   weekdayr   r  r?   r   rE  r#   r^  rP  printrC   dumps)t0calr  r  payloads        r   mainrx  N  sO   	B
q
!Cc"Dx&E	##%ghjhrhrhtu#I9yAFLLD[D[\dek\lDmmpssv|  wC  wC  wN  wN  OS  OW  OW  X^  O_  OC  cg  ck  ck  lt  cu  OC  yC  wD   D
 !""
!G, 
$**W5
;<r   __main__)returnr   )rz  rU   )r  N)rG   rU   r<   r   r:   dict | None)rd   N)rV   z	list[str]r<   r   rN   r{  rz  ztuple[int, str, str])r   z
str | None)rb   )r   r   )r  rU   rO  )rG   rU   r<  r   )0__doc__
__future__r   rC   r!   r:  rU  rO   sysurllib.parser?   urllib.requestxml.etree.ElementTreeetreeElementTreer6  r   r   r   pathlibr   zoneinfor   r   homeHOMErT  r   r   r%   r   r-  r   r5   rJ   rP   r   r   r   r  r  r  r0  rA  rP  r^  rx  __name__r   r   r   <module>r     s   
 #  	 	   
   " " 2 2  otyy{==	'''99!'&Awv>U,F;!|0f&R!($0=< zF r   