280 lines
6.6 KiB
Markdown
280 lines
6.6 KiB
Markdown
# Textpipe - SMS API Gateway
|
|
|
|
An Android app that turns your phone into an SMS API gateway with a web interface.
|
|
|
|
## Features
|
|
|
|
- **REST API** - Send and receive SMS via HTTP endpoints
|
|
- **Dual SIM Support** - Each SIM gets its own API key
|
|
- **Web UI** - Google Messages-like interface accessible from any browser
|
|
- **Local Database** - All messages stored locally with delivery tracking
|
|
- **Background Service** - Runs as a foreground service with persistent notification
|
|
- **Auto-start** - Optionally start on device boot
|
|
- **Root Support** - Bind directly to ports 80/443 with root access
|
|
|
|
## Requirements
|
|
|
|
- Android 7.0+ (API 24+)
|
|
- SMS permissions
|
|
- Phone state permissions (for dual SIM)
|
|
- (Optional) Root access for privileged ports
|
|
|
|
## Building
|
|
|
|
### Prerequisites
|
|
|
|
- Android Studio or command line with Android SDK
|
|
- JDK 11+
|
|
|
|
### Build Steps
|
|
|
|
1. **Clone the repository**
|
|
```bash
|
|
git clone https://git.shihaam.dev/shihaam/textpipe
|
|
cd textpipe
|
|
```
|
|
|
|
2. **Build the Android App**
|
|
```bash
|
|
./gradlew assembleDebug
|
|
```
|
|
The APK will be at `app/build/outputs/apk/debug/app-debug.apk`
|
|
|
|
3. **Install on device**
|
|
```bash
|
|
adb install app/build/outputs/apk/debug/app-debug.apk
|
|
```
|
|
|
|
### Release Build
|
|
|
|
```bash
|
|
./gradlew assembleRelease
|
|
```
|
|
|
|
Note: You'll need to configure signing in `app/build.gradle.kts` for release builds.
|
|
|
|
## Usage
|
|
|
|
### Initial Setup
|
|
|
|
1. Install and open the app
|
|
2. Grant all requested permissions (SMS, Phone, Notifications)
|
|
3. Note the API key(s) shown for each SIM card
|
|
4. Configure the port (default: 8080)
|
|
5. Tap "Start Server"
|
|
6. (Optional) Disable battery optimization for reliable background operation
|
|
|
|
### API Endpoints
|
|
|
|
Base URL: `http://<phone-ip>:<port>`
|
|
|
|
#### Status (No auth required)
|
|
```
|
|
GET /api/status
|
|
```
|
|
Returns server status and SIM information.
|
|
|
|
#### Send SMS
|
|
```
|
|
POST /api/sms/send
|
|
Header: X-API-Key: <your-api-key>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"to": "+1234567890",
|
|
"text": "Hello from Textpipe!"
|
|
}
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"status": "pending",
|
|
"simSlot": 0
|
|
}
|
|
```
|
|
|
|
#### List Messages
|
|
```
|
|
GET /api/sms/messages
|
|
Header: X-API-Key: <your-api-key>
|
|
```
|
|
|
|
Optional query parameter: `?type=sent` or `?type=received`
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"messages": [
|
|
{
|
|
"id": 1,
|
|
"type": "sent",
|
|
"address": "+1234567890",
|
|
"text": "Hello!",
|
|
"simSlot": 0,
|
|
"status": "delivered",
|
|
"timestamp": 1707148800000,
|
|
"deliveryTimestamp": 1707148805000
|
|
}
|
|
],
|
|
"total": 1
|
|
}
|
|
```
|
|
|
|
#### Get Message Status
|
|
```
|
|
GET /api/sms/status/{id}
|
|
Header: X-API-Key: <your-api-key>
|
|
```
|
|
|
|
### Authentication
|
|
|
|
Pass your API key in one of these ways:
|
|
- Header: `Authorization: Bearer <key>`
|
|
- Header: `X-API-Key: <key>`
|
|
- Query param: `?api_key=<key>`
|
|
|
|
Each SIM card has its own unique API key. The API key determines which SIM sends the message.
|
|
|
|
### Web Interface
|
|
|
|
Open `http://<phone-ip>:<port>/` in any browser to access the web UI.
|
|
|
|
1. Enter your API key to login
|
|
2. View conversations grouped by contact
|
|
3. Send new messages using the + button
|
|
4. Click on a conversation to view message thread
|
|
|
|
### cURL Examples
|
|
|
|
**Send SMS:**
|
|
```bash
|
|
curl -X POST http://10.0.1.12:8080/api/sms/send \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-Key: your-api-key-here" \
|
|
-d '{"to": "+1234567890", "text": "Hello!"}'
|
|
```
|
|
|
|
**Check status:**
|
|
```bash
|
|
curl http://10.0.1.12:8080/api/status
|
|
```
|
|
|
|
**List messages:**
|
|
```bash
|
|
curl -H "X-API-Key: your-api-key-here" \
|
|
http://10.0.1.12:8080/api/sms/messages
|
|
```
|
|
|
|
**Get specific message:**
|
|
```bash
|
|
curl -H "X-API-Key: your-api-key-here" \
|
|
http://10.0.1.12:8080/api/sms/status/1
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Port Configuration
|
|
|
|
- Default port: 8080
|
|
- Can be changed in the app UI
|
|
- For ports below 1024 (like 80 or 443), root access is required
|
|
- With root, the app uses sysctl to allow binding to privileged ports directly
|
|
|
|
### Auto-start
|
|
|
|
Enable "Auto-start on boot" in Settings to automatically start the server when the device boots.
|
|
|
|
### Battery Optimization
|
|
|
|
For reliable background operation, disable battery optimization for Textpipe:
|
|
1. Go to Settings in the app
|
|
2. Tap "Disable" next to Battery Optimization
|
|
3. Confirm in the system dialog
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
textpipe/
|
|
├── app/ # Android app
|
|
│ └── src/main/
|
|
│ ├── java/sh/sar/textpipe/
|
|
│ │ ├── MainActivity.kt
|
|
│ │ ├── TextpipeApplication.kt
|
|
│ │ ├── data/
|
|
│ │ │ ├── db/ # Room database
|
|
│ │ │ ├── model/ # API models
|
|
│ │ │ └── repository/ # Data repository
|
|
│ │ ├── server/ # Ktor HTTP server
|
|
│ │ │ ├── TextpipeServer.kt
|
|
│ │ │ ├── auth/ # API key auth
|
|
│ │ │ └── routes/ # API endpoints
|
|
│ │ ├── service/ # Android services
|
|
│ │ │ ├── TextpipeService.kt
|
|
│ │ │ ├── SmsSender.kt
|
|
│ │ │ ├── SmsReceiver.kt
|
|
│ │ │ └── BootReceiver.kt
|
|
│ │ ├── sim/ # SIM management
|
|
│ │ ├── root/ # Root utilities
|
|
│ │ └── ui/ # Compose UI
|
|
│ ├── assets/webui/ # Web UI (vanilla HTML/CSS/JS)
|
|
│ │ └── index.html
|
|
│ └── AndroidManifest.xml
|
|
├── gradle/
|
|
│ └── libs.versions.toml # Dependency versions
|
|
└── build.gradle.kts
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
### Android App
|
|
- Kotlin
|
|
- Jetpack Compose (UI)
|
|
- Ktor CIO (HTTP server)
|
|
- Room (Database)
|
|
- Kotlin Coroutines
|
|
- kotlinx.serialization (JSON)
|
|
|
|
### Web UI
|
|
- Vanilla HTML/CSS/JS (no build step required)
|
|
|
|
## Message Status Flow
|
|
|
|
```
|
|
pending → sent → delivered
|
|
↘ failed
|
|
```
|
|
|
|
- **pending** - Message queued, sending in progress
|
|
- **sent** - Message sent successfully
|
|
- **delivered** - Delivery confirmation received
|
|
- **failed** - Send failed
|
|
|
|
## Troubleshooting
|
|
|
|
### "Address already in use" error
|
|
The port is still bound from a previous instance. Either:
|
|
- Wait a few seconds and try again
|
|
- Change to a different port
|
|
- Force stop the app and restart
|
|
|
|
### Server doesn't start
|
|
- Check that no other app is using the port
|
|
- Verify all permissions are granted
|
|
- Check logcat for errors: `adb logcat -s TextpipeServer TextpipeService`
|
|
|
|
### Messages not sending
|
|
- Verify SMS permission is granted
|
|
- Check you have cellular signal
|
|
- Ensure the API key matches an active SIM
|
|
|
|
### Web UI not loading
|
|
- Verify the server is running (check app status)
|
|
- Check you're using the correct IP and port
|
|
- Try accessing `/api/status` directly
|
|
|
|
## License
|
|
|
|
MIT
|