CoolFace
Apppublic

Hammad712/website-audit

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
main.py194 linesDownload Raw Back to root
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