diff --git a/Database/database.py b/Database/database.py index 0e8998f..b43d42c 100644 --- a/Database/database.py +++ b/Database/database.py @@ -218,13 +218,17 @@ async def get_thumbnail(self, user_id): async def delete_thumbnail(self, user_id): await self.files_col.update_one({'id': user_id}, {'$unset': {'thumbnail_file_id': ""}}) - async def save_attach_photo(self, user_id, file_id): - await self.files_col.update_one({'id': user_id}, {'$set': {'attach_photo_file_id': file_id}}, upsert=True) - + async def save_attach_photo(self, user_id, custom_photo_path): + await self.files_col.update_one( + {'id': user_id}, + {'$set': {'attach_photo_file_path': custom_photo_path}}, + upsert=True + ) + async def get_attach_photo(self, user_id): file_data = await self.files_col.find_one({'id': user_id}) if file_data: - return file_data.get('attach_photo_file_id') + return file_data.get('attach_photo_file_path') return None async def save_merge_state(self, user_id, merge_state): diff --git a/Dockerfile b/Dockerfile index 9cd0097..fd7aedd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,10 @@ FROM python:3.10 WORKDIR /app COPY . /app/ +# Install FFmpeg +RUN apt-get update && \ + apt-get install -y ffmpeg +RUN apt -qq update && apt -qq install -y git wget pv jq wget python3-dev ffmpeg mediainfo RUN pip install -r requirements.txt CMD ["python", "bot.py"] - -#TG: @Sunrises_24 +#TG:@Sunrises_24 diff --git a/Procfile b/Procfile index 44511d8..d5776f8 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,2 @@ -web: python bot.py +web: python3 update.py #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 diff --git a/README.md b/README.md index e2a1879..34ec348 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Deploy To Koyeb -[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&repository=github.com/Aluval/MetaMorpher&env[BOT_TOKEN]&env[API_ID]&env[API_HASH]&env[FSUB_UPDATES]&env[FSUB_GROUP]&env[AUTH_USERS]&env[LOG_CHANNEL_ID]&env[WEBHOOK]=True&env[ADMIN]&env[DATABASE_URI]&env[DATABASE_NAME]=Cluster0&env[SUNRISES_PIC]&env[PORT]=8080&run_command=python%20bot.py&branch=SH24BOTS-GD-REVERSION-PVT&name=MetaMorpher) +[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&repository=github.com/Aluval/MetaMorpher&env[BOT_TOKEN]&env[API_ID]&env[API_HASH]&env[FSUB_UPDATES]&env[FSUB_GROUP]&env[AUTH_USERS]&env[LOG_CHANNEL_ID]&env[WEBHOOK]=True&env[ADMIN]&env[DATABASE_URI]&env[DATABASE_NAME]=Cluster0&env[SUNRISES_PIC]&env[PORT]=8080&run_command=python%20bot.py&branch=SH24BOTS-GD-REVERSION-GRP&name=MetaMorpher) ## Deploy To Render @@ -27,7 +27,7 @@ Press Below Button to Deploy! **ADD YOUR TOKEN.PICKLE For Google Drive Access** -**This Branch Only In Bot [Private] Support** +**This Branch Only In Bot [GROUP] Support** **This Bot Is Follows the 2GB Below Files To Telegram. 2GB Above Files To Google Drive.** @@ -43,8 +43,12 @@ Press Below Button to Deploy! - `Extract Audios` - Extract audio from files. - `Extract Subtitles` - Extract subtitles from files. - `Extract Video` - Extract video from files. -- `Change index audio`: Adjusts metadata or index information for audio files. -- `Change Index Subtitles`: Manages and updates index or metadata for subtitle files. +- `Stream Remove` - ๐‘…๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐ด๐‘ข๐‘‘๐‘–๐‘œ๐‘  ๐‘œ๐‘Ÿ ๐‘†๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’๐‘  +- `Multitaskfile` - For File Changemetadata, Rename, Changeindexaudio, Changeindexsub = multitaskfile +- `Multitasklink ` - For link [Workers & Seedr Links] Metadata, Rename, Indexaudio, Indexsub = multitasklink +- `Compress` - compress the file as 480p ,libopus[Anime & Webseries Best] +- `Swap Audio`: Adjusts metadata or index information for audio files." +- `Swap Subtitles`: Manages and updates index or metadata for subtitle files. - `Attach photo attachment.jpg`: Attaches specific photos like attachment.jpg. - `Remove tags in files`: Cleans and removes tags or metadata from files. - `Merge`: Merges files and data [Video + Video]. @@ -72,6 +76,8 @@ Press Below Button to Deploy! * `AUTH_USERS` - for restart owner id +* `GROUP` - group id add and admin it + * `DATABASE_NAME` - Database Name * `DATABASE_URI` - Mongdb Url From mongodb.com. @@ -99,8 +105,12 @@ extractsubtitles - ๐ธ๐‘ฅ๐‘ก๐‘Ÿ๐‘Ž๐‘๐‘ก ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’ extractvideo - ๐ธ๐‘ฅ๐‘ก๐‘Ÿ๐‘Ž๐‘๐‘ก ๐‘ฃ๐‘–๐‘‘๐‘’๐‘œ ๐‘“๐‘Ÿ๐‘œ๐‘š ๐‘“๐‘–๐‘™๐‘’๐‘ . rename - ๐‘Ÿ๐‘’๐‘๐‘™๐‘Ž๐‘ฆ ๐‘ค๐‘–๐‘กโ„Ž ๐‘“๐‘–๐‘™๐‘’ ๐‘ก๐‘œ ๐‘…๐‘’๐‘›๐‘Ž๐‘š๐‘’๐Ÿ“ gofile - ๐‘‡โ„Ž๐‘’ ๐น๐‘–๐‘™๐‘’๐‘  ๐‘ˆ๐‘๐‘™๐‘œ๐‘Ž๐‘‘ ๐‘‡๐‘œ ๐บ๐‘œ๐‘“๐‘–๐‘™๐‘’ ๐ฟ๐‘–๐‘›๐‘˜ ๐Ÿ”— -changeindexaudio - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [a-1 ๐‘“๐‘œ๐‘Ÿ ๐‘Ÿ๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ , a-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ] -changeindexsub - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [s-1 ๐‘“๐‘œ๐‘Ÿ ๐‘Ÿ๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’ , s-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’] +streamremove - ๐‘…๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐ด๐‘ข๐‘‘๐‘–๐‘œ๐‘  ๐‘œ๐‘Ÿ ๐‘†๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’๐‘  +multitaskfile - ๐น๐‘œ๐‘Ÿ ๐น๐‘–๐‘™๐‘’ ๐ถโ„Ž๐‘Ž๐‘›๐‘”๐‘’๐‘š๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž, ๐‘…๐‘’๐‘›๐‘Ž๐‘š๐‘’, ๐ถโ„Ž๐‘Ž๐‘›๐‘”๐‘’๐‘–๐‘›๐‘‘๐‘’๐‘ฅ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ, ๐ถโ„Ž๐‘Ž๐‘›๐‘”๐‘’๐‘–๐‘›๐‘‘๐‘’๐‘ฅ๐‘ ๐‘ข๐‘ = ๐‘š๐‘ข๐‘™๐‘ก๐‘–๐‘ก๐‘Ž๐‘ ๐‘˜๐‘“๐‘–๐‘™๐‘’ +multitasklink - ๐น๐‘œ๐‘Ÿ ๐‘™๐‘–๐‘›๐‘˜ [๐‘Š๐‘œ๐‘Ÿ๐‘˜๐‘’๐‘Ÿ๐‘  & ๐‘†๐‘’๐‘’๐‘‘๐‘Ÿ ๐ฟ๐‘–๐‘›๐‘˜๐‘ ] ๐‘€๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž, ๐‘…๐‘’๐‘›๐‘Ž๐‘š๐‘’, ๐ผ๐‘›๐‘‘๐‘’๐‘ฅ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ, ๐ผ๐‘›๐‘‘๐‘’๐‘ฅ๐‘ ๐‘ข๐‘ = ๐‘š๐‘ข๐‘™๐‘ก๐‘–๐‘ก๐‘Ž๐‘ ๐‘˜๐‘™๐‘–๐‘›๐‘˜ +compress - ๐‘๐‘œ๐‘š๐‘๐‘Ÿ๐‘’๐‘ ๐‘  ๐‘กโ„Ž๐‘’ ๐‘“๐‘–๐‘™๐‘’ ๐‘Ž๐‘  480๐‘ ,๐‘™๐‘–๐‘๐‘œ๐‘๐‘ข๐‘ [๐ด๐‘›๐‘–๐‘š๐‘’ & ๐‘Š๐‘’๐‘๐‘ ๐‘’๐‘Ÿ๐‘–๐‘’๐‘  ๐ต๐‘’๐‘ ๐‘ก] +swapaudio - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [a-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ] +swapsubitles - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [s-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’] changemetadata - ๐‘‡๐‘Ÿ๐‘Ž๐‘›๐‘ ๐‘“๐‘œ๐‘Ÿ๐‘š ๐‘กโ„Ž๐‘’ ๐‘š๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž removetags - ๐‘‡๐‘œ ๐‘…๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐ด๐‘™๐‘™ ๐‘€๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž ๐‘‡๐‘Ž๐‘”๐‘  samplevideo - ๐ถ๐‘Ÿ๐‘’๐‘Ž๐‘ก๐‘’ ๐ด ๐‘†๐‘Ž๐‘š๐‘๐‘™๐‘’ ๐‘‰๐‘–๐‘‘๐‘’๐‘œ ๐ŸŽž๏ธ diff --git a/app.json b/app.json index 86d1c7e..03d0444 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,7 @@ "name": "MetaMorpher", "description": "ADVANCE RENAME BOT WITH THUMBNAIL,CAPTION & HIGH SPEED โšก๏ธ", "logo":"https://graph.org/file/bd91761f6e938e2e6d23a.jpg", - "repository": "https://github.com/Aluval/ADVANCERENAME24BOT", + "repository": "https://github.com/Aluval/MetaMorpher", "keywords": ["Rename-bot", "Telegram", "ADVANCE RENAME 24 BOT"], "env": { "BOT_TOKEN": { @@ -17,13 +17,42 @@ "description": "Your API_HASH from https://my.telegram.org/apps", "required": true }, + "DATABASE_URI": { + "description": "mongoDB URI. Get this value from https://www.mongodb.com. For more help watch this video - https://youtu.be/dsuTn4qV2GA", + "value": "", + "required": true + }, + "DATABASE_NAME": { + "description": "Name of the database in mongoDB. For more contact to admin", + "value": "Cluster0", + "required": false + }, + "LOG_CHANNEL_ID": { + "description": "Add to bot & admin the bot in channel", + "value": "", + "required": true + }, + "WEBHOOK": { + "description": "web true only", + "value": "True", + "required": true + }, + "PORT": { + "description": "8080", + "value": "8080", + "required": true + }, "FSUB_UPDATES": { "description": "forcesub username channel and admin it", "required": true }, "FSUB_GROUP": { "description": "forcesub username group and admin it", - "required": true + "required": true + }, + "GROUP": { + "description": "Group id", + "required": true }, "SUNRISES_PIC": { "description": "Start Pic", diff --git a/bot.py b/bot.py index 8abc596..e3b4d78 100644 --- a/bot.py +++ b/bot.py @@ -26,7 +26,7 @@ async def start(self): await app.setup() bind_address = "0.0.0.0" await web.TCPSite(app, bind_address, PORT).start() - await self.send_message(LOG_CHANNEL_ID, f"{me.first_name} | @{me.username} ๐š‚๐šƒ๐™ฐ๐š๐šƒ๐™ด๐™ณ...โšก๏ธ") + print(f"{me.first_name} | @{me.username} ๐š‚๐šƒ๐™ฐ๐š๐šƒ๐™ด๐™ณ...โšก๏ธ") diff --git a/config.py b/config.py index ee9a818..89df2fc 100644 --- a/config.py +++ b/config.py @@ -6,18 +6,20 @@ id_pattern = re.compile(r'^.\d+$') -API_ID = int(os.environ.get("API_ID", "10811400")) -API_HASH = os.environ.get("API_HASH", "191bf5ae7a6c39771e7b13cf4ffd1279") -BOT_TOKEN = os.environ.get("BOT_TOKEN", "6487202001:AAHvkz9vPGnVX_QpIPr-YvOJvHMBARepPyY") -ADMIN = int(os.environ.get("ADMIN", '6469754522')) +API_ID = os.environ.get("API_ID", "20577207") +API_HASH = os.environ.get("API_HASH", "40b5e72e7b9607c2e5563fff5c7b0a37") +BOT_TOKEN = os.environ.get("BOT_TOKEN", "7565764530:AAGCGRi2p23_QX86Vcm4vUIm3t85PIxMTyk") +ADMIN = int(os.environ.get("ADMIN", '2041855080')) FSUB_UPDATES = os.environ.get("FSUB_CHANNEL", "Sunrises24BotUpdates") FSUB_GROUP = os.environ.get("FSUB_GROUP", "Sunrises24BotSupport") -DATABASE_URI = os.environ.get("DATABASE_URI", "mongodb+srv://UPLOADXPRO24BOT:UPLOADXPRO24BOT@cluster0.hjfk60f.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0") +DATABASE_URI = os.environ.get("DATABASE_URI", "mongodb+srv://krishnajha2034:8905563700@cluster0.flb9u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0") DATABASE_NAME = os.environ.get("DATABASE_NAME", "Cluster0") CAPTION = os.environ.get("CAPTION", "") +group = environ.get('GROUP', '-1002425543008) +GROUP = int(group) if group and id_pattern.search(group) else None #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 SUNRISES_PIC= "https://graph.org/file/bd91761f6e938e2e6d23a.jpg" # Replace with your Telegraph link -AUTH_USERS = int(os.environ.get("AUTH_USERS", '6469754522')) +AUTH_USERS = int(os.environ.get("AUTH_USERS", '7906265673')) WEBHOOK = bool(os.environ.get("WEBHOOK", True)) PORT = int(os.environ.get("PORT", "8080")) -LOG_CHANNEL_ID = os.environ.get("LOG_CHANNEL_ID", -1002145984196) +LOG_CHANNEL_ID = os.environ.get("LOG_CHANNEL_ID", -1002237472046) diff --git a/main/ffmpeg.py b/main/ffmpeg.py index 8eff959..3eb6ba8 100644 --- a/main/ffmpeg.py +++ b/main/ffmpeg.py @@ -283,3 +283,56 @@ def get_mediainfo(file_path): if process.returncode != 0: raise Exception(f"Error getting media info: {stderr.decode().strip()}") return stdout.decode().strip() + +# Function to compress Ffmpeg information using compress command +def compress_video(input_path, output_path, video_title, audio_title, subtitle_title): + command = [ + 'ffmpeg', + '-hide_banner', + '-loglevel', 'quiet', + '-i', input_path, + '-c:v', 'libx264', + '-crf', '28', + '-pix_fmt', 'yuv420p', + '-s', '854x480', + '-b:v', '150k', + '-c:a', 'libopus', + '-b:a', '35k', + '-preset', 'veryfast', + '-map', '0:v:0', # Map the first video stream + '-map', '0:a', # Map all audio streams + '-map', '0:s?', # Map all subtitle streams if present + '-metadata', f'title={video_title}', + '-metadata:s:v:0', f'title={video_title}', + '-metadata:s:a', f'title={audio_title}', + '-metadata:s:s', f'title={subtitle_title}', + '-y', + output_path + ] + + process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + if process.returncode != 0: + raise Exception(f"FFmpeg error: {stderr.decode('utf-8')}") + +# Function to compress mediainfo information using compress command +async def get_and_upload_mediainfo(bot, output_file, media): + media_info_html = get_mediainfo(output_file) + + media_info_html = ( + f"SUNRISES 24 BOT UPDATES
" + f"MediaInfo X
" + f"{media_info_html}" + f"

Rights Designed By Sแดœษดส€ษชsแด‡s Hแด€ส€sสœแด€ ๐Ÿธ๐Ÿบ ๐Ÿ‡ฎ๐Ÿ‡ณ แต€แดฑแดธ

" + ) + + response = telegraph.post( + title="MediaInfo", + author="SUNRISES 24 BOT UPDATES", + author_url="https://t.me/Sunrises24BotUpdates", + text=media_info_html + ) + link = f"https://graph.org/{response['path']}" + + return media_info_html, link + diff --git a/main/gdrive.py b/main/gdrive.py index 27de243..f26be4e 100644 --- a/main/gdrive.py +++ b/main/gdrive.py @@ -52,6 +52,23 @@ async def upload_to_google_drive(file_path, file_name, sts): return response.get('webViewLink') +#Driveleech +def extract_id_from_driveurl(url): + file_id = None + # Match the different URL patterns for Google Drive links + patterns = [ + r'id=([a-zA-Z0-9-_]+)', # Format 1: ?id=FILE_ID + r'/d/([a-zA-Z0-9-_]+)', # Format 2: /d/FILE_ID/ + r'/file/d/([a-zA-Z0-9-_]+)' # Format 3: /file/d/FILE_ID/ + ] + + for pattern in patterns: + match = re.search(pattern, url) + if match: + file_id = match.group(1) + break + + return file_id #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 diff --git a/main/rename.py b/main/rename.py index 09e5c90..c692964 100644 --- a/main/rename.py +++ b/main/rename.py @@ -1,7 +1,7 @@ -#TG : @Sunrises_24 +#TG :@Sunrises_24 #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 import subprocess -import os +import os, json import time import shutil import zipfile @@ -14,12 +14,12 @@ from pyrogram.errors import MessageNotModified from main.utils import progress_message, humanbytes from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup,CallbackQuery -from config import AUTH_USERS, ADMIN, CAPTION -from main.utils import heroku_restart, upload_files, download_media +from config import AUTH_USERS, ADMIN, CAPTION, GROUP +from main.utils import heroku_restart, upload_files, download_media, download_file_from_drive import aiohttp from pyrogram.errors import RPCError, FloodWait import asyncio -from main.ffmpeg import remove_all_tags, change_video_metadata, generate_sample_video, add_photo_attachment, merge_videos, unzip_file, extract_audio_stream, extract_subtitle_stream, extract_video_stream, extract_audios_from_file, extract_subtitles_from_file, extract_video_from_file, get_mediainfo +from main.ffmpeg import remove_all_tags, change_video_metadata, generate_sample_video, add_photo_attachment, merge_videos, unzip_file, extract_audio_stream, extract_subtitle_stream, extract_video_stream, extract_audios_from_file, extract_subtitles_from_file, extract_video_from_file, get_mediainfo, compress_video, get_and_upload_mediainfo from googleapiclient.http import MediaFileUpload from main.gdrive import upload_to_google_drive, extract_id_from_url, copy_file, get_files_in_folder, drive_service from googleapiclient.errors import HttpError @@ -30,6 +30,19 @@ from pymongo.errors import PyMongoError from yt_dlp import YoutubeDL from html_telegraph_poster import TelegraphPoster +from os import execl as osexecl +from sys import executable +from config import * +import logging + +logging.basicConfig( + filename='SunrisesBot.txt', + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO +) + +# Example of logging a message +logging.info('Bot started successfully!') # Initialize Telegraph telegraph = TelegraphPoster(use_api=True) @@ -52,7 +65,14 @@ CHANGE_INDEX_ENABLED = True MERGE_ENABLED = True EXTRACT_ENABLED = True +MULTITASK_ENABLED = True +STREAMREMOVE_ENABLED = True +COMPRESS_ENABLED = True +SWAP_INDEX_ENABLED = True +#varibles for streameremove +selected_streams = set() +downloaded = None @@ -62,29 +82,34 @@ async def bot_settings_command(_, msg): await display_bot_settings_inline(msg) - # Inline function to display user settings with inline buttons async def display_bot_settings_inline(msg): - global METADATA_ENABLED, PHOTO_ATTACH_ENABLED, MIRROR_ENABLED, RENAME_ENABLED, REMOVETAGS_ENABLED, CHANGE_INDEX_ENABLED + global METADATA_ENABLED, PHOTO_ATTACH_ENABLED, MIRROR_ENABLED, RENAME_ENABLED, REMOVETAGS_ENABLED, SWAP_INDEX_ENABLED, MULTITASK_ENABLED, STREAMREMOVE_ENABLED, COMPRESS_ENABLED metadata_status = "โœ… Enabled" if METADATA_ENABLED else "โŒ Disabled" photo_attach_status = "โœ… Enabled" if PHOTO_ATTACH_ENABLED else "โŒ Disabled" mirror_status = "โœ… Enabled" if MIRROR_ENABLED else "โŒ Disabled" rename_status = "โœ… Enabled" if RENAME_ENABLED else "โŒ Disabled" removealltags_status = "โœ… Enabled" if REMOVETAGS_ENABLED else "โŒ Disabled" - change_index_status = "โœ… Enabled" if CHANGE_INDEX_ENABLED else "โŒ Disabled" - merge_video_status = "โœ… Enabled" if MERGE_ENABLED else "โŒ Disabled" - + swap_index_status = "โœ… Enabled" if SWAP_INDEX_ENABLED else "โŒ Disabled" + merge_video_status = "โœ… Enabled" if MERGE_ENABLED else "โŒ Disabled" + multitask_status = "โœ… Enabled" if MULTITASK_ENABLED else "โŒ Disabled" + streamremove_status = "โœ… Enabled" if STREAMREMOVE_ENABLED else "โŒ Disabled" + compress_status = "โœ… Enabled" if COMPRESS_ENABLED else "โŒ Disabled" + keyboard = InlineKeyboardMarkup( inline_keyboard=[ [InlineKeyboardButton("๐Ÿ’ ", callback_data="sunrises24_bot_updates")], [InlineKeyboardButton(f"{rename_status} Change Rename ๐Ÿ“", callback_data="toggle_rename")], [InlineKeyboardButton(f"{removealltags_status} Remove All Tags ๐Ÿ“›", callback_data="toggle_removealltags")], [InlineKeyboardButton(f"{metadata_status} Change Metadata โ˜„๏ธ", callback_data="toggle_metadata")], - [InlineKeyboardButton(f"{change_index_status} Change Index โ™ป๏ธ", callback_data="toggle_change_index")], + [InlineKeyboardButton(f"{swap_index_status} Swap Index โ™ป๏ธ", callback_data="toggle_swap_index")], [InlineKeyboardButton(f"{merge_video_status} Merge Video ๐ŸŽž๏ธ", callback_data="toggle_merge_video")], [InlineKeyboardButton(f"{photo_attach_status} Attach Photo ๐Ÿ–ผ๏ธ", callback_data="toggle_photo_attach")], - [InlineKeyboardButton(f"{mirror_status} Mirror ๐Ÿ’ฝ", callback_data="toggle_mirror")], + [InlineKeyboardButton(f"{mirror_status} Mirror ๐Ÿ’ฝ", callback_data="toggle_mirror")], + [InlineKeyboardButton(f"{multitask_status} MultiTask โฉ", callback_data="toggle_multitask")], + [InlineKeyboardButton(f"{streamremove_status} Stream Remove ๐Ÿ”Š", callback_data="toggle_streamremove")], + [InlineKeyboardButton(f"{compress_status} Compress ๐Ÿ—œ๏ธ", callback_data="toggle_compress")], [InlineKeyboardButton("Close โŒ", callback_data="del")], [InlineKeyboardButton("๐Ÿ’ ", callback_data="sunrises24_bot_updates")] ] @@ -140,11 +165,11 @@ async def toggle_multitask_callback(_, callback_query): MIRROR_ENABLED = not MIRROR_ENABLED await update_settings_message(callback_query.message) -@Client.on_callback_query(filters.regex("^toggle_change_index$")) -async def toggle_change_index_callback(_, callback_query): - global CHANGE_INDEX_ENABLED +@Client.on_callback_query(filters.regex("^toggle_swap_index$")) +async def toggle_swap_index_callback(_, callback_query): + global SWAP_INDEX_ENABLED - CHANGE_INDEX_ENABLED = not CHANGE_INDEX_ENABLED + SWAP_INDEX_ENABLED = not SWAP_INDEX_ENABLED await update_settings_message(callback_query.message) @Client.on_callback_query(filters.regex("^toggle_merge_video$")) @@ -153,6 +178,27 @@ async def toggle_merge_video_callback(_, callback_query): MERGE_ENABLED = not MERGE_ENABLED await update_settings_message(callback_query.message) + +@Client.on_callback_query(filters.regex("^toggle_multitask$")) +async def toggle_multitask_callback(_, callback_query): + global MULTITASK_ENABLED + + MULTITASK_ENABLED = not MULTITASK_ENABLED + await update_settings_message(callback_query.message) + +@Client.on_callback_query(filters.regex("^toggle_streamremove$")) +async def toggle_streamremove_callback(_, callback_query): + global STREAMREMOVE_ENABLED + + STREAMREMOVE_ENABLED = not STREAMREMOVE_ENABLED + await update_settings_message(callback_query.message) + +@Client.on_callback_query(filters.regex("^toggle_compress$")) +async def toggle_compress_callback(_, callback_query): + global COMPRESS_ENABLED + + COMPRESS_ENABLED = not COMPRESS_ENABLED + await update_settings_message(callback_query.message) # Callback query handler for the "sunrises24_bot_updates" button @Client.on_callback_query(filters.regex("^sunrises24_bot_updates$")) @@ -161,7 +207,7 @@ async def sunrises24_bot_updates_callback(_, callback_query): async def update_settings_message(message): - global METADATA_ENABLED, PHOTO_ATTACH_ENABLED, MIRROR_ENABLED, RENAME_ENABLED, REMOVETAGS_ENABLED, CHANGE_INDEX_ENABLED + global METADATA_ENABLED, PHOTO_ATTACH_ENABLED, MIRROR_ENABLED, RENAME_ENABLED, REMOVETAGS_ENABLED, SWAP_INDEX_ENABLED, MULTITASK_ENABLED, STREAMREMOVE_ENABLED, COMPRESS_ENABLED metadata_status = "โœ… Enabled" if METADATA_ENABLED else "โŒ Disabled" photo_attach_status = "โœ… Enabled" if PHOTO_ATTACH_ENABLED else "โŒ Disabled" @@ -169,8 +215,11 @@ async def update_settings_message(message): rename_status = "โœ… Enabled" if RENAME_ENABLED else "โŒ Disabled" removealltags_status = "โœ… Enabled" if REMOVETAGS_ENABLED else "โŒ Disabled" change_index_status = "โœ… Enabled" if CHANGE_INDEX_ENABLED else "โŒ Disabled" - merge_video_status = "โœ… Enabled" if MERGE_ENABLED else "โŒ Disabled" - + merge_video_status = "โœ… Enabled" if MERGE_ENABLED else "โŒ Disabled" + multitask_status = "โœ… Enabled" if MULTITASK_ENABLED else "โŒ Disabled" + streamremove_status = "โœ… Enabled" if STREAMREMOVE_ENABLED else "โŒ Disabled" + compress_status = "โœ… Enabled" if COMPRESS_ENABLED else "โŒ Disabled" + keyboard = InlineKeyboardMarkup( inline_keyboard=[ [InlineKeyboardButton("๐Ÿ’ ", callback_data="sunrises24_bot_updates")], @@ -180,7 +229,10 @@ async def update_settings_message(message): [InlineKeyboardButton(f"{change_index_status} Change Index โ™ป๏ธ", callback_data="toggle_change_index")], [InlineKeyboardButton(f"{merge_video_status} Merge Video ๐ŸŽž๏ธ", callback_data="toggle_merge_video")], [InlineKeyboardButton(f"{photo_attach_status} Attach Photo ๐Ÿ–ผ๏ธ", callback_data="toggle_photo_attach")], - [InlineKeyboardButton(f"{multitask_status} Mirror ๐Ÿ’ฝ", callback_data="toggle_mirror")], + [InlineKeyboardButton(f"{mirror_status} Mirror ๐Ÿ’ฝ", callback_data="toggle_mirror")], + [InlineKeyboardButton(f"{multitask_status} MultiTask โฉ", callback_data="toggle_multitask")], + [InlineKeyboardButton(f"{streamremove_status} Stream Remove ๐Ÿ”Š", callback_data="toggle_streamremove")], + [InlineKeyboardButton(f"{compress_status} Compress ๐Ÿ—œ๏ธ", callback_data="toggle_compress")], [InlineKeyboardButton("Close โŒ", callback_data="del")], [InlineKeyboardButton("๐Ÿ’ ", callback_data="sunrises24_bot_updates")] ] @@ -225,7 +277,7 @@ async def sample_video_option(client, callback_query: CallbackQuery): async def back_to_settings(client, callback_query: CallbackQuery): await display_user_settings(client, callback_query.message, edit=True) -@Client.on_message(filters.private & filters.command("usersettings")) +@Client.on_message(filters.command("usersettings") & filters.chat(GROUP)) async def display_user_settings(client, msg, edit=False): user_id = msg.from_user.id @@ -302,12 +354,26 @@ async def set_photo(bot, msg): if not reply or not reply.photo: return await msg.reply_text("Please reply to a photo with the setphoto command") + # Extract custom name from the command + if len(msg.command) < 2: + return await msg.reply_text("Please provide a custom name for the photo.") + + custom_name = msg.command[1] # The custom name is the second part of the command user_id = msg.from_user.id photo_file_id = reply.photo.file_id try: - await db.save_attach_photo(user_id, photo_file_id) - await msg.reply_text("Photo saved successfully.") + # Download the photo file + photo_path = await bot.download_media(photo_file_id) + + # Save the photo with the custom name + custom_photo_path = f"{custom_name}.jpg" + os.rename(photo_path, custom_photo_path) + + # Save the custom photo path to the database + await db.save_attach_photo(user_id, custom_photo_path) + await msg.reply_text(f"Photo saved successfully with the name: {custom_name}.jpg") + except Exception as e: await msg.reply_text(f"Error saving photo: {e}") @@ -339,7 +405,7 @@ async def inline_thumbnail_settings(client, callback_query: CallbackQuery): ) await callback_query.message.edit_text("Thumbnail Settings:", reply_markup=keyboard) -@Client.on_message(filters.private & filters.command("setthumbnail")) +@Client.on_message(filters.command("setthumbnail") & filters.chat(GROUP)) async def set_thumbnail_command(client, message): user_id = message.from_user.id @@ -350,7 +416,7 @@ async def set_thumbnail_command(client, message): else: await message.reply("Send a photo to set as your permanent thumbnail.") -@Client.on_message(filters.photo & filters.private) +@Client.on_message(filters.photo & filters.chat(GROUP)) async def set_thumbnail_handler(client, message): user_id = message.from_user.id photo_file_id = message.photo.file_id @@ -402,8 +468,7 @@ async def inline_preview_gdrive(bot, callback_query): await callback_query.message.reply_text(f"Current Google Drive Folder ID for user `{user_id}`: {gdrive_folder_id}") - -@Client.on_message(filters.private & filters.command("setmetadata")) +@Client.on_message(filters.command("setmetadata") & filters.chat(GROUP)) async def set_metadata_command(client, msg): # Extract titles from the command message if len(msg.command) < 2: @@ -481,11 +546,8 @@ async def inline_preview_gofile_api_key(bot, callback_query): - - - # Command handler for /mirror -@Client.on_message(filters.private & filters.command("mirror")) +@Client.on_message(filters.command("mirror") & filters.chat(GROUP)) async def mirror_to_google_drive(bot, msg: Message): global MIRROR_ENABLED @@ -564,8 +626,15 @@ async def mirror_to_google_drive(bot, msg: Message): #Rename Command -@Client.on_message(filters.private & filters.command("rename")) +@Client.on_message(filters.command("rename") & filters.chat(GROUP)) async def rename_file(bot, msg): + global RENAME_ENABLED + + if not RENAME_ENABLED: + return await msg.reply_text("Rename feature is currently disabled.") + + user_id = msg.from_user.id + if len(msg.command) < 2 or not msg.reply_to_message: return await msg.reply_text("Please reply to a file, video, or audio with the new filename and extension (e.g., .mkv, .mp4, .zip).") @@ -619,7 +688,7 @@ async def rename_file(bot, msg): await sts.delete() #Change Metadata Code -@Client.on_message(filters.private & filters.command("changemetadata")) +@Client.on_message(filters.command("changemetadata") & filters.chat(GROUP)) async def change_metadata(bot, msg: Message): global METADATA_ENABLED @@ -719,7 +788,8 @@ async def change_metadata(bot, msg: Message): #attach photo -@Client.on_message(filters.private & filters.command("attachphoto")) + +@Client.on_message(filters.command("attachphoto") & filters.chat(GROUP)) async def attach_photo(bot, msg: Message): global PHOTO_ATTACH_ENABLED @@ -756,18 +826,24 @@ async def attach_photo(bot, msg: Message): return # Retrieve attachment from the database - attachment_file_id = await db.get_attach_photo(msg.from_user.id) - if not attachment_file_id: + attachment_file_path = await db.get_attach_photo(msg.from_user.id) + if not attachment_file_path: await safe_edit_message(sts, "Please send a photo to be attached using the `setphoto` command.") os.remove(downloaded) return - attachment_path = await bot.download_media(attachment_file_id) + # Ensure the attachment exists and download it if necessary + attachment_path = attachment_file_path + if not os.path.exists(attachment_path): + await safe_edit_message(sts, "Attachment not found.") + os.remove(downloaded) + return output_file = output_filename await safe_edit_message(sts, "๐Ÿ’  Adding photo attachment... โšก") try: + # Function to add photo attachment (assume it's defined elsewhere) add_photo_attachment(downloaded, attachment_path, output_file) except Exception as e: await safe_edit_message(sts, f"Error adding photo attachment: {e}") @@ -796,6 +872,7 @@ async def attach_photo(bot, msg: Message): try: # Upload to Google Drive if file size exceeds the limit if filesize > FILE_SIZE_LIMIT: + # Function to upload to Google Drive (assume it's defined elsewhere) file_link = await upload_to_google_drive(output_file, os.path.basename(output_file), sts) button = [[InlineKeyboardButton("โ˜๏ธ CloudUrl โ˜๏ธ", url=f"{file_link}")]] await msg.reply_text( @@ -839,22 +916,21 @@ async def attach_photo(bot, msg: Message): - # Command handler # Command handler for changing audio index -@Client.on_message(filters.private & filters.command("changeindexaudio")) -async def change_index_audio(bot, msg): - global CHANGE_INDEX_ENABLED +@Client.on_message(filters.command("swapaudio") & filters.chat(GROUP)) +async def swap_audios(bot, msg): + global SWAP_INDEX_ENABLED - if not CHANGE_INDEX_ENABLED: - return await msg.reply_text("The changeindexaudio feature is currently disabled.") + if not SWAP_INDEX_ENABLED: + return await msg.reply_text("The swap audio index feature is currently disabled.") reply = msg.reply_to_message if not reply: - return await msg.reply_text("Please reply to a media file with the index command\nFormat: `/changeindexaudio a-3 -n filename.mkv` (Audio)") + return await msg.reply_text("Please reply to a media file with the index command\nFormat: `/swapaudio a-3-1-2-4 -n filename.mkv` (Audio)") if len(msg.command) < 3: - return await msg.reply_text("Please provide the index command with a filename\nFormat: `/changeindexaudio a-3 -n filename.mkv` (Audio)") + return await msg.reply_text("Please provide the index command with a filename\nFormat: `/swapaudio a-3-1-2-4 -n filename.mkv` (Audio)") index_cmd = None output_filename = None @@ -871,7 +947,7 @@ async def change_index_audio(bot, msg): return await msg.reply_text("Please provide a filename using the `-n` flag.") if not index_cmd or not index_cmd.startswith("a-"): - return await msg.reply_text("Invalid format. Use `/changeindexaudio a-3 -n filename.mkv` for audio.") + return await msg.reply_text("Invalid format. Use `/swapaudio a-3-1-2-4 -n filename.mkv` for audio.") media = reply.document or reply.audio or reply.video if not media: @@ -894,7 +970,7 @@ async def change_index_audio(bot, msg): indexes = [int(i) - 1 for i in index_params[1:]] # Construct the FFmpeg command to modify indexes - ffmpeg_cmd = ['ffmpeg', '-i', downloaded] + ffmpeg_cmd = ['ffmpeg', '-i', downloaded, '-map', '0:v'] # Always map video stream for idx in indexes: ffmpeg_cmd.extend(['-map', f'0:{stream_type}:{idx}']) @@ -904,7 +980,7 @@ async def change_index_audio(bot, msg): ffmpeg_cmd.extend(['-c', 'copy', output_file, '-y']) - await sts.edit("๐Ÿ’  Changing audio indexing... โšก") + await sts.edit("๐Ÿ’  Swaping audio indexing... โšก") process = await asyncio.create_subprocess_exec(*ffmpeg_cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) stdout, stderr = await process.communicate() @@ -949,6 +1025,7 @@ async def change_index_audio(bot, msg): await bot.send_document( msg.chat.id, document=output_file, + file_name=output_filename, # Apply the new file name here thumb=file_thumb, caption=cap, progress=progress_message, @@ -964,23 +1041,22 @@ async def change_index_audio(bot, msg): os.remove(file_thumb) await sts.delete() - #changeindex subtitles # Command to change index subtitle # Command handler for changing subtitle index -@Client.on_message(filters.private & filters.command("changeindexsub")) -async def change_index_subtitle(bot, msg): - global CHANGE_INDEX_ENABLED +@Client.on_message(filters.command("swapsubtitles") & filters.chat(GROUP)) +async def swap_subtitle(bot, msg): + global SWAP_INDEX_ENABLED - if not CHANGE_INDEX_ENABLED: - return await msg.reply_text("The changeindexsub feature is currently disabled.") + if not SWAP_INDEX_ENABLED: + return await msg.reply_text("The swap index subtitles feature is currently disabled.") reply = msg.reply_to_message if not reply: - return await msg.reply_text("Please reply to a media file with the index command\nFormat: `/changeindexsub s-3 -n filename.mkv` (Subtitle)") + return await msg.reply_text("Please reply to a media file with the index command\nFormat: `/swapsubtitles s-2-3-1 -n filename.mkv` (Subtitle)") if len(msg.command) < 3: - return await msg.reply_text("Please provide the index command with a filename\nFormat: `/changeindexsub s-3 -n filename.mkv` (Subtitle)") + return await msg.reply_text("Please provide the index command with a filename\nFormat: `/swapsubtitles s-2-3-1 -n filename.mkv` (Subtitle)") index_cmd = None output_filename = None @@ -997,7 +1073,7 @@ async def change_index_subtitle(bot, msg): return await msg.reply_text("Please provide a filename using the `-n` flag.") if not index_cmd or not index_cmd.startswith("s-"): - return await msg.reply_text("Invalid format. Use `/changeindexsub s-3 -n filename.mkv` for subtitles.") + return await msg.reply_text("Invalid format. Use `/swapsubtitles s-2-3-1 -n filename.mkv` for subtitles.") media = reply.document or reply.audio or reply.video if not media: @@ -1028,7 +1104,7 @@ async def change_index_subtitle(bot, msg): # Copy all audio and video streams ffmpeg_cmd.extend(['-map', '0:v?', '-map', '0:a?', '-c', 'copy', output_file, '-y']) - await safe_edit_message(sts, "๐Ÿ’  Changing subtitle indexing... โšก") + await safe_edit_message(sts, "๐Ÿ’  Swap subtitle indexing... โšก") process = await asyncio.create_subprocess_exec(*ffmpeg_cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) stdout, stderr = await process.communicate() @@ -1068,7 +1144,7 @@ async def change_index_subtitle(bot, msg): ) else: try: - await bot.send_document(msg.chat.id, document=output_file, thumb=file_thumb, caption=cap, progress=progress_message, progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time)) + await bot.send_document(msg.chat.id, document=output_file, file_name=output_filename, thumb=file_thumb, caption=cap, progress=progress_message, progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time)) except Exception as e: return await safe_edit_message(sts, f"Error: {e}") @@ -1082,18 +1158,19 @@ async def change_index_subtitle(bot, msg): #merge command # Command to start merging files -@Client.on_message(filters.private & filters.command("merge")) +# Command to start merging files +@Client.on_message(filters.command("merge") & filters.chat(GROUP)) async def start_merge_command(bot, msg: Message): global MERGE_ENABLED if not MERGE_ENABLED: return await msg.reply_text("The merge feature is currently disabled.") user_id = msg.from_user.id - merge_state[user_id] = {"files": [], "output_filename": None} + merge_state[user_id] = {"files": [], "output_filename": None, "is_merging": False} await msg.reply_text("Send up to 10 video/document files one by one. Once done, send `/videomerge filename`.") -@Client.on_message(filters.private & filters.command("videomerge")) +@Client.on_message(filters.command("videomerge") & filters.chat(GROUP)) async def start_video_merge_command(bot, msg: Message): user_id = msg.from_user.id if user_id not in merge_state or not merge_state[user_id]["files"]: @@ -1101,16 +1178,24 @@ async def start_video_merge_command(bot, msg: Message): output_filename = msg.text.split(' ', 1)[1].strip() # Extract output filename from command merge_state[user_id]["output_filename"] = output_filename + merge_state[user_id]["is_merging"] = True # Set the flag to indicate that merging has started await merge_and_upload(bot, msg) -@Client.on_message(filters.document | filters.video & filters.private) +@Client.on_message(filters.document | filters.video & filters.chat(GROUP)) async def handle_media_files(bot, msg: Message): user_id = msg.from_user.id - if user_id in merge_state and len(merge_state[user_id]["files"]) < 10: - merge_state[user_id]["files"].append(msg) - await msg.reply_text("File received. Send another file or use `/videomerge filename` to start merging.") + if user_id in merge_state: + if merge_state[user_id].get("is_merging"): + await msg.reply_text("Merging process has started. No more files can be added.") + return + if len(merge_state[user_id]["files"]) < 10: + merge_state[user_id]["files"].append(msg) + await msg.reply_text("File received. Send another file or use `/videomerge filename` to start merging.") + else: + await msg.reply_text("You have already sent 10 files. Use `/videomerge filename` to start merging.") + async def merge_and_upload(bot, msg: Message): user_id = msg.from_user.id if user_id not in merge_state: @@ -1205,7 +1290,7 @@ async def merge_and_upload(bot, msg: Message): # Leech command handler -@Client.on_message(filters.command("leech") & filters.chat(AUTH_USERS)) +@Client.on_message(filters.command("leech") & filters.chat(GROUP)) async def linktofile(bot, msg: Message): if len(msg.command) < 2 or not msg.reply_to_message: return await msg.reply_text("Please reply to a file, video, audio, or link with the desired filename and extension (e.g., `.mkv`, `.mp4`, `.zip`).") @@ -1349,7 +1434,7 @@ async def safe_edit_message(message, new_text): print(f"Failed to edit message: {e}") # Command to remove tags from media files -@Client.on_message(filters.private & filters.command("removetags")) +@Client.on_message(filters.command("removetags") & filters.chat(GROUP)) async def remove_tags(bot, msg): global REMOVETAGS_ENABLED if not REMOVETAGS_ENABLED: @@ -1454,7 +1539,7 @@ async def remove_tags(bot, msg): await db.save_new_filename(msg.from_user.id, new_filename) #Screenshots Command -@Client.on_message(filters.private & filters.command("screenshots")) +@Client.on_message(filters.command("screenshots") & filters.chat(GROUP)) async def screenshots_command(client, message: Message): user_id = message.from_user.id @@ -1542,8 +1627,7 @@ async def screenshots_command(client, message: Message): await sts.delete() # Delete the status message after completion - -@Client.on_message(filters.private & filters.command("samplevideo")) +@Client.on_message(filters.command("samplevideo") & filters.chat(GROUP)) async def sample_video(bot, msg): user_id = msg.from_user.id @@ -1607,7 +1691,7 @@ async def sample_video(bot, msg): await sts.delete() # Define restart_app command -@Client.on_message(filters.command("restart") & filters.chat(AUTH_USERS)) +@Client.on_message(filters.command("restartheroku") & filters.chat(AUTH_USERS)) async def restart_app(bot, msg): if not f'{msg.from_user.id}' == f'{int(AUTH_USERS)}': return await msg.reply_text("Only authorized user can restart!") @@ -1622,7 +1706,7 @@ async def restart_app(bot, msg): # Command to unzip a zip file -@Client.on_message(filters.private & filters.command("unzip")) +@Client.on_message(filters.command("unzip") & filters.chat(GROUP)) async def unzip(bot, msg): if not msg.reply_to_message: return await msg.reply_text("Please reply to a zip file to unzip.") @@ -1658,12 +1742,11 @@ async def unzip(bot, msg): os.remove(input_path) shutil.rmtree(extract_path) - -@Client.on_message(filters.command("gofile") & filters.private) +@Client.on_message(filters.command("gofile") & filters.chat(GROUP)) async def gofile_upload(bot, msg: Message): user_id = msg.from_user.id - - # Retrieve the user's Gofile API key from database + + # Retrieve the user's Gofile API key from the database gofile_api_key = await db.get_gofile_api_key(user_id) if not gofile_api_key: @@ -1692,13 +1775,21 @@ async def gofile_upload(bot, msg: Message): try: async with aiohttp.ClientSession() as session: - # Get the server to upload the file - async with session.get("https://api.gofile.io/getServer") as resp: + # Get available servers + async with session.get("https://api.gofile.io/servers") as resp: if resp.status != 200: - return await sts.edit(f"Failed to get server. Status code: {resp.status}") + return await sts.edit(f"Failed to get servers. Status code: {resp.status}") data = await resp.json() - server = data["data"]["server"] + servers = data.get("data", {}).get("servers", []) + if not servers: + return await sts.edit("No servers available.") + + server_name = servers[0].get("name") # Use the server name + if not server_name: + return await sts.edit("Server name is missing.") + + upload_url = f"https://{server_name}.gofile.io/contents/uploadfile" # Download the media file downloaded_file = await bot.download_media( @@ -1712,10 +1803,11 @@ async def gofile_upload(bot, msg: Message): with open(downloaded_file, "rb") as file: form_data = aiohttp.FormData() form_data.add_field("file", file, filename=file_name) - form_data.add_field("token", gofile_api_key) + headers = {"Authorization": f"Bearer {gofile_api_key}"} if gofile_api_key else {} async with session.post( - f"https://{server}.gofile.io/uploadFile", + upload_url, + headers=headers, data=form_data ) as resp: if resp.status != 200: @@ -1740,7 +1832,7 @@ async def gofile_upload(bot, msg: Message): -@Client.on_message(filters.private & filters.command("clone")) +@Client.on_message(filters.command("clone") & filters.chat(GROUP)) async def clone_file(bot, msg: Message): user_id = msg.from_user.id @@ -1793,7 +1885,7 @@ async def safe_edit_message(message, new_text): print(f"Failed to edit message: {e}") #extract audio command -@Client.on_message(filters.command("extractaudios") & filters.private) +@Client.on_message(filters.command("extractaudios") & filters.chat(GROUP)) async def extract_audios(bot, msg): global EXTRACT_ENABLED @@ -1853,7 +1945,7 @@ async def extract_audios(bot, msg): #extract subtitles command -@Client.on_message(filters.command("extractsubtitles") & filters.private) +@Client.on_message(filters.command("extractsubtitles") & filters.chat(GROUP)) async def extract_subtitles(bot, msg): global EXTRACT_ENABLED @@ -1912,7 +2004,7 @@ async def extract_subtitles(bot, msg): os.remove(file) ##extract video command -@Client.on_message(filters.command("extractvideo") & filters.private) +@Client.on_message(filters.command("extractvideo") & filters.chat(GROUP)) async def extract_video(bot, msg: Message): global EXTRACT_ENABLED @@ -1970,7 +2062,7 @@ async def extract_video(bot, msg: Message): os.remove(output_file) # Command handler for /list -@Client.on_message(filters.private & filters.command("list")) +@Client.on_message(filters.command("list") & filters.chat(GROUP)) async def list_files(bot, msg: Message): user_id = msg.from_user.id @@ -2033,7 +2125,7 @@ async def list_files(bot, msg: Message): await sts.edit(f"Error: {e}") #cleam command -@Client.on_message(filters.private & filters.command("clean")) +@Client.on_message(filters.command("clean") & filters.chat(GROUP)) async def clean_files(bot, msg: Message): user_id = msg.from_user.id @@ -2099,7 +2191,7 @@ async def hook(d): await safe_edit_message(status_message, "Download finished. ๐Ÿš€") return hook -@Client.on_message(filters.private & filters.command("ytdlleech")) +@Client.on_message(filters.command("ytdlleech") & filters.chat(GROUP)) async def ytdlleech_handler(client: Client, msg: Message): if len(msg.command) < 2: return await msg.reply_text("Please provide a YouTube link.") @@ -2226,8 +2318,7 @@ async def callback_query_handler(client: Client, query): await sts.delete() await query.message.delete() - -@Client.on_message(filters.command("mediainfo") & filters.private) +@Client.on_message(filters.command("mediainfo") & filters.chat(GROUP)) async def mediainfo_handler(client: Client, message: Message): if not message.reply_to_message or (not message.reply_to_message.document and not message.reply_to_message.video): await message.reply_text("Please reply to a document or video to get media info.") @@ -2303,7 +2394,7 @@ async def mediainfo_handler(client: Client, message: Message): # Function to handle "/getmodapk" command -@Client.on_message(filters.private & filters.command("getmodapk")) +@Client.on_message(filters.command("getmodapk") & filters.chat(GROUP)) async def get_mod_apk(bot, msg: Message): if len(msg.command) < 2: return await msg.reply_text("Please provide a URL from getmodsapk.com or gamedva.com.") @@ -2394,8 +2485,7 @@ async def count_users(bot, msg): except Exception as e: await msg.reply_text(f"An error occurred: {e}") - -@Client.on_message(filters.command("stats")) +@Client.on_message(filters.command("stats") & filters.chat(GROUP)) async def stats_command(_, msg): uptime = datetime.datetime.now() - START_TIME uptime_str = str(timedelta(seconds=int(uptime.total_seconds()))) @@ -2508,7 +2598,7 @@ async def about_command(bot, msg): โœฏ Dแด‡แด แด‡สŸแดแด˜แด‡ส€ ๐Ÿง‘๐Ÿปโ€๐Ÿ’ป : ๐’๐”๐๐‘๐ˆ๐’๐„๐’โ„ข โšก โœฏ Uแด˜แด…แด€แด›แด‡s ๐Ÿ“ข : ๐”๐๐ƒ๐€๐“๐„๐’ ๐Ÿ“ข โœฏ Sแดœแด˜แด˜แดส€แด› โœจ : ๐’๐”๐๐๐Ž๐‘๐“ โœจ -โœฏ BแดœษชสŸแด… Sแด›แด€แด›แดœs ๐Ÿ“Š : แด 2.4 [Sแด›แด€ส™สŸแด‡] +โœฏ BแดœษชสŸแด… Sแด›แด€แด›แดœs ๐Ÿ“Š : แด 2.5 [Sแด›แด€ส™สŸแด‡] """ await msg.reply_text(about_text) @@ -2541,8 +2631,12 @@ async def help_command(bot, msg): /gofile - ๐‘‡โ„Ž๐‘’ ๐น๐‘–๐‘™๐‘’๐‘  ๐‘ˆ๐‘๐‘™๐‘œ๐‘Ž๐‘‘ ๐‘‡๐‘œ ๐บ๐‘œ๐‘“๐‘–๐‘™๐‘’ ๐ฟ๐‘–๐‘›๐‘˜ ๐Ÿ”— /mediainfo - ๐‘€๐‘’๐‘‘๐‘–๐‘Ž & ๐‘‰๐‘–๐‘‘๐‘’๐‘œ ๐ผ๐‘›๐‘“๐‘œ๐‘Ÿ๐‘š๐‘Ž๐‘ก๐‘–๐‘œ๐‘› โ„น๏ธ /ytdlleech - ๐ฟ๐‘’๐‘’๐‘โ„Ž ๐‘กโ„Ž๐‘’ ๐‘Œ๐‘œ๐‘ข๐‘ก๐‘ข๐‘๐‘’ ๐ฟ๐‘–๐‘›๐‘˜๐‘  -/changeindexaudio - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [a-1 ๐‘“๐‘œ๐‘Ÿ ๐‘Ÿ๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ , a-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ] -/changeindexsub - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [s-1 ๐‘“๐‘œ๐‘Ÿ ๐‘Ÿ๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’ , s-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’] +/streamremove - ๐‘…๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐ด๐‘ข๐‘‘๐‘–๐‘œ๐‘  ๐‘œ๐‘Ÿ ๐‘†๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’๐‘  +/multitaskfile - ๐น๐‘œ๐‘Ÿ ๐น๐‘–๐‘™๐‘’ ๐ถโ„Ž๐‘Ž๐‘›๐‘”๐‘’๐‘š๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž, ๐‘…๐‘’๐‘›๐‘Ž๐‘š๐‘’, ๐ถโ„Ž๐‘Ž๐‘›๐‘”๐‘’๐‘–๐‘›๐‘‘๐‘’๐‘ฅ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ, ๐ถโ„Ž๐‘Ž๐‘›๐‘”๐‘’๐‘–๐‘›๐‘‘๐‘’๐‘ฅ๐‘ ๐‘ข๐‘ = ๐‘š๐‘ข๐‘™๐‘ก๐‘–๐‘ก๐‘Ž๐‘ ๐‘˜๐‘“๐‘–๐‘™๐‘’ +/multitasklink - ๐น๐‘œ๐‘Ÿ ๐‘™๐‘–๐‘›๐‘˜ [๐‘Š๐‘œ๐‘Ÿ๐‘˜๐‘’๐‘Ÿ๐‘  & ๐‘†๐‘’๐‘’๐‘‘๐‘Ÿ ๐ฟ๐‘–๐‘›๐‘˜๐‘ ] ๐‘€๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž, ๐‘…๐‘’๐‘›๐‘Ž๐‘š๐‘’, ๐ผ๐‘›๐‘‘๐‘’๐‘ฅ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ, ๐ผ๐‘›๐‘‘๐‘’๐‘ฅ๐‘ ๐‘ข๐‘ = ๐‘š๐‘ข๐‘™๐‘ก๐‘–๐‘ก๐‘Ž๐‘ ๐‘˜๐‘™๐‘–๐‘›๐‘˜ +/compress - ๐‘๐‘œ๐‘š๐‘๐‘Ÿ๐‘’๐‘ ๐‘  ๐‘กโ„Ž๐‘’ ๐‘“๐‘–๐‘™๐‘’ ๐‘Ž๐‘  480๐‘ ,๐‘™๐‘–๐‘๐‘œ๐‘๐‘ข๐‘ [๐ด๐‘›๐‘–๐‘š๐‘’ & ๐‘Š๐‘’๐‘๐‘ ๐‘’๐‘Ÿ๐‘–๐‘’๐‘  ๐ต๐‘’๐‘ ๐‘ก] +/swapaudio - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [a-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘Ž๐‘ข๐‘‘๐‘–๐‘œ] +/swapsubitles - ๐‘…๐‘’๐‘œ๐‘Ÿ๐‘‘๐‘’๐‘Ÿ ๐‘กโ„Ž๐‘’ ๐‘ ๐‘’๐‘ž๐‘ข๐‘’๐‘›๐‘๐‘’ [s-2-1-3-4 ๐‘“๐‘œ๐‘Ÿ ๐‘ ๐‘ค๐‘Ž๐‘ ๐‘ ๐‘ข๐‘๐‘ก๐‘–๐‘ก๐‘™๐‘’] /changemetadata - ๐‘‡๐‘Ÿ๐‘Ž๐‘›๐‘ ๐‘“๐‘œ๐‘Ÿ๐‘š ๐‘กโ„Ž๐‘’ ๐‘š๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž /removetags - ๐‘‡๐‘œ ๐‘…๐‘’๐‘š๐‘œ๐‘ฃ๐‘’ ๐ด๐‘™๐‘™ ๐‘€๐‘’๐‘ก๐‘Ž๐‘‘๐‘Ž๐‘ก๐‘Ž ๐‘‡๐‘Ž๐‘”๐‘  /merge - ๐‘†๐‘’๐‘›๐‘‘ ๐‘ข๐‘ ๐‘ก๐‘œ 10 ๐‘ฃ๐‘–๐‘‘๐‘’๐‘œ/๐‘‘๐‘œ๐‘๐‘ข๐‘š๐‘’๐‘›๐‘ก ๐‘“๐‘–๐‘™๐‘’๐‘  ๐‘œ๐‘›๐‘’ ๐‘๐‘ฆ ๐‘œ๐‘›๐‘’. @@ -2567,7 +2661,7 @@ async def help_command(bot, msg): """ await msg.reply_text(help_text) - + #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 #Ping @@ -2579,7 +2673,852 @@ async def ping(bot, msg): time_taken_s = (end_t - start_t) * 1000 await rm.edit(f"Pong!๐Ÿ“\n{time_taken_s:.3f} ms") - +@Client.on_message(filters.command("multitaskfile") & filters.chat(GROUP)) +async def multitask_file(bot, msg: Message): + global MULTITASK_ENABLED + + if not MULTITASK_ENABLED: + return await msg.reply_text("Multi Task feature are currently disabled.") + + user_id = msg.from_user.id + + # Fetch metadata titles from the database + metadata_titles = await db.get_metadata_titles(user_id) + video_title = metadata_titles.get('video_title', '') + audio_title = metadata_titles.get('audio_title', '') + subtitle_title = metadata_titles.get('subtitle_title', '') + + if not any([video_title, audio_title, subtitle_title]): + return await msg.reply_text("Metadata titles are not set. Please set metadata titles using `/setmetadata video_title audio_title subtitle_title`.") + + reply = msg.reply_to_message + if not reply: + return await msg.reply_text("Please reply to a media file with the change command\nFormat: `/change a-2 -m -n filename.mkv`") + + if len(msg.command) < 5 or '-m' not in msg.command or '-n' not in msg.command: + return await msg.reply_text("Please provide the correct format\nFormat: `/change a-2 -m -n filename.mkv`") + + index_cmd = msg.command[1] + metadata_flag_index = msg.command.index('-m') + output_flag_index = msg.command.index('-n') + output_filename = " ".join(msg.command[output_flag_index + 1:]).strip() + + if not output_filename.lower().endswith(('.mkv', '.mp4', '.avi')): + return await msg.reply_text("Invalid file extension. Please use a valid video file extension (e.g., .mkv, .mp4, .avi).") + + media = reply.document or reply.audio or reply.video + if not media: + return await msg.reply_text("Please reply to a valid media file (audio, video, or document) with the change command.") + + sts = await msg.reply_text("๐Ÿš€ Downloading media... โšก") + c_time = time.time() + try: + downloaded = await reply.download(progress=progress_message, progress_args=("๐Ÿš€ Download Started... โšก๏ธ", sts, c_time)) + except Exception as e: + await safe_edit_message(sts, f"Error downloading media: {e}") + return + + # Output file path (temporary file) + intermediate_file = os.path.splitext(downloaded)[0] + "_indexed" + os.path.splitext(downloaded)[1] + + index_params = index_cmd.split('-') + stream_type = index_params[0] + indexes = [int(i) - 1 for i in index_params[1:]] + + # Construct the FFmpeg command to modify indexes + ffmpeg_cmd = ['ffmpeg', '-i', downloaded, '-map', '0:v'] # Always map video stream + + for idx in indexes: + ffmpeg_cmd.extend(['-map', f'0:{stream_type}:{idx}']) + + # Copy all subtitle streams if they exist + ffmpeg_cmd.extend(['-map', '0:s?']) + + ffmpeg_cmd.extend(['-c', 'copy', intermediate_file, '-y']) + + await safe_edit_message(sts, "๐Ÿ’  Changing audio indexing... โšก") + process = await asyncio.create_subprocess_exec(*ffmpeg_cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + stdout, stderr = await process.communicate() + + if process.returncode != 0: + await safe_edit_message(sts, f"โ— FFmpeg error: {stderr.decode('utf-8')}") + os.remove(downloaded) + if os.path.exists(intermediate_file): + os.remove(intermediate_file) + return + + output_file = output_filename + + await safe_edit_message(sts, "๐Ÿ’  Changing metadata... โšก") + try: + change_video_metadata(intermediate_file, video_title, audio_title, subtitle_title, output_file) + except Exception as e: + await safe_edit_message(sts, f"Error changing metadata: {e}") + os.remove(downloaded) + os.remove(intermediate_file) + return + + # Retrieve thumbnail from the database + thumbnail_file_id = await db.get_thumbnail(user_id) + file_thumb = None + if thumbnail_file_id: + try: + file_thumb = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(media, 'thumbs') and media.thumbs: + try: + file_thumb = await bot.download_media(media.thumbs[0].file_id) + except Exception as e: + file_thumb = None + + filesize = os.path.getsize(output_file) + filesize_human = humanbytes(filesize) + cap = f"{output_filename}\n\n๐ŸŒŸ Size: {filesize_human}" + + await safe_edit_message(sts, "๐Ÿ’  Uploading... โšก") + c_time = time.time() + + if filesize > FILE_SIZE_LIMIT: + file_link = await upload_to_google_drive(output_file, output_filename, sts) + button = [[InlineKeyboardButton("โ˜๏ธ CloudUrl โ˜๏ธ", url=f"{file_link}")]] + await msg.reply_text( + f"**File successfully changed audio index and metadata, then uploaded to Google Drive!**\n\n" + f"**Google Drive Link**: [View File]({file_link})\n\n" + f"**Uploaded File**: {output_filename}\n" + f"**Request User:** {msg.from_user.mention}\n\n" + f"**Size**: {filesize_human}", + reply_markup=InlineKeyboardMarkup(button) + ) + else: + try: + await bot.send_document( + msg.chat.id, + document=output_file, + file_name=output_filename, + thumb=file_thumb, + caption=cap, + progress=progress_message, + progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time) + ) + except Exception as e: + return await safe_edit_message(sts, f"Error: {e}") + + os.remove(downloaded) + os.remove(intermediate_file) + os.remove(output_file) + if file_thumb and os.path.exists(file_thumb): + os.remove(file_thumb) + await sts.delete() + +@Client.on_message(filters.command("multitasklink") & filters.chat(GROUP)) +async def changeleech(bot, msg: Message): + if len(msg.command) < 2 or not msg.reply_to_message: + return await msg.reply_text("Please reply to a file, video, audio, or link with the desired filename and extension (e.g., `.mkv`, `.mp4`, `.zip`).Please provide the correct format\nFormat: `/multitasklink a-2 -m -n filename.mkv`") + + reply = msg.reply_to_message + new_name = msg.text.split(" ", 1)[1] + + if not new_name.endswith((".mkv", ".mp4", ".zip")): + return await msg.reply_text("Please specify a filename ending with .mkv, .mp4, or .zip.") + + media = reply.document or reply.audio or reply.video or reply.text + + sts = await msg.reply_text("๐Ÿš€ Downloading... โšก") + c_time = time.time() + + if reply.text and ("seedr" in reply.text or "workers" in reply.text): + await handle_link_download_multi(bot, msg, reply.text, new_name, media, sts, c_time) + else: + if not media: + return await msg.reply_text("Please reply to a valid file, video, audio, or link with the desired filename and extension (e.g., `.mkv`, `.mp4`, `.zip`).") + + try: + downloaded = await reply.download(file_name=new_name, progress=progress_message, progress_args=("๐Ÿš€ Download Started... โšก๏ธ", sts, c_time)) + except RPCError as e: + return await sts.edit(f"Download failed: {e}") + + if not os.path.exists(downloaded): + return await sts.edit("File not found after download. Please check the reply and try again.") + + filesize = humanbytes(os.path.getsize(downloaded)) + + # Change indexing and metadata if required + if len(msg.command) > 2: + await change_metadata_and_index(bot, msg, downloaded, new_name, media, sts, c_time) + + # Thumbnail handling + thumbnail_file_id = await db.get_thumbnail(msg.from_user.id) + og_thumbnail = None + if thumbnail_file_id: + try: + og_thumbnail = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(media, 'thumbs') and media.thumbs: + try: + og_thumbnail = await bot.download_media(media.thumbs[0].file_id) + except Exception: + pass + + await sts.edit("๐Ÿ’  Uploading... โšก") + c_time = time.time() + + if os.path.getsize(downloaded) > FILE_SIZE_LIMIT: + file_link = await upload_to_google_drive(downloaded, new_name, sts) + await msg.reply_text(f"File uploaded to Google Drive!\n\n๐Ÿ“ **File Name:** {new_name}\n๐Ÿ’พ **Size:** {filesize}\n๐Ÿ”— **Link:** {file_link}") + else: + try: + await bot.send_document(msg.chat.id, document=downloaded, thumb=og_thumbnail, caption=new_name, progress=progress_message, progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time)) + except ValueError as e: + return await sts.edit(f"Upload failed: {e}") + except TimeoutError as e: + return await sts.edit(f"Upload timed out: {e}") + + try: + if og_thumbnail and os.path.exists(og_thumbnail): + os.remove(og_thumbnail) + if os.path.exists(downloaded): + os.remove(downloaded) + except Exception as e: + print(f"Error deleting files: {e}") + + await sts.delete() + +async def handle_link_download_multi(bot, msg: Message, link: str, new_name: str, media, sts, c_time): + try: + async with aiohttp.ClientSession() as session: + async with session.get(link) as resp: + if resp.status == 200: + with open(new_name, 'wb') as f: + f.write(await resp.read()) + else: + await sts.edit(f"Failed to download file from link. Status code: {resp.status}") + return + except Exception as e: + await sts.edit(f"Error during download: {e}") + return + + if not os.path.exists(new_name): + await sts.edit("File not found after download. Please check the link and try again.") + return + + filesize = humanbytes(os.path.getsize(new_name)) + + # Change indexing and metadata if required + if len(msg.command) > 2: + await change_metadata_and_index(bot, msg, new_name, new_name, media, sts, c_time) + + # Thumbnail handling + thumbnail_file_id = await db.get_thumbnail(msg.from_user.id) + og_thumbnail = None + if thumbnail_file_id: + try: + og_thumbnail = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(media, 'thumbs') and media.thumbs: + try: + og_thumbnail = await bot.download_media(media.thumbs[0].file_id) + except Exception: + pass + + await sts.edit("๐Ÿ’  Uploading... โšก") + c_time = time.time() + + if os.path.getsize(new_name) > FILE_SIZE_LIMIT: + file_link = await upload_to_google_drive(new_name, new_name, sts) + await msg.reply_text(f"File uploaded to Google Drive!\n\n๐Ÿ“ **File Name:** {new_name}\n๐Ÿ’พ **Size:** {filesize}\n๐Ÿ”— **Link:** {file_link}") + else: + try: + await bot.send_document(msg.chat.id, document=new_name, thumb=og_thumbnail, caption=f"{new_name}\n\n๐ŸŒŸ Size: {filesize}", progress=progress_message, progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time)) + except ValueError as e: + return await sts.edit(f"Upload failed: {e}") + except TimeoutError as e: + return await sts.edit(f"Upload timed out: {e}") + + try: + if og_thumbnail and os.path.exists(og_thumbnail): + os.remove(og_thumbnail) + if os.path.exists(new_name): + os.remove(new_name) + except Exception as e: + print(f"Error deleting files: {e}") + + await sts.delete() + +async def change_metadata_and_index(bot, msg, downloaded, new_name, media, sts, c_time): + global METADATA_ENABLED, CHANGE_INDEX_ENABLED + + if not (METADATA_ENABLED and CHANGE_INDEX_ENABLED): + await msg.reply_text("One or more required features are currently disabled.") + return + + user_id = msg.from_user.id + + # Fetch metadata titles from the database + metadata_titles = await db.get_metadata_titles(user_id) + video_title = metadata_titles.get('video_title', '') + audio_title = metadata_titles.get('audio_title', '') + subtitle_title = metadata_titles.get('subtitle_title', '') + + if not any([video_title, audio_title, subtitle_title]): + await msg.reply_text("Metadata titles are not set. Please set metadata titles using `/setmetadata video_title audio_title subtitle_title`.") + return + + if len(msg.command) < 5 or '-m' not in msg.command or '-n' not in msg.command: + await msg.reply_text("Please provide the correct format\nFormat: `/multitasklink a-2 -m -n filename.mkv`") + return + + index_cmd = msg.command[1] + metadata_flag_index = msg.command.index('-m') + output_flag_index = msg.command.index('-n') + output_filename = " ".join(msg.command[output_flag_index + 1:]).strip() + + if not output_filename.lower().endswith(('.mkv', '.mp4', '.avi')): + await msg.reply_text("Invalid file extension. Please use a valid video file extension (e.g., .mkv, .mp4, .avi).") + return + + # Output file path (temporary file) + intermediate_file = os.path.splitext(downloaded)[0] + "_indexed" + os.path.splitext(downloaded)[1] + + index_params = index_cmd.split('-') + stream_type = index_params[0] + indexes = [int(i) - 1 for i in index_params[1:]] + + # Construct the FFmpeg command to modify indexes + ffmpeg_cmd = ['ffmpeg', '-i', downloaded, '-map', '0:v'] # Always map video stream + + for idx in indexes: + ffmpeg_cmd.extend(['-map', f'0:{stream_type}:{idx}']) + + # Copy all subtitle streams if they exist + ffmpeg_cmd.extend(['-map', '0:s?']) + + ffmpeg_cmd.extend(['-c', 'copy', intermediate_file, '-y']) + + await safe_edit_message(sts, "๐Ÿ’  Changing audio indexing... โšก") + process = await asyncio.create_subprocess_exec(*ffmpeg_cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + stdout, stderr = await process.communicate() + + if process.returncode != 0: + await safe_edit_message(sts, f"โ— FFmpeg error: {stderr.decode('utf-8')}") + os.remove(downloaded) + if os.path.exists(intermediate_file): + os.remove(intermediate_file) + return + + output_file = output_filename + + await safe_edit_message(sts, "๐Ÿ’  Changing metadata... โšก") + try: + change_video_metadata(intermediate_file, video_title, audio_title, subtitle_title, output_file) + except Exception as e: + await safe_edit_message(sts, f"Error changing metadata: {e}") + os.remove(downloaded) + os.remove(intermediate_file) + return + + # Retrieve thumbnail from the database + thumbnail_file_id = await db.get_thumbnail(user_id) + file_thumb = None + if thumbnail_file_id: + try: + file_thumb = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(media, 'thumbs') and media.thumbs: + try: + file_thumb = await bot.download_media(media.thumbs[0].file_id) + except Exception as e: + file_thumb = None + + filesize = os.path.getsize(output_file) + filesize_human = humanbytes(filesize) + cap = f"{output_filename}\n\n๐ŸŒŸ Size: {filesize_human}" + + await safe_edit_message(sts, "๐Ÿ’  Uploading... โšก") + c_time = time.time() + + if filesize > FILE_SIZE_LIMIT: + file_link = await upload_to_google_drive(output_file, output_filename, sts) + button = [[InlineKeyboardButton("โ˜๏ธ CloudUrl โ˜๏ธ", url=f"{file_link}")]] + await msg.reply_text( + f"**File successfully changed audio index and metadata, then uploaded to Google Drive!**\n\n" + f"**Google Drive Link**: [View File]({file_link})\n\n" + f"**Uploaded File**: {output_filename}\n" + f"**Request User:** {msg.from_user.mention}\n\n" + f"**Size**: {filesize_human}", + reply_markup=InlineKeyboardMarkup(button) + ) + else: + try: + await bot.send_document( + msg.chat.id, + document=output_file, + file_name=output_filename, + thumb=file_thumb, + caption=cap, + progress=progress_message, + progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time) + ) + except Exception as e: + return await safe_edit_message(sts, f"Error: {e}") + + os.remove(downloaded) + os.remove(intermediate_file) + os.remove(output_file) + if file_thumb and os.path.exists(file_thumb): + os.remove(file_thumb) + await sts.delete() + +#handler is streamremove +@Client.on_message(filters.command("streamremove") & filters.chat(GROUP)) +async def streamremove(bot, msg): + global STREAMREMOVE_ENABLED + global selected_streams + global downloaded + global output_filename + + if not STREAMREMOVE_ENABLED: + return await msg.reply_text("๐Ÿšซ The streamremove feature is currently disabled.") + + reply = msg.reply_to_message + if not reply: + return await msg.reply_text("โ— Please reply to a media file with the command\nFormat: `/streamremove -n filename.mkv`") + + if len(msg.command) < 3 or msg.command[1] != "-n": + return await msg.reply_text("Please provide the filename with the `-n` flag\nFormat: `/streamremove -n filename.mkv`") + + output_filename = " ".join(msg.command[2:]).strip() + + if not output_filename.lower().endswith(('.mkv', '.mp4', '.avi')): + return await msg.reply_text("Invalid file extension. Please use a valid video file extension (e.g., .mkv, .mp4, .avi).") + + media = reply.document or reply.audio or reply.video + if not media: + return await msg.reply_text("โ— Please reply to a valid media file (audio, video, or document) with the command.") + + sts = await msg.reply_text("๐Ÿš€ Downloading media... โšก") + c_time = time.time() + try: + downloaded = await reply.download(progress=progress_message, progress_args=("๐Ÿš€ Download Started... โšก๏ธ", sts, c_time)) + except Exception as e: + await sts.edit(f"โŒ Error downloading media: {e}") + return + + # Get the available streams + ffprobe_cmd = [ + 'ffprobe', '-v', 'error', '-show_entries', 'stream=index:stream_tags=language:stream=codec_type', '-of', 'json', downloaded + ] + process = await asyncio.create_subprocess_exec(*ffprobe_cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + stdout, stderr = await process.communicate() + + if process.returncode != 0: + await sts.edit(f"โ— FFprobe error: {stderr.decode('utf-8')}") + os.remove(downloaded) + return + + streams = json.loads(stdout.decode('utf-8')).get('streams', []) + audio_video_streams = [] + subtitle_streams = [] + + for stream in streams: + stream_index = stream['index'] + language = stream.get('tags', {}).get('language', 'unknown') + codec_type = stream['codec_type'] + + if codec_type == 'audio': + if language == 'tel': + audio_video_streams.append(f"{stream_index} ๐ŸŽต Telugu Audio") + elif language == 'tam': + audio_video_streams.append(f"{stream_index} ๐ŸŽต Tamil Audio") + elif language == 'hin': + audio_video_streams.append(f"{stream_index} ๐ŸŽต Hindi Audio") + else: + audio_video_streams.append(f"{stream_index} ๐ŸŽต Audio - {language}") + elif codec_type == 'subtitle': + if language == 'eng': + subtitle_streams.append(f"{stream_index} ๐Ÿ“ English Subtitle") + else: + subtitle_streams.append(f"{stream_index} ๐Ÿ“ {language} - Subtitle") + elif codec_type == 'video': + audio_video_streams.append(f"{stream_index} ๐Ÿ“น Video") + + # Build the inline keyboard with available streams + buttons = [] + max_len = max(len(audio_video_streams), len(subtitle_streams)) + for i in range(max_len): + row = [] + if i < len(audio_video_streams): + row.append(InlineKeyboardButton(f"{audio_video_streams[i]}", callback_data=f"toggle_{audio_video_streams[i].split()[0]}")) + if i < len(subtitle_streams): + row.append(InlineKeyboardButton(f"{subtitle_streams[i]}", callback_data=f"toggle_{subtitle_streams[i].split()[0]}")) + buttons.append(row) + + buttons.append([InlineKeyboardButton("๐Ÿ”„ Reverse Selection", callback_data="reverse")]) + buttons.append([InlineKeyboardButton("โŒ Cancel", callback_data="cancel"), InlineKeyboardButton("โœ… Done", callback_data="done")]) + markup = InlineKeyboardMarkup(buttons) + + selected_streams.clear() + start_time = time.time() + message = await sts.edit("Select the streams you want to remove (you have 60 seconds):", reply_markup=markup) + + # Wait for 60 seconds + await asyncio.sleep(60) + + if time.time() - start_time < 60: + # If the user has not interacted within 60 seconds, cancel the process + if message: + await message.edit("๐Ÿ•’ Time's up! Selection process has been canceled.") + await asyncio.sleep(5) # Keep the message visible for a short time before deleting + await message.delete() + if downloaded: + os.remove(downloaded) + + + +@Client.on_callback_query(filters.regex(r'toggle_\d+|done|cancel|reverse')) +async def callback_query_handler(bot, callback_query: CallbackQuery): + global selected_streams + global downloaded + global output_filename + data = callback_query.data + + # Check if the user who initiated the command matches the callback query user + if callback_query.from_user.id != callback_query.message.reply_to_message.from_user.id: + return + + if data == "cancel": + await callback_query.message.delete() + if downloaded: + os.remove(downloaded) + return + + if data == "reverse": + buttons = callback_query.message.reply_markup.inline_keyboard + all_indices = {btn.callback_data.split('_')[1] for row in buttons for btn in row if btn.callback_data.startswith('toggle_')} + selected_streams.symmetric_difference_update(all_indices) + + # Update button text + for row in buttons: + for button in row: + if button.callback_data.startswith("toggle_"): + index = button.callback_data.split('_')[1] + if index in selected_streams: + button.text = f"โœ… {button.text.lstrip('โœ…').strip()}" + else: + button.text = button.text.lstrip('โœ…').strip() + + await callback_query.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(buttons)) + return + + if data == "done": + sts = await callback_query.message.edit_text("๐Ÿ’  Removing selected streams... โšก") + await process_media(bot, callback_query, selected_streams, downloaded, output_filename, sts) + return + + # Toggle selection state + index = data.split('_')[1] + if index in selected_streams: + selected_streams.remove(index) + else: + selected_streams.add(index) + + # Update buttons to reflect selection + buttons = callback_query.message.reply_markup.inline_keyboard + for row in buttons: + for button in row: + if button.callback_data == f"toggle_{index}": + if button.text.startswith("โœ…"): + button.text = button.text[2:] # Remove the checkmark + else: + button.text = f"โœ… {button.text}" # Add the checkmark + break + + await callback_query.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(buttons)) + +# Process media function +async def process_media(bot, callback_query, selected_streams, downloaded, output_filename, sts): + user_id = callback_query.from_user.id + original_message = callback_query.message.reply_to_message + output_file = output_filename + + # Construct FFmpeg command to process media + ffmpeg_cmd = ['ffmpeg', '-i', downloaded, '-map', '0'] + for idx in selected_streams: + ffmpeg_cmd.extend(['-map', f'-0:{idx}']) + ffmpeg_cmd.extend(['-c', 'copy', output_file, '-y']) + + # Execute FFmpeg command + process = await asyncio.create_subprocess_exec( + *ffmpeg_cmd, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + stdout, stderr = await process.communicate() + + if process.returncode != 0: + await safe_edit_message(sts, f"โ— FFmpeg error: {stderr.decode('utf-8')}") + os.remove(downloaded) + if os.path.exists(output_file): + os.remove(output_file) + return + + # Retrieve thumbnail from the database + thumbnail_file_id = await db.get_thumbnail(user_id) + file_thumb = None + if thumbnail_file_id: + try: + file_thumb = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(original_message, 'thumbs') and original_message.thumbs: + try: + file_thumb = await bot.download_media(original_message.thumbs[0].file_id) + except Exception as e: + file_thumb = None + + filesize = os.path.getsize(output_file) + filesize_human = humanbytes(filesize) + cap = f"{output_filename}\n\n๐ŸŒŸ Size: {filesize_human}" + + await safe_edit_message(sts, "๐Ÿ’  Uploading... โšก") + c_time = time.time() + + if filesize > FILE_SIZE_LIMIT: + file_link = await upload_to_google_drive(output_file, output_filename, sts) + button = [[InlineKeyboardButton("โ˜๏ธ CloudUrl โ˜๏ธ", url=file_link)]] + await bot.send_message( + chat_id=user_id, + text=( + f"**File successfully stream removed and uploaded to Google Drive!**\n\n" + f"**Google Drive Link**: [View File]({file_link})\n\n" + f"**Uploaded File**: {output_filename}\n" + f"**Request User:** {callback_query.from_user.mention}\n\n" + f"**Size**: {filesize_human}" + ), + reply_markup=InlineKeyboardMarkup(button) + ) + else: + try: + await bot.send_document( + chat_id=user_id, + document=output_file, + thumb=file_thumb, + caption=cap, + progress=progress_message, + progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time) + ) + except Exception as e: + await safe_edit_message(sts, f"Error: {e}") + + # Send a message to the user after the file is sent to their PM + group_message_text = ( + f"โ”๐Ÿ“ฅ **File Name:** {output_filename}\n" + f"โ” ๐Ÿ’พ **Size:** {filesize_human}\n" + f"โ” โ™ป๏ธ **Mode:** Stream Remove\n" + f"โ”—๐Ÿšน **Request User:** {callback_query.from_user.mention}\n\n" + f"โ„ **File has been sent in Bot PM!**" + ) + await bot.send_message( + chat_id=GROUP, # Send the group message to the user + text=group_message_text + ) + + os.remove(downloaded) + os.remove(output_file) + if file_thumb and os.path.exists(file_thumb): + os.remove(file_thumb) + await sts.delete() + +#handler is Compress +@Client.on_message(filters.command("compress") & filters.chat(GROUP)) +async def compress_media(bot, msg: Message): + global COMPRESS_ENABLED + + if not COMPRESS_ENABLED: + return await msg.reply_text("Compress feature is currently disabled.") + + user_id = msg.from_user.id + + reply = msg.reply_to_message + if not reply: + return await msg.reply_text("Please reply to a media file with the compress command\nFormat: `compress -n output_filename`") + + if len(msg.command) < 3 or msg.command[1] != "-n": + return await msg.reply_text("Please provide the output filename with the `-n` flag\nFormat: `compress -n output_filename`") + + output_filename = " ".join(msg.command[2:]).strip() + + if not output_filename.lower().endswith(('.mkv', '.mp4', '.avi')): + return await msg.reply_text("Invalid file extension. Please use a valid video file extension (e.g., .mkv, .mp4, .avi).") + + media = reply.document or reply.audio or reply.video + if not media: + return await msg.reply_text("Please reply to a valid media file (audio, video, or document) with the compress command.") + + sts = await msg.reply_text("๐Ÿš€ Downloading media... โšก") + c_time = time.time() + try: + downloaded = await reply.download(progress=progress_message, progress_args=("๐Ÿš€ Download Started... โšก๏ธ", sts, c_time)) + except Exception as e: + await safe_edit_message(sts, f"Error downloading media: {e}") + return + + output_file = output_filename + + # Retrieve metadata from the database + metadata_titles = await db.get_metadata_titles(user_id) + video_title = metadata_titles.get('video_title', '') + audio_title = metadata_titles.get('audio_title', '') + subtitle_title = metadata_titles.get('subtitle_title', '') + + await safe_edit_message(sts, "๐Ÿ’  Compressing media... โšก") + try: + compress_video(downloaded, output_file, video_title, audio_title, subtitle_title) + except Exception as e: + await safe_edit_message(sts, f"Error compressing media: {e}") + os.remove(downloaded) + return + + # Retrieve thumbnail from the database + thumbnail_file_id = await db.get_thumbnail(user_id) + file_thumb = None + if thumbnail_file_id: + try: + file_thumb = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(media, 'thumbs') and media.thumbs: + try: + file_thumb = await bot.download_media(media.thumbs[0].file_id) + except Exception as e: + file_thumb = None + + # Get media info and upload to Telegraph + media_info_html, media_info_link = await get_and_upload_mediainfo(bot, output_file, media) + + filesize = os.path.getsize(output_file) + filesize_human = humanbytes(filesize) + cap = f"{output_filename}\n\n๐ŸŒŸ Size: {filesize_human}\n\n[MediaInfo โ„น๏ธ]({media_info_link})" + + await safe_edit_message(sts, "๐Ÿ’  Uploading... โšก") + c_time = time.time() + + if filesize > FILE_SIZE_LIMIT: + file_link = await upload_to_google_drive(output_file, output_filename, sts) + button = [[InlineKeyboardButton("โ˜๏ธ CloudUrl โ˜๏ธ", url=f"{file_link}")]] + await msg.reply_text( + f"**File successfully compressed and uploaded to Google Drive!**\n\n" + f"**Google Drive Link**: [View File]({file_link})\n\n" + f"**Uploaded File**: {output_filename}\n" + f"**Request User:** {msg.from_user.mention}\n\n" + f"**Size**: {filesize_human}\n" + f"[MediaInfo โ„น๏ธ]({media_info_link})", + reply_markup=InlineKeyboardMarkup(button) + ) + else: + try: + await bot.send_document(msg.chat.id, document=output_file, thumb=file_thumb, caption=cap, progress=progress_message, progress_args=("๐Ÿ’  Upload Started... โšก", sts, c_time)) + except Exception as e: + return await safe_edit_message(sts, f"Error: {e}") + + os.remove(downloaded) + os.remove(output_file) + if file_thumb and os.path.exists(file_thumb): + os.remove(file_thumb) + await sts.delete() + +@Client.on_message(filters.command("dleech") & filters.chat(GROUP)) +async def drive_leech(bot, msg: Message): + global MIRROR_ENABLED + + if not MIRROR_ENABLED: + return await msg.reply_text("Rename feature is currently disabled.") + + user_id = msg.from_user.id + + if len(msg.command) < 2 or not msg.reply_to_message: + return await msg.reply_text("Please reply to a file, video, or audio with the new filename and extension (e.g., .mkv, .mp4, .zip).") + + reply = msg.reply_to_message + media = reply.document or reply.audio or reply.video or reply.text + if not media: + return await msg.reply_text("Please reply to a file, video, or audio with the new filename and extension (e.g., .mkv, .mp4, .zip).") + + new_name = msg.text.split(" ", 1)[1] + sts = await msg.reply_text("๐Ÿš€ Downloading... โšก") + + # Extract the Google Drive link from the caption or message text + drive_url = reply.text or reply.caption + file_id = extract_id_from_url(drive_url) + + if not file_id: + return await sts.edit("โŒ Invalid Google Drive link.") + + # Download the file from Google Drive with progress updates + downloaded_file = await download_file_from_drive(drive_service, file_id, new_name, sts) + filesize = humanbytes(os.path.getsize(downloaded_file)) + + if CAPTION: + try: + cap = CAPTION.format(file_name=new_name, file_size=filesize) + except KeyError as e: + return await sts.edit(text=f"Caption error: unexpected keyword ({e})") + else: + cap = f"{new_name}\n\n๐ŸŒŸ Size: {filesize}" + + # Retrieve thumbnail from the database + thumbnail_file_id = await db.get_thumbnail(msg.from_user.id) + og_thumbnail = None + if thumbnail_file_id: + try: + og_thumbnail = await bot.download_media(thumbnail_file_id) + except Exception: + pass + else: + if hasattr(media, 'thumbs') and media.thumbs: + try: + og_thumbnail = await bot.download_media(media.thumbs[0].file_id) + except Exception: + pass + + await sts.edit("๐Ÿ’  Uploading... โšก") + + try: + await bot.send_document(msg.chat.id, document=downloaded_file, thumb=og_thumbnail, caption=cap, progress=progress_message, progress_args=("๐Ÿ’  Upload Started... โšก", sts, time.time())) + except Exception as e: + return await sts.edit(f"Error: {e}") + + os.remove(downloaded_file) + await sts.delete() + +@Client.on_message(filters.command('restart') & filters.user(ADMIN)) +async def restart_message(app, message): + reply = await message.reply_text('Restarting...') + textx = f"Done Restart...โœ…" + await reply.edit_text(textx) + try: + exit() + finally: + osexecl(executable, executable, "bot.py") + + +@Client.on_message(filters.command('logs') & filters.user(ADMIN)) +async def log_file(b, m): + try: + await m.reply_document('SunrisesBot.txt') + except Exception as e: + await m.reply(str(e)) + + if __name__ == '__main__': app = Client("my_bot", bot_token=BOT_TOKEN) app.run() diff --git a/main/utils.py b/main/utils.py index 0d54993..d18badd 100644 --- a/main/utils.py +++ b/main/utils.py @@ -2,6 +2,8 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup import heroku3 import os +import io +from googleapiclient.http import MediaIoBaseDownload #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 PROGRESS_BAR = """ @@ -19,6 +21,7 @@ โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โŸ""" + #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 async def progress_message(current, total, ud_type, message, start): now = time.time() @@ -55,6 +58,7 @@ async def progress_message(current, total, ud_type, message, start): print(f"Error editing message: {e}") + #ALL FILES UPLOADED - CREDITS ๐ŸŒŸ - @Sunrises_24 def TimeFormatter(milliseconds: int) -> str: seconds, milliseconds = divmod(milliseconds, 1000) @@ -134,3 +138,43 @@ async def upload_files(bot, chat_id, directory, base_path=""): elif os.path.isdir(item_path): await upload_files(bot, chat_id, item_path, base_path=os.path.join(base_path, item)) +async def drive_progress(current, total, ud_type, message, start): + now = time.time() + diff = now - start + + # Calculate the percentage and speed + percentage = current * 100 / total + speed = humanbytes(current / diff) + "/s" + # Create a short progress message + progress = f"{round(percentage, 2)}% - {humanbytes(current)} of {humanbytes(total)} @ {speed}" + try: + # Update the bot message with the short progress + await message.edit( + text=f"{ud_type}\n\nProgress: {progress}", + reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("๐ŸŒŸ Jแดษชษด Us ๐ŸŒŸ", url="https://t.me/Sunrises24botupdates")]]) + ) + except Exception as e: + print(f"Error editing message: {e}") + +async def download_file_from_drive(service, file_id, file_name, message): + request = service.files().get_media(fileId=file_id) + file_buffer = io.BytesIO() + downloader = MediaIoBaseDownload(file_buffer, request) + + done = False + start_time = time.time() + + while not done: + status, done = downloader.next_chunk() + if status: + current_size = status.resumable_progress + total_size = status.total_size + + # Update progress message + await drive_progress(current_size, total_size, "๐Ÿš€ Downloading from Google Drive... โšก", message, start_time) + + file_buffer.seek(0) + with open(file_name, 'wb') as f: + f.write(file_buffer.read()) + + return file_name diff --git a/requirements.txt b/requirements.txt index e933fd4..4118b39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -pyrogram==2.0.83 -pyrofork +pyrogram==2.0.83 Tgcrypto ffmpeg-python rarfile @@ -20,3 +19,5 @@ lxml_html_clean motor pymongo datetime +psutil +ujson diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..4d3190c --- /dev/null +++ b/run.sh @@ -0,0 +1 @@ +python3 update.py && python3 bot.py diff --git a/update.py b/update.py new file mode 100644 index 0000000..5e532f9 --- /dev/null +++ b/update.py @@ -0,0 +1,29 @@ + +from subprocess import run as srun +from os import path as ospath +from sys import executable +from os import execl as osexecl + +UPSTREAM_REPO = 'https://github.com/harsha7668/metabor' +UPSTREAM_BRANCH = 'SH24BOTS-GD-REVERSION-GRP' + +if UPSTREAM_REPO is not None: + if ospath.exists('.git'): + srun(["rm", "-rf", ".git"]) + + update = srun([f"git init -q \ + && git config --global user.email sunriseseditsoffical249@gmail.com \ + && git config --global user.name metamorpher \ + && git add . \ + && git commit -sm update -q \ + && git remote add origin {UPSTREAM_REPO} \ + && git fetch origin -q \ + && git reset --hard origin/{UPSTREAM_BRANCH} -q"], shell=True) + + + if update.returncode == 0: + osexecl(executable, executable, "bot.py") + else: + print('Something went wrong while updating, check UPSTREAM_REPO if valid or not!') + +osexecl(executable, executable, "bot.py") diff --git a/versions.txt b/versions.txt new file mode 100644 index 0000000..9dfcae7 --- /dev/null +++ b/versions.txt @@ -0,0 +1,88 @@ +โ”€โ”€ใ€Œ Version v.1.0 ใ€โ”€โ”€ +โ€ข Initial commit + +โ”€โ”€ใ€Œ Version V.2.0 ใ€โ”€โ”€ +โ€ข /Rename ,/help, /about ,/ping commands. +โ€ข Adding button. + +โ”€โ”€ใ€Œ Version V.2.1 ใ€โ”€โ”€ +โ€ข Added Start With Forcesub. +โ€ข Dual Forcesub +โ€ข New variables: +[FSUB_CHANNEL, FSUB_GROUP] + +โ”€โ”€ใ€Œ Version V.2.2 ใ€โ”€โ”€ +โ€ข Auth fix. +โ€ข Precommit file fixed. +โ€ข Variables errors fixed. + +โ”€โ”€ใ€Œ Version V.2.3 ใ€โ”€โ”€ +โ€ข New Command: + /usersettings + /bsettings + /changemetadata + /changeindexaudio + /Changeindexsub + /removetags + /screenshots + /samplevideo + /attachphoto + -setphoto cmd +โ€ข Sort imports +โ€ข Removed useless imports. +โ€ข Removed useless codes. +โ€ข Format python code. +โ€ข print() function use. +โ€ข Group & Private Branch Separate +โ€ข updates.txt file for updates logs. + +โ”€โ”€ใ€Œ Version V.2.4 ใ€โ”€โ”€ +โ€ขNew Comamnd : + /gofile + /gofilesetup + /gdriveid - setup + /mirror + /clone + /clean + /list +โ€ข Implemented Progress Status Bar. +โ€ข Added Google drive For Above 2GB files upload - For all commands +โ€ข Small changes and fixes. + +โ”€โ”€ใ€Œ Version V.2.5 ใ€โ”€โ”€ +**Major Update** +โ€ข Database Support. +โ€ข Implemented Settings. +โ€ข New Command: + /ytdlleech + /mediainfo + /stats +โ€ข Admin Command: + /clear - Clear Database + /ban + /unban + /users + /broadcast +โ€ข Log Channel +โ€ข Small changes and fixes. +โ€ข Support Render, Koyeb Support. +โ€ข Docker File Updated : Mediainfo, Ffmpeg +โ€ข Use pyrofork for Peer ID Invalid error +โ€ข version.txt file for updates logs. + +โ”€โ”€ใ€Œ Version V.2.6 ใ€โ”€โ”€ +**Minor Update** +โ€ข Implemented Settings. +โ€ข New Command: + /streamremove + /multitaskfile + /multitasklink + /compress +โ€ข Implement Some Help Command + +โ”€โ”€ใ€Œ Version V.2.7 ใ€โ”€โ”€ +Minor Update +โ€ข New Commands: + /Logs + /Restart + /Dleech (drive link leech) (2GB)