
    dj#                         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rSrSr " S S\	5      r
 " S S\	5      rS	 rS
 rS rS rSrSS jrS rSS jrSrSrS r\S:X  a  \" 5         gg)uc   Сбор постов feedwatch (Instagram: Apify/Meta Graph API; Telegram: web/TGStat) → SQLite.    NzPhttps://api.apify.com/v2/acts/apify~instagram-scraper/run-sync-get-dataset-itemsz(https://graph.facebook.com/v21.0/{ig_id}c                       \ rS rSrSrSrg)TokenExpiredError   uN   Meta Graph API вернул код 190 — long-lived токен протух. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       /home/rasp/feedwatch/fetch.pyr   r      s    Xr   r   c                       \ rS rSrSrSrg)ConfigError   uB   Не хватает обязательного ключа в .env.r   Nr   r   r   r   r   r      s    Lr   r   c                    U Vs/ s H  o R                  U5      (       a  M  UPM     nnU(       d  g [        U5      S:X  a  [        SR                  US   5      5      e[        SR                  SR	                  U5      5      5      es  snf )N   uW   Не найден {} в .env — заполни его по образцу .env.exampler   uW   Не найдены {} в .env — заполни их по образцу .env.examplez, )getlenr   formatjoin)envkeyskmissings       r   _require_envr      s    1$Qggajq$G1
7|qellmtuvmwx
 	
 ahhimirirszi{|  2s
   BBc                    U R                  S5      nUb  US:  a  S nU S   U S   R                  5       U R                  S5      =(       d    SU S   R                  SS	5      UU R                  S
5      U R                  S5      =(       d    U R                  S5      U R                  S5      =(       d    SR                  U S   5      S.$ )N
likesCountr   	shortCodeownerUsernamecaption 	timestampZz+00:00commentsCountvideoPlayCountvideoViewCounturlzhttps://www.instagram.com/p/{}/post_idaccountr"   	posted_atlikescommentsviews	permalink)r   lowerreplacer   )itemr.   s     r   normalize_apifyr5   %   s    HH\"EUQY$(..088I&,"+&..sH=HH_-*+Itxx8H/IXXe_ T9@@kARS
 
r   c           	         U  Vs/ s H  nSR                  U5      PM     snSUS.n[        R                  " [        SU0USS9nUR	                  5         / 0 pvUR                  5        Hu  nUR                  S5      (       a:  [        US   5      U[        UR                  SS	5      5      R                  5       '   MS  S
U;  a  M[  UR                  [        U5      5        Mw     U V	s1 s H  oS   iM	     n
n	U  HA  nUR                  5       U
;  d  M  UR                  5       U;  d  M/  SXsR                  5       '   MC     Xg4$ s  snf s  sn	f )Nzhttps://www.instagram.com/{}/posts)
directUrlsresultsTyperesultsLimittokeniX  )paramsjsontimeouterrorusername?r    r,   uR   нет данных (закрыт / переименован / не найден?))r   requestspost	APIFY_URLraise_for_statusr=   r   strr2   appendr5   )accountslimitr;   apayloadresprecordserrorsr4   rgots              r   fetch_apifyrQ   6   s&   JRS(Q6==a@(SG
 ==GU+;'SVWD"V		88G=@g=OF3txx
C01779:d"t,-  ")
)AY<C
)779CAGGIV$; tF779  ?% T *s   D>$Ec           	          US   U R                  5       UR                  S5      =(       d    SUS   UR                  S5      UR                  S5      S US   S.$ )	Nidr"   r#   r$   
like_countcomments_countr1   r*   )r2   r   )r,   medias     r   normalize_graphrW   M   sY    ;==?99Y'-2;'<(II./;'	 	r   z,https://graph.facebook.com/v21.0/debug_tokenc                 N   Ub  UO[         R                   " 5       n [        R                  " [        X S.SS9R	                  5       nUR                  S5      =(       d    0 R                  S5      nU(       d  g[        X1-
  S-  5      $ ! [        R
                  [        4 a     gf = f)u  Сколько дней осталось токену Meta. None — бессрочный или не выяснили.

Токен на 60 дней сам не продлевается: протухнув, он не роняет прогон, а
тихо перестаёт отдавать чужие аккаунты. Поэтому спрашиваем срок заранее.
Сама проверка сервисная — её сбой не должен мешать сбору данных.
N)input_tokenaccess_token   r<   r>   data
expires_atiQ )timerB   r   DEBUG_TOKEN_URLr=   RequestException
ValueErrorint)r;   nowrK   r^   s       r   token_days_leftre   ]   s     #diikC,, 89BDFFJdf 	 ++f%+00>J
 U*++ %%z2 s   *B B$#B$c                 ^  ^ / 0 pTU  H  mSR                  TU5      n[        R                  " [        R                  US9XcS.SS9n UR	                  5       nSU;   aZ  US   n	U	R                  S5      S	:X  a  [        U	R                  S
S5      5      eU	R                  S
S5      UTR                  5       '   M  UR                  S0 5      R                  S0 5      R                  S/ 5      n
UR                  U4S jU
 5       5        M     XE4$ ! [
         a    SUTR                  5       '    GM$  f = f)Nznbusiness_discovery.username({}){{media.limit({}){{id,caption,like_count,comments_count,permalink,timestamp}}}})ig_id)fieldsrZ   <   r\   u(   не-JSON ответ от Meta Graph APIr?   code   messageztoken expiredu#   неизвестная ошибкаbusiness_discoveryrV   r]   c              3   <   >#    U  H  n[        TU5      v   M     g 7fN)rW   ).0mr,   s     r   	<genexpr>fetch_graph.<locals>.<genexpr>   s     BEqw22Es   )	r   rB   r   	GRAPH_URLr=   rb   r2   r   extend)rH   rI   rg   r;   rM   rN   rh   rL   r]   errrV   r,   s              @r   fetch_graphrw   p   s'   "VSF7E* 	 ||I,,5,9.4#L$&(	99;D d?w-Cwwv#%'	?(KLL&)ggi9^&_F7==?#-r266wCGGPRSBEBB' ( ?  	&PF7==?#	s   D

D,+D,c           
      ^   U=(       d    [         R                  " 5       nU=(       d    [         R                  " 5       nU=(       d    [         R                  " 5       nUR	                  S5      =(       d    0 nUR	                  S5      =(       d    0 nUR	                  S5      (       d!  UR	                  S5      (       d  [        S5      e/ 0 pUR	                  S5      (       a  US   n	 UR	                  SS5      S:X  a  [        US/5        [        XUS   5      u  pO$[        US	S
/5        [        XUS
   US	   5      u  p Xz-  n[         R                  " X:5        U	 HM  nUR                  5       nUR	                  U5      USU4'   [         R                  " X=UR	                  U5      S9  MO     UR	                  S5      (       a  US   nUR	                  SS5      S:X  a  [        R                   " X5      u  pnO)[        US/5        [        R"                  " XUS   US9u  pnXz-  n[         R                  " X:5        U H_  nUR                  5       nUR	                  U5      USU4'   [         R                  " UUUR	                  U5      SUR	                  U5      S9  Ma     XxR%                  5        VVs0 s H  u  nnU(       d  M  UU_M     snn4$ ! [        R                   aC  n/ U	 Vs0 s H#  nUR                  5       SR                  U5      _M%     Os  snf nnn
 S nAGNS nAff = fs  snnf )N	instagramtelegramrH   channelsu   В config.json не настроена ни одна платформа — заполни секцию instagram и/или telegram по образцу config.example.jsonsourceapifyAPIFY_TOKENIG_ACCESS_TOKENIG_BUSINESS_IDu"   Instagram недоступен: {})r?   webTGSTAT_TOKEN)subscribers)r?   platformr   )commonload_configload_envconnectr   r   r   rQ   rw   rB   ra   r2   r   
save_postsset_account_statusfetch_tg	fetch_webfetch_tgstatitems)rI   cfgr   conr   igtgrM   rN   rH   recserrsexcrJ   r{   subscr   vs                      r   	run_fetchr      s   

%##%C

""C

!!C			#B			"B66*bffZ&8&8 D E 	E "V	vvjj>	0vvh(G3S=/2(#m:LM
dS#46F"GH(),-=)>DU@VX
d 	#$A	A'+xx{FK#$%%cDHHQK@  
vvjj>66(E"e+'11(BD~./'44X585HAL ND 	#$A	A&*hhqkFJ?#%%c1DHHQK/9txxPQ{T 
 lln:ndaTQTn:::5 (( 	0&.0&.  ggi)M)T)TUX)YY&.0$ 0D$	04 ;s6   %4K #K 1L)L)L&#L!(*L	L!!L&u   ⚠️ feedwatch: токен Meta Graph API протух (он живёт 60 дней).
Скажи Claude: «обнови токен инстаграма» — он проведёт по шагам.u   ⚠️ Не удалось собрать данные — проблема с сетью или источником. Проверь .env и подключение.c                     [         R                  " SS9n U R                  S[        SSS9  U R	                  5       n [        UR                  5      u  p#[        S	R%                  ['        W5      5      5        WR)                  5        H0  u  u  pVn[        S
R%                  XVU5      [        R                  S9  M2     g ! [         a5    [        [        [        R                  S9  [        R                  " S5         N[         aA  n[        [        U5      [        R                  S9  [        R                  " S5         S nANS nAf[        R                    a6    [        ["        [        R                  S9  [        R                  " S5         GN7f = f)Nu+   Сбор постов в базу feedwatch)descriptionz--limit   uL   постов на аккаунт (30 для холодного старта))typedefaulthelp)filer   u#   Сохранено постов: {}u   ⚠️ [{}] @{}: {})argparseArgumentParseradd_argumentrc   
parse_argsr   rI   r   printTOKEN_EXPIRED_MSGsysstderrexitr   rF   rB   ra   FETCH_ERROR_MSGr   r   r   )apargsrM   rN   r   r   rJ   es           r   mainr      s   		 	 -Z	[BOOICg  i==?D
#DJJ/ 

/
6
6s7|
DE"LLNq#**8:L +  cjj1 c#hSZZ($$ oCJJ/s$   B; ;<F9	F7D>>A	F
F__main__ro   )NNNF)r   r   r   r_   rB   r   r   rD   rt   	Exceptionr   r   r   r5   rQ   rW   r`   re   rw   r   r   r   r   r   r   r   r   <module>r      s    i  
    *	6	Y	 YM) M
".
 A,&2/;fu 5 M* zF r   