import os import csv import re import requests from bs4 import BeautifulSoup from fpdf import FPDF # ------------------------------------------------------------------------- # CODE & CANVAS BRAND DESIGN TOKENS # ------------------------------------------------------------------------- COLOR_LINEN = (250, 248, 245) # #FAF8F5 - Default background canvas COLOR_NAVY = (26, 35, 50) # #1A2332 - Deep structural base color COLOR_TERRACOTTA = (211, 107, 77) # #D36B4D - Primary visual accents COLOR_CHARCOAL = (43, 43, 43) # #2B2B2B - High-legibility body text COLOR_BORDER = (229, 222, 201) # #E5DEC9 - Thin muted gridlines LOCAL_CSV_PATH = "RepoDatabase.csv" REMOTE_CSV_URL = "https://raw.githubusercontent.com/CodeAndCanvas728/repobase/refs/heads/main/RepoDatabase.csv" class CodeCanvasPDF(FPDF): def header(self): self.set_fill_color(*COLOR_LINEN) self.rect(0, 0, 210, 297, 'F') self.set_draw_color(*COLOR_BORDER) self.set_line_width(0.5) self.line(15, 15, 195, 15) # Standalone Ampersand Shorthand self.set_text_color(*COLOR_TERRACOTTA) self.set_font("Times", "I", 16) # Classic serif self.text(15, 25, "&") self.set_text_color(*COLOR_NAVY) self.set_font("Helvetica", "B", 8) # Sans-serif technical data 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 absolute purity of text: No unicode or markdown em-dashes.""" return text.replace("—", " : ").replace("--", " - ") def fetch_and_update_subject(): """Reads local repository CSV to find an unused row, updates it to 'yes', and writes it back immediately to prevent duplicate scheduling entries.""" rows = [] selected_subject = None file_exists_locally = os.path.exists(LOCAL_CSV_PATH) # 1. Read Database Data if file_exists_locally: with open(LOCAL_CSV_PATH, mode='r', newline='', encoding='utf-8') as f: reader = csv.DictReader(f) fieldnames = reader.fieldnames for row in reader: # Find the first unused item matching criteria if not selected_subject and row.get('Used', '').strip().lower() == 'no': row['Used'] = 'yes' # State Update Mutation selected_subject = { "title": row['Title'], "desc": row['Description'], "points": [row['Point1'], row['Point2'], row['Point3']], "url": row.get('URL', f"https://github.com/search?q={row['Title']}") } rows.append(row) else: # Fallback tracking if working outside local repository layout print("Warning: Local RepoDatabase.csv not found. Reverting to remote live endpoint.") try: res = requests.get(REMOTE_CSV_URL, timeout=10) if res.status_code == 200: lines = res.text.splitlines() reader = csv.DictReader(lines) fieldnames = reader.fieldnames for row in reader: if not selected_subject and row.get('Used', '').strip().lower() == 'no': selected_subject = { "title": row['Title'], "desc": row['Description'], "points": [row['Point1'], row['Point2'], row['Point3']], "url": row.get('URL', '') } except Exception: pass # 2. Save Updated Database State if modified locally if selected_subject and file_exists_locally: with open(LOCAL_CSV_PATH, mode='w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(rows) return selected_subject # 3. Dynamic GitHub Scraping Fallback Routine if not selected_subject: print("Database exhausted or unreachable. Querying trending open-source indexes...") 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') raw_title = repo.find('h2', class_='h3').text.strip().replace('\n', '').replace(' ', '') desc = repo.find('p', class_='col-9').text.strip() return { "title": raw_title.split('/')[-1], "desc": desc, "points": ["Open-source workflow standard", "Highly modular architectural design", "Streamlined environment footprint"], "url": f"https://github.com/{raw_title}" } except Exception: # Absolute hard-fail recovery state return { "title": "Model Context Protocol", "desc": "An open standard enabling secure, structured data communication layers between local environments and generative applications.", "points": ["Eliminates custom integration glue code", "Maintains clear architectural boundaries", "Built for cross-tool interoperability"], "url": "https://github.com/modelcontextprotocol" } def generate_assets(): data = fetch_and_update_subject() title = clean_typography(data['title']) desc = clean_typography(data['desc']) points = [clean_typography(p) for p in data['points']] # Target path configuration os.makedirs("_drafts", exist_ok=True) safe_date = "weekly-draft" # ------------------------------------------------------------------------- # PDF COMPILATION BLOCK # ------------------------------------------------------------------------- pdf = CodeCanvasPDF() pdf.set_margins(15, 30, 15) pdf.add_page() # Header display layout pdf.set_y(40) pdf.set_text_color(*COLOR_NAVY) pdf.set_font("Times", "", 26) pdf.multi_cell(180, 12, title) # Layout dividing grid rules pdf.set_draw_color(*COLOR_BORDER) pdf.line(15, pdf.get_y() + 5, 80, pdf.get_y() + 5) # Copy layout execution pdf.set_y(pdf.get_y() + 15) pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 11) pdf.multi_cell(180, 7, desc) # Balanced spacing grids for parameters 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) 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_path = f"_drafts/{safe_date}.pdf" pdf.output(pdf_path) # ------------------------------------------------------------------------- # MARKDOWN CONVERSION BLOCK # ------------------------------------------------------------------------- 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""" md_path = f"_drafts/{safe_date}.md" with open(md_path, mode='w', encoding='utf-8') as f: f.write(post_copy) print(f"Workflow Complete: Created tracking drafts inside configuration paths.") if __name__ == "__main__": generate_assets()