
    iY                       d Z ddlmZ ddlZddlZddlmZ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mZmZ d
ZddZddZdddZ G d d      ZddZddZddZ ddZ!ddZ"e#dk(  r e"        yy# e$ r dZY Bw xY w)uS   AIO Tracker: AI 검색엔진별 유입 트래픽 Before/After 변화 자동 계산.    )annotationsN)date	timedelta)Path)DictListOptional)classify_ai_sourceis_ga4_configured)BetaAnalyticsDataClient)	DateRange	DimensionMetricRunReportRequestTFc                   t        |       } | j                         st        d|        i }| j                  dd      5 }t	        j
                  |      }|j                  xs g }t        d |D        d      }|t        d|        |D ]L  }||   j                         }t        |d   j                               }|s5|j                  |d	      |z   ||<   N 	 ddd       |S # 1 sw Y   |S xY w)
u   CSV를 파싱해 {referrer: sessions} 반환. 컬럼: 'referrer' 또는 'source'.

    Raises:
        FileNotFoundError: 파일 미존재
        ValueError: 필수 컬럼 없음
    u'   CSV 파일을 찾을 수 없습니다: utf-8 )encodingnewlinec              3  b   K   | ]'  }|j                         j                         d v s$| ) yw))referrersourceN)striplower).0cs     P/home/jay/workspace/.worktrees/task-2116-dev1/tools/geo-analytics/aio_tracker.py	<genexpr>zparse_csv.<locals>.<genexpr>*   s%     ]a1BF\1\]s   %//Nu:   CSV에 'referrer' 또는 'source' 컬럼이 없습니다: sessionsr   )r   existsFileNotFoundErroropencsv
DictReader
fieldnamesnext
ValueErrorr   intget)	pathresultfreaderr%   ref_colrowkeyr   s	            r   	parse_csvr1      s     :D;;="I$ PQQF	GR	0 
<A"&&,"
]:]_cd?YZ^Y_`aa 	<Cg,$$&C3z?0023H$jja08;s		<
< M
< Ms   A?C$?C$$C.c                $    | dk(  ry|| z
  | z  dz  S )uL   변화율 계산: (after - before) / before * 100. before=0이면 None(NEW).r   Nd    )beforeafters     r   calculate_change_rater7   5   s     {FNf$s**    c                    |rd| dnd}d| ddddg}| D ]F  }|d   }|d	}n|d
k\  rd|dd}n|dd}|j                  d|d    d|d    d|d    d| d	       H dj                  |      S )uE   AI 소스 요약을 마크다운 리포트 문자열로 변환한다.z ()r   u   # AIO 성과 리포트u   ## AI 유입 트래픽 변화u'   | 소스 | Before | After | 변화율 |z"|------|--------|-------|--------|change_rateNEWr   +z.1f%z| r   z | r5   r6   z |
)appendjoin)summary
date_label
title_datelinesr/   raterate_strs          r   generate_markdown_reportrH   <   s    '12j\#rJ
 -
'1,E  ]=!<HQY4*AHs1~Hr#h-CM?#c'l^3xjXZ[\] 99Ur8   c                  >    e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 ddZddZy)
AioTrackeru8   AI 검색엔진 유입 트래픽 Before/After 분석기.Nc                *   || _         |r#|r!t        |      | _        t        |      | _        y |rWt        rQt               rG|xs
 t               \  }}|xs
 t               \  }}	t        |||      | _        t        |||	      | _        y i | _        i | _        y N)	property_idr1   before_data
after_data_GA4_AVAILABLEr   _default_before_range_default_after_range_fetch_ga4_referrers)
self
before_csv	after_csvrM   before_rangeafter_rangeb_startb_enda_starta_ends
             r   __init__zAioTracker.__init__U   s     ')(4D'	2DO^0A0C)D-B-DNGU(B,@,BNGU3K%PD2;ODO!D DOr8   c           
        i }i }| j                   j                         D ].  \  }}t        |      }|dk7  s|j                  |d      |z   ||<   0 | j                  j                         D ].  \  }}t        |      }|dk7  s|j                  |d      |z   ||<   0 g }t        t        |      t        |      z        D ]F  }|j                  |d      }|j                  |d      }	|j                  |||	t        ||	      d       H |S )uE   Before/After를 AI 소스별로 집계. 기타(비-AI) 소스 제외.u   기타r   )r   r5   r6   r;   )	rN   itemsr
   r)   rO   sortedsetr@   r7   )
rT   	ai_beforeai_afterrefssrcr+   r   r5   r6   s
             r   compute_ai_summaryzAioTracker.compute_ai_summaryj   s   $&	#%&&,,. 	;FC$S)Ch!*sA!6!:	#	; oo++- 	9FC$S)Ch (S! 4q 8	9 S^c(m;< 
	F]]61-FLL+EMM$$"#8#G	
	 r8   )NNr   NN)
rU   Optional[Path]rV   rh   rM   strrW   Optional[tuple]rX   rj   )return
List[Dict])__name__
__module____qualname____doc__r]   rg   r4   r8   r   rJ   rJ   R   sP    B &*$((,'+!"! "! 	!
 &! %!*r8   rJ   c                     t        j                         } | t        | j                         dz         z
  }|t        d      z
  j	                         |j	                         fS N   )days   r   todayr   weekday	isoformat)rw   ends     r   rQ   rQ      sK    JJLE
)1!45
5C)##..0#--/AAr8   c                     t        j                         } | t        | j                         dz         z
  }|t        d      z   }|j	                         |t        d      z   j	                         fS rr   rv   )rw   rz   starts      r   rR   rR      s[    JJLE
)1!45
5C)##E??uya'88CCEEEr8   c           	     |   t         si S t               }t        d|  t        d      gt	        d      gt        ||      g      }|j                  |      }i }|j                  D ]S  }|j                  d   j                  }|j                  |d      t        |j                  d   j                        z   ||<   U |S )u,   GA4 Data API로 소스별 세션 수 조회.zproperties/sessionSource)namer   )
start_dateend_date)property
dimensionsmetricsdate_rangesr   )rP   r   r   r   r   r   
run_reportrowsdimension_valuesvaluer)   r(   metric_values)	rM   r   r   clientrequestresponser+   r/   rf   s	            r   rS   rS      s    	$&F{m,?34Z()*xHI	G   )HF}} K""1%++jja(3s/@/@/C/I/I+JJsK Mr8   c                8   t        j                  d      }|j                  dd       |j                  ddd       |j                  d	dd       |j                  d
d       |j                  dd       |j                  dd       |j                  |       S )Nu4   AI 검색엔진 유입 트래픽 Before/After 분석)descriptionz--property-idr   )defaultz--beforezYYYY-MM-DD:YYYY-MM-DD)r   helpz--afterz--before-csvz--after-csvz--output)argparseArgumentParseradd_argument
parse_args)argvparsers     r   _parse_argsr      s    $$1ghF
4

B5LM
	24KL
3
r2

B/T""r8   c                   t        |       }|j                  rt        |j                        nd }|j                  rt        |j                        nd }|j                  r$t        |j                  j                  d            nd }|j                  r$t        |j                  j                  d            nd }t        |||j                  ||      }|j                         }t        |t        j                         j                               }|j                  rTt        |j                        }	|	j                   j#                  dd       |	j%                  |d       t'        d|	        y t'        |       y )	N:)rU   rV   rM   rW   rX   )rC   T)parentsexist_okr   )r   u   리포트 저장 완료: )r   rU   r   rV   r5   tuplesplitr6   rJ   rM   rg   rH   r   rw   ry   outputparentmkdir
write_textprint)
r   argsrU   rV   rW   rX   trackerrB   reportouts
             r   mainr      s   tD*.//doo&tJ(,T^^$DI48KK5**3/0TL26**%

((-.$K$$!G ((*G%g$**,:P:P:RSF{{4;;

5v0)#/0fr8   __main__)r*   r   rk   Dict[str, int])r5   r(   r6   r(   rk   zOptional[float])r   )rB   rl   rC   ri   rk   ri   )rk   r   )rM   ri   r   ri   r   ri   rk   r   rL   )$rp   
__future__r   r   r#   datetimer   r   pathlibr   typingr   r   r	   configr
   r   google.analytics.data_v1betar   "google.analytics.data_v1beta.typesr   r   r   r   rP   ImportErrorr1   r7   rH   rJ   rQ   rR   rS   r   r   rm   r4   r8   r   <module>r      s    Y "  
 $  ' ' 8D  N
2+,0 0fBF&#4 zF e  Ns   A? ?B	B	