Skip to content

Commit 584bf7c

Browse files
author
github-actions[bot]
committed
mastodon comment system and working footnotes
1 parent 02ebddc commit 584bf7c

12 files changed

Lines changed: 1337 additions & 49 deletions

.github/scripts/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
PyYAML>=6.0
2+
requests>=2.28
3+
python-dateutil>=2.8

.github/scripts/toot_and_commit.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generated by the github copilot agent, but heavily modified and corrected by me
4+
"""
5+
6+
"""
7+
What this script does:
8+
Finds published posts in _posts/, post a toot for those missing comment_id, write the comment_id back and commit.
9+
10+
11+
This is compatible to jekyll, regarding publishing it considers the `publish` and `published` flag and checks the date whether it is already published
12+
(YAML has precedence over filename).
13+
NOTE: This will generate wrong links, if you wrote one of the predefined permalinks schemes into the frontmatter (or changed the default). Only the default scheme is currently supported.
14+
15+
16+
Environment variables:
17+
MASTODON_TOKEN - access token for Mastodon
18+
GITHUB_TOKEN - token with repo write permissions (provided by Actions)
19+
20+
Furthermore in _config.yml:
21+
url for generating links to the blog
22+
mastodon:
23+
- username: xyz
24+
instance: abc.com
25+
26+
The mastodon username and instance
27+
28+
29+
This script edits files in-place and commits changes using git.
30+
"""
31+
import os
32+
import re
33+
import sys
34+
import yaml
35+
import requests
36+
from datetime import datetime, timezone
37+
from dateutil import parser as date_parser
38+
from pathlib import Path
39+
import subprocess
40+
import logging
41+
42+
# TODO change
43+
logging.basicConfig(level=logging.DEBUG)
44+
45+
46+
POSTS_DIR = Path("_posts")
47+
48+
49+
def parse_front_matter(text):
50+
m = re.match(r"^---\n(.*?)\n---\n(.*)$", text, re.S)
51+
if not m:
52+
logging.warning(f"Frontmatter regex failed on a post: {text}")
53+
return None, text
54+
fm_text, body = m.group(1), m.group(2)
55+
data = yaml.safe_load(fm_text) or {}
56+
logging.debug(data)
57+
return data, body
58+
59+
60+
def build_content(fm, body):
61+
fm_text = yaml.safe_dump(fm, sort_keys=False).rstrip() + "\n"
62+
return "---\n" + fm_text + "---\n" + (body.lstrip())
63+
64+
65+
def get_date(fm, filename):
66+
date = fm.get("date")
67+
if date is None:
68+
date = "-".join(filename.split("-")[:3])
69+
# Crashes if date does not exist or is invalid
70+
d = date_parser.parse(str(date))
71+
if d.tzinfo is None:
72+
d = d.replace(tzinfo=timezone.utc)
73+
return d
74+
75+
76+
def is_published(fm, filename):
77+
pub = fm.get("publish") or fm.get("published") or fm.get("published",
78+
None)
79+
if isinstance(pub, bool) and not pub:
80+
return False
81+
# allow publish: true or published: true; if absent, consider published if date <= now
82+
d = get_date(fm, filename)
83+
if d:
84+
return d <= datetime.now(timezone.utc)
85+
86+
return True
87+
88+
89+
def toot_post(instance, token, content, in_reply_to_id=None):
90+
url = instance.rstrip("/") + "/api/v1/statuses"
91+
data = {"status": content, "visibility": "public"}
92+
if in_reply_to_id:
93+
data["in_reply_to_id"] = in_reply_to_id
94+
headers = {"Authorization": f"Bearer {token}"}
95+
r = requests.post(url, data=data, headers=headers, timeout=30)
96+
logging.debug(data, headers)
97+
r.raise_for_status() # Throw exception if this did not work
98+
return r.json()
99+
100+
101+
def git_commit_and_push(files, message):
102+
if not files:
103+
return
104+
subprocess.check_call(["git", "config", "user.name", "github-actions[bot]"])
105+
subprocess.check_call(["git", "config", "user.email", "invalid@example.com"])
106+
subprocess.check_call(["git", "add"] + files)
107+
subprocess.check_call(["git", "commit", "-m", message])
108+
# push using the repository origin; GITHUB_TOKEN is available in env for auth via checkout
109+
subprocess.check_call(["git", "push"])
110+
111+
112+
def main():
113+
token = os.getenv("MASTODON_TOKEN")
114+
115+
with open("_config.yml") as file:
116+
config = yaml.safe_load(file.read())
117+
instance = config.get("mastodon")[0]["instance"]
118+
if not instance or not token:
119+
logging.error("MASTODON_TOKEN must be set in github actions env and the mastodon block (see at the beginning of this file) configured in _config.yml")
120+
sys.exit(1)
121+
122+
if not POSTS_DIR.exists():
123+
logging.error(f"Posts dir {POSTS_DIR} not found")
124+
sys.exit(1)
125+
126+
changed_files = []
127+
128+
for path in sorted(POSTS_DIR.iterdir()):
129+
if not path.is_file():
130+
logging.debug("A")
131+
continue
132+
text = path.read_text(encoding="utf-8")
133+
fm, body = parse_front_matter(text)
134+
if fm is None:
135+
logging.debug("B")
136+
continue
137+
if not is_published(fm, path.name):
138+
logging.debug("C")
139+
continue
140+
if fm.get("comment_id"):
141+
logging.debug("D")
142+
continue
143+
# check file has correct naming scheme
144+
145+
logging.debug(f"Current filename: {path.name}")
146+
147+
# prepare toot content: use title and permalink if present
148+
title = fm.get("title") or path.stem
149+
# Link schemas are listed here: https://mademistakes.com/mastering-jekyll/how-to-link/
150+
# /:categories/:year/:month/:day/:title:output_ext
151+
152+
if type(fm.get("categories")) == list:
153+
categories = "/".join(fm.get("categories"))
154+
else:
155+
categories = fm.get("categories")
156+
date = get_date(fm, path.name)
157+
if date is False:
158+
raise Exception("Could not parse Date")
159+
160+
blog_url = config.get("url")
161+
url = fm.get("permalink") or f"{blog_url}/{categories}/{str(date.year)}/{str(date.day)}/{path.name.split(".")[-2]}.html"
162+
toot = f"""Read my new post {title}:
163+
{url}
164+
165+
To comment on it, please just answer to this toot. The toots will be loaded underneath the article.
166+
167+
Lies meinen neuen Blogpost (link oberhalb)
168+
Zum kommentieren, einfach unter diesem Toot kommentieren, die toots landen dann unter dem Artikel.
169+
"""
170+
171+
logging.info(f"Tooting for {path.name}: {toot}")
172+
try:
173+
res = toot_post(instance, token, toot)
174+
except Exception as e:
175+
logging.error(f"Failed to toot {path}: {e}")
176+
continue
177+
178+
comment_id = res.get("id")
179+
if not comment_id:
180+
logging.error(f"No id returned for {path}")
181+
break
182+
183+
fm["comment_id"] = str(comment_id)
184+
new_content = build_content(fm, body)
185+
path.write_text(new_content, encoding="utf-8")
186+
changed_files.append(str(path))
187+
188+
if changed_files:
189+
git_commit_and_push(changed_files, "Add comment_id for tooted posts")
190+
191+
192+
if __name__ == "__main__":
193+
main()

.github/workflows/jekyll.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@ concurrency:
2727
cancel-in-progress: false
2828

2929
jobs:
30+
toot:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Checkout repository
34+
uses: actions/checkout@v4
35+
with:
36+
persist-credentials: true
37+
38+
- name: Set up Python
39+
uses: actions/setup-python@v4
40+
with:
41+
python-version: '3.x'
42+
43+
- name: Install script dependencies
44+
run: pip install -r .github/scripts/requirements.txt
45+
46+
- name: Run toot script
47+
env:
48+
MASTODON_TOKEN: ${{ secrets.MASTODON_TOKEN }}
49+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
run: python .github/scripts/toot_and_commit.py
51+
52+
53+
3054
# Build job
3155
build:
3256
runs-on: ubuntu-latest

README.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
# Das soll mein Blog werden
22
This blog is inconsistently German and English
33

4-
Jekyll Template verwenden (https://jekyllrb.com/)
4+
Favicon/Logo: https://openclipart.org/detail/349961/brain (everything on the website is licensed under CC0)
5+
jekyll template: https://github.com/jekyll/minima
6+
comment embedding js: https://github.com/dpecos/mastodon-comments/
57

6-
## Kategorie: Was mich beeinflusst
8+
The autoposting works like this: TODO
79

810
TODO:
9-
- banner on every page (footer and header basically (footer with commments, and how they would like to be informed about updates))
11+
- banner on every page (header with disclaimer about being civil and favorable when reading as well as asking whether people want updates)
1012
- Mail Newsletter?
11-
- mastodon comments?
12-
- footnotes? https://stackoverflow.com/questions/19483975/jekyll-on-github-pages-any-way-to-add-footnotes-in-markdown
13-
14-
15-
Nice to have: https://jan.wildeboer.net/2023/02/Jekyll-Mastodon-Comments/
16-
17-
18-
https://www.fabriziomusacchio.com/blog/2023-07-31-mastodon_blog_comment_system/
13+
- get comment_embedding and autoposting through git submodule

_config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ email: blog@twooceans.de
2323
baseurl: "" # the subpath of your site, e.g. /blog
2424
url: "https://blog.twoooceans.de" # the base hostname & protocol for your site, e.g. http://example.com
2525
github_username: jon011235
26+
mastodon:
27+
- username: overwhelming_complexity
28+
instance: troet.cafe
29+
2630
lang: de-DE
2731

2832
# Build settings

_layouts/post1.html

Lines changed: 0 additions & 9 deletions
This file was deleted.

_layouts/post_comment.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
layout: post
3+
---
4+
5+
{{content}}
6+
7+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
8+
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.4.1/purify.min.js" integrity="sha512-uHOKtSfJWScGmyyFr2O2+efpDx2nhwHU2v7MVeptzZoiC7bdF6Ny/CmZhN2AwIK1oCFiVQQ5DA/L9FSzyPNu6Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
9+
10+
<script type="module" src="/scripts/mastodon-comments.js"></script>
11+
12+
<div>
13+
<mastodon-comments
14+
host="{{ site.mastodon[0].instance }}"
15+
user="{{ site.mastodon[0].username }}"
16+
tootId="{{ page.comment_id }}"
17+
style="width:1024px"></mastodon-comments>
18+
</div>

_posts/2025-12-04-instagram.markdown

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
---
2-
layout: post
3-
title: "Ein Monat Instagram - die ultimative Social Media Challenge"
4-
date: 2025-12-04 16:43:32 +0100
2+
layout: post_comment
3+
title: "Ein Monat Instagram - Eindr\xFCcke nach langer Verweigerung"
4+
date: 2025-12-04 16:43:32 +0100
55
categories: reflection
6+
comment_id: '115827220511082913'
67
---
8+
> **Update: 2.1.2026**: Ursprünglich hieß der Text "Ein Monat Instagram - die ultimative Challenge", was ich schön ironisch fand, aber anscheinend kam die Ironie nicht an und es wurde stattdessen als tatsächlicher Clickbait interpretiert. Ich fürchte der Titel ist immer noch nicht gut, aber hoffentlich besser.
79
810
Ich probiere aktuell Instagram aus, nachdem ich es 20 Jahre lang verweigert habe. Ich habe mir einen Monat gesetzt, um die App zu erkunden, und muss schon jetzt sagen: Ich freue mich darauf, sie bald wieder zu deinstallieren. Ich weiß jetzt schon, dass ich trotzdem einiges vermissen werde:
911

_posts/2025-12-14-atheismus.md

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
---
2-
layout: post
3-
title: "Atheismus – eine erkenntnistheoretisch schwer haltbare Position"
4-
date: 2025-12-14 14:24:00 +0100
5-
categories: reflection
6-
---
7-
8-
:::note
9-
Dieser Text ist definitiv nichts **Unglaubliches Neues** und ist wahrscheinlich auch schlechter belegt. Ich hoffe, du findest ihn trotzdem interessant.
10-
Als Gegenthese könnte man beispielsweise Richard Dawkins lesen, den ich persönlich als selbst dogmatisch empfinde. Ich möchte außerdem hinzufügen, dass ich zu den meisten hier genannten Dingen bislang keine Primärquelle gelesen habe.
11-
:::
1+
---
2+
layout: post_comment
3+
title: Atheismus - eine erkenntnistheoretisch schwer haltbare Position
4+
date: 2025-12-14 14:24:00 +0100
5+
categories: reflection
6+
---
7+
8+
> Dieser Text ist definitiv nichts **Unglaubliches Neues** und ist wahrscheinlich auch schlechter belegt. Ich hoffe, du findest ihn trotzdem interessant.
9+
> Als Gegenthese könnte man beispielsweise Richard Dawkins lesen, den ich persönlich als selbst dogmatisch empfinde. Ich möchte außerdem hinzufügen, dass ich zu den meisten hier genannten Dingen bislang keine Primärquelle gelesen habe.
10+
1211

1312
Einige Definitionen zum Zweck dieses Posts:
1413

@@ -20,9 +19,9 @@ Die hier verwendete Definition geht letztlich auf Karl Popper zurück, der als
2019

2120
Damit die „klassische“ empirische Methode funktioniert, sind Wiederholbarkeit und damit die Kontrolle über die relevanten Faktoren eines Experiments unerlässlich. Im Umkehrschluss bedeutet das, dass ein göttliches Wesen, das nicht bei dem Experiment „mitspielen“ will, nicht feststellbar ist. Es lassen sich keine überprüfbaren (falsifizierbaren) Hypothesen aufstellen; die Frage nach einem göttlichen Wesen liegt somit außerhalb der Aussagekraft der Wissenschaft[^2].
2221

23-
Daraus ergeben sich unendlich viele hypothetische Welten, die durch Experimente für uns nicht unterscheidbar sind. Noch gravierender: Auch ohne die Möglichkeit irgendeiner „göttlichen Wesen“ gibt es unendlich viele Modelle[^6], die bislang durch unsere Experimente nicht unterschieden werden können, und darüber hinaus zahlreiche Deutungen dieser Modelle[^1] (wobei Theorie und Deutung nicht scharf getrennt sind).
22+
Daraus ergeben sich unendlich viele hypothetische Welten, die durch Experimente für uns nicht unterscheidbar sind. Noch gravierender: Auch ohne die Möglichkeit irgendeiner „göttlichen Wesen“ gibt es unendlich viele Modelle[^6], die bislang durch unsere Experimente nicht unterschieden werden können, und darüber hinaus zahlreiche Deutungen dieser Modelle[^1] (wobei Theorie und Deutung nicht scharf getrennt sind).
2423

25-
##Widerspruch durch Ockhams Rasiermesser und untestbare Götter
24+
## Widerspruch durch Ockhams Rasiermesser und untestbare Götter
2625

2726
Um aus einer Vielzahl nicht falsifizierbarer Modelle eines auszuwählen, das man als das „wahrscheinlichste“ betrachtet[^7], benötigt man zusätzliche Annahmen. Sehr beliebt ist hierbei das Prinzip von [Ockhams Rasiermesser](https://de.wikipedia.org/wiki/Ockhams_Rasiermesser). Es bezeichnet das eher abstrakte Konzept, die „einfachere“ Theorie auszuwählen – typischerweise jene, die weniger oder schwächer ausgeprägte Annahmen erfordert. Dieses Prinzip kann natürlich dazu führen, dass Theorien, die der zugrunde liegenden „echten“ Wahrheit näher kommen, ausgeschlossen werden[^3].
2827

@@ -35,21 +34,28 @@ Das macht Ockhams Rasiermesser keineswegs zu einer schlechten Annahme; es ist be
3534

3635
Das Problem liegt darin, dass Ockhams Rasiermesser häufig in Debatten angeführt wird, um Gott zu „widerlegen“. Dabei ist Ockhams Rasiermesser genauso leichtfertig ein Glaube (bzw. eine Annahme) wie die Annahme eines Gottes, die Atheisten oftmals als bloße Annahme bezeichnen. Es gibt keinen tiefer liegenden Grund dafür, außer Praktikabilität und Vereinfachung – genauso wie Glaube, der auch ohne die Existenz Gottes zu Geborgenheit und Gemeinschaft führen kann.
3736

38-
## Fazit
37+
## Fazit
3938

4039
Weniger Annahmen und damit mehr Allgemeingültigkeit erreicht man, wenn man weder Ockhams Rasiermesser noch Gott annimmt (oder glaubt) und stattdessen eine agnostische Haltung einnimmt. Für konkrete Glaubensschemata, die falsifizierbare Hypothesen aufweisen (z. B. die Wirksamkeit von Talismanen oder Homöopathie), sieht das Bild natürlich anders aus. Gleichzeitig schließt es beispielsweise Gotteserscheinungen nicht aus, da diese inhärent nicht wiederholbar sind und damit ebenfalls keine testbare Hypothese darstellen.
4140

4241
<!--
4342
Hinzu kommt, dass einige Atheisten (darunter beispielsweise [Richard Dawkins](https://de.wikipedia.org/wiki/Richard_Dawkins)) das System von Glaube recht gut reproduzieren: Sie vertreten mit großer Überzeugung die Ansicht, dass es keinen Gott gibt. Diese Position ist zwar völlig vertretbar, aber nicht belegbar und führt teilweise zu Pauschalisierungen wie „Alle Gläubigen sind Fanatiker“, wodurch die Kritik an Religion selbst reproduziert wird.
44-
-->
45-
46-
## Fußnoten
47-
48-
[^2] Ein (oder mehrere) potenziell existierende göttliche Wesen nehmen anscheinend nicht an den Experimenten (z. B. einem Gespräch) teil, weil sie nicht können oder wir das passende Experiment noch nicht gefunden haben.
49-
[^6] Beispielsweise alle Supersymmetrien und Stringtheorien, die in der heutigen Physik diskutiert werden.
50-
[^1] In der Quantenphysik etwa die Kopenhagener Deutung versus die Viele‑Welten‑Theorie; früher gleichwertige, experimentell nicht unterscheidbare Deutungen wie der [Dirac‑See](https://de.wikipedia.org/wiki/Dirac-See) oder der [Lichtäther](https://de.wikipedia.org/wiki/%C3%84ther_(Physik)).
51-
[^7] Zweck der Priorisierung von Forschung oder zur Entscheidung, was gelehrt und kommuniziert wird.
52-
[^3] Als einfachstes Beispiel dient [Flatland](https://de.wikipedia.org/wiki/Flatland)[^5]: Eine Gesellschaft von Wesen, die nur eine zweidimensionale Welt wahrnehmen können, aber in Wirklichkeit in einer dreidimensionalen leben. Das Buch ist eine empfehlenswerte Satire, die die Begrenztheit unserer Vorstellungskraft verdeutlicht, wenn wir versuchen, höhere Dimensionen zu begreifen.
53-
[^5] Auch erwähnt auf der [Seite](/influential) mit Medien, die mich beeindruckt haben.
54-
[^4] Mathematischer Fachausdruck für „widersprüchlich“.
55-
[^8] Der Hinweis, dass wir uns nicht sicher sind, ist eine eher langweilige Erklärung für Menschen, die prinzipiell Interesse an aktuellem Forschungsstand haben, aber nicht die Zeit und Kapazität, sich hundert verschiedene Modelle anzuschauen.
43+
-->
44+
45+
## Fußnoten
46+
47+
[^2]: Ein (oder mehrere) potenziell existierende göttliche Wesen nehmen anscheinend nicht an den Experimenten (z. B. einem Gespräch) teil, weil sie nicht können oder wir das passende Experiment noch nicht gefunden haben.
48+
49+
[^6]: Beispielsweise alle Supersymmetrien und Stringtheorien, die in der heutigen Physik diskutiert werden.
50+
51+
[^1]: In der Quantenphysik etwa die Kopenhagener Deutung versus die Viele‑Welten‑Theorie; früher gleichwertige, experimentell nicht unterscheidbare Deutungen wie der [Dirac‑See](https://de.wikipedia.org/wiki/Dirac-See) oder der [Lichtäther](https://de.wikipedia.org/wiki/%C3%84ther_(Physik)).
52+
53+
[^7]: Zweck der Priorisierung von Forschung oder zur Entscheidung, was gelehrt und kommuniziert wird.
54+
55+
[^3]: Als einfachstes Beispiel dient [Flatland](https://de.wikipedia.org/wiki/Flatland)[^5]: Eine Gesellschaft von Wesen, die nur eine zweidimensionale Welt wahrnehmen können, aber in Wirklichkeit in einer dreidimensionalen leben. Das Buch ist eine empfehlenswerte Satire, die die Begrenztheit unserer Vorstellungskraft verdeutlicht, wenn wir versuchen, höhere Dimensionen zu begreifen.
56+
57+
[^5]: Auch erwähnt auf der [Seite](/influential) mit Medien, die mich beeindruckt haben.
58+
59+
[^4]: Mathematischer Fachausdruck für „widersprüchlich“.
60+
61+
[^8]: Der Hinweis, dass wir uns nicht sicher sind, ist eine eher langweilige Erklärung für Menschen, die prinzipiell Interesse an aktuellem Forschungsstand haben, aber nicht die Zeit und Kapazität, sich hundert verschiedene Modelle anzuschauen.

favicon.ico

207 KB
Binary file not shown.

0 commit comments

Comments
 (0)