from fastapi import FastAPI, File, UploadFile, Form, HTTPException, Request, Depends from fastapi.staticfiles import StaticFiles from fastapi.responses import HTMLResponse from fastapi.responses import JSONResponse, FileResponse from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from pydantic import BaseModel, HttpUrl from typing import Optional import uvicorn from fastapi.middleware.cors import CORSMiddleware from utils import read_file, fetch_job_description, optimize_resume_api import logging import os import json from supabase import create_client from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates # Set up templates templates = Jinja2Templates(directory="static") # Configuration variables (use environment variables in production) SUPABASE_URL = os.getenv("SUPABASE_URL") SUPABASE_KEY = os.getenv("SUPABASE_KEY") # Initialize Supabase client supabase = create_client(SUPABASE_URL, SUPABASE_KEY) API_SECRET = os.getenv("API_SECRET") # Set up logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) app = FastAPI(title="Resume Optimizer API") app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"]) security = HTTPBearer() class OptimizationResponse(BaseModel): optimized_resume: str changes_made: str metadata: dict class ErrorResponse(BaseModel): detail: str def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)): token = credentials.credentials if token != API_SECRET: raise HTTPException(status_code=401, detail="Invalid authentication token") return token import re def extract_xml_content(text, tag): pattern = f"<{tag}>(.*?)" matches = re.findall(pattern, text, re.DOTALL) return matches @app.post("/api/v1/optimize-resume", response_model=OptimizationResponse, responses={400: {"model": ErrorResponse}, 401: {"model": ErrorResponse}, 500: {"model": ErrorResponse}}) async def optimize_resume( resume: Optional[UploadFile] = File(None), resumeText: Optional[str] = Form(None), jobDescription: Optional[str] = Form(None), jobDescriptionUrl: Optional[HttpUrl] = Form(None), token: str = Depends(verify_token) ): try: # Input validation if (resume is None) == (resumeText is None): raise ValueError("Provide either resume file or resume text, but not both") if (jobDescription is None) == (jobDescriptionUrl is None): raise ValueError("Provide either job description text or URL, but not both") # Process resume if resume: resume_content = read_file(resume) else: resume_content = resumeText # Process job description if jobDescription: job_description_content = jobDescription else: job_description_content = fetch_job_description(jobDescriptionUrl) # Perform optimization output = optimize_resume_api(resume_content, job_description_content) optimized_resume = extract_xml_content(output, "optimized_resume") changes_made = extract_xml_content(output, "changes_made") # Prepare the response response_data = OptimizationResponse( optimized_resume=optimized_resume[0] if optimized_resume else "", changes_made=changes_made[0] if changes_made else "", metadata={ "original_resume": resume_content, "original_jd": job_description_content } ) return response_data except ValueError as ve: logger.error(f"ValueError occurred: {str(ve)}", exc_info=True) raise HTTPException(status_code=400, detail=str(ve)) except Exception as e: logger.error(f"Unexpected error occurred: {str(e)}", exc_info=True) raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}") # Mount the static directory static_dir = os.path.join(os.path.dirname(__file__), "static") app.mount("/static", StaticFiles(directory=static_dir), name="static") # Set up templates templates = Jinja2Templates(directory="static") app.mount("/iresearcher-v3", StaticFiles(directory="static/iresearcher", html=True), name="iresearcher") app.mount("/dashboard", StaticFiles(directory="static", html=True), name="mult-agent-auth") # App1 route @app.get("/iresearcher-v2", response_class=HTMLResponse) async def iresearcher_v2(request: Request): try: # Debug: Print the current working directory print(f"Current working directory: {os.getcwd()}") # Debug: Print the full path of the template template_path = os.path.join(static_dir, "iresearcher", "index.html") print(f"Full template path: {template_path}") # Debug: Check if the file exists if not os.path.exists(template_path): raise HTTPException(status_code=404, detail=f"Template not found: {template_path}") # Debug: Print the content of the template file with open(template_path, 'r') as f: print(f"Template content:\n{f.read()}") # Render the template return templates.TemplateResponse("iresearcher/index.html", {"request": request}) except Exception as e: # Log any exceptions print(f"Error rendering template: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.get("/js/{path:path}") async def send_js(path: str): file_path = f"static/js/apps-hub/{path}" if os.path.exists(file_path): return FileResponse(file_path) raise HTTPException(status_code=404, detail="File not found") @app.get("/css/{path:path}") async def send_css(path: str): file_path = f"static/css/apps-hub/{path}" if os.path.exists(file_path): return FileResponse(file_path) raise HTTPException(status_code=404, detail="File not found") @app.get("/svg/{path:path}") async def send_svg(path: str): file_path = f"static/svg/{path}" if os.path.exists(file_path): return FileResponse(file_path) raise HTTPException(status_code=404, detail="File not found") @app.get("/png/{path:path}") async def send_png(path: str): file_path = f"static/png/{path}" if os.path.exists(file_path): return FileResponse(file_path) raise HTTPException(status_code=404, detail="File not found") # Add a route for serving the HTML file @app.get("/", response_class=HTMLResponse) async def serve_landing_page(): with open("static/landing-page.html", "r") as file: content = file.read() return HTMLResponse(content=content) # Add a route for serving the HTML file @app.get("/career", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/resume-optimizer.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/followup-agent", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/followup-agent.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/digiyatra", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/digiyatra.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/auth", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/auth.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/auth-success", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/auth-success.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/app-selector", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/v0/app-selector.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/multi-agent", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/multi-agent.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/medium-report", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/medium-report.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/iresearcher", response_class=HTMLResponse) async def serve_iresearcher(): with open("static/iresearcher.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/graph-maker", response_class=HTMLResponse) async def serve_iresearcher(): with open("static/graph-maker.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/indic-tts", response_class=HTMLResponse) async def serve_indic_tts(): with open("static/indic-text-to-speech.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/presentation", response_class=HTMLResponse) async def presentation(): with open("static/presentation-agent.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/dashboard", response_class=HTMLResponse) async def presentation(): with open("static/mult-agent-auth.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/login", response_class=HTMLResponse) async def presentation(): with open("static/login.html", "r") as file: content = file.read() return HTMLResponse(content=content) @app.get("/file-convert", response_class=HTMLResponse) async def serve_resume_optimizer(): with open("static/file-convert.html", "r") as file: content = file.read() return HTMLResponse(content=content) from fastapi import HTTPException from pydantic import BaseModel class EmailCheck(BaseModel): email: str @app.post("/check-allowlist") async def check_allowlist(email_check: EmailCheck): logging.debug(f"Checking email: {email_check.email}") try: # Fetch allowlist from Supabase, including email and access_type response = supabase.table('email_allowlist').select('email,access_type').eq('email', email_check.email).execute() if response.data: user_data = response.data[0] logging.debug(f"Email is in allowlist with access type: {user_data['access_type']}") try: # Read the appropriate JSON file based on access type if user_data['access_type'] == 'team': file_name = "app_urls_team.json" else: file_name = "app_urls_public.json" # Try to read the JSON file with UTF-8 encoding with open(file_name, "r", encoding="utf-8") as file: app_data = json.load(file) except UnicodeDecodeError: # If UTF-8 fails, try with ISO-8859-1 encoding with open(file_name, "r", encoding="iso-8859-1") as file: app_data = json.load(file) return { "allowed": True, "access_type": user_data['access_type'], "app_data": app_data } else: logging.debug("Email is not in allowlist") return {"allowed": False} except Exception as e: logging.error(f"Error: {e}") raise HTTPException(status_code=500, detail=str(e)) @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc: HTTPException): return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail}) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000, debug=True)