Gurucool_Test / api /endpoints /class_session.py
ashwinR's picture
Upload 245 files
b7a7f32
import json
import os
from hashlib import sha256
from typing import Any, List
import aiofiles
from fastapi import (
APIRouter,
Depends,
FastAPI,
File,
Form,
HTTPException,
UploadFile,
WebSocket,
WebSocketDisconnect,
)
from fastapi.encoders import jsonable_encoder
from fastapi.responses import FileResponse, HTMLResponse
from sqlalchemy.orm import Session
from starlette.status import HTTP_406_NOT_ACCEPTABLE
from core.config import settings
from core.security import get_uid_hash
from core.websocket import ws, ChatMessageTypes
from cruds import crud_class_session, crud_file, crud_user
from forms.class_session import ClassSessionCreateForm
from models import ClassSession as ClassSessionModel
from models import File as FileModel
from schemas.class_session import (
ClassSession,
ClassSessionCreate,
ClassSessionReturn,
ClassSessionUpdate,
ClassSessionTeacherReturn,
AttendanceUpdate,
ParticipantOfClassSession,
)
from schemas.file import FileCreate
from schemas.group import GroupStudentReturn
from utils import deps
from utils.deps import get_current_active_teacher_or_above, get_current_active_user, get_current_active_ws_user
import datetime
import cruds
router = APIRouter()
@router.get("/", response_model=List[ClassSessionReturn])
def get_class_session(
db: Session = Depends(deps.get_db),
user=Depends(get_current_active_user),
skip: int = 0,
limit: int = 100,
) -> Any:
class_sessions = crud_class_session.get_user_class_session(db, user=user)
return class_sessions
@router.get("/active", response_model=List[ClassSessionReturn])
def get_active_class_session(
db: Session = Depends(deps.get_db),
user=Depends(get_current_active_user),
) -> Any:
class_sessions = crud_class_session.get_user_class_session(db, user=user)
active_class_sessions = []
for class_session in class_sessions:
if(class_session.start_time < datetime.datetime.now() and class_session.end_time > datetime.datetime.now()):
active_class_sessions.append(class_session)
return active_class_sessions
@router.post("/", response_model=ClassSession)
async def create_class_session(
db: Session = Depends(deps.get_db),
user=Depends(get_current_active_teacher_or_above),
*,
form: ClassSessionCreateForm = Depends(),
) -> Any:
course_id = None
for item in user.teacher_group:
course_id = item.course.id if item.group.id == form.group else course_id
if(course_id == None):
raise HTTPException(
status_code=HTTP_406_NOT_ACCEPTABLE, detail="Invalid group id!")
data = ClassSessionCreate(
start_time=form.start_time,
end_time=form.end_time,
instructor=[user.id]+(form.instructor or []),
description=form.description,
group_id=form.group,
course_id=course_id,
)
class_session = crud_class_session.create(db, obj_in=data)
hasher = sha256()
hasher.update(bytes(f"{class_session.id}_{settings.SECRET_KEY}", "utf-8"))
db_folder_path = os.path.join("class_files", hasher.hexdigest())
folder_path = os.path.join(settings.UPLOAD_DIR_ROOT, db_folder_path)
if not os.path.exists(folder_path):
os.makedirs(folder_path)
if form.file:
for file in form.file:
file_path = os.path.join(folder_path, file.filename)
async with aiofiles.open(file_path, mode="wb") as f:
content = await file.read()
await f.write(content)
db.add(
FileModel(
name=file.filename,
path=db_folder_path,
file_type=file.content_type,
description=None,
class_session=class_session,
)
)
db.commit()
return class_session
@router.get("/{id}/", response_model=ClassSessionReturn)
def get_specific_class_session(
db: Session = Depends(deps.get_db),
user=Depends(get_current_active_user),
*,
id: int,
) -> Any:
class_session = crud_class_session.get_user_class_session(
db=db, user=user, id=id)
return class_session
@router.get("/{id}/participants", response_model=List[ParticipantOfClassSession])
def get_specific_class_session(
db: Session = Depends(deps.get_db),
current_user=Depends(get_current_active_user),
*,
id: int,
) -> Any:
class_session = crud_class_session.get(db, id)
group = cruds.crud_group.get(db, class_session.group_id)
participants = group.student + class_session.instructor
return participants
@router.get("/{id}/attendance", response_model=ClassSessionTeacherReturn)
def get_class_session_with_attendance(
db: Session = Depends(deps.get_db),
user=Depends(get_current_active_teacher_or_above),
*,
id: int,
) -> Any:
class_session = crud_class_session.get_user_class_session(
db=db, user=user, id=id)
return class_session
@router.put("/{id}/", response_model=ClassSession)
def update_class_session(
db: Session = Depends(deps.get_db), *, id: int, obj_in: ClassSessionUpdate
) -> Any:
class_session = crud_class_session.get(db, id)
class_session = crud_class_session.update(
db, db_obj=class_session, obj_in=obj_in)
return class_session
@router.put("/{class_id}/files")
async def update_class_session(
db: Session = Depends(deps.get_db),
*,
class_id: int,
files: List[UploadFile] = File(None),
) -> Any:
class_session = crud_class_session.get(db, class_id)
hasher = sha256()
hasher.update(bytes(f"{class_id}_{settings.SECRET_KEY}", "utf-8"))
db_folder_path = os.path.join("class_files", hasher.hexdigest())
folder_path = os.path.join(settings.UPLOAD_DIR_ROOT, db_folder_path)
if not os.path.exists(folder_path):
os.makedirs(folder_path)
for file in files:
file_path = os.path.join(folder_path, file.filename)
async with aiofiles.open(file_path, mode="wb") as f:
content = await file.read()
await f.write(content)
db.add(
FileModel(
name=file.filename,
path=db_folder_path,
file_type=file.content_type,
description=None,
class_session=class_session,
)
)
db.commit()
return {"msg": "success"}
@router.put("/{id}/attendance")
def attendance_of_class_session(
db: Session = Depends(deps.get_db),
*,
id: int,
obj_in: AttendanceUpdate,
current_teacher=Depends(get_current_active_teacher_or_above),
) -> Any:
class_session = crud_class_session.get_user_class_session(
db=db, user=current_teacher, id=id
)
if not class_session:
raise HTTPException(
status_code=403, detail="Class session access denied!")
class_session = crud_class_session.attendance_update(
db, db_obj=class_session, obj_in=obj_in
)
return {"msg": "success"}
# @router.post("/{id}/file/")
# async def create_upload_files(
# db: Session = Depends(deps.get_db),
# files: List[UploadFile] = File(...),
# current_teacher=Depends(
# get_current_active_teacher_or_above
# ), # FIXME : Get current user ?
# *,
# id: int,
# ):
# class_session = crud_class_session.get_user_class_session(
# db=db, user=current_teacher, id=id
# )
# if not class_session:
# raise HTTPException(status_code=403, detail="Error ID: 100") # Access denied!
# FILE_PATH = os.path.join("static", settings.UPLOAD_DIR_ROOT)
# working_directory = os.getcwd()
# FILE_PATH = os.path.join(working_directory, FILE_PATH)
# for file in files:
# filename = f"{FILE_PATH}/{id}/{file.filename}"
# async with aiofiles.open(filename, mode="wb") as f:
# content = await file.read()
# await f.write(content)
# obj_in = ClassSessionUpdate(file=[file.filename for file in files])
# crud_class_session.update(db=db, db_obj=class_session, obj_in=obj_in)
# return {"msg": "success"}
@router.websocket("/ws/{id}/")
async def websocket_endpoint(
db: Session = Depends(deps.get_db),
*,
websocket: WebSocket,
req_user=Depends(get_current_active_ws_user),
id: int,
):
user_id = req_user.id
class_session = crud_class_session.get_user_class_session(
db=db, user=req_user, id=id
)
if not class_session:
raise HTTPException(
status_code=403, detail="Error Code: 144"
) # User doesn't have access to classsession
await ws.connect(websocket=websocket, class_session_id=id, user_id=user_id)
try:
while True:
data = await websocket.receive_json()
if data.get("msg_type") == ChatMessageTypes.MESSAGE_HISTORY.value:
await ws.send_history(websocket, id)
else:
await ws.message(
websocket=websocket,
user_id=user_id,
class_session_id=id,
message=data.get("message"),
anon=data.get("anon"),
)
except WebSocketDisconnect:
await ws.disconnect(websocket, class_session_id=id, user_id=user_id)