
    ʱje                        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 d dl	m	Z	m
Z
 d dlmZ d dlmZ d dlmZmZmZ d dlmZmZ d dlmZ d d	lmZmZ d d
lmZmZ d dlm Z!m"Z"m#Z$ d dl%m&Z&m'Z( ejR                  jU                  e+      Z,ejZ                  j]                  dd      Z/ ej`                   e1ejR                  je                  e,d      d            Z3dZ4d\  Z5Z6 G d de      Z7d Z8d Z9d Z:d Z;d Z<d Z=d Z>d Z?d Z@d ZAd-d ZBd! ZCd" ZDd# ZEd$ ZFd% ZG G d& d'e      ZHd( ZI e9         ej                  eId)d*+      j                           ed,eH      j                          y).    N)Path)datetimetimezone)parsedate_to_datetime)
HTMLParser)urljoinurlparseparse_qs)Requesturlopen)ElementTree)BaseHTTPRequestHandlerThreadingHTTPServer)GoogleTranslatorMyMemoryTranslator)ensure_schemabuffer_statushandoff)ensure_post_graphic
public_urlASOL_DBz/var/lib/asol/signals.dbzsources.jsonutf-8encodingzJASOL-Website-Collector/1.1 (+https://sma-asol.agentsolutions-mallorca.com))   gffffff?c                   0     e Zd Z fdZd Zd Zd Z xZS )Pc                 h    t         |           g | _        i | _        d| _        d| _        g | _        y )N F)super__init__linksmetatitlein_titletext)self	__class__s    !/opt/struktur/asol-runtime/app.pyr!   z
P.__init__   s0    rDJR49BV[gi]a]f    c                    t        |      }|dk(  r/|j                  d      r| j                  j                  |d          |dk(  rq|j                  d      s|j                  d      rO|j                  dd      | j                  |j                  d      xs |j                  d      j                         <   |dk(  r0|j                  d	      r| j                  j                  d|d	          |d
k(  rd| _        y y )Nahrefr#   propertynamecontentr   timer   r$   T)dictgetr"   appendr#   lower
setdefaultr%   )r'   tagattrsds       r)   handle_starttagzP.handle_starttag   s    
u+#:!%%-):):1V9)E&=aeeJ/155=}~  ~C  ~C  DM  NP  ~Q499aeeT^N_NpcdchchiocpMwMwMyCz&=QUU:.		0D0DVQz]0['>4=>r*   c                     |dk(  rd| _         y y )Nr$   F)r%   )r'   r7   s     r)   handle_endtagzP.handle_endtag   s    '>4=>r*   c                     | j                   r| xj                  |z  c_        t        dj                  | j                              dk  r*| j                  j                  |j                                y y )N i@  )r%   r$   lenjoinr&   r4   strip)r'   datas     r)   handle_datazP.handle_data    sJ    ==$**,*sxx		"#d*DII,<,<TZZ\,J*r*   )__name__
__module____qualname__r!   r:   r<   rC   __classcell__)r(   s   @r)   r   r      s    j./Kr*   r   c                  b    t        j                  t              } t         j                  | _        | S N)sqlite3connectDBRowrow_factory)cs    r)   dbrP   $   s    oobA1=Qhr*   c                     t        t               t               } | j                  d       dD ]  }| j	                  |dk7  rd| dnd         | j	                  d       | j	                  d      D ch c]  }|d	   	 }}d
D ]  }||vs| j	                  d| d        | j                          | j                          y # t
        j                  $ r Y w xY wc c}w )Na  CREATE TABLE IF NOT EXISTS source_runs(id INTEGER PRIMARY KEY,source_key TEXT,started_at TEXT,finished_at TEXT,status TEXT,found INTEGER DEFAULT 0,stored INTEGER DEFAULT 0,error TEXT, candidate_count INTEGER DEFAULT 0, excluded_count INTEGER DEFAULT 0, dedupe_count INTEGER DEFAULT 0, diagnostics_json TEXT); CREATE TABLE IF NOT EXISTS signals(id TEXT PRIMARY KEY,source_key TEXT,source_name TEXT,url TEXT UNIQUE,title TEXT,summary TEXT,published_at TEXT,discovered_at TEXT,image_url TEXT,image_source TEXT,topics TEXT,company_relevance INTEGER,ai_value INTEGER,automation_potential INTEGER,content_potential INTEGER,score INTEGER,metadata_json TEXT); CREATE TABLE IF NOT EXISTS signal_translations(signal_id TEXT PRIMARY KEY,title_de TEXT NOT NULL,summary_de TEXT NOT NULL,translated_at TEXT NOT NULL,FOREIGN KEY(signal_id) REFERENCES signals(id)); CREATE INDEX IF NOT EXISTS ix_signals_published ON signals(published_at);)candidate_countexcluded_countdedupe_countdiagnostics_jsonrU   z#ALTER TABLE source_runs ADD COLUMN z INTEGER DEFAULT 0z8ALTER TABLE source_runs ADD COLUMN diagnostics_json TEXTa  CREATE TABLE IF NOT EXISTS content_items(id INTEGER PRIMARY KEY AUTOINCREMENT,signal_id TEXT NOT NULL,platform TEXT NOT NULL,title TEXT NOT NULL,body TEXT NOT NULL,image_url TEXT,image_source TEXT,created_at TEXT NOT NULL,updated_at TEXT NOT NULL,UNIQUE(signal_id,platform))z pragma table_info(content_items)   )post_media_urlpost_media_kindpost_media_sourcez%alter table content_items add column z TEXT)	buffer_ensure_schemarL   rP   executescriptexecuterJ   OperationalErrorcommitclose)rO   colrcolsr/   s        r)   initrc   '   s    dAAOO  ~  U .YYX[_qXq<SEAST  xr  s. II  g  h		"DE	F1!A$	FD	FH KtII=dV5IJK HHJ	 ''--	Fs   C2CCCc                 0    dddddj                  | |       S )NLinkedInFacebook	InstagramzReels/TikToklinkedinfacebook	instagramreels)r3   )ps    r)   _platform_labelrn   4   s!    !ZKXfgkklmnoppr*   c                 8   | j                  d      xs | j                  d      xs dj                         }| j                  d      xs | j                  d      xs dj                         }|dk(  r| d| d	S |d
k(  r| d| dS |dk(  r| d| dS | d| dS )Ntitle_der$   z'Aktuelles KI- und Automatisierungsthema
summary_desummaryr   ri   z

u   

Einordnung für Unternehmen: Entscheidend ist, welche konkrete Verbesserung sich für Prozesse, Service oder Produktivität ableiten lässt.

#KI #Automation #AgentSolutionsrj   u   

Was davon ist für Unternehmen praktisch nutzbar? Entscheidend ist die konkrete Anwendung statt reiner Technologie-Schlagzeilen.rk   u   

Technologie wird dann relevant, wenn sie im Alltag messbar Arbeit abnimmt oder bessere Ergebnisse ermöglicht.

#KI #AutomationuM   

Hook: Was davon verändert echte Arbeit – und was bleibt nur Schlagzeile?)r3   rA   )sigplatformr$   rr   s       r)   _draft_bodyru   7   s    77:_#'''"2_6_
f
f
hEWW\">cggi&8>BEEGGWI  &Y  Z  	ZWI  &j  k  	kWI  &k  l  	lWD	!pqqr*   c                    t               }|j                  d| f      j                         }|s|j                          y |j                  d| |f      j                         }|st	        |      }t        j                  t        j                        j                         }t        ||      }t        |j                  d      xs |j                  d      xs d|j                  d      xs |j                  d      xs dd|d	k(  rd
nd|j                  d      xs d      }|j                  d| ||j                  d      xs |j                  d      xs d||j                  d      |j                  d      |j                  d      r|j                  d      ndd|j                  d      r|j                  d      nd||f       |j                          |j                  d| |f      j                         }t	        |      }	|	j                  d      xs dj                         s<t	        |      }t        |j                  d      xs |j                  d      xs d|j                  d      xs |j                  d      xs dd|d	k(  rd
nd|j                  d      xs d      }|j                  d      r|j                  d|j                  d      xs dd|j                  d      xs dt        j                  t        j                        j                         | |f       |j                          |j                  d| |f      j                         }t	        |      }	|d   |	d<   |d   |	d<   |j                          |	S )NzrSELECT s.*,t.title_de,t.summary_de FROM signals s LEFT JOIN signal_translations t ON t.signal_id=s.id WHERE s.id=?z<SELECT * FROM content_items WHERE signal_id=? AND platform=?rp   r$   r   rq   rr   asolrk   4x51x1	image_urlbrandfmt
source_urlzINSERT INTO content_items(signal_id,platform,title,body,image_url,image_source,post_media_url,post_media_kind,post_media_source,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?)image_sourceokurlimagesourcerW   z}UPDATE content_items SET post_media_url=?,post_media_kind=?,post_media_source=?,updated_at=? WHERE signal_id=? AND platform=?	generatedr~   source_name)rP   r\   fetchoner_   r2   r   nowr   utc	isoformatru   r   r3   r^   rA   )
	signal_idrt   rO   rs   rowr9   r   bodymediaouts
             r)   _get_or_create_draftr   B   s7   dA		  O  QZ  P\  ]  f  f  hC		$			PR[\dQefooqC
s)hll3==?SkRST\F]!!%%
"3"KquuW~"KQUUS_M`MzdedidijsdtMzxz  CI  X`  bm  Xm  OT  sx  EF  EJ  EJ  KV  EW  E]  []  ^			  I  KT  U]  ^_  ^c  ^c  dn  ^o  ^G  st  sx  sx  y@  sA  ^G  EG  HL  MN  MR  MR  S^  M_  `a  `e  `e  ft  `u  JO  JS  JS  TX  JY  v{  v  v  @E  vF  _a  cj  CH  CL  CL  MQ  CR  lq  lu  lu  v~  l  XZ  \_  `c  Jd  	e  gh  go  go  gqIITV_`hUijssuS	CGG$%+224
s)!!%%
"3"KquuW~"KQUUS_M`MzdedidijsdtMzxz  CI  X`  bm  Xm  OT  sx  EF  EJ  EJ  KV  EW  E]  []  ^99T?II  V  X]  Xa  Xa  bg  Xh  Xn  ln  pw  y~  yB  yB  CK  yL  y[  P[  ]e  ]i  ]i  jr  jv  jv  ]w  ]A  ]A  ]C  EN  PX  WY  Z  \]  \d  \d  \f		XZcdlYmnwwyC  @D  EH  @I{~%jCS5G#m"4[^T^r*   c                    dd l }| sy| j                  d      xs | j                  d      xs d}| j                  d      xs | j                  d      xs d}|rd	|j                  |       d
nd}d|j                  t        | d                d|j                  t        | d                d|j                  | d          d|j                  | d          d| d|j                  |       d|j                  | j                  d      xs d       d|j                  | j                  d      xs d       d| d   d| d   dS )Nr   z`<!doctype html><html lang="de"><meta charset="utf-8"><body>Entwurf nicht gefunden.</body></html>rW   rz   r   rY   r   u   —z<img id='mediaImg' src='zb' style='max-width:100%;max-height:460px;object-fit:contain;border-radius:8px;background:#0b0e14'>z3<div class='emptyimg'>Keine Grafik vorhanden.</div>z<!doctype html><html lang='de'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>rt   uN  -Beitrag</title><style>body{margin:0;background:#0f1117;color:#e2e8f0;font:14px system-ui}a{color:#8bb4ff;text-decoration:none}.wrap{max-width:1180px;margin:auto;padding:22px}.grid{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(320px,.8fr);gap:18px}.card{background:#1a1d27;border:1px solid #3a4354;border-radius:9px;padding:16px;margin-bottom:14px}h1{font-size:20px}h2{font-size:16px}.tag{display:inline-block;background:#4f8ef722;border:1px solid #4f8ef766;color:#8bb4ff;padding:5px 8px;border-radius:5px;font-weight:700}textarea,input,select{background:#0b0e14;color:#fff;border:1px solid #3a4354;border-radius:7px;padding:9px}textarea{width:100%;min-height:430px;line-height:1.55;font:14px system-ui;resize:vertical}button{background:#4f8ef7;color:#fff;border:0;border-radius:6px;padding:9px 13px;font-weight:700;cursor:pointer}label{display:block;margin:8px 0;color:#cbd5e1;font-size:12px}.meta,.emptyimg{color:#cbd5e1;font-size:12px}@media(max-width:850px){.grid{grid-template-columns:1fr}}</style></head><body><div class='wrap'><div><a href='/'>← Cockpit</a></div><span class='tag'>zG</span><h1>Beitragsentwurf</h1><div class='grid'><div class='card'><h2>r$   z</h2><textarea id='body'>r   z</textarea><p><button onclick='saveDraft()'>Speichern</button> <span id='saveStatus' class='meta'></span></p></div><aside><div class='card'><h2>Grafik / Video</h2>z<div class='meta'>Herkunft: u  </div><button onclick='generateGraphic()' style='margin-top:8px'>Ersatzgrafik erzeugen</button></div><div class='card'><h2>Veröffentlichen / planen (Buffer)</h2><label>Plattform <select id='pubPlatform'><option value='facebook'>Facebook</option><option value='instagram'>Instagram</option><option value='linkedin'>LinkedIn</option></select></label><label>Aktion <select id='pubAction' onchange='toggleDue()'><option value='draft'>Draft</option><option value='queue'>Queue</option><option value='schedule'>Termin</option><option value='now'>Jetzt</option></select></label><label id='dueWrap' style='display:none'>Datum/Uhrzeit <input type='datetime-local' id='dueAt'></label><label>Medientyp <select id='mediaKind'><option value='image'>Bild</option><option value='video'>Video</option></select></label><label>Post/Reel/Story <select id='postType'><option value='post'>Post</option><option value='reel'>Reel</option><option value='story'>Story</option></select></label><label>Link <input id='linkUrl' placeholder='optional' style='width:100%'></label><button onclick='sendBuffer()'>An Buffer senden</button><div id='bufStatus' class='meta'></div></div><div class='card'><h2>Quelle/Fakten</h2><div class='meta'>Quelle: r   z</div><a href='r~   uc   ' target='_blank' rel='noopener'>Quelle öffnen ↗</a></div></aside></div></div><script>const sid=r   z,plat=a  ;document.getElementById('pubPlatform').value=plat==='reels'?'instagram':plat;function toggleDue(){document.getElementById('dueWrap').style.display=document.getElementById('pubAction').value==='schedule'?'block':'none'}function saveDraft(){fetch('/api/draft/save',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({signal_id:sid,platform:plat,body:document.getElementById('body').value})}).then(r=>r.json()).then(d=>document.getElementById('saveStatus').textContent=d.ok?'Gespeichert':(d.error||'Fehler'))}function generateGraphic(){fetch('/api/draft/graphic',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({signal_id:sid,platform:plat})}).then(r=>r.json()).then(d=>{if(!d.ok)alert(d.error||'Fehler');else location.reload();})}function sendBuffer(){let a=document.getElementById('pubAction').value,due=document.getElementById('dueAt').value;if(a==='schedule'&&!due){alert('Datum/Uhrzeit fehlt');return}fetch('/api/draft/buffer',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({signal_id:sid,platform:document.getElementById('pubPlatform').value,body:document.getElementById('body').value,action:a,due_at:due,media_kind:document.getElementById('mediaKind').value,post_type:document.getElementById('postType').value,link_url:document.getElementById('linkUrl').value})}).then(r=>r.json()).then(d=>{document.getElementById('bufStatus').textContent=d.ok?('Buffer-ID: '+d.post_id):('Fehler: '+(d.error||'?'));})}</script></body></html>)htmlr3   escapern   )item_hr   r   imgs        r)   _draft_pager   U   s   z
((#
$
C(=
CE88'(MDHH^,DMF ]b#BIIe$4#5  6X  
Y  h]C U  VX  V_  V_  `o  pt  u  p@  `A  VB  UC  Co  pr  py  py  zI  JN  OY  JZ  z[  p\  o]  ]d  eg  en  en  os  t{  o|  e}  d~  ~W  XZ  Xa  Xa  bf  gm  bn  Xo  Wp  pS  TW  SX  Xt  uw  u~  u~  E  uF  tG  GI.  J.L.  J.S.  J.S.  T.X.  T.\.  T.\.  ].j.  T.k.  T.q.  o.q.  J.r.  I.s.  s.B/  C/E/  C/L/  C/L/  M/Q/  M/U/  M/U/  V/b/  M/c/  M/i/  g/i/  C/j/  B/k/  k/N1  O1S1  T1_1  O1`1  N1c1  c1i1  j1n1  o1y1  j1z1  i1}1  }1NJ  QJ  QJr*   c                 X   | xs dj                         } | syd}	 t        dd      j                  |       xs drt        fd|D              sS 	 t        dd      j                  |       xs drt        fd	|D              sS y# t        $ r Y Ew xY w# t        $ r Y yw xY w)
Nr   )z	Error 500u   That’s an errorzThat's an errorzServer Errorautode)r   targetc              3   &   K   | ]  }|v  
 y wrI    .0xr   s     r)   	<genexpr>ztranslate_de.<locals>.<genexpr>c        1181   zen-GBzde-DEc              3   &   K   | ]  }|v  
 y wrI   r   r   s     r)   r   ztranslate_de.<locals>.<genexpr>h   r   r   )rA   r   	translateany	Exceptionr   )r&   badr   s     @r)   translate_der   ]   s    
*"			DKCF48BB4HNBs1S11#:gW=GGMSQSs1S11#:   
  s#   7B 7B 	BB	B)(B)c           	      >   | j                  d|f      j                         }|r|d   r|d   r
|d   |d   fS t        |      xs d}t        |      xs d}| j                  d|||t        j                  t
        j                        j                         f       ||fS )NESELECT title_de,summary_de FROM signal_translations WHERE signal_id=?rp   rq   %   Übersetzung derzeit nicht verfügbar2   Deutsche Zusammenfassung derzeit nicht verfügbar.zINSERT INTO signal_translations(signal_id,title_de,summary_de,translated_at) VALUES(?,?,?,?) ON CONFLICT(signal_id) DO UPDATE SET title_de=excluded.title_de,summary_de=excluded.summary_de,translated_at=excluded.translated_at)r\   r   r   r   r   r   r   r   )rO   sidr$   rr   r   rp   rq   s          r)   ensure_translationr   m   s    			Y[^Z`ajjlC
s:3|#4:s<000% K$KHG$\(\JII  q  sv  w  @J  KS  KW  KW  X`  Xd  Xd  Ke  Ko  Ko  Kq  rr  sJr*   c                     t        t        | t        dd      t              }|j	                  d      j                  dd      |j                  j                         fS )NzBtext/html,application/rss+xml,application/atom+xml,application/xml)z
User-AgentAccept)headers)timeouti r   ignore)r   r   UATIMEOUTreaddecoder   get_content_type)r   ra   s     r)   fetchr   v   sZ    gc  ?C  $D  E  OV  WA66)##GH5qyy7Q7Q7SSSr*   c                    | sy t        |       j                         } 	 t        j                  | j	                  dd            }|j                   |j	                  t        j                        }|j                  t        j                        j                         S # t
        $ r% t        |       }n# t        t
        f$ r Y Y y w xY wY w xY w)NZz+00:00)tzinfo)strrA   r   fromisoformatreplace
ValueErrorr   	TypeErrorr   r   r   
astimezoner   )valuer9   s     r)   iso_dater   z   s    
e*


E4

 
 s8!<
= 	xx199HLL99<<%//11	  4$U+Q:&3t3 4s5   %B 	C
%B10C
1C C
CC
	C
c                    dD ]f  }t        j                  d|z   dz   |t         j                        }|s1t        |j	                  d            sLt        |j	                  d            c S  dD ]P  }| j
                  j                  |      st        | j
                  |         s8t        | j
                  |         c S  y )N)datePublisheddateCreated"z"\s*:\s*"([^"]+)"rV   )datepublishedzarticle:published_timezog:published_timepubdatepublishdatezsailthru.dater1   date)researchIr   groupr#   r3   )rm   rawkeymks        r)   	date_metar      s    . C
))DH113
=!''!*%hqwwqz.B'BC B M66::a=XaffQi0!&&)9L2LMr*   c                    g }t        j                  |       }|j                  d      |j                  d      z   D ]  fd} |d      }|s1j	                  d      }||j
                  j                  dd      nd}|j                  t        ||       |d       |d	d
d      t         |dddd            d        |S # t         j                  $ r |cY S w xY w)Nz.//itemz.//{*}entryc                      | D ]f  }j                  |      xs j                  d|z         }|-|j                  xs dj                         sL|j                  j                         c S  y)Nz{*}r   )findr&   rA   )namesr/   r   nodes      r)   r&   zxml_items.<locals>.text   s_     S))D/:TYYuTz%:=affl%9%9%;AFFLLN=RS r*   linkz{*}linkr-   r   r$   descriptionrr   r0   pubDate	publishedupdatedr   )r   r$   rr   published_at)
ET
fromstring
ParseErrorfindallr   attribr3   r4   r   r   )r   baser   rootr&   r   r   r   s          @r)   	xml_itemsr      s    
CmmC Y'$,,}*EE 
@	
 &\ii	"A-.]!((,,vb)D

'$t,d7mtTabkluOv  HP  QU  V_  `k  lu  v|  Q}  H~    	@
@ J ==$*$s   C CCc                    t        || d         }|r|S t               }|j                  |       | d   }g }|j                  D ]  }t	        ||      j                  d      d   }t        |      j                  j                         t        |      j                  t        |      j                  k7  s#|j                  d      |j                  d      k(  rj                  d      dk\  st        fddD              r|j                  d|i        t        j                  d |D              D cg c]  }d|i c}S c c}w )	Nr   #r   /   c              3   &   K   | ]  }|v  
 y wrI   r   )r   r   paths     r)   r   zcandidates.<locals>.<genexpr>   s       ,A!AI  ,Ar   )/tag//author//page/z/assets/z/public/
/category/c              3   &   K   | ]	  }|d      yw)r   Nr   )r   r   s     r)   r   zcandidates.<locals>.<genexpr>   s     ,C!QuX,Cs   )r   r   feedr"   r   splitr	   r   r5   netlocrstripcountr   r4   r2   fromkeys)	srcr   
feed_itemsrm   r   r   hur   s	           @r)   
candidatesr      s8   s5z*J*$cA166$<c%jb#WW X
$q/


$Q
'hqk.>.>.D.D.FA;$!6!66!((3-4;;WZK[:[]e::c?a  ,A?  ,A  )A  CF  CM  CM  OT  UV  NW  CXX  $}},Cs,CCD!U1IDDDs   3Ec           	      l   | dz   |z   j                         dj                  |      j                         }g dg dg dd}|j                         D ci c]  \  }}|t        fd|D               }}}t        fd|D              }|d   |d	   |d
   }}
}	t	        ddt	        |	d      dz  z   t	        |
d      dz  z   t	        |d      dz  z   t	        |d      dz  z         }|t	        dd|	dz  z   |dz  z         t	        dd|
dz  z         t	        dd|	|
z   |z   dz  z   |dz  z         |fS c c}}w )Nr>   )aiu   künstkillmgptcopilotagentmodel)

automation	automatisworkflown8nzapiermakeintegrationapimcpvoice)	
enterprisebusinesscrmerp
governance
complianceauditsecurity
backoffice)r   r  companyc              3   &   K   | ]  }|v  
 y wrI   r   r   r   ss     r)   r   zscore.<locals>.<genexpr>   s     "1Q"r   c              3   &   K   | ]  }|v  
 y wrI   r   r  s     r)   r   zscore.<locals>.<genexpr>   s     MeYZaSTfMer   r   r  r  d         	      
               r   )r5   r@   itemssummin)r$   rr   topicstopicsetgroupsr   vhits
topic_hitsr,   brO   	relevancer  s                @r)   scorer4     sI   Sy!ACHHV,<,B,B,D8K  Zw  Ba  bF.4lln	=sq!C"""
"	=D	=#Me^dMeJez
t*T,'YaA#bQq!mC!HRK/Aa;C
1<Ma<OOPISR"WQqS[)#c"QrT'*:3s2qs1ubj=Q[\]Q]C];^_ccc 
>s   D0c                  Z    t                dx} }g }t        D ]  }t        j                  t        j
                        j                         }ddddddd}d}d}d}t               }	|	j                  d|d   |df      j                  }
|	j                          	 g }|j                  d      r|j                  d      gng |j                  d	      r|j                  d	      gng z   |j                  d
g       z   D ]    s	 t               \  }}|dxx   dz  cc<   d	 v rM|t        j                  d|t        j                  t        j                   z        d d D cg c]  }d|i c}z  }n|t#        |       z  } 	 t        |d         \  }}|dxx   dz  cc<   |t'        ||      z  }g }t)               }|D ]L  }|j                  dd      j+                           s& |vs+|j-                          |j/                  |       N t1        |      |d<   |d d D ]   }|d    |j                  dd      }|j                  dd      }|j                  d      }	 t               \  }}|dxx   dz  cc<   t3               }|j5                  |       t        j6                  dd|j8                  j                  d      xs |j:                  xs |      j+                         }t        j6                  dd|j8                  j                  d      xs< |j8                  j                  d      xs |xs dj=                  |j>                              j+                         d d }tA        ||      }|xs |}|stA        ||      }|j8                  j                  d      xs |j8                  j                  d      }|r|s|dxx   dz  cc<   tC         fddD              r|d xx   dz  cc<   tE        |||d!         \  }}}}}tG        |jI                               dk(  r|d xx   dz  cc<   tK        jL                   jO                               jQ                         d d" }	 |	j                  d#||d   |d$    |||t        j                  t        j
                        j                         ||r|d$   nd d%j=                  |d!         ||||tS        ||z   |z   |z   d&z        tU        jV                  d'd(|d)      f       tY        |	|||       |dz  }|	j                          t_        j`                  tb               # 	 |	j                  d-t        j                  t        j
                        j                         ||d   |d   z
  |d    z
  |||d   |d   |d    z   |d*   tU        jV                  |      |
f
       |	j                          |	jg                          | |d   z  } ||z  }|j/                  |d   ||d   ||d   |d    z   |d*   d.        t1        t              | ||d/S c c}w # t$        $ r Y Bw xY w# t$        $ r Y w xY w# t$        $ r Y @w xY w# tZ        j\                  $ r |d*xx   dz  cc<   Y _w xY w# t$        $ r}d+}te        |      d d, }Y d }~ed }~ww xY w)0Nr   )fetchesparse_itemsr   date_missing
irrelevantdeduper   r   zCINSERT INTO source_runs(source_key,started_at,status) VALUES(?,?,?)r   runningrsssitemaparticlesr6  rV   z<loc[^>]*>(.*?)</loc>2   r   r   (   r$   rr   r   z\s+r>   zog:titlezog:descriptionr   i  zog:imageztwitter:imager8  c              3   B   K   | ]  }|j                         v   y wrI   )r5   )r   r   r   s     r)   r   zcollect.<locals>.<genexpr>   s     Z!qAGGI~Zs   )r   r   r   r   r9  r,     a  INSERT INTO signals VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(url) DO UPDATE SET title=excluded.title,summary=excluded.summary,published_at=excluded.published_at,image_url=excluded.image_url,score=excluded.score,metadata_json=excluded.metadata_jsonr/   ,r!  zrss/link+page metadataasol-direct-website)date_source	collectorscore_componentsr:  errori,  zUPDATE source_runs SET finished_at=?,status=?,found=?,stored=?,error=?,candidate_count=?,excluded_count=?,dedupe_count=?,diagnostics_json=? WHERE id=?)r   statusr   storedexcludedr:  )sourcesfoundrJ  runs)4rc   SOURCESr   r   r   r   r   rP   r\   	lastrowidr^   r3   r   r   r   r   Sr   r   r   setrA   addr4   r?   r   r   subr#   r$   r@   r&   r   r   r4  r*  valueshashlibsha256encode	hexdigestroundjsondumpsr   rJ   IntegrityErrorr1   sleepDELAYr   r_   )!totalrJ  rN  r   starteddiagrI  errsavedrO   ridr)  r   _r   uniqueseenr   r$   rr   pubpagerm   page_pubr   scr   autcontr0  r   er   s!                                   @r)   collectrp     s.
   FNE&D 'o	X\\*446XYghxy  HI  ST  >U  ^b  W]  hj  dg  rs  lq  wy  w{  uv  AB  AJ  AJ  KP  RU  V[  R\  ]d  en  Qo  Ap  Az  Az  }@  |}  |D  |D  |F$	@E*-''%.swwu~&b]`]d]den]ocggiFXEYuwx{~  |C  |C  DN  OQ  |R  R '('(ECDOQ$6O A~uBJJOghklnlplpqsququluDvwzxzD{0|q%0|'|u9S#33%'#CJ'Ai!);UjQTUXFY=YUFCEt F%%b/'')$V]]15EF  #6{Ds "u+TXXgb%9u488IVXCY7_c_g_ghv_w[^+ 8FDT)_a%7_13t&&AFFJJz,B,Vagg,VQVW]]_Eikioiopvwz|}  }C  }C  }G  }G  HX  }Y  }U  ]^  ]c  ]c  ]g  ]g  hu  ]v  }U  zA  }U  EH  EM  EM  NO  NT  NT  EU  jW  j]  j]  j_  `d  ad  jeah  py  z{  |@  pA  go  GO  GV  SV  CFIa$6

:.M!&&**_2MCCn)=q)@)=(Z/YZZ\`am\npq\q\ns{$)%H$F#2c$tt{{}%*D,>,A,>8NN188:.88:3B?AII  i  kn  or  sx  oy  z}  ~D  zE  FG  HM  NU  VY  Zb  Zf  Zf  go  gs  gs  Zt  Z~  Z~  Z@  AD  TW  EH  IO  EP  ]a  be  bj  bj  kn  ow  kx  by  z|  }  @C  DH  IN  PR  SU  PU  VY  PY  Z^  P^  `a  Oa  Ib  cg  cm  cm  }U  bw  K	O	  nP	  cQ	  jR	  S	&qU7;1HEahhj

5!%"( 	
		  k  mu  my  my  zB  zF  zF  mG  mQ  mQ  mS  TZ  [_  `l  [m  nr  sA  nB  [B  CG  HT  CU  [U  V[  \_  `d  eq  `r  sw  xF  sG  HL  MY  HZ  sZ  [_  `h  [i  jn  jt  jt  uy  jz  {~  l  	@  BC  BJ  BJ  BL  NO  NU  NU  NW  Y^  `d  eq  `r  Yr  Y^  tz  |A  tA  tz  CG  CN  CN  Y\  ]b  Yc  ms  AE  FR  AS  ]b  nr  sA	  nB	  C	G	  H	T	  C	U	  nU	  _	c	  d	l	  _	m	  On	  Co	O'o	P 'l5&MMA 1} &$& "d" !*(* --@tH~q/@~@?gv3q6$3<s?s   A&Z AX/X*
&X/;Z>-X?+3ZZ$A5ZEY7B+Z#C Y#Z*X//	X<8Z;X<<Z?	YZYZ	YZYZ Z?ZZZ	Z*Z%%Z*c                      t               } | j                  d      D cg c]  }t        |       }}| j                  d      D cg c]  }t        |       }}| j                          ||dS c c}w c c}w )NzSELECT source_key,source_name,COUNT(*) AS signals,MAX(published_at) AS newest FROM signals GROUP BY source_key ORDER BY source_keyzSELECT source_key,status,candidate_count,stored,excluded_count,dedupe_count,finished_at,error FROM source_runs WHERE id IN (SELECT MAX(id) FROM source_runs GROUP BY source_key) ORDER BY source_key)rL  latest_runs)rP   r\   r2   r_   )rO   r   rowsrN  s       r)   read_sourcesrt     s    dA199  .r  $s  ta$q'  tD  t  MN  MV  MV  W]  M^  {_  HI  |@  AB  |C  {_  vz  {_  ab  ah  ah  aj  ~B  QU  sV  lV  t  {_s   A.A3c                       e Zd Zd Zd Zd Zy)Hc           	      N   t        j                  |d      }| j                  d       | j                  dd       | j                  dt	        t        |j                                            | j                          | j                  j                  |j                                y )NF)ensure_ascii   Content-Typezapplication/json; charset=utf-8Content-Length)
r[  r\  send_responsesend_headerr   r?   rX  end_headerswfilewrite)r'   r   r   s      r)   r[  zH.json   s    ZZu-t/A/A#/FHXHXYg  iJ  IK  MQ  M]  M]  ^n  or  sv  w{  wB  wB  wD  sE  oF  MG  IM  IY  IY  I[  ]a  ]g  ]g  ]m  ]m  nr  ny  ny  n{  ]|r*   c           	      	   | j                   j                  dd      d   }|dk(  r| j                  ddt        ddd	       y |d
k(  rt	               }g }|j                  d      D ]d  }t        |      }|j                  d|d   f      j                         }|r
|d   r|d   nd|d<   |r
|d   r|d   nd|d<   |j                  |       f | j                  |       |j                          y |dk(  r| j                  t                      y |j                  d      rot        t        j                  j                  dd            j!                         }||t#        d      d  j%                  d      z  j!                         }t'        |      j                  t'        |            r|j)                         r|j+                         }	| j-                  d       |j.                  j1                         }
ddddddj                  |
d      }| j3                  d |       | j3                  d!t'        t#        |	                   | j5                          | j6                  j9                  |	       y | j-                  d"       | j5                          y |d#k(  r| j                  t;                      y |d$k(  rt=        d| j                   v r| j                   j                  dd      d   nd%      }|j                  d&      xs d%gd   }|j                  d'      xs d(gd   }|d)vrd(}t?        tA        ||            jC                  d*      }| j-                  d       | j3                  d d+       | j3                  d!t'        t#        |                   | j5                          | j6                  j9                  |       y | j-                  d       | j3                  d d+       tE        t        j                   jG                  tH        d,      d*-      jK                         }| j3                  d!t'        t#        |jC                                            | j5                          | j6                  j9                  |jC                                y ).N?rV   r   z/api/healthTrD  Factive)r   runtimerP   mas_connectedrF  z
/api/radarzESELECT * FROM signals ORDER BY score DESC,published_at DESC LIMIT 100r   idrp   r   r$   rq   r   rr   z/api/source-statsz/static/ASOL_STATIC_DIRz/var/lib/asol/staticr   ry  z	image/pngz
image/jpegz
image/webpz	image/gif)z.pngz.jpgz.jpegz.webpz.gifzapplication/octet-streamrz  r{    z/api/buffer/statusz/draftr   r   rt   rj   rh   r   ztext/html; charset=utf-8zcockpit.htmlr   )&r   r   r[  rL   rP   r\   r2   r   r4   r_   rt  
startswithr   osenvironr3   resolver?   lstripr   is_file
read_bytesr|  suffixr5   r}  r~  r  r  r   r
   r   r   rX  openr@   BASEr   )r'   r   rO   rs  ra   r9   trstatic_rootfprB   extmimeqr   rt   r   s                   r)   do_GETzH.do_GET   s   YY__S#A&		?TZ\mr  @H  +I  !J<dADYYfg q'aii(oqrswqxpz{  E  E  G2.0R
^BzNIp'
24L9Ib.  PD)A	
 IIdOQWWY&&		,.(A__Z(RZZ^^,=>TUV^^`KDZ!1299#>>GGIB2w!!#k"23

]]_d&8&8&=299??CTscn  wC  LX  am  u@  \A  \E  \E  FI  Jd  \eVZ  gk  gw  gw  xF  GK  gL  NR  N^  N^  _o  ps  tw  x|  t}  p~  N  AE  AQ  AQ  AS  UY  U_  U_  Ue  Ue  fj  Uk$$S)4+;+;+=''=?)C8^C4994Dtyys1-a0"MATUTYTYZeTfTnkmjnpqSrs~  D  D  EO  P  `  U_  T`  bc  ~dt|JJU_H1#h?@GGPDRVRdRdehRikok{k{  }K  Lf  lg  im  iy  iy  zJ  KN  OR  SW  OX  KY  iZ  \`  \l  \l  \n  pt  pz  pz  p@  p@  AE  pFs#T%5%5nE_%`gklnlslslxlxy}  M  mN  X_  h`  he  he  hgbf  im  iy  iy  zJ  KN  OR  SW  S^  S^  S`  Oa  Kb  ic  ei  eu  eu  ew  y}  yC  yC  yI  yI  JN  JU  JU  JW  yXr*   c           	         | j                   dvr"| j                  d       | j                          y 	 t        | j                  j                  dd            }t        j                  | j                  j                  |      xs d      }|j                  dd      }|j                  dd      }t        |j                  d	d            }| j                   d
k(  rt               }t        j                  |_        |j                  d||f      j!                         }|s%|j#                          | j                  ddd       y t%        |      }t'        |j                  d      xs d|j                  d      xs |j                  d	      xs dd|dk(  rdnd|j                  d      xs d      }	|	j                  d      ru|j                  d|	j                  d      d|	j                  d      t)        j*                  t,        j.                        j1                         ||f       |j3                          |j#                          | j                  dt5        |	j                  d            i|	       y | j                   dk(  r | j                  t7        t8        |             y t               }|j                  d|t)        j*                  t,        j.                        j1                         ||f       |j3                          |j#                          | j                  ddi       y # t:        $ r'}
| j                  dt        |
      d       Y d }
~
y d }
~
ww xY w)N)z/api/draft/save/api/draft/buffer/api/draft/graphicr  r{  0s   {}r   r   rt   r   r  zpselect ci.*,s.summary from content_items ci join signals s on s.id=ci.signal_id where signal_id=? and platform=?FzEntwurf nicht gefunden)r   rH  r$   rr   rw   rk   rx   ry   rz   r{   r   z}update content_items set post_media_url=?,post_media_kind=?,post_media_source=?,updated_at=? where signal_id=? and platform=?r   r   r   r  zMUPDATE content_items SET body=?,updated_at=? WHERE signal_id=? AND platform=?T)r   r|  r~  intr   r3   r[  loadsrfiler   r   rP   rJ   rM   rN   r\   r   r_   r2   r   r   r   r   r   r   r^   boolbuffer_handoffrL   r   )r'   nrB   r   rm   r   rO   r   r9   r   ro  s              r)   do_POSTz	H.do_POST   sY   99XXZ^ZlZlmpZqsw  tD  tD  tF  HN	F$,,""#3C89A

4::??[\K]Kfaf@g4mqmumu  wB  CE  nFil  JN  JR  JR  S]  ^`  Ja  HI  hk  lp  lt  lt  u{  |~  l  h@  cgyy..$gkkqyy  Bt  vy  z{  u|  8}  8F  8F  8H3AGGItyyuE]1^'_ags)#6quuW~7KQUUS\M]MtabafafgmanMtrt  }C  RS  U`  R`  IN  fk  xy  x}  x}  ~I  xJ  xP  NP  $QU99T?II  ^  `e  `i  `i  jo  `p  qx  y~  yB  yB  CK  yL  MU  MY  MY  Zb  Zf  Zf  Mg  Mq  Mq  Ms  tw  xy  _z  {  }~  }E  }E  }G	499d4		$+@%JE%JKVyy--tyy49P/QSYdAAIImost|  uA  uA  BJ  BN  BN  uO  uY  uY  u[  \_  `a  ob  c  ef  em  em  eo  qr  qx  qx  qz  |@  |E  |E  GK  LP  FQ  |REtyyuSV)DEEEs,   DL$  D1L$ 2.L$ !BL$ $	M-MMN)rD   rE   rF   r[  r  r  r   r*   r)   rv  rv     s    |X2Fr*   rv  c                  b    	 t                t        j                  d        # t        $ r Y !w xY w)Ni  )rp  r   r1   r^  r   r*   r)   background_collectorr    s'    
Y

3 $s   
" 	..zasol-collectorT)r   r/   daemon)z	127.0.0.1iOI  )r   )MrV  r[  r  r   rJ   r1   	threadingpathlibr   r   r   email.utilsr   html.parserr   urllib.parser   r	   r
   urllib.requestr   r   	xml.etreer   r   http.serverr   r   deep_translatorr   r   buffer_supportr   rZ   r   r   r  media_pipeliner   r   media_public_urlr   dirname__file__r  r  r3   rL   loadr  r@   rO  r   r   r_  r   rP   rc   rn   ru   r   r   r   r   r   r   r   r   r   r4  rp  rt  rv  r  Threadstartserve_foreverr   r*   r)   <module>r     se   6 6 6 6  ' - " 4 4 + ' C @ j j N	wwx ZZ^^I9:
$))DdN;gN
OQK
 K?q	r_&QJ T	2"Ed*NXV)F )FV 	 4:JRVW]]_at  vI  JK  bL  bZ  bZ  b\r*   