# Migracja: „working copy" → „prototype"

Runbook upgrade'u działającego deploymentu bota (Raspberry Pi) z wersji
**working copy** (kod w roocie repo, bez auth między usługami, bez integracji
Conan) na wersję **prototype** (konfiguracja przez zmienne środowiskowe,
opcjonalna autoryzacja wewnętrznych wywołań HTTP, integracja Conan Exiles).

> **Najważniejsze:** upgrade jest **wstecznie kompatybilny**. Bez ustawiania
> żadnych nowych zmiennych bot działa tak jak dotąd — istniejące tokeny z
> `~/.netrc` i domyślne ścieżki są zachowane. Wszystkie nowe funkcje
> (autoryzacja API, most Conan, powiadomienia o graczach) są **opt-in**.

---

## 0. Status / warunek wstępny

Pełny kod prototype znajduje się obecnie na branchu **`proto-improvements`**.
Na `main` jest na razie sama restrukturyzacja (working copy w roocie). Zanim
zmigrujesz produkcję z `main`, zmerguj prototype do `main`
(`proto-improvements` → `main`) albo deployuj bezpośrednio z brancha
`proto-improvements`. Dalsza część zakłada, że prototype jest już dostępny pod
refem, który checkoutujesz w kroku 2.

**Układ deploymentu (bez zmian):**

| | Ścieżka |
|---|---|
| Klon repo | `/home/pi/conjurer` |
| Runtime bota | `/home/pi/Conjurer` |
| Virtualenv | `/home/pi/Conjurer/env` (używany przez `conjurer.service`) |
| Usługa systemd | `conjurer.service` → `ExecStart … /home/pi/Conjurer/bot.py` |
| Deploy | `deploy.sh` (kopiuje pliki z repo do runtime i restartuje usługę) |

---

## 1. Backup i punkt powrotu

```bash
# zapamiętaj aktualny commit (do ewentualnego rollbacku)
git -C /home/pi/conjurer rev-parse HEAD > /home/pi/conjurer_rollback_commit.txt

# snapshot runtime (config + dane)
sudo cp -a /home/pi/Conjurer /home/pi/Conjurer.bak.$(date +%Y%m%d_%H%M%S)
```

Sekrety nadal pochodzą z `~/.netrc` (Discord/OpenAI/Spotify/YouTube) — upewnij
się, że ten plik istnieje i jest aktualny. Migracja go nie dotyka.

---

## 2. Pobranie kodu prototype

```bash
cd /home/pi/conjurer
git fetch --all
git checkout main && git pull          # gdy prototype jest już w main
# albo, do czasu merge:  git checkout proto-improvements && git pull
```

---

## 3. Instalacja nowych zależności

Wersja prototype dodaje do `requirements_bot.txt` dwa pakiety używane przez most
Conan: **`aiomcrcon`** i **`asyncssh`**.

```bash
source /home/pi/Conjurer/env/bin/activate
python3 -m pip install -r /home/pi/conjurer/requirements_bot.txt
deactivate
```

> Nawet bez tych pakietów bot się uruchomi — importy w module Conan są osłonięte
> (`try/except ImportError`), a integracja pozostaje uśpiona. Instalacja jest
> potrzebna tylko jeśli faktycznie używasz mostu Conan.

---

## 4. (Opcjonalnie) Konfiguracja zmiennych środowiskowych

Wersja prototype czyta konfigurację ze zmiennych środowiskowych z fallbackiem na
dotychczasowe wartości. **Pomiń ten krok dla zwykłego upgrade'u** — domyślne
ścieżki i `~/.netrc` wystarczą. Ustaw zmienne tylko gdy włączasz nową funkcję.

### 4a. Plik środowiskowy dla systemd

```bash
sudo tee /home/pi/Conjurer/conjurer.env >/dev/null <<'EOF'
# --- Autoryzacja wewnętrznych wywołań HTTP (opcjonalne) ---
# Ten sam klucz MUSI być ustawiony na bocie, musicianie i librarianie.
CONJURER_API_KEY=

# --- Adresy usług wewnętrznych (domyślne wartości jak dotąd) ---
#CONJURER_FILE_SERVICE=http://192.168.1.15:5000
#CONJURER_RADIO_HARBOR=http://192.168.1.15:54321
#CONJURER_LIBRARIAN_SERVICE=http://192.168.1.192:5001

# --- Most Conan Exiles (opcjonalne; puste = wyłączone) ---
#CONAN_GM_ROLE_ID=0
#CONAN_RCON_HOST=
#CONAN_RCON_PORT=25575
#CONAN_RCON_PASSWORD=
#CONAN_CHAT_CHANNEL_ID=0
#CONAN_EVENTS_CHANNEL_ID=0
# Powiadomienia o wejściu gracza — ustaw id kanału, by włączyć:
#CONAN_JOIN_CHANNEL_ID=0
#CONAN_PLAYER_POLL_SECONDS=60
#CONAN_LOG_MODE=local
#CONAN_LOG_PATH=
EOF
sudo chmod 600 /home/pi/Conjurer/conjurer.env
```

### 4b. Podłączenie pliku do usługi

Dodaj `EnvironmentFile` do sekcji `[Service]` w `conjurer.service`
(`/etc/systemd/system/conjurer.service`):

```ini
[Service]
Type=simple
EnvironmentFile=/home/pi/Conjurer/conjurer.env
ExecStart=/home/pi/Conjurer/env/bin/python3 /home/pi/Conjurer/bot.py
Restart=on-abort
```

```bash
sudo systemctl daemon-reload
```

> `conjurer.service` w repo również warto zaktualizować o tę linię, ale `deploy.sh`
> **nie** nadpisuje jednostki systemd przy każdym deployu — wpis robisz raz, ręcznie.

---

## 5. Deploy i restart

```bash
cd /home/pi/conjurer
./deploy.sh        # kopiuje m.in. bot.py oraz conanjurer_commands/_functions.py do runtime
```

`deploy.sh` na końcu sam wykonuje `systemctl restart conjurer.service`. Jeśli
zmieniałeś jednostkę systemd w kroku 4b, wcześniej zrób `daemon-reload`.

---

## 6. Weryfikacja

```bash
journalctl -u conjurer.service -f
```

Czego szukać w logu (`/home/pi/Conjurer` → plik logu również):

- `Loading … module done` dla kolejnych rozszerzeń, w tym **`Loading conanjurer commands module done`**
- Gdy most Conan nieskonfigurowany: `Conan: log watch disabled (not configured)`
  oraz `Conan: player-join notifications disabled (no channel or RCON)` — to
  oczekiwane, integracja jest uśpiona
- `All systems: operational`

Szybki test funkcjonalny: bot łączy się z Discordem, dotychczasowe komendy
działają, radio/biblioteka odpowiadają jak wcześniej.

---

## 7. Zmiany zachowania, o których warto wiedzieć

| Obszar | Working copy | Prototype |
|---|---|---|
| Konfiguracja | zahardkodowana per-platforma | env-vary z fallbackiem na stare wartości |
| Tokeny | tylko `~/.netrc` | env-var → fallback `~/.netrc` (stare działa) |
| Wewnętrzne HTTP (music/radio/librarian) | bez nagłówków | wysyła `X-Conjurer-Api-Key`, **gdy** `CONJURER_API_KEY` ustawione |
| Endpointy przychodzące bota | bez weryfikacji | `_authorize_request()` zwraca 401 przy złym kluczu (no-op gdy klucz pusty) |
| Pętla bota | wątki + `join()` | pojedyncza pętla asyncio z czystym shutdownem |
| Moduł Conan | obecny, **nieładowany** (miał SyntaxError) | naprawiony i ładowany; uśpiony bez konfiguracji |

---

## 8. Włączanie funkcji opcjonalnych

### 8a. Autoryzacja wewnętrznych wywołań HTTP
Ustaw **ten sam** `CONJURER_API_KEY` na **wszystkich** usługach: bocie,
musicianie (`conjurer_musician`) i librarianie. Po ustawieniu:
- bot dokleja nagłówek do wywołań do file-service/radia/biblioteki,
- usługi odrzucają (401) żądania bez poprawnego klucza.

⚠️ Ustawienie klucza tylko po jednej stronie zepsuje komunikację (401). Albo
wszędzie, albo nigdzie.

### 8b. Most Conan Exiles
Ustaw `CONAN_RCON_HOST` + `CONAN_RCON_PASSWORD` (komendy GM `say/players/kick/
rcon/ogłoś`) oraz, dla mirrorowania czatu/zdarzeń, `CONAN_LOG_PATH`
(+ `CONAN_CHAT_CHANNEL_ID`/`CONAN_EVENTS_CHANNEL_ID`).

### 8c. Powiadomienia o wejściu gracza
Ustaw **`CONAN_JOIN_CHANNEL_ID`** na id kanału Discord. Funkcja odpytuje RCON
`listplayers` co `CONAN_PLAYER_POLL_SECONDS` i ogłasza nowych graczy. Pozostaw
`0`, aby trzymać ją wyłączoną.

---

## 9. Rollback

```bash
cd /home/pi/conjurer
git checkout "$(cat /home/pi/conjurer_rollback_commit.txt)"
./deploy.sh
sudo systemctl restart conjurer.service
```

W razie potrzeby przywróć snapshot runtime z `/home/pi/Conjurer.bak.*`. Nowe
zależności (`aiomcrcon`, `asyncssh`) mogą zostać w venv — nie przeszkadzają
starszej wersji.

---

## 10. Migracja usługi musician (jeśli prowadzisz radio)

Stabilny wariant `musician_old` (zahardkodowane adresy) został zastąpiony przez
`conjurer_musician` (env-driven, domyślnie `127.0.0.1`). Jeśli bot i musician są
na **różnych** hostach, ustaw na musicianie:

```bash
CONJURER_MAIN_BOT=http://<ip-bota>:5000      # gdzie bot serwuje /prepped_tracks
CONJURER_API_KEY=<ten sam sekret co bot>     # jeśli włączasz auth (8a)
CONJURER_MUSIC_FOLDER=/home/pi/MediaShare/mp3
```

oraz na bocie `CONJURER_FILE_SERVICE=http://<ip-musiciana>:5000`. Szczegóły
auth/kontraktu — patrz opis usługi `conjurer_musician`.
