
    iM                        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.                  j1                  e	j.                  j3                  e      d
d              ede      Z e	j:                  d      ZdZ ej@                  e      Z!ddhZ"ejG                  d       e       d               Z$ejG                  ddg      d        Z%ejG                  ddg       e       d               Z&ejG                  ddg      d        Z'ejG                  ddg       e       d               Z(ejG                  ddg       e       d               Z)ejG                  dd g       e       d!               Z*ejG                  d"dg       e       d#               Z+ejG                  d$d g       e       d%               Z,ejG                  d&dg       e       d'               Z-y)(    )	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                    	 t        |       }t        j                  d|        |j                  d      r$|j                  d      s|j	                  ddd      }|j                  d      r$|j                  d      s|j	                  ddd      }|j                  d      s%|j                  d      sd|j                  d      z   }t        |      }|j                  t        vr1t        j                  d|j                          t        d	d
i      dfS t        j                  d|        t        j                  |dddddi      }|j                          |j                  j                  dd      ddddd}t        t!        |j#                  d            |j$                  |      S # t&        $ r:}t        j)                  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         C/home/kdj-ubuntu1/mlink_AI_Server/mlink-backend/./src/routes/gif.pyproxy_imager7      s   5Si (./ >>)$S^^J-G++iQ7C>>(#CNN9,E++h	15C~~i(
1Kszz#.C SM::00NN^AJJ<89G%7893>>&se,- << I
 	!!# %,,00M3+.,1,:
  5 5 5 FG''
 	
  S3CF8<=!KLMsRRSs%   DF* BF* *	G-3/G("G-(G-z/api/gif/searchr   )methodsc                     	 t         st        dg d      dfS t        j                  j	                  dd      } t        t        j                  j	                  dd            }t        t        j                  j	                  dd	            }t         | ||d
ddd}t        j                  t         d|      }|j                          |j                         }g }|j	                  dg       D ]&  }|j	                  d      |j	                  dd      |j	                  di       j	                  d
i       j	                  dd      |j	                  di       j	                  di       j	                  dd      |j	                  di       j	                  d
i       j	                  dd	d	g      d	   |j	                  di       j	                  d
i       j	                  dd	d	g      d   d}|d   rd|d    |d<   |d   rd|d    |d<   |j                  |       ) t        ||j	                  dd	      d      S # t        $ r;}	t        j                  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   s~   ;I      b)GLL$$Wb12',,""5!,- !!#
 <<>"2' :6J!!#}} HHY+Dhhtn"7<xx488CGGrR#xx<@@BOSSTY[]^/26::5"EII&STVWRXYZ[\((?B7;;E2FJJ6TUWXSYZ[\]H *9(5/9J(K%&2A(=BYAZ0[,-KK!! ,$ HHVQ'
  	
  *3q6(348
   	s#   H2 HH2 2	I6;0I1+I61I6z/api/gif/trendingc                  h   	 t         st        dg d      dfS t        j                  j	                  dd      } g d}t         |d   t        t        |       d      d	d
dd}t        j                  t         d|d      }|j                          |j                         }g }|j	                  dg       D ]!  }t        |      }|s|j                  |       # t        ||j	                  dd      d      dfS # t        $ r2}t        j                  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      sS   (I   
   "-j !!!$UR(!#
 <<>"2' :6SUV!!#}}hhy"-F'/HH% .
 HHVQ'
   	
  7s;<S
   	s)   C6 B*C6 2C6 6	D1?'D,&D1,D1z/api/gif/randomc                     	 t         st        dg d      dfS t        t        j                  j                  dd            } t         d| ddd	d
}t        j
                  t         d|      }|j                          |j                         }g }|j                  dg       D ]&  }|j                  d      |j                  dd      |j                  di       j                  di       j                  dd      |j                  di       j                  di       j                  dd      |j                  di       j                  di       j                  dddg      d   |j                  di       j                  di       j                  dddg      d   d}|d   rd|d    |d<   |d   rd|d    |d<   |j                  |       ) t        ||j                  dd      d      S # t        $ r;}t        j                  dt        |              t        dg d      dfcY d }~S d }~wt        $ r2}t        j                  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{      s   >I    GLL$$Wb12 !!#
 <<>"2' :6J!!#}} HHY+Dhhtn"7<xx488CGGrR#xx<@@BOSSTY[]^/26::5"EII&STVWRXYZ[\((?B7;;E2FJJ6TUWXSYZ[\]H *9(5/9J(K%&2A(=BYAZ0[,-KK!! ,$ HHVQ'
  	
  7Ax@A@
   	  7s;<;
   	s5   G( GG( (	I%10H'!I%'I%3'I I% I%z/api/gif/categoriesc                  .   	 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        $ r2}t        j	                  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     s    I     Gb'RzBPZ["-"VcdGb'R6BO6BOi"iX%"eL	

 j12C77 =aSABY
   	s#   A A A 	B"'B	BBz/api/gif/featuredc                  Z   	 t         st        dg d      dfS t        j                  j	                  dd      } t         dt        t        |       d      dd	d
d}t        j                  t         d|d      }|j                          |j                         }g }|j	                  dg       D ]!  }t        |      }|s|j                  |       # t        ||j	                  dd      d      dfS # t        $ r2}t        j                  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  sH   'I   
   "- !UR(!#
 <<>"2' :6SUV!!#}}hhy"-F'/HH% .
 HHVQ'
   	
  7s;<S
   	s)   C/ B#C/ <2C/ /	D*8'D%D*%D*z/api/gif/feedbackPOSTc                     	 t        j                         } g d}|D ]  }|| vst        dd| i      dfc S  g d}| d   |vrt        ddi      dfS d| v r7| d   2t        | d   t              r| d   d
k  s| d   dkD  rt        ddi      dfS | j                  d      }|st        t        j                               }t        | d   | j                  dd      | d   | j                  d      || d   | j                  d      | j                  dd            }t        j                  j                  |       t        j                  j                          t        d|j                  |d      dfS # t        $ rX}t        j                  j!                          t"        j%                  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$ED +STYSZ)[\]_bbb %
  W (<<G%UVWY\\\ tX :d8nc2d8nq6HDQYN]^L^)Z[\^aaa XXl+
TZZ\*J >hh{B/OHHY'!/88H%HHY+	
 	

x 


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


4SVH=>!JKLcQQRs5   !E0 E0 E0 :E0 C!E0 0	G9AGGGz/api/gif/feedback/<gif_id>c           	         	 t         j                  j                  t        j                  t         j
                  j                  t        j                        j                  d            j                  t        j                  | k(        j                  t        j                        j                         }t         j                  j                  t         j
                  j                  t        j                        j                  d      t         j
                  j                  t        j                        j                  d            j                  t        j                  | k(  t        j                  j                  d            j!                         }t        j                  j                  t        j                  | k(        j#                  t        j$                  j'                               j)                  d      j                         }t+        d |D              |D ci c]  }|j                  |j                   c}|j,                  rt/        |j,                        nd|j0                  r|j0                  nd|D cg c]  }|j3                          c}d}t5        |      d	fS c c}w c c}w # t6        $ r:}t8        j;                  d
t=        |              t5        ddi      dfcY d}~S d}~ww xY w)u   특정 GIF의 피드백 조회countaverage_ratingrating_countNr   c              3   4   K   | ]  }|j                     y w)N)r   ).0stats     r6   	<genexpr>z#get_gif_feedback.<locals>.<genexpr>  s     "I.$4::.s   r   )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   to_dictr   r/   r"   r   r0   )r   feedback_statsrating_statsr   r   r   statsr5   s           r6   get_gif_feedbackr     s;   $R))%%GGMM+..)//8
 &&(

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

(;))..0
1%%)CCE 	  #"I."IIN\"]nd4#5#5tzz#An"]DPD_D_eL$?$?@ei9E9R9RL55XYDT UDT!1!1!3DT U
 u~s"" #^ !V
  R4SVH=>!JKLcQQRs=   H J4 "J* AJ4 J/J4 *
J4 4	K7=/K2,K72K7z/api/gif/usagec                     	 t        j                         } g d}|D ]  }|| vst        dd| i      dfc S  g d}| d   |vrt        ddi      dfS | j                  d      }|st	        t        j                               }t        | d	   | j                  d
d      | d   | j                  d      || d   | j                  dd            }t        j                  j                  |       t        j                  j                          t        d|j                  |d      dfS # t        $ rX}t        j                  j                          t        j!                  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! >$ED +STYSZ)[\]_bbb %
 9%66G%RSTVYYY XXl+
TZZ\*J >hh{B/OHHY'!L)HHY/
 	

u


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


1#a&:;!GHI3NNOs/   !D% D% D% CD% %	F.AF;FFz/api/gif/analyticsc            
         	 t         j                  j                         } t        j                  j                         }t        j
                  j                  t         j                  t         j                  t        j                  j                  t         j                        j                  d            j                  t         j                  t         j                        j                  t        j                  j                  t         j                        j                               j                  d      j                         }t        j
                  j                  t        j                   t        j                  j                  t        j                        j                  d            j                  t        j                         j                         }ddlm}m}  |j&                          |d      z
  }t        j
                  j                  t        j                  j)                  t         j*                        j                  d      t        j                  j                  t         j                        j                  d            j-                  t         j*                  |k\        j                  t        j                  j)                  t         j*                              j                         }| ||D cg c]&  }|j                  |j                  |j.                  d	( c}|D 	ci c]  }	|	j                   |	j                   c}	|D 
cg c])  }
|
j(                  j1                         |
j                  d
+ c}
d}t3        |      dfS c c}w c c}	w c c}
w # t4        $ r:}t6        j9                  dt;        |              t3        ddi      dfcY d}~S d}~ww xY w)u   GIF 분석 데이터 조회usage_countr   r   r   )r   	timedelta   )daysdate)r   r   r   )r   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   	isoformatr   r/   r"   r   r0   )
total_gifsr   r   feedback_by_typer   r   seven_days_agor   r   r   r   	analyticsr5   s                r6   get_gif_analyticsr     s   ?Y^^))+
%++113 zz''OOGGMM(++&,,];
 (OOX//

(GGMM(++&++-

%)CCE 	 ::++%%GGMM+..)//8
 (;,,
-cce 	 	1%)*;;jj&&GGLL,,-33F;GGMM(++&,,W5
 &>1

(GGLL,,-

#% 	  *. ( (C	 "jj!$#&??
 ( !1# 0H &&6 0# )
 )E "JJ002"[[ )
	0 y!3&&+#  Y;CF8DE!QRSUXXXYsH   K<N" >+N)N" /N
N" .NN" N" "	O%+/O O% O%).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        r6   <module>r      sa   L L #  	      9   * BGGLL2D&A B	5(	# 		/*2			8	$  
 /0>S  1>SB %1= 2=~ !E73*  4*X %1@ 2@D #eW5  6: !E73)  4)V !F842R  52Rh *UG<&R  =&RP 1,O  2,O\ "UG4AY  5AYr   