Files
2026-07-07 14:18:49 +03:00

141 lines
4.3 KiB
Markdown

# QMAX
QMAX is a private Android messenger client backed by a personal bridge server. The Android app talks to your QMAX server, and the server uses PyMax as the only MAX bridge.
Current shape:
- `server/QMax.Api` - ASP.NET Core API, SQLite cache, JWT pairing auth, SignalR hub, attachment storage, APK update catalog.
- `pymax-worker` - Python/PyMax worker with a persistent MAX mobile API session.
- `android` - Kotlin + Jetpack Compose Android client pointed at `https://qmax.kusoft.xyz`.
- `deploy` - Docker Compose + Caddy for Raspberry Pi 5.
## Local Checks
```powershell
dotnet test QMax.slnx
python -m py_compile pymax-worker/src/server.py
cd android
.\gradlew.bat :app:assembleDebug :app:assembleRelease --console=plain --no-daemon
```
## Raspberry Pi Deployment
1. Point DNS `qmax.kusoft.xyz` to the Raspberry Pi public IP.
2. Install Docker Engine and the Docker Compose plugin on the Pi.
3. Copy the repository or the archive produced by `scripts/deploy-rpi.ps1`.
4. On the Pi:
```bash
cd ~/qmax/deploy
cp .env.example .env
nano .env
docker compose up -d --build
```
This compose publishes QMAX API on `127.0.0.1:18080`. The existing system Caddy should contain:
```caddy
qmax.kusoft.xyz {
encode zstd gzip
reverse_proxy 127.0.0.1:18080
}
```
Set strong values in `.env`:
- `QMAX_JWT_SECRET` - at least 32 random characters.
- `QMAX_PAIRING_CODE` - one-time-ish pairing password for your Android client and `/admin/max`.
- `QMAX_MAX_PHONE_NUMBER` - the phone number linked to the MAX account used by PyMax.
Secrets must stay in `.env`, not in git.
## MAX Login
Open:
```text
https://qmax.kusoft.xyz/admin/max?pairingCode=YOUR_PAIRING_CODE
```
Use **Start phone login**. When MAX sends the confirmation code, submit it on the same page or from the Android app settings.
The worker stores PyMax session state in the `qmax-pymax-session` Docker volume, so the MAX session should survive restarts until MAX expires the login token.
## Android Pairing
Build or install:
```powershell
cd android
.\gradlew.bat :app:assembleRelease --console=plain --no-daemon
```
On first launch:
- Server: `https://qmax.kusoft.xyz`
- Code: `QMAX_PAIRING_CODE` from `.env`
The first screen after pairing is the chat list.
## APK Update Catalog
Create a release package:
```powershell
.\scripts\package-android-release.ps1 -Version 0.1.4 -VersionCode 5
```
The compose file mounts `deploy/releases` as `/data/releases`, so files generated by the packaging script are served automatically after `docker compose up -d`. The server exposes:
```text
GET /api/app-updates/android/latest
GET /api/app-updates/android/download/{fileName}
```
Use one stable release key for production APKs. Do not install a new APK signed by a different key over an already installed QMAX app.
## Push Notifications
The server has an FCM HTTP v1 dispatcher. To enable real push delivery on the Raspberry Pi, put a Firebase service account JSON under `deploy/secrets/` and set:
```dotenv
QMAX_FIREBASE_PROJECT_ID=qmax-29df6
QMAX_FIREBASE_SERVICE_ACCOUNT_PATH=/run/secrets/qmax/firebase-service-account.json
```
The Android app registers its FCM token after pairing. It uses the Google Services Gradle plugin with `android/app/google-services.json` for the package `xyz.kusoft.qmax`. `FirebaseBootstrap` still supports asset-based `firebase.android.json` or `google-services.json` as a fallback for custom local builds.
## Argus Publication
QMAX is published in Argus with:
- base URL: `https://argus.kusoft.xyz`
- slug: `qmax`
- platform: `android`
- channel: `stable`
Manifest:
```text
https://argus.kusoft.xyz/api/apps/qmax/manifest?platform=android&channel=stable
```
Latest APK:
```text
https://argus.kusoft.xyz/api/apps/qmax/download/latest?platform=android&channel=stable
```
The Android app checks this manifest, compares semantic versions, downloads the APK to a temporary file, verifies SHA-256, and only then opens Android's package installer.
## Current MAX Mapping Status
The deployed worker is authorized through PyMax and currently maps:
- chat list and message history through PyMax;
- text sending through PyMax;
- attachment upload through PyMax file/photo/video models;
- image, video, file and voice attachment projection through the API;
- Android image attachment caching with `.part` downloads before a file is shown from local storage;
- explicit session status and phone-code re-login from Android settings.