├── Procfile ├── start.sh ├── utils ├── __init__.py └── logging_setup.py ├── heroku.yml ├── requirements.txt ├── sample.env ├── Dockerfile ├── app.json ├── config.py ├── adminpanel ├── logs │ └── logs.py ├── restart │ └── restart.py └── admin │ └── admin.py ├── cookies └── ItsSmartToolBot.txt ├── pinterest └── pinterest.py ├── tiktok └── tiktok.py ├── facebook └── facebook.py ├── instagram └── instagram.py ├── main.py ├── README.md ├── spotify └── spotify.py └── youtube └── youtube.py /Procfile: -------------------------------------------------------------------------------- 1 | web: python main.py 2 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | python3 main.py 2 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .logging_setup import LOGGER -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | web: Dockerfile 4 | 5 | run: 6 | web: python main.py 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram 2 | yt-dlp 3 | spotipy 4 | requests 5 | pillow 6 | asyncio 7 | aiofiles 8 | aiohttp 9 | youtube-search-python 10 | tgcrypto 11 | pymongo 12 | moviepy 13 | Flask 14 | -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | API_ID=28210 2 | API_HASH=7fc5b356973318b86481ab5eca3 3 | BOT_TOKEN=7234398375:AqarF90O20Dcza8XGA-L33f904ywk 4 | ADMIN_IDS=7303810912,6249257243,5991909954 5 | SPOTIFY_CLIENT_ID=5941bb55d4a52a91c5297f616e325 6 | SPOTIFY_CLIENT_SECRET=408f04b237add2ba1b8bfc5da9eff8 7 | MONGO_URL=mongodb+srv://ytpremium4434360:zxx1VPDzGssmarttoolbot.dhsl4.mongodb.net/?retryWrites=true&w=majority&appName=ItsSmartToolBot 8 | COMMAND_PREFIX="!|.|#|,|/" 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the official Python image (full version) as a base 2 | FROM python:3.10 3 | 4 | # Set the working directory in the container 5 | WORKDIR /app 6 | 7 | # Install system dependencies (only ffmpeg now) 8 | RUN apt-get update && \ 9 | apt-get install -y ffmpeg && \ 10 | apt-get clean && \ 11 | rm -rf /var/lib/apt/lists/* 12 | 13 | # Copy the current directory contents into the container at /app 14 | COPY . /app 15 | 16 | # Install Python dependencies from requirements.txt 17 | COPY requirements.txt . 18 | RUN pip install --no-cache-dir -r requirements.txt 19 | 20 | # Expose the port (optional for Heroku, as it's dynamically assigned) 21 | EXPOSE 5000 22 | 23 | # Run the Flask server and bot when the container starts 24 | CMD ["python", "main.py"] 25 | -------------------------------------------------------------------------------- /utils/logging_setup.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from logging.handlers import RotatingFileHandler 3 | 4 | # Setup logging configuration 5 | logging.basicConfig( 6 | level=logging.INFO, 7 | format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s", 8 | datefmt='%d-%b-%y %H:%M:%S', 9 | handlers=[ 10 | RotatingFileHandler( 11 | "botlog.txt", 12 | maxBytes=50000000, 13 | backupCount=10 14 | ), 15 | logging.StreamHandler() 16 | ] 17 | ) 18 | 19 | # Set logging levels for specific libraries 20 | logging.getLogger("pyrogram").setLevel(logging.ERROR) 21 | logging.getLogger("pytgcalls").setLevel(logging.ERROR) 22 | logging.getLogger("apscheduler").setLevel(logging.ERROR) 23 | 24 | LOGGER = logging.getLogger(__name__) 25 | LOGGER.info("Bot Successfully Started! 💥") 26 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SmartDlBot", 3 | "description": "A smart Telegram bot with Spotify and MongoDB integration.", 4 | "repository": "https://github.com/abirxdhack/SmartDlBot", 5 | "keywords": ["telegram", "bot", "docker", "flask", "ffmpeg"], 6 | "stack": "container", 7 | "env": { 8 | "API_ID": { 9 | "description": "Telegram API ID", 10 | "required": true 11 | }, 12 | "API_HASH": { 13 | "description": "Telegram API Hash", 14 | "required": true 15 | }, 16 | "BOT_TOKEN": { 17 | "description": "Telegram Bot Token", 18 | "required": true 19 | }, 20 | "ADMIN_IDS": { 21 | "description": "Comma-separated list of Telegram admin user IDs", 22 | "required": true 23 | }, 24 | "SPOTIFY_CLIENT_ID": { 25 | "description": "Spotify Client ID", 26 | "required": true 27 | }, 28 | "SPOTIFY_CLIENT_SECRET": { 29 | "description": "Spotify Client Secret", 30 | "required": true 31 | }, 32 | "MONGO_URL": { 33 | "description": "MongoDB connection string", 34 | "required": true 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import os 2 | from dotenv import load_dotenv 3 | 4 | # Load environment variables from .env file 5 | load_dotenv() 6 | 7 | # Telegram Bot & API Configuration 8 | API_ID = int(os.getenv("API_ID", 0)) 9 | API_HASH = os.getenv("API_HASH") 10 | BOT_TOKEN = os.getenv("BOT_TOKEN") 11 | 12 | # Admin IDs (as a list of integers) 13 | ADMIN_IDS_RAW = os.getenv("ADMIN_IDS", "") 14 | try: 15 | ADMIN_IDS = list(map(int, ADMIN_IDS_RAW.split(","))) 16 | except ValueError: 17 | raise ValueError("Invalid ADMIN_IDS. Must be comma-separated integers.") 18 | 19 | # Spotify API 20 | SPOTIFY_CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID") 21 | SPOTIFY_CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET") 22 | 23 | # MongoDB 24 | MONGO_URL = os.getenv("MONGO_URL") 25 | 26 | # Command Prefix Support 27 | COMMAND_PREFIX_RAW = os.getenv("COMMAND_PREFIX", "!|.|#|,|/") 28 | COMMAND_PREFIX = [prefix.strip() for prefix in COMMAND_PREFIX_RAW.split("|") if prefix.strip()] 29 | 30 | print("Loaded COMMAND_PREFIX:", COMMAND_PREFIX) 31 | 32 | if not COMMAND_PREFIX: 33 | raise ValueError("Sorry Bro No Command Prefix Found. First Fix It!") 34 | 35 | # YouTube cookies file path (if required for yt-dlp or similar) 36 | YT_COOKIES_PATH = "./cookies/ItsSmartToolBot.txt" 37 | -------------------------------------------------------------------------------- /adminpanel/logs/logs.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pyrogram import Client, filters 3 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, InputMediaDocument 4 | from pyrogram.enums import ParseMode 5 | from config import ADMIN_IDS # Import ADMIN_IDS 6 | 7 | def setup_logs_handler(app: Client): 8 | """Sets up the logs handler to send logs from botlog.txt only.""" 9 | 10 | @app.on_message(filters.command(["dump", "logs"], prefixes=["/", "."]) & (filters.private | filters.group)) 11 | async def logs_command(client, message): 12 | """Sends logs from botlog.txt to admins only.""" 13 | 14 | # Check if the user is an admin 15 | if message.from_user.id not in ADMIN_IDS: 16 | await client.send_message( 17 | chat_id=message.chat.id, 18 | text="**❌ You do not have permission to use this command.**", 19 | parse_mode=ParseMode.MARKDOWN 20 | ) 21 | return 22 | 23 | # Send loading message 24 | loading_msg = await client.send_message( 25 | chat_id=message.chat.id, 26 | text="🚀 **Fetching Logs Database🔥**", 27 | parse_mode=ParseMode.MARKDOWN 28 | ) 29 | 30 | logs = "No logs available yet." 31 | 32 | # Read the logs from botlog.txt if it exists 33 | if os.path.exists("botlog.txt"): 34 | with open("botlog.txt", "r", encoding="utf-8") as f: 35 | logs = f.read().strip() 36 | 37 | # If logs are too long, send as a text file 38 | if len(logs) > 4000: 39 | log_file_path = "botlog.txt" 40 | await client.send_document( 41 | chat_id=message.chat.id, 42 | document=log_file_path, 43 | caption="📜 **Here are the latest logs:**", 44 | parse_mode=ParseMode.MARKDOWN 45 | ) 46 | await loading_msg.delete() 47 | else: 48 | # Format logs as plain text 49 | logs_formatted = f"📜 Latest Logs:\n\n{logs}" 50 | 51 | # Create an inline "Close" button 52 | keyboard = InlineKeyboardMarkup( 53 | [[InlineKeyboardButton("❌ Close", callback_data="close_logs")]] 54 | ) 55 | 56 | # Edit the loading message with logs 57 | await loading_msg.edit_text(logs_formatted, parse_mode=ParseMode.DISABLED, reply_markup=keyboard) 58 | 59 | @app.on_callback_query(filters.regex("close_logs")) 60 | async def close_logs(client: Client, query: CallbackQuery): 61 | """Deletes the log message when the 'Close' button is clicked.""" 62 | await query.message.delete() 63 | -------------------------------------------------------------------------------- /cookies/ItsSmartToolBot.txt: -------------------------------------------------------------------------------- 1 | # Netscape HTTP Cookie File 2 | # This file is generated by yt-dlp. Do not edit. 3 | 4 | .youtube.com TRUE / FALSE 1774622896 APISID CBIU23q_IRz8zUMC/AK5EKs8V1J3cIo4Yv 5 | .youtube.com TRUE / TRUE 1755684748 DEVICE_INFO ChxOelEzTXpjNU5EUXdOVGN5TXpJeE5Ea3lNUT09EIyj4b0GGOqA4b0G 6 | .youtube.com TRUE / FALSE 1774622896 HSID A_-19jXoFqKYujfTz 7 | .youtube.com TRUE / TRUE 1774577579 LOGIN_INFO AFmmF2swRQIhANfJ2G2diIVBK4EYG6bqkKnWh67HjeHDuea2l4ceFDnwAiBeHeB5n30zGHnL1n1jomEjP7poOtr3lDTX3E1J_fLSFA:QUQ3MjNmemZTaGZLSWhkNjdrQW9rNGw4NHdqRUhFdHV4WTlLcVA3YjBqSWFsZmhtRGxSNERYdWdmVTRBYkF2TzRMS0pBOU5OVzVUQVhBOXdfOWljUTJpdGUtVFBFeXRiZmhralJCRFFCY1pvNEZ5NWxaY0kyMHkyckZIbEpYZVRESk81NVdoQjVfTzc2X0RqRVZkSzZPSUVSbWlRZmxCem93 8 | .youtube.com TRUE / FALSE 0 PREF tz=UTC&hl=en 9 | .youtube.com TRUE / TRUE 1774622896 SAPISID 2Emco1lnxcDmbLGY/ANgzdhAo24coY-UIA 10 | .youtube.com TRUE / FALSE 1774622896 SID g.a000twgnImlPrIzD18Kef2opfvo_pOQnd1O7fb2--ZxsyVjCdeBD-B02UtSy0gfeAvWrmXL3hwACgYKAcoSARQSFQHGX2MiQXAQYcYr-eE_Fglrx5PC3BoVAUF8yKpmysJww1ncQVrseGjyjjXI0076 11 | .youtube.com TRUE / FALSE 1771668748 SIDCC AKEyXzUpAhUnUw7PqjZrbg-BQWl0xXuezjZAW0sFRO3gBVDMxDs83N1Xuk7j89z62Nql-mHsNg 12 | .youtube.com TRUE / TRUE 1774622896 SSID AZgiZbxZq9X-aLRJv 13 | .youtube.com TRUE / TRUE 1755684748 VISITOR_INFO1_LIVE SoP5njC7B50 14 | .youtube.com TRUE / TRUE 1755684748 VISITOR_PRIVACY_METADATA CgJHQhIEGgAgQA%3D%3D 15 | .youtube.com TRUE / TRUE 0 YSC Q7J-x5s_qbs 16 | .youtube.com TRUE / TRUE 1774622896 __Secure-1PAPISID 2Emco1lnxcDmbLGY/ANgzdhAo24coY-UIA 17 | .youtube.com TRUE / TRUE 1774622896 __Secure-1PSID g.a000twgnImlPrIzD18Kef2opfvo_pOQnd1O7fb2--ZxsyVjCdeBD4gkDUBvFdcY-2l42OLwfkgACgYKAakSARQSFQHGX2MisSnXuiV09Q6FxLr0bHd6oRoVAUF8yKpbZSlHqqRHdXeCbNN-lZQ_0076 18 | .youtube.com TRUE / TRUE 1771668748 __Secure-1PSIDCC AKEyXzVTFXTTCKOH5KRDGp8hqPfsrfELYD8ZKmysTgCR8RJ28LFVY9NfktczqLnVrnXp7U81bbo 19 | .youtube.com TRUE / TRUE 1771664360 __Secure-1PSIDTS sidts-CjIBEJ3XVzJGcl0NceEdgnrI8FwmeYcCAH9UJEUC4urMBD5p7E1Lb1D_qa4aALxICsuvuBAA 20 | .youtube.com TRUE / TRUE 1774622896 __Secure-3PAPISID 2Emco1lnxcDmbLGY/ANgzdhAo24coY-UIA 21 | .youtube.com TRUE / TRUE 1774622896 __Secure-3PSID g.a000twgnImlPrIzD18Kef2opfvo_pOQnd1O7fb2--ZxsyVjCdeBDifk5G0j5eWL0lQTWLfGBJgACgYKAdYSARQSFQHGX2MiC2jwMq06dmBcbSmo3LG5phoVAUF8yKqGVFfJNVxJnJVgqHGz3uqc0076 22 | .youtube.com TRUE / TRUE 1771668748 __Secure-3PSIDCC AKEyXzVs9_qhXrBw64BYIIA1t0aL-Uz0BzejFsIxzkYI8k8WVQV1qgGs1QGnFMwd83SKhIfB6Q 23 | .youtube.com TRUE / TRUE 1771664360 __Secure-3PSIDTS sidts-CjIBEJ3XVzJGcl0NceEdgnrI8FwmeYcCAH9UJEUC4urMBD5p7E1Lb1D_qa4aALxICsuvuBAA 24 | .youtube.com TRUE / TRUE 1755680362 __Secure-ROLLOUT_TOKEN CJCmtMHEyPeccxCl3Nams9SLAxjv3oans9SLAw%3D%3D 25 | .youtube.com TRUE / TRUE 1774256360 __Secure-YEC CgsyTzBvTkk1RmNEMCjpgOG9BjIKCgJHQhIEGgAgWw%3D%3D 26 | .youtube.com TRUE / TRUE 1803204748 __Secure-YT_TVFAS t=483368&s=3 27 | -------------------------------------------------------------------------------- /adminpanel/restart/restart.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import os 3 | import asyncio 4 | from pyrogram import Client, filters 5 | from pyrogram.enums import ParseMode 6 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 7 | from config import ADMIN_IDS 8 | 9 | def setup_restart_handler(app: Client): 10 | @app.on_message(filters.command(["restart", "reboot", "reload"], prefixes=["/", "."]) & (filters.private | filters.group)) 11 | async def restart(_, message): 12 | if message.from_user.id not in ADMIN_IDS: 13 | await message.reply_text( 14 | "❌ You are not authorized to use this command.", 15 | parse_mode=ParseMode.HTML, 16 | reply_markup=InlineKeyboardMarkup( 17 | [ 18 | [ 19 | InlineKeyboardButton("👨🏼💻 Developer", url='https://t.me/abirxdhackz'), 20 | InlineKeyboardButton("🤖 Other Bots", url="https://t.me/Modvip_rm") 21 | ], 22 | [ 23 | InlineKeyboardButton("🔗 Source Code", url="https://github.com/abirxdhack/RestartModule"), 24 | InlineKeyboardButton("⚙️ Update Channel", url="https://t.me/Modvip_rm") 25 | ] 26 | ] 27 | ) 28 | ) 29 | return 30 | 31 | response = await message.reply_text( 32 | "Restarting Bot...", 33 | parse_mode=ParseMode.HTML 34 | ) 35 | 36 | # Active chats handling logic here if applicable 37 | # Example: 38 | # served_chats = await get_active_chats() 39 | # for x in served_chats: 40 | # try: 41 | # await app.send_message( 42 | # x, 43 | # "The bot is restarting for updating purposes. Sorry for the inconvenience." 44 | # ) 45 | # await remove_active_chat(x) 46 | # except Exception: 47 | # pass 48 | 49 | # Directories to be removed 50 | directories = ["downloads", "temp", "temp_media"] 51 | for directory in directories: 52 | try: 53 | shutil.rmtree(directory) 54 | except FileNotFoundError: 55 | pass 56 | 57 | # Delete the botlogs.txt file if it exists 58 | if os.path.exists("botlog.txt"): 59 | os.remove("botlog.txt") 60 | 61 | await asyncio.sleep(6) 62 | 63 | await response.edit( 64 | "Bot Successfully Started! 💥", 65 | parse_mode=ParseMode.HTML 66 | ) 67 | os.system(f"kill -9 {os.getpid()} && bash start.sh") 68 | 69 | @app.on_message(filters.command(["stop", "kill", "off"], prefixes=["/", "."]) & (filters.private | filters.group)) 70 | async def stop(_, message): 71 | if message.from_user.id not in ADMIN_IDS: 72 | await message.reply_text( 73 | "❌ You are not authorized to use this command.", 74 | parse_mode=ParseMode.HTML, 75 | reply_markup=InlineKeyboardMarkup( 76 | [ 77 | [ 78 | InlineKeyboardButton("👨🏼💻 Developer", url='https://t.me/abirxdhackz'), 79 | InlineKeyboardButton("🤖 Other Bots", url="https://t.me/Modvip_rm") 80 | ], 81 | [ 82 | InlineKeyboardButton("🔗 Source Code", url="https://github.com/abirxdhack/RestartModule"), 83 | InlineKeyboardButton("⚙️ Update Channel", url="https://t.me/Modvip_rm") 84 | ] 85 | ] 86 | ) 87 | ) 88 | return 89 | 90 | await message.reply_text( 91 | "Bot Off Successfully", 92 | parse_mode=ParseMode.HTML 93 | ) 94 | os.system("pkill -f main.py") 95 | -------------------------------------------------------------------------------- /pinterest/pinterest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import time 4 | from pathlib import Path 5 | from typing import Optional 6 | import aiohttp 7 | import re 8 | import asyncio 9 | import aiofiles 10 | from pyrogram import Client, filters 11 | from pyrogram.types import Message 12 | from pyrogram.enums import ParseMode 13 | from config import COMMAND_PREFIX 14 | 15 | # Configure logging 16 | logging.basicConfig( 17 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 18 | level=logging.INFO 19 | ) 20 | logger = logging.getLogger(__name__) 21 | 22 | # Configuration 23 | class Config: 24 | TEMP_DIR = Path("temp") 25 | 26 | Config.TEMP_DIR.mkdir(exist_ok=True) 27 | 28 | class PinterestDownloader: 29 | def __init__(self, temp_dir: Path): 30 | self.temp_dir = temp_dir 31 | 32 | async def download_media(self, url: str, downloading_message: Message) -> Optional[dict]: 33 | self.temp_dir.mkdir(exist_ok=True) 34 | api_url = f"https://tele-social.vercel.app/down?url={url}" 35 | 36 | try: 37 | async with aiohttp.ClientSession() as session: 38 | async with session.get(api_url) as response: 39 | logger.info(f"API request to {api_url} returned status {response.status}") 40 | if response.status == 200: 41 | data = await response.json() 42 | logger.info(f"API response: {data}") 43 | if data["status"]: 44 | await downloading_message.edit_text("**Found ☑️ Downloading...**", parse_mode=ParseMode.MARKDOWN) 45 | media_url = data["url"] 46 | title = data.get("filename", "Pinterest Media") 47 | filename = self.temp_dir / title 48 | await self._download_file(session, media_url, filename) 49 | return { 50 | 'title': title, 51 | 'filename': str(filename), 52 | 'webpage_url': url 53 | } 54 | return None 55 | except Exception as e: 56 | logger.error(f"Pinterest download error: {e}") 57 | return None 58 | 59 | async def _download_file(self, session, url, dest): 60 | async with session.get(url) as response: 61 | if response.status == 200: 62 | logger.info(f"Downloading media from {url} to {dest}") 63 | f = await aiofiles.open(dest, mode='wb') 64 | await f.write(await response.read()) 65 | await f.close() 66 | 67 | async def progress_bar(current, total, status_message, start_time, last_update_time): 68 | """ 69 | Display a progress bar for uploads. 70 | """ 71 | elapsed_time = time.time() - start_time 72 | percentage = (current / total) * 100 73 | progress = "▓" * int(percentage // 5) + "░" * (20 - int(percentage // 5)) 74 | speed = current / elapsed_time / 1024 / 1024 # Speed in MB/s 75 | uploaded = current / 1024 / 1024 # Uploaded size in MB 76 | total_size = total / 1024 / 1024 # Total size in MB 77 | 78 | # Throttle updates: Only update if at least second has passed since the last update 79 | if time.time() - last_update_time[0] < 1: 80 | return 81 | last_update_time[0] = time.time() # Update the last update time 82 | 83 | text = ( 84 | f"📥 Upload Progress 📥\n\n" 85 | f"{progress}\n\n" 86 | f"🚧 Percentage: {percentage:.2f}%\n" 87 | f"⚡️ Speed: {speed:.2f} MB/s\n" 88 | f"📶 Uploaded: {uploaded:.2f} MB of {total_size:.2f} MB" 89 | ) 90 | try: 91 | await status_message.edit(text) 92 | except Exception as e: 93 | logger.error(f"Error updating progress: {e}") 94 | 95 | def setup_pinterest_handler(app: Client): 96 | pin_downloader = PinterestDownloader(Config.TEMP_DIR) 97 | 98 | # Create a regex pattern from the COMMAND_PREFIX list 99 | command_prefix_regex = f"[{''.join(map(re.escape, COMMAND_PREFIX))}]" 100 | 101 | @app.on_message(filters.regex(rf"^{command_prefix_regex}pin(\s+https?://\S+)?$") & (filters.private | filters.group)) 102 | async def pin_handler(client: Client, message: Message): 103 | command_parts = message.text.split(maxsplit=1) 104 | if len(command_parts) < 2: 105 | await client.send_message( 106 | chat_id=message.chat.id, 107 | text="**Please provide a Pinterest link ❌**", 108 | parse_mode=ParseMode.MARKDOWN 109 | ) 110 | return 111 | 112 | url = command_parts[1] 113 | downloading_message = await client.send_message( 114 | chat_id=message.chat.id, 115 | text="**Searching The Media**", 116 | parse_mode=ParseMode.MARKDOWN 117 | ) 118 | 119 | try: 120 | media_info = await pin_downloader.download_media(url, downloading_message) 121 | if media_info: 122 | title = media_info['title'] 123 | filename = media_info['filename'] 124 | webpage_url = media_info['webpage_url'] 125 | 126 | if message.from_user: 127 | user_full_name = f"{message.from_user.first_name} {message.from_user.last_name or ''}".strip() 128 | user_info = f"[{user_full_name}](tg://user?id={message.from_user.id})" 129 | else: 130 | group_name = message.chat.title or "this group" 131 | group_url = f"https://t.me/{message.chat.username}" if message.chat.username else "this group" 132 | user_info = f"[{group_name}]({group_url})" 133 | 134 | caption = ( 135 | f"🎥 **Title**: **{title}**\n" 136 | f"━━━━━━━━━━━━━━━━━━━━━\n" 137 | f"🔗 **Url**: [Watch On Pinterest]({webpage_url})\n" 138 | f"━━━━━━━━━━━━━━━━━━━━━\n" 139 | f"**Downloaded By**: {user_info}" 140 | ) 141 | 142 | async with aiofiles.open(filename, 'rb') as media_file: 143 | start_time = time.time() 144 | last_update_time = [start_time] 145 | await client.send_video( 146 | chat_id=message.chat.id, 147 | video=filename, 148 | supports_streaming=True, 149 | caption=caption, 150 | parse_mode=ParseMode.MARKDOWN, 151 | progress=progress_bar, 152 | progress_args=(downloading_message, start_time, last_update_time) 153 | ) 154 | 155 | await downloading_message.delete() 156 | os.remove(filename) 157 | else: 158 | await downloading_message.edit_text("**Unable To Extract Url**") 159 | except Exception as e: 160 | logger.error(f"Error downloading Pinterest Media: {e}") 161 | await downloading_message.edit_text("**Pinterest Downloader API Dead**") 162 | -------------------------------------------------------------------------------- /tiktok/tiktok.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import re 4 | import logging 5 | import aiohttp 6 | from pyrogram import Client, filters 7 | from pyrogram.enums import ParseMode 8 | from pyrogram.types import Message 9 | from config import COMMAND_PREFIX 10 | 11 | # Set up logging 12 | logging.basicConfig(level=logging.INFO) 13 | logger = logging.getLogger(__name__) 14 | 15 | # Progress bar function for uploads 16 | async def progress_bar(current, total, status_message: Message, start_time, last_update_time): 17 | elapsed_time = time.time() - start_time 18 | percentage = (current / total) * 100 19 | progress = "▓" * int(percentage // 5) + "░" * (20 - int(percentage // 5)) 20 | speed = current / elapsed_time / 1024 / 1024 # Speed in MB/s 21 | uploaded = current / 1024 / 1024 # Uploaded size in MB 22 | total_size = total / 1024 / 1024 # Total size in MB 23 | 24 | # Throttle updates: Only update if at least 1 second has passed since the last update 25 | if time.time() - last_update_time[0] < 1: 26 | return 27 | last_update_time[0] = time.time() # Update the last update time 28 | 29 | text = ( 30 | f"📥 Upload Progress 📥\n\n" 31 | f"{progress}\n\n" 32 | f"🚧 Percentage: {percentage:.2f}%\n" 33 | f"⚡️ Speed: {speed:.2f} MB/s\n" 34 | f"📶 Uploaded: {uploaded:.2f} MB of {total_size:.2f} MB" 35 | ) 36 | try: 37 | await status_message.edit(text) 38 | except Exception as e: 39 | logger.error(f"Error updating progress: {e}") 40 | 41 | # Function to download video and audio using the provided API 42 | async def download_video(url, downloading_message: Message): 43 | api_url = f"https://tele-social.vercel.app/down?url={url}" 44 | 45 | try: 46 | async with aiohttp.ClientSession() as session: 47 | async with session.get(api_url) as response: 48 | if response.status == 200: 49 | data = await response.json() 50 | if data["status"]: 51 | await downloading_message.edit_text("**Found ☑️ Downloading...**", parse_mode=ParseMode.MARKDOWN) 52 | video_url = data["data"]["video"] 53 | audio_url = data["data"]["audio"] 54 | 55 | video_output = "tiktok_video.mp4" 56 | async with session.get(video_url) as video_response: 57 | if video_response.status == 200: 58 | with open(video_output, 'wb') as f: 59 | f.write(await video_response.read()) 60 | logger.info(f"Video downloaded successfully to: {video_output}") 61 | return video_output 62 | else: 63 | logger.error("Failed to download video") 64 | return None 65 | else: 66 | logger.error("Failed to get a valid response from the API") 67 | return None 68 | else: 69 | logger.error("Failed to reach the download API") 70 | return None 71 | except Exception as e: 72 | logger.error(f"Error downloading video: {e}") 73 | return None 74 | 75 | # Function to set up TikTok handler 76 | def setup_tt_handler(app: Client): 77 | @app.on_message(filters.command(["tt"], prefixes=COMMAND_PREFIX) & (filters.private | filters.group)) 78 | async def tiktok_handler(client, message): 79 | match = re.findall(r"^[/.]tt(\s+https?://\S+)?$", message.text) 80 | if not match or len(match[0].strip()) == 0: 81 | await client.send_message( 82 | chat_id=message.chat.id, 83 | text="**❌ Please provide a TikTok video link.**", 84 | parse_mode=ParseMode.MARKDOWN 85 | ) 86 | return 87 | 88 | url = match[0].strip() 89 | 90 | # Step 1: Send the initial "Searching Video" message 91 | status_message = await client.send_message( 92 | chat_id=message.chat.id, 93 | text="**Searching The Video...**", 94 | parse_mode=ParseMode.MARKDOWN 95 | ) 96 | 97 | try: 98 | # Step 2: Download the TikTok video using the provided API 99 | video_path = await download_video(url, status_message) 100 | 101 | if not video_path: 102 | await status_message.edit("**❌Invalid Video URL Inputed**") 103 | return 104 | 105 | # Step 3: Get user information 106 | if message.from_user: 107 | user_full_name = f"{message.from_user.first_name} {message.from_user.last_name or ''}".strip() 108 | user_info = f"[{user_full_name}](tg://user?id={message.from_user.id})" 109 | else: 110 | group_name = message.chat.title or "this group" 111 | group_url = f"https://t.me/{message.chat.username}" if message.chat.username else "this group" 112 | user_info = f"[{group_name}]({group_url})" 113 | 114 | # Dummy metadata for demonstration purposes 115 | title = "TikTok Video" 116 | views = 1000 117 | duration_minutes = 0 118 | duration_seconds = 20 119 | 120 | # Step 4: Create the formatted message with dummy data 121 | caption = ( 122 | f"🎵 **Title**: **{title}**\n" 123 | f"━━━━━━━━━━━━━━━━━━━━━\n" 124 | f"👁️🗨️ **Views**: **{views} views**\n" 125 | f"🔗 **Url**: [Watch On TikTok]({url})\n" 126 | f"⏱️ **Duration**: **{duration_minutes}:{duration_seconds:02d}**\n" 127 | f"━━━━━━━━━━━━━━━━━━━━━\n" 128 | f"**Downloaded By**: {user_info}" 129 | ) 130 | 131 | # Step 5: Start uploading the video with progress 132 | start_time = time.time() 133 | last_update_time = [start_time] # Store the last update time to throttle the progress updates 134 | 135 | await client.send_video( 136 | chat_id=message.chat.id, 137 | video=video_path, 138 | caption=caption, 139 | parse_mode=ParseMode.MARKDOWN, 140 | progress=progress_bar, 141 | progress_args=(status_message, start_time, last_update_time) 142 | ) 143 | 144 | # Step 6: Delete the status message after upload starts 145 | await status_message.delete() 146 | 147 | # Clean up the downloaded video file after sending 148 | os.remove(video_path) 149 | logger.info(f"Deleted the video file: {video_path}") 150 | 151 | except Exception as e: 152 | logger.error(f"An error occurred: {e}") 153 | # If something goes wrong during the download, show error message 154 | await client.send_message( 155 | chat_id=message.chat.id, 156 | text="**TikTok Downloader API Dead**", 157 | parse_mode=ParseMode.MARKDOWN 158 | ) 159 | -------------------------------------------------------------------------------- /facebook/facebook.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import time 4 | import re 5 | from pathlib import Path 6 | from typing import Optional 7 | import aiohttp 8 | import asyncio 9 | import aiofiles 10 | from pyrogram import Client, filters 11 | from pyrogram.types import Message 12 | from pyrogram.enums import ParseMode 13 | from config import COMMAND_PREFIX # Import COMMAND_PREFIX from config 14 | 15 | # Configure logging 16 | logging.basicConfig( 17 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 18 | level=logging.INFO 19 | ) 20 | logger = logging.getLogger(__name__) 21 | 22 | # Configuration 23 | class Config: 24 | TEMP_DIR = Path("temp") 25 | 26 | Config.TEMP_DIR.mkdir(exist_ok=True) 27 | 28 | class FacebookDownloader: 29 | def __init__(self, temp_dir: Path): 30 | self.temp_dir = temp_dir 31 | 32 | async def download_video(self, url: str, downloading_message: Message) -> Optional[dict]: 33 | self.temp_dir.mkdir(exist_ok=True) 34 | api_url = f"https://tooly.chative.io/facebook/video?url={url}" 35 | 36 | try: 37 | connector = aiohttp.TCPConnector(limit_per_host=10) 38 | async with aiohttp.ClientSession(connector=connector) as session: 39 | async with session.get(api_url) as response: 40 | logger.info(f"API request to {api_url} returned status {response.status}") 41 | if response.status == 200: 42 | data = await response.json() 43 | logger.info(f"API response: {data}") 44 | if data["success"]: 45 | await downloading_message.edit_text("**Found ☑️ Downloading...**", parse_mode=ParseMode.MARKDOWN) 46 | video_url = data["videos"]["hd"]["url"] 47 | title = data["title"] 48 | filename = self.temp_dir / f"{title}.mp4" 49 | await self._download_file(session, video_url, filename) 50 | return { 51 | 'title': title, 52 | 'filename': str(filename), 53 | 'webpage_url': url 54 | } 55 | return None 56 | except Exception as e: 57 | logger.error(f"Facebook download error: {e}") 58 | return None 59 | 60 | async def _download_file(self, session, url, dest): 61 | async with session.get(url) as response: 62 | if response.status == 200: 63 | logger.info(f"Downloading video from {url} to {dest}") 64 | f = await aiofiles.open(dest, mode='wb') 65 | await f.write(await response.read()) 66 | await f.close() 67 | 68 | def setup_dl_handlers(app: Client): 69 | fb_downloader = FacebookDownloader(Config.TEMP_DIR) 70 | 71 | # Create a regex pattern from the COMMAND_PREFIX list 72 | command_prefix_regex = f"[{''.join(map(re.escape, COMMAND_PREFIX))}]" 73 | 74 | @app.on_message(filters.regex(rf"^{command_prefix_regex}fb(\s+https?://\S+)?$") & (filters.private | filters.group)) 75 | async def fb_handler(client: Client, message: Message): 76 | command_parts = message.text.split(maxsplit=1) 77 | if len(command_parts) < 2: 78 | await client.send_message( 79 | chat_id=message.chat.id, 80 | text="**Please provide a Facebook link ❌**", 81 | parse_mode=ParseMode.MARKDOWN 82 | ) 83 | return 84 | 85 | url = command_parts[1] 86 | downloading_message = await client.send_message( 87 | chat_id=message.chat.id, 88 | text="**Searching The Video**", 89 | parse_mode=ParseMode.MARKDOWN 90 | ) 91 | 92 | try: 93 | video_info = await fb_downloader.download_video(url, downloading_message) 94 | if video_info: 95 | title = video_info['title'] 96 | filename = video_info['filename'] 97 | webpage_url = video_info['webpage_url'] 98 | 99 | if message.from_user: 100 | user_full_name = f"{message.from_user.first_name} {message.from_user.last_name or ''}".strip() 101 | user_info = f"[{user_full_name}](tg://user?id={message.from_user.id})" 102 | else: 103 | group_name = message.chat.title or "this group" 104 | group_url = f"https://t.me/{message.chat.username}" if message.chat.username else "this group" 105 | user_info = f"[{group_name}]({group_url})" 106 | 107 | caption = ( 108 | f"🎵 **Title**: **{title}**\n" 109 | f"━━━━━━━━━━━━━━━━━━━━━\n" 110 | f"🔗 **Url**: [Watch On Facebook]({webpage_url})\n" 111 | f"━━━━━━━━━━━━━━━━━━━━━\n" 112 | f"**Downloaded By**: {user_info}" 113 | ) 114 | 115 | async with aiofiles.open(filename, 'rb') as video_file: 116 | start_time = time.time() 117 | last_update_time = [start_time] 118 | await client.send_video( 119 | chat_id=message.chat.id, 120 | video=filename, 121 | supports_streaming=True, 122 | caption=caption, 123 | parse_mode=ParseMode.MARKDOWN, 124 | progress=progress_bar, 125 | progress_args=(downloading_message, start_time, last_update_time) 126 | ) 127 | 128 | await downloading_message.delete() 129 | os.remove(filename) 130 | else: 131 | logger.info("Invalid Video URL or Video is Private") 132 | await downloading_message.edit_text("**Invalid Video URL Or Video Private**") 133 | except Exception as e: 134 | logger.error(f"Error downloading Facebook video: {e}") 135 | await downloading_message.edit_text("**Facebook Downloader API Dead**") 136 | 137 | async def progress_bar(current, total, status_message, start_time, last_update_time): 138 | """ 139 | Display a progress bar for uploads. 140 | """ 141 | elapsed_time = time.time() - start_time 142 | percentage = (current / total) * 100 143 | progress = "▓" * int(percentage // 5) + "░" * (20 - int(percentage // 5)) 144 | speed = current / elapsed_time / 1024 / 1024 # Speed in MB/s 145 | uploaded = current / 1024 / 1024 # Uploaded size in MB 146 | total_size = total / 1024 / 1024 # Total size in MB 147 | 148 | # Throttle updates: Only update if at least 1 second has passed since the last update 149 | if time.time() - last_update_time[0] < 1: 150 | return 151 | last_update_time[0] = time.time() # Update the last update time 152 | 153 | text = ( 154 | f"📥 Upload Progress 📥\n\n" 155 | f"{progress}\n\n" 156 | f"🚧 Percentage: {percentage:.2f}%\n" 157 | f"⚡️ Speed: {speed:.2f} MB/s\n" 158 | f"📶 Uploaded: {uploaded:.2f} MB of {total_size:.2f} MB" 159 | ) 160 | try: 161 | await status_message.edit(text) 162 | except Exception as e: 163 | logger.error(f"Error updating progress: {e}") 164 | -------------------------------------------------------------------------------- /instagram/instagram.py: -------------------------------------------------------------------------------- 1 | #Copyright @ISmartDevs 2 | #Channel t.me/TheSmartDev 3 | import os 4 | import re 5 | import logging 6 | import time 7 | from pathlib import Path 8 | from typing import Optional 9 | import aiohttp 10 | import asyncio 11 | import aiofiles 12 | from pyrogram import Client, filters 13 | from pyrogram.types import Message 14 | from pyrogram.enums import ParseMode 15 | from config import COMMAND_PREFIX 16 | 17 | # Configure logging 18 | logging.basicConfig( 19 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 20 | level=logging.INFO 21 | ) 22 | logger = logging.getLogger(__name__) 23 | 24 | # Configuration 25 | class Config: 26 | TEMP_DIR = Path("temp") 27 | 28 | Config.TEMP_DIR.mkdir(exist_ok=True) 29 | 30 | class InstagramDownloader: 31 | def __init__(self, temp_dir: Path): 32 | self.temp_dir = temp_dir 33 | 34 | async def download_reel(self, url: str, downloading_message: Message) -> Optional[dict]: 35 | self.temp_dir.mkdir(exist_ok=True) 36 | api_url = f"https://www.alphaapis.org/Instagram/dl/v1?url={url}" 37 | 38 | try: 39 | async with aiohttp.ClientSession() as session: 40 | async with session.get(api_url) as response: 41 | logger.info(f"API request to {api_url} returned status {response.status}") 42 | if response.status == 200: 43 | data = await response.json() 44 | logger.info(f"API response: {data}") 45 | if data["success"]: 46 | await downloading_message.edit_text("**Found ☑️ Downloading...**", parse_mode=ParseMode.MARKDOWN) 47 | video_url = data["result"][0]["downloadLink"] 48 | title = data["result"][0].get("filename", "Instagram Reel") 49 | filename = self.temp_dir / title 50 | await self._download_file(session, video_url, filename) 51 | return { 52 | 'title': title, 53 | 'filename': str(filename), 54 | 'webpage_url': url 55 | } 56 | return None 57 | except Exception as e: 58 | logger.error(f"Instagram Reels download error: {e}") 59 | return None 60 | 61 | async def _download_file(self, session, url, dest): 62 | async with session.get(url) as response: 63 | if response.status == 200: 64 | logger.info(f"Downloading video from {url} to {dest}") 65 | f = await aiofiles.open(dest, mode='wb') 66 | await f.write(await response.read()) 67 | await f.close() 68 | 69 | async def progress_bar(current, total, status_message, start_time, last_update_time): 70 | """ 71 | Display a progress bar for uploads. 72 | """ 73 | elapsed_time = time.time() - start_time 74 | percentage = (current / total) * 100 75 | progress = "▓" * int(percentage // 5) + "░" * (20 - int(percentage // 5)) 76 | speed = current / elapsed_time / 1024 / 1024 # Speed in MB/s 77 | uploaded = current / 1024 / 1024 # Uploaded size in MB 78 | total_size = total / 1024 / 1024 # Total size in MB 79 | 80 | # Throttle updates: Only update if at least second has passed since the last update 81 | if time.time() - last_update_time[0] < 1: 82 | return 83 | last_update_time[0] = time.time() # Update the last update time 84 | 85 | text = ( 86 | f"📥 Upload Progress 📥\n\n" 87 | f"{progress}\n\n" 88 | f"🚧 Percentage: {percentage:.2f}%\n" 89 | f"⚡️ Speed: {speed:.2f} MB/s\n" 90 | f"📶 Uploaded: {uploaded:.2f} MB of {total_size:.2f} MB" 91 | ) 92 | try: 93 | await status_message.edit(text) 94 | except Exception as e: 95 | logger.error(f"Error updating progress: {e}") 96 | 97 | def setup_in_handlers(app: Client): 98 | ig_downloader = InstagramDownloader(Config.TEMP_DIR) 99 | 100 | # Create a regex pattern from the COMMAND_PREFIX list 101 | command_prefix_regex = f"[{''.join(map(re.escape, COMMAND_PREFIX))}]" 102 | 103 | @app.on_message(filters.regex(rf"^{command_prefix_regex}in(\s+https?://\S+)?$") & (filters.private | filters.group)) 104 | async def ig_handler(client: Client, message: Message): 105 | command_parts = message.text.split(maxsplit=1) 106 | if len(command_parts) < 2: 107 | await client.send_message( 108 | chat_id=message.chat.id, 109 | text="**Please provide an Instagram Reels link ❌**", 110 | parse_mode=ParseMode.MARKDOWN 111 | ) 112 | return 113 | 114 | url = command_parts[1] 115 | downloading_message = await client.send_message( 116 | chat_id=message.chat.id, 117 | text="**Searching The Reel**", 118 | parse_mode=ParseMode.MARKDOWN 119 | ) 120 | 121 | try: 122 | reel_info = await ig_downloader.download_reel(url, downloading_message) 123 | if reel_info: 124 | title = reel_info['title'] 125 | filename = reel_info['filename'] 126 | webpage_url = reel_info['webpage_url'] 127 | 128 | if message.from_user: 129 | user_full_name = f"{message.from_user.first_name} {message.from_user.last_name or ''}".strip() 130 | user_info = f"[{user_full_name}](tg://user?id={message.from_user.id})" 131 | else: 132 | group_name = message.chat.title or "this group" 133 | group_url = f"https://t.me/{message.chat.username}" if message.chat.username else "this group" 134 | user_info = f"[{group_name}]({group_url})" 135 | 136 | caption = ( 137 | f"🎥 **Title**: **{title}**\n" 138 | f"━━━━━━━━━━━━━━━━━━━━━\n" 139 | f"🔗 **Url**: [Watch On Instagram]({webpage_url})\n" 140 | f"━━━━━━━━━━━━━━━━━━━━━\n" 141 | f"**Downloaded By**: {user_info}" 142 | ) 143 | 144 | async with aiofiles.open(filename, 'rb') as video_file: 145 | start_time = time.time() 146 | last_update_time = [start_time] 147 | await client.send_video( 148 | chat_id=message.chat.id, 149 | video=filename, 150 | supports_streaming=True, 151 | caption=caption, 152 | parse_mode=ParseMode.MARKDOWN, 153 | progress=progress_bar, 154 | progress_args=(downloading_message, start_time, last_update_time) 155 | ) 156 | 157 | await downloading_message.delete() 158 | os.remove(filename) 159 | else: 160 | await downloading_message.edit_text("**Unable To Extract Url**") 161 | except Exception as e: 162 | logger.error(f"Error downloading Instagram Reel: {e}") 163 | await downloading_message.edit_text("**Instagram Downloader API Dead**") 164 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import asyncio 3 | from threading import Thread 4 | from flask import Flask 5 | from pyrogram import Client, filters 6 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery 7 | from pyrogram.enums import ParseMode 8 | from config import API_ID, API_HASH, BOT_TOKEN 9 | from utils import LOGGER 10 | 11 | # Import the handlers 12 | from youtube.youtube import setup_downloader_handler 13 | from pinterest.pinterest import setup_pinterest_handler 14 | from facebook.facebook import setup_dl_handlers 15 | from spotify.spotify import setup_spotify_handler 16 | from tiktok.tiktok import setup_tt_handler 17 | from instagram.instagram import setup_in_handlers 18 | from adminpanel.restart.restart import setup_restart_handler 19 | from adminpanel.admin.admin import setup_admin_handler 20 | from adminpanel.logs.logs import setup_logs_handler 21 | 22 | # Setup minimal Flask server to prevent Heroku R10 error 23 | flask_app = Flask(__name__) 24 | 25 | @flask_app.route('/') 26 | def index(): 27 | return "Smart Tool Bot is running!" 28 | 29 | def run_flask(): 30 | port = int(os.environ.get("PORT", 5000)) 31 | flask_app.run(host="0.0.0.0", port=port) 32 | 33 | # Start Flask in background 34 | Thread(target=run_flask).start() 35 | 36 | # Initialize the bot client 37 | app = Client( 38 | "app_session", 39 | api_id=API_ID, 40 | api_hash=API_HASH, 41 | bot_token=BOT_TOKEN 42 | ) 43 | 44 | # Setup all handlers 45 | setup_downloader_handler(app) 46 | setup_pinterest_handler(app) 47 | setup_dl_handlers(app) 48 | setup_spotify_handler(app) 49 | setup_restart_handler(app) 50 | setup_admin_handler(app) 51 | setup_logs_handler(app) 52 | setup_in_handlers(app) 53 | setup_tt_handler(app) 54 | 55 | @app.on_message(filters.command(["start"], prefixes=["/", "."]) & filters.private) 56 | async def send_start_message(client, message): 57 | chat_id = message.chat.id 58 | full_name = f"{message.from_user.first_name} {message.from_user.last_name}" if message.from_user.last_name else message.from_user.first_name 59 | 60 | animation_message = await message.reply_text("Starting Smart Tool ⚙️...", parse_mode=ParseMode.HTML) 61 | await asyncio.sleep(0.4) 62 | await animation_message.edit_text("Generating Session Keys Please Wait...", parse_mode=ParseMode.HTML) 63 | await asyncio.sleep(0.4) 64 | await animation_message.delete() 65 | 66 | start_message = ( 67 | f"Hi {full_name}! Welcome To This Bot...\n" 68 | "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" 69 | "Smart Tool ⚙️: The ultimate toolkit on Telegram, offering Facebook,YouTube,Pinterest,Spotify Downloader. Simplify your tasks with ease!\n" 70 | "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" 71 | "Don't Forget To Join Here For Updates!" 72 | ) 73 | 74 | await message.reply_text( 75 | start_message, 76 | parse_mode=ParseMode.HTML, 77 | reply_markup=InlineKeyboardMarkup([ 78 | [InlineKeyboardButton("⚙️ Help", callback_data="help_menu"), 79 | InlineKeyboardButton("➕ Add Me", url="https://t.me/ItsSmartToolBot?startgroup=new&admin=post_messages+delete_messages+edit_messages+pin_messages+change_info+invite_users+promote_members")], 80 | [InlineKeyboardButton("🔄 Updates", url="https://t.me/ModVipRM"), 81 | InlineKeyboardButton("ℹ️ About Me", callback_data="about_me")] 82 | ]), 83 | disable_web_page_preview=True, 84 | ) 85 | 86 | @app.on_callback_query(filters.regex("help_menu")) 87 | async def help_menu_callback(client: Client, callback_query: CallbackQuery): 88 | help_message = ( 89 | "🎥 Social Media and Music Downloader\n" 90 | "━━━━━━━━━━━━━━━━━━━━━━\n" 91 | "USAGE:\n" 92 | "Download videos and tracks from popular platforms using these commands:\n\n" 93 | "➢ /fb [Video URL] - Download a Facebook video.\n" 94 | "➢ /pin [Video URL] - Download a Pinterest video.\n" 95 | "➢ /tt [Video URL] - Download a TikTok video.\n" 96 | "➢ /in [Video URL] - Download Instagram Reels.\n" 97 | "➢ /sp [Track URL] - Download a Spotify track.\n" 98 | "➢ /yt [Video URL] - Download a YouTube video.\n" 99 | "➢ /song [Video URL] - Download as MP3\n" 100 | "━━━━━━━━━━━━━━━━━━━━━━\n" 101 | "🔔 For Bot Updates: Join Now" 102 | ) 103 | 104 | await callback_query.message.edit_text( 105 | help_message, 106 | parse_mode=ParseMode.HTML, 107 | disable_web_page_preview=True, 108 | reply_markup=InlineKeyboardMarkup([ 109 | [InlineKeyboardButton("🔙 Back", callback_data="start_menu")] 110 | ]) 111 | ) 112 | 113 | @app.on_callback_query(filters.regex("about_me")) 114 | async def about_me_callback(client: Client, callback_query: CallbackQuery): 115 | about_message = ( 116 | "Name: Smart Tool ⚙️\n" 117 | "Version: 3.0 (Beta Testing)\n\n" 118 | "Creator: ⏤͟͞〲ᗩᗷiᖇ 𓊈乂ᗪ𓊉 👨💻\n" 119 | "Tech: Python · Pyrogram · Telethon · MongoDB\n" 120 | "About: Download from YouTube, Instagram, Facebook, Pinterest, TikTok, Spotify.\n" 121 | "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" 122 | "🔔 Updates: Join Here" 123 | ) 124 | 125 | await callback_query.message.edit_text( 126 | about_message, 127 | parse_mode=ParseMode.HTML, 128 | disable_web_page_preview=True, 129 | reply_markup=InlineKeyboardMarkup([ 130 | [InlineKeyboardButton("🔙 Back", callback_data="start_menu")] 131 | ]) 132 | ) 133 | 134 | @app.on_callback_query(filters.regex("start_menu")) 135 | async def start_menu_callback(client: Client, callback_query: CallbackQuery): 136 | full_name = f"{callback_query.from_user.first_name} {callback_query.from_user.last_name}" if callback_query.from_user.last_name else callback_query.from_user.first_name 137 | 138 | start_message = ( 139 | f"Hi {full_name}! Welcome To This Bot...\n" 140 | "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" 141 | "Smart Tool ⚙️: The ultimate toolkit on Telegram, offering Facebook,YouTube,Pinterest,Spotify Downloader. Simplify your tasks with ease!\n" 142 | "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" 143 | "Don't Forget To Join Here For Updates!" 144 | ) 145 | 146 | await callback_query.message.edit_text( 147 | start_message, 148 | parse_mode=ParseMode.HTML, 149 | reply_markup=InlineKeyboardMarkup([ 150 | [InlineKeyboardButton("⚙️ Help", callback_data="help_menu"), 151 | InlineKeyboardButton("➕ Add Me", url="https://t.me/ItsSmartToolBot?startgroup=new&admin=post_messages+delete_messages+edit_messages+pin_messages+change_info+invite_users+promote_members")], 152 | [InlineKeyboardButton("🔄 Updates", url="https://t.me/ModVipRM"), 153 | InlineKeyboardButton("ℹ️ About Me", callback_data="about_me")] 154 | ]), 155 | disable_web_page_preview=True, 156 | ) 157 | 158 | # Final confirmation that the bot has started 159 | print("✅ Bot Successfully Started and Flask is running on Heroku.") 160 | app.run() 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
4 | SmartDlBot: The ultimate toolkit on Telegram, offering Facebook,YouTube,Pinterest,Spotify Downloader. Simplify your tasks with ease! 5 |
6 | 7 | 14 | 15 |