├── 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 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tele-userbot
2 |
3 |
4 |
5 | [](https://www.python.org/)
6 | [](https://pyrogram.org/)
7 | [](LICENSE)
8 | [](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 |
--------------------------------------------------------------------------------