@router.post("/import") async def import_subjects(file: UploadFile = File(...), user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): fname = (file.filename or "").lower() if fname.endswith(".json"): raise HTTPException(400, "Only CSV/TXT subject imports are supported") content = (await file.read()).decode("utf-8", errors="replace") subjects = [] if fname.endswith(".csv"): for row in csv.reader(io.StringIO(content)): if row and row[0].strip() and not row[0].lower().startswith(("subject", "subject line")): subjects.append(row[0].strip()) else: for line in content.splitlines(): line = line.strip() if line and not line.startswith("#") and not line.lower().startswith("subject"): subjects.append(line) subjects = subjects[:settings.MAX_SUBJECTS] existing = set((await db.execute(select(SubjectLine.subject).where( SubjectLine.user_id == user.id))).scalars().all()) added = 0 for s in subjects: if s not in existing: db.add(SubjectLine(user_id=user.id, subject=s[:500])) added += 1 await db.commit() return {"ok": True, "seen": len(subjects), "added": added} @router.get("/export") async def export_subjects(user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): rows = (await db.execute(select(SubjectLine).where(SubjectLine.user_id == user.id) .order_by(SubjectLine.id))).scalars().all() buf = io.StringIO() w = csv.writer(buf) w.writerow(["subject", "use_count"]) for s in rows: w.writerow([s.subject, s.use_count]) buf.seek(0) return StreamingResponse(iter([buf.getvalue()]), media_type="text/csv", headers={"Content-Disposition": "attachment; filename=subjects.csv"}) @router.put("/{subject_id}") async def edit_subject(subject_id: int, payload: SubjectIn, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): row = await db.get(SubjectLine, subject_id) if not row or row.user_id != user.id: raise HTTPException(404, "Not found") row.subject = payload.subject.strip()[:500] await db.commit() return {"ok": True} @router.delete("/{subject_id}") async def delete_subject(subject_id: int, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): row = await db.get(SubjectLine, subject_id) if not row or row.user_id != user.id: raise HTTPException(404, "Not found") await db.delete(row) await db.commit() return {"ok": True} @router.post("/clear-all") async def clear_all(user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): await db.execute(sa_delete(SubjectLine).where(SubjectLine.user_id == user.id))