├── runtime.txt ├── Procfile ├── run cmd.txt ├── app.py ├── heroku.yml ├── vars.py ├── Dockerfile ├── logs.py ├── requirements.txt ├── app.json ├── README.md ├── utils.py ├── youtube_cookies.txt ├── core.py └── main.py /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.13.2 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 main.py 2 | -------------------------------------------------------------------------------- /run cmd.txt: -------------------------------------------------------------------------------- 1 | gunicorn app:app & python3 main.py 2 | python youtube_downloader.py 3 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app = Flask(__name__) 3 | 4 | @app.route('/') 5 | def hello_world(): 6 | return 'Tushar' 7 | 8 | 9 | if __name__ == "__main__": 10 | app.run() 11 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: python3 main.py 6 | 7 | # for heroku deployment...add this bulidpack. 8 | 9 | # https://github.com/heroku/heroku-buildpack-activestorage-preview 10 | 11 | # https://github.com/heroku/heroku-buildpack-apt 12 | -------------------------------------------------------------------------------- /vars.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit Tg - @Tushar0125 2 | # Ask Doubt on telegram @Tushar0125 3 | 4 | from os import environ 5 | 6 | API_ID = int(environ.get("API_ID", "23237831")) #Replace with your api id 7 | API_HASH = environ.get("API_HASH", "017dc661ca1432ac2fe5ecb62499d88f") #Replace with your api hash 8 | BOT_TOKEN = environ.get("BOT_TOKEN", "") #Replace with your bot token 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10.8-slim-buster 2 | RUN apt-get update -y && apt-get upgrade -y \ 3 | && apt-get install -y --no-install-recommends gcc libffi-dev musl-dev ffmpeg aria2 python3-pip \ 4 | && apt-get clean \ 5 | && rm -rf /var/lib/apt/lists/* 6 | 7 | COPY . /app/ 8 | WORKDIR /app/ 9 | RUN pip3 install --no-cache-dir --upgrade --requirement requirements.txt 10 | RUN pip install pytube 11 | ENV COOKIES_FILE_PATH="youtube_cookies.txt" 12 | CMD gunicorn app:app & python3 main.py 13 | -------------------------------------------------------------------------------- /logs.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit Tg - @Tushar0125 2 | # Ask Doubt on telegram @Tushar0125 3 | 4 | import logging 5 | from logging.handlers import RotatingFileHandler 6 | 7 | logging.basicConfig( 8 | level=logging.ERROR, 9 | format= 10 | "%(asctime)s - %(levelname)s - %(message)s [%(filename)s:%(lineno)d]", 11 | datefmt="%d-%b-%y %H:%M:%S", 12 | handlers=[ 13 | RotatingFileHandler("logs.txt", maxBytes=50000000, backupCount=10), 14 | logging.StreamHandler(), 15 | ], 16 | ) 17 | logging.getLogger("pyrogram").setLevel(logging.WARNING) 18 | 19 | 20 | logging = logging.getLogger() 21 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | async-lru==2.0.2 2 | certifi==2023.5.7 3 | charset-normalizer==3.1.0 4 | idna==3.4 5 | mutagen==1.46.0 6 | pyaes==1.6.1 7 | pycryptodome==3.18.0 8 | pyrogram 9 | pyromod==1.5 10 | PySocks==1.7.1 11 | python-dotenv==1.0.0 12 | requests==2.31.0 13 | soupsieve==2.4.1 14 | TgCrypto==1.2.5 15 | urllib3==2.0.3 16 | websockets==11.0.3 17 | beautifulsoup4 18 | cloudscraper 19 | yt-dlp 20 | motor 21 | aiohttp 22 | aiofiles 23 | pytz 24 | ffmpeg==1.4 25 | umongo==3.1.0 26 | speedtest-cli 27 | Flask==1.1.2 28 | gunicorn 29 | fastapi 30 | uvicorn 31 | Jinja2==3.0.3 32 | werkzeug==2.0.2 33 | itsdangerous==2.0.1 34 | ffprobe 35 | youtube-dl 36 | mediainfo 37 | aria2 38 | pycurl 39 | m3u8 40 | bs4 41 | pytube 42 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "anonymous", 4 | "description": "anonymous", 5 | "repository": "https://github.com/", 6 | "keywords": [ 7 | "telegram bot", 8 | "pyrogram" 9 | ], 10 | "env": { 11 | "API_ID":{ 12 | "description": "Get your telegram API ID from https://my.telegram.org", 13 | "value":"20114039" 14 | }, 15 | "API_HASH":{ 16 | "description":"Get your telegram API HASH from https://my.telegram.org", 17 | "value":"87297b8f3cc8fc9bbce591ad30da5896" 18 | }, 19 | "BOT_TOKEN":{ 20 | "description":"Get from BotFather", 21 | "value":"7559250442:AAF_HDC3Fb_yG6xHxXkRhhwlMm3LiwT9MkE" 22 | }, 23 | "AUTH_USERS":{ 24 | "description":"Admin/Owner/Friends ID Seperate by ',' Ex: 44578878,8878899", 25 | "value":"8172163893" 26 | 27 | } 28 | }, 29 | "addons": [], 30 | "buildpacks": [ 31 | { 32 | "url": "heroku/python" 33 | "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git" 34 | "url": "https://github.com/heroku/heroku-buildpack-activestorage-preview" 35 | } 36 | 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 🇮🇳 ᴛᴜsʜᴀʀ ᴛxᴛ ᴜᴘʟᴏᴀᴅᴇʀ 🇮🇳 3 |

4 | 5 | ![Typing SVG](https://readme-typing-svg.herokuapp.com/?lines=Welcome+To+Txt+Uploader+Bot+!) 6 | 7 | ## 😎 Credit 8 | 9 | 🥳 Credit Goes To [Tushar](https://t.me/Tushar0125) 10 | 11 | 12 | ## 🔥 Commands 13 | 14 | - **`/start`**: ⚡ check bot is alive. 15 | - **`/tushar`**: 📁 upload txt file. 16 | - **`/stop`**: 🛑 stop ongoing process. 17 | - **`/restart`**: 🔮 restart the bot. 18 | - **`/cookies`**: 🍪 upload cookies file. 19 | - **`/e2t`**: 📝 edit txt file. 20 | - **`/yt2txt`**: 🗃️ create txt of yt playlist (owner). 21 | - **`/sudo add`**: 🎊 add user or group or channel (owner). 22 | - **`/sudo remove`**: ❌ remove user or group or channel (owner). 23 | - **`/userlist`**: 📜 list of sudo user/group/channel. 24 | - **`/help`**: 🎉 for help. 25 | 26 | 27 | ## ✅ Pw & Cp Without Purchase Txt Extractor Bot 28 | 29 | 🥳 Pw & Cp Without Purchase Txt Extractor Bot [Click Here](https://t.me/PwCpTxtExtractorBot) 30 | 31 | 32 | ## Guide For Heroku Deployment 33 | 34 | Firstly fill the value of api id,api hash,bot token in vars.py file. After it connect heroku from GitHub and then connect this repo. After it , go to in heroku setting,again fill the api id, api hash,bot token and then deploy. After deployment of this repo,again go to this deployment repo setting and add buildpack and again deploy. 35 | 36 | Buildpack - https://github.com/heroku/heroku-buildpack-activestorage-preview 37 | 38 | 39 | 40 | सर्वप्रथम vars.py file में api id , api hash ,bot token Fill करें। 41 | उसके बाद heroku में github को connect करके इस repo को conneect कर ले । 42 | इसके बाद heroku setting में जाकर फिर से api id , api hash,bot token डालें। और फिर deploy कर दे। 43 | deploy करने के बाद उसी deploy वाली repo के setting में जाकर buildpack add करके again Deploy करें। 44 | 45 | Buildpack - https://github.com/heroku/heroku-buildpack-activestorage-preview 46 | 47 | ## Deploy To Koyeb 48 | 49 | [![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?name=advance-txt-uploader&repository=Tushar557845%2FADVANCE-TXT-UPLOADER&branch=main&builder=dockerfile&instance_type=free&instances_min=0&autoscaling_sleep_idle_delay=300&ports=8080%3Bhttp%3B%2F&hc_protocol%5B8080%5D=tcp&hc_grace_period%5B8080%5D=5&hc_interval%5B8080%5D=30&hc_restart_limit%5B8080%5D=3&hc_timeout%5B8080%5D=5&hc_path%5B8080%5D=%2F&hc_method%5B8080%5D=get) 50 | 51 | ## Deploy To Render 52 | 53 | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/Tushar557845/ADVANCE-TXT-UPLOADER) 54 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit Telegram - @Tushar0125 2 | import time 3 | import math 4 | import os 5 | from pyrogram.errors import FloodWait 6 | 7 | class Timer: 8 | def __init__(self, time_between=5): 9 | self.start_time = time.time() 10 | self.time_between = time_between 11 | 12 | def can_send(self): 13 | if time.time() > (self.start_time + self.time_between): 14 | self.start_time = time.time() 15 | return True 16 | return False 17 | 18 | 19 | from datetime import datetime,timedelta 20 | 21 | def hrb(value, digits= 2, delim= "", postfix=""): 22 | """Return a human-readable file size. 23 | """ 24 | if value is None: 25 | return None 26 | chosen_unit = "B" 27 | for unit in ("KiB", "MiB", "GiB", "TiB"): 28 | if value > 1000: 29 | value /= 1024 30 | chosen_unit = unit 31 | else: 32 | break 33 | return f"{value:.{digits}f}" + delim + chosen_unit + postfix 34 | 35 | def hrt(seconds, precision = 0): 36 | """Return a human-readable time delta as a string. 37 | """ 38 | pieces = [] 39 | value = timedelta(seconds=seconds) 40 | 41 | 42 | if value.days: 43 | pieces.append(f"{value.days}d") 44 | 45 | seconds = value.seconds 46 | 47 | if seconds >= 3600: 48 | hours = int(seconds / 3600) 49 | pieces.append(f"{hours}h") 50 | seconds -= hours * 3600 51 | 52 | if seconds >= 60: 53 | minutes = int(seconds / 60) 54 | pieces.append(f"{minutes}m") 55 | seconds -= minutes * 60 56 | 57 | if seconds > 0 or not pieces: 58 | pieces.append(f"{seconds}s") 59 | 60 | if not precision: 61 | return "".join(pieces) 62 | 63 | return "".join(pieces[:precision]) 64 | 65 | 66 | 67 | timer = Timer() 68 | 69 | async def progress_bar(current, total, reply, start): 70 | if timer.can_send(): 71 | now = time.time() 72 | diff = now - start 73 | if diff < 1: 74 | return 75 | else: 76 | perc = f"{current * 100 / total:.1f}%" 77 | elapsed_time = round(diff) 78 | speed = current / elapsed_time 79 | remaining_bytes = total - current 80 | if speed > 0: 81 | eta_seconds = remaining_bytes / speed 82 | eta = hrt(eta_seconds, precision=1) 83 | else: 84 | eta = "-" 85 | sp = str(hrb(speed)) + "/s" 86 | tot = hrb(total) 87 | cur = hrb(current) 88 | bar_length = 11 89 | completed_length = int(current * bar_length / total) 90 | remaining_length = bar_length - completed_length 91 | progress_bar = "▰" * completed_length + "▱" * remaining_length 92 | 93 | #try: 94 | #await reply.edit(f'\n ╭──⌯════⬇️𝗨𝗣𝗟𝗢𝗔𝗗𝗜𝗡𝗚⬇️═════⌯──╮ \n├⚡ {progress_bar}|﹝{perc}﹞ \n├🚀 Speed » {sp} \n├📟 Processed » {cur}\n├🧲 Size - ETA » {tot} - {eta} \n├🤖 Bot Made By » Tushar\n╰─═══ ✪👨🏻‍💻𝗧𝗨𝗦𝗛𝗔𝗥👨🏻‍💻✪ ═══─╯\n\n🙂 चलो फिर से अजनबी बन जायें 🙂') 95 | #except FloodWait as e: 96 | #time.sleep(e.x) 97 | 98 | try: 99 | await reply.edit(f'╭──⌯════🌟𝗨𝗣𝗟𝗢𝗔𝗗𝗜𝗡𝗚🌟═════⌯──╮ \n├⚡ {progress_bar}\n ├🚀 𝗦𝗽𝗲𝗲𝗱 ➠ {sp} \n ├📛 𝗣𝗿𝗼𝗴𝗿𝗲𝘀𝘀 ➠ {perc} \n ├📟 𝗟𝗼𝗮𝗱𝗲𝗱 ➠ {cur} \n ├🧲 𝗦𝗶𝘇𝗲 ➠ {tot} \n ├🕑 𝗘𝘁𝗮 ➠ {eta} \n╰─══👨🏻‍💻𝗧𝗨𝗦𝗛𝗔𝗥👨🏻‍💻══─╯\n\n🙂 चलो फिर से अजनबी बन जायें 🙂') 100 | except FloodWait as e: 101 | time.sleep(e.x) 102 | -------------------------------------------------------------------------------- /youtube_cookies.txt: -------------------------------------------------------------------------------- 1 | # Netscape HTTP Cookie File 2 | # https://curl.haxx.se/rfc/cookie_spec.html 3 | # This is a generated file! Do not edit. 4 | 5 | .youtube.com TRUE / TRUE 1774951809 __Secure-1PSIDTS sidts-CjIB7pHptZ4bkJGRHMjJXryNPmN6APHanQBqDXy00udJ8TVsRZ5KDW6lagpbswsuvbkHDhAA 6 | .youtube.com TRUE / TRUE 1774951809 __Secure-3PSIDTS sidts-CjIB7pHptZ4bkJGRHMjJXryNPmN6APHanQBqDXy00udJ8TVsRZ5KDW6lagpbswsuvbkHDhAA 7 | .youtube.com TRUE / TRUE 1777975809 __Secure-3PSID g.a000vQhbPmsIVyRvu6fyQHcuhF1K9O1d8IbaZ6LbXRT4KLI8Nl2iWIM02QbdqeXcv1GOV_0pPQACgYKATYSARQSFQHGX2Mi2lpVcwqDXOzjYSpUoAzL-RoVAUF8yKromfoh1Io0QNA6FJqwxfiA0076 8 | .youtube.com TRUE / TRUE 1777975809 __Secure-3PAPISID CYh62DCqwNyRsVqs/A4EeH9FLzaJ3gyKZd 9 | .youtube.com TRUE / TRUE 1774868135 __Secure-3PSIDCC AKEyXzXVWQd-20Mo3Em4P-kWVPk3HETIwF3fQTd7d6Hbtfz84sPgTh8Vc-0CWNg5t2yko4xtH1s 10 | .youtube.com TRUE / TRUE 1759595940 __Secure-ROLLOUT_TOKEN CL-gmfP10OPZigEQy6WcyazSiwMY2LzO_K3GjAM%3D 11 | .youtube.com TRUE / TRUE 1759595944 VISITOR_INFO1_LIVE sLtxd7RaOq4 12 | .youtube.com TRUE / TRUE 1759595944 VISITOR_PRIVACY_METADATA CgJJThIEGgAgJQ%3D%3D 13 | .youtube.com TRUE / TRUE 1778603945 PREF f6=40000000&tz=Asia.Kolkata&f7=100&f4=4000000 14 | .youtube.com TRUE / FALSE 1740121460 ST-10d87nd csn=RWQXIQky0d9RTq8C&itct=CG0Q_FoiEwj-h5XHmdSLAxXXjWYCHfRUEBsyCmctaGlnaC1yZWNaD0ZFd2hhdF90b193YXRjaJoBBhCOHhieAQ%3D%3D 15 | .youtube.com TRUE / FALSE 1740145530 ST-x3zc7r csn=VNEM7hwVfOiXXS9K&itct=CGoQ_FoiEwiM5s6c89SLAxV2tFYBHY28ErMyCmctaGlnaC1yZWNaD0ZFd2hhdF90b193YXRjaJoBBhCOHhieAQ%3D%3D 16 | .youtube.com TRUE / FALSE 1740398801 ST-h3az29 csn=1dm2HeRfs0reoVLa&itct=CG0Q_FoiEwjT8tfdotyLAxWit1YBHVL-NqIyCmctaGlnaC1yZWNaD0ZFd2hhdF90b193YXRjaJoBBhCOHhieAQ%3D%3D 17 | .youtube.com TRUE / FALSE 1740407388 ST-1yod0rt csn=xbaMD_ZSl3bDpf1D&itct=CBAQ1TYiEwixs5u8wtyLAxVchNgFHfWHEqs%3D 18 | .youtube.com TRUE / FALSE 1740575089 ST-13avi31 csn=TMcaElOy7oFUEZ6t&itct=CG0Q_FoiEwjjpby6s-GLAxXozjQHHVTGMoYyCmctaGlnaC1yZWNaD0ZFd2hhdF90b193YXRjaJoBBhCOHhieAQ%3D%3D 19 | .youtube.com TRUE / FALSE 1740575166 ST-up1ya7 csn=ci2T3xaoyMSW60FS&itct=CGQQh_YEGAEiEwjK1aC8s-GLAxXSdF4EHUewKZ9aD0ZFd2hhdF90b193YXRjaJoBBQgkEI4e 20 | .youtube.com TRUE / FALSE 1740825158 ST-15v4jje csn=ShR-kMwzS2nm7NWc&itct=CG0Q_FoiEwiBsrqE1-iLAxVU4jQHHUARAuMyCmctaGlnaC1yZWNaD0ZFd2hhdF90b193YXRjaJoBBhCOHhieAQ%3D%3D 21 | .youtube.com TRUE / FALSE 1740839233 ST-1668un8 csn=6FQ8DPHFfRuLy6aq&itct=CFYQ_9AFIhMI0OarvIvpiwMVKutMAh1paQ7RMhhob21lcGFnZV9tb2JpbGVfbWFzdGhlYWRI_sec0qyblacZ 22 | .youtube.com TRUE / FALSE 1741175595 ST-zg8eie csn=OdLo7ZrCDAXILz7N&itct=CBQQkeQHGAUiEwjJg9LA8PKLAxVkmWMGHdbDKcE%3D 23 | .youtube.com TRUE / FALSE 1741411252 ST-s1ooxb csn=V3e-y-Hmmo0Q-IxF&itct=CCsQpDAiEwje4_-z3vmLAxV1dJ0JHTdTAstaGFVDQndHdjQwbWhDNmRIN1gwZmFVQ2ZzUZoBAxDyOA%3D%3D 24 | .youtube.com TRUE / FALSE 1742880962 ST-1qhkeb4 csn=_P4y2MejdGQTDVUb&itct=CIcBEIf2BBgAIhMI_bLkv8GkjAMV8p-vAR3Xhy0xWg9GRXdoYXRfdG9fd2F0Y2iaAQUIJBCOHg%3D%3D 25 | .youtube.com TRUE / FALSE 1743136480 ST-1do3kmd csn=8IHUhDnprdjSA2L_&itct=CIMBEIf2BBgAIhMIkcOesPmrjAMVjuugAh1leCdWWg9GRXdoYXRfdG9fd2F0Y2iaAQUIJBCOHg%3D%3D 26 | .youtube.com TRUE / FALSE 1743317821 ST-yqazgl csn=O1Lf1G_rEqxY4H-V&itct=CIEBEPxaIhMIreCU-JyxjAMVbapWAR0xhShjMgpnLWhpZ2gtcmVjWg9GRXdoYXRfdG9fd2F0Y2iaAQYQjh4YngE%3D 27 | .youtube.com TRUE / FALSE 1743317827 ST-1wb13c7 csn=mHKD4Y9sMu6DpwqY&itct=CH8Qh_YEGAEiEwis-uP5nLGMAxXiWF4EHcpRKzNaD0ZFd2hhdF90b193YXRjaJoBBQgkEI4e 28 | .youtube.com TRUE / FALSE 1743668361 ST-19ldxaq csn=K1gEJz-mFtruoMwQ&itct=CFgQh_YEGAAiEwjR05XjtruMAxUwjWYCHZLLO4JaD0ZFd2hhdF90b193YXRjaJoBBQgkEI4e 29 | .youtube.com TRUE / TRUE 1743668955 CONSISTENCY AKreu9uHBw-v3JbcLtJFS6zFOYQX_8F7T-uO0wdm5Lzq7ULD83-_1lR0JENCJkNS0b-SMeHs5r6b9pKphhPGCpIY9o-wh_5dWNnIxIPs-4egFQi4RFRM8bk 30 | .youtube.com TRUE / FALSE 1743940711 ST-1oeln6b csn=e677Mdkztt1iYQi-&itct=CAYQ040EGAEiEwiSz_qmrcOMAxV13TgGHW_LAZlImLvx0srzpvSvAQ%3D%3D 31 | .youtube.com TRUE / FALSE 1743940710 ST-zepmww csn=e677Mdkztt1iYQi-&itct=CAYQ040EGAEiEwiSz_qmrcOMAxV13TgGHW_LAZlImLvx0srzpvSvAQ%3D%3D 32 | .youtube.com TRUE / TRUE 1744045740 GPS 1 33 | -------------------------------------------------------------------------------- /core.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit Tg - @Tushar0125 2 | 3 | import os 4 | import time 5 | import datetime 6 | import aiohttp 7 | import aiofiles 8 | import asyncio 9 | import logging 10 | import requests 11 | import tgcrypto 12 | import subprocess 13 | import concurrent.futures 14 | 15 | from utils import progress_bar 16 | 17 | from pyrogram import Client, filters 18 | from pyrogram.types import Message 19 | 20 | from pytube import Playlist #Youtube Playlist Extractor 21 | from yt_dlp import YoutubeDL 22 | import yt_dlp as youtube_dl 23 | 24 | def duration(filename): 25 | result = subprocess.run(["ffprobe", "-v", "error", "-show_entries", 26 | "format=duration", "-of", 27 | "default=noprint_wrappers=1:nokey=1", filename], 28 | stdout=subprocess.PIPE, 29 | stderr=subprocess.STDOUT) 30 | return float(result.stdout) 31 | 32 | def exec(cmd): 33 | process = subprocess.run(cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE) 34 | output = process.stdout.decode() 35 | print(output) 36 | return output 37 | #err = process.stdout.decode() 38 | def pull_run(work, cmds): 39 | with concurrent.futures.ThreadPoolExecutor(max_workers=work) as executor: 40 | print("Waiting for tasks to complete") 41 | fut = executor.map(exec,cmds) 42 | async def aio(url,name): 43 | k = f'{name}.pdf' 44 | async with aiohttp.ClientSession() as session: 45 | async with session.get(url) as resp: 46 | if resp.status == 200: 47 | f = await aiofiles.open(k, mode='wb') 48 | await f.write(await resp.read()) 49 | await f.close() 50 | return k 51 | 52 | 53 | async def download(url,name): 54 | ka = f'{name}.pdf' 55 | async with aiohttp.ClientSession() as session: 56 | async with session.get(url) as resp: 57 | if resp.status == 200: 58 | f = await aiofiles.open(ka, mode='wb') 59 | await f.write(await resp.read()) 60 | await f.close() 61 | return ka 62 | 63 | 64 | 65 | def parse_vid_info(info): 66 | info = info.strip() 67 | info = info.split("\n") 68 | new_info = [] 69 | temp = [] 70 | for i in info: 71 | i = str(i) 72 | if "[" not in i and '---' not in i: 73 | while " " in i: 74 | i = i.replace(" ", " ") 75 | i.strip() 76 | i = i.split("|")[0].split(" ",2) 77 | try: 78 | if "RESOLUTION" not in i[2] and i[2] not in temp and "audio" not in i[2]: 79 | temp.append(i[2]) 80 | new_info.append((i[0], i[2])) 81 | except: 82 | pass 83 | return new_info 84 | 85 | 86 | def vid_info(info): 87 | info = info.strip() 88 | info = info.split("\n") 89 | new_info = dict() 90 | temp = [] 91 | for i in info: 92 | i = str(i) 93 | if "[" not in i and '---' not in i: 94 | while " " in i: 95 | i = i.replace(" ", " ") 96 | i.strip() 97 | i = i.split("|")[0].split(" ",3) 98 | try: 99 | if "RESOLUTION" not in i[2] and i[2] not in temp and "audio" not in i[2]: 100 | temp.append(i[2]) 101 | 102 | # temp.update(f'{i[2]}') 103 | # new_info.append((i[2], i[0])) 104 | # mp4,mkv etc ==== f"({i[1]})" 105 | 106 | new_info.update({f'{i[2]}':f'{i[0]}'}) 107 | 108 | except: 109 | pass 110 | return new_info 111 | 112 | 113 | 114 | async def run(cmd): 115 | proc = await asyncio.create_subprocess_shell( 116 | cmd, 117 | stdout=asyncio.subprocess.PIPE, 118 | stderr=asyncio.subprocess.PIPE) 119 | 120 | stdout, stderr = await proc.communicate() 121 | 122 | print(f'[{cmd!r} exited with {proc.returncode}]') 123 | if proc.returncode == 1: 124 | return False 125 | if stdout: 126 | return f'[stdout]\n{stdout.decode()}' 127 | if stderr: 128 | return f'[stderr]\n{stderr.decode()}' 129 | 130 | 131 | 132 | def old_download(url, file_name, chunk_size = 1024 * 10): 133 | if os.path.exists(file_name): 134 | os.remove(file_name) 135 | r = requests.get(url, allow_redirects=True, stream=True) 136 | with open(file_name, 'wb') as fd: 137 | for chunk in r.iter_content(chunk_size=chunk_size): 138 | if chunk: 139 | fd.write(chunk) 140 | return file_name 141 | 142 | 143 | def human_readable_size(size, decimal_places=2): 144 | for unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']: 145 | if size < 1024.0 or unit == 'PB': 146 | break 147 | size /= 1024.0 148 | return f"{size:.{decimal_places}f} {unit}" 149 | 150 | 151 | def time_name(): 152 | date = datetime.date.today() 153 | now = datetime.datetime.now() 154 | current_time = now.strftime("%H%M%S") 155 | return f"{date} {current_time}.mp4" 156 | 157 | def get_playlist_videos(playlist_url): 158 | try: 159 | # Create a Playlist object 160 | playlist = Playlist(playlist_url) 161 | 162 | # Get the playlist title 163 | playlist_title = playlist.title 164 | 165 | # Initialize an empty dictionary to store video names and links 166 | videos = {} 167 | 168 | # Iterate through the videos in the playlist 169 | for video in playlist.videos: 170 | try: 171 | video_title = video.title 172 | video_url = video.watch_url 173 | videos[video_title] = video_url 174 | except Exception as e: 175 | logging.error(f"Could not retrieve video details: {e}") 176 | 177 | return playlist_title, videos 178 | except Exception as e: 179 | logging.error(f"An error occurred: {e}") 180 | return None, None 181 | 182 | def get_all_videos(channel_url): 183 | ydl_opts = { 184 | 'quiet': True, 185 | 'extract_flat': True, 186 | 'skip_download': True 187 | } 188 | 189 | all_videos = [] 190 | with YoutubeDL(ydl_opts) as ydl: 191 | result = ydl.extract_info(channel_url, download=False) 192 | 193 | if 'entries' in result: 194 | channel_name = result['title'] 195 | all_videos.extend(result['entries']) 196 | 197 | while 'entries' in result and '_next' in result: 198 | next_page_url = result['_next'] 199 | result = ydl.extract_info(next_page_url, download=False) 200 | all_videos.extend(result['entries']) 201 | 202 | video_links = {index+1: (video['title'], video['url']) for index, video in enumerate(all_videos)} 203 | return video_links, channel_name 204 | else: 205 | return None, None 206 | 207 | def save_to_file(video_links, channel_name): 208 | # Sanitize the channel name to be a valid filename 209 | sanitized_channel_name = re.sub(r'[^\w\s-]', '', channel_name).strip().replace(' ', '_') 210 | filename = f"{sanitized_channel_name}.txt" 211 | with open(filename, 'w', encoding='utf-8') as file: 212 | for number, (title, url) in video_links.items(): 213 | # Ensure the URL is formatted correctly 214 | if url.startswith("https://"): 215 | formatted_url = url 216 | elif "shorts" in url: 217 | formatted_url = f"https://www.youtube.com{url}" 218 | else: 219 | formatted_url = f"https://www.youtube.com/watch?v={url}" 220 | file.write(f"{number}. {title}: {formatted_url}\n") 221 | return filename 222 | 223 | async def download_video(url, cmd, name): 224 | download_cmd = f'{cmd} -R 25 --fragment-retries 25 --external-downloader aria2c --downloader-args "aria2c: -x 16 -j 32"' 225 | global failed_counter 226 | print(download_cmd) 227 | logging.info(download_cmd) 228 | k = subprocess.run(download_cmd, shell=True) 229 | 230 | # Check if the URL is of type 'visionias' or 'penpencilvod' 231 | if "visionias" in cmd: 232 | return await download_visionias(url, cmd, name) 233 | elif "penpencilvod" in cmd: 234 | return await download_penpencilvod(url, cmd, name) 235 | else: 236 | # Default handling for other types of URLs 237 | return await default_download(url, cmd, name) 238 | 239 | async def download_visionias(url, cmd, name): 240 | global failed_counter 241 | # Retry logic for 'visionias' URLs 242 | if failed_counter <= 10: 243 | failed_counter += 1 244 | await asyncio.sleep(5) 245 | return await download_video(url, cmd, name) 246 | else: 247 | # Reset failed_counter if the download succeeds 248 | failed_counter = 0 249 | return await default_download(url, cmd, name) 250 | 251 | 252 | async def download_penpencilvod(url, cmd, name): 253 | global failed_counter 254 | # Retry logic for 'penpencilvod' URLs 255 | if failed_counter <= 10: 256 | failed_counter += 1 257 | await asyncio.sleep(5) 258 | return await download_video(url, cmd, name) 259 | else: 260 | # Reset failed_counter if the download succeeds 261 | failed_counter = 0 262 | return await default_download(url, cmd, name) 263 | 264 | async def download_video(url,cmd, name): 265 | download_cmd = f'{cmd} -R 25 --fragment-retries 25 --external-downloader aria2c --downloader-args "aria2c: -x 16 -j 32"' 266 | global failed_counter 267 | print(download_cmd) 268 | logging.info(download_cmd) 269 | k = subprocess.run(download_cmd, shell=True) 270 | if "visionias" in cmd and k.returncode != 0 and failed_counter <= 10: 271 | failed_counter += 1 272 | await asyncio.sleep(5) 273 | await download_video(url, cmd, name) 274 | failed_counter = 0 275 | try: 276 | if os.path.isfile(name): 277 | return name 278 | elif os.path.isfile(f"{name}.webm"): 279 | return f"{name}.webm" 280 | name = name.split(".")[0] 281 | if os.path.isfile(f"{name}.mkv"): 282 | return f"{name}.mkv" 283 | elif os.path.isfile(f"{name}.mp4"): 284 | return f"{name}.mp4" 285 | elif os.path.isfile(f"{name}.mp4.webm"): 286 | return f"{name}.mp4.webm" 287 | 288 | return name 289 | except FileNotFoundError as exc: 290 | return os.path.isfile.splitext[0] + "." + "mp4" 291 | 292 | 293 | async def send_doc(bot: Client, m: Message,cc,ka,cc1,prog,count,name): 294 | reply = await m.reply_text(f"🚀🚀🚀𝗨𝗣𝗟𝗢𝗔𝗗𝗜𝗡𝗚🚀🚀🚀 » `{name}`\n\n🤖𝗕𝗢𝗧 𝗠𝗔𝗗𝗘 𝗕𝗬 ➤ 𝗧𝗨𝗦𝗛𝗔𝗥") 295 | time.sleep(1) 296 | start_time = time.time() 297 | await m.reply_document(ka,caption=cc1) 298 | count+=1 299 | await reply.delete (True) 300 | time.sleep(1) 301 | os.remove(ka) 302 | time.sleep(3) 303 | 304 | 305 | async def send_vid(bot: Client, m: Message,cc,filename,thumb,name,prog): 306 | 307 | subprocess.run(f'ffmpeg -i "{filename}" -ss 00:00:12 -vframes 1 "{filename}.jpg"', shell=True) 308 | await prog.delete (True) 309 | reply = await m.reply_text(f"**🚀🚀🚀𝗨𝗣𝗟𝗢𝗔𝗗𝗜𝗡𝗚🚀🚀🚀** » `{name}`\n\n🤖𝗕𝗢𝗧 𝗠𝗔𝗗𝗘 𝗕𝗬 ➤ 𝗧𝗨𝗦𝗛𝗔𝗥") 310 | try: 311 | if thumb == "no": 312 | thumbnail = f"{filename}.jpg" 313 | else: 314 | thumbnail = thumb 315 | except Exception as e: 316 | await m.reply_text(str(e)) 317 | 318 | dur = int(duration(filename)) 319 | 320 | start_time = time.time() 321 | 322 | try: 323 | await m.reply_video(filename,caption=cc, supports_streaming=True,height=720,width=1280,thumb=thumbnail,duration=dur, progress=progress_bar,progress_args=(reply,start_time)) 324 | except Exception: 325 | await m.reply_document(filename,caption=cc, progress=progress_bar,progress_args=(reply,start_time)) 326 | 327 | 328 | os.remove(filename) 329 | 330 | os.remove(f"{filename}.jpg") 331 | await reply.delete (True) 332 | 333 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit Tg - @Tushar0125 2 | # Ask Doubt on telegram @Tushar0125 3 | 4 | import os 5 | import re 6 | import sys 7 | import json 8 | import time 9 | import m3u8 10 | import aiohttp 11 | import asyncio 12 | import requests 13 | import subprocess 14 | import urllib.parse 15 | import cloudscraper 16 | import datetime 17 | import random 18 | import ffmpeg 19 | import logging 20 | import yt_dlp 21 | from subprocess import getstatusoutput 22 | from aiohttp import web 23 | from core import * 24 | from urllib.parse import urlparse, parse_qs 25 | from bs4 import BeautifulSoup 26 | from yt_dlp import YoutubeDL 27 | import yt_dlp as youtube_dl 28 | import cloudscraper 29 | import m3u8 30 | import core as helper 31 | from utils import progress_bar 32 | from vars import API_ID, API_HASH, BOT_TOKEN 33 | from aiohttp import ClientSession 34 | from pyromod import listen 35 | from subprocess import getstatusoutput 36 | from pytube import YouTube 37 | 38 | from pyrogram import Client, filters 39 | from pyrogram.types import Message 40 | from pyrogram.errors import FloodWait 41 | from pyrogram.errors.exceptions.bad_request_400 import StickerEmojiInvalid 42 | from pyrogram.types.messages_and_media import message 43 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 44 | cookies_file_path = os.getenv("COOKIES_FILE_PATH", "youtube_cookies.txt") 45 | 46 | #pwimg = "https://graph.org/file/8add8d382169e326f67e0-3bf38f92e52955e977.jpg" 47 | #ytimg = "https://graph.org/file/3aa806c302ceec62e6264-60ced740281395f68f.jpg" 48 | cpimg = "https://graph.org/file/5ed50675df0faf833efef-e102210eb72c1d5a17.jpg" 49 | 50 | 51 | async def show_random_emojis(message): 52 | emojis = ['🎊', '🔮', '😎', '⚡️', '🚀', '✨', '💥', '🎉', '🥂', '🍾', '🦠', '🤖', '❤️‍🔥', '🕊️', '💃', '🥳','🐅','🦁'] 53 | emoji_message = await message.reply_text(' '.join(random.choices(emojis, k=1))) 54 | return emoji_message 55 | 56 | # Define the owner's user ID 57 | OWNER_ID = 5840594311 # Replace with the actual owner's user ID 58 | 59 | # List of sudo users (initially empty or pre-populated) 60 | SUDO_USERS = [5840594311] 61 | 62 | # ✅ Multiple AUTH CHANNELS allowed 63 | AUTH_CHANNELS = [-1002605113558,-1002663510614] # Add more channel IDs here 64 | 65 | # Function to check if a user is authorized 66 | def is_authorized(user_id: int) -> bool: 67 | return ( 68 | user_id == OWNER_ID 69 | or user_id in SUDO_USERS 70 | or user_id in AUTH_CHANNELS # ✅ Checks if user_id matches any channel ID 71 | ) 72 | 73 | 74 | bot = Client( 75 | "bot", 76 | api_id=API_ID, 77 | api_hash=API_HASH, 78 | bot_token=BOT_TOKEN) 79 | 80 | # Sudo command to add/remove sudo users 81 | @bot.on_message(filters.command("sudo")) 82 | async def sudo_command(bot: Client, message: Message): 83 | user_id = message.chat.id 84 | if user_id != OWNER_ID: 85 | await message.reply_text("**🚫 You are not authorized to use this command.**") 86 | return 87 | 88 | try: 89 | args = message.text.split(" ", 2) 90 | if len(args) < 2: 91 | await message.reply_text("**Usage:** `/sudo add ` or `/sudo remove `") 92 | return 93 | 94 | action = args[1].lower() 95 | target_user_id = int(args[2]) 96 | 97 | if action == "add": 98 | if target_user_id not in SUDO_USERS: 99 | SUDO_USERS.append(target_user_id) 100 | await message.reply_text(f"**✅ User {target_user_id} added to sudo list.**") 101 | else: 102 | await message.reply_text(f"**⚠️ User {target_user_id} is already in the sudo list.**") 103 | elif action == "remove": 104 | if target_user_id == OWNER_ID: 105 | await message.reply_text("**🚫 The owner cannot be removed from the sudo list.**") 106 | elif target_user_id in SUDO_USERS: 107 | SUDO_USERS.remove(target_user_id) 108 | await message.reply_text(f"**✅ User {target_user_id} removed from sudo list.**") 109 | else: 110 | await message.reply_text(f"**⚠️ User {target_user_id} is not in the sudo list.**") 111 | else: 112 | await message.reply_text("**Usage:** `/sudo add ` or `/sudo remove `") 113 | except Exception as e: 114 | await message.reply_text(f"**Error:** {str(e)}") 115 | 116 | # Inline keyboard for start command 117 | keyboard = InlineKeyboardMarkup( 118 | [ 119 | [ 120 | InlineKeyboardButton("🇮🇳ʙᴏᴛ ᴍᴀᴅᴇ ʙʏ🇮🇳" ,url=f"https://t.me/Tushar0125") ], 121 | [ 122 | InlineKeyboardButton("🔔ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟ🔔" ,url="https://t.me/TxtToVideoUpdateChannel") ], 123 | [ 124 | InlineKeyboardButton("🦋ғᴏʟʟᴏᴡ ᴜs🦋" ,url="https://t.me/TxtToVideoUpdateChannel") 125 | ], 126 | ] 127 | ) 128 | 129 | # Image URLs for the random image feature 130 | image_urls = [ 131 | "https://graph.org/file/996d4fc24564509244988-a7d93d020c96973ba8.jpg", 132 | "https://graph.org/file/96d25730136a3ea7e48de-b0a87a529feb485c8f.jpg", 133 | "https://graph.org/file/6593f76ddd8c735ae3ce2-ede9fa2df40079b8a0.jpg", 134 | "https://graph.org/file/a5dcdc33020aa7a488590-79e02b5a397172cc35.jpg", 135 | "https://graph.org/file/0346106a432049e391181-7560294e8652f9d49d.jpg", 136 | "https://graph.org/file/ba49ebe9a8e387addbcdc-be34c4cd4432616699.jpg", 137 | "https://graph.org/file/26f98dec8b3966687051f-557a430bf36b660e24.jpg", 138 | "https://graph.org/file/2ae78907fa4bbf3160ffa-2d69cd23fa75cb0c3a.jpg", 139 | "https://graph.org/file/05ef9478729f165809dd7-3df2f053d2842ed098.jpg", 140 | "https://graph.org/file/b1330861fed21c4d7275c-0f95cca72c531382c1.jpg", 141 | "https://graph.org/file/0ebb95807047b062e402a-9e670a0821d74e3306.jpg", 142 | "https://graph.org/file/b4e5cfd4932d154ad6178-7559c5266426c0a399.jpg", 143 | "https://graph.org/file/44ffab363c1a2647989bc-00e22c1e36a9fd4156.jpg", 144 | "https://graph.org/file/5f0980969b54bb13f2a8a-a3e131c00c81c19582.jpg", 145 | "https://graph.org/file/6341c0aa94c803f94cdb5-225b2999a89ff87e39.jpg", 146 | "https://graph.org/file/90c9f79ec52e08e5a3025-f9b73e9d17f3da5040.jpg", 147 | "https://graph.org/file/1aaf27a49b6bd81692064-30016c0a382f9ae22b.jpg", 148 | "https://graph.org/file/702aa31236364e4ebb2be-3f88759834a4b164a0.jpg", 149 | "https://graph.org/file/d0c6b9f6566a564cd7456-27fb594d26761d3dc0.jpg", 150 | # Add more image URLs as needed 151 | ] 152 | random_image_url = random.choice(image_urls) 153 | # Caption for the image 154 | caption = ( 155 | "**ʜᴇʟʟᴏ👋**\n\n" 156 | "➠ **ɪ ᴀᴍ ᴛxᴛ ᴛᴏ ᴠɪᴅᴇᴏ ᴜᴘʟᴏᴀᴅᴇʀ ʙᴏᴛ.**\n" 157 | "➠ **ғᴏʀ ᴜsᴇ ᴍᴇ sᴇɴᴅ /tushar.\n" 158 | "➠ **ғᴏʀ ɢᴜɪᴅᴇ sᴇɴᴅ /help." 159 | ) 160 | 161 | # Start command handler 162 | @bot.on_message(filters.command(["start"])) 163 | async def start_command(bot: Client, message: Message): 164 | await bot.send_photo(chat_id=message.chat.id, photo=random_image_url, caption=caption, reply_markup=keyboard) 165 | 166 | # Stop command handler 167 | @bot.on_message(filters.command("stop")) 168 | async def restart_handler(_, m: Message): 169 | await m.reply_text("**𝗦𝘁𝗼𝗽𝗽𝗲𝗱**🚦", True) 170 | os.execl(sys.executable, sys.executable, *sys.argv) 171 | 172 | @bot.on_message(filters.command("restart")) 173 | async def restart_handler(_, m): 174 | if not is_authorized(m.from_user.id): 175 | await m.reply_text("**🚫 You are not authorized to use this command.**") 176 | return 177 | await m.reply_text("🔮Restarted🔮", True) 178 | os.execl(sys.executable, sys.executable, *sys.argv) 179 | 180 | 181 | COOKIES_FILE_PATH = "youtube_cookies.txt" 182 | 183 | @bot.on_message(filters.command("cookies") & filters.private) 184 | async def cookies_handler(client: Client, m: Message): 185 | if not is_authorized(m.from_user.id): 186 | await m.reply_text("🚫 You are not authorized to use this command.") 187 | return 188 | """ 189 | Command: /cookies 190 | Allows any user to upload a cookies file dynamically. 191 | """ 192 | await m.reply_text( 193 | "𝗣𝗹𝗲𝗮𝘀𝗲 𝗨𝗽𝗹𝗼𝗮𝗱 𝗧𝗵𝗲 𝗖𝗼𝗼𝗸𝗶𝗲𝘀 𝗙𝗶𝗹𝗲 (.𝘁𝘅𝘁 𝗳𝗼𝗿𝗺𝗮𝘁).", 194 | quote=True 195 | ) 196 | 197 | try: 198 | # Wait for the user to send the cookies file 199 | input_message: Message = await client.listen(m.chat.id) 200 | 201 | # Validate the uploaded file 202 | if not input_message.document or not input_message.document.file_name.endswith(".txt"): 203 | await m.reply_text("Invalid file type. Please upload a .txt file.") 204 | return 205 | 206 | # Download the cookies file 207 | downloaded_path = await input_message.download() 208 | 209 | # Read the content of the uploaded file 210 | with open(downloaded_path, "r") as uploaded_file: 211 | cookies_content = uploaded_file.read() 212 | 213 | # Replace the content of the target cookies file 214 | with open(COOKIES_FILE_PATH, "w") as target_file: 215 | target_file.write(cookies_content) 216 | 217 | await input_message.reply_text( 218 | "✅ 𝗖𝗼𝗼𝗸𝗶𝗲𝘀 𝗨𝗽𝗱𝗮𝘁𝗲𝗱 𝗦𝘂𝗰𝗰𝗲𝘀𝘀𝗳𝘂𝗹𝗹𝘆.\n\𝗻📂 𝗦𝗮𝘃𝗲𝗱 𝗜𝗻 youtube_cookies.txt." 219 | ) 220 | 221 | except Exception as e: 222 | await m.reply_text(f"⚠️ An error occurred: {str(e)}") 223 | 224 | # Define paths for uploaded file and processed file 225 | UPLOAD_FOLDER = '/path/to/upload/folder' 226 | EDITED_FILE_PATH = '/path/to/save/edited_output.txt' 227 | 228 | @bot.on_message(filters.command('e2t')) 229 | async def edit_txt(client, message: Message): 230 | 231 | 232 | # Prompt the user to upload the .txt file 233 | await message.reply_text( 234 | "🎉 **Welcome to the .txt File Editor!**\n\n" 235 | "Please send your `.txt` file containing subjects, links, and topics." 236 | ) 237 | 238 | # Wait for the user to upload the file 239 | input_message: Message = await bot.listen(message.chat.id) 240 | if not input_message.document: 241 | await message.reply_text("🚨 **Error**: Please upload a valid `.txt` file.") 242 | return 243 | 244 | # Get the file name 245 | file_name = input_message.document.file_name.lower() 246 | 247 | # Define the path where the file will be saved 248 | uploaded_file_path = os.path.join(UPLOAD_FOLDER, file_name) 249 | 250 | # Download the file 251 | uploaded_file = await input_message.download(uploaded_file_path) 252 | 253 | # After uploading the file, prompt the user for the file name or 'd' for default 254 | await message.reply_text( 255 | "🔄 **Send your .txt file name, or type 'd' for the default file name.**" 256 | ) 257 | 258 | # Wait for the user's response 259 | user_response: Message = await bot.listen(message.chat.id) 260 | if user_response.text: 261 | user_response_text = user_response.text.strip().lower() 262 | if user_response_text == 'd': 263 | # Handle default file name logic (e.g., use the original file name) 264 | final_file_name = file_name 265 | else: 266 | final_file_name = user_response_text + '.txt' 267 | else: 268 | final_file_name = file_name # Default to the uploaded file name 269 | 270 | # Read and process the uploaded file 271 | try: 272 | with open(uploaded_file, 'r', encoding='utf-8') as f: 273 | content = f.readlines() 274 | except Exception as e: 275 | await message.reply_text(f"🚨 **Error**: Unable to read the file.\n\nDetails: {e}") 276 | return 277 | 278 | # Parse the content into subjects with links and topics 279 | subjects = {} 280 | current_subject = None 281 | for line in content: 282 | line = line.strip() 283 | if line and ":" in line: 284 | # Split the line by the first ":" to separate title and URL 285 | title, url = line.split(":", 1) 286 | title, url = title.strip(), url.strip() 287 | 288 | # Add the title and URL to the dictionary 289 | if title in subjects: 290 | subjects[title]["links"].append(url) 291 | else: 292 | subjects[title] = {"links": [url], "topics": []} 293 | 294 | # Set the current subject 295 | current_subject = title 296 | elif line.startswith("-") and current_subject: 297 | # Add topics under the current subject 298 | subjects[current_subject]["topics"].append(line.strip("- ").strip()) 299 | 300 | # Sort the subjects alphabetically and topics within each subject 301 | sorted_subjects = sorted(subjects.items()) 302 | for title, data in sorted_subjects: 303 | data["topics"].sort() 304 | 305 | # Save the edited file to the defined path with the final file name 306 | try: 307 | final_file_path = os.path.join(UPLOAD_FOLDER, final_file_name) 308 | with open(final_file_path, 'w', encoding='utf-8') as f: 309 | for title, data in sorted_subjects: 310 | # Write title and its links 311 | for link in data["links"]: 312 | f.write(f"{title}:{link}\n") 313 | # Write topics under the title 314 | for topic in data["topics"]: 315 | f.write(f"- {topic}\n") 316 | except Exception as e: 317 | await message.reply_text(f"🚨 **Error**: Unable to write the edited file.\n\nDetails: {e}") 318 | return 319 | 320 | # Send the sorted and edited file back to the user 321 | try: 322 | await message.reply_document( 323 | document=final_file_path, 324 | caption="📥**𝗘𝗱𝗶𝘁𝗲𝗱 𝗕𝘆 ➤ 𝗧𝘂𝘀𝗵𝗮𝗿**" 325 | ) 326 | except Exception as e: 327 | await message.reply_text(f"🚨 **Error**: Unable to send the file.\n\nDetails: {e}") 328 | finally: 329 | # Clean up the temporary file 330 | if os.path.exists(uploaded_file_path): 331 | os.remove(uploaded_file_path) 332 | 333 | from pytube import Playlist 334 | import youtube_dl 335 | 336 | # --- Configuration --- 337 | logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") 338 | 339 | # --- Utility Functions --- 340 | 341 | def sanitize_filename(name): 342 | """ 343 | Sanitizes a string to create a valid filename. 344 | """ 345 | return re.sub(r'[^\w\s-]', '', name).strip().replace(' ', '_') 346 | 347 | def get_videos_with_ytdlp(url): 348 | """ 349 | Retrieves video titles and URLs using `yt-dlp`. 350 | If a title is not available, only the URL is saved. 351 | """ 352 | ydl_opts = { 353 | 'quiet': True, 354 | 'extract_flat': True, 355 | 'skip_download': True, 356 | } 357 | try: 358 | with YoutubeDL(ydl_opts) as ydl: 359 | result = ydl.extract_info(url, download=False) 360 | if 'entries' in result: 361 | title = result.get('title', 'Unknown Title') 362 | videos = {} 363 | for entry in result['entries']: 364 | video_url = entry.get('url', None) 365 | video_title = entry.get('title', None) 366 | if video_url: 367 | videos[video_title if video_title else "Unknown Title"] = video_url 368 | return title, videos 369 | return None, None 370 | except Exception as e: 371 | logging.error(f"Error retrieving videos: {e}") 372 | return None, None 373 | 374 | def save_to_file(videos, name): 375 | """ 376 | Saves video titles and URLs to a .txt file. 377 | If a title is unavailable, only the URL is saved. 378 | """ 379 | filename = f"{sanitize_filename(name)}.txt" 380 | with open(filename, 'w', encoding='utf-8') as file: 381 | for title, url in videos.items(): 382 | if title == "Unknown Title": 383 | file.write(f"{url}\n") 384 | else: 385 | file.write(f"{title}: {url}\n") 386 | return filename 387 | 388 | # --- Bot Command --- 389 | 390 | @bot.on_message(filters.command('yt2txt')) 391 | async def ytplaylist_to_txt(client: Client, message: Message): 392 | """ 393 | Handles the extraction of YouTube playlist/channel videos and sends a .txt file. 394 | """ 395 | user_id = message.chat.id 396 | if user_id != OWNER_ID: 397 | await message.reply_text("**🚫 You are not authorized to use this command.\n\n🫠 This Command is only for owner.**") 398 | return 399 | 400 | # Request YouTube URL 401 | await message.delete() 402 | editable = await message.reply_text("📥 **Please enter the YouTube Playlist Url :**") 403 | input_msg = await client.listen(editable.chat.id) 404 | youtube_url = input_msg.text 405 | await input_msg.delete() 406 | await editable.delete() 407 | 408 | # Process the URL 409 | title, videos = get_videos_with_ytdlp(youtube_url) 410 | if videos: 411 | file_name = save_to_file(videos, title) 412 | await message.reply_document( 413 | document=file_name, 414 | caption=f"`{title}`\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ 𝗧𝘂𝘀𝗵𝗮𝗿" 415 | ) 416 | os.remove(file_name) 417 | else: 418 | await message.reply_text("⚠️ **Unable to retrieve videos. Please check the URL.**") 419 | 420 | 421 | # List users command 422 | @bot.on_message(filters.command("userlist") & filters.user(SUDO_USERS)) 423 | async def list_users(client: Client, msg: Message): 424 | if SUDO_USERS: 425 | users_list = "\n".join([f"User ID : `{user_id}`" for user_id in SUDO_USERS]) 426 | await msg.reply_text(f"SUDO_USERS :\n{users_list}") 427 | else: 428 | await msg.reply_text("No sudo users.") 429 | 430 | 431 | # Help command 432 | @bot.on_message(filters.command("help")) 433 | async def help_command(client: Client, msg: Message): 434 | help_text = ( 435 | "`/start` - Start the bot⚡\n\n" 436 | "`/tushar` - Download and upload files (sudo)🎬\n\n" 437 | "`/restart` - Restart the bot🔮\n\n" 438 | "`/stop` - Stop ongoing process🛑\n\n" 439 | "`/cookies` - Upload cookies file🍪\n\n" 440 | "`/e2t` - Edit txt file📝\n\n" 441 | "`/yt2txt` - Create txt of yt playlist (owner)🗃️\n\n" 442 | "`/sudo add` - Add user or group or channel (owner)🎊\n\n" 443 | "`/sudo remove` - Remove user or group or channel (owner)❌\n\n" 444 | "`/userlist` - List of sudo user or group or channel📜\n\n" 445 | 446 | ) 447 | await msg.reply_text(help_text) 448 | 449 | # Upload command handler 450 | @bot.on_message(filters.command(["tushar"])) 451 | async def upload(bot: Client, m: Message): 452 | if not is_authorized(m.chat.id): 453 | await m.reply_text("**🚫You are not authorized to use this bot.**") 454 | return 455 | 456 | editable = await m.reply_text(f"⚡𝗦𝗘𝗡𝗗 𝗧𝗫𝗧 𝗙𝗜𝗟𝗘⚡") 457 | input: Message = await bot.listen(editable.chat.id) 458 | x = await input.download() 459 | await input.delete(True) 460 | file_name, ext = os.path.splitext(os.path.basename(x)) 461 | pdf_count = 0 462 | img_count = 0 463 | zip_count = 0 464 | video_count = 0 465 | 466 | try: 467 | with open(x, "r") as f: 468 | content = f.read() 469 | content = content.split("\n") 470 | 471 | links = [] 472 | for i in content: 473 | if "://" in i: 474 | url = i.split("://", 1)[1] 475 | links.append(i.split("://", 1)) 476 | if ".pdf" in url: 477 | pdf_count += 1 478 | elif url.endswith((".png", ".jpeg", ".jpg")): 479 | img_count += 1 480 | elif ".zip" in url: 481 | zip_count += 1 482 | else: 483 | video_count += 1 484 | os.remove(x) 485 | except: 486 | await m.reply_text("😶𝗜𝗻𝘃𝗮𝗹𝗶𝗱 𝗙𝗶𝗹𝗲 𝗜𝗻𝗽𝘂𝘁😶") 487 | os.remove(x) 488 | return 489 | 490 | await editable.edit(f"`𝗧𝗼𝘁𝗮𝗹 🔗 𝗟𝗶𝗻𝗸𝘀 𝗙𝗼𝘂𝗻𝗱 𝗔𝗿𝗲 {len(links)}\n\n🔹Img : {img_count} 🔹Pdf : {pdf_count}\n🔹Zip : {zip_count} 🔹Video : {video_count}\n\n𝗦𝗲𝗻𝗱 𝗙𝗿𝗼𝗺 𝗪𝗵𝗲𝗿𝗲 𝗬𝗼𝘂 𝗪𝗮𝗻𝘁 𝗧𝗼 𝗗𝗼𝘄𝗻𝗹𝗼𝗮𝗱.`") 491 | input0: Message = await bot.listen(editable.chat.id) 492 | raw_text = input0.text 493 | await input0.delete(True) 494 | try: 495 | arg = int(raw_text) 496 | except: 497 | arg = 1 498 | await editable.edit("📚 𝗘𝗻𝘁𝗲𝗿 𝗬𝗼𝘂𝗿 𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 📚\n\n🦠 𝗦𝗲𝗻𝗱 `1` 𝗙𝗼𝗿 𝗨𝘀𝗲 𝗗𝗲𝗳𝗮𝘂𝗹𝘁 🦠") 499 | input1: Message = await bot.listen(editable.chat.id) 500 | raw_text0 = input1.text 501 | await input1.delete(True) 502 | if raw_text0 == '1': 503 | b_name = file_name 504 | else: 505 | b_name = raw_text0 506 | 507 | 508 | await editable.edit("**📸 𝗘𝗻𝘁𝗲𝗿 𝗥𝗲𝘀𝗼𝗹𝘂𝘁𝗶𝗼𝗻 📸**\n➤ `144`\n➤ `240`\n➤ `360`\n➤ `480`\n➤ `720`\n➤ `1080`") 509 | input2: Message = await bot.listen(editable.chat.id) 510 | raw_text2 = input2.text 511 | await input2.delete(True) 512 | try: 513 | if raw_text2 == "144": 514 | res = "256x144" 515 | elif raw_text2 == "240": 516 | res = "426x240" 517 | elif raw_text2 == "360": 518 | res = "640x360" 519 | elif raw_text2 == "480": 520 | res = "854x480" 521 | elif raw_text2 == "720": 522 | res = "1280x720" 523 | elif raw_text2 == "1080": 524 | res = "1920x1080" 525 | else: 526 | res = "UN" 527 | except Exception: 528 | res = "UN" 529 | 530 | 531 | 532 | await editable.edit("📛 𝗘𝗻𝘁𝗲𝗿 𝗬𝗼𝘂𝗿 𝗡𝗮𝗺𝗲 📛\n\n🐥 𝗦𝗲𝗻𝗱 `1` 𝗙𝗼𝗿 𝗨𝘀𝗲 𝗗𝗲𝗳𝗮𝘂𝗹𝘁 🐥") 533 | input3: Message = await bot.listen(editable.chat.id) 534 | raw_text3 = input3.text 535 | await input3.delete(True) 536 | # Default credit message with link 537 | credit = "️[𝗧𝘂𝘀𝗵𝗮𝗿](https://t.me/Tushar0125)" 538 | if raw_text3 == '1': 539 | CR = '[𝗧𝘂𝘀𝗵𝗮𝗿](https://t.me/Tushar0125)' 540 | elif raw_text3: 541 | try: 542 | text, link = raw_text3.split(',') 543 | CR = f'[{text.strip()}]({link.strip()})' 544 | except ValueError: 545 | CR = raw_text3 # In case the input is not in the expected format, use the raw text 546 | else: 547 | CR = credit 548 | #highlighter = f"️ " 549 | #if raw_text3 == 'Robin': 550 | #MR = highlighter 551 | #else: 552 | #MR = raw_text3 553 | 554 | await editable.edit("**𝗘𝗻𝘁𝗲𝗿 𝗣𝘄 𝗧𝗼𝗸𝗲𝗻 𝗙𝗼𝗿 𝗣𝘄 𝗨𝗽𝗹𝗼𝗮𝗱𝗶𝗻𝗴 𝗼𝗿 𝗦𝗲𝗻𝗱 `3` 𝗙𝗼𝗿 𝗢𝘁𝗵𝗲𝗿𝘀**") 555 | input4: Message = await bot.listen(editable.chat.id) 556 | raw_text4 = input4.text 557 | await input4.delete(True) 558 | if raw_text4 == 3: 559 | MR = token 560 | else: 561 | MR = raw_text4 562 | 563 | 564 | 565 | await editable.edit("𝗡𝗼𝘄 𝗦𝗲𝗻𝗱 𝗧𝗵𝗲 𝗧𝗵𝘂𝗺𝗯 𝗨𝗿𝗹 𝗘𝗴 » https://graph.org/file/13a89d77002442255efad-989ac290c1b3f13b44.jpg\n\n𝗢𝗿 𝗜𝗳 𝗗𝗼𝗻'𝘁 𝗪𝗮𝗻𝘁 𝗧𝗵𝘂𝗺𝗯𝗻𝗮𝗶𝗹 𝗦𝗲𝗻𝗱 = 𝗻𝗼") 566 | input6 = message = await bot.listen(editable.chat.id) 567 | raw_text6 = input6.text 568 | await input6.delete(True) 569 | await editable.delete() 570 | 571 | #thumb = input6.text 572 | #if thumb.startswith("http://") or thumb.startswith("https://"): 573 | #getstatusoutput(f"wget '{thumb}' -O 'thumb.jpg'") 574 | #thumb = "thumb.jpg" 575 | else: 576 | thumb == "no" 577 | failed_count =0 578 | if len(links) == 1: 579 | count = 1 580 | else: 581 | count = int(raw_text) 582 | 583 | try: 584 | for i in range(count - 1, len(links)): 585 | V = links[i][1].replace("file/d/","uc?export=download&id=").replace("www.youtube-nocookie.com/embed", "youtu.be").replace("?modestbranding=1", "").replace("/view?usp=sharing","") # .replace("mpd","m3u8") 586 | url = "https://" + V 587 | 588 | if "visionias" in url: 589 | async with ClientSession() as session: 590 | async with session.get(url, headers={'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Language': 'en-US,en;q=0.9', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Pragma': 'no-cache', 'Referer': 'http://www.visionias.in/', 'Sec-Fetch-Dest': 'iframe', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'cross-site', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; RMX2121) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36', 'sec-ch-ua': '"Chromium";v="107", "Not=A?Brand";v="24"', 'sec-ch-ua-mobile': '?1', 'sec-ch-ua-platform': '"Android"',}) as resp: 591 | text = await resp.text() 592 | url = re.search(r"(https://.*?playlist.m3u8.*?)\"", text).group(1) 593 | 594 | elif 'media-cdn.classplusapp.com/drm/' in url: 595 | url = f"https://dragoapi.vercel.app/video/{url}" 596 | 597 | elif 'videos.classplusapp' in url: 598 | url = requests.get(f'https://api.classplusapp.com/cams/uploader/video/jw-signed-url?url={url}', headers={'x-access-token': 'eyJjb3Vyc2VJZCI6IjQ1NjY4NyIsInR1dG9ySWQiOm51bGwsIm9yZ0lkIjo0ODA2MTksImNhdGVnb3J5SWQiOm51bGx9'}).json()['url'] 599 | 600 | elif "tencdn.classplusapp" in url or "media-cdn-alisg.classplusapp.com" in url or "videos.classplusapp" in url or "media-cdn.classplusapp" in url: 601 | headers = {'Host': 'api.classplusapp.com', 'x-access-token': 'eyJjb3Vyc2VJZCI6IjQ1NjY4NyIsInR1dG9ySWQiOm51bGwsIm9yZ0lkIjo0ODA2MTksImNhdGVnb3J5SWQiOm51bGx9', 'user-agent': 'Mobile-Android', 'app-version': '1.4.37.1', 'api-version': '18', 'device-id': '5d0d17ac8b3c9f51', 'device-details': '2848b866799971ca_2848b8667a33216c_SDK-30', 'accept-encoding': 'gzip'} 602 | params = (('url', f'{url}'),) 603 | response = requests.get('https://api.classplusapp.com/cams/uploader/video/jw-signed-url', headers=headers, params=params) 604 | url = response.json()['url'] 605 | 606 | elif "https://appx-transcoded-videos.livelearn.in/videos/rozgar-data/" in url: 607 | url = url.replace("https://appx-transcoded-videos.livelearn.in/videos/rozgar-data/", "") 608 | name1 = links[i][0].replace("\t", "").replace(":", "").replace("/", "").replace("+", "").replace("#", "").replace("|", "").replace("@", "@").replace("*", "").replace(".", "").replace("https", "").replace("http", "").strip() 609 | name = f'{str(count).zfill(3)}) {name1[:60]}' 610 | cmd = f'yt-dlp -o "{name}.mp4" "{url}"' 611 | 612 | elif "https://appx-transcoded-videos-mcdn.akamai.net.in/videos/bhainskipathshala-data/" in url: 613 | url = url.replace("https://appx-transcoded-videos-mcdn.akamai.net.in/videos/bhainskipathshala-data/", "") 614 | name1 = links[i][0].replace("\t", "").replace(":", "").replace("/", "").replace("+", "").replace("#", "").replace("|", "").replace("@", "@").replace("*", "").replace(".", "").replace("https", "").replace("http", "").strip() 615 | name = f'{str(count).zfill(3)}) {name1[:60]}' 616 | cmd = f'yt-dlp -o "{name}.mp4" "{url}"' 617 | 618 | elif "apps-s3-jw-prod.utkarshapp.com" in url: 619 | if 'enc_plain_mp4' in url: 620 | url = url.replace(url.split("/")[-1], res+'.mp4') 621 | 622 | elif 'Key-Pair-Id' in url: 623 | url = None 624 | 625 | elif '.m3u8' in url: 626 | q = ((m3u8.loads(requests.get(url).text)).data['playlists'][1]['uri']).split("/")[0] 627 | x = url.split("/")[5] 628 | x = url.replace(x, "") 629 | url = ((m3u8.loads(requests.get(url).text)).data['playlists'][1]['uri']).replace(q+"/", x) 630 | #elif '/master.mpd' in url: 631 | #id = url.split("/")[-2] 632 | #url = f"https://player.muftukmall.site/?id={id}" 633 | elif "/master.mpd" in url or "d1d34p8vz63oiq" in url or "sec1.pw.live" in url: 634 | id = url.split("/")[-2] 635 | #url = f"https://anonymouspwplayer-b99f57957198.herokuapp.com/pw?url={url}?token={raw_text4}" 636 | url = f"https://anonymouspwplayerr-f996115ea61a.herokuapp.com/pw?url={url}&token={raw_text4}" 637 | #url = f"https://madxabhi-pw.onrender.com/{id}/master.m3u8?token={raw_text4}" 638 | #elif '/master.mpd' in url: 639 | #id = url.split("/")[-2] 640 | #url = f"https://dl.alphacbse.site/download/{id}/master.m3u8" 641 | 642 | 643 | name1 = links[i][0].replace("\t", "").replace(":", "").replace("/", "").replace("+", "").replace("#", "").replace("|", "").replace("@", "").replace("*", "").replace(".", "").replace("https", "").replace("http", "").strip() 644 | name = f'{str(count).zfill(3)}) {name1[:60]}' 645 | 646 | #if 'cpvod.testbook' in url: 647 | #CPVOD = url.split("/")[-2] 648 | #url = requests.get(f'https://extractbot.onrender.com/classplus?link=https://cpvod.testbook.com/{CPVOD}/playlist.m3u8', headers={'x-access-token': 'eyJjb3Vyc2VJZCI6IjQ1NjY4NyIsInR1dG9ySWQiOm51bGwsIm9yZ0lkIjo0ODA2MTksImNhdGVnb3J5SWQiOm51bGx9r'}).json()['url'] 649 | 650 | #if 'cpvod.testbook' in url: 651 | #url = requests.get(f'https://mon-key-3612a8154345.herokuapp.com/get_keys?url=https://cpvod.testbook.com/{CPVOD}/playlist.m3u8', headers={'x-access-token': 'eyJjb3Vyc2VJZCI6IjQ1NjY4NyIsInR1dG9ySWQiOm51bGwsIm9yZ0lkIjo0ODA2MTksImNhdGVnb3J5SWQiOm51bGx9r'}).json()['url'] 652 | 653 | 654 | if 'khansirvod4.pc.cdn.bitgravity.com' in url: 655 | parts = url.split('/') 656 | part1 = parts[1] 657 | part2 = parts[2] 658 | part3 = parts[3] 659 | part4 = parts[4] 660 | part5 = parts[5] 661 | 662 | print(f"PART1: {part1}") 663 | print(f"PART2: {part2}") 664 | print(f"PART3: {part3}") 665 | print(f"PART4: {part4}") 666 | print(f"PART5: {part5}") 667 | url = f"https://kgs-v4.akamaized.net/kgs-cv/{part3}/{part4}/{part5}" 668 | 669 | if "youtu" in url: 670 | ytf = f"b[height<={raw_text2}][ext=mp4]/bv[height<={raw_text2}][ext=mp4]+ba[ext=m4a]/b[ext=mp4]" 671 | else: 672 | ytf = f"b[height<={raw_text2}]/bv[height<={raw_text2}]+ba/b/bv+ba" 673 | 674 | if "edge.api.brightcove.com" in url: 675 | bcov = 'bcov_auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3MzUxMzUzNjIsImNvbiI6eyJpc0FkbWluIjpmYWxzZSwiYXVzZXIiOiJVMFZ6TkdGU2NuQlZjR3h5TkZwV09FYzBURGxOZHowOSIsImlkIjoiYmt3cmVIWmxZMFUwVXpkSmJYUkxVemw2ZW5Oclp6MDkiLCJmaXJzdF9uYW1lIjoiY25GdVpVdG5kRzR4U25sWVNGTjRiVW94VFhaUVVUMDkiLCJlbWFpbCI6ImFFWllPRXhKYVc1NWQyTlFTazk0YmtWWWJISTNRM3BKZW1OUVdIWXJWWE0wWldFNVIzZFNLelE0ZHowPSIsInBob25lIjoiZFhSNlFrSm9XVlpCYkN0clRUWTFOR3REU3pKTVVUMDkiLCJhdmF0YXIiOiJLM1ZzY1M4elMwcDBRbmxrYms4M1JEbHZla05pVVQwOSIsInJlZmVycmFsX2NvZGUiOiJhVVZGZGpBMk9XSnhlbXRZWm14amF6TTBVazQxUVQwOSIsImRldmljZV90eXBlIjoid2ViIiwiZGV2aWNlX3ZlcnNpb24iOiJDaHJvbWUrMTE5IiwiZGV2aWNlX21vZGVsIjoiY2hyb21lIiwicmVtb3RlX2FkZHIiOiIyNDA5OjQwYzI6MjA1NTo5MGQ0OjYzYmM6YTNjOTozMzBiOmIxOTkifX0.Kifitj1wCe_ohkdclvUt7WGuVBsQFiz7eezXoF1RduDJi4X7egejZlLZ0GCZmEKBwQpMJLvrdbAFIRniZoeAxL4FZ-pqIoYhH3PgZU6gWzKz5pdOCWfifnIzT5b3rzhDuG7sstfNiuNk9f-HMBievswEIPUC_ElazXdZPPt1gQqP7TmVg2Hjj6-JBcG7YPSqa6CUoXNDHpjWxK_KREnjWLM7vQ6J3vF1b7z_S3_CFti167C6UK5qb_turLnOUQzWzcwEaPGB3WXO0DAri6651WF33vzuzeclrcaQcMjum8n7VQ0Cl3fqypjaWD30btHQsu5j8j3pySWUlbyPVDOk-g' 676 | url = url.split("bcov_auth")[0]+bcov 677 | 678 | if "jw-prod" in url: 679 | cmd = f'yt-dlp -o "{name}.mp4" "{url}"' 680 | 681 | elif "webvideos.classplusapp." in url: 682 | cmd = f'yt-dlp --add-header "referer:https://web.classplusapp.com/" --add-header "x-cdn-tag:empty" -f "{ytf}" "{url}" -o "{name}.mp4"' 683 | 684 | elif "youtube.com" in url or "youtu.be" in url: 685 | cmd = f'yt-dlp --cookies youtube_cookies.txt -f "{ytf}" "{url}" -o "{name}".mp4' 686 | 687 | else: 688 | cmd = f'yt-dlp -f "{ytf}" "{url}" -o "{name}.mp4"' 689 | 690 | try: 691 | cc = f'**[🎬] 𝗩𝗶𝗱_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.({res}).𝔗𝔲𝔰𝔥𝔞𝔯.mkv\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 692 | #cpw = f'**[🎬] 𝗩𝗶𝗱_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.({res}).𝔗𝔲𝔰𝔥𝔞𝔯.mkv\n\n\n🔗𝗩𝗶𝗱𝗲𝗼 𝗨𝗿𝗹 ➤ __Click Here to Watch Video__\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 693 | #cyt = f'**[🎬] 𝗩𝗶𝗱_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.({res}).𝔗𝔲𝔰𝔥𝔞𝔯.mp4\n\n\n🔗𝗩𝗶𝗱𝗲𝗼 𝗨𝗿𝗹 ➤ __Click Here to Watch Video__\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 694 | cpvod = f'**[🎬] 𝗩𝗶𝗱_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.({res}).𝔗𝔲𝔰𝔥𝔞𝔯.mkv\n\n\n🔗𝗩𝗶𝗱𝗲𝗼 𝗨𝗿𝗹 ➤ __Click Here to Watch Video__\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 695 | cimg = f'**[📁] 𝗜𝗺𝗴_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.𝔗𝔲𝔰𝔥𝔞𝔯.jpg\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 696 | cczip = f'**[📁] 𝗣𝗱𝗳_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.𝔗𝔲𝔰𝔥𝔞𝔯.zip\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 697 | cc1 = f'**[📁] 𝗣𝗱𝗳_𝗜𝗱 : {str(count).zfill(3)}.\n\n\n☘️𝗧𝗶𝘁𝗹𝗲 𝗡𝗮𝗺𝗲 ➤ {name1}.𝔗𝔲𝔰𝔥𝔞𝔯.pdf\n\n\n
📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 ➤ {b_name}
\n\n\n📥 𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤ {CR}**' 698 | 699 | if "drive" in url: 700 | try: 701 | ka = await helper.download(url, name) 702 | copy = await bot.send_document(chat_id=m.chat.id,document=ka, caption=cc1) 703 | count+=1 704 | os.remove(ka) 705 | time.sleep(1) 706 | except FloodWait as e: 707 | await m.reply_text(str(e)) 708 | time.sleep(e.x) 709 | continue 710 | 711 | elif ".pdf" in url: 712 | try: 713 | await asyncio.sleep(4) 714 | # Replace spaces with %20 in the URL 715 | url = url.replace(" ", "%20") 716 | 717 | # Create a cloudscraper session 718 | scraper = cloudscraper.create_scraper() 719 | 720 | # Send a GET request to download the PDF 721 | response = scraper.get(url) 722 | 723 | # Check if the response status is OK 724 | if response.status_code == 200: 725 | # Write the PDF content to a file 726 | with open(f'{name}.pdf', 'wb') as file: 727 | file.write(response.content) 728 | 729 | # Send the PDF document 730 | await asyncio.sleep(4) 731 | copy = await bot.send_document(chat_id=m.chat.id, document=f'{name}.pdf', caption=cc1) 732 | count += 1 733 | 734 | # Remove the PDF file after sending 735 | os.remove(f'{name}.pdf') 736 | else: 737 | await m.reply_text(f"Failed to download PDF: {response.status_code} {response.reason}") 738 | 739 | except FloodWait as e: 740 | await m.reply_text(str(e)) 741 | time.sleep(e.x) 742 | continue 743 | 744 | #elif "muftukmall" in url: 745 | #try: 746 | #await bot.send_photo(chat_id=m.chat.id, photo=pwimg, caption=cpw) 747 | #count +=1 748 | #except Exception as e: 749 | #await m.reply_text(str(e)) 750 | #time.sleep(1) 751 | #continue 752 | 753 | #elif "youtu" in url: 754 | #try: 755 | #await bot.send_photo(chat_id=m.chat.id, photo=ytimg, caption=cyt) 756 | #count +=1 757 | #except Exception as e: 758 | #await m.reply_text(str(e)) 759 | #time.sleep(1) 760 | #continue 761 | 762 | elif "media-cdn.classplusapp.com/drm/" in url: 763 | try: 764 | await bot.send_photo(chat_id=m.chat.id, photo=cpimg, caption=cpvod) 765 | count +=1 766 | except Exception as e: 767 | await m.reply_text(str(e)) 768 | time.sleep(1) 769 | continue 770 | 771 | 772 | elif any(ext in url.lower() for ext in [".jpg", ".jpeg", ".png"]): 773 | try: 774 | await asyncio.sleep(4) # Use asyncio.sleep for non-blocking sleep 775 | # Replace spaces with %20 in the URL 776 | url = url.replace(" ", "%20") 777 | 778 | # Create a cloudscraper session for image download 779 | scraper = cloudscraper.create_scraper() 780 | 781 | # Send a GET request to download the image 782 | response = scraper.get(url) 783 | 784 | # Check if the response status is OK 785 | if response.status_code == 200: 786 | # Write the image content to a file 787 | with open(f'{name}.jpg', 'wb') as file: # Save as JPG (or PNG if you want) 788 | file.write(response.content) 789 | 790 | # Send the image document 791 | await asyncio.sleep(2) # Non-blocking sleep 792 | copy = await bot.send_photo(chat_id=m.chat.id, photo=f'{name}.jpg', caption=cimg) 793 | count += 1 794 | 795 | # Remove the image file after sending 796 | os.remove(f'{name}.jpg') 797 | 798 | else: 799 | await m.reply_text(f"Failed to download Image: {response.status_code} {response.reason}") 800 | 801 | except FloodWait as e: 802 | await m.reply_text(str(e)) 803 | await asyncio.sleep(2) # Use asyncio.sleep for non-blocking sleep 804 | return # Exit the function to avoid continuation 805 | 806 | except Exception as e: 807 | await m.reply_text(f"An error occurred: {str(e)}") 808 | await asyncio.sleep(4) # You can replace this with more specific 809 | 810 | elif ".zip" in url: 811 | try: 812 | cmd = f'yt-dlp -o "{name}.zip" "{url}"' 813 | download_cmd = f"{cmd} -R 25 --fragment-retries 25" 814 | os.system(download_cmd) 815 | copy = await bot.send_document(chat_id=m.chat.id, document=f'{name}.zip', caption=cczip) 816 | count += 1 817 | os.remove(f'{name}.zip') 818 | except FloodWait as e: 819 | await m.reply_text(str(e)) 820 | time.sleep(e.x) 821 | count += 1 822 | continue 823 | 824 | elif ".pdf" in url: 825 | try: 826 | cmd = f'yt-dlp -o "{name}.pdf" "{url}"' 827 | download_cmd = f"{cmd} -R 25 --fragment-retries 25" 828 | os.system(download_cmd) 829 | copy = await bot.send_document(chat_id=m.chat.id, document=f'{name}.pdf', caption=cc1) 830 | count += 1 831 | os.remove(f'{name}.pdf') 832 | except FloodWait as e: 833 | await m.reply_text(str(e)) 834 | time.sleep(e.x) 835 | continue 836 | else: 837 | emoji_message = await show_random_emojis(message) 838 | remaining_links = len(links) - count 839 | Show = f"**🍁 𝗗𝗢𝗪𝗡𝗟𝗢𝗔𝗗𝗜𝗡𝗚 🍁**\n\n**📝ɴᴀᴍᴇ » ** `{name}\n\n🔗ᴛᴏᴛᴀʟ ᴜʀʟ » {len(links)}\n\n🗂️ɪɴᴅᴇx » {str(count)}/{len(links)}\n\n🌐ʀᴇᴍᴀɪɴɪɴɢ ᴜʀʟ » {remaining_links}\n\n❄ǫᴜᴀʟɪᴛʏ » {res}`\n\n**🔗ᴜʀʟ » ** `{url}`\n\n🤖𝗕𝗢𝗧 𝗠𝗔𝗗𝗘 𝗕𝗬 ➤ 𝗧𝗨𝗦𝗛𝗔𝗥\n\n🙂 चलो फिर से अजनबी बन जायें 🙂" 840 | prog = await m.reply_text(Show) 841 | res_file = await helper.download_video(url, cmd, name) 842 | filename = res_file 843 | await prog.delete(True) 844 | await emoji_message.delete() 845 | await helper.send_vid(bot, m, cc, filename, thumb, name, prog) 846 | count += 1 847 | time.sleep(1) 848 | 849 | except Exception as e: 850 | await m.reply_text(f'‼️𝗗𝗼𝘄𝗻𝗹𝗼𝗮𝗱𝗶𝗻𝗴 𝗙𝗮𝗶𝗹𝗲𝗱‼️\n\n' 851 | f'📝𝗡𝗮𝗺𝗲 » `{name}`\n\n' 852 | f'🔗𝗨𝗿𝗹 » __**Click Here to See Link**__`') 853 | 854 | count += 1 855 | failed_count += 1 856 | continue 857 | 858 | 859 | except Exception as e: 860 | await m.reply_text(e) 861 | #await m.reply_text("**🥳𝗦𝘂𝗰𝗰𝗲𝘀𝘀𝗳𝘂𝗹𝗹𝘆 𝗗𝗼𝗻𝗲🥳**") 862 | await m.reply_text(f"`✨𝗕𝗔𝗧𝗖𝗛 𝗦𝗨𝗠𝗠𝗔𝗥𝗬✨\n\n" 863 | f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n" 864 | f"📛𝗜𝗻𝗱𝗲𝘅 𝗥𝗮𝗻𝗴𝗲 » ({raw_text} to {len(links)})\n" 865 | f"📚𝗕𝗮𝘁𝗰𝗵 𝗡𝗮𝗺𝗲 » {b_name}\n\n" 866 | f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n" 867 | f"✨𝗧𝗫𝗧 𝗦𝗨𝗠𝗠𝗔𝗥𝗬✨ : {len(links)}\n" 868 | f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n" 869 | f"🔹𝗩𝗶𝗱𝗲𝗼 » {video_count}\n🔹𝗣𝗱𝗳 » {pdf_count}\n🔹𝗜𝗺𝗴 » {img_count}\n🔹𝗭𝗶𝗽 » {zip_count}\n🔹𝗙𝗮𝗶𝗹𝗲𝗱 𝗨𝗿𝗹 » {failed_count}\n\n" 870 | f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n" 871 | f"✅𝗦𝗧𝗔𝗧𝗨𝗦 » 𝗖𝗢𝗠𝗣𝗟𝗘𝗧𝗘𝗗`") 872 | await m.reply_text(f"
📥𝗘𝘅𝘁𝗿𝗮𝗰𝘁𝗲𝗱 𝗕𝘆 ➤『{CR}』
") 873 | await m.reply_text(f"
『😏𝗥𝗲𝗮𝗰𝘁𝗶𝗼𝗻 𝗞𝗼𝗻 𝗗𝗲𝗴𝗮😏』
") 874 | 875 | bot.run() 876 | if __name__ == "__main__": 877 | asyncio.run(main()) 878 | --------------------------------------------------------------------------------