File size: 3,938 Bytes
c7e5db4
050ab1a
c7e5db4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11962ff
 
c7e5db4
11962ff
 
 
 
 
 
 
 
 
 
c7e5db4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
050ab1a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c7e5db4
 
 
 
54ed3b2
c7e5db4
54ed3b2
c7e5db4
 
54ed3b2
c7e5db4
 
54ed3b2
 
 
 
 
 
 
 
 
 
050ab1a
54ed3b2
 
 
 
c7e5db4
54ed3b2
 
 
c7e5db4
 
 
 
050ab1a
54ed3b2
 
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
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from dotenv import load_dotenv
from .core.nlp_handler import NLPHandler
import os

# Load environment variables dari file .env
load_dotenv()

from api.predict import predict_endpoint
from api.quiz import get_quiz_questions, submit_quiz
from api.core.chatbot import MBTIChatbot
from pydantic import BaseModel

# Init Chatbot (Load dataset sekali di awal)
chatbot = MBTIChatbot()

class ChatRequest(BaseModel):
    message: str
    lang: str = "id" # Default ke Indo kalo gak dikirim


from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Tambahkan CORS biar frontend (port 3000) bisa akses backend (port 8000)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"], # Di produksi, ganti "*" dengan domain frontend lu
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# --- TAMBAHAN DEBUGGING (CEK SAAT SERVER NYALA) ---

@app.on_event("startup")
async def startup_event():
    api_key = os.getenv("YOUTUBE_API_KEY")
    print("\n" + "="*40)
    if api_key:
        print(f"[OK] API KEY DITEMUKAN: {api_key[:5]}...******")
        print("[MODE] Mode: OFFICIAL API (Anti-Blokir)")
    else:
        print("[ERR] API KEY TIDAK DITEMUKAN!")
        print("[WARN] Mode: FALLBACK SCRAPING (Rawan Error)")
    
    print("\n[WAIT] PRE-LOADING MODELS (Transformer + Emotions)...")
    try:
        NLPHandler.load_models()
        print("[OK] Models Loaded Successfully!")
    except Exception as e:
        print(f"[ERR] Model Preload Failed: {e}")
        
    print("="*40 + "\n")

app.add_api_route("/api/predict", predict_endpoint, methods=["POST"])
app.add_api_route("/api/quiz", get_quiz_questions, methods=["GET"])
app.add_api_route("/api/quiz", submit_quiz, methods=["POST"])

@app.post("/api/chat")
async def chat_endpoint(request: ChatRequest):
    return {"response": chatbot.generate_response(request.message, request.lang)}


@app.get("/api/hello")
def health_check():
    # Biar bisa dicek lewat browser: http://localhost:8000/api/hello
    has_key = bool(os.getenv("YOUTUBE_API_KEY"))
    return {
        "status": "online", 
        "mode": "youtube_ready", 
        "api_key_detected": has_key 
    }

@app.get("/", response_class=HTMLResponse)
def read_root():
    return """
    <!DOCTYPE html>
    <html>
    <head>
        <title>Sentimind API</title>
        <style>
            body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
            iframe { width: 100%; height: 100%; border: none; }
        </style>
    </head>
    <body>
        <iframe src="https://sentimind.vercel.app"></iframe>
    </body>
    </html>
    """

# --- ROUTE YOUTUBE BARU ---
@app.get("/api/youtube/{video_id}") 
def analyze_youtube_video(video_id: str):
    # Panggil fungsi fetch YouTube
    data = NLPHandler.fetch_youtube_transcript(video_id)
    
    if not data:
        return {
            "success": False, 
            "error": "NO_TRANSCRIPT"
        }
    
    # Handle structured data from official API
    if isinstance(data, dict) and "text_for_analysis" in data:
        text_for_analysis = data["text_for_analysis"]
        result = NLPHandler.predict_all(text_for_analysis)
        
        return {
            "success": True,
            "mbti_type": result["mbti"],
            "emotion": result["emotion"],
            "keywords": result["keywords"],
            "reasoning": result["reasoning"],
            "video": data.get("video"),
            "comments": data.get("comments", []),
            "fetched_text": text_for_analysis
        }
    
    # Fallback for plain text (transcript fallback)
    result = NLPHandler.predict_all(data)
    return {
        "success": True,
        "mbti_type": result["mbti"],
        "emotion": result["emotion"],
        "keywords": result["keywords"],
        "reasoning": result["reasoning"],
        "fetched_text": data
    }