import os, json, requests
import gradio as gr
from dotenv import load_dotenv
# 환경 변수 로드
load_dotenv(os.path.join(os.path.dirname(__file__), "..", "backend", ".env"), override=True)
BACKEND = os.getenv('BACKEND_URL','http://localhost:9000')
with gr.Blocks(title='PersonaMate Pro (OAuth + Simplified UI)') as demo:
gr.Markdown('## PersonaMate Pro — OAuth 수집 + 추천 UI')
with gr.Row():
with gr.Column(scale=1):
gr.Markdown('### 1) OAuth 로그인')
google_html = gr.HTML(f'Google (YouTube) 로그인 열기')
instagram_html = gr.HTML(f'Instagram 로그인 열기')
x_html = gr.HTML(f'X (Twitter) 로그인 열기')
with gr.Column(scale=2):
gr.Markdown('### 2) 자동 수집')
yt_chk=gr.Checkbox(label='YouTube 구독 목록 사용', value=True)
ig_chk=gr.Checkbox(label='Instagram 해시태그 사용', value=False)
x_chk=gr.Checkbox(label='X 팔로잉 사용자명 사용', value=False)
fetch_btn=gr.Button('내 계정에서 데이터 수집')
fetch_result=gr.JSON(label="수집된 데이터 미리보기")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown('### 3) 입력/MBTI')
yt_text=gr.Textbox(lines=6,label='유튜브 구독 (수집/수동 혼용)')
sns_text=gr.Textbox(lines=6,label='SNS 키워드/계정 (수집/수동 혼용)')
mbti=gr.Dropdown(choices=['ISTJ','ISFJ','INFJ','INTJ','ISTP','ISFP','INFP','INTP','ESTP','ESFP','ENFP','ENTP','ESTJ','ESFJ','ENFJ','ENTJ'], value='ENFP', label='MBTI')
use_openai=gr.Checkbox(label='OpenAI 임베딩 사용', value=True)
run_btn=gr.Button('분석 & 추천 실행', variant='primary')
send_email_btn=gr.Button("추천 결과 이메일로 보내기 (Gmail)")
with gr.Column(scale=3):
gr.Markdown('### 4) 추천 결과')
result_table=gr.Dataframe(headers=["채널 이름","사이트 주소"], row_count=10, col_count=2)
# 버튼 동작 연결 제거 (Hugging Face에서는 webbrowser.open 사용 불가)
# 대신 gr.Link 컴포넌트로 대체
def fetch_data_fn():
try:
res = requests.get(f"{BACKEND}/fetch_data", timeout=60)
res.raise_for_status()
return res.json()
except Exception as e:
return {"error": str(e)}
fetch_btn.click(fetch_data_fn, inputs=[], outputs=[fetch_result])
def _run(yt, sns, mbti, use_openai):
try:
payload = {
"youtube_subscriptions": [s.strip() for s in yt.splitlines() if s.strip()],
"sns_keywords": [s.strip() for s in sns.splitlines() if s.strip()],
"mbti": mbti
}
res = requests.post(f"{BACKEND}/youtube/recommendations", json=payload, timeout=120)
res.raise_for_status()
data = res.json().get("recommendations", {})
except Exception as e:
data = {"youtube":[{"name":"추천 실패","url":str(e)}], "web":[]}
rows = []
youtube_list = data.get("youtube", [])
web_list = data.get("web", [])
if not youtube_list and not web_list:
# fallback: 최소한 1개라도 표시
youtube_list = [{"name":"추천 실패","url":"http://youtube.com"}]
web_list = [{"name":"추천 실패","url":"http://example.com"}]
for c in youtube_list + web_list:
rows.append([
c.get("name",""),
c.get("url","")
])
return rows
run_btn.click(_run, [yt_text, sns_text, mbti, use_openai], [result_table])
if __name__=='__main__':
demo.launch()