Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ API_HASH=
OWNER_ID=

BOT_TOKEN=
BOT_USERNAME= # without @
# Optional: bot username without @. Usually auto-fetched from BOT_TOKEN.
BOT_USERNAME=

MONGO_URI=
DB_NAME=Ether
SESSION_NAME=etheruserbot

DEBUG=False
WEB_SERVICE=False
PORT=8080
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
worker: python3 main.py
worker: python main.py
139 changes: 102 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,21 @@ Ether uses environment variables for configuration. These can be set in a `.env`
| :--- | :--- | :--- |
| `API_ID` | Required | Your Telegram API ID from [my.telegram.org](https://my.telegram.org) |
| `API_HASH` | Required | Your Telegram API Hash from [my.telegram.org](https://my.telegram.org) |
| `BOT_TOKEN` | Required | Your Bot Token from [@BotFather](https://t.me/BotFather) |
| `OWNER_ID` | Required | Your numeric Telegram User ID |
| `BOT_TOKEN` | Required | Your Bot Token from [@BotFather](https://t.me/BotFather) |
| `MONGO_URI` | Required | MongoDB Atlas connection string |
| `BOT_USERNAME` | Required | Your Bot's username (without @) |
| `BOT_USERNAME` | Optional | Auto-fetched from `BOT_TOKEN`; set manually only if needed |
| `SESSION_NAME` | Optional | MongoDB session document name (Default: `etheruserbot`) |
| `DB_NAME` | Optional | Database name (Default: `Ether`) |
| `DEBUG` | Optional | Set to `true` for verbose logging (Default: `false`) |
| `WEB_SERVICE` | Optional | Set to `true` for cloud keep-alive services |
| `PORT` | Optional | Port for the web service (Default: `8080`) |
| `WEB_SERVICE` | Optional | Set to `true` when the host requires an HTTP health endpoint |
| `PORT` | Optional | Port for the web service (Default: `8080`; Render uses `10000`) |

---

## Deployment Options

Ether is designed to be deployed anywhere. Choose the platform that fits your needs.
Ether is a long-running Telegram client. For reliable operation, use a host that allows long-lived processes and provide a persistent MongoDB database for sessions and settings.

<div align="center">

Expand All @@ -126,59 +127,108 @@ Ether is designed to be deployed anywhere. Choose the platform that fits your ne

</div>

### Deployment Matrix

| Target | Files Used | Runtime Type | How to Verify |
| :--- | :--- | :--- | :--- |
| Render | `render.yaml`, `Dockerfile` | Docker web service | HTTP health check at `/health` |
| Heroku | `app.json`, `heroku.yml`, `Dockerfile` | Container worker dyno | Worker logs and Telegram `/login` |
| Docker Compose / VPS | `docker-compose.yml`, `Dockerfile` | Local Docker service | `docker compose config` and `/health` |
| Manual Python | `requirements.txt`, `main.py` | Local Python process | Import and compile checks |
| JustRunMyApp / Generic Docker Host | `Dockerfile` | Long-running Docker container | Same env vars and health endpoint rules as Docker |

### Quick Start Guides

#### 1. Cloud Hosting (Render - Recommended)
Render provides the most stable environment for Ether with native Docker support.
Render should be deployed as a Docker **Web Service** because Render requires web services to bind an HTTP port.

1. **Fork** this repository to your own GitHub account.
2. Click the **Deploy to Render** button above.
3. Connect your GitHub account and select the forked repository.
4. Configure the **Environment Variables** (see [Configuration](#configuration)).
* **Crucial:** Ensure `WEB_SERVICE` is set to `true` to prevent the service from sleeping.
5. Render will automatically build and deploy the container.
4. Use the checked-in `render.yaml` blueprint:
* Runtime: `docker`
* Dockerfile: `./Dockerfile`
* Health check path: `/health`
* `PORT=10000`
* `WEB_SERVICE=true`
5. Set the required environment variables from [Configuration](#configuration).
6. Deploy, then open:
```text
https://your-app.onrender.com/health
```
Expected response:
```json
{"status":"healthy"}
```
7. Open your Telegram bot and run `/login`.

> [!IMPORTANT]
> Render Free web services sleep after idle periods and can restart at any time. The HTTP endpoint keeps the deploy valid, but it does not make the free plan always-on. Use a paid Render instance, VPS, or another always-on host for a 24/7 userbot.

---

### Keep-Alive & Automation (Cloud)

Cloud providers like Render often put free-tier apps to "sleep" after inactivity. Use these tools to ensure Ether stays online 24/7.
Cloud providers often put free-tier apps to sleep after inactivity. External monitors can reduce idle sleep, but a paid always-on service or VPS is the more reliable option for a 24/7 userbot.

#### UptimeRobot (Keep-Alive)
To prevent Render from sleeping, set up a monitor to ping your bot's URL:
To keep a Render web service receiving inbound HTTP traffic, set up a monitor to ping the health endpoint:
1. Go to [UptimeRobot](https://uptimerobot.com/) and create a free account.
2. Click **Add New Monitor**.
3. **Monitor Type**: `HTTP(s)`
4. **Friendly Name**: `Ether Userbot`
5. **URL**: Your Render app URL (e.g., `https://your-app.onrender.com/`)
5. **URL**: `https://your-app.onrender.com/health`
6. **Monitoring Interval**: Every `5 minutes`.
7. Click **Create Monitor**.

#### Cron-job.org (Scheduled Tasks)
If you need to trigger specific bot actions or ensure the web service remains active via external triggers:
1. Create an account at [Cron-job.org](https://cron-job.org/).
2. Create a **New Cronjob**.
3. **URL**: Your Render app URL.
3. **URL**: `https://your-app.onrender.com/health`
4. **Schedule**: Every 5 or 10 minutes.
5. This acts as a secondary heart-beat for your bot.

---

#### 2. Heroku Deployment
Ideal for users familiar with the Heroku ecosystem.
Heroku should be deployed as a container **worker** dyno. Do not run a web dyno unless you add a separate web process.

1. Click the **Deploy to Heroku** button above.
2. Enter a unique app name and fill in the required environment variables.
3. Once the build finishes, go to the **Resources** tab.
4. **Important:** Turn off the `web` dyno and turn **ON** the `worker` dyno.
5. Render will automatically build and deploy the container.
4. Confirm the `worker` dyno is enabled and the `web` dyno is disabled.
5. Set `WEB_SERVICE=false` for worker-only Heroku deployments.
6. Check logs:
```bash
heroku logs --tail --ps worker -a your-app-name
```
7. Open your Telegram bot and run `/login`.

CLI deployment:
```bash
heroku create your-app-name
heroku stack:set container -a your-app-name
heroku config:set API_ID=... API_HASH=... OWNER_ID=... BOT_TOKEN=... MONGO_URI=... WEB_SERVICE=false -a your-app-name
git push heroku main
heroku ps:scale web=0 worker=1 -a your-app-name
```

> [!NOTE]
> Heroku no longer has free dynos. Use a paid dyno type appropriate for a long-running worker.

---

#### 3. JustRunMyApp (One-Click)
A simple, zero-config deployment platform.
Use this path only if the platform supports long-running Docker containers and runtime environment variables.

1. Click the **Deploy Now** button for JustRunMyApp above.
2. Paste the repository URL: `https://github.com/LearningBotsOfficial/Ether`
3. Follow the on-screen prompts to set your Environment Variables.
4. Launch the app and wait for the status to show "Running".
2. Paste the repository URL: `https://github.com/LearningBotsOfficial/Ether`.
3. Choose Dockerfile-based deployment.
4. Set the required environment variables from [Configuration](#configuration).
5. If the platform requires an HTTP endpoint, set `WEB_SERVICE=true` and `PORT` to the platform-provided port.
6. Launch the app and wait for the status to show `Running`.
7. If a public URL is provided, verify `/health`.

#### 4. Docker Deployment (Local / VPS)
The preferred method for developers and privacy-focused users.
Expand All @@ -191,10 +241,20 @@ cp .env.example .env
nano .env

# 3. Build and launch with Docker Compose
docker-compose up -d --build
docker compose up -d --build

# 4. Verify the service
docker compose ps
curl http://localhost:8080/health
```

For Windows PowerShell, the health check command is:
```powershell
Invoke-RestMethod http://localhost:8080/health
```

> [!TIP]
> Using Docker Compose handles the health checks and automatic restarts for you.
> Docker Compose sets `WEB_SERVICE=true`, exposes `${PORT:-8080}`, and uses the `/health` endpoint for container health checks. If you set `PORT` in `.env`, use that value instead of `8080` in the health check URL.

#### 5. Manual Setup (Linux / VPS / Windows)
For users who want full control over the environment.
Expand All @@ -221,7 +281,8 @@ For users who want full control over the environment.
.venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```

4. **Configure Environment Variables**
Expand All @@ -237,37 +298,41 @@ For users who want full control over the environment.
python main.py
```

If your host requires a health endpoint, set:
```bash
export WEB_SERVICE=true
export PORT=8080
```

---

### Managing Dependencies & Upgrading

#### Adding or Removing Packages
To add a new library:
```bash
pip install <package-name>
# Then update requirements.txt
pip freeze > requirements.txt
python -m pip install <package-name>
# Then add the reviewed direct dependency pin to requirements.txt
```
To remove a library:
```bash
pip uninstall <package-name>
# Then update requirements.txt
pip freeze > requirements.txt
python -m pip uninstall <package-name>
# Then remove the direct dependency pin from requirements.txt
```

#### Upgrading All Packages
To upgrade all dependencies to their latest versions:
#### Syncing Pinned Dependencies
Install exactly the versions listed in `requirements.txt`:
```bash
pip install --upgrade -r requirements.txt
pip freeze > requirements.txt
python -m pip install -r requirements.txt
```

#### Syncing Environment
Whenever you pull new changes from GitHub that include an updated `requirements.txt`, simply run:
If you use `uv`:
```bash
pip install -r requirements.txt
uv pip install -r requirements.txt
```
This ensures your local `.venv` matches the project's requirements.

#### Upgrading Dependency Pins
Pinned requirements do not upgrade automatically. To upgrade safely, check the latest package versions, edit `requirements.txt`, sync the environment, and run the verification commands in the deployment section.

---

Expand Down
4 changes: 2 additions & 2 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"required": true
},
"WEB_SERVICE": {
"description": "Set to true to enable the keep-alive web service (requires 'web' process type).",
"description": "Set to false for the default Heroku worker dyno. Use true only if you add a web process.",
"value": "false",
"required": false
},
Expand All @@ -51,4 +51,4 @@
}
},
"stack": "container"
}
}
21 changes: 11 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
version: '3.8'

services:
ether-userbot:
build: .
container_name: ether-userbot
restart: unless-stopped
env_file:
- .env
environment:
WEB_SERVICE: "true"
PORT: "${PORT:-8080}"
ports:
- "${PORT:-8080}:${PORT:-8080}"
volumes:
# Map the specific directories where data is generated
- ./media:/app/media
- ./logs:/app/logs
# Map session files explicitly to persist logins
- ./sessions:/app/sessions
# Note: Since the bot creates session files in the root dir by default
# you may need to map them explicitly or configure SESSION_DIR in .env
- ./:/app/sessions_data # Or bind mount specific .session files
# If the app relies heavily on an external MongoDB,
# network settings can be configured here.
network_mode: bridge
healthcheck:
test: ["CMD-SHELL", "python -c \"import os, urllib.request; urllib.request.urlopen('http://127.0.0.1:' + os.getenv('PORT', '8080') + '/health', timeout=5).read()\""]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
2 changes: 2 additions & 0 deletions heroku.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
build:
docker:
worker: Dockerfile
run:
worker: python main.py
7 changes: 4 additions & 3 deletions plugins/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# =============================================================================

import time
from datetime import datetime, timedelta
from datetime import UTC, datetime, timedelta
from telethon import events
from utils.logger import get_logger
from utils.task_helper import safe_run
Expand Down Expand Up @@ -179,14 +179,15 @@ async def cache_messages(event):
):
return

expire_at = datetime.utcnow() + timedelta(hours=48)
now = datetime.now(UTC)
expire_at = now + timedelta(hours=48)

await msg_col.insert_one({
"msg_id": event.id,
"chat_id": event.chat_id,
"sender_id": event.sender_id,
"text": event.text,
"date": datetime.utcnow(),
"date": now,
"expire_at": expire_at
})

Expand Down
8 changes: 4 additions & 4 deletions render.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ services:
plan: free
region: oregon

autoDeploy: false
autoDeployTrigger: off

# Use root endpoint for health checks (always available)
healthCheckPath: /
# Use the lightweight health endpoint for Render health checks.
healthCheckPath: /health

envVars:
# Telegram API Credentials (Required - Get from my.telegram.org)
Expand All @@ -32,7 +32,7 @@ services:
- key: MONGO_URI
sync: false

# Port (Render will override with dynamic port)
# Public HTTP port for the health-check web service.
- key: PORT
value: "10000"

Expand Down
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
aiohttp==3.13.5
fastapi==0.136.1
aiohttp==3.14.1
fastapi==0.136.3
psutil==7.2.2
pymongo[srv]==4.13.0
python-dotenv==1.2.0
telethon==1.43.0
uvicorn[standard]==0.47.0
pymongo==4.17.0
python-dotenv==1.2.2
telethon==1.43.2
uvicorn[standard]==0.49.0