Spaces:
Sleeping
Sleeping
File size: 6,383 Bytes
add7d3f 6528e6f c0ebd19 95f8d1c c0ebd19 6528e6f 95f8d1c c0ebd19 95f8d1c c0ebd19 b97f664 c0ebd19 add7d3f b97f664 c0ebd19 b97f664 c0ebd19 add7d3f c0ebd19 b97f664 c0ebd19 d0c9819 6c9843d b97f664 6c9843d c0ebd19 e592770 c91f7f1 6c9843d e592770 c91f7f1 e592770 d0c9819 6c9843d c0ebd19 6c9843d c0ebd19 6c9843d c0ebd19 b97f664 6528e6f b97f664 6528e6f c0ebd19 b97f664 6528e6f b97f664 e592770 6528e6f c0ebd19 e592770 c0ebd19 eadc151 6528e6f c0ebd19 6528e6f b97f664 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
import os, json, requests
import gradio as gr
from dotenv import load_dotenv
import httpx
import time
# ํ๊ฒฝ ๋ณ์ ๋ก๋
load_dotenv(os.path.join(os.path.dirname(__file__), "..", "backend", ".env"), override=True)
# Vercel ๋ฐฑ์๋ URL
BACKEND = os.getenv('BACKEND_URL', 'https://personamate-kimddols-projects.vercel.app')
async def fetch_data_fn():
try:
async with httpx.AsyncClient() as client:
res = await client.get(f"{BACKEND}/fetch_data", timeout=60)
res.raise_for_status()
return res.json()
except Exception as e:
return {"error": str(e)}
async def run_recommendations(yt, sns, mbti):
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
}
async with httpx.AsyncClient() as client:
res = await client.post(f"{BACKEND}/youtube/recommendations", json=payload, timeout=120)
res.raise_for_status()
data = res.json()
except Exception as e:
return "<h3>์ถ์ฒ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.</h3>", f"API ํธ์ถ ์คํจ: {e}", None
recommendations_data = data.get("recommendations", {})
youtube_recs = recommendations_data.get("youtube", [])
summary_reason = recommendations_data.get("summary_reason", "์ถ์ฒ ์ฌ์ ๋ฅผ ์์ฑํ์ง ๋ชปํ์ต๋๋ค.")
if not youtube_recs:
return "<h3>์ถ์ฒ ๊ฒฐ๊ณผ๊ฐ ์์ต๋๋ค.</h3>", summary_reason, None
table_html = "<table><thead><tr><th>์ฑ๋ ์ด๋ฆ</th><th>์ฌ์ดํธ ์ฃผ์</th></tr></thead><tbody>"
for c in youtube_recs:
url = c.get("url", "")
name = c.get("name", "")
table_html += f'<tr><td>{name}</td><td><a href="{url}" target="_blank">{url}</a></td></tr>'
table_html += "</tbody></table>"
# Store the necessary data for export/email
state_data = {
"recommendations": {"youtube": youtube_recs},
"summary_reason": summary_reason
}
return table_html, summary_reason, state_data
async def export_file(file_type, recommendations_state):
if not recommendations_state:
return None, "๋จผ์ ์ถ์ฒ์ ์คํํด์ฃผ์ธ์."
endpoint = f"{BACKEND}/youtube/recommendations/export/{file_type}"
try:
# The payload is already in the correct format in recommendations_state
async with httpx.AsyncClient() as client:
res = await client.post(endpoint, json=recommendations_state, timeout=60)
res.raise_for_status()
file_path = f"/tmp/recommendations_{int(time.time())}.{file_type}"
with open(file_path, "wb") as f:
f.write(res.content)
return file_path, f"{file_type.upper()} ํ์ผ ์์ฑ ์๋ฃ"
except Exception as e:
return None, f"ํ์ผ ์์ฑ ์คํจ: {e}"
async def send_email_fn(recipient_email, recommendations_state):
if not recommendations_state:
return "๋จผ์ ์ถ์ฒ์ ์คํํด์ฃผ์ธ์."
if not recipient_email:
return "์ด๋ฉ์ผ ์ฃผ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์."
endpoint = f"{BACKEND}/youtube/recommendations/email"
payload = {
"recipient_email": recipient_email,
"recommendations": recommendations_state.get("recommendations", {}),
"summary_reason": recommendations_state.get("summary_reason", "")
}
try:
async with httpx.AsyncClient() as client:
res = await client.post(endpoint, json=payload, timeout=60)
res.raise_for_status()
return "์ด๋ฉ์ผ ์ ์ก ์ฑ๊ณต!"
except Exception as e:
return f"์ด๋ฉ์ผ ์ ์ก ์คํจ: {e}"
with gr.Blocks(title='PersonaMate Pro (OAuth + Simplified UI)') as demo:
recommendations_state = gr.State()
gr.Markdown('## PersonaMate Pro โ OAuth ์์ง + ์ถ์ฒ UI')
with gr.Row():
with gr.Column(scale=1):
gr.Markdown('### 1) OAuth ๋ก๊ทธ์ธ')
gr.HTML(f'<a href="{BACKEND}/oauth/google/start" target="_blank">Google (YouTube) ๋ก๊ทธ์ธ</a>')
with gr.Column(scale=2):
gr.Markdown('### 2) ์๋ ์์ง')
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'
)
run_btn = gr.Button('๋ถ์ & ์ถ์ฒ ์คํ', variant='primary')
with gr.Column(scale=3):
gr.Markdown('### 4) ์ถ์ฒ ๊ฒฐ๊ณผ')
result_html = gr.HTML(label="์ถ์ฒ ๊ฒฐ๊ณผ")
gr.Markdown('### 5) ์ถ์ฒ ์ฌ์ ')
summary_output = gr.Markdown(label="์ถ์ฒ ์ฌ์ ์์ฝ")
with gr.Row():
gr.Markdown('### 6) ๊ฒฐ๊ณผ ์ ์ฅ ๋ฐ ๊ณต์ ')
with gr.Row():
with gr.Column(scale=1):
html_btn = gr.Button("HTML ์ ์ฅ")
pdf_btn = gr.Button("PDF ์ ์ฅ")
download_file = gr.File(label="๋ค์ด๋ก๋")
with gr.Column(scale=2):
email_input = gr.Textbox(label="์ด๋ฉ์ผ ์ฃผ์", placeholder="๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ์ด๋ฉ์ผ์ ์
๋ ฅํ์ธ์...")
email_btn = gr.Button("์ด๋ฉ์ผ๋ก ๋ณด๋ด๊ธฐ")
status_output = gr.Textbox(label="์ํ", interactive=False)
fetch_btn.click(fetch_data_fn, inputs=[], outputs=[fetch_result])
run_btn.click(run_recommendations, [yt_text, sns_text, mbti], [result_html, summary_output, recommendations_state])
html_btn.click(export_file, inputs=[gr.State("html"), recommendations_state], outputs=[download_file, status_output])
pdf_btn.click(export_file, inputs=[gr.State("pdf"), recommendations_state], outputs=[download_file, status_output])
email_btn.click(send_email_fn, inputs=[email_input, recommendations_state], outputs=[status_output])
if __name__ == '__main__':
demo.launch()
|