repobase/generate_post.py
2026-06-17 17:14:21 +02:00

227 lines
8.6 KiB
Python

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
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 CodeCanvasCarousel(FPDF):
def __init__(self):
# Initialize in Landscape mode ('L') using millimeters, explicitly custom sizing (A5 Landscape)
super().__init__(orientation='L', unit='mm', format='A5')
self.set_margins(20, 25, 20)
self.set_auto_page_break(False)
def draw_brand_canvas(self):
"""Fills background with Linen Canvas and draws the minimal header framework."""
self.set_fill_color(*COLOR_LINEN)
self.rect(0, 0, 210, 148, 'F') # A5 Landscape boundary dimensions
# Thin editorial top rule
self.set_draw_color(*COLOR_BORDER)
self.set_line_width(0.4)
self.line(20, 15, 190, 15)
# Standalone Ampersand Shorthand as visual anchor
self.set_text_color(*COLOR_TERRACOTTA)
self.set_font("Times", "I", 16)
self.text(20, 24, "&")
# Sans-serif technical meta-tag
self.set_text_color(*COLOR_NAVY)
self.set_font("Helvetica", "B", 7)
self.text(28, 22, "CODE & CANVAS | INSIGHTS")
def draw_footer(self, current_slide, total_slides):
"""Draws page numbering following clean, minimal layout scales."""
self.set_text_color(*COLOR_CHARCOAL)
self.set_font("Helvetica", "", 8)
self.text(180, 138, f"{current_slide} / {total_slides}")
def clean_typography(text):
"""Enforces absolute micro-styling purity: completely strips out em-dashes."""
return text.replace("", " : ").replace("--", " - ")
def fetch_and_update_subject():
rows = []
selected_subject = None
file_exists_locally = os.path.exists(LOCAL_CSV_PATH)
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:
if not selected_subject and row.get('Used', '').strip().lower() == 'no':
row['Used'] = 'yes'
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)
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
# Ultimate fallback logic if CSV down or empty
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 clean 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']]
os.makedirs("_drafts", exist_ok=True)
TOTAL_SLIDES = 4
pdf = CodeCanvasCarousel()
# -------------------------------------------------------------------------
# SLIDE 1: DISPLAY TITLE CARD
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(45)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 32) # Editorial high-contrast serif display
pdf.multi_cell(170, 14, title)
pdf.set_y(pdf.get_y() + 6)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 12) # Sans-serif structural subtitle
pdf.multi_cell(170, 6, "An architectural breakdown of engineering utility and integration footprints.")
pdf.draw_footer(1, TOTAL_SLIDES)
# -------------------------------------------------------------------------
# SLIDE 2: THE CORE PROBLEMATIQUE / OVERVIEW
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(40)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 18)
pdf.cell(170, 8, "Core Structural Objective", ln=True)
# Subtle geometric divider line
pdf.set_draw_color(*COLOR_BORDER)
pdf.line(20, pdf.get_y() + 2, 60, pdf.get_y() + 2)
pdf.set_y(pdf.get_y() + 12)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 11)
pdf.multi_cell(170, 7, desc)
pdf.draw_footer(2, TOTAL_SLIDES)
# -------------------------------------------------------------------------
# SLIDE 3: TECHNICAL CONSIDERATIONS (GRID BLOCK)
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(38)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 18)
pdf.cell(170, 8, "Key Architecture Vectors", ln=True)
start_y = pdf.get_y() + 8
for idx, pt in enumerate(points):
current_item_y = start_y + (idx * 22)
# Structural card containers using thin borders
pdf.set_draw_color(*COLOR_BORDER)
pdf.set_fill_color(*COLOR_LINEN)
pdf.rect(20, current_item_y, 170, 16, 'DF')
# Terracotta index anchor points
pdf.set_y(current_item_y + 4)
pdf.set_x(24)
pdf.set_text_color(*COLOR_TERRACOTTA)
pdf.set_font("Times", "I", 11)
pdf.cell(10, 8, f"0{idx+1}")
# Clean structural sans body text
pdf.set_x(36)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 10)
pdf.cell(150, 8, pt)
pdf.draw_footer(3, TOTAL_SLIDES)
# -------------------------------------------------------------------------
# SLIDE 4: THE CALL TO ACTION / ARCHITECTURE ROOT
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(45)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 24)
pdf.multi_cell(170, 10, f"Explore the Open-Source Blueprint")
pdf.set_y(pdf.get_y() + 10)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 11)
pdf.multi_cell(170, 6, "Review the configuration patterns, track the baseline execution logs, and implement the layout block directly into your development container environments.")
# High-contrast action footer block
pdf.set_y(pdf.get_y() + 12)
pdf.set_text_color(*COLOR_TERRACOTTA)
pdf.set_font("Helvetica", "B", 10)
pdf.cell(170, 6, f"Source Index: {data['url']}", ln=True)
pdf.draw_footer(4, TOTAL_SLIDES)
# Output file generation paths
pdf.output("_drafts/weekly-draft.pdf")
# -------------------------------------------------------------------------
# GENERATE MARKDOWN TEXT FILE
# -------------------------------------------------------------------------
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"""
with open("_drafts/weekly-draft.md", mode='w', encoding='utf-8') as f:
f.write(post_copy)
if __name__ == "__main__":
generate_assets()