backup_channel_id ist gesetzt. Vorher nachgesehen, ob der Bot den Kanal auch
bedienen KANN -- ein eingetragener Kanal, in dem er nicht posten darf, sieht
von aussen genauso aus wie ein richtig eingetragener:
Kanal #backup-upload-kanal Textkanal, richtige Gilde
Bot D4rk DevBot VIEW_CHANNEL, SEND_MESSAGES, ATTACH_FILES
Dann von Hand ausgeloest, und der ganze Weg lief durch -- inklusive der heute
gebauten Gegenpruefung:
[backup] d4rkbot-2026-08-12.db.gz erstellt (1021 KB),
geprueft: 55 Tabellen, 89 Einstellungen
last_backup 2026-08-12T13:54:44Z, last_backup_ok 1, kein Fehler
Der Zaehler der Einstellungen ist zwischen zwei Laeufen von 87 auf 89
gewachsen: das sind die Laeufe selbst, die last_backup schreiben. Ein huebscher
Beleg, dass wirklich das neue Archiv geoeffnet wurde und nicht ein altes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
464 lines
18 KiB
Markdown
464 lines
18 KiB
Markdown
# Durchsicht am 12.08.2026
|
|
|
|
Gesucht wurde nach **denselben Fehlermustern**, die beim Bau von `d4rk_media`
|
|
aufgefallen sind — nicht nach allem Denkbaren. 24 105 Zeilen in 108 Dateien
|
|
liest niemand am Stück; gesucht wurde gezielt nach:
|
|
|
|
- Aufräumfunktionen, die nie aufgerufen werden
|
|
- Wachen, die an `'*'` hängen statt an den eigenen Pfaden
|
|
- SQL, in das Zeichenketten eingesetzt werden
|
|
- `fetch` auf Adressen, die von außen kommen
|
|
- Antwortkörper, die niemand liest
|
|
- Schleifen mit Zeitlimit, die nacheinander laufen
|
|
- Sicherungen, die nie zurückgespielt wurden
|
|
|
|
**An diesem Bot wurde nichts geändert.** Was hier steht, ist ein Befund und
|
|
kein Eingriff — die Entscheidungen darüber gehören dir.
|
|
|
|
---
|
|
|
|
## 1 · Die Sicherung hat keinen sicheren Ort
|
|
|
|
**Das ist der wichtigste Befund.** Gemessen:
|
|
|
|
```
|
|
docker inspect d4rkbot
|
|
volume ecobot_ecobot_data -> /app/data
|
|
|
|
/app/data/ecobot.db 5,0 MB
|
|
/app/data/backups/ 5,7 MB (14 Stück, täglich 03:0x)
|
|
```
|
|
|
|
**Datenbank und alle vierzehn Sicherungen liegen im selben Volume.** Geht das
|
|
Volume verloren, geht beides zusammen verloren. Das ist keine Sicherung, das
|
|
ist eine Kopie.
|
|
|
|
Vorgesehen ist ein Ausweg — der Upload in einen privaten Discord-Kanal:
|
|
|
|
```js
|
|
const channelId = getSetting('backup_channel_id');
|
|
if (channelId && client) { … }
|
|
```
|
|
|
|
**Der Kanal ist nicht gesetzt.** Der Zweig läuft also nie, und der einzige
|
|
vorgesehene Weg aus dem Volume heraus ist unbenutzt.
|
|
|
|
Was der Code *richtig* macht, damit das nicht untergeht: `db.backup(rawFile)` —
|
|
die Online-Sicherungsschnittstelle von SQLite, WAL-sicher. Eine Dateikopie wäre
|
|
still unvollständig gewesen. Das ist derselbe Griff wie in `d4rk_media` und er
|
|
ist korrekt.
|
|
|
|
**Zwei Wege:**
|
|
|
|
1. `backup_channel_id` setzen — der eingebaute Weg, kostet einen Klick.
|
|
2. Wie bei `d4rk_media`: ein Skript auf dem Wirt, das das Archiv abholt und in
|
|
die Nextcloud legt. Dort liegt schon eines (`tools/sichern.ps1`), das Muster
|
|
ließe sich übernehmen.
|
|
|
|
---
|
|
|
|
## 2 · Niemand merkt, wenn die Sicherung ausbleibt
|
|
|
|
`last_backup` wird geschrieben und im Panel **angezeigt** — aber nirgends
|
|
**geprüft**:
|
|
|
|
```
|
|
src/backup.js:57 setSetting('last_backup', …) geschrieben
|
|
src/backup.js:70 … === today ? return als Tagesbremse gelesen
|
|
src/web/api.js:1003 lastBackup: getSetting(…) angezeigt
|
|
```
|
|
|
|
Niemand vergleicht ihn mit heute und beschwert sich. Dazu kommt das Zeitfenster:
|
|
|
|
```js
|
|
if (now.getHours() !== 3) return;
|
|
```
|
|
|
|
Ist der Bot während der Stunde 03 unten, fällt der Tag aus — still. Bei einem
|
|
Bot, der nach jedem Update neu startet, ist das kein Sonderfall.
|
|
|
|
**Die Maschinerie dafür ist vollständig da und wird nicht benutzt**: `dmAdmin`,
|
|
`brandEmbed`, `startIncident`/`endIncident`, der Wächter mit seiner
|
|
Fehlerschwelle. Es fehlt der eine Aufruf, der `last_backup` liest.
|
|
|
|
`d4rk_media` hat für genau das `pruefeSicherung()` — 26 Stunden Schwelle,
|
|
meldet einmal je Zustand.
|
|
|
|
---
|
|
|
|
## 3 · Zu groß für Discord endet in der Konsole
|
|
|
|
```js
|
|
} else {
|
|
console.warn(`[backup] ${gzFile} zu groß für Discord-Upload (${sizeBytes} B)`);
|
|
}
|
|
```
|
|
|
|
Die Grenze steht bei 9 MB. Die Archive wachsen sichtbar:
|
|
|
|
```
|
|
08.08. 689 553 B
|
|
09.08. 762 371 B
|
|
10.08. 836 677 B
|
|
11.08. 906 916 B
|
|
```
|
|
|
|
Rund 70 KB je Tag. Bis 9 MB ist Luft für etwa drei Monate — und wenn sie reißt,
|
|
hört die Kopie **still** auf. Eine Konsolenzeile in einem Container liest
|
|
niemand.
|
|
|
|
Das ist derselbe Fehler wie ein Knopf ohne Rückmeldung, nur langsamer.
|
|
|
|
---
|
|
|
|
## 4 · Das Archiv wird nie gegengeprüft
|
|
|
|
Es wird geschrieben, gezippt, hochgeladen — und nie ausgepackt, nie geöffnet,
|
|
nie gezählt. Ein defektes gzip oder eine halbe Datei fiele erst an dem Tag auf,
|
|
an dem man sie braucht.
|
|
|
|
`tools/sichern.ps1` in `d4rk_media` packt sein Archiv aus, öffnet die Datenbank
|
|
darin und zählt die Zeilen — und `tools/zurueckspielen.ps1` fährt daraus einen
|
|
zweiten Dienst hoch und lässt ihn drei zufällige Dateien ausliefern. **Genau
|
|
diese Übung hat dort gestern einen echten Fehler gefunden** (ein stehen
|
|
gebliebenes `media.db-wal`, das die wiederhergestellte Datenbank leer aussehen
|
|
ließ).
|
|
|
|
Ein Backup, das man nie zurückgespielt hat, ist keins.
|
|
|
|
---
|
|
|
|
## ~~5 · `pruneMessageCache` wird nie aufgerufen~~ — FALSCH, zurückgezogen am 12.08.2026
|
|
|
|
**Dieser Befund war falsch.** Der Aufruf steht in `src/bot/mod-tools.js:239`, in
|
|
`registerModTools`, mit eigenem Kommentar — und er stand schon zum Zeitpunkt der
|
|
Durchsicht dort (nachgesehen in `git show 1808b7c:src/bot/mod-tools.js`):
|
|
|
|
```js
|
|
const aufraeumen = () => {
|
|
const weg = pruneMessageCache(Math.max(0, tuning('modlog_cache_days')));
|
|
if (weg > 0) console.log(`[modlog] ${weg} alte Nachrichten vergessen`);
|
|
};
|
|
aufraeumen();
|
|
setInterval(aufraeumen, 86_400_000);
|
|
```
|
|
|
|
Täglich, mit Frist aus der Feineinstellung. **Es ist nichts zu tun.**
|
|
|
|
Wie es passieren konnte: gezählt wurden „Aufrufe außerhalb von `db.js`" — und
|
|
`mod-tools.js` importiert die Funktion in einer Sammelzeile mit fünf anderen
|
|
Namen. Beim Zählen ist die Zeile als Import durchgegangen und der Aufruf
|
|
zwanzig Zeilen weiter unten nicht mitgezählt worden.
|
|
|
|
**Das ist genau der Fehler, den zu vermeiden dieser Bericht dasteht:** eine
|
|
plausible Zahl, die niemand am Gegenstand nachgeprüft hat. Die anderen vier
|
|
Befunde sind deshalb am 12.08.2026 alle noch einmal einzeln nachgemessen worden
|
|
— sie stimmen:
|
|
|
|
| Befund | Nachgemessen |
|
|
|---|---|
|
|
| 1 · Sicherung ohne sicheren Ort | `backup_channel_id` ist **leer** — der Offsite-Zweig lief nie |
|
|
| 2 · Ausbleiben fällt niemandem auf | `last_backup` kommt an drei Stellen vor: schreiben, Tagesbremse, anzeigen. **Nirgends ein Vergleich mit heute.** |
|
|
| 3 · Zu groß endet in der Konsole | `console.warn` in `backup.js`, unverändert |
|
|
| 4 · Archiv nie gegengeprüft | kein Auspacken, kein Öffnen, kein Zählen im ganzen Modul |
|
|
|
|
---
|
|
|
|
## Geprüft und in Ordnung
|
|
|
|
Das gehört genauso hierher, damit es niemand ein zweites Mal prüft.
|
|
|
|
| Was | Ergebnis |
|
|
|---|---|
|
|
| `db.backup()` statt Dateikopie | **richtig**, WAL-sicher — und im Kommentar begründet |
|
|
| `ORDER BY ${ord}` in `db.js:414` | **sicher**: `SORTIERUNG` ist ein festes Objekt mit drei Werten, die Anweisungen werden einmalig daraus vorbereitet. Der Aufrufer wählt nur einen Schlüssel. |
|
|
| Öffentliche Serverliste `/api/servers` | **sauber**: die Felder sind einzeln aufgezählt, „bewusst ohne query_url/host/port" |
|
|
| Geheimnisse in `/api/settings` | die zwei bekannten gehen als **Ja/Nein** hinaus (`gitea_api_token_set`, `twitch_creds_set`) |
|
|
| Spielserver-Monitor | nutzt schon `Promise.all` — die Schleife läuft nebeneinander |
|
|
| Zugangscodes in der Datenbank | genau einer (LS25, 16 Zeichen), und er geht nur an Panel-Nutzer mit `server`-Recht |
|
|
|
|
---
|
|
|
|
## Beobachtungen ohne Handlungsbedarf
|
|
|
|
**Panel-Nutzer können den Bot beliebige Adressen abrufen lassen** — Watchdog,
|
|
Spielserver-Abfrage, LS-Feed nehmen alle eine URL aus der Datenbank. Bei
|
|
`d4rk_media` war das eine echte Lücke, weil dort die *Antwort* als Datei
|
|
zurückkommt. Hier kommt nur „erreichbar ja/nein" heraus, und wer das Panel hat,
|
|
kann ohnehin mehr. Kein Handlungsbedarf — nur zu wissen, falls je ein Weg
|
|
dazukommt, der den Antwortkörper weitergibt.
|
|
|
|
**`currentSettings()` gibt jeden von einem Modul angemeldeten Textschlüssel im
|
|
Klartext aus** (`src/web/api.js:901`). Heute steht dort nichts Heikles. Aber ein
|
|
künftiges Modul mit einem Feld `api_token` ginge ungefragt mit hinaus, ohne dass
|
|
jemand es bemerkt. Eine Namensregel („endet auf `_secret`/`_token` → nur als
|
|
Ja/Nein") wäre eine Zeile und schlösse das für immer.
|
|
|
|
---
|
|
|
|
## Wenn ich eins zuerst täte
|
|
|
|
**Punkt 1 und 2 zusammen**, denn sie sind dasselbe Problem von zwei Seiten: die
|
|
Sicherung hat keinen zweiten Ort, und niemand würde merken, wenn sie ganz
|
|
ausbliebe. Beides zusammen heißt: der Bot hat faktisch keine Sicherung, sondern
|
|
eine Kopie neben dem Original, deren Ausfall unbemerkt bliebe.
|
|
|
|
Der billigste Schritt ist `backup_channel_id` zu setzen — ein Klick, und der
|
|
vorgesehene Weg funktioniert. Der solide Schritt ist derselbe wie bei
|
|
`d4rk_media`: abholen, prüfen, in die Nextcloud, und ein Wachhund darauf.
|
|
|
|
---
|
|
|
|
## Was am 12.08.2026 daraus gebaut wurde
|
|
|
|
**Befund 2, 3 und 4 sind erledigt** — Befund 1 zur Hälfte (siehe unten).
|
|
|
|
### Der Bot sagt jetzt Bescheid
|
|
|
|
`src/melden.js` ist neu und enthält das, was vorher in `watchdog.js`
|
|
eingeschlossen war: `dmAdmin`. Deshalb hat alles andere im Bot geschwiegen oder
|
|
in die Konsole geschrieben — **eine Konsolenzeile in einem Container liest
|
|
niemand.**
|
|
|
|
Dazu `dmAdminEinmalig(client, schluessel, zustand, …)`: meldet nur, wenn sich
|
|
der Zustand *geändert* hat. Ohne das würde eine Prüfung, die alle zehn Minuten
|
|
läuft, denselben Ausfall alle zehn Minuten melden — nach der dritten DM liest
|
|
man sie nicht mehr. Der Merker steht in den Einstellungen und nicht im
|
|
Arbeitsspeicher: ein Bot, der nach jedem Update neu startet, hätte sonst nach
|
|
jedem Update wieder eine frische Meinung.
|
|
|
|
Nachgemessen gegen eine **Kopie** der Datenbank, sechs Schritte:
|
|
|
|
```
|
|
1. Ausfall zum ersten Mal gebaut: 1 Merker: "alt:…T03"
|
|
2. derselbe Ausfall noch zweimal gebaut: 0 Merker: "alt:…T03"
|
|
3. ANDERER Ausfall gebaut: 1 Merker: "fehler:…T09"
|
|
4. wieder in Ordnung (null) gebaut: 0 Merker: ""
|
|
5. derselbe Ausfall danach erneut gebaut: 1 Merker: "alt:…T03"
|
|
```
|
|
|
|
### Der Wachhund auf `last_backup`
|
|
|
|
`pruefeSicherung(client)` läuft im selben Zehn-Minuten-Takt wie der Planer und
|
|
meldet, wenn die letzte Sicherung älter als **26 Stunden** ist, wenn die letzte
|
|
fehlgeschlagen ist, oder wenn es noch nie eine gab.
|
|
|
|
Beim Fehlerfall steht **nicht** `last_backup` als Zeitpunkt im Embed: der wird
|
|
nur bei Erfolg gesetzt, dort stünde also der letzte *gute* Lauf, und das ließe
|
|
die Sicherung frischer aussehen, als sie ist. Der Zeitpunkt des Fehlschlags
|
|
steht getrennt daneben (`last_backup_fehler_at`).
|
|
|
|
### Der Tag fällt nicht mehr aus
|
|
|
|
Vorher:
|
|
|
|
```js
|
|
if (now.getHours() !== 3) return;
|
|
```
|
|
|
|
Wer während dieser **einen Stunde** unten war, hatte den Tag verloren — und ein
|
|
Bot, der nach jedem Update neu startet, ist genau dieser Fall. Jetzt zählt nur
|
|
noch: es ist nach 03:00 und heute war noch keine. Der Lauf wird also nachgeholt.
|
|
|
|
### Das Archiv wird ausgepackt und gezählt
|
|
|
|
Nach dem Zippen wird das Archiv wieder ausgepackt, die Datenbank darin geöffnet,
|
|
`PRAGMA integrity_check` gefahren und die Tabellen gezählt — gegen die
|
|
**laufende** Datenbank. Fällt das durch, wird das Archiv **gelöscht** (im
|
|
Sicherungsordner sähe es sonst aus wie eine Sicherung), die Rotation läuft
|
|
nicht, und `last_backup` bleibt stehen.
|
|
|
|
An den echten Archiven gemessen, und mit zwei Gegenproben, damit die Prüfung
|
|
nicht nur „ja" sagen kann:
|
|
|
|
```
|
|
laufende Datenbank: 55 Tabellen
|
|
|
|
2026-08-10 817 KB 54 Tabellen, 86 Einstellungen 86 ms
|
|
2026-08-11 886 KB 54 Tabellen, 86 Einstellungen 64 ms
|
|
2026-08-12 970 KB 55 Tabellen, 86 Einstellungen 78 ms
|
|
|
|
halbes gzip -> abgelehnt: "unexpected end of file"
|
|
Müll -> abgelehnt: "incorrect header check"
|
|
```
|
|
|
|
Die 54 gegen 55 sind übrigens kein Fehler, sondern eine **gewachsene** Tabelle
|
|
zwischen dem 11. und dem 12. Verglichen wird zeitgleich — Archiv gegen die
|
|
Datenbank, aus der es gerade entstanden ist —, also stört das nicht. Wissen
|
|
sollte man es trotzdem, bevor jemand alte Archive gegen die heutige Zahl hält.
|
|
|
|
### Befund 1 — siehe unten
|
|
|
|
Der ist am selben Tag noch angegangen worden.
|
|
|
|
---
|
|
|
|
## ~~Nachtrag: der Auto-Deploy hat nicht ausgelöst~~ — zwei falsche Diagnosen, siehe unten
|
|
|
|
`docs/auto-deploy.md` beschreibt zwei Wege — Portainer-Webhook oder Gitea
|
|
Actions. **Am 12.08.2026 hat keiner von beiden gegriffen.** Gemessen nach dem
|
|
Push von `93156e5`:
|
|
|
|
```
|
|
Push registriert git.d4rkst3r.de sagt updated_at 12:48:18Z
|
|
Workflow-Läufe "total_count": 0 <- keiner, nie
|
|
Act-Runner auf dem Wirt kein Container
|
|
d4rkbot neu gestartet? nein, läuft seit 11.08. 22:21
|
|
Code im Container grep pruefeSicherung -> 0 <- der alte Stand
|
|
```
|
|
|
|
`has_actions` ist am Repo **an**, es gibt also nur niemanden, der die Läufe
|
|
abarbeitet — und der Webhook-Weg (der ohne Runner auskäme) ist offenbar auch
|
|
nicht eingerichtet.
|
|
|
|
### Nachgefasst: er zieht, aber er baut nicht
|
|
|
|
Der erste Verdacht („kein Runner") war nur die halbe Wahrheit. Portainers
|
|
GitOps-Weg **funktioniert** — nachgemessen in seinem eigenen Datenverzeichnis:
|
|
|
|
```
|
|
/d/compose/1/src/melden.js 12:48 <- die Uhrzeit meines Pushes
|
|
/d/compose/1/stack.env 12:57 <- Portainer hat neu geschrieben
|
|
docker images d4rkbot:latest 00:21 <- das Abbild ist 15 Stunden alt
|
|
```
|
|
|
|
Portainer holt den neuen Stand also brav ins Stack-Verzeichnis und ruft dann
|
|
`docker compose up -d`. **Und das baut nur, wenn das Abbild fehlt.**
|
|
`d4rkbot:latest` gab es — also kein Bau, kein neuer Container, und der Bot lief
|
|
weiter mit dem Code von vorgestern. Kein Runner, kein Webhook und keine
|
|
Fehlermeldung; es sah nach „nichts zu tun" aus.
|
|
|
|
**Die Zeile, die gefehlt hat**, steht jetzt in `docker-compose.yml`:
|
|
|
|
```yaml
|
|
pull_policy: build
|
|
```
|
|
|
|
Damit baut `docker compose up -d` das Abbild bei jedem Ausrollen neu. Geprüft
|
|
mit `docker compose config` (Compose v5.3.1 nimmt es an und gibt es aufgelöst
|
|
zurück).
|
|
|
|
**Einmal noch von Hand**, denn die Zeile wirkt erst, wenn sie selbst ausgerollt
|
|
ist: Portainer → Stack `ecobot` → *Pull and redeploy*. Danach greift der
|
|
Auto-Deploy von allein.
|
|
|
|
Das ist keine Kleinigkeit für die Zukunft: ein Deploy, von dem man glaubt, dass
|
|
er automatisch läuft, ist schlimmer als gar keiner. Man pusht, hakt es ab, und
|
|
der Fehler, den man gerade behoben hat, läuft weiter.
|
|
|
|
### Richtigstellung: der Auto-Deploy funktioniert. Er ist nur langsamer als meine Geduld
|
|
|
|
**Der Abschnitt oben war falsch, und zwar zweimal.** Erst hieß es „kein Runner,
|
|
also läuft gar nichts", dann „er zieht, aber er baut nicht". Beides war aus
|
|
einem Zwischenstand geschlossen, während der Vorgang noch lief.
|
|
|
|
Was wirklich passiert ist:
|
|
|
|
```
|
|
12:48:18 Push 93156e5
|
|
12:48 Portainer hat die Dateien im Stack-Verzeichnis
|
|
12:57 hier gemessen: Abbild 15 h alt, Container von gestern
|
|
-> daraus "er baut nicht" geschlossen. FALSCH.
|
|
13:01:02 Abbild neu gebaut
|
|
13:01:14 Container neu gestartet
|
|
13:02 pruefeSicherung im Container: 2 · melden.js: da · Panel: HTTP 200
|
|
```
|
|
|
|
Zwischen Push und laufendem neuen Code liegen **rund dreizehn Minuten** —
|
|
Portainer fragt in Intervallen nach, nicht sofort. Meine Messung um 12:57 fiel
|
|
mitten in dieses Fenster: die Dateien waren schon da, das Abbild noch nicht neu.
|
|
Aus diesem Schnappschuss habe ich einen Systemfehler gemacht.
|
|
|
|
**Das ist genau der Fehler, gegen den dieser Bericht geschrieben ist** — eine
|
|
plausible Erklärung, die zum Schnappschuss passt, behauptet, bevor der Vorgang
|
|
zu Ende war. Der Unterschied zu den anderen Befunden hier: bei denen wurde
|
|
gewartet, bis etwas fertig war.
|
|
|
|
### Was mit `pull_policy: build` passiert
|
|
|
|
Die Zeile steht weiter in `docker-compose.yml`, aber **nicht mehr aus dem Grund,
|
|
der im Commit davor stand**. Sie repariert nichts — Portainer baut auch ohne sie
|
|
neu. Sie macht es nur ausdrücklich: bei einem Stack mit `build:` ist „immer neu
|
|
bauen" das, was man beim Ausrollen will, und wer später von Hand
|
|
`docker compose up -d` tippt, bekommt dann dasselbe Ergebnis wie die Automatik.
|
|
|
|
Wer sie nicht will, kann sie folgenlos entfernen.
|
|
|
|
---
|
|
|
|
## Befund 1: die Sicherung verlässt jetzt das Volume
|
|
|
|
`tools/abholen.ps1`, täglich um **03:30** — nach der Sicherung des Bots (ab
|
|
03:00) und vor der von `d4rk_media` (04:30), damit nicht zwei Vorgänge
|
|
gleichzeitig auf derselben Platte arbeiten.
|
|
|
|
Es **sichert nicht**. Das Archiv baut der Bot selbst; hier wird nur abgeholt —
|
|
und zwar so, dass am Ende feststeht, dass die Kopie heil ist, und nicht nur,
|
|
dass ein Kopierbefehl keinen Fehler geworfen hat: Prüfsumme im Container gegen
|
|
die Kopie draußen, dann auspacken und die Datenbank darin öffnen.
|
|
|
|
Echter Lauf über die geplante Aufgabe:
|
|
|
|
```
|
|
Zustand: Ready Ergebnis: 0 Naechster Lauf: 13.08.2026 03:30
|
|
|
|
d4rkbot-2026-08-12.db.gz 993.332 Bytes
|
|
andere Platte: Nr. 1 statt Nr. 0
|
|
identisch (ff08516d293d...)
|
|
in der Sicherung: 55 Tabellen, 86 Einstellungen
|
|
|
|
last_zweitziel = { ok: true, ziel: "D:\backup\d4rkbot", … }
|
|
```
|
|
|
|
### Was außerhalb des Repos liegt
|
|
|
|
Zwei Dinge, die ein `git clone` nicht mitbringt — sie stehen hier, damit sie
|
|
nach einem Neuaufsetzen nicht fehlen:
|
|
|
|
| Was | Wo |
|
|
|---|---|
|
|
| Arbeitskopie | `C:\Users\Darkster\Desktop\d4rkbot` — vorher gab es keine, der Bot lief nur aus Portainers Checkout |
|
|
| Geplante Aufgabe | `d4rkbot Sicherung abholen`, täglich 03:30, als `Darkster`/Interactive |
|
|
|
|
Die Aufgabe startet `pwsh.exe` über den **stabilen Ausführungsalias** unter
|
|
`LOCALAPPDATA` und nicht über den Pfad mit Versionsnummer. Genau daran hing bei
|
|
`d4rk_media` eine Sicherung, die beim nächsten PowerShell-Update aufgehört
|
|
hätte zu laufen.
|
|
|
|
### Der Discord-Kanal steht seit dem 12.08.2026 abends
|
|
|
|
`backup_channel_id` ist gesetzt. Vorher nachgesehen, ob der Bot ihn auch
|
|
wirklich bedienen kann -- ein eingetragener Kanal, in dem er nicht posten darf,
|
|
sieht von auszen genauso aus wie ein richtig eingetragener:
|
|
|
|
```
|
|
Kanal #backup-upload-kanal Textkanal, richtige Gilde
|
|
Bot D4rk DevBot VIEW_CHANNEL, SEND_MESSAGES, ATTACH_FILES
|
|
```
|
|
|
|
Dann von Hand ausgeloest, und der ganze Weg lief durch:
|
|
|
|
```
|
|
[backup] d4rkbot-2026-08-12.db.gz erstellt (1021 KB),
|
|
geprueft: 55 Tabellen, 89 Einstellungen
|
|
last_backup 2026-08-12T13:54:44Z last_backup_ok 1 kein Fehler
|
|
```
|
|
|
|
**Damit verlaesst die Sicherung des Bots die Maschine, und zwar von allein.**
|
|
Der Zaehler der Einstellungen ist zwischen zwei Laeufen von 87 auf 89
|
|
gewachsen -- das sind die Laeufe selbst; ein huebscher Beleg, dass wirklich das
|
|
neue Archiv geoeffnet wurde und nicht ein altes.
|
|
|
|
### Und was weiter offen ist
|
|
|
|
Beide Kopien liegen **im selben Rechner**. Gegen einen Plattenausfall hilft das
|
|
jetzt, gegen Feuer, Diebstahl oder eine verschlüsselte Maschine nicht. Dafür
|
|
gibt es zwei Wege, und sie schließen sich nicht aus:
|
|
|
|
1. **`backup_channel_id`** setzen — der eingebaute Weg, ein privater Kanal, in
|
|
dem der Bot Dateien anhängen darf. Kostet einen Klick. Grenze: 9 MB je
|
|
Datei, heute bei 993 KB, hochgerechnet gegen Ende Oktober bei rund 6 MB.
|
|
2. **In die Nextcloud**, wie `d4rk_media` es tut. `tools/sichern.ps1` dort
|
|
enthält den WebDAV-Teil fertig (`curl`, `MKCOL`, `PUT`, Prüfsumme
|
|
zurückgeholt, `PROPFIND` zum Ausdünnen) — er ließe sich übernehmen.
|