[Gobal] added flake8 and did format

This commit is contained in:
coja
2026-05-04 10:33:09 +02:00
parent 732640cf90
commit aa26a3675e
13 changed files with 308 additions and 150 deletions

8
.flake8 Normal file
View File

@@ -0,0 +1,8 @@
[tool.black]
line-length = 88
target-version = ['py312']
[tool.flake8]
max-line-length = 88
extend-ignore = "E203"
exclude = ".venv"

15
AGENTS.md Normal file
View File

@@ -0,0 +1,15 @@
# AGENTS.md
## Core Workflow
- **Setup**: `make prep` (creates `.venv` and installs `requirements.txt`)
- **Build**: `make build` (runs `atom_gen.py`, `prep.py`, and `build_pages.py`)
- **Events**: Update `dogadjaji.csv` then run `make events` (updates pages and generates images via `image_poster.py`)
- **Development**: `make dev` (starts Nginx using `nginx.dev.conf`) and `make stop` to terminate.
## Technical Details
- **Environment**: Uses a local virtual environment in `.venv`. Always use `./.venv/bin/python` or ensure the venv is activated.
- **Output**: The generated website is stored in the `site/` directory.
- **Data**: Events are driven by `dogadjaji.csv`.
- **Web Server**: Uses Nginx for the development server.

View File

@@ -1,4 +1,4 @@
.PHONY: build events dev stop help prep .PHONY: build events dev stop help prep lint format
help: help:
@echo "Available commands:" @echo "Available commands:"
@@ -29,3 +29,9 @@ dev:
stop: stop:
nginx -p . -s stop nginx -p . -s stop
lint:
./.venv/bin/flake8 . --config .flake8 --exclude .venv
format:
./.venv/bin/black .

View File

@@ -26,6 +26,7 @@ blogs_dir = os.fsencode("blog")
# output_list.append([author, title, time, content_html, full_path]) # output_list.append([author, title, time, content_html, full_path])
# return output_list # return output_list
def events_list_gen(): def events_list_gen():
output_list = [] output_list = []
events_file = open("dogadjaji.csv", "r") events_file = open("dogadjaji.csv", "r")
@@ -38,34 +39,35 @@ def events_list_gen():
events_file.close() events_file.close()
return output_list return output_list
def feedgen(blogs, events): def feedgen(blogs, events):
fg_blog = FeedGenerator() fg_blog = FeedGenerator()
fg_blog.id('http://dmz.rs/') fg_blog.id("http://dmz.rs/")
fg_blog.title('Decentrala Blog') fg_blog.title("Decentrala Blog")
fg_blog.author( {'name':'Decentrala','email':'dmz@dmz.rs'} ) fg_blog.author({"name": "Decentrala", "email": "dmz@dmz.rs"})
fg_blog.link( href='https://dmz.rs/atom_blog.xml', rel='self' ) fg_blog.link(href="https://dmz.rs/atom_blog.xml", rel="self")
fg_events = FeedGenerator() fg_events = FeedGenerator()
fg_events.id('http://dmz.rs/') fg_events.id("http://dmz.rs/")
fg_events.title('Decentrala Blog') fg_events.title("Decentrala Blog")
fg_events.author( {'name':'Decentrala','email':'dmz@dmz.rs'} ) fg_events.author({"name": "Decentrala", "email": "dmz@dmz.rs"})
fg_events.link( href='https://dmz.rs/atom_events.xml', rel='self' ) fg_events.link(href="https://dmz.rs/atom_events.xml", rel="self")
for post in blogs: for post in blogs:
fe_blogs = fg_blog.add_entry() fe_blogs = fg_blog.add_entry()
fe_blogs.id("https://dmz.rs/" + post[4][:-3] + ".html") fe_blogs.id("https://dmz.rs/" + post[4][:-3] + ".html")
fe_blogs.author({'name': post[0]}) fe_blogs.author({"name": post[0]})
fe_blogs.title(post[1]) fe_blogs.title(post[1])
fe_blogs.updated(post[2]) fe_blogs.updated(post[2])
fe_blogs.content(content=post[3], type='html') fe_blogs.content(content=post[3], type="html")
for event in events: for event in events:
fe_events = fg_events.add_entry() fe_events = fg_events.add_entry()
fe_events.id("https://dmz.rs/pages/events.html") fe_events.id("https://dmz.rs/pages/events.html")
fe_events.author({'name': event[0]}) fe_events.author({"name": event[0]})
fe_events.title(event[1]) fe_events.title(event[1])
fe_events.updated(datetime.datetime.now(datetime.timezone.utc)) fe_events.updated(datetime.datetime.now(datetime.timezone.utc))
fe_events.content(content=event[2], type='html') fe_events.content(content=event[2], type="html")
fg_blog.atom_file('site/atom_blog.xml') fg_blog.atom_file("site/atom_blog.xml")
fg_events.atom_file('site/atom_events.xml') fg_events.atom_file("site/atom_events.xml")

View File

@@ -5,8 +5,8 @@ from markdown import markdown as to_markdown
blog = "" blog = ""
with open('blogs/Lorem Ipsum.md','rt') as file: with open("blogs/Lorem Ipsum.md", "rt") as file:
blog = file.read() blog = file.read()
with open('blogs/Lorem Ipsum.html', 'wt') as file: with open("blogs/Lorem Ipsum.html", "wt") as file:
file.write(to_markdown(blog)) file.write(to_markdown(blog))

View File

@@ -2,39 +2,61 @@ from jinja2 import Environment, FileSystemLoader
import os import os
PAGES = [ PAGES = [
{'name': 'index', 'titleSR': 'Početna', 'titleEN': 'Home', 'style': 'home'}, {"name": "index", "titleSR": "Početna", "titleEN": "Home", "style": "home"},
{'name': 'account', 'titleSR': 'Nalog', 'titleEN': 'Account', 'style': 'account'}, {"name": "account", "titleSR": "Nalog", "titleEN": "Account", "style": "account"},
{'name': 'about', 'titleSR': 'O nama', 'titleEN': 'About us', 'style': 'about'}, {"name": "about", "titleSR": "O nama", "titleEN": "About us", "style": "about"},
{'name': 'statute', 'titleSR': 'Statut', 'titleEN': 'Statute', 'style': 'statute'}, {"name": "statute", "titleSR": "Statut", "titleEN": "Statute", "style": "statute"},
{'name': 'events', 'titleSR': 'Događaji', 'titleEN': 'Events', 'style': 'events'}, {"name": "events", "titleSR": "Događaji", "titleEN": "Events", "style": "events"},
{'name': 'events_archive', 'titleSR': 'Arhiva događaja', 'titleEN': 'Events archive', 'style': 'events'}, {
{'name': 'services', 'titleSR': 'Servisi', 'titleEN': 'Services', 'style': 'services'}, "name": "events_archive",
{'name': 'webring', 'titleSR': 'Webring', 'titleEN': 'Webring', 'style': ''}, "titleSR": "Arhiva događaja",
{'name': 'support', 'titleSR': 'Podrška', 'titleEN': 'Support', 'style': 'support'}, "titleEN": "Events archive",
{'name': 'deconference', 'titleSR': 'Dekonferencija', 'titleEN': 'Deconference', 'style': 'deconference'}, "style": "events",
},
{
"name": "services",
"titleSR": "Servisi",
"titleEN": "Services",
"style": "services",
},
{"name": "webring", "titleSR": "Webring", "titleEN": "Webring", "style": ""},
{"name": "support", "titleSR": "Podrška", "titleEN": "Support", "style": "support"},
{
"name": "deconference",
"titleSR": "Dekonferencija",
"titleEN": "Deconference",
"style": "deconference",
},
] ]
env = Environment(loader=FileSystemLoader('template')) env = Environment(loader=FileSystemLoader("template"))
def main(): def main():
os.makedirs('site/en/', exist_ok=True) os.makedirs("site/en/", exist_ok=True)
for page in PAGES: for page in PAGES:
# Build SR Page # Build SR Page
with open(f'pages/sr/{page["name"]}.html') as f: with open(f'pages/sr/{page["name"]}.html') as f:
page_content = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Studenti su nasli bug' /></div>" page_content = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Studenti su nasli bug' /></div>"
page_content += f.read() page_content += f.read()
sr_html = env.get_template('page-sr.html').render( sr_html = env.get_template("page-sr.html").render(
title=page['titleSR'], title=page["titleSR"],
content=page_content, content=page_content,
extra_styles=f'<link rel="stylesheet" href="/styles/{page["style"]}.css">' if page['style'] else '', extra_styles=(
f'<link rel="stylesheet" href="/styles/{page["style"]}.css">'
if page["style"]
else ""
),
lang="sr", lang="sr",
sr_link=f"/en/{page['name']}", sr_link=f"/en/{page['name']}",
current_path=f"/{page['name']}" if page['name'] != 'index' else "/" current_path=f"/{page['name']}" if page["name"] != "index" else "/",
) )
sr_filename = "index.html" if page['name'] == 'index' else f"{page['name']}.html" sr_filename = (
with open(f'site/{sr_filename}', 'w') as f: "index.html" if page["name"] == "index" else f"{page['name']}.html"
)
with open(f"site/{sr_filename}", "w") as f:
f.write(sr_html) f.write(sr_html)
# Build EN Page # Build EN Page
@@ -42,19 +64,25 @@ def main():
page_content = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Students found the bug' /></div>" page_content = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Students found the bug' /></div>"
page_content += f.read() page_content += f.read()
en_html = env.get_template('page-en.html').render( en_html = env.get_template("page-en.html").render(
title=page['titleEN'], title=page["titleEN"],
content=page_content, content=page_content,
extra_styles=f'<link rel="stylesheet" href="/styles/{page["style"]}.css">' if page['style'] else '', extra_styles=(
f'<link rel="stylesheet" href="/styles/{page["style"]}.css">'
if page["style"]
else ""
),
lang="en", lang="en",
sr_link=f"/{page['name']}", sr_link=f"/{page['name']}",
current_path=f"/en/{page['name']}" if page['name'] != 'index' else "/en/" current_path=f"/en/{page['name']}" if page["name"] != "index" else "/en/",
) )
en_filename = "index.html" if page['name'] == 'index' else f"{page['name']}.html" en_filename = (
with open(f'site/en/{en_filename}', 'w') as f: "index.html" if page["name"] == "index" else f"{page['name']}.html"
)
with open(f"site/en/{en_filename}", "w") as f:
f.write(en_html) f.write(en_html)
if __name__ == '__main__':
main()
if __name__ == "__main__":
main()

View File

@@ -13,10 +13,34 @@ NEXT_MONTH = CURRENT_TIME + relativedelta.relativedelta(months=1, day=1)
DAYS_OF_WEEK_SR = ("PON", "UTO", "SRE", "ČET", "PET", "SUB", "NED") DAYS_OF_WEEK_SR = ("PON", "UTO", "SRE", "ČET", "PET", "SUB", "NED")
DAYS_OF_WEEK_EN = ("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUn") DAYS_OF_WEEK_EN = ("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUn")
MONTHS_SR = ("Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", MONTHS_SR = (
"Avgust", "Septembar", "Oktobar", "Novembar", "Decembar") "Januar",
MONTHS_EN = ("January", "February", "March", "April", "May", "June", "July", "Februar",
"August", "September", "October", "November", "December") "Mart",
"April",
"Maj",
"Jun",
"Jul",
"Avgust",
"Septembar",
"Oktobar",
"Novembar",
"Decembar",
)
MONTHS_EN = (
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
)
HEADER_SR = "Plan za {}" HEADER_SR = "Plan za {}"
@@ -38,8 +62,13 @@ def parseArgs(parser):
""" """
Parse all arguments and return the list of argument values Parse all arguments and return the list of argument values
""" """
parser.add_argument("month", metavar="MM", parser.add_argument(
help="two digit number representing the month for which to generate poster", default="empty", nargs="?") "month",
metavar="MM",
help="two digit number representing the month for which to generate poster",
default="empty",
nargs="?",
)
return parser.parse_args() return parser.parse_args()
@@ -51,18 +80,19 @@ def load_events(csv_path: str, month: int) -> list[dict]:
next(csv_reader, None) next(csv_reader, None)
for event in csv_reader: for event in csv_reader:
event_date = event[0] event_date = event[0]
event_date_parsed = dt.datetime.strptime( event_date_parsed = dt.datetime.strptime(event_date, "%d-%m-%Y").date()
event_date, "%d-%m-%Y").date()
event_time = event[1] event_time = event[1]
event_title = event[3] event_title = event[3]
event_title_en = event[3] event_title_en = event[3]
if len(event) > 6: if len(event) > 6:
event_title_en = event[6] event_title_en = event[6]
current_event = {"date": event_date_parsed, current_event = {
"date": event_date_parsed,
"time": event_time, "time": event_time,
"title": event_title.strip(), "title": event_title.strip(),
"title_en": event_title_en.strip()} "title_en": event_title_en.strip(),
}
if event_date_parsed >= month and event_date_parsed < monthafter: if event_date_parsed >= month and event_date_parsed < monthafter:
events.append(current_event) events.append(current_event)
return events return events
@@ -71,8 +101,7 @@ def load_events(csv_path: str, month: int) -> list[dict]:
def drawMesh(draw, img, fg, bg, font, W, H): def drawMesh(draw, img, fg, bg, font, W, H):
def drawCircle(x, y): def drawCircle(x, y):
r = 50 r = 50
draw.ellipse((x - r, y - r, x + r, y+r), draw.ellipse((x - r, y - r, x + r, y + r), fill=fg, outline=(0, 0, 0), width=0)
fill=fg, outline=(0, 0, 0), width=0)
LCX = 415 # logo center x LCX = 415 # logo center x
LCY = 4350 # logo center y LCY = 4350 # logo center y
@@ -84,11 +113,15 @@ def drawMesh(draw, img, fg, bg, font, W, H):
drawCircle(LCX + d, LCY) drawCircle(LCX + d, LCY)
draw.line([(LCX - d, LCY), (LCX + d, LCY)], fill=fg, width=20, joint=None) draw.line([(LCX - d, LCY), (LCX + d, LCY)], fill=fg, width=20, joint=None)
draw.line([(LCX, LCY), (LCX, LCY + d), (LCX + d, LCY), draw.line(
(LCX, LCY - d)], fill=fg, width=20, joint=None) [(LCX, LCY), (LCX, LCY + d), (LCX + d, LCY), (LCX, LCY - d)],
fill=fg,
width=20,
joint=None,
)
draw.text((LCX - 1.7 * d, LCY + 1.5 * d), "dmz.rs", font=font, fill=fg) draw.text((LCX - 1.7 * d, LCY + 1.5 * d), "dmz.rs", font=font, fill=fg)
mesh_svg = svg2png(url='site/img/mesh-light.svg') mesh_svg = svg2png(url="site/img/mesh-light.svg")
mesh_svg_bytes = io.BytesIO(mesh_svg) mesh_svg_bytes = io.BytesIO(mesh_svg)
mesh_img = Image.open(mesh_svg_bytes) mesh_img = Image.open(mesh_svg_bytes)
if bg == (0, 0, 0): if bg == (0, 0, 0):
@@ -107,15 +140,13 @@ def drawMesh(draw, img, fg, bg, font, W, H):
def drawPoster(events, bg, fg, month: int, en: bool): def drawPoster(events, bg, fg, month: int, en: bool):
fontFacade = ImageFont.truetype('./site/font/Facade-Sud.woff', size=365) fontFacade = ImageFont.truetype("./site/font/Facade-Sud.woff", size=365)
fontIosevka = ImageFont.truetype( fontIosevka = ImageFont.truetype("./site/font/iosevka-regular.woff", size=200)
'./site/font/iosevka-regular.woff', size=200) fontIosevkaSmall = ImageFont.truetype("./site/font/iosevka-regular.woff", size=150)
fontIosevkaSmall = ImageFont.truetype(
'./site/font/iosevka-regular.woff', size=150)
W = 3508 W = 3508
H = 4960 H = 4960
img = Image.new('RGB', (W, H), bg) img = Image.new("RGB", (W, H), bg)
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
drawMesh(draw, img, fg, bg, fontIosevka, W, H) drawMesh(draw, img, fg, bg, fontIosevka, W, H)
@@ -134,8 +165,7 @@ def drawPoster(events, bg, fg, month: int, en: bool):
height = 890 height = 890
sub_header = SUBHEADER_EN if en else SUBHEADER_SR sub_header = SUBHEADER_EN if en else SUBHEADER_SR
draw.text((165, height), sub_header, draw.text((165, height), sub_header, font=fontIosevkaSmall, fill=fg)
font=fontIosevkaSmall, fill=fg)
height += 800 height += 800
# Write list of events to sperate text file as well # Write list of events to sperate text file as well
@@ -167,8 +197,7 @@ def drawPoster(events, bg, fg, month: int, en: bool):
def main(): def main():
# Parse arguments # Parse arguments
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(description="Generate images of the poster")
description="Generate images of the poster")
args = parseArgs(parser) args = parseArgs(parser)
# Set month based on user input # Set month based on user input
@@ -176,22 +205,24 @@ def main():
if args.month.isdigit(): if args.month.isdigit():
month = dt.date(CURRENT_TIME.year, int(args.month), 1) month = dt.date(CURRENT_TIME.year, int(args.month), 1)
elif args.month != "empty": elif args.month != "empty":
print("Month has to be specified as a number. I will use next month as the default") print(
"Month has to be specified as a number. I will use next month as the default"
)
# Load events and draw a poseter # Load events and draw a poseter
events = load_events("dogadjaji.csv", month) events = load_events("dogadjaji.csv", month)
img = drawPoster(events, (0, 0, 0), (20, 250, 50), month, False) img = drawPoster(events, (0, 0, 0), (20, 250, 50), month, False)
img.save('poster_dark.png') img.save("poster_dark.png")
img = drawPoster(events, (255, 255, 255), (0, 0, 0), month, False) img = drawPoster(events, (255, 255, 255), (0, 0, 0), month, False)
img.save('poster_light.png') img.save("poster_light.png")
img = drawPoster(events, (0, 0, 0), (20, 250, 50), month, True) img = drawPoster(events, (0, 0, 0), (20, 250, 50), month, True)
img.save('poster_dark_en.png') img.save("poster_dark_en.png")
img = drawPoster(events, (255, 255, 255), (0, 0, 0), month, True) img = drawPoster(events, (255, 255, 255), (0, 0, 0), month, True)
img.save('poster_light_en.png') img.save("poster_light_en.png")
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -24,9 +24,7 @@
By simply using services we are hosting, conts as contributing, because in By simply using services we are hosting, conts as contributing, because in
that way you joining the decetralization. that way you joining the decetralization.
</p> </p>
<p> <p>Also, we accept donations in bitcoin to the following address:</p>
Also, we accept donations in bitcoin and monero to the following addresses:
</p>
<ul> <ul>
<li>Bitcoin: <i>bc1qjhsfgq79wuzzv32yml9zglwzf9qcwfj3atuy74</i></li> <li>Bitcoin: <i>bc1qjhsfgq79wuzzv32yml9zglwzf9qcwfj3atuy74</i></li>
<!-- <li> <!-- <li>

View File

@@ -24,7 +24,7 @@
Jednostavno koriscenje naseg softwera se takodje racuna kao doprinos, posto Jednostavno koriscenje naseg softwera se takodje racuna kao doprinos, posto
bi se time pridruzili decentralizaciji. bi se time pridruzili decentralizaciji.
</p> </p>
<p>Takođe primamo donacije u bitcoinu i moneru na adresama:</p> <p>Takođe primamo donacije u bitcoinu na adresi:</p>
<ul> <ul>
<li>Bitcoin: <i>bc1qjhsfgq79wuzzv32yml9zglwzf9qcwfj3atuy74</i></li> <li>Bitcoin: <i>bc1qjhsfgq79wuzzv32yml9zglwzf9qcwfj3atuy74</i></li>
<!-- <!--

View File

@@ -7,8 +7,21 @@ EVENTS_CSV_PATH = "dogadjaji.csv"
CURRENT_TIME = dt.date.today() CURRENT_TIME = dt.date.today()
NEXT_MONTH = CURRENT_TIME + relativedelta.relativedelta(months=1, day=1) NEXT_MONTH = CURRENT_TIME + relativedelta.relativedelta(months=1, day=1)
DAYS_OF_WEEK_SR = ("PON", "UTO", "SRE", "ČET", "PET", "SUB", "NED") DAYS_OF_WEEK_SR = ("PON", "UTO", "SRE", "ČET", "PET", "SUB", "NED")
MONTHS_SR = ("Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust",\ MONTHS_SR = (
"Septembar", "Oktobar", "Novembar", "Decembar") "Januar",
"Februar",
"Mart",
"April",
"Maj",
"Jun",
"Jul",
"Avgust",
"Septembar",
"Oktobar",
"Novembar",
"Decembar",
)
def load_events(csv_path: str) -> list[dict]: def load_events(csv_path: str) -> list[dict]:
events = [] events = []
@@ -20,13 +33,16 @@ def load_events(csv_path:str) -> list[dict]:
event_date_parsed = dt.datetime.strptime(event_date, "%d-%m-%Y").date() event_date_parsed = dt.datetime.strptime(event_date, "%d-%m-%Y").date()
event_time = event[1] event_time = event[1]
event_title = event[3] event_title = event[3]
current_event = {"date":event_date_parsed, current_event = {
"date": event_date_parsed,
"time": event_time, "time": event_time,
"title":event_title.strip()} "title": event_title.strip(),
}
if event_date_parsed >= NEXT_MONTH: if event_date_parsed >= NEXT_MONTH:
events.append(current_event) events.append(current_event)
return events return events
def render_table(events: list[dict]) -> str: def render_table(events: list[dict]) -> str:
html = "" html = ""
for event in events: for event in events:
@@ -36,12 +52,13 @@ def render_table(events:list[dict])-> str:
html += f"\t\t\t<tr> <td>{date}</td> <td>{day}.</td> <td>{title}</td> </tr>\n" html += f"\t\t\t<tr> <td>{date}</td> <td>{day}.</td> <td>{title}</td> </tr>\n"
return html return html
def render_page(table: str) -> str: def render_page(table: str) -> str:
head = "<head><meta charset=\"UTF-8\"><link rel=\"stylesheet\"\ head = '<head><meta charset="UTF-8"><link rel="stylesheet"\
href=\"styles/poster.css\"><head>" href="styles/poster.css"><head>'
header = "<h1>DECENTRALA</h1>" header = "<h1>DECENTRALA</h1>"
subheader = f"<h2>Plan za {MONTHS_SR[NEXT_MONTH.month - 1]}</h2>" subheader = f"<h2>Plan za {MONTHS_SR[NEXT_MONTH.month - 1]}</h2>"
link = "<div id=link><img src=\"/img/logo-light.svg\"> dmz.rs</div>" link = '<div id=link><img src="/img/logo-light.svg"> dmz.rs</div>'
p1 = "<p>Radionice počinju u <strong>19h</strong> u Društvenom centru Krov\ p1 = "<p>Radionice počinju u <strong>19h</strong> u Društvenom centru Krov\
u <strong>Kraljice Marije 47</strong>.</p>" u <strong>Kraljice Marije 47</strong>.</p>"
p2 = "<p>Ulaz u zgradu je u prolazu pored Štark prodavnice slatkiša, odmah\ p2 = "<p>Ulaz u zgradu je u prolazu pored Štark prodavnice slatkiša, odmah\
@@ -50,6 +67,7 @@ pored menjačnice. DC Krov je na poslednjem spratu.</p>"
return f"<html>{head}<body><main>{header}{subheader}\ return f"<html>{head}<body><main>{header}{subheader}\
<table>{table}</table>{footer}</main></body></html>" <table>{table}</table>{footer}</main></body></html>"
def main(): def main():
events = load_events(EVENTS_CSV_PATH) events = load_events(EVENTS_CSV_PATH)
table = render_table(events) table = render_table(events)
@@ -58,5 +76,6 @@ def main():
f.write(page) f.write(page)
f.close() f.close()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

79
prep.py
View File

@@ -18,11 +18,12 @@ TYPES_DICT = {
"party": ("zabava", "entertainment"), "party": ("zabava", "entertainment"),
} }
env = Environment(loader=FileSystemLoader('template')) env = Environment(loader=FileSystemLoader("template"))
def load_events(csv_path: str) -> list[dict]: def load_events(csv_path: str) -> list[dict]:
events = [] events = []
with open(csv_path, encoding='utf-8') as csv_file: with open(csv_path, encoding="utf-8") as csv_file:
csv_reader = csv.DictReader(csv_file, skipinitialspace=True) csv_reader = csv.DictReader(csv_file, skipinitialspace=True)
for event in csv_reader: for event in csv_reader:
event_date = event["datum"] event_date = event["datum"]
@@ -32,15 +33,18 @@ def load_events(csv_path:str) -> list[dict]:
event_title = event["tema"] event_title = event["tema"]
types = event["tip"].split() types = event["tip"].split()
link = event.get("link", "") link = event.get("link", "")
current_event = {"date":event_date_parsed, current_event = {
"date": event_date_parsed,
"time": event_time, "time": event_time,
"location": event_location, "location": event_location,
"title": event_title.strip(), "title": event_title.strip(),
"types": types, "types": types,
"link": link} "link": link,
}
events.append(current_event) events.append(current_event)
return events return events
def build_ical(events: list[dict]) -> str: def build_ical(events: list[dict]) -> str:
today = datetime.today().now() today = datetime.today().now()
events_ical = "" events_ical = ""
@@ -55,7 +59,16 @@ def build_ical(events: list[dict]) -> str:
uid = str(date.month).zfill(2) + str(date.day).zfill(2) + time[:2] uid = str(date.month).zfill(2) + str(date.day).zfill(2) + time[:2]
date_str = str(date.year) + str(date.month).zfill(2) + str(date.day).zfill(2) date_str = str(date.year) + str(date.month).zfill(2) + str(date.day).zfill(2)
created = str(today.year) + str(today.month).zfill(2) + str(today.day).zfill(2) + "T" + str(today.hour).zfill(2) + str(today.minute).zfill(2) + str(today.second).zfill(2) + "Z" created = (
str(today.year)
+ str(today.month).zfill(2)
+ str(today.day).zfill(2)
+ "T"
+ str(today.hour).zfill(2)
+ str(today.minute).zfill(2)
+ str(today.second).zfill(2)
+ "Z"
)
date_str = date_str + "T" + time.replace(":", "") + "00" date_str = date_str + "T" + time.replace(":", "") + "00"
event_template_str = env.get_template("event.ical").render( event_template_str = env.get_template("event.ical").render(
@@ -64,7 +77,15 @@ def build_ical(events: list[dict]) -> str:
DATE=date_str, DATE=date_str,
TITLE=title, TITLE=title,
URL=url, URL=url,
LOCATION="DC Krov\\, Kraljice Marije 47\\, 6\\, Beograd\\, Serbia" if location.startswith("DC Krov") else ("Matematički fakultet\\, Svetog Nikole 39\\, Beograd\\, Serbia" if location.startswith("Matematički fakultet (Učionica 153)") else location) LOCATION=(
"DC Krov\\, Kraljice Marije 47\\, 6\\, Beograd\\, Serbia"
if location.startswith("DC Krov")
else (
"Matematički fakultet\\, Svetog Nikole 39\\, Beograd\\, Serbia"
if location.startswith("Matematički fakultet (Učionica 153)")
else location
)
),
) )
events_ical += event_template_str events_ical += event_template_str
@@ -72,23 +93,30 @@ def build_ical(events: list[dict]) -> str:
events_ical += file.read() events_ical += file.read()
return events_ical return events_ical
def render_page(template_name, output_path, context): def render_page(template_name, output_path, context):
template = env.get_template(template_name) template = env.get_template(template_name)
with open(output_path, "w") as file: with open(output_path, "w") as file:
file.write(template.render(context)) file.write(template.render(context))
# Main execution # Main execution
events = sorted(load_events("dogadjaji.csv"), key=lambda e: e["date"]) events = sorted(load_events("dogadjaji.csv"), key=lambda e: e["date"])
today = datetime.today().date() today = datetime.today().date()
past_events = sorted([e for e in events if e["date"] <= today], key=lambda e: e["date"], reverse=True) past_events = sorted(
[e for e in events if e["date"] <= today], key=lambda e: e["date"], reverse=True
)
new_events = [e for e in events if e["date"] >= today] new_events = [e for e in events if e["date"] >= today]
sr_types = {k: v[0] for k, v in TYPES_DICT.items()} sr_types = {k: v[0] for k, v in TYPES_DICT.items()}
en_types = {k: v[1] for k, v in TYPES_DICT.items()} en_types = {k: v[1] for k, v in TYPES_DICT.items()}
# Build Serbian Pages # Build Serbian Pages
render_page("events-sr.html", "pages/sr/events.html", { render_page(
"events-sr.html",
"pages/sr/events.html",
{
"lang": "sr", "lang": "sr",
"title": "Događaji", "title": "Događaji",
"sr_link": "/events_archive", "sr_link": "/events_archive",
@@ -116,10 +144,14 @@ render_page("events-sr.html", "pages/sr/events.html", {
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}
""").render(events=new_events, types_names=sr_types) """).render(events=new_events, types_names=sr_types),
}) },
)
render_page("events-en.html", "pages/en/events.html", { render_page(
"events-en.html",
"pages/en/events.html",
{
"lang": "en", "lang": "en",
"title": "Events", "title": "Events",
"sr_link": "/events_archive", "sr_link": "/events_archive",
@@ -147,11 +179,15 @@ render_page("events-en.html", "pages/en/events.html", {
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}
""").render(events=new_events, types_names=en_types) """).render(events=new_events, types_names=en_types),
}) },
)
# Build Archive Pages # Build Archive Pages
render_page("events_archive-sr.html", "pages/sr/events_archive.html", { render_page(
"events_archive-sr.html",
"pages/sr/events_archive.html",
{
"lang": "sr", "lang": "sr",
"title": "Arhiva događaja", "title": "Arhiva događaja",
"sr_link": "/events", "sr_link": "/events",
@@ -179,10 +215,14 @@ render_page("events_archive-sr.html", "pages/sr/events_archive.html", {
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}
""").render(events=past_events, types_names=sr_types) """).render(events=past_events, types_names=sr_types),
}) },
)
render_page("events_archive-en.html", "pages/en/events_archive.html", { render_page(
"events_archive-en.html",
"pages/en/events_archive.html",
{
"lang": "en", "lang": "en",
"title": "Events archive", "title": "Events archive",
"sr_link": "/en/events", "sr_link": "/en/events",
@@ -210,8 +250,9 @@ render_page("events_archive-en.html", "pages/en/events_archive.html", {
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}
""").render(events=past_events, types_names=en_types) """).render(events=past_events, types_names=en_types),
}) },
)
# Build ical # Build ical
with open("site/events.ical", "w") as file: with open("site/events.ical", "w") as file:

8
pyproject.toml Normal file
View File

@@ -0,0 +1,8 @@
[tool.black]
line-length = 88
target-version = ['py312']
[tool.flake8]
max-line-length = 88
extend-ignore = "E203"
exclude = ".venv"

View File

@@ -1,7 +1,9 @@
cairosvg cairosvg
markdown black
freetype-py
python-dateutil
feedgen feedgen
pillow flake8
freetype-py
jinja2 jinja2
markdown
pillow
python-dateutil