├── start ├── Utils ├── Query.jpg ├── ayiin.jpg ├── black.PNG ├── blue.PNG ├── green.PNG ├── grey.PNG ├── icon.gif ├── pink.PNG ├── red.PNG ├── Result.JPEG ├── orange.PNG ├── yellow.PNG ├── Playlist.jpg ├── Telegram.JPEG └── finalfont.ttf ├── heroku.yml ├── Ayiin ├── Database │ ├── .DS_Store │ ├── onoff.py │ ├── pmpermit.py │ ├── blacklistchat.py │ ├── sudo.py │ ├── theme.py │ ├── gban.py │ ├── chats.py │ ├── start.py │ ├── assistant.py │ ├── __init__.py │ ├── videocalls.py │ ├── queue.py │ ├── auth.py │ └── playlist.py ├── Utilities │ ├── heroku.py │ ├── formatters.py │ ├── theme.py │ ├── ping.py │ ├── url.py │ ├── assistant.py │ ├── paste.py │ ├── changers.py │ ├── tasks.py │ ├── thumbnails.py │ ├── youtube.py │ ├── inline.py │ ├── chat.py │ ├── stream.py │ ├── timer.py │ └── videostream.py ├── Plugins │ ├── __init__.py │ ├── Ping.py │ ├── Watcher.py │ ├── Speedtest.py │ ├── Theme.py │ ├── Blacklist.py │ ├── Multi-Assistant │ │ └── Assistant.py │ ├── Lyrics.py │ ├── Assistant.py │ ├── Auth.py │ ├── Song.py │ ├── Developer.py │ ├── Stream.py │ └── Voicechat.py ├── Inline │ ├── __init__.py │ ├── song.py │ ├── others.py │ ├── videocalls.py │ ├── stats.py │ ├── playlist.py │ ├── start.py │ └── play.py ├── Core │ ├── PyTgCalls │ │ ├── Converter.py │ │ ├── Queues.py │ │ ├── Tgdownloader.py │ │ └── Downloader.py │ └── Clients │ │ └── cli.py ├── Decorators │ ├── logger.py │ ├── permission.py │ ├── checker.py │ ├── admins.py │ └── assistant.py └── __init__.py ├── .dockerignore ├── .gitignore ├── Dockerfile ├── requirements.txt ├── sample.env ├── gen_session.py ├── config.py ├── README.md └── app.json /start: -------------------------------------------------------------------------------- 1 | python3 -m Ayiin 2 | -------------------------------------------------------------------------------- /Utils/Query.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/Query.jpg -------------------------------------------------------------------------------- /Utils/ayiin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/ayiin.jpg -------------------------------------------------------------------------------- /Utils/black.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/black.PNG -------------------------------------------------------------------------------- /Utils/blue.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/blue.PNG -------------------------------------------------------------------------------- /Utils/green.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/green.PNG -------------------------------------------------------------------------------- /Utils/grey.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/grey.PNG -------------------------------------------------------------------------------- /Utils/icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/icon.gif -------------------------------------------------------------------------------- /Utils/pink.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/pink.PNG -------------------------------------------------------------------------------- /Utils/red.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/red.PNG -------------------------------------------------------------------------------- /Utils/Result.JPEG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/Result.JPEG -------------------------------------------------------------------------------- /Utils/orange.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/orange.PNG -------------------------------------------------------------------------------- /Utils/yellow.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/yellow.PNG -------------------------------------------------------------------------------- /Utils/Playlist.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/Playlist.jpg -------------------------------------------------------------------------------- /Utils/Telegram.JPEG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/Telegram.JPEG -------------------------------------------------------------------------------- /Utils/finalfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Utils/finalfont.ttf -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: bash start 6 | -------------------------------------------------------------------------------- /Ayiin/Database/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AyiinXd/YinsMusic/HEAD/Ayiin/Database/.DS_Store -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.log 3 | .git/ 4 | .idea/ 5 | README.md 6 | downloads/ 7 | raw_files/ 8 | .gitignore 9 | __pycache__/ 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.log 3 | venv/ 4 | .idea/ 5 | *.session 6 | raw_files/ 7 | downloads/ 8 | __pycache__/ 9 | *.session-journal 10 | -------------------------------------------------------------------------------- /Ayiin/Utilities/heroku.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | from config import HEROKU_API_KEY 4 | 5 | 6 | async def is_heroku(): 7 | return "heroku" in socket.getfqdn() 8 | 9 | 10 | async def user_input(input): 11 | if " " in input or "\n" in input: 12 | return str(input.split(maxsplit=1)[1].strip()) 13 | return "" 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nikolaik/python-nodejs:latest 2 | RUN apt-get update \ 3 | && apt-get install -y --no-install-recommends ffmpeg \ 4 | && apt-get clean \ 5 | && rm -rf /var/lib/apt/lists/* 6 | COPY . /app/ 7 | WORKDIR /app/ 8 | RUN pip3 install --no-cache-dir --upgrade --requirement requirements.txt 9 | CMD bash start 10 | -------------------------------------------------------------------------------- /Ayiin/Utilities/formatters.py: -------------------------------------------------------------------------------- 1 | def bytes(size: float) -> str: 2 | """humanize size""" 3 | if not size: 4 | return "" 5 | power = 1024 6 | t_n = 0 7 | power_dict = {0: " ", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 8 | while size > power: 9 | size /= power 10 | t_n += 1 11 | return "{:.2f} {}B".format(size, power_dict[t_n]) 12 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp 2 | aiofiles 3 | asyncio 4 | ffmpeg-python 5 | pillow 6 | pyrogram==1.4.12 7 | hachoir 8 | lyricsgenius 9 | py-tgcalls==0.8.5 10 | wget 11 | python-dotenv 12 | youtube-search-python 13 | youtube-search 14 | speedtest-cli 15 | motor 16 | psutil 17 | requests 18 | rich 19 | dnspython 20 | yt-dlp==2021.11.10.1 21 | tgcrypto 22 | gitpython 23 | heroku3 24 | -------------------------------------------------------------------------------- /Ayiin/Plugins/__init__.py: -------------------------------------------------------------------------------- 1 | import glob 2 | from os.path import basename, dirname, isfile 3 | 4 | 5 | def __list_all_modules(): 6 | mod_paths = glob.glob(dirname(__file__) + "/*.py") 7 | 8 | all_modules = [ 9 | basename(f)[:-3] 10 | for f in mod_paths 11 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 12 | ] 13 | 14 | return all_modules 15 | 16 | 17 | ALL_MODULES = sorted(__list_all_modules()) 18 | __all__ = ALL_MODULES + ["ALL_MODULES"] 19 | -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | STRING_SESSION1 = PYROGRAMSESSION 2 | API_ID = 6 3 | API_HASH = eb06d4abfb49dc3eeb1aeb98ae0f581e 4 | BOT_TOKEN = 504729834470:AAHidqz_M26xIem_Cn4Hs3BHrIokG1W43bo 5 | SUDO_USERS = 18920183 39103921 6 | MONGO_DB_URI = mongodb+srv://a:a@a.a.mongodb.net/a?retryWrites=a&w=majority 7 | LOG_GROUP_ID = -1003209382042 8 | MUSIC_BOT_NAME = Ayiin 9 | OWNER_ID = 482049203 10 | DURATION_LIMIT = 90 11 | SUPPORT_CHANNEL = https://t.me/AyiinSupport 12 | SUPPORT_GROUP = https://t.me/AyiinXdSupport 13 | ASSISTANT_PREFIX = ! 14 | -------------------------------------------------------------------------------- /gen_session.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from pyrogram import Client as c 3 | 4 | API_ID = input("\nEnter Your API_ID:\n > ") 5 | API_HASH = input("\nEnter Your API_HASH:\n > ") 6 | 7 | print("\n\n Enter Phone number when asked.\n\n") 8 | 9 | i = c(":memory:", api_id=API_ID, api_hash=API_HASH) 10 | 11 | 12 | async def main(): 13 | await i.start() 14 | ss = await i.export_session_string() 15 | print("\nHERE IS YOUR STRING SESSION, COPY IT, DON'T SHARE!!\n") 16 | print(f"\n{ss}\n") 17 | 18 | 19 | asyncio.run(main()) 20 | -------------------------------------------------------------------------------- /Ayiin/Utilities/theme.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from Ayiin.Database import get_theme 4 | 5 | themes = [ 6 | "blue", 7 | "black", 8 | "red", 9 | "green", 10 | "grey", 11 | "orange", 12 | "pink", 13 | "yellow", 14 | ] 15 | 16 | 17 | async def check_theme(chat_id: int): 18 | _theme = await get_theme(chat_id, "theme") 19 | if not _theme: 20 | theme = random.choice(themes) 21 | else: 22 | theme = _theme["theme"] 23 | if theme == "Random": 24 | theme = random.choice(themes) 25 | return theme 26 | -------------------------------------------------------------------------------- /Ayiin/Database/onoff.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | onoffdb = db.onoffper 6 | 7 | 8 | async def is_on_off(on_off: int) -> bool: 9 | onoff = await onoffdb.find_one({"on_off": on_off}) 10 | if not onoff: 11 | return False 12 | return True 13 | 14 | 15 | async def add_on(on_off: int): 16 | is_on = await is_on_off(on_off) 17 | if is_on: 18 | return 19 | return await onoffdb.insert_one({"on_off": on_off}) 20 | 21 | 22 | async def add_off(on_off: int): 23 | is_off = await is_on_off(on_off) 24 | if not is_off: 25 | return 26 | return await onoffdb.delete_one({"on_off": on_off}) 27 | -------------------------------------------------------------------------------- /Ayiin/Database/pmpermit.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | pmpermitdb = db.permit 6 | 7 | 8 | async def is_pmpermit_approved(user_id: int) -> bool: 9 | user = await pmpermitdb.find_one({"user_id": user_id}) 10 | if not user: 11 | return False 12 | return True 13 | 14 | 15 | async def approve_pmpermit(user_id: int): 16 | is_pmpermit = await is_pmpermit_approved(user_id) 17 | if is_pmpermit: 18 | return 19 | return await pmpermitdb.insert_one({"user_id": user_id}) 20 | 21 | 22 | async def disapprove_pmpermit(user_id: int): 23 | is_pmpermit = await is_pmpermit_approved(user_id) 24 | if not is_pmpermit: 25 | return 26 | return await pmpermitdb.delete_one({"user_id": user_id}) 27 | -------------------------------------------------------------------------------- /Ayiin/Utilities/ping.py: -------------------------------------------------------------------------------- 1 | def get_readable_time(seconds: int) -> str: 2 | count = 0 3 | ping_time = "" 4 | time_list = [] 5 | time_suffix_list = ["s", "m", "h", "days"] 6 | while count < 4: 7 | count += 1 8 | if count < 3: 9 | remainder, result = divmod(seconds, 60) 10 | else: 11 | remainder, result = divmod(seconds, 24) 12 | if seconds == 0 and remainder == 0: 13 | break 14 | time_list.append(int(result)) 15 | seconds = int(remainder) 16 | for i in range(len(time_list)): 17 | time_list[i] = str(time_list[i]) + time_suffix_list[i] 18 | if len(time_list) == 4: 19 | ping_time += time_list.pop() + ", " 20 | time_list.reverse() 21 | ping_time += ":".join(time_list) 22 | return ping_time 23 | -------------------------------------------------------------------------------- /Ayiin/Utilities/url.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram.types import Message 4 | 5 | 6 | def get_url(message_1: Message) -> Union[str, None]: 7 | messages = [message_1] 8 | if message_1.reply_to_message: 9 | messages.append(message_1.reply_to_message) 10 | text = "" 11 | offset = None 12 | length = None 13 | for message in messages: 14 | if offset: 15 | break 16 | if message.entities: 17 | for entity in message.entities: 18 | if entity.type == "url": 19 | text = message.text or message.caption 20 | offset, length = entity.offset, entity.length 21 | break 22 | if offset in (None,): 23 | return None 24 | return text[offset : offset + length] 25 | -------------------------------------------------------------------------------- /Ayiin/Database/blacklistchat.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | blacklist_chatdb = db.blacklistChat 6 | 7 | 8 | async def blacklisted_chats() -> list: 9 | chats = blacklist_chatdb.find({"chat_id": {"$lt": 0}}) 10 | return [ 11 | chat["chat_id"] for chat in await chats.to_list(length=1000000000) 12 | ] 13 | 14 | 15 | async def blacklist_chat(chat_id: int) -> bool: 16 | if not await blacklist_chatdb.find_one({"chat_id": chat_id}): 17 | await blacklist_chatdb.insert_one({"chat_id": chat_id}) 18 | return True 19 | return False 20 | 21 | 22 | async def whitelist_chat(chat_id: int) -> bool: 23 | if await blacklist_chatdb.find_one({"chat_id": chat_id}): 24 | await blacklist_chatdb.delete_one({"chat_id": chat_id}) 25 | return True 26 | return False 27 | -------------------------------------------------------------------------------- /Ayiin/Database/sudo.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | sudoersdb = db.sudoers 6 | 7 | 8 | async def get_sudoers() -> list: 9 | sudoers = await sudoersdb.find_one({"sudo": "sudo"}) 10 | if not sudoers: 11 | return [] 12 | return sudoers["sudoers"] 13 | 14 | 15 | async def add_sudo(user_id: int) -> bool: 16 | sudoers = await get_sudoers() 17 | sudoers.append(user_id) 18 | await sudoersdb.update_one( 19 | {"sudo": "sudo"}, {"$set": {"sudoers": sudoers}}, upsert=True 20 | ) 21 | return True 22 | 23 | 24 | async def remove_sudo(user_id: int) -> bool: 25 | sudoers = await get_sudoers() 26 | sudoers.remove(user_id) 27 | await sudoersdb.update_one( 28 | {"sudo": "sudo"}, {"$set": {"sudoers": sudoers}}, upsert=True 29 | ) 30 | return True 31 | -------------------------------------------------------------------------------- /Ayiin/Database/theme.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | themedb = db.notes 6 | 7 | 8 | async def _get_theme(chat_id: int) -> Dict[str, int]: 9 | _notes = await themedb.find_one({"chat_id": chat_id}) 10 | if not _notes: 11 | return {} 12 | return _notes["notes"] 13 | 14 | 15 | async def get_theme(chat_id: int, name: str) -> Union[bool, dict]: 16 | name = name.lower().strip() 17 | _notes = await _get_theme(chat_id) 18 | if name in _notes: 19 | return _notes[name] 20 | else: 21 | return False 22 | 23 | 24 | async def save_theme(chat_id: int, name: str, note: dict): 25 | name = name.lower().strip() 26 | _notes = await _get_theme(chat_id) 27 | _notes[name] = note 28 | await themedb.update_one( 29 | {"chat_id": chat_id}, {"$set": {"notes": _notes}}, upsert=True 30 | ) 31 | -------------------------------------------------------------------------------- /Ayiin/Database/gban.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | gbansdb = db.gban 6 | 7 | 8 | async def get_gbans_count() -> int: 9 | users = gbansdb.find({"user_id": {"$gt": 0}}) 10 | users = await users.to_list(length=100000) 11 | return len(users) 12 | 13 | 14 | async def is_gbanned_user(user_id: int) -> bool: 15 | user = await gbansdb.find_one({"user_id": user_id}) 16 | if not user: 17 | return False 18 | return True 19 | 20 | 21 | async def add_gban_user(user_id: int): 22 | is_gbanned = await is_gbanned_user(user_id) 23 | if is_gbanned: 24 | return 25 | return await gbansdb.insert_one({"user_id": user_id}) 26 | 27 | 28 | async def remove_gban_user(user_id: int): 29 | is_gbanned = await is_gbanned_user(user_id) 30 | if not is_gbanned: 31 | return 32 | return await gbansdb.delete_one({"user_id": user_id}) 33 | -------------------------------------------------------------------------------- /Ayiin/Inline/__init__.py: -------------------------------------------------------------------------------- 1 | from .others import download_markup, others_markup 2 | from .play import (audio_markup, audio_markup2, audio_timer_markup_start, 3 | primary_markup, search_markup, search_markup2, 4 | secondary_markup, secondary_markup2, timer_markup, 5 | url_markup, url_markup2) 6 | from .playlist import (add_genre_markup, check_genre_markup, check_markup, 7 | delete_playlist_markuup, fetch_playlist, 8 | paste_queue_markup, play_genre_playlist, 9 | playlist_markup, third_playlist_markup) 10 | from .song import song_download_markup, song_markup 11 | from .start import (custommarkup, dashmarkup, private_panel, setting_markup, 12 | setting_markup2, start_pannel, usermarkup, volmarkup) 13 | from .stats import stats1, stats2, stats3, stats4, stats5, stats6, stats7 14 | from .videocalls import choose_markup, livestream_markup, stream_quality_markup 15 | -------------------------------------------------------------------------------- /Ayiin/Database/chats.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | chatsdb = db.chats 6 | 7 | 8 | async def get_served_chats() -> list: 9 | chats = chatsdb.find({"chat_id": {"$lt": 0}}) 10 | if not chats: 11 | return [] 12 | chats_list = [] 13 | for chat in await chats.to_list(length=1000000000): 14 | chats_list.append(chat) 15 | return chats_list 16 | 17 | 18 | async def is_served_chat(chat_id: int) -> bool: 19 | chat = await chatsdb.find_one({"chat_id": chat_id}) 20 | if not chat: 21 | return False 22 | return True 23 | 24 | 25 | async def add_served_chat(chat_id: int): 26 | is_served = await is_served_chat(chat_id) 27 | if is_served: 28 | return 29 | return await chatsdb.insert_one({"chat_id": chat_id}) 30 | 31 | 32 | async def remove_served_chat(chat_id: int): 33 | is_served = await is_served_chat(chat_id) 34 | if not is_served: 35 | return 36 | return await chatsdb.delete_one({"chat_id": chat_id}) 37 | -------------------------------------------------------------------------------- /Ayiin/Database/start.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | assisdb = db.start 6 | 7 | 8 | async def get_start_names(chat_id: int) -> List[str]: 9 | _notes = [] 10 | for note in await _get_start(chat_id): 11 | _notes.append(note) 12 | return _notes 13 | 14 | 15 | async def _get_start(chat_id: int) -> Dict[str, int]: 16 | _notes = await assisdb.find_one({"chat_id": chat_id}) 17 | if not _notes: 18 | return {} 19 | return _notes["notes"] 20 | 21 | 22 | async def get_start(chat_id: int, name: str) -> Union[bool, dict]: 23 | name = name.lower().strip() 24 | _notes = await _get_start(chat_id) 25 | if name in _notes: 26 | return _notes[name] 27 | else: 28 | return False 29 | 30 | 31 | async def save_start(chat_id: int, name: str, note: dict): 32 | name = name.lower().strip() 33 | _notes = await _get_start(chat_id) 34 | _notes[name] = note 35 | await assisdb.update_one( 36 | {"chat_id": chat_id}, {"$set": {"notes": _notes}}, upsert=True 37 | ) 38 | -------------------------------------------------------------------------------- /Ayiin/Utilities/assistant.py: -------------------------------------------------------------------------------- 1 | from Ayiin import (ASS_CLI_1, ASS_CLI_2, ASS_CLI_3, ASS_CLI_4, ASS_CLI_5, 2 | ASSID1, ASSID2, ASSID3, ASSID4, ASSID5, ASSNAME1, ASSNAME2, 3 | ASSNAME3, ASSNAME4, ASSNAME5, ASSUSERNAME1, ASSUSERNAME2, 4 | ASSUSERNAME3, ASSUSERNAME4, ASSUSERNAME5) 5 | 6 | 7 | async def get_assistant_details(assistant: int): 8 | if int(assistant) == 1: 9 | x = ASSID1 10 | y = ASSNAME1 11 | z = ASSUSERNAME1 12 | a = ASS_CLI_1 13 | elif int(assistant) == 2: 14 | x = ASSID2 15 | y = ASSNAME2 16 | z = ASSUSERNAME2 17 | a = ASS_CLI_2 18 | elif int(assistant) == 3: 19 | x = ASSID3 20 | y = ASSNAME3 21 | z = ASSUSERNAME3 22 | a = ASS_CLI_3 23 | elif int(assistant) == 4: 24 | x = ASSID4 25 | y = ASSNAME4 26 | z = ASSUSERNAME4 27 | a = ASS_CLI_4 28 | elif int(assistant) == 5: 29 | x = ASSID5 30 | y = ASSNAME5 31 | z = ASSUSERNAME5 32 | a = ASS_CLI_5 33 | return x, y, z, a 34 | -------------------------------------------------------------------------------- /Ayiin/Database/assistant.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | assisdb = db.assistantmultimode 6 | 7 | 8 | async def get_as_names(chat_id: int) -> List[str]: 9 | _notes = [] 10 | for note in await _get_assistant(chat_id): 11 | _notes.append(note) 12 | return _notes 13 | 14 | 15 | async def _get_assistant(chat_id: int) -> Dict[str, int]: 16 | _notes = await assisdb.find_one({"chat_id": chat_id}) 17 | if not _notes: 18 | return {} 19 | return _notes["notes"] 20 | 21 | 22 | async def get_assistant(chat_id: int, name: str) -> Union[bool, dict]: 23 | name = name.lower().strip() 24 | _notes = await _get_assistant(chat_id) 25 | if name in _notes: 26 | return _notes[name] 27 | else: 28 | return False 29 | 30 | 31 | async def save_assistant(chat_id: int, name: str, note: dict): 32 | name = name.lower().strip() 33 | _notes = await _get_assistant(chat_id) 34 | _notes[name] = note 35 | await assisdb.update_one( 36 | {"chat_id": chat_id}, {"$set": {"notes": _notes}}, upsert=True 37 | ) 38 | -------------------------------------------------------------------------------- /Ayiin/Core/PyTgCalls/Converter.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from os import path 3 | 4 | 5 | class FFmpegReturnCodeError(Exception): 6 | pass 7 | 8 | 9 | async def convert(file_path: str) -> str: 10 | out = path.basename(file_path) 11 | out = out.split(".") 12 | out[-1] = "raw" 13 | out = ".".join(out) 14 | out = path.basename(out) 15 | out = path.join("raw_files", out) 16 | 17 | if path.isfile(out): 18 | return out 19 | 20 | try: 21 | proc = await asyncio.create_subprocess_shell( 22 | cmd=( 23 | "ffmpeg " 24 | "-y -i " 25 | f"{file_path} " 26 | "-f s16le " 27 | "-ac 1 " 28 | "-ar 48000 " 29 | "-acodec " 30 | "pcm_s16le " 31 | f"{out}" 32 | ), 33 | stdin=asyncio.subprocess.PIPE, 34 | stderr=asyncio.subprocess.PIPE, 35 | ) 36 | 37 | await proc.communicate() 38 | 39 | if proc.returncode != 0: 40 | raise FFmpegReturnCodeError("FFmpeg did not return 0") 41 | 42 | return out 43 | except: 44 | raise FFmpegReturnCodeError("FFmpeg did not return 0") 45 | -------------------------------------------------------------------------------- /Ayiin/Core/PyTgCalls/Queues.py: -------------------------------------------------------------------------------- 1 | from asyncio import Queue as _Queue 2 | from asyncio import QueueEmpty as Empty 3 | from typing import Dict 4 | 5 | 6 | class Queue(_Queue): 7 | _queue: list = [] 8 | 9 | def clear(self): 10 | self._queue.clear() 11 | 12 | 13 | queues: Dict[int, Queue] = {} 14 | 15 | 16 | async def put(chat_id: int, **kwargs) -> int: 17 | if chat_id not in queues: 18 | queues[chat_id] = Queue() 19 | await queues[chat_id].put({**kwargs}) 20 | return queues[chat_id].qsize() 21 | 22 | 23 | def get(chat_id: int) -> Dict[str, str]: 24 | if chat_id in queues: 25 | try: 26 | return queues[chat_id].get_nowait() 27 | except Empty: 28 | return {} 29 | return {} 30 | 31 | 32 | def is_empty(chat_id: int) -> bool: 33 | if chat_id in queues: 34 | return queues[chat_id].empty() 35 | return True 36 | 37 | 38 | def task_done(chat_id: int): 39 | if chat_id in queues: 40 | try: 41 | queues[chat_id].task_done() 42 | except ValueError: 43 | pass 44 | 45 | 46 | def clear(chat_id: int): 47 | if chat_id in queues: 48 | if queues[chat_id].empty(): 49 | raise Empty 50 | else: 51 | queues[chat_id].clear() 52 | raise Empty 53 | -------------------------------------------------------------------------------- /Ayiin/Utilities/paste.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import socket 3 | from asyncio import get_running_loop 4 | from functools import partial 5 | 6 | from Ayiin import aiohttpsession as session 7 | 8 | 9 | def _netcat(host, port, content): 10 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 11 | s.connect((host, port)) 12 | s.sendall(content.encode()) 13 | s.shutdown(socket.SHUT_WR) 14 | while True: 15 | data = s.recv(4096).decode("utf-8").strip("\n\x00") 16 | if not data: 17 | break 18 | return data 19 | s.close() 20 | 21 | 22 | async def paste_queue(content): 23 | loop = get_running_loop() 24 | link = await loop.run_in_executor( 25 | None, partial(_netcat, "ezup.dev", 9999, content) 26 | ) 27 | return link 28 | 29 | 30 | async def isPreviewUp(preview: str) -> bool: 31 | for _ in range(7): 32 | try: 33 | async with session.head(preview, timeout=2) as resp: 34 | status, size = resp.status, resp.content_length 35 | except asyncio.exceptions.TimeoutError: 36 | return False 37 | if status == 404 or (status == 200 and size == 0): 38 | await asyncio.sleep(0.4) 39 | else: 40 | return True if status == 200 else False 41 | return False 42 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Ping.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from datetime import datetime 4 | 5 | import psutil 6 | from pyrogram import Client, filters 7 | from pyrogram.types import Message 8 | 9 | from Ayiin import BOT_USERNAME, MUSIC_BOT_NAME, app, boottime 10 | from Ayiin.Utilities.ping import get_readable_time 11 | 12 | __MODULE__ = "Ping" 13 | __HELP__ = """ 14 | 15 | /ping - Check if Bot is alive or not. 16 | """ 17 | 18 | 19 | async def bot_sys_stats(): 20 | bot_uptime = int(time.time() - boottime) 21 | cpu = psutil.cpu_percent(interval=0.5) 22 | mem = psutil.virtual_memory().percent 23 | disk = psutil.disk_usage("/").percent 24 | stats = f""" 25 | Uptime: {get_readable_time((bot_uptime))} 26 | CPU: {cpu}% 27 | RAM: {mem}% 28 | Disk: {disk}%""" 29 | return stats 30 | 31 | 32 | @app.on_message(filters.command(["ping", f"ping@{BOT_USERNAME}"])) 33 | async def ping(_, message): 34 | start = datetime.now() 35 | response = await message.reply_photo( 36 | photo="Utils/ayiin.jpg", 37 | caption=">> Pong!", 38 | ) 39 | uptime = await bot_sys_stats() 40 | end = datetime.now() 41 | resp = (end - start).microseconds / 1000 42 | await response.edit_text( 43 | f"**Pong!**\n`⚡{resp} ms`\n\n{MUSIC_BOT_NAME} System Stats:{uptime}" 44 | ) 45 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Watcher.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | 3 | from Ayiin import LOG_GROUP_ID, OWNER_ID, SUDOERS, app 4 | from Ayiin.Database import is_gbanned_user, is_on_off 5 | 6 | 7 | @app.on_message(filters.private & ~filters.user(SUDOERS)) 8 | async def bot_forward(client, message): 9 | if await is_on_off(5): 10 | if message.text == "/start": 11 | return 12 | try: 13 | await app.forward_messages( 14 | chat_id=LOG_GROUP_ID, 15 | from_chat_id=message.from_user.id, 16 | message_ids=message.message_id, 17 | ) 18 | except Exception as err: 19 | print(err) 20 | return 21 | else: 22 | return 23 | 24 | 25 | chat_watcher_group = 5 26 | 27 | 28 | @app.on_message(group=chat_watcher_group) 29 | async def chat_watcher_func(_, message): 30 | try: 31 | userid = message.from_user.id 32 | except Exception: 33 | return 34 | checking = f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})" 35 | if await is_gbanned_user(userid): 36 | try: 37 | await message.chat.ban_member(userid) 38 | except Exception: 39 | return 40 | await message.reply_text( 41 | f"{checking} is globally banned by Sudo Users and has been kicked out of the chat.\n\n**Possible Reason:** Potential Spammer and Abuser." 42 | ) 43 | -------------------------------------------------------------------------------- /Ayiin/Utilities/changers.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | 4 | async def int_to_alpha(user_id: int) -> str: 5 | alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] 6 | text = "" 7 | user_id = str(user_id) 8 | for i in user_id: 9 | text += alphabet[int(i)] 10 | return text 11 | 12 | 13 | async def alpha_to_int(user_id_alphabet: str) -> int: 14 | alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] 15 | user_id = "" 16 | for i in user_id_alphabet: 17 | index = alphabet.index(i) 18 | user_id += str(index) 19 | user_id = int(user_id) 20 | return user_id 21 | 22 | 23 | def time_to_seconds(time): 24 | stringt = str(time) 25 | return sum( 26 | int(x) * 60 ** i for i, x in enumerate(reversed(stringt.split(":"))) 27 | ) 28 | 29 | 30 | def seconds_to_min(seconds): 31 | if seconds is not None: 32 | seconds = int(seconds) 33 | d, h, m, s = ( 34 | seconds // (3600 * 24), 35 | seconds // 3600 % 24, 36 | seconds % 3600 // 60, 37 | seconds % 3600 % 60, 38 | ) 39 | if d > 0: 40 | return "{:02d}:{:02d}:{:02d}:{:02d}".format(d, h, m, s) 41 | elif h > 0: 42 | return "{:02d}:{:02d}:{:02d}".format(h, m, s) 43 | elif m > 0: 44 | return "{:02d}:{:02d}".format(m, s) 45 | elif s > 0: 46 | return "00:{:02d}".format(s) 47 | return "-" 48 | -------------------------------------------------------------------------------- /Ayiin/Decorators/logger.py: -------------------------------------------------------------------------------- 1 | from config import LOG_GROUP_ID 2 | from Ayiin.Core.Clients.cli import LOG_CLIENT 3 | from Ayiin.Database import is_on_off 4 | 5 | 6 | def logging(mystic): 7 | async def wrapper(_, message): 8 | if await is_on_off(5): 9 | if message.chat.username: 10 | chatusername = f"@{message.chat.username}" 11 | else: 12 | chatusername = "Private Group" 13 | try: 14 | query = message.text.split(None, 1)[1] 15 | what = "Query Given" 16 | except: 17 | try: 18 | if not message.reply_to_message: 19 | what = "Command Given Only" 20 | else: 21 | what = "Replied to any file." 22 | except: 23 | what = "Command" 24 | logger_text = f""" 25 | __**New {what}**__ 26 | 27 | **Chat:** {message.chat.title} [`{message.chat.id}`] 28 | **User:** {message.from_user.mention} 29 | **Username:** @{message.from_user.username} 30 | **User ID:** `{message.from_user.id}` 31 | **Chat Link:** {chatusername} 32 | **Query:** {message.text}""" 33 | if LOG_CLIENT != "None": 34 | await LOG_CLIENT.send_message( 35 | LOG_GROUP_ID, 36 | f"{logger_text}", 37 | disable_web_page_preview=True, 38 | ) 39 | return await mystic(_, message) 40 | 41 | return wrapper 42 | -------------------------------------------------------------------------------- /Ayiin/Database/__init__.py: -------------------------------------------------------------------------------- 1 | from .assistant import (_get_assistant, get_as_names, get_assistant, 2 | save_assistant) 3 | from .auth import (_get_authusers, add_nonadmin_chat, delete_authuser, 4 | get_authuser, get_authuser_count, get_authuser_names, 5 | is_nonadmin_chat, remove_nonadmin_chat, save_authuser) 6 | from .blacklistchat import blacklist_chat, blacklisted_chats, whitelist_chat 7 | from .chats import (add_served_chat, get_served_chats, is_served_chat, 8 | remove_served_chat) 9 | from .gban import (add_gban_user, get_gbans_count, is_gbanned_user, 10 | remove_gban_user) 11 | from .onoff import add_off, add_on, is_on_off 12 | from .playlist import (_get_playlists, delete_playlist, get_playlist, 13 | get_playlist_names, save_playlist) 14 | from .pmpermit import (approve_pmpermit, disapprove_pmpermit, 15 | is_pmpermit_approved) 16 | from .queue import (add_active_chat, get_active_chats, is_active_chat, 17 | is_music_playing, music_off, music_on, remove_active_chat) 18 | from .start import _get_start, get_start, get_start_names, save_start 19 | from .sudo import add_sudo, get_sudoers, remove_sudo 20 | from .theme import _get_theme, get_theme, save_theme 21 | from .videocalls import (add_active_video_chat, get_active_video_chats, 22 | get_video_limit, is_active_video_chat, 23 | remove_active_video_chat, set_video_limit) 24 | -------------------------------------------------------------------------------- /Ayiin/Database/videocalls.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | videodb = db.Ayiinvideocalls 6 | 7 | 8 | ## limit 9 | 10 | 11 | async def get_video_limit(chat_id: int) -> str: 12 | limit = await videodb.find_one({"chat_id": chat_id}) 13 | if not limit: 14 | return "" 15 | return limit["limit"] 16 | 17 | 18 | async def set_video_limit(chat_id: int, limit: str): 19 | return await videodb.update_one( 20 | {"chat_id": chat_id}, {"$set": {"limit": limit}}, upsert=True 21 | ) 22 | 23 | 24 | ## Queue Chats Video 25 | 26 | 27 | async def get_active_video_chats() -> list: 28 | chats = videodb.find({"chat_id": {"$lt": 0}}) 29 | if not chats: 30 | return [] 31 | chats_list = [] 32 | for chat in await chats.to_list(length=1000000000): 33 | chats_list.append(chat) 34 | return chats_list 35 | 36 | 37 | async def is_active_video_chat(chat_id: int) -> bool: 38 | chat = await videodb.find_one({"chat_id": chat_id}) 39 | if not chat: 40 | return False 41 | return True 42 | 43 | 44 | async def add_active_video_chat(chat_id: int): 45 | is_served = await is_active_video_chat(chat_id) 46 | if is_served: 47 | return 48 | return await videodb.insert_one({"chat_id": chat_id}) 49 | 50 | 51 | async def remove_active_video_chat(chat_id: int): 52 | is_served = await is_active_video_chat(chat_id) 53 | if not is_served: 54 | return 55 | return await videodb.delete_one({"chat_id": chat_id}) 56 | -------------------------------------------------------------------------------- /Ayiin/Decorators/permission.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import BOT_ID, app 4 | 5 | 6 | def PermissionCheck(mystic): 7 | async def wrapper(_, message): 8 | if message.chat.type == "private": 9 | return await mystic(_, message) 10 | a = await app.get_chat_member(message.chat.id, BOT_ID) 11 | if a.status != "administrator": 12 | return await message.reply_text( 13 | "I need to be admin with some permissions:\n" 14 | + "\n- **can_manage_voice_chats:** To manage voice chats" 15 | + "\n- **can_delete_messages:** To delete Bot's Searched Waste" 16 | + "\n- **can_invite_users**: For inviting assistant to chat." 17 | ) 18 | if not a.can_manage_voice_chats: 19 | await message.reply_text( 20 | "I don't have the required permission to perform this action." 21 | + "\n**Permission:** __MANAGE VOICE CHATS__" 22 | ) 23 | return 24 | if not a.can_delete_messages: 25 | await message.reply_text( 26 | "I don't have the required permission to perform this action." 27 | + "\n**Permission:** __DELETE MESSAGES__" 28 | ) 29 | return 30 | if not a.can_invite_users: 31 | await message.reply_text( 32 | "I don't have the required permission to perform this action." 33 | + "\n**Permission:** __INVITE USERS VIA LINK__" 34 | ) 35 | return 36 | return await mystic(_, message) 37 | 38 | return wrapper 39 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Speedtest.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import speedtest 4 | import wget 5 | from pyrogram import Client, filters 6 | from pyrogram.types import Message 7 | 8 | from Ayiin import BOT_ID, SUDOERS, app 9 | from Ayiin.Utilities.formatters import bytes 10 | 11 | __MODULE__ = "Speedtest" 12 | __HELP__ = """ 13 | 14 | /speedtest 15 | - Check Server Latency and Speed. 16 | 17 | """ 18 | 19 | 20 | @app.on_message(filters.command("speedtest") & ~filters.edited) 21 | async def statsguwid(_, message): 22 | m = await message.reply_text("Running Speed test") 23 | try: 24 | test = speedtest.Speedtest() 25 | test.get_best_server() 26 | m = await m.edit("Running Download SpeedTest") 27 | test.download() 28 | m = await m.edit("Running Upload SpeedTest") 29 | test.upload() 30 | test.results.share() 31 | result = test.results.dict() 32 | except Exception as e: 33 | return await m.edit(e) 34 | m = await m.edit("Sharing SpeedTest Results") 35 | path = wget.download(result["share"]) 36 | 37 | output = f"""**Speedtest Results** 38 | 39 | **Client:** 40 | **__ISP:__** {result['client']['isp']} 41 | **__Country:__** {result['client']['country']} 42 | 43 | **Server:** 44 | **__Name:__** {result['server']['name']} 45 | **__Country:__** {result['server']['country']}, {result['server']['cc']} 46 | **__Sponsor:__** {result['server']['sponsor']} 47 | **__Latency:__** {result['server']['latency']} 48 | **__Ping:__** {result['ping']}""" 49 | msg = await app.send_photo( 50 | chat_id=message.chat.id, photo=path, caption=output 51 | ) 52 | os.remove(path) 53 | await m.delete() 54 | -------------------------------------------------------------------------------- /Ayiin/Inline/song.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | 5 | def song_markup(videoid, duration, user_id, query, query_type): 6 | buttons = [ 7 | [ 8 | InlineKeyboardButton( 9 | text="❮", 10 | callback_data=f"song_right B|{query_type}|{query}|{user_id}", 11 | ), 12 | InlineKeyboardButton( 13 | text="𝙳𝙾𝚆𝙽𝙻𝙾𝙰𝙳", 14 | callback_data=f"qwertyuiopasdfghjkl {videoid}|{user_id}", 15 | ), 16 | InlineKeyboardButton( 17 | text="❯", 18 | callback_data=f"song_right F|{query_type}|{query}|{user_id}", 19 | ), 20 | ], 21 | [ 22 | InlineKeyboardButton( 23 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", 24 | callback_data=f"forceclose {query}|{user_id}", 25 | ) 26 | ], 27 | ] 28 | return buttons 29 | 30 | 31 | def song_download_markup(videoid, user_id): 32 | buttons = [ 33 | [ 34 | InlineKeyboardButton( 35 | text="☟︎︎︎ 𝙶𝙴𝚃 𝙰𝚄𝙳𝙸𝙾", 36 | callback_data=f"gets audio|{videoid}|{user_id}", 37 | ), 38 | InlineKeyboardButton( 39 | text="☟︎︎︎ 𝙶𝙴𝚃 𝚅𝙸𝙳𝙴𝙾", 40 | callback_data=f"gets video|{videoid}|{user_id}", 41 | ), 42 | ], 43 | [ 44 | InlineKeyboardButton( 45 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", 46 | callback_data=f"forceclose {videoid}|{user_id}", 47 | ) 48 | ], 49 | ] 50 | return buttons 51 | -------------------------------------------------------------------------------- /Ayiin/Database/queue.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | pytgdb = db.pytg 6 | admindb = db.admin 7 | 8 | 9 | ## Queue Chats Audio 10 | 11 | 12 | async def get_active_chats() -> list: 13 | chats = pytgdb.find({"chat_id": {"$lt": 0}}) 14 | if not chats: 15 | return [] 16 | chats_list = [] 17 | for chat in await chats.to_list(length=1000000000): 18 | chats_list.append(chat) 19 | return chats_list 20 | 21 | 22 | async def is_active_chat(chat_id: int) -> bool: 23 | chat = await pytgdb.find_one({"chat_id": chat_id}) 24 | if not chat: 25 | return False 26 | return True 27 | 28 | 29 | async def add_active_chat(chat_id: int): 30 | is_served = await is_active_chat(chat_id) 31 | if is_served: 32 | return 33 | return await pytgdb.insert_one({"chat_id": chat_id}) 34 | 35 | 36 | async def remove_active_chat(chat_id: int): 37 | is_served = await is_active_chat(chat_id) 38 | if not is_served: 39 | return 40 | return await pytgdb.delete_one({"chat_id": chat_id}) 41 | 42 | 43 | ## Music Playing or Paused 44 | 45 | 46 | async def is_music_playing(chat_id: int) -> bool: 47 | chat = await admindb.find_one({"chat_id_toggle": chat_id}) 48 | if not chat: 49 | return True 50 | return False 51 | 52 | 53 | async def music_on(chat_id: int): 54 | is_on = await is_music_playing(chat_id) 55 | if is_on: 56 | return 57 | return await admindb.delete_one({"chat_id_toggle": chat_id}) 58 | 59 | 60 | async def music_off(chat_id: int): 61 | is_on = await is_music_playing(chat_id) 62 | if not is_on: 63 | return 64 | return await admindb.insert_one({"chat_id_toggle": chat_id}) 65 | -------------------------------------------------------------------------------- /Ayiin/Core/Clients/cli.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from config import (API_HASH, API_ID, BOT_TOKEN, LOG_SESSION, STRING1, STRING2, 4 | STRING3, STRING4, STRING5) 5 | 6 | app = Client( 7 | "AyiinMusic", 8 | API_ID, 9 | API_HASH, 10 | bot_token=BOT_TOKEN, 11 | ) 12 | 13 | 14 | if not STRING1: 15 | ASS_CLI_1 = None 16 | else: 17 | ASS_CLI_1 = Client( 18 | api_id=API_ID, 19 | api_hash=API_HASH, 20 | session_name=STRING1, 21 | plugins=dict(root="Ayiin.Plugins.Multi-Assistant"), 22 | ) 23 | 24 | 25 | if not STRING2: 26 | ASS_CLI_2 = None 27 | else: 28 | ASS_CLI_2 = Client( 29 | api_id=API_ID, 30 | api_hash=API_HASH, 31 | session_name=STRING2, 32 | plugins=dict(root="Ayiin.Plugins.Multi-Assistant"), 33 | ) 34 | 35 | 36 | if not STRING3: 37 | ASS_CLI_3 = None 38 | else: 39 | ASS_CLI_3 = Client( 40 | api_id=API_ID, 41 | api_hash=API_HASH, 42 | session_name=STRING3, 43 | plugins=dict(root="Ayiin.Plugins.Multi-Assistant"), 44 | ) 45 | 46 | 47 | if not STRING4: 48 | ASS_CLI_4 = None 49 | else: 50 | ASS_CLI_4 = Client( 51 | api_id=API_ID, 52 | api_hash=API_HASH, 53 | session_name=STRING4, 54 | plugins=dict(root="Ayiin.Plugins.Multi-Assistant"), 55 | ) 56 | 57 | 58 | if not STRING5: 59 | ASS_CLI_5 = None 60 | else: 61 | ASS_CLI_5 = Client( 62 | api_id=API_ID, 63 | api_hash=API_HASH, 64 | session_name=STRING5, 65 | plugins=dict(root="Ayiin.Plugins.Multi-Assistant"), 66 | ) 67 | 68 | 69 | if not LOG_SESSION: 70 | LOG_CLIENT = None 71 | else: 72 | LOG_CLIENT = Client(LOG_SESSION, API_ID, API_HASH) 73 | -------------------------------------------------------------------------------- /Ayiin/Utilities/tasks.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from asyncio import Lock, create_task 3 | from time import time 4 | 5 | from pyrogram import filters 6 | from pyrogram.types import Message 7 | 8 | tasks = {} 9 | TASKS_LOCK = Lock() 10 | arrow = lambda x: (x.text if x else "") + "\n`→`" 11 | 12 | import shlex 13 | from typing import Tuple 14 | 15 | 16 | async def install_requirements(cmd: str) -> Tuple[str, str, int, int]: 17 | args = shlex.split(cmd) 18 | process = await asyncio.create_subprocess_exec( 19 | *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE 20 | ) 21 | stdout, stderr = await process.communicate() 22 | return ( 23 | stdout.decode("utf-8", "replace").strip(), 24 | stderr.decode("utf-8", "replace").strip(), 25 | process.returncode, 26 | process.pid, 27 | ) 28 | 29 | 30 | def all_tasks(): 31 | return tasks 32 | 33 | 34 | async def add_task( 35 | taskFunc, 36 | task_name, 37 | *args, 38 | **kwargs, 39 | ): 40 | 41 | async with TASKS_LOCK: 42 | global tasks 43 | 44 | task_id = (list(tasks.keys())[-1] + 1) if tasks else 0 45 | 46 | task = create_task( 47 | taskFunc(*args, **kwargs), 48 | name=task_name, 49 | ) 50 | tasks[task_id] = task, int(time()) 51 | return task, task_id 52 | 53 | 54 | async def rm_task(task_id=None): 55 | global tasks 56 | 57 | async with TASKS_LOCK: 58 | for key, value in list(tasks.items()): 59 | if value[0].done() or value[0].cancelled(): 60 | del tasks[key] 61 | 62 | if (task_id is not None) and (task_id in tasks): 63 | task = tasks[task_id][0] 64 | 65 | if not task.done(): 66 | task.cancel() 67 | 68 | del tasks[task_id] 69 | -------------------------------------------------------------------------------- /Ayiin/Core/PyTgCalls/Tgdownloader.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | from datetime import datetime, timedelta 4 | 5 | from pyrogram.errors.exceptions import FloodWait 6 | 7 | from Ayiin import MUSIC_BOT_NAME, app, db_mem 8 | from Ayiin.Utilities.formatters import bytes 9 | from Ayiin.Utilities.ping import get_readable_time 10 | 11 | 12 | async def telegram_download(message, mystic): 13 | ### Download Media From Telegram by AyiinMusic 14 | left_time = {} 15 | speed_counter = {} 16 | 17 | async def progress(current, total): 18 | if current == total: 19 | return 20 | current_time = time.time() 21 | start_time = speed_counter.get(message.message_id) 22 | check_time = current_time - start_time 23 | if datetime.now() > left_time.get(message.message_id): 24 | percentage = current * 100 / total 25 | percentage = round(percentage, 2) 26 | speed = current / check_time 27 | eta = get_readable_time(int((total - current) / speed)) 28 | if not eta: 29 | eta = "0 sec" 30 | total_size = bytes(total) 31 | completed_size = bytes(current) 32 | speed = bytes(speed) 33 | text = f""" 34 | **{MUSIC_BOT_NAME} Telegram Media Downloader** 35 | 36 | **Total FileSize:** {total_size} 37 | **Completed:** {completed_size} 38 | **Percentage:** {percentage}% 39 | 40 | **Speed:** {speed}/s 41 | **ETA:** {eta}""" 42 | try: 43 | await mystic.edit(text) 44 | except FloodWait as e: 45 | await asyncio.sleep(e.x) 46 | left_time[message.message_id] = datetime.now() + timedelta( 47 | seconds=5 48 | ) 49 | 50 | speed_counter[message.message_id] = time.time() 51 | left_time[message.message_id] = datetime.now() 52 | X = await app.download_media(message.reply_to_message, progress=progress) 53 | return X 54 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Theme.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from pyrogram import Client, filters 4 | 5 | from Ayiin import BOT_USERNAME, MUSIC_BOT_NAME, app, db 6 | from Ayiin.Database import _get_theme, get_theme, save_theme 7 | from Ayiin.Decorators.permission import PermissionCheck 8 | 9 | themes = [ 10 | "blue", 11 | "black", 12 | "red", 13 | "green", 14 | "grey", 15 | "orange", 16 | "pink", 17 | "yellow", 18 | "Random", 19 | ] 20 | 21 | themes2 = [ 22 | "blue", 23 | "black", 24 | "red", 25 | "green", 26 | "grey", 27 | "orange", 28 | "pink", 29 | "yellow", 30 | ] 31 | 32 | __MODULE__ = "Theme" 33 | __HELP__ = """ 34 | 35 | 36 | /settheme 37 | - Set a theme for thumbnails. 38 | 39 | /theme 40 | - Check Theme for your chat. 41 | """ 42 | 43 | 44 | @app.on_message( 45 | filters.command(["settheme", f"settheme@{BOT_USERNAME}"]) & filters.group 46 | ) 47 | async def settheme(_, message): 48 | usage = f"This isn't a theme.\n\nSelect from them\n{' | '.join(themes)}\n\nUse 'Random' to get random choice of themes" 49 | if len(message.command) != 2: 50 | return await message.reply_text(usage) 51 | theme = message.text.split(None, 1)[1].strip() 52 | if theme not in themes: 53 | return await message.reply_text(usage) 54 | note = { 55 | "theme": theme, 56 | } 57 | await save_theme(message.chat.id, "theme", note) 58 | await message.reply_text(f"Changed thumbnail theme to {theme}") 59 | 60 | 61 | @app.on_message(filters.command("theme")) 62 | @PermissionCheck 63 | async def theme_func(_, message): 64 | await message.delete() 65 | _note = await get_theme(message.chat.id, "theme") 66 | if not _note: 67 | theme = "Random" 68 | else: 69 | theme = _note["theme"] 70 | await message.reply_text( 71 | f"**{MUSIC_BOT_NAME} Thumbnails Theme**\n\n**Current Theme:-** {theme}\n\n**Available Themes:-** {' | '.join(themes2)} \n\nUse /settheme to change theme." 72 | ) 73 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | from os import getenv 2 | 3 | from dotenv import load_dotenv 4 | 5 | load_dotenv() 6 | 7 | # VARS 8 | 9 | get_queue = {} 10 | BOT_TOKEN = getenv("BOT_TOKEN") 11 | API_ID = int(getenv("API_ID", "")) 12 | API_HASH = getenv("API_HASH") 13 | DURATION_LIMIT_MIN = int(getenv("DURATION_LIMIT", "10")) 14 | ASSISTANT_PREFIX = list(getenv("ASSISTANT_PREFIX", ".").split()) 15 | MONGO_DB_URI = getenv("MONGO_DB_URI") 16 | SUDO_USERS = list(map(int, getenv("SUDO_USERS", "").split())) 17 | OWNER_ID = list(map(int, getenv("OWNER_ID", "").split())) 18 | LOG_GROUP_ID = int(getenv("LOG_GROUP_ID", "")) 19 | MUSIC_BOT_NAME = getenv("MUSIC_BOT_NAME") 20 | HEROKU_API_KEY = getenv("HEROKU_API_KEY") 21 | HEROKU_APP_NAME = getenv("HEROKU_APP_NAME") 22 | 23 | UPSTREAM_REPO = getenv( 24 | "UPSTREAM_REPO", "https://github.com/AyiinXd/MultiAssistant" 25 | ) 26 | UPSTREAM_BRANCH = getenv("UPSTREAM_BRANCH", "master") 27 | 28 | if str(getenv("SUPPORT_CHANNEL")).strip() == "": 29 | SUPPORT_CHANNEL = None 30 | else: 31 | SUPPORT_CHANNEL = str(getenv("SUPPORT_CHANNEL")) 32 | if str(getenv("SUPPORT_GROUP")).strip() == "": 33 | SUPPORT_GROUP = None 34 | else: 35 | SUPPORT_GROUP = str(getenv("SUPPORT_GROUP")) 36 | 37 | 38 | if str(getenv("STRING_SESSION1")).strip() == "": 39 | STRING1 = str(None) 40 | else: 41 | STRING1 = str(getenv("STRING_SESSION1")) 42 | 43 | if str(getenv("STRING_SESSION2")).strip() == "": 44 | STRING2 = str(None) 45 | else: 46 | STRING2 = str(getenv("STRING_SESSION2")) 47 | 48 | if str(getenv("STRING_SESSION3")).strip() == "": 49 | STRING3 = str(None) 50 | else: 51 | STRING3 = str(getenv("STRING_SESSION3")) 52 | 53 | if str(getenv("STRING_SESSION4")).strip() == "": 54 | STRING4 = str(None) 55 | else: 56 | STRING4 = str(getenv("STRING_SESSION4")) 57 | 58 | if str(getenv("STRING_SESSION5")).strip() == "": 59 | STRING5 = str(None) 60 | else: 61 | STRING5 = str(getenv("STRING_SESSION5")) 62 | 63 | if str(getenv("LOG_SESSION")).strip() == "": 64 | LOG_SESSION = str(None) 65 | else: 66 | LOG_SESSION = str(getenv("LOG_SESSION")) 67 | -------------------------------------------------------------------------------- /Ayiin/Utilities/thumbnails.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | from os import path 4 | 5 | import aiofiles 6 | import aiohttp 7 | from PIL import Image, ImageDraw, ImageFont 8 | 9 | 10 | def changeImageSize(maxWidth, maxHeight, image): 11 | widthRatio = maxWidth / image.size[0] 12 | heightRatio = maxHeight / image.size[1] 13 | newWidth = int(widthRatio * image.size[0]) 14 | newHeight = int(heightRatio * image.size[1]) 15 | newImage = image.resize((newWidth, newHeight)) 16 | return newImage 17 | 18 | 19 | async def gen_thumb(thumbnail, title, userid, theme, ctitle): 20 | async with aiohttp.ClientSession() as session: 21 | async with session.get(thumbnail) as resp: 22 | if resp.status == 200: 23 | f = await aiofiles.open(f"cache/thumb{userid}.jpg", mode="wb") 24 | await f.write(await resp.read()) 25 | await f.close() 26 | image1 = Image.open(f"cache/thumb{userid}.jpg") 27 | image2 = Image.open(f"Utils/{theme}.PNG") 28 | image3 = changeImageSize(1280, 720, image1) 29 | image4 = changeImageSize(1280, 720, image2) 30 | image5 = image3.convert("RGBA") 31 | image6 = image4.convert("RGBA") 32 | Image.alpha_composite(image5, image6).save(f"cache/temp{userid}.png") 33 | img = Image.open(f"cache/temp{userid}.png") 34 | draw = ImageDraw.Draw(img) 35 | font = ImageFont.truetype("Utils/finalfont.ttf", 85) 36 | font2 = ImageFont.truetype("Utils/finalfont.ttf", 60) 37 | draw.text( 38 | (20, 45), 39 | f"Playing on: {ctitle[:14]}...", 40 | fill="white", 41 | stroke_width=1, 42 | stroke_fill="white", 43 | font=font2, 44 | ) 45 | draw.text( 46 | (25, 595), 47 | f"{title[:27]}...", 48 | fill="white", 49 | stroke_width=2, 50 | stroke_fill="white", 51 | font=font, 52 | ) 53 | img.save(f"cache/final{userid}.png") 54 | os.remove(f"cache/temp{userid}.png") 55 | os.remove(f"cache/thumb{userid}.jpg") 56 | final = f"cache/final{userid}.png" 57 | return final 58 | -------------------------------------------------------------------------------- /Ayiin/Inline/others.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | from Ayiin import db_mem 5 | 6 | 7 | def others_markup(videoid, user_id): 8 | if videoid not in db_mem: 9 | db_mem[videoid] = {} 10 | db_mem[videoid]["check"] = 1 11 | buttons = [ 12 | [ 13 | InlineKeyboardButton( 14 | text="🔎 𝚂𝙴𝙰𝚁𝙲𝙷 𝙻𝚈𝚁𝙸𝙲𝚂", 15 | callback_data=f"lyrics {videoid}|{user_id}", 16 | ) 17 | ], 18 | [ 19 | InlineKeyboardButton( 20 | text="✚ 𝚈𝙾𝚄𝚁 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 21 | callback_data=f"your_playlist {videoid}|{user_id}", 22 | ), 23 | InlineKeyboardButton( 24 | text="✚ 𝙶𝚁𝙾𝚄𝙿 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 25 | callback_data=f"group_playlist {videoid}|{user_id}", 26 | ), 27 | ], 28 | [ 29 | InlineKeyboardButton( 30 | text="☟︎︎︎ 𝙳𝙾𝚆𝙽𝙻𝙾𝙰𝙳 𝙰𝚄𝙳𝙸𝙾/𝚅𝙸𝙳𝙴𝙾", 31 | callback_data=f"audio_video_download {videoid}|{user_id}", 32 | ) 33 | ], 34 | [ 35 | InlineKeyboardButton( 36 | text="❮ 𝙶𝙾 𝙱𝙰𝙲𝙺", 37 | callback_data=f"pr_go_back_timer {videoid}|{user_id}", 38 | ), 39 | InlineKeyboardButton( 40 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟", 41 | callback_data=f"close", 42 | ), 43 | ], 44 | ] 45 | return buttons 46 | 47 | 48 | def download_markup(videoid, user_id): 49 | buttons = [ 50 | [ 51 | InlineKeyboardButton( 52 | text="☟︎︎︎ 𝙶𝙴𝚃 𝙰𝚄𝙳𝙸𝙾", 53 | callback_data=f"gets audio|{videoid}|{user_id}", 54 | ), 55 | InlineKeyboardButton( 56 | text="☟︎︎︎ 𝙶𝙴𝚃 𝚅𝙸𝙳𝙴𝙾", 57 | callback_data=f"gets video|{videoid}|{user_id}", 58 | ), 59 | ], 60 | [ 61 | InlineKeyboardButton( 62 | text="❮ 𝙶𝙾 𝙱𝙰𝙲𝙺", callback_data=f"goback {videoid}|{user_id}" 63 | ), 64 | InlineKeyboardButton(text="•Cʟᴏsᴇ•​", callback_data=f"close"), 65 | ], 66 | ] 67 | return buttons 68 | -------------------------------------------------------------------------------- /Ayiin/Utilities/youtube.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from youtubesearchpython import VideosSearch 4 | 5 | from Ayiin.Utilities.changers import time_to_seconds 6 | 7 | 8 | def get_yt_info_id(videoid): 9 | url = f"https://www.youtube.com/watch?v={videoid}" 10 | results = VideosSearch(url, limit=1) 11 | for result in results.result()["result"]: 12 | title = result["title"] 13 | duration_min = result["duration"] 14 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 15 | if str(duration_min) == "None": 16 | duration_sec = 0 17 | else: 18 | duration_sec = int(time_to_seconds(duration_min)) 19 | return title, duration_min, duration_sec, thumbnail 20 | 21 | 22 | def get_yt_info_query(query: str): 23 | results = VideosSearch(query, limit=1) 24 | for result in results.result()["result"]: 25 | title = result["title"] 26 | duration_min = result["duration"] 27 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 28 | videoid = result["id"] 29 | if str(duration_min) == "None": 30 | duration_sec = 0 31 | else: 32 | duration_sec = int(time_to_seconds(duration_min)) 33 | return title, duration_min, duration_sec, thumbnail, videoid 34 | 35 | 36 | def get_yt_info_query_slider(query: str, query_type: int): 37 | a = VideosSearch(query, limit=10) 38 | result = (a.result()).get("result") 39 | title = result[query_type]["title"] 40 | duration_min = result[query_type]["duration"] 41 | videoid = result[query_type]["id"] 42 | thumbnail = result[query_type]["thumbnails"][0]["url"].split("?")[0] 43 | if str(duration_min) == "None": 44 | duration_sec = 0 45 | else: 46 | duration_sec = int(time_to_seconds(duration_min)) 47 | return title, duration_min, duration_sec, thumbnail, videoid 48 | 49 | 50 | async def get_m3u8(videoid): 51 | link = f"https://www.youtube.com/watch?v={videoid}" 52 | proc = await asyncio.create_subprocess_exec( 53 | "yt-dlp", 54 | "-g", 55 | "-f", 56 | "best[height<=?720][width<=?1280]", 57 | f"{link}", 58 | stdout=asyncio.subprocess.PIPE, 59 | stderr=asyncio.subprocess.PIPE, 60 | ) 61 | stdout, stderr = await proc.communicate() 62 | if stdout: 63 | return 1, stdout.decode().split("\n")[0] 64 | else: 65 | return 0, stderr.decode() 66 | -------------------------------------------------------------------------------- /Ayiin/Decorators/checker.py: -------------------------------------------------------------------------------- 1 | from Ayiin import BOT_USERNAME, LOG_GROUP_ID, app 2 | from Ayiin.Database import blacklisted_chats, is_gbanned_user, is_on_off 3 | 4 | 5 | def checker(mystic): 6 | async def wrapper(_, message): 7 | if message.sender_chat: 8 | return await message.reply_text( 9 | "You're an __Anonymous Admin__ in this Chat Group!\nRevert back to User Account From Admin Rights." 10 | ) 11 | blacklisted_chats_list = await blacklisted_chats() 12 | if message.chat.id in blacklisted_chats_list: 13 | await message.reply_text( 14 | f"**Blacklisted Chat**\n\nYour chat has been blacklisted by Sudo Users.Ask any __SUDO USER__ to whitelist.\nCheck Sudo Users List [From Here](https://t.me/{BOT_USERNAME}?start=sudolist)" 15 | ) 16 | return await app.leave_chat(message.chat.id) 17 | if await is_on_off(1): 18 | if int(message.chat.id) != int(LOG_GROUP_ID): 19 | return await message.reply_text( 20 | f"Bot is under Maintenance. Sorry for the inconvenience!" 21 | ) 22 | if await is_gbanned_user(message.from_user.id): 23 | return await message.reply_text( 24 | f"**Gbanned User**\n\nYou're gbanned from using Bot.Ask any __SUDO USER__ to ungban.\nCheck Sudo Users List [From Here](https://t.me/{BOT_USERNAME}?start=sudolist)" 25 | ) 26 | return await mystic(_, message) 27 | 28 | return wrapper 29 | 30 | 31 | def checkerCB(mystic): 32 | async def wrapper(_, CallbackQuery): 33 | blacklisted_chats_list = await blacklisted_chats() 34 | if CallbackQuery.message.chat.id in blacklisted_chats_list: 35 | return await CallbackQuery.answer( 36 | "Blacklisted Chat", show_alert=True 37 | ) 38 | if await is_on_off(1): 39 | if int(CallbackQuery.message.chat.id) != int(LOG_GROUP_ID): 40 | return await CallbackQuery.answer( 41 | "Bot is under Maintenance. Sorry for the inconvenience!", 42 | show_alert=True, 43 | ) 44 | if await is_gbanned_user(CallbackQuery.from_user.id): 45 | return await CallbackQuery.answer( 46 | "You're Gbanned", show_alert=True 47 | ) 48 | return await mystic(_, CallbackQuery) 49 | 50 | return wrapper 51 | -------------------------------------------------------------------------------- /Ayiin/Inline/videocalls.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | 5 | def choose_markup(videoid, duration, user_id): 6 | buttons = [ 7 | [ 8 | InlineKeyboardButton( 9 | text="⍟ 𝙼𝚄𝚂𝙸𝙲 ⍟", 10 | callback_data=f"MusicStream {videoid}|{duration}|{user_id}", 11 | ), 12 | InlineKeyboardButton( 13 | text="⍟ 𝚅𝙸𝙳𝙴𝙾 ⍟", 14 | callback_data=f"Choose {videoid}|{duration}|{user_id}", 15 | ), 16 | ], 17 | [ 18 | InlineKeyboardButton( 19 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟", 20 | callback_data=f"forceclose {videoid}|{user_id}", 21 | ) 22 | ], 23 | ] 24 | return buttons 25 | 26 | 27 | def livestream_markup(quality, videoid, duration, user_id): 28 | buttons = [ 29 | [ 30 | InlineKeyboardButton( 31 | text="⍟ 𝙻𝙸𝚅𝙴 ⍟", 32 | callback_data=f"LiveStream {quality}|{videoid}|{duration}|{user_id}", 33 | ), 34 | InlineKeyboardButton( 35 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟", 36 | callback_data=f"forceclose {videoid}|{user_id}", 37 | ), 38 | ], 39 | ] 40 | return buttons 41 | 42 | 43 | def stream_quality_markup(videoid, duration, user_id): 44 | buttons = [ 45 | [ 46 | InlineKeyboardButton( 47 | text="📽 360P", 48 | callback_data=f"VideoStream 360|{videoid}|{duration}|{user_id}", 49 | ), 50 | InlineKeyboardButton( 51 | text="📽 720P", 52 | callback_data=f"VideoStream 720|{videoid}|{duration}|{user_id}", 53 | ), 54 | InlineKeyboardButton( 55 | text="📽 480P", 56 | callback_data=f"VideoStream 480|{videoid}|{duration}|{user_id}", 57 | ), 58 | ], 59 | [ 60 | InlineKeyboardButton( 61 | text="❮ 𝙶𝙾 𝙱𝙰𝙲𝙺​", 62 | callback_data=f"gback_list_chose_stream {videoid}|{duration}|{user_id}", 63 | ), 64 | InlineKeyboardButton( 65 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟", 66 | callback_data=f"forceclose {videoid}|{user_id}", 67 | ), 68 | ], 69 | ] 70 | return buttons 71 | -------------------------------------------------------------------------------- /Ayiin/Database/auth.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | authdb = db.adminauth 6 | 7 | 8 | async def is_nonadmin_chat(user_id: int) -> bool: 9 | user = await authdb.find_one({"user_id": user_id}) 10 | if not user: 11 | return False 12 | return True 13 | 14 | 15 | async def add_nonadmin_chat(user_id: int): 16 | is_gbanned = await is_nonadmin_chat(user_id) 17 | if is_gbanned: 18 | return 19 | return await authdb.insert_one({"user_id": user_id}) 20 | 21 | 22 | async def remove_nonadmin_chat(user_id: int): 23 | is_gbanned = await is_nonadmin_chat(user_id) 24 | if not is_gbanned: 25 | return 26 | return await authdb.delete_one({"user_id": user_id}) 27 | 28 | 29 | ## Save Auth User 30 | 31 | authuserdb = db.authuser 32 | 33 | 34 | async def get_authuser_count() -> dict: 35 | chats = authuserdb.find({"chat_id": {"$lt": 0}}) 36 | if not chats: 37 | return {} 38 | chats_count = 0 39 | notes_count = 0 40 | for chat in await chats.to_list(length=1000000000): 41 | notes_name = await get_authuser_names(chat["chat_id"]) 42 | notes_count += len(notes_name) 43 | chats_count += 1 44 | return {"chats_count": chats_count, "notes_count": notes_count} 45 | 46 | 47 | async def _get_authusers(chat_id: int) -> Dict[str, int]: 48 | _notes = await authuserdb.find_one({"chat_id": chat_id}) 49 | if not _notes: 50 | return {} 51 | return _notes["notes"] 52 | 53 | 54 | async def get_authuser_names(chat_id: int) -> List[str]: 55 | _notes = [] 56 | for note in await _get_authusers(chat_id): 57 | _notes.append(note) 58 | return _notes 59 | 60 | 61 | async def get_authuser(chat_id: int, name: str) -> Union[bool, dict]: 62 | name = name 63 | _notes = await _get_authusers(chat_id) 64 | if name in _notes: 65 | return _notes[name] 66 | else: 67 | return False 68 | 69 | 70 | async def save_authuser(chat_id: int, name: str, note: dict): 71 | name = name 72 | _notes = await _get_authusers(chat_id) 73 | _notes[name] = note 74 | 75 | await authuserdb.update_one( 76 | {"chat_id": chat_id}, {"$set": {"notes": _notes}}, upsert=True 77 | ) 78 | 79 | 80 | async def delete_authuser(chat_id: int, name: str) -> bool: 81 | notesd = await _get_authusers(chat_id) 82 | name = name 83 | if name in notesd: 84 | del notesd[name] 85 | await authuserdb.update_one( 86 | {"chat_id": chat_id}, {"$set": {"notes": notesd}}, upsert=True 87 | ) 88 | return True 89 | return False 90 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Blacklist.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from pyrogram.types import Message 3 | 4 | from Ayiin import SUDOERS, app 5 | from Ayiin.Database import blacklist_chat, blacklisted_chats, whitelist_chat 6 | 7 | __MODULE__ = "Blacklist" 8 | __HELP__ = """ 9 | 10 | 11 | /blacklistedchat 12 | - Check Blacklisted Chats of Bot. 13 | 14 | 15 | **Note:** 16 | Only for Sudo Users. 17 | 18 | 19 | /blacklistchat [CHAT_ID] 20 | - Blacklist any chat from using Music Bot 21 | 22 | 23 | /whitelistchat [CHAT_ID] 24 | - Whitelist any blacklisted chat from using Music Bot 25 | 26 | """ 27 | 28 | 29 | @app.on_message(filters.command("blacklistchat") & filters.user(SUDOERS)) 30 | async def blacklist_chat_func(_, message: Message): 31 | if len(message.command) != 2: 32 | return await message.reply_text( 33 | "**Usage:**\n/blacklistchat [CHAT_ID]" 34 | ) 35 | chat_id = int(message.text.strip().split()[1]) 36 | if chat_id in await blacklisted_chats(): 37 | return await message.reply_text("Chat is already blacklisted.") 38 | blacklisted = await blacklist_chat(chat_id) 39 | if blacklisted: 40 | return await message.reply_text( 41 | "Chat has been successfully blacklisted" 42 | ) 43 | await message.reply_text("Something wrong happened, check logs.") 44 | 45 | 46 | @app.on_message(filters.command("whitelistchat") & filters.user(SUDOERS)) 47 | async def whitelist_chat_func(_, message: Message): 48 | if len(message.command) != 2: 49 | return await message.reply_text( 50 | "**Usage:**\n/whitelistchat [CHAT_ID]" 51 | ) 52 | chat_id = int(message.text.strip().split()[1]) 53 | if chat_id not in await blacklisted_chats(): 54 | return await message.reply_text("Chat is already whitelisted.") 55 | whitelisted = await whitelist_chat(chat_id) 56 | if whitelisted: 57 | return await message.reply_text( 58 | "Chat has been successfully whitelisted" 59 | ) 60 | await message.reply_text("Something wrong happened, check logs.") 61 | 62 | 63 | @app.on_message(filters.command("blacklistedchat")) 64 | async def blacklisted_chats_func(_, message: Message): 65 | text = "**Blacklisted Chats:**\n\n" 66 | j = 0 67 | for count, chat_id in enumerate(await blacklisted_chats(), 1): 68 | try: 69 | title = (await app.get_chat(chat_id)).title 70 | except Exception: 71 | title = "Private" 72 | j = 1 73 | text += f"**{count}. {title}** [`{chat_id}`]\n" 74 | if j == 0: 75 | await message.reply_text("No Blacklisted Chats") 76 | else: 77 | await message.reply_text(text) 78 | -------------------------------------------------------------------------------- /Ayiin/Utilities/inline.py: -------------------------------------------------------------------------------- 1 | from math import ceil 2 | 3 | from pyrogram.types import InlineKeyboardButton 4 | 5 | from Ayiin import MOD_LOAD, MOD_NOLOAD 6 | 7 | 8 | class EqInlineKeyboardButton(InlineKeyboardButton): 9 | def __eq__(self, other): 10 | return self.text == other.text 11 | 12 | def __lt__(self, other): 13 | return self.text < other.text 14 | 15 | def __gt__(self, other): 16 | return self.text > other.text 17 | 18 | 19 | def paginate_modules(page_n, module_dict, prefix, chat=None): 20 | if not chat: 21 | modules = sorted( 22 | [ 23 | EqInlineKeyboardButton( 24 | x.__MODULE__, 25 | callback_data="{}_module({})".format( 26 | prefix, x.__MODULE__.lower() 27 | ), 28 | ) 29 | for x in module_dict.values() 30 | ] 31 | ) 32 | else: 33 | modules = sorted( 34 | [ 35 | EqInlineKeyboardButton( 36 | x.__MODULE__, 37 | callback_data="{}_module({},{})".format( 38 | prefix, chat, x.__MODULE__.lower() 39 | ), 40 | ) 41 | for x in module_dict.values() 42 | ] 43 | ) 44 | 45 | pairs = list(zip(modules[::3], modules[1::3], modules[2::3])) 46 | i = 0 47 | for m in pairs: 48 | for _ in m: 49 | i += 1 50 | if len(modules) - i == 1: 51 | pairs.append((modules[-1],)) 52 | elif len(modules) - i == 2: 53 | pairs.append( 54 | ( 55 | modules[-2], 56 | modules[-1], 57 | ) 58 | ) 59 | 60 | COLUMN_SIZE = 3 61 | 62 | max_num_pages = ceil(len(pairs) / COLUMN_SIZE) 63 | modulo_page = page_n % max_num_pages 64 | 65 | # can only have a certain amount of buttons side by side 66 | if len(pairs) > COLUMN_SIZE: 67 | pairs = pairs[ 68 | modulo_page * COLUMN_SIZE : COLUMN_SIZE * (modulo_page + 1) 69 | ] + [ 70 | ( 71 | EqInlineKeyboardButton( 72 | "❮", 73 | callback_data="{}_prev({})".format(prefix, modulo_page), 74 | ), 75 | EqInlineKeyboardButton( 76 | "Close", 77 | callback_data="close", 78 | ), 79 | EqInlineKeyboardButton( 80 | "❯", 81 | callback_data="{}_next({})".format(prefix, modulo_page), 82 | ), 83 | ) 84 | ] 85 | 86 | return pairs 87 | 88 | 89 | def is_module_loaded(name): 90 | return (not MOD_LOAD or name in MOD_LOAD) and name not in MOD_NOLOAD 91 | -------------------------------------------------------------------------------- /Ayiin/Utilities/chat.py: -------------------------------------------------------------------------------- 1 | async def specialfont_to_normal(ctitle): 2 | string = ctitle 3 | font1 = list("𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ") 4 | font2 = list("𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅") 5 | font3 = list("𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩") 6 | font4 = list("𝒜𝐵𝒞𝒟𝐸𝐹𝒢𝐻𝐼𝒥𝒦𝐿𝑀𝒩𝒪𝒫𝒬𝑅𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵") 7 | font5 = list("𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ") 8 | font6 = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ") 9 | font26 = list("𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙") 10 | font27 = list("𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭") 11 | font28 = list("𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡") 12 | font29 = list("𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕") 13 | font30 = list("𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉") 14 | font1L = list("𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷") 15 | font2L = list("𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟") 16 | font3L = list("𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃") 17 | font4L = list("𝒶𝒷𝒸𝒹𝑒𝒻𝑔𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝑜𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏") 18 | font5L = list("𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫") 19 | font6L = list("abcdefghijklmnopqrstuvwxyz") 20 | font27L = list("𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳") 21 | font28L = list("𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇") 22 | font29L = list("𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻") 23 | font30L = list("𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯") 24 | font31L = list("𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣") 25 | normal = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ") 26 | normalL = list("abcdefghijklmnopqrstuvwxyz") 27 | cout = 0 28 | for XCB in font1: 29 | string = string.replace(font1[cout], normal[cout]) 30 | string = string.replace(font2[cout], normal[cout]) 31 | string = string.replace(font3[cout], normal[cout]) 32 | string = string.replace(font4[cout], normal[cout]) 33 | string = string.replace(font5[cout], normal[cout]) 34 | string = string.replace(font6[cout], normal[cout]) 35 | string = string.replace(font26[cout], normal[cout]) 36 | string = string.replace(font27[cout], normal[cout]) 37 | string = string.replace(font28[cout], normal[cout]) 38 | string = string.replace(font29[cout], normal[cout]) 39 | string = string.replace(font30[cout], normal[cout]) 40 | string = string.replace(font1L[cout], normalL[cout]) 41 | string = string.replace(font2L[cout], normalL[cout]) 42 | string = string.replace(font3L[cout], normalL[cout]) 43 | string = string.replace(font4L[cout], normalL[cout]) 44 | string = string.replace(font5L[cout], normalL[cout]) 45 | string = string.replace(font6L[cout], normalL[cout]) 46 | string = string.replace(font27L[cout], normalL[cout]) 47 | string = string.replace(font28L[cout], normalL[cout]) 48 | string = string.replace(font29L[cout], normalL[cout]) 49 | string = string.replace(font30L[cout], normalL[cout]) 50 | string = string.replace(font31L[cout], normalL[cout]) 51 | cout += 1 52 | return string 53 | -------------------------------------------------------------------------------- /Ayiin/Database/playlist.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import db 4 | 5 | playlistdb_lofi = db.playlistlofi 6 | playlistdb_rock = db.playlistrock 7 | playlistdb_sad = db.playlistsad 8 | playlistdb_party = db.playlistparty 9 | playlistdb_bollywood = db.playlistbollywood 10 | playlistdb_hollywood = db.playlisthollywood 11 | playlistdb_punjabi = db.playlistpunjabi 12 | playlistdb_others = db.playlistothers 13 | 14 | 15 | async def _get_playlists(chat_id: int, type: str) -> Dict[str, int]: 16 | if type == "Lofi": 17 | xd = playlistdb_lofi 18 | elif type == "Weeb": 19 | xd = playlistdb_rock 20 | elif type == "Sad": 21 | xd = playlistdb_sad 22 | elif type == "Party": 23 | xd = playlistdb_party 24 | elif type == "Bollywood": 25 | xd = playlistdb_bollywood 26 | elif type == "Hollywood": 27 | xd = playlistdb_hollywood 28 | elif type == "Punjabi": 29 | xd = playlistdb_punjabi 30 | elif type == "Others": 31 | xd = playlistdb_others 32 | _notes = await xd.find_one({"chat_id": chat_id}) 33 | if not _notes: 34 | return {} 35 | return _notes["notes"] 36 | 37 | 38 | async def get_playlist_names(chat_id: int, type: str) -> List[str]: 39 | _notes = [] 40 | for note in await _get_playlists(chat_id, type): 41 | _notes.append(note) 42 | return _notes 43 | 44 | 45 | async def get_playlist( 46 | chat_id: int, name: str, type: str 47 | ) -> Union[bool, dict]: 48 | name = name 49 | _notes = await _get_playlists(chat_id, type) 50 | if name in _notes: 51 | return _notes[name] 52 | else: 53 | return False 54 | 55 | 56 | async def save_playlist(chat_id: int, name: str, note: dict, type: str): 57 | name = name 58 | _notes = await _get_playlists(chat_id, type) 59 | _notes[name] = note 60 | if type == "Lofi": 61 | xd = playlistdb_lofi 62 | elif type == "Weeb": 63 | xd = playlistdb_rock 64 | elif type == "Sad": 65 | xd = playlistdb_sad 66 | elif type == "Party": 67 | xd = playlistdb_party 68 | elif type == "Bollywood": 69 | xd = playlistdb_bollywood 70 | elif type == "Hollywood": 71 | xd = playlistdb_hollywood 72 | elif type == "Punjabi": 73 | xd = playlistdb_punjabi 74 | elif type == "Others": 75 | xd = playlistdb_others 76 | await xd.update_one( 77 | {"chat_id": chat_id}, {"$set": {"notes": _notes}}, upsert=True 78 | ) 79 | 80 | 81 | async def delete_playlist(chat_id: int, name: str, type: str) -> bool: 82 | notesd = await _get_playlists(chat_id, type) 83 | name = name 84 | if type == "Lofi": 85 | xd = playlistdb_lofi 86 | elif type == "Weeb": 87 | xd = playlistdb_rock 88 | elif type == "Sad": 89 | xd = playlistdb_sad 90 | elif type == "Party": 91 | xd = playlistdb_party 92 | elif type == "Bollywood": 93 | xd = playlistdb_bollywood 94 | elif type == "Hollywood": 95 | xd = playlistdb_hollywood 96 | elif type == "Punjabi": 97 | xd = playlistdb_punjabi 98 | elif type == "Others": 99 | xd = playlistdb_others 100 | if name in notesd: 101 | del notesd[name] 102 | await xd.update_one( 103 | {"chat_id": chat_id}, {"$set": {"notes": notesd}}, upsert=True 104 | ) 105 | return True 106 | return False 107 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Multi-Assistant/Assistant.py: -------------------------------------------------------------------------------- 1 | from inspect import getfullargspec 2 | 3 | from pyrogram import Client, filters 4 | from pyrogram.raw.functions.messages import DeleteHistory 5 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 6 | InlineKeyboardMarkup, InlineQueryResultArticle, 7 | InlineQueryResultPhoto, InputTextMessageContent, 8 | Message) 9 | 10 | from Ayiin import (ASS_CLI_1, ASS_CLI_2, ASS_CLI_3, ASS_CLI_4, ASS_CLI_5, 11 | ASSISTANT_PREFIX, BOT_ID, BOT_USERNAME, LOG_GROUP_ID, 12 | MUSIC_BOT_NAME, SUDOERS, app) 13 | from Ayiin.Database import (approve_pmpermit, disapprove_pmpermit, is_on_off, 14 | is_pmpermit_approved) 15 | 16 | flood = {} 17 | 18 | 19 | @Client.on_message( 20 | filters.command("block", prefixes=ASSISTANT_PREFIX) 21 | & filters.user(SUDOERS) 22 | & ~filters.user("me") 23 | & ~filters.me 24 | & ~filters.via_bot 25 | ) 26 | async def block_user_func(client, message): 27 | if not message.reply_to_message: 28 | return await eor(message, text="Reply to a user's message to block.") 29 | user_id = message.reply_to_message.from_user.id 30 | await eor(message, text="Successfully blocked the user") 31 | await client.block_user(user_id) 32 | 33 | 34 | @Client.on_message( 35 | filters.command("unblock", prefixes=ASSISTANT_PREFIX) 36 | & filters.user(SUDOERS) 37 | & ~filters.user("me") 38 | & ~filters.me 39 | & ~filters.via_bot 40 | ) 41 | async def unblock_user_func(client, message): 42 | if not message.reply_to_message: 43 | return await eor( 44 | message, text="Reply to a user's message to unblock." 45 | ) 46 | user_id = message.reply_to_message.from_user.id 47 | await client.unblock_user(user_id) 48 | await eor(message, text="Successfully Unblocked the user") 49 | 50 | 51 | @Client.on_message( 52 | filters.command("pfp", prefixes=ASSISTANT_PREFIX) 53 | & filters.user(SUDOERS) 54 | & ~filters.user("me") 55 | & ~filters.me 56 | & ~filters.via_bot 57 | ) 58 | async def set_pfp(client, message): 59 | if not message.reply_to_message or not message.reply_to_message.photo: 60 | return await eor(message, text="Reply to a photo.") 61 | photo = await message.reply_to_message.download() 62 | try: 63 | await client.set_profile_photo(photo=photo) 64 | await eor(message, text="Successfully Changed PFP.") 65 | except Exception as e: 66 | await eor(message, text=e) 67 | 68 | 69 | @Client.on_message( 70 | filters.command("bio", prefixes=ASSISTANT_PREFIX) 71 | & filters.user(SUDOERS) 72 | & ~filters.user("me") 73 | & ~filters.me 74 | & ~filters.via_bot 75 | ) 76 | async def set_bio(client, message): 77 | if len(message.command) == 1: 78 | return await eor(message, text="Give some text to set as bio.") 79 | elif len(message.command) > 1: 80 | bio = message.text.split(None, 1)[1] 81 | try: 82 | await client.update_profile(bio=bio) 83 | await eor(message, text="Changed Bio.") 84 | except Exception as e: 85 | await eor(message, text=e) 86 | else: 87 | return await eor(message, text="Give some text to set as bio.") 88 | 89 | 90 | async def eor(msg: Message, **kwargs): 91 | func = ( 92 | (msg.edit_text if msg.from_user.is_self else msg.reply) 93 | if msg.from_user 94 | else msg.reply 95 | ) 96 | spec = getfullargspec(func.__wrapped__).args 97 | return await func(**{k: v for k, v in kwargs.items() if k in spec}) 98 | -------------------------------------------------------------------------------- /Ayiin/Decorators/admins.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Union 2 | 3 | from Ayiin import SUDOERS, app 4 | from Ayiin.Database import (_get_authusers, add_nonadmin_chat, delete_authuser, 5 | get_authuser, get_authuser_count, 6 | get_authuser_names, is_nonadmin_chat, 7 | remove_nonadmin_chat, save_authuser) 8 | from Ayiin.Utilities.changers import int_to_alpha 9 | 10 | 11 | def AdminRightsCheck(mystic): 12 | async def wrapper(_, message): 13 | if message.sender_chat: 14 | return await message.reply_text( 15 | "You're an __Anonymous Admin__!\nRevert back to User Account." 16 | ) 17 | is_non_admin = await is_nonadmin_chat(message.chat.id) 18 | if not is_non_admin: 19 | member = await app.get_chat_member( 20 | message.chat.id, message.from_user.id 21 | ) 22 | if not member.can_manage_voice_chats: 23 | if message.from_user.id not in SUDOERS: 24 | token = await int_to_alpha(message.from_user.id) 25 | _check = await get_authuser_names(message.chat.id) 26 | if token not in _check: 27 | return await message.reply( 28 | "You don't have the required permission to perform this action.\n\n__REQUIRES ADMIN WITH MANAGE VC RIGHTS__" 29 | ) 30 | return await mystic(_, message) 31 | 32 | return wrapper 33 | 34 | 35 | def AdminActual(mystic): 36 | async def wrapper(_, message): 37 | if message.sender_chat: 38 | return await message.reply_text( 39 | "You're an __Anonymous Admin__!\nRevert back to User Account." 40 | ) 41 | member = await app.get_chat_member( 42 | message.chat.id, message.from_user.id 43 | ) 44 | if not member.can_manage_voice_chats: 45 | return await message.reply( 46 | "You don't have the required permission to perform this action.\n\n__REQUIRES ADMIN WITH MANAGE VC RIGHTS__" 47 | ) 48 | return await mystic(_, message) 49 | 50 | return wrapper 51 | 52 | 53 | def AdminRightsCheckCB(mystic): 54 | async def wrapper(_, CallbackQuery): 55 | is_non_admin = await is_nonadmin_chat(CallbackQuery.message.chat.id) 56 | if not is_non_admin: 57 | a = await app.get_chat_member( 58 | CallbackQuery.message.chat.id, CallbackQuery.from_user.id 59 | ) 60 | if not a.can_manage_voice_chats: 61 | if CallbackQuery.from_user.id not in SUDOERS: 62 | token = await int_to_alpha(CallbackQuery.from_user.id) 63 | _check = await get_authuser_names( 64 | CallbackQuery.from_user.id 65 | ) 66 | if token not in _check: 67 | return await CallbackQuery.answer( 68 | "You don't have the required permission to perform this action.\nPermission: MANAGE VOICE CHATS", 69 | show_alert=True, 70 | ) 71 | return await mystic(_, CallbackQuery) 72 | 73 | return wrapper 74 | 75 | 76 | def ActualAdminCB(mystic): 77 | async def wrapper(_, CallbackQuery): 78 | a = await app.get_chat_member( 79 | CallbackQuery.message.chat.id, CallbackQuery.from_user.id 80 | ) 81 | if not a.can_manage_voice_chats: 82 | return await CallbackQuery.answer( 83 | "You don't have the required permission to perform this action.\nPermission: MANAGE VOICE CHATS", 84 | show_alert=True, 85 | ) 86 | return await mystic(_, CallbackQuery) 87 | 88 | return wrapper 89 | -------------------------------------------------------------------------------- /Ayiin/Core/PyTgCalls/Downloader.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | 3 | from yt_dlp import YoutubeDL 4 | 5 | from Ayiin import MUSIC_BOT_NAME 6 | 7 | ytdl = YoutubeDL( 8 | { 9 | "outtmpl": "downloads/%(id)s.%(ext)s", 10 | "format": "bestaudio/best", 11 | "geo_bypass": True, 12 | "nocheckcertificate": True, 13 | "quiet": True, 14 | "no_warnings": True, 15 | } 16 | ) 17 | 18 | 19 | def download(videoid: str, mystic, title) -> str: 20 | flex = {} 21 | url = f"https://www.youtube.com/watch?v={videoid}" 22 | 23 | def my_hook(d): 24 | if d["status"] == "downloading": 25 | percentage = d["_percent_str"] 26 | per = (str(percentage)).replace(".", "", 1).replace("%", "", 1) 27 | per = int(per) 28 | eta = d["eta"] 29 | speed = d["_speed_str"] 30 | size = d["_total_bytes_str"] 31 | bytesx = d["total_bytes"] 32 | if str(bytesx) in flex: 33 | pass 34 | else: 35 | flex[str(bytesx)] = 1 36 | if flex[str(bytesx)] == 1: 37 | flex[str(bytesx)] += 1 38 | try: 39 | if eta > 2: 40 | mystic.edit( 41 | f"**{MUSIC_BOT_NAME} Downloader**\n\n**Title:** {title[:50]}:\n**FileSize:** {size}\n\n**Downloaded:**\n**Speed:** {speed}\n**ETA:** {eta} Seconds\n\n\n{percentage} ▓▓▓▓▓▓▓▓▓▓▓▓ 100%" 42 | ) 43 | except Exception as e: 44 | pass 45 | if per > 250: 46 | if flex[str(bytesx)] == 2: 47 | flex[str(bytesx)] += 1 48 | if eta > 2: 49 | mystic.edit( 50 | f"**{MUSIC_BOT_NAME}Downloader**\n\n**Title:** {title[:50]}:\n**FileSize:** {size}\n\n**Downloaded:**\n**Speed:** {speed}\n**ETA:** {eta} Seconds\n\n\n{percentage} ███▓▓▓▓▓▓▓▓▓ 100%" 51 | ) 52 | if per > 500: 53 | if flex[str(bytesx)] == 3: 54 | flex[str(bytesx)] += 1 55 | if eta > 2: 56 | mystic.edit( 57 | f"**{MUSIC_BOT_NAME} Downloader**\n\n**Title:** {title[:50]}:\n**FileSize:** {size}\n\n**Downloaded:**\n**Speed:** {speed}\n**ETA:** {eta} Seconds\n\n\n{percentage} ██████▓▓▓▓▓▓ 100%" 58 | ) 59 | if per > 800: 60 | if flex[str(bytesx)] == 4: 61 | flex[str(bytesx)] += 1 62 | if eta > 2: 63 | mystic.edit( 64 | f"**{MUSIC_BOT_NAME} Downloader**\n\n**Title:** {title[:50]}:\n**FileSize:** {size}\n\n**Downloaded:**\n**Speed:** {speed}\n**ETA:** {eta} Seconds\n\n\n{percentage} ██████████▓▓ 100%" 65 | ) 66 | if d["status"] == "finished": 67 | try: 68 | taken = d["_elapsed_str"] 69 | except Exception as e: 70 | taken = "00:00" 71 | size = d["_total_bytes_str"] 72 | mystic.edit( 73 | f"**{MUSIC_BOT_NAME} Downloader**\n\n**Title:** {title[:50]}:\n\n100% ████████████100%\n\n**Time Taken:** {taken} Seconds\n\nConverting Audio[FFmpeg Process]" 74 | ) 75 | 76 | ydl_optssx = { 77 | "format": "bestaudio/best", 78 | "outtmpl": "downloads/%(id)s.%(ext)s", 79 | "geo_bypass": True, 80 | "nocheckcertificate": True, 81 | "quiet": True, 82 | "no_warnings": True, 83 | } 84 | try: 85 | x = YoutubeDL(ydl_optssx) 86 | x.add_progress_hook(my_hook) 87 | dloader = x.download([url]) 88 | except Exception as y_e: 89 | return print(y_e) 90 | else: 91 | dloader 92 | info = x.extract_info(url, False) 93 | xyz = path.join("downloads", f"{info['id']}.{info['ext']}") 94 | return xyz 95 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Lyrics.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | import lyricsgenius 5 | from pyrogram import Client, filters 6 | from pyrogram.types import Message 7 | from youtubesearchpython import VideosSearch 8 | 9 | from Ayiin import MUSIC_BOT_NAME, app 10 | 11 | __MODULE__ = "Lyrics" 12 | __HELP__ = """ 13 | 14 | /Lyrics [Music Name] 15 | - Searches Lyrics for the particular Music on web. 16 | 17 | **Note**: 18 | Inline button of Lyrics has some bugs. Searches only 50% results. You can use command instead if you want lyrics for any playing music. 19 | 20 | """ 21 | 22 | 23 | @app.on_callback_query(filters.regex(pattern=r"lyrics")) 24 | async def lyricssex(_, CallbackQuery): 25 | callback_data = CallbackQuery.data.strip() 26 | callback_request = callback_data.split(None, 1)[1] 27 | try: 28 | id, user_id = callback_request.split("|") 29 | except Exception as e: 30 | return await CallbackQuery.message.edit( 31 | f"Error Occured\n**Possible reason could be**:{e}" 32 | ) 33 | url = f"https://www.youtube.com/watch?v={id}" 34 | print(url) 35 | try: 36 | results = VideosSearch(url, limit=1) 37 | for result in results.result()["result"]: 38 | title = result["title"] 39 | except Exception as e: 40 | return await CallbackQuery.answer( 41 | "Sound not found. Youtube issues.", show_alert=True 42 | ) 43 | x = "OXaVabSRKQLqwpiYOn-E4Y7k3wj-TNdL5RfDPXlnXhCErbcqVvdCF-WnMR5TBctI" 44 | y = lyricsgenius.Genius(x) 45 | t = re.sub(r"[^\w]", " ", title) 46 | y.verbose = False 47 | S = y.search_song(t, get_full_info=False) 48 | if S is None: 49 | return await CallbackQuery.answer( 50 | "Lyrics not found :p", show_alert=True 51 | ) 52 | await CallbackQuery.message.delete() 53 | userid = CallbackQuery.from_user.id 54 | usr = f"[{CallbackQuery.from_user.first_name}](tg://user?id={userid})" 55 | xxx = f""" 56 | **Lyrics Search Powered By {MUSIC_BOT_NAME}** 57 | 58 | **Searched By:-** {usr} 59 | **Searched Song:-** __{title}__ 60 | 61 | **Found Lyrics For:-** __{S.title}__ 62 | **Artist:-** {S.artist} 63 | 64 | **__Lyrics:__** 65 | 66 | {S.lyrics}""" 67 | if len(xxx) > 4096: 68 | filename = "lyrics.txt" 69 | with open(filename, "w+", encoding="utf8") as out_file: 70 | out_file.write(str(xxx.strip())) 71 | await CallbackQuery.message.reply_document( 72 | document=filename, 73 | caption=f"**OUTPUT:**\n\n`Lyrics`", 74 | quote=False, 75 | ) 76 | os.remove(filename) 77 | else: 78 | await CallbackQuery.message.reply_text(xxx) 79 | 80 | 81 | @app.on_message(filters.command("lyrics")) 82 | async def lrsearch(_, message: Message): 83 | if len(message.command) < 2: 84 | return await message.reply_text("**Usage:**\n\n/lyrics [ Music Name]") 85 | m = await message.reply_text("Searching Lyrics") 86 | query = message.text.split(None, 1)[1] 87 | x = "OXaVabSRKQLqwpiYOn-E4Y7k3wj-TNdL5RfDPXlnXhCErbcqVvdCF-WnMR5TBctI" 88 | y = lyricsgenius.Genius(x) 89 | y.verbose = False 90 | S = y.search_song(query, get_full_info=False) 91 | if S is None: 92 | return await m.edit("Lyrics not found :p") 93 | xxx = f""" 94 | **Lyrics Search Powered By {MUSIC_BOT_NAME}** 95 | 96 | **Searched Song:-** __{query}__ 97 | **Found Lyrics For:-** __{S.title}__ 98 | **Artist:-** {S.artist} 99 | 100 | **__Lyrics:__** 101 | 102 | {S.lyrics}""" 103 | if len(xxx) > 4096: 104 | await m.delete() 105 | filename = "lyrics.txt" 106 | with open(filename, "w+", encoding="utf8") as out_file: 107 | out_file.write(str(xxx.strip())) 108 | await message.reply_document( 109 | document=filename, 110 | caption=f"**OUTPUT:**\n\n`Lyrics`", 111 | quote=False, 112 | ) 113 | os.remove(filename) 114 | else: 115 | await m.edit(xxx) 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

ICON

2 | 3 |

4 | A Telegram Music+video Bot written in Python using Pyrogram and Py-Tgcalls 5 |

6 |

7 | Ready-To-Use Bot • 8 | Support Channel • 9 | Support Chat 10 |

11 | 12 | # Ayiin Music Bot 13 | A Powerful Telegram Music+Video Bot by which you can stream songs, videos and even live streams in your group calls via various sources. It comes with user friendly and easy to use yet elegant features. 14 | 15 | 16 | 17 | ## TUTORIAL LINK DEPLOY 18 | ``` 19 | - Pertama fork repositori ini. 20 | - Kemudian Salin Link Fork Repo Anda. 21 | - Dan Klik Tombol Dibawah Ini. 22 | - ☟︎︎︎ ☟︎︎︎ ☟︎︎︎ ☟︎︎︎ 23 | ``` 24 | 25 | 26 | [![Deploy](https://vercel.com/button)](https://ayiin.vercel.app) 27 | 28 | 29 | > Click on buttons to expand! 30 |
31 | 🔗 Requirements 32 |
33 | 34 | - [Python3.9](https://www.python.org/downloads/release/python-390/) 35 | - [Telegram API Key](https://docs.pyrogram.org/intro/setup#api-keys) 36 | - [Telegram Bot Token](https://t.me/botfather) 37 | - [MongoDB URI](https://telegra.ph/How-To-get-Mongodb-URI-04-06) 38 | - [Pyrogram String Session](https://notreallyshikhar.gitbook.io/AyiinMusic/deployment/string-session) 39 | 40 |
41 | 42 |
43 | 🔗 String Session 44 |
45 | 46 | > You'll need a [API_ID](https://notreallyshikar.gitbook.io/AyiinMusic/vars/mandatory-vars#1.-api_id) & [API_HASH](https://notreallyshikhar.gitbook.io/AyiinMusic/vars/mandatory-vars#2.-api_hash) in order to generate pyrogram session. 47 | > Always remeber to use good API combo else your account could be deleted. 48 | 49 |

Generate Session via Repl:

50 |

51 | 52 |

Generate Session via Telegram StringGen Bot:

53 |

54 | 55 |
56 | 57 | 58 |
59 | 🔗 Deploy to VPS 60 |
61 | 62 | > Checkout [Docs](https://notreallyshikhar.gitbook.io/AyiinMusic/deployment/local-hosting-or-vps) for Detailed Explanation on VPS Deploy 63 | 64 | 65 | ```console 66 | ayiin@ayiin~ $ git clone https://github.com/AyiinXd/AyiinMusic 67 | ayiin@ayiin~ $ cd AyiinMusic 68 | ayiin@ayiin~ $ pip3 install -U -r requirements.txt 69 | ayiin@ayiin~ $ nano sample.env 70 | ayiin@ayiin~ $ cp sample.env .env 71 | ``` 72 | > Edit .env with your values and then start bot with 73 | ```console 74 | ayiin@ayiin~ $ screen -S AyiinMusic 75 | ayiin@ayiin~ $ python3 -m Ayiin 76 | ``` 77 | 78 | > Not Getting VPS Method? [Watch Tutorial](https://t.me/OfficialYukki/2275) 79 |
80 | 81 | ## Contact & Support 82 | 83 | - [Telegram Channel](https://t.me/AyiinSupport) 84 | - [Telegram Support Group](https://t.me/AyiinXdSupport) 85 | - [Contact Owner](https://t.me/AyiinXd) 86 | 87 | 88 | ## License 89 | 90 | Distributed under the [GNU General Public License v3.0 License.](https://github.com/AyiinXd/AyiinMusic/blob/main/LICENSE) See `LICENSE.md` for more information. 91 | 92 | ## Acknowledgements 93 | 94 | Special thanks to these amazing projects/people which/who help power Ayiin Music Bot: 95 | 96 | - [Pyrogram](https://github.com/pyrogram/pyrogram) 97 | - [Py-Tgcalls](https://github.com/pytgcalls/pytgcalls) 98 | - [CallsMusic Team](https://github.com/Callsmusic) 99 | - [TheHamkerCat](https://github.com/TheHamkerCat) 100 | - [Charon Baglari](https://github.com/XCBv021) 101 | - [AyiinXd](https://github.com/AyiinXd) 102 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Assistant.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from pyrogram import filters 4 | from pyrogram.raw.functions.messages import DeleteHistory 5 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 6 | InlineKeyboardMarkup, InlineQueryResultArticle, 7 | InlineQueryResultPhoto, InputTextMessageContent, 8 | Message) 9 | 10 | from Ayiin import ASSISTANT_PREFIX, SUDOERS, app, random_assistant 11 | from Ayiin.Database import get_assistant, save_assistant 12 | from Ayiin.Utilities.assistant import get_assistant_details 13 | 14 | __MODULE__ = "Assistant" 15 | __HELP__ = f""" 16 | 17 | 18 | /checkassistant 19 | - Check the alloted assistant of your chat 20 | 21 | 22 | **Note:** 23 | - Only for Sudo Users 24 | 25 | {ASSISTANT_PREFIX[0]}block [ Reply to a User Message] 26 | - Blocks the User from Assistant Account. 27 | 28 | {ASSISTANT_PREFIX[0]}unblock [ Reply to a User Message] 29 | - Unblocks the User from Assistant Account. 30 | 31 | {ASSISTANT_PREFIX[0]}approve [ Reply to a User Message] 32 | - Approves the User for DM. 33 | 34 | {ASSISTANT_PREFIX[0]}disapprove [ Reply to a User Message] 35 | - Disapproves the User for DM. 36 | 37 | {ASSISTANT_PREFIX[0]}pfp [ Reply to a Photo] 38 | - Changes Assistant account PFP. 39 | 40 | {ASSISTANT_PREFIX[0]}bio [Bio text] 41 | - Changes Bio of Assistant Account. 42 | 43 | /changeassistant [ASS NUMBER] 44 | - Change the previoius alloted assistant to new one. 45 | 46 | /setassistant [ASS NUMBER or Random] 47 | - Set a assistant account for chat. 48 | """ 49 | 50 | 51 | ass_num_list = ["1", "2", "3", "4", "5"] 52 | 53 | 54 | @app.on_message(filters.command("changeassistant") & filters.user(SUDOERS)) 55 | async def assis_change(_, message: Message): 56 | usage = f"**Usage:**\n/changeassistant [ASS_NO]\n\nSelect from them\n{' | '.join(ass_num_list)}" 57 | if len(message.command) != 2: 58 | return await message.reply_text(usage) 59 | num = message.text.split(None, 1)[1].strip() 60 | if num not in ass_num_list: 61 | return await message.reply_text(usage) 62 | ass_num = int(message.text.strip().split()[1]) 63 | _assistant = await get_assistant(message.chat.id, "assistant") 64 | if not _assistant: 65 | return await message.reply_text( 66 | "No Pre-Saved Assistant Found.\n\nYou can set Assistant Via /setassistant" 67 | ) 68 | else: 69 | ass = _assistant["saveassistant"] 70 | assis = { 71 | "saveassistant": ass_num, 72 | } 73 | await save_assistant(message.chat.id, "assistant", assis) 74 | await message.reply_text( 75 | f"**Changed Assistant**\n\nChanged Assistant Account from **{ass}** to Assistant Number **{ass_num}**" 76 | ) 77 | 78 | 79 | ass_num_list2 = ["1", "2", "3", "4", "5", "Random"] 80 | 81 | 82 | @app.on_message(filters.command("setassistant") & filters.user(SUDOERS)) 83 | async def assis_change(_, message: Message): 84 | usage = f"**Usage:**\n/setassistant [ASS_NO or Random]\n\nSelect from them\n{' | '.join(ass_num_list2)}\n\nUse 'Random' to set random Assistant" 85 | if len(message.command) != 2: 86 | return await message.reply_text(usage) 87 | query = message.text.split(None, 1)[1].strip() 88 | if query not in ass_num_list2: 89 | return await message.reply_text(usage) 90 | if str(query) == "Random": 91 | ran_ass = random.choice(random_assistant) 92 | else: 93 | ran_ass = int(message.text.strip().split()[1]) 94 | _assistant = await get_assistant(message.chat.id, "assistant") 95 | if not _assistant: 96 | await message.reply_text( 97 | f"**__Ayiin Music Bot Assistant Alloted__**\n\nAssistant No. **{ran_ass}**" 98 | ) 99 | assis = { 100 | "saveassistant": ran_ass, 101 | } 102 | await save_assistant(message.chat.id, "assistant", assis) 103 | else: 104 | ass = _assistant["saveassistant"] 105 | return await message.reply_text( 106 | f"Pre-Saved Assistant Number {ass} Found.\n\nYou can change Assistant Via /changeassistant" 107 | ) 108 | 109 | 110 | @app.on_message(filters.command("checkassistant") & filters.group) 111 | async def check_ass(_, message: Message): 112 | _assistant = await get_assistant(message.chat.id, "assistant") 113 | if not _assistant: 114 | return await message.reply_text( 115 | "No Pre-Saved Assistant Found.\n\nYou can set Assistant Via /play" 116 | ) 117 | else: 118 | ass = _assistant["saveassistant"] 119 | return await message.reply_text( 120 | f"Pre-Saved Assistant Found\n\nAssistanty Number {ass} " 121 | ) 122 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AyiinMusic", 3 | "description": "A Telegram Music Bot with proper functions written in Python with Pyrogram and Py-Tgcalls.", 4 | "logo": "https://upload.wikimedia.org/wikipedia/commons/c/c3/Python-logo-notext.svg", 5 | "keywords": [ 6 | "python3", 7 | "telegram", 8 | "bot", 9 | "Ayiin", 10 | "AyiinMusic", 11 | "telegram-bot", 12 | "pyrogram" 13 | ], 14 | "stack": "container", 15 | "env": { 16 | "API_ID": { 17 | "description": "Get this value from https://my.telegram.org", 18 | "value": "", 19 | "required": true 20 | }, 21 | "API_HASH": { 22 | "description": "Get this value from https://my.telegram.org", 23 | "value": "", 24 | "required": true 25 | }, 26 | "BOT_TOKEN": { 27 | "description": "A Bot's token from Botfather", 28 | "value": "", 29 | "required": true 30 | }, 31 | "DURATION_LIMIT": { 32 | "description": "Duration Limit for Playout (In Mins).. Example: 60", 33 | "value": "60", 34 | "required": true 35 | }, 36 | "ASSISTANT_PREFIX": { 37 | "description": "Prefix for Assistant Commands.", 38 | "value": ".", 39 | "required": true 40 | }, 41 | "MONGO_DB_URI": { 42 | "description": "Mongo DB URL", 43 | "value": "", 44 | "required": true 45 | }, 46 | "MUSIC_BOT_NAME": { 47 | "description": "A name for your Music Bot.", 48 | "value": "", 49 | "required": true 50 | }, 51 | "SUPPORT_CHANNEL": { 52 | "description": "Support Channel Link if you have any, Leave blank if no support. Your link must start with https://t.me/", 53 | "value": "", 54 | "required": false 55 | }, 56 | "SUPPORT_GROUP": { 57 | "description": "Support Group Link if you have any, Leave blank if no support. Your link must start with https://t.me/", 58 | "value": "", 59 | "required": false 60 | }, 61 | "OWNER_ID": { 62 | "description": "The user id(s) of user(s) whom you would like to add as a OWNER. Multiple values shall be seperated with a space.", 63 | "value": "", 64 | "required": true 65 | }, 66 | "STRING_SESSION1": { 67 | "description": "A Pyrogram String Session. One Assistant is Compulsory.", 68 | "value": "", 69 | "required": true 70 | }, 71 | "STRING_SESSION2": { 72 | "description": "A Pyrogram String Session. Leave blank if you dont want Multi-Assistant", 73 | "value": "", 74 | "required": false 75 | }, 76 | "STRING_SESSION3": { 77 | "description": "A Pyrogram String Session. Leave blank if you dont want Multi-Assistant", 78 | "value": "", 79 | "required": false 80 | }, 81 | "STRING_SESSION4": { 82 | "description": "A Pyrogram String Session. Leave blank if you dont want Multi-Assistant", 83 | "value": "", 84 | "required": false 85 | }, 86 | "STRING_SESSION5": { 87 | "description": "A Pyrogram String Session. Leave blank if you dont want Multi-Assistant", 88 | "value": "", 89 | "required": false 90 | }, 91 | "HEROKU_API_KEY": { 92 | "description": "Your Heroku account's API key", 93 | "value": "", 94 | "required": false 95 | }, 96 | "HEROKU_APP_NAME": { 97 | "description": "Your heroku app/bot's name", 98 | "value": "", 99 | "required": false 100 | }, 101 | "LOG_GROUP_ID": { 102 | "description": "Your Log Group ID, add your bot and promote as an admin with full rights!. Use only Group. Please don't use Channel ID.", 103 | "value": "", 104 | "required": true 105 | }, 106 | "SUDO_USERS": { 107 | "description": "The user id(s) of user(s) whom you would like to add as a SUDO. Multiple values shall be seperated with a space.", 108 | "value": "", 109 | "required": true 110 | }, 111 | "LOG_SESSION": { 112 | "description": "A Pyrogram String Session for LOGGING or u can also add STRING_SESSION1 Also.", 113 | "value": "", 114 | "required": true 115 | }, 116 | "UPSTREAM_REPO": { 117 | "description": "If you dont know this, Leave as it is", 118 | "value": "https://github.com/AyiinXd/AyiinMusic", 119 | "required": true 120 | }, 121 | "UPSTREAM_BRANCH": { 122 | "description": "Repo's Branch Name", 123 | "value": "master", 124 | "required": true 125 | } 126 | }, 127 | "buildpacks": [ 128 | { 129 | "url": "heroku/python" 130 | }, 131 | { 132 | "url": "heroku/nodejs" 133 | }, 134 | { 135 | "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git" 136 | } 137 | ], 138 | "formation": { 139 | "worker": { 140 | "quantity": 1, 141 | "size": "free" 142 | } 143 | }, 144 | "stack": "container" 145 | } 146 | -------------------------------------------------------------------------------- /Ayiin/Decorators/assistant.py: -------------------------------------------------------------------------------- 1 | import random 2 | from typing import Dict, List, Union 3 | 4 | from pyrogram import filters 5 | from pyrogram.errors import UserAlreadyParticipant, UserNotParticipant 6 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 7 | InlineKeyboardMarkup, InputMediaPhoto, Message) 8 | 9 | from Ayiin import BOT_ID, MUSIC_BOT_NAME, app, random_assistant 10 | from Ayiin.Database import get_assistant, save_assistant 11 | from Ayiin.Utilities.assistant import get_assistant_details 12 | 13 | 14 | @app.on_callback_query(filters.regex("unban_assistant")) 15 | async def unban_assistant_(_, CallbackQuery): 16 | callback_data = CallbackQuery.data.strip() 17 | callback_request = callback_data.split(None, 1)[1] 18 | query, user_id = callback_request.split("|") 19 | a = await app.get_chat_member(CallbackQuery.message.chat.id, BOT_ID) 20 | if not a.can_restrict_members: 21 | return await CallbackQuery.answer( 22 | "I am not having ban/unban user permission. Ask any admin to unban the assistant.", 23 | show_alert=True, 24 | ) 25 | else: 26 | try: 27 | await app.unban_chat_member( 28 | CallbackQuery.message.chat.id, user_id 29 | ) 30 | except: 31 | return await CallbackQuery.answer( 32 | "Failed to unban", 33 | show_alert=True, 34 | ) 35 | return await CallbackQuery.edit_message_text( 36 | "Assistant Unbanned. Try Playing Now." 37 | ) 38 | 39 | 40 | def AssistantAdd(mystic): 41 | async def wrapper(_, message): 42 | _assistant = await get_assistant(message.chat.id, "assistant") 43 | if not _assistant: 44 | ran_ass = random.choice(random_assistant) 45 | assis = { 46 | "saveassistant": ran_ass, 47 | } 48 | await save_assistant(message.chat.id, "assistant", assis) 49 | else: 50 | ran_ass = _assistant["saveassistant"] 51 | if ran_ass not in random_assistant: 52 | ran_ass = random.choice(random_assistant) 53 | assis = { 54 | "saveassistant": ran_ass, 55 | } 56 | await save_assistant(message.chat.id, "assistant", assis) 57 | ASS_ID, ASS_NAME, ASS_USERNAME, ASS_ACC = await get_assistant_details( 58 | ran_ass 59 | ) 60 | try: 61 | b = await app.get_chat_member(message.chat.id, ASS_ID) 62 | key = InlineKeyboardMarkup( 63 | [ 64 | [ 65 | InlineKeyboardButton( 66 | text="🗑 Unban Assistant", 67 | callback_data=f"unban_assistant a|{ASS_ID}", 68 | ) 69 | ], 70 | ] 71 | ) 72 | if b.status == "kicked": 73 | return await message.reply_text( 74 | f"Assistant Account[{ASS_ID}] is banned.\nUnban it first to use Music Bot\n\nUsername: @{ASS_USERNAME}", 75 | reply_markup=key, 76 | ) 77 | if b.status == "banned": 78 | return await message.reply_text( 79 | f"Assistant Account[{ASS_ID}] is banned.\nUnban it first to use Music Bot\n\nUsername: @{ASS_USERNAME}", 80 | reply_markup=key, 81 | ) 82 | except UserNotParticipant: 83 | if message.chat.username: 84 | try: 85 | await ASS_ACC.join_chat(message.chat.username) 86 | except UserAlreadyParticipant: 87 | pass 88 | except Exception as e: 89 | await message.reply_text( 90 | f"__Assistant Failed To Join__\n\n**Reason**: {e}" 91 | ) 92 | return 93 | else: 94 | try: 95 | invitelink = await app.export_chat_invite_link( 96 | message.chat.id 97 | ) 98 | if invitelink.startswith("https://t.me/+"): 99 | invitelink = invitelink.replace( 100 | "https://t.me/+", "https://t.me/joinchat/" 101 | ) 102 | await ASS_ACC.join_chat(invitelink) 103 | await message.reply( 104 | f"{ASS_NAME} Joined Successfully", 105 | ) 106 | except UserAlreadyParticipant: 107 | pass 108 | except Exception as e: 109 | await message.reply_text( 110 | f"__Assistant Failed To Join__\n\n**Reason**: {e}" 111 | ) 112 | return 113 | return await mystic(_, message) 114 | 115 | return wrapper 116 | -------------------------------------------------------------------------------- /Ayiin/Inline/stats.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | stats1 = InlineKeyboardMarkup( 5 | [ 6 | [ 7 | InlineKeyboardButton( 8 | text="System Stats", callback_data=f"sys_stats" 9 | ), 10 | InlineKeyboardButton( 11 | text="Storage Stats", callback_data=f"sto_stats" 12 | ), 13 | ], 14 | [ 15 | InlineKeyboardButton( 16 | text="Bot Stats", callback_data=f"bot_stats" 17 | ), 18 | InlineKeyboardButton( 19 | text="MongoDB Stats", callback_data=f"mongo_stats" 20 | ), 21 | ], 22 | [ 23 | InlineKeyboardButton( 24 | text="Assistant Stats", callback_data=f"assis_stats" 25 | ) 26 | ], 27 | ] 28 | ) 29 | 30 | stats2 = InlineKeyboardMarkup( 31 | [ 32 | [ 33 | InlineKeyboardButton( 34 | text="General Stats", callback_data=f"gen_stats" 35 | ), 36 | InlineKeyboardButton( 37 | text="Storage Stats", callback_data=f"sto_stats" 38 | ), 39 | ], 40 | [ 41 | InlineKeyboardButton( 42 | text="Bot Stats", callback_data=f"bot_stats" 43 | ), 44 | InlineKeyboardButton( 45 | text="MongoDB Stats", callback_data=f"mongo_stats" 46 | ), 47 | ], 48 | [ 49 | InlineKeyboardButton( 50 | text="Assistant Stats", callback_data=f"assis_stats" 51 | ) 52 | ], 53 | ] 54 | ) 55 | 56 | stats3 = InlineKeyboardMarkup( 57 | [ 58 | [ 59 | InlineKeyboardButton( 60 | text="System Stats", callback_data=f"sys_stats" 61 | ), 62 | InlineKeyboardButton( 63 | text="General Stats", callback_data=f"gen_stats" 64 | ), 65 | ], 66 | [ 67 | InlineKeyboardButton( 68 | text="Bot Stats", callback_data=f"bot_stats" 69 | ), 70 | InlineKeyboardButton( 71 | text="MongoDB Stats", callback_data=f"mongo_stats" 72 | ), 73 | ], 74 | [ 75 | InlineKeyboardButton( 76 | text="Assistant Stats", callback_data=f"assis_stats" 77 | ) 78 | ], 79 | ] 80 | ) 81 | 82 | stats4 = InlineKeyboardMarkup( 83 | [ 84 | [ 85 | InlineKeyboardButton( 86 | text="System Stats", callback_data=f"sys_stats" 87 | ), 88 | InlineKeyboardButton( 89 | text="Storage Stats", callback_data=f"sto_stats" 90 | ), 91 | ], 92 | [ 93 | InlineKeyboardButton( 94 | text="General Stats", callback_data=f"gen_stats" 95 | ), 96 | InlineKeyboardButton( 97 | text="MongoDB Stats", callback_data=f"mongo_stats" 98 | ), 99 | ], 100 | [ 101 | InlineKeyboardButton( 102 | text="Assistant Stats", callback_data=f"assis_stats" 103 | ) 104 | ], 105 | ] 106 | ) 107 | 108 | stats5 = InlineKeyboardMarkup( 109 | [ 110 | [ 111 | InlineKeyboardButton( 112 | text="System Stats", callback_data=f"sys_stats" 113 | ), 114 | InlineKeyboardButton( 115 | text="Storage Stats", callback_data=f"sto_stats" 116 | ), 117 | ], 118 | [ 119 | InlineKeyboardButton( 120 | text="Bot Stats", callback_data=f"bot_stats" 121 | ), 122 | InlineKeyboardButton( 123 | text="General Stats", callback_data=f"gen_stats" 124 | ), 125 | ], 126 | [ 127 | InlineKeyboardButton( 128 | text="Assistant Stats", callback_data=f"assis_stats" 129 | ) 130 | ], 131 | ] 132 | ) 133 | 134 | stats6 = InlineKeyboardMarkup( 135 | [ 136 | [ 137 | InlineKeyboardButton( 138 | text="System Stats", callback_data=f"sys_stats" 139 | ), 140 | InlineKeyboardButton( 141 | text="Storage Stats", callback_data=f"sto_stats" 142 | ), 143 | ], 144 | [ 145 | InlineKeyboardButton( 146 | text="Bot Stats", callback_data=f"bot_stats" 147 | ), 148 | InlineKeyboardButton( 149 | text="MongoDB Stats", callback_data=f"mongo_stats" 150 | ), 151 | ], 152 | [ 153 | InlineKeyboardButton( 154 | text="General Stats", callback_data=f"gen_stats" 155 | ) 156 | ], 157 | ] 158 | ) 159 | 160 | 161 | stats7 = InlineKeyboardMarkup( 162 | [ 163 | [ 164 | InlineKeyboardButton( 165 | text="Getting Assistant Stats....", 166 | callback_data=f"wait_stats", 167 | ) 168 | ] 169 | ] 170 | ) 171 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Auth.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from pyrogram.types import Message 3 | 4 | from Ayiin import SUDOERS, app 5 | from Ayiin.Database import (_get_authusers, delete_authuser, get_authuser, 6 | get_authuser_count, get_authuser_names, 7 | save_authuser) 8 | from Ayiin.Decorators.admins import AdminActual 9 | from Ayiin.Utilities.changers import (alpha_to_int, int_to_alpha, 10 | time_to_seconds) 11 | 12 | __MODULE__ = "Auth Users" 13 | __HELP__ = """ 14 | 15 | **Note:** 16 | -Auth users can skip, pause, stop, resume Voice Chats even without Admin Rights. 17 | 18 | 19 | /auth [Username or Reply to a Message] 20 | - Add a user to AUTH LIST of the group. 21 | 22 | /unauth [Username or Reply to a Message] 23 | - Remove a user from AUTH LIST of the group. 24 | 25 | /authusers 26 | - Check AUTH LIST of the group. 27 | """ 28 | 29 | 30 | @app.on_message(filters.command("auth") & filters.group) 31 | @AdminActual 32 | async def auth(_, message: Message): 33 | if not message.reply_to_message: 34 | if len(message.command) != 2: 35 | await message.reply_text( 36 | "Reply to a user's message or give username/user_id." 37 | ) 38 | return 39 | user = message.text.split(None, 1)[1] 40 | if "@" in user: 41 | user = user.replace("@", "") 42 | user = await app.get_users(user) 43 | user_id = message.from_user.id 44 | token = await int_to_alpha(user.id) 45 | from_user_name = message.from_user.first_name 46 | from_user_id = message.from_user.id 47 | _check = await get_authuser_names(message.chat.id) 48 | count = 0 49 | for smex in _check: 50 | count += 1 51 | if int(count) == 20: 52 | return await message.reply_text( 53 | "You can only have 20 Users In Your Groups Authorised Users List (AUL)" 54 | ) 55 | if token not in _check: 56 | assis = { 57 | "auth_user_id": user.id, 58 | "auth_name": user.first_name, 59 | "admin_id": from_user_id, 60 | "admin_name": from_user_name, 61 | } 62 | await save_authuser(message.chat.id, token, assis) 63 | await message.reply_text( 64 | f"Added to Authorised Users List of this group." 65 | ) 66 | return 67 | else: 68 | await message.reply_text(f"Already in the Authorised Users List.") 69 | return 70 | from_user_id = message.from_user.id 71 | user_id = message.reply_to_message.from_user.id 72 | user_name = message.reply_to_message.from_user.first_name 73 | token = await int_to_alpha(user_id) 74 | from_user_name = message.from_user.first_name 75 | _check = await get_authuser_names(message.chat.id) 76 | count = 0 77 | for smex in _check: 78 | count += 1 79 | if int(count) == 20: 80 | return await message.reply_text( 81 | "You can only have 20 Users In Your Groups Authorised Users List (AUL)" 82 | ) 83 | if token not in _check: 84 | assis = { 85 | "auth_user_id": user_id, 86 | "auth_name": user_name, 87 | "admin_id": from_user_id, 88 | "admin_name": from_user_name, 89 | } 90 | await save_authuser(message.chat.id, token, assis) 91 | await message.reply_text( 92 | f"Added to Authorised Users List of this group." 93 | ) 94 | return 95 | else: 96 | await message.reply_text(f"Already in the Authorised Users List.") 97 | 98 | 99 | @app.on_message(filters.command("unauth") & filters.group) 100 | @AdminActual 101 | async def whitelist_chat_func(_, message: Message): 102 | if not message.reply_to_message: 103 | if len(message.command) != 2: 104 | await message.reply_text( 105 | "Reply to a user's message or give username/user_id." 106 | ) 107 | return 108 | user = message.text.split(None, 1)[1] 109 | if "@" in user: 110 | user = user.replace("@", "") 111 | user = await app.get_users(user) 112 | token = await int_to_alpha(user.id) 113 | deleted = await delete_authuser(message.chat.id, token) 114 | if deleted: 115 | return await message.reply_text( 116 | f"Removed from Authorised Users List of this Group." 117 | ) 118 | else: 119 | return await message.reply_text(f"Not an Authorised User.") 120 | user_id = message.reply_to_message.from_user.id 121 | token = await int_to_alpha(user_id) 122 | deleted = await delete_authuser(message.chat.id, token) 123 | if deleted: 124 | return await message.reply_text( 125 | f"Removed from Authorised Users List of this Group." 126 | ) 127 | else: 128 | return await message.reply_text(f"Not an Authorised User.") 129 | 130 | 131 | @app.on_message(filters.command("authusers") & filters.group) 132 | async def authusers(_, message: Message): 133 | _playlist = await get_authuser_names(message.chat.id) 134 | if not _playlist: 135 | return await message.reply_text( 136 | f"No Authorised Users in this Group.\n\nAdd Auth users by /auth and remove by /unauth." 137 | ) 138 | else: 139 | j = 0 140 | m = await message.reply_text( 141 | "Fetching Authorised Users... Please Wait" 142 | ) 143 | msg = f"**Authorised Users List[AUL]:**\n\n" 144 | for note in _playlist: 145 | _note = await get_authuser(message.chat.id, note) 146 | user_id = _note["auth_user_id"] 147 | user_name = _note["auth_name"] 148 | admin_id = _note["admin_id"] 149 | admin_name = _note["admin_name"] 150 | try: 151 | user = await app.get_users(user_id) 152 | user = user.first_name 153 | j += 1 154 | except Exception: 155 | continue 156 | msg += f"{j}➤ {user}[`{user_id}`]\n" 157 | msg += f" ┗ Added By:- {admin_name}[`{admin_id}`]\n\n" 158 | await m.edit_text(msg) 159 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Song.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from os import path 3 | 4 | from pyrogram import filters 5 | from pyrogram.types import (InlineKeyboardMarkup, InputMediaPhoto, Message, 6 | Voice) 7 | from youtube_search import YoutubeSearch 8 | 9 | from Ayiin import (BOT_USERNAME, DURATION_LIMIT, DURATION_LIMIT_MIN, 10 | MUSIC_BOT_NAME, app, db_mem) 11 | from Ayiin.Decorators.permission import PermissionCheck 12 | from Ayiin.Inline import song_download_markup, song_markup 13 | from Ayiin.Utilities.url import get_url 14 | from Ayiin.Utilities.youtube import get_yt_info_query, get_yt_info_query_slider 15 | 16 | loop = asyncio.get_event_loop() 17 | 18 | __MODULE__ = "Song" 19 | __HELP__ = """ 20 | 21 | 22 | /song [Youtube URL or Search Query] 23 | - Download the particular query in audio or video format. 24 | 25 | 26 | 27 | """ 28 | 29 | 30 | @app.on_message( 31 | filters.command(["song", f"song@{BOT_USERNAME}"]) 32 | ) 33 | @PermissionCheck 34 | async def play(_, message: Message): 35 | if message.chat.type == "private": 36 | pass 37 | else: 38 | if message.sender_chat: 39 | return await message.reply_text( 40 | "You're an __Anonymous Admin__ in this Chat Group!\nRevert back to User Account From Admin Rights." 41 | ) 42 | try: 43 | await message.delete() 44 | except: 45 | pass 46 | url = get_url(message) 47 | if url: 48 | mystic = await message.reply_text("🔄 Processing URL... Please Wait!") 49 | query = message.text.split(None, 1)[1] 50 | ( 51 | title, 52 | duration_min, 53 | duration_sec, 54 | thumb, 55 | videoid, 56 | ) = await loop.run_in_executor(None, get_yt_info_query, query) 57 | if str(duration_min) == "None": 58 | return await mystic.edit("Sorry! Its a Live Video") 59 | await mystic.delete() 60 | buttons = song_download_markup(videoid, message.from_user.id) 61 | return await message.reply_photo( 62 | photo=thumb, 63 | caption=f"📎Title: **{title}\n\n⏳Duration:** {duration_min} Mins\n\n__[Get Additional Information About Video](https://t.me/{BOT_USERNAME}?start=info_{videoid})__", 64 | reply_markup=InlineKeyboardMarkup(buttons), 65 | ) 66 | else: 67 | if len(message.command) < 2: 68 | await message.reply_text( 69 | "**Usage:**\n\n/song [Youtube Url or Music Name]\n\nDownloads the Particular Query." 70 | ) 71 | return 72 | mystic = await message.reply_text("🔍 Searching Your Query...") 73 | query = message.text.split(None, 1)[1] 74 | ( 75 | title, 76 | duration_min, 77 | duration_sec, 78 | thumb, 79 | videoid, 80 | ) = await loop.run_in_executor(None, get_yt_info_query, query) 81 | if str(duration_min) == "None": 82 | return await mystic.edit("Sorry! Its a Live Video") 83 | await mystic.delete() 84 | buttons = song_markup( 85 | videoid, duration_min, message.from_user.id, query, 0 86 | ) 87 | return await message.reply_photo( 88 | photo=thumb, 89 | caption=f"📎Title: **{title}\n\n⏳Duration:** {duration_min} Mins\n\n__[Get Additional Information About Video](https://t.me/{BOT_USERNAME}?start=info_{videoid})__", 90 | reply_markup=InlineKeyboardMarkup(buttons), 91 | ) 92 | 93 | 94 | @app.on_callback_query(filters.regex("qwertyuiopasdfghjkl")) 95 | async def qwertyuiopasdfghjkl(_, CallbackQuery): 96 | print("234") 97 | await CallbackQuery.answer() 98 | callback_data = CallbackQuery.data.strip() 99 | callback_request = callback_data.split(None, 1)[1] 100 | userid = CallbackQuery.from_user.id 101 | videoid, user_id = callback_request.split("|") 102 | buttons = song_download_markup(videoid, user_id) 103 | await CallbackQuery.edit_message_reply_markup( 104 | reply_markup=InlineKeyboardMarkup(buttons) 105 | ) 106 | 107 | 108 | @app.on_callback_query(filters.regex(pattern=r"song_right")) 109 | async def song_right(_, CallbackQuery): 110 | callback_data = CallbackQuery.data.strip() 111 | callback_request = callback_data.split(None, 1)[1] 112 | what, type, query, user_id = callback_request.split("|") 113 | if CallbackQuery.from_user.id != int(user_id): 114 | return await CallbackQuery.answer( 115 | "Search Your Own Music. You're not allowed to use this button.", 116 | show_alert=True, 117 | ) 118 | what = str(what) 119 | type = int(type) 120 | if what == "F": 121 | if type == 9: 122 | query_type = 0 123 | else: 124 | query_type = int(type + 1) 125 | await CallbackQuery.answer("Getting Next Result", show_alert=True) 126 | ( 127 | title, 128 | duration_min, 129 | duration_sec, 130 | thumb, 131 | videoid, 132 | ) = await loop.run_in_executor( 133 | None, get_yt_info_query_slider, query, query_type 134 | ) 135 | buttons = song_markup( 136 | videoid, duration_min, user_id, query, query_type 137 | ) 138 | med = InputMediaPhoto( 139 | media=thumb, 140 | caption=f"📎Title: **{title}\n\n⏳Duration:** {duration_min} Mins\n\n__[Get Additional Information About Video](https://t.me/{BOT_USERNAME}?start=info_{videoid})__", 141 | ) 142 | return await CallbackQuery.edit_message_media( 143 | media=med, reply_markup=InlineKeyboardMarkup(buttons) 144 | ) 145 | if what == "B": 146 | if type == 0: 147 | query_type = 9 148 | else: 149 | query_type = int(type - 1) 150 | await CallbackQuery.answer("Getting Previous Result", show_alert=True) 151 | ( 152 | title, 153 | duration_min, 154 | duration_sec, 155 | thumb, 156 | videoid, 157 | ) = await loop.run_in_executor( 158 | None, get_yt_info_query_slider, query, query_type 159 | ) 160 | buttons = song_markup( 161 | videoid, duration_min, user_id, query, query_type 162 | ) 163 | med = InputMediaPhoto( 164 | media=thumb, 165 | caption=f"📎Title: **{title}\n\n⏳Duration:** {duration_min} Mins\n\n__[Get Additional Information About Video](https://t.me/{BOT_USERNAME}?start=info_{videoid})__", 166 | ) 167 | return await CallbackQuery.edit_message_media( 168 | media=med, reply_markup=InlineKeyboardMarkup(buttons) 169 | ) 170 | -------------------------------------------------------------------------------- /Ayiin/Inline/playlist.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | 5 | def check_markup(user_name, user_id, videoid): 6 | buttons = [ 7 | [ 8 | InlineKeyboardButton( 9 | text=f"𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 10 | callback_data=f"playlist_check {user_id}|𝙶𝚁𝙾𝚄𝙿|{videoid}", 11 | ), 12 | InlineKeyboardButton( 13 | text=f"{user_name[:8]}'s 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 14 | callback_data=f"playlist_check {user_id}|𝙿𝙴𝚁𝚂𝙾𝙽𝙰𝙻|{videoid}", 15 | ), 16 | ], 17 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data="close")], 18 | ] 19 | return buttons 20 | 21 | 22 | def playlist_markup(user_name, user_id, videoid): 23 | buttons = [ 24 | [ 25 | InlineKeyboardButton( 26 | text=f"𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃​", 27 | callback_data=f"show_genre {user_id}|𝙶𝚁𝙾𝚄𝙿|{videoid}", 28 | ), 29 | InlineKeyboardButton( 30 | text=f"{user_name[:8]}'s 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 31 | callback_data=f"show_genre {user_id}|𝙿𝙴𝚁𝚂𝙾𝙽𝙰𝙻|{videoid}", 32 | ), 33 | ], 34 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data="close")], 35 | ] 36 | return buttons 37 | 38 | 39 | def play_genre_playlist(user_id, type, videoid): 40 | buttons = [ 41 | [ 42 | InlineKeyboardButton( 43 | text=f"𝙳𝙹", 44 | callback_data=f"play_playlist {user_id}|{type}|𝙱𝙾𝙻𝙻𝚈𝚆𝙾𝙾𝙳", 45 | ), 46 | InlineKeyboardButton( 47 | text=f"𝚂𝙻𝙴𝙴𝙿", 48 | callback_data=f"play_playlist {user_id}|{type}|𝙷𝙾𝙻𝙻𝚈𝚆𝙾𝙾𝙳", 49 | ), 50 | ], 51 | [ 52 | InlineKeyboardButton( 53 | text=f"𝚂𝙰𝙳", 54 | callback_data=f"play_playlist {user_id}|{type}|𝙿𝙰𝚁𝚃𝚈", 55 | ), 56 | InlineKeyboardButton( 57 | text=f"𝙿𝙰𝚁𝚃𝚈", 58 | callback_data=f"play_playlist {user_id}|{type}|𝙻𝙾𝙵𝙸", 59 | ), 60 | ], 61 | [ 62 | InlineKeyboardButton( 63 | text="⍟ 𝙱𝙰𝙲𝙺 ⍟", 64 | callback_data=f"main_playlist {videoid}|{type}|{user_id}", 65 | ), 66 | InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data="close"), 67 | ], 68 | ] 69 | return buttons 70 | 71 | 72 | def add_genre_markup(user_id, type, videoid): 73 | buttons = [ 74 | [ 75 | InlineKeyboardButton( 76 | text=f"✚ 𝙳𝙹", 77 | callback_data=f"add_playlist {videoid}|{type}|𝚆𝙴𝙴𝙱", 78 | ), 79 | InlineKeyboardButton( 80 | text=f"✚ 𝙿𝙰𝚁𝚃𝚈", 81 | callback_data=f"add_playlist {videoid}|{type}|𝚂𝙰𝙳", 82 | ), 83 | ], 84 | [ 85 | InlineKeyboardButton( 86 | text=f"✚ 𝚂𝙰𝙳", 87 | callback_data=f"add_playlist {videoid}|{type}|𝙿𝙰𝚁𝚃𝚈", 88 | ), 89 | InlineKeyboardButton( 90 | text=f"✚ 𝚂𝙻𝙴𝙴𝙿", 91 | callback_data=f"add_playlist {videoid}|{type}|𝙻𝙾𝙵𝙸", 92 | ), 93 | ], 94 | [ 95 | InlineKeyboardButton( 96 | text="⍟ 𝙱𝙰𝙲𝙺 ⍟​", callback_data=f"goback {videoid}|{user_id}" 97 | ), 98 | InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟", callback_data="close"), 99 | ], 100 | ] 101 | return buttons 102 | 103 | 104 | def check_genre_markup(type, videoid, user_id): 105 | buttons = [ 106 | [ 107 | InlineKeyboardButton( 108 | text=f"𝙳𝙹", callback_data=f"check_playlist {type}|𝚆𝙴𝙴𝙱" 109 | ), 110 | InlineKeyboardButton( 111 | text=f"𝙿𝙰𝚁𝚃𝚈", callback_data=f"check_playlist {type}|𝚂𝙰𝙳" 112 | ), 113 | ], 114 | [ 115 | InlineKeyboardButton( 116 | text=f"𝚂𝙰𝙳", callback_data=f"check_playlist {type}|𝙿𝙰𝚁𝚃𝚈" 117 | ), 118 | InlineKeyboardButton( 119 | text=f"𝚂𝙻𝙴𝙴𝙿", callback_data=f"check_playlist {type}|𝙻𝙾𝙵𝙸" 120 | ), 121 | ], 122 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data="close")], 123 | ] 124 | return buttons 125 | 126 | 127 | def third_playlist_markup(user_name, user_id, third_name, userid, videoid): 128 | buttons = [ 129 | [ 130 | InlineKeyboardButton( 131 | text=f"𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃​", 132 | callback_data=f"show_genre {user_id}|Group|{videoid}", 133 | ), 134 | InlineKeyboardButton( 135 | text=f"{user_name[:8]}'s 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 136 | callback_data=f"show_genre {user_id}|Personal|{videoid}", 137 | ), 138 | ], 139 | [ 140 | InlineKeyboardButton( 141 | text=f"{third_name[:16]}'s 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 142 | callback_data=f"show_genre {userid}|third|{videoid}", 143 | ), 144 | ], 145 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data="close")], 146 | ] 147 | return buttons 148 | 149 | 150 | def paste_queue_markup(url): 151 | buttons = [ 152 | [ 153 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 154 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 155 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 156 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 157 | ], 158 | [InlineKeyboardButton(text="𝙲𝙷𝙴𝙲𝙺𝙾𝚄𝚃 𝚀𝚄𝙴𝚄𝙴𝙳 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", url=f"{url}")], 159 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close")], 160 | ] 161 | return buttons 162 | 163 | 164 | def fetch_playlist(user_name, type, genre, user_id, url): 165 | buttons = [ 166 | [ 167 | InlineKeyboardButton( 168 | text=f"𝙿𝙻𝙰𝚈 {user_name[:10]}'s {genre} 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", 169 | callback_data=f"play_playlist {user_id}|{type}|{genre}", 170 | ), 171 | ], 172 | [InlineKeyboardButton(text="𝙲𝙷𝙴𝙲𝙺𝙾𝚄𝚃 𝙿𝙻𝙰𝚈𝙻𝙸𝚂𝚃", url=f"{url}")], 173 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close")], 174 | ] 175 | return buttons 176 | 177 | 178 | def delete_playlist_markuup(type, genre): 179 | buttons = [ 180 | [ 181 | InlineKeyboardButton( 182 | text=f"𝚈𝙴𝚂 𝙳𝙴𝙻𝙴𝚃𝙴!", 183 | callback_data=f"delete_playlist {type}|{genre}", 184 | ), 185 | InlineKeyboardButton(text="⍟ 𝙽𝙾 ⍟​", callback_data=f"close"), 186 | ], 187 | ] 188 | return buttons 189 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Developer.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import subprocess 4 | import sys 5 | import traceback 6 | from html import escape 7 | from inspect import getfullargspec 8 | from io import StringIO 9 | from time import time 10 | 11 | from pyrogram import filters 12 | from pyrogram.errors import MessageNotModified 13 | from pyrogram.types import (InlineKeyboardButton, InlineKeyboardMarkup, 14 | Message, ReplyKeyboardMarkup) 15 | 16 | from Ayiin import SUDOERS, app 17 | from Ayiin.Utilities.tasks import add_task, rm_task 18 | 19 | # Eval and Sh module from WBB 20 | 21 | __MODULE__ = "Broadcast" 22 | __HELP__ = """ 23 | **Note:** 24 | Only for Sudo Users. 25 | 26 | 27 | /broadcast [Message or Reply to a Message] 28 | - Broadcast any message to Bot's Served Chats. 29 | 30 | 31 | /broadcast_pin [Message or Reply to a Message] 32 | - Broadcast any message to Bot's Served Chats with message getting Pinned in chat [Disabled Notifications]. 33 | 34 | 35 | /broadcast_pin_loud [Message or Reply to a Message] 36 | - Broadcast any message to Bot's Served Chats with message getting Pinned in chat [Enabled Notifications]. 37 | """ 38 | 39 | 40 | async def aexec(code, client, message): 41 | exec( 42 | "async def __aexec(client, message): " 43 | + "".join(f"\n {a}" for a in code.split("\n")) 44 | ) 45 | return await locals()["__aexec"](client, message) 46 | 47 | 48 | async def edit_or_reply(msg: Message, **kwargs): 49 | func = msg.edit_text if msg.from_user.is_self else msg.reply 50 | spec = getfullargspec(func.__wrapped__).args 51 | await func(**{k: v for k, v in kwargs.items() if k in spec}) 52 | 53 | 54 | @app.on_message( 55 | filters.user(SUDOERS) 56 | & ~filters.forwarded 57 | & ~filters.via_bot 58 | & filters.command("eval") 59 | ) 60 | async def executor(client, message): 61 | if len(message.command) < 2: 62 | return await edit_or_reply( 63 | message, text="__Nigga Give me some command to execute.__" 64 | ) 65 | try: 66 | cmd = message.text.split(" ", maxsplit=1)[1] 67 | except IndexError: 68 | return await message.delete() 69 | t1 = time() 70 | old_stderr = sys.stderr 71 | old_stdout = sys.stdout 72 | redirected_output = sys.stdout = StringIO() 73 | redirected_error = sys.stderr = StringIO() 74 | stdout, stderr, exc = None, None, None 75 | try: 76 | await aexec(cmd, client, message) 77 | except Exception: 78 | exc = traceback.format_exc() 79 | stdout = redirected_output.getvalue() 80 | stderr = redirected_error.getvalue() 81 | sys.stdout = old_stdout 82 | sys.stderr = old_stderr 83 | evaluation = "" 84 | if exc: 85 | evaluation = exc 86 | elif stderr: 87 | evaluation = stderr 88 | elif stdout: 89 | evaluation = stdout 90 | else: 91 | evaluation = "Success" 92 | final_output = f"**OUTPUT**:\n```{evaluation.strip()}```" 93 | if len(final_output) > 4096: 94 | filename = "output.txt" 95 | with open(filename, "w+", encoding="utf8") as out_file: 96 | out_file.write(str(evaluation.strip())) 97 | t2 = time() 98 | keyboard = InlineKeyboardMarkup( 99 | [ 100 | [ 101 | InlineKeyboardButton( 102 | text="⏳", callback_data=f"runtime {t2-t1} Seconds" 103 | ) 104 | ] 105 | ] 106 | ) 107 | await message.reply_document( 108 | document=filename, 109 | caption=f"**INPUT:**\n`{cmd[0:980]}`\n\n**OUTPUT:**\n`Attached Document`", 110 | quote=False, 111 | reply_markup=keyboard, 112 | ) 113 | await message.delete() 114 | os.remove(filename) 115 | else: 116 | t2 = time() 117 | keyboard = InlineKeyboardMarkup( 118 | [ 119 | [ 120 | InlineKeyboardButton( 121 | text="⏳", 122 | callback_data=f"runtime {round(t2-t1, 3)} Seconds", 123 | ), 124 | InlineKeyboardButton( 125 | text="🗑", 126 | callback_data=f"forceclose abc|{message.from_user.id}", 127 | ), 128 | ] 129 | ] 130 | ) 131 | await edit_or_reply(message, text=final_output, reply_markup=keyboard) 132 | 133 | 134 | @app.on_callback_query(filters.regex(r"runtime")) 135 | async def runtime_func_cq(_, cq): 136 | runtime = cq.data.split(None, 1)[1] 137 | await cq.answer(runtime, show_alert=True) 138 | 139 | 140 | @app.on_message( 141 | filters.user(SUDOERS) 142 | & ~filters.forwarded 143 | & ~filters.via_bot 144 | & filters.command("sh"), 145 | ) 146 | async def shellrunner(client, message): 147 | if len(message.command) < 2: 148 | return await edit_or_reply(message, text="**Usage:**\n/sh git pull") 149 | text = message.text.split(None, 1)[1] 150 | if "\n" in text: 151 | code = text.split("\n") 152 | output = "" 153 | for x in code: 154 | shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x) 155 | try: 156 | process = subprocess.Popen( 157 | shell, 158 | stdout=subprocess.PIPE, 159 | stderr=subprocess.PIPE, 160 | ) 161 | except Exception as err: 162 | print(err) 163 | await edit_or_reply(message, text=f"**ERROR:**\n```{err}```") 164 | output += f"**{code}**\n" 165 | output += process.stdout.read()[:-1].decode("utf-8") 166 | output += "\n" 167 | else: 168 | shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text) 169 | for a in range(len(shell)): 170 | shell[a] = shell[a].replace('"', "") 171 | try: 172 | process = subprocess.Popen( 173 | shell, 174 | stdout=subprocess.PIPE, 175 | stderr=subprocess.PIPE, 176 | ) 177 | except Exception as err: 178 | print(err) 179 | exc_type, exc_obj, exc_tb = sys.exc_info() 180 | errors = traceback.format_exception( 181 | etype=exc_type, 182 | value=exc_obj, 183 | tb=exc_tb, 184 | ) 185 | return await edit_or_reply( 186 | message, text=f"**ERROR:**\n```{''.join(errors)}```" 187 | ) 188 | output = process.stdout.read()[:-1].decode("utf-8") 189 | if str(output) == "\n": 190 | output = None 191 | if output: 192 | if len(output) > 4096: 193 | with open("output.txt", "w+") as file: 194 | file.write(output) 195 | await app.send_document( 196 | message.chat.id, 197 | "output.txt", 198 | reply_to_message_id=message.message_id, 199 | caption="`Output`", 200 | ) 201 | return os.remove("output.txt") 202 | await edit_or_reply(message, text=f"**OUTPUT:**\n```{output}```") 203 | else: 204 | await edit_or_reply(message, text="**OUTPUT: **\n`No output`") 205 | -------------------------------------------------------------------------------- /Ayiin/Utilities/stream.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import shutil 4 | 5 | from pyrogram.types import InlineKeyboardMarkup 6 | 7 | from config import get_queue 8 | from Ayiin import BOT_USERNAME, db_mem 9 | from Ayiin.Core.PyTgCalls import Queues 10 | from Ayiin.Core.PyTgCalls.Ayiin import join_stream 11 | from Ayiin.Database import (add_active_chat, add_active_video_chat, 12 | is_active_chat, music_off, music_on) 13 | from Ayiin.Inline import (audio_markup, audio_markup2, primary_markup, 14 | secondary_markup) 15 | from Ayiin.Utilities.timer import start_timer 16 | 17 | loop = asyncio.get_event_loop() 18 | 19 | 20 | async def start_stream( 21 | CallbackQuery, 22 | file, 23 | videoid, 24 | thumb, 25 | title, 26 | duration_min, 27 | duration_sec, 28 | mystic, 29 | ): 30 | global get_queue 31 | if CallbackQuery.message.chat.id not in db_mem: 32 | db_mem[CallbackQuery.message.chat.id] = {} 33 | wtfbro = db_mem[CallbackQuery.message.chat.id] 34 | wtfbro["live_check"] = False 35 | if await is_active_chat(CallbackQuery.message.chat.id): 36 | position = await Queues.put(CallbackQuery.message.chat.id, file=file) 37 | _path_ = ( 38 | (str(file)) 39 | .replace("_", "", 1) 40 | .replace("/", "", 1) 41 | .replace(".", "", 1) 42 | ) 43 | buttons = secondary_markup(videoid, CallbackQuery.from_user.id) 44 | if file not in db_mem: 45 | db_mem[file] = {} 46 | cpl = f"cache/{_path_}final.png" 47 | shutil.copyfile(thumb, cpl) 48 | wtfbro = db_mem[file] 49 | wtfbro["title"] = title 50 | wtfbro["duration"] = duration_min 51 | wtfbro["username"] = CallbackQuery.from_user.mention 52 | wtfbro["videoid"] = videoid 53 | got_queue = get_queue.get(CallbackQuery.message.chat.id) 54 | title = title 55 | user = CallbackQuery.from_user.first_name 56 | duration = duration_min 57 | to_append = [title, user, duration] 58 | got_queue.append(to_append) 59 | final_output = await CallbackQuery.message.reply_photo( 60 | photo=thumb, 61 | caption=( 62 | f"🎬__Song:__ [{title[:25]}](https://www.youtube.com/watch?v={videoid}) \n⏳__Duration:__ {duration_min} \n💡__Info:__ [Get Additional Information](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n👤__Requested by:__ {CallbackQuery.from_user.mention} \n🚧__Queued at:__ #{position}!" 63 | ), 64 | reply_markup=InlineKeyboardMarkup(buttons), 65 | ) 66 | await mystic.delete() 67 | await CallbackQuery.message.delete() 68 | os.remove(thumb) 69 | return 70 | else: 71 | if not await join_stream(CallbackQuery.message.chat.id, file): 72 | return await mystic.edit("Error Joining Voice Chat.") 73 | get_queue[CallbackQuery.message.chat.id] = [] 74 | got_queue = get_queue.get(CallbackQuery.message.chat.id) 75 | title = title 76 | user = CallbackQuery.from_user.first_name 77 | duration = duration_min 78 | to_append = [title, user, duration] 79 | got_queue.append(to_append) 80 | await music_on(CallbackQuery.message.chat.id) 81 | await add_active_chat(CallbackQuery.message.chat.id) 82 | buttons = primary_markup( 83 | videoid, CallbackQuery.from_user.id, duration_min, duration_min 84 | ) 85 | await mystic.delete() 86 | cap = f"🎥__Playing:__ [{title[:25]}](https://www.youtube.com/watch?v={videoid}) \n💡__Info:__ [Get Additional Information](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n👤**__Requested by:__** {CallbackQuery.from_user.mention}" 87 | final_output = await CallbackQuery.message.reply_photo( 88 | photo=thumb, 89 | reply_markup=InlineKeyboardMarkup(buttons), 90 | caption=cap, 91 | ) 92 | os.remove(thumb) 93 | await CallbackQuery.message.delete() 94 | await start_timer( 95 | videoid, 96 | duration_min, 97 | duration_sec, 98 | final_output, 99 | CallbackQuery.message.chat.id, 100 | CallbackQuery.from_user.id, 101 | 0, 102 | ) 103 | 104 | 105 | async def start_stream_audio( 106 | message, file, videoid, title, duration_min, duration_sec, mystic 107 | ): 108 | global get_queue 109 | if message.chat.id not in db_mem: 110 | db_mem[message.chat.id] = {} 111 | wtfbro = db_mem[message.chat.id] 112 | wtfbro["live_check"] = False 113 | if message.chat.username: 114 | link = f"https://t.me/{message.chat.username}/{message.reply_to_message.message_id}" 115 | else: 116 | xf = str((message.chat.id))[4:] 117 | link = f"https://t.me/c/{xf}/{message.reply_to_message.message_id}" 118 | if await is_active_chat(message.chat.id): 119 | position = await Queues.put(message.chat.id, file=file) 120 | if file not in db_mem: 121 | db_mem[file] = {} 122 | db_mem[file]["title"] = title 123 | db_mem[file]["duration"] = duration_min 124 | db_mem[file]["username"] = message.from_user.mention 125 | db_mem[file]["videoid"] = videoid 126 | got_queue = get_queue.get(message.chat.id) 127 | title = title 128 | user = message.from_user.first_name 129 | duration = duration_min 130 | to_append = [title, user, duration] 131 | got_queue.append(to_append) 132 | final_output = await message.reply_photo( 133 | photo="Utils/Telegram.JPEG", 134 | caption=( 135 | f"🎬__Audio:__ [Given Audio Via Telegram]({link})\n⏳__Duration:__ {duration_min} \n👤__Requested by:__ {message.from_user.mention} \n🚧__Queued at:__ #{position}!" 136 | ), 137 | reply_markup=audio_markup2, 138 | ) 139 | await mystic.delete() 140 | return 141 | else: 142 | if not await join_stream(message.chat.id, file): 143 | return await mystic.edit( 144 | "Error Joining Voice Chat. Make sure Voice Chat is Enabled." 145 | ) 146 | get_queue[message.chat.id] = [] 147 | got_queue = get_queue.get(message.chat.id) 148 | title = title 149 | user = message.from_user.first_name 150 | duration = duration_min 151 | to_append = [title, user, duration] 152 | got_queue.append(to_append) 153 | await music_on(message.chat.id) 154 | await add_active_chat(message.chat.id) 155 | buttons = audio_markup( 156 | videoid, message.from_user.id, duration_min, duration_min 157 | ) 158 | await mystic.delete() 159 | cap = f"🎥__Playing:__ [Given Audio Via Telegram]({link})\n👤**__Requested by:__** {message.from_user.mention}" 160 | final_output = await message.reply_photo( 161 | photo="Utils/Telegram.JPEG", 162 | reply_markup=InlineKeyboardMarkup(buttons), 163 | caption=cap, 164 | ) 165 | await start_timer( 166 | videoid, 167 | duration_min, 168 | duration_sec, 169 | final_output, 170 | message.chat.id, 171 | message.from_user.id, 172 | 1, 173 | ) 174 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Stream.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from os import path 3 | 4 | from pyrogram import filters 5 | from pyrogram.types import (InlineKeyboardMarkup, InputMediaPhoto, 6 | KeyboardButton, Message, ReplyKeyboardMarkup, 7 | ReplyKeyboardRemove, Voice) 8 | from youtube_search import YoutubeSearch 9 | from youtubesearchpython import VideosSearch 10 | 11 | from Ayiin import (BOT_USERNAME, DURATION_LIMIT, DURATION_LIMIT_MIN, 12 | MUSIC_BOT_NAME, app, db_mem) 13 | from Ayiin.Core.PyTgCalls.Converter import convert 14 | from Ayiin.Core.PyTgCalls.Downloader import download 15 | from Ayiin.Database import (get_active_video_chats, get_video_limit, 16 | is_active_video_chat, is_on_off) 17 | from Ayiin.Decorators.assistant import AssistantAdd 18 | from Ayiin.Decorators.checker import checker 19 | from Ayiin.Decorators.permission import PermissionCheck 20 | from Ayiin.Inline import (choose_markup, livestream_markup, playlist_markup, 21 | search_markup, search_markup2, stream_quality_markup, 22 | url_markup, url_markup2) 23 | from Ayiin.Utilities.changers import seconds_to_min, time_to_seconds 24 | from Ayiin.Utilities.chat import specialfont_to_normal 25 | from Ayiin.Utilities.theme import check_theme 26 | from Ayiin.Utilities.thumbnails import gen_thumb 27 | from Ayiin.Utilities.url import get_url 28 | from Ayiin.Utilities.videostream import start_live_stream, start_video_stream 29 | from Ayiin.Utilities.youtube import (get_m3u8, get_yt_info_id, 30 | get_yt_info_query, 31 | get_yt_info_query_slider) 32 | 33 | loop = asyncio.get_event_loop() 34 | 35 | __MODULE__ = "VideoCalls" 36 | __HELP__ = f""" 37 | 38 | /play [Reply to any Video] or [YT Link] or [Music Name] 39 | - Stream Video on Voice Chat 40 | 41 | **For Sudo User:-** 42 | 43 | /set_video_limit [Number of Chats] 44 | - Set a maximum Number of Chats allowed for Video Calls at a time. 45 | 46 | 47 | """ 48 | 49 | 50 | @app.on_callback_query(filters.regex(pattern=r"Ayiin")) 51 | async def choose_playmode(_, CallbackQuery): 52 | await CallbackQuery.answer() 53 | callback_data = CallbackQuery.data.strip() 54 | callback_request = callback_data.split(None, 1)[1] 55 | videoid, duration, user_id = callback_request.split("|") 56 | if CallbackQuery.from_user.id != int(user_id): 57 | return await CallbackQuery.answer( 58 | "This is not for you! Search You Own Song.", show_alert=True 59 | ) 60 | buttons = choose_markup(videoid, duration, user_id) 61 | await CallbackQuery.edit_message_reply_markup( 62 | reply_markup=InlineKeyboardMarkup(buttons) 63 | ) 64 | 65 | 66 | @app.on_callback_query(filters.regex(pattern=r"Choose")) 67 | async def quality_markup(_, CallbackQuery): 68 | limit = await get_video_limit(141414) 69 | if not limit: 70 | await CallbackQuery.message.delete() 71 | return await CallbackQuery.message.reply_text( 72 | "**No Limit Defined for Video Calls**\n\nSet a Limit for Number of Maximum Video Calls allowed on Bot by /set_video_limit [Sudo Users Only]" 73 | ) 74 | count = len(await get_active_video_chats()) 75 | if int(count) == int(limit): 76 | if await is_active_video_chat(CallbackQuery.message.chat.id): 77 | pass 78 | else: 79 | return await CallbackQuery.answer( 80 | "Sorry! Bot only allows limited number of video calls due to CPU overload issues. Other chats are using video call right now. Try switching to audio or try again later", 81 | show_alert=True, 82 | ) 83 | if CallbackQuery.message.chat.id not in db_mem: 84 | db_mem[CallbackQuery.message.chat.id] = {} 85 | try: 86 | read1 = db_mem[CallbackQuery.message.chat.id]["live_check"] 87 | if read1: 88 | return await CallbackQuery.answer( 89 | "Live Streaming Playing...Stop it to play music", 90 | show_alert=True, 91 | ) 92 | else: 93 | pass 94 | except: 95 | pass 96 | await CallbackQuery.answer() 97 | callback_data = CallbackQuery.data.strip() 98 | callback_request = callback_data.split(None, 1)[1] 99 | videoid, duration, user_id = callback_request.split("|") 100 | if CallbackQuery.from_user.id != int(user_id): 101 | return await CallbackQuery.answer( 102 | "This is not for you! Search You Own Song.", show_alert=True 103 | ) 104 | buttons = stream_quality_markup(videoid, duration, user_id) 105 | await CallbackQuery.edit_message_reply_markup( 106 | reply_markup=InlineKeyboardMarkup(buttons) 107 | ) 108 | 109 | 110 | @app.on_callback_query(filters.regex(pattern=r"LiveStream")) 111 | async def Live_Videos_Stream(_, CallbackQuery): 112 | limit = await get_video_limit(141414) 113 | if not limit: 114 | await CallbackQuery.message.delete() 115 | return await CallbackQuery.message.reply_text( 116 | "**No Limit Defined for Video Calls**\n\nSet a Limit for Number of Maximum Video Calls allowed on Bot by /set_video_limit [Sudo Users Only]" 117 | ) 118 | count = len(await get_active_video_chats()) 119 | if int(count) == int(limit): 120 | if await is_active_video_chat(CallbackQuery.message.chat.id): 121 | pass 122 | else: 123 | return await CallbackQuery.answer( 124 | "Sorry! Bot only allows limited number of video calls due to CPU overload issues. Other chats are using video call right now. Try switching to audio or try again later", 125 | show_alert=True, 126 | ) 127 | if CallbackQuery.message.chat.id not in db_mem: 128 | db_mem[CallbackQuery.message.chat.id] = {} 129 | callback_data = CallbackQuery.data.strip() 130 | callback_request = callback_data.split(None, 1)[1] 131 | chat_id = CallbackQuery.message.chat.id 132 | chat_title = CallbackQuery.message.chat.title 133 | quality, videoid, duration, user_id = callback_request.split("|") 134 | if CallbackQuery.from_user.id != int(user_id): 135 | return await CallbackQuery.answer( 136 | "This is not for you! Search You Own Song.", show_alert=True 137 | ) 138 | await CallbackQuery.message.delete() 139 | title, duration_min, duration_sec, thumbnail = get_yt_info_id(videoid) 140 | await CallbackQuery.answer() 141 | theme = await check_theme(chat_id) 142 | chat_title = await specialfont_to_normal(chat_title) 143 | thumb = await gen_thumb(thumbnail, title, user_id, theme, chat_title) 144 | nrs, ytlink = await get_m3u8(videoid) 145 | if nrs == 0: 146 | return await CallbackQuery.message.reply_text( 147 | "Video Formats not Found.." 148 | ) 149 | await start_live_stream( 150 | CallbackQuery, 151 | quality, 152 | ytlink, 153 | thumb, 154 | title, 155 | duration_min, 156 | duration_sec, 157 | videoid, 158 | ) 159 | 160 | 161 | @app.on_callback_query(filters.regex(pattern=r"VideoStream")) 162 | async def Videos_Stream(_, CallbackQuery): 163 | if CallbackQuery.message.chat.id not in db_mem: 164 | db_mem[CallbackQuery.message.chat.id] = {} 165 | callback_data = CallbackQuery.data.strip() 166 | callback_request = callback_data.split(None, 1)[1] 167 | chat_id = CallbackQuery.message.chat.id 168 | chat_title = CallbackQuery.message.chat.title 169 | quality, videoid, duration, user_id = callback_request.split("|") 170 | if CallbackQuery.from_user.id != int(user_id): 171 | return await CallbackQuery.answer( 172 | "This is not for you! Search You Own Song.", show_alert=True 173 | ) 174 | if str(duration) == "None": 175 | buttons = livestream_markup(quality, videoid, duration, user_id) 176 | return await CallbackQuery.edit_message_text( 177 | "**Live Stream Detected**\n\nWant to play live stream? This will stop the current playing musics(if any) and will start streaming live video.", 178 | reply_markup=InlineKeyboardMarkup(buttons), 179 | ) 180 | await CallbackQuery.message.delete() 181 | title, duration_min, duration_sec, thumbnail = get_yt_info_id(videoid) 182 | if duration_sec > DURATION_LIMIT: 183 | return await CallbackQuery.message.reply_text( 184 | f"**Duration Limit Exceeded**\n\n**Allowed Duration: **{DURATION_LIMIT_MIN} minute(s)\n**Received Duration:** {duration_min} minute(s)" 185 | ) 186 | await CallbackQuery.answer() 187 | theme = await check_theme(chat_id) 188 | chat_title = await specialfont_to_normal(chat_title) 189 | thumb = await gen_thumb(thumbnail, title, user_id, theme, chat_title) 190 | nrs, ytlink = await get_m3u8(videoid) 191 | if nrs == 0: 192 | return await CallbackQuery.message.reply_text( 193 | "Video Formats not Found.." 194 | ) 195 | await start_video_stream( 196 | CallbackQuery, 197 | quality, 198 | ytlink, 199 | thumb, 200 | title, 201 | duration_min, 202 | duration_sec, 203 | videoid, 204 | ) 205 | -------------------------------------------------------------------------------- /Ayiin/Utilities/timer.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | from datetime import datetime, timedelta 4 | 5 | from pyrogram.errors import FloodWait, MessageNotModified 6 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 7 | InlineKeyboardMarkup, InputMediaPhoto, Message) 8 | 9 | from Ayiin import db_mem 10 | from Ayiin.Database import is_active_chat, is_music_playing 11 | from Ayiin.Inline import audio_timer_markup_start, timer_markup 12 | 13 | 14 | async def start_timer( 15 | videoid, duration_min, duration_sec, finaltext, chat_id, user_id, aud 16 | ): 17 | left_time = {} 18 | db_mem[chat_id]["videoid"] = videoid 19 | db_mem[chat_id]["left"] = duration_min 20 | db_mem[chat_id]["total"] = duration_min 21 | user_input_time = int(duration_sec - 8) 22 | left_time[videoid] = datetime.now() 23 | try: 24 | if 0 < user_input_time <= 7: 25 | while user_input_time: 26 | if await is_active_chat(chat_id): 27 | if db_mem[chat_id]["videoid"] == videoid: 28 | if await is_music_playing(chat_id): 29 | if datetime.now() > left_time.get(videoid): 30 | s = user_input_time % 60 31 | c_t = "00:{:02d}".format(s) 32 | if aud == 0: 33 | buttons = timer_markup( 34 | videoid, user_id, c_t, duration_min 35 | ) 36 | else: 37 | buttons = audio_timer_markup_start( 38 | videoid, user_id, c_t, duration_min 39 | ) 40 | user_input_time -= 1 41 | db_mem[chat_id]["left"] = c_t 42 | try: 43 | if db_mem[videoid]["check"] == 2: 44 | await finaltext.edit_reply_markup( 45 | reply_markup=InlineKeyboardMarkup( 46 | buttons 47 | ) 48 | ) 49 | except FloodWait as e: 50 | await asyncio.sleep(e.x) 51 | user_input_time -= e.x 52 | left_time[ 53 | videoid 54 | ] = datetime.now() + timedelta( 55 | milliseconds=550 56 | ) 57 | else: 58 | break 59 | else: 60 | break 61 | elif 7 < user_input_time < 60: 62 | while user_input_time > 0: 63 | if await is_active_chat(chat_id): 64 | if db_mem[chat_id]["videoid"] == videoid: 65 | if await is_music_playing(chat_id): 66 | if datetime.now() > left_time.get(videoid): 67 | s = user_input_time % 60 68 | c_t = "00:{:02d}".format(s) 69 | user_input_time -= 4 70 | if aud == 0: 71 | buttons = timer_markup( 72 | videoid, user_id, c_t, duration_min 73 | ) 74 | else: 75 | buttons = audio_timer_markup_start( 76 | videoid, user_id, c_t, duration_min 77 | ) 78 | db_mem[chat_id]["left"] = c_t 79 | try: 80 | if db_mem[videoid]["check"] == 2: 81 | await finaltext.edit_reply_markup( 82 | reply_markup=InlineKeyboardMarkup( 83 | buttons 84 | ) 85 | ) 86 | except FloodWait as e: 87 | await asyncio.sleep(e.x) 88 | user_input_time -= e.x 89 | left_time[ 90 | videoid 91 | ] = datetime.now() + timedelta( 92 | milliseconds=3500 93 | ) 94 | else: 95 | break 96 | else: 97 | break 98 | elif 60 <= user_input_time < 3600: 99 | while user_input_time > 0: 100 | if await is_active_chat(chat_id): 101 | if db_mem[chat_id]["videoid"] == videoid: 102 | if await is_music_playing(chat_id): 103 | if datetime.now() > left_time.get(videoid): 104 | m = user_input_time % 3600 // 60 105 | s = user_input_time % 60 106 | c_t = "{:02d}:{:02d}".format(m, s) 107 | user_input_time -= 6 108 | if aud == 0: 109 | buttons = timer_markup( 110 | videoid, user_id, c_t, duration_min 111 | ) 112 | else: 113 | buttons = audio_timer_markup_start( 114 | videoid, user_id, c_t, duration_min 115 | ) 116 | db_mem[chat_id]["left"] = c_t 117 | try: 118 | if db_mem[videoid]["check"] == 2: 119 | await finaltext.edit_reply_markup( 120 | reply_markup=InlineKeyboardMarkup( 121 | buttons 122 | ) 123 | ) 124 | except FloodWait as e: 125 | await asyncio.sleep(e.x) 126 | user_input_time -= e.x 127 | left_time[ 128 | videoid 129 | ] = datetime.now() + timedelta( 130 | milliseconds=5300 131 | ) 132 | else: 133 | break 134 | else: 135 | break 136 | elif 3600 <= user_input_time < 86400: 137 | while user_input_time > 0: 138 | if await is_active_chat(chat_id): 139 | if db_mem[chat_id]["videoid"] == videoid: 140 | if await is_music_playing(chat_id): 141 | if datetime.now() > left_time.get(videoid): 142 | h = user_input_time % (3600 * 24) // 3600 143 | m = user_input_time % 3600 // 60 144 | s = user_input_time % 60 145 | c_t = "{:02d}:{:02d}:{:02d}".format(h, m, s) 146 | user_input_time -= 10 147 | if aud == 0: 148 | buttons = timer_markup( 149 | videoid, user_id, c_t, duration_min 150 | ) 151 | else: 152 | buttons = audio_timer_markup_start( 153 | videoid, user_id, c_t, duration_min 154 | ) 155 | db_mem[chat_id]["left"] = c_t 156 | try: 157 | if db_mem[videoid]["check"] == 2: 158 | await finaltext.edit_reply_markup( 159 | reply_markup=InlineKeyboardMarkup( 160 | buttons 161 | ) 162 | ) 163 | except FloodWait as e: 164 | await asyncio.sleep(e.x) 165 | user_input_time -= e.x 166 | left_time[ 167 | videoid 168 | ] = datetime.now() + timedelta( 169 | milliseconds=9100 170 | ) 171 | else: 172 | break 173 | else: 174 | break 175 | else: 176 | return 177 | except Exception as e: 178 | print(e) 179 | return 180 | -------------------------------------------------------------------------------- /Ayiin/Utilities/videostream.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import shutil 4 | from asyncio import QueueEmpty 5 | 6 | from pyrogram.types import InlineKeyboardMarkup 7 | from pyrogram.types.messages_and_media import message 8 | 9 | from config import get_queue 10 | from Ayiin import BOT_USERNAME, db_mem 11 | from Ayiin.Core.PyTgCalls import Queues 12 | from Ayiin.Core.PyTgCalls.Ayiin import (join_live_stream, join_video_stream, 13 | stop_stream) 14 | from Ayiin.Database import (add_active_chat, add_active_video_chat, 15 | is_active_chat, music_off, music_on, 16 | remove_active_chat) 17 | from Ayiin.Inline import (audio_markup, audio_markup2, primary_markup, 18 | secondary_markup, secondary_markup2) 19 | from Ayiin.Utilities.timer import start_timer 20 | 21 | loop = asyncio.get_event_loop() 22 | 23 | 24 | async def start_stream_video(message, file, title, mystic): 25 | global get_queue 26 | if message.chat.id not in db_mem: 27 | db_mem[message.chat.id] = {} 28 | wtfbro = db_mem[message.chat.id] 29 | wtfbro["live_check"] = False 30 | if message.chat.username: 31 | link = f"https://t.me/{message.chat.username}/{message.reply_to_message.message_id}" 32 | else: 33 | xf = str((message.chat.id))[4:] 34 | link = f"https://t.me/c/{xf}/{message.reply_to_message.message_id}" 35 | if await is_active_chat(message.chat.id): 36 | file = f"s1s_1080_+_{file}" 37 | position = await Queues.put(message.chat.id, file=file) 38 | if file not in db_mem: 39 | db_mem[file] = {} 40 | wtfbro = db_mem[file] 41 | wtfbro["chat_title"] = message.chat.title 42 | wtfbro["duration"] = 0 43 | wtfbro["username"] = message.from_user.mention 44 | wtfbro["videoid"] = "videoid" 45 | wtfbro["user_id"] = message.from_user.id 46 | got_queue = get_queue.get(message.chat.id) 47 | title = title 48 | user = message.from_user.first_name 49 | duration = 0 50 | to_append = [title, user, duration] 51 | got_queue.append(to_append) 52 | final_output = await message.reply_photo( 53 | photo="Utils/Telegram.JPEG", 54 | caption=( 55 | f"🎬__Video:__ [Given Video Via Telegram]({link})\n\n👤__Requested by:__ {message.from_user.mention} \n🚧__Queued at:__ #{position}!" 56 | ), 57 | reply_markup=audio_markup2, 58 | ) 59 | await mystic.delete() 60 | return 61 | else: 62 | if not await join_video_stream(message.chat.id, file, 720): 63 | return await mystic.edit( 64 | "Error Joining Voice Chat. Make sure Voice Chat is Enabled." 65 | ) 66 | get_queue[message.chat.id] = [] 67 | got_queue = get_queue.get(message.chat.id) 68 | title = title 69 | user = message.from_user.first_name 70 | duration = 0 71 | to_append = [title, user, duration] 72 | got_queue.append(to_append) 73 | await music_on(message.chat.id) 74 | await add_active_chat(message.chat.id) 75 | await add_active_video_chat(message.chat.id) 76 | buttons = secondary_markup2("Smex1", message.from_user.id) 77 | await mystic.delete() 78 | cap = f"🎥__Playing:__ [Given Video Via Telegram]({link})\n👤**__Requested by:__** {message.from_user.mention}" 79 | final_output = await message.reply_photo( 80 | photo="Utils/Telegram.JPEG", 81 | reply_markup=InlineKeyboardMarkup(buttons), 82 | caption=cap, 83 | ) 84 | 85 | 86 | async def start_live_stream( 87 | CallbackQuery, 88 | quality, 89 | link, 90 | thumb, 91 | title, 92 | duration_min, 93 | duration_sec, 94 | videoid, 95 | ): 96 | global get_queue 97 | if CallbackQuery.message.chat.id not in db_mem: 98 | db_mem[CallbackQuery.message.chat.id] = {} 99 | wtfbro = db_mem[CallbackQuery.message.chat.id] 100 | wtfbro["live_check"] = True 101 | if await is_active_chat(CallbackQuery.message.chat.id): 102 | try: 103 | Queues.clear(CallbackQuery.message.chat.id) 104 | except QueueEmpty: 105 | pass 106 | await remove_active_chat(CallbackQuery.message.chat.id) 107 | try: 108 | await stop_stream(CallbackQuery.message.chat.id) 109 | except: 110 | pass 111 | if not await join_live_stream( 112 | CallbackQuery.message.chat.id, link, quality 113 | ): 114 | return await CallbackQuery.message.reply_text( 115 | f"Error Joining Voice Chat." 116 | ) 117 | await music_on(CallbackQuery.message.chat.id) 118 | await add_active_chat(CallbackQuery.message.chat.id) 119 | await add_active_video_chat(CallbackQuery.message.chat.id) 120 | buttons = secondary_markup2(videoid, CallbackQuery.from_user.id) 121 | cap = f"**Live Streaming**\n\n🎥__Playing:__ [{title[:25]}](https://www.youtube.com/watch?v={videoid}) \n💡__Info:__ [Get Additional Information](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n👤**__Requested by:__** {CallbackQuery.from_user.mention}" 122 | final_output = await CallbackQuery.message.reply_photo( 123 | photo=thumb, 124 | reply_markup=InlineKeyboardMarkup(buttons), 125 | caption=cap, 126 | ) 127 | os.remove(thumb) 128 | await CallbackQuery.message.delete() 129 | 130 | 131 | async def start_video_stream( 132 | CallbackQuery, 133 | quality, 134 | link, 135 | thumb, 136 | title, 137 | duration_min, 138 | duration_sec, 139 | videoid, 140 | ): 141 | global get_queue 142 | if CallbackQuery.message.chat.id not in db_mem: 143 | db_mem[CallbackQuery.message.chat.id] = {} 144 | wtfbro = db_mem[CallbackQuery.message.chat.id] 145 | wtfbro["live_check"] = False 146 | if await is_active_chat(CallbackQuery.message.chat.id): 147 | file = f"s1s_{quality}_+_{videoid}" 148 | position = await Queues.put(CallbackQuery.message.chat.id, file=file) 149 | _path_ = ( 150 | (str(file)) 151 | .replace("_", "", 1) 152 | .replace("/", "", 1) 153 | .replace(".", "", 1) 154 | ) 155 | buttons = secondary_markup(videoid, CallbackQuery.from_user.id) 156 | if file not in db_mem: 157 | db_mem[file] = {} 158 | cpl = f"cache/{_path_}final.png" 159 | shutil.copyfile(thumb, cpl) 160 | wtfbro = db_mem[file] 161 | wtfbro["chat_title"] = CallbackQuery.message.chat.title 162 | wtfbro["duration"] = duration_min 163 | wtfbro["username"] = CallbackQuery.from_user.mention 164 | wtfbro["videoid"] = videoid 165 | wtfbro["user_id"] = CallbackQuery.from_user.id 166 | got_queue = get_queue.get(CallbackQuery.message.chat.id) 167 | title = title 168 | user = CallbackQuery.from_user.first_name 169 | duration = duration_min 170 | to_append = [title, user, duration] 171 | got_queue.append(to_append) 172 | final_output = await CallbackQuery.message.reply_photo( 173 | photo=thumb, 174 | caption=( 175 | f"🎬Video:__ [{title[:25]}](https://www.youtube.com/watch?v={videoid}) \n⏳__Duration:__ {duration_min} \n💡__Info:__ [Get Additional Information](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n👤__Requested by:__ {CallbackQuery.from_user.mention} \n🚧__ Video Queued at:__ #{position}!" 176 | ), 177 | reply_markup=InlineKeyboardMarkup(buttons), 178 | ) 179 | await CallbackQuery.message.delete() 180 | os.remove(thumb) 181 | return 182 | else: 183 | if not await join_video_stream( 184 | CallbackQuery.message.chat.id, link, quality 185 | ): 186 | return await CallbackQuery.message.reply_text( 187 | f"Error Joining Voice Chat." 188 | ) 189 | get_queue[CallbackQuery.message.chat.id] = [] 190 | got_queue = get_queue.get(CallbackQuery.message.chat.id) 191 | title = title 192 | user = CallbackQuery.from_user.first_name 193 | duration = duration_min 194 | to_append = [title, user, duration] 195 | got_queue.append(to_append) 196 | await music_on(CallbackQuery.message.chat.id) 197 | await add_active_video_chat(CallbackQuery.message.chat.id) 198 | await add_active_chat(CallbackQuery.message.chat.id) 199 | 200 | buttons = primary_markup( 201 | videoid, CallbackQuery.from_user.id, duration_min, duration_min 202 | ) 203 | cap = f"**Video Streaming**\n\n🎥__Playing:__ [{title[:25]}](https://www.youtube.com/watch?v={videoid}) \n💡__Info:__ [Get Additional Information](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n👤**__Requested by:__** {CallbackQuery.from_user.mention}" 204 | final_output = await CallbackQuery.message.reply_photo( 205 | photo=thumb, 206 | reply_markup=InlineKeyboardMarkup(buttons), 207 | caption=cap, 208 | ) 209 | os.remove(thumb) 210 | await CallbackQuery.message.delete() 211 | await start_timer( 212 | videoid, 213 | duration_min, 214 | duration_sec, 215 | final_output, 216 | CallbackQuery.message.chat.id, 217 | CallbackQuery.from_user.id, 218 | 0, 219 | ) 220 | -------------------------------------------------------------------------------- /Ayiin/__init__.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import time 4 | from os import listdir, mkdir 5 | 6 | import heroku3 7 | from aiohttp import ClientSession 8 | from git import Repo 9 | from git.exc import GitCommandError, InvalidGitRepositoryError 10 | from motor.motor_asyncio import AsyncIOMotorClient as Bot 11 | from rich.console import Console 12 | from rich.table import Table 13 | 14 | from config import (ASSISTANT_PREFIX, DURATION_LIMIT_MIN, LOG_GROUP_ID, 15 | LOG_SESSION) 16 | from config import MONGO_DB_URI as mango 17 | from config import (MUSIC_BOT_NAME, OWNER_ID, STRING1, STRING2, STRING3, 18 | STRING4, STRING5, SUDO_USERS, UPSTREAM_BRANCH, 19 | UPSTREAM_REPO, get_queue) 20 | from Ayiin.Core.Clients.cli import (ASS_CLI_1, ASS_CLI_2, ASS_CLI_3, ASS_CLI_4, 21 | ASS_CLI_5, LOG_CLIENT, app) 22 | from Ayiin.Utilities.changers import time_to_seconds 23 | from Ayiin.Utilities.tasks import install_requirements 24 | 25 | loop = asyncio.get_event_loop() 26 | console = Console() 27 | 28 | 29 | ### Heroku Shit 30 | UPSTREAM_BRANCH = UPSTREAM_BRANCH 31 | UPSTREAM_REPO = UPSTREAM_REPO 32 | 33 | ### Modules 34 | MOD_LOAD = [] 35 | MOD_NOLOAD = [] 36 | 37 | ### Mongo DB 38 | MONGODB_CLI = Bot(mango) 39 | db = MONGODB_CLI.Ayiin 40 | 41 | ### Boot Time 42 | boottime = time.time() 43 | 44 | ### Clients 45 | app = app 46 | ASS_CLI_1 = ASS_CLI_1 47 | ASS_CLI_2 = ASS_CLI_2 48 | ASS_CLI_3 = ASS_CLI_3 49 | ASS_CLI_4 = ASS_CLI_4 50 | ASS_CLI_5 = ASS_CLI_5 51 | LOG_CLIENT = LOG_CLIENT 52 | aiohttpsession = ClientSession() 53 | 54 | ### Config 55 | SUDOERS = SUDO_USERS 56 | OWNER_ID = OWNER_ID 57 | LOG_GROUP_ID = LOG_GROUP_ID 58 | MUSIC_BOT_NAME = MUSIC_BOT_NAME 59 | DURATION_LIMIT = int(time_to_seconds(f"{DURATION_LIMIT_MIN}:00")) 60 | ASSISTANT_PREFIX = ASSISTANT_PREFIX 61 | 62 | ### Bot Info 63 | BOT_ID = 0 64 | BOT_NAME = "" 65 | BOT_USERNAME = "" 66 | 67 | ### Assistant Info 68 | ASSIDS = [] 69 | ASSID1 = 0 70 | ASSNAME1 = "" 71 | ASSUSERNAME1 = "" 72 | ASSMENTION1 = "" 73 | ASSID2 = 0 74 | ASSNAME2 = "" 75 | ASSUSERNAME2 = "" 76 | ASSMENTION2 = "" 77 | ASSID3 = 0 78 | ASSNAME3 = "" 79 | ASSUSERNAME3 = "" 80 | ASSMENTION3 = "" 81 | ASSID4 = 0 82 | ASSNAME4 = "" 83 | ASSUSERNAME4 = "" 84 | ASSMENTION4 = "" 85 | ASSID5 = 0 86 | ASSNAME5 = "" 87 | ASSUSERNAME5 = "" 88 | ASSMENTION5 = "" 89 | random_assistant = [] 90 | 91 | 92 | async def initiate_bot(): 93 | global SUDOERS, OWNER_ID, ASSIDS 94 | global BOT_ID, BOT_NAME, BOT_USERNAME 95 | global ASSID1, ASSNAME1, ASSMENTION1, ASSUSERNAME1 96 | global ASSID2, ASSNAME2, ASSMENTION2, ASSUSERNAME2 97 | global ASSID3, ASSNAME3, ASSMENTION3, ASSUSERNAME3 98 | global ASSID4, ASSNAME4, ASSMENTION4, ASSUSERNAME4 99 | global ASSID5, ASSNAME5, ASSMENTION5, ASSUSERNAME5 100 | global Heroku_cli, Heroku_app 101 | os.system("clear") 102 | header = Table(show_header=True, header_style="bold yellow") 103 | header.add_column( 104 | "\x41\x79\x69\x69\x6e\x20\x4d\x75\x73\x69\x63\x20\x3a\x20\x54\x68\x65\x20\x4d\x6f\x73\x74\x20\x41\x64\x76\x61\x6e\x63\x65\x64\x20\x4d\x75\x73\x69\x63\x20\x42\x6f\x74" 105 | ) 106 | console.print(header) 107 | with console.status( 108 | "[magenta] Ayiin Music Booting...", 109 | ) as status: 110 | console.print("┌ [red]Booting Up The Clients...\n") 111 | await app.start() 112 | console.print("└ [green]Booted Bot Client") 113 | console.print("\n┌ [red]Booting Up The Assistant Clients...") 114 | if STRING1 != "None": 115 | await ASS_CLI_1.start() 116 | random_assistant.append(1) 117 | console.print("├ [yellow]Booted Assistant Client") 118 | if STRING2 != "None": 119 | await ASS_CLI_2.start() 120 | random_assistant.append(2) 121 | console.print("├ [yellow]Booted Assistant Client 2") 122 | if STRING3 != "None": 123 | await ASS_CLI_3.start() 124 | random_assistant.append(3) 125 | console.print("├ [yellow]Booted Assistant Client 3") 126 | if STRING4 != "None": 127 | await ASS_CLI_4.start() 128 | random_assistant.append(4) 129 | console.print("├ [yellow]Booted Assistant Client 4") 130 | if STRING5 != "None": 131 | await ASS_CLI_5.start() 132 | random_assistant.append(5) 133 | console.print("├ [yellow]Booted Assistant Client 5") 134 | console.print("└ [green]Assistant Clients Booted Successfully!") 135 | if LOG_SESSION != "None": 136 | console.print("\n┌ [red]Booting Logger Client") 137 | await LOG_CLIENT.start() 138 | console.print("└ [green]Logger Client Booted Successfully!") 139 | if "raw_files" not in listdir(): 140 | mkdir("raw_files") 141 | if "downloads" not in listdir(): 142 | mkdir("downloads") 143 | if "cache" not in listdir(): 144 | mkdir("cache") 145 | if "search" not in listdir(): 146 | mkdir("search") 147 | console.print("\n┌ [red]Loading Clients Information...") 148 | getme = await app.get_me() 149 | BOT_ID = getme.id 150 | if getme.last_name: 151 | BOT_NAME = getme.first_name + " " + getme.last_name 152 | else: 153 | BOT_NAME = getme.first_name 154 | BOT_USERNAME = getme.username 155 | if STRING1 != "None": 156 | getme1 = await ASS_CLI_1.get_me() 157 | ASSID1 = getme1.id 158 | ASSIDS.append(ASSID1) 159 | ASSNAME1 = ( 160 | f"{getme1.first_name} {getme1.last_name}" 161 | if getme1.last_name 162 | else getme1.first_name 163 | ) 164 | ASSUSERNAME1 = getme1.username 165 | ASSMENTION1 = getme1.mention 166 | if STRING2 != "None": 167 | getme2 = await ASS_CLI_2.get_me() 168 | ASSID2 = getme2.id 169 | ASSIDS.append(ASSID2) 170 | ASSNAME2 = ( 171 | f"{getme2.first_name} {getme2.last_name}" 172 | if getme2.last_name 173 | else getme2.first_name 174 | ) 175 | ASSUSERNAME2 = getme2.username 176 | ASSMENTION2 = getme2.mention 177 | if STRING3 != "None": 178 | getme3 = await ASS_CLI_3.get_me() 179 | ASSID3 = getme3.id 180 | ASSIDS.append(ASSID3) 181 | ASSNAME3 = ( 182 | f"{getme3.first_name} {getme3.last_name}" 183 | if getme3.last_name 184 | else getme3.first_name 185 | ) 186 | ASSUSERNAME3 = getme3.username 187 | ASSMENTION3 = getme3.mention 188 | if STRING4 != "None": 189 | getme4 = await ASS_CLI_4.get_me() 190 | ASSID4 = getme4.id 191 | ASSIDS.append(ASSID4) 192 | ASSNAME4 = ( 193 | f"{getme4.first_name} {getme4.last_name}" 194 | if getme4.last_name 195 | else getme4.first_name 196 | ) 197 | ASSUSERNAME4 = getme4.username 198 | ASSMENTION4 = getme4.mention 199 | if STRING5 != "None": 200 | getme5 = await ASS_CLI_5.get_me() 201 | ASSID5 = getme5.id 202 | ASSIDS.append(ASSID5) 203 | ASSNAME5 = ( 204 | f"{getme5.first_name} {getme5.last_name}" 205 | if getme5.last_name 206 | else getme5.first_name 207 | ) 208 | ASSUSERNAME5 = getme5.username 209 | ASSMENTION5 = getme5.mention 210 | console.print("└ [green]Loaded Clients Information!") 211 | console.print("\n┌ [red]Loading Sudo Users...") 212 | sudoersdb = db.sudoers 213 | sudoers = await sudoersdb.find_one({"sudo": "sudo"}) 214 | sudoers = [] if not sudoers else sudoers["sudoers"] 215 | for user_id in SUDOERS: 216 | if user_id not in sudoers: 217 | sudoers.append(user_id) 218 | await sudoersdb.update_one( 219 | {"sudo": "sudo"}, 220 | {"$set": {"sudoers": sudoers}}, 221 | upsert=True, 222 | ) 223 | SUDOERS = (SUDOERS + sudoers + OWNER_ID) if sudoers else SUDOERS 224 | console.print("└ [green]Loaded Sudo Users Successfully!\n") 225 | try: 226 | repo = Repo() 227 | except GitCommandError: 228 | console.print("┌ [red] Checking Git Updates!") 229 | console.print("└ [red]Git Command Error\n") 230 | return 231 | except InvalidGitRepositoryError: 232 | console.print("┌ [red] Checking Git Updates!") 233 | repo = Repo.init() 234 | if "origin" in repo.remotes: 235 | origin = repo.remote("origin") 236 | else: 237 | origin = repo.create_remote("origin", UPSTREAM_REPO) 238 | origin.fetch() 239 | repo.create_head(UPSTREAM_BRANCH, origin.refs[UPSTREAM_BRANCH]) 240 | repo.heads[UPSTREAM_BRANCH].set_tracking_branch( 241 | origin.refs[UPSTREAM_BRANCH] 242 | ) 243 | repo.heads[UPSTREAM_BRANCH].checkout(True) 244 | try: 245 | repo.create_remote("origin", UPSTREAM_REPO) 246 | except BaseException: 247 | pass 248 | nrs = repo.remote("origin") 249 | nrs.fetch(UPSTREAM_BRANCH) 250 | try: 251 | nrs.pull(UPSTREAM_BRANCH) 252 | except GitCommandError: 253 | repo.git.reset("--hard", "FETCH_HEAD") 254 | await install_requirements( 255 | "pip3 install --no-cache-dir -r requirements.txt" 256 | ) 257 | console.print("└ [red]Git Client Update Completed\n") 258 | 259 | 260 | loop.run_until_complete(initiate_bot()) 261 | 262 | 263 | def init_db(): 264 | global db_mem 265 | db_mem = {} 266 | 267 | 268 | init_db() 269 | -------------------------------------------------------------------------------- /Ayiin/Inline/start.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | from config import MUSIC_BOT_NAME, SUPPORT_CHANNEL, SUPPORT_GROUP 5 | from Ayiin import BOT_USERNAME 6 | 7 | 8 | def setting_markup2(): 9 | buttons = [ 10 | [ 11 | InlineKeyboardButton(text="🔈 Quality", callback_data="AQ"), 12 | InlineKeyboardButton(text="🎚 Volume", callback_data="AV"), 13 | ], 14 | [ 15 | InlineKeyboardButton( 16 | text="👥 Users", callback_data="AU" 17 | ), 18 | InlineKeyboardButton( 19 | text="💻 Dashboard", callback_data="Dashboard" 20 | ), 21 | ], 22 | [ 23 | InlineKeyboardButton(text="•Cʟᴏsᴇ•​", callback_data="close"), 24 | ], 25 | ] 26 | return f"🔧 **{MUSIC_BOT_NAME} Settings**", buttons 27 | 28 | 29 | def start_pannel(): 30 | if not SUPPORT_CHANNEL and not SUPPORT_GROUP: 31 | buttons = [ 32 | [ 33 | InlineKeyboardButton( 34 | text="🗂 Helper Commands", callback_data="yins" 35 | ), 36 | ], 37 | [ 38 | InlineKeyboardButton( 39 | text="🔧 Settings", callback_data="settingm" 40 | ) 41 | ], 42 | ] 43 | return f"🎛 **This is {MUSIC_BOT_NAME}**", buttons 44 | if not SUPPORT_CHANNEL and SUPPORT_GROUP: 45 | buttons = [ 46 | [ 47 | InlineKeyboardButton( 48 | text="🗂 Helper Commands", callback_data="yins" 49 | ), 50 | ], 51 | [ 52 | InlineKeyboardButton( 53 | text="🔧 Settings", callback_data="settingm" 54 | ) 55 | ], 56 | [ 57 | InlineKeyboardButton( 58 | text="📨Group", url=f"{SUPPORT_GROUP}" 59 | ), 60 | ], 61 | ] 62 | return f"🎛 **This is {MUSIC_BOT_NAME}*", buttons 63 | if SUPPORT_CHANNEL and not SUPPORT_GROUP: 64 | buttons = [ 65 | [ 66 | InlineKeyboardButton( 67 | text="🗂 Helper Commands", callback_data="yins" 68 | ), 69 | ], 70 | [ 71 | InlineKeyboardButton( 72 | text="🔧 Settings", callback_data="settingm" 73 | ) 74 | ], 75 | [ 76 | InlineKeyboardButton( 77 | text="📨Channel", url=f"{SUPPORT_CHANNEL}" 78 | ), 79 | ], 80 | ] 81 | return f"🎛 **This is {MUSIC_BOT_NAME}**", buttons 82 | if SUPPORT_CHANNEL and SUPPORT_GROUP: 83 | buttons = [ 84 | [ 85 | InlineKeyboardButton( 86 | text="🗂 Helper Commands", callback_data="yins" 87 | ), 88 | ], 89 | [ 90 | InlineKeyboardButton( 91 | text="🔧 Settings", callback_data="settingm" 92 | ) 93 | ], 94 | [ 95 | InlineKeyboardButton( 96 | text="📨Channel", url=f"{SUPPORT_CHANNEL}" 97 | ), 98 | InlineKeyboardButton( 99 | text="📨Group", url=f"{SUPPORT_GROUP}" 100 | ), 101 | ], 102 | ] 103 | return f"🎛 **This is {MUSIC_BOT_NAME}**", buttons 104 | 105 | 106 | def private_panel(): 107 | if not SUPPORT_CHANNEL and not SUPPORT_GROUP: 108 | buttons = [ 109 | [ 110 | InlineKeyboardButton( 111 | text="🗂 Helper Commands", callback_data="yins" 112 | ), 113 | ], 114 | [ 115 | InlineKeyboardButton( 116 | "➕ Add me to your Group ➕", 117 | url=f"https://t.me/{BOT_USERNAME}?startgroup=true", 118 | ) 119 | ], 120 | ] 121 | return f"🎛 **This is {MUSIC_BOT_NAME}**", buttons 122 | if not SUPPORT_CHANNEL and SUPPORT_GROUP: 123 | buttons = [ 124 | [ 125 | InlineKeyboardButton( 126 | text="🗂 Helper Commands", callback_data="yins" 127 | ), 128 | ], 129 | [ 130 | InlineKeyboardButton( 131 | "➕ Add me to your Group ➕", 132 | url=f"https://t.me/{BOT_USERNAME}?startgroup=true", 133 | ) 134 | ], 135 | [ 136 | InlineKeyboardButton( 137 | text="📨Group", url=f"{SUPPORT_GROUP}" 138 | ), 139 | ], 140 | ] 141 | return f"🎛 **This is {MUSIC_BOT_NAME}*", buttons 142 | if SUPPORT_CHANNEL and not SUPPORT_GROUP: 143 | buttons = [ 144 | [ 145 | InlineKeyboardButton( 146 | text="🗂 Helper Commands", callback_data="yins" 147 | ), 148 | ], 149 | [ 150 | InlineKeyboardButton( 151 | "➕ Add me to your Group ➕", 152 | url=f"https://t.me/{BOT_USERNAME}?startgroup=true", 153 | ) 154 | ], 155 | [ 156 | InlineKeyboardButton( 157 | text="📨Channel", url=f"{SUPPORT_CHANNEL}" 158 | ), 159 | ], 160 | ] 161 | return f"🎛 **This is {MUSIC_BOT_NAME}**", buttons 162 | if SUPPORT_CHANNEL and SUPPORT_GROUP: 163 | buttons = [ 164 | [ 165 | InlineKeyboardButton( 166 | text="🗂 Helper Commands ", callback_data="yins" 167 | ), 168 | ], 169 | [ 170 | InlineKeyboardButton( 171 | "➕ Add me to your Group ➕", 172 | url=f"https://t.me/{BOT_USERNAME}?startgroup=true", 173 | ) 174 | ], 175 | [ 176 | InlineKeyboardButton( 177 | text="📨Channel", url=f"{SUPPORT_CHANNEL}" 178 | ), 179 | InlineKeyboardButton( 180 | text="📨Groups", url=f"{SUPPORT_GROUP}" 181 | ), 182 | ], 183 | ] 184 | return f"🎛 **This is {MUSIC_BOT_NAME}**", buttons 185 | 186 | 187 | def setting_markup(): 188 | buttons = [ 189 | [ 190 | InlineKeyboardButton(text="🔈 Quality", callback_data="AQ"), 191 | InlineKeyboardButton(text="🎚 Volume", callback_data="AV"), 192 | ], 193 | [ 194 | InlineKeyboardButton( 195 | text="👥 Users", callback_data="AU" 196 | ), 197 | InlineKeyboardButton( 198 | text="💻 Dashboard", callback_data="Dashboard" 199 | ), 200 | ], 201 | [ 202 | InlineKeyboardButton(text="•Cʟᴏsᴇ•​", callback_data="close"), 203 | InlineKeyboardButton(text="•Bᴀᴄᴋ​•​", callback_data="okaybhai"), 204 | ], 205 | ] 206 | return f"🔧 **{MUSIC_BOT_NAME} Settings**", buttons 207 | 208 | 209 | def volmarkup(): 210 | buttons = [ 211 | [ 212 | InlineKeyboardButton( 213 | text="🔄 Reset Audio Volume 🔄", callback_data="HV" 214 | ) 215 | ], 216 | [ 217 | InlineKeyboardButton(text="🔈 Low Vol", callback_data="LV"), 218 | InlineKeyboardButton(text="🔉 Medium Vol", callback_data="MV"), 219 | ], 220 | [ 221 | InlineKeyboardButton(text="🔊 High Vol", callback_data="HV"), 222 | InlineKeyboardButton(text="🔈 Amplified Vol", callback_data="VAM"), 223 | ], 224 | [ 225 | InlineKeyboardButton( 226 | text="🔽 Custom Volume 🔽", callback_data="Custommarkup" 227 | ) 228 | ], 229 | [InlineKeyboardButton(text="•Bᴀᴄᴋ​•", callback_data="settingm")], 230 | ] 231 | return f"🔧 **{MUSIC_BOT_NAME} Settings**", buttons 232 | 233 | 234 | def custommarkup(): 235 | buttons = [ 236 | [ 237 | InlineKeyboardButton(text="+10", callback_data="PTEN"), 238 | InlineKeyboardButton(text="-10", callback_data="MTEN"), 239 | ], 240 | [ 241 | InlineKeyboardButton(text="+25", callback_data="PTF"), 242 | InlineKeyboardButton(text="-25", callback_data="MTF"), 243 | ], 244 | [ 245 | InlineKeyboardButton(text="+50", callback_data="PFZ"), 246 | InlineKeyboardButton(text="-50", callback_data="MFZ"), 247 | ], 248 | [InlineKeyboardButton(text="🔼Custom Volume 🔼", callback_data="AV")], 249 | ] 250 | return f"🔧 **{MUSIC_BOT_NAME} Settings**", buttons 251 | 252 | 253 | def usermarkup(): 254 | buttons = [ 255 | [ 256 | InlineKeyboardButton(text="👥 Everyone", callback_data="EVE"), 257 | InlineKeyboardButton(text="🙍 Admins", callback_data="AMS"), 258 | ], 259 | [ 260 | InlineKeyboardButton( 261 | text="📋 Users Lists", callback_data="USERLIST" 262 | ) 263 | ], 264 | [InlineKeyboardButton(text="•Bᴀᴄᴋ​•​", callback_data="settingm")], 265 | ] 266 | return f"🔧 **{MUSIC_BOT_NAME} Settings**", buttons 267 | 268 | 269 | def dashmarkup(): 270 | buttons = [ 271 | [ 272 | InlineKeyboardButton(text="✔️ Uptime", callback_data="UPT"), 273 | InlineKeyboardButton(text="💾 Ram", callback_data="RAT"), 274 | ], 275 | [ 276 | InlineKeyboardButton(text="💻 Cpu", callback_data="CPT"), 277 | InlineKeyboardButton(text="💽 Disk", callback_data="DIT"), 278 | ], 279 | [InlineKeyboardButton(text="•Bᴀᴄᴋ​•", callback_data="settingm")], 280 | ] 281 | return f"🔧 **{MUSIC_BOT_NAME} Settings**", buttons 282 | -------------------------------------------------------------------------------- /Ayiin/Inline/play.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import (CallbackQuery, InlineKeyboardButton, 2 | InlineKeyboardMarkup, InputMediaPhoto, Message) 3 | 4 | from Ayiin import db_mem 5 | 6 | 7 | def url_markup(videoid, duration, user_id, query, query_type): 8 | buttons = [ 9 | [ 10 | InlineKeyboardButton( 11 | text="❮", 12 | callback_data=f"slider B|{query_type}|{query}|{user_id}", 13 | ), 14 | InlineKeyboardButton( 15 | text="🎵", 16 | callback_data=f"MusicStream {videoid}|{duration}|{user_id}", 17 | ), 18 | InlineKeyboardButton( 19 | text="🎥", 20 | callback_data=f"Choose {videoid}|{duration}|{user_id}", 21 | ), 22 | InlineKeyboardButton( 23 | text="❯", 24 | callback_data=f"slider F|{query_type}|{query}|{user_id}", 25 | ), 26 | ], 27 | [ 28 | InlineKeyboardButton( 29 | text="⍟ 𝙼𝙾𝚁𝙴 ⍟", 30 | callback_data=f"Search {query}|{user_id}", 31 | ), 32 | InlineKeyboardButton( 33 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", 34 | callback_data=f"forceclose {query}|{user_id}", 35 | ), 36 | ], 37 | ] 38 | return buttons 39 | 40 | 41 | def url_markup2(videoid, duration, user_id): 42 | buttons = [ 43 | [ 44 | InlineKeyboardButton( 45 | text="⍟ 𝙼𝚄𝚂𝙸𝙲 ​⍟", 46 | callback_data=f"MusicStream {videoid}|{duration}|{user_id}", 47 | ), 48 | InlineKeyboardButton( 49 | text="⍟ 𝚅𝙸𝙳𝙴𝙾 ​⍟", 50 | callback_data=f"Choose {videoid}|{duration}|{user_id}", 51 | ), 52 | ], 53 | [ 54 | InlineKeyboardButton( 55 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", 56 | callback_data=f"forceclose {videoid}|{user_id}", 57 | ) 58 | ], 59 | ] 60 | return buttons 61 | 62 | 63 | def search_markup( 64 | ID1, 65 | ID2, 66 | ID3, 67 | ID4, 68 | ID5, 69 | duration1, 70 | duration2, 71 | duration3, 72 | duration4, 73 | duration5, 74 | user_id, 75 | query, 76 | ): 77 | buttons = [ 78 | [ 79 | InlineKeyboardButton( 80 | text="1️⃣", callback_data=f"Ayiin {ID1}|{duration1}|{user_id}" 81 | ), 82 | InlineKeyboardButton( 83 | text="2️⃣", callback_data=f"Ayiin {ID2}|{duration2}|{user_id}" 84 | ), 85 | InlineKeyboardButton( 86 | text="3️⃣", callback_data=f"Ayiin {ID3}|{duration3}|{user_id}" 87 | ), 88 | ], 89 | [ 90 | InlineKeyboardButton( 91 | text="4️⃣", callback_data=f"Ayiin {ID4}|{duration4}|{user_id}" 92 | ), 93 | InlineKeyboardButton( 94 | text="5️⃣", callback_data=f"Ayiin {ID5}|{duration5}|{user_id}" 95 | ), 96 | ], 97 | [ 98 | InlineKeyboardButton( 99 | text="❮❮", callback_data=f"popat 1|{query}|{user_id}" 100 | ), 101 | InlineKeyboardButton( 102 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"forceclose {query}|{user_id}" 103 | ), 104 | InlineKeyboardButton( 105 | text="❯❯", callback_data=f"popat 1|{query}|{user_id}" 106 | ), 107 | ], 108 | ] 109 | return buttons 110 | 111 | 112 | def search_markup2( 113 | ID6, 114 | ID7, 115 | ID8, 116 | ID9, 117 | ID10, 118 | duration6, 119 | duration7, 120 | duration8, 121 | duration9, 122 | duration10, 123 | user_id, 124 | query, 125 | ): 126 | buttons = [ 127 | [ 128 | InlineKeyboardButton( 129 | text="6️⃣", 130 | callback_data=f"Ayiin {ID6}|{duration6}|{user_id}", 131 | ), 132 | InlineKeyboardButton( 133 | text="7️⃣", 134 | callback_data=f"Ayiin {ID7}|{duration7}|{user_id}", 135 | ), 136 | InlineKeyboardButton( 137 | text="8️⃣", 138 | callback_data=f"Ayiin {ID8}|{duration8}|{user_id}", 139 | ), 140 | ], 141 | [ 142 | InlineKeyboardButton( 143 | text="9️⃣", 144 | callback_data=f"Ayiin {ID9}|{duration9}|{user_id}", 145 | ), 146 | InlineKeyboardButton( 147 | text="🔟", 148 | callback_data=f"Ayiin {ID10}|{duration10}|{user_id}", 149 | ), 150 | ], 151 | [ 152 | InlineKeyboardButton( 153 | text="❮❮", callback_data=f"popat 2|{query}|{user_id}" 154 | ), 155 | InlineKeyboardButton( 156 | text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"forceclose {query}|{user_id}" 157 | ), 158 | InlineKeyboardButton( 159 | text="❯❯", callback_data=f"popat 2|{query}|{user_id}" 160 | ), 161 | ], 162 | ] 163 | return buttons 164 | 165 | 166 | def secondary_markup(videoid, user_id): 167 | buttons = [ 168 | [ 169 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 170 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 171 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 172 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 173 | ], 174 | [ 175 | InlineKeyboardButton( 176 | text="⍟ 𝙼𝙾𝚁𝙴 ​⍟", callback_data=f"other {videoid}|{user_id}" 177 | ), 178 | InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close"), 179 | ], 180 | ] 181 | return buttons 182 | 183 | 184 | def secondary_markup2(videoid, user_id): 185 | buttons = [ 186 | [ 187 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 188 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 189 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 190 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 191 | ], 192 | [ 193 | InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟", callback_data=f"close"), 194 | ], 195 | ] 196 | return buttons 197 | 198 | 199 | def primary_markup(videoid, user_id, current_time, total_time): 200 | if videoid not in db_mem: 201 | db_mem[videoid] = {} 202 | db_mem[videoid]["check"] = 2 203 | buttons = [ 204 | [ 205 | InlineKeyboardButton( 206 | text=f"{total_time} ------------------ {current_time}", 207 | callback_data=f"timer_checkup_markup {videoid}|{user_id}", 208 | ) 209 | ], 210 | [ 211 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 212 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 213 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 214 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 215 | ], 216 | [ 217 | InlineKeyboardButton( 218 | text="⍟ 𝙼𝙾𝚁𝙴 ​⍟", callback_data=f"other {videoid}|{user_id}" 219 | ), 220 | InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close"), 221 | ], 222 | ] 223 | return buttons 224 | 225 | 226 | def timer_markup(videoid, user_id, current_time, total_time): 227 | buttons = [ 228 | [ 229 | InlineKeyboardButton( 230 | text=f"{total_time} ------------------ {current_time}", 231 | callback_data=f"timer_checkup_markup {videoid}|{user_id}", 232 | ) 233 | ], 234 | [ 235 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 236 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 237 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 238 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 239 | ], 240 | [ 241 | InlineKeyboardButton( 242 | text="⍟ 𝙼𝙾𝚁𝙴 ​⍟", callback_data=f"other {videoid}|{user_id}" 243 | ), 244 | InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close"), 245 | ], 246 | ] 247 | return buttons 248 | 249 | 250 | def audio_markup(videoid, user_id, current_time, total_time): 251 | if videoid not in db_mem: 252 | db_mem[videoid] = {} 253 | db_mem[videoid]["check"] = 2 254 | buttons = [ 255 | [ 256 | InlineKeyboardButton( 257 | text=f"{total_time} ------------------ {current_time}", 258 | callback_data=f"timer_checkup_markup {videoid}|{user_id}", 259 | ) 260 | ], 261 | [ 262 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 263 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 264 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 265 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 266 | ], 267 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close")], 268 | ] 269 | return buttons 270 | 271 | 272 | def audio_timer_markup_start(videoid, user_id, current_time, total_time): 273 | buttons = [ 274 | [ 275 | InlineKeyboardButton( 276 | text=f"{total_time} ------------------ {current_time}", 277 | callback_data=f"timer_checkup_markup {videoid}|{user_id}", 278 | ) 279 | ], 280 | [ 281 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 282 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 283 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 284 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 285 | ], 286 | [InlineKeyboardButton(text="⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data=f"close")], 287 | ] 288 | return buttons 289 | 290 | 291 | audio_markup2 = InlineKeyboardMarkup( 292 | [ 293 | [ 294 | InlineKeyboardButton(text="▶️", callback_data=f"resumecb"), 295 | InlineKeyboardButton(text="⏸️", callback_data=f"pausecb"), 296 | InlineKeyboardButton(text="⏭️", callback_data=f"skipcb"), 297 | InlineKeyboardButton(text="⏹️", callback_data=f"stopcb"), 298 | ], 299 | [InlineKeyboardButton("⍟ 𝙲𝙻𝙾𝚂𝙴 ⍟​", callback_data="close")], 300 | ] 301 | ) 302 | -------------------------------------------------------------------------------- /Ayiin/Plugins/Voicechat.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import shutil 4 | import subprocess 5 | from sys import version as pyver 6 | 7 | from pyrogram import Client, filters 8 | from pyrogram.types import (InlineKeyboardMarkup, InputMediaPhoto, Message, 9 | Voice) 10 | 11 | from config import get_queue 12 | from Ayiin import SUDOERS, app, db_mem, random_assistant 13 | from Ayiin.Database import (get_active_chats, get_active_video_chats, 14 | get_assistant, is_active_chat, save_assistant) 15 | from Ayiin.Decorators.checker import checker, checkerCB 16 | from Ayiin.Inline import primary_markup,choose_markup 17 | from Ayiin.Utilities.assistant import get_assistant_details 18 | 19 | loop = asyncio.get_event_loop() 20 | 21 | __MODULE__ = "Join/Leave" 22 | __HELP__ = """ 23 | 24 | **Note:** 25 | Only for Sudo Users 26 | 27 | 28 | /joinassistant [Chat Username or Chat ID] 29 | - Join assistant to a group. 30 | 31 | 32 | /leaveassistant [Chat Username or Chat ID] 33 | - Assistant will leave the particular group. 34 | 35 | 36 | /leavebot [Chat Username or Chat ID] 37 | - Bot will leave the particular chat. 38 | """ 39 | 40 | @app.on_callback_query(filters.regex("gback_list_chose_stream")) 41 | async def gback_list_chose_stream(_, CallbackQuery): 42 | await CallbackQuery.answer() 43 | callback_data = CallbackQuery.data.strip() 44 | callback_request = callback_data.split(None, 1)[1] 45 | videoid, duration, user_id = callback_request.split("|") 46 | if CallbackQuery.from_user.id != int(user_id): 47 | return await CallbackQuery.answer( 48 | "This is not for you! Search You Own Song.", show_alert=True 49 | ) 50 | buttons = choose_markup(videoid, duration, user_id) 51 | await CallbackQuery.edit_message_reply_markup( 52 | reply_markup=InlineKeyboardMarkup(buttons) 53 | ) 54 | 55 | 56 | @app.on_callback_query(filters.regex("pr_go_back_timer")) 57 | async def pr_go_back_timer(_, CallbackQuery): 58 | await CallbackQuery.answer() 59 | callback_data = CallbackQuery.data.strip() 60 | callback_request = callback_data.split(None, 1)[1] 61 | videoid, user_id = callback_request.split("|") 62 | if await is_active_chat(CallbackQuery.message.chat.id): 63 | if db_mem[CallbackQuery.message.chat.id]["videoid"] == videoid: 64 | dur_left = db_mem[CallbackQuery.message.chat.id]["left"] 65 | duration_min = db_mem[CallbackQuery.message.chat.id]["total"] 66 | buttons = primary_markup(videoid, user_id, dur_left, duration_min) 67 | await CallbackQuery.edit_message_reply_markup( 68 | reply_markup=InlineKeyboardMarkup(buttons) 69 | ) 70 | 71 | 72 | @app.on_callback_query(filters.regex("timer_checkup_markup")) 73 | async def timer_checkup_markup(_, CallbackQuery): 74 | callback_data = CallbackQuery.data.strip() 75 | callback_request = callback_data.split(None, 1)[1] 76 | videoid, user_id = callback_request.split("|") 77 | if await is_active_chat(CallbackQuery.message.chat.id): 78 | if db_mem[CallbackQuery.message.chat.id]["videoid"] == videoid: 79 | dur_left = db_mem[CallbackQuery.message.chat.id]["left"] 80 | duration_min = db_mem[CallbackQuery.message.chat.id]["total"] 81 | return await CallbackQuery.answer( 82 | f"Remaining {dur_left} out of {duration_min} Mins.", 83 | show_alert=True, 84 | ) 85 | return await CallbackQuery.answer(f"Not Playing.", show_alert=True) 86 | else: 87 | return await CallbackQuery.answer( 88 | f"No Active Voice Chat", show_alert=True 89 | ) 90 | 91 | 92 | @app.on_message(filters.command("queue")) 93 | async def activevc(_, message: Message): 94 | global get_queue 95 | if await is_active_chat(message.chat.id): 96 | mystic = await message.reply_text("Please Wait... Getting Queue..") 97 | dur_left = db_mem[message.chat.id]["left"] 98 | duration_min = db_mem[message.chat.id]["total"] 99 | got_queue = get_queue.get(message.chat.id) 100 | if not got_queue: 101 | await mystic.edit(f"Nothing in Queue") 102 | fetched = [] 103 | for get in got_queue: 104 | fetched.append(get) 105 | 106 | ### Results 107 | current_playing = fetched[0][0] 108 | user_name = fetched[0][1] 109 | 110 | msg = "**Queued List**\n\n" 111 | msg += "**Currently Playing:**" 112 | msg += "\n▶️" + current_playing[:30] 113 | msg += f"\n ╚By:- {user_name}" 114 | msg += f"\n ╚Duration:- Remaining `{dur_left}` out of `{duration_min}` Mins." 115 | fetched.pop(0) 116 | if fetched: 117 | msg += "\n\n" 118 | msg += "**Up Next In Queue:**" 119 | for song in fetched: 120 | name = song[0][:30] 121 | usr = song[1] 122 | dur = song[2] 123 | msg += f"\n⏸️{name}" 124 | msg += f"\n ╠Duration : {dur}" 125 | msg += f"\n ╚Requested by : {usr}\n" 126 | if len(msg) > 4096: 127 | await mystic.delete() 128 | filename = "queue.txt" 129 | with open(filename, "w+", encoding="utf8") as out_file: 130 | out_file.write(str(msg.strip())) 131 | await message.reply_document( 132 | document=filename, 133 | caption=f"**OUTPUT:**\n\n`Queued List`", 134 | quote=False, 135 | ) 136 | os.remove(filename) 137 | else: 138 | await mystic.edit(msg) 139 | else: 140 | await message.reply_text(f"Nothing in Queue") 141 | 142 | 143 | @app.on_message(filters.command("activevc") & filters.user(SUDOERS)) 144 | async def activevc(_, message: Message): 145 | served_chats = [] 146 | try: 147 | chats = await get_active_chats() 148 | for chat in chats: 149 | served_chats.append(int(chat["chat_id"])) 150 | except Exception as e: 151 | await message.reply_text(f"**Error:-** {e}") 152 | text = "" 153 | j = 0 154 | for x in served_chats: 155 | try: 156 | title = (await app.get_chat(x)).title 157 | except Exception: 158 | title = "Private Group" 159 | if (await app.get_chat(x)).username: 160 | user = (await app.get_chat(x)).username 161 | text += ( 162 | f"{j + 1}. [{title}](https://t.me/{user})[`{x}`]\n" 163 | ) 164 | else: 165 | text += f"{j + 1}. {title} [`{x}`]\n" 166 | j += 1 167 | if not text: 168 | await message.reply_text("No Active Voice Chats") 169 | else: 170 | await message.reply_text( 171 | f"**Active Voice Chats:-**\n\n{text}", 172 | disable_web_page_preview=True, 173 | ) 174 | 175 | 176 | @app.on_message(filters.command("activevideo") & filters.user(SUDOERS)) 177 | async def activevi_(_, message: Message): 178 | served_chats = [] 179 | try: 180 | chats = await get_active_video_chats() 181 | for chat in chats: 182 | served_chats.append(int(chat["chat_id"])) 183 | except Exception as e: 184 | await message.reply_text(f"**Error:-** {e}") 185 | text = "" 186 | j = 0 187 | for x in served_chats: 188 | try: 189 | title = (await app.get_chat(x)).title 190 | except Exception: 191 | title = "Private Group" 192 | if (await app.get_chat(x)).username: 193 | user = (await app.get_chat(x)).username 194 | text += ( 195 | f"{j + 1}. [{title}](https://t.me/{user})[`{x}`]\n" 196 | ) 197 | else: 198 | text += f"{j + 1}. {title} [`{x}`]\n" 199 | j += 1 200 | if not text: 201 | await message.reply_text("No Active Voice Chats") 202 | else: 203 | await message.reply_text( 204 | f"**Active Video Calls:-**\n\n{text}", 205 | disable_web_page_preview=True, 206 | ) 207 | 208 | 209 | @app.on_message(filters.command("joinassistant") & filters.user(SUDOERS)) 210 | async def basffy(_, message): 211 | if len(message.command) != 2: 212 | await message.reply_text( 213 | "**Usage:**\n/joinassistant [Chat Username or Chat ID]" 214 | ) 215 | return 216 | chat = message.text.split(None, 2)[1] 217 | try: 218 | chat_id = (await app.get_chat(chat)).id 219 | except: 220 | return await message.reply_text( 221 | "Add Bot to this Chat First.. Unknown Chat for the bot" 222 | ) 223 | _assistant = await get_assistant(chat_id, "assistant") 224 | if not _assistant: 225 | return await message.reply_text( 226 | "No Pre-Saved Assistant Found.\n\nYou can set Assistant Via /play inside {Chat}'s Group" 227 | ) 228 | else: 229 | ran_ass = _assistant["saveassistant"] 230 | ASS_ID, ASS_NAME, ASS_USERNAME, ASS_ACC = await get_assistant_details( 231 | ran_ass 232 | ) 233 | try: 234 | await ASS_ACC.join_chat(chat_id) 235 | except Exception as e: 236 | await message.reply_text(f"Failed\n**Possible reason could be**:{e}") 237 | return 238 | await message.reply_text("Joined.") 239 | 240 | 241 | @app.on_message(filters.command("leavebot") & filters.user(SUDOERS)) 242 | async def baaaf(_, message): 243 | if len(message.command) != 2: 244 | await message.reply_text( 245 | "**Usage:**\n/leavebot [Chat Username or Chat ID]" 246 | ) 247 | return 248 | chat = message.text.split(None, 2)[1] 249 | try: 250 | await app.leave_chat(chat) 251 | except Exception as e: 252 | await message.reply_text(f"Failed\n**Possible reason could be**:{e}") 253 | print(e) 254 | return 255 | await message.reply_text("Bot has left the chat successfully") 256 | 257 | 258 | @app.on_message(filters.command("leaveassistant") & filters.user(SUDOERS)) 259 | async def baujaf(_, message): 260 | if len(message.command) != 2: 261 | await message.reply_text( 262 | "**Usage:**\n/leave [Chat Username or Chat ID]" 263 | ) 264 | return 265 | chat = message.text.split(None, 2)[1] 266 | try: 267 | chat_id = (await app.get_chat(chat)).id 268 | except: 269 | return await message.reply_text( 270 | "Add Bot to this Chat First.. Unknown Chat for the bot" 271 | ) 272 | _assistant = await get_assistant(chat, "assistant") 273 | if not _assistant: 274 | return await message.reply_text( 275 | "No Pre-Saved Assistant Found.\n\nYou can set Assistant Via /play inside {Chat}'s Group" 276 | ) 277 | else: 278 | ran_ass = _assistant["saveassistant"] 279 | ASS_ID, ASS_NAME, ASS_USERNAME, ASS_ACC = await get_assistant_details( 280 | ran_ass 281 | ) 282 | try: 283 | await ASS_ACC.leave_chat(chat_id) 284 | except Exception as e: 285 | await message.reply_text(f"Failed\n**Possible reason could be**:{e}") 286 | return 287 | await message.reply_text("Left.") 288 | --------------------------------------------------------------------------------