Files
felhom.eu/documentation/audits/website-refresh-2026-10-08/tools/og_en.py
T
admin 67b3fd23d1
gates / gates (push) Failing after 13m1s
website refresh: true numbers (56 apps), claims checked against the capability map, ten missing apps, an English twin of every public page (public, choice B), 404 page; site gates 13-18 + 11 decoys; R-902 opened
Part A: claim table documentation/audits/website-refresh-2026-10-08/claims.md; "100% open source" corrected
from the licence read; unbacked claims cut (firewall, RAID, snapshots, new-machine restore, self-managed
mode, household VPN, "never lost"). Part B: dawarich, docmost, grimmory, homebox, karakeep, mealie, metube,
radicale, recipe-importer, sparkyfitness cards; plant-it and wger cut (not offered). Part C: /en/ twins,
nav language switch, hreflang both ways, sitemap with xhtml:link, og-image-en.png. Part D: site_gates.py
twins/lang/same-apps/no-Hungarian/FAQ-JSON-LD/tail. Operator ruling 9 + choice B in 10-localisation.md §11,
§10.7. Register: R-902 (contact mailer source in no repo); R-813, R-784, R-559 annotated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-08 08:29:17 +02:00

47 lines
2.3 KiB
Python

"""og-image-en.png: the English twin of og-image.png (1200x630). The Hungarian text areas are repainted from the card's
own radial background profile, then the English text is drawn in the site's own font (Plus Jakarta Sans, vendored)."""
import math, sys
from PIL import Image, ImageDraw, ImageFont, ImageFilter
A = "/mnt/5_hdd/felhom.eu/git/felhom.eu/website/assets/"
im = Image.open(A + "og-image.png").convert("RGB")
W_, H_ = im.size
px = im.load()
boxes = [(60, 190, 760, 370), (60, 380, 1060, 470), (60, 505, 460, 580)] # headline, subtitle, button + url
def inbox(x, y): return any(a <= x <= c and b <= y <= d for a, b, c, d in boxes)
blur = im.filter(ImageFilter.GaussianBlur(25))
cx, cy, best = 0, 0, -1
for y in range(100, 400, 4):
for x in range(700, 1199, 4):
r, g, b = blur.getpixel((x, y))
if b > best: best, cx, cy = b, x, y
prof = {}
for y in range(8, H_):
for x in range(0, W_, 2):
if inbox(x, y) or (x < 450 and y < 160): continue
r = int(math.hypot(x - cx, y - cy))
prof.setdefault(r, []).append(px[x, y])
med = {}
for r, v in prof.items():
v.sort(key=lambda t: t[2]); med[r] = v[len(v) // 2]
def at(r):
while r not in med and r > 0: r -= 1
return med.get(r, (10, 18, 32))
for a, b, c, d in boxes:
for y in range(b, d + 1):
for x in range(a, c + 1):
px[x, y] = at(int(math.hypot(x - cx, y - cy)))
dr = ImageDraw.Draw(im)
def font(size, wght):
f = ImageFont.truetype(A + "fonts/pjs-latin.woff2", size); f.set_variation_by_axes([wght]); return f
h = font(78, 800); sub = font(27, 400); btn = font(23, 700); url = font(23, 700)
dr.text((72, 196), "Your own cloud,", font=h, fill=(237, 242, 249))
dr.text((72, 280), "your own rules", font=h, fill=(46, 168, 245))
dr.text((72, 388), "A home server in your own home in Hungary: photos, documents,", font=sub, fill=(148, 166, 191))
dr.text((72, 426), "media — with automatic backups and a recovery code only you know.", font=sub, fill=(148, 166, 191))
tw = dr.textlength("Closed test starting", font=btn)
dr.rectangle((72, 517, 72 + tw + 44, 566), fill=(46, 168, 245))
dr.text((94, 528), "Closed test starting", font=btn, fill=(10, 18, 32))
dr.text((72 + tw + 44 + 22, 528), "felhom.eu", font=url, fill=(94, 115, 146))
im.save(A + "og-image-en.png", optimize=True)
print("glow centre", cx, cy, "written og-image-en.png")