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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ users
botlog.txt
cookies.txt
rclone.conf
rclone/
config.env
*.json
*.pickle
*.pyc
.netrc
.vscode
.idea/
.DS_Store
pyrogram.session
pyrogram_session.session
Thumbnails/*
*.tar
bot/Gilang*

3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ FROM sammax23/rcmltb
WORKDIR /usr/src/app
RUN chmod 777 /usr/src/app

# Install latest rclone with pixeldrain support
RUN curl -fsSL https://rclone.org/install.sh | bash

COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

Expand Down
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,98 @@

An Rclone Mirror-Leech Telegram Bot to transfer to and from many clouds. Based on [mirror-leech-telegram-bot](https://github.com/anasty17/mirror-leech-telegram-bot) with rclone support added, and other features and changes from base code.

This is a fork of [Sam-Max/rcmltb](https://github.com/Sam-Max/rcmltb) with additional improvements and bug fixes.

**NOTE**: Base repository added recently its own rclone implementation.
**NOTE**: Base repository added recently its own rclone implementation.

---

## 🍎 ARM64 Support (Apple Silicon / Raspberry Pi / ARM Servers)

**Running on ARM64?** Use the [`arm64` branch](https://github.com/cybercyberz/rcmltb/tree/arm64) for native support:

```bash
git clone -b arm64 https://github.com/cybercyberz/rcmltb.git
```

The ARM64 branch includes:
- Native ARM64 Dockerfile (Apple M1/M2/M3, Raspberry Pi 4/5, ARM cloud servers)
- All features work except MEGA downloads (SDK not available for ARM64)
- Bug fixes backported from master

---

## 🆕 Fork Improvements & Changelog

This fork includes the following enhancements over the original repository:

### v1.1.0 - Private Channel Batch Fix (2024-12-24)

#### 🐛 Bug Fixes
- **Fixed "Peer id invalid" error for private channel batch operations**: The original bot would fail with `BAD_REQUEST: Peer id invalid` error when using `/mb` (mirror batch) or `/lb` (leech batch) commands with private/restricted channel links.
- **Root Cause**: Pyrogram requires the peer (channel) to be in its internal cache before it can fetch messages. For private channels, this cache wasn't being populated.
- **Solution**: The fix now iterates through user dialogs to find and cache the channel peer before attempting to fetch messages from private channels.

#### 🔧 Enhanced Error Handling
- **Improved error messages for batch commands**: When batch operations fail on private channels, the bot now provides more descriptive error messages including the actual exception, making it easier to diagnose issues.
- **Added channel validation**: The bot now checks if the channel exists in user's dialogs and provides a clear message if the channel is not found.

#### 📝 Documentation
- Added comprehensive guide for generating User Session String
- Added step-by-step instructions for private channel batch operations
- Updated README with fork improvements and changelog

---

## 📱 How to Use Private Channel Batch Operations

To download/mirror files from **private or restricted Telegram channels**, you need to set up a User Session String. This allows the bot to access channels that your Telegram account has joined.

### Step 1: Generate User Session String

1. **Install requirements** (if not already installed):
```bash
pip3 install pyrogram
```

2. **Run the session generator script**:
```bash
python3 session_generator.py
```

3. **Enter your credentials when prompted**:
- `API_ID`: Get from https://my.telegram.org
- `API_HASH`: Get from https://my.telegram.org
- You will receive a verification code on your Telegram app - enter it when prompted

4. **Copy the generated session string**: The script will output a long string starting with `BQ...` - this is your session string.

### Step 2: Configure the Bot

Add your session string to `config.env`:
```env
USER_SESSION_STRING = "your_session_string_here"
```

### Step 3: Join the Private Channel

Make sure the Telegram account (whose session string you generated) has **joined the private channel** you want to download from.

### Step 4: Use Batch Commands

Now you can use batch commands with private channel links:

```
/mb https://t.me/c/1234567890/100 https://t.me/c/1234567890/150
```

This will mirror all files from message 100 to 150 from the private channel.

**Commands:**
- `/mb` or `/mirror_batch` - Mirror files from private channel to cloud
- `/lb` or `/leech_batch` - Leech files from private channel to Telegram

---

## Features:

Expand Down
2 changes: 2 additions & 0 deletions bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
__author__ = "Sam-Max"

from uvloop import install
import asyncio
from asyncio import Lock
from socket import setdefaulttimeout
from logging import getLogger, FileHandler, StreamHandler, INFO, basicConfig
Expand All @@ -23,6 +24,7 @@
faulthandler_enable()

install()
asyncio.set_event_loop(asyncio.new_event_loop())

setdefaulttimeout(600)

Expand Down
3 changes: 2 additions & 1 deletion bot/helper/ext_utils/rclone_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@


async def is_remote_selected(user_id, message):
if CustomFilters.sudo_filter("", message):
# Use sync CustomFilters.sudo() instead of async sudo_filter to avoid coroutine warning
if CustomFilters.sudo(user_id):
if DEFAULT_OWNER_REMOTE := config_dict["DEFAULT_OWNER_REMOTE"]:
update_rclone_data("MIRROR_SELECT_REMOTE", DEFAULT_OWNER_REMOTE, user_id)
return True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ async def upload(
"-P",
]

is_gdrive = is_gdrive_remote(remote, conf_path)
is_gdrive = await is_gdrive_remote(remote, conf_path)
await setRcloneFlags(cmd, "upload")

if ospath.isdir(path):
Expand Down
5 changes: 5 additions & 0 deletions bot/helper/telegram_helper/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ async def custom_sudo_filter(self, client, update):

sudo_filter = create(custom_sudo_filter)

@staticmethod
def sudo(user_id):
"""Check if user_id is owner or sudo user"""
return user_id == OWNER_ID or (user_id in user_data and user_data[user_id].get("is_sudo", False))

15 changes: 13 additions & 2 deletions bot/modules/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,20 @@ async def download(message, link, multi, isLeech, value=0):
try:
client = app
chat = int("-100" + link.split("/")[-2])
# Search for the channel in dialogs to populate peer cache
found = False
async for dialog in app.get_dialogs():
if dialog.chat.id == chat:
found = True
break
if not found:
await sendMessage("Could not find the channel in your chats. Make sure you joined it!", message)
return
msg = await app.get_messages(chat, msg_id)
except Exception:
await sendMessage("Make sure you joined the channel!!", message)
except Exception as e:
from bot import LOGGER
LOGGER.error(f"Error accessing private channel: {e}")
await sendMessage(f"Make sure you joined the channel!! Error: {e}", message)
return
else:
client = bot
Expand Down
2 changes: 1 addition & 1 deletion bot/modules/tasks_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ async def onUploadComplete(
)
else:
cmd = ["rclone", "link", f"--config={rclone_config}", rclone_path]
res, code = await cmd_exec(cmd)
res, err, code = await cmd_exec(cmd)
if code == 0:
buttons.url_buildbutton("Cloud Link 🔗", res)
else:
Expand Down