Hammad712 commited on
Commit
2c69db6
·
verified ·
1 Parent(s): 6237f01

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +193 -0
main.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import os
3
+ import json
4
+ import requests
5
+ import google.generativeai as genai
6
+ from reportlab.lib.pagesizes import letter
7
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, ListFlowable, ListItem
8
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
9
+ from fastapi import FastAPI, HTTPException, Query
10
+ from fastapi.responses import FileResponse
11
+
12
+ # ----------------------------
13
+ # Helper functions (provided code)
14
+ # ----------------------------
15
+
16
+ def 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
+
22
+ def parse_report_text(report_text):
23
+ """
24
+ Parse the generated report text and return a list of ReportLab flowables
25
+ 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 items
41
+
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
+ continue
53
+
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 flowables
81
+
82
+ def 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_key
90
+ }
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
+
97
+ def 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 key
102
+ 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, "
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.text
120
+ else:
121
+ return "No report could be generated."
122
+
123
+ def 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 PDF
128
+ doc = SimpleDocTemplate(pdf_filename, pagesize=letter,
129
+ rightMargin=72, leftMargin=72,
130
+ topMargin=72, bottomMargin=72)
131
+
132
+ # Parse the report text into platypus flowables
133
+ 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 Endpoints
141
+ # ----------------------------
142
+ app = FastAPI()
143
+
144
+ # Load API keys from environment variables.
145
+ PAGESPEED_API_KEY = os.environ.get("PAGESPEED_API_KEY")
146
+ GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
147
+ PDF_FILENAME = "pagespeed_report.pdf"
148
+
149
+ if 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("/")
153
+ def 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")
163
+ def 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")
183
+ def 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 --reload