
    BiM                     
   d dl mZmZmZmZmZ d dlmZ d dlZd dl	Z	d dl
mZ d dlZd dlmZ d dlmZ d dlmZmZ d dlmZ d dlZd d	lmZmZ  ee	j                            e	j                            e          d
d                      ede          Z e	j        d          ZdZ ej         e          Z!ddhZ"e#                    d           e            d                         Z$e#                    ddg          d             Z%e#                    ddg           e            d                         Z&e#                    ddg          d             Z'e#                    ddg           e            d                         Z(e#                    ddg           e            d                         Z)e#                    dd g           e            d!                         Z*e#                    d"dg           e            d#                         Z+e#                    d$d g           e            d%                         Z,e#                    d&dg           e            d'                         Z-dS )(    )	BlueprintrequestjsonifyResponsestream_with_context)cross_originN)load_dotenv)unquote)db)GifFeedbackGifUsage)datetime)r
   urlparsez..z.envgifTENOR_API_KEYzhttps://tenor.googleapis.com/v2zmedia.tenor.comzmlink.kdjsystem.comz/api/gif/proxy/<path:image_url>c                 z   	 t          |           }t                              d|            |                    d          r,|                    d          s|                    ddd          }|                    d          r,|                    d          s|                    ddd          }|                    d          s-|                    d          sd|                    d          z   }t          |          }|j        t          vr5t          	                    d|j                    t          d	d
i          dfS t                              d|            t          j        |dddddi          }|                                 |j                            dd          ddddd}t          t!          |                    d                    |j        |          S # t&          $ rG}t                              dt+          |                      t          d	di          dfcY d}~S d}~ww xY w)u$  
    이미지 프록시:
    - 프론트에서 전체 URL을 encodeURIComponent 해서 넘김
    - 여기서 1회만 unquote
    - 잘못된 scheme/slash 보정
    - 화이트리스트 호스트만 허용 (SSRF 방지)
    - 원격 상태코드/헤더를 최대한 유지하여 반환
    u   프록시 요청: zhttps:/zhttps://   zhttp:/zhttp:///zBlocked host: errorzHost not allowed  z[GIF Proxy] GET T
   z
User-Agentz)Mozilla/5.0 (compatible; MLINK-Proxy/1.0))streamtimeoutallow_redirectsheadersContent-Typez	image/pngzpublic, max-age=3600*GET)r   zCache-ControlzAccess-Control-Allow-OriginzAccess-Control-Allow-MethodszAccess-Control-Allow-Headersi    )
chunk_size)statusr   u   이미지 프록시 오류: u(   이미지를 가져올 수 없습니다.  N)r
   loggerinfo
startswithreplacelstripr   hostnameALLOWED_IMAGE_HOSTSwarningr   requestsgetraise_for_statusr   r   r   iter_contentstatus_code	Exceptionr   str)	image_urlrawpupstreamr   es         G/var/www/html/web/mlink/mlink_AI_Server/mlink-backend/src/routes/gif.pyproxy_imager7      sp   5Si  .../// >>)$$ 	8S^^J-G-G 	8++iQ77C>>(## 	6CNN9,E,E 	6++h	155C~~i(( 	/
1K1K 	/szz#.C SMM:000NN8AJ88999G%78993>>,s,,--- < I
 
 
 	!!### %,00MM3+.,1,:
 
  5 5 5 F FGG'
 
 
 	
  S S S<CFF<<===!KLMMsRRRRRRRSs%   EG) B$G) )
H:3<H5/H:5H:z/api/gif/searchr   )methodsc                     	 t           st          dg d          dfS t          j                            dd          } t          t          j                            dd                    }t          t          j                            dd	                    }t           | ||d
ddd}t          j        t           d|          }|                                 |	                                }g }|                    dg           D ]t}|                    d          |                    dd          |                    di                               d
i                               dd          |                    di                               di                               dd          |                    di                               d
i                               dd	d	g          d	         |                    di                               d
i                               dd	d	g          d         d}|d         rd|d          |d<   |d         rd|d          |d<   |
                    |           vt          ||                    dd	          d          S # t          $ rH}	t                              dt          |	                      t          d g d          dfcY d!}	~	S d!}	~	ww xY w)"u$   Tenor API를 사용하여 GIF 검색.   Tenor API 키가 설정되지 않았습니다.r   gifsr!   q limit   posr   r   highall)keyr=   r?   rA   media_filtercontentfilterar_range/searchparamsresultsidcontent_descriptionmedia_formatsurltinygifdimsr   rL   titlerO   preview_urlwidthheight/api/gif/proxy/	proxy_urlrT   preview_proxy_urlnextr<   rZ   u   GIF 검색 실패: u!   GIF 검색에 실패했습니다.N)r   r   r   argsr+   intr*   TENOR_BASE_URLr,   jsonappendr/   r"   r   r0   )
queryr?   rA   rJ   responsedatar<   itemgif_datar5   s
             r6   search_gifsrf   a   s9   ; 	I        b))GL$$Wb1122',""5!,,-- !!#
 
 <> : : :6JJJ!!###}} HHY++ 	" 	"Dhhtnn"7<<xx4488CCGGrRR#xx<<@@BOOSSTY[]^^/266::5"EEII&STVWRXYYZ[\((?B77;;E2FFJJ6TUWXSYZZ[\] H  L(K(5/(K(K%& \0[(=BY0[0[,-KK!!!!HHVQ''
 
   	
    33q66334448
 
    	 	 	 	 	 	s#   J  JJ   
K2*=K-'K2-K2z/api/gif/trendingc                     	 t           st          dg d          dfS t          j                            dd          } g d}t           |d         t          t          |           d          d	d
dd}t          j        t           d|d          }|	                                 |
                                }g }|                    dg           D ](}t          |          }|r|                    |           )t          ||                    dd          d          dfS # t          $ r;}t                              d|            t          dg d          dfcY d}~S d}~ww xY w)u   인기 GIF 가져오기r:   r;   r!   r?   r@   )funnyreactioncelebrationhappyexcitedlovewowcoolr   2   r   rB   rC   rD   r=   r?   rE   rF   rG   rH   r   rJ   r   rK   rZ   r[      u    인기 GIF 가져오기 실패: u<   인기 GIF를 가져오는 중 오류가 발생했습니다.Nr   r   r   r\   r+   minr]   r*   r^   r,   r_   process_gif_datar`   r/   r"   r   )	r?   popular_keywordsrJ   rb   rc   r<   resultre   r5   s	            r6   get_trending_gifsry      s   ( 	I     
   "--jjj !!!$UR((!#
 
 <> : : :6SUVVV!!###}}hhy"-- 	& 	&F'//H &H%%%HHVQ''
 
    	
    ;;;<<<S
 
    	 	 	 	 	 	s#   D  DD   
E%*0E E% E%z/api/gif/randomc                     	 t           st          dg d          dfS t          t          j                            dd                    } t           d| ddd	d
}t          j        t           d|          }|                                 |	                                }g }|                    dg           D ]t}|                    d          |                    dd          |                    di                               di                               dd          |                    di                               di                               dd          |                    di                               di                               dddg          d         |                    di                               di                               dddg          d         d}|d         rd|d          |d<   |d         rd|d          |d<   |
                    |           vt          ||                    dd          d          S # t          $ rH}t                              dt          |                      t          dg d          dfcY d }~S d }~wt          $ r;}t                              d!|            t          d"g d          dfcY d }~S d }~ww xY w)#u   랜덤 GIF 가져오기r:   r;   r!   r?   r@   rh   r   rB   rC   rq   rH   rI   rK   rL   rM   r>   rN   rO   rP   rQ   r   r   rR   rW   rX   rT   rY   rZ   r[   u    랜덤 GIF 가져오기 실패: u)   랜덤 GIF를 가져올 수 없습니다.Nu    랜덤 GIF 가져오기 예외: u$   서버 오류가 발생했습니다.)r   r   r]   r   r\   r+   r*   r^   r,   r_   r`   r/   r"   r   r0   )r?   rJ   rb   rc   r<   rd   re   r5   s           r6   get_random_gifsr{      sx   > 	I      GL$$Wb1122 !!#
 
 <> : : :6JJJ!!###}} HHY++ 	" 	"Dhhtnn"7<<xx4488CCGGrRR#xx<<@@BOOSSTY[]^^/266::5"EEII&STVWRXYYZ[\((?B77;;E2FFJJ6TUWXSYZZ[\] H  L(K(5/(K(K%& \0[(=BY0[0[,-KK!!!!HHVQ''
 
   	
    @A@@AAA@
 
    	 	 	 	 	 	    ;;;<<<;
 
    	 	 	 	 	 	s5   I H4I 
K'=JK'K',0K"K'"K'z/api/gif/categoriesc                  T   	 t           st          dg d          dfS 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dg} t          d| i          dfS # t          $ r;}t                              d|            t          dg d          dfcY d}~S d}~ww xY w)u   GIF 카테고리 가져오기r:   )r   
categoriesr!   Funnyrh   r>   )name
searchtermimagepathReactionri   Celebrationrj   Happyrk   Loverm   Coolro   Excitedrl   Wowrn   r}   rs   u&   GIF 카테고리 가져오기 실패: uB   GIF 카테고리를 가져오는 중 오류가 발생했습니다.N)r   r   r/   r"   r   )r}   r5   s     r6   get_gif_categoriesr     sW    	I       Gb'RRzBPZ[["-"VcddGb'RR6BOO6BOOi"iXX%"eLL	

 j122C77   AaAABBBY
 
    	 	 	 	 	 	s#   A" AA" "
B',0B"B'"B'z/api/gif/featuredc                     	 t           st          dg d          dfS t          j                            dd          } t           dt          t          |           d          dd	d
d}t          j        t           d|d          }|	                                 |
                                }g }|                    dg           D ](}t          |          }|r|                    |           )t          ||                    dd          d          dfS # t          $ r;}t                              d|            t          dg d          dfcY d}~S d}~ww xY w)u   추천 GIF 가져오기r:   r;   r!   r?   r@   trendingrp   r   rB   rC   rq   rH   r   rr   rK   rZ   r   r[   rs   u    추천 GIF 가져오기 실패: u<   추천 GIF를 가져오는 중 오류가 발생했습니다.Nrt   )r?   rJ   rb   rc   r<   rx   re   r5   s           r6   get_featured_gifsr   1  s   ' 	I     
   "-- !UR((!#
 
 <> : : :6SUVVV!!###}}hhy"-- 	& 	&F'//H &H%%%HHVQ''
 
    	
    ;;;<<<S
 
    	 	 	 	 	 	s#   D C8D 
E 0EEEz/api/gif/feedbackPOSTc                  H   	 t          j                    } g d}|D ]}|| vrt          dd| i          dfc S g d}| d         |vrt          ddi          dfS d| v rN| d         Ft          | d         t                    r| d         d
k     s| d         dk    rt          ddi          dfS |                     d          }|s t          t          j                              }t          | d         |                     dd          | d         |                     d          || d         |                     d          |                     dd                    }t          j                            |           t          j                                         t          d|j        |d          dfS # t          $ re}t          j                                         t"                              dt          |                      t          ddi          dfcY d	}~S d	}~ww xY w)u   GIF 피드백 제출)gif_idgif_urlfeedback_typer   (   필수 필드가 누락되었습니다: r   )likedislikerh   usefulinappropriater   u.   유효하지 않은 피드백 타입입니다.ratingNr      u/   평점은 1-5 사이의 정수여야 합니다.
session_idr   	gif_titler>   r   user_idcomment)r   r   r   r   r   r   r   r   u3   피드백이 성공적으로 제출되었습니다.)messagefeedback_idr      u   GIF 피드백 제출 실패: u'   피드백 제출에 실패했습니다.r!   )r   get_jsonr   
isinstancer]   r+   r0   uuiduuid4r   r   sessionaddcommitrL   r/   rollbackr"   r   )rc   required_fieldsfieldvalid_feedback_typesr   feedbackr5   s          r6   submit_gif_feedbackr   ^  s   0R!! A@@$ 	c 	cED  )[TY)[)[\]]_bbbbb !  WVV (<<<G%UVWWY\\\ tX :d8nc22 bd8nq6H6HDQYN]^L^L^)Z[\\^aaa XXl++
 	+TZ\\**J >hh{B//OHHY''!/88H%%HHY++	
 	
 	
 	
x   

L#;$
 
   	 	  R R R

=SVV==>>>!JKLLcQQQQQQQRs1   6F2 !F2 AF2 -DF2 2
H!<AHH!H!z/api/gif/feedback/<gif_id>c                    	 t           j                            t          j        t           j                            t          j                                      d                    	                    t          j
        | k                                  t          j                                                  }t           j                            t           j                            t          j                                      d          t           j                            t          j                                      d                    	                    t          j
        | k    t          j                            d                                                    }t          j        	                    t          j
        | k                                  t          j                                                                      d                                          }t+          d |D                       d |D             |j        rt/          |j                  nd|j        r|j        ndd	 |D             d
}t3          |          dfS # t4          $ rG}t6                              dt;          |                      t3          ddi          dfcY d}~S d}~ww xY w)u   특정 GIF의 피드백 조회countaverage_ratingrating_countNr   c              3   $   K   | ]}|j         V  d S )N)r   .0stats     r6   	<genexpr>z#get_gif_feedback.<locals>.<genexpr>  s$      "I"I$4:"I"I"I"I"I"I    c                 (    i | ]}|j         |j        S  r   r   r   s     r6   
<dictcomp>z$get_gif_feedback.<locals>.<dictcomp>  s    "]"]"]d4#5tz"]"]"]r   r   c                 6    g | ]}|                                 S r   )to_dictr   r   s     r6   
<listcomp>z$get_gif_feedback.<locals>.<listcomp>  s$     U U U!1!1!3!3 U U Ur   )total_feedbacksfeedback_breakdownr   r   recent_feedbacksrs   u   GIF 피드백 조회 실패: r   u'   피드백 조회에 실패했습니다.r!   )r   r   ra   r   r   funcr   rL   labelfilterr   group_byrC   avgr   isnotfirstorder_by
created_atdescr?   sumr   floatr   r   r/   r"   r   r0   )r   feedback_statsrating_statsr   statsr5   s         r6   get_gif_feedbackr     si   $R))%GMM+.))//88
 
 &&(
 

(;,
-
-ccee 	 z''GKK*++112BCCGMM+,--33NCC
 
 &&($$T**
 
 %'' 	 ',33&(
 

(;)..00
1
1%%))CCEE 	  #"I"I."I"I"III"]"]n"]"]"]DPD_ieL$?@@@ei9E9RYL55XY U UDT U U U
 
 u~~s"" R R R=SVV==>>>!JKLLcQQQQQQQRs   JJ	 	
K<KKKz/api/gif/usagec                  |   	 t          j                    } g d}|D ]}|| vrt          dd| i          dfc S g d}| d         |vrt          ddi          dfS |                     d          }|s t	          t          j                              }t          | d	         |                     d
d          | d         |                     d          || d         |                     dd                    }t          j	        
                    |           t          j	                                         t          d|j        |d          dfS # t          $ re}t          j	                                         t                              dt	          |                      t          ddi          dfcY d}~S d}~ww xY w)u   GIF 사용 추적)r   r   
usage_typer   r   r   )sentviewedsharedr   u+   유효하지 않은 사용 타입입니다.r   r   r   r>   r   r   contextchat)r   r   r   r   r   r   r   u7   사용 기록이 성공적으로 저장되었습니다.)r   usage_idr   r   u   GIF 사용 추적 실패: u$   사용 추적에 실패했습니다.r!   N)r   r   r   r+   r0   r   r   r   r   r   r   r   rL   r/   r   r"   r   )rc   r   r   valid_usage_typesr   usager5   s          r6   track_gif_usager     s   *O!! >==$ 	c 	cED  )[TY)[)[\]]_bbbbb ! 988%666G%RSTTVYYY XXl++
 	+TZ\\**J >hh{B//OHHY''!L)HHY//
 
 
 	
u

P$
 
   	 	  O O O

:#a&&::;;;!GHII3NNNNNNNOs*   6E !E C0E 
F;AF60F;6F;z/api/gif/analyticsc                     	 t           j                                        } t          j                                        }t          j                            t           j        t           j        t          j                            t           j	                  
                    d                                        t           j        t           j                                      t          j                            t           j	                                                                                d                                          }t          j                            t          j        t          j                            t          j	                  
                    d                                        t          j                                                  }ddlm}m}  |j                     |d          z
  }t          j                            t          j                            t           j                  
                    d          t          j                            t           j	                  
                    d                                        t           j        |k                                  t          j                            t           j                                                            }| |d	 |D             d
 |D             d |D             d}t/          |          dfS # t0          $ rG}	t2                              dt7          |	                      t/          ddi          dfcY d}	~	S d}	~	ww xY w)u   GIF 분석 데이터 조회usage_countr   r   r   )r   	timedelta   )daysdatec                 8    g | ]}|j         |j        |j        d S )r   r   r   r   )r   r   s     r6   r   z%get_gif_analytics.<locals>.<listcomp>  s@        	 "j!$#&?   r   c                 (    i | ]}|j         |j        S r   r   r   s     r6   r   z%get_gif_analytics.<locals>.<dictcomp>   s/     # # # &# # #r   c                 P    g | ]#}|j                                         |j        d $S ))r   r   )r   	isoformatr   )r   r   s     r6   r   z%get_gif_analytics.<locals>.<listcomp>$  sG       
  "J0022"[   r   )total_gifs_usedr   popular_gifsr   daily_usagers   u$   GIF 분석 데이터 조회 실패: r   u.   분석 데이터 조회에 실패했습니다.r!   N)r   ra   r   r   r   r   r   r   r   rL   r   r   r   r   r?   rC   r   r   r   nowr   r   r   r   r/   r"   r   r0   )

total_gifsr   r   feedback_by_typer   r   seven_days_agor   	analyticsr5   s
             r6   get_gif_analyticsr     s   ?Y^))++
%+1133 z''OGMM(+&&,,];;
 
 (OX/
 

(GMM(+&&++--
 

%))CCEE 	 :++%GMM+.))//88
 
 (;,
-
-ccee 	 	10000000%))*;*;*;;j&&GLL,--33F;;GMM(+&&,,W55
 
 &>1
 

(GLL,--
 

#%% 	  *.  (  # # 0# # # 
 )  
 
	0 y!!3&& Y Y YDCFFDDEEE!QRSSUXXXXXXXXYs   L2L5 5
N?<N;NN).flaskr   r   r   r   r   
flask_corsr   r*   osdotenvr	   loggingurllib.parser
   src.models.dbr   src.models.gif_feedbackr   r   r   r   r   r   joindirname__file____name__gif_bpgetenvr   r^   	getLoggerr"   r(   router7   rf   ry   r{   r   r   r   r   r   r   r   r   r6   <module>r     s   L L L L L L L L L L L L L L # # # # # #  				                          9 9 9 9 9 9 9 9        * * * * * * * * BGLL22D&AA B B B	5(	#	# 	/**2		8	$	$  
 /00>S >S  10>SB %11= = 21=~ !E733* *  43*X %11@ @ 21@D #eW55   65: !E733) )  43)V !F8442R 2R  542Rh *UG<<&R &R  =<&RP 11,O ,O  21,O\ "UG44AY AY  54AY AY AYr   