ALI7ADEL commited on
Commit
bc6734b
·
verified ·
1 Parent(s): 8c6b97e

Update src/api/main.py

Browse files
Files changed (1) hide show
  1. src/api/main.py +11 -212
src/api/main.py CHANGED
@@ -1,70 +1,22 @@
1
- import uuid
2
- import re
3
- import logging
4
- from datetime import datetime
5
- from typing import Dict, Optional
6
- from enum import Enum
7
  from contextlib import asynccontextmanager
8
-
9
- from fastapi import FastAPI, HTTPException, BackgroundTasks, Depends
10
  from fastapi.middleware.cors import CORSMiddleware
11
- from pydantic import BaseModel, HttpUrl
12
-
13
- # --- استيراد الأدوات الجديدة (POT Solver & New Downloader) ---
14
- from src.api.downloader import YouTubeDownloader
15
  from src.api.pot_server import pot_server
16
-
17
- # --- استيراد مكونات النظام ---
18
- from src.transcription.transcript_fetcher import TranscriptFetcher
19
- from src.transcription.whisper_transcriber import WhisperTranscriber
20
- from src.summarization.note_generator import NoteGenerator
21
- from src.utils.logger import setup_logger
22
- from src.db.firebase import get_firebase_db
23
- from src.db.models import Note, User
24
- from src.auth.dependencies import get_current_user
25
- from src.api.auth_routes import router as auth_router
26
  from src.api.notes_routes import router as notes_router
 
 
27
 
28
- logger = setup_logger(__name__)
29
-
30
- # --- Models ---
31
- class TaskStatus(str, Enum):
32
- PENDING = "pending"
33
- DOWNLOADING = "downloading"
34
- TRANSCRIBING = "transcribing"
35
- GENERATING_NOTES = "generating_notes"
36
- COMPLETED = "completed"
37
- FAILED = "failed"
38
-
39
- class GenerateNotesRequest(BaseModel):
40
- youtube_url: HttpUrl
41
- language: str = "en"
42
-
43
- class TaskResponse(BaseModel):
44
- task_id: str
45
- status: TaskStatus
46
- message: str
47
-
48
- # مخزن المهام المؤقت
49
- tasks: Dict[str, Dict] = {}
50
-
51
- # --- إدارة دورة حياة السيرفر (Lifespan) ---
52
  @asynccontextmanager
53
  async def lifespan(app: FastAPI):
54
- logger.info("🚀 Lifespan: Initializing Firebase...")
55
- get_firebase_db()
56
-
57
- logger.info("🚀 Lifespan: Starting POT solver server (bgutil v1.3.1)...")
58
- # تشغيل سيرفر الـ Node.js في الخلفية لحل تحديات يوتيوب
59
- pot_server.start()
60
-
61
  yield
62
-
63
- logger.info("🛑 Lifespan: Stopping POT solver server...")
64
  pot_server.stop()
65
 
66
- app = FastAPI(title="YouTube Study Notes AI", lifespan=lifespan)
67
 
 
68
  app.add_middleware(
69
  CORSMiddleware,
70
  allow_origins=["*"],
@@ -73,163 +25,10 @@ app.add_middleware(
73
  allow_headers=["*"],
74
  )
75
 
76
- # --- تسجيل الـ Routers ---
77
- app.include_router(auth_router)
78
  app.include_router(notes_router)
79
-
80
- # --- Endpoints الأساسية ---
81
 
82
  @app.get("/")
83
  def read_root():
84
- return {"message": "Welcome to AIdea API! The server is running perfectly with POT Solver."}
85
-
86
- @app.get("/health")
87
- async def health_check():
88
- """اختبار حالة السيرفر والاتصال بيوتيوب"""
89
- import socket
90
- import httpx
91
- dns_results = {}
92
- for domain in ["www.youtube.com", "google.com"]:
93
- try:
94
- dns_results[domain] = socket.gethostbyname(domain)
95
- except:
96
- dns_results[domain] = "Error"
97
-
98
- return {
99
- "status": "online",
100
- "pot_server_running": pot_server._proc is not None,
101
- "dns": dns_results,
102
- "timestamp": datetime.now()
103
- }
104
-
105
- @app.post("/generate", response_model=TaskResponse)
106
- async def generate(
107
- request: GenerateNotesRequest,
108
- background_tasks: BackgroundTasks,
109
- current_user: User = Depends(get_current_user),
110
- ):
111
- task_id = str(uuid.uuid4())
112
- user_id = current_user.id
113
-
114
- tasks[task_id] = {
115
- "status": TaskStatus.PENDING,
116
- "message": "Initializing...",
117
- "youtube_url": str(request.youtube_url),
118
- "user_id": user_id,
119
- "created_at": datetime.now(),
120
- }
121
-
122
- background_tasks.add_task(
123
- process_video_and_save,
124
- task_id,
125
- str(request.youtube_url),
126
- request.language,
127
- user_id,
128
- )
129
-
130
- return TaskResponse(
131
- task_id=task_id,
132
- status=TaskStatus.PENDING,
133
- message="Generation started successfully.",
134
- )
135
-
136
- @app.get("/status/{task_id}")
137
- async def get_task_status(task_id: str):
138
- if task_id not in tasks:
139
- raise HTTPException(status_code=404, detail="Task not found")
140
- return tasks[task_id]
141
-
142
- # --- منطق معالجة الفيديو (Logic) ---
143
-
144
- async def transcribeAudio(task_id: str, youtube_url: str, language: str):
145
- audio_file = None
146
- downloader = YouTubeDownloader() # يستخدم النسخة الجديدة في src/api/downloader.py
147
-
148
- # استخراج الـ Video ID للتعامل مع الملفات
149
- video_id_match = re.search(r"(?:v=|youtu\.be/)([A-Za-z0-9_-]{11})", youtube_url)
150
- video_id = video_id_match.group(1) if video_id_match else task_id
151
-
152
- video_info = {"title": "YouTube Video", "duration": 0}
153
-
154
- tasks[task_id]["status"] = TaskStatus.TRANSCRIBING
155
- fetcher = TranscriptFetcher()
156
-
157
- try:
158
- # محاولة جلب الترجمة الجاهزة أولاً (أسرع)
159
- transcript_text = fetcher.fetch_transcript(youtube_url, languages=[language, 'ar', 'en'])
160
- except Exception as e:
161
- logger.error(f"Transcript fetching failed: {e}")
162
- transcript_text = None
163
-
164
- if transcript_text:
165
- logger.info(f"✅ Using direct YouTube transcript for {video_id}")
166
- else:
167
- # لو فشل نجلب الصوت باستخدام yt-dlp + POT Solver
168
- logger.info(f"🚀 Falling back to audio download + Whisper for {video_id}")
169
- tasks[task_id]["status"] = TaskStatus.DOWNLOADING
170
-
171
- audio_file = downloader.download_audio(youtube_url, video_id)
172
-
173
- if not audio_file:
174
- raise Exception("Failed to download audio even with POT Solver.")
175
-
176
- tasks[task_id]["status"] = TaskStatus.TRANSCRIBING
177
- transcriber = WhisperTranscriber()
178
- transcript_data = transcriber.transcribe(str(audio_file), language=language)
179
- transcript_text = transcript_data["text"]
180
-
181
- return transcript_text, video_info, audio_file, downloader
182
-
183
- async def process_video_and_save(task_id: str, youtube_url: str, language: str, user_id: str):
184
- audio_file = None
185
- downloader = None
186
- try:
187
- # 1. الحصول على النص (Transcribe)
188
- transcript_text, video_info, audio_file, downloader = await transcribeAudio(
189
- task_id, youtube_url, language
190
- )
191
-
192
- # 2. توليد الملخص (Generate Summary)
193
- tasks[task_id]["status"] = TaskStatus.GENERATING_NOTES
194
- note_gen = NoteGenerator()
195
- summary_json = note_gen.generateSummary(transcript_text, video_info["title"])
196
-
197
- # 3. استخراج أهم النقاط (Action Items)
198
- action_items_json = note_gen.extractActionItems(transcript_text, video_info["title"])
199
-
200
- combined_json = {
201
- **summary_json,
202
- "action_items": action_items_json.get("action_items", [])
203
- }
204
-
205
- final_notes = note_gen.format_final_notes(
206
- note_gen.format_notes_to_markdown(combined_json),
207
- video_info["title"],
208
- youtube_url,
209
- video_info["duration"],
210
- )
211
-
212
- # 4. الحفظ في Firebase
213
- db = get_firebase_db()
214
- if db:
215
- note_data = {
216
- "user_id": user_id,
217
- "video_url": youtube_url,
218
- "video_title": video_info.get("title", "YouTube Video"),
219
- "summary_content": final_notes,
220
- "created_at": datetime.utcnow()
221
- }
222
- db.collection("notes").add(note_data)
223
-
224
- tasks[task_id]["notes"] = final_notes
225
- tasks[task_id]["status"] = TaskStatus.COMPLETED
226
- logger.info(f"✅ Task {task_id} completed successfully!")
227
-
228
- except Exception as e:
229
- logger.error(f"❌ Task {task_id} failed: {str(e)}")
230
- tasks[task_id]["status"] = TaskStatus.FAILED
231
- tasks[task_id]["message"] = f"Error: {str(e)}"
232
- finally:
233
- # تنظيف الملفات المؤقتة
234
- if downloader and audio_file:
235
- downloader.cleanup(audio_file)
 
 
 
 
 
 
 
1
  from contextlib import asynccontextmanager
2
+ from fastapi import FastAPI
 
3
  from fastapi.middleware.cors import CORSMiddleware
 
 
 
 
4
  from src.api.pot_server import pot_server
 
 
 
 
 
 
 
 
 
 
5
  from src.api.notes_routes import router as notes_router
6
+ from src.api.auth_routes import router as auth_router
7
+ # استورد أي routers تانية عندك هنا
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  @asynccontextmanager
10
  async def lifespan(app: FastAPI):
11
+ print("🚀 Starting POT solver server...")
12
+ pot_server.start()
 
 
 
 
 
13
  yield
14
+ print("🛑 Stopping POT solver server...")
 
15
  pot_server.stop()
16
 
17
+ app = FastAPI(title="AIdea API", lifespan=lifespan)
18
 
19
+ # تفعيل الـ CORS عشان الـ Flutter Web يشتغل
20
  app.add_middleware(
21
  CORSMiddleware,
22
  allow_origins=["*"],
 
25
  allow_headers=["*"],
26
  )
27
 
28
+ # تسجيل المسارات (مهم جداً عشان الـ 404 تختفي)
 
29
  app.include_router(notes_router)
30
+ app.include_router(auth_router)
 
31
 
32
  @app.get("/")
33
  def read_root():
34
+ return {"message": "AIdea API is Live and POT is working!"}