2026-07-07 14:35:26 +03:00
2026-07-07 14:35:26 +03:00
2026-07-07 14:18:49 +03:00
2026-07-07 14:18:49 +03:00
2026-07-07 14:18:49 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-03 22:39:48 +03:00
2026-07-07 14:18:49 +03:00
2026-07-03 22:39:48 +03:00

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

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:
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:

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:

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:

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:

.\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:

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:

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:

https://argus.kusoft.xyz/api/apps/qmax/manifest?platform=android&channel=stable

Latest APK:

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.
S
Description
No description provided
Readme 186 MiB
Languages
C# 51.1%
Kotlin 42.9%
Python 5.3%
PowerShell 0.6%