MLK DVR Receiver is an internal Android SMS receiver backed by a small Node.js service and a Telegram bot. It detects Divar verification messages, submits the extracted six-digit code over HTTPS, and delivers it privately to the authorized requester without exposing it in the group.
- A user sends
/code 09xxxxxxxxxfor a registered number in the active Telegram group. - The bot opens a two-minute session after confirming that it can message the requester privately.
- The Android app detects the Divar SMS and queues the code for backend delivery.
- The backend matches the receiving number to one active session.
- The requester receives the code privately; the group receives only a delivery confirmation.
If no matching code arrives within two minutes, the requester and the original group message are notified that the session expired.
A short walkthrough of the setup and usage of MLK DVR Receiver.
| Component | Responsibility |
|---|---|
| Android app | Receives matching SMS messages and reliably submits extracted codes |
| Express backend | Validates requests, manages sessions and audit history, and routes Telegram messages |
| Telegram bot | Accepts group commands and delivers codes privately |
The Android app never contains the Telegram bot token or calls the Telegram API directly.
- Node.js 22 and npm 10
- JDK 17 and Android SDK 35
- A Telegram bot added to the intended groups
- A public HTTPS endpoint for the backend
Copy backend/.env.example to backend/.env and provide:
TELEGRAM_BOT_TOKENAPP_SECRETAPP_MODE(devorproduct)TELEGRAM_DEV_GROUP_IDTELEGRAM_PRODUCT_GROUP_IDPUBLIC_BASE_URL
APP_MODE selects one active Telegram group and an isolated set of session and phone files. Changing the mode requires restarting the backend and rebuilding the Android app.
Start the service:
Set-Location backend
npm ci
npm startGET /health returns {"status":"ok"}. See the deployment guide for Docker, persistent storage, HTTPS, webhook registration, updates, and backups.
The build reads PUBLIC_BASE_URL, APP_SECRET, and APP_MODE from backend/.env. The corresponding RECEIVER_BACKEND_URL, RECEIVER_APP_SECRET, and RECEIVER_APP_MODE Gradle properties or environment variables take precedence.
Build a debug APK:
.\gradlew.bat assembleDebugSigned release builds use the ignored root-level signing.properties file:
storeFile=<path-to-keystore>
storePassword=<store-password>
keyAlias=<key-alias>
keyPassword=<key-password>.\gradlew.bat assembleReleaseKeep the release keystore private and backed up. Losing it prevents future in-place updates. Short local build and install commands are available in docs/commands.md.
- Install and open the APK.
- Enter one or two receiver numbers in
09xxxxxxxxxformat; their order does not matter. - Turn Status on and grant incoming/read SMS access.
- Complete the Background readiness checks, including Autostart and unrestricted battery usage on Xiaomi-family devices.
- Save the configuration and use TEST AND SEND to verify the backend and register the numbers.
The receiver restores pending work after reboot or app update. Android force-stop, revoked permissions, OEM restrictions, or a disconnected phone can still prevent delivery.
| Command | Scope | Description |
|---|---|---|
/start |
Private chat or group | Registers the conversation |
/code 09xxxxxxxxx |
Active group | Opens a two-minute code session |
/get_phone |
Active group | Shows registered numbers and usage statistics |
/opt_out 09xxxxxxxxx |
Active group | Removes a number and its counters |
/group_id |
Any group | Returns the current Telegram group ID |
Before requesting a code, each user must open the bot privately and press Start once. Commands also support Telegram's bot suffix, such as /code@BotUsername 09901283916.
- Android API requests require matching
X-App-SecretandX-App-Modeheaders. - Codes are delivered only in private chat and never posted in the group.
- The app sends only the extracted code and configured candidate phone numbers, not the complete SMS body or sender.
- Pending deliveries are persisted locally, require network access, retry transient failures, and expire after one minute.
- Recent matching messages can be recovered from the Inbox when
READ_SMSis granted; fingerprints suppress duplicate submissions. - Ambiguous matches are not delivered when more than one candidate has an active session.
- OTP values are never retained in backend audit history.
- Runtime data,
.env, signing properties, and keystores are excluded from Git.
Audit history can contain phone numbers and Telegram identities and is not pruned automatically. Protect the backend data directory and its backups. The shared app secret is embedded in the APK and should not be treated as unextractable.
Backend tests use a mocked Telegram client and do not send real messages:
Set-Location backend
npm testRun Android tests, lint, and both builds from the repository root:
.\gradlew.bat testDebugUnitTest testReleaseUnitTest lintDebug lintRelease assembleDebug assembleRelease

