
    \j=-                        S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKrSSK	r	SSK
r
\" \5      R                  5       R                  R                  r\S-  r\S-  S-  S-  r\R"                  R%                  S\" \" \5      R                  5       R                  5      5        SSKJr  S/rS	rS
rSrS rS\\\4   S-  4S jrSS jrSS jrS\4S jr \!S:X  a  \RD                  " \ " 5       5        gg)u?  
Tribunale dei tipster — collector Telegram (via Telethon, account utente).

Legge i canali configurati (anche privati/VIP a cui il TUO account è iscritto,
per ID numerico o @username), salva i messaggi nuovi in telegram_messages e
poi estrae le pick con l'LLM nella tabella tips (stesso vocabolario e stesso
scoring del resto del tribunale). Il timestamp della pick è quello ESATTO di
pubblicazione del messaggio Telegram: il migliore possibile per il CLV.

Setup una tantum (solo la prima volta, va fatto dal proprietario dell'account):
  1. Prendi api_id e api_hash su https://my.telegram.org -> API development tools
     e aggiungili al file .env:
         TELEGRAM_API_ID=1234567
         TELEGRAM_API_HASH=abcdef...
  2. Esegui:  python scripts/telegram_collector.py --login
     (ti chiede il numero di telefono e il codice che arriva su Telegram;
      la sessione resta salvata in telegram.session e non serve più)

Uso quotidiano (automatizzabile):
    python scripts/telegram_collector.py
    python scripts/telegram_collector.py --no-extract   # solo raccolta messaggi
    N)Pathtelegramdataraw)load_api_keylc
!zclaude-opus-4-8a  
CREATE TABLE IF NOT EXISTS telegram_messages (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    channel_id  BIGINT       NOT NULL,
    msg_id      BIGINT       NOT NULL,
    tipster_id  SMALLINT UNSIGNED NULL,
    sent_at     DATETIME     NOT NULL,
    text        TEXT         NULL,
    has_media   TINYINT(1)   NOT NULL DEFAULT 0,
    processed   TINYINT(1)   NOT NULL DEFAULT 0,
    UNIQUE KEY uq_msg (channel_id, msg_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
u  Questo è un messaggio di un canale Telegram di pronostici
calcistici. Se contiene UNA O PIÙ pick concrete PRE-partita (partita
identificabile + selezione precisa, con o senza quota), estraile. Ignora:
resoconti di vincite, promozioni, chiacchiere, schedine già giocate/risultati.

Rispondi SOLO con un blocco ```json```:
{"picks": [
  {"home": "...", "away": "...", "kickoff": "YYYY-MM-DD HH:MM" o null,
   "raw": "testo esatto della pick",
   "market": "1x2"|"double_chance"|"over_under"|"btts"|"multigol_total"|"multigol_home"|"multigol_away"|"other",
   "selection": "...", "line": null o 2.5, "odds": null o 1.85}
]}
Se non ci sono pick: {"picks": []}. Non inventare quote né partite.
ATTENZIONE alle schedine MULTIPLE (più partite con una quota complessiva):
estrai le singole selezioni solo se ciascuna ha la PROPRIA quota; altrimenti
estraile con odds null. Non attribuire MAI la quota complessiva della
schedina a una singola selezione.
Se è allegata un'immagine (screenshot di schedina), leggi le pick dall'immagine
con le stesse regole; se immagine e testo ripetono la stessa pick, estraila
una volta sola.

MESSAGGIO (inviato il {sent_at}):
c                     [         R                  " U R                  U R                  U R                  U R
                  SS9$ )N	tigertips)hostportuserpassworddatabase)pymysqlconnectr
   r   r   r   )argss    5C:\wamp64\www\Tigertips\scripts\telegram_collector.py
db_connectr   Z   s0    ??						$(MMKI I    returnc                     SS K n 0 n[        S-  nUR                  5       (       aa  UR                  5       R	                  5        H?  nSU;   d  M  UR                  SS5      u  pEUR                  5       XR                  5       '   MA     U R                  R                  S5      =(       d    UR                  S5      nU R                  R                  S5      =(       d    UR                  S5      nU(       a  U(       a  [        U5      U4$ g )Nr   z.env=   TELEGRAM_API_IDTELEGRAM_API_HASH)
osPROJECT_ROOTexists	read_text
splitlinessplitstripenvirongetint)r   valuesenv_filelinekvapi_idapi_hashs           r   load_tg_credentialsr,   _   s    Ff$H&&(335Dd{zz#q)$%GGIwwy! 6 ZZ^^-.O&**=N2OFzz~~12UfjjAT6UH(6{H$$r   c                   #    SSK Jn  [        5       nUc  [        S5        g Uu  p4[	        U 5      nUR                  5       nUR                  [        5        UR                  5         U" [        [        5      X45      nUR                  5       I S h  vN   [        S5        U R                  (       a$  [        S5        UR                  5       I S h  vN   g [         GH  nUR                  U5      I S h  vN n	[!        U	S[        U5      5      n
UR                  SU
S S S	U 345        UR                  5         UR                  S
S	U 345        UR#                  5       S   nUR                  S[%        U[&        5      (       a  ['        U5      OS45        UR#                  5       S   nSnUR)                  U	['        U5      U R*                  S9  S h  vN nUR                  S[%        U[&        5      (       a  ['        U5      OU	R,                  UR,                  XR.                  R1                  S S9UR2                  =(       d    SUR4                  (       a  SOS45        XR6                  S:  -  nM     UR                  5       I S h  vN   URK                  5         g  GN GN GN N
 UR                  5         [        SU
 SU S35        [8        R;                  SSS9  [%        U[&        5      (       a  ['        U5      OU	R,                  nUR                  SU45        UR=                  5        Vs/ s H  n['        US   5      PM     Os  snf nnU Vs/ s H)  n[8        U SU S3-  R?                  5       (       a  M'  UPM+     Os  snf nnSn[A        S[C        U5      S5       H  nUUUS-    nURE                  U	US9I S h  vN   H\  nU(       d  M  URF                  (       d  M  URI                  [        [8        U SUR,                   S3-  5      S9I S h  vN    US-  nM^     M     U(       d  GMZ  [        SU
 SU S[C        U5      U-
   S35        GM~   GN7f)Nr   )TelegramClientz_Mancano TELEGRAM_API_ID / TELEGRAM_API_HASH nel file .env (prendili su https://my.telegram.org)zConnesso a Telegram.zDLogin completato: sessione salvata. Ora puoi eseguire senza --login.titlezQINSERT IGNORE INTO tipsters (name, source_url, notes) VALUES (%s, %s, 'telegram')2   ztg:z-SELECT id FROM tipsters WHERE source_url = %szLSELECT COALESCE(MAX(msg_id), 0) FROM telegram_messages WHERE channel_id = %s)min_idlimitz
                INSERT IGNORE INTO telegram_messages
                    (channel_id, msg_id, tipster_id, sent_at, text, has_media)
                VALUES (%s, %s, %s, %s, %s, %s)
            )tzinfo r   z  z: z messaggi nuoviT)parentsexist_okz
            SELECT msg_id FROM telegram_messages
            WHERE channel_id = %s AND has_media = 1 AND processed = 0
        _.jpg)ids)filez: scaricate z immagini (z media non-foto))&telethonr.   r,   printr   cursorexecuteSCHEMAcommitstrSESSION_PATHstartlogin
disconnectCHANNELS
get_entitygetattrfetchone
isinstancer$   iter_messagesmax_messagesiddatereplacetextmediarowcount	MEDIA_DIRmkdirfetchallr   rangelenget_messagesphotodownload_mediaclose)r   r.   credsr*   r+   conncurclientchannelentityr/   
tipster_idlast_idn_newmsgchan_keyrwantmidmissingn_imgbatch_startbatchms                           r   collectro   o   s    '!E} 6 	7FdD
++-CKKKKMC-v@F
,,.	
 !zzTU!!!8((11W6 23BZ3wi1	3 	CG9oEWX\\^A&
 ,>HRU>V>Vc'l\]-_	a,,.#--fS\484E4E . G 		&#KK  #-Wc":":#g,		&&*hh&6&6d&6&C((.bsyy!a9	: \\A%%E1 d 


JJLu  	" 2		& G 	5'E7/23 	t4#-gs#;#;3w<  [	 $'<<>2>aAaD	>22"& J$3$(1SE'>>FFH $ J J CL"5KKb(89E!..v5.AAA1** z144&-E!EF + H H HQJE	 B 6 7Bug\% 1'lU*++;= > s   BQJ>QJ#Q2J!3CQJ&J$J&B1QQQQ!Q$J&&BQ.MQ&N<N>Q OQQ%2QP
Q4%Qc                 f   [        5       nU(       d  [        S5        g [        R                  " US9n[	        U 5      nUR                  5       nUR                  SU R                  45        UR                  5       n[        S[        U5       35        SnSnU GH  u  pppnU=(       d    Sn[        U SU S3-  n/ nU(       ad  UR                  5       (       aO  SS KnUR                  UR                  5       5      R                  5       nUR!                  S	S
SUS.S.5        US-  nO4[        U5      S:  a%  UR                  SU45        UR#                  5         M  [$        R'                  S[)        U
5      5      US S -   nUR!                  SUS.5        UR*                  R-                  U R.                  SSUS./S9nSR1                  S UR2                   5       5      n[4        R6                  " SU[4        R8                  5      nU(       a  UR;                  S5      O%UUR=                  S5      UR?                  S5      S-    n [@        RB                  " U5      RE                  S5      =(       d    / nU H  n[I        U[J        5      (       a  UO0 nUR                  SU	SU 3U
RM                  5       URE                  S 5      URE                  S!5      URE                  S"5      URE                  S#5      URE                  S$5      URE                  S%5      URE                  S&5      URE                  S'5      =(       d    SS S( 45        US-  nM     UR                  SU45        UR#                  5         GM     [        S)U S*U S+35        URO                  5         g ! [@        RF                   a    / n GN=f = f),Nz+Manca ANTHROPIC_API_KEY: estrazione saltata)api_keyz
        SELECT id, tipster_id, sent_at, text, channel_id, msg_id, has_media
        FROM telegram_messages
        WHERE processed = 0
          AND (CHAR_LENGTH(COALESCE(text, '')) >= 25 OR has_media = 1)
        ORDER BY sent_at LIMIT %s
    zMessaggi da esaminare: r   r4   r7   r8   imagebase64z
image/jpeg)type
media_typer   )rt   sourcer      z8UPDATE telegram_messages SET processed = 1 WHERE id = %sz	{sent_at}i  rP   rt   rP   i  r   )rolecontent)model
max_tokensmessagesc              3   \   #    U  H"  oR                   S :X  d  M  UR                  v   M$     g7f)rP   Nrx   ).0bs     r   	<genexpr>extract.<locals>.<genexpr>   s!     K&6&&F:Jfaff&6s   ,,z```json\s*(\{.*?\})\s*```{}picksa<  
                INSERT IGNORE INTO tips
                    (tipster_id, article_url, published_date, scraped_at,
                     home_team, away_team, kickoff, market, selection, line,
                     odds, raw_text)
                VALUES (%s, %s, %s, NOW(), %s, %s, %s, %s, %s, %s, %s, %s)
            ztg-msg:homeawaykickoffmarket	selectionr'   oddsr   i,  zPick estratte: z# (messaggi con immagine esaminati: ))(r   r<   	anthropic	Anthropicr   r=   r>   max_extractrU   rW   rS   r   rs   standard_b64encode
read_bytesdecodeappendr@   EXTRACT_PROMPTrO   rA   r}   creater{   joinrz   researchDOTALLgroupfindrfindjsonloadsr#   JSONDecodeErrorrJ   dictrN   r[   )r   rq   r_   r]   r^   rowsn_picksrk   msg_pkrb   sent_atrP   
channel_idmsg_id	has_media
image_pathrz   rs   r   promptresponseoutrn   r   r   ptips                              r   extractr      sJ   nG;<  1FdD
++-CKK  

	 <<>D	#CI;
/0GELPHG:yzrJ<q!==
**,,,,Z-B-B-DELLNDNNG/75A4'QR S QJEY^KKR	#KKM''S\BT%4[P78??))

t=CPW4X3Y * [ggKh&6&6KKII2CCaggaj3sxx}SYYs^a5G#H	JJsO''06BE A!!T**!CKK  x0',,.''&/3776?CGGI4F''(#SWW[%93776?''&/CGGEN$8b$3#?A	B qLG  	NI	W MQX 
OG9$Gwa
PQJJL' ## 	E	s   .NN0/N0c                     [         R                  " SS9n U R                  SSSS9  U R                  SSS9  U R                  S	[        S
SS9  U R                  S[        SS9  U R                  S[        S9  [
        R                  " U 5        U R                  5       n[        R                  " [        U5      5        UR                  (       d  UR                  (       d  [        U5        g)Nz/Collector Telegram per il tribunale dei tipster)descriptionz--login
store_truezSolo login interattivo iniziale)actionhelpz--no-extract)r   z--max-messages   z"Max messaggi per canale a raccolta)rt   defaultr   z--max-extractr0   )rt   r   z--model)r   r   )argparseArgumentParseradd_argumentr$   DEFAULT_MODELconfigadd_db_args
parse_argsasynciorunro   rD   
no_extractr   )parserr   s     r   mainr     s    $$1bcF
	,>  @
|<
(sCA  C
c2>
	=9
vDKK::door   __main__)r   N)#__doc__r   r   r   r   syspathlibr   r   r   r   __file__resolveparentr   rB   rS   pathinsertrA   agent_formazionir   rF   r   r?   r   r   tupler$   r,   ro   r   r   __name__exit r   r   <module>r      s  .    	 
    H~%%'..55j(6!E)J6	 3tH~--/667 8 )  "
2I
U38_t3  JZBJc $ zHHTV r   