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:
25
README.md
25
README.md
@@ -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
200
WEB_DIALOG_INTEGRATION.md
Normal 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
60
install-systemd.sh
Executable 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"
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user