matsuap commited on
Commit
77f281e
·
verified ·
1 Parent(s): ed6e189

Upload folder using huggingface_hub

Browse files
api/canvas.py CHANGED
@@ -1,76 +1,104 @@
1
- from fastapi import APIRouter, Depends, HTTPException, status, Response
2
  from sqlalchemy.orm import Session
3
  from typing import List, Optional
4
  import logging
5
  from datetime import datetime
6
 
7
- from core.database import get_db
8
  from models import db_models
9
  from models.schemas import CanvasCreateRequest, CanvasEditRequest, CanvasResponse
10
  from services.canvas_service import canvas_service
11
  from api.auth import get_current_user
 
12
 
13
  router = APIRouter(prefix="/api/canvas", tags=["Canvas - Collaborative Editing"])
14
  logger = logging.getLogger(__name__)
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  @router.post("/create", response_model=CanvasResponse)
17
  async def create_canvas(
18
  request: CanvasCreateRequest,
 
19
  current_user: db_models.User = Depends(get_current_user),
20
  db: Session = Depends(get_db)
21
  ):
22
  """
23
- Create a new Canvas entry.
24
- Pass file_key to extract text and generate an initial Markdown summary.
25
  """
26
- try:
27
- source_id = None
28
- if request.file_key:
29
- source = db.query(db_models.Source).filter(
30
- db_models.Source.s3_key == request.file_key,
31
- db_models.Source.user_id == current_user.id
32
- ).first()
33
- if not source:
34
- raise HTTPException(status_code=404, detail="Source file not found")
35
- source_id = source.id
 
 
 
 
 
 
 
 
 
 
36
 
37
- # Create initial record
38
- title = request.title or f"Canvas {datetime.now().strftime('%Y-%m-%d %H:%M')}"
39
- db_canvas = db_models.Canvas(
40
- title=title,
41
- user_id=current_user.id,
42
- source_id=source_id,
43
- status="processing"
44
- )
45
- db.add(db_canvas)
46
- db.commit()
47
- db.refresh(db_canvas)
48
-
49
- try:
50
- # Generate summary
51
- content = await canvas_service.generate_canvas_summary(
52
- file_key=request.file_key,
53
- text_input=request.text_input
54
- )
55
-
56
- db_canvas.text = content
57
- db_canvas.status = "completed"
58
- db.commit()
59
- db.refresh(db_canvas)
60
-
61
- return db_canvas
62
-
63
- except Exception as e:
64
- db_canvas.status = "failed"
65
- db_canvas.error_message = str(e)
66
- db.commit()
67
- raise HTTPException(status_code=500, detail=f"Generation failed: {str(e)}")
68
 
69
- except HTTPException:
70
- raise
71
- except Exception as e:
72
- logger.error(f"Error creating canvas: {e}")
73
- raise HTTPException(status_code=500, detail=str(e))
74
 
75
  @router.get("/", response_model=List[CanvasResponse])
76
  async def list_canvases(
 
1
+ from fastapi import APIRouter, Depends, HTTPException, status, Response, BackgroundTasks
2
  from sqlalchemy.orm import Session
3
  from typing import List, Optional
4
  import logging
5
  from datetime import datetime
6
 
7
+ from core.database import get_db, SessionLocal
8
  from models import db_models
9
  from models.schemas import CanvasCreateRequest, CanvasEditRequest, CanvasResponse
10
  from services.canvas_service import canvas_service
11
  from api.auth import get_current_user
12
+ from api.websocket_routes import manager
13
 
14
  router = APIRouter(prefix="/api/canvas", tags=["Canvas - Collaborative Editing"])
15
  logger = logging.getLogger(__name__)
16
 
17
+ async def run_canvas_generation(canvas_id: int, request: CanvasCreateRequest, user_id: int):
18
+ """Background task for canvas summary generation"""
19
+ db = SessionLocal()
20
+ connection_id = f"user_{user_id}"
21
+ try:
22
+ db_canvas = db.query(db_models.Canvas).filter(db_models.Canvas.id == canvas_id).first()
23
+ if not db_canvas: return
24
+
25
+ # Call AI service
26
+ content = await canvas_service.generate_canvas_summary(
27
+ file_key=request.file_key,
28
+ text_input=request.text_input
29
+ )
30
+
31
+ if not content:
32
+ raise Exception("AI failed to generate canvas content")
33
+
34
+ db_canvas.text = content
35
+ db_canvas.status = "completed"
36
+ db.commit()
37
+
38
+ # Notify via WebSocket
39
+ await manager.send_result(connection_id, {
40
+ "type": "canvas",
41
+ "id": db_canvas.id,
42
+ "status": "completed",
43
+ "title": db_canvas.title
44
+ })
45
+
46
+ except Exception as e:
47
+ logger.error(f"Background canvas generation failed: {e}")
48
+ db_canvas = db.query(db_models.Canvas).filter(db_models.Canvas.id == canvas_id).first()
49
+ if db_canvas:
50
+ db_canvas.status = "failed"
51
+ db_canvas.error_message = str(e)
52
+ db.commit()
53
+ await manager.send_error(connection_id, f"Canvas generation failed: {str(e)}")
54
+ finally:
55
+ db.close()
56
+
57
  @router.post("/create", response_model=CanvasResponse)
58
  async def create_canvas(
59
  request: CanvasCreateRequest,
60
+ background_tasks: BackgroundTasks,
61
  current_user: db_models.User = Depends(get_current_user),
62
  db: Session = Depends(get_db)
63
  ):
64
  """
65
+ Initiates Canvas creation in the background.
 
66
  """
67
+ source_id = None
68
+ if request.file_key:
69
+ source = db.query(db_models.Source).filter(
70
+ db_models.Source.s3_key == request.file_key,
71
+ db_models.Source.user_id == current_user.id
72
+ ).first()
73
+ if not source:
74
+ raise HTTPException(status_code=403, detail="Not authorized to access this file")
75
+ source_id = source.id
76
+
77
+ # Create initial record
78
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
79
+
80
+ # Priority: 1. File-based name, 2. User Title (if not default 'string'), 3. Default timestamp
81
+ if file_base:
82
+ title = f"Canvas-{file_base}"
83
+ elif request.title and request.title != "string":
84
+ title = request.title
85
+ else:
86
+ title = f"Canvas {datetime.now().strftime('%Y-%m-%d %H:%M')}"
87
 
88
+ db_canvas = db_models.Canvas(
89
+ title=title,
90
+ user_id=current_user.id,
91
+ source_id=source_id,
92
+ status="processing"
93
+ )
94
+ db.add(db_canvas)
95
+ db.commit()
96
+ db.refresh(db_canvas)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
+ # Offload to background task
99
+ background_tasks.add_task(run_canvas_generation, db_canvas.id, request, current_user.id)
100
+
101
+ return db_canvas
 
102
 
103
  @router.get("/", response_model=List[CanvasResponse])
104
  async def list_canvases(
api/flashcards.py CHANGED
@@ -101,7 +101,15 @@ async def generate_flashcards(
101
  source_id = source.id
102
 
103
  # Create initial processing record
104
- title = request.topic if request.topic else f"Flashcards {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
 
 
 
 
 
 
 
 
105
  db_set = db_models.FlashcardSet(
106
  title=title,
107
  difficulty=request.difficulty,
 
101
  source_id = source.id
102
 
103
  # Create initial processing record
104
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
105
+
106
+ # Priority: 1. File-based name, 2. User Topic (if not default 'string'), 3. Default timestamp
107
+ if file_base:
108
+ title = f"Flashcard-{file_base}"
109
+ elif request.topic and request.topic != "string":
110
+ title = request.topic
111
+ else:
112
+ title = f"Flashcards {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
113
  db_set = db_models.FlashcardSet(
114
  title=title,
115
  difficulty=request.difficulty,
api/mindmaps.py CHANGED
@@ -75,7 +75,15 @@ async def generate_mindmap(
75
  source_id = source.id
76
 
77
  # Create initial processing record
78
- title = request.title if request.title else (request.file_key.split('/')[-1] if request.file_key else f"Mind Map {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}")
 
 
 
 
 
 
 
 
79
  db_mindmap = db_models.MindMap(
80
  title=title,
81
  user_id=current_user.id,
 
75
  source_id = source.id
76
 
77
  # Create initial processing record
78
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
79
+
80
+ # Priority: 1. File-based name, 2. User Title (if not default 'string'), 3. Default timestamp
81
+ if file_base:
82
+ title = f"Mind Map-{file_base}"
83
+ elif request.title and request.title != "string":
84
+ title = request.title
85
+ else:
86
+ title = f"Mind Map {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
87
  db_mindmap = db_models.MindMap(
88
  title=title,
89
  user_id=current_user.id,
api/podcast.py CHANGED
@@ -159,8 +159,10 @@ async def generate_podcast(
159
  source_id = source.id
160
 
161
  # 2. Create pending record
 
 
162
  db_podcast = db_models.Podcast(
163
- title=f"Podcast {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}",
164
  user_id=current_user.id,
165
  source_id=source_id,
166
  status="processing"
 
159
  source_id = source.id
160
 
161
  # 2. Create pending record
162
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
163
+ title = f"Podcast-{file_base}" if file_base else f"Podcast {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
164
  db_podcast = db_models.Podcast(
165
+ title=title,
166
  user_id=current_user.id,
167
  source_id=source_id,
168
  status="processing"
api/quizzes.py CHANGED
@@ -104,7 +104,15 @@ async def generate_quiz(
104
  source_id = source.id
105
 
106
  # Create initial processing record
107
- title = request.topic if request.topic else f"Quiz {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
 
 
 
 
 
 
 
 
108
  db_set = db_models.QuizSet(
109
  title=title,
110
  difficulty=request.difficulty,
 
104
  source_id = source.id
105
 
106
  # Create initial processing record
107
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
108
+
109
+ # Priority: 1. File-based name, 2. User Topic (if not default 'string'), 3. Default timestamp
110
+ if file_base:
111
+ title = f"Quiz-{file_base}"
112
+ elif request.topic and request.topic != "string":
113
+ title = request.topic
114
+ else:
115
+ title = f"Quiz {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
116
  db_set = db_models.QuizSet(
117
  title=title,
118
  difficulty=request.difficulty,
api/reports.py CHANGED
@@ -35,12 +35,12 @@ async def run_report_generation(report_id: int, request: ReportGenerateRequest,
35
  if not content:
36
  raise Exception("AI failed to generate report content")
37
 
38
- # Extract title (usually the first line)
39
- title = content.split('\n')[0].replace('#', '').strip()
40
- if not title or len(title) < 3:
41
- title = f"Report {request.format_key}"
42
-
43
- db_report.title = title
44
  db_report.content = content
45
  db_report.status = "completed"
46
  db.commit()
@@ -109,7 +109,8 @@ async def generate_report(
109
  source_id = source.id
110
 
111
  # Create initial processing record
112
- title = f"Report {request.format_key} {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
 
113
  db_report = db_models.Report(
114
  title=title,
115
  format_key=request.format_key,
 
35
  if not content:
36
  raise Exception("AI failed to generate report content")
37
 
38
+ if not db_report.title or "report-" not in db_report.title:
39
+ # Extract title (usually the first line)
40
+ extracted_title = content.split('\n')[0].replace('#', '').strip()
41
+ if not extracted_title or len(extracted_title) < 3:
42
+ extracted_title = f"Report {request.format_key}"
43
+ db_report.title = extracted_title
44
  db_report.content = content
45
  db_report.status = "completed"
46
  db.commit()
 
109
  source_id = source.id
110
 
111
  # Create initial processing record
112
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
113
+ title = f"report-{file_base}" if file_base else f"Report {request.format_key} {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
114
  db_report = db_models.Report(
115
  title=title,
116
  format_key=request.format_key,
api/video_generator.py CHANGED
@@ -43,7 +43,8 @@ async def run_video_generation(summary_id: int, request: VideoSummaryGenerateReq
43
  voice_name=request.voice_name
44
  )
45
 
46
- db_summary.title = result["title"]
 
47
  db_summary.s3_key = result["s3_key"]
48
  db_summary.s3_url = result["s3_url"]
49
  db_summary.status = "completed"
@@ -89,7 +90,8 @@ async def generate_video_summary(
89
  raise HTTPException(status_code=403, detail="Not authorized to access this file")
90
 
91
  # Create initial processing record
92
- title = f"Video Summary {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
 
93
  db_summary = db_models.VideoSummary(
94
  title=title,
95
  user_id=current_user.id,
 
43
  voice_name=request.voice_name
44
  )
45
 
46
+ if not db_summary.title or "Video-" not in db_summary.title:
47
+ db_summary.title = result["title"]
48
  db_summary.s3_key = result["s3_key"]
49
  db_summary.s3_url = result["s3_url"]
50
  db_summary.status = "completed"
 
90
  raise HTTPException(status_code=403, detail="Not authorized to access this file")
91
 
92
  # Create initial processing record
93
+ file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
94
+ title = f"video-{file_base}" if file_base else f"Video Summary {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}"
95
  db_summary = db_models.VideoSummary(
96
  title=title,
97
  user_id=current_user.id,