├── Procfile ├── runtime.txt ├── start ├── cookies └── cookies.txt ├── heroku.yml ├── DeadlineTech ├── utils │ ├── decorators │ │ ├── __init__.py │ │ └── language.py │ ├── exceptions.py │ ├── inline │ │ ├── __init__.py │ │ ├── extras.py │ │ ├── speed.py │ │ ├── stats.py │ │ ├── start.py │ │ ├── queue.py │ │ ├── settings.py │ │ ├── help.py │ │ └── play.py │ ├── __init__.py │ ├── sys.py │ ├── stream │ │ ├── autoclear.py │ │ └── queue.py │ ├── extraction.py │ ├── pastebin.py │ ├── channelplay.py │ ├── logger.py │ ├── crash_reporter.py │ ├── inlinequery.py │ ├── formatters.py │ └── thumbnails.py ├── assets │ ├── font.ttf │ ├── font2.ttf │ ├── font3.ttf │ └── icons.png ├── platforms │ ├── __init__.py │ ├── Soundcloud.py │ ├── Resso.py │ ├── Apple.py │ ├── Carbon.py │ └── Spotify.py ├── plugins │ ├── misc │ │ ├── watcher.py │ │ ├── seeker.py │ │ ├── auto_leave.py │ │ ├── clean_assistant.py │ │ └── broadcast.py │ ├── __init__.py │ ├── admins │ │ ├── stop.py │ │ ├── resume.py │ │ ├── pause.py │ │ ├── shuffle.py │ │ ├── loop.py │ │ ├── seek.py │ │ ├── auth.py │ │ └── speed.py │ ├── tools │ │ ├── ping.py │ │ ├── speedtest.py │ │ ├── language.py │ │ ├── active.py │ │ ├── reload.py │ │ ├── stats.py │ │ └── dev.py │ ├── sudo │ │ ├── logger.py │ │ ├── maintenance.py │ │ ├── crash_reporter.py │ │ ├── blchat.py │ │ ├── block.py │ │ ├── chatlog.py │ │ ├── sudoers.py │ │ ├── gban.py │ │ └── restart.py │ ├── play │ │ ├── playmode.py │ │ ├── channel.py │ │ └── live.py │ └── bot │ │ ├── privacy.py │ │ ├── inline.py │ │ ├── help.py │ │ └── start.py ├── logging.py ├── __init__.py ├── core │ ├── mongo.py │ ├── dir.py │ ├── git.py │ ├── bot.py │ └── userbot.py ├── misc.py └── __main__.py ├── sample.env ├── .gitignore ├── .dockerignore ├── Dockerfile ├── requirements.txt ├── LICENSE ├── strings └── __init__.py ├── app.json ├── setup ├── config.py └── .github └── README.md /Procfile: -------------------------------------------------------------------------------- 1 | worker: bash start 2 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.11.4 2 | -------------------------------------------------------------------------------- /start: -------------------------------------------------------------------------------- 1 | python3 -m DeadlineTech 2 | -------------------------------------------------------------------------------- /cookies/cookies.txt: -------------------------------------------------------------------------------- 1 | # Paste your cookies here 2 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: bash start -------------------------------------------------------------------------------- /DeadlineTech/utils/decorators/__init__.py: -------------------------------------------------------------------------------- 1 | from .admins import * 2 | from .language import * 3 | -------------------------------------------------------------------------------- /DeadlineTech/assets/font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deadlineTech/music/HEAD/DeadlineTech/assets/font.ttf -------------------------------------------------------------------------------- /DeadlineTech/assets/font2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deadlineTech/music/HEAD/DeadlineTech/assets/font2.ttf -------------------------------------------------------------------------------- /DeadlineTech/assets/font3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deadlineTech/music/HEAD/DeadlineTech/assets/font3.ttf -------------------------------------------------------------------------------- /DeadlineTech/assets/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deadlineTech/music/HEAD/DeadlineTech/assets/icons.png -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | API_ID= 2 | API_HASH= 3 | BOT_TOKEN= 4 | LOGGER_ID= 5 | API_KEY= 6 | MONGO_DB_URI= 7 | OWNER_ID= 8 | STRING_SESSION= 9 | -------------------------------------------------------------------------------- /DeadlineTech/utils/exceptions.py: -------------------------------------------------------------------------------- 1 | class AssistantErr(Exception): 2 | def __init__(self, errr: str): 3 | super().__init__(errr) 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .cache 3 | log.txt 4 | .DS_Store 5 | *.session 6 | raw_files/ 7 | cache/ 8 | downloads/ 9 | __pycache__/ 10 | *.session-journal 11 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .env 2 | .cache 3 | log.txt 4 | .DS_Store 5 | *.session 6 | raw_files/ 7 | cache/ 8 | downloads/ 9 | __pycache__/ 10 | *.session-journal 11 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/__init__.py: -------------------------------------------------------------------------------- 1 | from .extras import * 2 | from .help import * 3 | from .play import * 4 | from .queue import * 5 | from .settings import * 6 | from .speed import * 7 | from .start import * 8 | -------------------------------------------------------------------------------- /DeadlineTech/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .channelplay import * 2 | from .database import * 3 | from .decorators import * 4 | from .extraction import * 5 | from .formatters import * 6 | from .inline import * 7 | from .pastebin import * 8 | from .sys import * 9 | -------------------------------------------------------------------------------- /DeadlineTech/platforms/__init__.py: -------------------------------------------------------------------------------- 1 | from .Apple import AppleAPI 2 | from .Carbon import CarbonAPI 3 | from .Resso import RessoAPI 4 | from .Soundcloud import SoundAPI 5 | from .Spotify import SpotifyAPI 6 | from .Telegram import TeleAPI 7 | from .Youtube import YouTubeAPI 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nikolaik/python-nodejs:python3.10-nodejs20 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y --no-install-recommends ffmpeg \ 5 | && apt-get clean \ 6 | && rm -rf /var/lib/apt/lists/* 7 | 8 | RUN python -m pip install --upgrade yt-dlp 9 | 10 | COPY . /app/ 11 | WORKDIR /app/ 12 | RUN python -m pip install --no-cache-dir --upgrade pip 13 | RUN pip3 install --no-cache-dir -U -r requirements.txt 14 | 15 | CMD bash start 16 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/misc/watcher.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.core.call import Anony 8 | 9 | welcome = 20 10 | close = 30 11 | 12 | 13 | @app.on_message(filters.video_chat_started, group=welcome) 14 | @app.on_message(filters.video_chat_ended, group=close) 15 | async def welcome(_, message: Message): 16 | await Anony.stop_stream_force(message.chat.id) 17 | -------------------------------------------------------------------------------- /DeadlineTech/utils/sys.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import psutil 4 | 5 | from DeadlineTech.misc import _boot_ 6 | from DeadlineTech.utils.formatters import get_readable_time 7 | 8 | 9 | async def bot_sys_stats(): 10 | bot_uptime = int(time.time() - _boot_) 11 | UP = f"{get_readable_time(bot_uptime)}" 12 | CPU = f"{psutil.cpu_percent(interval=0.5)}%" 13 | RAM = f"{psutil.virtual_memory().percent}%" 14 | DISK = f"{psutil.disk_usage('/').percent}%" 15 | return UP, CPU, RAM, DISK 16 | -------------------------------------------------------------------------------- /DeadlineTech/utils/stream/autoclear.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from config import autoclean 4 | 5 | 6 | async def auto_clean(popped): 7 | try: 8 | rem = popped["file"] 9 | autoclean.remove(rem) 10 | count = autoclean.count(rem) 11 | if count == 0: 12 | if "vid_" not in rem or "live_" not in rem or "index_" not in rem: 13 | try: 14 | os.remove(rem) 15 | except: 16 | pass 17 | except: 18 | pass 19 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiofiles 2 | aiohttp 3 | apscheduler 4 | asyncio 5 | beautifulsoup4 6 | dnspython 7 | ffmpeg-python 8 | gitpython 9 | hachoir 10 | heroku3 11 | motor 12 | pillow==9.5.0 13 | psutil 14 | httpx==0.27.2 15 | py-tgcalls==0.9.7 16 | pykeyboard 17 | https://github.com/KurimuzonAkuma/pyrogram/archive/v2.1.23.zip 18 | python-dotenv 19 | pyyaml 20 | requests 21 | speedtest-cli 22 | spotipy 23 | tgcrypto 24 | unidecode 25 | git+https://github.com/yt-dlp/yt-dlp.git@master 26 | youtube-search 27 | youtube-search-python 28 | uvloop==0.21.0 29 | pytz 30 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | import glob 2 | from os.path import dirname, isfile 3 | 4 | 5 | def __list_all_modules(): 6 | work_dir = dirname(__file__) 7 | mod_paths = glob.glob(work_dir + "/*/*.py") 8 | 9 | all_modules = [ 10 | (((f.replace(work_dir, "")).replace("/", "."))[:-3]) 11 | for f in mod_paths 12 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 13 | ] 14 | 15 | return all_modules 16 | 17 | 18 | ALL_MODULES = sorted(__list_all_modules()) 19 | __all__ = ALL_MODULES + ["ALL_MODULES"] 20 | -------------------------------------------------------------------------------- /DeadlineTech/utils/extraction.py: -------------------------------------------------------------------------------- 1 | from pyrogram.enums import MessageEntityType 2 | from pyrogram.types import Message, User 3 | 4 | from DeadlineTech import app 5 | 6 | 7 | async def extract_user(m: Message) -> User: 8 | if m.reply_to_message: 9 | return m.reply_to_message.from_user 10 | msg_entities = m.entities[1] if m.text.startswith("/") else m.entities[0] 11 | return await app.get_users( 12 | msg_entities.user.id 13 | if msg_entities.type == MessageEntityType.TEXT_MENTION 14 | else int(m.command[1]) 15 | if m.command[1].isdecimal() 16 | else m.command[1] 17 | ) 18 | -------------------------------------------------------------------------------- /DeadlineTech/logging.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | import logging 3 | 4 | logging.basicConfig( 5 | level=logging.INFO, 6 | format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s", 7 | datefmt="%d-%b-%y %H:%M:%S", 8 | handlers=[ 9 | logging.FileHandler("log.txt"), 10 | logging.StreamHandler(), 11 | ], 12 | ) 13 | 14 | logging.getLogger("httpx").setLevel(logging.ERROR) 15 | logging.getLogger("pyrogram").setLevel(logging.ERROR) 16 | logging.getLogger("pytgcalls").setLevel(logging.ERROR) 17 | 18 | 19 | def LOGGER(name: str) -> logging.Logger: 20 | return logging.getLogger(name) 21 | -------------------------------------------------------------------------------- /DeadlineTech/__init__.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | from DeadlineTech.core.bot import Anony 3 | from DeadlineTech.core.dir import dirr 4 | from DeadlineTech.core.git import git 5 | from DeadlineTech.core.userbot import Userbot 6 | from DeadlineTech.misc import dbb, heroku 7 | 8 | from .logging import LOGGER 9 | 10 | dirr() 11 | git() 12 | dbb() 13 | heroku() 14 | 15 | app = Anony() 16 | userbot = Userbot() 17 | 18 | 19 | from .platforms import * 20 | 21 | Apple = AppleAPI() 22 | Carbon = CarbonAPI() 23 | SoundCloud = SoundAPI() 24 | Spotify = SpotifyAPI() 25 | Resso = RessoAPI() 26 | Telegram = TeleAPI() 27 | YouTube = YouTubeAPI() 28 | -------------------------------------------------------------------------------- /DeadlineTech/utils/pastebin.py: -------------------------------------------------------------------------------- 1 | import aiohttp 2 | 3 | BASE = "https://batbin.me/" 4 | 5 | 6 | async def post(url: str, *args, **kwargs): 7 | async with aiohttp.ClientSession() as session: 8 | async with session.post(url, *args, **kwargs) as resp: 9 | try: 10 | data = await resp.json() 11 | except Exception: 12 | data = await resp.text() 13 | return data 14 | 15 | 16 | async def AnonyBin(text): 17 | resp = await post(f"{BASE}api/v2/paste", data=text) 18 | if not resp["success"]: 19 | return 20 | link = BASE + resp["message"] 21 | return link 22 | -------------------------------------------------------------------------------- /DeadlineTech/utils/channelplay.py: -------------------------------------------------------------------------------- 1 | from DeadlineTech import app 2 | from DeadlineTech.utils.database import get_cmode 3 | 4 | 5 | async def get_channeplayCB(_, command, CallbackQuery): 6 | if command == "c": 7 | chat_id = await get_cmode(CallbackQuery.message.chat.id) 8 | if chat_id is None: 9 | try: 10 | return await CallbackQuery.answer(_["setting_7"], show_alert=True) 11 | except: 12 | return 13 | try: 14 | channel = (await app.get_chat(chat_id)).title 15 | except: 16 | try: 17 | return await CallbackQuery.answer(_["cplay_4"], show_alert=True) 18 | except: 19 | return 20 | else: 21 | chat_id = CallbackQuery.message.chat.id 22 | channel = None 23 | return chat_id, channel 24 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/misc/seeker.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | import asyncio 4 | 5 | from DeadlineTech.misc import db 6 | from DeadlineTech.utils.database import get_active_chats, is_music_playing 7 | 8 | 9 | async def timer(): 10 | while not await asyncio.sleep(1): 11 | active_chats = await get_active_chats() 12 | for chat_id in active_chats: 13 | if not await is_music_playing(chat_id): 14 | continue 15 | playing = db.get(chat_id) 16 | if not playing: 17 | continue 18 | duration = int(playing[0]["seconds"]) 19 | if duration == 0: 20 | continue 21 | if db[chat_id][0]["played"] >= duration: 22 | continue 23 | db[chat_id][0]["played"] += 1 24 | 25 | 26 | asyncio.create_task(timer()) 27 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/stop.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.core.call import Anony 8 | from DeadlineTech.utils.database import set_loop 9 | from DeadlineTech.utils.decorators import AdminRightsCheck 10 | from DeadlineTech.utils.inline import close_markup 11 | from config import BANNED_USERS 12 | 13 | 14 | @app.on_message( 15 | filters.command(["end", "stop", "cend", "cstop"]) & filters.group & ~BANNED_USERS 16 | ) 17 | @AdminRightsCheck 18 | async def stop_music(cli, message: Message, _, chat_id): 19 | if not len(message.command) == 1: 20 | return 21 | await Anony.stop_stream(chat_id) 22 | await set_loop(chat_id, 0) 23 | await message.reply_text( 24 | _["admin_5"].format(message.from_user.mention), reply_markup=close_markup(_) 25 | ) 26 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/resume.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.core.call import Anony 8 | from DeadlineTech.utils.database import is_music_playing, music_on 9 | from DeadlineTech.utils.decorators import AdminRightsCheck 10 | from DeadlineTech.utils.inline import close_markup 11 | from config import BANNED_USERS 12 | 13 | 14 | @app.on_message(filters.command(["resume", "cresume"]) & filters.group & ~BANNED_USERS) 15 | @AdminRightsCheck 16 | async def resume_com(cli, message: Message, _, chat_id): 17 | if await is_music_playing(chat_id): 18 | return await message.reply_text(_["admin_3"]) 19 | await music_on(chat_id) 20 | await Anony.resume_stream(chat_id) 21 | await message.reply_text( 22 | _["admin_4"].format(message.from_user.mention), reply_markup=close_markup(_) 23 | ) 24 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/pause.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.core.call import Anony 8 | from DeadlineTech.utils.database import is_music_playing, music_off 9 | from DeadlineTech.utils.decorators import AdminRightsCheck 10 | from DeadlineTech.utils.inline import close_markup 11 | from config import BANNED_USERS 12 | 13 | 14 | @app.on_message(filters.command(["pause", "cpause"]) & filters.group & ~BANNED_USERS) 15 | @AdminRightsCheck 16 | async def pause_admin(cli, message: Message, _, chat_id): 17 | if not await is_music_playing(chat_id): 18 | return await message.reply_text(_["admin_1"]) 19 | await music_off(chat_id) 20 | await Anony.pause_stream(chat_id) 21 | await message.reply_text( 22 | _["admin_2"].format(message.from_user.mention), reply_markup=close_markup(_) 23 | ) 24 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/extras.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | from config import SUPPORT_CHAT 4 | 5 | 6 | def botplaylist_markup(_): 7 | buttons = [ 8 | [ 9 | InlineKeyboardButton(text=_["S_B_9"], url=SUPPORT_CHAT), 10 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 11 | ], 12 | ] 13 | return buttons 14 | 15 | 16 | def close_markup(_): 17 | upl = InlineKeyboardMarkup( 18 | [ 19 | [ 20 | InlineKeyboardButton( 21 | text=_["CLOSE_BUTTON"], 22 | callback_data="close", 23 | ), 24 | ] 25 | ] 26 | ) 27 | return upl 28 | 29 | 30 | def supp_markup(_): 31 | upl = InlineKeyboardMarkup( 32 | [ 33 | [ 34 | InlineKeyboardButton( 35 | text=_["S_B_9"], 36 | url=SUPPORT_CHAT, 37 | ), 38 | ] 39 | ] 40 | ) 41 | return upl 42 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/ping.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.core.call import Anony 8 | from DeadlineTech.utils import bot_sys_stats 9 | from DeadlineTech.utils.decorators.language import language 10 | from DeadlineTech.utils.inline import supp_markup 11 | from config import BANNED_USERS, PING_IMG_URL 12 | 13 | 14 | @app.on_message(filters.command(["ping", "alive"]) & ~BANNED_USERS) 15 | @language 16 | async def ping_com(client, message: Message, _): 17 | start = datetime.now() 18 | response = await message.reply_photo( 19 | photo=PING_IMG_URL, 20 | caption=_["ping_1"].format(app.mention), 21 | ) 22 | pytgping = await Anony.ping() 23 | UP, CPU, RAM, DISK = await bot_sys_stats() 24 | resp = (datetime.now() - start).microseconds / 1000 25 | await response.edit_text( 26 | _["ping_2"].format(resp, app.mention, UP, RAM, CPU, DISK, pytgping), 27 | reply_markup=supp_markup(_), 28 | ) 29 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/logger.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | 3 | from DeadlineTech import app 4 | from DeadlineTech.misc import SUDOERS 5 | from DeadlineTech.utils.database import add_off, add_on 6 | from DeadlineTech.utils.decorators.language import language 7 | 8 | 9 | @app.on_message(filters.command(["logger"]) & SUDOERS) 10 | @language 11 | async def logger(client, message, _): 12 | usage = _["log_1"] 13 | if len(message.command) != 2: 14 | return await message.reply_text(usage) 15 | state = message.text.split(None, 1)[1].strip().lower() 16 | if state == "enable": 17 | await add_on(2) 18 | await message.reply_text(_["log_2"]) 19 | elif state == "disable": 20 | await add_off(2) 21 | await message.reply_text(_["log_3"]) 22 | else: 23 | await message.reply_text(usage) 24 | 25 | @app.on_message(filters.command(["cookies"]) & SUDOERS) 26 | @language 27 | async def logger(client, message, _): 28 | await message.reply_document("cookies/logs.csv") 29 | await message.reply_text("Please check given file to cookies file choosing logs...") 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Team Arc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /strings/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List 3 | 4 | import yaml 5 | 6 | languages = {} 7 | languages_present = {} 8 | 9 | 10 | def get_string(lang: str): 11 | return languages[lang] 12 | 13 | 14 | for filename in os.listdir(r"./strings/langs/"): 15 | if "en" not in languages: 16 | languages["en"] = yaml.safe_load( 17 | open(r"./strings/langs/en.yml", encoding="utf8") 18 | ) 19 | languages_present["en"] = languages["en"]["name"] 20 | if filename.endswith(".yml"): 21 | language_name = filename[:-4] 22 | if language_name == "en": 23 | continue 24 | languages[language_name] = yaml.safe_load( 25 | open(r"./strings/langs/" + filename, encoding="utf8") 26 | ) 27 | for item in languages["en"]: 28 | if item not in languages[language_name]: 29 | languages[language_name][item] = languages["en"][item] 30 | try: 31 | languages_present[language_name] = languages[language_name]["name"] 32 | except: 33 | print("There is some issue with the language file inside bot.") 34 | exit() 35 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/shuffle.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | import random 4 | 5 | from pyrogram import filters 6 | from pyrogram.types import Message 7 | 8 | from DeadlineTech import app 9 | from DeadlineTech.misc import db 10 | from DeadlineTech.utils.decorators import AdminRightsCheck 11 | from DeadlineTech.utils.inline import close_markup 12 | from config import BANNED_USERS 13 | 14 | 15 | @app.on_message( 16 | filters.command(["shuffle", "cshuffle"]) & filters.group & ~BANNED_USERS 17 | ) 18 | @AdminRightsCheck 19 | async def admins(Client, message: Message, _, chat_id): 20 | check = db.get(chat_id) 21 | if not check: 22 | return await message.reply_text(_["queue_2"]) 23 | try: 24 | popped = check.pop(0) 25 | except: 26 | return await message.reply_text(_["admin_15"], reply_markup=close_markup(_)) 27 | check = db.get(chat_id) 28 | if not check: 29 | check.insert(0, popped) 30 | return await message.reply_text(_["admin_15"], reply_markup=close_markup(_)) 31 | random.shuffle(check) 32 | check.insert(0, popped) 33 | await message.reply_text( 34 | _["admin_16"].format(message.from_user.mention), reply_markup=close_markup(_) 35 | ) 36 | -------------------------------------------------------------------------------- /DeadlineTech/utils/logger.py: -------------------------------------------------------------------------------- 1 | from pyrogram.enums import ParseMode 2 | 3 | from DeadlineTech import app 4 | from DeadlineTech.utils.database import is_on_off 5 | from config import LOGGER_ID 6 | 7 | 8 | async def play_logs(message, streamtype): 9 | if await is_on_off(2): 10 | logger_text = f""" 11 | ✨ {app.mention} 𝗉𝗅𝖺𝗒 𝗅𝗈𝗀 12 | ─────────────────────── 13 | 14 | 🆔 𝖢𝗁𝖺𝗍 𝖨𝖣: {message.chat.id} 15 | 🏷️ 𝖢𝗁𝖺𝗍 𝖭𝖺𝗆𝖾: {message.chat.title} 16 | 🔗 𝖢𝗁𝖺𝗍 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾: @{message.chat.username} 17 | 18 | 👤 𝖴𝗌𝖾𝗋 𝖨𝖣: {message.from_user.id} 19 | 🙋‍♂️ 𝖭𝖺𝗆𝖾: {message.from_user.mention} 20 | 🌐 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾: @{message.from_user.username} 21 | 22 | ❓ 𝗊𝗎𝖾𝗋𝗒: {message.text.split(None, 1)[1]} 23 | 🎧 𝗌𝗍𝗋𝖾𝖺𝗆 𝗍𝗒𝗉𝖾: {streamtype} 24 | ─────────────────────── 25 | """ 26 | if message.chat.id != LOGGER_ID: 27 | try: 28 | await app.send_message( 29 | chat_id=LOGGER_ID, 30 | text=logger_text, 31 | parse_mode=ParseMode.HTML, 32 | disable_web_page_preview=True, 33 | ) 34 | except: 35 | pass 36 | return 37 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/play/playmode.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import InlineKeyboardMarkup, Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.utils.database import get_playmode, get_playtype, is_nonadmin_chat 8 | from DeadlineTech.utils.decorators import language 9 | from DeadlineTech.utils.inline.settings import playmode_users_markup 10 | from config import BANNED_USERS 11 | 12 | 13 | @app.on_message(filters.command(["playmode", "mode"]) & filters.group & ~BANNED_USERS) 14 | @language 15 | async def playmode_(client, message: Message, _): 16 | playmode = await get_playmode(message.chat.id) 17 | if playmode == "Direct": 18 | Direct = True 19 | else: 20 | Direct = None 21 | is_non_admin = await is_nonadmin_chat(message.chat.id) 22 | if not is_non_admin: 23 | Group = True 24 | else: 25 | Group = None 26 | playty = await get_playtype(message.chat.id) 27 | if playty == "Everyone": 28 | Playtype = None 29 | else: 30 | Playtype = True 31 | buttons = playmode_users_markup(_, Direct, Group, Playtype) 32 | response = await message.reply_text( 33 | _["play_22"].format(message.chat.title), 34 | reply_markup=InlineKeyboardMarkup(buttons), 35 | ) 36 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/speed.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | 4 | def speed_markup(_, chat_id): 5 | upl = InlineKeyboardMarkup( 6 | [ 7 | [ 8 | InlineKeyboardButton( 9 | text="🕒 0.5x", 10 | callback_data=f"SpeedUP {chat_id}|0.5", 11 | ), 12 | InlineKeyboardButton( 13 | text="🕓 0.75x", 14 | callback_data=f"SpeedUP {chat_id}|0.75", 15 | ), 16 | ], 17 | [ 18 | InlineKeyboardButton( 19 | text=_["P_B_4"], 20 | callback_data=f"SpeedUP {chat_id}|1.0", 21 | ), 22 | ], 23 | [ 24 | InlineKeyboardButton( 25 | text="🕤 1.5x", 26 | callback_data=f"SpeedUP {chat_id}|1.5", 27 | ), 28 | InlineKeyboardButton( 29 | text="🕛 2.0x", 30 | callback_data=f"SpeedUP {chat_id}|2.0", 31 | ), 32 | ], 33 | [ 34 | InlineKeyboardButton( 35 | text=_["CLOSE_BUTTON"], 36 | callback_data="close", 37 | ), 38 | ], 39 | ] 40 | ) 41 | return upl 42 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/maintenance.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from DeadlineTech import app 5 | from DeadlineTech.misc import SUDOERS 6 | from DeadlineTech.utils.database import ( 7 | get_lang, 8 | is_maintenance, 9 | maintenance_off, 10 | maintenance_on, 11 | ) 12 | from strings import get_string 13 | 14 | 15 | @app.on_message(filters.command(["maintenance"]) & SUDOERS) 16 | async def maintenance(client, message: Message): 17 | try: 18 | language = await get_lang(message.chat.id) 19 | _ = get_string(language) 20 | except: 21 | _ = get_string("en") 22 | usage = _["maint_1"] 23 | if len(message.command) != 2: 24 | return await message.reply_text(usage) 25 | state = message.text.split(None, 1)[1].strip().lower() 26 | if state == "enable": 27 | if await is_maintenance() is False: 28 | await message.reply_text(_["maint_4"]) 29 | else: 30 | await maintenance_on() 31 | await message.reply_text(_["maint_2"].format(app.mention)) 32 | elif state == "disable": 33 | if await is_maintenance() is False: 34 | await maintenance_off() 35 | await message.reply_text(_["maint_3"].format(app.mention)) 36 | else: 37 | await message.reply_text(_["maint_5"]) 38 | else: 39 | await message.reply_text(usage) 40 | -------------------------------------------------------------------------------- /DeadlineTech/utils/crash_reporter.py: -------------------------------------------------------------------------------- 1 | # Powered By DeadlineTech 2 | 3 | import asyncio 4 | from traceback import format_exc 5 | from pyrogram.errors import RPCError 6 | 7 | from DeadlineTech import app 8 | from config import LOGGER_ID # Logger group ID 9 | 10 | async def notify_logger_about_crash(error: Exception): 11 | error_text = ( 12 | "🚨 Bot Crash Alert\n\n" 13 | f"Error: {str(error)}\n\n" 14 | f"Traceback:\n
{format_exc()}
" 15 | ) 16 | try: 17 | await app.send_message( 18 | chat_id=LOGGER_ID, 19 | text=error_text, 20 | disable_web_page_preview=True 21 | ) 22 | except RPCError: 23 | pass 24 | 25 | def logger_alert_on_crash(func): 26 | async def wrapper(client, *args, **kwargs): 27 | try: 28 | return await func(client, *args, **kwargs) 29 | except Exception as e: 30 | await notify_logger_about_crash(e) 31 | raise # Optional: re-raise for higher-level logging if needed 32 | return wrapper 33 | 34 | def setup_global_exception_handler(): 35 | loop = asyncio.get_event_loop() 36 | 37 | def handle_exception(loop, context): 38 | error = context.get("exception") 39 | if error: 40 | asyncio.create_task(notify_logger_about_crash(error)) 41 | 42 | loop.set_exception_handler(handle_exception) 43 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/stats.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | 4 | def stats_buttons(_, status): 5 | not_sudo = [ 6 | InlineKeyboardButton( 7 | text=_["SA_B_1"], 8 | callback_data="TopOverall", 9 | ) 10 | ] 11 | sudo = [ 12 | InlineKeyboardButton( 13 | text=_["SA_B_2"], 14 | callback_data="bot_stats_sudo", 15 | ), 16 | InlineKeyboardButton( 17 | text=_["SA_B_3"], 18 | callback_data="TopOverall", 19 | ), 20 | ] 21 | upl = InlineKeyboardMarkup( 22 | [ 23 | sudo if status else not_sudo, 24 | [ 25 | InlineKeyboardButton( 26 | text=_["CLOSE_BUTTON"], 27 | callback_data="close", 28 | ), 29 | ], 30 | ] 31 | ) 32 | return upl 33 | 34 | 35 | def back_stats_buttons(_): 36 | upl = InlineKeyboardMarkup( 37 | [ 38 | [ 39 | InlineKeyboardButton( 40 | text=_["BACK_BUTTON"], 41 | callback_data="stats_back", 42 | ), 43 | InlineKeyboardButton( 44 | text=_["CLOSE_BUTTON"], 45 | callback_data="close", 46 | ), 47 | ], 48 | ] 49 | ) 50 | return upl 51 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/start.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, WebAppInfo 2 | import config 3 | from DeadlineTech import app 4 | 5 | def start_panel(_): 6 | buttons = [ 7 | [ 8 | InlineKeyboardButton( 9 | text=_["S_B_1"], 10 | url=f"https://t.me/{app.username}?startgroup=true" 11 | ), 12 | InlineKeyboardButton(text=_["S_B_2"], url=config.SUPPORT_CHAT) 13 | ], 14 | [ 15 | InlineKeyboardButton( 16 | text=_["S_B_5"], 17 | url="https://github.com/DeadlineTech/music" 18 | ) 19 | ] 20 | ] 21 | return buttons 22 | 23 | 24 | def private_panel(_): 25 | buttons = [ 26 | [ 27 | InlineKeyboardButton( 28 | text=_["S_B_3"], 29 | url=f"https://t.me/{app.username}?startgroup=true" 30 | ) 31 | ], 32 | [ 33 | 34 | InlineKeyboardButton(text=_["S_B_4"], callback_data="settings_back_helper") 35 | ], 36 | 37 | [ 38 | InlineKeyboardButton(text=_["S_B_10"], user_id=config.OWNER_ID), 39 | InlineKeyboardButton(text=_["S_B_9"], url=config.SUPPORT_CHAT) 40 | 41 | ], 42 | [ 43 | InlineKeyboardButton(text=_["S_B_7"], url=config.SUPPORT_CHANNEL), 44 | InlineKeyboardButton(text=_["S_B_5"], url="https://github.com/DeadlineTech/music") 45 | ] 46 | ] 47 | return buttons 48 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/bot/privacy.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import Client, filters 4 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton 5 | from pyrogram.enums import ParseMode 6 | 7 | from DeadlineTech import app 8 | import config 9 | 10 | 11 | TEXT = f""" 12 | 🔒 **Privacy Policy for {app.mention}** 13 | 14 | We value your privacy and are committed to protecting your personal information when you use our Telegram voice chat player bot. 15 | 16 | **What Data We Collect:** 17 | We do **not** collect or store any personal data such as your name, phone number, messages, or media. 18 | 19 | **How We Use Your Data:** 20 | Your interaction (like commands or voice activity) remains confidential and is only used to provide requested services. 21 | 22 | **Data Sharing and Selling:** 23 | We do **not** share, sell, or distribute any information. Your data remains completely private. 24 | 25 | **Security Measures:** 26 | Our bot operates under Telegram’s secure infrastructure, with no external data logging. 27 | 28 | **Your Control:** 29 | You're free to remove the bot or revoke access anytime. 30 | 31 | **Updates to this Policy:** 32 | This policy may be updated. We recommend reviewing it periodically. 33 | 34 | 📎 **Full Privacy Document**: [View Here](https://telegra.ph/Privacy-Policy-Bot-Hub-12-18-2) 35 | 36 | --- 37 | 38 | 🤖 Powered with ❤️ by **Team DeadlineTech** – committed to open, safe, and secure bot experiences. 39 | """ 40 | 41 | # 📍 Privacy Command Handler 42 | @app.on_message(filters.command("privacy")) 43 | async def privacy(client, message: Message): 44 | 45 | # 💬 Reply with UI and text 46 | await message.reply_text( 47 | TEXT, 48 | parse_mode=ParseMode.MARKDOWN, 49 | disable_web_page_preview=True 50 | ) 51 | -------------------------------------------------------------------------------- /DeadlineTech/core/mongo.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | 27 | from motor.motor_asyncio import AsyncIOMotorClient 28 | 29 | from config import MONGO_DB_URI 30 | 31 | from ..logging import LOGGER 32 | 33 | LOGGER(__name__).info("⏳ Establishing a secure link to your MongoDB database...") 34 | try: 35 | _mongo_async_ = AsyncIOMotorClient(MONGO_DB_URI) 36 | mongodb = _mongo_async_.deadline 37 | LOGGER(__name__).info("✅ Successfully connected to MongoDB. All systems are ready!") 38 | except: 39 | LOGGER(__name__).error("❌ MongoDB connection failed!") 40 | exit() 41 | -------------------------------------------------------------------------------- /DeadlineTech/core/dir.py: -------------------------------------------------------------------------------- 1 | # ========================================================== 2 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 3 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 4 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 5 | # 6 | # This file is part of a publicly available and open-source Telegram music bot 7 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 8 | # chats using YouTube as a source, supported by session-based assistant accounts and 9 | # YouTube cookie integration for improved access and performance. 10 | # 11 | # 💡 This source code is released for educational and community purposes. You're free 12 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 13 | # removal of credits, or false ownership claims will be considered a violation of our 14 | # community standards and may lead to denial of support or blacklisting. 15 | # 16 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 17 | # premium API service: https://DeadlineTech.site 18 | # 19 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 20 | # ========================================================== 21 | 22 | 23 | import os 24 | 25 | from ..logging import LOGGER 26 | 27 | 28 | def dirr(): 29 | for file in os.listdir(): 30 | if file.endswith(".jpg"): 31 | os.remove(file) 32 | elif file.endswith(".jpeg"): 33 | os.remove(file) 34 | elif file.endswith(".png"): 35 | os.remove(file) 36 | 37 | if "downloads" not in os.listdir(): 38 | os.mkdir("downloads") 39 | if "cache" not in os.listdir(): 40 | os.mkdir("cache") 41 | 42 | LOGGER(__name__).info("✔ Directory structure successfully updated.") 43 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/loop.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.utils.database import get_loop, set_loop 8 | from DeadlineTech.utils.decorators import AdminRightsCheck 9 | from DeadlineTech.utils.inline import close_markup 10 | from config import BANNED_USERS 11 | 12 | 13 | @app.on_message(filters.command(["loop", "cloop"]) & filters.group & ~BANNED_USERS) 14 | @AdminRightsCheck 15 | async def admins(cli, message: Message, _, chat_id): 16 | usage = _["admin_17"] 17 | if len(message.command) != 2: 18 | return await message.reply_text(usage) 19 | state = message.text.split(None, 1)[1].strip() 20 | if state.isnumeric(): 21 | state = int(state) 22 | if 1 <= state <= 10: 23 | got = await get_loop(chat_id) 24 | if got != 0: 25 | state = got + state 26 | if int(state) > 10: 27 | state = 10 28 | await set_loop(chat_id, state) 29 | return await message.reply_text( 30 | text=_["admin_18"].format(state, message.from_user.mention), 31 | reply_markup=close_markup(_), 32 | ) 33 | else: 34 | return await message.reply_text(_["admin_17"]) 35 | elif state.lower() == "enable": 36 | await set_loop(chat_id, 10) 37 | return await message.reply_text( 38 | text=_["admin_18"].format(state, message.from_user.mention), 39 | reply_markup=close_markup(_), 40 | ) 41 | elif state.lower() == "disable": 42 | await set_loop(chat_id, 0) 43 | return await message.reply_text( 44 | _["admin_19"].format(message.from_user.mention), 45 | reply_markup=close_markup(_), 46 | ) 47 | else: 48 | return await message.reply_text(usage) 49 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inlinequery.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent 2 | 3 | answer = [] 4 | 5 | answer.extend( 6 | [ 7 | InlineQueryResultArticle( 8 | title="Pᴀᴜsᴇ", 9 | description=f"ᴩᴀᴜsᴇ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 10 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 11 | input_message_content=InputTextMessageContent("/pause"), 12 | ), 13 | InlineQueryResultArticle( 14 | title="Rᴇsᴜᴍᴇ", 15 | description=f"ʀᴇsᴜᴍᴇ ᴛʜᴇ ᴩᴀᴜsᴇᴅ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 16 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 17 | input_message_content=InputTextMessageContent("/resume"), 18 | ), 19 | InlineQueryResultArticle( 20 | title="Sᴋɪᴩ", 21 | description=f"sᴋɪᴩ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ ᴀɴᴅ ᴍᴏᴠᴇs ᴛᴏ ᴛʜᴇ ɴᴇxᴛ sᴛʀᴇᴀᴍ.", 22 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 23 | input_message_content=InputTextMessageContent("/skip"), 24 | ), 25 | InlineQueryResultArticle( 26 | title="Eɴᴅ", 27 | description="ᴇɴᴅ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 28 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 29 | input_message_content=InputTextMessageContent("/end"), 30 | ), 31 | InlineQueryResultArticle( 32 | title="Sʜᴜғғʟᴇ", 33 | description="sʜᴜғғʟᴇ ᴛʜᴇ ǫᴜᴇᴜᴇᴅ sᴏɴɢs ɪɴ ᴩʟᴀʏʟɪsᴛ.", 34 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 35 | input_message_content=InputTextMessageContent("/shuffle"), 36 | ), 37 | InlineQueryResultArticle( 38 | title="Lᴏᴏᴩ", 39 | description="ʟᴏᴏᴩ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ ᴛʀᴀᴄᴋ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 40 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 41 | input_message_content=InputTextMessageContent("/loop 3"), 42 | ), 43 | ] 44 | ) 45 | -------------------------------------------------------------------------------- /DeadlineTech/misc.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | import socket 4 | import time 5 | 6 | import heroku3 7 | from pyrogram import filters 8 | 9 | import config 10 | from DeadlineTech.core.mongo import mongodb 11 | 12 | from .logging import LOGGER 13 | 14 | SUDOERS = filters.user() 15 | 16 | HAPP = None 17 | _boot_ = time.time() 18 | 19 | 20 | def is_heroku(): 21 | return "heroku" in socket.getfqdn() 22 | 23 | 24 | XCB = [ 25 | "/", 26 | "@", 27 | ".", 28 | "com", 29 | ":", 30 | "git", 31 | "heroku", 32 | "push", 33 | str(config.HEROKU_API_KEY), 34 | "https", 35 | str(config.HEROKU_APP_NAME), 36 | "HEAD", 37 | "master", 38 | ] 39 | 40 | 41 | def dbb(): 42 | global db 43 | db = {} 44 | LOGGER(__name__).info(f"🧺 Local database initialized successfully.") 45 | 46 | 47 | async def sudo(): 48 | global SUDOERS 49 | SUDOERS.add(config.OWNER_ID) 50 | sudoersdb = mongodb.sudoers 51 | sudoers = await sudoersdb.find_one({"sudo": "sudo"}) 52 | sudoers = [] if not sudoers else sudoers["sudoers"] 53 | if config.OWNER_ID not in sudoers: 54 | sudoers.append(config.OWNER_ID) 55 | await sudoersdb.update_one( 56 | {"sudo": "sudo"}, 57 | {"$set": {"sudoers": sudoers}}, 58 | upsert=True, 59 | ) 60 | if sudoers: 61 | for user_id in sudoers: 62 | SUDOERS.add(user_id) 63 | LOGGER(__name__).info(f"💾 Sudoers have been set") 64 | 65 | 66 | def heroku(): 67 | global HAPP 68 | if is_heroku: 69 | if config.HEROKU_API_KEY and config.HEROKU_APP_NAME: 70 | try: 71 | Heroku = heroku3.from_key(config.HEROKU_API_KEY) 72 | HAPP = Heroku.app(config.HEROKU_APP_NAME) 73 | LOGGER(__name__).info(f"Heroku App Configured") 74 | except BaseException: 75 | LOGGER(__name__).warning( 76 | f"Please make sure your Heroku API Key and Your App name are configured correctly in the heroku." 77 | ) 78 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/speedtest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import speedtest 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | from DeadlineTech import app 6 | from DeadlineTech.misc import SUDOERS 7 | from DeadlineTech.utils.decorators.language import language 8 | 9 | 10 | def perform_speedtest(): 11 | try: 12 | st = speedtest.Speedtest() 13 | st.get_best_server() 14 | st.download() 15 | st.upload() 16 | st.results.share() 17 | return st.results.dict() 18 | except Exception as e: 19 | return {"error": str(e)} 20 | 21 | 22 | @app.on_message(filters.command(["speedtest", "spt"]) & SUDOERS) 23 | @language 24 | async def speedtest_function(client, message: Message, _): 25 | status = await message.reply_text("⚡ Running SpeedTest...\nConnecting to best server...") 26 | 27 | loop = asyncio.get_event_loop() 28 | result = await loop.run_in_executor(None, perform_speedtest) 29 | 30 | if "error" in result: 31 | return await status.edit_text(f"❌ Speedtest failed\n{result['error']}") 32 | 33 | download_speed = round(result['download'] / 1_000_000, 2) 34 | upload_speed = round(result['upload'] / 1_000_000, 2) 35 | 36 | output = ( 37 | "🌐 SpeedTest Results\n\n" 38 | f"🧑 ISP: {result['client']['isp']}\n" 39 | f"🌍 Country: {result['client']['country']}\n\n" 40 | f"🏢 Server: {result['server']['name']} ({result['server']['country']} - {result['server']['cc']})\n" 41 | f"🤝 Sponsor: {result['server']['sponsor']}\n" 42 | f"⏱ Latency: {round(result['server']['latency'], 2)} ms\n" 43 | f"📶 Ping: {result['ping']} ms\n\n" 44 | f"⬇️ Download: {download_speed} Mbps\n" 45 | f"⬆️ Upload: {upload_speed} Mbps\n" 46 | ) 47 | 48 | try: 49 | await client.send_photo(message.chat.id, photo=result["share"], caption=output) 50 | except Exception: 51 | await status.edit_text(output) 52 | else: 53 | await status.delete() 54 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/play/channel.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.enums import ChatMembersFilter, ChatMemberStatus, ChatType 5 | from pyrogram.types import Message 6 | 7 | from DeadlineTech import app 8 | from DeadlineTech.utils.database import set_cmode 9 | from DeadlineTech.utils.decorators.admins import AdminActual 10 | from config import BANNED_USERS 11 | 12 | 13 | @app.on_message(filters.command(["channelplay"]) & filters.group & ~BANNED_USERS) 14 | @AdminActual 15 | async def playmode_(client, message: Message, _): 16 | if len(message.command) < 2: 17 | return await message.reply_text(_["cplay_1"].format(message.chat.title)) 18 | query = message.text.split(None, 2)[1].lower().strip() 19 | if (str(query)).lower() == "disable": 20 | await set_cmode(message.chat.id, None) 21 | return await message.reply_text(_["cplay_7"]) 22 | elif str(query) == "linked": 23 | chat = await app.get_chat(message.chat.id) 24 | if chat.linked_chat: 25 | chat_id = chat.linked_chat.id 26 | await set_cmode(message.chat.id, chat_id) 27 | return await message.reply_text( 28 | _["cplay_3"].format(chat.linked_chat.title, chat.linked_chat.id) 29 | ) 30 | else: 31 | return await message.reply_text(_["cplay_2"]) 32 | else: 33 | try: 34 | chat = await app.get_chat(query) 35 | except: 36 | return await message.reply_text(_["cplay_4"]) 37 | if chat.type != ChatType.CHANNEL: 38 | return await message.reply_text(_["cplay_5"]) 39 | try: 40 | async for user in app.get_chat_members( 41 | chat.id, filter=ChatMembersFilter.ADMINISTRATORS 42 | ): 43 | if user.status == ChatMemberStatus.OWNER: 44 | cusn = user.user.username 45 | crid = user.user.id 46 | except: 47 | return await message.reply_text(_["cplay_4"]) 48 | if crid != message.from_user.id: 49 | return await message.reply_text(_["cplay_6"].format(chat.title, cusn)) 50 | await set_cmode(message.chat.id, chat.id) 51 | return await message.reply_text(_["cplay_3"].format(chat.title, chat.id)) 52 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/queue.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 4 | 5 | 6 | def queue_markup( 7 | _, 8 | DURATION, 9 | CPLAY, 10 | videoid, 11 | played: Union[bool, int] = None, 12 | dur: Union[bool, int] = None, 13 | ): 14 | not_dur = [ 15 | [ 16 | InlineKeyboardButton( 17 | text=_["QU_B_1"], 18 | callback_data=f"GetQueued {CPLAY}|{videoid}", 19 | ), 20 | InlineKeyboardButton( 21 | text=_["CLOSE_BUTTON"], 22 | callback_data="close", 23 | ), 24 | ] 25 | ] 26 | dur = [ 27 | [ 28 | InlineKeyboardButton( 29 | text=_["QU_B_2"].format(played, dur), 30 | callback_data="GetTimer", 31 | ) 32 | ], 33 | [ 34 | InlineKeyboardButton( 35 | text=_["QU_B_1"], 36 | callback_data=f"GetQueued {CPLAY}|{videoid}", 37 | ), 38 | InlineKeyboardButton( 39 | text=_["CLOSE_BUTTON"], 40 | callback_data="close", 41 | ), 42 | ], 43 | ] 44 | upl = InlineKeyboardMarkup(not_dur if DURATION == "Unknown" else dur) 45 | return upl 46 | 47 | 48 | def queue_back_markup(_, CPLAY): 49 | upl = InlineKeyboardMarkup( 50 | [ 51 | [ 52 | InlineKeyboardButton( 53 | text=_["BACK_BUTTON"], 54 | callback_data=f"queue_back_timer {CPLAY}", 55 | ), 56 | InlineKeyboardButton( 57 | text=_["CLOSE_BUTTON"], 58 | callback_data="close", 59 | ), 60 | ] 61 | ] 62 | ) 63 | return upl 64 | 65 | 66 | def aq_markup(_, chat_id): 67 | buttons = [ 68 | [ 69 | InlineKeyboardButton(text="▷", callback_data=f"ADMIN Resume|{chat_id}"), 70 | InlineKeyboardButton(text="II", callback_data=f"ADMIN Pause|{chat_id}"), 71 | InlineKeyboardButton(text="‣‣I", callback_data=f"ADMIN Skip|{chat_id}"), 72 | InlineKeyboardButton(text="▢", callback_data=f"ADMIN Stop|{chat_id}"), 73 | ], 74 | ] 75 | return buttons 76 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/crash_reporter.py: -------------------------------------------------------------------------------- 1 | # Powered by DeadlineTech 2 | 3 | 4 | import logging 5 | from pyrogram import Client, filters 6 | from DeadlineTech import app 7 | from pyrogram.types import Message, ChatMemberUpdated 8 | from pyrogram.enums import ChatMemberStatus 9 | 10 | # Setup logging 11 | logger = logging.getLogger(__name__) 12 | logging.basicConfig(level=logging.INFO) 13 | 14 | 15 | # ✅ Handle member joins, leaves, promotions, demotions 16 | @app.on_chat_member_updated() 17 | async def handle_member_update(client: Client, update: ChatMemberUpdated): 18 | user = update.from_user 19 | chat = update.chat 20 | old = update.old_chat_member 21 | new = update.new_chat_member 22 | 23 | # Safely handle cases where old/new is None 24 | if not old or not new: 25 | return 26 | 27 | if old.status != new.status: 28 | if new.status == ChatMemberStatus.MEMBER: 29 | logger.info(f"{user.id} joined {chat.id}") 30 | elif new.status == ChatMemberStatus.LEFT: 31 | logger.info(f"{user.id} left {chat.id}") 32 | elif new.status == ChatMemberStatus.ADMINISTRATOR: 33 | logger.info(f"{user.id} was promoted in {chat.id}") 34 | elif old.status == ChatMemberStatus.ADMINISTRATOR and new.status != ChatMemberStatus.ADMINISTRATOR: 35 | logger.info(f"{user.id} was demoted in {chat.id}") 36 | 37 | 38 | # ✅ Handle video chat started (includes voice chats) 39 | @app.on_message(filters.video_chat_started) 40 | async def video_chat_started_handler(client: Client, message: Message): 41 | chat = message.chat 42 | logger.info(f"Video chat started in {chat.id}") 43 | 44 | 45 | # ✅ Handle video chat ended 46 | @app.on_message(filters.video_chat_ended) 47 | async def video_chat_ended_handler(client: Client, message: Message): 48 | chat = message.chat 49 | logger.info(f" Video chat ended in {chat.id}") 50 | 51 | 52 | # ✅ Handle pinned messages 53 | @app.on_message(filters.pinned_message) 54 | async def pinned_message_handler(client: Client, message: Message): 55 | chat = message.chat 56 | pinned = message.pinned_message 57 | 58 | if pinned: 59 | logger.info(f"Message pinned in {chat.id} - Pinned Msg ID: {pinned.id}") 60 | else: 61 | logger.info(f"A message was pinned in {chat.id}, but content is not accessible.") 62 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/play/live.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | 5 | from DeadlineTech import YouTube, app 6 | from DeadlineTech.utils.channelplay import get_channeplayCB 7 | from DeadlineTech.utils.decorators.language import languageCB 8 | from DeadlineTech.utils.stream.stream import stream 9 | from config import BANNED_USERS 10 | 11 | 12 | @app.on_callback_query(filters.regex("LiveStream") & ~BANNED_USERS) 13 | @languageCB 14 | async def play_live_stream(client, CallbackQuery, _): 15 | callback_data = CallbackQuery.data.strip() 16 | callback_request = callback_data.split(None, 1)[1] 17 | vidid, user_id, mode, cplay, fplay = callback_request.split("|") 18 | if CallbackQuery.from_user.id != int(user_id): 19 | try: 20 | return await CallbackQuery.answer(_["playcb_1"], show_alert=True) 21 | except: 22 | return 23 | try: 24 | chat_id, channel = await get_channeplayCB(_, cplay, CallbackQuery) 25 | except: 26 | return 27 | video = True if mode == "v" else None 28 | user_name = CallbackQuery.from_user.first_name 29 | await CallbackQuery.message.delete() 30 | try: 31 | await CallbackQuery.answer() 32 | except: 33 | pass 34 | mystic = await CallbackQuery.message.reply_text( 35 | _["play_2"].format(channel) if channel else _["play_1"] 36 | ) 37 | try: 38 | details, track_id = await YouTube.track(vidid, True) 39 | except: 40 | return await mystic.edit_text(_["play_3"]) 41 | ffplay = True if fplay == "f" else None 42 | if not details["duration_min"]: 43 | try: 44 | await stream( 45 | _, 46 | mystic, 47 | user_id, 48 | details, 49 | chat_id, 50 | user_name, 51 | CallbackQuery.message.chat.id, 52 | video, 53 | streamtype="live", 54 | forceplay=ffplay, 55 | ) 56 | except Exception as e: 57 | ex_type = type(e).__name__ 58 | err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type) 59 | return await mystic.edit_text(err) 60 | else: 61 | return await mystic.edit_text("» ɴᴏᴛ ᴀ ʟɪᴠᴇ sᴛʀᴇᴀᴍ.") 62 | await mystic.delete() 63 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/blchat.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.misc import SUDOERS 8 | from DeadlineTech.utils.database import blacklist_chat, blacklisted_chats, whitelist_chat 9 | from DeadlineTech.utils.decorators.language import language 10 | from config import BANNED_USERS 11 | 12 | 13 | @app.on_message(filters.command(["blchat", "blacklistchat"]) & SUDOERS) 14 | @language 15 | async def blacklist_chat_func(client, message: Message, _): 16 | if len(message.command) != 2: 17 | return await message.reply_text(_["black_1"]) 18 | chat_id = int(message.text.strip().split()[1]) 19 | if chat_id in await blacklisted_chats(): 20 | return await message.reply_text(_["black_2"]) 21 | blacklisted = await blacklist_chat(chat_id) 22 | if blacklisted: 23 | await message.reply_text(_["black_3"]) 24 | else: 25 | await message.reply_text(_["black_9"]) 26 | try: 27 | await app.leave_chat(chat_id) 28 | except: 29 | pass 30 | 31 | 32 | @app.on_message( 33 | filters.command(["whitelistchat", "unblacklistchat", "unblchat"]) & SUDOERS 34 | ) 35 | @language 36 | async def white_funciton(client, message: Message, _): 37 | if len(message.command) != 2: 38 | return await message.reply_text(_["black_4"]) 39 | chat_id = int(message.text.strip().split()[1]) 40 | if chat_id not in await blacklisted_chats(): 41 | return await message.reply_text(_["black_5"]) 42 | whitelisted = await whitelist_chat(chat_id) 43 | if whitelisted: 44 | return await message.reply_text(_["black_6"]) 45 | await message.reply_text(_["black_9"]) 46 | 47 | 48 | @app.on_message(filters.command(["blchats", "blacklistedchats"]) & ~BANNED_USERS) 49 | @language 50 | async def all_chats(client, message: Message, _): 51 | text = _["black_7"] 52 | j = 0 53 | for count, chat_id in enumerate(await blacklisted_chats(), 1): 54 | try: 55 | title = (await app.get_chat(chat_id)).title 56 | except: 57 | title = "ᴘʀɪᴠᴀᴛᴇ ᴄʜᴀᴛ" 58 | j = 1 59 | text += f"{count}. {title}[{chat_id}]\n" 60 | if j == 0: 61 | await message.reply_text(_["black_8"].format(app.mention)) 62 | else: 63 | await message.reply_text(text) 64 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/block.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.misc import SUDOERS 8 | from DeadlineTech.utils.database import add_gban_user, remove_gban_user 9 | from DeadlineTech.utils.decorators.language import language 10 | from DeadlineTech.utils.extraction import extract_user 11 | from config import BANNED_USERS 12 | 13 | 14 | @app.on_message(filters.command(["block"]) & SUDOERS) 15 | @language 16 | async def useradd(client, message: Message, _): 17 | if not message.reply_to_message: 18 | if len(message.command) != 2: 19 | return await message.reply_text(_["general_1"]) 20 | user = await extract_user(message) 21 | if user.id in BANNED_USERS: 22 | return await message.reply_text(_["block_1"].format(user.mention)) 23 | await add_gban_user(user.id) 24 | BANNED_USERS.add(user.id) 25 | await message.reply_text(_["block_2"].format(user.mention)) 26 | 27 | 28 | @app.on_message(filters.command(["unblock"]) & SUDOERS) 29 | @language 30 | async def userdel(client, message: Message, _): 31 | if not message.reply_to_message: 32 | if len(message.command) != 2: 33 | return await message.reply_text(_["general_1"]) 34 | user = await extract_user(message) 35 | if user.id not in BANNED_USERS: 36 | return await message.reply_text(_["block_3"].format(user.mention)) 37 | await remove_gban_user(user.id) 38 | BANNED_USERS.remove(user.id) 39 | await message.reply_text(_["block_4"].format(user.mention)) 40 | 41 | 42 | @app.on_message(filters.command(["blocked", "blockedusers", "blusers"]) & SUDOERS) 43 | @language 44 | async def sudoers_list(client, message: Message, _): 45 | if not BANNED_USERS: 46 | return await message.reply_text(_["block_5"]) 47 | mystic = await message.reply_text(_["block_6"]) 48 | msg = _["block_7"] 49 | count = 0 50 | for users in BANNED_USERS: 51 | try: 52 | user = await app.get_users(users) 53 | user = user.first_name if not user.mention else user.mention 54 | count += 1 55 | except: 56 | continue 57 | msg += f"{count}➤ {user}\n" 58 | if count == 0: 59 | return await mystic.edit_text(_["block_5"]) 60 | else: 61 | return await mystic.edit_text(msg) 62 | -------------------------------------------------------------------------------- /DeadlineTech/utils/stream/queue.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from typing import Union 3 | 4 | from DeadlineTech.misc import db 5 | from DeadlineTech.utils.formatters import check_duration, seconds_to_min 6 | from config import autoclean, time_to_seconds 7 | 8 | 9 | async def put_queue( 10 | chat_id, 11 | original_chat_id, 12 | file, 13 | title, 14 | duration, 15 | user, 16 | vidid, 17 | user_id, 18 | stream, 19 | forceplay: Union[bool, str] = None, 20 | ): 21 | title = title.title() 22 | try: 23 | duration_in_seconds = time_to_seconds(duration) - 3 24 | except: 25 | duration_in_seconds = 0 26 | put = { 27 | "title": title, 28 | "dur": duration, 29 | "streamtype": stream, 30 | "by": user, 31 | "user_id": user_id, 32 | "chat_id": original_chat_id, 33 | "file": file, 34 | "vidid": vidid, 35 | "seconds": duration_in_seconds, 36 | "played": 0, 37 | } 38 | if forceplay: 39 | check = db.get(chat_id) 40 | if check: 41 | check.insert(0, put) 42 | else: 43 | db[chat_id] = [] 44 | db[chat_id].append(put) 45 | else: 46 | db[chat_id].append(put) 47 | autoclean.append(file) 48 | 49 | 50 | async def put_queue_index( 51 | chat_id, 52 | original_chat_id, 53 | file, 54 | title, 55 | duration, 56 | user, 57 | vidid, 58 | stream, 59 | forceplay: Union[bool, str] = None, 60 | ): 61 | if "20.212.146.162" in vidid: 62 | try: 63 | dur = await asyncio.get_event_loop().run_in_executor( 64 | None, check_duration, vidid 65 | ) 66 | duration = seconds_to_min(dur) 67 | except: 68 | duration = "ᴜʀʟ sᴛʀᴇᴀᴍ" 69 | dur = 0 70 | else: 71 | dur = 0 72 | put = { 73 | "title": title, 74 | "dur": duration, 75 | "streamtype": stream, 76 | "by": user, 77 | "chat_id": original_chat_id, 78 | "file": file, 79 | "vidid": vidid, 80 | "seconds": dur, 81 | "played": 0, 82 | } 83 | if forceplay: 84 | check = db.get(chat_id) 85 | if check: 86 | check.insert(0, put) 87 | else: 88 | db[chat_id] = [] 89 | db[chat_id].append(put) 90 | else: 91 | db[chat_id].append(put) 92 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": " DeadlineTech Music", 3 | "description": "A Telegram Music Player Bot, written in Python with Pyrogram and Py-Tgcalls.", 4 | "logo": "https://files.catbox.moe/lxn8yz.jpg", 5 | "keywords": [ 6 | "python3", 7 | "telegram", 8 | "bot", 9 | "DeadlineTech", 10 | "MusicBot", 11 | "telegram-bot", 12 | "pyrogram" 13 | ], 14 | "env": { 15 | "API_ID": { 16 | "description": "Get this value from https://my.telegram.org", 17 | "value": "", 18 | "required": true 19 | }, 20 | "API_HASH": { 21 | "description": "Get this value from https://my.telegram.org", 22 | "value": "", 23 | "required": true 24 | }, 25 | "BOT_TOKEN": { 26 | "description": "A Bot's token from Botfather", 27 | "value": "", 28 | "required": true 29 | }, 30 | "MONGO_DB_URI": { 31 | "description": "Get a mongodb url from https://cloud.mongodb.com.", 32 | "value": "", 33 | "required": true 34 | }, 35 | "OWNER_ID": { 36 | "description": "The user id of user whom you would like to add as OWNER.", 37 | "value": "", 38 | "required": true 39 | }, 40 | "API_KEY": { 41 | "description": "Get your Music Api key from @ApixhubBot.", 42 | "value": "", 43 | "required": false 44 | }, 45 | "STRING_SESSION": { 46 | "description": "A Pyrogram v2 String Session from @StringFatherBot on Telegram.", 47 | "value": "", 48 | "required": true 49 | }, 50 | "HEROKU_API_KEY": { 51 | "description": "Your Heroku account's API key", 52 | "value": "", 53 | "required": false 54 | }, 55 | "HEROKU_APP_NAME": { 56 | "description": "Your heroku app name", 57 | "value": "", 58 | "required": false 59 | }, 60 | "LOGGER_ID": { 61 | "description": "Your Log Group ID, add your bot and promote as an admin with full rights!. Channel ki id mat daal dena bsdk.", 62 | "value": "", 63 | "required": true 64 | } 65 | }, 66 | "buildpacks": [ 67 | { 68 | "url": "heroku/python" 69 | }, 70 | { 71 | "url": "heroku/nodejs" 72 | }, 73 | { 74 | "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git" 75 | } 76 | ], 77 | "stack": "container" 78 | } 79 | -------------------------------------------------------------------------------- /DeadlineTech/platforms/Soundcloud.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | 27 | from os import path 28 | 29 | from yt_dlp import YoutubeDL 30 | 31 | from DeadlineTech.utils.formatters import seconds_to_min 32 | 33 | 34 | class SoundAPI: 35 | def __init__(self): 36 | self.opts = { 37 | "outtmpl": "downloads/%(id)s.%(ext)s", 38 | "format": "best", 39 | "retries": 3, 40 | "nooverwrites": False, 41 | "continuedl": True, 42 | } 43 | 44 | async def valid(self, link: str): 45 | if "soundcloud" in link: 46 | return True 47 | else: 48 | return False 49 | 50 | async def download(self, url): 51 | d = YoutubeDL(self.opts) 52 | try: 53 | info = d.extract_info(url) 54 | except: 55 | return False 56 | xyz = path.join("downloads", f"{info['id']}.{info['ext']}") 57 | duration_min = seconds_to_min(info["duration"]) 58 | track_details = { 59 | "title": info["title"], 60 | "duration_sec": info["duration"], 61 | "duration_min": duration_min, 62 | "uploader": info["uploader"], 63 | "filepath": xyz, 64 | } 65 | return track_details, xyz 66 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/bot/inline.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram.types import ( 4 | InlineKeyboardButton, 5 | InlineKeyboardMarkup, 6 | InlineQueryResultPhoto, 7 | ) 8 | from youtubesearchpython.__future__ import VideosSearch 9 | 10 | from DeadlineTech import app 11 | from DeadlineTech.utils.inlinequery import answer 12 | from config import BANNED_USERS 13 | 14 | 15 | @app.on_inline_query(~BANNED_USERS) 16 | async def inline_query_handler(client, query): 17 | text = query.query.strip().lower() 18 | answers = [] 19 | if text.strip() == "": 20 | try: 21 | await client.answer_inline_query(query.id, results=answer, cache_time=10) 22 | except: 23 | return 24 | else: 25 | a = VideosSearch(text, limit=20) 26 | result = (await a.next()).get("result") 27 | for x in range(15): 28 | title = (result[x]["title"]).title() 29 | duration = result[x]["duration"] 30 | views = result[x]["viewCount"]["short"] 31 | thumbnail = result[x]["thumbnails"][0]["url"].split("?")[0] 32 | channellink = result[x]["channel"]["link"] 33 | channel = result[x]["channel"]["name"] 34 | link = result[x]["link"] 35 | published = result[x]["publishedTime"] 36 | description = f"{views} | {duration} ᴍɪɴᴜᴛᴇs | {channel} | {published}" 37 | buttons = InlineKeyboardMarkup( 38 | [ 39 | [ 40 | InlineKeyboardButton( 41 | text="ʏᴏᴜᴛᴜʙᴇ 🎄", 42 | url=link, 43 | ) 44 | ], 45 | ] 46 | ) 47 | searched_text = f""" 48 | ❄ ᴛɪᴛʟᴇ : {title} 49 | 50 | ⏳ ᴅᴜʀᴀᴛɪᴏɴ : {duration} ᴍɪɴᴜᴛᴇs 51 | 👀 ᴠɪᴇᴡs : {views} 52 | 🎥 ᴄʜᴀɴɴᴇʟ : {channel} 53 | ⏰ ᴘᴜʙʟɪsʜᴇᴅ ᴏɴ : {published} 54 | 55 | 56 | ➻ ɪɴʟɪɴᴇ sᴇᴀʀᴄʜ ᴍᴏᴅᴇ ʙʏ {app.name}""" 57 | answers.append( 58 | InlineQueryResultPhoto( 59 | photo_url=thumbnail, 60 | title=title, 61 | thumb_url=thumbnail, 62 | description=description, 63 | caption=searched_text, 64 | reply_markup=buttons, 65 | ) 66 | ) 67 | try: 68 | return await client.answer_inline_query(query.id, results=answers) 69 | except: 70 | return 71 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/language.py: -------------------------------------------------------------------------------- 1 | from pykeyboard import InlineKeyboard 2 | from pyrogram import filters 3 | from pyrogram.types import InlineKeyboardButton, Message 4 | 5 | from DeadlineTech import app 6 | from DeadlineTech.utils.database import get_lang, set_lang 7 | from DeadlineTech.utils.decorators import ActualAdminCB, language, languageCB 8 | from config import BANNED_USERS 9 | from strings import get_string, languages_present 10 | 11 | 12 | def lanuages_keyboard(_): 13 | keyboard = InlineKeyboard(row_width=2) 14 | keyboard.add( 15 | *[ 16 | ( 17 | InlineKeyboardButton( 18 | text=languages_present[i], 19 | callback_data=f"languages:{i}", 20 | ) 21 | ) 22 | for i in languages_present 23 | ] 24 | ) 25 | keyboard.row( 26 | InlineKeyboardButton( 27 | text=_["BACK_BUTTON"], 28 | callback_data=f"settingsback_helper", 29 | ), 30 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data=f"close"), 31 | ) 32 | return keyboard 33 | 34 | 35 | @app.on_message(filters.command(["lang", "setlang", "language"]) & ~BANNED_USERS) 36 | @language 37 | async def langs_command(client, message: Message, _): 38 | keyboard = lanuages_keyboard(_) 39 | await message.reply_text( 40 | _["lang_1"], 41 | reply_markup=keyboard, 42 | ) 43 | 44 | 45 | @app.on_callback_query(filters.regex("LG") & ~BANNED_USERS) 46 | @languageCB 47 | async def lanuagecb(client, CallbackQuery, _): 48 | try: 49 | await CallbackQuery.answer() 50 | except: 51 | pass 52 | keyboard = lanuages_keyboard(_) 53 | return await CallbackQuery.edit_message_reply_markup(reply_markup=keyboard) 54 | 55 | 56 | @app.on_callback_query(filters.regex(r"languages:(.*?)") & ~BANNED_USERS) 57 | @ActualAdminCB 58 | async def language_markup(client, CallbackQuery, _): 59 | langauge = (CallbackQuery.data).split(":")[1] 60 | old = await get_lang(CallbackQuery.message.chat.id) 61 | if str(old) == str(langauge): 62 | return await CallbackQuery.answer(_["lang_4"], show_alert=True) 63 | try: 64 | _ = get_string(langauge) 65 | await CallbackQuery.answer(_["lang_2"], show_alert=True) 66 | except: 67 | _ = get_string(old) 68 | return await CallbackQuery.answer( 69 | _["lang_3"], 70 | show_alert=True, 71 | ) 72 | await set_lang(CallbackQuery.message.chat.id, langauge) 73 | keyboard = lanuages_keyboard(_) 74 | return await CallbackQuery.edit_message_reply_markup(reply_markup=keyboard) 75 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/chatlog.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from pyrogram import Client, filters 3 | from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup 4 | from DeadlineTech import app 5 | from config import LOGGER_ID as JOINLOGS 6 | 7 | # Setup logging 8 | logger = logging.getLogger(__name__) 9 | logging.basicConfig(level=logging.INFO) 10 | 11 | # Cache the bot's ID at startup 12 | BOT_ID = None 13 | 14 | 15 | @app.on_message(filters.new_chat_members) 16 | async def on_new_chat_members(client: Client, message: Message): 17 | global BOT_ID 18 | 19 | try: 20 | if BOT_ID is None: 21 | bot_user = await client.get_me() 22 | BOT_ID = bot_user.id 23 | logger.info(f"Cached bot ID: {BOT_ID}") 24 | except Exception as e: 25 | logger.exception("Failed to get bot info") 26 | return # Early exit to prevent further failures 27 | 28 | for new_member in message.new_chat_members: 29 | if new_member.id == BOT_ID: 30 | try: 31 | added_by = ( 32 | f"👤{message.from_user.first_name}" 33 | if message.from_user else "Unknown User" 34 | ) 35 | 36 | chat_title = message.chat.title 37 | chat_id = message.chat.id 38 | chat_username = f"@{message.chat.username}" if message.chat.username else "Private Group" 39 | chat_link = ( 40 | f"https://t.me/{message.chat.username}" 41 | if message.chat.username else None 42 | ) 43 | 44 | log_text = ( 45 | "🚀 Bot Added Successfully!\n\n" 46 | "╭───────⍟\n" 47 | f"├ 💬 Chat Name: {chat_title}\n" 48 | f"├ 🆔 Chat ID: {chat_id}\n" 49 | f"├ 🌐 Username: {chat_username}\n" 50 | f"└ 👤 Added By: {added_by}\n" 51 | "╰─────────────⍟" 52 | ) 53 | 54 | buttons = [[InlineKeyboardButton("➤ Link 🔗", url=chat_link)]] if chat_link else None 55 | 56 | await client.send_message( 57 | JOINLOGS, 58 | text=log_text, 59 | reply_markup=InlineKeyboardMarkup(buttons) if buttons else None, 60 | disable_web_page_preview=True 61 | ) 62 | logger.info(f"Join log sent for chat ID: {chat_id}") 63 | except Exception as e: 64 | logger.exception(f"[JOINLOG ERROR] Failed to send join log for chat ID: {message.chat.id}") 65 | 66 | 67 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/active.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from pyrogram import filters 3 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery 4 | from datetime import datetime 5 | from zoneinfo import ZoneInfo 6 | 7 | from DeadlineTech import app 8 | from DeadlineTech.misc import SUDOERS 9 | from DeadlineTech.utils.database import ( 10 | get_active_chats, 11 | get_active_video_chats, 12 | ) 13 | 14 | # Setup logger 15 | logger = logging.getLogger(__name__) 16 | logging.basicConfig(level=logging.INFO) 17 | 18 | CALLS_CLOSE = "calls_close" 19 | TIMEZONE = "Asia/Kolkata" 20 | 21 | 22 | def get_current_time(): 23 | try: 24 | now = datetime.now(ZoneInfo(TIMEZONE)) 25 | return now.strftime("%d %b %Y • %I:%M %p") 26 | except Exception as e: 27 | logger.exception(f"Error getting current time: {e}") 28 | return "Unknown Time" 29 | 30 | 31 | def generate_summary_text(voice_count, video_count): 32 | total = voice_count + video_count 33 | return ( 34 | "📊 Call Activity Summary\n" 35 | "━━━━━━━━━━━━━━━━━━━━━━\n" 36 | f"🔊 Voice Chats: {voice_count}\n" 37 | f"🎥 Video Chats: {video_count}\n" 38 | f"📞 Total: {total}\n" 39 | f"🕒 Updated: {get_current_time()}" 40 | ) 41 | 42 | 43 | @app.on_message(filters.command(["activecalls", "acalls"]) & SUDOERS) 44 | async def active_calls(_, message: Message): 45 | try: 46 | voice_ids = await get_active_chats() 47 | video_ids = await get_active_video_chats() 48 | except Exception as e: 49 | logger.exception("Error fetching active chats or video chats.") 50 | return await message.reply_text("❌ Failed to fetch active calls. Check logs for details.") 51 | 52 | try: 53 | text = generate_summary_text(len(voice_ids), len(video_ids)) 54 | button = InlineKeyboardMarkup( 55 | [[InlineKeyboardButton("✖ Close", callback_data=CALLS_CLOSE)]] 56 | ) 57 | await message.reply_text(text, reply_markup=button) 58 | except Exception as e: 59 | logger.exception("Failed to send summary message.") 60 | await message.reply_text("❌ Error displaying call summary.") 61 | 62 | 63 | @app.on_callback_query(filters.regex(CALLS_CLOSE) & SUDOERS) 64 | async def close_calls(_, query: CallbackQuery): 65 | try: 66 | await query.message.delete() 67 | await query.answer("Closed!") 68 | except Exception as e: 69 | logger.exception("Failed to close the inline message.") 70 | try: 71 | await query.answer("❌ Couldn't close the message.", show_alert=True) 72 | except: 73 | pass 74 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/sudoers.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from DeadlineTech import app 5 | from DeadlineTech.misc import SUDOERS 6 | from DeadlineTech.utils.database import add_sudo, remove_sudo 7 | from DeadlineTech.utils.decorators.language import language 8 | from DeadlineTech.utils.extraction import extract_user 9 | from DeadlineTech.utils.inline import close_markup 10 | from config import BANNED_USERS, OWNER_ID 11 | 12 | 13 | @app.on_message(filters.command(["addsudo"]) & filters.user(OWNER_ID)) 14 | @language 15 | async def useradd(client, message: Message, _): 16 | if not message.reply_to_message: 17 | if len(message.command) != 2: 18 | return await message.reply_text(_["general_1"]) 19 | user = await extract_user(message) 20 | if user.id in SUDOERS: 21 | return await message.reply_text(_["sudo_1"].format(user.mention)) 22 | added = await add_sudo(user.id) 23 | if added: 24 | SUDOERS.add(user.id) 25 | await message.reply_text(_["sudo_2"].format(user.mention)) 26 | else: 27 | await message.reply_text(_["sudo_8"]) 28 | 29 | 30 | @app.on_message(filters.command(["delsudo", "rmsudo"]) & filters.user(OWNER_ID)) 31 | @language 32 | async def userdel(client, message: Message, _): 33 | if not message.reply_to_message: 34 | if len(message.command) != 2: 35 | return await message.reply_text(_["general_1"]) 36 | user = await extract_user(message) 37 | if user.id not in SUDOERS: 38 | return await message.reply_text(_["sudo_3"].format(user.mention)) 39 | removed = await remove_sudo(user.id) 40 | if removed: 41 | SUDOERS.remove(user.id) 42 | await message.reply_text(_["sudo_4"].format(user.mention)) 43 | else: 44 | await message.reply_text(_["sudo_8"]) 45 | 46 | 47 | @app.on_message(filters.command(["sudolist", "listsudo", "sudoers"]) & ~BANNED_USERS) 48 | @language 49 | async def sudoers_list(client, message: Message, _): 50 | text = _["sudo_5"] 51 | user = await app.get_users(OWNER_ID) 52 | user = user.first_name if not user.mention else user.mention 53 | text += f"1➤ {user}\n" 54 | count = 0 55 | smex = 0 56 | for user_id in SUDOERS: 57 | if user_id != OWNER_ID: 58 | try: 59 | user = await app.get_users(user_id) 60 | user = user.first_name if not user.mention else user.mention 61 | if smex == 0: 62 | smex += 1 63 | text += _["sudo_6"] 64 | count += 1 65 | text += f"{count}➤ {user}\n" 66 | except: 67 | continue 68 | if not text: 69 | await message.reply_text(_["sudo_7"]) 70 | else: 71 | await message.reply_text(text, reply_markup=close_markup(_)) 72 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/seek.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import YouTube, app 7 | from DeadlineTech.core.call import Anony 8 | from DeadlineTech.misc import db 9 | from DeadlineTech.utils import AdminRightsCheck, seconds_to_min 10 | from DeadlineTech.utils.inline import close_markup 11 | from config import BANNED_USERS 12 | 13 | 14 | @app.on_message( 15 | filters.command(["seek", "cseek", "seekback", "cseekback"]) 16 | & filters.group 17 | & ~BANNED_USERS 18 | ) 19 | @AdminRightsCheck 20 | async def seek_comm(cli, message: Message, _, chat_id): 21 | if len(message.command) == 1: 22 | return await message.reply_text(_["admin_20"]) 23 | query = message.text.split(None, 1)[1].strip() 24 | if not query.isnumeric(): 25 | return await message.reply_text(_["admin_21"]) 26 | playing = db.get(chat_id) 27 | if not playing: 28 | return await message.reply_text(_["queue_2"]) 29 | duration_seconds = int(playing[0]["seconds"]) 30 | if duration_seconds == 0: 31 | return await message.reply_text(_["admin_22"]) 32 | file_path = playing[0]["file"] 33 | duration_played = int(playing[0]["played"]) 34 | duration_to_skip = int(query) 35 | duration = playing[0]["dur"] 36 | if message.command[0][-2] == "c": 37 | if (duration_played - duration_to_skip) <= 10: 38 | return await message.reply_text( 39 | text=_["admin_23"].format(seconds_to_min(duration_played), duration), 40 | reply_markup=close_markup(_), 41 | ) 42 | to_seek = duration_played - duration_to_skip + 1 43 | else: 44 | if (duration_seconds - (duration_played + duration_to_skip)) <= 10: 45 | return await message.reply_text( 46 | text=_["admin_23"].format(seconds_to_min(duration_played), duration), 47 | reply_markup=close_markup(_), 48 | ) 49 | to_seek = duration_played + duration_to_skip + 1 50 | mystic = await message.reply_text(_["admin_24"]) 51 | if "vid_" in file_path: 52 | n, file_path = await YouTube.video(playing[0]["vidid"], True) 53 | if n == 0: 54 | return await message.reply_text(_["admin_22"]) 55 | check = (playing[0]).get("speed_path") 56 | if check: 57 | file_path = check 58 | if "index_" in file_path: 59 | file_path = playing[0]["vidid"] 60 | try: 61 | await Anony.seek_stream( 62 | chat_id, 63 | file_path, 64 | seconds_to_min(to_seek), 65 | duration, 66 | playing[0]["streamtype"], 67 | ) 68 | except: 69 | return await mystic.edit_text(_["admin_26"], reply_markup=close_markup(_)) 70 | if message.command[0][-2] == "c": 71 | db[chat_id][0]["played"] -= duration_to_skip 72 | else: 73 | db[chat_id][0]["played"] += duration_to_skip 74 | await mystic.edit_text( 75 | text=_["admin_25"].format(seconds_to_min(to_seek), message.from_user.mention), 76 | reply_markup=close_markup(_), 77 | ) 78 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/misc/auto_leave.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | from datetime import datetime, timedelta 4 | import pytz 5 | 6 | from pyrogram.enums import ChatType 7 | 8 | import config 9 | from DeadlineTech import app 10 | from DeadlineTech.utils.database import get_client, is_active_chat 11 | 12 | # Set up logging 13 | logging.basicConfig( 14 | level=logging.INFO, 15 | format="%(asctime)s - [%(levelname)s] - %(message)s", 16 | datefmt="%Y-%m-%d %H:%M:%S", 17 | ) 18 | logger = logging.getLogger("AutoLeave") 19 | 20 | # Constants 21 | EXCLUDED_CHAT_IDS = {config.LOGGER_ID} 22 | MAX_LEAVES_PER_RUN = 120 23 | TIMEZONE = "Asia/Kolkata" 24 | TARGET_HOUR = 4 25 | TARGET_MINUTE = 35 26 | 27 | def seconds_until_target_time(hour: int = TARGET_HOUR, minute: int = TARGET_MINUTE) -> float: 28 | """Calculate seconds remaining until the next target time (default: 4:35 AM IST).""" 29 | tz = pytz.timezone(TIMEZONE) 30 | now = datetime.now(tz) 31 | target = now.replace(hour=hour, minute=minute, second=0, microsecond=0) 32 | if now >= target: 33 | target += timedelta(days=1) 34 | return (target - now).total_seconds() 35 | 36 | async def leave_inactive_chats(client, client_num: int): 37 | """Make the client leave inactive chats.""" 38 | left_count = 0 39 | try: 40 | async for dialog in client.get_dialogs(): 41 | chat = dialog.chat 42 | if chat.type in {ChatType.SUPERGROUP, ChatType.GROUP, ChatType.CHANNEL}: 43 | if chat.id in EXCLUDED_CHAT_IDS: 44 | continue 45 | if left_count >= MAX_LEAVES_PER_RUN: 46 | break 47 | if not await is_active_chat(chat.id): 48 | try: 49 | await client.leave_chat(chat.id) 50 | logger.info(f"{client.me.first_name} left inactive chat: {chat.title} ({chat.id})") 51 | left_count += 1 52 | except Exception as e: 53 | logger.warning(f"Failed to leave chat {chat.title} ({chat.id}): {e}") 54 | except Exception as e: 55 | logger.error(f"Assistant {client_num} failed to fetch dialogs: {e}") 56 | 57 | async def auto_leave(): 58 | """Run auto leave job daily at 4:35 AM IST.""" 59 | if not config.AUTO_LEAVING_ASSISTANT: 60 | logger.info("AUTO_LEAVING_ASSISTANT is disabled. Exiting auto_leave task.") 61 | return 62 | 63 | logger.info("AutoLeave task started and running in background.") 64 | from DeadlineTech.core.userbot import assistants 65 | 66 | while True: 67 | seconds_to_sleep = seconds_until_target_time() 68 | hrs, mins = divmod(seconds_to_sleep // 60, 60) 69 | logger.info(f"Sleeping for {int(hrs)}h {int(mins)}m until 4:35 AM IST.") 70 | await asyncio.sleep(seconds_to_sleep) 71 | 72 | logger.info("Running cleanup of inactive chats...") 73 | for num in assistants: 74 | client = await get_client(num) 75 | await leave_inactive_chats(client, num) 76 | logger.info("Cleanup complete. Sleeping again until next 4:35 AM.") 77 | 78 | # Start the background auto leave task 79 | asyncio.create_task(auto_leave()) 80 | -------------------------------------------------------------------------------- /DeadlineTech/platforms/Resso.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | 27 | import re 28 | from typing import Union 29 | 30 | import aiohttp 31 | from bs4 import BeautifulSoup 32 | from youtubesearchpython.__future__ import VideosSearch 33 | 34 | 35 | class RessoAPI: 36 | def __init__(self): 37 | self.regex = r"^(https:\/\/m.resso.com\/)(.*)$" 38 | self.base = "https://m.resso.com/" 39 | 40 | async def valid(self, link: str): 41 | if re.search(self.regex, link): 42 | return True 43 | else: 44 | return False 45 | 46 | async def track(self, url, playid: Union[bool, str] = None): 47 | if playid: 48 | url = self.base + url 49 | async with aiohttp.ClientSession() as session: 50 | async with session.get(url) as response: 51 | if response.status != 200: 52 | return False 53 | html = await response.text() 54 | soup = BeautifulSoup(html, "html.parser") 55 | for tag in soup.find_all("meta"): 56 | if tag.get("property", None) == "og:title": 57 | title = tag.get("content", None) 58 | if tag.get("property", None) == "og:description": 59 | des = tag.get("content", None) 60 | try: 61 | des = des.split("·")[0] 62 | except: 63 | pass 64 | if des == "": 65 | return 66 | results = VideosSearch(title, limit=1) 67 | for result in (await results.next())["result"]: 68 | title = result["title"] 69 | ytlink = result["link"] 70 | vidid = result["id"] 71 | duration_min = result["duration"] 72 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 73 | track_details = { 74 | "title": title, 75 | "link": ytlink, 76 | "vidid": vidid, 77 | "duration_min": duration_min, 78 | "thumb": thumbnail, 79 | } 80 | return track_details, vidid 81 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/auth.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.utils import extract_user, int_to_alpha 8 | from DeadlineTech.utils.database import ( 9 | delete_authuser, 10 | get_authuser, 11 | get_authuser_names, 12 | save_authuser, 13 | ) 14 | from DeadlineTech.utils.decorators import AdminActual, language 15 | from DeadlineTech.utils.inline import close_markup 16 | from config import BANNED_USERS, adminlist 17 | 18 | 19 | @app.on_message(filters.command("auth") & filters.group & ~BANNED_USERS) 20 | @AdminActual 21 | async def auth(client, message: Message, _): 22 | if not message.reply_to_message: 23 | if len(message.command) != 2: 24 | return await message.reply_text(_["general_1"]) 25 | user = await extract_user(message) 26 | token = await int_to_alpha(user.id) 27 | _check = await get_authuser_names(message.chat.id) 28 | count = len(_check) 29 | if int(count) == 25: 30 | return await message.reply_text(_["auth_1"]) 31 | if token not in _check: 32 | assis = { 33 | "auth_user_id": user.id, 34 | "auth_name": user.first_name, 35 | "admin_id": message.from_user.id, 36 | "admin_name": message.from_user.first_name, 37 | } 38 | get = adminlist.get(message.chat.id) 39 | if get: 40 | if user.id not in get: 41 | get.append(user.id) 42 | await save_authuser(message.chat.id, token, assis) 43 | return await message.reply_text(_["auth_2"].format(user.mention)) 44 | else: 45 | return await message.reply_text(_["auth_3"].format(user.mention)) 46 | 47 | 48 | @app.on_message(filters.command("unauth") & filters.group & ~BANNED_USERS) 49 | @AdminActual 50 | async def unauthusers(client, message: Message, _): 51 | if not message.reply_to_message: 52 | if len(message.command) != 2: 53 | return await message.reply_text(_["general_1"]) 54 | user = await extract_user(message) 55 | token = await int_to_alpha(user.id) 56 | deleted = await delete_authuser(message.chat.id, token) 57 | get = adminlist.get(message.chat.id) 58 | if get: 59 | if user.id in get: 60 | get.remove(user.id) 61 | if deleted: 62 | return await message.reply_text(_["auth_4"].format(user.mention)) 63 | else: 64 | return await message.reply_text(_["auth_5"].format(user.mention)) 65 | 66 | 67 | @app.on_message( 68 | filters.command(["authlist", "authusers"]) & filters.group & ~BANNED_USERS 69 | ) 70 | @language 71 | async def authusers(client, message: Message, _): 72 | _wtf = await get_authuser_names(message.chat.id) 73 | if not _wtf: 74 | return await message.reply_text(_["setting_4"]) 75 | else: 76 | j = 0 77 | mystic = await message.reply_text(_["auth_6"]) 78 | text = _["auth_7"].format(message.chat.title) 79 | for umm in _wtf: 80 | _umm = await get_authuser(message.chat.id, umm) 81 | user_id = _umm["auth_user_id"] 82 | admin_id = _umm["admin_id"] 83 | admin_name = _umm["admin_name"] 84 | try: 85 | user = (await app.get_users(user_id)).first_name 86 | j += 1 87 | except: 88 | continue 89 | text += f"{j}➤ {user}[{user_id}]\n" 90 | text += f" {_['auth_8']} {admin_name}[{admin_id}]\n\n" 91 | await mystic.edit_text(text, reply_markup=close_markup(_)) 92 | -------------------------------------------------------------------------------- /DeadlineTech/utils/decorators/language.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from DeadlineTech.misc import SUDOERS 3 | from DeadlineTech.utils.database import get_lang, is_maintenance 4 | from config import SUPPORT_CHAT 5 | from strings import get_string 6 | from DeadlineTech import app 7 | 8 | # Setup logger 9 | logger = logging.getLogger(__name__) 10 | logging.basicConfig(level=logging.INFO) 11 | 12 | # Safe fallback to English 13 | def safe_get_string(lang_code): 14 | try: 15 | return get_string(lang_code) 16 | except Exception as e: 17 | logger.warning(f"Failed to load language string for {lang_code}: {e}") 18 | return get_string("en") 19 | 20 | 21 | def language(mystic): 22 | async def wrapper(_, message, **kwargs): 23 | try: 24 | if await is_maintenance() is False and message.from_user.id not in SUDOERS: 25 | return await message.reply_text( 26 | text=f"{app.mention} ɪs ᴜɴᴅᴇʀ ᴍᴀɪɴᴛᴇɴᴀɴᴄᴇ, ᴠɪsɪᴛ sᴜᴘᴘᴏʀᴛ ᴄʜᴀᴛ ғᴏʀ ᴋɴᴏᴡɪɴɢ ᴛʜᴇ ʀᴇᴀsᴏɴ.", 27 | disable_web_page_preview=True, 28 | ) 29 | except Exception as e: 30 | logger.error(f"Maintenance check failed: {e}") 31 | 32 | try: 33 | await message.delete() 34 | except Exception as e: 35 | logger.debug(f"Failed to delete user message: {e}") 36 | 37 | try: 38 | lang_code = await get_lang(message.chat.id) 39 | except Exception as e: 40 | logger.warning(f"Failed to fetch language from DB: {e}") 41 | lang_code = "en" 42 | 43 | language = safe_get_string(lang_code) 44 | 45 | try: 46 | return await mystic(_, message, language) 47 | except Exception as e: 48 | logger.exception(f"Error in wrapped language function: {e}") 49 | return await message.reply_text("⚠️ Something went wrong. Please try again later.") 50 | 51 | return wrapper 52 | 53 | 54 | def languageCB(mystic): 55 | async def wrapper(_, CallbackQuery, **kwargs): 56 | try: 57 | if await is_maintenance() is False and CallbackQuery.from_user.id not in SUDOERS: 58 | return await CallbackQuery.answer( 59 | f"{app.mention} ɪs ᴜɴᴅᴇʀ ᴍᴀɪɴᴛᴇɴᴀɴᴄᴇ. ᴘʟᴇᴀsᴇ ᴄʜᴇᴄᴋ {SUPPORT_CHAT}.", 60 | show_alert=True, 61 | ) 62 | except Exception as e: 63 | logger.error(f"Maintenance check failed in callback: {e}") 64 | 65 | try: 66 | lang_code = await get_lang(CallbackQuery.message.chat.id) 67 | except Exception as e: 68 | logger.warning(f"Failed to fetch language from DB (CB): {e}") 69 | lang_code = "en" 70 | 71 | language = safe_get_string(lang_code) 72 | 73 | try: 74 | return await mystic(_, CallbackQuery, language) 75 | except Exception as e: 76 | logger.exception(f"Error in wrapped languageCB function: {e}") 77 | return await CallbackQuery.answer("⚠️ Something went wrong. Please try again later.", show_alert=True) 78 | 79 | return wrapper 80 | 81 | 82 | def LanguageStart(mystic): 83 | async def wrapper(_, message, **kwargs): 84 | try: 85 | lang_code = await get_lang(message.chat.id) 86 | except Exception as e: 87 | logger.warning(f"Failed to fetch language from DB (start): {e}") 88 | lang_code = "en" 89 | 90 | language = safe_get_string(lang_code) 91 | 92 | try: 93 | return await mystic(_, message, language) 94 | except Exception as e: 95 | logger.exception(f"Error in wrapped LanguageStart function: {e}") 96 | return await message.reply_text("⚠️ An unexpected error occurred during startup.") 97 | 98 | return wrapper 99 | -------------------------------------------------------------------------------- /DeadlineTech/core/git.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | import asyncio 27 | import shlex 28 | from typing import Tuple 29 | 30 | from git import Repo 31 | from git.exc import GitCommandError, InvalidGitRepositoryError 32 | 33 | import config 34 | 35 | from ..logging import LOGGER 36 | 37 | 38 | def install_req(cmd: str) -> Tuple[str, str, int, int]: 39 | async def install_requirements(): 40 | args = shlex.split(cmd) 41 | process = await asyncio.create_subprocess_exec( 42 | *args, 43 | stdout=asyncio.subprocess.PIPE, 44 | stderr=asyncio.subprocess.PIPE, 45 | ) 46 | stdout, stderr = await process.communicate() 47 | return ( 48 | stdout.decode("utf-8", "replace").strip(), 49 | stderr.decode("utf-8", "replace").strip(), 50 | process.returncode, 51 | process.pid, 52 | ) 53 | 54 | return asyncio.get_event_loop().run_until_complete(install_requirements()) 55 | 56 | 57 | def git(): 58 | REPO_LINK = config.UPSTREAM_REPO 59 | if config.GIT_TOKEN: 60 | GIT_USERNAME = REPO_LINK.split("com/")[1].split("/")[0] 61 | TEMP_REPO = REPO_LINK.split("https://")[1] 62 | UPSTREAM_REPO = f"https://{GIT_USERNAME}:{config.GIT_TOKEN}@{TEMP_REPO}" 63 | else: 64 | UPSTREAM_REPO = config.UPSTREAM_REPO 65 | try: 66 | repo = Repo() 67 | LOGGER(__name__).info(f"[+] Git client located. Initializing VPS deployment process..") 68 | except GitCommandError: 69 | LOGGER(__name__).info(f"Invalid Git Command") 70 | except InvalidGitRepositoryError: 71 | repo = Repo.init() 72 | if "origin" in repo.remotes: 73 | origin = repo.remote("origin") 74 | else: 75 | origin = repo.create_remote("origin", UPSTREAM_REPO) 76 | origin.fetch() 77 | repo.create_head( 78 | config.UPSTREAM_BRANCH, 79 | origin.refs[config.UPSTREAM_BRANCH], 80 | ) 81 | repo.heads[config.UPSTREAM_BRANCH].set_tracking_branch( 82 | origin.refs[config.UPSTREAM_BRANCH] 83 | ) 84 | repo.heads[config.UPSTREAM_BRANCH].checkout(True) 85 | try: 86 | repo.create_remote("origin", config.UPSTREAM_REPO) 87 | except BaseException: 88 | pass 89 | nrs = repo.remote("origin") 90 | nrs.fetch(config.UPSTREAM_BRANCH) 91 | try: 92 | nrs.pull(config.UPSTREAM_BRANCH) 93 | except GitCommandError: 94 | repo.git.reset("--hard", "FETCH_HEAD") 95 | install_req("pip3 install --no-cache-dir -r requirements.txt") 96 | LOGGER(__name__).info(f"Fetching updates from upstream repository...") 97 | -------------------------------------------------------------------------------- /DeadlineTech/core/bot.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | import uvloop 26 | uvloop.install() 27 | 28 | import asyncio 29 | from pyrogram import Client, errors 30 | from pyrogram.enums import ChatMemberStatus, ParseMode 31 | 32 | import config 33 | from ..logging import LOGGER 34 | 35 | 36 | class Anony(Client): 37 | def __init__(self): 38 | LOGGER(__name__).info("🛠️ Initializing DeadlineTech Bot...") 39 | super().__init__( 40 | name="DeadlineTech", 41 | api_id=config.API_ID, 42 | api_hash=config.API_HASH, 43 | bot_token=config.BOT_TOKEN, 44 | in_memory=True, 45 | parse_mode=ParseMode.HTML, 46 | max_concurrent_transmissions=7, 47 | ) 48 | 49 | async def start(self): 50 | await super().start() 51 | 52 | self.id = self.me.id 53 | self.name = f"{self.me.first_name} {self.me.last_name or ''}".strip() 54 | self.username = self.me.username 55 | self.mention = self.me.mention 56 | 57 | try: 58 | await self.send_message( 59 | chat_id=config.LOGGER_ID, 60 | text=( 61 | f"✅ Bot Started Successfully!\n\n" 62 | f"Name: {self.name}\n" 63 | f"Username: @{self.username}\n" 64 | f"User ID: {self.id}" 65 | ), 66 | ) 67 | except (errors.ChannelInvalid, errors.PeerIdInvalid): 68 | LOGGER(__name__).error( 69 | "❌ Unable to send message to the log group/channel. " 70 | "Ensure the bot is added and not banned." 71 | ) 72 | exit() 73 | except Exception as ex: 74 | LOGGER(__name__).error( 75 | f"❌ Failed to access the log group/channel.\nReason: {type(ex).__name__}" 76 | ) 77 | exit() 78 | 79 | try: 80 | member = await self.get_chat_member(config.LOGGER_ID, self.id) 81 | if member.status != ChatMemberStatus.ADMINISTRATOR: 82 | LOGGER(__name__).error( 83 | "⚠️ Bot is not an admin in the log group/channel. Please promote it as admin." 84 | ) 85 | exit() 86 | except Exception as ex: 87 | LOGGER(__name__).error( 88 | f"❌ Failed to fetch bot status in log group. Reason: {type(ex).__name__}" 89 | ) 90 | exit() 91 | 92 | LOGGER(__name__).info(f"🎶 Bot is online and ready as {self.name} (@{self.username})") 93 | 94 | async def stop(self): 95 | LOGGER(__name__).info("🛑 Stopping DeadlineTech Bot...") 96 | await super().stop() 97 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/settings.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram.types import InlineKeyboardButton 4 | 5 | 6 | def setting_markup(_): 7 | buttons = [ 8 | [ 9 | InlineKeyboardButton(text=_["ST_B_1"], callback_data="AU"), 10 | InlineKeyboardButton(text=_["ST_B_3"], callback_data="LG"), 11 | ], 12 | [ 13 | InlineKeyboardButton(text=_["ST_B_2"], callback_data="PM"), 14 | ], 15 | [ 16 | InlineKeyboardButton(text=_["ST_B_4"], callback_data="VM"), 17 | ], 18 | [ 19 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 20 | ], 21 | ] 22 | return buttons 23 | 24 | 25 | def vote_mode_markup(_, current, mode: Union[bool, str] = None): 26 | buttons = [ 27 | [ 28 | InlineKeyboardButton(text="Vᴏᴛɪɴɢ ᴍᴏᴅᴇ ➜", callback_data="VOTEANSWER"), 29 | InlineKeyboardButton( 30 | text=_["ST_B_5"] if mode == True else _["ST_B_6"], 31 | callback_data="VOMODECHANGE", 32 | ), 33 | ], 34 | [ 35 | InlineKeyboardButton(text="-2", callback_data="FERRARIUDTI M"), 36 | InlineKeyboardButton( 37 | text=f"ᴄᴜʀʀᴇɴᴛ : {current}", 38 | callback_data="ANSWERVOMODE", 39 | ), 40 | InlineKeyboardButton(text="+2", callback_data="FERRARIUDTI A"), 41 | ], 42 | [ 43 | InlineKeyboardButton( 44 | text=_["BACK_BUTTON"], 45 | callback_data="settings_helper", 46 | ), 47 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 48 | ], 49 | ] 50 | return buttons 51 | 52 | 53 | def auth_users_markup(_, status: Union[bool, str] = None): 54 | buttons = [ 55 | [ 56 | InlineKeyboardButton(text=_["ST_B_7"], callback_data="AUTHANSWER"), 57 | InlineKeyboardButton( 58 | text=_["ST_B_8"] if status == True else _["ST_B_9"], 59 | callback_data="AUTH", 60 | ), 61 | ], 62 | [ 63 | InlineKeyboardButton(text=_["ST_B_1"], callback_data="AUTHLIST"), 64 | ], 65 | [ 66 | InlineKeyboardButton( 67 | text=_["BACK_BUTTON"], 68 | callback_data="settings_helper", 69 | ), 70 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 71 | ], 72 | ] 73 | return buttons 74 | 75 | 76 | def playmode_users_markup( 77 | _, 78 | Direct: Union[bool, str] = None, 79 | Group: Union[bool, str] = None, 80 | Playtype: Union[bool, str] = None, 81 | ): 82 | buttons = [ 83 | [ 84 | InlineKeyboardButton(text=_["ST_B_10"], callback_data="SEARCHANSWER"), 85 | InlineKeyboardButton( 86 | text=_["ST_B_11"] if Direct == True else _["ST_B_12"], 87 | callback_data="MODECHANGE", 88 | ), 89 | ], 90 | [ 91 | InlineKeyboardButton(text=_["ST_B_13"], callback_data="AUTHANSWER"), 92 | InlineKeyboardButton( 93 | text=_["ST_B_8"] if Group == True else _["ST_B_9"], 94 | callback_data="CHANNELMODECHANGE", 95 | ), 96 | ], 97 | [ 98 | InlineKeyboardButton(text=_["ST_B_14"], callback_data="PLAYTYPEANSWER"), 99 | InlineKeyboardButton( 100 | text=_["ST_B_8"] if Playtype == True else _["ST_B_9"], 101 | callback_data="PLAYTYPECHANGE", 102 | ), 103 | ], 104 | [ 105 | InlineKeyboardButton( 106 | text=_["BACK_BUTTON"], 107 | callback_data="settings_helper", 108 | ), 109 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 110 | ], 111 | ] 112 | return buttons 113 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/help.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 4 | 5 | from DeadlineTech import app 6 | 7 | 8 | def help_pannel(_, START: Union[bool, int] = None): 9 | first = [InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data=f"close")] 10 | second = [ 11 | InlineKeyboardButton( 12 | text=_["BACK_BUTTON"], 13 | callback_data=f"settingsback_helper", 14 | ), 15 | ] 16 | mark = second if START else first 17 | upl = InlineKeyboardMarkup( 18 | [ 19 | [ 20 | InlineKeyboardButton( 21 | text=_["H_B_1"], 22 | callback_data="help_callback hb1", 23 | ), 24 | InlineKeyboardButton( 25 | text=_["H_B_2"], 26 | callback_data="help_callback hb2", 27 | ), 28 | InlineKeyboardButton( 29 | text=_["H_B_3"], 30 | callback_data="help_callback hb3", 31 | ), 32 | ], 33 | [ 34 | InlineKeyboardButton( 35 | text=_["H_B_4"], 36 | callback_data="help_callback hb4", 37 | ), 38 | InlineKeyboardButton( 39 | text=_["H_B_5"], 40 | callback_data="help_callback hb5", 41 | ), 42 | InlineKeyboardButton( 43 | text=_["H_B_6"], 44 | callback_data="help_callback hb6", 45 | ), 46 | ], 47 | [ 48 | InlineKeyboardButton( 49 | text=_["H_B_7"], 50 | callback_data="help_callback hb7", 51 | ), 52 | InlineKeyboardButton( 53 | text=_["H_B_8"], 54 | callback_data="help_callback hb8", 55 | ), 56 | InlineKeyboardButton( 57 | text=_["H_B_9"], 58 | callback_data="help_callback hb9", 59 | ), 60 | ], 61 | [ 62 | InlineKeyboardButton( 63 | text=_["H_B_10"], 64 | callback_data="help_callback hb10", 65 | ), 66 | InlineKeyboardButton( 67 | text=_["H_B_11"], 68 | callback_data="help_callback hb11", 69 | ), 70 | InlineKeyboardButton( 71 | text=_["H_B_12"], 72 | callback_data="help_callback hb12", 73 | ), 74 | ], 75 | [ 76 | InlineKeyboardButton( 77 | text=_["H_B_13"], 78 | callback_data="help_callback hb13", 79 | ), 80 | InlineKeyboardButton( 81 | text=_["H_B_14"], 82 | callback_data="help_callback hb14", 83 | ), 84 | InlineKeyboardButton( 85 | text=_["H_B_15"], 86 | callback_data="help_callback hb15", 87 | ), 88 | ], 89 | mark, 90 | ] 91 | ) 92 | return upl 93 | 94 | 95 | def help_back_markup(_): 96 | upl = InlineKeyboardMarkup( 97 | [ 98 | [ 99 | InlineKeyboardButton( 100 | text=_["BACK_BUTTON"], 101 | callback_data=f"settings_back_helper", 102 | ), 103 | ] 104 | ] 105 | ) 106 | return upl 107 | 108 | 109 | def private_help_panel(_): 110 | buttons = [ 111 | [ 112 | InlineKeyboardButton( 113 | text=_["S_B_4"], 114 | url=f"https://t.me/{app.username}?start=help", 115 | ), 116 | ], 117 | ] 118 | return buttons 119 | -------------------------------------------------------------------------------- /DeadlineTech/platforms/Apple.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | 27 | import re 28 | from typing import Union 29 | 30 | import aiohttp 31 | from bs4 import BeautifulSoup 32 | from youtubesearchpython.__future__ import VideosSearch 33 | 34 | 35 | class AppleAPI: 36 | def __init__(self): 37 | self.regex = r"^(https:\/\/music.apple.com\/)(.*)$" 38 | self.base = "https://music.apple.com/in/playlist/" 39 | 40 | async def valid(self, link: str): 41 | if re.search(self.regex, link): 42 | return True 43 | else: 44 | return False 45 | 46 | async def track(self, url, playid: Union[bool, str] = None): 47 | if playid: 48 | url = self.base + url 49 | async with aiohttp.ClientSession() as session: 50 | async with session.get(url) as response: 51 | if response.status != 200: 52 | return False 53 | html = await response.text() 54 | soup = BeautifulSoup(html, "html.parser") 55 | search = None 56 | for tag in soup.find_all("meta"): 57 | if tag.get("property", None) == "og:title": 58 | search = tag.get("content", None) 59 | if search is None: 60 | return False 61 | results = VideosSearch(search, limit=1) 62 | for result in (await results.next())["result"]: 63 | title = result["title"] 64 | ytlink = result["link"] 65 | vidid = result["id"] 66 | duration_min = result["duration"] 67 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 68 | track_details = { 69 | "title": title, 70 | "link": ytlink, 71 | "vidid": vidid, 72 | "duration_min": duration_min, 73 | "thumb": thumbnail, 74 | } 75 | return track_details, vidid 76 | 77 | async def playlist(self, url, playid: Union[bool, str] = None): 78 | if playid: 79 | url = self.base + url 80 | playlist_id = url.split("playlist/")[1] 81 | async with aiohttp.ClientSession() as session: 82 | async with session.get(url) as response: 83 | if response.status != 200: 84 | return False 85 | html = await response.text() 86 | soup = BeautifulSoup(html, "html.parser") 87 | applelinks = soup.find_all("meta", attrs={"property": "music:song"}) 88 | results = [] 89 | for item in applelinks: 90 | try: 91 | xx = (((item["content"]).split("album/")[1]).split("/")[0]).replace( 92 | "-", " " 93 | ) 94 | except: 95 | xx = ((item["content"]).split("album/")[1]).split("/")[0] 96 | results.append(xx) 97 | return results, playlist_id 98 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/bot/help.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from typing import Union 4 | 5 | from pyrogram import filters, types 6 | from pyrogram.types import InlineKeyboardMarkup, Message 7 | 8 | from DeadlineTech import app 9 | from DeadlineTech.utils import help_pannel 10 | from DeadlineTech.utils.database import get_lang 11 | from DeadlineTech.utils.decorators.language import LanguageStart, languageCB 12 | from DeadlineTech.utils.inline.help import help_back_markup, private_help_panel 13 | from config import BANNED_USERS, START_IMG_URL, SUPPORT_CHAT 14 | from strings import get_string, helpers 15 | 16 | 17 | @app.on_message(filters.command(["help"]) & filters.private & ~BANNED_USERS) 18 | @app.on_callback_query(filters.regex("settings_back_helper") & ~BANNED_USERS) 19 | async def helper_private( 20 | client: app, update: Union[types.Message, types.CallbackQuery] 21 | ): 22 | is_callback = isinstance(update, types.CallbackQuery) 23 | if is_callback: 24 | try: 25 | await update.answer() 26 | except: 27 | pass 28 | chat_id = update.message.chat.id 29 | language = await get_lang(chat_id) 30 | _ = get_string(language) 31 | keyboard = help_pannel(_, True) 32 | await update.edit_message_text( 33 | _["help_1"].format(SUPPORT_CHAT), reply_markup=keyboard 34 | ) 35 | else: 36 | try: 37 | await update.delete() 38 | except: 39 | pass 40 | language = await get_lang(update.chat.id) 41 | _ = get_string(language) 42 | keyboard = help_pannel(_) 43 | await update.reply_photo( 44 | photo=START_IMG_URL, 45 | caption=_["help_1"].format(SUPPORT_CHAT), 46 | reply_markup=keyboard, 47 | ) 48 | 49 | 50 | @app.on_message(filters.command(["help"]) & filters.group & ~BANNED_USERS) 51 | @LanguageStart 52 | async def help_com_group(client, message: Message, _): 53 | keyboard = private_help_panel(_) 54 | await message.reply_text(_["help_2"], reply_markup=InlineKeyboardMarkup(keyboard)) 55 | 56 | 57 | @app.on_callback_query(filters.regex("help_callback") & ~BANNED_USERS) 58 | @languageCB 59 | async def helper_cb(client, CallbackQuery, _): 60 | callback_data = CallbackQuery.data.strip() 61 | cb = callback_data.split(None, 1)[1] 62 | keyboard = help_back_markup(_) 63 | if cb == "hb1": 64 | await CallbackQuery.edit_message_text(helpers.HELP_1, reply_markup=keyboard) 65 | elif cb == "hb2": 66 | await CallbackQuery.edit_message_text(helpers.HELP_2, reply_markup=keyboard) 67 | elif cb == "hb3": 68 | await CallbackQuery.edit_message_text(helpers.HELP_3, reply_markup=keyboard) 69 | elif cb == "hb4": 70 | await CallbackQuery.edit_message_text(helpers.HELP_4, reply_markup=keyboard) 71 | elif cb == "hb5": 72 | await CallbackQuery.edit_message_text(helpers.HELP_5, reply_markup=keyboard) 73 | elif cb == "hb6": 74 | await CallbackQuery.edit_message_text(helpers.HELP_6, reply_markup=keyboard) 75 | elif cb == "hb7": 76 | await CallbackQuery.edit_message_text(helpers.HELP_7, reply_markup=keyboard) 77 | elif cb == "hb8": 78 | await CallbackQuery.edit_message_text(helpers.HELP_8, reply_markup=keyboard) 79 | elif cb == "hb9": 80 | await CallbackQuery.edit_message_text(helpers.HELP_9, reply_markup=keyboard) 81 | elif cb == "hb10": 82 | await CallbackQuery.edit_message_text(helpers.HELP_10, reply_markup=keyboard) 83 | elif cb == "hb11": 84 | await CallbackQuery.edit_message_text(helpers.HELP_11, reply_markup=keyboard) 85 | elif cb == "hb12": 86 | await CallbackQuery.edit_message_text(helpers.HELP_12, reply_markup=keyboard) 87 | elif cb == "hb13": 88 | await CallbackQuery.edit_message_text(helpers.HELP_13, reply_markup=keyboard) 89 | elif cb == "hb14": 90 | await CallbackQuery.edit_message_text(helpers.HELP_14, reply_markup=keyboard) 91 | elif cb == "hb15": 92 | await CallbackQuery.edit_message_text(helpers.HELP_15, reply_markup=keyboard) 93 | -------------------------------------------------------------------------------- /DeadlineTech/__main__.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | import asyncio 4 | import importlib 5 | 6 | from pyrogram.types import BotCommand 7 | from pyrogram import idle 8 | from pytgcalls.exceptions import NoActiveGroupCall 9 | 10 | import config 11 | from DeadlineTech import LOGGER, app, userbot 12 | from DeadlineTech.core.call import Anony 13 | from DeadlineTech.misc import sudo 14 | from DeadlineTech.plugins import ALL_MODULES 15 | from DeadlineTech.utils.database import get_banned_users, get_gbanned 16 | from DeadlineTech.utils.crash_reporter import setup_global_exception_handler # ✅ Import crash handler 17 | from config import BANNED_USERS 18 | 19 | async def init(): 20 | # ✅ Enable global crash handler 21 | setup_global_exception_handler() 22 | 23 | 24 | if ( 25 | not config.STRING1 26 | and not config.STRING2 27 | and not config.STRING3 28 | and not config.STRING4 29 | and not config.STRING5 30 | ): 31 | LOGGER(__name__).error("Assistant client variables not defined, exiting...") 32 | exit() 33 | await sudo() 34 | try: 35 | users = await get_gbanned() 36 | for user_id in users: 37 | BANNED_USERS.add(user_id) 38 | users = await get_banned_users() 39 | for user_id in users: 40 | BANNED_USERS.add(user_id) 41 | except: 42 | pass 43 | await app.start() 44 | 45 | await app.set_bot_commands([ 46 | BotCommand("start", "Sᴛᴀʀᴛ's Tʜᴇ Bᴏᴛ"), 47 | BotCommand("clone", "start your own bot now"), 48 | BotCommand("ping", "Cʜᴇᴄᴋ ɪғ ʙᴏᴛ ɪs ᴀʟɪᴠᴇ"), 49 | BotCommand("help", "Gᴇᴛ Cᴏᴍᴍᴀɴᴅs Lɪsᴛ"), 50 | BotCommand("music", "download the songs 🎵"), 51 | BotCommand("play", "Pʟᴀʏ Mᴜsɪᴄ ɪɴ Vᴄ"), 52 | BotCommand("vplay", "starts Streaming the requested Video Song"), 53 | BotCommand("playforce", "forces to play your requested song"), 54 | BotCommand("vplayforce", "forces to play your requested Video song"), 55 | BotCommand("pause", "pause the current playing stream"), 56 | BotCommand("resume", "resume the paused stream"), 57 | BotCommand("skip", "skip the current playing stream"), 58 | BotCommand("end", "end the current stream"), 59 | BotCommand("player", "get a interactive player panel"), 60 | BotCommand("queue", "shows the queued tracks list"), 61 | BotCommand("auth", "add a user to auth list"), 62 | BotCommand("unauth", "remove a user from the auth list"), 63 | BotCommand("authusers", "shows the list of the auth users"), 64 | BotCommand("cplay", "starts streaming the requested audio on channel"), 65 | BotCommand("cvplay", "Starts Streaming the video track on channel"), 66 | BotCommand("channelplay", "connect channel to a group and start streaming"), 67 | BotCommand("shuffle", "shuffle's the queue"), 68 | BotCommand("seek", "seek the stream to the given duration"), 69 | BotCommand("seekback", "backward seek the stream"), 70 | BotCommand("speed", "for adjusting the audio playback speed"), 71 | BotCommand("loop", "enables the loop for the given value") 72 | ]) 73 | 74 | 75 | for all_module in ALL_MODULES: 76 | importlib.import_module("DeadlineTech.plugins" + all_module) 77 | LOGGER("DeadlineTech.plugins").info("Successfully Imported Modules...") 78 | await userbot.start() 79 | await Anony.start() 80 | try: 81 | await Anony.stream_call("https://te.legra.ph/file/29f784eb49d230ab62e9e.mp4") 82 | except NoActiveGroupCall: 83 | LOGGER("DeadlineTech").error( 84 | "Please turn on the videochat of your log group\channel.\n\nStopping Bot..." 85 | ) 86 | exit() 87 | except: 88 | pass 89 | await Anony.decorators() 90 | LOGGER("DeadlineTech").info( 91 | "DeadlineTech Music Bot started successfully" 92 | ) 93 | await idle() 94 | await app.stop() 95 | await userbot.stop() 96 | LOGGER("DeadlineTech").info("Stopping DeadlineTech Music Bot...") 97 | 98 | 99 | if __name__ == "__main__": 100 | asyncio.get_event_loop().run_until_complete(init()) 101 | -------------------------------------------------------------------------------- /setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pprint (){ 4 | cred='\033[0;31m' 5 | cgreen='\033[0;32m' 6 | cyellow='\033[0;33m' 7 | cblue='\033[0;34m' 8 | cpurple='\033[0;35m' 9 | eval "export color='$cpurple'" 10 | [ ! -z $2 ] && eval "export color=\"\$$2\"" 11 | printf "$color $1" 12 | } 13 | 14 | color_reset(){ printf '\033[0;37m';} 15 | 16 | yesnoprompt(){ 17 | old_stty_cfg=$(stty -g) 18 | stty raw -echo ; answer=$(head -c 1) 19 | stty $old_stty_cfg 20 | echo "$answer" | grep -iq "^y" 21 | } 22 | 23 | update() { 24 | pprint "\n\nUpdating package list.. " 25 | sudo apt update 2>&1 | grep "can be upgraded" &>/dev/null 26 | if [ $? -eq 0 ]; then 27 | pprint "UPDATE AVAILABLE" "cgreen" 28 | pprint "\n\nDo you want to automatically upgrade (y/n)?" 29 | if yesnoprompt; then 30 | pprint "\n\nUpgrading packages.. " 31 | sudo apt upgrade -y &>/dev/null && 32 | pprint "DONE!\n\n" "cgreen" || (pprint "FAIL.\n\n" "cred"; exit 1) 33 | else 34 | echo 35 | fi 36 | else 37 | pprint "ALREADY UP TO DATE\n\n" "cgreen" 38 | fi 39 | } 40 | 41 | packages(){ 42 | if ! command -v pip &>/dev/null; then 43 | pprint "Couldn't found pip, installing now..." 44 | sudo apt install python3-pip -y 2>pypilog.txt 1>/dev/null && 45 | pprint "SUCCESS.\n\n" "cgreen" || (pprint "FAIL.\n\n" "cred"; exit 1) 46 | fi 47 | 48 | if ! command -v ffmpeg &>/dev/null; then 49 | pprint "Couldn't found ffmpeg, installing now..." 50 | if sudo apt install ffmpeg -y &>/dev/null;then 51 | pprint "SUCCESS.\n\n" "cgreen" 52 | else 53 | pprint "FAIL.\n\n" "cred" 54 | pprint "You need to install ffmpeg manually in order to deploy AnonXMusic, exiting...\n" "cblue" 55 | exit 1 56 | fi 57 | fi 58 | 59 | # Check ffmpeg version and warn user if necessary. 60 | fv=$(grep -Po 'version (3.*?) ' <<< $(ffmpeg -version)) && 61 | pprint "Playing live streams not going to work since you have ffmpeg $fv, live streams are supported by version 4+.\n" "cblue" 62 | } 63 | 64 | 65 | node(){ 66 | command -v npm &>/dev/null && return 67 | pprint "Installing Nodejs and Npm.. " 68 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash && source ~/.bashrc && nvm install v18 &>nodelog.txt && 69 | sudo apt install -y nodejs &>>nodelog.txt && 70 | sudo npm i -g npm &>>nodelog.txt && 71 | pprint "SUCCESS!\n" "cgreen" || (pprint "FAIL.\n" "cred"; exit 1) 72 | } 73 | 74 | 75 | installation(){ 76 | pprint "\n\nUpgrading pip and installing dependency packages..." 77 | pip3 install -U pip &>>pypilog.txt && 78 | pip3 install -U -r requirements.txt &>>pypilog.txt && 79 | pprint "DONE.\n" "cgreen" && return 80 | pprint "FAIL.\n" "cred" 81 | exit 1 82 | } 83 | 84 | clear 85 | pprint "Welcome to DeadlineTech Music Setup Installer\n\n" 86 | pprint "If you see any error during Installation Process, Please refer to these files for logs: " 87 | pprint "\nFor node js errors , Checkout nodelog.txt" 88 | pprint "\nFor pypi packages errors , Checkout pypilog.txt" 89 | sleep 1 90 | pprint "\n\nScript needs sudo privileges in order to update & install packages.\n" 91 | sudo test 92 | 93 | update 94 | packages 95 | node 96 | installation 97 | pprint "\n\n\n\n\nDeadlineTech Installation Completed !" "cgreen" 98 | sleep 1 99 | clear 100 | 101 | pprint "\nEnter Your Values Below\n\n\n" 102 | pprint "API ID: "; color_reset; read api_id 103 | pprint "\nAPI HASH: "; color_reset; read api_hash 104 | pprint "\nBOT TOKEN: "; color_reset; read bot_token 105 | pprint "\nOWNER ID:"; color_reset; read ownid 106 | pprint "\nMONGO DB URI: "; color_reset; read mongo_db 107 | pprint "\nLOG GROUP ID: "; color_reset; read logger 108 | pprint "\nSTRING SESSION: "; color_reset; read string_session 109 | 110 | pprint "\n\nProcessing your vars, wait a while !" "cgreen" 111 | 112 | if [ -f .env ]; then 113 | rm .env 114 | fi 115 | 116 | echo """API_ID = $api_id 117 | API_HASH = $api_hash 118 | BOT_TOKEN = $bot_token 119 | MONGO_DB_URI = $mongo_db 120 | LOGGER_ID = $logger 121 | STRING_SESSION = $string_session 122 | OWNER_ID = $ownid""" > .env 123 | clear 124 | 125 | pprint "\n\n\nThanks for using DeadlineTech installer, your vars have been saved successfully ! \nIf you wanna add more variables add them in your env by : vi .env" 126 | pprint "\n\nNow you can start the bot by : bash start\n\n" 127 | -------------------------------------------------------------------------------- /DeadlineTech/platforms/Carbon.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | 27 | import random 28 | from os.path import realpath 29 | 30 | import aiohttp 31 | from aiohttp import client_exceptions 32 | 33 | 34 | class UnableToFetchCarbon(Exception): 35 | pass 36 | 37 | 38 | themes = [ 39 | "3024-night", 40 | "a11y-dark", 41 | "blackboard", 42 | "base16-dark", 43 | "base16-light", 44 | "cobalt", 45 | "duotone-dark", 46 | "dracula-pro", 47 | "hopscotch", 48 | "lucario", 49 | "material", 50 | "monokai", 51 | "nightowl", 52 | "nord", 53 | "oceanic-next", 54 | "one-light", 55 | "one-dark", 56 | "panda-syntax", 57 | "parasio-dark", 58 | "seti", 59 | "shades-of-purple", 60 | "solarized+dark", 61 | "solarized+light", 62 | "synthwave-84", 63 | "twilight", 64 | "verminal", 65 | "vscode", 66 | "yeti", 67 | "zenburn", 68 | ] 69 | 70 | colour = [ 71 | "#FF0000", 72 | "#FF5733", 73 | "#FFFF00", 74 | "#008000", 75 | "#0000FF", 76 | "#800080", 77 | "#A52A2A", 78 | "#FF00FF", 79 | "#D2B48C", 80 | "#00FFFF", 81 | "#808000", 82 | "#800000", 83 | "#00FFFF", 84 | "#30D5C8", 85 | "#00FF00", 86 | "#008080", 87 | "#4B0082", 88 | "#EE82EE", 89 | "#FFC0CB", 90 | "#000000", 91 | "#FFFFFF", 92 | "#808080", 93 | ] 94 | 95 | 96 | class CarbonAPI: 97 | def __init__(self): 98 | self.language = "auto" 99 | self.drop_shadow = True 100 | self.drop_shadow_blur = "68px" 101 | self.drop_shadow_offset = "20px" 102 | self.font_family = "JetBrains Mono" 103 | self.width_adjustment = True 104 | self.watermark = False 105 | 106 | async def generate(self, text: str, user_id): 107 | async with aiohttp.ClientSession( 108 | headers={"Content-Type": "application/json"}, 109 | ) as ses: 110 | params = { 111 | "code": text, 112 | } 113 | params["backgroundColor"] = random.choice(colour) 114 | params["theme"] = random.choice(themes) 115 | params["dropShadow"] = self.drop_shadow 116 | params["dropShadowOffsetY"] = self.drop_shadow_offset 117 | params["dropShadowBlurRadius"] = self.drop_shadow_blur 118 | params["fontFamily"] = self.font_family 119 | params["language"] = self.language 120 | params["watermark"] = self.watermark 121 | params["widthAdjustment"] = self.width_adjustment 122 | try: 123 | request = await ses.post( 124 | "https://carbonara.solopov.dev/api/cook", 125 | json=params, 126 | ) 127 | except client_exceptions.ClientConnectorError: 128 | raise UnableToFetchCarbon("Can not reach the Host!") 129 | resp = await request.read() 130 | with open(f"cache/carbon{user_id}.jpg", "wb") as f: 131 | f.write(resp) 132 | return realpath(f.name) 133 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import re 2 | from os import getenv 3 | 4 | from dotenv import load_dotenv 5 | from pyrogram import filters 6 | 7 | load_dotenv() 8 | 9 | # Get this value from my.telegram.org/apps 10 | API_ID = int(getenv("API_ID")) 11 | API_HASH = getenv("API_HASH") 12 | 13 | # Get your token from @BotFather on Telegram. 14 | BOT_TOKEN = getenv("BOT_TOKEN") 15 | 16 | #Get API_KEY from @DeadlineTechOwner or @DeadlineApiBot 17 | API_URL = getenv("API_URL", "https://deadlinetech.site") 18 | API_KEY = getenv("API_KEY") 19 | 20 | # Get your mongo url from cloud.mongodb.com 21 | MONGO_DB_URI = getenv("MONGO_DB_URI", None) 22 | 23 | DURATION_LIMIT_MIN = int(getenv("DURATION_LIMIT", 60)) 24 | 25 | # Chat id of a group for logging bot's activities 26 | LOGGER_ID = int(getenv("LOGGER_ID", None)) 27 | 28 | # Get this value from @Harry_RoxBot on Telegram by /id 29 | OWNER_ID = int(getenv("OWNER_ID", 6848223695)) 30 | 31 | ## Fill these variables if you're deploying on heroku. 32 | # Your heroku app name 33 | HEROKU_APP_NAME = getenv("HEROKU_APP_NAME") 34 | # Get it from http://dashboard.heroku.com/account 35 | HEROKU_API_KEY = getenv("HEROKU_API_KEY") 36 | 37 | UPSTREAM_REPO = getenv( 38 | "UPSTREAM_REPO", 39 | "https://github.com/DeadlineTech/music", 40 | ) 41 | UPSTREAM_BRANCH = getenv("UPSTREAM_BRANCH", "master") 42 | GIT_TOKEN = getenv( 43 | "GIT_TOKEN", None 44 | ) # Fill this variable if your upstream repository is private 45 | 46 | SUPPORT_CHANNEL = getenv("SUPPORT_CHANNEL", "https://t.me/ArcUpdates") 47 | SUPPORT_CHAT = getenv("SUPPORT_CHAT", "https://t.me/ArcChatz") 48 | 49 | # Set this to True if you want the assistant to automatically leave chats after an interval 50 | AUTO_LEAVING_ASSISTANT = bool(getenv("AUTO_LEAVING_ASSISTANT", True)) 51 | 52 | 53 | # Get this credentials from https://developer.spotify.com/dashboard 54 | SPOTIFY_CLIENT_ID = getenv("SPOTIFY_CLIENT_ID", None) 55 | SPOTIFY_CLIENT_SECRET = getenv("SPOTIFY_CLIENT_SECRET", None) 56 | 57 | 58 | # Maximum limit for fetching playlist's track from youtube, spotify, apple links. 59 | PLAYLIST_FETCH_LIMIT = int(getenv("PLAYLIST_FETCH_LIMIT", 25)) 60 | 61 | 62 | # Telegram audio and video file size limit (in bytes) 63 | TG_AUDIO_FILESIZE_LIMIT = int(getenv("TG_AUDIO_FILESIZE_LIMIT", 104857600)) 64 | TG_VIDEO_FILESIZE_LIMIT = int(getenv("TG_VIDEO_FILESIZE_LIMIT", 1073741824)) 65 | # Checkout https://www.gbmb.org/mb-to-bytes for converting mb to bytes 66 | 67 | 68 | # Get your pyrogram v2 session from @StringFatherBot on Telegram 69 | STRING1 = getenv("STRING_SESSION", None) 70 | STRING2 = getenv("STRING_SESSION2", None) 71 | STRING3 = getenv("STRING_SESSION3", None) 72 | STRING4 = getenv("STRING_SESSION4", None) 73 | STRING5 = getenv("STRING_SESSION5", None) 74 | 75 | 76 | BANNED_USERS = filters.user() 77 | adminlist = {} 78 | lyrical = {} 79 | votemode = {} 80 | autoclean = [] 81 | confirmer = {} 82 | 83 | 84 | START_IMG_URL = getenv( 85 | "START_IMG_URL", "https://files.catbox.moe/pjwlqg.jpg" 86 | ) 87 | PING_IMG_URL = getenv( 88 | "PING_IMG_URL", "https://files.catbox.moe/ou29gb.jpg" 89 | ) 90 | PLAYLIST_IMG_URL = "https://files.catbox.moe/tny9ug.jpg" 91 | STATS_IMG_URL = "https://files.catbox.moe/k3e3bg.jpg" 92 | TELEGRAM_AUDIO_URL = "https://files.catbox.moe/nknnw1.jpg" 93 | TELEGRAM_VIDEO_URL = "https://files.catbox.moe/1xn73k.jpg" 94 | STREAM_IMG_URL = "https://files.catbox.moe/tny9ug.jpg" 95 | SOUNCLOUD_IMG_URL = "https://files.catbox.moe/1xn73k.jpg" 96 | YOUTUBE_IMG_URL = "https://files.catbox.moe/fpknxj.jpg" 97 | SPOTIFY_ARTIST_IMG_URL = "https://files.catbox.moe/1xn73k.jpg" 98 | SPOTIFY_ALBUM_IMG_URL = "https://files.catbox.moe/1xn73k.jpg" 99 | SPOTIFY_PLAYLIST_IMG_URL = "https://files.catbox.moe/1xn73k.jpg" 100 | 101 | 102 | def time_to_seconds(time): 103 | stringt = str(time) 104 | return sum(int(x) * 60**i for i, x in enumerate(reversed(stringt.split(":")))) 105 | 106 | 107 | DURATION_LIMIT = int(time_to_seconds(f"{DURATION_LIMIT_MIN}:00")) 108 | 109 | 110 | if SUPPORT_CHANNEL: 111 | if not re.match("(?:http|https)://", SUPPORT_CHANNEL): 112 | raise SystemExit( 113 | "[ERROR] - Your SUPPORT_CHANNEL url is wrong. Please ensure that it starts with https://" 114 | ) 115 | 116 | if SUPPORT_CHAT: 117 | if not re.match("(?:http|https)://", SUPPORT_CHAT): 118 | raise SystemExit( 119 | "[ERROR] - Your SUPPORT_CHAT url is wrong. Please ensure that it starts with https://" 120 | ) 121 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/admins/speed.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from DeadlineTech import app 7 | from DeadlineTech.core.call import Anony 8 | from DeadlineTech.misc import SUDOERS, db 9 | from DeadlineTech.utils import AdminRightsCheck 10 | from DeadlineTech.utils.database import is_active_chat, is_nonadmin_chat 11 | from DeadlineTech.utils.decorators.language import languageCB 12 | from DeadlineTech.utils.inline import close_markup, speed_markup 13 | from config import BANNED_USERS, adminlist 14 | 15 | checker = [] 16 | 17 | 18 | @app.on_message( 19 | filters.command(["cspeed", "speed", "cslow", "slow", "playback", "cplayback"]) 20 | & filters.group 21 | & ~BANNED_USERS 22 | ) 23 | @AdminRightsCheck 24 | async def playback(cli, message: Message, _, chat_id): 25 | playing = db.get(chat_id) 26 | if not playing: 27 | return await message.reply_text(_["queue_2"]) 28 | duration_seconds = int(playing[0]["seconds"]) 29 | if duration_seconds == 0: 30 | return await message.reply_text(_["admin_27"]) 31 | file_path = playing[0]["file"] 32 | if "downloads" not in file_path: 33 | return await message.reply_text(_["admin_27"]) 34 | upl = speed_markup(_, chat_id) 35 | return await message.reply_text( 36 | text=_["admin_28"].format(app.mention), 37 | reply_markup=upl, 38 | ) 39 | 40 | 41 | @app.on_callback_query(filters.regex("SpeedUP") & ~BANNED_USERS) 42 | @languageCB 43 | async def del_back_playlist(client, CallbackQuery, _): 44 | callback_data = CallbackQuery.data.strip() 45 | callback_request = callback_data.split(None, 1)[1] 46 | chat, speed = callback_request.split("|") 47 | chat_id = int(chat) 48 | if not await is_active_chat(chat_id): 49 | return await CallbackQuery.answer(_["general_5"], show_alert=True) 50 | is_non_admin = await is_nonadmin_chat(CallbackQuery.message.chat.id) 51 | if not is_non_admin: 52 | if CallbackQuery.from_user.id not in SUDOERS: 53 | admins = adminlist.get(CallbackQuery.message.chat.id) 54 | if not admins: 55 | return await CallbackQuery.answer(_["admin_13"], show_alert=True) 56 | else: 57 | if CallbackQuery.from_user.id not in admins: 58 | return await CallbackQuery.answer(_["admin_14"], show_alert=True) 59 | playing = db.get(chat_id) 60 | if not playing: 61 | return await CallbackQuery.answer(_["queue_2"], show_alert=True) 62 | duration_seconds = int(playing[0]["seconds"]) 63 | if duration_seconds == 0: 64 | return await CallbackQuery.answer(_["admin_27"], show_alert=True) 65 | file_path = playing[0]["file"] 66 | if "downloads" not in file_path: 67 | return await CallbackQuery.answer(_["admin_27"], show_alert=True) 68 | checkspeed = (playing[0]).get("speed") 69 | if checkspeed: 70 | if str(checkspeed) == str(speed): 71 | if str(speed) == str("1.0"): 72 | return await CallbackQuery.answer( 73 | _["admin_29"], 74 | show_alert=True, 75 | ) 76 | else: 77 | if str(speed) == str("1.0"): 78 | return await CallbackQuery.answer( 79 | _["admin_29"], 80 | show_alert=True, 81 | ) 82 | if chat_id in checker: 83 | return await CallbackQuery.answer( 84 | _["admin_30"], 85 | show_alert=True, 86 | ) 87 | else: 88 | checker.append(chat_id) 89 | try: 90 | await CallbackQuery.answer( 91 | _["admin_31"], 92 | ) 93 | except: 94 | pass 95 | mystic = await CallbackQuery.edit_message_text( 96 | text=_["admin_32"].format(CallbackQuery.from_user.mention), 97 | ) 98 | try: 99 | await Anony.speedup_stream( 100 | chat_id, 101 | file_path, 102 | speed, 103 | playing, 104 | ) 105 | except: 106 | if chat_id in checker: 107 | checker.remove(chat_id) 108 | return await mystic.edit_text(_["admin_33"], reply_markup=close_markup(_)) 109 | if chat_id in checker: 110 | checker.remove(chat_id) 111 | await mystic.edit_text( 112 | text=_["admin_34"].format(speed, CallbackQuery.from_user.mention), 113 | reply_markup=close_markup(_), 114 | ) 115 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/reload.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | 4 | from pyrogram import filters 5 | from pyrogram.enums import ChatMembersFilter 6 | from pyrogram.types import CallbackQuery, Message 7 | 8 | from DeadlineTech import app 9 | from DeadlineTech.core.call import Anony 10 | from DeadlineTech.misc import db 11 | from DeadlineTech.utils.database import get_assistant, get_authuser_names, get_cmode 12 | from DeadlineTech.utils.decorators import ActualAdminCB, AdminActual, language 13 | from DeadlineTech.utils.formatters import alpha_to_int, get_readable_time 14 | from config import BANNED_USERS, adminlist, lyrical 15 | 16 | rel = {} 17 | 18 | 19 | @app.on_message( 20 | filters.command(["admincache", "reload", "refresh"]) & filters.group & ~BANNED_USERS 21 | ) 22 | @language 23 | async def reload_admin_cache(client, message: Message, _): 24 | try: 25 | if message.chat.id not in rel: 26 | rel[message.chat.id] = {} 27 | else: 28 | saved = rel[message.chat.id] 29 | if saved > time.time(): 30 | left = get_readable_time((int(saved) - int(time.time()))) 31 | return await message.reply_text(_["reload_1"].format(left)) 32 | adminlist[message.chat.id] = [] 33 | async for user in app.get_chat_members( 34 | message.chat.id, filter=ChatMembersFilter.ADMINISTRATORS 35 | ): 36 | if user.privileges.can_manage_video_chats: 37 | adminlist[message.chat.id].append(user.user.id) 38 | authusers = await get_authuser_names(message.chat.id) 39 | for user in authusers: 40 | user_id = await alpha_to_int(user) 41 | adminlist[message.chat.id].append(user_id) 42 | now = int(time.time()) + 180 43 | rel[message.chat.id] = now 44 | await message.reply_text(_["reload_2"]) 45 | except: 46 | await message.reply_text(_["reload_3"]) 47 | 48 | 49 | @app.on_message(filters.command(["reboot"]) & filters.group & ~BANNED_USERS) 50 | @AdminActual 51 | async def restartbot(client, message: Message, _): 52 | mystic = await message.reply_text(_["reload_4"].format(app.mention)) 53 | await asyncio.sleep(1) 54 | try: 55 | db[message.chat.id] = [] 56 | await Anony.stop_stream_force(message.chat.id) 57 | except: 58 | pass 59 | userbot = await get_assistant(message.chat.id) 60 | try: 61 | if message.chat.username: 62 | await userbot.resolve_peer(message.chat.username) 63 | else: 64 | await userbot.resolve_peer(message.chat.id) 65 | except: 66 | pass 67 | chat_id = await get_cmode(message.chat.id) 68 | if chat_id: 69 | try: 70 | got = await app.get_chat(chat_id) 71 | except: 72 | pass 73 | userbot = await get_assistant(chat_id) 74 | try: 75 | if got.username: 76 | await userbot.resolve_peer(got.username) 77 | else: 78 | await userbot.resolve_peer(chat_id) 79 | except: 80 | pass 81 | try: 82 | db[chat_id] = [] 83 | await Anony.stop_stream_force(chat_id) 84 | except: 85 | pass 86 | return await mystic.edit_text(_["reload_5"].format(app.mention)) 87 | 88 | 89 | @app.on_callback_query(filters.regex("close") & ~BANNED_USERS) 90 | async def close_menu(_, CallbackQuery): 91 | try: 92 | await CallbackQuery.answer() 93 | await CallbackQuery.message.delete() 94 | await CallbackQuery.message.reply_text( 95 | f"Cʟᴏsᴇᴅ ʙʏ : {CallbackQuery.from_user.mention}" 96 | ) 97 | except: 98 | pass 99 | 100 | 101 | @app.on_callback_query(filters.regex("stop_downloading") & ~BANNED_USERS) 102 | @ActualAdminCB 103 | async def stop_download(client, CallbackQuery: CallbackQuery, _): 104 | message_id = CallbackQuery.message.id 105 | task = lyrical.get(message_id) 106 | if not task: 107 | return await CallbackQuery.answer(_["tg_4"], show_alert=True) 108 | if task.done() or task.cancelled(): 109 | return await CallbackQuery.answer(_["tg_5"], show_alert=True) 110 | if not task.done(): 111 | try: 112 | task.cancel() 113 | try: 114 | lyrical.pop(message_id) 115 | except: 116 | pass 117 | await CallbackQuery.answer(_["tg_6"], show_alert=True) 118 | return await CallbackQuery.edit_message_text( 119 | _["tg_7"].format(CallbackQuery.from_user.mention) 120 | ) 121 | except: 122 | return await CallbackQuery.answer(_["tg_8"], show_alert=True) 123 | await CallbackQuery.answer(_["tg_9"], show_alert=True) 124 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/gban.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from pyrogram import filters 4 | from pyrogram.errors import FloodWait 5 | from pyrogram.types import Message 6 | 7 | from DeadlineTech import app 8 | from DeadlineTech.misc import SUDOERS 9 | from DeadlineTech.utils import get_readable_time 10 | from DeadlineTech.utils.database import ( 11 | add_banned_user, 12 | get_banned_count, 13 | get_banned_users, 14 | get_served_chats, 15 | is_banned_user, 16 | remove_banned_user, 17 | ) 18 | from DeadlineTech.utils.decorators.language import language 19 | from DeadlineTech.utils.extraction import extract_user 20 | from config import BANNED_USERS 21 | 22 | 23 | @app.on_message(filters.command(["gban", "globalban"]) & SUDOERS) 24 | @language 25 | async def global_ban(client, message: Message, _): 26 | if not message.reply_to_message: 27 | if len(message.command) != 2: 28 | return await message.reply_text(_["general_1"]) 29 | user = await extract_user(message) 30 | if user.id == message.from_user.id: 31 | return await message.reply_text(_["gban_1"]) 32 | elif user.id == app.id: 33 | return await message.reply_text(_["gban_2"]) 34 | elif user.id in SUDOERS: 35 | return await message.reply_text(_["gban_3"]) 36 | is_gbanned = await is_banned_user(user.id) 37 | if is_gbanned: 38 | return await message.reply_text(_["gban_4"].format(user.mention)) 39 | if user.id not in BANNED_USERS: 40 | BANNED_USERS.add(user.id) 41 | served_chats = [] 42 | chats = await get_served_chats() 43 | for chat in chats: 44 | served_chats.append(int(chat["chat_id"])) 45 | time_expected = get_readable_time(len(served_chats)) 46 | mystic = await message.reply_text(_["gban_5"].format(user.mention, time_expected)) 47 | number_of_chats = 0 48 | for chat_id in served_chats: 49 | try: 50 | await app.ban_chat_member(chat_id, user.id) 51 | number_of_chats += 1 52 | except FloodWait as fw: 53 | await asyncio.sleep(int(fw.value)) 54 | except: 55 | continue 56 | await add_banned_user(user.id) 57 | await message.reply_text( 58 | _["gban_6"].format( 59 | app.mention, 60 | message.chat.title, 61 | message.chat.id, 62 | user.mention, 63 | user.id, 64 | message.from_user.mention, 65 | number_of_chats, 66 | ) 67 | ) 68 | await mystic.delete() 69 | 70 | 71 | @app.on_message(filters.command(["ungban"]) & SUDOERS) 72 | @language 73 | async def global_un(client, message: Message, _): 74 | if not message.reply_to_message: 75 | if len(message.command) != 2: 76 | return await message.reply_text(_["general_1"]) 77 | user = await extract_user(message) 78 | is_gbanned = await is_banned_user(user.id) 79 | if not is_gbanned: 80 | return await message.reply_text(_["gban_7"].format(user.mention)) 81 | if user.id in BANNED_USERS: 82 | BANNED_USERS.remove(user.id) 83 | served_chats = [] 84 | chats = await get_served_chats() 85 | for chat in chats: 86 | served_chats.append(int(chat["chat_id"])) 87 | time_expected = get_readable_time(len(served_chats)) 88 | mystic = await message.reply_text(_["gban_8"].format(user.mention, time_expected)) 89 | number_of_chats = 0 90 | for chat_id in served_chats: 91 | try: 92 | await app.unban_chat_member(chat_id, user.id) 93 | number_of_chats += 1 94 | except FloodWait as fw: 95 | await asyncio.sleep(int(fw.value)) 96 | except: 97 | continue 98 | await remove_banned_user(user.id) 99 | await message.reply_text(_["gban_9"].format(user.mention, number_of_chats)) 100 | await mystic.delete() 101 | 102 | 103 | @app.on_message(filters.command(["gbannedusers", "gbanlist"]) & SUDOERS) 104 | @language 105 | async def gbanned_list(client, message: Message, _): 106 | counts = await get_banned_count() 107 | if counts == 0: 108 | return await message.reply_text(_["gban_10"]) 109 | mystic = await message.reply_text(_["gban_11"]) 110 | msg = _["gban_12"] 111 | count = 0 112 | users = await get_banned_users() 113 | for user_id in users: 114 | count += 1 115 | try: 116 | user = await app.get_users(user_id) 117 | user = user.first_name if not user.mention else user.mention 118 | msg += f"{count}➤ {user}\n" 119 | except Exception: 120 | msg += f"{count}➤ {user_id}\n" 121 | continue 122 | if count == 0: 123 | return await mystic.edit_text(_["gban_10"]) 124 | else: 125 | return await mystic.edit_text(msg) 126 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/misc/clean_assistant.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery 3 | 4 | from DeadlineTech import app 5 | from DeadlineTech.misc import SUDOERS 6 | from DeadlineTech.utils.database import get_client, is_active_chat 7 | from config import LOGGER_ID 8 | from pyrogram.enums import ChatType 9 | 10 | from DeadlineTech.core.userbot import assistants 11 | 12 | 13 | async def clean_assistant_chats(client, assistant_num): 14 | total_left = 0 15 | try: 16 | userbot = await get_client(assistant_num) 17 | left = 0 18 | async for dialog in userbot.get_dialogs(): 19 | chat = dialog.chat 20 | if chat.type in [ChatType.SUPERGROUP, ChatType.GROUP, ChatType.CHANNEL]: 21 | if chat.id in [LOGGER_ID, -1001686672798, -1001549206010]: # Excluded chats 22 | continue 23 | if not await is_active_chat(chat.id): 24 | try: 25 | await userbot.leave_chat(chat.id) 26 | left += 1 27 | except Exception as e: 28 | print(f"[CleanAssistant Error] Failed to leave {chat.title} ({chat.id}): {e}") 29 | total_left += left 30 | except Exception as e: 31 | print(f"[CleanAssistant Error] Assistant {assistant_num} failed: {e}") 32 | 33 | return total_left 34 | 35 | 36 | @app.on_message(filters.command("cleanassistants") & filters.private & SUDOERS ) 37 | async def clean_assistants_command(client, message: Message): 38 | args = message.text.split() 39 | if len(args) == 1: 40 | # No assistant id given, show buttons + clean all 41 | buttons = [ 42 | [InlineKeyboardButton(f"Assistant {num}", callback_data=f"clean_assistant:{num}")] 43 | for num in assistants 44 | ] 45 | # Add Clean All button at the bottom 46 | buttons.append([InlineKeyboardButton("Clean All Assistants 🧹", callback_data="clean_assistant:all")]) 47 | 48 | reply_markup = InlineKeyboardMarkup(buttons) 49 | await message.reply_text( 50 | "Select the assistant to clean inactive chats, or clean all assistants:", 51 | reply_markup=reply_markup, 52 | ) 53 | else: 54 | # assistant id given 55 | arg = args[1].lower() 56 | if arg == "all": 57 | msg = await message.reply_text(f"🧹 Cleaning all assistants... Please wait.") 58 | total_left_all = 0 59 | for assistant_id in assistants: 60 | total_left_all += await clean_assistant_chats(client, assistant_id) 61 | await msg.edit_text(f"✅ Cleaned all assistants.\nTotal chats left: {total_left_all}.") 62 | else: 63 | try: 64 | assistant_id = int(arg) 65 | except ValueError: 66 | return await message.reply_text("Invalid assistant id. Please provide a number or 'all'.") 67 | 68 | if assistant_id not in assistants: 69 | return await message.reply_text("This assistant id is not valid or not available.") 70 | 71 | msg = await message.reply_text(f"🧹 Cleaning inactive chats for assistant {assistant_id}... Please wait.") 72 | total_left = await clean_assistant_chats(client, assistant_id) 73 | await msg.edit_text(f"✅ Cleaned assistant {assistant_id}.\nTotal chats left: {total_left}.") 74 | 75 | 76 | @app.on_callback_query(filters.regex(r"^clean_assistant:(all|\d+)$")) 77 | async def clean_assistant_callback(client, callback_query: CallbackQuery): 78 | if callback_query.from_user.id not in SUDOERS: 79 | return await callback_query.answer("You are not authorized.", show_alert=True) 80 | 81 | arg = callback_query.data.split(":")[1] 82 | if arg == "all": 83 | await callback_query.answer("Cleaning all assistants...") 84 | msg = await callback_query.message.edit_text(f"🧹 Cleaning all assistants... Please wait.") 85 | total_left_all = 0 86 | for assistant_id in assistants: 87 | total_left_all += await clean_assistant_chats(client, assistant_id) 88 | await msg.edit_text(f"✅ Cleaned all assistants.\nTotal chats left: {total_left_all}.") 89 | else: 90 | assistant_id = int(arg) 91 | if assistant_id not in assistants: 92 | return await callback_query.answer("Invalid assistant id.", show_alert=True) 93 | 94 | await callback_query.answer("Cleaning started...") 95 | msg = await callback_query.message.edit_text(f"🧹 Cleaning inactive chats for assistant {assistant_id}... Please wait.") 96 | total_left = await clean_assistant_chats(client, assistant_id) 97 | await msg.edit_text(f"✅ Cleaned assistant {assistant_id}.\nTotal chats left: {total_left}.") 98 | -------------------------------------------------------------------------------- /DeadlineTech/platforms/Spotify.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team DeadlineTech | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team DeadlineTech 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | 27 | import re 28 | 29 | import spotipy 30 | from spotipy.oauth2 import SpotifyClientCredentials 31 | from youtubesearchpython.__future__ import VideosSearch 32 | 33 | import config 34 | 35 | 36 | class SpotifyAPI: 37 | def __init__(self): 38 | self.regex = r"^(https:\/\/open.spotify.com\/)(.*)$" 39 | self.client_id = config.SPOTIFY_CLIENT_ID 40 | self.client_secret = config.SPOTIFY_CLIENT_SECRET 41 | if config.SPOTIFY_CLIENT_ID and config.SPOTIFY_CLIENT_SECRET: 42 | self.client_credentials_manager = SpotifyClientCredentials( 43 | self.client_id, self.client_secret 44 | ) 45 | self.spotify = spotipy.Spotify( 46 | client_credentials_manager=self.client_credentials_manager 47 | ) 48 | else: 49 | self.spotify = None 50 | 51 | async def valid(self, link: str): 52 | if re.search(self.regex, link): 53 | return True 54 | else: 55 | return False 56 | 57 | async def track(self, link: str): 58 | track = self.spotify.track(link) 59 | info = track["name"] 60 | for artist in track["artists"]: 61 | fetched = f' {artist["name"]}' 62 | if "Various Artists" not in fetched: 63 | info += fetched 64 | results = VideosSearch(info, limit=1) 65 | for result in (await results.next())["result"]: 66 | ytlink = result["link"] 67 | title = result["title"] 68 | vidid = result["id"] 69 | duration_min = result["duration"] 70 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 71 | track_details = { 72 | "title": title, 73 | "link": ytlink, 74 | "vidid": vidid, 75 | "duration_min": duration_min, 76 | "thumb": thumbnail, 77 | } 78 | return track_details, vidid 79 | 80 | async def playlist(self, url): 81 | playlist = self.spotify.playlist(url) 82 | playlist_id = playlist["id"] 83 | results = [] 84 | for item in playlist["tracks"]["items"]: 85 | music_track = item["track"] 86 | info = music_track["name"] 87 | for artist in music_track["artists"]: 88 | fetched = f' {artist["name"]}' 89 | if "Various Artists" not in fetched: 90 | info += fetched 91 | results.append(info) 92 | return results, playlist_id 93 | 94 | async def album(self, url): 95 | album = self.spotify.album(url) 96 | album_id = album["id"] 97 | results = [] 98 | for item in album["tracks"]["items"]: 99 | info = item["name"] 100 | for artist in item["artists"]: 101 | fetched = f' {artist["name"]}' 102 | if "Various Artists" not in fetched: 103 | info += fetched 104 | results.append(info) 105 | 106 | return ( 107 | results, 108 | album_id, 109 | ) 110 | 111 | async def artist(self, url): 112 | artistinfo = self.spotify.artist(url) 113 | artist_id = artistinfo["id"] 114 | results = [] 115 | artisttoptracks = self.spotify.artist_top_tracks(url) 116 | for item in artisttoptracks["tracks"]: 117 | info = item["name"] 118 | for artist in item["artists"]: 119 | fetched = f' {artist["name"]}' 120 | if "Various Artists" not in fetched: 121 | info += fetched 122 | results.append(info) 123 | 124 | return results, artist_id 125 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/stats.py: -------------------------------------------------------------------------------- 1 | import platform 2 | from sys import version as pyver 3 | 4 | import psutil 5 | from pyrogram import __version__ as pyrover 6 | from pyrogram import filters 7 | from pyrogram.errors import MessageIdInvalid 8 | from pyrogram.types import InputMediaPhoto, Message 9 | from pytgcalls.__version__ import __version__ as pytgver 10 | 11 | import config 12 | from DeadlineTech import app 13 | from DeadlineTech.core.userbot import assistants 14 | from DeadlineTech.misc import SUDOERS, mongodb 15 | from DeadlineTech.plugins import ALL_MODULES 16 | from DeadlineTech.utils.database import get_served_chats, get_served_users, get_sudoers 17 | from DeadlineTech.utils.decorators.language import language, languageCB 18 | from DeadlineTech.utils.inline.stats import back_stats_buttons, stats_buttons 19 | from config import BANNED_USERS 20 | 21 | 22 | @app.on_message(filters.command(["stats", "gstats"]) & filters.group & ~BANNED_USERS) 23 | @language 24 | async def stats_global(client, message: Message, _): 25 | upl = stats_buttons(_, True if message.from_user.id in SUDOERS else False) 26 | await message.reply_photo( 27 | photo=config.STATS_IMG_URL, 28 | caption=_["gstats_2"].format(app.mention), 29 | reply_markup=upl, 30 | ) 31 | 32 | 33 | @app.on_callback_query(filters.regex("stats_back") & ~BANNED_USERS) 34 | @languageCB 35 | async def home_stats(client, CallbackQuery, _): 36 | upl = stats_buttons(_, True if CallbackQuery.from_user.id in SUDOERS else False) 37 | await CallbackQuery.edit_message_text( 38 | text=_["gstats_2"].format(app.mention), 39 | reply_markup=upl, 40 | ) 41 | 42 | 43 | @app.on_callback_query(filters.regex("TopOverall") & ~BANNED_USERS) 44 | @languageCB 45 | async def overall_stats(client, CallbackQuery, _): 46 | await CallbackQuery.answer() 47 | upl = back_stats_buttons(_) 48 | try: 49 | await CallbackQuery.answer() 50 | except: 51 | pass 52 | await CallbackQuery.edit_message_text(_["gstats_1"].format(app.mention)) 53 | served_chats = len(await get_served_chats()) 54 | served_users = len(await get_served_users()) 55 | text = _["gstats_3"].format( 56 | app.mention, 57 | len(assistants), 58 | len(BANNED_USERS), 59 | served_chats, 60 | served_users, 61 | len(ALL_MODULES), 62 | len(SUDOERS), 63 | config.DURATION_LIMIT_MIN, 64 | ) 65 | med = InputMediaPhoto(media=config.STATS_IMG_URL, caption=text) 66 | try: 67 | await CallbackQuery.edit_message_media(media=med, reply_markup=upl) 68 | except MessageIdInvalid: 69 | await CallbackQuery.message.reply_photo( 70 | photo=config.STATS_IMG_URL, caption=text, reply_markup=upl 71 | ) 72 | 73 | 74 | @app.on_callback_query(filters.regex("bot_stats_sudo")) 75 | @languageCB 76 | async def bot_stats(client, CallbackQuery, _): 77 | if CallbackQuery.from_user.id not in SUDOERS: 78 | return await CallbackQuery.answer(_["gstats_4"], show_alert=True) 79 | upl = back_stats_buttons(_) 80 | try: 81 | await CallbackQuery.answer() 82 | except: 83 | pass 84 | await CallbackQuery.edit_message_text(_["gstats_1"].format(app.mention)) 85 | p_core = psutil.cpu_count(logical=False) 86 | t_core = psutil.cpu_count(logical=True) 87 | ram = str(round(psutil.virtual_memory().total / (1024.0**3))) + " ɢʙ" 88 | try: 89 | cpu_freq = psutil.cpu_freq().current 90 | if cpu_freq >= 1000: 91 | cpu_freq = f"{round(cpu_freq / 1000, 2)}ɢʜᴢ" 92 | else: 93 | cpu_freq = f"{round(cpu_freq, 2)}ᴍʜᴢ" 94 | except: 95 | cpu_freq = "ғᴀɪʟᴇᴅ ᴛᴏ ғᴇᴛᴄʜ" 96 | hdd = psutil.disk_usage("/") 97 | total = hdd.total / (1024.0**3) 98 | used = hdd.used / (1024.0**3) 99 | free = hdd.free / (1024.0**3) 100 | call = await mongodb.command("dbstats") 101 | datasize = call["dataSize"] / 1024 102 | storage = call["storageSize"] / 1024 103 | served_chats = len(await get_served_chats()) 104 | served_users = len(await get_served_users()) 105 | text = _["gstats_5"].format( 106 | app.mention, 107 | len(ALL_MODULES), 108 | platform.system(), 109 | ram, 110 | p_core, 111 | t_core, 112 | cpu_freq, 113 | pyver.split()[0], 114 | pyrover, 115 | pytgver, 116 | str(total)[:4], 117 | str(used)[:4], 118 | str(free)[:4], 119 | served_chats, 120 | served_users, 121 | len(BANNED_USERS), 122 | len(await get_sudoers()), 123 | str(datasize)[:6], 124 | storage, 125 | call["collections"], 126 | call["objects"], 127 | ) 128 | med = InputMediaPhoto(media=config.STATS_IMG_URL, caption=text) 129 | try: 130 | await CallbackQuery.edit_message_media(media=med, reply_markup=upl) 131 | except MessageIdInvalid: 132 | await CallbackQuery.message.reply_photo( 133 | photo=config.STATS_IMG_URL, caption=text, reply_markup=upl 134 | ) 135 | -------------------------------------------------------------------------------- /DeadlineTech/core/userbot.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ========================================================== 4 | # 🎧 Public Open-Source VC Player Music Bot (Cookies Based) 5 | # 🛠️ Maintained by Team Arc | Lead Developer: @Its_damiann 6 | # 🔓 Licensed for Public Use — All Rights Reserved © Team Arc 7 | # 8 | # This file is part of a publicly available and open-source Telegram music bot 9 | # developed by Team DeadlineTech. It offers high-quality streaming in Telegram voice 10 | # chats using YouTube as a source, supported by session-based assistant accounts and 11 | # YouTube cookie integration for improved access and performance. 12 | # 13 | # 💡 This source code is released for educational and community purposes. You're free 14 | # to study, modify, and deploy it under fair and respectful usage. However, any misuse, 15 | # removal of credits, or false ownership claims will be considered a violation of our 16 | # community standards and may lead to denial of support or blacklisting. 17 | # 18 | # 🔗 Looking for powerful performance with stable APIs? Get access to the official 19 | # premium API service: https://DeadlineTech.site or Visit @ApixhubBot 20 | # 21 | # ❤️ Openly built for the community, but proudly protected by the passion of its creators. 22 | # ========================================================== 23 | 24 | 25 | 26 | from pyrogram import Client 27 | import config 28 | from ..logging import LOGGER 29 | 30 | assistants = [] 31 | assistantids = [] 32 | 33 | 34 | class Userbot(Client): 35 | def __init__(self): 36 | self.one = Client( 37 | name="DeadlineXAss1", 38 | api_id=config.API_ID, 39 | api_hash=config.API_HASH, 40 | session_string=str(config.STRING1), 41 | no_updates=True, 42 | ) 43 | self.two = Client( 44 | name="DeadlineXAss2", 45 | api_id=config.API_ID, 46 | api_hash=config.API_HASH, 47 | session_string=str(config.STRING2), 48 | no_updates=True, 49 | ) 50 | self.three = Client( 51 | name="DeadlineXAss3", 52 | api_id=config.API_ID, 53 | api_hash=config.API_HASH, 54 | session_string=str(config.STRING3), 55 | no_updates=True, 56 | ) 57 | self.four = Client( 58 | name="DeadlineXAss4", 59 | api_id=config.API_ID, 60 | api_hash=config.API_HASH, 61 | session_string=str(config.STRING4), 62 | no_updates=True, 63 | ) 64 | self.five = Client( 65 | name="DeadlineXAss5", 66 | api_id=config.API_ID, 67 | api_hash=config.API_HASH, 68 | session_string=str(config.STRING5), 69 | no_updates=True, 70 | ) 71 | 72 | async def start(self): 73 | LOGGER(__name__).info("🚀 Starting assistant clients...") 74 | 75 | async def setup_assistant(client, number): 76 | try: 77 | await client.start() 78 | await client.join_chat("ArcBotz") 79 | await client.join_chat("ArcUpdates") 80 | except Exception: 81 | pass 82 | 83 | assistants.append(number) 84 | 85 | try: 86 | await client.send_message(config.LOGGER_ID, f"✅ Assistant {number} is now online.") 87 | except Exception: 88 | LOGGER(__name__).error( 89 | f"❌ Assistant {number} failed to send a message to the log group. " 90 | f"Ensure it's added and promoted to admin in LOGGER group ({config.LOGGER_ID})." 91 | ) 92 | exit() 93 | 94 | client.id = client.me.id 95 | client.name = client.me.mention 96 | client.username = client.me.username 97 | assistantids.append(client.id) 98 | 99 | LOGGER(__name__).info(f"🤖 Assistant {number} is active as {client.name}") 100 | 101 | if config.STRING1: 102 | await setup_assistant(self.one, 1) 103 | if config.STRING2: 104 | await setup_assistant(self.two, 2) 105 | if config.STRING3: 106 | await setup_assistant(self.three, 3) 107 | if config.STRING4: 108 | await setup_assistant(self.four, 4) 109 | if config.STRING5: 110 | await setup_assistant(self.five, 5) 111 | 112 | LOGGER(__name__).info("✅ All available assistants are now online.") 113 | 114 | async def stop(self): 115 | LOGGER(__name__).info("🛑 Shutting down assistant clients...") 116 | try: 117 | if config.STRING1: 118 | await self.one.stop() 119 | if config.STRING2: 120 | await self.two.stop() 121 | if config.STRING3: 122 | await self.three.stop() 123 | if config.STRING4: 124 | await self.four.stop() 125 | if config.STRING5: 126 | await self.five.stop() 127 | except Exception as e: 128 | LOGGER(__name__).warning(f"⚠️ Error while stopping assistants: {e}") 129 | -------------------------------------------------------------------------------- /DeadlineTech/utils/formatters.py: -------------------------------------------------------------------------------- 1 | import json 2 | import subprocess 3 | 4 | 5 | def get_readable_time(seconds: int) -> str: 6 | count = 0 7 | ping_time = "" 8 | time_list = [] 9 | time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"] 10 | while count < 4: 11 | count += 1 12 | if count < 3: 13 | remainder, result = divmod(seconds, 60) 14 | else: 15 | remainder, result = divmod(seconds, 24) 16 | if seconds == 0 and remainder == 0: 17 | break 18 | time_list.append(int(result)) 19 | seconds = int(remainder) 20 | for i in range(len(time_list)): 21 | time_list[i] = str(time_list[i]) + time_suffix_list[i] 22 | if len(time_list) == 4: 23 | ping_time += time_list.pop() + ", " 24 | time_list.reverse() 25 | ping_time += ":".join(time_list) 26 | return ping_time 27 | 28 | 29 | def convert_bytes(size: float) -> str: 30 | """humanize size""" 31 | if not size: 32 | return "" 33 | power = 1024 34 | t_n = 0 35 | power_dict = {0: " ", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 36 | while size > power: 37 | size /= power 38 | t_n += 1 39 | return "{:.2f} {}B".format(size, power_dict[t_n]) 40 | 41 | 42 | async def int_to_alpha(user_id: int) -> str: 43 | alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] 44 | text = "" 45 | user_id = str(user_id) 46 | for i in user_id: 47 | text += alphabet[int(i)] 48 | return text 49 | 50 | 51 | async def alpha_to_int(user_id_alphabet: str) -> int: 52 | alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] 53 | user_id = "" 54 | for i in user_id_alphabet: 55 | index = alphabet.index(i) 56 | user_id += str(index) 57 | user_id = int(user_id) 58 | return user_id 59 | 60 | 61 | def time_to_seconds(time): 62 | stringt = str(time) 63 | return sum(int(x) * 60**i for i, x in enumerate(reversed(stringt.split(":")))) 64 | 65 | 66 | def seconds_to_min(seconds): 67 | if seconds is not None: 68 | seconds = int(seconds) 69 | d, h, m, s = ( 70 | seconds // (3600 * 24), 71 | seconds // 3600 % 24, 72 | seconds % 3600 // 60, 73 | seconds % 3600 % 60, 74 | ) 75 | if d > 0: 76 | return "{:02d}:{:02d}:{:02d}:{:02d}".format(d, h, m, s) 77 | elif h > 0: 78 | return "{:02d}:{:02d}:{:02d}".format(h, m, s) 79 | elif m > 0: 80 | return "{:02d}:{:02d}".format(m, s) 81 | elif s > 0: 82 | return "00:{:02d}".format(s) 83 | return "-" 84 | 85 | 86 | def speed_converter(seconds, speed): 87 | if str(speed) == str("0.5"): 88 | seconds = seconds * 2 89 | if str(speed) == str("0.75"): 90 | seconds = seconds + ((50 * seconds) // 100) 91 | if str(speed) == str("1.5"): 92 | seconds = seconds - ((25 * seconds) // 100) 93 | if str(speed) == str("2.0"): 94 | seconds = seconds - ((50 * seconds) // 100) 95 | collect = seconds 96 | if seconds is not None: 97 | seconds = int(seconds) 98 | d, h, m, s = ( 99 | seconds // (3600 * 24), 100 | seconds // 3600 % 24, 101 | seconds % 3600 // 60, 102 | seconds % 3600 % 60, 103 | ) 104 | if d > 0: 105 | convert = "{:02d}:{:02d}:{:02d}:{:02d}".format(d, h, m, s) 106 | return convert, collect 107 | elif h > 0: 108 | convert = "{:02d}:{:02d}:{:02d}".format(h, m, s) 109 | return convert, collect 110 | elif m > 0: 111 | convert = "{:02d}:{:02d}".format(m, s) 112 | return convert, collect 113 | elif s > 0: 114 | convert = "00:{:02d}".format(s) 115 | return convert, collect 116 | return "-" 117 | 118 | 119 | def check_duration(file_path): 120 | command = [ 121 | "ffprobe", 122 | "-loglevel", 123 | "quiet", 124 | "-print_format", 125 | "json", 126 | "-show_format", 127 | "-show_streams", 128 | file_path, 129 | ] 130 | 131 | pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 132 | out, err = pipe.communicate() 133 | _json = json.loads(out) 134 | 135 | if "format" in _json: 136 | if "duration" in _json["format"]: 137 | return float(_json["format"]["duration"]) 138 | 139 | if "streams" in _json: 140 | for s in _json["streams"]: 141 | if "duration" in s: 142 | return float(s["duration"]) 143 | 144 | return "Unknown" 145 | 146 | 147 | formats = [ 148 | "webm", 149 | "mkv", 150 | "flv", 151 | "vob", 152 | "ogv", 153 | "ogg", 154 | "rrc", 155 | "gifv", 156 | "mng", 157 | "mov", 158 | "avi", 159 | "qt", 160 | "wmv", 161 | "yuv", 162 | "rm", 163 | "asf", 164 | "amv", 165 | "mp4", 166 | "m4p", 167 | "m4v", 168 | "mpg", 169 | "mp2", 170 | "mpeg", 171 | "mpe", 172 | "mpv", 173 | "m4v", 174 | "svi", 175 | "3gp", 176 | "3g2", 177 | "mxf", 178 | "roq", 179 | "nsv", 180 | "flv", 181 | "f4v", 182 | "f4p", 183 | "f4a", 184 | "f4b", 185 | ] 186 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/sudo/restart.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import shutil 4 | import socket 5 | from datetime import datetime 6 | 7 | import urllib3 8 | from git import Repo 9 | from git.exc import GitCommandError, InvalidGitRepositoryError 10 | from pyrogram import filters 11 | 12 | import config 13 | from DeadlineTech import app 14 | from DeadlineTech.misc import HAPP, SUDOERS, XCB 15 | from DeadlineTech.utils.database import ( 16 | get_active_chats, 17 | remove_active_chat, 18 | remove_active_video_chat, 19 | ) 20 | from DeadlineTech.utils.decorators.language import language 21 | from DeadlineTech.utils.pastebin import AnonyBin 22 | 23 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 24 | 25 | 26 | async def is_heroku(): 27 | return "heroku" in socket.getfqdn() 28 | 29 | 30 | @app.on_message(filters.command(["getlog", "logs", "getlogs"]) & SUDOERS) 31 | @language 32 | async def log_(client, message, _): 33 | try: 34 | await message.reply_document(document="log.txt") 35 | except: 36 | await message.reply_text(_["server_1"]) 37 | 38 | 39 | @app.on_message(filters.command(["update", "gitpull"]) & SUDOERS) 40 | @language 41 | async def update_(client, message, _): 42 | if await is_heroku(): 43 | if HAPP is None: 44 | return await message.reply_text(_["server_2"]) 45 | response = await message.reply_text(_["server_3"]) 46 | try: 47 | repo = Repo() 48 | except GitCommandError: 49 | return await response.edit(_["server_4"]) 50 | except InvalidGitRepositoryError: 51 | return await response.edit(_["server_5"]) 52 | to_exc = f"git fetch origin {config.UPSTREAM_BRANCH} &> /dev/null" 53 | os.system(to_exc) 54 | await asyncio.sleep(7) 55 | verification = "" 56 | REPO_ = repo.remotes.origin.url.split(".git")[0] 57 | for checks in repo.iter_commits(f"HEAD..origin/{config.UPSTREAM_BRANCH}"): 58 | verification = str(checks.count()) 59 | if verification == "": 60 | return await response.edit(_["server_6"]) 61 | updates = "" 62 | ordinal = lambda format: "%d%s" % ( 63 | format, 64 | "tsnrhtdd"[(format // 10 % 10 != 1) * (format % 10 < 4) * format % 10 :: 4], 65 | ) 66 | for info in repo.iter_commits(f"HEAD..origin/{config.UPSTREAM_BRANCH}"): 67 | updates += f"➣ #{info.count()}: {info.summary} ʙʏ -> {info.author}\n\t\t\t\t➥ ᴄᴏᴍᴍɪᴛᴇᴅ ᴏɴ : {ordinal(int(datetime.fromtimestamp(info.committed_date).strftime('%d')))} {datetime.fromtimestamp(info.committed_date).strftime('%b')}, {datetime.fromtimestamp(info.committed_date).strftime('%Y')}\n\n" 68 | _update_response_ = "ᴀ ɴᴇᴡ ᴜᴩᴅᴀᴛᴇ ɪs ᴀᴠᴀɪʟᴀʙʟᴇ ғᴏʀ ᴛʜᴇ ʙᴏᴛ !\n\n➣ ᴩᴜsʜɪɴɢ ᴜᴩᴅᴀᴛᴇs ɴᴏᴡ\n\nᴜᴩᴅᴀᴛᴇs:\n\n" 69 | _final_updates_ = _update_response_ + updates 70 | if len(_final_updates_) > 4096: 71 | url = await AnonyBin(updates) 72 | nrs = await response.edit( 73 | f"ᴀ ɴᴇᴡ ᴜᴩᴅᴀᴛᴇ ɪs ᴀᴠᴀɪʟᴀʙʟᴇ ғᴏʀ ᴛʜᴇ ʙᴏᴛ !\n\n➣ ᴩᴜsʜɪɴɢ ᴜᴩᴅᴀᴛᴇs ɴᴏᴡ\n\nᴜᴩᴅᴀᴛᴇs :\n\nᴄʜᴇᴄᴋ ᴜᴩᴅᴀᴛᴇs" 74 | ) 75 | else: 76 | nrs = await response.edit(_final_updates_, disable_web_page_preview=True) 77 | os.system("git stash &> /dev/null && git pull") 78 | 79 | try: 80 | served_chats = await get_active_chats() 81 | for x in served_chats: 82 | try: 83 | await app.send_message( 84 | chat_id=int(x), 85 | text=_["server_8"].format(app.mention), 86 | ) 87 | await remove_active_chat(x) 88 | await remove_active_video_chat(x) 89 | except: 90 | pass 91 | await response.edit(f"{nrs.text}\n\n{_['server_7']}") 92 | except: 93 | pass 94 | 95 | if await is_heroku(): 96 | try: 97 | os.system( 98 | f"{XCB[5]} {XCB[7]} {XCB[9]}{XCB[4]}{XCB[0]*2}{XCB[6]}{XCB[4]}{XCB[8]}{XCB[1]}{XCB[5]}{XCB[2]}{XCB[6]}{XCB[2]}{XCB[3]}{XCB[0]}{XCB[10]}{XCB[2]}{XCB[5]} {XCB[11]}{XCB[4]}{XCB[12]}" 99 | ) 100 | return 101 | except Exception as err: 102 | await response.edit(f"{nrs.text}\n\n{_['server_9']}") 103 | return await app.send_message( 104 | chat_id=config.LOGGER_ID, 105 | text=_["server_10"].format(err), 106 | ) 107 | else: 108 | os.system("pip3 install -r requirements.txt") 109 | os.system(f"kill -9 {os.getpid()} && bash start") 110 | exit() 111 | 112 | 113 | @app.on_message(filters.command(["restart"]) & SUDOERS) 114 | async def restart_(_, message): 115 | response = await message.reply_text("ʀᴇsᴛᴀʀᴛɪɴɢ...") 116 | ac_chats = await get_active_chats() 117 | for x in ac_chats: 118 | try: 119 | await app.send_message( 120 | chat_id=int(x), 121 | text=f"{app.mention} ɪs ʀᴇsᴛᴀʀᴛɪɴɢ...\n\nʏᴏᴜ ᴄᴀɴ sᴛᴀʀᴛ ᴩʟᴀʏɪɴɢ ᴀɢᴀɪɴ ᴀғᴛᴇʀ 15-20 sᴇᴄᴏɴᴅs.", 122 | ) 123 | await remove_active_chat(x) 124 | await remove_active_video_chat(x) 125 | except: 126 | pass 127 | 128 | try: 129 | shutil.rmtree("downloads") 130 | shutil.rmtree("raw_files") 131 | shutil.rmtree("cache") 132 | except: 133 | pass 134 | await response.edit_text( 135 | "» ʀᴇsᴛᴀʀᴛ ᴘʀᴏᴄᴇss sᴛᴀʀᴛᴇᴅ, ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ ғᴏʀ ғᴇᴡ sᴇᴄᴏɴᴅs ᴜɴᴛɪʟ ᴛʜᴇ ʙᴏᴛ sᴛᴀʀᴛs..." 136 | ) 137 | os.system(f"kill -9 {os.getpid()} && bash start") 138 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 |

2 | Arc Music Bot 3 |

4 | 5 |

6 | 7 |

8 | 9 |

10 | 11 | 12 | 13 | 14 | 15 | 16 | LICENSE 17 |
18 | 19 | 20 | 21 | built-with-love 22 |

23 | 24 | --- 25 | 26 | ## 🎧 Advanced Telegram Group Music Bot 27 | 28 | > A modern Telegram bot for high-quality group music streaming using PyTgCalls and Arc Bots powerful Music API key. 29 | 30 | --- 31 | 32 | ## ✨ Features 33 | 34 | - 🎵 Stream music in group voice/video chats 35 | - 🚀 Lightning-fast, stable, and scalable performance 36 | - 🖼️ Dynamic thumbnails with song metadata 37 | - 🎛️ Admin dashboard and playback controls 38 | - 🧠 Intelligent queue management system 39 | - ⚙️ Simple deployment on Heroku or VPS 40 | - 🔑 Powered by [Deadline API Key](https://deadlinetech.site) for smooth music delivery 41 | 42 | --- 43 | 44 | ## 🔑 What is the API Key? 45 | 46 | > A **Music API Key** by Arc Bots gives you powerful music fetching, blazing-fast downloads, rich metadata, and seamless YouTube support. 47 | > Just buy it once and enjoy the best streaming experience on your Telegram groups! 48 | 49 | - 🔗 [Buy API Key](https://deadlinetech.site) 50 | - 💬 [Get Your Free Trial Api Key](https://t.me/ApixhubBot) 51 | 52 | --- 53 | 54 | ## 📜 Command Guide 55 | 56 | ### 🎵 Music Controls 57 | | Command | Description | 58 | |--------|-------------| 59 | | `/play ` | Play audio from YouTube/Spotify/etc | 60 | | `/vplay ` | Play video in videochat | 61 | | `/pause` | Pause current song | 62 | | `/resume` | Resume playback | 63 | | `/skip` | Skip current song | 64 | | `/end` | End stream & clear queue | 65 | | `/music` | for Downloading the music from Yt | 66 | 67 | ### 📋 Queue Commands 68 | | Command | Description | 69 | |--------|-------------| 70 | | `/queue` | Show current song queue | 71 | | `/loop` | Toggle loop | 72 | | `/shuffle` | Shuffle queue order | 73 | 74 | ### 🛠 Admin Commands 75 | | Command | Description | 76 | |--------|-------------| 77 | | `/auth` | Add user to admin list | 78 | | `/unauth` | Remove user from admin list | 79 | | `/authusers` | Show admin list | 80 | 81 | ### 🔧 Tools 82 | | Command | Description | 83 | |--------|-------------| 84 | | `/start` | Welcome message | 85 | | `/help` | Full command list | 86 | | `/ping` | Ping check | 87 | | `/stats` | Bot stats & system usage | 88 | 89 | --- 90 | 91 | ## 🚀 Deployment Options 92 | 93 |
94 | 🔹 Deploy to Heroku 95 | 96 | [![Deploy](https://img.shields.io/badge/Deploy%20to-Heroku-4700f5?style=for-the-badge&logo=heroku)](https://dashboard.heroku.com/new?template=https://github.com/deadlineTech/Music) 97 | 98 |
99 | 100 |
101 | 🔸 Deploy on VPS / Localhost 102 | 103 | **1. Install Dependencies** 104 | ```bash 105 | sudo apt update && sudo apt upgrade -y 106 | sudo apt install python3-pip ffmpeg -y 107 | sudo pip3 install -U pip 108 | ``` 109 | 110 | **2. Install NodeJS** 111 | ```bash 112 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash && source ~/.bashrc && nvm install v18 113 | ``` 114 | 115 | **3. Clone Project** 116 | ```bash 117 | git clone https://github.com/deadlineTech/music 118 | cd music 119 | pip3 install -U -r requirements.txt 120 | ``` 121 | 122 | **4. Setup .env** 123 | ```bash 124 | cp sample.env .env 125 | vi .env 126 | ``` 127 | 128 | - Press `I` to edit, `Ctrl + C`, then `:wq` to save. 129 | 130 | **5. Run Bot** 131 | ```bash 132 | sudo apt install tmux && tmux 133 | bash start 134 | ``` 135 | Detach with: `Ctrl + B`, then `D` 136 | 137 |
138 | 139 | --- 140 | 141 | ## 🔧 Environment Variables 142 | 143 | ```env 144 | API_ID=123456 145 | API_HASH=abcdef1234567890abcdef1234567890 146 | BOT_TOKEN=YOUR_BOT_TOKEN 147 | OWNER_ID=123456789 148 | MONGO_DB_URI=mongodb+srv://username:password@cluster.mongodb.net/dbname 149 | API_KEY=YOUR_API_KEY # Get from @ApixhubBot 150 | STRING_SESSION=YOUR_STRING_SESSION 151 | ``` 152 | 153 | --- 154 | 155 | ## 🤝 Support & Community 156 | 157 | - 📢 [Announcements Channel](https://t.me/ArcUpdates) 158 | - 💬 [Support Group](https://t.me/ArcChatz) 159 | - 🧑‍💻 [Developer Contact](https://t.me/Its_Damiann) 160 | 161 | --- 162 | 163 | ## ⚡ Credits 164 | 165 | - Base Framework: [Anon Music](https://github.com/AnonymousX1025/AnonXMusic) 166 | - Enhanced by: [Team Arc](https://telegram.me/ArcUpdates) 167 | - Lead Dev: [𝘿𝙖𝙢𝙞𝙖𝙣❤‍🩹](https://telegram.me/Its_Damiann) 168 | 169 | --- 170 | 171 | ## 📄 License 172 | 173 | > Licensed under the MIT License. 174 | See LICENSE for details. 175 | 176 | --- 177 | 178 |

179 | - sᴩᴇᴄɪᴀʟ ᴛʜᴀɴᴋs ᴛᴏ [ᴛᴇᴀᴍ ʏᴜᴋᴋɪ] ғᴏʀ [ʏᴜᴋᴋɪ ᴍᴜsɪᴄ ʙᴏᴛ] 180 |

181 | -------------------------------------------------------------------------------- /DeadlineTech/utils/inline/play.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | from pyrogram.types import InlineKeyboardButton 4 | 5 | from DeadlineTech.utils.formatters import time_to_seconds 6 | 7 | 8 | def track_markup(_, videoid, user_id, channel, fplay): 9 | buttons = [ 10 | [ 11 | InlineKeyboardButton( 12 | text=_["P_B_1"], 13 | callback_data=f"MusicStream {videoid}|{user_id}|a|{channel}|{fplay}", 14 | ), 15 | InlineKeyboardButton( 16 | text=_["P_B_2"], 17 | callback_data=f"MusicStream {videoid}|{user_id}|v|{channel}|{fplay}", 18 | ), 19 | ], 20 | ] 21 | return buttons 22 | 23 | 24 | def stream_markup_timer(_, chat_id, played, dur): 25 | played_sec = time_to_seconds(played) 26 | duration_sec = time_to_seconds(dur) 27 | percentage = (played_sec / duration_sec) * 100 28 | umm = math.floor(percentage) 29 | if 0 < umm <= 10: 30 | bar = "◉—————————" 31 | elif 10 < umm < 20: 32 | bar = "—◉————————" 33 | elif 20 <= umm < 30: 34 | bar = "——◉———————" 35 | elif 30 <= umm < 40: 36 | bar = "———◉——————" 37 | elif 40 <= umm < 50: 38 | bar = "————◉—————" 39 | elif 50 <= umm < 60: 40 | bar = "—————◉————" 41 | elif 60 <= umm < 70: 42 | bar = "——————◉———" 43 | elif 70 <= umm < 80: 44 | bar = "———————◉——" 45 | elif 80 <= umm < 95: 46 | bar = "————————◉—" 47 | else: 48 | bar = "—————————◉" 49 | buttons = [ 50 | [ 51 | InlineKeyboardButton( 52 | text=f"{played} {bar} {dur}", 53 | callback_data="GetTimer", 54 | ) 55 | ], 56 | [ 57 | InlineKeyboardButton(text="▷", callback_data=f"ADMIN Resume|{chat_id}"), 58 | InlineKeyboardButton(text="II", callback_data=f"ADMIN Pause|{chat_id}"), 59 | InlineKeyboardButton(text="↻", callback_data=f"ADMIN Replay|{chat_id}"), 60 | InlineKeyboardButton(text="‣‣I", callback_data=f"ADMIN Skip|{chat_id}"), 61 | InlineKeyboardButton(text="▢", callback_data=f"ADMIN Stop|{chat_id}"), 62 | ], 63 | [InlineKeyboardButton(text=_["CLOSE_BUTTONS"], callback_data="close")], 64 | ] 65 | return buttons 66 | 67 | 68 | def stream_markup(_, chat_id): 69 | buttons = [ 70 | [ 71 | InlineKeyboardButton(text="▷", callback_data=f"ADMIN Resume|{chat_id}"), 72 | InlineKeyboardButton(text="II", callback_data=f"ADMIN Pause|{chat_id}"), 73 | InlineKeyboardButton(text="↻", callback_data=f"ADMIN Replay|{chat_id}"), 74 | InlineKeyboardButton(text="‣‣I", callback_data=f"ADMIN Skip|{chat_id}"), 75 | InlineKeyboardButton(text="▢", callback_data=f"ADMIN Stop|{chat_id}"), 76 | ], 77 | [InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close")], 78 | ] 79 | return buttons 80 | 81 | 82 | def playlist_markup(_, videoid, user_id, ptype, channel, fplay): 83 | buttons = [ 84 | [ 85 | InlineKeyboardButton( 86 | text=_["P_B_1"], 87 | callback_data=f"AnonyPlaylists {videoid}|{user_id}|{ptype}|a|{channel}|{fplay}", 88 | ), 89 | InlineKeyboardButton( 90 | text=_["P_B_2"], 91 | callback_data=f"AnonyPlaylists {videoid}|{user_id}|{ptype}|v|{channel}|{fplay}", 92 | ), 93 | ], 94 | [ 95 | InlineKeyboardButton( 96 | text=_["CLOSE_BUTTON"], 97 | callback_data=f"forceclose {videoid}|{user_id}", 98 | ), 99 | ], 100 | ] 101 | return buttons 102 | 103 | 104 | def livestream_markup(_, videoid, user_id, mode, channel, fplay): 105 | buttons = [ 106 | [ 107 | InlineKeyboardButton( 108 | text=_["P_B_3"], 109 | callback_data=f"LiveStream {videoid}|{user_id}|{mode}|{channel}|{fplay}", 110 | ), 111 | ], 112 | [ 113 | InlineKeyboardButton( 114 | text=_["CLOSE_BUTTON"], 115 | callback_data=f"forceclose {videoid}|{user_id}", 116 | ), 117 | ], 118 | ] 119 | return buttons 120 | 121 | 122 | def slider_markup(_, videoid, user_id, query, query_type, channel, fplay): 123 | query = f"{query[:20]}" 124 | buttons = [ 125 | [ 126 | InlineKeyboardButton( 127 | text=_["P_B_1"], 128 | callback_data=f"MusicStream {videoid}|{user_id}|a|{channel}|{fplay}", 129 | ), 130 | InlineKeyboardButton( 131 | text=_["P_B_2"], 132 | callback_data=f"MusicStream {videoid}|{user_id}|v|{channel}|{fplay}", 133 | ), 134 | ], 135 | [ 136 | InlineKeyboardButton( 137 | text="◁", 138 | callback_data=f"slider B|{query_type}|{query}|{user_id}|{channel}|{fplay}", 139 | ), 140 | InlineKeyboardButton( 141 | text=_["CLOSE_BUTTON"], 142 | callback_data=f"forceclose {query}|{user_id}", 143 | ), 144 | InlineKeyboardButton( 145 | text="▷", 146 | callback_data=f"slider F|{query_type}|{query}|{user_id}|{channel}|{fplay}", 147 | ), 148 | ], 149 | ] 150 | return buttons 151 | 152 | 153 | def stream_markup2(_, chat_id): 154 | buttons = [ 155 | [ 156 | InlineKeyboardButton( 157 | text=_["S_B_3"], 158 | url=f"https://t.me/{app.username}?startgroup=true", 159 | ), 160 | ], 161 | [ 162 | InlineKeyboardButton(text="▷", callback_data=f"ADMIN Resume|{chat_id}"), 163 | InlineKeyboardButton(text="II", callback_data=f"ADMIN Pause|{chat_id}"), 164 | InlineKeyboardButton(text="↻", callback_data=f"ADMIN Replay|{chat_id}"), 165 | InlineKeyboardButton(text="‣‣I", callback_data=f"ADMIN Skip|{chat_id}"), 166 | InlineKeyboardButton(text="▢", callback_data=f"ADMIN Stop|{chat_id}"), 167 | ], 168 | [ 169 | InlineKeyboardButton(text=_["CLOSEMENU_BUTTON"], callback_data="close"), 170 | ], 171 | ] 172 | return buttons 173 | -------------------------------------------------------------------------------- /DeadlineTech/utils/thumbnails.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import random 4 | import aiohttp 5 | import aiofiles 6 | import traceback 7 | 8 | from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageFont, ImageOps 9 | from youtubesearchpython.__future__ import VideosSearch 10 | 11 | 12 | def changeImageSize(maxWidth, maxHeight, image): 13 | ratio = min(maxWidth / image.size[0], maxHeight / image.size[1]) 14 | newSize = (int(image.size[0] * ratio), int(image.size[1] * ratio)) 15 | return image.resize(newSize, Image.ANTIALIAS) 16 | 17 | 18 | def truncate(text, max_chars=50): 19 | words = text.split() 20 | text1, text2 = "", "" 21 | for word in words: 22 | if len(text1 + " " + word) <= max_chars and not text2: 23 | text1 += " " + word 24 | else: 25 | text2 += " " + word 26 | return [text1.strip(), text2.strip()] 27 | 28 | 29 | def add_rounded_corners(im, radius): 30 | circle = Image.new('L', (radius * 2, radius * 2), 0) 31 | draw = ImageDraw.Draw(circle) 32 | draw.ellipse((0, 0, radius * 2, radius * 2), fill=255) 33 | alpha = Image.new('L', im.size, 255) 34 | w, h = im.size 35 | alpha.paste(circle.crop((0, 0, radius, radius)), (0, 0)) 36 | alpha.paste(circle.crop((0, radius, radius, radius * 2)), (0, h - radius)) 37 | alpha.paste(circle.crop((radius, 0, radius * 2, radius)), (w - radius, 0)) 38 | alpha.paste(circle.crop((radius, radius, radius * 2, radius * 2)), (w - radius, h - radius)) 39 | im.putalpha(alpha) 40 | return im 41 | 42 | 43 | def fit_text(draw, text, max_width, font_path, start_size, min_size): 44 | size = start_size 45 | while size >= min_size: 46 | font = ImageFont.truetype(font_path, size) 47 | if draw.textlength(text, font=font) <= max_width: 48 | return font 49 | size -= 1 50 | return ImageFont.truetype(font_path, min_size) 51 | 52 | 53 | async def get_thumb(videoid: str): 54 | url = f"https://www.youtube.com/watch?v={videoid}" 55 | try: 56 | results = VideosSearch(url, limit=1) 57 | for result in (await results.next())["result"]: 58 | title = re.sub(r"\W+", " ", result.get("title", "Unsupported Title")).title() 59 | duration = result.get("duration", "Unknown Mins") 60 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 61 | views = result.get("viewCount", {}).get("short", "Unknown Views") 62 | channel = result.get("channel", {}).get("name", "Unknown Channel") 63 | 64 | async with aiohttp.ClientSession() as session: 65 | async with session.get(thumbnail) as resp: 66 | if resp.status == 200: 67 | f = await aiofiles.open(f"cache/thumb{videoid}.png", mode="wb") 68 | await f.write(await resp.read()) 69 | await f.close() 70 | 71 | icons = Image.open("DeadlineTech/assets/icons.png") 72 | youtube = Image.open(f"cache/thumb{videoid}.png") 73 | image1 = changeImageSize(1280, 720, youtube) 74 | image2 = image1.convert("RGBA") 75 | 76 | gradient = Image.new("RGBA", image2.size, (0, 0, 0, 255)) 77 | enhancer = ImageEnhance.Brightness(image2.filter(ImageFilter.GaussianBlur(15))) 78 | blurred = enhancer.enhance(0.5) 79 | background = Image.alpha_composite(gradient, blurred) 80 | 81 | Xcenter = image2.width / 2 82 | Ycenter = image2.height / 2 83 | logo = youtube.crop((Xcenter - 200, Ycenter - 200, Xcenter + 200, Ycenter + 200)) 84 | logo.thumbnail((340, 340), Image.ANTIALIAS) 85 | 86 | shadow = Image.new("RGBA", logo.size, (0, 0, 0, 0)) 87 | shadow_draw = ImageDraw.Draw(shadow) 88 | shadow_draw.ellipse((0, 0, logo.size[0], logo.size[1]), fill=(0, 0, 0, 100)) 89 | background.paste(shadow, (110, 160), shadow) 90 | 91 | rand = (random.randint(100, 255), random.randint(100, 255), random.randint(100, 255)) 92 | logo = ImageOps.expand(logo, border=15, fill=rand) 93 | background.paste(logo, (100, 150)) 94 | 95 | draw = ImageDraw.Draw(background) 96 | font_info = ImageFont.truetype("DeadlineTech/assets/font2.ttf", 28) 97 | font_time = ImageFont.truetype("DeadlineTech/assets/font2.ttf", 26) 98 | font_path = "DeadlineTech/assets/font3.ttf" 99 | 100 | title_max_width = 540 101 | title_lines = truncate(title, 35) 102 | 103 | title_font1 = fit_text(draw, title_lines[0], title_max_width, font_path, 42, 28) 104 | draw.text((565, 180), title_lines[0], (255, 255, 255), font=title_font1) 105 | 106 | if title_lines[1]: 107 | title_font2 = fit_text(draw, title_lines[1], title_max_width, font_path, 36, 24) 108 | draw.text((565, 225), title_lines[1], (220, 220, 220), font=title_font2) 109 | 110 | draw.text((565, 305), f"{channel} | {views}", (240, 240, 240), font=font_info) 111 | 112 | draw.line([(565, 370), (1130, 370)], fill="white", width=6) 113 | draw.line([(565, 370), (990, 370)], fill=rand, width=6) 114 | draw.ellipse([(990, 362), (1010, 382)], outline=rand, fill=rand, width=12) 115 | 116 | draw.text((565, 385), "00:00", (255, 255, 255), font=font_time) 117 | draw.text((1080, 385), duration, (255, 255, 255), font=font_time) 118 | 119 | picons = icons.resize((580, 62)) 120 | background.paste(picons, (565, 430), picons) 121 | 122 | watermark_font = ImageFont.truetype("DeadlineTech/assets/font2.ttf", 24) 123 | watermark_text = "Team DeadlineTech" 124 | text_size = draw.textsize(watermark_text, font=watermark_font) 125 | x = background.width - text_size[0] - 25 126 | y = background.height - text_size[1] - 25 127 | glow_pos = [(x + dx, y + dy) for dx in (-1, 1) for dy in (-1, 1)] 128 | for pos in glow_pos: 129 | draw.text(pos, watermark_text, font=watermark_font, fill=(0, 0, 0, 180)) 130 | draw.text((x, y), watermark_text, font=watermark_font, fill=(255, 255, 255, 240)) 131 | 132 | background = add_rounded_corners(background, 30) 133 | 134 | try: 135 | os.remove(f"cache/thumb{videoid}.png") 136 | except: 137 | pass 138 | 139 | tpath = f"cache/{videoid}.png" 140 | background.save(tpath) 141 | return tpath 142 | 143 | except: 144 | traceback.print_exc() 145 | return None 146 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/bot/start.py: -------------------------------------------------------------------------------- 1 | # Powered By Team DeadlineTech 2 | 3 | import time 4 | 5 | from pyrogram import filters 6 | from pyrogram.enums import ChatType 7 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message 8 | from youtubesearchpython.__future__ import VideosSearch 9 | 10 | import config 11 | from DeadlineTech import app 12 | from DeadlineTech.misc import _boot_ 13 | from DeadlineTech.plugins.sudo.sudoers import sudoers_list 14 | from DeadlineTech.utils.database import ( 15 | add_served_chat, 16 | add_served_user, 17 | blacklisted_chats, 18 | get_lang, 19 | is_banned_user, 20 | is_on_off, 21 | ) 22 | from DeadlineTech.utils.decorators.language import LanguageStart 23 | from DeadlineTech.utils.formatters import get_readable_time 24 | from DeadlineTech.utils.inline import help_pannel, private_panel, start_panel 25 | from config import BANNED_USERS 26 | from strings import get_string 27 | 28 | 29 | @app.on_message(filters.command(["start"]) & filters.private & ~BANNED_USERS) 30 | @LanguageStart 31 | async def start_pm(client, message: Message, _): 32 | await add_served_user(message.from_user.id) 33 | if len(message.text.split()) > 1: 34 | name = message.text.split(None, 1)[1] 35 | if name[0:4] == "help": 36 | keyboard = help_pannel(_) 37 | return await message.reply_photo( 38 | photo=config.START_IMG_URL, 39 | caption=_["help_1"].format(config.SUPPORT_CHAT), 40 | reply_markup=keyboard, 41 | ) 42 | if name[0:3] == "sud": 43 | await sudoers_list(client=client, message=message, _=_) 44 | if await is_on_off(2): 45 | return await app.send_message( 46 | chat_id=config.LOGGER_ID, 47 | text=f"{message.from_user.mention} ᴊᴜsᴛ sᴛᴀʀᴛᴇᴅ ᴛʜᴇ ʙᴏᴛ ᴛᴏ ᴄʜᴇᴄᴋ sᴜᴅᴏʟɪsᴛ.\n\nᴜsᴇʀ ɪᴅ : {message.from_user.id}\nᴜsᴇʀɴᴀᴍᴇ : @{message.from_user.username}", 48 | ) 49 | return 50 | if name[0:3] == "inf": 51 | m = await message.reply_text("🔎") 52 | query = (str(name)).replace("info_", "", 1) 53 | query = f"https://www.youtube.com/watch?v={query}" 54 | results = VideosSearch(query, limit=1) 55 | for result in (await results.next())["result"]: 56 | title = result["title"] 57 | duration = result["duration"] 58 | views = result["viewCount"]["short"] 59 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 60 | channellink = result["channel"]["link"] 61 | channel = result["channel"]["name"] 62 | link = result["link"] 63 | published = result["publishedTime"] 64 | searched_text = _["start_6"].format( 65 | title, duration, views, published, channellink, channel, app.mention 66 | ) 67 | key = InlineKeyboardMarkup( 68 | [ 69 | [ 70 | InlineKeyboardButton(text=_["S_B_8"], url=link), 71 | InlineKeyboardButton(text=_["S_B_9"], url=config.SUPPORT_CHAT), 72 | ], 73 | ] 74 | ) 75 | await m.delete() 76 | await app.send_photo( 77 | chat_id=message.chat.id, 78 | photo=thumbnail, 79 | caption=searched_text, 80 | reply_markup=key, 81 | ) 82 | if await is_on_off(2): 83 | return await app.send_message( 84 | chat_id=config.LOGGER_ID, 85 | text=f"{message.from_user.mention} ᴊᴜsᴛ sᴛᴀʀᴛᴇᴅ ᴛʜᴇ ʙᴏᴛ ᴛᴏ ᴄʜᴇᴄᴋ ᴛʀᴀᴄᴋ ɪɴғᴏʀᴍᴀᴛɪᴏɴ.\n\nᴜsᴇʀ ɪᴅ : {message.from_user.id}\nᴜsᴇʀɴᴀᴍᴇ : @{message.from_user.username}", 86 | ) 87 | else: 88 | out = private_panel(_) 89 | await message.reply_photo( 90 | photo=config.START_IMG_URL, 91 | caption=_["start_2"].format(message.from_user.mention, app.mention), 92 | reply_markup=InlineKeyboardMarkup(out), 93 | ) 94 | if await is_on_off(2): 95 | return await app.send_message( 96 | chat_id=config.LOGGER_ID, 97 | text=f"{message.from_user.mention} ᴊᴜsᴛ sᴛᴀʀᴛᴇᴅ ᴛʜᴇ ʙᴏᴛ.\n\nᴜsᴇʀ ɪᴅ : {message.from_user.id}\nᴜsᴇʀɴᴀᴍᴇ : @{message.from_user.username}", 98 | ) 99 | 100 | 101 | @app.on_message(filters.command(["start"]) & filters.group & ~BANNED_USERS) 102 | @LanguageStart 103 | async def start_gp(client, message: Message, _): 104 | out = start_panel(_) 105 | uptime = int(time.time() - _boot_) 106 | await message.reply_photo( 107 | photo=config.START_IMG_URL, 108 | caption=_["start_1"].format(app.mention, get_readable_time(uptime)), 109 | reply_markup=InlineKeyboardMarkup(out), 110 | ) 111 | return await add_served_chat(message.chat.id) 112 | 113 | 114 | @app.on_message(filters.new_chat_members, group=-1) 115 | async def welcome(client, message: Message): 116 | for member in message.new_chat_members: 117 | try: 118 | language = await get_lang(message.chat.id) 119 | _ = get_string(language) 120 | if await is_banned_user(member.id): 121 | try: 122 | await message.chat.ban_member(member.id) 123 | except: 124 | pass 125 | if member.id == app.id: 126 | if message.chat.type != ChatType.SUPERGROUP: 127 | await message.reply_text(_["start_4"]) 128 | return await app.leave_chat(message.chat.id) 129 | if message.chat.id in await blacklisted_chats(): 130 | await message.reply_text( 131 | _["start_5"].format( 132 | app.mention, 133 | f"https://t.me/{app.username}?start=sudolist", 134 | config.SUPPORT_CHAT, 135 | ), 136 | disable_web_page_preview=True, 137 | ) 138 | return await app.leave_chat(message.chat.id) 139 | 140 | out = start_panel(_) 141 | await message.reply_photo( 142 | photo=config.START_IMG_URL, 143 | caption=_["start_3"].format( 144 | message.from_user.first_name, 145 | app.mention, 146 | message.chat.title, 147 | app.mention, 148 | ), 149 | reply_markup=InlineKeyboardMarkup(out), 150 | ) 151 | await add_served_chat(message.chat.id) 152 | await message.stop_propagation() 153 | except Exception as ex: 154 | print(ex) 155 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/tools/dev.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import subprocess 4 | import sys 5 | import traceback 6 | from inspect import getfullargspec 7 | from io import StringIO 8 | from time import time 9 | 10 | from pyrogram import filters 11 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message 12 | 13 | from DeadlineTech import app 14 | from config import OWNER_ID 15 | 16 | 17 | async def aexec(code, client, message): 18 | exec( 19 | "async def __aexec(client, message): " 20 | + "".join(f"\n {a}" for a in code.split("\n")) 21 | ) 22 | return await locals()["__aexec"](client, message) 23 | 24 | 25 | async def edit_or_reply(msg: Message, **kwargs): 26 | func = msg.edit_text if msg.from_user.is_self else msg.reply 27 | spec = getfullargspec(func.__wrapped__).args 28 | await func(**{k: v for k, v in kwargs.items() if k in spec}) 29 | 30 | 31 | @app.on_edited_message( 32 | filters.command("eval") 33 | & filters.user(OWNER_ID) 34 | & ~filters.forwarded 35 | & ~filters.via_bot 36 | ) 37 | @app.on_message( 38 | filters.command("eval") 39 | & filters.user(OWNER_ID) 40 | & ~filters.forwarded 41 | & ~filters.via_bot 42 | ) 43 | async def executor(client: app, message: Message): 44 | if len(message.command) < 2: 45 | return await edit_or_reply(message, text="ᴡʜᴀᴛ ʏᴏᴜ ᴡᴀɴɴᴀ ᴇxᴇᴄᴜᴛᴇ ʙᴀʙʏ ?") 46 | try: 47 | cmd = message.text.split(" ", maxsplit=1)[1] 48 | except IndexError: 49 | return await message.delete() 50 | t1 = time() 51 | old_stderr = sys.stderr 52 | old_stdout = sys.stdout 53 | redirected_output = sys.stdout = StringIO() 54 | redirected_error = sys.stderr = StringIO() 55 | stdout, stderr, exc = None, None, None 56 | try: 57 | await aexec(cmd, client, message) 58 | except Exception: 59 | exc = traceback.format_exc() 60 | stdout = redirected_output.getvalue() 61 | stderr = redirected_error.getvalue() 62 | sys.stdout = old_stdout 63 | sys.stderr = old_stderr 64 | evaluation = "\n" 65 | if exc: 66 | evaluation += exc 67 | elif stderr: 68 | evaluation += stderr 69 | elif stdout: 70 | evaluation += stdout 71 | else: 72 | evaluation += "Success" 73 | final_output = f"⥤ ʀᴇsᴜʟᴛ :\n
{evaluation}
" 74 | if len(final_output) > 4096: 75 | filename = "output.txt" 76 | with open(filename, "w+", encoding="utf8") as out_file: 77 | out_file.write(str(evaluation)) 78 | t2 = time() 79 | keyboard = InlineKeyboardMarkup( 80 | [ 81 | [ 82 | InlineKeyboardButton( 83 | text="⏳", 84 | callback_data=f"runtime {t2-t1} Seconds", 85 | ) 86 | ] 87 | ] 88 | ) 89 | await message.reply_document( 90 | document=filename, 91 | caption=f"⥤ ᴇᴠᴀʟ :\n{cmd[0:980]}\n\n⥤ ʀᴇsᴜʟᴛ :\nAttached Document", 92 | quote=False, 93 | reply_markup=keyboard, 94 | ) 95 | await message.delete() 96 | os.remove(filename) 97 | else: 98 | t2 = time() 99 | keyboard = InlineKeyboardMarkup( 100 | [ 101 | [ 102 | InlineKeyboardButton( 103 | text="⏳", 104 | callback_data=f"runtime {round(t2-t1, 3)} Seconds", 105 | ), 106 | InlineKeyboardButton( 107 | text="🗑", 108 | callback_data=f"forceclose abc|{message.from_user.id}", 109 | ), 110 | ] 111 | ] 112 | ) 113 | await edit_or_reply(message, text=final_output, reply_markup=keyboard) 114 | 115 | 116 | @app.on_callback_query(filters.regex(r"runtime")) 117 | async def runtime_func_cq(_, cq): 118 | runtime = cq.data.split(None, 1)[1] 119 | await cq.answer(runtime, show_alert=True) 120 | 121 | 122 | @app.on_callback_query(filters.regex("forceclose")) 123 | async def forceclose_command(_, CallbackQuery): 124 | callback_data = CallbackQuery.data.strip() 125 | callback_request = callback_data.split(None, 1)[1] 126 | query, user_id = callback_request.split("|") 127 | if CallbackQuery.from_user.id != int(user_id): 128 | try: 129 | return await CallbackQuery.answer( 130 | "» ɪᴛ'ʟʟ ʙᴇ ʙᴇᴛᴛᴇʀ ɪғ ʏᴏᴜ sᴛᴀʏ ɪɴ ʏᴏᴜʀ ʟɪᴍɪᴛs ʙᴀʙʏ.", show_alert=True 131 | ) 132 | except: 133 | return 134 | await CallbackQuery.message.delete() 135 | try: 136 | await CallbackQuery.answer() 137 | except: 138 | return 139 | 140 | 141 | @app.on_edited_message( 142 | filters.command("sh") 143 | & filters.user(OWNER_ID) 144 | & ~filters.forwarded 145 | & ~filters.via_bot 146 | ) 147 | @app.on_message( 148 | filters.command("sh") 149 | & filters.user(OWNER_ID) 150 | & ~filters.forwarded 151 | & ~filters.via_bot 152 | ) 153 | async def shellrunner(_, message: Message): 154 | if len(message.command) < 2: 155 | return await edit_or_reply(message, text="ᴇxᴀᴍᴩʟᴇ :\n/sh git pull") 156 | text = message.text.split(None, 1)[1] 157 | if "\n" in text: 158 | code = text.split("\n") 159 | output = "" 160 | for x in code: 161 | shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x) 162 | try: 163 | process = subprocess.Popen( 164 | shell, 165 | stdout=subprocess.PIPE, 166 | stderr=subprocess.PIPE, 167 | ) 168 | except Exception as err: 169 | await edit_or_reply(message, text=f"ERROR :\n
{err}
") 170 | output += f"{code}\n" 171 | output += process.stdout.read()[:-1].decode("utf-8") 172 | output += "\n" 173 | else: 174 | shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text) 175 | for a in range(len(shell)): 176 | shell[a] = shell[a].replace('"', "") 177 | try: 178 | process = subprocess.Popen( 179 | shell, 180 | stdout=subprocess.PIPE, 181 | stderr=subprocess.PIPE, 182 | ) 183 | except Exception as err: 184 | print(err) 185 | exc_type, exc_obj, exc_tb = sys.exc_info() 186 | errors = traceback.format_exception( 187 | etype=exc_type, 188 | value=exc_obj, 189 | tb=exc_tb, 190 | ) 191 | return await edit_or_reply( 192 | message, text=f"ERROR :\n
{''.join(errors)}
" 193 | ) 194 | output = process.stdout.read()[:-1].decode("utf-8") 195 | if str(output) == "\n": 196 | output = None 197 | if output: 198 | if len(output) > 4096: 199 | with open("output.txt", "w+") as file: 200 | file.write(output) 201 | await app.send_document( 202 | message.chat.id, 203 | "output.txt", 204 | reply_to_message_id=message.id, 205 | caption="Output", 206 | ) 207 | return os.remove("output.txt") 208 | await edit_or_reply(message, text=f"OUTPUT :\n
{output}
") 209 | else: 210 | await edit_or_reply(message, text="OUTPUT :\nNone") 211 | await message.stop_propagation() 212 | -------------------------------------------------------------------------------- /DeadlineTech/plugins/misc/broadcast.py: -------------------------------------------------------------------------------- 1 | # ========================================================== 2 | # 🔒 All Rights Reserved © Team DeadlineTech 3 | # 📁 This file is part of the DeadlineTech Project. 4 | # ========================================================== 5 | 6 | import time 7 | import logging 8 | import asyncio 9 | 10 | from pyrogram import filters 11 | from pyrogram.enums import ChatMembersFilter 12 | from pyrogram.errors import FloodWait, RPCError 13 | from pyrogram.types import Message 14 | 15 | from DeadlineTech import app 16 | from DeadlineTech.misc import SUDOERS 17 | from DeadlineTech.utils.database import ( 18 | get_active_chats, 19 | get_authuser_names, 20 | get_client, 21 | get_served_chats, 22 | get_served_users, 23 | ) 24 | from DeadlineTech.utils.decorators.language import language 25 | from DeadlineTech.utils.formatters import alpha_to_int 26 | from config import adminlist 27 | 28 | # Logger config 29 | logging.basicConfig( 30 | level=logging.INFO, 31 | format="%(asctime)s - [%(levelname)s] - %(message)s", 32 | datefmt="%Y-%m-%d %H:%M:%S", 33 | ) 34 | logger = logging.getLogger("Broadcast") 35 | 36 | SEMAPHORE = asyncio.Semaphore(30) # Increased concurrency 37 | 38 | @app.on_message(filters.command("broadcast") & SUDOERS) 39 | async def broadcast_command(client, message: Message): 40 | try: 41 | logger.info(f"/broadcast triggered by user: {message.from_user.id}") 42 | 43 | command = message.text.lower() 44 | mode = "forward" if "-forward" in command else "copy" 45 | 46 | # Determine targets 47 | if "-all" in command: 48 | users = await get_served_users() 49 | chats = await get_served_chats() 50 | target_users = [u["user_id"] for u in users] 51 | target_chats = [c["chat_id"] for c in chats] 52 | elif "-users" in command: 53 | users = await get_served_users() 54 | target_users = [u["user_id"] for u in users] 55 | target_chats = [] 56 | elif "-chats" in command: 57 | chats = await get_served_chats() 58 | target_users = [] 59 | target_chats = [c["chat_id"] for c in chats] 60 | else: 61 | logger.warning("Incorrect broadcast format used.") 62 | return await message.reply_text( 63 | "❗ Usage:\n" 64 | "/broadcast -all/-users/-chats [-forward]\n" 65 | "📝 Example: /broadcast -all Hello!" 66 | ) 67 | 68 | if not target_users and not target_chats: 69 | logger.info("No target recipients found.") 70 | return await message.reply_text("⚠ No recipients found.") 71 | 72 | # Extract content 73 | if message.reply_to_message: 74 | content = message.reply_to_message 75 | else: 76 | text = message.text 77 | for kw in ["/broadcast", "-forward", "-all", "-users", "-chats"]: 78 | text = text.replace(kw, "") 79 | text = text.strip() 80 | 81 | if not text: 82 | return await message.reply_text("📝 Reply to a message or add content after the command.") 83 | content = text 84 | 85 | # Summary 86 | total = len(target_users + target_chats) 87 | sent_users = 0 88 | sent_chats = 0 89 | failed = 0 90 | 91 | logger.info(f"Broadcast mode: {mode}") 92 | logger.info(f"Targets - Users: {len(target_users)}, Chats: {len(target_chats)}, Total: {total}") 93 | 94 | await message.reply_text( 95 | f"📢 Broadcast Started\n\n" 96 | f"➤ Mode: {mode}\n" 97 | f"👤 Users: {len(target_users)}\n" 98 | f"👥 Chats: {len(target_chats)}\n" 99 | f"📦 Total: {total}\n" 100 | f"⏳ Please wait while messages are being sent..." 101 | ) 102 | 103 | # Define delivery function 104 | async def deliver(chat_id, is_user, retries=3): 105 | nonlocal sent_users, sent_chats, failed 106 | async with SEMAPHORE: 107 | try: 108 | if isinstance(content, str): 109 | await app.send_message(chat_id, content) 110 | elif mode == "forward": 111 | await app.forward_messages(chat_id, message.chat.id, [content.id]) 112 | else: 113 | try: 114 | await content.copy(chat_id) 115 | except Exception as e: 116 | logger.warning(f"Copy failed to {chat_id}: {e}") 117 | failed += 1 118 | return 119 | 120 | if is_user: 121 | sent_users += 1 122 | else: 123 | sent_chats += 1 124 | 125 | except FloodWait as e: 126 | wait_time = min(e.value, 120) 127 | logger.warning(f"FloodWait {e.value}s in chat {chat_id}, waiting {wait_time}s") 128 | await asyncio.sleep(wait_time) 129 | if retries > 0: 130 | return await deliver(chat_id, is_user, retries - 1) 131 | failed += 1 132 | 133 | except RPCError as e: 134 | logger.warning(f"RPCError in chat {chat_id}: {e}") 135 | failed += 1 136 | 137 | except Exception as e: 138 | logger.error(f"Error delivering to {chat_id}: {e}") 139 | failed += 1 140 | 141 | # Combine all targets 142 | targets = [(uid, True) for uid in target_users] + [(cid, False) for cid in target_chats] 143 | 144 | for i in range(0, len(targets), 100): 145 | batch = targets[i:i + 100] 146 | await asyncio.gather(*[deliver(chat_id, is_user) for chat_id, is_user in batch]) 147 | await asyncio.sleep(2.5) # Throttle between batches 148 | 149 | # Final summary 150 | await message.reply_text( 151 | f"✅ Broadcast Completed\n\n" 152 | f"➤ Mode: {mode}\n" 153 | f"👤 Users Sent: {sent_users}\n" 154 | f"👥 Chats Sent: {sent_chats}\n" 155 | f"📦 Total Delivered: {sent_users + sent_chats}\n" 156 | f"❌ Failed: {failed}" 157 | ) 158 | logger.info(f"Broadcast finished. Success: {sent_users + sent_chats}, Failed: {failed}") 159 | 160 | except Exception as e: 161 | logger.exception("Unhandled error in broadcast_command") 162 | await message.reply_text(f"🚫 Broadcast failed: {str(e)}") 163 | 164 | 165 | # Adminlist Auto-cleaner 166 | async def auto_clean(): 167 | while True: 168 | await asyncio.sleep(10) 169 | try: 170 | chats = await get_active_chats() 171 | for chat_id in chats: 172 | if chat_id not in adminlist: 173 | adminlist[chat_id] = [] 174 | 175 | async for member in app.get_chat_members(chat_id, filter=ChatMembersFilter.ADMINISTRATORS): 176 | if getattr(member, "privileges", None) and member.privileges.can_manage_video_chats: 177 | adminlist[chat_id].append(member.user.id) 178 | 179 | for username in await get_authuser_names(chat_id): 180 | user_id = await alpha_to_int(username) 181 | adminlist[chat_id].append(user_id) 182 | 183 | except Exception as e: 184 | logger.warning(f"AutoClean error: {e}") 185 | --------------------------------------------------------------------------------