Hammad712/website-audit
0
1import re2import os3import json4import requests5import google.generativeai as genai6from reportlab.lib.pagesizes import letter7from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, ListFlowable, ListItem8from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle9from fastapi import FastAPI, HTTPException, Query10from fastapi.responses import FileResponse11 12# ----------------------------13# Helper functions (provided code)14# ----------------------------15 16def convert_markdown(text):17 """18 Convert simple markdown bold markers **text** to HTML <b> tags.19 """20 return re.sub(r"\*\*(.*?)\*\*", r"<b>\1</b>", text)21 22def parse_report_text(report_text):23 """24 Parse the generated report text and return a list of ReportLab flowables25 with proper headings, subheadings, and bullet-point formatting.26 27 Conventions used:28 - A line that starts and ends with '**' is treated as a heading.29 - Lines starting with '*' are treated as bullet items.30 - All other nonempty lines are treated as normal paragraphs.31 """32 styles = getSampleStyleSheet()33 # You can tweak these styles if needed.34 heading_style = styles["Heading1"]35 subheading_style = styles["Heading2"]36 normal_style = styles["BodyText"]37 bullet_style = styles["Bullet"]38 39 flowables = []40 bullet_items = [] # temporary list for bullet items41 42 # Split the report text into lines.43 lines = report_text.splitlines()44 for line in lines:45 line = line.strip()46 # If the line is empty, flush any bullet list and add a spacer.47 if not line:48 if bullet_items:49 flowables.append(ListFlowable(bullet_items, bulletType='bullet', leftIndent=20))50 bullet_items = []51 flowables.append(Spacer(1, 12))52 continue53 54 # Check if line is a bullet point (starts with '*')55 if line.startswith("*"):56 bullet_text = line.lstrip("*").strip()57 bullet_text = convert_markdown(bullet_text)58 bullet_paragraph = Paragraph(bullet_text, bullet_style)59 bullet_items.append(bullet_paragraph)60 # Check if the entire line is a heading (starts and ends with '**')61 elif line.startswith("**") and line.endswith("**"):62 if bullet_items:63 flowables.append(ListFlowable(bullet_items, bulletType='bullet', leftIndent=20))64 bullet_items = []65 # Remove the asterisks and convert markdown if needed.66 heading_text = convert_markdown(line.strip("*").strip())67 flowables.append(Paragraph(heading_text, heading_style))68 else:69 if bullet_items:70 flowables.append(ListFlowable(bullet_items, bulletType='bullet', leftIndent=20))71 bullet_items = []72 # Otherwise, treat as normal paragraph.73 normal_text = convert_markdown(line)74 flowables.append(Paragraph(normal_text, normal_style))75 76 # Flush any remaining bullet items.77 if bullet_items:78 flowables.append(ListFlowable(bullet_items, bulletType='bullet', leftIndent=20))79 80 return flowables81 82def get_pagespeed_data(target_url, pagespeed_api_key):83 """84 Fetch data from the PageSpeed Insights API for the given URL.85 """86 endpoint = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed"87 params = {88 "url": target_url,89 "key": pagespeed_api_key90 }91 response = requests.get(endpoint, params=params)92 if response.status_code == 200:93 return response.json()94 else:95 raise Exception(f"Error fetching PageSpeed data: {response.status_code} - {response.text}")96 97def generate_report_with_gemini(pagespeed_data, gemini_api_key):98 """99 Uses the Gemini model to generate a detailed report based on the PageSpeed Insights data.100 """101 # Configure the Gemini API with the provided key102 genai.configure(api_key=gemini_api_key)103 104 # Select a Gemini model. For this example, we use 'gemini-2.0-flash'.105 model = genai.GenerativeModel("gemini-2.0-flash")106 107 # Prepare the prompt including the pretty-printed JSON.108 prompt = (109 "Please generate a detailed and well-structured report on the website performance based "110 "on the following PageSpeed Insights data. Organize the report with clear headings, do not generate tables in the report "111 "subheadings, and bullet points for key metrics and recommendations:\n\n" +112 json.dumps(pagespeed_data, indent=2)113 )114 115 # Generate the content using Gemini.116 response = model.generate_content(prompt)117 118 if response and hasattr(response, "text"):119 return response.text120 else:121 return "No report could be generated."122 123def save_report_to_pdf(report_text, pdf_filename="pagespeed_report.pdf"):124 """125 Format the report text into headings, subheadings, and bullet points, then save it as a PDF.126 """127 # Create a SimpleDocTemplate for the PDF128 doc = SimpleDocTemplate(pdf_filename, pagesize=letter,129 rightMargin=72, leftMargin=72,130 topMargin=72, bottomMargin=72)131 132 # Parse the report text into platypus flowables133 flowables = parse_report_text(report_text)134 135 # Build the PDF document.136 doc.build(flowables)137 print(f"Report saved as {pdf_filename}")138 139# ----------------------------140# FastAPI App and Endpoints141# ----------------------------142app = FastAPI()143 144# Load API keys from environment variables.145PAGESPEED_API_KEY = os.environ.get("PAGESPEED_API_KEY")146GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")147PDF_FILENAME = "pagespeed_report.pdf"148 149if not PAGESPEED_API_KEY or not GEMINI_API_KEY:150 raise Exception("Please set the PAGESPEED_API_KEY and GEMINI_API_KEY environment variables.")151 152@app.get("/")153def read_root():154 """155 Root endpoint providing basic information.156 """157 return {158 "message": "Welcome to the PageSpeed Insights Report Generator API. "159 "Use /generate_report?url=<target_url> (POST) to generate a report and /download_pdf (GET) to download the PDF."160 }161 162@app.post("/generate_report")163def generate_report(url: str = Query(..., description="The target URL for which to generate the report")):164 """165 Generates the report by:166 1. Fetching PageSpeed Insights data for the given URL.167 2. Generating a report via the Gemini API.168 3. Saving the report as a PDF.169 Returns the generated report text.170 """171 try:172 # Step 1: Fetch PageSpeed data for the provided URL.173 pagespeed_data = get_pagespeed_data(url, PAGESPEED_API_KEY)174 # Step 2: Generate report using the Gemini API.175 report_text = generate_report_with_gemini(pagespeed_data, GEMINI_API_KEY)176 # Step 3: Save the report as a PDF.177 save_report_to_pdf(report_text, pdf_filename=PDF_FILENAME)178 return {"report": report_text}179 except Exception as e:180 raise HTTPException(status_code=500, detail=str(e))181 182@app.get("/download_pdf")183def download_pdf():184 """185 Returns the generated PDF file for download.186 Make sure you have already called /generate_report.187 """188 if not os.path.exists(PDF_FILENAME):189 raise HTTPException(status_code=404, detail="PDF report not found. Please generate the report first.")190 return FileResponse(PDF_FILENAME, media_type="application/pdf", filename=PDF_FILENAME)191 192# To run the app, use the command:193# uvicorn main:app --reload194 