Initial commit with Flutter and Node.js code

This commit is contained in:
Hamza-Ayed
2026-05-18 14:04:39 +03:00
commit a60a173b51
21 changed files with 3107 additions and 0 deletions

307
README.md Normal file
View File

@@ -0,0 +1,307 @@
# WhatsApp Mirror — Full-Stack Real-Time Bridge
A production-grade, highly-responsive WhatsApp Mirror application. This system allows you to remotely view and manage a WhatsApp account on a dark-themed Flutter mobile app (iOS + Android) by bridging commands and real-time events over a standalone WebSockets Node.js bridge server.
---
## 🏗️ Architecture
```
📱 Mobile Client (Flutter) ⚡ [WebSockets Protocol] ⚡ 🖥️ standalone Backend Server (Node.js) ⚙️ [Puppeteer] ⚙️ 🟩 WhatsApp Web (LocalAuth Session)
```
---
## 📂 Project Structure
```
whatsapp-app/
├── README.md ← Full system configuration & documentation
├── whatsapp_bridge/ ← standalone Node.js server
│ ├── package.json ← Package dependencies (whatsapp-web.js, ws, qrcode, express)
│ ├── server.js ← Bridge server entrypoint (Port 3025)
│ └── .wwebjs_auth/ ← Session persistence auth cache (git-ignored)
└── whatsapp_app/ ← Dark-themed Flutter Client
├── pubspec.yaml ← Flutter configuration and plugins
└── lib/
├── main.dart ← Flutter app entry point (GetX service initializer)
├── config/
│ └── app_config.dart ← Server host & port variables
├── theme/
│ └── app_theme.dart ← WhatsApp-style immersive Dark Theme
├── services/
│ └── whatsapp_service.dart ← Websocket request/response manager
├── models/
│ ├── conversation_model.dart
│ └── message_model.dart
├── controllers/
│ ├── conversations_controller.dart
│ └── chat_controller.dart
├── screens/
│ ├── conversations_screen.dart
│ ├── chat_screen.dart
│ └── qr_screen.dart
└── widgets/
├── conversation_tile.dart
└── message_bubble.dart
```
---
## ⚡ WebSockets Protocol Specification
To handle asynchronous requests and map them back to specific UI components or triggers, a strict **Request-Response ID matching mechanism** is implemented.
### 1. Client-to-Server Requests
Every request from the Flutter client MUST contain a unique `requestId`. The server replies with the exact same `requestId`.
#### A. Ping Check (`ping`)
* **Request:**
```json
{ "type": "ping", "requestId": "1" }
```
* **Response:**
```json
{ "type": "pong", "ready": true, "requestId": "1" }
```
#### B. Get Conversation List (`get_conversations`)
* **Request:**
```json
{ "type": "get_conversations", "limit": 50, "offset": 0, "requestId": "2" }
```
* **Response:**
```json
{
"type": "conversations",
"data": [
{
"id": "1234567890@c.us",
"name": "Jane Doe",
"isGroup": false,
"unreadCount": 2,
"avatar": "https://pps.whatsapp.net/v/...",
"lastMessage": {
"body": "Hello there!",
"timestamp": 1716035000,
"fromMe": false,
"hasMedia": false
},
"timestamp": 1716035000,
"pinned": false,
"isMuted": false
}
],
"total": 1,
"requestId": "2"
}
```
#### C. Get Message History (`get_messages`)
* **Request:**
```json
{ "type": "get_messages", "chatId": "1234567890@c.us", "limit": 50, "requestId": "3" }
```
* **Response:**
```json
{
"type": "messages",
"chatId": "1234567890@c.us",
"data": [
{
"id": "true_1234567890@c.us_ABC123",
"body": "Hello there!",
"fromMe": false,
"timestamp": 1716035000,
"type": "chat",
"hasMedia": false,
"isForwarded": false,
"author": null,
"ack": 4
}
],
"requestId": "3"
}
```
#### D. Send Message (`send_message`)
* **Request:**
```json
{ "type": "send_message", "chatId": "1234567890@c.us", "text": "Hello!", "requestId": "4" }
```
* **Response:**
```json
{
"type": "message_sent",
"chatId": "1234567890@c.us",
"data": {
"id": "true_1234567890@c.us_XYZ987",
"body": "Hello!",
"fromMe": true,
"timestamp": 1716035005,
"type": "chat",
"hasMedia": false,
"isForwarded": false,
"author": null,
"ack": 1
},
"requestId": "4"
}
```
#### E. Mark Chat as Read (`mark_read`)
* **Request:**
```json
{ "type": "mark_read", "chatId": "1234567890@c.us", "requestId": "5" }
```
* **Response:**
```json
{ "type": "marked_read", "chatId": "1234567890@c.us", "requestId": "5" }
```
#### F. Search Conversations (`search_conversations`)
* **Request:**
```json
{ "type": "search_conversations", "query": "Jane", "requestId": "6" }
```
* **Response:**
```json
{
"type": "conversations",
"data": [...],
"search": true,
"requestId": "6"
}
```
---
### 2. Server-to-Client Push Events
The server broadcasts live events to all connected clients immediately.
* **QR Code Broadcast:**
```json
{ "type": "qr", "qr": "data:image/png;base64,iVBORw0KGgo..." }
```
* **Authenticated:**
```json
{ "type": "authenticated" }
```
* **Client Ready:**
```json
{ "type": "ready" }
```
* **Status Updates:**
```json
{ "type": "status", "ready": true }
```
* **Client Disconnected:**
```json
{ "type": "disconnected", "reason": "Session expired or logged out" }
```
* **New Incoming Message:**
```json
{
"type": "new_message",
"chatId": "1234567890@c.us",
"data": {
"id": "false_1234567890@c.us_DEF456",
"body": "Live incoming text!",
"fromMe": false,
"timestamp": 1716035100,
"type": "chat",
"hasMedia": false,
"isForwarded": false,
"author": null,
"ack": 2
}
}
```
* **Message Delivery / Read Receipt (`message_ack`):**
```json
{
"type": "message_ack",
"messageId": "true_1234567890@c.us_XYZ987",
"chatId": "1234567890@c.us",
"ack": 4
}
```
*(Ack codes: 0 = Error/None, 1 = Pending, 2 = Sent, 3 = Delivered, 4 = Read)*
---
## 🚀 Quick Setup & Installation
### 1. Server Setup (`whatsapp_bridge/`)
Navigate into the backend project, install dependencies, and start the standalone service:
```bash
cd whatsapp_bridge
npm install
node server.js
```
The server will boot up and bind to **Port 3025**. It will automatically print:
`[SERVER] Standalone WhatsApp Bridge running on port 3025`
### 2. Flutter App Setup (`whatsapp_app/`)
First, ensure that you have created the Flutter project structure using standard platform templates:
```bash
# Run this inside the workspace directory
flutter create whatsapp_app
```
Then, copy all files in `whatsapp_app/` into the newly created project folder. Open the folder and install Dart packages:
```bash
cd whatsapp_app
flutter pub get
```
#### Run on Simulator / Device
```bash
flutter run
```
---
## 🌐 Production Deployment (CloudPanel Server)
Since this backend server acts as a standalone daemon and does not conflict with existing apps, it operates exclusively on **Port 3025**.
### 1. Create Node.js Site in CloudPanel
1. Navigate to **CloudPanel Admin Portal** -> **Sites** -> **Add Site** -> **Create a Node.js Application**.
2. Set Domain Name: `mywhatsappapp.interlap.com` (or your subdomain).
3. Set Port: `3025`.
4. Set Entry Point: `server.js`.
5. Select Node.js Version: `18+ LTS` (or Node 20 LTS).
### 2. Bypass Nginx Reverse Proxy
By default, CloudPanel routes external traffic from Port 80/443 through an Nginx reverse proxy. For our standalone WebSockets configuration, we want direct access.
Make sure to open **Port 3025** on your firewall (e.g. AWS Security Group or UFW):
```bash
sudo ufw allow 3025/tcp
```
This isolates Node.js directly on port 3025.
### 3. Keep Server Alive with PM2
We highly recommend running your Node.js application inside PM2 to ensure it auto-reconnects, logs diagnostic crashes, and recovers seamlessly:
```bash
# Install PM2 globally
npm install -g pm2
# Start the bridge server
pm2 start server.js --name "whatsapp-bridge"
# Persist server launch on reboot
pm2 save
pm2 startup
```
---
## 🔒 Security & Performance Features
* **Session Persistence:** Configured using `whatsapp-web.js`'s built-in `LocalAuth` session strategies, meaning that once you scan the QR code once, you will not have to scan it again unless explicitly logged out.
* **Resilience & Crash Prevention:** The server wraps critical events in structured `try/catch` clauses and binds events to `process.on('uncaughtException')`, protecting the server from unexpected Puppeteer execution crashes.
* **Auto-Reconnection:** If WhatsApp Web loses connection or the user logs out, the server attempts re-initialization automatically after a 5-second backoff delay.
* **Dark Mode Design:** Beautiful custom-tailored dark theme matching official WhatsApp guidelines (`#111B21`, `#1F2C34`, `#00A884`) with full custom ripple alerts, status badges, and tick indicators.