├── Procfile ├── config.py ├── requirements.txt ├── Dockerfile ├── app.py ├── LICENSE ├── templates └── welcome.html ├── README.md └── main.py /Procfile: -------------------------------------------------------------------------------- 1 | worker: python main.py 2 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # basic bro 2 | import os 3 | 4 | API_ID = int(os.getenv("API_ID", "")) 5 | API_HASH = os.getenv("API_HASH", "") 6 | SESSION_STRING = os.getenv("SESSION_STRING", "") 7 | UNPLASH_API = os.getenv("UNPLASH_API", "") 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp 2 | requests 3 | pytz 4 | wikipedia 5 | qrcode 6 | feedparser 7 | whoisdomain 8 | Pillow 9 | beautifulsoup4 10 | pyfiglet 11 | googlesearch-python 12 | pyppeteer 13 | pyrofork 14 | tgcrypto 15 | flask 16 | werkzeug==2.2.2 17 | deep-translator 18 | psutil 19 | matplotlib 20 | speedtest-cli 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12-slim 2 | RUN apt update && apt upgrade -y 3 | RUN apt-get install git curl python3-pip ffmpeg -y 4 | RUN apt-get -y install git 5 | RUN apt-get install -y wget python3-pip curl bash neofetch ffmpeg software-properties-common 6 | WORKDIR /app 7 | COPY requirements.txt . 8 | 9 | RUN pip3 install wheel 10 | RUN pip3 install --no-cache-dir -U -r requirements.txt 11 | COPY . . 12 | EXPOSE 5000 13 | 14 | CMD flask run -h 0.0.0.0 -p 5000 & python3 main.py 15 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 devgagan : https://github.com/devgaganin. 2 | # Licensed under the GNU General Public License v3.0. 3 | # See LICENSE file in the repository root for full license text. 4 | 5 | import os 6 | from flask import Flask, render_template 7 | 8 | app = Flask(__name__) 9 | 10 | @app.route("/") 11 | def welcome(): 12 | # Render the welcome page with animated "Team SPY" text 13 | return render_template("welcome.html") 14 | 15 | if __name__ == "__main__": 16 | # Default to port 5000 if PORT is not set in the environment 17 | port = int(os.environ.get("PORT", 5000)) 18 | app.run(host="0.0.0.0", port=port) 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Gagan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /templates/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Team SPY - Bot is Live 7 | 123 | 124 | 125 | 126 |
127 |
Team SPY
128 |
⚡ Bot is Live ⚡
129 | 130 |
131 | Join Us 132 | GitHub 133 |
134 |
135 | 136 | 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tele-userbot 2 | 3 |
4 | 5 | [![Python](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://www.python.org/) 6 | [![Pyrogram](https://img.shields.io/badge/Pyrogram-2.0+-green.svg)](https://pyrogram.org/) 7 | [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) 8 | [![Telegram](https://img.shields.io/badge/Telegram-@devgaganin-blue.svg)](https://t.me/team_spy_pro) 9 | 10 | **A powerful, feature-rich Telegram userbot with versatile commands for automation, media management, and enhanced Telegram experience.** 11 | **✨ Note: this code is bot ready code means you can run userbot as well use second client for bot for callbacks and functions ✨** 12 | 13 |
14 | 15 | ## ✨ Features 16 | 17 | - 🔧 **Pro Commands** - Comprehensive command library 18 | - 🤖 **Automation** - Auto replies, filters, scheduled tasks 19 | - 💾 **Media Management** - Save, organize, and manage media files 20 | - 🛡️ **Privacy & Security** - Ghost mode, anti-spam, user blocking 21 | - 🎮 **Entertainment** - Games, jokes, ASCII art, and fun commands 22 | - 🌐 **Search & Translation** - Multi-platform search and language tools 23 | - 👑 **Administration** - Full group management capabilities 24 | - 📝 **Notes & Reminders** - Personal productivity tools 25 | - 🔌 **Custom Addons** - Extensible plugin system 26 | - ⚡ **High Performance** - Fast and lightweight 27 | 28 | ## 📋 Complete Command List 29 | 30 | ### 👑 Administration Commands (22) 31 | | Command | Usage | Description | 32 | |---------|-------|-------------| 33 | | `.ban` | `.ban [reply/user_id]` | Ban user from group | 34 | | `.unban` | `.unban [user_id]` | Unban user from group | 35 | | `.kick` | `.kick [reply/user_id]` | Kick user from group | 36 | | `.promote` | `.promote [reply/user_id] [role]` | Promote user to admin | 37 | | `.demote` | `.demote [reply/user_id]` | Demote admin to member | 38 | | `.roles` | `.demote` | List the roles and usages | 39 | | `.pin` | `.pin [reply]` | Pin replied message | 40 | | `.unpin` | `.unpin [reply]` | Unpin replied message | 41 | | `.vc` | `.vc` | Turn on voice chat | 42 | | `.mute` | `.mute [reply/user_id] [time]` | Mute user for specified time | 43 | | `.unmute` | `.unmute [reply/user_id]` | Unmute user | 44 | | `.purge` | `.purge [reply]` | Delete messages from replied message | 45 | | `.del` | `.del [reply]` | Delete replied message | 46 | | `.lock` | `.lock [permission]` | Lock chat permissions | 47 | | `.unlock` | `.unlock [permission]` | Unlock chat permissions | 48 | | `.admins` | `.admins` | List all group admins | 49 | | `.bots` | `.bots` | List all bots in group | 50 | | `.users` | `.users` | List all users in group | 51 | | `.zombies` | `.zombies` | Find deleted accounts | 52 | | `.delservice` | `.delservice [on/off or direct` | Service messages deletion on off| 53 | | `.keepservice` | `.keepservice [serive type eg. voice_chat]` | to keep service type from deletion | 54 | | `.servicestatus` | `.servicestatus` | Get current status of deletion | 55 | | `.settitle` | `.settitle [title]` | Set group title | 56 | | `.restoretitle` | `.restoretitle` | Restore original title | 57 | | `.welcome` | `.welcome [on/off] [msg]` | Set welcome message | 58 | | `.goodbye` | `.goodbye [on/off] [msg]` | Set goodbye message | 59 | | `.filter` | `.filter [trigger] [response]` | Add auto-response filter | 60 | | `.filters` | `.filters` | List all active filters | 61 | | `.stop` | `.stop [trigger]` | Remove filter | 62 | 63 | ### 💾 Media & Storage Commands (7) 64 | | Command | Usage | Description | 65 | |---------|-------|-------------| 66 | | `.save` | `.save [reply]` | Save media file | 67 | | `.get` | `.get [file_id]` | Retrieve saved file | 68 | | `.files` | `.files` | List all saved files | 69 | | `.delmedia` | `.delmedia [file_id]` | Delete saved media | 70 | | `.cloud` | `.cloud` | Access cloud storage menu | 71 | | `.backup` | `.backup` | Backup all userbot data | 72 | | `.restore` | `.restore` | Restore from backup | 73 | 74 | ### 🛡️ Privacy & Security Commands (10) 75 | | Command | Usage | Description | 76 | |---------|-------|-------------| 77 | | `.block` | `.block [reply/user_id]` | Block user | 78 | | `.unblock` | `.unblock [user_id]` | Unblock user | 79 | | `.blocked` | `.blocked` | List blocked users | 80 | | `.afk` | `.afk [reason]` | Set AFK mode with reason | 81 | | `.unafk` | `.unafk` | disable AFK mode | 82 | | `.ghost` | `.ghost [on/off]` | Toggle ghost mode | 83 | | `.antispam` | `.antispam [on/off]` | Toggle anti-spam protection | 84 | | `.captcha` | `.captcha [on/off]` | Enable CAPTCHA for new users | 85 | | `.report` | `.report [reply]` | Report message to admins | 86 | | `.whitelist` | `.whitelist [user_id]` | Add user to whitelist | 87 | 88 | ### 🤖 Automation & Custom Commands (12) 89 | | Command | Usage | Description | 90 | |---------|-------|-------------| 91 | | `.autoreply` | `.autoreply [trigger] [response]` | Set automatic reply | 92 | | `.delreply` | `.delreply [trigger]` | Delete auto reply | 93 | | `.replies` | `.replies` | List all auto replies | 94 | | `.alias` | `.alias [name] [command]` | Create command alias | 95 | | `.unalias` | `.unalias [name]` | Remove command alias | 96 | | `.aliases` | `.aliases` | List all aliases | 97 | | `.menu` | `.menu [name] [buttons]` | Create custom menu | 98 | | `.menus` | `.menus` | List all custom menus | 99 | | `.reaction` | `.reaction [trigger] [emoji]` | Set auto reaction | 100 | | `.delreaction` | `.delreaction [trigger]` | Delete auto reaction | 101 | | `.schedule` | `.schedule [time] [command]` | Schedule command execution | 102 | | `.unschedule` | `.unschedule [id]` | Cancel scheduled task | 103 | | `.tasks` | `.tasks` | List scheduled tasks | 104 | 105 | ### 📝 Notes & Reminders Commands (8) 106 | | Command | Usage | Description | 107 | |---------|-------|-------------| 108 | | `.note` | `.note [name] [content]` | Save a note | 109 | | `.getnote` | `.getnote [name]` | Retrieve saved note | 110 | | `.delnote` | `.delnote [name]` | Delete note | 111 | | `.notes` | `.notes` | List all saved notes | 112 | | `.remind` | `.remind [time] [message]` | Set reminder | 113 | | `.reminders` | `.reminders` | List all reminders | 114 | | `.todo` | `.todo [task]` | Add task to todo list | 115 | | `.todos` | `.todos` | List todo items | 116 | | `.done` | `.done [id]` | Mark todo as completed | 117 | 118 | ### 🌐 Search & Translation Commands (11) 119 | | Command | Usage | Description | 120 | |---------|-------|-------------| 121 | | `.search` | `.search [query]` | Search YouTube videos | 122 | | `.tr` | `.tr [language] [text]` | Translate text | 123 | | `.wiki` | `.wiki [query]` | Search Wikipedia | 124 | | `.img` | `.img [query]` | Search images | 125 | | `.weather` | `.weather [city]` | Get weather information | 126 | | `.ud` | `.ud [word]` | Urban Dictionary lookup | 127 | | `.define` | `.define [word]` | Dictionary definition | 128 | | `.syn` | `.syn [word]` | Find synonyms | 129 | | `.ant` | `.ant [word]` | Find antonyms | 130 | | `.news` | `.news [category]` | Get latest news | 131 | | `.rss` | `.rss [url]` | Add RSS feed | 132 | | `.feeds` | `.feeds` | List RSS feeds | 133 | 134 | ### 👤 Profile & Presence Commands (10) 135 | | Command | Usage | Description | 136 | |---------|-------|-------------| 137 | | `.setbio` | `.setbio [text]` | Set profile bio | 138 | | `.setpic` | `.setpic [reply/photo]` | Set profile picture | 139 | | `.setname` | `.setname [first] [last]` | Set display name | 140 | | `.username` | `.username [username]` | Set username | 141 | | `.qr` | `.qr [text]` | Generate QR code | 142 | | `.readqr` | `.readqr [reply]` | Read QR code | 143 | | `.avatar` | `.avatar [user_id]` | Get user avatar | 144 | | `.status` | `.status [text]` | Set custom status | 145 | | `.clone` | `.clone [user_id]` | Clone user profile | 146 | | `.revert` | `.revert` | Revert profile changes | 147 | 148 | ### 🎮 Entertainment & Fun Commands (23) 149 | | Command | Usage | Description | 150 | |---------|-------|-------------| 151 | | `.quote` | `.quote` | Get random quote | 152 | | `.addquote` | `.addquote [text]` | Add custom quote | 153 | | `.delquote` | `.delquote [id]` | Delete custom quote | 154 | | `.myquotes` | `.myquotes` | List your quotes | 155 | | `.joke` | `.joke` | Get random joke | 156 | | `.fact` | `.fact` | Get random fact | 157 | | `.meme` | `.meme` | Get random meme | 158 | | `.ascii` | `.ascii [text]` | Convert text to ASCII art | 159 | | `.reverse` | `.reverse [text]` | Reverse text | 160 | | `.mock` | `.mock [text]` | Create mocking text | 161 | | `.vapor` | `.vapor [text]` | Convert to vaporwave text | 162 | | `.clap` | `.clap [text]` | Add claps between words | 163 | | `.emojify` | `.emojify [text]` | Add random emojis | 164 | | `.spoiler` | `.spoiler [text]` | Create spoiler text | 165 | | `.password` | `.password [length]` | Generate random password | 166 | | `.hash` | `.hash [text]` | Generate text hash | 167 | | `.base64` | `.base64 [encode/decode] [text]` | Base64 encoding/decoding | 168 | | `.leet` | `.leet [text]` | Convert to 1337 speak | 169 | | `.flip` | `.flip [text]` | Flip text upside down | 170 | | `.cowsay` | `.cowsay [text]` | ASCII cow says text | 171 | | `.roll` | `.roll [dice]` | Roll dice | 172 | | `.8ball` | `.8ball [question]` | Magic 8 ball | 173 | | `.choose` | `.choose [option1\|option2]` | Random choice picker | 174 | 175 | ### ⚙️ Utilities & Tools Commands (22) 176 | | Command | Usage | Description | 177 | |---------|-------|-------------| 178 | | `.calc` | `.calc [expression]` | Calculator | 179 | | `.ping` | `.ping` | Check bot response time | 180 | | `.leave` | `.leave` | Leave current chat | 181 | | `.echo` | `.echo [text]` | Echo message | 182 | | `.type` | `.type [text]` | Typing animation | 183 | | `.alive` | `.alive` | Check bot status | 184 | | `.short` | `.short [url]` | Shorten URL | 185 | | `.expand` | `.expand [url]` | Expand shortened URL | 186 | | `.spb` | `.spb [user_id]` | Check SpamWatch ban | 187 | | `.whois` | `.whois [user_id]` | Advanced user information | 188 | | `.id` | `.id [reply/user_id]` | Get user/chat IDs | 189 | | `.info` | `.info [reply/user_id]` | Detailed user info | 190 | | `.stats` | `.stats` | Group statistics | 191 | | `.invite` | `.invite [user_id]` | Invite user to group | 192 | | `.export` | `.export [chat_id]` | Export chat members | 193 | | `.import` | `.import [file]` | Import member list | 194 | | `.ss` | `.ss [url]` | Take website screenshot | 195 | | `.currency` | `.currency [amount] [from] [to]` | Currency converter | 196 | | `.time` | `.time [location]` | Get current time | 197 | | `.domain` | `.domain [domain]` | Domain information | 198 | | `.ip` | `.ip [ip_address]` | IP address lookup | 199 | | `.whoisdomain` | `.whoisdomain [domain]` | Whois domain lookup | 200 | 201 | ### 🔧 Developer & Advanced Commands (12) 202 | | Command | Usage | Description | 203 | |---------|-------|-------------| 204 | | `.eval` | `.eval [code]` | Evaluate Python code | 205 | | `.exec` | `.exec [code]` | Execute Python code | 206 | | `.shell` | `.shell [command]` | Execute shell command | 207 | | `.restart` | `.restart` | Restart userbot | 208 | | `.update` | `.update` | Update userbot | 209 | | `.logs` | `.logs` | Get bot logs | 210 | | `.sysinfo` | `.sysinfo` | System information | 211 | | `.speedtest` | `.speedtest` | Network speed test | 212 | | `.pingall` | `.pingall` | Ping all group members | 213 | | `.broadcast` | `.broadcast [message]` | Broadcast message | 214 | | `.cleanup` | `.cleanup` | Clean temporary files | 215 | | `.debug` | `.debug [on/off]` | Toggle debug mode | 216 | 217 | ### 📱 Custom Addons Commands (6) 218 | | Command | Usage | Description | 219 | |---------|-------|-------------| 220 | | `.addon` | `.addon [name]` | Load custom addon | 221 | | `.addons` | `.addons` | List available addons | 222 | | `.createaddon` | `.createaddon [name]` | Create new addon | 223 | | `.editaddon` | `.editaddon [name]` | Edit existing addon | 224 | | `.deleteaddon` | `.deleteaddon [name]` | Delete addon | 225 | | `.reloadaddons` | `.reloadaddons` | Reload all addons | 226 | 227 | **Total: 120+ Commands across 11 categories** 228 | 229 | ## 🚀 Quick Start 230 | 231 | ### Prerequisites 232 | - Python 3.8 or higher 233 | - Telegram API credentials 234 | - Unsplash API key (optional, for image features) 235 | 236 | ### Local Installation 237 | 238 | 1. **Clone the repository** 239 | ```bash 240 | git clone https://github.com/devgaganin/tele-userbot.git 241 | cd tele-userbot 242 | ``` 243 | 244 | 2. **Install dependencies** 245 | ```bash 246 | pip3 install -r requirements.txt 247 | ``` 248 | 249 | 3. **Configure the bot** 250 | 251 | Edit `config.py` with your credentials: 252 | ```python 253 | # Telegram API Configuration 254 | API_ID = "your_api_id" 255 | API_HASH = "your_api_hash" 256 | SESSION_STRING = "your_session_string" 257 | 258 | # Optional: Unsplash API Key 259 | UNSPLASH_KEY = "your_unsplash_key" 260 | ``` 261 | 262 | 4. **Run the bot** 263 | ```bash 264 | python3 main.py 265 | ``` 266 | 267 | ## 🚀 Deployment Guide 268 | 269 | ### Heroku Deployment 270 | 271 | 1. **Create a new Heroku app** 272 | ```bash 273 | heroku create your-app-name 274 | ``` 275 | 276 | 2. **Connect your GitHub repository** 277 | - Go to Heroku Dashboard 278 | - Select your app 279 | - Go to "Deploy" tab 280 | - Connect to GitHub and select `devgaganin/tele-userbot` 281 | 282 | 3. **Set environment variables** 283 | - Go to "Settings" tab 284 | - Click "Reveal Config Vars" 285 | - Add the following variables: 286 | ``` 287 | API_ID = your_api_id 288 | API_HASH = your_api_hash 289 | SESSION_STRING = your_session_string 290 | UNSPLASH_KEY = your_unsplash_key (optional) 291 | ``` 292 | 293 | 4. **Deploy the app** 294 | - Go back to "Deploy" tab 295 | - Click "Deploy Branch" or enable automatic deploys 296 | 297 | ### Koyeb Deployment 298 | 299 | 1. **Connect your repository** 300 | - Sign up at [Koyeb](https://koyeb.com) 301 | - Create new app from GitHub 302 | - Select `devgaganin/tele-userbot` repository 303 | 304 | 2. **Configure environment variables** 305 | ``` 306 | API_ID = your_api_id 307 | API_HASH = your_api_hash 308 | SESSION_STRING = your_session_string 309 | UNSPLASH_KEY = your_unsplash_key (optional) 310 | PORT = 5000 311 | ``` 312 | 313 | 3. **Set build settings** 314 | - Build command: `pip install -r requirements.txt` 315 | - Run command: `python3 main.py` 316 | - Port: `5000` 317 | 318 | 4. **Deploy the application** 319 | 320 | ### Railway Deployment 321 | 322 | 1. **Connect repository** 323 | - Sign up at [Railway](https://railway.app) 324 | - Create new project from GitHub 325 | - Select `devgaganin/tele-userbot` 326 | 327 | 2. **Set environment variables** 328 | ``` 329 | API_ID = your_api_id 330 | API_HASH = your_api_hash 331 | SESSION_STRING = your_session_string 332 | UNSPLASH_KEY = your_unsplash_key (optional) 333 | PORT = 5000 334 | ``` 335 | 336 | 3. **Configure settings** 337 | - Railway will auto-detect Python 338 | - Ensure port is set to `5000` 339 | - Deploy automatically 340 | 341 | ### Render Deployment 342 | 343 | 1. **Create new web service** 344 | - Sign up at [Render](https://render.com) 345 | - Create new "Web Service" 346 | - Connect `devgaganin/tele-userbot` repository 347 | 348 | 2. **Configure build settings** 349 | - Build command: `pip install -r requirements.txt` 350 | - Start command: `python3 main.py` 351 | 352 | 3. **Set environment variables** 353 | ``` 354 | API_ID = your_api_id 355 | API_HASH = your_api_hash 356 | SESSION_STRING = your_session_string 357 | UNSPLASH_KEY = your_unsplash_key (optional) 358 | PORT = 5000 359 | ``` 360 | 361 | 4. **Deploy the service** 362 | 363 | ### VPS Deployment (Ubuntu/Debian) 364 | 365 | 1. **Update system and install Python** 366 | ```bash 367 | sudo apt update && sudo apt upgrade -y 368 | sudo apt install python3 python3-pip git -y 369 | ``` 370 | 371 | 2. **Clone and setup** 372 | ```bash 373 | git clone https://github.com/devgaganin/tele-userbot.git 374 | cd tele-userbot 375 | pip3 install -r requirements.txt 376 | ``` 377 | 378 | 3. **Configure environment** 379 | ```bash 380 | nano config.py # Edit with your credentials 381 | ``` 382 | 383 | 4. **Run with screen (persistent session)** 384 | ```bash 385 | screen -S userbot 386 | python3 main.py 387 | # Press Ctrl+A then D to detach 388 | ``` 389 | 390 | ### Docker Deployment 391 | 392 | 1. **Create Dockerfile** (if not included) 393 | ```dockerfile 394 | FROM python:3.9-slim 395 | WORKDIR /app 396 | COPY requirements.txt . 397 | RUN pip install -r requirements.txt 398 | COPY . . 399 | EXPOSE 5000 400 | CMD ["python3", "main.py"] 401 | ``` 402 | 403 | 2. **Build and run** 404 | ```bash 405 | docker build -t tele-userbot . 406 | docker run -d -p 5000:5000 --name userbot tele-userbot 407 | ``` 408 | 409 | ### Getting Session String 410 | 411 | You can get your session string using various methods: 412 | - [Pyrogram Session String Generator](https://replit.com/@SpEcHiDe/GenerateStringSession) 413 | - [Telegram Web Session](https://my.telegram.org/auth) 414 | 415 | ## 📖 Usage 416 | 417 | ### Basic Commands 418 | ``` 419 | .help # Show main help menu 420 | .help [category] # Show specific category commands 421 | .help admin # Show administration commands 422 | .help all # Show all commands in separate messages 423 | ``` 424 | 425 | ### Example Commands 426 | ``` 427 | .ban @username # Ban a user 428 | .save # Save replied media 429 | .tr en Hello # Translate to English 430 | .joke # Get a random joke 431 | .calc 2+2 # Calculator 432 | .weather London # Get weather info 433 | .remind 1h Meeting # Set reminder 434 | .quote # Random quote 435 | ``` 436 | 437 | ## 🔧 Configuration 438 | 439 | ### Environment Variables 440 | Create a `config.py` file with the following variables: 441 | 442 | | Variable | Description | Required | 443 | |----------|-------------|----------| 444 | | `API_ID` | Telegram API ID from my.telegram.org | Yes | 445 | | `API_HASH` | Telegram API Hash from my.telegram.org | Yes | 446 | | `SESSION_STRING` | Pyrogram session string | Yes | 447 | | `UNSPLASH_KEY` | Unsplash API key for image features | No | 448 | 449 | ### Custom Configuration 450 | - Modify command prefixes in main code 451 | - Add custom commands in the addons system 452 | - Configure auto-replies and filters 453 | - Set up custom menus and aliases 454 | 455 | ## 🏗️ Project Structure 456 | 457 | ``` 458 | tele-userbot/ 459 | ├── main.py # Single file containing all bot functionality 460 | ├── config.py # Configuration file 461 | ├── requirements.txt # Python dependencies 462 | └── README.md # This file 463 | ``` 464 | 465 | **Note**: This is an advanced standalone userbot - everything is contained in a single `main.py` file for simplicity and portability. 466 | 467 | ## 🤝 Contributing 468 | 469 | Contributions are welcome! Here's how you can help: 470 | 471 | ### Areas for Contribution 472 | - 🔌 **Raw API Usage** - Implement more Telegram Bot API features 473 | - 🆕 **New Features** - Add new commands and functionality 474 | - 🐛 **Bug Fixes** - Report and fix issues 475 | - 📚 **Documentation** - Improve docs and examples 476 | - 🧪 **Testing** - Help test new features and updates 477 | - 🔄 **Module Updates** - Keep dependencies updated 478 | 479 | ### How to Contribute 480 | 1. Fork the repository 481 | 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 482 | 3. Commit your changes (`git commit -m 'Add amazing feature'`) 483 | 4. Push to the branch (`git push origin feature/amazing-feature`) 484 | 5. Open a Pull Request 485 | 486 | ### Development Guidelines 487 | - Follow Python PEP 8 style guidelines 488 | - Add proper error handling 489 | - Include docstrings for new functions 490 | - Test your changes thoroughly 491 | - Update documentation if needed 492 | 493 | ## 📝 Module Updates Needed 494 | 495 | This project needs updates in the following areas: 496 | 497 | - [ ] **Raw API Integration** - More direct Telegram API usage 498 | - [ ] **Async Optimization** - Better async/await implementation 499 | - [ ] **Database Integration** - SQLite/MongoDB support 500 | - [ ] **Plugin System** - Enhanced addon architecture 501 | - [ ] **Error Handling** - Comprehensive exception management 502 | - [ ] **Logging System** - Better logging and debugging 503 | - [ ] **Security Features** - Enhanced privacy and security 504 | - [ ] **Performance** - Optimization and caching 505 | - [ ] **UI/UX** - Better command interfaces 506 | - [ ] **Documentation** - More examples and tutorials 507 | 508 | ## 🧪 Tested Version 509 | 510 | - **Python**: 3.8, 3.9, 3.10, 3.11 511 | - **Pyrogram**: 2.0+ 512 | - **Platform**: Linux, Windows, macOS 513 | - **Telegram**: Latest stable version 514 | 515 | ## ⚠️ Disclaimer 516 | 517 | - This is a **standalone userbot project** for personal use 518 | - Use at your own risk and responsibility 519 | - Follow Telegram's Terms of Service 520 | - Not affiliated with Telegram 521 | - Educational purposes only 522 | 523 | ## 📄 License 524 | 525 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 526 | 527 | ## 🔗 Links 528 | 529 | - **Developer**: [@devgaganin](https://github.com/devgaganin) 530 | - **Telegram**: [@team_spy_pro](https://t.me/team_spy_pro) 531 | - **Issues**: [Report Issues](https://github.com/devgaganin/tele-userbot/issues) 532 | - **Discussions**: [GitHub Discussions](https://github.com/devgaganin/tele-userbot/discussions) 533 | 534 | ## 🌟 Support 535 | 536 | If you find this project helpful, please: 537 | - ⭐ Star the repository 538 | - 🍴 Fork and contribute 539 | - 📢 Share with others 540 | - 🐛 Report issues 541 | - 💡 Suggest new features 542 | 543 | --- 544 | 545 |
546 | 547 | **Made with ❤️ by [devgaganin](https://github.com/devgaganin)** 548 | 549 | **[⬆ Back to Top](#-tele-userbot---pro-edition)** 550 | 551 |
552 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | """ 2 | 🌐 Open Source Project - Tele-Userbot (Note : this is bot ready code means you can import token and start second client for bot) 3 | 👨‍💻 Developer: Gagan 4 | 📂 Repo: https://github.com/devgaganin/tele-userbot 5 | 📜 License: MIT 6 | 7 | Built with ❤️ for the Telegram community. 8 | """ 9 | 10 | import asyncio 11 | import base64 12 | import hashlib 13 | import io 14 | import json 15 | import logging 16 | import math 17 | import os 18 | import platform 19 | import random 20 | import re 21 | import socket 22 | import statistics 23 | import string 24 | import sys 25 | import time 26 | from collections import defaultdict 27 | from datetime import datetime, timedelta 28 | from typing import Dict, List, Optional, Union 29 | from urllib.parse import quote_plus, urlparse 30 | 31 | import aiohttp 32 | import pytz 33 | import qrcode 34 | import requests 35 | import feedparser 36 | from PIL import Image 37 | from bs4 import BeautifulSoup 38 | from pyfiglet import figlet_format 39 | from pyppeteer import launch 40 | from googlesearch import search as google_search 41 | import whoisdomain as whois 42 | 43 | from pyrogram import Client, filters, enums, idle 44 | from pyrogram.types import ( 45 | Message, 46 | InlineKeyboardMarkup, 47 | InlineKeyboardButton, 48 | ReplyKeyboardMarkup, 49 | ChatPrivileges, 50 | ) 51 | from pyrogram.errors import ( 52 | FloodWait, 53 | RPCError, 54 | UserNotParticipant, 55 | ChatAdminRequired, 56 | ) 57 | from pyrogram.enums import ChatType 58 | from pyrogram.raw.types import ( 59 | InputPeerChannel, 60 | UpdateGroupCall, 61 | InputGroupCall, 62 | ) 63 | from pyrogram.raw.functions.account import UpdateProfile, UpdateUsername 64 | from pyrogram.raw.functions.channels import EditTitle 65 | from pyrogram.raw.functions.phone import CreateGroupCall 66 | 67 | from config import API_ID, API_HASH, SESSION_STRING, UNPLASH_API as api_key 68 | 69 | if not API_ID or not API_HASH or not SESSION_STRING: 70 | print("One of the required config values is missing: API_ID, API_HASH, or SESSION_STRING") 71 | sys.exit() 72 | 73 | if not api_key: 74 | print("You can't use the .img command since the Unsplash API key is not provided in config") 75 | 76 | app = Client( 77 | "ultra_userbot", 78 | api_id=API_ID, 79 | api_hash=API_HASH, 80 | session_string=SESSION_STRING, 81 | workers=20 82 | ) 83 | 84 | 85 | logging.basicConfig( 86 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 87 | level=logging.INFO 88 | ) 89 | logger = logging.getLogger(__name__) 90 | 91 | 92 | MEDIA_DIR = "saved_media" 93 | AUTO_REPLY_FILE = "auto_replies.json" 94 | BLOCKED_USERS_FILE = "blocked_users.json" 95 | NOTES_FILE = "notes.json" 96 | REMINDERS_FILE = "reminders.json" 97 | PROFILE_PICS_DIR = "profile_pics" 98 | QUOTES_FILE = "quotes.json" 99 | CUSTOM_COMMANDS_FILE = "custom_commands.json" 100 | SCHEDULED_TASKS_FILE = "scheduled_tasks.json" 101 | USER_DATA_FILE = "user_data.json" 102 | GROUP_SETTINGS_FILE = "group_settings.json" 103 | 104 | 105 | for directory in [MEDIA_DIR, PROFILE_PICS_DIR, "downloads", "temp"]: 106 | os.makedirs(directory, exist_ok=True) 107 | 108 | 109 | auto_replies = {} 110 | blocked_users = set() 111 | notes = {} 112 | reminders = {} 113 | speed_history = [] 114 | custom_quotes = {} 115 | custom_commands = {} 116 | scheduled_tasks = {} 117 | user_data = {} 118 | group_settings = {} 119 | afk_mode = False 120 | afk_reason = "" 121 | afk_start_time = None 122 | chat_titles = {} 123 | spam_protection = {} 124 | user_stats = defaultdict(lambda: {"messages": 0, "commands": 0}) 125 | active_filters = {} 126 | rss_feeds = {} 127 | rss_last_check = {} 128 | custom_menus = {} 129 | auto_reactions = {} 130 | scheduled_messages = {} 131 | user_aliases = {} 132 | group_aliases = {} 133 | SERVICE_DELETION_ENABLED = True 134 | KEEP_SERVICE_TYPES = set() 135 | SERVICE_TYPE_MAP = { 136 | 'join': ['new_chat_members', 'chat_member_updated'], 137 | 'left': ['left_chat_member'], 138 | 'pin': ['pinned_message'], 139 | 'photo': ['new_chat_photo', 'delete_chat_photo'], 140 | 'name': ['new_chat_title'], 141 | 'voice': ['voice_chat_started', 'voice_chat_ended'], 142 | 'video': ['video_chat_started', 'video_chat_ended', 'video_chat_participants_invited'], 143 | 'description': ['new_chat_description'], 144 | 'migrate': ['migrate_to_chat_id', 'migrate_from_chat_id'], 145 | 'boost': ['chat_boost'], 146 | 'background': ['chat_background_set'], 147 | 'forum': ['forum_topic_created', 'forum_topic_edited', 'forum_topic_closed', 'forum_topic_reopened'], 148 | 'payment': ['successful_payment', 'invoice'], 149 | 'game': ['game_high_score'], 150 | 'contact': ['contact_registered'] 151 | } 152 | 153 | def get_service_type(message): 154 | if not message.service: 155 | return None 156 | service_str = str(message.service).lower() 157 | for service_name, patterns in SERVICE_TYPE_MAP.items(): 158 | for pattern in patterns: 159 | if pattern in service_str: 160 | return service_name 161 | return str(message.service).split('(')[0].lower() 162 | 163 | 164 | def load_data(): 165 | global auto_replies, blocked_users, notes, reminders, custom_quotes, custom_commands 166 | global scheduled_tasks, user_data, group_settings 167 | try: 168 | for file_path, variable in [ 169 | (AUTO_REPLY_FILE, auto_replies), 170 | (BLOCKED_USERS_FILE, blocked_users), 171 | (NOTES_FILE, notes), 172 | (REMINDERS_FILE, reminders), 173 | (QUOTES_FILE, custom_quotes), 174 | (CUSTOM_COMMANDS_FILE, custom_commands), 175 | (SCHEDULED_TASKS_FILE, scheduled_tasks), 176 | (USER_DATA_FILE, user_data), 177 | (GROUP_SETTINGS_FILE, group_settings) 178 | ]: 179 | if os.path.exists(file_path): 180 | with open(file_path, 'r') as f: 181 | data = json.load(f) 182 | if isinstance(variable, set): 183 | variable.clear() 184 | variable.update(data) 185 | else: 186 | variable.clear() 187 | variable.update(data) 188 | except Exception as e: 189 | logger.error(f"Error loading {e}") 190 | 191 | 192 | 193 | def save_data(): 194 | try: 195 | mappings = [ 196 | (AUTO_REPLY_FILE, auto_replies), 197 | (BLOCKED_USERS_FILE, list(blocked_users)), 198 | (NOTES_FILE, notes), 199 | (REMINDERS_FILE, reminders), 200 | (QUOTES_FILE, custom_quotes), 201 | (CUSTOM_COMMANDS_FILE, custom_commands), 202 | (SCHEDULED_TASKS_FILE, scheduled_tasks), 203 | (USER_DATA_FILE, user_data), 204 | (GROUP_SETTINGS_FILE, group_settings) 205 | ] 206 | 207 | for file_path, data in mappings: 208 | with open(file_path, 'w') as f: 209 | json.dump(data, f, indent=2) 210 | except Exception as e: 211 | logger.error(f"Error saving {e}") 212 | 213 | 214 | load_data() 215 | 216 | # Split help text into categories 217 | HELP_CATEGORIES = { 218 | "admin": """**👑 ADMINISTRATION:** 219 | - `.ban [reply/user_id]` - Ban user 220 | - `.unban [user_id]` - Unban user 221 | - `.kick [reply/user_id]` - Kick user 222 | - `.promote [reply/user_id] [rank]` - Promote user 223 | - `.demote [reply/user_id]` - Demote admin 224 | - `.pin [reply]` - Pin message 225 | - `.unpin [reply]` - Unpin message 226 | - `.vc ` - VC on 227 | - `.mute [reply/user_id] [time]` - Mute user 228 | - `.unmute [reply/user_id]` - Unmute user 229 | - `.purge [reply]` - Delete messages 230 | - `.del [reply]` - Delete replied message 231 | - `.lock [perm]` - Lock chat permissions 232 | - `.unlock [perm]` - Unlock permissions 233 | - `.admins` - List admins 234 | - `.bots` - List bots 235 | - `.users` - List users 236 | - `.zombies` - Find deleted accounts 237 | - `.settitle [title]` - Set chat title 238 | - `.restoretitle` - Restore original title 239 | - `.welcome [on/off] [msg]` - Welcome message 240 | - `.goodbye [on/off] [msg]` - Goodbye message 241 | - `.filter [trigger] [response]` - Add filter 242 | - `.filters` - List filters 243 | - `.keepservice` - to keep service message 244 | - `.delservice` - service on / off deletion 245 | - `.servicesatatus` - check status of deletion 246 | - `.stop [trigger]` - Remove filter""", 247 | 248 | "media": """**💾 MEDIA & STORAGE:** 249 | - `.save [reply]` - Save media (forward/download) 250 | - `.get [file_id]` - Get saved file 251 | - `.files` - List saved files 252 | - `.delmedia [file_id]` - Delete saved file 253 | - `.cloud` - Cloud storage menu 254 | - `.backup` - Backup all data 255 | - `.restore` - Restore from backup""", 256 | 257 | "security": """**🛡️ PRIVACY & SECURITY:** 258 | - `.block [reply/user_id]` - Block user 259 | - `.unblock [user_id]` - Unblock user 260 | - `.blocked` - List blocked users 261 | - `.afk [reason]` - Set AFK mode 262 | - `.unafk` - Disable AFK mode 263 | - `.ghost [on/off]` - Ghost mode (invisible) 264 | - `.antispam [on/off]` - Anti-spam protection 265 | - `.captcha [on/off]` - CAPTCHA for new users 266 | - `.report [reply]` - Report message 267 | - `.whitelist [user_id]` - Whitelist user""", 268 | 269 | "automation": """**🤖 AUTOMATION & CUSTOM:** 270 | - `.autoreply [trigger] [response]` - Set auto reply 271 | - `.delreply [trigger]` - Delete auto reply 272 | - `.replies` - List all auto replies 273 | - `.alias [name] [command]` - Create command alias 274 | - `.unalias [name]` - Remove alias 275 | - `.aliases` - List aliases 276 | - `.menu [name] [buttons]` - Create custom menu 277 | - `.menus` - List menus 278 | - `.reaction [trigger] [emoji]` - Auto reaction 279 | - `.delreaction [trigger]` - del reaction 280 | - `.schedule [time] [command]` - Schedule task 281 | - `.unschedule [id]` - Cancel scheduled task 282 | - `.tasks` - List scheduled tasks""", 283 | 284 | "notes": """**📝 NOTES & REMINDERS:** 285 | - `.note [name] [content]` - Save a note 286 | - `.getnote [name]` - Get a note 287 | - `.delnote [name]` - Delete a note 288 | - `.notes` - List all notes 289 | - `.remind [time] [message]` - Set reminder 290 | - `.reminders` - List all reminders 291 | - `.todo [task]` - Add todo item 292 | - `.todos` - List todo items 293 | - `.done [id]` - Mark todo as done""", 294 | 295 | "search": """**🌐 SEARCH & TRANSLATION:** 296 | - `.search [query]` - Search YouTube 297 | - `.tr [lang] [text]` - Translate text 298 | - `.wiki [query]` - Wikipedia search 299 | - `.img [query]` - Image search 300 | - `.weather [city]` - Weather information 301 | - `.ud [word]` - Urban Dictionary 302 | - `.define [word]` - Dictionary definition 303 | - `.syn [word]` - Synonyms 304 | - `.ant [word]` - Antonyms 305 | - `.news [category]` - Latest news 306 | - `.rss [url]` - Add RSS feed 307 | - `.feeds` - List RSS feeds""", 308 | 309 | "profile": """**👤 PROFILE & PRESENCE:** 310 | - `.setbio [text]` - Set profile bio 311 | - `.setpic [reply/photo]` - Set profile picture 312 | - `.setname [first] [last]` - Set name 313 | - `.username [username]` - Set username 314 | - `.qr [text]` - Generate QR code 315 | - `.readqr [reply]` - Read QR code 316 | - `.avatar [user_id]` - Get user avatar 317 | - `.status [text]` - Set custom status 318 | - `.clone [user_id]` - Clone profile 319 | - `.revert` - Revert profile""", 320 | 321 | "fun": """**🎮 ENTERTAINMENT & FUN:** 322 | - `.quote` - Random quote 323 | - `.addquote [text]` - Add custom quote 324 | - `.delquote [id]` - Delete custom quote 325 | - `.myquotes` - List your quotes 326 | - `.joke` - Random joke 327 | - `.fact` - Random fact 328 | - `.meme` - Random meme 329 | - `.ascii [text]` - Convert text to ASCII art 330 | - `.reverse [text]` - Reverse text 331 | - `.mock [text]` - Mock text (aLtErNaTiNg cApS) 332 | - `.vapor [text]` - Vaporwave text 333 | - `.clap [text]` - Add claps between words 334 | - `.emojify [text]` - Add random emojis 335 | - `.spoiler [text]` - Create spoiler text 336 | - `.password [length]` - Generate random password 337 | - `.hash [text]` - Generate hash of text 338 | - `.base64 [encode/decode] [text]` - Base64 encoding/decoding 339 | - `.leet [text]` - 1337 speak 340 | - `.flip [text]` - Flip text upside down 341 | - `.cowsay [text]` - Cow says... 342 | - `.roll [dice]` - Roll dice 343 | - `.8ball [question]` - Magic 8 ball 344 | - `.choose [option1|option2]` - Random choice""", 345 | 346 | "utils": """**⚙️ UTILITIES & TOOLS:** 347 | - `.calc [expression]` - Calculator (works in reply too) 348 | - `.ping` - Check bot response 349 | - `.leave` - Leave current chat 350 | - `.echo [text]` - Echo message 351 | - `.type [text]` - Typing animation 352 | - `.alive` - Bot status 353 | - `.short [url]` - URL shortener 354 | - `.expand [url]` - Expand short URL 355 | - `.spb [user_id]` - Check SpamWatch 356 | - `.whois [user_id]` - Advanced user info 357 | - `.id [reply/user_id]` - Get IDs 358 | - `.info [reply/user_id]` - Detailed user info 359 | - `.stats` - Group statistics 360 | - `.invite [user_id]` - Invite user to group 361 | - `.export [chat_id]` - Export chat members 362 | - `.import [file]` - Import members 363 | - `.ss [url]` - Take website screenshot 364 | - `.currency [amount] [from] [to]` - Currency converter 365 | - `.time [location]` - Current time 366 | - `.domain [domain]` - Domain info 367 | - `.ip [ip]` - IP address info 368 | - `.whoisdomain [domain]` - Whois domain lookup""", 369 | 370 | "dev": """**🔧 DEVELOPER & ADVANCED:** 371 | - `.eval [code]` - Evaluate Python code 372 | - `.exec [code]` - Execute Python code 373 | - `.shell [command]` - Execute shell command 374 | - `.restart` - Restart bot 375 | - `.update` - Update bot 376 | - `.logs` - Get bot logs 377 | - `.sysinfo` - System information 378 | - `.speedtest` - Network speed test 379 | - `.pingall` - Ping all members 380 | - `.broadcast [message]` - Broadcast message 381 | - `.cleanup` - Clean up files 382 | - `.debug [on/off]` - Debug mode""", 383 | 384 | "addons": """**📱 CUSTOM ADDONS:** 385 | - `.addon [name]` - Load custom addon 386 | - `.addons` - List available addons 387 | - `.createaddon [name]` - Create new addon 388 | - `.editaddon [name]` - Edit existing addon 389 | - `.deleteaddon [name]` - Delete addon 390 | - `.reloadaddons` - Reload all addons""" 391 | } 392 | 393 | MAIN_HELP = """**🚀 ULTRA USERBOT - PRO EDITION 🚀** 394 | 395 | **📋 Available Categories:** 396 | • `admin` - Administration commands 397 | • `media` - Media & storage commands 398 | • `security` - Privacy & security commands 399 | • `automation` - Automation & custom commands 400 | • `notes` - Notes & reminders 401 | • `search` - Search & translation 402 | • `profile` - Profile & presence 403 | • `fun` - Entertainment & fun commands 404 | • `utils` - Utilities & tools 405 | • `dev` - Developer & advanced 406 | • `addons` - Custom addons 407 | 408 | **Usage:** 409 | • `.help` - Show this menu 410 | • `.help [category]` - Show specific category 411 | • `.help all` - Show all commands (multiple messages) 412 | 413 | **Examples:** 414 | • `.help admin` - Show admin commands 415 | • `.help fun` - Show fun commands""" 416 | 417 | @app.on_message(filters.command("help", prefixes=".") & filters.me) 418 | async def help_command(client: Client, message: Message): 419 | if len(message.command) > 1: 420 | category = message.command[1].lower() 421 | 422 | if category == "all": 423 | await message.edit_text("**🚀 Sending all help categories...**") 424 | await asyncio.sleep(1) 425 | 426 | for cat_name, cat_text in HELP_CATEGORIES.items(): 427 | try: 428 | await message.reply_text(cat_text, parse_mode=enums.ParseMode.MARKDOWN) 429 | await asyncio.sleep(0.5) 430 | except Exception as e: 431 | await message.reply_text(f"Error sending {cat_name}: {str(e)}") 432 | 433 | await message.edit_text("**✅ All help categories sent!**") 434 | 435 | elif category in HELP_CATEGORIES: 436 | try: 437 | await message.edit_text(HELP_CATEGORIES[category], parse_mode=enums.ParseMode.MARKDOWN) 438 | except Exception as e: 439 | await message.edit_text(f"Error: {str(e)}") 440 | else: 441 | available = ", ".join(HELP_CATEGORIES.keys()) 442 | await message.edit_text(f"**❌ Invalid category!**\n\n**Available categories:**\n{available}\n\nUse `.help [category]` or `.help all`") 443 | else: 444 | try: 445 | await message.edit_text(MAIN_HELP, parse_mode=enums.ParseMode.MARKDOWN) 446 | except Exception as e: 447 | await message.edit_text(f"Error: {str(e)}") 448 | 449 | # -------- BOT READY VERSION ----- 450 | 451 | @app.on_message(filters.command("helpx", prefixes=".") & filters.me) 452 | async def help_paginated(client: Client, message: Message): 453 | """Alternative paginated help command""" 454 | keyboard = InlineKeyboardMarkup([ 455 | [InlineKeyboardButton("👑 Admin", callback_data="help_admin"), 456 | InlineKeyboardButton("💾 Media", callback_data="help_media")], 457 | [InlineKeyboardButton("🛡️ Security", callback_data="help_security"), 458 | InlineKeyboardButton("🤖 Automation", callback_data="help_automation")], 459 | [InlineKeyboardButton("📝 Notes", callback_data="help_notes"), 460 | InlineKeyboardButton("🌐 Search", callback_data="help_search")], 461 | [InlineKeyboardButton("👤 Profile", callback_data="help_profile"), 462 | InlineKeyboardButton("🎮 Fun", callback_data="help_fun")], 463 | [InlineKeyboardButton("⚙️ Utils", callback_data="help_utils"), 464 | InlineKeyboardButton("🔧 Dev", callback_data="help_dev")], 465 | [InlineKeyboardButton("📱 Addons", callback_data="help_addons")], 466 | [InlineKeyboardButton("📋 Show All", callback_data="help_all")] 467 | ]) 468 | 469 | await message.edit_text(MAIN_HELP, parse_mode=enums.ParseMode.MARKDOWN, reply_markup=keyboard) 470 | 471 | # BOT READY VERSION ... (TEAM SPY) 472 | @app.on_callback_query() 473 | async def help_callback(client: Client, callback_query): 474 | if callback_query.data.startswith("help_"): 475 | category = callback_query.data.replace("help_", "") 476 | 477 | if category == "all": 478 | # Send all as separate messages 479 | await callback_query.message.edit_text("**🚀 Sending all help categories...**") 480 | for cat_name, cat_text in HELP_CATEGORIES.items(): 481 | await callback_query.message.reply_text(cat_text, parse_mode=enums.ParseMode.MARKDOWN) 482 | await asyncio.sleep(0.5) 483 | elif category in HELP_CATEGORIES: 484 | await callback_query.message.edit_text(HELP_CATEGORIES[category], parse_mode=enums.ParseMode.MARKDOWN) 485 | 486 | await callback_query.answer() 487 | 488 | 489 | def get_media_type(message: Message): 490 | if message.photo: 491 | return "photo" 492 | elif message.video: 493 | return "video" 494 | elif message.document: 495 | return "document" 496 | elif message.audio: 497 | return "audio" 498 | elif message.voice: 499 | return "voice" 500 | elif message.animation: 501 | return "animation" 502 | elif message.sticker: 503 | return "sticker" 504 | return None 505 | 506 | async def check_admin(client: Client, chat_id: int, user_id: int): 507 | try: 508 | member = await client.get_chat_member(chat_id, user_id) 509 | return member.status in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER] 510 | except: 511 | return False 512 | 513 | def format_time(seconds): 514 | hours = seconds // 3600 515 | minutes = (seconds % 3600) // 60 516 | secs = seconds % 60 517 | return f"{hours:02d}:{minutes:02d}:{secs:02d}" 518 | 519 | def is_valid_url(url): 520 | try: 521 | result = urlparse(url) 522 | return all([result.scheme, result.netloc]) 523 | except: 524 | return False 525 | 526 | def safe_eval(expression): 527 | """Safe evaluation of mathematical expressions""" 528 | 529 | expression = expression.replace(" ", "") 530 | 531 | 532 | allowed_chars = set('0123456789+-*/().%') 533 | if not all(c in allowed_chars for c in expression): 534 | raise ValueError("Invalid characters in expression") 535 | 536 | 537 | expression = expression.replace("%", "/100") 538 | 539 | 540 | try: 541 | result = eval(expression, {"__builtins__": {}}, {}) 542 | return result 543 | except ZeroDivisionError: 544 | raise ValueError("Division by zero") 545 | except Exception: 546 | raise ValueError("Invalid expression") 547 | 548 | def mock_text(text): 549 | """Convert text to alternating caps (mocking)""" 550 | return ''.join(c.upper() if i % 2 == 0 else c.lower() for i, c in enumerate(text)) 551 | 552 | def vapor_text(text): 553 | """Convert text to vaporwave style""" 554 | vapor_map = { 555 | ' ': ' ', 556 | '!': '!', '"': '"', '#': '#', '$': '$', '%': '%', '&': '&', "'": ''', 557 | '(': '(', ')': ')', '*': '*', '+': '+', ',': ',', '-': '-', '.': '.', 558 | '/': '/', '0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', 559 | '6': '6', '7': '7', '8': '8', '9': '9', ':': ':', ';': ';', '<': '<', 560 | '=': '=', '>': '>', '?': '?', '@': '@', 'A': 'A', 'B': 'B', 'C': 'C', 561 | 'D': 'D', 'E': 'E', 'F': 'F', 'G': 'G', 'H': 'H', 'I': 'I', 'J': 'J', 562 | 'K': 'K', 'L': 'L', 'M': 'M', 'N': 'N', 'O': 'O', 'P': 'P', 'Q': 'Q', 563 | 'R': 'R', 'S': 'S', 'T': 'T', 'U': 'U', 'V': 'V', 'W': 'W', 'X': 'X', 564 | 'Y': 'Y', 'Z': 'Z', '[': '[', '\\': '\', ']': ']', '^': '^', '_': '_', 565 | '`': '`', 'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd', 'e': 'e', 'f': 'f', 566 | 'g': 'g', 'h': 'h', 'i': 'i', 'j': 'j', 'k': 'k', 'l': 'l', 'm': 'm', 567 | 'n': 'n', 'o': 'o', 'p': 'p', 'q': 'q', 'r': 'r', 's': 's', 't': 't', 568 | 'u': 'u', 'v': 'v', 'w': 'w', 'x': 'x', 'y': 'y', 'z': 'z', '{': '{', 569 | '|': '|', '}': '}', '~': '~' 570 | } 571 | 572 | result = "" 573 | for char in text: 574 | result += vapor_map.get(char, char) 575 | return result 576 | 577 | def clap_text(text): 578 | """Add claps between words""" 579 | return " 👏 ".join(text.split()) 580 | 581 | def emojify_text(text): 582 | """Add random emojis to text""" 583 | emojis = ["😀", "😂", "🥰", "😎", "🤩", "😍", "🤗", "🤔", "😱", "🥳", "😭", "😡", "😴", "😈", "👻"] 584 | words = text.split() 585 | result = [] 586 | for word in words: 587 | result.append(word) 588 | result.append(emojis[hash(word) % len(emojis)]) 589 | return " ".join(result) 590 | 591 | def spoiler_text(text): 592 | """Create spoiler text""" 593 | return f"||{text}||" 594 | 595 | def generate_password(length=12): 596 | """Generate random password""" 597 | chars = string.ascii_letters + string.digits + "!@#$%^&*" 598 | return ''.join(random.choice(chars) for _ in range(length)) 599 | 600 | 601 | def leet_speak(text): 602 | """Convert text to 1337 speak""" 603 | leet_map = { 604 | 'a': '4', 'e': '3', 'i': '1', 'o': '0', 's': '5', 't': '7', 605 | 'A': '4', 'E': '3', 'I': '1', 'O': '0', 'S': '5', 'T': '7' 606 | } 607 | return ''.join(leet_map.get(c, c) for c in text) 608 | 609 | def flip_text(text): 610 | """Flip text upside down""" 611 | flip_map = { 612 | 'a': 'ɐ', 'b': 'q', 'c': 'ɔ', 'd': 'p', 'e': 'ǝ', 'f': 'ɟ', 613 | 'g': 'ƃ', 'h': 'ɥ', 'i': 'ᴉ', 'j': 'ɾ', 'k': 'ʞ', 'l': 'l', 614 | 'm': 'ɯ', 'n': 'u', 'o': 'o', 'p': 'd', 'q': 'b', 'r': 'ɹ', 615 | 's': 's', 't': 'ʇ', 'u': 'n', 'v': 'ʌ', 'w': 'ʍ', 'x': 'x', 616 | 'y': 'ʎ', 'z': 'z', 'A': '∀', 'B': '𐐒', 'C': 'Ɔ', 'D': '◖', 617 | 'E': 'Ǝ', 'F': 'Ⅎ', 'G': '⅁', 'H': 'H', 'I': 'I', 'J': 'ſ', 618 | 'K': '⋊', 'L': '˥', 'M': 'W', 'N': 'N', 'O': 'O', 'P': 'Ԁ', 619 | 'Q': 'Ό', 'R': 'ᴚ', 'S': 'S', 'T': '⊥', 'U': '∩', 'V': 'Λ', 620 | 'W': 'M', 'X': 'X', 'Y': '⅄', 'Z': 'Z', '0': '0', '1': 'Ɩ', 621 | '2': 'ᄅ', '3': 'Ɛ', '4': 'ㄣ', '5': 'ϛ', '6': '9', '7': 'ㄥ', 622 | '8': '8', '9': '6', '.': '˙', ',': "'", '!': '¡', '?': '¿', 623 | '(': ')', ')': '(', '[': ']', ']': '[', '{': '}', '}': '{', 624 | '<': '>', '>': '<', '&': '⅋', '_': '‾' 625 | } 626 | return ''.join(flip_map.get(c, c) for c in text[::-1]) 627 | 628 | def cowsay(text): 629 | """Generate cowsay ASCII art""" 630 | lines = text.split('\n') 631 | max_len = max(len(line) for line in lines) 632 | border = " " + "_" * (max_len + 2) + " " 633 | bottom_border = " " + "-" * (max_len + 2) + " " 634 | 635 | result = [border] 636 | for line in lines: 637 | padding = " " * (max_len - len(line)) 638 | result.append(f"< {line}{padding} >") 639 | result.append(bottom_border) 640 | result.append(" \\ ^__^") 641 | result.append(" \\ (oo)\\_______") 642 | result.append(" (__)\\ )\\/\\") 643 | result.append(" ||----w |") 644 | result.append(" || ||") 645 | 646 | return "\n".join(result) 647 | 648 | def roll_dice(dice_notation="1d6"): 649 | """Roll dice with notation like 2d6, 1d20, etc.""" 650 | try: 651 | if 'd' in dice_notation: 652 | num, sides = map(int, dice_notation.split('d')) 653 | else: 654 | num, sides = 1, int(dice_notation) 655 | 656 | if num > 100 or sides > 1000: 657 | return "Too many dice or sides!" 658 | 659 | rolls = [random.randint(1, sides) for _ in range(num)] 660 | total = sum(rolls) 661 | 662 | if len(rolls) == 1: 663 | return f"🎲 Rolled {rolls[0]} on a d{sides}" 664 | else: 665 | return f"🎲 Rolled {rolls} = {total} on {num}d{sides}" 666 | except: 667 | return "Invalid dice notation! Use format like 1d6, 2d20, etc." 668 | 669 | def magic_8ball(question): 670 | """Magic 8 ball responses""" 671 | responses = [ 672 | "It is certain", "It is decidedly so", "Without a doubt", "Yes definitely", 673 | "You may rely on it", "As I see it, yes", "Most likely", "Outlook good", 674 | "Yes", "Signs point to yes", "Reply hazy, try again", "Ask again later", 675 | "Better not tell you now", "Cannot predict now", "Concentrate and ask again", 676 | "Don't count on it", "My reply is no", "My sources say no", 677 | "Outlook not so good", "Very doubtful" 678 | ] 679 | return f"🎱 {random.choice(responses)}" 680 | 681 | def random_choice(options): 682 | """Randomly choose from options""" 683 | choices = [opt.strip() for opt in options.split('|')] 684 | return f"🎲 I choose: {random.choice(choices)}" 685 | 686 | 687 | 688 | @app.on_message(filters.command("ping", prefixes=".") & filters.me) 689 | async def ping_command(client: Client, message: Message): 690 | start = datetime.now() 691 | msg = await message.edit_text("Pinging...") 692 | end = datetime.now() 693 | latency = (end - start).microseconds / 1000 694 | await msg.edit_text(f"**Pong!** `{latency}ms`") 695 | 696 | @app.on_message(filters.command("alive", prefixes=".") & filters.me) 697 | async def alive_command(client: Client, message: Message): 698 | uptime = datetime.now() - client.start_time if hasattr(client, 'start_time') else "Unknown" 699 | await message.edit_text(f"**🚀 ULTRA USERBOT IS ALIVE!**\n⏱️ Uptime: {uptime}") 700 | 701 | @app.on_message(filters.command("id", prefixes=".") & filters.me) 702 | async def id_command(client: Client, message: Message): 703 | chat_id = message.chat.id 704 | if message.reply_to_message: 705 | user_id = message.reply_to_message.from_user.id 706 | await message.edit_text(f"**User ID:** `{user_id}`\n**Chat ID:** `{chat_id}`") 707 | else: 708 | await message.edit_text(f"**Chat ID:** `{chat_id}`") 709 | 710 | @app.on_message(filters.command("ban", prefixes=".") & filters.me) 711 | async def ban_user(client: Client, message: Message): 712 | if not await check_admin(client, message.chat.id, client.me.id): 713 | return await message.edit_text("I'm not admin here!") 714 | 715 | user_id = None 716 | if message.reply_to_message: 717 | user_id = message.reply_to_message.from_user.id 718 | elif len(message.command) > 1: 719 | user_id = message.command[1] 720 | else: 721 | return await message.edit_text("Reply to user or provide user ID") 722 | 723 | try: 724 | await client.ban_chat_member(message.chat.id, user_id) 725 | await message.edit_text(f"**Banned** {user_id}!") 726 | except Exception as e: 727 | await message.edit_text(f"Error: {str(e)}") 728 | 729 | @app.on_message(filters.command("kick", prefixes=".") & filters.me) 730 | async def kick_user(client: Client, message: Message): 731 | if not await check_admin(client, message.chat.id, client.me.id): 732 | return await message.edit_text("I'm not admin here!") 733 | 734 | user_id = None 735 | if message.reply_to_message: 736 | user_id = message.reply_to_message.from_user.id 737 | elif len(message.command) > 1: 738 | user_id = message.command[1] 739 | else: 740 | return await message.edit_text("Reply to user or provide user ID") 741 | 742 | try: 743 | await client.ban_chat_member(message.chat.id, user_id) 744 | await client.unban_chat_member(message.chat.id, user_id) 745 | await message.edit_text(f"**Kicked** {user_id}!") 746 | except Exception as e: 747 | await message.edit_text(f"Error: {str(e)}") 748 | 749 | @app.on_message(filters.command("unban", prefixes=".") & filters.me) 750 | async def unban_user(client: Client, message: Message): 751 | if not await check_admin(client, message.chat.id, client.me.id): 752 | return await message.edit_text("I'm not admin here!") 753 | 754 | if len(message.command) < 2: 755 | return await message.edit_text("Provide user ID to unban") 756 | 757 | user_id = message.command[1] 758 | try: 759 | await client.unban_chat_member(message.chat.id, user_id) 760 | await message.edit_text(f"**Unbanned** {user_id}!") 761 | except Exception as e: 762 | await message.edit_text(f"Error: {str(e)}") 763 | 764 | ROLES = { 765 | "owner": {"full": True, "emoji": "🔴", "desc": "Full control access"}, 766 | "admin": {"full": True, "emoji": "🟠", "desc": "Administrative privileges"}, 767 | "mod": { 768 | "can_delete_messages": True, 769 | "can_restrict_members": True, 770 | "can_pin_messages": True, 771 | "emoji": "🟡", "desc": "Moderation access" 772 | }, 773 | "helper": { 774 | "can_invite_users": True, 775 | "can_pin_messages": True, 776 | "emoji": "🟢", "desc": "Basic assistance" 777 | }, 778 | "manager": { 779 | "can_delete_messages": True, 780 | "can_manage_video_chats": True, 781 | "can_change_info": True, 782 | "emoji": "🔵", "desc": "Content management" 783 | } 784 | } 785 | 786 | def get_privileges(role: str) -> ChatPrivileges: 787 | """Get privileges for role""" 788 | config = ROLES.get(role.lower(), ROLES["admin"]) 789 | 790 | if config.get("full"): 791 | return ChatPrivileges( 792 | can_manage_chat=True, can_change_info=True, can_post_messages=True, 793 | can_edit_messages=True, can_delete_messages=True, can_invite_users=True, 794 | can_restrict_members=True, can_pin_messages=True, can_promote_members=True, 795 | can_manage_video_chats=True 796 | ) 797 | 798 | return ChatPrivileges(**{k: v for k, v in config.items() if k not in ["emoji", "desc"]}) 799 | 800 | def format_message(action: str, role: str, user_id: int, success: bool = True) -> str: 801 | """Format response message""" 802 | if not success: 803 | return f"❌ **{action.title()} failed**" 804 | 805 | config = ROLES.get(role.lower(), ROLES["admin"]) 806 | emoji = config["emoji"] 807 | 808 | if action == "promote": 809 | return f"{emoji} **{role.upper()}** promoted `{user_id}`\n**{config['desc']}**" 810 | else: 811 | return f"⚫ **DEMOTED** `{user_id}`\n**All privileges removed**" 812 | 813 | 814 | def parse_args(message: Message) -> tuple[Optional[int], str]: 815 | """Parse command arguments""" 816 | user_id, role = None, "admin" 817 | 818 | if message.reply_to_message: 819 | user_id = message.reply_to_message.from_user.id 820 | if len(message.command) > 1: 821 | role = message.command[1] 822 | elif len(message.command) > 1: 823 | try: 824 | user_id = int(message.command[1]) 825 | role = message.command[2] if len(message.command) > 2 else "admin" 826 | except ValueError: 827 | return None, role 828 | 829 | return user_id, role 830 | 831 | @app.on_message(filters.command("promote", prefixes=".") & filters.me) 832 | async def promote_user(client: Client, message: Message): 833 | """Promote user with admin role""" 834 | if not await check_admin(client, message.chat.id, client.me.id): 835 | return await message.edit_text("❌ No admin permissions") 836 | 837 | user_id, role = parse_args(message) 838 | if not user_id: 839 | roles_list = "\n".join([f"• `{k}` {v['emoji']} - {v['desc']}" for k, v in ROLES.items()]) 840 | return await message.edit_text(f"**Usage:** `.promote [user_id] [role]`\n\n**Roles:**\n{roles_list}") 841 | 842 | try: 843 | privileges = get_privileges(role) 844 | await client.promote_chat_member(message.chat.id, user_id, privileges) 845 | await client.set_administrator_title(message.chat.id, user_id, role.title()) 846 | await message.edit_text(format_message("promote", role, user_id)) 847 | except Exception as e: 848 | await message.edit_text(f"❌ Error: `{str(e)}`") 849 | 850 | @app.on_message(filters.command("demote", prefixes=".") & filters.me) 851 | async def demote_user(client: Client, message: Message): 852 | """Remove admin privileges""" 853 | if not await check_admin(client, message.chat.id, client.me.id): 854 | return await message.edit_text("❌ No admin permissions") 855 | 856 | user_id = None 857 | if message.reply_to_message: 858 | user_id = message.reply_to_message.from_user.id 859 | elif len(message.command) > 1: 860 | try: 861 | user_id = int(message.command[1]) 862 | except ValueError: 863 | pass 864 | 865 | if not user_id: 866 | return await message.edit_text("**Usage:** `.demote [user_id]` or reply to message") 867 | 868 | try: 869 | await client.promote_chat_member(message.chat.id, user_id, ChatPrivileges()) 870 | await client.set_administrator_title(message.chat.id, user_id, "") 871 | await message.edit_text(format_message("demote", "", user_id)) 872 | except Exception as e: 873 | await message.edit_text(f"❌ Error: `{str(e)}`") 874 | 875 | @app.on_message(filters.command("roles", prefixes=".") & filters.me) 876 | async def show_roles(client: Client, message: Message): 877 | """Show available admin roles""" 878 | roles_text = "**🎭 Available Roles:**\n\n" 879 | for role, config in ROLES.items(): 880 | roles_text += f"{config['emoji']} **{role.upper()}**\n**{config['desc']}**\n\n" 881 | 882 | roles_text += "**Usage:** `.promote `" 883 | await message.edit_text(roles_text) 884 | 885 | 886 | @app.on_message(filters.command("pin", prefixes=".") & filters.me) 887 | async def pin_message(client: Client, message: Message): 888 | if not await check_admin(client, message.chat.id, client.me.id): 889 | return await message.edit_text("I'm not admin here!") 890 | 891 | if not message.reply_to_message: 892 | return await message.edit_text("Reply to a message to pin") 893 | 894 | try: 895 | await client.pin_chat_message( 896 | message.chat.id, 897 | message.reply_to_message.id, 898 | disable_notification=False 899 | ) 900 | await message.edit_text("**Pinned!**") 901 | except Exception as e: 902 | await message.edit_text(f"Error: {str(e)}") 903 | 904 | 905 | @app.on_message(filters.command("keepservice", prefixes=".") & filters.me) 906 | async def manage_keep_service(client: Client, message: Message): 907 | global KEEP_SERVICE_TYPES 908 | args = message.command[1:] if len(message.command) > 1 else [] 909 | if not args: 910 | if KEEP_SERVICE_TYPES: 911 | keep_list = "🛡️ **Protected Service Types:**\n" 912 | for service_type in sorted(KEEP_SERVICE_TYPES): 913 | keep_list += f"• `{service_type}`\n" 914 | keep_list += f"\n📊 **Total Protected:** {len(KEEP_SERVICE_TYPES)} types" 915 | else: 916 | keep_list = "❌ **No service types are protected**\nAll service messages will be deleted" 917 | status = "✅ ENABLED" if SERVICE_DELETION_ENABLED else "❌ DISABLED" 918 | await message.edit_text( 919 | f"🔧 **Service Deletion Status:** {status}\n\n" 920 | f"{keep_list}\n\n" 921 | f"**📝 Usage:**\n" 922 | f"• `.keepservice pin voice` - Protect pin and voice messages\n" 923 | f"• `.keepservice -pin` - Remove pin from protection\n" 924 | f"• `.keepservice clear` - Remove all protections\n" 925 | f"• `.keepservice list` - Show all available types\n" 926 | f"• `.delservice` - Toggle auto-deletion on/off" 927 | ) 928 | return 929 | if args[0].lower() == "list": 930 | type_list = "📋 **Available Service Types:**\n\n" 931 | for service_name, patterns in SERVICE_TYPE_MAP.items(): 932 | description = { 933 | 'join': 'User joined group', 934 | 'left': 'User left group', 935 | 'pin': 'Message pinned/unpinned', 936 | 'photo': 'Group photo changed', 937 | 'name': 'Group name changed', 938 | 'voice': 'Voice chat started/ended', 939 | 'video': 'Video chat events', 940 | 'description': 'Group description changed', 941 | 'migrate': 'Group migrated', 942 | 'boost': 'Group boosted', 943 | 'background': 'Chat background changed', 944 | 'forum': 'Forum topic events', 945 | 'payment': 'Payment messages', 946 | 'game': 'Game score messages', 947 | 'contact': 'Contact registered' 948 | }.get(service_name, 'Other service message') 949 | protected = "🛡️" if service_name in KEEP_SERVICE_TYPES else "🗑️" 950 | type_list += f"{protected} `{service_name}` - {description}\n" 951 | type_list += f"\n**Legend:** 🛡️ Protected | 🗑️ Will be deleted" 952 | await message.edit_text(type_list) 953 | return 954 | if args[0].lower() == "clear": 955 | KEEP_SERVICE_TYPES.clear() 956 | await message.edit_text( 957 | "🧹 **All service type protections cleared!**\n\n" 958 | "❌ All service messages will now be deleted automatically" 959 | ) 960 | return 961 | added = [] 962 | removed = [] 963 | invalid = [] 964 | for arg in args: 965 | if arg.startswith('-'): 966 | service_type = arg[1:].lower() 967 | if service_type in KEEP_SERVICE_TYPES: 968 | KEEP_SERVICE_TYPES.remove(service_type) 969 | removed.append(service_type) 970 | else: 971 | invalid.append(f"'{service_type}' (not in keep list)") 972 | else: 973 | service_type = arg.lower() 974 | if service_type in SERVICE_TYPE_MAP: 975 | KEEP_SERVICE_TYPES.add(service_type) 976 | added.append(service_type) 977 | else: 978 | invalid.append(f"'{service_type}' (unknown type)") 979 | response = "🔧 **Service Keep List Updated!**\n\n" 980 | if added: 981 | response += f"✅ **Added to protection:**\n" 982 | for item in added: 983 | response += f"• `{item}`\n" 984 | response += "\n" 985 | if removed: 986 | response += f"❌ **Removed from protection:**\n" 987 | for item in removed: 988 | response += f"• `{item}`\n" 989 | response += "\n" 990 | if invalid: 991 | response += f"⚠️ **Invalid items:**\n" 992 | for item in invalid: 993 | response += f"• {item}\n" 994 | response += "\n" 995 | if KEEP_SERVICE_TYPES: 996 | response += f"🛡️ **Currently protected:** {', '.join(sorted(KEEP_SERVICE_TYPES))}" 997 | else: 998 | response += "❌ **No protections active** - All service messages will be deleted" 999 | await message.edit_text(response) 1000 | 1001 | @app.on_message(filters.command("delservice", prefixes=".") & filters.me) 1002 | async def toggle_service_deletion(client: Client, message: Message): 1003 | global SERVICE_DELETION_ENABLED 1004 | args = message.command[1:] if len(message.command) > 1 else [] 1005 | if args: 1006 | arg = args[0].lower() 1007 | if arg in ['on', 'enable', 'true', '1']: 1008 | SERVICE_DELETION_ENABLED = True 1009 | elif arg in ['off', 'disable', 'false', '0']: 1010 | SERVICE_DELETION_ENABLED = False 1011 | else: 1012 | return await message.edit_text( 1013 | "❌ **Invalid argument!**\n\n" 1014 | "**Usage:**\n" 1015 | "• `.delservice` - Toggle on/off\n" 1016 | "• `.delservice on` - Force enable\n" 1017 | "• `.delservice off` - Force disable" 1018 | ) 1019 | else: 1020 | SERVICE_DELETION_ENABLED = not SERVICE_DELETION_ENABLED 1021 | status = "✅ ENABLED" if SERVICE_DELETION_ENABLED else "❌ DISABLED" 1022 | emoji = "🗑️" if SERVICE_DELETION_ENABLED else "⏸️" 1023 | protected_info = "" 1024 | if KEEP_SERVICE_TYPES and SERVICE_DELETION_ENABLED: 1025 | protected_info = f"\n\n🛡️ **Protected types:** {', '.join(sorted(KEEP_SERVICE_TYPES))}" 1026 | elif SERVICE_DELETION_ENABLED: 1027 | protected_info = f"\n\n❌ **No protections** - All service messages will be deleted" 1028 | await message.edit_text( 1029 | f"{emoji} **Auto Service Message Deletion:** {status}\n\n" 1030 | f"{'🔄 Service messages will be automatically deleted' if SERVICE_DELETION_ENABLED else '⏸️ Service messages will NOT be deleted'}" 1031 | f"{protected_info}\n\n" 1032 | f"**💡 Quick Commands:**\n" 1033 | f"• `.keepservice pin voice` - Protect pin & voice messages\n" 1034 | f"• `.keepservice list` - See all available types\n" 1035 | f"• `.delservice` - Toggle this setting" 1036 | ) 1037 | 1038 | @app.on_message(filters.service & ~filters.me) 1039 | async def auto_delete_service_messages(client: Client, message: Message): 1040 | global SERVICE_DELETION_ENABLED, KEEP_SERVICE_TYPES 1041 | if not SERVICE_DELETION_ENABLED: 1042 | return 1043 | service_type = get_service_type(message) 1044 | if not service_type: 1045 | return 1046 | if service_type in KEEP_SERVICE_TYPES: 1047 | print(f"🛡️ Keeping {service_type} service message (protected)") 1048 | return 1049 | try: 1050 | await message.delete() 1051 | print(f"🗑️ Auto-deleted {service_type} service message") 1052 | except Exception as e: 1053 | print(f"❌ Failed to delete {service_type} service message: {e}") 1054 | 1055 | @app.on_message(filters.command("servicestatus", prefixes=".") & filters.me) 1056 | async def show_service_status(client: Client, message: Message): 1057 | global SERVICE_DELETION_ENABLED, KEEP_SERVICE_TYPES 1058 | status = "✅ ENABLED" if SERVICE_DELETION_ENABLED else "❌ DISABLED" 1059 | if KEEP_SERVICE_TYPES: 1060 | protected = f"🛡️ **Protected:** {', '.join(sorted(KEEP_SERVICE_TYPES))}" 1061 | else: 1062 | protected = "❌ **No protected types** (all will be deleted)" 1063 | await message.edit_text( 1064 | f"📊 **Service Message Settings**\n\n" 1065 | f"🔧 **Auto-Deletion:** {status}\n" 1066 | f"{protected}\n\n" 1067 | f"**📝 Commands:**\n" 1068 | f"• `.delservice` - Toggle auto-deletion\n" 1069 | f"• `.keepservice pin voice` - Protect specific types\n" 1070 | f"• `.keepservice list` - Show all available types" 1071 | ) 1072 | 1073 | 1074 | @app.on_message(filters.command("unpin", prefixes=".") & filters.me) 1075 | async def unpin_message(client: Client, message: Message): 1076 | if not await check_admin(client, message.chat.id, client.me.id): 1077 | return await message.edit_text("I'm not admin here!") 1078 | 1079 | if not message.reply_to_message: 1080 | return await message.edit_text("Reply to a pinned message to unpin") 1081 | 1082 | try: 1083 | await client.unpin_chat_message( 1084 | message.chat.id, 1085 | message.reply_to_message.id 1086 | ) 1087 | await message.edit_text("**Unpinned!**") 1088 | except Exception as e: 1089 | await message.edit_text(f"Error: {str(e)}") 1090 | 1091 | @app.on_message(filters.command("mute", prefixes=".") & filters.me) 1092 | async def mute_user(client: Client, message: Message): 1093 | if not await check_admin(client, message.chat.id, client.me.id): 1094 | return await message.edit_text("I'm not admin here!") 1095 | 1096 | user_id = None 1097 | mute_time = 0 1098 | 1099 | if message.reply_to_message: 1100 | user_id = message.reply_to_message.from_user.id 1101 | if len(message.command) > 1: 1102 | time_str = message.command[1] 1103 | 1104 | if time_str[-1] == 'm': 1105 | mute_time = int(time_str[:-1]) * 60 1106 | elif time_str[-1] == 'h': 1107 | mute_time = int(time_str[:-1]) * 3600 1108 | elif time_str[-1] == 'd': 1109 | mute_time = int(time_str[:-1]) * 86400 1110 | else: 1111 | mute_time = int(time_str) 1112 | elif len(message.command) > 2: 1113 | user_id = message.command[1] 1114 | time_str = message.command[2] 1115 | if time_str[-1] == 'm': 1116 | mute_time = int(time_str[:-1]) * 60 1117 | elif time_str[-1] == 'h': 1118 | mute_time = int(time_str[:-1]) * 3600 1119 | elif time_str[-1] == 'd': 1120 | mute_time = int(time_str[:-1]) * 86400 1121 | else: 1122 | mute_time = int(time_str) 1123 | elif len(message.command) > 1: 1124 | user_id = message.command[1] 1125 | else: 1126 | return await message.edit_text("Reply to user or provide user ID and optional time") 1127 | 1128 | try: 1129 | until_date = int(time.time() + mute_time) if mute_time > 0 else 0 1130 | await client.restrict_chat_member( 1131 | message.chat.id, 1132 | user_id, 1133 | permissions=client.get_chat(message.chat.id).permissions, 1134 | until_date=until_date 1135 | ) 1136 | time_text = f" for {mute_time//3600}h {mute_time%3600//60}m" if mute_time > 0 else "" 1137 | await message.edit_text(f"**Muted** {user_id}{time_text}!") 1138 | except Exception as e: 1139 | await message.edit_text(f"Error: {str(e)}") 1140 | 1141 | @app.on_message(filters.command("unmute", prefixes=".") & filters.me) 1142 | async def unmute_user(client: Client, message: Message): 1143 | if not await check_admin(client, message.chat.id, client.me.id): 1144 | return await message.edit_text("I'm not admin here!") 1145 | 1146 | user_id = None 1147 | if message.reply_to_message: 1148 | user_id = message.reply_to_message.from_user.id 1149 | elif len(message.command) > 1: 1150 | user_id = message.command[1] 1151 | else: 1152 | return await message.edit_text("Reply to user or provide user ID") 1153 | 1154 | try: 1155 | await client.restrict_chat_member( 1156 | message.chat.id, 1157 | user_id, 1158 | permissions=client.get_chat(message.chat.id).permissions 1159 | ) 1160 | await message.edit_text(f"**Unmuted** {user_id}!") 1161 | except Exception as e: 1162 | await message.edit_text(f"Error: {str(e)}") 1163 | 1164 | @app.on_message(filters.command("purge", prefixes=".") & filters.me) 1165 | async def purge_messages(client: Client, message: Message): 1166 | if not await check_admin(client, message.chat.id, client.me.id): 1167 | return await message.edit_text("I'm not admin here!") 1168 | 1169 | if not message.reply_to_message: 1170 | return await message.edit_text("Reply to start purging from") 1171 | 1172 | try: 1173 | start_id = message.reply_to_message.id 1174 | end_id = message.id 1175 | deleted = 0 1176 | 1177 | for i in range(start_id, end_id + 1): 1178 | try: 1179 | await client.delete_messages(message.chat.id, i) 1180 | deleted += 1 1181 | except FloodWait as e: 1182 | await asyncio.sleep(e.value) 1183 | except: 1184 | pass 1185 | 1186 | msg = await message.edit_text(f"**Purged {deleted} messages!**") 1187 | await asyncio.sleep(3) 1188 | await msg.delete() 1189 | except Exception as e: 1190 | await message.edit_text(f"Error: {str(e)}") 1191 | 1192 | @app.on_message(filters.command("del", prefixes=".") & filters.me) 1193 | async def delete_message(client: Client, message: Message): 1194 | if not message.reply_to_message: 1195 | return await message.edit_text("Reply to a message to delete") 1196 | 1197 | try: 1198 | await client.delete_messages( 1199 | message.chat.id, 1200 | [message.reply_to_message.id, message.id] 1201 | ) 1202 | except Exception as e: 1203 | await message.edit_text(f"Error: {str(e)}") 1204 | 1205 | @app.on_message(filters.command("info", prefixes=".") & filters.me) 1206 | async def user_info(client: Client, message: Message): 1207 | user_id = None 1208 | if message.reply_to_message: 1209 | user_id = message.reply_to_message.from_user.id 1210 | elif len(message.command) > 1: 1211 | user_id = message.command[1] 1212 | else: 1213 | user_id = message.from_user.id 1214 | 1215 | try: 1216 | user = await client.get_users(user_id) 1217 | chat_member = await client.get_chat_member(message.chat.id, user_id) 1218 | 1219 | info = f"**User Info:**\n" 1220 | info += f"ID: `{user.id}`\n" 1221 | info += f"Name: [{user.first_name}](tg://user?id={user.id})" 1222 | if user.last_name: 1223 | info += f" {user.last_name}" 1224 | info += "\n" 1225 | if user.username: 1226 | info += f"Username: @{user.username}\n" 1227 | info += f"Bot: {user.is_bot}\n" 1228 | info += f"Verified: {user.is_verified}\n" 1229 | info += f"Restricted: {user.is_restricted}\n" 1230 | info += f"Scam: {user.is_scam}\n" 1231 | info += f"Premium: {user.is_premium}\n" 1232 | info += f"Status: {chat_member.status.value}" 1233 | await message.edit_text(info) 1234 | except Exception as e: 1235 | await message.edit_text(f"Error: {str(e)}") 1236 | 1237 | @app.on_message(filters.command("admins", prefixes=".") & filters.me) 1238 | async def list_admins(client: Client, message: Message): 1239 | try: 1240 | admins = [] 1241 | async for admin in client.get_chat_members(message.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS): 1242 | if not admin.user.is_bot: 1243 | admins.append(f"[{admin.user.first_name}](tg://user?id={admin.user.id})") 1244 | 1245 | admin_list = "**Admins:**\n" + "\n".join(admins) 1246 | await message.edit_text(admin_list) 1247 | except Exception as e: 1248 | await message.edit_text(f"Error: {str(e)}") 1249 | 1250 | @app.on_message(filters.command("invite", prefixes=".") & filters.me) 1251 | async def invite_user(client: Client, message: Message): 1252 | if not await check_admin(client, message.chat.id, client.me.id): 1253 | return await message.edit_text("I'm not admin here!") 1254 | 1255 | if len(message.command) < 2: 1256 | return await message.edit_text("Provide user ID to invite") 1257 | 1258 | user_id = message.command[1] 1259 | try: 1260 | await client.add_chat_members(message.chat.id, [user_id]) 1261 | await message.edit_text(f"**Invited** {user_id}!") 1262 | except Exception as e: 1263 | await message.edit_text(f"Error: {str(e)}") 1264 | 1265 | @app.on_message(filters.command("stats", prefixes=".") & filters.me) 1266 | async def chat_stats(client: Client, message: Message): 1267 | try: 1268 | chat = await client.get_chat(message.chat.id) 1269 | stats = f"**Chat Stats:**\n" 1270 | stats += f"Title: {chat.title}\n" 1271 | stats += f"ID: `{chat.id}`\n" 1272 | stats += f"Members: {chat.members_count}\n" 1273 | stats += f"Type: {chat.type.value}" 1274 | await message.edit_text(stats) 1275 | except Exception as e: 1276 | await message.edit_text(f"Error: {str(e)}") 1277 | 1278 | @app.on_message(filters.command("leave", prefixes=".") & filters.me) 1279 | async def leave_chat(client: Client, message: Message): 1280 | try: 1281 | await message.edit_text("**Leaving chat...**") 1282 | await client.leave_chat(message.chat.id) 1283 | except Exception as e: 1284 | await message.edit_text(f"Error: {str(e)}") 1285 | 1286 | @app.on_message(filters.command("echo", prefixes=".") & filters.me) 1287 | async def echo_message(client: Client, message: Message): 1288 | if len(message.command) < 2: 1289 | return await message.edit_text("Provide text to echo") 1290 | 1291 | text = message.text[6:] 1292 | await message.edit_text(text) 1293 | 1294 | @app.on_message(filters.command("type", prefixes=".") & filters.me) 1295 | async def type_animation(client: Client, message: Message): 1296 | if len(message.command) < 2: 1297 | return await message.edit_text("Provide text to type") 1298 | 1299 | text = message.text[6:] 1300 | typing_text = "" 1301 | 1302 | for char in text: 1303 | typing_text += char 1304 | await message.edit_text(typing_text) 1305 | await asyncio.sleep(0.1) 1306 | 1307 | @app.on_message(filters.command("lock", prefixes=".") & filters.me) 1308 | async def lock_chat(client: Client, message: Message): 1309 | if not await check_admin(client, message.chat.id, client.me.id): 1310 | return await message.edit_text("I'm not admin here!") 1311 | 1312 | permissions = client.get_chat(message.chat.id).permissions 1313 | 1314 | 1315 | if len(message.command) > 1: 1316 | perm = message.command[1].lower() 1317 | if perm == "messages": 1318 | permissions.can_send_messages = False 1319 | elif perm == "media": 1320 | permissions.can_send_media_messages = False 1321 | elif perm == "polls": 1322 | permissions.can_send_polls = False 1323 | elif perm == "other": 1324 | permissions.can_send_other_messages = False 1325 | elif perm == "web": 1326 | permissions.can_add_web_page_previews = False 1327 | elif perm == "change": 1328 | permissions.can_change_info = False 1329 | elif perm == "invite": 1330 | permissions.can_invite_users = False 1331 | elif perm == "pin": 1332 | permissions.can_pin_messages = False 1333 | else: 1334 | return await message.edit_text("Invalid permission! Use: messages, media, polls, other, web, change, invite, pin") 1335 | else: 1336 | 1337 | permissions = client.get_chat(message.chat.id).permissions 1338 | permissions.can_send_messages = False 1339 | permissions.can_send_media_messages = False 1340 | permissions.can_send_polls = False 1341 | permissions.can_send_other_messages = False 1342 | permissions.can_add_web_page_previews = False 1343 | permissions.can_change_info = False 1344 | permissions.can_invite_users = False 1345 | permissions.can_pin_messages = False 1346 | 1347 | try: 1348 | await client.set_chat_permissions( 1349 | message.chat.id, 1350 | permissions=permissions 1351 | ) 1352 | await message.edit_text("**Chat locked!**") 1353 | except Exception as e: 1354 | await message.edit_text(f"Error: {str(e)}") 1355 | 1356 | @app.on_message(filters.command("unlock", prefixes=".") & filters.me) 1357 | async def unlock_chat(client: Client, message: Message): 1358 | if not await check_admin(client, message.chat.id, client.me.id): 1359 | return await message.edit_text("I'm not admin here!") 1360 | 1361 | chat = await client.get_chat(message.chat.id) 1362 | permissions = chat.permissions 1363 | 1364 | 1365 | if len(message.command) > 1: 1366 | perm = message.command[1].lower() 1367 | if perm == "messages": 1368 | permissions.can_send_messages = chat.permissions.can_send_messages or True 1369 | elif perm == "media": 1370 | permissions.can_send_media_messages = chat.permissions.can_send_media_messages or True 1371 | elif perm == "polls": 1372 | permissions.can_send_polls = chat.permissions.can_send_polls or True 1373 | elif perm == "other": 1374 | permissions.can_send_other_messages = chat.permissions.can_send_other_messages or True 1375 | elif perm == "web": 1376 | permissions.can_add_web_page_previews = chat.permissions.can_add_web_page_previews or True 1377 | elif perm == "change": 1378 | permissions.can_change_info = chat.permissions.can_change_info or True 1379 | elif perm == "invite": 1380 | permissions.can_invite_users = chat.permissions.can_invite_users or True 1381 | elif perm == "pin": 1382 | permissions.can_pin_messages = chat.permissions.can_pin_messages or True 1383 | else: 1384 | return await message.edit_text("Invalid permission! Use: messages, media, polls, other, web, change, invite, pin") 1385 | else: 1386 | 1387 | permissions = client.get_chat(message.chat.id).permissions 1388 | 1389 | try: 1390 | await client.set_chat_permissions( 1391 | message.chat.id, 1392 | permissions=permissions 1393 | ) 1394 | await message.edit_text("**Chat unlocked!**") 1395 | except Exception as e: 1396 | await message.edit_text(f"Error: {str(e)}") 1397 | 1398 | @app.on_message(filters.command("bots", prefixes=".") & filters.me) 1399 | async def list_bots(client: Client, message: Message): 1400 | try: 1401 | bots = [] 1402 | async for member in client.get_chat_members(message.chat.id, filter=enums.ChatMembersFilter.BOTS): 1403 | bots.append(f"[{member.user.first_name}](tg://user?id={member.user.id})") 1404 | 1405 | if bots: 1406 | bot_list = "**Bots in chat:**\n" + "\n".join(bots) 1407 | else: 1408 | bot_list = "**No bots in chat**" 1409 | await message.edit_text(bot_list) 1410 | except Exception as e: 1411 | await message.edit_text(f"Error: {str(e)}") 1412 | 1413 | @app.on_message(filters.command("users", prefixes=".") & filters.me) 1414 | async def list_users(client: Client, message: Message): 1415 | try: 1416 | users = [] 1417 | async for member in client.get_chat_members(message.chat.id): 1418 | if not member.user.is_bot: 1419 | users.append(f"[{member.user.first_name}](tg://user?id={member.user.id})") 1420 | 1421 | if len(users) > 50: 1422 | users = users[:50] 1423 | user_list = f"**First 50 users in chat:**\n" + "\n".join(users) 1424 | else: 1425 | user_list = f"**Users in chat ({len(users)}):**\n" + "\n".join(users) 1426 | await message.edit_text(user_list) 1427 | except Exception as e: 1428 | await message.edit_text(f"Error: {str(e)}") 1429 | 1430 | @app.on_message(filters.command("zombies", prefixes=".") & filters.me) 1431 | async def find_zombies(client: Client, message: Message): 1432 | if not await check_admin(client, message.chat.id, client.me.id): 1433 | return await message.edit_text("I'm not admin here!") 1434 | 1435 | try: 1436 | zombies = [] 1437 | async for member in client.get_chat_members(message.chat.id): 1438 | if member.user.is_deleted: 1439 | zombies.append(str(member.user.id)) 1440 | 1441 | if zombies: 1442 | zombie_list = "**Deleted accounts found:**\n" + "\n".join([f"`{id}`" for id in zombies[:10]]) 1443 | if len(zombies) > 10: 1444 | zombie_list += f"\n\nAnd {len(zombies) - 10} more..." 1445 | else: 1446 | zombie_list = "**No deleted accounts found**" 1447 | await message.edit_text(zombie_list) 1448 | except Exception as e: 1449 | await message.edit_text(f"Error: {str(e)}") 1450 | 1451 | @app.on_message(filters.command("settitle", prefixes=".") & filters.me) 1452 | async def set_chat_title(client: Client, message: Message): 1453 | if not await check_admin(client, message.chat.id, client.me.id): 1454 | return await message.edit_text("I'm not admin here!") 1455 | 1456 | if len(message.command) < 2: 1457 | return await message.edit_text("Provide a title to set") 1458 | 1459 | title = " ".join(message.command[1:]) 1460 | try: 1461 | 1462 | if message.chat.id not in chat_titles: 1463 | chat_titles[message.chat.id] = message.chat.title 1464 | 1465 | await client.set_chat_title(message.chat.id, title) 1466 | await message.edit_text(f"**Chat title changed to:** {title}") 1467 | except Exception as e: 1468 | await message.edit_text(f"**Error:** {str(e)}") 1469 | 1470 | @app.on_message(filters.command("restoretitle", prefixes=".") & filters.me) 1471 | async def restore_chat_title(client: Client, message: Message): 1472 | if not await check_admin(client, message.chat.id, client.me.id): 1473 | return await message.edit_text("I'm not admin here!") 1474 | 1475 | if message.chat.id not in chat_titles: 1476 | return await message.edit_text("No original title stored for this chat") 1477 | 1478 | try: 1479 | original_title = chat_titles[message.chat.id] 1480 | await client.set_chat_title(message.chat.id, original_title) 1481 | await message.edit_text(f"**Chat title restored to:** {original_title}") 1482 | del chat_titles[message.chat.id] 1483 | except Exception as e: 1484 | await message.edit_text(f"**Error:** {str(e)}") 1485 | 1486 | 1487 | @app.on_message(filters.command("block", prefixes=".") & filters.me) 1488 | async def block_user(client: Client, message: Message): 1489 | user_id = None 1490 | if message.reply_to_message: 1491 | user_id = message.reply_to_message.from_user.id 1492 | elif len(message.command) > 1: 1493 | user_id = message.command[1] 1494 | else: 1495 | return await message.edit_text("Reply to user or provide user ID") 1496 | 1497 | try: 1498 | await client.block_user(user_id) 1499 | blocked_users.add(str(user_id)) 1500 | save_data() 1501 | await message.edit_text(f"**Blocked** {user_id}!") 1502 | except Exception as e: 1503 | await message.edit_text(f"Error: {str(e)}") 1504 | 1505 | @app.on_message(filters.command("unblock", prefixes=".") & filters.me) 1506 | async def unblock_user(client: Client, message: Message): 1507 | if len(message.command) < 2: 1508 | return await message.edit_text("Provide user ID to unblock") 1509 | 1510 | user_id = message.command[1] 1511 | try: 1512 | await client.unblock_user(user_id) 1513 | blocked_users.discard(str(user_id)) 1514 | save_data() 1515 | await message.edit_text(f"**Unblocked** {user_id}!") 1516 | except Exception as e: 1517 | await message.edit_text(f"Error: {str(e)}") 1518 | 1519 | @app.on_message(filters.command("blocked", prefixes=".") & filters.me) 1520 | async def list_blocked(client: Client, message: Message): 1521 | if not blocked_users: 1522 | return await message.edit_text("No blocked users") 1523 | 1524 | blocked_list = "**Blocked Users:**\n" 1525 | for user_id in list(blocked_users)[:10]: 1526 | try: 1527 | user = await client.get_users(int(user_id)) 1528 | blocked_list += f"[{user.first_name}](tg://user?id={user.id}) - `{user_id}`\n" 1529 | except: 1530 | blocked_list += f"`{user_id}`\n" 1531 | 1532 | await message.edit_text(blocked_list) 1533 | 1534 | 1535 | @app.on_message(filters.command("afk", prefixes=".") & filters.me) 1536 | async def set_afk(client: Client, message: Message): 1537 | global afk_mode, afk_reason, afk_start_time 1538 | 1539 | afk_mode = True 1540 | afk_reason = " ".join(message.command[1:]) if len(message.command) > 1 else "AFK" 1541 | afk_start_time = datetime.now() 1542 | 1543 | await message.edit_text(f"**AFK Mode Activated**\nReason: {afk_reason}") 1544 | 1545 | @app.on_message(filters.command("unafk", prefixes=".") & filters.me) 1546 | async def unset_afk(client: Client, message: Message): 1547 | global afk_mode, afk_reason, afk_start_time 1548 | 1549 | afk_mode = False 1550 | afk_reason = "" 1551 | afk_start_time = None 1552 | 1553 | await message.edit_text("**AFK Mode Deactivated**") 1554 | 1555 | 1556 | @app.on_message(filters.command("autoreply", prefixes=".") & filters.me) 1557 | async def set_auto_reply(client: Client, message: Message): 1558 | if len(message.command) < 3: 1559 | return await message.edit_text("Usage: .autoreply [trigger] [response]") 1560 | 1561 | trigger = message.command[1].lower() 1562 | response = " ".join(message.command[2:]) 1563 | 1564 | auto_replies[trigger] = response 1565 | save_data() 1566 | await message.edit_text(f"Auto reply set for '{trigger}'") 1567 | 1568 | @app.on_message(filters.command("delreply", prefixes=".") & filters.me) 1569 | async def delete_auto_reply(client: Client, message: Message): 1570 | if len(message.command) < 2: 1571 | return await message.edit_text("Provide trigger to delete") 1572 | 1573 | trigger = message.command[1].lower() 1574 | if trigger in auto_replies: 1575 | del auto_replies[trigger] 1576 | save_data() 1577 | await message.edit_text(f"Deleted auto reply for '{trigger}'") 1578 | else: 1579 | await message.edit_text("Trigger not found") 1580 | 1581 | @app.on_message(filters.command("replies", prefixes=".") & filters.me) 1582 | async def list_auto_replies(client: Client, message: Message): 1583 | if not auto_replies: 1584 | return await message.edit_text("No auto replies set") 1585 | 1586 | reply_list = "**Auto Replies:**\n" 1587 | for trigger, response in auto_replies.items(): 1588 | reply_list += f"`{trigger}` → {response[:30]}{'...' if len(response) > 30 else ''}\n" 1589 | 1590 | await message.edit_text(reply_list) 1591 | 1592 | 1593 | @app.on_message(filters.regex(r"^\.save$") & filters.reply & filters.me) 1594 | async def save_media(client: Client, message: Message): 1595 | replied = message.reply_to_message 1596 | media_type = get_media_type(replied) 1597 | 1598 | if not media_type: 1599 | return 1600 | 1601 | try: 1602 | 1603 | forwarded_msg = await replied.forward("me") 1604 | message = await app.send_message("me", "saving bro!") 1605 | await asyncio.sleep(2) 1606 | await message.delete() 1607 | except Exception as e: 1608 | 1609 | try: 1610 | await message.edit_text(f"**Forward failed, downloading {media_type}...**") 1611 | 1612 | 1613 | file_path = f"{MEDIA_DIR}/{media_type}_{replied.id}" 1614 | if media_type == "photo": 1615 | downloaded_path = await client.download_media(replied.photo.file_id, file_path + ".jpg") 1616 | elif media_type == "video": 1617 | downloaded_path = await client.download_media(replied.video.file_id, file_path + ".mp4") 1618 | elif media_type == "document": 1619 | downloaded_path = await client.download_media(replied.document.file_id, file_path + ".document") 1620 | elif media_type == "audio": 1621 | downloaded_path = await client.download_media(replied.audio.file_id, file_path + ".mp3") 1622 | elif media_type == "voice": 1623 | downloaded_path = await client.download_media(replied.voice.file_id, file_path + ".ogg") 1624 | elif media_type == "animation": 1625 | downloaded_path = await client.download_media(replied.animation.file_id, file_path + ".mp4") 1626 | elif media_type == "sticker": 1627 | downloaded_path = await client.download_media(replied.sticker.file_id, file_path + ".webp") 1628 | else: 1629 | return await message.edit_text("Unsupported media type!") 1630 | 1631 | 1632 | await message.edit_text(f"**Uploading {media_type}...**") 1633 | 1634 | if media_type == "photo": 1635 | await client.send_photo("me", downloaded_path, caption="Saved media") 1636 | elif media_type == "video": 1637 | await client.send_video("me", downloaded_path, caption="Saved media") 1638 | elif media_type == "document": 1639 | await client.send_document("me", downloaded_path, caption="Saved media") 1640 | elif media_type == "audio": 1641 | await client.send_audio("me", downloaded_path, caption="Saved media") 1642 | elif media_type == "voice": 1643 | await client.send_voice("me", downloaded_path, caption="Saved media") 1644 | elif media_type == "animation": 1645 | await client.send_animation("me", downloaded_path, caption="Saved media") 1646 | elif media_type == "sticker": 1647 | await client.send_sticker("me", downloaded_path, caption="Saved media") 1648 | 1649 | 1650 | if os.path.exists(downloaded_path): 1651 | os.remove(downloaded_path) 1652 | 1653 | await message.edit_text(f"**Saved {media_type}!** (Downloaded & Uploaded)") 1654 | await asyncio.sleep(2) 1655 | await message.delete() 1656 | 1657 | except Exception as upload_error: 1658 | await message.edit_text(f"Error saving media: {str(upload_error)}") 1659 | 1660 | 1661 | @app.on_message(filters.command("setbio", prefixes=".") & filters.me) 1662 | async def set_bio(client: Client, message: Message): 1663 | if len(message.command) < 2: 1664 | return await message.edit_text("Provide bio text") 1665 | 1666 | bio = " ".join(message.command[1:]) 1667 | try: 1668 | await client.update_profile(bio=bio) 1669 | await message.edit_text("**Bio updated successfully!**") 1670 | except Exception as e: 1671 | await message.edit_text(f"**Error:** {str(e)}") 1672 | 1673 | @app.on_message(filters.command("setpic", prefixes=".") & filters.me & filters.reply) 1674 | async def set_profile_pic(client: Client, message: Message): 1675 | if not message.reply_to_message.photo: 1676 | return await message.edit_text("Reply to a photo to set as profile picture") 1677 | 1678 | try: 1679 | 1680 | file_path = await client.download_media(message.reply_to_message.photo.file_id) 1681 | 1682 | await client.set_profile_photo(photo=file_path) 1683 | 1684 | os.remove(file_path) 1685 | await message.edit_text("**Profile picture updated successfully!**") 1686 | except Exception as e: 1687 | await message.edit_text(f"**Error:** {str(e)}") 1688 | 1689 | @app.on_message(filters.command("setname", prefixes=".") & filters.me) 1690 | async def set_name(client: Client, message: Message): 1691 | if len(message.command) < 2: 1692 | return await message.edit_text("Usage: .setname [first_name] [last_name]") 1693 | 1694 | first_name = message.command[1] 1695 | last_name = " ".join(message.command[2:]) if len(message.command) > 2 else "" 1696 | 1697 | try: 1698 | await client.update_profile(first_name=first_name, last_name=last_name) 1699 | await message.edit_text("**Name updated successfully!**") 1700 | except Exception as e: 1701 | await message.edit_text(f"**Error:** {str(e)}") 1702 | 1703 | @app.on_message(filters.command("username", prefixes=".") & filters.me) 1704 | async def set_username(client: Client, message: Message): 1705 | if len(message.command) < 2: 1706 | return await message.edit_text("Usage: .username [username]") 1707 | 1708 | username = message.command[1] 1709 | try: 1710 | await client.update_username(username) 1711 | await message.edit_text("**Username updated successfully!**") 1712 | except Exception as e: 1713 | await message.edit_text(f"**Error:** {str(e)}") 1714 | 1715 | 1716 | @app.on_message(filters.command("calc", prefixes=".") & filters.me) 1717 | async def calculator(client: Client, message: Message): 1718 | 1719 | expression = "" 1720 | if len(message.command) > 1: 1721 | expression = " ".join(message.command[1:]) 1722 | elif message.reply_to_message: 1723 | 1724 | expression = message.reply_to_message.text or "" 1725 | else: 1726 | return await message.edit_text("Provide expression to calculate or reply to a message with expression") 1727 | 1728 | if not expression: 1729 | return await message.edit_text("No expression found!") 1730 | 1731 | try: 1732 | result = safe_eval(expression) 1733 | await message.edit_text(f"**Calculation:**\n{expression} = {result}") 1734 | except Exception as e: 1735 | await message.edit_text(f"Error: {str(e)}") 1736 | 1737 | @app.on_message(filters.command("short", prefixes=".") & filters.me) 1738 | async def url_shortener(client: Client, message: Message): 1739 | if len(message.command) < 2: 1740 | return await message.edit_text("Provide URL to shorten") 1741 | 1742 | url = message.command[1] 1743 | try: 1744 | 1745 | api_url = f"http://tinyurl.com/api-create.php?url={url}" 1746 | response = requests.get(api_url) 1747 | if response.status_code == 200: 1748 | short_url = response.text 1749 | await message.edit_text(f"**Shortened URL:** {short_url}") 1750 | else: 1751 | await message.edit_text("Error shortening URL") 1752 | except Exception as e: 1753 | await message.edit_text(f"Error: {str(e)}") 1754 | 1755 | @app.on_message(filters.command("qr", prefixes=".") & filters.me) 1756 | async def generate_qr(client: Client, message: Message): 1757 | if len(message.command) < 2: 1758 | return await message.edit_text("Provide text to encode") 1759 | 1760 | text = " ".join(message.command[1:]) 1761 | try: 1762 | 1763 | qr_url = f"https://api.qrserver.com/v1/create-qr-code/?data={text}&size=200x200" 1764 | 1765 | 1766 | qr_path = f"{PROFILE_PICS_DIR}/qr_{int(datetime.now().timestamp())}.png" 1767 | async with aiohttp.ClientSession() as session: 1768 | async with session.get(qr_url) as resp: 1769 | if resp.status == 200: 1770 | with open(qr_path, 'wb') as f: 1771 | f.write(await resp.read()) 1772 | 1773 | 1774 | await message.reply_photo( 1775 | qr_path, 1776 | caption=f"**QR Code for:** {text}" 1777 | ) 1778 | await message.delete() 1779 | 1780 | 1781 | os.remove(qr_path) 1782 | else: 1783 | await message.edit_text("Error generating QR code") 1784 | except Exception as e: 1785 | await message.edit_text(f"Error: {str(e)}") 1786 | 1787 | @app.on_message(filters.command("readqr", prefixes=".") & filters.me & filters.reply) 1788 | async def read_qr(client: Client, message: Message): 1789 | if not message.reply_to_message.photo: 1790 | return await message.edit_text("Reply to a QR code image") 1791 | 1792 | try: 1793 | 1794 | file_path = await client.download_media(message.reply_to_message.photo.file_id) 1795 | 1796 | 1797 | with open(file_path, 'rb') as f: 1798 | files = {'file': f} 1799 | response = requests.post("https://api.qrserver.com/v1/read-qr-code/", files=files) 1800 | 1801 | os.remove(file_path) 1802 | 1803 | if response.status_code == 200: 1804 | data = response.json() 1805 | if data[0]['symbol'][0]['data']: 1806 | decoded = data[0]['symbol'][0]['data'] 1807 | await message.edit_text(f"**Decoded QR Code:**\n{decoded}") 1808 | else: 1809 | await message.edit_text("Could not decode QR code") 1810 | else: 1811 | await message.edit_text("Error reading QR code") 1812 | except Exception as e: 1813 | await message.edit_text(f"Error: {str(e)}") 1814 | 1815 | @app.on_message(filters.command("spb", prefixes=".") & filters.me) 1816 | async def spamwatch_check(client: Client, message: Message): 1817 | if len(message.command) < 2: 1818 | user_id = message.from_user.id 1819 | else: 1820 | user_id = message.command[1] 1821 | 1822 | try: 1823 | user = await client.get_users(user_id) 1824 | await message.edit_text(f"**SpamWatch Check for {user.first_name}:**\nNot integrated yet. Please add SpamWatch API integration.") 1825 | except Exception as e: 1826 | await message.edit_text(f"Error: {str(e)}") 1827 | 1828 | @app.on_message(filters.command("whois", prefixes=".") & filters.me) 1829 | async def advanced_user_info(client: Client, message: Message): 1830 | user_id = None 1831 | if message.reply_to_message: 1832 | user_id = message.reply_to_message.from_user.id 1833 | elif len(message.command) > 1: 1834 | user_id = message.command[1] 1835 | else: 1836 | user_id = message.from_user.id 1837 | 1838 | try: 1839 | user = await client.get_users(user_id) 1840 | chat_member = await client.get_chat_member(message.chat.id, user_id) 1841 | 1842 | info = f"**Advanced User Info:**\n" 1843 | info += f"ID: `{user.id}`\n" 1844 | info += f"Name: [{user.first_name}](tg://user?id={user.id})" 1845 | if user.last_name: 1846 | info += f" {user.last_name}" 1847 | info += "\n" 1848 | if user.username: 1849 | info += f"Username: @{user.username}\n" 1850 | info += f"Bot: {user.is_bot}\n" 1851 | info += f"Verified: {user.is_verified}\n" 1852 | info += f"Restricted: {user.is_restricted}\n" 1853 | info += f"Scam: {user.is_scam}\n" 1854 | info += f"Premium: {user.is_premium}\n" 1855 | info += f"Status: {chat_member.status.value}" 1856 | await message.edit_text(info) 1857 | except Exception as e: 1858 | await message.edit_text(f"Error: {str(e)}") 1859 | 1860 | 1861 | 1862 | @app.on_message(filters.command("search", prefixes=".") & filters.me) 1863 | async def search_command(client: Client, message: Message): 1864 | if len(message.command) < 2: 1865 | return await message.edit_text("Provide search query.") 1866 | 1867 | query = " ".join(message.command[1:]) 1868 | await message.edit_text("🔍 Searching...") 1869 | 1870 | try: 1871 | links = list(google_search(query, num_results=5)) 1872 | 1873 | if not links: 1874 | return await message.edit_text("No results found.") 1875 | 1876 | first_link = links[0] 1877 | snippet = "" 1878 | 1879 | async with aiohttp.ClientSession() as session: 1880 | try: 1881 | async with session.get(first_link, timeout=10) as resp: 1882 | html = await resp.text() 1883 | soup = BeautifulSoup(html, "html.parser") 1884 | texts = soup.stripped_strings 1885 | combined_text = " ".join(texts) 1886 | snippet = combined_text[:1000] 1887 | except Exception as e: 1888 | snippet = f"Could not scrape the first link: {e}" 1889 | 1890 | result_text = f"**🔎 Search Results for:** `{query}`\n\n" 1891 | result_text += f"**📄 Snippet from:** [First Link]({first_link})\n" 1892 | result_text += f"```{snippet}```\n\n" 1893 | result_text += "**🔗 Other Results:**\n" 1894 | for i, link in enumerate(links[1:], start=2): 1895 | result_text += f"{i}. {link}\n" 1896 | 1897 | await message.edit_text(result_text, disable_web_page_preview=True) 1898 | 1899 | except Exception as e: 1900 | await message.edit_text(f"Error: {str(e)}") 1901 | 1902 | 1903 | @app.on_message(filters.command("tr", prefixes=".") & filters.me) 1904 | async def ggn_translate(client: Client, message: Message): 1905 | args = message.command[1:] if len(message.command) > 1 else [] 1906 | target_lang = "en" 1907 | mode = "single" 1908 | batch_count = 3 1909 | custom_text = "" 1910 | auto_detect = False 1911 | 1912 | if not args: 1913 | mode = "single" 1914 | elif len(args) == 1: 1915 | if args[0].lower() in ["batch", "b"]: 1916 | mode = "batch" 1917 | elif args[0].lower() in ["quick", "q"]: 1918 | mode = "quick" 1919 | elif args[0].lower() == "auto": 1920 | auto_detect = True 1921 | else: 1922 | target_lang = args[0] 1923 | elif len(args) >= 2: 1924 | if args[0].lower() in ["batch", "b"]: 1925 | mode = "batch" 1926 | target_lang = args[1] 1927 | if len(args) > 2: 1928 | try: 1929 | batch_count = min(int(args[2]), 10) 1930 | except: 1931 | batch_count = 3 1932 | elif args[0].lower() in ["quick", "q"]: 1933 | mode = "quick" 1934 | target_lang = args[1] 1935 | elif args[0].lower() == "auto": 1936 | auto_detect = True 1937 | target_lang = args[1] 1938 | else: 1939 | target_lang = args[0] 1940 | custom_text = " ".join(args[1:]) 1941 | mode = "single" 1942 | 1943 | text_to_translate = "" 1944 | if custom_text: 1945 | text_to_translate = custom_text 1946 | elif message.reply_to_message and message.reply_to_message.text: 1947 | text_to_translate = message.reply_to_message.text 1948 | elif mode == "single": 1949 | return await message.edit_text( 1950 | "**🔤 Universal Translator Usage:**\n\n" 1951 | "**Single Translation:**\n" 1952 | "• `.tr` - Translate replied message to English\n" 1953 | "• `.tr es` - Translate replied message to Spanish\n" 1954 | "• `.tr fr Hello` - Translate 'Hello' to French\n\n" 1955 | "**Batch Translation:**\n" 1956 | "• `.tr batch` - Translate last 3 messages to English\n" 1957 | "• `.tr batch es 5` - Translate last 5 messages to Spanish\n\n" 1958 | "**Quick Translation:**\n" 1959 | "• `.tr quick` - Quick translate recent messages to English\n" 1960 | "• `.tr quick fr` - Quick translate recent messages to French\n\n" 1961 | "**Auto Detection:**\n" 1962 | "• `.tr auto` - Auto-detect language and translate to English\n" 1963 | "• `.tr auto es` - Auto-detect and translate to Spanish" 1964 | ) 1965 | 1966 | status_msg = { 1967 | "batch": f"🔄 Collecting last {batch_count} messages for batch translation to {target_lang.upper()}...", 1968 | "quick": f"🚀 Quick translating recent messages to {target_lang.upper()}...", 1969 | }.get(mode, f"🔤 Translating to {target_lang.upper()}...") 1970 | 1971 | await message.edit_text(status_msg) 1972 | 1973 | try: 1974 | translator_services = [] 1975 | try: 1976 | from deep_translator import GoogleTranslator 1977 | translator_services.append(("Google", GoogleTranslator)) 1978 | except: pass 1979 | try: 1980 | from deep_translator import MyMemoryTranslator 1981 | translator_services.append(("MyMemory", MyMemoryTranslator)) 1982 | except: pass 1983 | try: 1984 | from deep_translator import LibreTranslator 1985 | translator_services.append(("Libre", LibreTranslator)) 1986 | except: pass 1987 | if not translator_services: 1988 | return await message.edit_text("❌ No translation services available. Install: `pip install deep-translator`") 1989 | if mode == "single": 1990 | await handle_single_translation(message, text_to_translate, target_lang, auto_detect, translator_services) 1991 | elif mode == "batch": 1992 | await handle_batch_translation(client, message, target_lang, batch_count, translator_services) 1993 | elif mode == "quick": 1994 | await handle_quick_translation(client, message, target_lang, translator_services) 1995 | except Exception as e: 1996 | await message.edit_text(f"❌ Translation failed: {str(e)}") 1997 | 1998 | 1999 | async def handle_single_translation(message, text, target_lang, auto_detect, translator_services): 2000 | if not text: 2001 | return await message.edit_text("❌ No text to translate!") 2002 | for service_name, TranslatorClass in translator_services: 2003 | try: 2004 | if auto_detect: 2005 | detector = TranslatorClass(source='auto', target='en') 2006 | detected_lang = detector.detect(text) 2007 | if detected_lang == target_lang: 2008 | return await message.edit_text( 2009 | f"✅ **Text is already in {target_lang.upper()}**\n\n" 2010 | f"📝 **Text:** {text}\n" 2011 | f"🔍 **Detected Language:** {detected_lang}" 2012 | ) 2013 | translator = TranslatorClass(source='auto', target=target_lang, base_url='https://libretranslate.de') if service_name == "Libre" else TranslatorClass(source='auto', target=target_lang) 2014 | translated_text = translator.translate(text) 2015 | try: 2016 | detected_lang = translator.detect(text) if hasattr(translator, 'detect') else TranslatorClass(source='auto', target='en').detect(text) 2017 | except: 2018 | detected_lang = "auto" 2019 | result = ( 2020 | f"✅ **Translated to {target_lang.upper()}:**\n" 2021 | f"{translated_text}\n\n" 2022 | f"🔍 **Detected Language:** {detected_lang}\n" 2023 | f"🔧 **Service:** {service_name}" 2024 | ) 2025 | if len(text) > 100: 2026 | result += f"\n\n📝 **Original:** {text[:200]}{'...' if len(text) > 200 else ''}" 2027 | return await message.edit_text(result) 2028 | except: 2029 | continue 2030 | await message.edit_text("❌ All translation services failed. Please try again later.") 2031 | 2032 | 2033 | async def handle_batch_translation(client, message, target_lang, count, translator_services): 2034 | service_name, TranslatorClass = translator_services[0] 2035 | try: 2036 | translator = TranslatorClass(source='auto', target=target_lang, base_url='https://libretranslate.de') if service_name == "Libre" else TranslatorClass(source='auto', target=target_lang) 2037 | except: 2038 | return await message.edit_text("❌ Failed to initialize translator") 2039 | messages_to_translate = [] 2040 | try: 2041 | async for msg in client.get_chat_history(message.chat.id, limit=50): 2042 | if msg.text and len(messages_to_translate) < count and msg.id != message.id: 2043 | messages_to_translate.append({'text': msg.text, 'sender': msg.from_user.first_name if msg.from_user else "Unknown", 'id': msg.id}) 2044 | if len(messages_to_translate) >= count: 2045 | break 2046 | except Exception as e: 2047 | return await message.edit_text(f"❌ Failed to get chat history: {str(e)}") 2048 | if not messages_to_translate: 2049 | return await message.edit_text("❌ No messages found to translate") 2050 | messages_to_translate.reverse() 2051 | await message.edit_text(f"🔄 Translating {len(messages_to_translate)} messages to {target_lang.upper()}...") 2052 | translated_batch = [] 2053 | for i, msg_data in enumerate(messages_to_translate): 2054 | try: 2055 | translated = translator.translate(msg_data['text']) 2056 | preview = msg_data['text'][:80] + "..." if len(msg_data['text']) > 80 else msg_data['text'] 2057 | translated_batch.append(f"**{i+1}. {msg_data['sender']}:**\n📝 {preview}\n🔄 **{translated}**\n") 2058 | except: 2059 | translated_batch.append(f"**{i+1}. {msg_data['sender']}:** ❌ Translation failed\n") 2060 | result = f"📚 **Batch Translation to {target_lang.upper()}:**\n\n" + "\n".join(translated_batch) + f"\n🔧 **Service:** {service_name}" 2061 | if len(result) > 4000: 2062 | parts, part_num, current = [], 1, f"📚 **Batch Translation to {target_lang.upper()}:** (Part 1)\n\n" 2063 | for t in translated_batch: 2064 | if len(current + t) > 3500: 2065 | parts.append(current) 2066 | part_num += 1 2067 | current = f"📚 **Part {part_num}:**\n\n" + t 2068 | else: 2069 | current += t 2070 | if current: 2071 | parts.append(current) 2072 | await message.edit_text(parts[0]) 2073 | for part in parts[1:]: 2074 | await message.reply_text(part) 2075 | else: 2076 | await message.edit_text(result) 2077 | 2078 | 2079 | async def handle_quick_translation(client, message, target_lang, translator_services): 2080 | service_name, TranslatorClass = translator_services[0] 2081 | try: 2082 | translator = TranslatorClass(source='auto', target=target_lang, base_url='https://libretranslate.de') if service_name == "Libre" else TranslatorClass(source='auto', target=target_lang) 2083 | except: 2084 | return await message.edit_text("❌ Failed to initialize translator") 2085 | recent_messages = [] 2086 | try: 2087 | async for msg in client.get_chat_history(message.chat.id, limit=10): 2088 | if msg.text and msg.id != message.id and len(recent_messages) < 3: 2089 | recent_messages.append(msg.text) 2090 | except Exception as e: 2091 | return await message.edit_text(f"❌ Failed to get recent messages: {str(e)}") 2092 | if not recent_messages: 2093 | return await message.edit_text("❌ No recent messages to translate") 2094 | recent_messages.reverse() 2095 | translated_messages = [] 2096 | for i, text in enumerate(recent_messages): 2097 | try: 2098 | translated = translator.translate(text) 2099 | translated_messages.append(f"**{i+1}.** {translated}") 2100 | except: 2101 | translated_messages.append(f"**{i+1}.** ❌ Translation failed") 2102 | result = f"🚀 **Quick Translation to {target_lang.upper()}:**\n\n" + "\n\n".join(translated_messages) + f"\n\n🔧 **Service:** {service_name}" 2103 | await message.edit_text(result) 2104 | 2105 | 2106 | @app.on_message(filters.command("wiki", prefixes=".") & filters.me) 2107 | async def wikipedia_search(client: Client, message: Message): 2108 | if len(message.command) < 2: 2109 | return await message.edit_text("Provide search query") 2110 | 2111 | query = " ".join(message.command[1:]) 2112 | try: 2113 | import wikipedia 2114 | result = wikipedia.summary(query, sentences=3) 2115 | await message.edit_text(f"**Wikipedia:** `{query}`\n\n{result}") 2116 | except Exception as e: 2117 | await message.edit_text(f"Error: {str(e)}") 2118 | 2119 | @app.on_message(filters.command("img", prefixes=".") & filters.me) 2120 | async def image_search(client: Client, message: Message): 2121 | if len(message.command) < 2: 2122 | return await message.edit_text("Provide search query") 2123 | 2124 | query = " ".join(message.command[1:]) 2125 | try: 2126 | url = f"https://api.unsplash.com/photos/random?query={query}&count=5&client_id={api_key}" 2127 | 2128 | async with aiohttp.ClientSession() as session: 2129 | async with session.get(url) as resp: 2130 | if resp.status == 200: 2131 | data = await resp.json() 2132 | images = [] 2133 | for item in data: 2134 | images.append(item['urls']['regular']) 2135 | 2136 | 2137 | await message.reply_photo( 2138 | images[0], 2139 | caption=f"**Image Search Results for:** `{query}`" 2140 | ) 2141 | 2142 | 2143 | for img_url in images[1:]: 2144 | await message.reply_photo(img_url) 2145 | 2146 | await message.delete() 2147 | else: 2148 | await message.edit_text("Error fetching images") 2149 | except Exception as e: 2150 | await message.edit_text(f"Error: {str(e)}") 2151 | 2152 | 2153 | @app.on_message(filters.command("weather", prefixes=".") & filters.me) 2154 | async def weather_info(client: Client, message: Message): 2155 | if len(message.command) < 2: 2156 | return await message.edit_text("Provide city name") 2157 | 2158 | city = " ".join(message.command[1:]) 2159 | url = f"https://wttr.in/{city}?format=j1" 2160 | 2161 | try: 2162 | async with aiohttp.ClientSession() as session: 2163 | async with session.get(url) as resp: 2164 | if resp.status != 200: 2165 | return await message.edit_text("Couldn't fetch weather data.") 2166 | 2167 | data = await resp.json() 2168 | current = data['current_condition'][0] 2169 | 2170 | 2171 | weather_report = f"**🌤 Weather in {city.title()}**\n" 2172 | weather_report += f"🌡 Temperature: {current['temp_C']}°C (Feels like {current['FeelsLikeC']}°C)\n" 2173 | weather_report += f"💧 Humidity: {current['humidity']}%\n" 2174 | weather_report += f"💨 Wind: {current['windspeedKmph']} km/h ({current['winddir16Point']})\n" 2175 | weather_report += f"🔍 Condition: {current['weatherDesc'][0]['value']}\n" 2176 | weather_report += f"☁️ Cloud Cover: {current['cloudcover']}%\n" 2177 | weather_report += f"🌅 Sunrise: {data['weather'][0]['astronomy'][0]['sunrise']}\n" 2178 | weather_report += f"🌇 Sunset: {data['weather'][0]['astronomy'][0]['sunset']}" 2179 | 2180 | await message.edit_text(weather_report) 2181 | except Exception as e: 2182 | await message.edit_text(f"Error: {str(e)}") 2183 | 2184 | 2185 | @app.on_message(filters.command("ud", prefixes=".") & filters.me) 2186 | async def urban_dictionary(client: Client, message: Message): 2187 | if len(message.command) < 2: 2188 | return await message.edit_text("Provide a word to search") 2189 | 2190 | word = " ".join(message.command[1:]) 2191 | try: 2192 | import urllib.parse 2193 | url = f"http://api.urbandictionary.com/v0/define?term={urllib.parse.quote(word)}" 2194 | response = requests.get(url) 2195 | if response.status_code == 200: 2196 | data = response.json() 2197 | if data['list']: 2198 | definition = data['list'][0] 2199 | result = f"**{word}**\n\n" 2200 | result += f"{definition['definition'][:500]}{'...' if len(definition['definition']) > 500 else ''}\n\n" 2201 | result += f"*Example:*\n{definition['example'][:300]}{'...' if len(definition['example']) > 300 else ''}" 2202 | await message.edit_text(result) 2203 | else: 2204 | await message.edit_text("No definition found") 2205 | else: 2206 | await message.edit_text("Error fetching definition") 2207 | except Exception as e: 2208 | await message.edit_text(f"Error: {str(e)}") 2209 | 2210 | @app.on_message(filters.command("define", prefixes=".") & filters.me) 2211 | async def dictionary_definition(client: Client, message: Message): 2212 | if len(message.command) < 2: 2213 | return await message.edit_text("Provide a word to define") 2214 | 2215 | word = " ".join(message.command[1:]) 2216 | try: 2217 | 2218 | url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}" 2219 | response = requests.get(url) 2220 | if response.status_code == 200: 2221 | data = response.json() 2222 | if isinstance(data, list) and len(data) > 0: 2223 | entry = data[0] 2224 | result = f"**{entry['word']}**\n" 2225 | if 'phonetic' in entry: 2226 | result += f"**Phonetic:** {entry['phonetic']}\n\n" 2227 | if 'meanings' in entry and len(entry['meanings']) > 0: 2228 | meaning = entry['meanings'][0] 2229 | result += f"**Part of Speech:** {meaning['partOfSpeech']}\n" 2230 | if 'definitions' in meaning and len(meaning['definitions']) > 0: 2231 | definition = meaning['definitions'][0] 2232 | result += f"**Definition:** {definition['definition']}\n" 2233 | if 'example' in definition: 2234 | result += f"**Example:** {definition['example']}\n" 2235 | await message.edit_text(result) 2236 | else: 2237 | await message.edit_text("No definition found") 2238 | else: 2239 | await message.edit_text("Error fetching definition") 2240 | except Exception as e: 2241 | await message.edit_text(f"Error: {str(e)}") 2242 | 2243 | @app.on_message(filters.command("syn", prefixes=".") & filters.me) 2244 | async def synonyms(client: Client, message: Message): 2245 | if len(message.command) < 2: 2246 | return await message.edit_text("Provide a word to find synonyms") 2247 | 2248 | word = " ".join(message.command[1:]) 2249 | try: 2250 | url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}" 2251 | response = requests.get(url) 2252 | print(response) 2253 | if response.status_code == 200: 2254 | data = response.json() 2255 | if isinstance(data, list) and len(data) > 0: 2256 | entry = data[0] 2257 | synonyms = [] 2258 | 2259 | 2260 | for meaning in entry.get('meanings', []): 2261 | 2262 | synonyms.extend(meaning.get('synonyms', [])) 2263 | 2264 | 2265 | for definition in meaning.get('definitions', []): 2266 | synonyms.extend(definition.get('synonyms', [])) 2267 | 2268 | if synonyms: 2269 | 2270 | unique_synonyms = list(set(synonyms))[:10] 2271 | result = f"**Synonyms for {word}:**\n" 2272 | result += ", ".join(unique_synonyms) 2273 | await message.edit_text(result) 2274 | else: 2275 | await message.edit_text(f"No synonyms found for {word}") 2276 | else: 2277 | await message.edit_text("No entry found for this word") 2278 | else: 2279 | await message.edit_text(f"Error fetching synonyms (HTTP {response.status_code})") 2280 | except Exception as e: 2281 | await message.edit_text(f"Error: {str(e)}") 2282 | 2283 | @app.on_message(filters.command("ant", prefixes=".") & filters.me) 2284 | async def antonyms(client: Client, message: Message): 2285 | if len(message.command) < 2: 2286 | return await message.edit_text("Provide a word to find antonyms") 2287 | 2288 | word = " ".join(message.command[1:]) 2289 | try: 2290 | 2291 | url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}" 2292 | response = requests.get(url) 2293 | if response.status_code == 200: 2294 | data = response.json() 2295 | if isinstance(data, list) and len(data) > 0: 2296 | entry = data[0] 2297 | antonyms = [] 2298 | for meaning in entry.get('meanings', []): 2299 | for definition in meaning.get('definitions', []): 2300 | antonyms.extend(definition.get('antonyms', [])) 2301 | 2302 | if antonyms: 2303 | unique_antonyms = list(set(antonyms))[:10] 2304 | result = f"**Antonyms for {word}:**\n" 2305 | result += ", ".join(unique_antonyms) 2306 | await message.edit_text(result) 2307 | else: 2308 | await message.edit_text(f"No antonyms found for {word}") 2309 | else: 2310 | await message.edit_text("No antonyms found") 2311 | else: 2312 | await message.edit_text("Error fetching antonyms") 2313 | except Exception as e: 2314 | await message.edit_text(f"Error: {str(e)}") 2315 | 2316 | 2317 | @app.on_message(filters.command("news", prefixes=".") & filters.me) 2318 | async def latest_news(client: Client, message: Message): 2319 | category = "general" 2320 | if len(message.command) > 1: 2321 | category = message.command[1].lower() 2322 | 2323 | try: 2324 | 2325 | rss_urls = { 2326 | "general": "http://feeds.bbci.co.uk/news/rss.xml", 2327 | "world": "http://feeds.bbci.co.uk/news/world/rss.xml", 2328 | "technology": "http://feeds.bbci.co.uk/news/technology/rss.xml", 2329 | "business": "http://feeds.bbci.co.uk/news/business/rss.xml", 2330 | "science": "http://feeds.bbci.co.uk/news/science_and_environment/rss.xml", 2331 | "health": "http://feeds.bbci.co.uk/news/health/rss.xml" 2332 | } 2333 | 2334 | 2335 | alt_rss = { 2336 | "general": "https://rss.cnn.com/rss/edition.rss", 2337 | "world": "https://rss.cnn.com/rss/edition_world.rss", 2338 | "technology": "https://rss.cnn.com/rss/edition_technology.rss", 2339 | "business": "https://rss.cnn.com/rss/money_latest.rss" 2340 | } 2341 | 2342 | url = rss_urls.get(category, rss_urls["general"]) 2343 | 2344 | 2345 | feed = feedparser.parse(url) 2346 | 2347 | if feed.entries: 2348 | result = f"**📰 Latest {category.title()} News:**\n\n" 2349 | for i, entry in enumerate(feed.entries[:5], 1): 2350 | title = entry.title 2351 | link = entry.link 2352 | summary = entry.get('summary', '') 2353 | 2354 | 2355 | if summary: 2356 | 2357 | summary = BeautifulSoup(summary, 'html.parser').get_text() 2358 | summary = summary[:150] + "..." if len(summary) > 150 else summary 2359 | 2360 | result += f"{i}. [{title}]({link})\n" 2361 | if summary: 2362 | result += f" {summary}\n" 2363 | result += f" 📅 {entry.get('published', 'N/A')}\n\n" 2364 | 2365 | await message.edit_text(result, disable_web_page_preview=True) 2366 | else: 2367 | 2368 | await scrape_news(message, category) 2369 | 2370 | except Exception as e: 2371 | await message.edit_text(f"❌ Error fetching news: {str(e)}") 2372 | 2373 | async def scrape_news(message: Message, category: str): 2374 | """Fallback method using web scraping""" 2375 | try: 2376 | headers = { 2377 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' 2378 | } 2379 | 2380 | 2381 | search_query = f"{category} news" if category != "general" else "latest news" 2382 | url = f"https://news.google.com/rss/search?q={search_query}&hl=en-US&gl=US&ceid=US:en" 2383 | 2384 | feed = feedparser.parse(url) 2385 | 2386 | if feed.entries: 2387 | result = f"**📰 Latest {category.title()} News (Google News):**\n\n" 2388 | for i, entry in enumerate(feed.entries[:5], 1): 2389 | title = entry.title 2390 | link = entry.link 2391 | source = entry.get('source', {}).get('title', 'Unknown') 2392 | 2393 | result += f"{i}. [{title}]({link})\n" 2394 | result += f" 📰 Source: {source}\n" 2395 | result += f" 📅 {entry.get('published', 'N/A')}\n\n" 2396 | 2397 | await message.edit_text(result, disable_web_page_preview=True) 2398 | else: 2399 | await message.edit_text("❌ No news found") 2400 | 2401 | except Exception as e: 2402 | await message.edit_text(f"❌ Scraping failed: {str(e)}") 2403 | 2404 | 2405 | @app.on_message(filters.command("quicknews", prefixes=".") & filters.me) 2406 | async def quick_news(client: Client, message: Message): 2407 | """Simple news using Google News RSS""" 2408 | try: 2409 | category = "general" 2410 | if len(message.command) > 1: 2411 | category = message.command[1].lower() 2412 | 2413 | 2414 | if category == "general": 2415 | url = "https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en" 2416 | else: 2417 | url = f"https://news.google.com/rss/search?q={category}&hl=en-US&gl=US&ceid=US:en" 2418 | 2419 | response = requests.get(url, timeout=10) 2420 | 2421 | if response.status_code == 200: 2422 | feed = feedparser.parse(response.content) 2423 | 2424 | if feed.entries: 2425 | result = f"**📰 {category.title()} News:**\n\n" 2426 | for i, entry in enumerate(feed.entries[:5], 1): 2427 | result += f"{i}. [{entry.title}]({entry.link})\n\n" 2428 | 2429 | await message.edit_text(result, disable_web_page_preview=True) 2430 | else: 2431 | await message.edit_text("No news found") 2432 | else: 2433 | await message.edit_text(f"Error: HTTP {response.status_code}") 2434 | 2435 | except Exception as e: 2436 | await message.edit_text(f"Error: {str(e)}") 2437 | 2438 | 2439 | 2440 | @app.on_message(filters.command("note", prefixes=".") & filters.me) 2441 | async def save_note(client: Client, message: Message): 2442 | if len(message.command) < 3: 2443 | return await message.edit_text("Usage: .note [name] [content]") 2444 | 2445 | note_name = message.command[1].lower() 2446 | content = " ".join(message.command[2:]) 2447 | 2448 | notes[note_name] = content 2449 | save_data() 2450 | await message.edit_text(f"Note '{note_name}' saved!") 2451 | 2452 | @app.on_message(filters.command("getnote", prefixes=".") & filters.me) 2453 | async def get_note(client: Client, message: Message): 2454 | if len(message.command) < 2: 2455 | return await message.edit_text("Provide note name") 2456 | 2457 | note_name = message.command[1].lower() 2458 | if note_name in notes: 2459 | await message.edit_text(f"**{note_name}:**\n{notes[note_name]}") 2460 | else: 2461 | await message.edit_text("Note not found") 2462 | 2463 | @app.on_message(filters.command("delnote", prefixes=".") & filters.me) 2464 | async def delete_note(client: Client, message: Message): 2465 | if len(message.command) < 2: 2466 | return await message.edit_text("Provide note name") 2467 | 2468 | note_name = message.command[1].lower() 2469 | if note_name in notes: 2470 | del notes[note_name] 2471 | save_data() 2472 | await message.edit_text(f"Note '{note_name}' deleted!") 2473 | else: 2474 | await message.edit_text("Note not found") 2475 | 2476 | @app.on_message(filters.command("notes", prefixes=".") & filters.me) 2477 | async def list_notes(client: Client, message: Message): 2478 | if not notes: 2479 | return await message.edit_text("No notes saved") 2480 | 2481 | note_list = "**Saved Notes:**\n" 2482 | for name in notes.keys(): 2483 | note_list += f"`{name}`\n" 2484 | 2485 | await message.edit_text(note_list) 2486 | 2487 | @app.on_message(filters.command("remind", prefixes=".") & filters.me) 2488 | async def set_reminder(client: Client, message: Message): 2489 | if len(message.command) < 3: 2490 | return await message.edit_text("Usage: .remind [minutes] [message]") 2491 | 2492 | try: 2493 | minutes = int(message.command[1]) 2494 | reminder_text = " ".join(message.command[2:]) 2495 | 2496 | 2497 | reminder_id = str(len(reminders) + 1) 2498 | reminders[reminder_id] = { 2499 | "text": reminder_text, 2500 | "time": minutes, 2501 | "created": datetime.now().isoformat() 2502 | } 2503 | save_data() 2504 | 2505 | await message.edit_text(f"Reminder set for {minutes} minutes!") 2506 | 2507 | 2508 | async def reminder_task(): 2509 | await asyncio.sleep(minutes * 60) 2510 | if reminder_id in reminders: 2511 | await message.reply_text(f"⏰ **Reminder:** {reminder_text}") 2512 | 2513 | reminders.pop(reminder_id, None) 2514 | save_data() 2515 | 2516 | asyncio.create_task(reminder_task()) 2517 | except ValueError: 2518 | await message.edit_text("Invalid time format. Use minutes as number") 2519 | 2520 | @app.on_message(filters.command("reminders", prefixes=".") & filters.me) 2521 | async def list_reminders(client: Client, message: Message): 2522 | if not reminders: 2523 | return await message.edit_text("No active reminders") 2524 | 2525 | reminder_list = "**Active Reminders:**\n" 2526 | for i, (id, reminder) in enumerate(reminders.items(), 1): 2527 | reminder_list += f"{i}. {reminder['text']} (in {reminder['time']} min)\n" 2528 | 2529 | await message.edit_text(reminder_list) 2530 | 2531 | 2532 | @app.on_message(filters.command("quote", prefixes=".") & filters.me) 2533 | async def random_quote(client: Client, message: Message): 2534 | try: 2535 | 2536 | apis = [ 2537 | "https://api.quotable.io/random", 2538 | "https://zenquotes.io/api/random" 2539 | ] 2540 | 2541 | for api_url in apis: 2542 | try: 2543 | response = requests.get(api_url, timeout=5) 2544 | if response.status_code == 200: 2545 | data = response.json() 2546 | if "quotable" in api_url: 2547 | quote = f"**{data['content']}**\n\n— {data['author']}" 2548 | else: 2549 | quote = f"**{data[0]['q']}**\n\n— {data[0]['a']}" 2550 | await message.edit_text(quote) 2551 | return 2552 | except: 2553 | continue 2554 | 2555 | 2556 | if custom_quotes: 2557 | import random 2558 | quote_id = random.choice(list(custom_quotes.keys())) 2559 | quote_data = custom_quotes[quote_id] 2560 | await message.edit_text(f"**{quote_data['text']}**\n\n— {quote_data['author']}") 2561 | else: 2562 | await message.edit_text("Error fetching quote. Try again later.") 2563 | except Exception as e: 2564 | await message.edit_text(f"Error: {str(e)}") 2565 | 2566 | @app.on_message(filters.command("addquote", prefixes=".") & filters.me) 2567 | async def add_custom_quote(client: Client, message: Message): 2568 | if len(message.command) < 2: 2569 | return await message.edit_text("Usage: .addquote [text] or reply to message") 2570 | 2571 | 2572 | if len(message.command) > 1: 2573 | text = " ".join(message.command[1:]) 2574 | author = message.from_user.first_name 2575 | elif message.reply_to_message: 2576 | text = message.reply_to_message.text or "" 2577 | author = message.reply_to_message.from_user.first_name 2578 | else: 2579 | return await message.edit_text("Provide quote text or reply to a message") 2580 | 2581 | if not text: 2582 | return await message.edit_text("No text found!") 2583 | 2584 | 2585 | quote_id = str(len(custom_quotes) + 1) 2586 | custom_quotes[quote_id] = { 2587 | "text": text, 2588 | "author": author, 2589 | "added_by": message.from_user.id, 2590 | "added_at": datetime.now().isoformat() 2591 | } 2592 | save_data() 2593 | 2594 | await message.edit_text("**Quote added successfully!**") 2595 | 2596 | @app.on_message(filters.command("delquote", prefixes=".") & filters.me) 2597 | async def delete_custom_quote(client: Client, message: Message): 2598 | if len(message.command) < 2: 2599 | return await message.edit_text("Provide quote ID to delete") 2600 | 2601 | quote_id = message.command[1] 2602 | if quote_id in custom_quotes: 2603 | del custom_quotes[quote_id] 2604 | save_data() 2605 | await message.edit_text(f"**Quote {quote_id} deleted!**") 2606 | else: 2607 | await message.edit_text("Quote not found") 2608 | 2609 | @app.on_message(filters.command("myquotes", prefixes=".") & filters.me) 2610 | async def list_my_quotes(client: Client, message: Message): 2611 | user_quotes = {k: v for k, v in custom_quotes.items() if v["added_by"] == message.from_user.id} 2612 | 2613 | if not user_quotes: 2614 | return await message.edit_text("You haven't added any quotes yet") 2615 | 2616 | quote_list = "**Your Quotes:**\n" 2617 | for quote_id, quote_data in list(user_quotes.items())[:10]: 2618 | quote_list += f"`{quote_id}.` {quote_data['text'][:50]}{'...' if len(quote_data['text']) > 50 else ''}\n" 2619 | 2620 | await message.edit_text(quote_list) 2621 | 2622 | @app.on_message(filters.command("joke", prefixes=".") & filters.me) 2623 | async def random_joke(client: Client, message: Message): 2624 | try: 2625 | response = requests.get("https://official-joke-api.appspot.com/jokes/random") 2626 | if response.status_code == 200: 2627 | data = response.json() 2628 | joke = f"**{data['setup']}**\n\n{data['punchline']}" 2629 | await message.edit_text(joke) 2630 | else: 2631 | await message.edit_text("Error fetching joke") 2632 | except Exception as e: 2633 | await message.edit_text(f"Error: {str(e)}") 2634 | 2635 | @app.on_message(filters.command("fact", prefixes=".") & filters.me) 2636 | async def random_fact(client: Client, message: Message): 2637 | try: 2638 | response = requests.get("https://uselessfacts.jsph.pl/random.json?language=en") 2639 | if response.status_code == 200: 2640 | data = response.json() 2641 | await message.edit_text(f"**Fact:** {data['text']}") 2642 | else: 2643 | await message.edit_text("Error fetching fact") 2644 | except Exception as e: 2645 | await message.edit_text(f"Error: {str(e)}") 2646 | 2647 | 2648 | 2649 | @app.on_message(filters.command("meme", prefixes=".") & filters.me) 2650 | async def custom_meme(client: Client, message: Message): 2651 | try: 2652 | 2653 | if len(message.command) > 1: 2654 | 2655 | keywords = message.command[1:] 2656 | elif message.reply_to_message and message.reply_to_message.text: 2657 | 2658 | keywords = message.reply_to_message.text.split() 2659 | else: 2660 | keywords = [] 2661 | 2662 | urls_tried = set() 2663 | meme_data = None 2664 | 2665 | if keywords: 2666 | search_variants = ['-'.join(keywords)] + keywords 2667 | 2668 | for keyword in search_variants: 2669 | url = f"https://api.apileague.com/retrieve-random-meme?keywords={keyword}" 2670 | if url in urls_tried: 2671 | continue 2672 | urls_tried.add(url) 2673 | 2674 | response = requests.get(url) 2675 | if response.status_code == 200: 2676 | data = response.json() 2677 | if 'url' in data: 2678 | meme_data = data 2679 | break 2680 | else: 2681 | 2682 | response = requests.get("https://api.apileague.com/retrieve-random-meme") 2683 | if response.status_code == 200: 2684 | meme_data = response.json() 2685 | 2686 | if meme_data: 2687 | await message.reply_photo( 2688 | photo=meme_data['url'], 2689 | caption=f"**{meme_data.get('description', 'Meme')}**" 2690 | ) 2691 | await message.delete() 2692 | else: 2693 | await message.edit_text("No meme found for given keywords.") 2694 | except Exception as e: 2695 | await message.edit_text(f"Error: {str(e)}") 2696 | 2697 | 2698 | @app.on_message(filters.command("ascii", prefixes=".") & filters.me) 2699 | async def ascii_command(client, message): 2700 | if len(message.command) < 2 and not message.reply_to_message: 2701 | await message.edit("Usage: `.ascii ` or reply to a message.") 2702 | return 2703 | 2704 | if len(message.command) >= 2: 2705 | text = " ".join(message.command[1:]) 2706 | elif message.reply_to_message and message.reply_to_message.text: 2707 | text = message.reply_to_message.text 2708 | else: 2709 | await message.edit("No valid text found to convert.") 2710 | return 2711 | 2712 | try: 2713 | ascii_art = figlet_format(text) 2714 | if len(ascii_art) > 4096: 2715 | ascii_art = ascii_art[:4093] + "..." 2716 | await message.edit(f"```\n{ascii_art}\n```") 2717 | except Exception as e: 2718 | await message.edit(f"Error creating ASCII art: `{e}`") 2719 | 2720 | @app.on_message(filters.command("reverse", prefixes=".") & filters.me) 2721 | async def reverse_text(client: Client, message: Message): 2722 | 2723 | text = "" 2724 | if len(message.command) > 1: 2725 | text = " ".join(message.command[1:]) 2726 | elif message.reply_to_message: 2727 | text = message.reply_to_message.text or "" 2728 | else: 2729 | return await message.edit_text("Provide text or reply to message") 2730 | 2731 | if not text: 2732 | return await message.edit_text("No text found!") 2733 | 2734 | await message.edit_text(text[::-1]) 2735 | 2736 | @app.on_message(filters.command("mock", prefixes=".") & filters.me) 2737 | async def mock_text_command(client: Client, message: Message): 2738 | 2739 | text = "" 2740 | if len(message.command) > 1: 2741 | text = " ".join(message.command[1:]) 2742 | elif message.reply_to_message: 2743 | text = message.reply_to_message.text or "" 2744 | else: 2745 | return await message.edit_text("Provide text or reply to message") 2746 | 2747 | if not text: 2748 | return await message.edit_text("No text found!") 2749 | 2750 | await message.edit_text(mock_text(text)) 2751 | 2752 | @app.on_message(filters.command("vapor", prefixes=".") & filters.me) 2753 | async def vapor_text_command(client: Client, message: Message): 2754 | 2755 | text = "" 2756 | if len(message.command) > 1: 2757 | text = " ".join(message.command[1:]) 2758 | elif message.reply_to_message: 2759 | text = message.reply_to_message.text or "" 2760 | else: 2761 | return await message.edit_text("Provide text or reply to message") 2762 | 2763 | if not text: 2764 | return await message.edit_text("No text found!") 2765 | 2766 | await message.edit_text(vapor_text(text)) 2767 | 2768 | @app.on_message(filters.command("clap", prefixes=".") & filters.me) 2769 | async def clap_text_command(client: Client, message: Message): 2770 | 2771 | text = "" 2772 | if len(message.command) > 1: 2773 | text = " ".join(message.command[1:]) 2774 | elif message.reply_to_message: 2775 | text = message.reply_to_message.text or "" 2776 | else: 2777 | return await message.edit_text("Provide text or reply to message") 2778 | 2779 | if not text: 2780 | return await message.edit_text("No text found!") 2781 | 2782 | await message.edit_text(clap_text(text)) 2783 | 2784 | @app.on_message(filters.command("emojify", prefixes=".") & filters.me) 2785 | async def emojify_text_command(client: Client, message: Message): 2786 | 2787 | text = "" 2788 | if len(message.command) > 1: 2789 | text = " ".join(message.command[1:]) 2790 | elif message.reply_to_message: 2791 | text = message.reply_to_message.text or "" 2792 | else: 2793 | return await message.edit_text("Provide text or reply to message") 2794 | 2795 | if not text: 2796 | return await message.edit_text("No text found!") 2797 | 2798 | await message.edit_text(emojify_text(text)) 2799 | 2800 | @app.on_message(filters.command("spoiler", prefixes=".") & filters.me) 2801 | async def spoiler_text_command(client: Client, message: Message): 2802 | 2803 | text = "" 2804 | if len(message.command) > 1: 2805 | text = " ".join(message.command[1:]) 2806 | elif message.reply_to_message: 2807 | text = message.reply_to_message.text or "" 2808 | else: 2809 | return await message.edit_text("Provide text or reply to message") 2810 | 2811 | if not text: 2812 | return await message.edit_text("No text found!") 2813 | 2814 | await message.edit_text(spoiler_text(text)) 2815 | 2816 | @app.on_message(filters.command("password", prefixes=".") & filters.me) 2817 | async def generate_password_command(client: Client, message: Message): 2818 | length = 12 2819 | if len(message.command) > 1: 2820 | try: 2821 | length = int(message.command[1]) 2822 | if length < 4: 2823 | length = 4 2824 | elif length > 100: 2825 | length = 100 2826 | except: 2827 | pass 2828 | 2829 | password = generate_password(length) 2830 | await message.edit_text(f"**Generated Password:** `{password}`") 2831 | 2832 | @app.on_message(filters.command("hash", prefixes=".") & filters.me) 2833 | async def hash_text(client: Client, message: Message): 2834 | 2835 | text = "" 2836 | if len(message.command) > 1: 2837 | text = " ".join(message.command[1:]) 2838 | elif message.reply_to_message: 2839 | text = message.reply_to_message.text or "" 2840 | else: 2841 | return await message.edit_text("Provide text or reply to message") 2842 | 2843 | if not text: 2844 | return await message.edit_text("No text found!") 2845 | 2846 | md5_hash = hashlib.md5(text.encode()).hexdigest() 2847 | sha1_hash = hashlib.sha1(text.encode()).hexdigest() 2848 | sha256_hash = hashlib.sha256(text.encode()).hexdigest() 2849 | 2850 | result = f"**Hashes for:** `{text}`\n\n" 2851 | result += f"**MD5:** `{md5_hash}`\n" 2852 | result += f"**SHA1:** `{sha1_hash}`\n" 2853 | result += f"**SHA256:** `{sha256_hash}`" 2854 | 2855 | await message.edit_text(result) 2856 | 2857 | @app.on_message(filters.command("base64", prefixes=".") & filters.me) 2858 | async def base64_command(client: Client, message: Message): 2859 | if len(message.command) < 3: 2860 | return await message.edit_text("Usage: .base64 [encode/decode] [text] or reply to message") 2861 | 2862 | operation = message.command[1].lower() 2863 | text = " ".join(message.command[2:]) if len(message.command) > 2 else "" 2864 | 2865 | 2866 | if not text and message.reply_to_message: 2867 | text = message.reply_to_message.text or "" 2868 | 2869 | if not text: 2870 | return await message.edit_text("No text found!") 2871 | 2872 | try: 2873 | if operation == "encode": 2874 | encoded = base64.b64encode(text.encode()).decode() 2875 | await message.edit_text(f"**Base64 Encoded:**\n`{encoded}`") 2876 | elif operation == "decode": 2877 | decoded = base64.b64decode(text).decode() 2878 | await message.edit_text(f"**Base64 Decoded:**\n`{decoded}`") 2879 | else: 2880 | await message.edit_text("Usage: .base64 [encode/decode] [text]") 2881 | except Exception as e: 2882 | await message.edit_text(f"Error: {str(e)}") 2883 | 2884 | @app.on_message(filters.command("leet", prefixes=".") & filters.me) 2885 | async def leet_speak_command(client: Client, message: Message): 2886 | 2887 | text = "" 2888 | if len(message.command) > 1: 2889 | text = " ".join(message.command[1:]) 2890 | elif message.reply_to_message: 2891 | text = message.reply_to_message.text or "" 2892 | else: 2893 | return await message.edit_text("Provide text or reply to message") 2894 | 2895 | if not text: 2896 | return await message.edit_text("No text found!") 2897 | 2898 | await message.edit_text(leet_speak(text)) 2899 | 2900 | @app.on_message(filters.command("flip", prefixes=".") & filters.me) 2901 | async def flip_text_command(client: Client, message: Message): 2902 | 2903 | text = "" 2904 | if len(message.command) > 1: 2905 | text = " ".join(message.command[1:]) 2906 | elif message.reply_to_message: 2907 | text = message.reply_to_message.text or "" 2908 | else: 2909 | return await message.edit_text("Provide text or reply to message") 2910 | 2911 | if not text: 2912 | return await message.edit_text("No text found!") 2913 | 2914 | await message.edit_text(flip_text(text)) 2915 | 2916 | @app.on_message(filters.command("cowsay", prefixes=".") & filters.me) 2917 | async def cowsay_command(client: Client, message: Message): 2918 | 2919 | text = "" 2920 | if len(message.command) > 1: 2921 | text = " ".join(message.command[1:]) 2922 | elif message.reply_to_message: 2923 | text = message.reply_to_message.text or "" 2924 | else: 2925 | return await message.edit_text("Provide text or reply to message") 2926 | 2927 | if not text: 2928 | return await message.edit_text("No text found!") 2929 | 2930 | try: 2931 | result = cowsay(text) 2932 | await message.edit_text(f"```\n{result}\n```") 2933 | except Exception as e: 2934 | await message.edit_text(f"Error: {str(e)}") 2935 | 2936 | @app.on_message(filters.command("roll", prefixes=".") & filters.me) 2937 | async def roll_dice_command(client: Client, message: Message): 2938 | dice_notation = "1d6" 2939 | if len(message.command) > 1: 2940 | dice_notation = message.command[1] 2941 | 2942 | result = roll_dice(dice_notation) 2943 | await message.edit_text(result) 2944 | 2945 | @app.on_message(filters.command("8ball", prefixes=".") & filters.me) 2946 | async def magic_8ball_command(client: Client, message: Message): 2947 | question = "" 2948 | if len(message.command) > 1: 2949 | question = " ".join(message.command[1:]) 2950 | elif message.reply_to_message: 2951 | question = message.reply_to_message.text or "" 2952 | 2953 | if not question: 2954 | return await message.edit_text("Ask a question!") 2955 | 2956 | result = magic_8ball(question) 2957 | await message.edit_text(result) 2958 | 2959 | @app.on_message(filters.command("choose", prefixes=".") & filters.me) 2960 | async def random_choice_command(client: Client, message: Message): 2961 | if len(message.command) < 2: 2962 | return await message.edit_text("Usage: .choose [option1|option2|option3]") 2963 | 2964 | options = " ".join(message.command[1:]) 2965 | result = random_choice(options) 2966 | await message.edit_text(result) 2967 | 2968 | 2969 | @app.on_message(filters.command("alias", prefixes=".") & filters.me) 2970 | async def create_alias(client: Client, message: Message): 2971 | if len(message.command) < 3: 2972 | return await message.edit_text("Usage: .alias [name] [command]") 2973 | 2974 | alias_name = message.command[1].lower() 2975 | command = " ".join(message.command[2:]) 2976 | 2977 | 2978 | if "aliases" not in user_data: 2979 | user_data["aliases"] = {} 2980 | 2981 | user_data["aliases"][alias_name] = command 2982 | save_data() 2983 | 2984 | await message.edit_text(f"**Alias '{alias_name}' created for command:** `{command}`") 2985 | 2986 | @app.on_message(filters.command("unalias", prefixes=".") & filters.me) 2987 | async def remove_alias(client: Client, message: Message): 2988 | if len(message.command) < 2: 2989 | return await message.edit_text("Usage: .unalias [name]") 2990 | 2991 | alias_name = message.command[1].lower() 2992 | 2993 | if "aliases" in user_data and alias_name in user_data["aliases"]: 2994 | del user_data["aliases"][alias_name] 2995 | save_data() 2996 | await message.edit_text(f"**Alias '{alias_name}' removed!**") 2997 | else: 2998 | await message.edit_text("Alias not found!") 2999 | 3000 | @app.on_message(filters.command("aliases", prefixes=".") & filters.me) 3001 | async def list_aliases(client: Client, message: Message): 3002 | if "aliases" not in user_data or not user_data["aliases"]: 3003 | return await message.edit_text("No aliases found!") 3004 | 3005 | alias_list = "**Your Aliases:**\n" 3006 | for name, command in user_data["aliases"].items(): 3007 | alias_list += f"`{name}` → `{command}`\n" 3008 | 3009 | await message.edit_text(alias_list) 3010 | 3011 | @app.on_message(filters.command("filter", prefixes=".") & filters.me) 3012 | async def add_filter(client: Client, message: Message): 3013 | if len(message.command) < 3: 3014 | return await message.edit_text("Usage: .filter [trigger] [response]") 3015 | 3016 | trigger = message.command[1].lower() 3017 | response = " ".join(message.command[2:]) 3018 | 3019 | 3020 | if message.chat.id not in active_filters: 3021 | active_filters[message.chat.id] = {} 3022 | 3023 | active_filters[message.chat.id][trigger] = response 3024 | await message.edit_text(f"**Filter added for '{trigger}'**") 3025 | 3026 | @app.on_message(filters.command("filters", prefixes=".") & filters.me) 3027 | async def list_filters(client: Client, message: Message): 3028 | if message.chat.id not in active_filters or not active_filters[message.chat.id]: 3029 | return await message.edit_text("No filters found in this chat!") 3030 | 3031 | filter_list = "**Active Filters:**\n" 3032 | for trigger, response in active_filters[message.chat.id].items(): 3033 | filter_list += f"`{trigger}` → {response[:30]}{'...' if len(response) > 30 else ''}\n" 3034 | 3035 | await message.edit_text(filter_list) 3036 | 3037 | @app.on_message(filters.command("stop", prefixes=".") & filters.me) 3038 | async def remove_filter(client: Client, message: Message): 3039 | if len(message.command) < 2: 3040 | return await message.edit_text("Usage: .stop [trigger]") 3041 | 3042 | trigger = message.command[1].lower() 3043 | 3044 | if message.chat.id in active_filters and trigger in active_filters[message.chat.id]: 3045 | del active_filters[message.chat.id][trigger] 3046 | await message.edit_text(f"**Filter '{trigger}' removed!**") 3047 | else: 3048 | await message.edit_text("Filter not found!") 3049 | 3050 | @app.on_message(filters.command("schedule", prefixes=".") & filters.me) 3051 | async def schedule_task(client: Client, message: Message): 3052 | if len(message.command) < 3: 3053 | return await message.edit_text("Usage: .schedule [time_in_minutes] [command]") 3054 | 3055 | try: 3056 | minutes = int(message.command[1]) 3057 | command = " ".join(message.command[2:]) 3058 | 3059 | 3060 | task_id = str(len(scheduled_tasks) + 1) 3061 | scheduled_tasks[task_id] = { 3062 | "command": command, 3063 | "time": minutes, 3064 | "chat_id": message.chat.id, 3065 | "created": datetime.now().isoformat() 3066 | } 3067 | save_data() 3068 | 3069 | await message.edit_text(f"**Task scheduled for {minutes} minutes!** (ID: {task_id})") 3070 | 3071 | 3072 | async def execute_task(): 3073 | await asyncio.sleep(minutes * 60) 3074 | if task_id in scheduled_tasks: 3075 | 3076 | try: 3077 | 3078 | await message.reply_text(f"⏰ **Scheduled task executed:** {command}") 3079 | 3080 | scheduled_tasks.pop(task_id, None) 3081 | save_data() 3082 | except Exception as e: 3083 | logger.error(f"Error executing scheduled task: {e}") 3084 | 3085 | asyncio.create_task(execute_task()) 3086 | except ValueError: 3087 | await message.edit_text("Invalid time format. Use minutes as number") 3088 | 3089 | @app.on_message(filters.command("unschedule", prefixes=".") & filters.me) 3090 | async def unschedule_task(client: Client, message: Message): 3091 | if len(message.command) < 2: 3092 | return await message.edit_text("Usage: .unschedule [task_id]") 3093 | 3094 | task_id = message.command[1] 3095 | if task_id in scheduled_tasks: 3096 | del scheduled_tasks[task_id] 3097 | save_data() 3098 | await message.edit_text(f"**Task {task_id} cancelled!**") 3099 | else: 3100 | await message.edit_text("Task not found!") 3101 | 3102 | @app.on_message(filters.command("tasks", prefixes=".") & filters.me) 3103 | async def list_scheduled_tasks(client: Client, message: Message): 3104 | if not scheduled_tasks: 3105 | return await message.edit_text("No scheduled tasks!") 3106 | 3107 | task_list = "**Scheduled Tasks:**\n" 3108 | for task_id, task in scheduled_tasks.items(): 3109 | task_list += f"`{task_id}.` {task['command']} (in {task['time']} min)\n" 3110 | 3111 | await message.edit_text(task_list) 3112 | 3113 | @app.on_message(filters.command("todo", prefixes=".") & filters.me) 3114 | async def add_todo(client: Client, message: Message): 3115 | if len(message.command) < 2: 3116 | return await message.edit_text("Usage: .todo [task]") 3117 | 3118 | task = " ".join(message.command[1:]) 3119 | 3120 | 3121 | if "todos" not in user_data: 3122 | user_data["todos"] = [] 3123 | 3124 | todo_id = len(user_data["todos"]) + 1 3125 | user_data["todos"].append({ 3126 | "id": todo_id, 3127 | "task": task, 3128 | "completed": False, 3129 | "created": datetime.now().isoformat() 3130 | }) 3131 | save_data() 3132 | 3133 | await message.edit_text(f"**Todo added!** (ID: {todo_id})") 3134 | 3135 | @app.on_message(filters.command("todos", prefixes=".") & filters.me) 3136 | async def list_todos(client: Client, message: Message): 3137 | if "todos" not in user_data or not user_data["todos"]: 3138 | return await message.edit_text("No todos found!") 3139 | 3140 | todo_list = "**Your Todos:**\n" 3141 | for todo in user_data["todos"]: 3142 | status = "✅" if todo["completed"] else "❌" 3143 | todo_list += f"{status} `{todo['id']}.` {todo['task']}\n" 3144 | 3145 | await message.edit_text(todo_list) 3146 | 3147 | @app.on_message(filters.command("done", prefixes=".") & filters.me) 3148 | async def mark_todo_done(client: Client, message: Message): 3149 | if len(message.command) < 2: 3150 | return await message.edit_text("Usage: .done [todo_id]") 3151 | 3152 | try: 3153 | todo_id = int(message.command[1]) 3154 | if "todos" in user_data: 3155 | for todo in user_data["todos"]: 3156 | if todo["id"] == todo_id: 3157 | todo["completed"] = True 3158 | save_data() 3159 | await message.edit_text(f"**Todo {todo_id} marked as done!**") 3160 | return 3161 | await message.edit_text("Todo not found!") 3162 | except ValueError: 3163 | await message.edit_text("Invalid todo ID!") 3164 | 3165 | @app.on_message(filters.command("rss", prefixes=".") & filters.me) 3166 | async def add_rss_feed(client: Client, message: Message): 3167 | if len(message.command) < 2: 3168 | return await message.edit_text("Usage: .rss [feed_url]") 3169 | 3170 | feed_url = message.command[1] 3171 | 3172 | 3173 | if "rss_feeds" not in user_data: 3174 | user_data["rss_feeds"] = [] 3175 | 3176 | user_data["rss_feeds"].append({ 3177 | "url": feed_url, 3178 | "chat_id": message.chat.id, 3179 | "added": datetime.now().isoformat() 3180 | }) 3181 | save_data() 3182 | 3183 | await message.edit_text(f"**RSS feed added:** {feed_url}") 3184 | 3185 | @app.on_message(filters.command("feeds", prefixes=".") & filters.me) 3186 | async def list_rss_feeds(client: Client, message: Message): 3187 | if "rss_feeds" not in user_data or not user_data["rss_feeds"]: 3188 | return await message.edit_text("No RSS feeds found!") 3189 | 3190 | feed_list = "**Your RSS Feeds:**\n" 3191 | for i, feed in enumerate(user_data["rss_feeds"], 1): 3192 | feed_list += f"`{i}.` {feed['url']}\n" 3193 | 3194 | await message.edit_text(feed_list) 3195 | 3196 | @app.on_message(filters.command("menu", prefixes=".") & filters.me) 3197 | async def create_menu(client: Client, message: Message): 3198 | if len(message.command) < 3: 3199 | return await message.edit_text("Usage: .menu [name] [button1|button2|button3]") 3200 | 3201 | menu_name = message.command[1] 3202 | buttons_text = " ".join(message.command[2:]) 3203 | 3204 | 3205 | buttons = [] 3206 | for button_def in buttons_text.split('|'): 3207 | if '=' in button_def: 3208 | text, url = button_def.split('=', 1) 3209 | buttons.append([InlineKeyboardButton(text.strip(), url=url.strip())]) 3210 | 3211 | 3212 | if "menus" not in user_data: 3213 | user_data["menus"] = {} 3214 | 3215 | user_data["menus"][menu_name] = { 3216 | "buttons": buttons, 3217 | "created": datetime.now().isoformat() 3218 | } 3219 | save_data() 3220 | 3221 | await message.edit_text(f"**Menu '{menu_name}' created!**") 3222 | 3223 | @app.on_message(filters.command("menus", prefixes=".") & filters.me) 3224 | async def list_menus(client: Client, message: Message): 3225 | if "menus" not in user_data or not user_data["menus"]: 3226 | return await message.edit_text("No menus found!") 3227 | 3228 | menu_list = "**Your Menus:**\n" 3229 | for name in user_data["menus"].keys(): 3230 | menu_list += f"`{name}`\n" 3231 | 3232 | await message.edit_text(menu_list) 3233 | 3234 | @app.on_message(filters.command("reaction", prefixes=".") & filters.me) 3235 | async def set_auto_reaction(client: Client, message: Message): 3236 | if len(message.command) < 3: 3237 | return await message.edit_text("Usage: .reaction [trigger] [emoji]") 3238 | 3239 | trigger = message.command[1].lower() 3240 | emoji = message.command[2] 3241 | 3242 | 3243 | if "reactions" not in user_data: 3244 | user_data["reactions"] = {} 3245 | 3246 | user_data["reactions"][trigger] = emoji 3247 | save_data() 3248 | 3249 | await message.edit_text(f"**Auto reaction set for '{trigger}':** {emoji}") 3250 | 3251 | @app.on_message(filters.command("delreaction", prefixes=".") & filters.me) 3252 | async def delete_auto_reaction(client: Client, message: Message): 3253 | if len(message.command) < 2: 3254 | return await message.edit_text("Usage: .delreaction [trigger]") 3255 | 3256 | trigger = message.command[1].lower() 3257 | 3258 | if "reactions" in user_data and trigger in user_data["reactions"]: 3259 | deleted_emoji = user_data["reactions"].pop(trigger) 3260 | save_data() 3261 | await message.edit_text(f"**Auto reaction removed for '{trigger}':** {deleted_emoji}") 3262 | else: 3263 | await message.edit_text(f"❌ No reaction found for trigger '{trigger}'") 3264 | 3265 | 3266 | @app.on_message(filters.command("ghost", prefixes=".") & filters.me) 3267 | async def ghost_mode(client: Client, message: Message): 3268 | if len(message.command) < 2: 3269 | return await message.edit_text("Usage: .ghost [on/off]") 3270 | 3271 | mode = message.command[1].lower() 3272 | if mode == "on": 3273 | 3274 | await message.edit_text("**Ghost mode activated!** (Implementation pending)") 3275 | elif mode == "off": 3276 | await message.edit_text("**Ghost mode deactivated!**") 3277 | else: 3278 | await message.edit_text("Usage: .ghost [on/off]") 3279 | 3280 | @app.on_message(filters.command("antispam", prefixes=".") & filters.me) 3281 | async def antispam_protection(client: Client, message: Message): 3282 | if len(message.command) < 2: 3283 | return await message.edit_text("Usage: .antispam [on/off]") 3284 | 3285 | mode = message.command[1].lower() 3286 | if mode == "on": 3287 | spam_protection[message.chat.id] = True 3288 | await message.edit_text("**Anti-spam protection enabled!**") 3289 | elif mode == "off": 3290 | spam_protection[message.chat.id] = False 3291 | await message.edit_text("**Anti-spam protection disabled!**") 3292 | else: 3293 | await message.edit_text("Usage: .antispam [on/off]") 3294 | 3295 | @app.on_message(filters.command("captcha", prefixes=".") & filters.me) 3296 | async def captcha_protection(client: Client, message: Message): 3297 | if len(message.command) < 2: 3298 | return await message.edit_text("Usage: .captcha [on/off]") 3299 | 3300 | mode = message.command[1].lower() 3301 | if mode == "on": 3302 | 3303 | await message.edit_text("**CAPTCHA protection enabled!** (Implementation pending)") 3304 | elif mode == "off": 3305 | await message.edit_text("**CAPTCHA protection disabled!**") 3306 | else: 3307 | await message.edit_text("Usage: .captcha [on/off]") 3308 | 3309 | @app.on_message(filters.command("welcome", prefixes=".") & filters.me) 3310 | async def set_welcome_message(client: Client, message: Message): 3311 | if len(message.command) < 3: 3312 | return await message.edit_text("Usage: .welcome [on/off] [message]") 3313 | 3314 | mode = message.command[1].lower() 3315 | welcome_msg = " ".join(message.command[2:]) 3316 | 3317 | if message.chat.id not in group_settings: 3318 | group_settings[message.chat.id] = {} 3319 | 3320 | if mode == "on": 3321 | group_settings[message.chat.id]["welcome"] = welcome_msg 3322 | group_settings[message.chat.id]["welcome_enabled"] = True 3323 | await message.edit_text("**Welcome message enabled!**") 3324 | elif mode == "off": 3325 | group_settings[message.chat.id]["welcome_enabled"] = False 3326 | await message.edit_text("**Welcome message disabled!**") 3327 | else: 3328 | await message.edit_text("Usage: .welcome [on/off] [message]") 3329 | 3330 | save_data() 3331 | 3332 | @app.on_message(filters.command("goodbye", prefixes=".") & filters.me) 3333 | async def set_goodbye_message(client: Client, message: Message): 3334 | if len(message.command) < 3: 3335 | return await message.edit_text("Usage: .goodbye [on/off] [message]") 3336 | 3337 | mode = message.command[1].lower() 3338 | goodbye_msg = " ".join(message.command[2:]) 3339 | 3340 | if message.chat.id not in group_settings: 3341 | group_settings[message.chat.id] = {} 3342 | 3343 | if mode == "on": 3344 | group_settings[message.chat.id]["goodbye"] = goodbye_msg 3345 | group_settings[message.chat.id]["goodbye_enabled"] = True 3346 | await message.edit_text("**Goodbye message enabled!**") 3347 | elif mode == "off": 3348 | group_settings[message.chat.id]["goodbye_enabled"] = False 3349 | await message.edit_text("**Goodbye message disabled!**") 3350 | else: 3351 | await message.edit_text("Usage: .goodbye [on/off] [message]") 3352 | 3353 | save_data() 3354 | 3355 | @app.on_message(filters.command("cloud", prefixes=".") & filters.me) 3356 | async def cloud_storage_menu(client: Client, message: Message): 3357 | keyboard = InlineKeyboardMarkup([ 3358 | [InlineKeyboardButton("Upload File", callback_data="cloud_upload")], 3359 | [InlineKeyboardButton("List Files", callback_data="cloud_list")], 3360 | [InlineKeyboardButton("Download File", callback_data="cloud_download")], 3361 | [InlineKeyboardButton("Delete File", callback_data="cloud_delete")] 3362 | ]) 3363 | 3364 | await message.edit_text("**☁️ Cloud Storage Menu**", reply_markup=keyboard) 3365 | 3366 | @app.on_message(filters.command("backup", prefixes=".") & filters.me) 3367 | async def backup_data(client: Client, message: Message): 3368 | try: 3369 | 3370 | backup_data = { 3371 | "auto_replies": auto_replies, 3372 | "blocked_users": list(blocked_users), 3373 | "notes": notes, 3374 | "reminders": reminders, 3375 | "custom_quotes": custom_quotes, 3376 | "custom_commands": custom_commands, 3377 | "scheduled_tasks": scheduled_tasks, 3378 | "user_data": user_data, 3379 | "group_settings": group_settings, 3380 | "timestamp": datetime.now().isoformat() 3381 | } 3382 | 3383 | backup_file = f"backup_{int(datetime.now().timestamp())}.json" 3384 | with open(backup_file, 'w') as f: 3385 | json.dump(backup_data, f, indent=2) 3386 | 3387 | 3388 | await client.send_document("me", backup_file, caption="**UserBot Backup**") 3389 | 3390 | 3391 | os.remove(backup_file) 3392 | 3393 | await message.edit_text("**Backup created and sent to Saved Messages!**") 3394 | except Exception as e: 3395 | await message.edit_text(f"**Error creating backup:** {str(e)}") 3396 | 3397 | @app.on_message(filters.command("restore", prefixes=".") & filters.me) 3398 | async def restore_data(client: Client, message: Message): 3399 | await message.edit_text("**Restore functionality needs implementation with file upload handling**") 3400 | 3401 | @app.on_message(filters.command("debug", prefixes=".") & filters.me) 3402 | async def debug_mode(client: Client, message: Message): 3403 | if len(message.command) < 2: 3404 | return await message.edit_text("Usage: .debug [on/off]") 3405 | 3406 | mode = message.command[1].lower() 3407 | if mode == "on": 3408 | 3409 | logger.setLevel(logging.DEBUG) 3410 | await message.edit_text("**Debug mode enabled!**") 3411 | elif mode == "off": 3412 | 3413 | logger.setLevel(logging.INFO) 3414 | await message.edit_text("**Debug mode disabled!**") 3415 | else: 3416 | await message.edit_text("Usage: .debug [on/off]") 3417 | 3418 | @app.on_message(filters.command("sysinfo", prefixes=".") & filters.me) 3419 | async def system_info(client: Client, message: Message): 3420 | try: 3421 | import psutil 3422 | import platform 3423 | 3424 | 3425 | uname = platform.uname() 3426 | boot_time = datetime.fromtimestamp(psutil.boot_time()) 3427 | uptime = datetime.now() - boot_time 3428 | 3429 | info = "**System Information:**\n" 3430 | info += f"System: {uname.system}\n" 3431 | info += f"Node Name: {uname.node}\n" 3432 | info += f"Release: {uname.release}\n" 3433 | info += f"Version: {uname.version}\n" 3434 | info += f"Machine: {uname.machine}\n" 3435 | info += f"Processor: {uname.processor}\n" 3436 | info += f"Boot Time: {boot_time.strftime('%Y-%m-%d %H:%M:%S')}\n" 3437 | info += f"Uptime: {uptime}\n\n" 3438 | 3439 | 3440 | info += "**CPU Info:**\n" 3441 | info += f"Physical cores: {psutil.cpu_count(logical=False)}\n" 3442 | info += f"Total cores: {psutil.cpu_count(logical=True)}\n" 3443 | info += f"Max Frequency: {psutil.cpu_freq().max:.2f}Mhz\n" 3444 | info += f"Current Frequency: {psutil.cpu_freq().current:.2f}Mhz\n" 3445 | info += f"CPU Usage: {psutil.cpu_percent()}%\n\n" 3446 | 3447 | 3448 | svmem = psutil.virtual_memory() 3449 | info += "**Memory Information:**\n" 3450 | info += f"Total: {svmem.total / (1024**3):.2f} GB\n" 3451 | info += f"Available: {svmem.available / (1024**3):.2f} GB\n" 3452 | info += f"Used: {svmem.used / (1024**3):.2f} GB\n" 3453 | info += f"Percentage: {svmem.percent}%\n" 3454 | 3455 | await message.edit_text(info) 3456 | except Exception as e: 3457 | await message.edit_text(f"**Error:** {str(e)}") 3458 | 3459 | 3460 | @app.on_message(filters.command("speedtest", prefixes=".") & filters.me) 3461 | async def speed_test(client: Client, message: Message): 3462 | try: 3463 | args = message.text.split()[1:] if len(message.text.split()) > 1 else [] 3464 | mode = args[0].lower() if args else "quick" 3465 | 3466 | if mode in ["q", "quick"]: 3467 | await quick_speedtest(message) 3468 | elif mode in ["adv", "advanced"]: 3469 | await advanced_speedtest(message) 3470 | else: 3471 | await message.edit_text("**Usage:** `.speedtest [q/quick] [adv/advanced]`") 3472 | 3473 | except Exception as e: 3474 | await message.edit_text(f"**❌ Speedtest failed:** `{str(e)}`") 3475 | 3476 | async def quick_speedtest(message): 3477 | await message.edit_text("**⚡ Quick Speedtest**\n\n🏓 Testing ping...") 3478 | start = time.time() 3479 | async with aiohttp.ClientSession() as session: 3480 | async with session.get('https://www.google.com', timeout=5) as r: 3481 | pass 3482 | ping = round((time.time() - start) * 1000, 2) 3483 | 3484 | await message.edit_text("**⚡ Quick Speedtest**\n\n⬇️ Testing download...") 3485 | start = time.time() 3486 | async with aiohttp.ClientSession() as session: 3487 | async with session.get('https://speed.cloudflare.com/__down?bytes=10000000', timeout=20) as r: 3488 | size = 0 3489 | async for chunk in r.content.iter_chunked(8192): 3490 | size += len(chunk) 3491 | duration = time.time() - start 3492 | download = round((size * 8) / (duration * 1024 * 1024), 2) 3493 | 3494 | await message.edit_text("**⚡ Quick Speedtest**\n\n⬆️ Testing upload...") 3495 | data = b'0' * (1024 * 1024) 3496 | start = time.time() 3497 | async with aiohttp.ClientSession() as session: 3498 | async with session.post('https://httpbin.org/post', data=data, timeout=15) as r: 3499 | pass 3500 | upload = round((len(data) * 8) / ((time.time() - start) * 1024 * 1024), 2) 3501 | 3502 | if download >= 100: quality = "🟢 Excellent" 3503 | elif download >= 50: quality = "🟡 Good" 3504 | elif download >= 25: quality = "🟠 Fair" 3505 | else: quality = "🔴 Poor" 3506 | 3507 | result = f"""**⚡ Quick Speedtest Results** 3508 | 3509 | **📊 Quality:** {quality} 3510 | **🏓 Ping:** {ping} ms 3511 | **⬇️ Download:** {download} Mbps 3512 | **⬆️ Upload:** {upload} Mbps 3513 | 3514 | **📅 {datetime.now().strftime('%H:%M:%S')}** • Use `.speedtest adv` for detailed analysis""" 3515 | await message.edit_text(result) 3516 | 3517 | async def advanced_speedtest(message): 3518 | results = {} 3519 | await message.edit_text("**🚀 Advanced Speedtest**\n\n📊 System analysis...") 3520 | try: 3521 | import psutil 3522 | results['system'] = { 3523 | 'os': f"{platform.system()} {platform.release()}", 3524 | 'cpu': psutil.cpu_count(), 3525 | 'ram': f"{round(psutil.virtual_memory().available/1024**3, 1)}GB available" 3526 | } 3527 | except: 3528 | results['system'] = {'info': 'Limited system info available'} 3529 | 3530 | await message.edit_text("**🚀 Advanced Speedtest**\n\n🌐 Network analysis...") 3531 | try: 3532 | async with aiohttp.ClientSession() as session: 3533 | async with session.get('https://api.ipify.org?format=json', timeout=5) as r: 3534 | ip_data = await r.json() 3535 | async with session.get(f'https://ipapi.co/{ip_data["ip"]}/json/', timeout=5) as r: 3536 | geo_data = await r.json() 3537 | results['network'] = { 3538 | 'ip': ip_data['ip'], 3539 | 'isp': geo_data.get('org', 'Unknown'), 3540 | 'location': f"{geo_data.get('city', 'Unknown')}, {geo_data.get('country_name', 'Unknown')}" 3541 | } 3542 | except: 3543 | results['network'] = {'info': 'Network info unavailable'} 3544 | 3545 | await message.edit_text("**🚀 Advanced Speedtest**\n\n🏓 Multi-server ping test...") 3546 | servers = {'Google': 'https://www.google.com', 'Cloudflare': 'https://1.1.1.1', 'GitHub': 'https://github.com'} 3547 | ping_results = {} 3548 | for name, url in servers.items(): 3549 | try: 3550 | times = [] 3551 | for _ in range(3): 3552 | start = time.time() 3553 | async with aiohttp.ClientSession() as session: 3554 | async with session.get(url, timeout=3) as r: 3555 | pass 3556 | times.append((time.time() - start) * 1000) 3557 | await asyncio.sleep(0.2) 3558 | ping_results[name] = { 3559 | 'avg': round(statistics.mean(times), 1), 3560 | 'jitter': round(statistics.stdev(times), 1) if len(times) > 1 else 0 3561 | } 3562 | except: 3563 | ping_results[name] = {'avg': 999, 'jitter': 999} 3564 | results['ping'] = ping_results 3565 | 3566 | await message.edit_text("**🚀 Advanced Speedtest**\n\n📈 Connection stability...") 3567 | try: 3568 | stability_times = [] 3569 | for _ in range(5): 3570 | start = time.time() 3571 | async with aiohttp.ClientSession() as session: 3572 | async with session.get('https://www.google.com', timeout=3) as r: 3573 | pass 3574 | stability_times.append((time.time() - start) * 1000) 3575 | await asyncio.sleep(0.5) 3576 | avg_ping = statistics.mean(stability_times) 3577 | jitter = statistics.stdev(stability_times) 3578 | results['stability'] = { 3579 | 'avg_ping': round(avg_ping, 1), 3580 | 'jitter': round(jitter, 1), 3581 | 'quality': 'Excellent' if jitter < 5 else 'Good' if jitter < 15 else 'Poor' 3582 | } 3583 | except: 3584 | results['stability'] = {'quality': 'Test failed'} 3585 | 3586 | await message.edit_text("**🚀 Advanced Speedtest**\n\n⬇️ Multi-size download test...") 3587 | download_results = {} 3588 | test_sizes = [5, 25, 50] 3589 | for size_mb in test_sizes: 3590 | try: 3591 | start = time.time() 3592 | async with aiohttp.ClientSession() as session: 3593 | url = f'https://speed.cloudflare.com/__down?bytes={size_mb * 1024 * 1024}' 3594 | async with session.get(url, timeout=30) as r: 3595 | total = 0 3596 | async for chunk in r.content.iter_chunked(8192): 3597 | total += len(chunk) 3598 | duration = time.time() - start 3599 | speed = round((total * 8) / (duration * 1024 * 1024), 2) 3600 | download_results[f'{size_mb}MB'] = speed 3601 | except: 3602 | download_results[f'{size_mb}MB'] = 0 3603 | results['download'] = download_results 3604 | 3605 | await message.edit_text("**Advanced Speedtest**\n\n⬆️ Upload test...") 3606 | try: 3607 | data = b'0' * (2 * 1024 * 1024) 3608 | start = time.time() 3609 | async with aiohttp.ClientSession() as session: 3610 | async with session.post('https://httpbin.org/post', data=data, timeout=20) as r: 3611 | pass 3612 | upload_speed = round((len(data) * 8) / ((time.time() - start) * 1024 * 1024), 2) 3613 | results['upload'] = upload_speed 3614 | except: 3615 | results['upload'] = 0 3616 | 3617 | await message.edit_text("**Advanced Speedtest**\n\n🔍 DNS resolution test...") 3618 | dns_servers = {'Cloudflare': '1.1.1.1', 'Google': '8.8.8.8', 'OpenDNS': '208.67.222.222'} 3619 | dns_results = {} 3620 | for name, server in dns_servers.items(): 3621 | try: 3622 | start = time.time() 3623 | socket.gethostbyname('google.com') 3624 | dns_results[name] = round((time.time() - start) * 1000, 1) 3625 | except: 3626 | dns_results[name] = 999 3627 | results['dns'] = dns_results 3628 | 3629 | sys_info = results.get('system', {}) 3630 | net_info = results.get('network', {}) 3631 | ping_data = results.get('ping', {}) 3632 | stability = results.get('stability', {}) 3633 | downloads = results.get('download', {}) 3634 | 3635 | report = f"""**Advanced Speedtest Results** 3636 | 3637 | **💻 System:** {sys_info.get('os', 'N/A')} • {sys_info.get('cpu', 'N/A')} cores • {sys_info.get('ram', 'N/A')} 3638 | **🌐 Network:** {net_info.get('isp', 'N/A')} • {net_info.get('location', 'N/A')} 3639 | 3640 | **🏓 Multi-Server Ping:""" 3641 | for server, data in ping_data.items(): 3642 | report += f"\n• {server}: {data['avg']}ms (±{data['jitter']}ms)" 3643 | 3644 | report += f""" 3645 | 3646 | **📊 Connection Quality:** 3647 | • Stability: {stability.get('quality', 'N/A')} (Jitter: {stability.get('jitter', 'N/A')}ms) 3648 | 3649 | **⬇️ Download Speeds:**""" 3650 | for size, speed in downloads.items(): 3651 | report += f"\n• {size}: {speed} Mbps" 3652 | 3653 | avg_download = round(sum(downloads.values()) / len(downloads), 1) if downloads else 0 3654 | 3655 | report += f""" 3656 | 3657 | **⬆️ Upload:** {results.get('upload', 'N/A')} Mbps 3658 | **🔍 DNS:** {min(results.get('dns', {}).values(), default='N/A')}ms (fastest) 3659 | 3660 | **📈 Overall Score:** {avg_download} Mbps avg • {stability.get('quality', 'Unknown')} stability 3661 | **📅 Completed:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}""" 3662 | await message.edit_text(report) 3663 | 3664 | @app.on_message(filters.command("speedhistory", prefixes=".") & filters.me) 3665 | async def speed_history_cmd(client: Client, message: Message): 3666 | if not speed_history: 3667 | await message.edit_text("**📈 Speed History**\n\nNo tests recorded yet. Run `.speedtest` first!") 3668 | return 3669 | history_text = "**📈 Speed History (Last 10 tests)**\n\n" 3670 | for i, record in enumerate(speed_history[-10:], 1): 3671 | history_text += f"**{i}.** {record['time']} • ⬇️{record['download']}Mbps • 🏓{record['ping']}ms\n" 3672 | await message.edit_text(history_text) 3673 | 3674 | def save_speed_result(download, ping, upload=None): 3675 | speed_history.append({ 3676 | 'time': datetime.now().strftime('%m/%d %H:%M'), 3677 | 'download': download, 3678 | 'ping': ping, 3679 | 'upload': upload 3680 | }) 3681 | if len(speed_history) > 50: 3682 | speed_history.pop(0) 3683 | 3684 | @app.on_message(filters.command("logs", prefixes=".") & filters.me) 3685 | async def get_logs(client: Client, message: Message): 3686 | try: 3687 | 3688 | await message.edit_text("**Logs functionality needs implementation**") 3689 | except Exception as e: 3690 | await message.edit_text(f"**Error:** {str(e)}") 3691 | 3692 | @app.on_message(filters.command("restart", prefixes=".") & filters.me) 3693 | async def restart_bot(client: Client, message: Message): 3694 | await message.edit_text("**Restarting bot...**") 3695 | 3696 | 3697 | await asyncio.sleep(2) 3698 | await message.edit_text("**Bot restarted!**") 3699 | 3700 | @app.on_message(filters.command("update", prefixes=".") & filters.me) 3701 | async def update_bot(client: Client, message: Message): 3702 | await message.edit_text("**Checking for updates...** (Implementation pending)") 3703 | 3704 | @app.on_message(filters.command("cleanup", prefixes=".") & filters.me) 3705 | async def cleanup_files(client: Client, message: Message): 3706 | try: 3707 | 3708 | cleaned = 0 3709 | for root, dirs, files in os.walk("temp"): 3710 | for file in files: 3711 | try: 3712 | os.remove(os.path.join(root, file)) 3713 | cleaned += 1 3714 | except: 3715 | pass 3716 | 3717 | await message.edit_text(f"**Cleaned up {cleaned} temporary files!**") 3718 | except Exception as e: 3719 | await message.edit_text(f"**Error during cleanup:** {str(e)}") 3720 | 3721 | @app.on_message(filters.command("broadcast", prefixes=".") & filters.me) 3722 | async def broadcast_message(client: Client, message: Message): 3723 | if len(message.command) < 2: 3724 | return await message.edit_text("Usage: .broadcast [message]") 3725 | 3726 | broadcast_msg = " ".join(message.command[1:]) 3727 | 3728 | await message.edit_text("**Broadcast functionality needs implementation**") 3729 | 3730 | 3731 | 3732 | @app.on_message(filters.command("pingall", prefixes=".") & filters.me) 3733 | async def ping_all_members(client: Client, message: Message): 3734 | """Ping all members in the current chat""" 3735 | try: 3736 | await message.edit_text("**🔄 Fetching chat members...**") 3737 | 3738 | chat_id = message.chat.id 3739 | members = [] 3740 | mentions = [] 3741 | 3742 | 3743 | async for member in client.get_chat_members(chat_id): 3744 | if not member.user.is_bot and not member.user.is_deleted: 3745 | members.append(member.user) 3746 | 3747 | if not members: 3748 | return await message.edit_text("**❌ No members found to ping!**") 3749 | 3750 | 3751 | batch_size = 5 3752 | total_batches = (len(members) + batch_size - 1) // batch_size 3753 | 3754 | await message.edit_text(f"**📢 Pinging {len(members)} members in {total_batches} batches...**") 3755 | 3756 | for i in range(0, len(members), batch_size): 3757 | batch = members[i:i+batch_size] 3758 | mention_text = " ".join([f"[{user.first_name}](tg://user?id={user.id})" for user in batch]) 3759 | 3760 | if i == 0: 3761 | await message.edit_text(f"**📢 Ping {(i//batch_size)+1}:**\n{mention_text}") 3762 | else: 3763 | await message.reply_text(f"**📢 Ping {(i//batch_size)+1}:**\n{mention_text}") 3764 | 3765 | 3766 | await asyncio.sleep(1) 3767 | 3768 | await message.reply_text(f"**✅ Successfully pinged {len(members)} members!**") 3769 | 3770 | except FloodWait as e: 3771 | await message.edit_text(f"**⚠️ Rate limited! Wait {e.value} seconds**") 3772 | except Exception as e: 3773 | await message.edit_text(f"**❌ Error:** `{str(e)}`") 3774 | 3775 | @app.on_message(filters.command("export", prefixes=".") & filters.me) 3776 | async def export_chat_members(client: Client, message: Message): 3777 | """Export chat members to a file""" 3778 | try: 3779 | await message.edit_text("**🔄 Exporting chat members...**") 3780 | 3781 | chat_id = message.chat.id 3782 | chat_info = await client.get_chat(chat_id) 3783 | members_data = [] 3784 | 3785 | 3786 | async for member in client.get_chat_members(chat_id): 3787 | user = member.user 3788 | member_info = { 3789 | "id": user.id, 3790 | "first_name": user.first_name or "", 3791 | "last_name": user.last_name or "", 3792 | "username": user.username or "", 3793 | "phone_number": user.phone_number or "", 3794 | "is_bot": user.is_bot, 3795 | "is_verified": user.is_verified, 3796 | "is_premium": user.is_premium, 3797 | "status": str(member.status), 3798 | "joined_date": member.joined_date.isoformat() if member.joined_date else "", 3799 | } 3800 | members_data.append(member_info) 3801 | 3802 | 3803 | export_data = { 3804 | "chat_info": { 3805 | "id": chat_info.id, 3806 | "title": chat_info.title or "", 3807 | "type": str(chat_info.type), 3808 | "members_count": len(members_data), 3809 | "export_date": datetime.now().isoformat() 3810 | }, 3811 | "members": members_data 3812 | } 3813 | 3814 | 3815 | filename = f"chat_export_{chat_id}_{int(time.time())}.json" 3816 | with open(filename, 'w', encoding='utf-8') as f: 3817 | json.dump(export_data, f, indent=2, ensure_ascii=False) 3818 | 3819 | 3820 | await message.edit_text(f"**📁 Exported {len(members_data)} members**") 3821 | await client.send_document( 3822 | chat_id, 3823 | filename, 3824 | caption=f"**📊 Chat Export**\n**Chat:** {chat_info.title}\n**Members:** {len(members_data)}\n**Date:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" 3825 | ) 3826 | 3827 | 3828 | os.remove(filename) 3829 | 3830 | except Exception as e: 3831 | await message.edit_text(f"**❌ Export failed:** `{str(e)}`") 3832 | 3833 | @app.on_message(filters.command("import", prefixes=".") & filters.me) 3834 | async def import_chat_members(client: Client, message: Message): 3835 | """Import members from a JSON file to current chat""" 3836 | try: 3837 | 3838 | if not message.reply_to_message or not message.reply_to_message.document: 3839 | return await message.edit_text("**❌ Reply to a JSON export file to import members**") 3840 | 3841 | await message.edit_text("**🔄 Downloading and processing file...**") 3842 | 3843 | 3844 | file_path = await client.download_media(message.reply_to_message) 3845 | 3846 | 3847 | with open(file_path, 'r', encoding='utf-8') as f: 3848 | import_data = json.load(f) 3849 | 3850 | members = import_data.get('members', []) 3851 | chat_id = message.chat.id 3852 | 3853 | successful_adds = 0 3854 | failed_adds = 0 3855 | 3856 | await message.edit_text(f"**🔄 Importing {len(members)} members...**") 3857 | 3858 | for i, member in enumerate(members): 3859 | try: 3860 | user_id = member.get('id') 3861 | username = member.get('username') 3862 | 3863 | 3864 | if username: 3865 | await client.add_chat_members(chat_id, f"@{username}") 3866 | else: 3867 | await client.add_chat_members(chat_id, user_id) 3868 | 3869 | successful_adds += 1 3870 | 3871 | 3872 | if (i + 1) % 10 == 0: 3873 | await message.edit_text(f"**🔄 Progress: {i+1}/{len(members)}\n✅ Added: {successful_adds}\n❌ Failed: {failed_adds}**") 3874 | 3875 | 3876 | await asyncio.sleep(1) 3877 | 3878 | except FloodWait as e: 3879 | await asyncio.sleep(e.value) 3880 | continue 3881 | except Exception: 3882 | failed_adds += 1 3883 | continue 3884 | 3885 | await message.edit_text(f"**📊 Import Complete**\n**✅ Successfully added:** {successful_adds}\n**❌ Failed to add:** {failed_adds}") 3886 | 3887 | 3888 | os.remove(file_path) 3889 | 3890 | except Exception as e: 3891 | await message.edit_text(f"**❌ Import failed:** `{str(e)}`") 3892 | 3893 | @app.on_message(filters.command("ss", prefixes=".") & filters.me) 3894 | async def take_screenshot(client: Client, message: Message): 3895 | """Take screenshot of a website using Pyppeteer""" 3896 | if len(message.command) < 2: 3897 | return await message.edit_text("**Usage:** `.screenshot [url]`") 3898 | 3899 | try: 3900 | url = message.command[1] 3901 | if not url.startswith(('http://', 'https://')): 3902 | url = 'https://' + url 3903 | 3904 | await message.edit_text(f"**🔄 Taking screenshot of {url}...**") 3905 | 3906 | 3907 | browser = await launch( 3908 | headless=True, 3909 | args=[ 3910 | '--no-sandbox', 3911 | '--disable-setuid-sandbox', 3912 | '--disable-dev-shm-usage', 3913 | '--disable-accelerated-2d-canvas', 3914 | '--no-first-run', 3915 | '--no-zygote', 3916 | '--single-process', 3917 | '--disable-gpu' 3918 | ] 3919 | ) 3920 | 3921 | try: 3922 | 3923 | page = await browser.newPage() 3924 | 3925 | 3926 | await page.setViewport({'width': 1920, 'height': 1080}) 3927 | 3928 | 3929 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36') 3930 | 3931 | 3932 | await page.goto(url, {'waitUntil': 'networkidle2', 'timeout': 30000}) 3933 | 3934 | 3935 | await asyncio.sleep(2) 3936 | 3937 | 3938 | screenshot_path = f"screenshot_{int(time.time())}.png" 3939 | await page.screenshot({ 3940 | 'path': screenshot_path, 3941 | 'fullPage': True, 3942 | 'quality': 90 3943 | }) 3944 | 3945 | 3946 | title = await page.title() 3947 | 3948 | 3949 | await message.edit_text(f"**📸 Screenshot captured!**") 3950 | await client.send_photo( 3951 | message.chat.id, 3952 | screenshot_path, 3953 | caption=f"**🔗 URL:** {url}\n**📄 Title:** {title[:50]}{'...' if len(title) > 50 else ''}\n**📅 Time:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" 3954 | ) 3955 | 3956 | 3957 | os.remove(screenshot_path) 3958 | 3959 | finally: 3960 | await browser.close() 3961 | 3962 | except Exception as e: 3963 | await message.edit_text(f"**❌ Screenshot failed:** `{str(e)}`") 3964 | 3965 | @app.on_message(filters.command("currency", prefixes=".") & filters.me) 3966 | async def currency_converter(client: Client, message: Message): 3967 | """Convert currency using live exchange rates""" 3968 | if len(message.command) < 4: 3969 | return await message.edit_text("**Usage:** `.currency [amount] [from_currency] [to_currency]`\n**Example:** `.currency 100 USD EUR`") 3970 | 3971 | try: 3972 | amount = float(message.command[1]) 3973 | from_curr = message.command[2].upper() 3974 | to_curr = message.command[3].upper() 3975 | 3976 | await message.edit_text("**🔄 Getting exchange rates...**") 3977 | 3978 | 3979 | async with aiohttp.ClientSession() as session: 3980 | url = f"https://api.exchangerate-api.com/v4/latest/{from_curr}" 3981 | async with session.get(url) as response: 3982 | if response.status == 200: 3983 | data = await response.json() 3984 | 3985 | if to_curr in data['rates']: 3986 | rate = data['rates'][to_curr] 3987 | converted = amount * rate 3988 | 3989 | await message.edit_text( 3990 | f"**💱 Currency Conversion**\n\n" 3991 | f"**Amount:** {amount:,.2f} {from_curr}\n" 3992 | f"**Converts to:** {converted:,.2f} {to_curr}\n" 3993 | f"**Exchange Rate:** 1 {from_curr} = {rate:.4f} {to_curr}\n" 3994 | f"**Last Updated:** {data['date']}" 3995 | ) 3996 | else: 3997 | await message.edit_text(f"**❌ Currency '{to_curr}' not found!**") 3998 | else: 3999 | await message.edit_text("**❌ Failed to fetch exchange rates!**") 4000 | 4001 | except ValueError: 4002 | await message.edit_text("**❌ Invalid amount! Please enter a valid number.**") 4003 | except Exception as e: 4004 | await message.edit_text(f"**❌ Error:** `{str(e)}`") 4005 | 4006 | @app.on_message(filters.command("time", prefixes=".") & filters.me) 4007 | async def get_time(client: Client, message: Message): 4008 | """Get current time for a specific location""" 4009 | if len(message.command) < 2: 4010 | return await message.edit_text("**Usage:** `.time [location]`\n**Example:** `.time New York`") 4011 | 4012 | try: 4013 | location = " ".join(message.command[1:]) 4014 | await message.edit_text(f"**🔄 Getting time for {location}...**") 4015 | 4016 | 4017 | async with aiohttp.ClientSession() as session: 4018 | 4019 | url = f"http://worldtimeapi.org/api/timezone" 4020 | async with session.get(url) as response: 4021 | if response.status == 200: 4022 | timezones = await response.json() 4023 | 4024 | 4025 | location_lower = location.lower() 4026 | matching_tz = None 4027 | 4028 | for tz in timezones: 4029 | if location_lower in tz.lower(): 4030 | matching_tz = tz 4031 | break 4032 | 4033 | if not matching_tz: 4034 | 4035 | city_mapping = { 4036 | 'new york': 'America/New_York', 4037 | 'london': 'Europe/London', 4038 | 'tokyo': 'Asia/Tokyo', 4039 | 'dubai': 'Asia/Dubai', 4040 | 'sydney': 'Australia/Sydney', 4041 | 'paris': 'Europe/Paris', 4042 | 'berlin': 'Europe/Berlin', 4043 | 'moscow': 'Europe/Moscow', 4044 | 'delhi': 'Asia/Kolkata', 4045 | 'mumbai': 'Asia/Kolkata', 4046 | 'kolkata': 'Asia/Kolkata', 4047 | 'chennai': 'Asia/Kolkata', 4048 | 'bangalore': 'Asia/Kolkata', 4049 | } 4050 | matching_tz = city_mapping.get(location_lower) 4051 | 4052 | if matching_tz: 4053 | url = f"http://worldtimeapi.org/api/timezone/{matching_tz}" 4054 | async with session.get(url) as tz_response: 4055 | if tz_response.status == 200: 4056 | time_data = await tz_response.json() 4057 | 4058 | datetime_str = time_data['datetime'] 4059 | timezone = time_data['timezone'] 4060 | utc_offset = time_data['utc_offset'] 4061 | 4062 | 4063 | dt = datetime.fromisoformat(datetime_str.replace('Z', '+00:00')) 4064 | 4065 | await message.edit_text( 4066 | f"**🕐 Time Information**\n\n" 4067 | f"**Location:** {location}\n" 4068 | f"**Timezone:** {timezone}\n" 4069 | f"**Current Time:** {dt.strftime('%Y-%m-%d %H:%M:%S')}\n" 4070 | f"**UTC Offset:** {utc_offset}\n" 4071 | f"**Day of Year:** {time_data['day_of_year']}\n" 4072 | f"**Week Number:** {time_data['week_number']}" 4073 | ) 4074 | else: 4075 | await message.edit_text(f"**❌ Could not get time data for {location}**") 4076 | else: 4077 | await message.edit_text(f"**❌ Location '{location}' not found! Try a major city name.**") 4078 | 4079 | except Exception as e: 4080 | await message.edit_text(f"**❌ Error:** `{str(e)}`") 4081 | 4082 | @app.on_message(filters.command("domain", prefixes=".") & filters.me) 4083 | async def domain_info(client: Client, message: Message): 4084 | """Get comprehensive domain information""" 4085 | if len(message.command) < 2: 4086 | return await message.edit_text("**Usage:** `.domain [domain]`\n**Example:** `.domain google.com`") 4087 | 4088 | try: 4089 | domain = message.command[1].replace('http://', '').replace('https://', '').split('/')[0] 4090 | await message.edit_text(f"**🔄 Analyzing domain {domain}...**") 4091 | 4092 | domain_info = {} 4093 | 4094 | 4095 | try: 4096 | ip = socket.gethostbyname(domain) 4097 | domain_info['ip'] = ip 4098 | except: 4099 | domain_info['ip'] = "Not found" 4100 | 4101 | 4102 | try: 4103 | w = whois.whois(domain) 4104 | domain_info['registrar'] = w.registrar or "Not available" 4105 | domain_info['creation_date'] = str(w.creation_date) if w.creation_date else "Not available" 4106 | domain_info['expiration_date'] = str(w.expiration_date) if w.expiration_date else "Not available" 4107 | domain_info['name_servers'] = w.name_servers if w.name_servers else ["Not available"] 4108 | except: 4109 | domain_info.update({ 4110 | 'registrar': "Not available", 4111 | 'creation_date': "Not available", 4112 | 'expiration_date': "Not available", 4113 | 'name_servers': ["Not available"] 4114 | }) 4115 | 4116 | 4117 | try: 4118 | async with aiohttp.ClientSession() as session: 4119 | async with session.get(f"http://{domain}", timeout=10) as response: 4120 | domain_info['http_status'] = response.status 4121 | domain_info['server'] = response.headers.get('server', 'Not available') 4122 | except: 4123 | domain_info['http_status'] = "Not available" 4124 | domain_info['server'] = "Not available" 4125 | 4126 | 4127 | ns_list = domain_info['name_servers'] 4128 | if isinstance(ns_list, list) and len(ns_list) > 1: 4129 | ns_text = '\n'.join([f"• {ns}" for ns in ns_list[:5]]) 4130 | else: 4131 | ns_text = str(ns_list[0]) if ns_list else "Not available" 4132 | 4133 | result = f"""**🌐 Domain Information** 4134 | 4135 | **Domain:** {domain} 4136 | **IP Address:** {domain_info['ip']} 4137 | **HTTP Status:** {domain_info['http_status']} 4138 | **Server:** {domain_info['server']} 4139 | 4140 | **📋 Registration Details** 4141 | **Registrar:** {domain_info['registrar']} 4142 | **Created:** {domain_info['creation_date']} 4143 | **Expires:** {domain_info['expiration_date']} 4144 | 4145 | **🔧 Name Servers** 4146 | {ns_text}""" 4147 | 4148 | await message.edit_text(result) 4149 | 4150 | except Exception as e: 4151 | await message.edit_text(f"**❌ Error analyzing domain:** `{str(e)}`") 4152 | 4153 | @app.on_message(filters.command("ip", prefixes=".") & filters.me) 4154 | async def ip_info(client: Client, message: Message): 4155 | """Get detailed IP address information""" 4156 | if len(message.command) < 2: 4157 | return await message.edit_text("**Usage:** `.ip [ip_address]`\n**Example:** `.ip 8.8.8.8`") 4158 | 4159 | try: 4160 | ip = message.command[1] 4161 | await message.edit_text(f"**🔄 Analyzing IP {ip}...**") 4162 | 4163 | 4164 | async with aiohttp.ClientSession() as session: 4165 | url = f"http://ip-api.com/json/{ip}?fields=status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,offset,currency,isp,org,as,asname,reverse,mobile,proxy,hosting,query" 4166 | 4167 | async with session.get(url) as response: 4168 | if response.status == 200: 4169 | data = await response.json() 4170 | 4171 | if data['status'] == 'success': 4172 | result = f"""**🌍 IP Address Information** 4173 | 4174 | **IP:** {data['query']} 4175 | **ISP:** {data.get('isp', 'N/A')} 4176 | **Organization:** {data.get('org', 'N/A')} 4177 | **AS:** {data.get('as', 'N/A')} 4178 | 4179 | **📍 Location** 4180 | **Country:** {data.get('country', 'N/A')} ({data.get('countryCode', 'N/A')}) 4181 | **Region:** {data.get('regionName', 'N/A')} ({data.get('region', 'N/A')}) 4182 | **City:** {data.get('city', 'N/A')} 4183 | **ZIP Code:** {data.get('zip', 'N/A')} 4184 | **Coordinates:** {data.get('lat', 'N/A')}, {data.get('lon', 'N/A')} 4185 | 4186 | **🕐 Time Zone** 4187 | **Timezone:** {data.get('timezone', 'N/A')} 4188 | **UTC Offset:** {data.get('offset', 'N/A')} 4189 | 4190 | **🔍 Additional Info** 4191 | **Reverse DNS:** {data.get('reverse', 'N/A')} 4192 | **Mobile:** {'Yes' if data.get('mobile') else 'No'} 4193 | **Proxy:** {'Yes' if data.get('proxy') else 'No'} 4194 | **Hosting:** {'Yes' if data.get('hosting') else 'No'}""" 4195 | 4196 | await message.edit_text(result) 4197 | else: 4198 | await message.edit_text(f"**❌ Failed to get IP info:** {data.get('message', 'Unknown error')}") 4199 | else: 4200 | await message.edit_text("**❌ Failed to fetch IP information!**") 4201 | 4202 | except Exception as e: 4203 | await message.edit_text(f"**❌ Error:** `{str(e)}`") 4204 | 4205 | @app.on_message(filters.command("whoisdomain", prefixes=".") & filters.me) 4206 | async def whois_domain(client: Client, message: Message): 4207 | """Get detailed WHOIS information for a domain""" 4208 | if len(message.command) < 2: 4209 | return await message.edit_text("**Usage:** `.whoisdomain [domain]`\n**Example:** `.whoisdomain google.com`") 4210 | 4211 | try: 4212 | domain = message.command[1].replace('http://', '').replace('https://', '').split('/')[0] 4213 | await message.edit_text(f"**🔄 Getting WHOIS data for {domain}...**") 4214 | 4215 | 4216 | w = whois.query(domain) 4217 | 4218 | 4219 | def format_date(date_obj): 4220 | if isinstance(date_obj, list): 4221 | return str(date_obj[0]) if date_obj else "Not available" 4222 | return str(date_obj) if date_obj else "Not available" 4223 | 4224 | 4225 | name_servers = w.name_servers 4226 | if name_servers and isinstance(name_servers, list): 4227 | ns_text = '\n'.join([f"• {ns}" for ns in name_servers[:8]]) 4228 | else: 4229 | ns_text = str(name_servers) if name_servers else "Not available" 4230 | 4231 | 4232 | def format_contact(contact_list): 4233 | if contact_list and isinstance(contact_list, list): 4234 | return contact_list[0] if contact_list[0] else "Not available" 4235 | return str(contact_list) if contact_list else "Not available" 4236 | 4237 | result = f"""**📋 WHOIS Information** 4238 | 4239 | **Domain:** {domain} 4240 | **Registrar:** {w.registrar or 'Not available'} 4241 | **WHOIS Server:** {w.whois_server or 'Not available'} 4242 | 4243 | **📅 Important Dates** 4244 | **Created:** {format_date(w.creation_date)} 4245 | **Updated:** {format_date(w.updated_date)} 4246 | **Expires:** {format_date(w.expiration_date)} 4247 | 4248 | **👤 Registrant** 4249 | **Name:** {w.name or 'Not available'} 4250 | **Organization:** {w.org or 'Not available'} 4251 | **Email:** {format_contact(w.emails)} 4252 | 4253 | **🔧 Technical Details** 4254 | **Status:** {w.status or 'Not available'} 4255 | **DNSSEC:** {w.dnssec or 'Not available'} 4256 | 4257 | **🌐 Name Servers** 4258 | {ns_text} 4259 | 4260 | **🏢 Registrar Info** 4261 | **Registrar IANA ID:** {w.registrar_iana_id or 'Not available'} 4262 | **Registrar URL:** {w.registrar_url or 'Not available'}""" 4263 | 4264 | 4265 | if len(result) > 4096: 4266 | parts = [result[i:i+4000] for i in range(0, len(result), 4000)] 4267 | await message.edit_text(parts[0]) 4268 | for part in parts[1:]: 4269 | await message.reply_text(part) 4270 | else: 4271 | await message.edit_text(result) 4272 | 4273 | except Exception as e: 4274 | await message.edit_text(f"**❌ WHOIS lookup failed:** `{str(e)}`") 4275 | 4276 | 4277 | 4278 | async def get_chat_member_count(client: Client, chat_id: int) -> int: 4279 | """Get total member count of a chat""" 4280 | try: 4281 | chat = await client.get_chat(chat_id) 4282 | return chat.members_count or 0 4283 | except: 4284 | return 0 4285 | 4286 | @app.on_message(filters.command("eval", prefixes=".") & filters.me) 4287 | async def evaluate_code(client: Client, message: Message): 4288 | if len(message.command) < 2: 4289 | return await message.edit_text("Usage: .eval [code]") 4290 | 4291 | code = " ".join(message.command[1:]) 4292 | try: 4293 | 4294 | 4295 | result = eval(code) 4296 | await message.edit_text(f"**Result:**\n```\n{result}\n```") 4297 | except Exception as e: 4298 | await message.edit_text(f"**Error:** {str(e)}") 4299 | 4300 | @app.on_message(filters.command("exec", prefixes=".") & filters.me) 4301 | async def execute_code(client: Client, message: Message): 4302 | if len(message.command) < 2: 4303 | return await message.edit_text("Usage: .exec [code]") 4304 | 4305 | code = " ".join(message.command[1:]) 4306 | try: 4307 | 4308 | 4309 | exec(code) 4310 | await message.edit_text("**Code executed successfully!**") 4311 | except Exception as e: 4312 | await message.edit_text(f"**Error:** {str(e)}") 4313 | 4314 | @app.on_message(filters.command("shell", prefixes=".") & filters.me) 4315 | async def execute_shell(client: Client, message: Message): 4316 | if len(message.command) < 2: 4317 | return await message.edit_text("Usage: .shell [command]") 4318 | 4319 | command = " ".join(message.command[1:]) 4320 | try: 4321 | 4322 | 4323 | import subprocess 4324 | result = subprocess.run(command, shell=True, capture_output=True, text=True) 4325 | output = result.stdout or result.stderr 4326 | await message.edit_text(f"**Shell Output:**\n```\n{output}\n```") 4327 | except Exception as e: 4328 | await message.edit_text(f"**Error:** {str(e)}") 4329 | 4330 | @app.on_message(filters.command("addon", prefixes=".") & filters.me) 4331 | async def load_addon(client: Client, message: Message): 4332 | if len(message.command) < 2: 4333 | return await message.edit_text("Usage: .addon [addon_name]") 4334 | 4335 | addon_name = message.command[1] 4336 | await message.edit_text(f"**Loading addon '{addon_name}'...** (Implementation pending)") 4337 | 4338 | @app.on_message(filters.command("addons", prefixes=".") & filters.me) 4339 | async def list_addons(client: Client, message: Message): 4340 | await message.edit_text("**Available addons:** (Implementation pending)") 4341 | 4342 | @app.on_message(filters.command("createaddon", prefixes=".") & filters.me) 4343 | async def create_addon(client: Client, message: Message): 4344 | if len(message.command) < 2: 4345 | return await message.edit_text("Usage: .createaddon [addon_name]") 4346 | 4347 | addon_name = message.command[1] 4348 | await message.edit_text(f"**Creating addon '{addon_name}'...** (Implementation pending)") 4349 | 4350 | @app.on_message(filters.command("editaddon", prefixes=".") & filters.me) 4351 | async def edit_addon(client: Client, message: Message): 4352 | if len(message.command) < 2: 4353 | return await message.edit_text("Usage: .editaddon [addon_name]") 4354 | 4355 | addon_name = message.command[1] 4356 | await message.edit_text(f"**Editing addon '{addon_name}'...** (Implementation pending)") 4357 | 4358 | @app.on_message(filters.command("deleteaddon", prefixes=".") & filters.me) 4359 | async def delete_addon(client: Client, message: Message): 4360 | if len(message.command) < 2: 4361 | return await message.edit_text("Usage: .deleteaddon [addon_name]") 4362 | 4363 | addon_name = message.command[1] 4364 | await message.edit_text(f"**Deleting addon '{addon_name}'...** (Implementation pending)") 4365 | 4366 | @app.on_message(filters.command("reloadaddons", prefixes=".") & filters.me) 4367 | async def reload_addons(client: Client, message: Message): 4368 | await message.edit_text("**Reloading all addons...** (Implementation pending)") 4369 | 4370 | 4371 | @app.on_message( 4372 | filters.command("vc", prefixes=".") & 4373 | filters.me & 4374 | ~filters.private 4375 | ) 4376 | async def start_vc_command(client: Client, message: Message): 4377 | chat_id = message.chat.id 4378 | 4379 | 4380 | peer = await client.resolve_peer(chat_id) 4381 | 4382 | 4383 | result = await client.invoke( 4384 | CreateGroupCall( 4385 | peer=InputPeerChannel( 4386 | channel_id=peer.channel_id, 4387 | access_hash=peer.access_hash, 4388 | ), 4389 | random_id=client.rnd_id() // 9000000000, 4390 | ) 4391 | ) 4392 | 4393 | await message.edit("🎤 VC Started!") 4394 | 4395 | 4396 | @app.on_message(filters.command("pro", prefixes=".") & filters.me) 4397 | async def start_command(client: Client, message: Message): 4398 | client.start_time = datetime.now() 4399 | await message.reply_text( 4400 | "🚀 **ULTRA USERBOT STARTED!** 🚀\n\n" 4401 | "Use `.help` to see all available commands.\n" 4402 | "This is a PRO edition with maximum features!\n\n" 4403 | "**Features Include:**\n" 4404 | "• Advanced Group Management\n" 4405 | "• Media Saving & Cloud Storage\n" 4406 | "• Privacy & Security Controls\n" 4407 | "• Automation & Custom Commands\n" 4408 | "• Search & Translation\n" 4409 | "• Notes & Reminders\n" 4410 | "• Profile Management\n" 4411 | "• Entertainment & Fun\n" 4412 | "• Developer Tools\n" 4413 | "• Custom Addons\n" 4414 | ) 4415 | 4416 | @app.on_message(filters.incoming & ~filters.me) 4417 | async def unified_message_handler(client: Client, message: Message): 4418 | 4419 | if message.from_user and str(message.from_user.id) in blocked_users: 4420 | try: 4421 | await message.delete() 4422 | except: 4423 | pass 4424 | return 4425 | 4426 | if message.new_chat_members: 4427 | for user in message.new_chat_members: 4428 | 4429 | if (message.chat.id in group_settings and 4430 | group_settings[message.chat.id].get("welcome_enabled", False)): 4431 | welcome_msg = group_settings[message.chat.id].get("welcome", "Welcome to the group!") 4432 | await message.reply_text(welcome_msg) 4433 | 4434 | 4435 | if message.chat.id in group_settings and group_settings[message.chat.id].get("ghost_mode", False): 4436 | try: 4437 | await message.delete() 4438 | except: 4439 | pass 4440 | return 4441 | 4442 | if message.text: 4443 | text = message.text.lower() 4444 | if message.chat.type == ChatType.PRIVATE: 4445 | 4446 | global afk_mode, afk_reason, afk_start_time 4447 | 4448 | if afk_mode and message.from_user: 4449 | if afk_start_time: 4450 | afk_duration = datetime.now() - afk_start_time 4451 | duration_str = format_time(int(afk_duration.total_seconds())) 4452 | else: 4453 | duration_str = "unknown time" 4454 | 4455 | await message.reply_text( 4456 | f"**I'm currently AFK**\n" 4457 | f"Reason: {afk_reason}\n" 4458 | f"Since: {duration_str} ago" 4459 | ) 4460 | return 4461 | 4462 | 4463 | for trigger, response in auto_replies.items(): 4464 | if re.search(r'\b' + re.escape(trigger) + r'\b', text): 4465 | await message.reply_text(response) 4466 | return 4467 | 4468 | 4469 | if message.chat.id in active_filters: 4470 | for trigger, response in active_filters[message.chat.id].items(): 4471 | if re.search(r'\b' + re.escape(trigger) + r'\b', text): 4472 | await message.reply_text(response) 4473 | return 4474 | 4475 | 4476 | if "reactions" in user_data: 4477 | for trigger, emoji in user_data["reactions"].items(): 4478 | pattern = r'\b{}\b'.format(re.escape(trigger)) 4479 | if re.search(pattern, text, re.IGNORECASE): 4480 | try: 4481 | await message.react([emoji]) 4482 | except: 4483 | pass 4484 | break 4485 | 4486 | async def main(): 4487 | await app.start() 4488 | await idle() 4489 | 4490 | if __name__ == "__main__": 4491 | app.run(main()) 4492 | 4493 | # ------------------- REST FEATURES SOON PLEASE CONTRIBUTE TO MAKE IT MORE ADVANCE SPECIALLY RAW API Methods --------------- 4494 | --------------------------------------------------------------------------------