import os import csv import requests from bs4 import BeautifulSoup from fpdf import FPDF # ------------------------------------------------------------------------- # CODE & CANVAS BRAND DESIGN TOKENS # ------------------------------------------------------------------------- COLOR_LINEN = (250, 248, 245) # #FAF8F5 - Default background canvas[span_2](start_span)[span_2](end_span) COLOR_NAVY = (26, 35, 50) # #1A2332 - Deep structural headers[span_3](start_span)[span_3](end_span) COLOR_TERRACOTTA = (211, 107, 77) # #D36B4D - Primary visual accents[span_4](start_span)[span_4](end_span) COLOR_CHARCOAL = (43, 43, 43) # #2B2B2B - High-legibility body text[span_5](start_span)[span_5](end_span) COLOR_BORDER = (229, 222, 201) # #E5DEC9 - Thin muted gridlines[span_6](start_span)[span_6](end_span) CSV_URL = "https://raw.githubusercontent.com/CodeAndCanvas728/repobase/refs/heads/main/RepoDatabase.csv" class CodeCanvasPDF(FPDF): def header(self): # Establish Editorial Minimalism and generous margins self.set_fill_color(*COLOR_LINEN) self.rect(0, 0, 210, 297, 'F') # Subtle top accent line instead of heavy borders self.set_draw_color(*COLOR_BORDER) self.set_line_width(0.5) self.line(15, 15, 195, 15) # Standalone Ampersand Shorthand as the brand anchor self.set_text_color(*COLOR_TERRACOTTA) self.set_font("Times", "I", 16) # Elegant serif substitution for Georgia self.text(15, 25, "&") self.set_text_color(*COLOR_NAVY) self.set_font("Helvetica", "B", 8) # Sans-serif for technical meta-tags self.text(23, 23, "CODE & CANVAS | INSIGHTS") def footer(self): self.set_text_color(*COLOR_CHARCOAL) self.set_font("Helvetica", "", 8) self.text(185, 285, f"Page {self.page_no()}") def clean_typography(text): """Enforces the strict micro-styling rule: Absolutely no em-dashes.""" return text.replace("—", " : ").replace("--", " - ") def fetch_subject(): try: response = requests.get(CSV_URL, timeout=10) if response.status_code == 200 and response.text.strip(): lines = response.text.splitlines() reader = csv.DictReader(lines) for row in reader: if row.get('Used', '').lower() == 'no': return { "title": row['Title'], "desc": row['Description'], "points": [row['Point1'], row['Point2'], row['Point3']], "url": row.get('URL', '') } except Exception: pass # Fallback Logic: Scrape GitHub Trending AI/LLM Python/Go repositories try: fb_res = requests.get("https://github.com/trending", timeout=10) soup = BeautifulSoup(fb_res.text, 'html.parser') repo = soup.find('article', class_='Box-row') title = repo.find('h2', class_='h3').text.strip().replace('\n', '').replace(' ', '') desc = repo.find('p', class_='col-9').text.strip() return { "title": title, "desc": desc, "points": ["Open-source community standard", "Highly scalable architecture", "Streamlined local environment deployment"], "url": f"https://github.com/{title}" } except Exception: return { "title": "Model Context Protocol", "desc": "An open standard enabling secure, structured data communication layers between local environments and LLMs.", "points": ["Eliminates custom integration glue code", "Maintains clean architectural boundaries", "Built for developer tool interoperability"], "url": "https://github.com/modelcontextprotocol" } def generate_assets(): data = fetch_subject() title = clean_typography(data['title']) desc = clean_typography(data['desc']) points = [clean_typography(p) for p in data['points']] # ------------------------------------------------------------------------- # 1. GENERATE THE BRANDED PDF # ------------------------------------------------------------------------- pdf = CodeCanvasPDF() pdf.set_margins(15, 30, 15) pdf.add_page() # Title Layout (High-contrast Serif Display Style) pdf.set_y(40) pdf.set_text_color(*COLOR_NAVY) pdf.set_font("Times", "", 28) # Georgia alternative pdf.multi_cell(180, 12, title) # Accent Divider Line pdf.set_draw_color(*COLOR_BORDER) pdf.line(15, pdf.get_y() + 5, 80, pdf.get_y() + 5) # Brief Informational Summary pdf.set_y(pdf.get_y() + 15) pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 11) # Sans-serif structural body text pdf.multi_cell(180, 7, desc) # Structured Grid for Key Highlights pdf.set_y(pdf.get_y() + 15) for idx, pt in enumerate(points, 1): pdf.set_draw_color(*COLOR_BORDER) pdf.set_fill_color(*COLOR_LINEN) # Structural thin-bordered card layouts pdf.rect(15, pdf.get_y(), 180, 18, 'DF') pdf.set_x(20) pdf.set_text_color(*COLOR_TERRACOTTA) pdf.set_font("Times", "I", 12) pdf.cell(10, 18, f"0{idx}") pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 10) pdf.cell(160, 18, pt) pdf.set_y(pdf.get_y() + 22) pdf_filename = "linkedin_insight_asset.pdf" pdf.output(pdf_filename) # ------------------------------------------------------------------------- # 2. GENERATE LINKEDIN POST COPY # ------------------------------------------------------------------------- post_copy = f"""💡 Weekly AI Architecture Breakdown Looking closely at modern workflows, complexity often hides in plain sight. Today we are looking at {title}. What it is: {desc} Key Architecture Considerations: • {points[0]} • {points[1]} • {points[2]} The complete visual documentation is attached below as an editorial carousel blueprint. Repository Link: {data['url']} #SoftwareArchitecture #DeveloperTools #TechInsights #CodeAndCanvas""" print("--- LINKEDIN POST DRAFT ---") print(post_copy) print("\n--- ASSET STATUS ---") print(f"Success: {pdf_filename} generated inside your directory following brand design guidelines.") if __name__ == "__main__": generate_assets()