Init repository
This commit is contained in:
commit
0e2fcf3195
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
html
|
||||
result
|
21
README.md
Normal file
21
README.md
Normal 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
43
assets/style.css
Normal 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
77
chaosevents.py
Executable 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
27
flake.lock
Normal 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
40
flake.nix
Normal 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
34
pyproject.toml
Normal 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
43
templates/index.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user