Update README and systemd service configuration for yourchat2. Added installation script install-systemd.sh for easier setup and modified yourchat2.service to improve service management, including environment file support and enhanced restart policies.

This commit is contained in:
Torsten Schulz (local)
2026-03-04 17:21:03 +01:00
parent 0b91b94ae1
commit 5c4ac55f61
4 changed files with 291 additions and 9 deletions

View File

@@ -107,11 +107,26 @@ Dann verbindet sich die bestehende Bridge (`chatTcpBridge.js`) direkt mit `yourc
## Systemd (optional)
Es liegt eine Beispiel-Datei `yourchat2.service` im Projekt.
Nach Anpassung des User/Paths:
Es liegt eine Produktions-nahe Unit-Datei `yourchat2.service` im Projekt.
Zusaetzlich gibt es ein Installationsskript `install-systemd.sh`, das:
- Release-Binary baut
- Unit nach `/etc/systemd/system/yourchat2.service` installiert
- Environment-Datei unter `/etc/yourchat2/yourchat2.env` anlegt (falls nicht vorhanden)
- Service aktiviert und startet
Installation:
```bash
sudo cp yourchat2.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now yourchat2
cd ~/Programs/yourchat2
sudo ./install-systemd.sh
```
Danach Konfiguration ueber:
- `/etc/yourchat2/yourchat2.env`
Wichtige Variablen fuer produktiven Betrieb:
- `CHAT_DB_URL`
- `SECRET_KEY`

200
WEB_DIALOG_INTEGRATION.md Normal file
View File

@@ -0,0 +1,200 @@
# Web-Dialog Integration mit `yourchat2`
Diese Doku beschreibt, wie eine Web-Applikation den Chat-Dialog mit dem Daemon `yourchat2` verbindet.
Sie ist absichtlich auf das Protokoll und die Client-Integration fokussiert (ohne Betriebs-/Startanleitung).
## Verbindung
- Transport: WebSocket
- Standard-Endpunkt: `ws://<host>:1235`
- Nachrichtenformat: JSON (ein JSON-Objekt pro WebSocket-Frame)
## Verbindungs- und Login-Flow
1. WebSocket verbinden
2. `init` senden
3. Token (`type: 1`) aus der Antwort speichern
4. Alle weiteren auth-pflichtigen Commands mit `token` senden
### `init` Beispiel
```json
{
"type": "init",
"name": "alice_1",
"room": "lobby",
"password": ""
}
```
## Wichtige Antworttypen
- Token:
```json
{"type":1,"message":"<token>"}
```
- Raumliste:
```json
{"type":3,"message":[{"name":"lobby","users":2}]}
```
- Raum betreten / Status:
```json
{"type":5,"message":"room_entered","to":"lobby"}
```
- Chatnachricht:
```json
{"type":"message","userName":"alice","message":"Hallo","color":"#33aaee"}
```
- Fehler:
```json
{"type":"error","message":"invalid_token"}
```
## Commands (WebSocket JSON)
Nach erfolgreichem `init` (mit `token`):
- Nachricht senden
```json
{"type":"message","message":"Hallo zusammen","token":"..."}
```
- Raum wechseln
```json
{"type":"join","room":"sports","password":"","token":"..."}
```
- Räume abfragen
```json
{"type":"rooms","token":"..."}
```
- Userliste des aktuellen Raums
```json
{"type":"userlist","token":"..."}
```
- Farbe setzen
```json
{"type":"color","value":"#33aaee","token":"..."}
```
- Aktionen
```json
{"type":"scream","message":"Hallo alle","token":"..."}
{"type":"do","message":"winkt","token":"..."}
{"type":"dice","message":"1d6","token":"..."}
{"type":"roll","value":4,"token":"..."}
```
- Dice-Game
```json
{"type":"start_dice_game","rounds":3,"token":"..."}
{"type":"end_dice_game","token":"..."}
```
- Räume neu laden
```json
{"type":"reload_rooms","token":"..."}
```
## Slash-Commands im Dialogtext
Wenn das Frontend nur `type:"message"` sendet, werden folgende Slash-Kommandos serverseitig erkannt:
- `/join <room> [password]`
- `/color <hex>`
- `/dice [expr]`
- `/roll [wert]`
- `/start_dice_game <runden>`
- `/end_dice_game`
- `/reload_rooms`
- `/do <aktion>`
- `/scream <text>`
- `/rooms`
- `/userlist`
Beispiel:
```json
{"type":"message","message":"/join lounge geheim","token":"..."}
```
## Minimales Browser-Beispiel (Vanilla JS)
```javascript
const ws = new WebSocket("ws://127.0.0.1:1235");
let token = null;
ws.onopen = () => {
ws.send(JSON.stringify({
type: "init",
name: "alice_1",
room: "lobby",
password: ""
}));
};
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
if (msg.type === 1) {
token = msg.message;
return;
}
if (msg.type === "error") {
console.error("chat error:", msg.message);
return;
}
if (msg.type === "message") {
console.log(`${msg.userName}: ${msg.message}`);
return;
}
console.log("chat event:", msg);
};
function sendMessage(text) {
if (!token) return;
ws.send(JSON.stringify({ type: "message", message: text, token }));
}
```
## Häufige Fehlercodes
- `missing_name`: `init` ohne `name`
- `invalid_username`: Username entspricht nicht den Regeln
- `loggedin`: Username ist bereits aktiv
- `user_not_allowed`: User nicht erlaubt (DB/Allowlist)
- `not_initialized`: Command vor `init`
- `missing_token`: Token fehlt
- `invalid_token`: Token stimmt nicht
- `room_not_found_or_join_failed`: Raumzugriff verweigert (Passwort/Alter/Regeln)
- `permission_denied`: fehlende Rechte (z. B. Dice-Admin-Operationen)
## Hinweise für Frontend-Implementierung
- Token zentral im Chat-State halten
- Reconnect-Strategie einbauen (neues `init`, neues Token)
- Vor Senden auth-pflichtiger Commands Token prüfen
- UI sollte Fehler vom Typ `error` immer sichtbar machen
- Für Slash-Kommandos reicht normales `message`-Senden

60
install-systemd.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
set -euo pipefail
SERVICE_NAME="yourchat2"
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVICE_SRC="${PROJECT_DIR}/yourchat2.service"
SERVICE_DST="/etc/systemd/system/${SERVICE_NAME}.service"
ENV_DIR="/etc/yourchat2"
ENV_FILE="${ENV_DIR}/yourchat2.env"
BIN_PATH="${PROJECT_DIR}/target/release/yourchat2"
if [[ "${EUID}" -ne 0 ]]; then
echo "Dieses Skript muss als root ausgefuehrt werden (z. B. via sudo)." >&2
exit 1
fi
if [[ ! -f "${SERVICE_SRC}" ]]; then
echo "Service-Datei nicht gefunden: ${SERVICE_SRC}" >&2
exit 1
fi
echo "[1/6] Build release binary ..."
sudo -u torsten cargo build --release --manifest-path "${PROJECT_DIR}/Cargo.toml"
if [[ ! -x "${BIN_PATH}" ]]; then
echo "Binary wurde nicht erzeugt: ${BIN_PATH}" >&2
exit 1
fi
echo "[2/6] Install service file ..."
install -m 0644 "${SERVICE_SRC}" "${SERVICE_DST}"
echo "[3/6] Ensure environment directory ..."
install -d -m 0755 "${ENV_DIR}"
echo "[4/6] Ensure environment file ..."
if [[ ! -f "${ENV_FILE}" ]]; then
cat > "${ENV_FILE}" <<'EOF'
# yourchat2 environment
# CHAT_WS_ADDR=0.0.0.0:1235
# CHAT_TCP_ADDR=127.0.0.1:1236
# CHAT_UNIX_SOCKET=/run/yourchat2/yourchat2.sock
# CHAT_ALLOWED_USERS=alice,bob
# CHAT_DB_URL=postgres://user:pass@host:5432/dbname
# SECRET_KEY=replace-with-real-secret
EOF
chmod 0640 "${ENV_FILE}"
chown root:root "${ENV_FILE}"
fi
echo "[5/6] Reload and enable service ..."
systemctl daemon-reload
systemctl enable --now "${SERVICE_NAME}.service"
echo "[6/6] Service status ..."
systemctl --no-pager --full status "${SERVICE_NAME}.service" || true
echo
echo "Fertig. Konfiguration bei Bedarf in ${ENV_FILE} anpassen."
echo "Danach neu laden mit: systemctl restart ${SERVICE_NAME}.service"

View File

@@ -1,18 +1,25 @@
[Unit]
Description=yourchat2 Rust chat daemon
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=torsten
Group=torsten
WorkingDirectory=/home/torsten/Programs/yourchat2
EnvironmentFile=-/etc/yourchat2/yourchat2.env
Environment=CHAT_WS_ADDR=0.0.0.0:1235
Environment=CHAT_TCP_ADDR=127.0.0.1:1236
# Optional:
# Environment=CHAT_UNIX_SOCKET=/run/yourchat2/yourchat2.sock
RuntimeDirectory=yourchat2
RuntimeDirectoryMode=0750
ExecStart=/home/torsten/Programs/yourchat2/target/release/yourchat2
Restart=always
Restart=on-failure
RestartSec=2
TimeoutStopSec=15
LimitNOFILE=65535
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target