├── runtime.txt ├── Procfile ├── requirements.txt ├── Dockerfile ├── route.py ├── logging.conf ├── render.yaml ├── LICENSE ├── app.json ├── plugins ├── thumb_&_cap.py ├── auto_rename.py ├── antinsfw.py ├── force_subs.py ├── admin_panel.py ├── metadata.py ├── file_rename.py └── start_&_cb.py ├── bot.py ├── helper ├── utils.py └── database.py ├── README.md └── config.py /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.10.8 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python bot.py 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram==2.0.80 2 | TgCrypto 3 | motor 4 | dnspython 5 | hachoir 6 | Pillow 7 | aiohttp 8 | pytz 9 | humanize 10 | pyromod 11 | ffmpeg-python 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-slim 2 | 3 | # Install FFmpeg 4 | RUN apt update && \ 5 | apt install -y ffmpeg && \ 6 | apt clean 7 | 8 | WORKDIR /app 9 | 10 | COPY . /app 11 | 12 | RUN pip install --no-cache-dir -r requirements.txt 13 | 14 | CMD ["python", "bot.py"] 15 | 16 | -------------------------------------------------------------------------------- /route.py: -------------------------------------------------------------------------------- 1 | from aiohttp import web 2 | 3 | routes = web.RouteTableDef() 4 | 5 | @routes.get("/", allow_head=True) 6 | async def root_route_handler(request): 7 | return web.json_response("Codeflix bots") 8 | 9 | 10 | async def web_server(): 11 | web_app = web.Application(client_max_size=30000000) 12 | web_app.add_routes(routes) 13 | return web_app 14 | 15 | -------------------------------------------------------------------------------- /logging.conf: -------------------------------------------------------------------------------- 1 | [loggers] 2 | keys=root 3 | 4 | [handlers] 5 | keys=consoleHandler 6 | 7 | [formatters] 8 | keys=simpleFormatter 9 | 10 | [logger_root] 11 | level=DEBUG 12 | handlers=consoleHandler 13 | 14 | [handler_consoleHandler] 15 | class=StreamHandler 16 | level=DEBUG 17 | formatter=simpleFormatter 18 | args=(sys.stdout,) 19 | 20 | [formatter_simpleFormatter] 21 | format=%(asctime)s - %(name)s - %(levelname)s - %(message)s 22 | datefmt=%Y-%m-%d %H:%M:%S 23 | -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - type: web 3 | plan: free 4 | name: AutoRenameBot 5 | env: python 6 | buildCommand: pip install -r requirements.txt 7 | startCommand: python bot.py 8 | repo: https://github.com/Codeflix-Bots/AutoRenameBot.git 9 | branch: main 10 | autoDeploy: false 11 | envVars: 12 | - key: BOT_TOKEN 13 | sync: false 14 | - key: API_ID 15 | sync: false 16 | - key: API_HASH 17 | sync: false 18 | - key: FORCE_SUB 19 | sync: false 20 | - key: LOG_CHANNEL 21 | sync: false 22 | - key: DB_NAME 23 | sync: false 24 | - key: DB_URL 25 | sync: false 26 | - key: START_PIC 27 | sync: false 28 | - key: ADMIN 29 | sync: false 30 | - key: WEBHOOK 31 | sync: false 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 𝖢𝗈𝖽𝖾𝖿𝗅𝗂𝗑 𝖡𝗈𝗍𝗌 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 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Auto Renamer Bot", 3 | "description": "Telegram Auto File Renamer Bot ", 4 | "logo": "https://graph.org/file/2f461540c83b362772714.jpg", 5 | "keywords": ["Auto Renamer Bot", "Mongo DB"], 6 | "repository": "https://github.com/JishuDeveloper/Auto-Rename-Bot", 7 | "env": { 8 | "API_ID": { 9 | "description": "Your APP ID From my.telegram.org ", 10 | "value": "" 11 | }, 12 | "API_HASH": { 13 | "description": "Your API Hash From my.telegram.org ", 14 | "value": "" 15 | }, 16 | "WEBHOOK": { 17 | "description": "if your server is need web service! value = True else value = False", 18 | "value": "False" 19 | }, 20 | "FORCE_SUB": { 21 | "description": "Your force sub channel user name without [@] ", 22 | "value": "", 23 | "required": false 24 | }, 25 | "BOT_TOKEN": { 26 | "description": "Your Bot Token From @BotFather", 27 | "value": "" 28 | }, 29 | "ADMIN": { 30 | "description":"Add Your User ID multiple is use space to split" 31 | }, 32 | "LOG_CHANNEL": { 33 | "description":"Bot Log Sending Channel (just create a private channel and add bot to admin and take channel id to add this variable) ⚠️ id startswith -100 must", 34 | "required": false 35 | }, 36 | "DB_URL": { 37 | "description": "Your Mongo DB URL Obtained From mongodb.com", 38 | "value": "" 39 | }, 40 | "DB_NAME":{ 41 | "description":"Your Mongo DB Database Name ", 42 | "value": "", 43 | "required": false 44 | }, 45 | "START_PIC": { 46 | "description": "Your Bot start cmd Pic from @MT_TelegraPH_Bot", 47 | "value": "", 48 | "required": false 49 | } 50 | }, 51 | "buildpacks": [ 52 | { 53 | "url": "heroku/python" 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /plugins/thumb_&_cap.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from helper.database import codeflixbots 3 | 4 | @Client.on_message(filters.private & filters.command('set_caption')) 5 | async def add_caption(client, message): 6 | if len(message.command) == 1: 7 | return await message.reply_text("**Give The Caption\n\nExample :- `/set_caption 📕Name ➠ : {filename} \n\n🔗 Size ➠ : {filesize} \n\n⏰ Duration ➠ : {duration}`**") 8 | caption = message.text.split(" ", 1)[1] 9 | await codeflixbots.set_caption(message.from_user.id, caption=caption) 10 | await message.reply_text("**Your Caption Successfully Added ✅**") 11 | 12 | @Client.on_message(filters.private & filters.command('del_caption')) 13 | async def delete_caption(client, message): 14 | caption = await madflixbotz.get_caption(message.from_user.id) 15 | if not caption: 16 | return await message.reply_text("**You Don't Have Any Caption ❌**") 17 | await codeflixbots.set_caption(message.from_user.id, caption=None) 18 | await message.reply_text("**Your Caption Successfully Deleted 🗑️**") 19 | 20 | @Client.on_message(filters.private & filters.command(['see_caption', 'view_caption'])) 21 | async def see_caption(client, message): 22 | caption = await codeflixbots.get_caption(message.from_user.id) 23 | if caption: 24 | await message.reply_text(f"**Your Caption :**\n\n`{caption}`") 25 | else: 26 | await message.reply_text("**You Don't Have Any Caption ❌**") 27 | 28 | 29 | @Client.on_message(filters.private & filters.command(['view_thumb', 'viewthumb'])) 30 | async def viewthumb(client, message): 31 | thumb = await codeflixbots.get_thumbnail(message.from_user.id) 32 | if thumb: 33 | await client.send_photo(chat_id=message.chat.id, photo=thumb) 34 | else: 35 | await message.reply_text("**You Don't Have Any Thumbnail ❌**") 36 | 37 | @Client.on_message(filters.private & filters.command(['del_thumb', 'delthumb'])) 38 | async def removethumb(client, message): 39 | await codeflixbots.set_thumbnail(message.from_user.id, file_id=None) 40 | await message.reply_text("**Thumbnail Deleted Successfully 🗑️**") 41 | 42 | @Client.on_message(filters.private & filters.photo) 43 | async def addthumbs(client, message): 44 | mkn = await message.reply_text("Please Wait ...") 45 | await codeflixbots.set_thumbnail(message.from_user.id, file_id=message.photo.file_id) 46 | await mkn.edit("**Thumbnail Saved Successfully ✅️**") 47 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | import aiohttp, asyncio, warnings, pytz 2 | from datetime import datetime, timedelta 3 | from pytz import timezone 4 | from pyrogram import Client, __version__ 5 | from pyrogram.raw.all import layer 6 | from config import Config 7 | from aiohttp import web 8 | from route import web_server 9 | import pyrogram.utils 10 | import pyromod 11 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 12 | import os 13 | import time 14 | 15 | pyrogram.utils.MIN_CHANNEL_ID = -1009147483647 16 | 17 | # Setting SUPPORT_CHAT directly here 18 | SUPPORT_CHAT = int(os.environ.get("SUPPORT_CHAT", "-1001953724858")) 19 | 20 | PORT = Config.PORT 21 | 22 | class Bot(Client): 23 | 24 | def __init__(self): 25 | super().__init__( 26 | name="codeflixbots", 27 | api_id=Config.API_ID, 28 | api_hash=Config.API_HASH, 29 | bot_token=Config.BOT_TOKEN, 30 | workers=200, 31 | plugins={"root": "plugins"}, 32 | sleep_threshold=15, 33 | ) 34 | # Initialize the bot's start time for uptime calculation 35 | self.start_time = time.time() 36 | 37 | async def start(self, *args, **kwargs): 38 | await super().start(*args, **kwargs) 39 | me = await self.get_me() 40 | self.mention = me.mention 41 | self.username = me.username 42 | self.uptime = Config.BOT_UPTIME 43 | if Config.WEBHOOK: 44 | app = web.AppRunner(await web_server()) 45 | await app.setup() 46 | await web.TCPSite(app, "0.0.0.0", PORT).start() 47 | print(f"{me.first_name} Is Started.....✨️") 48 | 49 | # Calculate uptime using timedelta 50 | uptime_seconds = int(time.time() - self.start_time) 51 | uptime_string = str(timedelta(seconds=uptime_seconds)) 52 | 53 | for chat_id in [Config.LOG_CHANNEL, SUPPORT_CHAT]: 54 | try: 55 | curr = datetime.now(timezone("Asia/Kolkata")) 56 | date = curr.strftime('%d %B, %Y') 57 | time_str = curr.strftime('%I:%M:%S %p') 58 | 59 | # Send the message with the photo 60 | await self.send_photo( 61 | chat_id=chat_id, 62 | photo=Config.START_PIC, 63 | caption=( 64 | "**ᴀɴʏᴀ ɪs ʀᴇsᴛᴀʀᴛᴇᴅ ᴀɢᴀɪɴ !**\n\n" 65 | f"ɪ ᴅɪᴅɴ'ᴛ sʟᴇᴘᴛ sɪɴᴄᴇ​: `{uptime_string}`" 66 | ), 67 | reply_markup=InlineKeyboardMarkup( 68 | [[ 69 | InlineKeyboardButton("ᴜᴘᴅᴀᴛᴇs", url="https://t.me/codeflix_bots") 70 | ]] 71 | ) 72 | ) 73 | 74 | except Exception as e: 75 | print(f"Failed to send message in chat {chat_id}: {e}") 76 | 77 | Bot().run() 78 | -------------------------------------------------------------------------------- /plugins/auto_rename.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery 3 | from helper.database import codeflixbots 4 | 5 | @Client.on_message(filters.private & filters.command("autorename")) 6 | async def auto_rename_command(client, message): 7 | user_id = message.from_user.id 8 | 9 | # Extract and validate the format from the command 10 | command_parts = message.text.split(maxsplit=1) 11 | if len(command_parts) < 2 or not command_parts[1].strip(): 12 | await message.reply_text( 13 | "**Please provide a new name after the command /autorename**\n\n" 14 | "Here's how to use it:\n" 15 | "**Example format:** `/autorename Overflow [S{season}E{episode}] - [Dual] {quality}`" 16 | ) 17 | return 18 | 19 | format_template = command_parts[1].strip() 20 | 21 | # Save the format template in the database 22 | await codeflixbots.set_format_template(user_id, format_template) 23 | 24 | # Send confirmation message with the template in monospaced font 25 | await message.reply_text( 26 | f"**🌟 Fantastic! You're ready to auto-rename your files.**\n\n" 27 | "📩 Simply send the file(s) you want to rename.\n\n" 28 | f"**Your saved template:** `{format_template}`\n\n" 29 | "Remember, it might take some time, but I'll ensure your files are renamed perfectly!✨" 30 | ) 31 | 32 | 33 | @Client.on_message(filters.private & filters.command("setmedia")) 34 | async def set_media_command(client, message): 35 | """Initiate media type selection with a sleek inline keyboard.""" 36 | keyboard = InlineKeyboardMarkup([ 37 | [InlineKeyboardButton("📜 Documents", callback_data="setmedia_document")], 38 | [InlineKeyboardButton("🎬 Videos", callback_data="setmedia_video")], 39 | [InlineKeyboardButton("🎵 Audio", callback_data="setmedia_audio")], # Added audio option 40 | ]) 41 | 42 | await message.reply_text( 43 | "✨ **Choose Your Media Vibe** ✨\n" 44 | "Select the type of media you'd like to set as your preference:", 45 | reply_markup=keyboard, 46 | quote=True 47 | ) 48 | 49 | @Client.on_callback_query(filters.regex(r"^setmedia_")) 50 | async def handle_media_selection(client, callback_query: CallbackQuery): 51 | """Process the user's media type selection with flair and confirmation.""" 52 | user_id = callback_query.from_user.id 53 | media_type = callback_query.data.split("_", 1)[1].capitalize() # Extract and capitalize media type 54 | 55 | try: 56 | await codeflixbots.set_media_preference(user_id, media_type.lower()) 57 | 58 | await callback_query.answer(f"Locked in: {media_type} 🎉") 59 | await callback_query.message.edit_text( 60 | f"🎯 **Media Preference Updated** 🎯\n" 61 | f"Your vibe is now set to: **{media_type}** ✅\n" 62 | f"Ready to roll with your choice!" 63 | ) 64 | except Exception as e: 65 | await callback_query.answer("Oops, something went wrong! 😅") 66 | await callback_query.message.edit_text( 67 | f"⚠️ **Error Setting Preference** ⚠️\n" 68 | f"Couldn’t set {media_type} right now. Try again later!\n" 69 | f"Details: {str(e)}" 70 | ) 71 | -------------------------------------------------------------------------------- /plugins/antinsfw.py: -------------------------------------------------------------------------------- 1 | nsfw_keywords = { 2 | "general": [ 3 | "porn", "sex", "nude", "naked", "boobs", "tits", "pussy", "dick", "cock", "ass", 4 | "fuck", "blowjob", "cum", "orgasm", "shemale", "erotic", "masturbate", "anal", 5 | "hardcore", "bdsm", "fetish", "lingerie", "xxx", "milf", "gay", "lesbian", 6 | "threesome", "squirting", "butt plug", "dildo", "vibrator", "escort", "handjob", 7 | "striptease", "kinky", "pornstar", "sex tape", "spank", "swinger", "taboo", "cumshot", 8 | "deepthroat", "domination", "submission", "handcuffs", "orgy", "roleplay", "sex toy", 9 | "voyeur", "cosplay", "adult", "culture", "pornhwa", 10 | "netorare", "netori", "netorase", "eromanga", "incest", "stepmom", "stepdad", 11 | "stepsister", "stepbrother", "stepson", "stepdaughter", "ntr", "gangbang", 12 | "facial", "golden shower", "pegging", "rimming", "rough sex", "dirty talk", 13 | "sex chat", "nude pic", "lewd", "titty", "twerk", "breasts", "penis", "vagina", 14 | "clitoris", "genitals", "sexual", "kamasutra", "incest", "pedo", "rape", "bondage", 15 | "cum inside", "creampie", "sex slave", "sex doll", "sex machine", "latex", "oral sex", 16 | "butt", "slut", "whore", "tramp", "skank", "cumdumpster", "cultured", "ecchi", "doujin", 17 | "hentai", "smut", "lewd", "waifu", "futanari", "tentacle" 18 | ], 19 | "hentai": [ 20 | "hentai", "doujinshi", "ecchi", "yaoi", "shota", "loli", "tentacle", "futanari", 21 | "bishoujo", "bishounen", "mecha hentai", "hentai manga", "hentai anime", "smut", 22 | "eroge", "visual novel", "h-manga", "h-anime", "adult manga", "18+ anime", "18+ manga", 23 | "lewd anime", "lewd manga", "animated porn", "animated sex", "hentai game", "hentai art", 24 | "hentai drawing", "hentai doujin", "yaoi hentai", "hentai comic", 25 | "hentai picture", "hentai scene", "hentai story", "hentai video", "hentai movie", 26 | "hentai episode", "hentai series" 27 | ], 28 | "abbreviations": [ 29 | "pr0n", "s3x", "n00d", "fck", "bj", "hj", "l33t", "p0rn", "h3ntai", "h-ntai", "pnwh", 30 | "p0rnhwa", "l33tsp34k", "l3wd", "cultur3d", "s3xual" 31 | ], 32 | "offensive_slang": [ 33 | "slut", "whore", "tramp", "skank", "cumdumpster", "gangbang", "facial", "golden shower", 34 | "pegging", "rimming", "rough sex", "dirty talk", "sex chat", "nude pic", "lewd", "titty", 35 | "twerk", "breasts", "penis", "vagina", "clitoris", "genitals", "sexual", "kamasutra", 36 | "incest", "pedo", "rape", "sex slave", "bondage", "creampie", "cum inside", "sex doll", 37 | "sex machine", "latex", "oral sex", "cumshot", "deepthroat", "domination", "submission", 38 | "handcuffs", "orgy", "roleplay", "sex toy", "voyeur", "cosplay", "adult", "culture", 39 | "anal", "erotic", "masturbate", "hardcore", "bdsm", "fetish", "lingerie", "milf", "taboo" 40 | ] 41 | } 42 | 43 | exception_keywords = ["nxivm", "classroom", "assassination", "geass"] 44 | 45 | async def check_anti_nsfw(new_name, message): 46 | lower_name = new_name.lower() 47 | for keyword in exception_keywords: 48 | if keyword.lower() in lower_name: 49 | return False # Allow the filename if it contains an exception keyword 50 | 51 | for category, keywords in nsfw_keywords.items(): 52 | for keyword in keywords: 53 | if keyword.lower() in lower_name: 54 | await message.reply_text("You can't rename files with NSFW content.") 55 | return True 56 | return False 57 | -------------------------------------------------------------------------------- /plugins/force_subs.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pyrogram import Client, filters 3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery 4 | from pyrogram.errors import UserNotParticipant 5 | from config import Config 6 | 7 | FORCE_SUB_CHANNELS = Config.FORCE_SUB_CHANNELS 8 | IMAGE_URL = "https://graph.org/file/a27d85469761da836337c.jpg" 9 | 10 | async def not_subscribed(_, __, message): 11 | for channel in FORCE_SUB_CHANNELS: 12 | try: 13 | user = await message._client.get_chat_member(channel, message.from_user.id) 14 | if user.status in {"kicked", "left"}: 15 | return True 16 | except UserNotParticipant: 17 | return True 18 | return False 19 | 20 | @Client.on_message(filters.private & filters.create(not_subscribed)) 21 | async def forces_sub(client, message): 22 | not_joined_channels = [] 23 | for channel in FORCE_SUB_CHANNELS: 24 | try: 25 | user = await client.get_chat_member(channel, message.from_user.id) 26 | if user.status in {"kicked", "left"}: 27 | not_joined_channels.append(channel) 28 | except UserNotParticipant: 29 | not_joined_channels.append(channel) 30 | 31 | buttons = [ 32 | [ 33 | InlineKeyboardButton( 34 | text=f"• ᴊᴏɪɴ {channel.capitalize()} •", url=f"https://t.me/{channel}" 35 | ) 36 | ] 37 | for channel in not_joined_channels 38 | ] 39 | buttons.append( 40 | [ 41 | InlineKeyboardButton( 42 | text="• ᴊᴏɪɴᴇᴅ •", callback_data="check_subscription" 43 | ) 44 | ] 45 | ) 46 | 47 | text = "**ʙᴀᴋᴋᴀ!!, ʏᴏᴜ'ʀᴇ ɴᴏᴛ ᴊᴏɪɴᴇᴅ ᴛᴏ ᴀʟʟ ʀᴇǫᴜɪʀᴇᴅ ᴄʜᴀɴɴᴇʟs, ᴊᴏɪɴ ᴛʜᴇ ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟs ᴛᴏ ᴄᴏɴᴛɪɴᴜᴇ**" 48 | await message.reply_photo( 49 | photo=IMAGE_URL, 50 | caption=text, 51 | reply_markup=InlineKeyboardMarkup(buttons) 52 | ) 53 | 54 | @Client.on_callback_query(filters.regex("check_subscription")) 55 | async def check_subscription(client, callback_query: CallbackQuery): 56 | user_id = callback_query.from_user.id 57 | not_joined_channels = [] 58 | 59 | for channel in FORCE_SUB_CHANNELS: 60 | try: 61 | user = await client.get_chat_member(channel, user_id) 62 | if user.status in {"kicked", "left"}: 63 | not_joined_channels.append(channel) 64 | except UserNotParticipant: 65 | not_joined_channels.append(channel) 66 | 67 | if not not_joined_channels: 68 | new_text = "**ʏᴏᴜ ʜᴀᴠᴇ ᴊᴏɪɴᴇᴅ ᴀʟʟ ᴛʜᴇ ʀᴇǫᴜɪʀᴇᴅ ᴄʜᴀɴɴᴇʟs. ᴛʜᴀɴᴋ ʏᴏᴜ! 😊 /start ɴᴏᴡ**" 69 | if callback_query.message.caption != new_text: 70 | await callback_query.message.edit_caption( 71 | caption=new_text, 72 | reply_markup=InlineKeyboardMarkup([ 73 | [InlineKeyboardButton("• ɴᴏᴡ ᴄʟɪᴄᴋ ʜᴇʀᴇ •", callback_data='help')] 74 | ]) 75 | ) 76 | else: 77 | buttons = [ 78 | [ 79 | InlineKeyboardButton( 80 | text=f"• ᴊᴏɪɴ {channel.capitalize()} •", 81 | url=f"https://t.me/{channel}", 82 | ) 83 | ] 84 | for channel in not_joined_channels 85 | ] 86 | buttons.append( 87 | [ 88 | InlineKeyboardButton( 89 | text="• ᴊᴏɪɴᴇᴅ •", callback_data="check_subscription" 90 | ) 91 | ] 92 | ) 93 | 94 | text = "**ʏᴏᴜ ʜᴀᴠᴇ ᴊᴏɪɴᴇᴅ ᴀʟʟ ᴛʜᴇ ʀᴇǫᴜɪʀᴇᴅ ᴄʜᴀɴɴᴇʟs. ᴘʟᴇᴀsᴇ ᴊᴏɪɴ ᴛʜᴇ ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟs ᴛᴏ ᴄᴏɴᴛɪɴᴜᴇ**" 95 | if callback_query.message.caption != text: 96 | await callback_query.message.edit_caption( 97 | caption=text, 98 | reply_markup=InlineKeyboardMarkup(buttons) 99 | ) 100 | -------------------------------------------------------------------------------- /helper/utils.py: -------------------------------------------------------------------------------- 1 | import math, time 2 | from datetime import datetime 3 | from pytz import timezone 4 | from config import Config, Txt 5 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 6 | import re 7 | 8 | 9 | async def progress_for_pyrogram(current, total, ud_type, message, start): 10 | now = time.time() 11 | diff = now - start 12 | if round(diff % 5.00) == 0 or current == total: 13 | percentage = current * 100 / total 14 | speed = current / diff 15 | elapsed_time = round(diff) * 1000 16 | time_to_completion = round((total - current) / speed) * 1000 17 | estimated_total_time = elapsed_time + time_to_completion 18 | 19 | elapsed_time = TimeFormatter(milliseconds=elapsed_time) 20 | estimated_total_time = TimeFormatter(milliseconds=estimated_total_time) 21 | 22 | progress = "{0}{1}".format( 23 | ''.join(["■" for i in range(math.floor(percentage / 5))]), 24 | ''.join(["□" for i in range(20 - math.floor(percentage / 5))]) 25 | ) 26 | tmp = progress + Txt.PROGRESS_BAR.format( 27 | round(percentage, 2), 28 | humanbytes(current), 29 | humanbytes(total), 30 | humanbytes(speed), 31 | estimated_total_time if estimated_total_time != '' else "0 s" 32 | ) 33 | try: 34 | await message.edit( 35 | text=f"{ud_type}\n\n{tmp}", 36 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("• ᴄᴀɴᴄᴇʟ •", callback_data="close")]]) 37 | ) 38 | except: 39 | pass 40 | 41 | def humanbytes(size): 42 | if not size: 43 | return "" 44 | power = 2**10 45 | n = 0 46 | Dic_powerN = {0: ' ', 1: 'K', 2: 'M', 3: 'G', 4: 'T'} 47 | while size > power: 48 | size /= power 49 | n += 1 50 | return str(round(size, 2)) + " " + Dic_powerN[n] + 'ʙ' 51 | 52 | 53 | def TimeFormatter(milliseconds: int) -> str: 54 | seconds, milliseconds = divmod(int(milliseconds), 1000) 55 | minutes, seconds = divmod(seconds, 60) 56 | hours, minutes = divmod(minutes, 60) 57 | days, hours = divmod(hours, 24) 58 | tmp = ((str(days) + "ᴅ, ") if days else "") + \ 59 | ((str(hours) + "ʜ, ") if hours else "") + \ 60 | ((str(minutes) + "ᴍ, ") if minutes else "") + \ 61 | ((str(seconds) + "ꜱ, ") if seconds else "") + \ 62 | ((str(milliseconds) + "ᴍꜱ, ") if milliseconds else "") 63 | return tmp[:-2] 64 | 65 | def convert(seconds): 66 | seconds = seconds % (24 * 3600) 67 | hour = seconds // 3600 68 | seconds %= 3600 69 | minutes = seconds // 60 70 | seconds %= 60 71 | return "%d:%02d:%02d" % (hour, minutes, seconds) 72 | 73 | async def send_log(b, u): 74 | if Config.LOG_CHANNEL is not None: 75 | curr = datetime.now(timezone("Asia/Kolkata")) 76 | date = curr.strftime('%d %B, %Y') 77 | time = curr.strftime('%I:%M:%S %p') 78 | await b.send_message( 79 | Config.LOG_CHANNEL, 80 | f"**--Nᴇᴡ Uꜱᴇʀ Sᴛᴀʀᴛᴇᴅ Tʜᴇ Bᴏᴛ--**\n\nUꜱᴇʀ: {u.mention}\nIᴅ: `{u.id}`\nUɴ: @{u.username}\n\nDᴀᴛᴇ: {date}\nTɪᴍᴇ: {time}\n\nBy: {b.mention}" 81 | ) 82 | 83 | def add_prefix_suffix(input_string, prefix='', suffix=''): 84 | pattern = r'(?P.*?)(\.\w+)?$' 85 | match = re.search(pattern, input_string) 86 | if match: 87 | filename = match.group('filename') 88 | extension = match.group(2) or '' 89 | if prefix == None: 90 | if suffix == None: 91 | return f"{filename}{extension}" 92 | return f"{filename} {suffix}{extension}" 93 | elif suffix == None: 94 | if prefix == None: 95 | return f"{filename}{extension}" 96 | return f"{prefix}{filename}{extension}" 97 | else: 98 | return f"{prefix}{filename} {suffix}{extension}" 99 | 100 | 101 | else: 102 | return input_string 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ━━━━━━━━━━━━━━━━━━━━ 2 | 3 |

4 | ──「 ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ 」── 5 |

6 | 7 |

8 | 9 |

10 | 11 | _**ᴀᴠᴀɪʟᴀʙʟᴇ ᴏɴ ᴛᴇʟᴇɢʀᴀᴍ ᴀs [ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ](https://t.me/)**_ 12 | 13 |

14 | 𝗗𝗘𝗣𝗟𝗢𝗬𝗠𝗘𝗡𝗧 𝗠𝗘𝗧𝗛𝗢𝗗𝗦 15 |

16 | 17 |

18 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ʜᴇʀᴏᴋᴜ 」─ 19 |

20 | 21 |

22 | 23 |

24 | ─「 ᴅᴇᴘʟᴏʏ ᴏɴ ᴋᴏʏᴇʙ 」─ 25 |

26 |

27 | 28 | 29 |
- ғᴇᴀᴛᴜʀᴇs : 30 | 31 | ## ғᴇᴀᴛᴜʀᴇs 32 | - [x] Renames very fast . 33 | - [x] Metadata Support 34 | - [x] Permanent Thumbnail support. 35 | - [x] Supports Broadcasts. 36 | - [x] Set custom caption. 37 | - [x] Has a custom Start-up pic. 38 | - [x] Force subscribe available. 39 | - [x] Supports ulimited renaming at a time. 40 | - [x] Deploy to Koyeb + Heroku + Railway. 41 | - [x] Automatically rename your files 42 | - [x] Set mediatype to upload filetype 43 | - [x] Developer Service 24x7. 44 | 45 | ᴛᴏ ᴋɴᴏᴡ ᴀʙᴏᴜᴛ ᴀʟʟ ғᴇᴀᴛᴜʀᴇs, ᴊᴏɪɴ ᴏᴜʀ ᴜᴘᴅᴀᴛᴇs ᴄʜᴀɴɴᴇʟ. 46 |
47 | 48 |
- ᴅᴇᴘʟᴏʏᴍᴇɴᴛ ᴠᴀʀɪᴀʙʟᴇs : 49 | 50 | ## ᴅᴇᴘʟᴏʏᴍᴇɴᴛ ᴠᴀʀɪᴀʙʟᴇs 51 | ``` 52 | - [x] API_ID - get it from telegram app 53 | - [x] API_HASH - get it from telegram app 54 | - [x] BOT_TOKEN - get it from telegram app 55 | - [x] ADMIN - for 2 or more '12345678 89674523' add space between ids 56 | - [x] DB_URL - MongoDB URL from [MongoDB Atlas](https://cloud.mongodb.com). 57 | - [x] DB_NAME - Your MongoDB database name. **Optional**. 58 | - [x] FORCE_SUB_CHANNELS - Your force subscription channel usernames without `@`. **Optional**. Use format `1CHANNEL,2CHANNEL`. 59 | - [x] START_PIC - Start message photo. **Optional**. 60 | - [x] LOG_CHANNEL - add a private channel id 61 | - [x] WEBHOOK - Set to `True` if your server requires web services, otherwise set to `False`. **Optional**. 62 | ``` 63 |
64 |
- ᴄᴏᴍᴍᴍᴀɴᴅs : 65 | 66 | ## ᴄᴏᴍᴍᴍᴀɴᴅs 67 | ``` 68 | start - Check if the bot is running. 69 | autorename - To auto rename your files. 70 | metadata - to set metadata 71 | setmedia - To set your media type preference. 72 | tutorial - To know how to use me. 73 | viewthumb - To view current thumbnail. 74 | delthumb - To delete current thumbnail. 75 | set_caption - set a custom caption. 76 | see_caption - see your custom caption. 77 | del_caption - delete custom caption. 78 | restart - To restart the bot [FOR ADMINS USE ONLY] 79 | broadcast - Message Broadcast command [FOR ADMINS USE ONLY]. 80 | status - Check bot status [FOR ADMINS USE ONLY]. 81 | ``` 82 |
83 | ━━━━━━━━━━━━━━━━━━━━ 84 | 85 |

86 | ─「 sᴜᴩᴩᴏʀᴛ 」─ 87 |

88 | 89 |

90 | 91 |

92 |

93 | 94 |

95 | 96 | ━━━━━━━━━━━━━━━━━━━━ 97 | 98 |

99 | ─「 ᴄʀᴇᴅɪᴛs 」─ 100 |

101 | 102 | - [ʏᴀᴛᴏ](https://github.com/cosmic_freak) ➻ [sᴏᴍᴇᴛʜɪɴɢ](https://github.com/Codeflix-Bots/AutoFilter) 103 | 104 | ᴀɴᴅ ᴀʟʟ [ᴛʜᴇ ᴄᴏɴᴛʀɪʙᴜᴛᴏʀs](https://github.com/Codeflix-Bots/autorenamebot/graphs/contributors) ᴡʜᴏ ʜᴇʟᴩᴇᴅ ɪɴ ᴍᴀᴋɪɴɢ ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ᴜsᴇғᴜʟ & ᴩᴏᴡᴇʀғᴜʟ 🖤 105 | 106 | ━━━━━━━━━━━━━━━━━━━━ 107 | 108 | -------------------------------------------------------------------------------- /plugins/admin_panel.py: -------------------------------------------------------------------------------- 1 | from config import Config, Txt 2 | from helper.database import codeflixbots 3 | from pyrogram.types import Message 4 | from pyrogram import Client, filters 5 | from pyrogram.errors import FloodWait, InputUserDeactivated, UserIsBlocked, PeerIdInvalid 6 | import os, sys, time, asyncio, logging, datetime 7 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 8 | 9 | logger = logging.getLogger(__name__) 10 | logger.setLevel(logging.INFO) 11 | ADMIN_USER_ID = Config.ADMIN 12 | 13 | # Flag to indicate if the bot is restarting 14 | is_restarting = False 15 | 16 | @Client.on_message(filters.private & filters.command("restart") & filters.user(ADMIN_USER_ID)) 17 | async def restart_bot(b, m): 18 | global is_restarting 19 | if not is_restarting: 20 | is_restarting = True 21 | await m.reply_text("**Restarting.....**") 22 | 23 | # Gracefully stop the bot's event loop 24 | b.stop() 25 | time.sleep(2) # Adjust the delay duration based on your bot's shutdown time 26 | 27 | # Restart the bot process 28 | os.execl(sys.executable, sys.executable, *sys.argv) 29 | 30 | 31 | @Client.on_message(filters.private & filters.command("tutorial")) 32 | async def tutorial(bot: Client, message: Message): 33 | user_id = message.from_user.id 34 | format_template = await codeflixbots.get_format_template(user_id) 35 | await message.reply_text( 36 | text=Txt.FILE_NAME_TXT.format(format_template=format_template), 37 | disable_web_page_preview=True, 38 | reply_markup=InlineKeyboardMarkup([ 39 | [InlineKeyboardButton("• ᴏᴡɴᴇʀ", url="https://t.me/cosmic_freak"), 40 | InlineKeyboardButton("• ᴛᴜᴛᴏʀɪᴀʟ", url="https://t.me/codeflix_bots")] 41 | ]) 42 | ) 43 | 44 | 45 | @Client.on_message(filters.command(["stats", "status"]) & filters.user(Config.ADMIN)) 46 | async def get_stats(bot, message): 47 | total_users = await codeflixbots.total_users_count() 48 | uptime = time.strftime("%Hh%Mm%Ss", time.gmtime(time.time() - bot.uptime)) 49 | start_t = time.time() 50 | st = await message.reply('**Accessing The Details.....**') 51 | end_t = time.time() 52 | time_taken_s = (end_t - start_t) * 1000 53 | await st.edit(text=f"**--Bot Status--** \n\n**⌚️ Bot Uptime :** {uptime} \n**🐌 Current Ping :** `{time_taken_s:.3f} ms` \n**👭 Total Users :** `{total_users}`") 54 | 55 | @Client.on_message(filters.command("broadcast") & filters.user(Config.ADMIN) & filters.reply) 56 | async def broadcast_handler(bot: Client, m: Message): 57 | await bot.send_message(Config.LOG_CHANNEL, f"{m.from_user.mention} or {m.from_user.id} Is Started The Broadcast......") 58 | all_users = await codeflixbots.get_all_users() 59 | broadcast_msg = m.reply_to_message 60 | sts_msg = await m.reply_text("Broadcast Started..!") 61 | done = 0 62 | failed = 0 63 | success = 0 64 | start_time = time.time() 65 | total_users = await codeflixbots.total_users_count() 66 | async for user in all_users: 67 | sts = await send_msg(user['_id'], broadcast_msg) 68 | if sts == 200: 69 | success += 1 70 | else: 71 | failed += 1 72 | if sts == 400: 73 | await codeflixbots.delete_user(user['_id']) 74 | done += 1 75 | if not done % 20: 76 | await sts_msg.edit(f"Broadcast In Progress: \n\nTotal Users {total_users} \nCompleted : {done} / {total_users}\nSuccess : {success}\nFailed : {failed}") 77 | completed_in = datetime.timedelta(seconds=int(time.time() - start_time)) 78 | await sts_msg.edit(f"Bʀᴏᴀᴅᴄᴀꜱᴛ Cᴏᴍᴩʟᴇᴛᴇᴅ: \nCᴏᴍᴩʟᴇᴛᴇᴅ Iɴ `{completed_in}`.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nFailed: {failed}") 79 | 80 | async def send_msg(user_id, message): 81 | try: 82 | await message.copy(chat_id=int(user_id)) 83 | return 200 84 | except FloodWait as e: 85 | await asyncio.sleep(e.value) 86 | return send_msg(user_id, message) 87 | except InputUserDeactivated: 88 | logger.info(f"{user_id} : Deactivated") 89 | return 400 90 | except UserIsBlocked: 91 | logger.info(f"{user_id} : Blocked The Bot") 92 | return 400 93 | except PeerIdInvalid: 94 | logger.info(f"{user_id} : User ID Invalid") 95 | return 400 96 | except Exception as e: 97 | logger.error(f"{user_id} : {e}") 98 | return 500 99 | -------------------------------------------------------------------------------- /plugins/metadata.py: -------------------------------------------------------------------------------- 1 | from helper.database import codeflixbots as db 2 | from pyrogram import Client, filters 3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery 4 | from config import Txt 5 | 6 | @Client.on_message(filters.command("metadata")) 7 | async def metadata(client, message): 8 | user_id = message.from_user.id 9 | 10 | # Fetch user metadata from the database 11 | current = await db.get_metadata(user_id) 12 | title = await db.get_title(user_id) 13 | author = await db.get_author(user_id) 14 | artist = await db.get_artist(user_id) 15 | video = await db.get_video(user_id) 16 | audio = await db.get_audio(user_id) 17 | subtitle = await db.get_subtitle(user_id) 18 | 19 | # Display the current metadata 20 | text = f""" 21 | **㊋ Yᴏᴜʀ Mᴇᴛᴀᴅᴀᴛᴀ ɪꜱ ᴄᴜʀʀᴇɴᴛʟʏ: {current}** 22 | 23 | **◈ Tɪᴛʟᴇ ▹** `{title if title else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 24 | **◈ Aᴜᴛʜᴏʀ ▹** `{author if author else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 25 | **◈ Aʀᴛɪꜱᴛ ▹** `{artist if artist else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 26 | **◈ Aᴜᴅɪᴏ ▹** `{audio if audio else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 27 | **◈ Sᴜʙᴛɪᴛʟᴇ ▹** `{subtitle if subtitle else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 28 | **◈ Vɪᴅᴇᴏ ▹** `{video if video else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 29 | """ 30 | 31 | # Inline buttons to toggle metadata 32 | buttons = [ 33 | [ 34 | InlineKeyboardButton(f"On{' ✅' if current == 'On' else ''}", callback_data='on_metadata'), 35 | InlineKeyboardButton(f"Off{' ✅' if current == 'Off' else ''}", callback_data='off_metadata') 36 | ], 37 | [ 38 | InlineKeyboardButton("How to Set Metadata", callback_data="metainfo") 39 | ] 40 | ] 41 | keyboard = InlineKeyboardMarkup(buttons) 42 | 43 | await message.reply_text(text=text, reply_markup=keyboard, disable_web_page_preview=True) 44 | 45 | 46 | @Client.on_callback_query(filters.regex(r"on_metadata|off_metadata|metainfo")) 47 | async def metadata_callback(client, query: CallbackQuery): 48 | user_id = query.from_user.id 49 | data = query.data 50 | 51 | if data == "on_metadata": 52 | await db.set_metadata(user_id, "On") 53 | elif data == "off_metadata": 54 | await db.set_metadata(user_id, "Off") 55 | elif data == "metainfo": 56 | await query.message.edit_text( 57 | text=Txt.META_TXT, 58 | disable_web_page_preview=True, 59 | reply_markup=InlineKeyboardMarkup([ 60 | [ 61 | InlineKeyboardButton("Hᴏᴍᴇ", callback_data="home"), 62 | InlineKeyboardButton("close", callback_data="close") 63 | ] 64 | ]) 65 | ) 66 | return 67 | 68 | # Fetch updated metadata after toggling 69 | current = await db.get_metadata(user_id) 70 | title = await db.get_title(user_id) 71 | author = await db.get_author(user_id) 72 | artist = await db.get_artist(user_id) 73 | video = await db.get_video(user_id) 74 | audio = await db.get_audio(user_id) 75 | subtitle = await db.get_subtitle(user_id) 76 | 77 | # Updated metadata message after toggle 78 | text = f""" 79 | **㊋ Yᴏᴜʀ Mᴇᴛᴀᴅᴀᴛᴀ ɪꜱ ᴄᴜʀʀᴇɴᴛʟʏ: {current}** 80 | 81 | **◈ Tɪᴛʟᴇ ▹** `{title if title else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 82 | **◈ Aᴜᴛʜᴏʀ ▹** `{author if author else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 83 | **◈ Aʀᴛɪꜱᴛ ▹** `{artist if artist else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 84 | **◈ Aᴜᴅɪᴏ ▹** `{audio if audio else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 85 | **◈ Sᴜʙᴛɪᴛʟᴇ ▹** `{subtitle if subtitle else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 86 | **◈ Vɪᴅᴇᴏ ▹** `{video if video else 'Nᴏᴛ ꜰᴏᴜɴᴅ'}` 87 | """ 88 | 89 | # Update inline buttons 90 | buttons = [ 91 | [ 92 | InlineKeyboardButton(f"On{' ✅' if current == 'On' else ''}", callback_data='on_metadata'), 93 | InlineKeyboardButton(f"Off{' ✅' if current == 'Off' else ''}", callback_data='off_metadata') 94 | ], 95 | [ 96 | InlineKeyboardButton("How to Set Metadata", callback_data="metainfo") 97 | ] 98 | ] 99 | await query.message.edit_text(text=text, reply_markup=InlineKeyboardMarkup(buttons), disable_web_page_preview=True) 100 | 101 | 102 | @Client.on_message(filters.private & filters.command('settitle')) 103 | async def title(client, message): 104 | if len(message.command) == 1: 105 | return await message.reply_text( 106 | "**Gɪᴠᴇ Tʜᴇ Tɪᴛʟᴇ\n\nExᴀᴍᴩʟᴇ:- /settitle Encoded By @Animes_Cruise**") 107 | title = message.text.split(" ", 1)[1] 108 | await db.set_title(message.from_user.id, title=title) 109 | await message.reply_text("**✅ Tɪᴛʟᴇ Sᴀᴠᴇᴅ**") 110 | 111 | @Client.on_message(filters.private & filters.command('setauthor')) 112 | async def author(client, message): 113 | if len(message.command) == 1: 114 | return await message.reply_text( 115 | "**Gɪᴠᴇ Tʜᴇ Aᴜᴛʜᴏʀ\n\nExᴀᴍᴩʟᴇ:- /setauthor @Animes_Cruise**") 116 | author = message.text.split(" ", 1)[1] 117 | await db.set_author(message.from_user.id, author=author) 118 | await message.reply_text("**✅ Aᴜᴛʜᴏʀ Sᴀᴠᴇᴅ**") 119 | 120 | @Client.on_message(filters.private & filters.command('setartist')) 121 | async def artist(client, message): 122 | if len(message.command) == 1: 123 | return await message.reply_text( 124 | "**Gɪᴠᴇ Tʜᴇ Aʀᴛɪꜱᴛ\n\nExᴀᴍᴩʟᴇ:- /setartist @Animes_Cruise**") 125 | artist = message.text.split(" ", 1)[1] 126 | await db.set_artist(message.from_user.id, artist=artist) 127 | await message.reply_text("**✅ Aʀᴛɪꜱᴛ Sᴀᴠᴇᴅ**") 128 | 129 | @Client.on_message(filters.private & filters.command('setaudio')) 130 | async def audio(client, message): 131 | if len(message.command) == 1: 132 | return await message.reply_text( 133 | "**Gɪᴠᴇ Tʜᴇ Aᴜᴅɪᴏ Tɪᴛʟᴇ\n\nExᴀᴍᴩʟᴇ:- /setaudio @Animes_Cruise**") 134 | audio = message.text.split(" ", 1)[1] 135 | await db.set_audio(message.from_user.id, audio=audio) 136 | await message.reply_text("**✅ Aᴜᴅɪᴏ Sᴀᴠᴇᴅ**") 137 | 138 | @Client.on_message(filters.private & filters.command('setsubtitle')) 139 | async def subtitle(client, message): 140 | if len(message.command) == 1: 141 | return await message.reply_text( 142 | "**Gɪᴠᴇ Tʜᴇ Sᴜʙᴛɪᴛʟᴇ Tɪᴛʟᴇ\n\nExᴀᴍᴩʟᴇ:- /setsubtitle @Animes_Cruise**") 143 | subtitle = message.text.split(" ", 1)[1] 144 | await db.set_subtitle(message.from_user.id, subtitle=subtitle) 145 | await message.reply_text("**✅ Sᴜʙᴛɪᴛʟᴇ Sᴀᴠᴇᴅ**") 146 | 147 | @Client.on_message(filters.private & filters.command('setvideo')) 148 | async def video(client, message): 149 | if len(message.command) == 1: 150 | return await message.reply_text( 151 | "**Gɪᴠᴇ Tʜᴇ Vɪᴅᴇᴏ Tɪᴛʟᴇ\n\nExᴀᴍᴩʟᴇ:- /setvideo Encoded by @Animes_Cruise**") 152 | video = message.text.split(" ", 1)[1] 153 | await db.set_video(message.from_user.id, video=video) 154 | await message.reply_text("**✅ Vɪᴅᴇᴏ Sᴀᴠᴇᴅ**") 155 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import re, os, time 2 | from os import environ, getenv 3 | id_pattern = re.compile(r'^.\d+$') 4 | 5 | 6 | class Config(object): 7 | # pyro client config 8 | API_ID = os.environ.get("API_ID", "") 9 | API_HASH = os.environ.get("API_HASH", "") 10 | BOT_TOKEN = os.environ.get("BOT_TOKEN", "736532225-w") 11 | 12 | # database config 13 | DB_NAME = os.environ.get("DB_NAME","Yato") 14 | DB_URL = os.environ.get("DB_URL","mongodb") 15 | PORT = os.environ.get("PORT", "8080") 16 | 17 | # other configs 18 | BOT_UPTIME = time.time() 19 | START_PIC = os.environ.get("START_PIC", "https://graph.org/file/29a3acbbab9de5f45a5fe.jpg") 20 | ADMIN = [int(admin) if id_pattern.search(admin) else admin for admin in os.environ.get('ADMIN', '6497757690').split()] 21 | FORCE_SUB_CHANNELS = os.environ.get('FORCE_SUB_CHANNELS', 'codeflix_bots').split(',') 22 | LOG_CHANNEL = int(os.environ.get("LOG_CHANNEL", "-1001868871195")) 23 | DUMP_CHANNEL = int(os.environ.get("DUMP_CHANNEL", "-1001868871195")) 24 | 25 | # wes response configuration 26 | WEBHOOK = bool(os.environ.get("WEBHOOK", "True")) 27 | 28 | 29 | class Txt(object): 30 | # part of text configuration 31 | 32 | START_TXT = """ʜᴇʏ! {} 33 | 34 | » ɪ ᴀᴍ ᴀᴅᴠᴀɴᴄᴇᴅ ʀᴇɴᴀᴍᴇ ʙᴏᴛ! ᴡʜɪᴄʜ ᴄᴀɴ ᴀᴜᴛᴏʀᴇɴᴀᴍᴇ ʏᴏᴜʀ ғɪʟᴇs ᴡɪᴛʜ ᴄᴜsᴛᴏᴍ ᴄᴀᴘᴛɪᴏɴ ᴀɴᴅ ᴛʜᴜᴍʙɴᴀɪʟ ᴀɴᴅ ᴀʟsᴏ sᴇǫᴜᴇɴᴄᴇ ᴛʜᴇᴍ ᴘᴇʀғᴇᴄᴛʟʏ""" 35 | 36 | FILE_NAME_TXT = """» sᴇᴛᴜᴘ ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ғᴏʀᴍᴀᴛ 37 | 38 | ᴠᴀʀɪᴀʙʟᴇꜱ : 39 | ➲ ᴇᴘɪꜱᴏᴅᴇ - ᴛᴏ ʀᴇᴘʟᴀᴄᴇ ᴇᴘɪꜱᴏᴅᴇ ɴᴜᴍʙᴇʀ 40 | ➲ ꜱᴇᴀꜱᴏɴ - ᴛᴏ ʀᴇᴘʟᴀᴄᴇ ꜱᴇᴀꜱᴏɴ ɴᴜᴍʙᴇʀ 41 | ➲ ǫᴜᴀʟɪᴛʏ - ᴛᴏ ʀᴇᴘʟᴀᴄᴇ ǫᴜᴀʟɪᴛʏ 42 | 43 | ‣ ꜰᴏʀ ᴇx:- `/autorename Oᴠᴇʀғʟᴏᴡ [Sseason Eepisode] - [Dual] quality` 44 | 45 | ‣ /Autorename: ʀᴇɴᴀᴍᴇ ʏᴏᴜʀ ᴍᴇᴅɪᴀ ꜰɪʟᴇꜱ ʙʏ ɪɴᴄʟᴜᴅɪɴɢ 'ᴇᴘɪꜱᴏᴅᴇ' ᴀɴᴅ 'ǫᴜᴀʟɪᴛʏ' ᴠᴀʀɪᴀʙʟᴇꜱ ɪɴ ʏᴏᴜʀ ᴛᴇxᴛ, ᴛᴏ ᴇxᴛʀᴀᴄᴛ ᴇᴘɪꜱᴏᴅᴇ ᴀɴᴅ ǫᴜᴀʟɪᴛʏ ᴘʀᴇꜱᴇɴᴛ ɪɴ ᴛʜᴇ ᴏʀɪɢɪɴᴀʟ ꜰɪʟᴇɴᴀᴍᴇ. """ 46 | 47 | ABOUT_TXT = f"""❍ ᴍʏ ɴᴀᴍᴇ : ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ 48 | ❍ ᴅᴇᴠᴇʟᴏᴩᴇʀ : ʏᴀᴛᴏ 49 | ❍ ɢɪᴛʜᴜʙ : ʏᴀᴛᴏ 50 | ❍ ʟᴀɴɢᴜᴀɢᴇ : ᴘʏᴛʜᴏɴ 51 | ❍ ᴅᴀᴛᴀʙᴀꜱᴇ : ᴍᴏɴɢᴏ ᴅʙ 52 | ❍ ʜᴏꜱᴛᴇᴅ ᴏɴ : ᴠᴘs 53 | ❍ ᴍᴀɪɴ ᴄʜᴀɴɴᴇʟ : ᴀɴɪᴍᴇ ᴄʀᴜɪsᴇ 54 | 55 | ➻ ᴄʟɪᴄᴋ ᴏɴ ᴛʜᴇ ʙᴜᴛᴛᴏɴs ɢɪᴠᴇɴ ʙᴇʟᴏᴡ ғᴏʀ ɢᴇᴛᴛɪɴɢ ʙᴀsɪᴄ ʜᴇʟᴩ ᴀɴᴅ ɪɴғᴏ ᴀʙᴏᴜᴛ ᴍᴇ.""" 56 | 57 | 58 | THUMBNAIL_TXT = """» ᴛᴏ ꜱᴇᴛ ᴄᴜꜱᴛᴏᴍ ᴛʜᴜᴍʙɴᴀɪʟ 59 | 60 | ➲ /start: ꜱᴇɴᴅ ᴀɴʏ ᴘʜᴏᴛᴏ ᴛᴏ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ꜱᴇᴛ ɪᴛ ᴀꜱ ᴀ ᴛʜᴜᴍʙɴᴀɪʟ.. 61 | ➲ /del_thumb: ᴜꜱᴇ ᴛʜɪꜱ ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ ᴅᴇʟᴇᴛᴇ ʏᴏᴜʀ ᴏʟᴅ ᴛʜᴜᴍʙɴᴀɪʟ. 62 | ➲ /view_thumb: ᴜꜱᴇ ᴛʜɪꜱ ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ ᴠɪᴇᴡ ʏᴏᴜʀ ᴄᴜʀʀᴇɴᴛ ᴛʜᴜᴍʙɴᴀɪʟ. 63 | 64 | ɴᴏᴛᴇ: ɪꜰ ɴᴏ ᴛʜᴜᴍʙɴᴀɪʟ ꜱᴀᴠᴇᴅ ɪɴ ʙᴏᴛ ᴛʜᴇɴ, ɪᴛ ᴡɪʟʟ ᴜꜱᴇ ᴛʜᴜᴍʙɴᴀɪʟ ᴏꜰ ᴛʜᴇ ᴏʀɪɢɪɴɪᴀʟ ꜰɪʟᴇ ᴛᴏ ꜱᴇᴛ ɪɴ ʀᴇɴᴀᴍᴇᴅ ꜰɪʟᴇ""" 65 | 66 | CAPTION_TXT = """» ᴛᴏ ꜱᴇᴛ ᴄᴜꜱᴛᴏᴍ ᴄᴀᴘᴛɪᴏɴ ᴀɴᴅ ᴍᴇᴅɪᴀ ᴛʏᴘᴇ 67 | 68 | ᴠᴀʀɪᴀʙʟᴇꜱ : 69 | ꜱɪᴢᴇ: {ꜰɪʟᴇꜱɪᴢᴇ} 70 | ᴅᴜʀᴀᴛɪᴏɴ: {duration} 71 | ꜰɪʟᴇɴᴀᴍᴇ: {ꜰɪʟᴇɴᴀᴍᴇ} 72 | 73 | ➲ /set_caption: ᴛᴏ ꜱᴇᴛ ᴀ ᴄᴜꜱᴛᴏᴍ ᴄᴀᴘᴛɪᴏɴ. 74 | ➲ /see_caption: ᴛᴏ ᴠɪᴇᴡ ʏᴏᴜʀ ᴄᴜꜱᴛᴏᴍ ᴄᴀᴘᴛɪᴏɴ. 75 | ➲ /del_caption: ᴛᴏ ᴅᴇʟᴇᴛᴇ ʏᴏᴜʀ ᴄᴜꜱᴛᴏᴍ ᴄᴀᴘᴛɪᴏɴ. 76 | 77 | » ꜰᴏʀ ᴇx:- /set_caption ꜰɪʟᴇ ɴᴀᴍᴇ: {ꜰɪʟᴇɴᴀᴍᴇ}""" 78 | 79 | PROGRESS_BAR = """\n 80 | » Size : {1} | {2} 81 | » Done : {0}% 82 | » Speed : {3}/s 83 | » ETA : {4} """ 84 | 85 | 86 | DONATE_TXT = """
ᴛʜᴀɴᴋs ғᴏʀ sʜᴏᴡɪɴɢ ɪɴᴛᴇʀᴇsᴛ ɪɴ ᴅᴏɴᴀᴛɪᴏɴ
87 | 88 | 💞 ɪꜰ ʏᴏᴜ ʟɪᴋᴇ ᴏᴜʀ ʙᴏᴛ ꜰᴇᴇʟ ꜰʀᴇᴇ ᴛᴏ ᴅᴏɴᴀᴛᴇ ᴀɴʏ ᴀᴍᴏᴜɴᴛ ₹𝟷𝟶, ₹𝟸𝟶, ₹𝟻𝟶, ₹𝟷𝟶𝟶, ᴇᴛᴄ. 89 | 90 | ᴅᴏɴᴀᴛɪᴏɴs ᴀʀᴇ ʀᴇᴀʟʟʏ ᴀᴘᴘʀᴇᴄɪᴀᴛᴇᴅ ɪᴛ ʜᴇʟᴘs ɪɴ ʙᴏᴛ ᴅᴇᴠᴇʟᴏᴘᴍᴇɴᴛ 91 | 92 | ʏᴏᴜ ᴄᴀɴ ᴀʟsᴏ ᴅᴏɴᴀᴛᴇ ᴛʜʀᴏᴜɢʜ ᴜᴘɪ 93 | 94 | ᴜᴘɪ ɪᴅ : LodaLassan@fam 95 | 96 | ɪғ ʏᴏᴜ ᴡɪsʜ ʏᴏᴜ ᴄᴀɴ sᴇɴᴅ ᴜs ss 97 | ᴏɴ - @ProYato""" 98 | 99 | PREMIUM_TXT = """ᴜᴘɢʀᴀᴅᴇ ᴛᴏ ᴏᴜʀ ᴘʀᴇᴍɪᴜᴍ sᴇʀᴠɪᴄᴇ ᴀɴᴅ ᴇɴJᴏʏ ᴇxᴄʟᴜsɪᴠᴇ ғᴇᴀᴛᴜʀᴇs: 100 | ○ ᴜɴʟɪᴍɪᴛᴇᴅ Rᴇɴᴀᴍɪɴɢ: ʀᴇɴᴀᴍᴇ ᴀs ᴍᴀɴʏ ғɪʟᴇs ᴀs ʏᴏᴜ ᴡᴀɴᴛ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ʀᴇsᴛʀɪᴄᴛɪᴏɴs. 101 | ○ ᴇᴀʀʟʏ Aᴄᴄᴇss: ʙᴇ ᴛʜᴇ ғɪʀsᴛ ᴛᴏ ᴛᴇsᴛ ᴀɴᴅ ᴜsᴇ ᴏᴜʀ ʟᴀᴛᴇsᴛ ғᴇᴀᴛᴜʀᴇs ʙᴇғᴏʀᴇ ᴀɴʏᴏɴᴇ ᴇʟsᴇ. 102 | 103 | • ᴜꜱᴇ /plan ᴛᴏ ꜱᴇᴇ ᴀʟʟ ᴏᴜʀ ᴘʟᴀɴꜱ ᴀᴛ ᴏɴᴄᴇ. 104 | 105 | ➲ ғɪʀsᴛ sᴛᴇᴘ : ᴘᴀʏ ᴛʜᴇ ᴀᴍᴏᴜɴᴛ ᴀᴄᴄᴏʀᴅɪɴɢ ᴛᴏ ʏᴏᴜʀ ғᴀᴠᴏʀɪᴛᴇ ᴘʟᴀɴ ᴛᴏ ᴛʜɪs rohit162@fam ᴜᴘɪ ɪᴅ. 106 | 107 | ➲ secoɴᴅ sᴛᴇᴘ : ᴛᴀᴋᴇ ᴀ sᴄʀᴇᴇɴsʜᴏᴛ ᴏғ ʏᴏᴜʀ ᴘᴀʏᴍᴇɴᴛ ᴀɴᴅ sʜᴀʀᴇ ɪᴛ ᴅɪʀᴇᴄᴛʟʏ ʜᴇʀᴇ: @sewxiy 108 | 109 | ➲ ᴀʟᴛᴇʀɴᴀᴛɪᴠᴇ sᴛᴇᴘ : ᴏʀ ᴜᴘʟᴏᴀᴅ ᴛʜᴇ sᴄʀᴇᴇɴsʜᴏᴛ ʜᴇʀᴇ ᴀɴᴅ ʀᴇᴘʟʏ ᴡɪᴛʜ ᴛʜᴇ /bought ᴄᴏᴍᴍᴀɴᴅ. 110 | 111 | Yᴏᴜʀ ᴘʀᴇᴍɪᴜᴍ ᴘʟᴀɴ ᴡɪʟʟ ʙᴇ ᴀᴄᴛɪᴠᴀᴛᴇᴅ ᴀғᴛᴇʀ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴ""" 112 | 113 | PREPLANS_TXT = """👋 bro, 114 | 115 | 🎖️ ᴀᴠᴀɪʟᴀʙʟᴇ ᴘʟᴀɴs : 116 | 117 | Pʀɪᴄɪɴɢ: 118 | ➜ ᴍᴏɴᴛʜʟʏ ᴘʀᴇᴍɪᴜᴍ: ₹50/ᴍᴏɴᴛʜ 119 | ➜ ᴅᴀɪʟʏ ᴘʀᴇᴍɪᴜᴍ: ₹𝟻/ᴅᴀʏ 120 | ➜ ғᴏʀ ʙᴏᴛ ʜᴏsᴛɪɴɢ: ᴄᴏɴᴛᴀᴄᴛ @ProYato 121 | 122 | ➲ ᴜᴘɪ ɪᴅ - LodaLassan@fam 123 | 124 | ‼️ᴜᴘʟᴏᴀᴅ ᴛʜᴇ ᴘᴀʏᴍᴇɴᴛ sᴄʀᴇᴇɴsʜᴏᴛ ʜᴇʀᴇ ᴀɴᴅ ʀᴇᴘʟʏ ᴡɪᴛʜ ᴛʜᴇ /bought ᴄᴏᴍᴍᴀɴᴅ.""" 125 | 126 | HELP_TXT = """ʜᴇʀᴇ ɪꜱ ʜᴇʟᴘ ᴍᴇɴᴜ ɪᴍᴘᴏʀᴛᴀɴᴛ ᴄᴏᴍᴍᴀɴᴅꜱ: 127 | 128 | ᴀᴡᴇsᴏᴍᴇ ғᴇᴀᴛᴜʀᴇs🫧 129 | 130 | ʀᴇɴᴀᴍᴇ ʙᴏᴛ ɪꜱ ᴀ ʜᴀɴᴅʏ ᴛᴏᴏʟ ᴛʜᴀᴛ ʜᴇʟᴘꜱ ʏᴏᴜ ʀᴇɴᴀᴍᴇ ᴀɴᴅ ᴍᴀɴᴀɢᴇ ʏᴏᴜʀ ꜰɪʟᴇꜱ ᴇꜰꜰᴏʀᴛʟᴇꜱꜱʟʏ. 131 | 132 | ➲ /Autorename: ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ʏᴏᴜʀ ꜰɪʟᴇꜱ. 133 | ➲ /Metadata: ᴄᴏᴍᴍᴀɴᴅꜱ ᴛᴏ ᴛᴜʀɴ ᴏɴ ᴏғғ ᴍᴇᴛᴀᴅᴀᴛᴀ. 134 | ➲ /Help: ɢᴇᴛ ǫᴜɪᴄᴋ ᴀꜱꜱɪꜱᴛᴀɴᴄᴇ.""" 135 | 136 | SEND_METADATA = """ 137 | --Metadata Settings:-- 138 | 139 | ➜ /metadata: Turn on or off metadata. 140 | 141 | Description : Metadata will change MKV video files including all audio, streams, and subtitle titles.""" 142 | 143 | 144 | SOURCE_TXT = """ 145 | ʜᴇʏ, 146 | ᴛʜɪs ɪs ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ʙᴏᴛ, 147 | ᴀɴ ᴏᴩᴇɴ sᴏᴜʀᴄᴇ ᴛᴇʟᴇɢʀᴀᴍ ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ʙᴏᴛ. 148 | 149 | ᴡʀɪᴛᴛᴇɴ ɪɴ ᴩʏᴛʜᴏɴ ᴡɪᴛʜ ᴛʜᴇ ʜᴇʟᴩ ᴏғ : 150 | [ᴩʏʀᴏɢʀᴀᴍ](https://github.com/pyrogram/pyrogram) 151 | [ᴩʏᴛʜᴏɴ-ᴛᴇʟᴇɢʀᴀᴍ-ʙᴏᴛ](https://github.com/python-telegram-bot/python-telegram-bot) 152 | ᴀɴᴅ ᴜsɪɴɢ [ᴍᴏɴɢᴏ](https://cloud.mongodb.com) ᴀs ᴅᴀᴛᴀʙᴀsᴇ. 153 | 154 | 155 | ʜᴇʀᴇ ɪs ᴍʏ sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ : [ɢɪᴛʜᴜʙ](https://github.com/codeflix_bots/autorenamebot) 156 | 157 | 158 | ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ʙᴏᴛ ɪs ʟɪᴄᴇɴsᴇᴅ ᴜɴᴅᴇʀ ᴛʜᴇ [ᴍɪᴛ ʟɪᴄᴇɴsᴇ](https://github.com/codeflix_bots/autorenamebot/blob/main/LICENSE). 159 | © 2024 | [sᴜᴘᴘᴏʀᴛ ᴄʜᴀᴛ](https://t.me/codeflixsupport), ᴀʟʟ ʀɪɢʜᴛs ʀᴇsᴇʀᴠᴇᴅ.""" 160 | 161 | META_TXT = """ 162 | **ᴍᴀɴᴀɢɪɴɢ ᴍᴇᴛᴀᴅᴀᴛᴀ ғᴏʀ ʏᴏᴜʀ ᴠɪᴅᴇᴏs ᴀɴᴅ ғɪʟᴇs** 163 | 164 | **ᴠᴀʀɪᴏᴜꜱ ᴍᴇᴛᴀᴅᴀᴛᴀ:** 165 | 166 | - **ᴛɪᴛʟᴇ**: Descriptive title of the media. 167 | - **ᴀᴜᴛʜᴏʀ**: The creator or owner of the media. 168 | - **ᴀʀᴛɪꜱᴛ**: The artist associated with the media. 169 | - **ᴀᴜᴅɪᴏ**: Title or description of audio content. 170 | - **ꜱᴜʙᴛɪᴛʟᴇ**: Title of subtitle content. 171 | - **ᴠɪᴅᴇᴏ**: Title or description of video content. 172 | 173 | **ᴄᴏᴍᴍᴀɴᴅꜱ ᴛᴏ ᴛᴜʀɴ ᴏɴ ᴏғғ ᴍᴇᴛᴀᴅᴀᴛᴀ:** 174 | ➜ /metadata: Turn on or off metadata. 175 | 176 | **ᴄᴏᴍᴍᴀɴᴅꜱ ᴛᴏ ꜱᴇᴛ ᴍᴇᴛᴀᴅᴀᴛᴀ:** 177 | 178 | ➜ /settitle: Set a custom title of media. 179 | ➜ /setauthor: Set the author. 180 | ➜ /setartist: Set the artist. 181 | ➜ /setaudio: Set audio title. 182 | ➜ /setsubtitle: Set subtitle title. 183 | ➜ /setvideo: Set video title. 184 | 185 | **ᴇxᴀᴍᴘʟᴇ:** /settitle Your Title Here 186 | 187 | **ᴜꜱᴇ ᴛʜᴇꜱᴇ ᴄᴏᴍᴍᴀɴᴅꜱ ᴛᴏ ᴇɴʀɪᴄʜ ʏᴏᴜʀ ᴍᴇᴅɪᴀ ᴡɪᴛʜ ᴀᴅᴅɪᴛɪᴏɴᴀʟ ᴍᴇᴛᴀᴅᴀᴛᴀ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ!** 188 | """ 189 | -------------------------------------------------------------------------------- /helper/database.py: -------------------------------------------------------------------------------- 1 | import motor.motor_asyncio, datetime, pytz 2 | from config import Config 3 | import logging # Added for logging errors and important information 4 | from .utils import send_log 5 | 6 | 7 | class Database: 8 | def __init__(self, uri, database_name): 9 | try: 10 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri) 11 | self._client.server_info() # This will raise an exception if the connection fails 12 | logging.info("Successfully connected to MongoDB") 13 | except Exception as e: 14 | logging.error(f"Failed to connect to MongoDB: {e}") 15 | raise e # Re-raise the exception after logging it 16 | self.codeflixbots = self._client[database_name] 17 | self.col = self.codeflixbots.user 18 | 19 | def new_user(self, id): 20 | return dict( 21 | _id=int(id), 22 | join_date=datetime.date.today().isoformat(), 23 | file_id=None, 24 | caption=None, 25 | metadata=True, 26 | metadata_code="Telegram : @Codeflix_Bots", 27 | format_template=None, 28 | ban_status=dict( 29 | is_banned=False, 30 | ban_duration=0, 31 | banned_on=datetime.date.max.isoformat(), 32 | ban_reason='' 33 | ) 34 | ) 35 | 36 | async def add_user(self, b, m): 37 | u = m.from_user 38 | if not await self.is_user_exist(u.id): 39 | user = self.new_user(u.id) 40 | try: 41 | await self.col.insert_one(user) 42 | await send_log(b, u) 43 | except Exception as e: 44 | logging.error(f"Error adding user {u.id}: {e}") 45 | 46 | async def is_user_exist(self, id): 47 | try: 48 | user = await self.col.find_one({"_id": int(id)}) 49 | return bool(user) 50 | except Exception as e: 51 | logging.error(f"Error checking if user {id} exists: {e}") 52 | return False 53 | 54 | async def total_users_count(self): 55 | try: 56 | count = await self.col.count_documents({}) 57 | return count 58 | except Exception as e: 59 | logging.error(f"Error counting users: {e}") 60 | return 0 61 | 62 | async def get_all_users(self): 63 | try: 64 | all_users = self.col.find({}) 65 | return all_users 66 | except Exception as e: 67 | logging.error(f"Error getting all users: {e}") 68 | return None 69 | 70 | async def delete_user(self, user_id): 71 | try: 72 | await self.col.delete_many({"_id": int(user_id)}) 73 | except Exception as e: 74 | logging.error(f"Error deleting user {user_id}: {e}") 75 | 76 | async def set_thumbnail(self, id, file_id): 77 | try: 78 | await self.col.update_one({"_id": int(id)}, {"$set": {"file_id": file_id}}) 79 | except Exception as e: 80 | logging.error(f"Error setting thumbnail for user {id}: {e}") 81 | 82 | async def get_thumbnail(self, id): 83 | try: 84 | user = await self.col.find_one({"_id": int(id)}) 85 | return user.get("file_id", None) if user else None 86 | except Exception as e: 87 | logging.error(f"Error getting thumbnail for user {id}: {e}") 88 | return None 89 | 90 | async def set_caption(self, id, caption): 91 | try: 92 | await self.col.update_one({"_id": int(id)}, {"$set": {"caption": caption}}) 93 | except Exception as e: 94 | logging.error(f"Error setting caption for user {id}: {e}") 95 | 96 | async def get_caption(self, id): 97 | try: 98 | user = await self.col.find_one({"_id": int(id)}) 99 | return user.get("caption", None) if user else None 100 | except Exception as e: 101 | logging.error(f"Error getting caption for user {id}: {e}") 102 | return None 103 | 104 | async def set_format_template(self, id, format_template): 105 | try: 106 | await self.col.update_one( 107 | {"_id": int(id)}, {"$set": {"format_template": format_template}} 108 | ) 109 | except Exception as e: 110 | logging.error(f"Error setting format template for user {id}: {e}") 111 | 112 | async def get_format_template(self, id): 113 | try: 114 | user = await self.col.find_one({"_id": int(id)}) 115 | return user.get("format_template", None) if user else None 116 | except Exception as e: 117 | logging.error(f"Error getting format template for user {id}: {e}") 118 | return None 119 | 120 | async def set_media_preference(self, id, media_type): 121 | try: 122 | await self.col.update_one( 123 | {"_id": int(id)}, {"$set": {"media_type": media_type}} 124 | ) 125 | except Exception as e: 126 | logging.error(f"Error setting media preference for user {id}: {e}") 127 | 128 | async def get_media_preference(self, id): 129 | try: 130 | user = await self.col.find_one({"_id": int(id)}) 131 | return user.get("media_type", None) if user else None 132 | except Exception as e: 133 | logging.error(f"Error getting media preference for user {id}: {e}") 134 | return None 135 | 136 | async def get_metadata(self, user_id): 137 | user = await self.col.find_one({'_id': int(user_id)}) 138 | return user.get('metadata', "Off") 139 | 140 | async def set_metadata(self, user_id, metadata): 141 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'metadata': metadata}}) 142 | 143 | async def get_title(self, user_id): 144 | user = await self.col.find_one({'_id': int(user_id)}) 145 | return user.get('title', 'Encoded by @Animes_Cruise') 146 | 147 | async def set_title(self, user_id, title): 148 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'title': title}}) 149 | 150 | async def get_author(self, user_id): 151 | user = await self.col.find_one({'_id': int(user_id)}) 152 | return user.get('author', '@Animes_Cruise') 153 | 154 | async def set_author(self, user_id, author): 155 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'author': author}}) 156 | 157 | async def get_artist(self, user_id): 158 | user = await self.col.find_one({'_id': int(user_id)}) 159 | return user.get('artist', '@Animes_Cruise') 160 | 161 | async def set_artist(self, user_id, artist): 162 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'artist': artist}}) 163 | 164 | async def get_audio(self, user_id): 165 | user = await self.col.find_one({'_id': int(user_id)}) 166 | return user.get('audio', 'By @Animes_Cruise') 167 | 168 | async def set_audio(self, user_id, audio): 169 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'audio': audio}}) 170 | 171 | async def get_subtitle(self, user_id): 172 | user = await self.col.find_one({'_id': int(user_id)}) 173 | return user.get('subtitle', "By @Animes_Cruise") 174 | 175 | async def set_subtitle(self, user_id, subtitle): 176 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'subtitle': subtitle}}) 177 | 178 | async def get_video(self, user_id): 179 | user = await self.col.find_one({'_id': int(user_id)}) 180 | return user.get('video', 'Encoded By @Animes_Cruise') 181 | 182 | async def set_video(self, user_id, video): 183 | await self.col.update_one({'_id': int(user_id)}, {'$set': {'video': video}}) 184 | 185 | 186 | codeflixbots = Database(Config.DB_URL, Config.DB_NAME) 187 | -------------------------------------------------------------------------------- /plugins/file_rename.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import time 4 | import shutil 5 | import asyncio 6 | import logging 7 | from datetime import datetime 8 | from PIL import Image 9 | from pyrogram import Client, filters 10 | from pyrogram.errors import FloodWait 11 | from pyrogram.types import InputMediaDocument, Message 12 | from hachoir.metadata import extractMetadata 13 | from hachoir.parser import createParser 14 | from plugins.antinsfw import check_anti_nsfw 15 | from helper.utils import progress_for_pyrogram, humanbytes, convert 16 | from helper.database import codeflixbots 17 | from config import Config 18 | 19 | # Configure logging 20 | logging.basicConfig( 21 | level=logging.INFO, 22 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' 23 | ) 24 | logger = logging.getLogger(__name__) 25 | 26 | # Global dictionary to track ongoing operations 27 | renaming_operations = {} 28 | 29 | # Enhanced regex patterns for season and episode extraction 30 | SEASON_EPISODE_PATTERNS = [ 31 | # Standard patterns (S01E02, S01EP02) 32 | (re.compile(r'S(\d+)(?:E|EP)(\d+)'), ('season', 'episode')), 33 | # Patterns with spaces/dashes (S01 E02, S01-EP02) 34 | (re.compile(r'S(\d+)[\s-]*(?:E|EP)(\d+)'), ('season', 'episode')), 35 | # Full text patterns (Season 1 Episode 2) 36 | (re.compile(r'Season\s*(\d+)\s*Episode\s*(\d+)', re.IGNORECASE), ('season', 'episode')), 37 | # Patterns with brackets/parentheses ([S01][E02]) 38 | (re.compile(r'\[S(\d+)\]\[E(\d+)\]'), ('season', 'episode')), 39 | # Fallback patterns (S01 13, Episode 13) 40 | (re.compile(r'S(\d+)[^\d]*(\d+)'), ('season', 'episode')), 41 | (re.compile(r'(?:E|EP|Episode)\s*(\d+)', re.IGNORECASE), (None, 'episode')), 42 | # Final fallback (standalone number) 43 | (re.compile(r'\b(\d+)\b'), (None, 'episode')) 44 | ] 45 | 46 | # Quality detection patterns 47 | QUALITY_PATTERNS = [ 48 | (re.compile(r'\b(\d{3,4}[pi])\b', re.IGNORECASE), lambda m: m.group(1)), # 1080p, 720p 49 | (re.compile(r'\b(4k|2160p)\b', re.IGNORECASE), lambda m: "4k"), 50 | (re.compile(r'\b(2k|1440p)\b', re.IGNORECASE), lambda m: "2k"), 51 | (re.compile(r'\b(HDRip|HDTV)\b', re.IGNORECASE), lambda m: m.group(1)), 52 | (re.compile(r'\b(4kX264|4kx265)\b', re.IGNORECASE), lambda m: m.group(1)), 53 | (re.compile(r'\[(\d{3,4}[pi])\]', re.IGNORECASE), lambda m: m.group(1)) # [1080p] 54 | ] 55 | 56 | def extract_season_episode(filename): 57 | """Extract season and episode numbers from filename""" 58 | for pattern, (season_group, episode_group) in SEASON_EPISODE_PATTERNS: 59 | match = pattern.search(filename) 60 | if match: 61 | season = match.group(1) if season_group else None 62 | episode = match.group(2) if episode_group else match.group(1) 63 | logger.info(f"Extracted season: {season}, episode: {episode} from {filename}") 64 | return season, episode 65 | logger.warning(f"No season/episode pattern matched for {filename}") 66 | return None, None 67 | 68 | def extract_quality(filename): 69 | """Extract quality information from filename""" 70 | for pattern, extractor in QUALITY_PATTERNS: 71 | match = pattern.search(filename) 72 | if match: 73 | quality = extractor(match) 74 | logger.info(f"Extracted quality: {quality} from {filename}") 75 | return quality 76 | logger.warning(f"No quality pattern matched for {filename}") 77 | return "Unknown" 78 | 79 | async def cleanup_files(*paths): 80 | """Safely remove files if they exist""" 81 | for path in paths: 82 | try: 83 | if path and os.path.exists(path): 84 | os.remove(path) 85 | except Exception as e: 86 | logger.error(f"Error removing {path}: {e}") 87 | 88 | async def process_thumbnail(thumb_path): 89 | """Process and resize thumbnail image""" 90 | if not thumb_path or not os.path.exists(thumb_path): 91 | return None 92 | 93 | try: 94 | with Image.open(thumb_path) as img: 95 | img = img.convert("RGB").resize((320, 320)) 96 | img.save(thumb_path, "JPEG") 97 | return thumb_path 98 | except Exception as e: 99 | logger.error(f"Thumbnail processing failed: {e}") 100 | await cleanup_files(thumb_path) 101 | return None 102 | 103 | async def add_metadata(input_path, output_path, user_id): 104 | """Add metadata to media file using ffmpeg""" 105 | ffmpeg = shutil.which('ffmpeg') 106 | if not ffmpeg: 107 | raise RuntimeError("FFmpeg not found in PATH") 108 | 109 | metadata = { 110 | 'title': await codeflixbots.get_title(user_id), 111 | 'artist': await codeflixbots.get_artist(user_id), 112 | 'author': await codeflixbots.get_author(user_id), 113 | 'video_title': await codeflixbots.get_video(user_id), 114 | 'audio_title': await codeflixbots.get_audio(user_id), 115 | 'subtitle': await codeflixbots.get_subtitle(user_id) 116 | } 117 | 118 | cmd = [ 119 | ffmpeg, 120 | '-i', input_path, 121 | '-metadata', f'title={metadata["title"]}', 122 | '-metadata', f'artist={metadata["artist"]}', 123 | '-metadata', f'author={metadata["author"]}', 124 | '-metadata:s:v', f'title={metadata["video_title"]}', 125 | '-metadata:s:a', f'title={metadata["audio_title"]}', 126 | '-metadata:s:s', f'title={metadata["subtitle"]}', 127 | '-map', '0', 128 | '-c', 'copy', 129 | '-loglevel', 'error', 130 | output_path 131 | ] 132 | 133 | process = await asyncio.create_subprocess_exec( 134 | *cmd, 135 | stdout=asyncio.subprocess.PIPE, 136 | stderr=asyncio.subprocess.PIPE 137 | ) 138 | _, stderr = await process.communicate() 139 | 140 | if process.returncode != 0: 141 | raise RuntimeError(f"FFmpeg error: {stderr.decode()}") 142 | 143 | @Client.on_message(filters.private & (filters.document | filters.video | filters.audio)) 144 | async def auto_rename_files(client, message): 145 | """Main handler for auto-renaming files""" 146 | user_id = message.from_user.id 147 | format_template = await codeflixbots.get_format_template(user_id) 148 | 149 | if not format_template: 150 | return await message.reply_text("Please set a rename format using /autorename") 151 | 152 | # Get file information 153 | if message.document: 154 | file_id = message.document.file_id 155 | file_name = message.document.file_name 156 | file_size = message.document.file_size 157 | media_type = "document" 158 | elif message.video: 159 | file_id = message.video.file_id 160 | file_name = message.video.file_name or "video" 161 | file_size = message.video.file_size 162 | media_type = "video" 163 | elif message.audio: 164 | file_id = message.audio.file_id 165 | file_name = message.audio.file_name or "audio" 166 | file_size = message.audio.file_size 167 | media_type = "audio" 168 | else: 169 | return await message.reply_text("Unsupported file type") 170 | 171 | # NSFW check 172 | if await check_anti_nsfw(file_name, message): 173 | return await message.reply_text("NSFW content detected") 174 | 175 | # Prevent duplicate processing 176 | if file_id in renaming_operations: 177 | if (datetime.now() - renaming_operations[file_id]).seconds < 10: 178 | return 179 | renaming_operations[file_id] = datetime.now() 180 | 181 | try: 182 | # Extract metadata from filename 183 | season, episode = extract_season_episode(file_name) 184 | quality = extract_quality(file_name) 185 | 186 | # Replace placeholders in template 187 | replacements = { 188 | '{season}': season or 'XX', 189 | '{episode}': episode or 'XX', 190 | '{quality}': quality, 191 | 'Season': season or 'XX', 192 | 'Episode': episode or 'XX', 193 | 'QUALITY': quality 194 | } 195 | 196 | for placeholder, value in replacements.items(): 197 | format_template = format_template.replace(placeholder, value) 198 | 199 | # Prepare file paths 200 | ext = os.path.splitext(file_name)[1] or ('.mp4' if media_type == 'video' else '.mp3') 201 | new_filename = f"{format_template}{ext}" 202 | download_path = f"downloads/{new_filename}" 203 | metadata_path = f"metadata/{new_filename}" 204 | 205 | os.makedirs(os.path.dirname(download_path), exist_ok=True) 206 | os.makedirs(os.path.dirname(metadata_path), exist_ok=True) 207 | 208 | # Download file 209 | msg = await message.reply_text("**Downloading...**") 210 | try: 211 | file_path = await client.download_media( 212 | message, 213 | file_name=download_path, 214 | progress=progress_for_pyrogram, 215 | progress_args=("Downloading...", msg, time.time()) 216 | ) 217 | except Exception as e: 218 | await msg.edit(f"Download failed: {e}") 219 | raise 220 | 221 | # Process metadata 222 | await msg.edit("**Processing metadata...**") 223 | try: 224 | await add_metadata(file_path, metadata_path, user_id) 225 | file_path = metadata_path 226 | except Exception as e: 227 | await msg.edit(f"Metadata processing failed: {e}") 228 | raise 229 | 230 | # Prepare for upload 231 | await msg.edit("**Preparing upload...**") 232 | caption = await codeflixbots.get_caption(message.chat.id) or f"**{new_filename}**" 233 | thumb = await codeflixbots.get_thumbnail(message.chat.id) 234 | thumb_path = None 235 | 236 | # Handle thumbnail 237 | if thumb: 238 | thumb_path = await client.download_media(thumb) 239 | elif media_type == "video" and message.video.thumbs: 240 | thumb_path = await client.download_media(message.video.thumbs[0].file_id) 241 | 242 | thumb_path = await process_thumbnail(thumb_path) 243 | 244 | # Upload file 245 | await msg.edit("**Uploading...**") 246 | try: 247 | upload_params = { 248 | 'chat_id': message.chat.id, 249 | 'caption': caption, 250 | 'thumb': thumb_path, 251 | 'progress': progress_for_pyrogram, 252 | 'progress_args': ("Uploading...", msg, time.time()) 253 | } 254 | 255 | if media_type == "document": 256 | await client.send_document(document=file_path, **upload_params) 257 | elif media_type == "video": 258 | await client.send_video(video=file_path, **upload_params) 259 | elif media_type == "audio": 260 | await client.send_audio(audio=file_path, **upload_params) 261 | 262 | await msg.delete() 263 | except Exception as e: 264 | await msg.edit(f"Upload failed: {e}") 265 | raise 266 | 267 | except Exception as e: 268 | logger.error(f"Processing error: {e}") 269 | await message.reply_text(f"Error: {str(e)}") 270 | finally: 271 | # Clean up files 272 | await cleanup_files(download_path, metadata_path, thumb_path) 273 | renaming_operations.pop(file_id, None) 274 | -------------------------------------------------------------------------------- /plugins/start_&_cb.py: -------------------------------------------------------------------------------- 1 | import random 2 | import asyncio 3 | from pyrogram import Client, filters 4 | from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery 5 | 6 | from helper.database import codeflixbots 7 | from config import * 8 | from config import Config 9 | 10 | # Start Command Handler 11 | @Client.on_message(filters.private & filters.command("start")) 12 | async def start(client, message: Message): 13 | user = message.from_user 14 | await codeflixbots.add_user(client, message) 15 | 16 | # Initial interactive text and sticker sequence 17 | m = await message.reply_text("ʜᴇʜᴇ..ɪ'ᴍ ᴀɴʏᴀ!\nᴡᴀɪᴛ ᴀ ᴍᴏᴍᴇɴᴛ. . .") 18 | await asyncio.sleep(0.4) 19 | await m.edit_text("🎊") 20 | await asyncio.sleep(0.5) 21 | await m.edit_text("⚡") 22 | await asyncio.sleep(0.5) 23 | await m.edit_text("ᴡᴀᴋᴜ ᴡᴀᴋᴜ!...") 24 | await asyncio.sleep(0.4) 25 | await m.delete() 26 | 27 | # Send sticker after the text sequence 28 | await message.reply_sticker("CAACAgUAAxkBAAECroBmQKMAAQ-Gw4nibWoj_pJou2vP1a4AAlQIAAIzDxlVkNBkTEb1Lc4eBA") 29 | 30 | # Define buttons for the start message 31 | buttons = InlineKeyboardMarkup([ 32 | [ 33 | InlineKeyboardButton("• ᴍʏ ᴀʟʟ ᴄᴏᴍᴍᴀɴᴅs •", callback_data='help') 34 | ], 35 | [ 36 | InlineKeyboardButton('• ᴜᴘᴅᴀᴛᴇs', url='https://t.me/Codeflix_Bots'), 37 | InlineKeyboardButton('sᴜᴘᴘᴏʀᴛ •', url='https://t.me/CodeflixSupport') 38 | ], 39 | [ 40 | InlineKeyboardButton('• ᴀʙᴏᴜᴛ', callback_data='about'), 41 | InlineKeyboardButton('sᴏᴜʀᴄᴇ •', callback_data='source') 42 | ] 43 | ]) 44 | 45 | # Send start message with or without picture 46 | if Config.START_PIC: 47 | await message.reply_photo( 48 | Config.START_PIC, 49 | caption=Txt.START_TXT.format(user.mention), 50 | reply_markup=buttons 51 | ) 52 | else: 53 | await message.reply_text( 54 | text=Txt.START_TXT.format(user.mention), 55 | reply_markup=buttons, 56 | disable_web_page_preview=True 57 | ) 58 | 59 | 60 | # Callback Query Handler 61 | @Client.on_callback_query() 62 | async def cb_handler(client, query: CallbackQuery): 63 | data = query.data 64 | user_id = query.from_user.id 65 | 66 | print(f"Callback data received: {data}") # Debugging line 67 | 68 | if data == "home": 69 | await query.message.edit_text( 70 | text=Txt.START_TXT.format(query.from_user.mention), 71 | disable_web_page_preview=True, 72 | reply_markup=InlineKeyboardMarkup([ 73 | [InlineKeyboardButton("• ᴍʏ ᴀʟʟ ᴄᴏᴍᴍᴀɴᴅs •", callback_data='help')], 74 | [InlineKeyboardButton('• ᴜᴘᴅᴀᴛᴇs', url='https://t.me/Codeflix_Bots'), InlineKeyboardButton('sᴜᴘᴘᴏʀᴛ •', url='https://t.me/CodeflixSupport')], 75 | [InlineKeyboardButton('• ᴀʙᴏᴜᴛ', callback_data='about'), InlineKeyboardButton('sᴏᴜʀᴄᴇ •', callback_data='source')] 76 | ]) 77 | ) 78 | elif data == "caption": 79 | await query.message.edit_text( 80 | text=Txt.CAPTION_TXT, 81 | disable_web_page_preview=True, 82 | reply_markup=InlineKeyboardMarkup([ 83 | [InlineKeyboardButton("• sᴜᴘᴘᴏʀᴛ", url='https://t.me/CodeflixSupport'), InlineKeyboardButton("ʙᴀᴄᴋ •", callback_data="help")] 84 | ]) 85 | ) 86 | 87 | elif data == "help": 88 | await query.message.edit_text( 89 | text=Txt.HELP_TXT.format(client.mention), 90 | disable_web_page_preview=True, 91 | reply_markup=InlineKeyboardMarkup([ 92 | [InlineKeyboardButton("• ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ғᴏʀᴍᴀᴛ •", callback_data='file_names')], 93 | [InlineKeyboardButton('• ᴛʜᴜᴍʙɴᴀɪʟ', callback_data='thumbnail'), InlineKeyboardButton('ᴄᴀᴘᴛɪᴏɴ •', callback_data='caption')], 94 | [InlineKeyboardButton('• ᴍᴇᴛᴀᴅᴀᴛᴀ', callback_data='meta'), InlineKeyboardButton('ᴅᴏɴᴀᴛᴇ •', callback_data='donate')], 95 | [InlineKeyboardButton('• ʜᴏᴍᴇ', callback_data='home')] 96 | ]) 97 | ) 98 | 99 | elif data == "meta": 100 | await query.message.edit_text( # Change edit_caption to edit_text 101 | text=Txt.SEND_METADATA, # Changed from caption to text 102 | reply_markup=InlineKeyboardMarkup([ 103 | [InlineKeyboardButton("• ᴄʟᴏsᴇ", callback_data="close"), InlineKeyboardButton("ʙᴀᴄᴋ •", callback_data="help")] 104 | ]) 105 | ) 106 | elif data == "donate": 107 | await query.message.edit_text( 108 | text=Txt.DONATE_TXT, 109 | disable_web_page_preview=True, 110 | reply_markup=InlineKeyboardMarkup([ 111 | [InlineKeyboardButton("• ʙᴀᴄᴋ", callback_data="help"), InlineKeyboardButton("ᴏᴡɴᴇʀ •", url='https://t.me/sewxiy')] 112 | ]) 113 | ) 114 | elif data == "file_names": 115 | format_template = await codeflixbots.get_format_template(user_id) 116 | await query.message.edit_text( 117 | text=Txt.FILE_NAME_TXT.format(format_template=format_template), 118 | disable_web_page_preview=True, 119 | reply_markup=InlineKeyboardMarkup([ 120 | [InlineKeyboardButton("• ᴄʟᴏsᴇ", callback_data="close"), InlineKeyboardButton("ʙᴀᴄᴋ •", callback_data="help")] 121 | ]) 122 | ) 123 | elif data == "thumbnail": 124 | await query.message.edit_caption( 125 | caption=Txt.THUMBNAIL_TXT, 126 | reply_markup=InlineKeyboardMarkup([ 127 | [InlineKeyboardButton("• ᴄʟᴏsᴇ", callback_data="close"), InlineKeyboardButton("ʙᴀᴄᴋ •", callback_data="help")] 128 | ]) 129 | ) 130 | elif data == "metadatax": 131 | await query.message.edit_caption( 132 | caption=Txt.SEND_METADATA, 133 | reply_markup=InlineKeyboardMarkup([ 134 | [InlineKeyboardButton("• ᴄʟᴏsᴇ", callback_data="close"), InlineKeyboardButton("ʙᴀᴄᴋ •", callback_data="help")] 135 | ]) 136 | ) 137 | elif data == "source": 138 | await query.message.edit_caption( 139 | caption=Txt.SOURCE_TXT, 140 | reply_markup=InlineKeyboardMarkup([ 141 | [InlineKeyboardButton("• ᴄʟᴏsᴇ", callback_data="close"), InlineKeyboardButton("ʙᴀᴄᴋ •", callback_data="home")] 142 | ]) 143 | ) 144 | elif data == "premiumx": 145 | await query.message.edit_caption( 146 | caption=Txt.PREMIUM_TXT, 147 | reply_markup=InlineKeyboardMarkup([ 148 | [InlineKeyboardButton("• ʙᴀᴄᴋ", callback_data="help"), InlineKeyboardButton("ʙᴜʏ ᴘʀᴇᴍɪᴜᴍ •", url='https://t.me/sewxiy')] 149 | ]) 150 | ) 151 | elif data == "plans": 152 | await query.message.edit_caption( 153 | caption=Txt.PREPLANS_TXT, 154 | reply_markup=InlineKeyboardMarkup([ 155 | [InlineKeyboardButton("• ᴄʟᴏsᴇ", callback_data="close"), InlineKeyboardButton("ʙᴜʏ ᴘʀᴇᴍɪᴜᴍ •", url='https://t.me/sewxiy')] 156 | ]) 157 | ) 158 | elif data == "about": 159 | await query.message.edit_text( 160 | text=Txt.ABOUT_TXT, 161 | disable_web_page_preview=True, 162 | reply_markup=InlineKeyboardMarkup([ 163 | [InlineKeyboardButton("• sᴜᴘᴘᴏʀᴛ", url='https://t.me/CodeflixSupport'), InlineKeyboardButton("ᴄᴏᴍᴍᴀɴᴅs •", callback_data="help")], 164 | [InlineKeyboardButton("• ᴅᴇᴠᴇʟᴏᴘᴇʀ", url='https://t.me/cosmic_freak'), InlineKeyboardButton("ɴᴇᴛᴡᴏʀᴋ •", url='https://t.me/otakuflix_network')], 165 | [InlineKeyboardButton("• ʙᴀᴄᴋ •", callback_data="home")] 166 | ]) 167 | ) 168 | elif data == "close": 169 | try: 170 | await query.message.delete() 171 | await query.message.reply_to_message.delete() 172 | await query.message.continue_propagation() 173 | except: 174 | await query.message.delete() 175 | await query.message.continue_propagation() 176 | 177 | # Donation Command Handler 178 | @Client.on_message(filters.command("donate")) 179 | async def donation(client, message): 180 | buttons = InlineKeyboardMarkup([ 181 | [InlineKeyboardButton(text="ʙᴀᴄᴋ", callback_data="help"), InlineKeyboardButton(text="ᴏᴡɴᴇʀ", url='https://t.me/sewxiy')] 182 | ]) 183 | yt = await message.reply_photo(photo='https://graph.org/file/1919fe077848bd0783d4c.jpg', caption=Txt.DONATE_TXT, reply_markup=buttons) 184 | await asyncio.sleep(300) 185 | await yt.delete() 186 | await message.delete() 187 | 188 | # Premium Command Handler 189 | @Client.on_message(filters.command("premium")) 190 | async def getpremium(bot, message): 191 | buttons = InlineKeyboardMarkup([ 192 | [InlineKeyboardButton("ᴏᴡɴᴇʀ", url="https://t.me/sewxiy"), InlineKeyboardButton("ᴄʟᴏsᴇ", callback_data="close")] 193 | ]) 194 | yt = await message.reply_photo(photo='https://graph.org/file/feebef43bbdf76e796b1b.jpg', caption=Txt.PREMIUM_TXT, reply_markup=buttons) 195 | await asyncio.sleep(300) 196 | await yt.delete() 197 | await message.delete() 198 | 199 | # Plan Command Handler 200 | @Client.on_message(filters.command("plan")) 201 | async def premium(bot, message): 202 | buttons = InlineKeyboardMarkup([ 203 | [InlineKeyboardButton("sᴇɴᴅ ss", url="https://t.me/sewxiy"), InlineKeyboardButton("ᴄʟᴏsᴇ", callback_data="close")] 204 | ]) 205 | yt = await message.reply_photo(photo='https://graph.org/file/8b50e21db819f296661b7.jpg', caption=Txt.PREPLANS_TXT, reply_markup=buttons) 206 | await asyncio.sleep(300) 207 | await yt.delete() 208 | await message.delete() 209 | 210 | # Bought Command Handler 211 | @Client.on_message(filters.command("bought") & filters.private) 212 | async def bought(client, message): 213 | msg = await message.reply('Wait im checking...') 214 | replied = message.reply_to_message 215 | 216 | if not replied: 217 | await msg.edit("Please reply with the screenshot of your payment for the premium purchase to proceed.\n\nFor example, first upload your screenshot, then reply to it using the '/bought' command") 218 | elif replied.photo: 219 | await client.send_photo( 220 | chat_id=LOG_CHANNEL, 221 | photo=replied.photo.file_id, 222 | caption=f'User - {message.from_user.mention}\nUser id - {message.from_user.id}\nUsername - {message.from_user.username}\nName - {message.from_user.first_name}', 223 | reply_markup=InlineKeyboardMarkup([ 224 | [InlineKeyboardButton("Close", callback_data="close_data")] 225 | ]) 226 | ) 227 | await msg.edit_text('Your screenshot has been sent to Admins') 228 | 229 | @Client.on_message(filters.private & filters.command("help")) 230 | async def help_command(client, message): 231 | # Await get_me to get the bot's user object 232 | bot = await client.get_me() 233 | mention = bot.mention 234 | 235 | # Send the help message with inline buttons 236 | await message.reply_text( 237 | text=Txt.HELP_TXT.format(mention=mention), 238 | disable_web_page_preview=True, 239 | reply_markup=InlineKeyboardMarkup([ 240 | [InlineKeyboardButton("• ᴀᴜᴛᴏ ʀᴇɴᴀᴍᴇ ғᴏʀᴍᴀᴛ •", callback_data='file_names')], 241 | [InlineKeyboardButton('• ᴛʜᴜᴍʙɴᴀɪʟ', callback_data='thumbnail'), InlineKeyboardButton('ᴄᴀᴘᴛɪᴏɴ •', callback_data='caption')], 242 | [InlineKeyboardButton('• ᴍᴇᴛᴀᴅᴀᴛᴀ', callback_data='meta'), InlineKeyboardButton('ᴅᴏɴᴀᴛᴇ •', callback_data='donate')], 243 | [InlineKeyboardButton('• ʜᴏᴍᴇ', callback_data='home')] 244 | ]) 245 | ) 246 | --------------------------------------------------------------------------------