import streamlit as st import google.generativeai as genai from github import Github from pypdf import PdfReader import os from dotenv import load_dotenv # --- CONFIG --- st.set_page_config(page_title="DevResume Pro", layout="wide", page_icon="⚡") # Load Keys api_key = os.getenv("GEMINI_API_KEY") github_token = os.getenv("GITHUB_TOKEN") if not api_key: load_dotenv() api_key = os.getenv("GEMINI_API_KEY") github_token = os.getenv("GITHUB_TOKEN") # --- FUNC 1: PDF PARSER --- def extract_pdf_text(file): try: reader = PdfReader(file) text = "" for page in reader.pages: text += page.extract_text() return text except: return None # --- FUNC 2: GITHUB CRAWLER --- def fetch_github_data(username): try: g = Github(github_token) if github_token else Github() user = g.get_user(username) repos = sorted(user.get_repos(), key=lambda x: x.stargazers_count, reverse=True)[:4] repo_data = "" for repo in repos: readme = "No README" try: if repo.get_readme().decoded_content: readme = repo.get_readme().decoded_content.decode("utf-8")[:1000] except: pass repo_data += f"Project: {repo.name} ({repo.stargazers_count} Stars, {repo.language})\nDesc: {repo.description}\nContext: {readme}\n\n" return repo_data except Exception as e: return f"Error fetching GitHub: {str(e)}" # --- FUNC 3: THE RESUME ARCHITECT --- def generate_full_resume(old_resume_text, github_data, target_role): genai.configure(api_key=api_key) try: model = genai.GenerativeModel('gemini-2.5-flash') except: model = genai.GenerativeModel('gemini-1.5-flash') prompt = f""" You are an Elite Tech Resume Writer. SOURCE MATERIAL: 1. OLD RESUME TEXT: {old_resume_text[:4000]} 2. GITHUB PORTFOLIO ANALYSIS: {github_data} TARGET ROLE: {target_role} TASK: Write a complete, SOTA Resume (Markdown Format). STRUCTURE: 1. **Header:** Name, Title (Target Role), Links (GitHub/LinkedIn). 2. **Professional Summary:** Synthesize the old resume + new GitHub achievements into a killer 3-line bio. 3. **Technical Skills:** Grouped by category (Languages, Frameworks, Tools). 4. **Featured Projects:** Use the GitHub Data. Write "XYZ Style" impact bullets. 5. **Experience:** Polish the old resume's experience section. Make it punchy. 6. **Education:** Keep it simple. TONE: Senior, High-Impact, Quantified. """ try: response = model.generate_content(prompt) return response.text except Exception as e: return f"AI Error: {e}" # --- UI --- st.title("⚡ DevResume Pro: The Hybrid Architect") st.markdown("Combines your **Old Resume** + **Real GitHub Code** to build the ultimate portfolio.") col1, col2 = st.columns([1, 2]) with col1: st.subheader("1. Your Inputs") gh_user = st.text_input("GitHub Username", placeholder="eatosin") role = st.text_input("Target Role", value="Senior AI Engineer") uploaded_file = st.file_uploader("Upload Old Resume (PDF)", type="pdf") if st.button("🚀 Build Resume", type="primary"): if not gh_user or not uploaded_file: st.error("Please provide both GitHub User and PDF Resume.") else: with st.spinner("🕵️‍♂️ Reading PDF & Scraping GitHub..."): # 1. Read PDF pdf_text = extract_pdf_text(uploaded_file) # 2. Scrape GitHub gh_data = fetch_github_data(gh_user) # 3. Generate if pdf_text and gh_data: st.session_state['resume'] = generate_full_resume(pdf_text, gh_data, role) else: st.error("Failed to read inputs.") with col2: if 'resume' in st.session_state: st.subheader("📄 Your New Resume") st.markdown(st.session_state['resume']) st.download_button("📥 Download Markdown", st.session_state['resume'], file_name="SOTA_Resume.md")