added file and link create
This commit is contained in:
@@ -41,6 +41,9 @@ from src.services.background_jobs import (
|
||||
)
|
||||
from src.services.db_job_manager import job_manager
|
||||
from src.services.storage_service import storage
|
||||
from src.services.link_extractor import LinkExtractor, LinkExtractionError
|
||||
from src.services.file_extractor import FileExtractor, FileExtractionError
|
||||
from src.agents.link_topic_builder import LinkTopicBuilderAgent
|
||||
|
||||
# Router for user frontend
|
||||
user_router = APIRouter(tags=["user"])
|
||||
@@ -1813,6 +1816,64 @@ async def create_post_page(request: Request):
|
||||
})
|
||||
|
||||
|
||||
@user_router.get("/create/link-wizard", response_class=HTMLResponse)
|
||||
async def create_post_link_page(request: Request):
|
||||
"""Create post from link wizard page."""
|
||||
session = require_user_session(request)
|
||||
if not session:
|
||||
return RedirectResponse(url="/login", status_code=302)
|
||||
|
||||
# Check token limit for companies/employees
|
||||
limit_reached = False
|
||||
limit_message = ""
|
||||
if session.account_type in ("company", "employee") and session.company_id:
|
||||
can_create, error_msg, _, _ = await db.check_company_token_limit(UUID(session.company_id))
|
||||
limit_reached = not can_create
|
||||
limit_message = error_msg
|
||||
|
||||
user_id = UUID(session.user_id)
|
||||
profile_picture = await get_user_avatar(session, user_id)
|
||||
|
||||
return templates.TemplateResponse("create_post_link.html", {
|
||||
"request": request,
|
||||
"page": "create",
|
||||
"session": session,
|
||||
"user_id": session.user_id,
|
||||
"limit_reached": limit_reached,
|
||||
"limit_message": limit_message,
|
||||
"profile_picture": profile_picture
|
||||
})
|
||||
|
||||
|
||||
@user_router.get("/create/file-wizard", response_class=HTMLResponse)
|
||||
async def create_post_file_page(request: Request):
|
||||
"""Create post from file wizard page."""
|
||||
session = require_user_session(request)
|
||||
if not session:
|
||||
return RedirectResponse(url="/login", status_code=302)
|
||||
|
||||
# Check token limit for companies/employees
|
||||
limit_reached = False
|
||||
limit_message = ""
|
||||
if session.account_type in ("company", "employee") and session.company_id:
|
||||
can_create, error_msg, _, _ = await db.check_company_token_limit(UUID(session.company_id))
|
||||
limit_reached = not can_create
|
||||
limit_message = error_msg
|
||||
|
||||
user_id = UUID(session.user_id)
|
||||
profile_picture = await get_user_avatar(session, user_id)
|
||||
|
||||
return templates.TemplateResponse("create_post_file.html", {
|
||||
"request": request,
|
||||
"page": "create",
|
||||
"session": session,
|
||||
"user_id": session.user_id,
|
||||
"limit_reached": limit_reached,
|
||||
"limit_message": limit_message,
|
||||
"profile_picture": profile_picture
|
||||
})
|
||||
|
||||
|
||||
@user_router.get("/chat-create", response_class=HTMLResponse)
|
||||
async def chat_create_page(request: Request):
|
||||
"""Chat-based post creation page."""
|
||||
@@ -2063,6 +2124,117 @@ async def transcribe_audio(request: Request):
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@user_router.post("/api/link-extract")
|
||||
async def extract_link(request: Request):
|
||||
"""Extract context from a link and build a structured topic."""
|
||||
session = require_user_session(request)
|
||||
if not session:
|
||||
raise HTTPException(status_code=401, detail="Not authenticated")
|
||||
|
||||
# Check token limit for companies/employees
|
||||
if session.account_type in ("company", "employee") and session.company_id:
|
||||
can_create, error_msg, _, _ = await db.check_company_token_limit(UUID(session.company_id))
|
||||
if not can_create:
|
||||
raise HTTPException(status_code=429, detail=error_msg)
|
||||
|
||||
try:
|
||||
data = await request.json()
|
||||
url = (data.get("url") or "").strip()
|
||||
transcript = (data.get("transcript") or "").strip()
|
||||
manual_title = (data.get("title") or "").strip()
|
||||
source_type = (data.get("source_type") or "").strip()
|
||||
source_url = (data.get("source_url") or "").strip()
|
||||
|
||||
if transcript:
|
||||
source = {
|
||||
"source_url": source_url or url,
|
||||
"source_type": source_type or "manual",
|
||||
"title": manual_title or "Manuelles Transkript",
|
||||
"text": transcript
|
||||
}
|
||||
else:
|
||||
extractor = LinkExtractor()
|
||||
try:
|
||||
source = await extractor.extract(url)
|
||||
except LinkExtractionError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
builder = LinkTopicBuilderAgent()
|
||||
builder.set_tracking_context(
|
||||
operation="link_extract",
|
||||
user_id=session.user_id,
|
||||
company_id=session.company_id
|
||||
)
|
||||
topic = await builder.process(source)
|
||||
|
||||
return {"topic": topic, "source": source}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.exception(f"Link extraction failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@user_router.post("/api/file-extract")
|
||||
async def extract_file(request: Request):
|
||||
"""Extract context from an uploaded file and build a structured topic."""
|
||||
session = require_user_session(request)
|
||||
if not session:
|
||||
raise HTTPException(status_code=401, detail="Not authenticated")
|
||||
|
||||
# Check token limit for companies/employees
|
||||
if session.account_type in ("company", "employee") and session.company_id:
|
||||
can_create, error_msg, _, _ = await db.check_company_token_limit(UUID(session.company_id))
|
||||
if not can_create:
|
||||
raise HTTPException(status_code=429, detail=error_msg)
|
||||
|
||||
try:
|
||||
form = await request.form()
|
||||
upload: UploadFile = form.get("file") # type: ignore[assignment]
|
||||
if not upload:
|
||||
raise HTTPException(status_code=400, detail="Keine Datei hochgeladen.")
|
||||
|
||||
# Basic validation
|
||||
allowed_ext = {".pdf", ".docx", ".pptx", ".xlsx", ".txt", ".md", ".rtf"}
|
||||
filename = upload.filename or ""
|
||||
ext = Path(filename).suffix.lower()
|
||||
if not ext or ext not in allowed_ext:
|
||||
raise HTTPException(status_code=400, detail="Dateityp nicht unterstützt.")
|
||||
|
||||
file_bytes = await upload.read()
|
||||
max_bytes = 10 * 1024 * 1024 # 10 MB
|
||||
if len(file_bytes) > max_bytes:
|
||||
raise HTTPException(status_code=400, detail="Datei ist zu groß (max 10 MB).")
|
||||
|
||||
extractor = FileExtractor()
|
||||
try:
|
||||
text = extractor.extract_text(file_bytes, filename)
|
||||
except FileExtractionError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
source = {
|
||||
"source_url": "",
|
||||
"source_type": "file",
|
||||
"title": filename or "Datei",
|
||||
"text": text
|
||||
}
|
||||
|
||||
builder = LinkTopicBuilderAgent()
|
||||
builder.set_tracking_context(
|
||||
operation="file_extract",
|
||||
user_id=session.user_id,
|
||||
company_id=session.company_id
|
||||
)
|
||||
topic = await builder.process(source)
|
||||
|
||||
return {"topic": topic, "source": source}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.exception(f"File extraction failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@user_router.post("/api/hooks")
|
||||
async def generate_hooks(
|
||||
request: Request,
|
||||
|
||||
Reference in New Issue
Block a user