zurück zu Kategorien

Kategorie: ubuntuusers

Simpler quarto-bot für Nextcloud

Mit quarto setze ich unter anderem auch meine (Geschäfts)Briefe als PDF-Datei. Hierfür habe ich mir ein paar Vorlagen gebastelt, siehe z.B. dieses Beispiel.

Das funktioniert soweit auf dem PC sehr gut. Am Handy oder am Tablet ist quarto mit $\LaTeX$ nicht verfügbar, weshalb ich mir einen kleinen Bot programmiert habe, der einen Nextcloud-Ordner “überwacht” und die vorhandenen .qmd-Dateien zu PDFs rendert.

Der Bot

  • mountet den Nextcloud-Ordner per Webdav

  • überwacht in einem vorgegebenem Zeitintervall (30 Sek.), ob .qmd-Dateien in diesem Verzeichnis vorhanden sind

  • führt den Befehl quarto render DATEI.qmd auf jede .qmd-Datei im Verzeichnis aus. Quarto legt die erzeugten PDF-Dateien ins selbe Verzeichnis.

  • verschiebt die .qmd-Datei nach .qmd-TIMESTAMP. So wird sie nicht erneut gerendert.

  • wartet 30 Sekunden und fängt wieder von vorne an

  • wird über systemd gesteuert.

  • läuft nicht als root, sondern als normaler User, in meinem Falle produnis.

So kann ich “von überall”, z.B. am Handy, eine .qmd-Datei erzeugen, diese ins Nextcloud-Verzeichnis uploaden, 30 Sekunden warten, und die fertige PDF-Datei aus dem Nextcloud-Verzeichnis herunterladen.

Der Bot kann an jedem beliebigen Linux-PC mit Internetanschluss betrieben werden. Du musst “lediglich” sicherstellen, dass der Befehl

1
2
# muss fehlerfrei durchlaufen
quarto render Datei.qmd

korret auf dem Server ausgeführt wird. Der Bot führt ja letztendlich auch “nur” diesen Befehl aus.

Nextcloud

In Nextcloud habe ich in meinem Homeverzeichnis den Ornder quarto, und darunter den Ordner renderbot erstellt. In letzterem wird der Bot lauschen. Letztendlich ist es aber egal, welcher Ordner genau verwendet werden soll.

Mountpunkt

Auf dem Bot-PC erstelle ich mir das Verzeichis /media/Nextcloudquartobot.

1
2
# erstelle Verzeichnis
mkdir -p /media/Nextcloudquartobot

Hierhin mounten wir per WebDav unser Nextcloudverzeichnis. Die Dav-Adresse lautet:

1
2
# Webdav-Adresse
https://DEINE.NEXTCLOUD/remote.php/dav/files/USERNAME/pfad/zu/ordner

Wir mounten dieses Verzeichnis per systemd, daher müssen wir alles so einstellen, dass keine Passwortabfrage beim mounten erfolgt. Hierzu hinterlegen wir unsere Userdaten in der Datei /etc/davfs2/secrets :

1
2
# Passwörter hinzufügen
sudo nano /etc/davfs2/secrets

nach folgendem Schema:

1
2
# Schema
MOUNTPOINT  USERNAME "PASSWORD"

In meinem Falle also:

1
/media/Nextcloudquartobot  produnis "!SuperSecret#Password!"

Anschließend erstellen wir eine systemd.mount-Datei. Diese muss genau so heissen wie das Verzeichnis, in welches gemountet werden soll.

1
sudo nano /etc/systemd/system/media-Nextcloudquartobot.mount

Sie erhält folgenden Inhalt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Unit]
Description=WebDAV-Mount-Nextcloud-Quarto-Renderbot
After=network-online.target
Before=quarto-nextcloud-bot.service

[Mount]
Type=davfs
What=https://MEINE.NEXTCLOUD/remote.php/dav/files/USER/pfad/zu/ordner
Where=/media/Nextcloudquartobot
Options=noauto,user,uid=produnis,gid=produnis

[Install]
WantedBy=multi-user.target

In Zeile 4 habe ich bereits auf den noch zu erstellenden Bot-Service verwiesen. Die Mount-Unit soll immer vor dem Bot-Service starten.

In Zeile 8 müsst ihr eure Userdaten ergänzen

In Zeile 10 wird festgelegt, dass der User produnis den Mount durchführen soll, und nicht root. Hierdurch wird sichergestellt, dass ich auch alle Lese- und Schreibrechte erhalte.

Wir können das Verzeichnis nun per systemd mounten:

1
2
3
4
5
# mounten
sudo systemctl start media-Nextcloudquartobot.mount

#unmounten
sudo systemctl stop media-Nextcloudquartobot.mount

Bashscript

Die Aktion soll ein kleines Bashscript ausführen. Ich habe es quarto-nextcloud.sh genannt und wie folgt aufgebaut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

while [[ true ]]; do
        if ls /media/Nextcloudquartobot/*.qmd 1> /dev/null 2>&1; then
                cd /media/Nextcloudquartobot

                for i in *.qmd; do
                    echo "Found file $i"
                        timestamp=$(date "+%Y-%m-%d--%H-%M-%S")
                        echo "Trying to run 'quarto render $i'..."
                        /sbin/quarto render "$i";
                        echo "Moving .qmd-file..."
                        mv "$i" "$i-$timestamp"
                done
        else
                echo "Nothing to do..."
        fi
        echo "Sleeping for 30 seconds."
        sleep 30
done

Dieses Script soll nun mit systemd gesteuert werden. Hierfür erstellen wir die Datei /etc/systemd/system/quarto-nextcloud-bot.service und geben ihr folgenden Inhalt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Unit]
Description=quarto-Nextcloud-RenderBot
Wants=media-Nextcloudquartobot.mount

[Service]
Type=single
Nice=19
IOSchedulingClass=idle
ExecStart=/bin/bash -c "PATH=$PATH exec /pfad/zu/quarto-nextcloud.sh"
User=produnis

[Install]
WantedBy=multi-user.target

In Zeile 3 legen wir fest, dass vor unserem Bot das Mountscript “media-Nextcloudquartobot.mount ausgeführt werden soll. Sonst wäre ja der Nextcloudordner nicht da.

In Zeile 9 führen wir das Script aus und übergeben dabei den aktuellen $PATH.

In Zeile 10 sagen wir, dass das Script als User produnis ausgeführt werden soll.

Wir können das Script nun per systemd steuern:

1
2
3
sudo systemctl start quarto-nextcloud-bot.service
sudo systemctl stop quarto-nextcloud-bot.service
sudo systemctl enable quarto-nextcloud-bot.service

Sobald es läuft, können wir den Output mittels journalctl überwachen.

1
2
# journal laufend ausgeben
journalctl -u quarto-nextcloud-bot.service -f

So sehe ich, dass das Script läuft und sich langweilt:

1
2
3
4
5
Sep 23 17:40:19 SERVER bash[9086]: Sleeping for 30 seconds.
Sep 23 17:40:50 SERVER bash[9086]: Nothing to do...
Sep 23 17:40:50 SERVER bash[9086]: Sleeping for 30 seconds.
Sep 23 17:41:20 SERVER bash[9086]: Nothing to do...
Sep 23 17:41:20 SERVER bash[9086]: Sleeping for 30 seconds.

Sobald ich eine .qmd-Datei in das Nextcloudverzeichnis lege, fängt er an zu arbeiten:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Sep 23 17:42:52 SERVER bash[9086]: Found file Hinweise-zur-Klausuraufsicht.qmd
Sep 23 17:42:52 SERVER bash[9086]: Trying to run 'quarto render Hinweise-zur-Klausuraufsicht.qmd'...
Sep 23 17:42:55 SERVER bash[9360]: pandoc 
Sep 23 17:42:55 SERVER bash[9360]:   to: latex
Sep 23 17:42:55 SERVER bash[9360]:   output-file: Hinweise-zur-Klausuraufsicht.tex
Sep 23 17:42:55 SERVER bash[9360]: running xelatex - 1
Sep 23 17:42:58 SERVER bash[9360]: running xelatex - 2
Sep 23 17:43:01 SERVER bash[9360]:   This is XeTeX, Version 3.141592653-2.6-0.999994 (TeX Live 2022) (preloaded format=xelatex)
Sep 23 17:43:04 SERVER bash[9360]: Output created: Hinweise-zur-Klausuraufsicht.pdf
Sep 23 17:43:04 SERVER bash[9086]: Moving .qmd-file...
Sep 23 17:43:05 SERVER bash[9086]: Sleeping for 30 seconds.

Und die fertig gerenderte PDF-Datei ist im Nextcloudverzeichnis verfügbar.

Nutzung

Ich schmeiss also einfach eine qmd-Datei in den Nextcloudordner, und hole mir die PDF-Datei von dort zurück. Sollte ich Bilder einbinden (z.B. meine Unterschrift bei Briefen), oder Templates, müssen diese ebenfalls im Nextcloud-Ordner vorhanden sein, damit Quarto sie finden kann.



Briefvorlage für quarto erstellen

Vor ein paar Wochen wurde quarto als Next-Level-RMarkdown-Nachfolger veröffentlicht.

In diesem Blogpost zeige ich, wie ich mir eine Briefvorlage für quarto erstellt habe, die den Brief als PDF-Datei erzeugt.

Um mit quarto PDF-Dateien erzeugen zu können, muss eine $\LaTeX$-Distribution installiert sein. Sollte $\LaTeX$ auf Ihrem System nicht installiert sein, kann dies über folgenden Befehl nachgeholt werden:

quarto install tool tinytex

Mit dieser Methode installiert quarto alle weiteren benötigten Pakete automatisch, sofern diese benötigt werden. Sollten Sie bereits eine $\LaTeX$-Distribution installiert haben, müssen Sie das Paket fontawesome installieren.


Quarto ermöglicht es, zusätzlichen LaTeX-Code einzufügen (siehe https://quarto.org/docs/output-formats/pdf-basics.html#latex-includes) oder nur einzelne Teile des Templates auszutauschen (siehe https://quarto.org/docs/journals/templates.html#template-partials).

Es können aber auch eigene vollständige Vorlagen erzeugt werden. Folgende Punkte sind hierbei zu bedenken:

  • Möchten Sie alle Funktionen von quarto verfügbar und Ihre Vorlage so flexibel wie möglich machen, sollten Sie die quarto-Vorlage kopieren (siehe https://github.com/quarto-dev/quarto-cli/tree/main/src/resources/formats/pdf/pandoc) und Ihre Änderungen direkt dort einfügen.

  • Möchten Sie sich z.B. eine Briefvorlage erstellen, deren wesentlichen Parameter (Dokumentenklasse, Schriftgröße, Geomtery, etc.) sich eh nie ändern werden, ist es durchaus legitim, eine eigene “rudimentäre” $\LaTeX$ -Datei zu erstellen.

Und das geht so…

Quick and Dirty Vorlage

Unsere Briefvorlage besteht aus zwei Teilen:

  1. eine $\LaTeX$-Datei brieftamplate.tex, in welcher das Aussehen des Briefes festgelegt wird.

  2. eine quarto-Markdown-Datei MeinBrief.qmd, in welcher der eigentliche Brief geschrieben wird.

  • zudem benötigen Sie Ihre Unterschrift als Bilddatei.

$\LaTeX$-Datei

Es bietet sich an, die $\LaTeX$-Datei an einem “zentralen Ort” abzulegen, von wo aus sie für die Briefe.qmd erreichbar ist, z.B. Dokumente/Vorlagen/Quarto. Am besten kopieren Sie Ihre Unterschriftenbilddatei auch dorthin.

Kopieren Sie folgenden Inhalt in die Datei brieftamplate.tex:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
\documentclass[DIN,
    fontsize=11pt,          % fontsize
    paper=a4,               % page size a4
    firsthead=on,           % display header on first page
    firstfoot=on,           % display footer on first page
    pagenumber=off,         % position of the page number
    parskip=half,           % Use indent instead of skip, half, false
    enlargefirstpage=on,    % more space on first page
    fromalign=locationright, % placement of name in letter head
    fromrule=afteraddress,
    addrfield=on,           % address field for envelope with window, on or true
    subject=titled,         % placement of subject, beforeopening or titled
    foldmarks=on,          % print foldmarks
    numericaldate=off,      % display date in numbers only
    KOMAold]{scrlttr2}
\usepackage[dvips]{graphicx}
\usepackage[ngerman]{babel}
\usepackage{lipsum}
\usepackage[utf8]{inputenc}
\usepackage{times}
% \usepackage{lmodern}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{lastpage}
\usepackage[rgb]{xcolor}
\usepackage{hyperref}
\hypersetup{%
    pdfborder=0 0 0,
    pdfauthor={},
    pdftitle={},
    pdfsubject={},
    pdfkeywords={},
    pdfpagemode={UseOutlines},
    bookmarksopen,
    pdfstartview={FitH},
    colorlinks,
    linkcolor={black},
    citecolor={black},
    urlcolor={black}
  }
\urlstyle{same}
\usepackage{geometry}
\geometry{a4paper,left=25mm,right=20mm}

\usepackage{lastpage}
\usepackage{marvosym}
\usepackage{blindtext}

\newcommand{\myFirstname}{$myFirstname$}
\newcommand{\myFamilyname}{$myFamilyname$}
\newcommand{\myStreet}{$myStreet$}
\newcommand{\myTown}{$myTown$}

\setkomavar{date}{\today}
\setkomavar{fromname}{\flushright\normalfont\textbf{\myFirstname\ \myFamilyname}}
\setkomavar{signature}{\myFirstname\ \myFamilyname}
\setkomavar{fromaddress}{\flushright\normalfont\scriptsize%
$myGrads$ \myFirstname\ \myFamilyname\\
\myStreet\\\myTown\\%
$myTelefon$\\%
\normalfont $myMail$\\[2mm]
$myBank$\\
$myIBAN$\\[2mm]
Aktenzeichen:\quad\ $myAktenzeichen$\\
Datum:\quad \today}
\setkomavar{backaddress}{\myFamilyname\ | \myStreet\ | \myTown}
\setkomavar{signature}{\includegraphics[width=4cm]{$Unterschrift$}\\\myFirstname\ \myFamilyname}
\renewcommand*\familydefault{\sfdefault}
\setkomavar{firsthead}{}
\setkomavar{location}{%
  \raggedleft
  \usekomavar{fromname}\\
  \usekomavar{fromaddress}
}

% LOGO--------------kopf/fusszeile----------------
\usepackage{scrlayer-scrpage}
\clearmainofpairofpagestyles
\cfoot{\flushright\scriptsize\normalfont Seite \thepage\ von \pageref{LastPage} }
\RedeclarePageStyleAlias{empty}{scrheadings}
%----------------------------------------------
\setkomavar{date}{}
\setkomavar{subject}{$myBetreff$}

\setlength{\parindent}{0pt}

\makeatletter
  \@setplength{backaddrheight}{0pt}% because backaddress=off
  \@setplength{toaddrhpos}{2.5cm}%distance from left
  \@setplength{toaddrvpos}{5cm}%distance from top
  \@setplength{toaddrheight}{3.5cm}%height of the addressbox
  \@setplength{toaddrwidth}{10cm}% width of the addressbox
  \@addtoplength{locwidth}{45mm} % width of ABSENDERbox
  \@setplength{lochpos}{2cm}%distance from top
  \@setplength{locvpos}{32mm}%distance from top
  \@setplength{refvpos}{11cm}
\makeatother
$if(highlighting-macros)$
$highlighting-macros$
$endif$

\begin{document}
%
\begin{letter}{$toAdressName$\\
$toAdressHost$\\
$toAdressStr$\\
$toAdressCity$\\
$toAdressLand$
}
%
\opening{$opening$,}
%
%\setstretch{$spacing$}
$body$
%
\closing{$closing$,
}

$if(Anlagen)$
Anlage(n):
\begin{itemize}
$for(Anlagen)$\item $Anlagen$ %
$endfor$
\end{itemize}
$endif$

\end{letter}
\end{document}

quarto-Datei

Kopieren Sie folgenden Inhalt in die Datei MeinBrief.qmd. Beachten Sie, dass in Zeile 4 der Pfad zur brieftamplate.tex korrekt angegeben werden muss. Ebenso erwartet die Vorlage in Zeile 14 den Pfad zu einer Unterschrift.png-Bilddatei.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
format:
  pdf:
    template: /pfad/zu/brieftamplate.tex
    myFirstname: Andreas
    myFamilyname: Absendermann
    myStreet: Wegschickstraße 13
    myTown: 45899 Abschickstadt
    myGrads: Herr
    myTelefon: +49 555 0815 2342
    myMail: meinemail@adresse.de
    myBank:  Sparkasse Reibachstadt
    myIBAN: DE06 555 0815 2342
    Unterschrift: /pfad/zu/Unterschrift.png
    myAktenzeichen: 2021-A
    myBetreff: Betreff
    toAdressName: Erna Empfängerin
    toAdressHost: Empfangs GMBH
    toAdressStr: Empfänger-Straße 12
    toAdressCity: 45887 Empfangdorf
    toAdressLand: Germany
    opening: "Sehr geehrte Frau Empfängerin,"
    closing: "Mit freundlichen Grüßen"
    Anlagen:  
      - "Lebenslauf"
      - "Anwaltsschreiben"
      - "Schulzeugnis"
---

dies ist ein Testbrief.

Wenn Sie beide Pfade korrekt ersetzt haben, können Sie den Render-Button drücken. Das Ergebnis sieht dann so aus:

fertiger Brief

Für jeden weiteren Brief können Sie nun die MeinBrief.qmd duplizieren, umbenennen, bearbeiten und ein PDF erzeugen.

KaTeX zusammen mit cactus.chat

Ich verwende in meinem Blog $\KaTeX$ (siehe hier) und cactus.chat (siehe hier), und beides für sich genommen funktioniert ganz gut. Ein Problem tritt dann auf, wenn $\KaTeX$ und cactus.chat gemeinsam verwendet werden.

Dann kann es passieren, dass $\KaTeX$ in dem <div>-Container von cactus.chat herumschreibt, was dazu führt, dass cactus.chat nur “Getting comments…” anzeigt, ohne diese jedoch wirklich zu laden und ohne die Chance, einen neuen Kommentar hinzuzufügen.

Die Lösung besteht darin zu verhindern, dass $\KaTeX$ den <div>-Container anfasst. Die lässt sich in 2 Schritten umsetzen…

1. cactus.chat einrahmen

Wir modifizieren /layouts/shortcodes/chat.html (siehe hier) und packen den cactus.chat-Abschnitt komplett in ein eigenes <div>:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<br>
<div class="no-katex-here">
<script type="text/javascript" src="https://latest.cactus.chat/cactus.js"></script>
<link rel="stylesheet" href="https://latest.cactus.chat/style.css" type="text/css">
<div id="comment-section"></div>
<script>
initComments({
  node: document.getElementById("comment-section"),
  defaultHomeserverUrl: "https://matrix.cactus.chat:8448",
  serverName: "cactus.chat",
  siteName: "YOUR-SITE-NAME",
  commentSectionId: "{{ index .Params 0 }}"
})
</script>
</div>

In Zeile 2 beginnt unser Container mit der Klasse "no-katex-here", und in Zeile 15 endet er.

2. $\KaTeX$ anpassen

Man kann $\KaTeX$ anweisen, bestimmte Bereiche der Seite nicht anzufassen. Dies erfolgt entweder über den Parameter ignoredTags oder ignoredClasses (siehe $\KaTeX$-Docs). Da wir oben im Cactus-Shortcode den <div>-Container der Klasse "no-katex-here" zugewiesen haben, bedienen wir uns der letzteren Option und übergeben ignoredClasses:['no-katex-here'] beim Funktionsaufruf.

Dafür muss die Datei /layouts/partials/katex.html (siehe hier) entsprechend angepasst werden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">

<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.js" integrity="sha384-VQ8d8WVFw0yHhCk5E8I86oOhv48xLpnDZx5T9GogA/Y84DcCKWXDmSDfn13bzFZY" crossorigin="anonymous"></script>

<!-- To automatically render math in text elements, include the auto-render extension: -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous" onload="renderMathInElement(document.body,{ignoredClasses:['no-katex-here']});"></script>

<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {
            ignoredClasses:['no-katex-here'],
            delimiters: [
                {left: "$$", right: "$$", display: true},
                {left: "$", right: "$", display: false}
            ]      
        });
    });
</script>

In Zeile 7 und 12 haben wir den Funktionsaufruf um die Option ignoredClasses:['no-katex-here'] ergänzt.


Jetzt lässt $\KaTeX$ cactus.chat in Ruhe und beides funktioniert gemeinsam.

cactus.chat - Matrix-Comments für HUGO

Meinem Blog fehlt noch eine Kommentarfunktion, und HUGO bietet mir mehrere Möglichkeiten, dieses Vorhaben umzusetzen.

Eine davon ist Cactus Chat, welche das Matrix-Protokoll verwendet um die Kommentare bereitzustellen. Da schlägt das Herz des Datenveganers höher!

1. Matrix-Account erstellen

Ihr benötigt also einen Matrix-Account, um Cactus verwenden zu können.

2. Cactus klarmachen

Für den Anfang könnt ihr den bereitgestellten öffentlichen Service nutzen, oder aber cactus selbst installieren und hosten.

Startet eine Unterhaltung mit @cactusbot:cactus.chat. Sobald beide im Raum sind setzt ihr folgenden Befehl als Chatnachtricht ab:

 register YOUR-SITE-NAME
wobei YOUR-SITE-NAME ein eindeutiger Name sein muss (es geht hier aber nicht um eurer tatsächlichen Servernamen oder URL). Ich hab mal produnistest gewählt:

  register produnistest

Der Bot wird eure Seite registrieren und euch in den Raum #comments_YOUR-SITE-NAME:cactus.chat einladen, in meinem Falle #comments_produnistest:cactus.chat. Dieser gilt als Haupt-Moderationsraum.

3. In HUGO einbinden

Im Ordner /layouts/shortcodes/ erzeugt ihr die Datei chat.html und gebt ihr folgenden Inhalt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<br>
<script type="text/javascript" src="https://latest.cactus.chat/cactus.js"></script>
<link rel="stylesheet" href="https://latest.cactus.chat/style.css" type="text/css">
<div id="comment-section"></div>
<script>
initComments({
  node: document.getElementById("comment-section"),
  defaultHomeserverUrl: "https://matrix.cactus.chat:8448",
  serverName: "cactus.chat",
  siteName: "YOUR-SITE-NAME",
  commentSectionId: "{{ index .Params 0 }}"
})
</script>

wobei ihr YOUR-SITE-NAME entsprechend ersetzen müsst.

Dieser Shortcode kann nun innerhalb der Posts aufgerufen werden mittels:

   {{< chat RAUMNAME >}}

wobei RAUMNAME ein frei wählbarer Name ist. Wenn RAUMNAME in allen Posts gleich ist, steht unter jedem Post der selbe Chatverlauf. Es bietet sich daher an, für jeden Post einen eigenen Raum zu erstellen. Das geht ganz einfach. Sobald die Seite das erste mal aufgerufen wird (z.B. als Preview), erfolgt die Raumerstellung automatisch anhand der Angaben im Shortcode. Die Kommentarfunktion funktioniert dann bereits auch im Preview. Anschließend solltet ihr selbst mit eurem Matrix-Account dem Raum beitreten, sonst könnt ihr die Beiträge nicht moderieren. Hierbei folgt die Notation der Comment-Räume dem Schema:

    #comments_YOUR-SITE-NAME_RAUMNAME:cactus.chat

Also z.B.

    #comments_produnistest_testraum:cactus.chat

Das funktioniert hier direkt auf Anhieb. Im nächsten Schritt werde ich Peter mal darauf anfixen, Cactus selbst zu hosten.

KaTex für HUGO und Blogdown

$\KaTeX$ übersetzt die wichtigsten $\LaTeX$-Mathe-Notationen in HTML. Es ist dabei schneller als MathJax, hat im Gegenzug aber noch nicht (sooooo) viele Notationen umgesetzt wie der Platzhirsch. Zudem unterscheidet sich die Anwendung in Blogdown und HUGO.

$\KaTeX$ in HUGO einbinden

In meinem Themeordner erstelle ich die Datei /MEINTHEME/layouts/partials/katex.html und gebe ihr folgenden Inhalt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">

<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.js" integrity="sha384-VQ8d8WVFw0yHhCk5E8I86oOhv48xLpnDZx5T9GogA/Y84DcCKWXDmSDfn13bzFZY" crossorigin="anonymous"></script>

<!-- To automatically render math in text elements, include the auto-render extension: -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>

<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {
            delimiters: [
                {left: "$$", right: "$$", display: true},
                {left: "$", right: "$", display: false}
            ]
        });
    });
</script>

Ihr solltet nachschauen, ob die Version 0.15.2 immer noch die aktuellste ist und ggfs. die Zeilen entsprechend anpassen.

In der Datei /MEINTHEME/layouts/partials/head.html ergänze ich:

1
 {{ if .Params.math }}{{ partial "katex.html" . }}{{ end }}

Wenn ich später in Blogdown bei einem Post im Meta-Kopf folgenden Paramter setze:

1
 math: true

…dann wird $\KaTeX$ geladen und kann verwendet werden. Die Informationen hierzu hab ich in Mert Bakirs Blog gefunden.


Beispiele

Die Anwendung unterscheidet sich, je nachdem, ob .md, .Rmarkdown oder .Rmd-Files verwendet werden.



.md

In einfachen Markdowndokumenten funktioniert die Inline-Verwendung mittels Dollarzeichen:

1
 Dies ist ein Text mit $E=m\cdot c^2$ 

Das ergibt:

Dies ist ein Text mit $E=m\cdot c^2$

Das funktioniert auch mit Sonderzeichen:

1
 Wir verwenden $\LaTeX \rightarrow \KaTeX$ und das klappt ganz gut

Das ergibt:

Wir verwenden $\LaTeX \rightarrow \KaTeX$ und das klappt ganz gut

Mathe-Umgebungen werden mit zwei Dollarzeichen eingerahmt:

1
2
3
$$
E=m\cdot c^2
$$ 

Das ergibt:

$$ E=m\cdot c^2 $$

Mit dem align-Environment werden die Formelzeilen automatisch am rechten Rand durchnummeriert. Environments müssen nicht per Dollarzeichen eingeführt werden sondern funktioniert direkt im Text :

1
2
3
4
5
6
7
Dies ist eine Formel

\begin{align}
E=m\cdot c^2
\end{align}

und ich finde sie gut

Das ergibt:

Dies ist eine Formel \begin{align} E=m\cdot c^2 \end{align} und ich finde sie gut

So funktioniert auch das equation-Environment direkt im Text:

1
2
3
4
5
6
7
Einstein hat mal gesagt:

\begin{equation}
E=m\cdot c^2
\end{equation}

und ich glaube, er hatte Recht

Das ergibt:

Einstein hat mal gesagt:

\begin{equation} E=m\cdot c^2 \end{equation}

und ich glaube, er hatte Recht

Eine Übersicht aller unterstützer Environments findet ihr hier.



.Rmarkdown

In .Rmarkdown-Files ist die Notation leicht anders. So müssen bei der Inline-Verwendung die Dollarzeichen mittels Backslash auskommentiert werden:

1
 Dies ist ein Text mit \$a^2 + b^2 = c^2\$ 

Das ergibt:

Dies ist ein Text mit $a^2 + b^2 = c^2$

Das gilt auch für alle Sonderzeichen:

1
 Wir verwenden \$\\LaTeX \\rightarrow \\KaTeX\$ und das klappt ganz gut

Das ergibt:

Wir verwenden $\LaTeX \rightarrow \KaTeX$ und das klappt ganz gut

Mathe-Umgebungen werden wie gewohnt mit zwei Dollarzeichen eingerahmt.

1
2
3
$$
a^2 + b^2 = c^2
$$ 

Das ergibt:

$$ a^2 + b^2 = c^2 $$

Auch hier müssen die Backslashs von Sonderzeichen auskommentiert werden:

1
2
3
$$
\\LaTeX \\rightarrow \\LaTeX
$$ 

Das ergibt: $$ \LaTeX \rightarrow \LaTeX $$

In .Rmarkdown-Files müssen bei allen Environments und Sonderzeichen die \ von \begin{} und \end{} auskommentiert werden, damit sie direkt im Text funktionieren. Für das align-Environment sieht das dann so aus:

1
2
3
4
5
Irgendwas mit Dreiecken
\\begin{align}
a^2 + b^2 = c^2
\\end{align}
Was war das noch?

Das ergibt:

Irgendwas mit Dreiecken \begin{align} a^2 + b^2 = c^2 \end{align} Was war das noch?


Genau so funktioniert auch das equation-Environment:

1
2
3
4
5
6
7
Pythagoras hat mal gesagt:

\\begin{equation}
a^2 + b^2 = c^2
\\end{equation}

und ich glaube, er hatte Recht

Das ergibt:

Pythagoras hat mal gesagt:

\begin{equation} a^2 + b^2 = c^2 \end{equation}

und ich glaube, er hatte Recht

Eine Übersicht aller unterstützer Environments findet ihr hier.



.Rmd

In .Rmd-Dokumenten funktioniert die Inline-Verwendung wieder mittels Dollarzeichen:

1
 Dies ist ein Text mit $\Reals \backsim 2^\N$ 

Das ergibt:

Dies ist ein Text mit $\Reals \backsim 2^\N$

Das funktioniert auch mit Sonderzeichen:

1
 Wir verwenden $\LaTeX \rightarrow \KaTeX$ und das klappt ganz gut

Das ergibt:

Wir verwenden $\LaTeX \rightarrow \KaTeX$ und das klappt ganz gut

Mathe-Umgebungen werden mit zwei Dollarzeichen eingerahmt:

1
2
3
$$
\Reals \backsim 2^\N
$$ 

Das ergibt:

$$ \Reals \backsim 2^\N $$

Mit dem align-Environment werden die Formelzeilen automatisch am rechten Rand durchnummeriert. Environments müssen nicht mit Dollarzeichen eingerahmt werden, sondern funktionieren direkt im Text:

1
2
3
4
5
Was war das noch für eine Formel
\begin{align}
\Reals \backsim 2^\N
\end{align}
Und was bedeutet sie?

Das ergibt:

Was war das noch für eine Formel \begin{align} \Reals \backsim 2^\N \end{align} Und was bedeutet sie?

Das equation-Environment funktioniert genau so:

1
2
3
4
5
6
7
Cantor hat mal gesagt:

\begin{equation}
\Reals \backsim 2^\N
\end{equation}

und ich glaube, er hatte Recht

Das ergibt:

Cantor hat mal gesagt:

\begin{equation} \Reals \backsim 2^\N \end{equation}

und ich glaube, er hatte Recht

Eine Übersicht aller unterstützer Environments findet ihr hier.



Allgemein

Zeilenumbrüche funktionieren per \newline, aber nicht mit \\:

1
2
3
4
5
\begin{align}
 E &= m \cdot c^2 \newline
 a^2 + b^2 &= c^2 \newline
 \Reals &\backsim 2^\N
\end{align}

Das ergibt:

\begin{align} E &=m\cdot c^2 \newline a^2 + b^2 &= c^2 \newline \Reals &\backsim 2^\N \end{align}

Das Prozentzeichen muss mit zwei Backslashs auskommentiert werden:

1
2
3
$$
14\\% + 15\\% = 29\\%
$$

Das ergibt: $$ 14\% + 15\% = 29\% $$

Links

Templates für Briefe und Rechnungen in RMarkdown erstellen

1 Einleitung

Ich nutze RMarkdown und RStudio schon seit längerem für statistische Auswertungen und Beispielrechnungen in der Lehre. Für meine Briefe und Rechnungen habe ich immer LaTeX verwendet.

Im Dezember habe ich dann dieses Video von Rob Hyndman gesehen:

https://www.youtube.com/watch?v=_D-ux3MqGug

…und dachte mir: das will ich auch!

Zu dieser Anleitung gibt es ein Github-Repo mit dem Template-Paket und der Rmd-Datei dieser Anleitung: https://github.com/produnis/RMarkdownMyStyle.

Außerdem ist der Arikel bei RPubs.com veröffentlicht, und dort etwas “hübscher” dargestellt, siehe https://rpubs.com/produnis/RMarkdownTemplates.

1.1 Vorwarnung

Diese Anleitung setzt voraus, dass Sie Ihre Briefe und Rechnungen bereits in LaTeX schreiben, bzw, dass eine Brief- oder Rechnungsvorlage in LaTeX vorliegt. In diesem Tutorial möchte ich zeigen, wie Sie Ihre LaTeX-Vorlagen als Templates in RMarkdown verfügbar machen können, um die Briefe im PDF-Format zu erzeugen. Das heisst, dass letztendlich Ihr RMarkdown wieder über LaTeX nach PDF kompiliert wird. LaTeX muss also installiert sein, und Sie müssen das gewünschte Layout bereits in LaTeX erstellt haben. Ebenso muss das bookdown-Paket installiert sein.

1
install.packages("bookdown")

Die Überführung nach Rmarkdowngeht am einfachsten, indem man sie als Templates in einem eigenen R-Paket abpeichert.

2 Ein eigenes R-Paket anlegen

Klicke in RStudio auf FileNew Project...

Wählen Sie R Package aus.

Figure 1: R-Package wählen

Geben Sie dem Paket einen Namen, z.B. MyStyle, und klicken Sie auf Create Project...

Figure 2: Packagenamen wählen

Im Arbeitsverzeichnis des neuen Projekts liegen nun die notwendigen Dateien und grundlegenden Paketordner, wobei wir das meister ignorieren können.

In DESCRIPTION können Sie eine Beschreibung des Pakets vornehmen. Wenn Sie das Paket eh nie veröffentlichen, können Sie sich diesen Schritt sparen.

Im Verzeichnis R werden alle Scriptdateien automatisch ausgeführt, sobald das Paket aktiviert wird. Dort hat RStudio bereits die Dummy-Datei hello.R angelegt. Die dort hinterlegte Funktion hello() steht also nach Aktivierung des Pakets zur Verfügung.

Das können wir direkt testen, indem wir das Paket “bauen und installieren”.

Klicken Sie im Datenfenster (rechter oberer Bereich) auf den Reiter Build.

Figure 3: Reiter Build

In diesem Bereich können Sie auf den Knopf Install and Restart klicken.

Figure 4: Paket installieren

Dadurch wird Ihr neues Paket installiert und automatisch per library(MyStyle) geladen. Sie können nun alle Funktionen Ihres Pakets in der R-Konsole aufrufen. Probieren wir also die Dummy-Funktion hello() aus, die in der Datei R/hello.R hinterlegt ist:

1
hello()

Immer dann, wenn Sie dem Paket neue Funktionen (oder Templates) hinzugefügt haben, können Sie es durch Klick auf Install and Restart aktualisieren.

2.1 Ein Template für Briefe anlegen

Templates fürRMarkdown müssen innerhalb des Pakets im Ordner inst/rmardown/templates/ vorliegen. Jedes Template erhält einen eigenen Unterordner, in welchem die erforderlichen Dateien abgelegt sind. Auch hier folgend die Dateien einer gewissen Struktur.

Mit der Funktion use_rmarkdown_template() aus dem Paket usethis können wir das “Skelett” des neuen Templates erzeugen. Beginnen wir mit der Briefvorlage. Das Template soll meinBrief heissen.

1
install.packages("usethis", dependencies = T)
1
2
3
4
5
6
usethis::use_rmarkdown_template(
  template_name = "meinBrief",
  template_dir = NULL,
  template_description = "Meine private Briefvorlage",
  template_create_dir = FALSE
)

Wie Sie sehen, wurden die Unterordner inst/rmardown/templates/meinbrief angelegt. Hier liegt die Datei template.yaml. Sie enthält die Informationen, die wir der use_rmarkdown_template()-Funktion übergeben haben.

1
2
3
4
name: meinBrief
description: >
      Meine private Briefvorlage
create_dir: FALSE

Hier müssen wir nichts ändern.

Im Unterordner skeleton liegt die Datei skeleton.Rmd. In ihr werden Beispieltexte und -code hinterlegt, die später beim Aufruf des Templates als Starttext erzeugt werden. Wir benutzen diese Datei, um unser Template zu testen und die benötigten Variablen zu hinterlegen. Wenn wir unser Template später in RStudio aus den Vorlagen auswählen, dann werden alle Dateien, die im Unterorder skeleton liegen, in das neu erstellte Projekt kopiert.

2.1.1 LaTeX Vorlage

Nehmen wir als Beispiel die folgende LaTeX-Vorlage für einen Brief. Das Beispiel ist lauffähig, wenn Sie eine Bilddatei mit dem Namen Unterschrift.png im selben Verzeichnis liegen haben.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
\documentclass[DIN,
    fontsize=11pt,          % fontsize
    paper=a4,               % page size a4
    firsthead=on,           % display header on first page
    firstfoot=on,           % display footer on first page
    pagenumber=off,         % position of the page number
    parskip=half,           % Use indent instead of skip, half, false
    enlargefirstpage=on,    % more space on first page
    fromalign=locationright, % placement of name in letter head
    addrfield=on,           % address field for envelope with window, on or true
    subject=titled,         % placement of subject, beforeopening or titled
    foldmarks=on,          % print foldmarks
    numericaldate=off,      % display date in numbers only
    KOMAold]{scrlttr2}
\usepackage[T1]{fontenc}
\usepackage[dvips]{graphicx}
\usepackage[ngerman]{babel}
\usepackage{lipsum}
\usepackage[utf8]{inputenc}
\usepackage{times}
% \usepackage{lmodern}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{lastpage}
\usepackage[rgb]{xcolor}
\usepackage{hyperref}
\hypersetup{%
    pdfborder=0 0 0,
    pdfauthor={},
    pdftitle={},
    pdfsubject={},
    pdfkeywords={},
    pdfpagemode={UseOutlines},
    bookmarksopen,
    pdfstartview={FitH},
    colorlinks,
    linkcolor={black},
    citecolor={black},
    urlcolor={blue}
  }
\urlstyle{same}

% Randbereiche mit geometry
\usepackage{geometry}
\geometry{a4paper,left=25mm,right=20mm}

\usepackage{lastpage} % letzte Seite anzeigen
\usepackage{marvosym}   
\usepackage{blindtext}

% speichere eigene Variablen für Werte, die häufig drankommen
\newcommand{\myFirstname}{Timm}
\newcommand{\myFamilyname}{Thaler}
\newcommand{\myStreet}{Absenderstr. 7}
\newcommand{\myTown}{47325 Schickensen}

% ---Angaben für das Absenderfeld--------
\setkomavar{fromname}{\flushright\normalfont\textbf{\myFirstname\ \myFamilyname}}
\setkomavar{signature}{\myFirstname\ \myFamilyname}
\setkomavar{fromaddress}{\flushright\normalfont\scriptsize%
Prof. Dr. \myFirstname\ \myFamilyname\\
\myStreet\\\myTown\\%
+49 176 555 984 66\\%
timm@thaler.de\\[2mm]
ING DiBa\\
DE06 505 165 55 5555 4312 64\\[2mm]
Aktenzeichen:\quad\ 2021-4\\
\setkomavar{date}{\today} %datum im Absenderfeld 
Datum:\quad \today}
%---------------------------------------
\renewcommand*\familydefault{\sfdefault}

% Anordnung im Absenderfeld
\setkomavar{firsthead}{}
\setkomavar{location}{%
  \raggedleft
  \usekomavar{fromname}\\
  \usekomavar{fromaddress}
}

% Absender auch über dem Empfängeradressfeld
\setkomavar{backaddress}{\myFamilyname\ | \myStreet\ | \myTown}

% signatur mit Unterschrift
\setkomavar{signature}{\includegraphics[width=25mm]{Unterschrift.png}\\\myFirstname\ \myFamilyname} 
%
% --------------kopf/fusszeile----------------
\usepackage{scrlayer-scrpage}
\clearmainofpairofpagestyles
\cfoot{\flushright\scriptsize\normalfont Seite \thepage\ von \pageref{LastPage} }
\RedeclarePageStyleAlias{empty}{scrheadings}
%----------------------------------------------
%
\setkomavar{date}{} % Datum wieder löschen
\setkomavar{subject}{Dies ist der Betreff}
\setlength{\parindent}{0pt}

% positionierung von Absender und Empfängerboxen
\makeatletter
  \@setplength{backaddrheight}{0pt}% because backaddress=off
  \@setplength{toaddrhpos}{2.5cm}%distance from left
  \@setplength{toaddrvpos}{5cm}%distance from top
  \@setplength{toaddrheight}{3.5cm}%height of the addressbox
  \@setplength{toaddrwidth}{10cm}% width of the addressbox
  \@addtoplength{locwidth}{45mm} % width of ABSENDERbox
  \@setplength{lochpos}{2cm}%distance from top
  \@setplength{locvpos}{32mm}%distance from top
  \@setplength{refvpos}{11cm}% Abstand des Haupttextes von top
\makeatother
%------------------------------------------------------------------------------------

\begin{document}
%
\begin{letter}{Andrea Empfängerin\\
Schloss Schalkenstein\\ 
Adressatenstr. 23\\
22204 Briefkasten
}
%
\opening{Sehr geehrte Frau Empfängerin,}
%
\blindtext[1]

\closing{Mit freundlichen Grüßen,
}
\end{letter}
\end{document}  

Die Datei erzeugt folgendes PDF:

Figure 5: PDF-Version des Briefs

Den LaTeX-Code übertragen wir nun in unser Template. Hierfür muss im Ordner inst/markdown/templates/meinbrief der Unterordner resources angelegt werden. In diesem erzeugen wir die Datei meinbrief.tex und kopieren den LaTeX-Code hinein.

1
2
file.edit("inst/markdown/templates/meinbrief/resources/meinbrief.tex")
# kopiere nun den LaTeX Code hierhin.

Als nächstes kopieren wir die Bilddatei für die Unterschrift in den skeleton-Ordner. In unserem Beispiel heisst sie Unterschrift.png.

Figure 6: Datei Unterschrift.png

Ab jetzt wechseln wir immer zwischen den Dateien skeleton.Rmd und meinbrief.tex hin und her.

2.1.2 skeleton.Rmd und LaTeX-Datei anpassen

Schauen wir uns zunächst die Datei skeleton.Rmd an.

Hier löschen wir den Beispieltext und belassen nur die Kopfzeile

1
2
3
4
5
6
---
title: "Template Title"
author: "Your Name"
date: "The Date"
output: output_format
---

In der Kopfzeile werden Variablen vergeben. So hat z.B. Variable title derzeit den Wert Template Title, und date hat den Wert The Date.

Wir können uns dies zu nutze machen. In unserem LaTeX-Code sind all diese Variablen referenzierbar, wenn wir ihren Namen in Dollarzeichen einrahmen, also z.B. $title$. Wir können im Kopfbereich beliebige neue Variablen erzeugen und diese dann innerhalb der LaTeX-Vorlage nutzen.

Wir gehen also in die Datei meinbrief.tex, und ändern dort alle hardgecodeten Angaben (Name, Adresse, Telefonnummer, usw) in Variablen um. Diese Variablen tragen wir ebenfalls in die Datei skeleton.Rmd ein und hinterlegen dort die Werte.

Die Datei meinbrief.tex sieht danach z.B. so aus:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
\documentclass[DIN,
    fontsize=11pt,          % fontsize
    paper=a4,               % page size a4
    firsthead=on,           % display header on first page
    firstfoot=on,           % display footer on first page
    pagenumber=off,         % position of the page number
    parskip=half,           % Use indent instead of skip, half, false
    enlargefirstpage=on,    % more space on first page
    fromalign=locationright, % placement of name in letter head
    addrfield=on,           % address field for envelope with window, on or true
    subject=titled,         % placement of subject, beforeopening or titled
    foldmarks=on,          % print foldmarks
    numericaldate=off,      % display date in numbers only
    KOMAold]{scrlttr2}
\usepackage[T1]{fontenc}
\usepackage[dvips]{graphicx}
\usepackage[ngerman]{babel}
\usepackage{lipsum}
\usepackage[utf8]{inputenc}
\usepackage{times}
% \usepackage{lmodern}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{lastpage}
\usepackage[rgb]{xcolor}
\usepackage{hyperref}
\hypersetup{%
    pdfborder=0 0 0,
    pdfauthor={},
    pdftitle={},
    pdfsubject={},
    pdfkeywords={},
    pdfpagemode={UseOutlines},
    bookmarksopen,
    pdfstartview={FitH},
    colorlinks,
    linkcolor={black},
    citecolor={black},
    urlcolor={blue}
  }

\urlstyle{same}

% Randbereiche mit geometry
\usepackage{geometry}
\geometry{a4paper,left=25mm,right=20mm}

\usepackage{lastpage} % letzte Seite anzeigen
\usepackage{marvosym}
\usepackage{blindtext}

% speichere eigene Variablen für Werte, die häufig drankommen
\newcommand{\myFirstname}{$myFirstname$}
\newcommand{\myFamilyname}{$myFamilyname$}
\newcommand{\myStreet}{$myStreet$}
\newcommand{\myTown}{$myTown$}

% ---Angaben für das Absenderfeld--------
\setkomavar{fromname}{\flushright\normalfont\textbf{\myFirstname\ \myFamilyname}}
\setkomavar{signature}{\myFirstname\ \myFamilyname}
\setkomavar{fromaddress}{\flushright\normalfont\scriptsize%
$myGrade$ \myFirstname\ \myFamilyname\\
\myStreet\\\myTown\\%
$myTelefon$\\%
$myMail$\\[2mm]
$myBank$\\
$myIBAN$\\[2mm]
Aktenzeichen:\quad\ $myAktenzeichen$\\
\setkomavar{date}{\today} %datum im Absenderfeld
Datum:\quad \today}
%---------------------------------------
\renewcommand*\familydefault{\sfdefault}

% Anordnung im Absenderfeld
\setkomavar{firsthead}{}
\setkomavar{location}{%
  \raggedleft
  \usekomavar{fromname}\\
  \usekomavar{fromaddress}
}

% Absender auch über dem Empfängeradressfeld
\setkomavar{backaddress}{\myFamilyname\ | \myStreet\ | \myTown}

% signatur mit Unterschrift
\setkomavar{signature}{\includegraphics[width=25mm]{Unterschrift.png}\\\myFirstname\ \myFamilyname}
%
% --------------kopf/fusszeile----------------
\usepackage{scrlayer-scrpage}
\clearmainofpairofpagestyles
\cfoot{\flushright\scriptsize\normalfont Seite \thepage\ von \pageref{LastPage} }
\RedeclarePageStyleAlias{empty}{scrheadings}
%----------------------------------------------
%
\setkomavar{date}{} % Datum wieder löschen
\setkomavar{subject}{$Betreff$}
\setlength{\parindent}{0pt}

% positionierung von Absender und Empfängerboxen
\makeatletter
  \@setplength{backaddrheight}{0pt}% because backaddress=off
  \@setplength{toaddrhpos}{2.5cm}%distance from left
  \@setplength{toaddrvpos}{5cm}%distance from top
  \@setplength{toaddrheight}{3.5cm}%height of the addressbox
  \@setplength{toaddrwidth}{10cm}% width of the addressbox
  \@addtoplength{locwidth}{45mm} % width of ABSENDERbox
  \@setplength{lochpos}{2cm}%distance from top
  \@setplength{locvpos}{32mm}%distance from top
  \@setplength{refvpos}{11cm}% Abstand des Haupttextes von top
\makeatother
%------------------------------------------------------------------------------------

\begin{document}
%
\begin{letter}{$anName$\\
$anZusatz$\\
$anStrasse$\\
$anOrt$
}
%
\opening{$opening$,}
%
$body$

\closing{$closing$,
}
\end{letter}
\end{document}

Alle Angaben wurden durch Variablen ersetzt. Die Variable $body$ beinhaltet den gesamten Text des Markdown-Dokuments.

In der Datei skeleton.Rmd wurden die Variablen ebenfalls angelegt, und die Werte entsprechend zugeordnet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---
title: "Template Title"
author: "Your Name"
date: "The Date"
myFirstname: Timm
myFamilyname: Thaler
myStreet: Absenderstr. 7
myTown: 47325 Schickensen
myGrade: Prof. Dr.
myTelefon: +49 176 555 984 66
myMail: timm@thaler.de
myBank: ING DiBa
myIBAN: DE06 505 165 55 5555 4312 64
Betreff: Dies ist der Betreff
myAktenzeichen: 2021-4
anName: Andrea Empfängerin
anZusatz: Schloss Schalkenstein
anStrasse: Adressatenstr. 23
anOrt: 22204 Briefkasten
opening: Sehr geehrte Frau Empfängerin
closing: Mit freundlichen Grüßen
output: MyStyle::meinbrief
---

dies ist ein Testbrief, um zu schauen, ob es auch in `RMarkdown` funktioniert.

Als letzte Angabe im Kopfbereich wird der output auf unser Template meinbrief im Paket MyStyle gesetzt.

2.1.3 Ausgabeformat bereitstellen

Jetzt sind wir fast schon fertig. Wir müssen noch das eben angegebene Ausgabeformat MyStyle::meinbrief verfügbar machen. Hierzu erstellen wir im Paketordner “R” die Datei formats.R. Sie wird bei der Aktivierung des Paketes automatisch ausgeführt und soll das Ausgabgeformat bereitstellen.

1
2
# erstelle Datei R/formats.R
file.edit("R/formats.R")

Sie erhält folgenden Inhalt:

1
2
3
4
5
6
7
8
# mache output "meinbrief" verfügbar
meinbrief <- function(...) {
  template <- system.file("rmarkdown/templates/meinbrief/resources/meinbrief.tex",
                          package="MyStyle")
  bookdown::pdf_document2(...,
                          template = template
  )
}

Wie Sie sehen, verwenden wir letztendlich bookdown::pdf_document2 als Ausgabe.

2.1.4 Ausgabe kontrollieren

Jetzt können wir das Paket neu bauen und installieren, indem wir Install and Restart klicken.

Figure 7: Reiter Build

Wenn alles korrekt eingetragen wurde, können wir nun unsere Beispieldatei skeleton.Rmd knitten. Das erzeugt eine PDF-Datei im Unterordner skeleton (weil skeleton.Rmd dort liegt). Überprüfen Sie, ob alles so aussieht, wie Sie möchten. Ist alles gut, entfernen Sie die PDF-Datei und bauen Sie das Paket nocheinmal neu.

Fertig.

3 Paket als Vorlage nutzen

Ist das Paket installiert, steht das Template in RStudio zur Auswahl. Klicken Sie auf FileNew FileRMarkdown und wählen Sie “From Template”.

Figure 8: Template auswählen

Dort steht nun meinBrief zur Auswahl. Wenn Sie auf OK klicken, erhalten Sie den Beispielcode aus skeleton.Rmd sowie die Datei Unterschrift.png. Wenn Sie vergessen haben, die PDF-Datei Ihrer Testreihen zu entfernen, wird diese ebenfalls erzeugt.

4 weitere Templates erstellen

Auf diese Weise können wir beliebig weiterte Templates erstellen. Rob Hyndman hat für seine Fakultät z.B. Vorlagen für Abschlussarbeiten, Berichte und Klausuren erstellt, siehe https://github.com/robjhyndman/MonashEBSTemplates

Wir erzeugen in dieser Anleitung noch eine Vorlage für Rechnungen.

4.1 Vorlage für Rechnungen erzeugen

Für die Rechnungen-Vorlage bedienen wir uns bei unserem Brief und passen einige wenige Felder an.

Zunächst erzeugen wir wieder die Grundstruktur des Templates, welches diesmal meineRechnung heissen soll.

1
2
3
4
5
6
usethis::use_rmarkdown_template(
  template_name = "meineRechnung",
  template_dir = NULL,
  template_description = "Meine private Rechnungsvorlage",
  template_create_dir = FALSE
)

In den Ordner inst/markdown/templates/meinerechnung/skeleton/ kopieren wir zunächst die Datei Unterschrift.png. Dann öffnen wir die Datei skeleton.Rmd und entfernen alles bis auf den Kopfbereich.

1
2
3
4
5
6
---
title: "Template Title"
author: "Your Name"
date: "The Date"
output: output_format
---

Jetzt erstellen wir den Unterordner inst/markdown/templates/meinerechnung/resources/ und darin die Datei meinerechnung.tex.

Die Datei öffnen wir nun, und kopieren den Inhalt unserer Brief-Vorlage hinein.

1
2
file.edit("inst/markdown/templates/meinerechnung/resources/meinerechnung.tex")
# kopiere nun den LaTeX Code hierhin.

Jetzt nehmen wir einige Anpassungen vor, z.B. ersetzen wir das alte Aktenzeichen durch eine Rechnungsnummer. Auch fügen wir unsere Steuernummer hinzu.

Die LaTeX-Datei sieht danach so aus:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
\documentclass[DIN,
    fontsize=11pt,          % fontsize
    paper=a4,               % page size a4
    firsthead=on,           % display header on first page
    firstfoot=on,           % display footer on first page
    pagenumber=off,         % position of the page number
    parskip=half,           % Use indent instead of skip, half, false
    enlargefirstpage=on,    % more space on first page
    fromalign=locationright, % placement of name in letter head
    addrfield=on,           % address field for envelope with window, on or true
    subject=titled,         % placement of subject, beforeopening or titled
    foldmarks=on,          % print foldmarks
    numericaldate=off,      % display date in numbers only
    KOMAold]{scrlttr2}
\usepackage[T1]{fontenc}
\usepackage[dvips]{graphicx}
\usepackage[ngerman]{babel}
\usepackage{lipsum}
\usepackage[utf8]{inputenc}
\usepackage{times}
% \usepackage{lmodern}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{lastpage}
\usepackage[rgb]{xcolor}
\usepackage{hyperref}
\hypersetup{%
    pdfborder=0 0 0,
    pdfauthor={},
    pdftitle={},
    pdfsubject={},
    pdfkeywords={},
    pdfpagemode={UseOutlines},
    bookmarksopen,
    pdfstartview={FitH},
    colorlinks,
    linkcolor={black},
    citecolor={black},
    urlcolor={blue}
  }

\urlstyle{same}

% Randbereiche mit geometry
\usepackage{geometry}
\geometry{a4paper,left=25mm,right=20mm}

\usepackage{lastpage} % letzte Seite anzeigen
\usepackage{marvosym}
\usepackage{blindtext}

% speichere eigene Variablen für Werte, die häufig drankommen
\newcommand{\myFirstname}{$myFirstname$}
\newcommand{\myFamilyname}{$myFamilyname$}
\newcommand{\myStreet}{$myStreet$}
\newcommand{\myTown}{$myTown$}

% ---Angaben für das Absenderfeld--------
\setkomavar{fromname}{\flushright\normalfont\textbf{\myFirstname\ \myFamilyname}}
\setkomavar{signature}{\myFirstname\ \myFamilyname}
\setkomavar{fromaddress}{\flushright\normalfont\scriptsize%
$myGrade$ \myFirstname\ \myFamilyname\\
\myStreet\\\myTown\\%
$myTelefon$\\%
$myMail$\\[2mm]
$myBank$\\
$myIBAN$\\
Str-Nr. $myStrNr$\\[2mm]
Rechnungsnummer:\quad\ $myRechnungsnummer$\\
\setkomavar{date}{\today} %datum im Absenderfeld
Datum:\quad \today}
%---------------------------------------
\renewcommand*\familydefault{\sfdefault}

% Anordnung im Absenderfeld
\setkomavar{firsthead}{}
\setkomavar{location}{%
  \raggedleft
  \usekomavar{fromname}\\
  \usekomavar{fromaddress}
}

% Absender auch über dem Empfängeradressfeld
\setkomavar{backaddress}{\myFamilyname\ | \myStreet\ | \myTown}

% signatur mit Unterschrift
\setkomavar{signature}{\includegraphics[width=25mm]{Unterschrift.png}\\\myFirstname\ \myFamilyname}
%
% --------------kopf/fusszeile----------------
\usepackage{scrlayer-scrpage}
\clearmainofpairofpagestyles
\cfoot{\flushright\scriptsize\normalfont Seite \thepage\ von \pageref{LastPage} }
\RedeclarePageStyleAlias{empty}{scrheadings}
%----------------------------------------------
%
\setkomavar{date}{} % Datum wieder löschen
\setkomavar{subject}{$Betreff$}
\setlength{\parindent}{0pt}

% positionierung von Absender und Empfängerboxen
\makeatletter
  \@setplength{backaddrheight}{0pt}% because backaddress=off
  \@setplength{toaddrhpos}{2.5cm}%distance from left
  \@setplength{toaddrvpos}{5cm}%distance from top
  \@setplength{toaddrheight}{3.5cm}%height of the addressbox
  \@setplength{toaddrwidth}{10cm}% width of the addressbox
  \@addtoplength{locwidth}{45mm} % width of ABSENDERbox
  \@setplength{lochpos}{2cm}%distance from top
  \@setplength{locvpos}{32mm}%distance from top
  \@setplength{refvpos}{9cm}% Abstand des Haupttextes von top
\makeatother
%------------------------------------------------------------------------------------

\begin{document}
%
\begin{letter}{$anName$\\
$anZusatz$\\
$anStrasse$\\
$anOrt$
}
%
\opening{$opening$,}
%
$body$

\closing{$closing$,
}
\end{letter}
\end{document}

Die Variablen übertragen wir in die Datei skeleton.Rmd, die dann so aussieht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---
title: "Template Title"
author: "Your Name"
date: "The Date"
myFirstname: Timm
myFamilyname: Thaler
myStreet: Absenderstr. 7
myTown: 47325 Schickensen
myGrade: Prof. Dr.
myTelefon: +49 176 555 984 66
myMail: timm@thaler.de
myBank: ING DiBa
myIBAN: DE06 505 165 55 5555 4312 64
myStrNr: 313/5555/123
Betreff: RECHNUNG
myRechnungsnummer: 2021-4
anName: Andrea Empfängerin
anZusatz: Schloss Schalkenstein
anStrasse: Adressatenstr. 23
anOrt: 22204 Briefkasten
opening: Sehr geehrte Frau Empfängerin
closing: Mit freundlichen Grüßen
output: MyStyle::meinerechnung
---

Um das Ergebnis testen zu können, müssen wir das Ausgabeformat MyStyle::meinerechnung verfügbar machen. Hierfür ergänzen wir im Unterordner R in der Datei formats.R wie folgt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# mache output "meinbrief" verfügbar
meinbrief <- function(...) {
  template <- system.file("rmarkdown/templates/meinbrief/resources/meinbrief.tex",
                          package="MyStyle")
  bookdown::pdf_document2(...,
                          template = template
  )
}

# mache output "meinerechnung" verfügbar
meinerechnung <- function(...) {
  template <- system.file("rmarkdown/templates/meinerechnung/resources/meinerechnung.tex",
                          package="MyStyle")
  bookdown::pdf_document2(...,
                          template = template
  )
}

Wenn Sie jetzt das Paket neu bauen und installieren, sollte das knitten der Datei skeleton.Rmd schon funktionieren, und eine PDF-Datei ausspucken.

Die Rechnungsvorlage kann nun wie folgt erweitert werden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
---
title: "Template Title"
author: "Your Name"
date: "The Date"
myFirstname: Timm
myFamilyname: Thaler
myStreet: Absenderstr. 7
myTown: 47325 Schickensen
myGrade: Prof. Dr.
myTelefon: +49 176 555 984 66
myMail: timm@thaler.de
myBank: ING DiBa
myIBAN: DE06 505 165 55 5555 4312 64
myStrNr: 313/5555/123
Betreff: RECHNUNG
myRechnungsnummer: 2021-4
anName: Andrea Empfängerin
anZusatz: Schloss Schalkenstein
anStrasse: Adressatenstr. 23
anOrt: 22204 Briefkasten
opening: Sehr geehrte Frau Empfängerin
closing: Mit freundlichen Grüßen
output: MyStyle::meinerechnung
---


für die erbrachten Leistungen erlaube ich mir wie folgt in Rechnung zu stellen:



|  **Datum** |                 **Posten**                          | **Betrag**|
|------------|-----------------------------------------------------|----------:|
| 29.06.2021 | Zauberschow für Kinder in der KiTa Regenbogenland   |     300,01|
|            |                                                     |           |
|            |                                         Nettobetrag |     300,01|
|            |                      Umsatzsteuerfrei gem. §19 UstG |       0,00|
|            |                                    **Gesamtbetrag**:| **300,01**|




Bitte überweisen Sie den Betrag unter Angabe der Rechnungsnummer auf mein Konto bei der ING DiBa
mit der IBAN *DE06 505 165 55 5555 4312 64*.

Ich bedanke mich für Ihren Auftrag und verbleibe

Wenn Sie jetzt knitten, sieht die PDF-Datei skeleton.pdf so aus:

Figure 9: fertiges PDF-Dokument

Jetzt können Sie noch weitere Anpassungen vornehmen. Wenn Sie fertig sind, entfernen Sie die PDF-Datei skeleton.pdf und bauen und installieren Sie das Paket neu. Ab jetzt steht es in RStudio als Vorlage zur Verfügung.

Klicken Sie auf FileNew FileRMarkdown und wählen Sie “From Template”.

Figure 10: Vorlagen

5 noch mehr Templates

Noch weitere Templates bietet unter anderem das R-Paket rticles.

1
install.packages("rticles")

Nach einem Neustart von RStudio stehen die Templates bereit.

6 Weiterführende Links

Login bei MediaWiki mit Python

Es gibt zwei Möglichkeiten, sich bei MediaWiki einzuloggen,

  • per api.php
  • als “normaler” User (über die index.php)

api.php

Diese Variante setzt voraus, dass du Special:BotPasswords für deinen Account vergeben hast. Mit der API-Methode ist wirklich nur die api.php erreichbar. Versucht man mit der Session die index.php zu erreichen, erhält man die Meldung “Du musst angemeldet sein!”

Zunächst die Anmeldung, weche wir in einer request.session speichern:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    #!/usr/bin/env python3
    import requests
    username 		= 'produnis'					# Username to login with
    botpwd 			= 'myapibot@foobarfoobarfoobars52o8mk8apimpsb8'	# Password of Special:BotPasswords in the style BOTNAME@password
    
    api_url   = "https://my.wiki.ltd/api.php"
    session = requests.Session()
    r1 = session.get(api_url, params={
        'format': 'json',
        'action': 'query',
        'meta': 'tokens',
        'type': 'login',
    })
    
    r2 = session.post(api_url, data={
        'format': 'json',
        'action': 'login',
        'lgname': username,
        'lgpassword': botpwd,
        'lgtoken': r1.json()['query']['tokens']['logintoken'],
    })
    if r2.json()['login']['result'] != 'Success':
        raise RuntimeError(r2.json())
    

Nun kann die API wie folgt aufgerufen und ausgelesen werden:

1
2
3
4
5
6
7
8
9
    MyParams = {
    	"action": "query",
    	"format": "json",
    	"prop": "pageprops",
    	"titles": "Kategorie:Hauptkategorie"
    }
    mycontent = session.get(api_url, params=MyParams)
    mydata=mycontent.json
    print("i got: ", mydata()['query']['pages'])

index.php

Wenn wir die index.php nutzen wollen, zB um die Mpdf-Extension aufzurufen, müssen wir uns anders einloggen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    #!/usr/bin/env python3
    import requests
    from bs4 import BeautifulSoup as bs
    
    username 		= 'produnis'					# Username to login with
    userpwd			= 'SuperSecreet'				# Userpassword
    botpwd 			= 'myapibot@foobarfoobarfoobars52o8mk8apimpsb8'	# Password of Special:BotPasswords in the style BOTNAME@password
    
    api_url   = "https://my.wiki.ltd/api.php"
    index_url = "https://my.wiki.ltd/index.php"
    
    payload = {
    	'wpName': username,
    	'wpPassword': userpwd,
    	'wploginattempt': 'Log in',
    	'wpEditToken': "+\\",
    	'title': "Special:UserLogin",
    	'authAction': "login",
    	'force': "",
    	'wpForceHttps': "1",
    	'wpFromhttp': "1",
        #'wpLoginToken': '',
    	}
    
    def get_login_token(raw_resp):
    	soup = bs(raw_resp.text, 'lxml')
    	token = [n.get('value', '') for n in soup.find_all('input')
    		if n.get('name', '') == 'wpLoginToken']
    	return token[0]
    
    with requests.session() as s:
    	resp = s.get(index_url + '?title=Spezial:UserLogin')
    	payload['wpLoginToken'] = get_login_token(resp)
    	response_post = s.post(index_url + '?title=Spezial:UserLogin&action=submitlogin&type=login', data=payload)

Nun können Seiten ausgerufen werden per:

1
    	response = s.get(index_url + '?title=Special:Watchlist')

XFCE Autostart verzögern

Manche Programme, die ich im Autostart betreibe, starten bei mir unter XFCE so schnell, dass ihre Icons nicht im Benachrichtigungs-Panel erscheinen - eben weil das Panel noch nicht bereit ist. Dies betrifft bei mir z.B. Davmail und Nextcloud. Daher möchte ich eine Verzögerung von 5 Sekunden einbauen, bevor diese Programme gestartet werden.

Hier haben wir zwei Möglichkeiten:

  1. wir editieren die Autostartscripte, die unter ~/.config/autostart/ bereit liegen

  2. wir machen es Klicki-Bunti über XFCE-Menu - Einstellungen - Sitzung und Startverhalten - Automatisch gestartete Anwendungen

Für beide gilt folgendes Befehlsschema:

/bin/sh -c "sleep 5 && BEFEHL"

(Es hat mich etwas Zeit gekostet, bis ich herausgefunden habe, dass ein simples sleep 2 && BEFEHL nicht funktioniert, sondern dass man eine Shell angeben muss und der anschließend auszuführende Befehl ebenfalls an diese Shell übergeben werden muss /bin/sh -c "sleep 5 && BEFEHL")

Für davmail sieht das z.B. so aus:

nano ~/.config/autostart/davmail.desktop







[Desktop Entry]
Encoding=UTF-8
Version=0.9.4
Type=Application
Name=davmail
Comment=davmail
Exec=/bin/sh -c "sleep 5 && davmail"
OnlyShowIn=XFCE;
StartupNotify=false
Terminal=false
Hidden=false

Das funktioniert prima… :)

Subsonic ist tot, es lebe Airsonic

Seit ein paar Jahren habe ich einen Subsonic-Server für meine Musik. Ich habe sogar die 12,- Euro Zwangsabgabe pro Jahr bezahlt, damit meine Clients auf den Server zugreifen können.

Heute hab ich Subsonic zu Gunsten von Airsonic verworfen. Airsonic ist ein Subsonic-Fork, es ist “frei” wie in “Bier” (d.h. die 12,- fallen weg) und funktioniert prima mit meinem Apache-Proxy.

Folgendes Szenario möchte ich realisieren:

  • Airsonic läuft auf einem Port ohne SSL (in meinem Fall 4040)

  • Damit aber auch https-Verbindungen klappen, richte ich einen Apache-Proxy ein. Dieser leitet dann die HTTPS-Anfrage intern an Airsonic weiter. Das hat zB den Vorteil, dass die LetsEncrypt-Zertifikate nur in Apache aktualisiert werden müssen

  • Alle Clients haben von überall Zugriff auf Airsonic

Installation

Die Installation unter Archlinux ist recht einfach:

pacaur -S airsonic  jre8-openjdk-headless

Jetzt muss ich noch sicherstellen, dass auch wirklich jre8 verwendet wird:

archlinux-java status # auf jre8 umstellen

Konfiguration

Für Airsonic habe ich nur meinen Port eingetragen:

sudo nano /etc/airsonic/airsonic.conf






(...)
PORT=4040
CONTEXT_PATH=/airsonic
(...)

Für das Transcoding (also zB das Runterrechnen auf 128kb/s mp3) muss noch ein Symlink auf ffmpeg gesetzt werden:

cd /var/lib/airsonic/transcode
sudo ln -s /usr/bin/ffmpeg .
sudo chown -h airsonic:airsonic ffmpeg

Für Apache wird die httpd.conf wie folgt ergänzt:

sudo nano /etc/httpd/conf/httpd.conf






(...)
RequestHeader set X-Forwarded-Proto "https"
ProxyPass        /airsonic http://127.0.0.1:4040/airsonic
ProxyPassReverse /airsonic http://127.0.0.1:4040/airsonic
(...)

Dies bewirkt, dass Anfragen von _http://meinserver.org/airsonic_ als auch von https://meinserver.org/airsonic intern an den Port 4040, und somit an Airsonic, weitergereicht werden. Ich muss also keine Ports in der Firewall öffnen, und ich kann meine LetsEncrypt-Lösung für SSL verwenden.

Starten…

Nach einem Neustart von Apache kann auch Airsonic gestartet werden:

sudo apachectl graceful
sudo systemctl start airsonic.service

Voila, Airsonic ist nun unter http://IPDESSERVERS:4040 und auch unter http(s)://meinserver.org/airsonic erreichbar.

IPv6 im Congstar Mobilnetz

Ich nutze Android8 und habe festgestellt, dass ich mir im Congstar Mobilnetz eine IPv6-Adresse geben kann. Hierzu gehe ich in den Einstelungen zu VERBINDUNGEN - MOBILE NETZWERKE - ZUGANGSPUNKTE - und wähle “hinzufügen”.

Folgende Felder habe ich eingeragen:

Name: T-Mobile Internet
APN: internet.t-mobile
Benutzername: telekom (oder congstar eintragen)
Kennwort: tm (oder cs eintragen, wenn als Benutzer congstar gewählt wurde)
MCC: 262
MNC: 01
Authentifizierung: CHAP
APN-Typ: default,supl,mms
APN-Protokoll IPv4/IPv6

Alles andere habe ich nicht angegeben/so belassen.

Jetzt noch speichern, und ich kann den neuen ANP auswählen. Und zack, hat mein Handy eine gültige globale IPv6 Adresse. Diese sieht man zB unter Einstelungen, Telefoninfo, Status.

1 2 3 12