Init repository

This commit is contained in:
clerie 2023-06-13 12:30:20 +02:00
commit 0e2fcf3195
8 changed files with 287 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
html
result

21
README.md Normal file
View File

@ -0,0 +1,21 @@
# Chaos Events
This repository contains code that generates the [Chaos Events Website](https://chaosevents.clerie.de).
If fetches an ICS from a URL and generates html files that get placed in a specified directory.
## Use with pip
```
pip install .
```
```
chaosevents path/to/out/directory
```
## Use with flake
```
nix run . -- path/to/out/directory
```

43
assets/style.css Normal file
View File

@ -0,0 +1,43 @@
* {
padding: 0;
margin: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
.container {
max-width: 800px;
padding: 20px;
margin: auto;
}
header {
margin-top: 40px;
margin-bottom: 80px;
text-align: center;
}
section {
margin-top: 40px;
margin-bottom: 40px;
}
section h2 {
text-align: center;
}
section h3 .date {
font-size: medium;
color: dimgray;
}
section .description {
padding: 10px;
list-style-position: inside;
}
footer {
text-align: center;
}

77
chaosevents.py Executable file
View File

@ -0,0 +1,77 @@
#!/usr/bin/env python3
import arrow
from ics import Calendar
from jinja2 import Environment, FileSystemLoader, select_autoescape
from markdown2 import Markdown
from pathlib import Path
import re
import requests
import sys
basepath = Path(__file__).resolve().parent
env = Environment(
loader=FileSystemLoader(basepath / "templates"),
autoescape=select_autoescape()
)
def render_markdown(text):
pattern = re.compile(
r"""
\b
(
(?:https?://|(?<!//)www\.) # prefix - https:// or www.
\w[\w_\-]*(?:\.\w[\w_\-]*)* # host
[^<>\s"']* # rest of url
(?<![?!.,:*_~);]) # exclude trailing punctuation
(?=[?!.,:*_~);]?(?:[<\s]|$)) # make sure that we're not followed by " or ', i.e. we're outside of href="...".
)
""",
re.X
)
markdown = Markdown(
extras=["link-patterns"],
link_patterns=[(pattern, r'\1')]
)
return markdown.convert('' if text is None else text)
def main(ics_url, out_path):
(out_path / "style.css").write_text((basepath / "assets" / "style.css").read_text())
r = requests.get(ics_url)
c = Calendar(r.text)
t = c.timeline
for e in t:
e.description_rendered = render_markdown(e.description)
(out_path / "chaosevents.ics").write_text(r.text)
(out_path / "index.html").write_text(
env.get_template("index.html").render(
currentevents=t.now() if any(t.now()) else None,
upcomingevents=t.start_after(arrow.utcnow())
)
)
def cli():
ics_url = "https://cloud.fem.tu-ilmenau.de/remote.php/dav/public-calendars/Q58G8xM52HXPc6Jj/?export"
out_path = Path("html")
if len(sys.argv) > 1:
out_path = Path(sys.argv[1])
out_path.mkdir(exist_ok=True)
main(ics_url, out_path)
if __name__ == "__main__":
cli()

27
flake.lock Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1686501370,
"narHash": "sha256-G0WuM9fqTPRc2URKP9Lgi5nhZMqsfHGrdEbrLvAPJcg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "75a5ebf473cd60148ba9aec0d219f72e5cf52519",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

40
flake.nix Normal file
View File

@ -0,0 +1,40 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs, ... }: {
packages.x86_64-linux = let
pkgs = import nixpkgs {
system = "x86_64-linux";
};
in {
chaosevents = pkgs.python311Packages.buildPythonPackage rec {
pname = "chaosevents";
version = "0.0.1";
src = ./.;
format = "pyproject";
buildInputs = [ pkgs.python311Packages.hatchling ];
propagatedBuildInputs = with pkgs.python311Packages; [ attrs ics jinja2 markdown2 requests ];
pythonImportsCheck = [ "chaosevents" ];
};
default = self.packages.x86_64-linux.chaosevents;
};
apps.x86_64-linux = {
chaosevents = {
type = "app";
program = self.packages.x86_64-linux.chaosevents + "/bin/chaosevents";
};
default = self.apps.x86_64-linux.chaosevents;
};
hydraJobs = {
inherit (self)
packages;
};
};
}

34
pyproject.toml Normal file
View File

@ -0,0 +1,34 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "chaosevents"
version = "0.0.1"
authors = [
{ name="clerie", email="hallo@clerie.de" },
]
description = ""
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"ics",
"jinja2",
"markdown2",
"requests",
]
[project.scripts]
chaosevents = "chaosevents:cli"
[project.urls]
"Source" = "https://git.clerie.de/clerie/chaosevents"
[tool.hatch.build]
include = [
"*.py",
"assets",
"templates",
]

43
templates/index.html Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Upcoming Chaos Events</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<div class="container">
<header>
<h1>Chaos Events</h1>
<div>
<a href="/chaosevents.ics">Add to calendar</a> | <a href="mailto:chaosevents@clerie.de"> Event missing?</a>
</div>
</header>
{% if currentevents %}
<section>
<h2>Current</h2>
</section>
{% for event in currentevents %}
<section>
<h3>{{ event.name }} <span class="date">{{ event.begin.format("YYYY-MM-DD") }} - {{ event.end.shift(seconds=-1).format("YYYY-MM-DD") }}</span></h3>
<div class="description">
{{ event.description_rendered|safe }}
</div>
</section>
{% endfor %}
{% endif %}
<section>
<h2>Upcoming</h2>
</section>
{% for event in upcomingevents %}
<section>
<h3>{{ event.name }} <span class="date">{{ event.begin.format("YYYY-MM-DD") }} - {{ event.end.shift(seconds=-1).format("YYYY-MM-DD") }}</span></h3>
<div class="description">
{{ event.description_rendered|safe }}
</div>
</section>
{% endfor %}
<footer>
<a href="https://legal.clerie.de/impressum">Imprint</a> | <a href="https://legal.clerie.de/datenschutz">Privacy</a>
</footer>
</div>
</body>