├── 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 | 
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 | [](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 | [](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 |
--------------------------------------------------------------------------------