File size: 11,939 Bytes
efd6a61
90ca14a
 
9a99c76
efd6a61
 
 
75c5f1f
efd6a61
 
 
b1f421c
070678d
66cff10
876070a
 
 
 
 
 
589985f
 
 
efd6a61
589985f
 
 
efd6a61
589985f
 
 
efd6a61
589985f
 
 
 
 
efd6a61
97a1351
51c5935
 
 
97a1351
efd6a61
 
 
 
 
b1f421c
efd6a61
 
 
589985f
 
1cf0ddf
 
 
 
 
5d8720e
efd6a61
 
 
 
 
 
 
75c5f1f
efd6a61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1cf0ddf
 
 
 
 
97a1351
51c5935
 
 
1cf0ddf
 
 
97a1351
 
 
efd6a61
 
 
 
75c5f1f
efd6a61
 
efd67c2
589985f
607ce82
 
 
 
 
efd67c2
6d6fcef
 
43a2f5a
 
 
607ce82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43a2f5a
9a99c76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589985f
d4ebc98
36f58d9
 
90ca14a
 
efd67c2
589985f
a0fc312
 
 
 
 
 
4382787
 
 
 
 
 
973de0d
 
 
 
 
 
5ffacbe
 
 
 
 
973de0d
a9634f7
 
 
 
 
 
be2ede1
 
 
 
 
 
589985f
d8a939d
 
 
 
 
589985f
129ca08
 
 
 
 
20f564f
05d7096
 
 
 
 
 
a6517ab
 
 
 
 
 
589985f
508be3f
 
 
 
 
 
d9caca4
c7659f4
d9caca4
 
 
508be3f
bb610ed
 
 
 
 
 
9a37bde
 
 
 
 
589985f
a3b3bf7
20f564f
a3b3bf7
20f564f
 
129ca08
66cff10
 
 
070678d
 
 
 
 
66cff10
070678d
66cff10
 
 
 
 
 
 
070678d
66cff10
 
 
 
 
 
070678d
66cff10
070678d
 
 
66cff10
070678d
 
 
 
66cff10
070678d
 
 
66cff10
070678d
 
66cff10
070678d
 
efd6a61
 
503c1eb
 
 
589985f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
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}>(.*?)</{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")

# 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)