Spaces:
Running
Running
refactored codebase
Browse files- app.py +27 -104
- controller/__init__.py +0 -0
- controller/imports.py +40 -0
- jwtcoding.py → controller/jwtcoding.py +0 -0
- password.py → controller/password.py +0 -0
- scraper.py → controller/scraper.py +0 -2
- streaksManagement.py → controller/streaksManagement.py +0 -0
- tokenManagement.py → controller/tokenManagement.py +0 -0
- utils.py → controller/utils.py +0 -0
- gamification/routes.py +2 -2
- testing.py +0 -28
app.py
CHANGED
@@ -1,40 +1,10 @@
|
|
1 |
-
from
|
2 |
-
from dotenv import load_dotenv
|
3 |
-
import os
|
4 |
-
from gamification.objects import SimpleIndividualUserLevel
|
5 |
-
from utils import *
|
6 |
-
from fastapi import FastAPI, File, HTTPException, Header, UploadFile,status
|
7 |
-
from tokenManagement import *
|
8 |
-
from jwtcoding import *
|
9 |
-
from fastapi.responses import JSONResponse
|
10 |
-
import docx
|
11 |
-
import fitz
|
12 |
-
from gamification.routes import gamification
|
13 |
-
from scraper import scrapeCourse
|
14 |
-
import asyncio
|
15 |
-
from google import genai
|
16 |
-
from typing import Optional,List
|
17 |
-
from pydantic import BaseModel
|
18 |
-
import re
|
19 |
-
from bson.json_util import dumps
|
20 |
-
import threading
|
21 |
-
import concurrent.futures
|
22 |
-
from gamification.pointLogic import get_all_simple_points_func,get_dream_job
|
23 |
-
from pydantic import BaseModel
|
24 |
-
from datetime import datetime
|
25 |
-
from bson import ObjectId
|
26 |
-
import os
|
27 |
-
from concurrent.futures import ThreadPoolExecutor
|
28 |
-
executor = ThreadPoolExecutor(max_workers=5)
|
29 |
-
|
30 |
|
31 |
-
|
|
|
|
|
|
|
32 |
|
33 |
-
CX = os.getenv("SEARCH_ENGINE_ID")
|
34 |
-
API_KEY = os.getenv("GOOGLE_API_KEY")
|
35 |
-
PINECONE_API_KEY=os.getenv("PINECONE_API_KEY")
|
36 |
-
GEMINI_API_KEY=os.getenv("GEMINI_API_KEY")
|
37 |
-
MONGO_URI=os.getenv("MONGO_URI")
|
38 |
app = FastAPI()
|
39 |
app.mount('/gamification',gamification)
|
40 |
|
@@ -73,7 +43,19 @@ class UserCourse(BaseModel):
|
|
73 |
timeframeToAchieveDreamRole:str
|
74 |
recommendedCourses: Optional[List[RecommendedCourse]]=None
|
75 |
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
class CourseRecommendation(BaseModel):
|
79 |
courseName: str
|
@@ -93,8 +75,6 @@ def extract_course_info(text: str) -> CourseRecommendation:
|
|
93 |
return CourseRecommendation(courseName=coursename, completionTime=completiontime)
|
94 |
|
95 |
|
96 |
-
import re
|
97 |
-
from urllib.parse import urlparse
|
98 |
|
99 |
def extract_provider(url):
|
100 |
# Parse the URL
|
@@ -159,10 +139,6 @@ def get_course_func(query):
|
|
159 |
|
160 |
|
161 |
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
@app.post("/ai/upload",tags=["AI"])
|
167 |
async def upload_file(file: UploadFile = File(...),authorization: str = Header(...)):
|
168 |
# Extract the token from the Authorization header (Bearer token)
|
@@ -242,37 +218,6 @@ def ask_ai_about_resume(req:AiAnalysis,authorization: str = Header(...)):
|
|
242 |
@app.post("/ai/recommend",tags=["AI"])
|
243 |
def ask_ai_to_recommnd_courses(request:UserCourse,authorization:str=Header(...)):
|
244 |
"""
|
245 |
-
User Profile Information for Career Development
|
246 |
-
|
247 |
-
This section defines the parameters used to gather information from the user to understand their current employment situation, learning preferences, challenges, and goals related to achieving their dream role.
|
248 |
-
|
249 |
-
Parameters:
|
250 |
-
|
251 |
-
employment_status (str):
|
252 |
-
A description of the user's current employment situation (e.g., "unemployed", "part-time", "full-time").
|
253 |
-
|
254 |
-
interim_role (str):
|
255 |
-
Indicates whether the user is willing to prepare for an interim role to gain experience and income while pursuing their dream role (e.g., "yes" or "no").
|
256 |
-
|
257 |
-
desired_role (str):
|
258 |
-
The role the user ultimately wishes to obtain (e.g., "Full-Stack Developer", "Data Scientist").
|
259 |
-
|
260 |
-
motivation (str):
|
261 |
-
The user's reasons or motivations for pursuing the desired role.
|
262 |
-
|
263 |
-
learning_preference (str):
|
264 |
-
Describes how the user prefers to learn new skills (e.g., "online courses", "self-study", "bootcamp").
|
265 |
-
|
266 |
-
hours_spent_learning (str or int):
|
267 |
-
The number of hours per day the user can dedicate to learning.
|
268 |
-
|
269 |
-
challenges (str):
|
270 |
-
Outlines any obstacles or challenges the user faces in reaching their dream role.
|
271 |
-
|
272 |
-
timeframe_to_achieve_dream_role (str):
|
273 |
-
The ideal timeframe the user has in mind for achieving their dream role (e.g., "6-12 months").
|
274 |
-
|
275 |
-
|
276 |
"""
|
277 |
|
278 |
|
@@ -423,19 +368,7 @@ def protected_route(authorization: str = Header(...)):
|
|
423 |
|
424 |
|
425 |
|
426 |
-
|
427 |
-
userId:str
|
428 |
-
firstName:str
|
429 |
-
lastName:str
|
430 |
-
totalpoints:float
|
431 |
-
lastUpdated:datetime
|
432 |
-
careerPath:str
|
433 |
-
class Config:
|
434 |
-
json_encoder ={
|
435 |
-
ObjectId:str
|
436 |
-
}
|
437 |
-
|
438 |
-
|
439 |
def create_leaderboard_ranking( document: LeaderBoardRanking) -> bool:
|
440 |
|
441 |
collection = db['LeaderBoard']
|
@@ -479,16 +412,12 @@ def get_user_id_from_docKey(dockId):
|
|
479 |
|
480 |
|
481 |
|
|
|
|
|
482 |
|
483 |
-
|
484 |
-
# MongoDB connection setup
|
485 |
client = MongoClient(MONGO_URI)
|
486 |
db = client.crayonics
|
487 |
-
collection = db['Points']
|
488 |
-
import logging
|
489 |
-
from datetime import datetime
|
490 |
-
logging.basicConfig(level=logging.INFO)
|
491 |
-
logger = logging.getLogger(__name__)
|
492 |
|
493 |
def handle_change2(new_point):
|
494 |
logger.info(f"Extra info: {new_point}")
|
@@ -533,11 +462,8 @@ def handle_change2(new_point):
|
|
533 |
|
534 |
|
535 |
def handle_change3(userId:str):
|
536 |
-
logger.info(f"Extra info: {userId}")
|
537 |
-
print("No leaderboard so creating one now")
|
538 |
|
539 |
-
|
540 |
-
print("Leveled User", userId)
|
541 |
|
542 |
if not userId:
|
543 |
raise ValueError("User ID not found in inserted document")
|
@@ -545,17 +471,15 @@ def handle_change3(userId:str):
|
|
545 |
# Fetch user details
|
546 |
try:
|
547 |
leveleduser = get_all_users(user_id=userId)
|
548 |
-
|
549 |
-
print("Leveled User", leveleduser)
|
550 |
except Exception as e:
|
551 |
-
|
552 |
leveleduser = {} # Default empty dict to prevent KeyError
|
553 |
|
554 |
# Fetch user points
|
555 |
try:
|
556 |
points = get_all_simple_points_func(userId=userId)
|
557 |
-
|
558 |
-
print("Points", points)
|
559 |
except Exception as e:
|
560 |
logger.error(f"Error fetching points for userId {userId}: {e}")
|
561 |
points = SimpleIndividualUserLevel(totalpoints=0)
|
@@ -728,9 +652,8 @@ def handle_change(change=None):
|
|
728 |
|
729 |
logger.info(f"Change detected:")
|
730 |
|
731 |
-
# Function to run the change stream in a separate thread (non-blocking)
|
732 |
def watch_change_stream():
|
733 |
-
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: #
|
734 |
with collection.watch() as stream:
|
735 |
for change in stream:
|
736 |
# Submit the handle_change task to the thread pool
|
|
|
1 |
+
from controller.imports import *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
+
import logging
|
4 |
+
from datetime import datetime
|
5 |
+
logging.basicConfig(level=logging.INFO)
|
6 |
+
logger = logging.getLogger(__name__)
|
7 |
|
|
|
|
|
|
|
|
|
|
|
8 |
app = FastAPI()
|
9 |
app.mount('/gamification',gamification)
|
10 |
|
|
|
43 |
timeframeToAchieveDreamRole:str
|
44 |
recommendedCourses: Optional[List[RecommendedCourse]]=None
|
45 |
|
46 |
+
class LeaderBoardRanking(BaseModel):
|
47 |
+
userId:str
|
48 |
+
firstName:str
|
49 |
+
lastName:str
|
50 |
+
totalpoints:float
|
51 |
+
lastUpdated:datetime
|
52 |
+
careerPath:str
|
53 |
+
class Config:
|
54 |
+
json_encoder ={
|
55 |
+
ObjectId:str
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
|
60 |
class CourseRecommendation(BaseModel):
|
61 |
courseName: str
|
|
|
75 |
return CourseRecommendation(courseName=coursename, completionTime=completiontime)
|
76 |
|
77 |
|
|
|
|
|
78 |
|
79 |
def extract_provider(url):
|
80 |
# Parse the URL
|
|
|
139 |
|
140 |
|
141 |
|
|
|
|
|
|
|
|
|
142 |
@app.post("/ai/upload",tags=["AI"])
|
143 |
async def upload_file(file: UploadFile = File(...),authorization: str = Header(...)):
|
144 |
# Extract the token from the Authorization header (Bearer token)
|
|
|
218 |
@app.post("/ai/recommend",tags=["AI"])
|
219 |
def ask_ai_to_recommnd_courses(request:UserCourse,authorization:str=Header(...)):
|
220 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
"""
|
222 |
|
223 |
|
|
|
368 |
|
369 |
|
370 |
|
371 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
372 |
def create_leaderboard_ranking( document: LeaderBoardRanking) -> bool:
|
373 |
|
374 |
collection = db['LeaderBoard']
|
|
|
412 |
|
413 |
|
414 |
|
415 |
+
|
416 |
+
|
417 |
|
|
|
|
|
418 |
client = MongoClient(MONGO_URI)
|
419 |
db = client.crayonics
|
420 |
+
collection = db['Points']
|
|
|
|
|
|
|
|
|
421 |
|
422 |
def handle_change2(new_point):
|
423 |
logger.info(f"Extra info: {new_point}")
|
|
|
462 |
|
463 |
|
464 |
def handle_change3(userId:str):
|
|
|
|
|
465 |
|
466 |
+
|
|
|
467 |
|
468 |
if not userId:
|
469 |
raise ValueError("User ID not found in inserted document")
|
|
|
471 |
# Fetch user details
|
472 |
try:
|
473 |
leveleduser = get_all_users(user_id=userId)
|
474 |
+
|
|
|
475 |
except Exception as e:
|
476 |
+
|
477 |
leveleduser = {} # Default empty dict to prevent KeyError
|
478 |
|
479 |
# Fetch user points
|
480 |
try:
|
481 |
points = get_all_simple_points_func(userId=userId)
|
482 |
+
|
|
|
483 |
except Exception as e:
|
484 |
logger.error(f"Error fetching points for userId {userId}: {e}")
|
485 |
points = SimpleIndividualUserLevel(totalpoints=0)
|
|
|
652 |
|
653 |
logger.info(f"Change detected:")
|
654 |
|
|
|
655 |
def watch_change_stream():
|
656 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: # Limited to 10 threads, because there are only 10 server worker
|
657 |
with collection.watch() as stream:
|
658 |
for change in stream:
|
659 |
# Submit the handle_change task to the thread pool
|
controller/__init__.py
ADDED
File without changes
|
controller/imports.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from io import BytesIO
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
import os
|
4 |
+
from gamification.objects import SimpleIndividualUserLevel
|
5 |
+
from utils import *
|
6 |
+
from fastapi import FastAPI, File, HTTPException, Header, UploadFile,status
|
7 |
+
from tokenManagement import *
|
8 |
+
from jwtcoding import *
|
9 |
+
from fastapi.responses import JSONResponse
|
10 |
+
import docx
|
11 |
+
import fitz
|
12 |
+
from gamification.routes import gamification
|
13 |
+
from scraper import scrapeCourse
|
14 |
+
import asyncio
|
15 |
+
from google import genai
|
16 |
+
from typing import Optional,List
|
17 |
+
from pydantic import BaseModel
|
18 |
+
import re
|
19 |
+
from bson.json_util import dumps
|
20 |
+
import threading
|
21 |
+
import concurrent.futures
|
22 |
+
from gamification.pointLogic import get_all_simple_points_func,get_dream_job
|
23 |
+
from pydantic import BaseModel
|
24 |
+
from datetime import datetime
|
25 |
+
from bson import ObjectId
|
26 |
+
import os
|
27 |
+
import re
|
28 |
+
from urllib.parse import urlparse
|
29 |
+
|
30 |
+
from concurrent.futures import ThreadPoolExecutor
|
31 |
+
executor = ThreadPoolExecutor(max_workers=5)
|
32 |
+
|
33 |
+
|
34 |
+
load_dotenv()
|
35 |
+
|
36 |
+
CX = os.getenv("SEARCH_ENGINE_ID")
|
37 |
+
API_KEY = os.getenv("GOOGLE_API_KEY")
|
38 |
+
PINECONE_API_KEY=os.getenv("PINECONE_API_KEY")
|
39 |
+
GEMINI_API_KEY=os.getenv("GEMINI_API_KEY")
|
40 |
+
MONGO_URI=os.getenv("MONGO_URI")
|
jwtcoding.py → controller/jwtcoding.py
RENAMED
File without changes
|
password.py → controller/password.py
RENAMED
File without changes
|
scraper.py → controller/scraper.py
RENAMED
@@ -1,5 +1,3 @@
|
|
1 |
-
|
2 |
-
|
3 |
def scrapeCourse(url):
|
4 |
import requests
|
5 |
from bs4 import BeautifulSoup
|
|
|
|
|
|
|
1 |
def scrapeCourse(url):
|
2 |
import requests
|
3 |
from bs4 import BeautifulSoup
|
streaksManagement.py → controller/streaksManagement.py
RENAMED
File without changes
|
tokenManagement.py → controller/tokenManagement.py
RENAMED
File without changes
|
utils.py → controller/utils.py
RENAMED
File without changes
|
gamification/routes.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
from fastapi import FastAPI,HTTPException, Header
|
2 |
from gamification.objects import *
|
3 |
from gamification.logic import *
|
4 |
-
from jwtcoding import decode_jwt
|
5 |
-
from tokenManagement import verify_access_token
|
6 |
|
7 |
class EditableUserLevel(BaseModel):
|
8 |
levelId : str
|
|
|
1 |
from fastapi import FastAPI,HTTPException, Header
|
2 |
from gamification.objects import *
|
3 |
from gamification.logic import *
|
4 |
+
from controller.jwtcoding import decode_jwt
|
5 |
+
from controller.tokenManagement import verify_access_token
|
6 |
|
7 |
class EditableUserLevel(BaseModel):
|
8 |
levelId : str
|
testing.py
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
|
2 |
-
from typing import List
|
3 |
-
|
4 |
-
from bson import ObjectId
|
5 |
-
from pymongo import MongoClient
|
6 |
-
|
7 |
-
from app import MONGO_URI
|
8 |
-
|
9 |
-
|
10 |
-
def get_all_users(user_id:str =None) -> List:
|
11 |
-
client = MongoClient(MONGO_URI)
|
12 |
-
db = client.crayonics
|
13 |
-
collection = db['users']
|
14 |
-
# Insert the document
|
15 |
-
if user_id==None:
|
16 |
-
results= collection.find()
|
17 |
-
if results:
|
18 |
-
result = [result for result in results]
|
19 |
-
return result
|
20 |
-
|
21 |
-
client.close()
|
22 |
-
else:
|
23 |
-
result = collection.find_one(filter={"_id":ObjectId(user_id.strip())})
|
24 |
-
return result
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
print(get_all_users(user_id="67c9b68678fbf39f4ed94e01"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|