Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
@@ -654,15 +654,9 @@ with gr.Blocks(css_paths=["app.css"], theme=theme) as demo:
|
|
654 |
)
|
655 |
gr.HTML('<div class="help-text">💡 원하는 게임의 설명을 입력하세요. 예: "테트리스 게임 제작해줘."</div>')
|
656 |
|
657 |
-
#
|
658 |
-
|
659 |
-
|
660 |
-
<div class="deploy-header">📤 배포 결과</div>
|
661 |
-
<div id="deploy-result-box" class="deploy-result-box">
|
662 |
-
<div class="no-deploy">아직 배포된 게임이 없습니다.</div>
|
663 |
-
</div>
|
664 |
-
</div>
|
665 |
-
""")
|
666 |
|
667 |
# 더 이상 자바스크립트 삽입 없음
|
668 |
js_trigger = gr.HTML(elem_id="js-trigger", visible=False)
|
@@ -728,96 +722,35 @@ with gr.Blocks(css_paths=["app.css"], theme=theme) as demo:
|
|
728 |
outputs=[sandbox, state_tab]
|
729 |
)
|
730 |
|
731 |
-
|
732 |
-
|
733 |
-
배포 로직 (API 호출) - 스크립트 없이
|
734 |
-
"""
|
735 |
-
try:
|
736 |
-
token = "A8IFZmgW2cqA4yUNlLPnci0N" # 실제 토큰
|
737 |
-
if not token:
|
738 |
-
return {"status": "error", "message": "Vercel 토큰이 설정되지 않았습니다."}
|
739 |
-
|
740 |
-
project_name = ''.join(random.choice(string.ascii_lowercase) for i in range(6))
|
741 |
-
deploy_url = "https://api.vercel.com/v13/deployments"
|
742 |
-
headers = {
|
743 |
-
"Authorization": f"Bearer {token}",
|
744 |
-
"Content-Type": "application/json"
|
745 |
-
}
|
746 |
-
package_json = {
|
747 |
-
"name": project_name,
|
748 |
-
"version": "1.0.0",
|
749 |
-
"private": True,
|
750 |
-
"dependencies": {"vite": "^5.0.0"},
|
751 |
-
"scripts": {
|
752 |
-
"dev": "vite",
|
753 |
-
"build": "echo 'No build needed' && mkdir -p dist && cp index.html dist/",
|
754 |
-
"preview": "vite preview"
|
755 |
-
}
|
756 |
-
}
|
757 |
-
files = [
|
758 |
-
{"file": "index.html", "data": code},
|
759 |
-
{"file": "package.json", "data": json.dumps(package_json, indent=2)}
|
760 |
-
]
|
761 |
-
project_settings = {
|
762 |
-
"buildCommand": "npm run build",
|
763 |
-
"outputDirectory": "dist",
|
764 |
-
"installCommand": "npm install",
|
765 |
-
"framework": None
|
766 |
-
}
|
767 |
-
deploy_data = {
|
768 |
-
"name": project_name,
|
769 |
-
"files": files,
|
770 |
-
"target": "production",
|
771 |
-
"projectSettings": project_settings
|
772 |
-
}
|
773 |
-
deploy_response = requests.post(deploy_url, headers=headers, json=deploy_data)
|
774 |
-
if deploy_response.status_code != 200:
|
775 |
-
return {"status": "error", "message": f"배포 실패: {deploy_response.text}"}
|
776 |
-
|
777 |
-
deployment_url = f"https://{project_name}.vercel.app"
|
778 |
-
time.sleep(5)
|
779 |
-
|
780 |
-
return {
|
781 |
-
"status": "success",
|
782 |
-
"url": deployment_url,
|
783 |
-
"project_name": project_name
|
784 |
-
}
|
785 |
-
except Exception as e:
|
786 |
-
return {"status": "error", "message": f"배포 중 오류 발생: {str(e)}"}
|
787 |
-
|
788 |
-
# ─── 스크립트 없이 순수 HTML만 반환하는 handle_deploy ───
|
789 |
-
def handle_deploy(code, deploy_status):
|
790 |
if not code:
|
791 |
-
|
792 |
-
error_html = """
|
793 |
-
<div style="border-left:5px solid #ff3b30; padding:10px; background:#ffecec; margin-top:10px;">
|
794 |
-
<strong>⚠️ 배포 실패</strong><br>
|
795 |
-
배포할 코드가 없습니다. 먼저 게임 코드를 생성해주세요.
|
796 |
-
</div>
|
797 |
-
"""
|
798 |
-
return error_html, {
|
799 |
"is_deployed": False,
|
800 |
"status": "error",
|
801 |
"message": "배포할 코드가 없습니다.",
|
802 |
"url": ""
|
803 |
}
|
804 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
805 |
try:
|
806 |
-
# 배포 실행
|
807 |
clean_code = remove_code_block(code)
|
808 |
result = deploy_to_vercel(clean_code)
|
809 |
-
|
810 |
if result.get("status") == "success":
|
811 |
-
|
812 |
-
url =
|
813 |
-
|
814 |
-
<div style="border-left:5px solid #34c759; padding:10px; background:#e8f5e9; margin-top:10px;">
|
815 |
-
<strong>✅ 배포 완료!</strong><br>
|
816 |
-
<p>아래 주소에서 게임을 확인할 수 있습니다:</p>
|
817 |
-
<a href="{url}" target="_blank" style="color:#1976d2;">{url}</a>
|
818 |
-
</div>
|
819 |
-
"""
|
820 |
-
return success_html, {
|
821 |
"is_deployed": True,
|
822 |
"status": "success",
|
823 |
"url": url,
|
@@ -825,36 +758,28 @@ with gr.Blocks(css_paths=["app.css"], theme=theme) as demo:
|
|
825 |
}
|
826 |
else:
|
827 |
error_msg = result.get("message", "알 수 없는 오류")
|
828 |
-
|
829 |
-
<div style="border-left:5px solid #ff3b30; padding:10px; background:#ffecec; margin-top:10px;">
|
830 |
-
<strong>⚠️ 배포 실패</strong><br>{error_msg}
|
831 |
-
</div>
|
832 |
-
"""
|
833 |
-
return error_html, {
|
834 |
"is_deployed": False,
|
835 |
"status": "error",
|
836 |
"message": error_msg,
|
837 |
"url": ""
|
838 |
}
|
839 |
except Exception as e:
|
840 |
-
# 시스템 오류
|
841 |
err = str(e)
|
842 |
-
|
843 |
-
<div style="border-left:5px solid #ff3b30; padding:10px; background:#ffecec; margin-top:10px;">
|
844 |
-
<strong>⚠️ 시스템 오류</strong><br>{err}
|
845 |
-
</div>
|
846 |
-
"""
|
847 |
-
return error_html, {
|
848 |
"is_deployed": False,
|
849 |
"status": "error",
|
850 |
"message": err,
|
851 |
"url": ""
|
852 |
}
|
853 |
|
|
|
854 |
deploy_btn.click(
|
855 |
fn=handle_deploy,
|
856 |
inputs=[code_output, deploy_status],
|
857 |
-
outputs=[
|
|
|
|
|
858 |
)
|
859 |
|
860 |
|
|
|
654 |
)
|
655 |
gr.HTML('<div class="help-text">💡 원하는 게임의 설명을 입력하세요. 예: "테트리스 게임 제작해줘."</div>')
|
656 |
|
657 |
+
# 배포 결과 표시 - 수정된 부분
|
658 |
+
deploy_status_text = gr.Markdown("", elem_id="deploy-status-text")
|
659 |
+
deploy_url_link = gr.HTML("", elem_id="deploy-url-link")
|
|
|
|
|
|
|
|
|
|
|
|
|
660 |
|
661 |
# 더 이상 자바스크립트 삽입 없음
|
662 |
js_trigger = gr.HTML(elem_id="js-trigger", visible=False)
|
|
|
722 |
outputs=[sandbox, state_tab]
|
723 |
)
|
724 |
|
725 |
+
# 수정된 handle_deploy 함수
|
726 |
+
async def handle_deploy(code, deploy_status):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
727 |
if not code:
|
728 |
+
return "⚠️ **배포 실패**: 배포할 코드가 없습니다.", "", {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
729 |
"is_deployed": False,
|
730 |
"status": "error",
|
731 |
"message": "배포할 코드가 없습니다.",
|
732 |
"url": ""
|
733 |
}
|
734 |
|
735 |
+
# 로딩 상태 표시
|
736 |
+
yield "⏳ **배포 중**... 잠시만 기다려주세요.", "", {
|
737 |
+
"is_deployed": False,
|
738 |
+
"status": "loading",
|
739 |
+
"message": "배포 중...",
|
740 |
+
"url": ""
|
741 |
+
}
|
742 |
+
|
743 |
+
# 비동기 환경에서 UI 업데이트 보장
|
744 |
+
await asyncio.sleep(0.5)
|
745 |
+
|
746 |
try:
|
|
|
747 |
clean_code = remove_code_block(code)
|
748 |
result = deploy_to_vercel(clean_code)
|
749 |
+
|
750 |
if result.get("status") == "success":
|
751 |
+
url = result.get("url", "")
|
752 |
+
url_html = f'<a href="{url}" target="_blank" class="deploy-url">{url}</a>'
|
753 |
+
return "✅ **배포 완료!** 아래 주소에서 게임을 확인할 수 있습니다:", url_html, {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
754 |
"is_deployed": True,
|
755 |
"status": "success",
|
756 |
"url": url,
|
|
|
758 |
}
|
759 |
else:
|
760 |
error_msg = result.get("message", "알 수 없는 오류")
|
761 |
+
return f"⚠️ **배포 실패**: {error_msg}", "", {
|
|
|
|
|
|
|
|
|
|
|
762 |
"is_deployed": False,
|
763 |
"status": "error",
|
764 |
"message": error_msg,
|
765 |
"url": ""
|
766 |
}
|
767 |
except Exception as e:
|
|
|
768 |
err = str(e)
|
769 |
+
return f"⚠️ **시스템 오류**: {err}", "", {
|
|
|
|
|
|
|
|
|
|
|
770 |
"is_deployed": False,
|
771 |
"status": "error",
|
772 |
"message": err,
|
773 |
"url": ""
|
774 |
}
|
775 |
|
776 |
+
# 수정된 배포 버튼 이벤트
|
777 |
deploy_btn.click(
|
778 |
fn=handle_deploy,
|
779 |
inputs=[code_output, deploy_status],
|
780 |
+
outputs=[deploy_status_text, deploy_url_link, deploy_status],
|
781 |
+
api_name="deploy",
|
782 |
+
queue=True
|
783 |
)
|
784 |
|
785 |
|