diff --git a/program/__init__.py b/program/__init__.py new file mode 100644 index 0000000..4a13052 --- /dev/null +++ b/program/__init__.py @@ -0,0 +1 @@ +__version__ = "0.6.2 Beta" diff --git a/program/admins.py b/program/admins.py new file mode 100644 index 0000000..0b9be9d --- /dev/null +++ b/program/admins.py @@ -0,0 +1,272 @@ +from cache.admins import admins +from driver.veez import call_py, bot +from pyrogram import Client, filters +from driver.queues import QUEUE, clear_queue +from driver.filters import command, other_filters +from driver.decorators import authorized_users_only +from driver.utils import skip_current_song, skip_item +from program.utils.inline import stream_markup, close_mark, back_mark +from config import BOT_USERNAME, GROUP_SUPPORT, IMG_3, UPDATES_CHANNEL +from pyrogram.types import ( + CallbackQuery, + InlineKeyboardButton, + InlineKeyboardMarkup, + Message, +) + + +@Client.on_message(command(["reload", f"reload@{BOT_USERNAME}"]) & other_filters) +@authorized_users_only +async def update_admin(client, message): + global admins + new_admins = [] + new_ads = await client.get_chat_members(message.chat.id, filter="administrators") + for u in new_ads: + new_admins.append(u.user.id) + admins[message.chat.id] = new_admins + await message.reply_text( + "✅ Bot **reloaded correctly !**\n✅ **Admin list** has **updated !**" + ) + + +@Client.on_message(command(["skip", f"skip@{BOT_USERNAME}", "vskip"]) & other_filters) +@authorized_users_only +async def skip(client, m: Message): + await m.delete() + user_id = m.from_user.id + chat_id = m.chat.id + if len(m.command) < 2: + op = await skip_current_song(chat_id) + if op == 0: + await m.reply("❌ nothing is currently playing") + elif op == 1: + await m.reply("✅ __Queues__ **is empty.**\n\n**• userbot leaving voice chat**") + elif op == 2: + await m.reply("🗑️ **Clearing the Queues**\n\n**• userbot leaving voice chat**") + else: + buttons = stream_markup(user_id) + requester = f"[{m.from_user.first_name}](tg://user?id={m.from_user.id})" + await m.send_photo( + chat_id, + photo=f"{IMG_3}", + reply_markup=InlineKeyboardMarkup(buttons), + caption=f"⏭ **Skipped to the next track.**\n\n🗂 **Name:** [{op[0]}]({op[1]})\n💭 **Chat:** `{chat_id}`\n🧸 **Request by:** {requester}", + ) + else: + skip = m.text.split(None, 1)[1] + OP = "🗑 **removed song from queue:**" + if chat_id in QUEUE: + items = [int(x) for x in skip.split(" ") if x.isdigit()] + items.sort(reverse=True) + for x in items: + if x == 0: + pass + else: + hm = await skip_item(chat_id, x) + if hm == 0: + pass + else: + OP = OP + "\n" + f"**#{x}** - {hm}" + await m.reply(OP) + + +@Client.on_message( + command(["stop", f"stop@{BOT_USERNAME}", "end", f"end@{BOT_USERNAME}", "vstop"]) + & other_filters +) +@authorized_users_only +async def stop(client, m: Message): + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await call_py.leave_group_call(chat_id) + clear_queue(chat_id) + await m.reply("✅ The userbot has disconnected from the video chat.") + except Exception as e: + await m.reply(f"🚫 **error:**\n\n`{e}`") + else: + await m.reply("❌ **nothing is streaming**") + + +@Client.on_message( + command(["pause", f"pause@{BOT_USERNAME}", "vpause"]) & other_filters +) +@authorized_users_only +async def pause(client, m: Message): + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await call_py.pause_stream(chat_id) + await m.reply( + "⏸ **Track paused.**\n\n• **To resume the stream, use the**\n» /resume command." + ) + except Exception as e: + await m.reply(f"🚫 **error:**\n\n`{e}`") + else: + await m.reply("❌ **nothing in streaming**") + + +@Client.on_message( + command(["resume", f"resume@{BOT_USERNAME}", "vresume"]) & other_filters +) +@authorized_users_only +async def resume(client, m: Message): + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await call_py.resume_stream(chat_id) + await m.reply( + "▶️ **Track resumed.**\n\n• **To pause the stream, use the**\n» /pause command." + ) + except Exception as e: + await m.reply(f"🚫 **error:**\n\n`{e}`") + else: + await m.reply("❌ **nothing in streaming**") + + +@Client.on_message( + command(["mute", f"mute@{BOT_USERNAME}", "vmute"]) & other_filters +) +@authorized_users_only +async def mute(client, m: Message): + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await call_py.mute_stream(chat_id) + await m.reply( + "🔇 **Userbot muted.**\n\n• **To unmute the userbot, use the**\n» /unmute command." + ) + except Exception as e: + await m.reply(f"🚫 **error:**\n\n`{e}`") + else: + await m.reply("❌ **nothing in streaming**") + + +@Client.on_message( + command(["unmute", f"unmute@{BOT_USERNAME}", "vunmute"]) & other_filters +) +@authorized_users_only +async def unmute(client, m: Message): + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await call_py.unmute_stream(chat_id) + await m.reply( + "🔊 **Userbot unmuted.**\n\n• **To mute the userbot, use the**\n» /mute command." + ) + except Exception as e: + await m.reply(f"🚫 **error:**\n\n`{e}`") + else: + await m.reply("❌ **nothing in streaming**") + + +@Client.on_callback_query(filters.regex("cbpause")) +async def cbpause(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + chat_id = query.message.chat.id + if chat_id in QUEUE: + try: + await call_py.pause_stream(chat_id) + await query.answer("streaming paused") + await query.edit_message_text( + "⏸ the streaming has paused", reply_markup=back_mark + ) + except Exception as e: + await query.edit_message_text(f"🚫 **error:**\n\n`{e}`", reply_markup=close_mark) + else: + await query.answer("❌ nothing is currently streaming", show_alert=True) + + +@Client.on_callback_query(filters.regex("cbresume")) +async def cbresume(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + chat_id = query.message.chat.id + if chat_id in QUEUE: + try: + await call_py.resume_stream(chat_id) + await query.answer("streaming resumed") + await query.edit_message_text( + "▶️ the streaming has resumed", reply_markup=back_mark + ) + except Exception as e: + await query.edit_message_text(f"🚫 **error:**\n\n`{e}`", reply_markup=close_mark) + else: + await query.answer("❌ nothing is currently streaming", show_alert=True) + + +@Client.on_callback_query(filters.regex("cbstop")) +async def cbstop(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + chat_id = query.message.chat.id + if chat_id in QUEUE: + try: + await call_py.leave_group_call(chat_id) + clear_queue(chat_id) + await query.edit_message_text("✅ **this streaming has ended**", reply_markup=close_mark) + except Exception as e: + await query.edit_message_text(f"🚫 **error:**\n\n`{e}`", reply_markup=close_mark) + else: + await query.answer("❌ nothing is currently streaming", show_alert=True) + + +@Client.on_callback_query(filters.regex("cbmute")) +async def cbmute(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + chat_id = query.message.chat.id + if chat_id in QUEUE: + try: + await call_py.mute_stream(chat_id) + await query.answer("streaming muted") + await query.edit_message_text( + "🔇 userbot succesfully muted", reply_markup=back_mark + ) + except Exception as e: + await query.edit_message_text(f"🚫 **error:**\n\n`{e}`", reply_markup=close_mark) + else: + await query.answer("❌ nothing is currently streaming", show_alert=True) + + +@Client.on_callback_query(filters.regex("cbunmute")) +async def cbunmute(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + chat_id = query.message.chat.id + if chat_id in QUEUE: + try: + await call_py.unmute_stream(chat_id) + await query.answer("streaming unmuted") + await query.edit_message_text( + "🔊 userbot succesfully unmuted", reply_markup=back_mark + ) + except Exception as e: + await query.edit_message_text(f"🚫 **error:**\n\n`{e}`", reply_markup=close_mark) + else: + await query.answer("❌ nothing is currently streaming", show_alert=True) + + +@Client.on_message( + command(["volume", f"volume@{BOT_USERNAME}", "vol"]) & other_filters +) +@authorized_users_only +async def change_volume(client, m: Message): + range = m.command[1] + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await call_py.change_volume_call(chat_id, volume=int(range)) + await m.reply( + f"✅ **volume set to** `{range}`%" + ) + except Exception as e: + await m.reply(f"🚫 **error:**\n\n`{e}`") + else: + await m.reply("❌ **nothing in streaming**") diff --git a/program/callback.py b/program/callback.py new file mode 100644 index 0000000..dbd4968 --- /dev/null +++ b/program/callback.py @@ -0,0 +1,202 @@ +# Copyright (C) 2021 By VeezMusicProject + +from driver.queues import QUEUE +from pyrogram import Client, filters +from program.utils.inline import menu_markup +from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup +from config import ( + ASSISTANT_NAME, + BOT_NAME, + BOT_USERNAME, + GROUP_SUPPORT, + OWNER_NAME, + UPDATES_CHANNEL, +) + + +@Client.on_callback_query(filters.regex("cbstart")) +async def cbstart(_, query: CallbackQuery): + await query.answer("home start") + await query.edit_message_text( + f"""✨ **Welcome [{query.message.chat.first_name}](tg://user?id={query.message.chat.id}) !**\n +💭 **[{BOT_NAME}](https://t.me/{BOT_USERNAME}) allows you to play music and video on groups through the new Telegram's video chats!** + +💡 **Find out all the Bot's commands and how they work by clicking on the » 📚 Commands button!** + +🔖 **To know how to use this bot, please click on the » ❓ Basic Guide button!**""", + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + "➕ Add me to your Group ➕", + url=f"https://t.me/{BOT_USERNAME}?startgroup=true", + ) + ], + [InlineKeyboardButton("❓ Basic Guide", callback_data="cbhowtouse")], + [ + InlineKeyboardButton("📚 Commands", callback_data="cbcmds"), + InlineKeyboardButton("❤ Donate", url=f"https://t.me/{OWNER_NAME}"), + ], + [ + InlineKeyboardButton( + "👥 Official Group", url=f"https://t.me/{GROUP_SUPPORT}" + ), + InlineKeyboardButton( + "📣 Official Channel", url=f"https://t.me/{UPDATES_CHANNEL}" + ), + ], + [ + InlineKeyboardButton( + "🌐 Source Code", url="https://github.com/levina-lab/video-stream" + ) + ], + ] + ), + disable_web_page_preview=True, + ) + + +@Client.on_callback_query(filters.regex("cbhowtouse")) +async def cbguides(_, query: CallbackQuery): + await query.answer("user guide") + await query.edit_message_text( + f"""❓ How to use this Bot ?, read the Guide below ! + +1.) First, add this bot to your Group. +2.) Then, promote this bot as administrator on the Group also give all permissions except Anonymous admin. +3.) After promoting this bot, type /reload in Group to update the admin data. +3.) Invite @{ASSISTANT_NAME} to your group or type /userbotjoin to invite her (unfortunately the userbot will joined by itself when you type `/play (song name)` or `/vplay (song name)`). +4.) Turn on/Start the video chat first before start to play video/music. + +`- END, EVERYTHING HAS BEEN SETUP -` + +📌 If the userbot not joined to video chat, make sure if the video chat already turned on and the userbot in the chat. + +💡 If you have a follow-up questions about this bot, you can tell it on my support chat here: @{GROUP_SUPPORT}.""", + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton("🔙 Go Back", callback_data="cbstart")]] + ), + ) + + +@Client.on_callback_query(filters.regex("cbcmds")) +async def cbcmds(_, query: CallbackQuery): + await query.answer("commands menu") + await query.edit_message_text( + f"""✨ **Hello [{query.message.chat.first_name}](tg://user?id={query.message.chat.id}) !** + +» Choose the menu below to read the explanation & see the list of available Commands ! + +⚡ __Powered by {BOT_NAME} A.I__""", + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton("👷🏻 Admin Cmd", callback_data="cbadmin"), + InlineKeyboardButton("🧙🏻 Sudo Cmd", callback_data="cbsudo"), + ],[ + InlineKeyboardButton("📚 Basic Cmd", callback_data="cbbasic") + ],[ + InlineKeyboardButton("🔙 Go Back", callback_data="cbstart") + ], + ] + ), + ) + + +@Client.on_callback_query(filters.regex("cbbasic")) +async def cbbasic(_, query: CallbackQuery): + await query.answer("basic commands") + await query.edit_message_text( + f"""🏮 here is the basic commands: + +» /play (song name/link) - play music on video chat +» /vplay (video name/link) - play video on video chat +» /vstream - play live video from yt live/m3u8 +» /playlist - show you the playlist +» /video (query) - download video from youtube +» /song (query) - download song from youtube +» /lyric (query) - scrap the song lyric +» /search (query) - search a youtube video link + +» /ping - show the bot ping status +» /uptime - show the bot uptime status +» /alive - show the bot alive info (in Group only) + +⚡️ __Powered by {BOT_NAME} AI__""", + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton("🔙 Go Back", callback_data="cbcmds")]] + ), + ) + + +@Client.on_callback_query(filters.regex("cbadmin")) +async def cbadmin(_, query: CallbackQuery): + await query.answer("admin commands") + await query.edit_message_text( + f"""🏮 here is the admin commands: + +» /pause - pause the stream +» /resume - resume the stream +» /skip - switch to next stream +» /stop - stop the streaming +» /vmute - mute the userbot on voice chat +» /vunmute - unmute the userbot on voice chat +» /volume `1-200` - adjust the volume of music (userbot must be admin) +» /reload - reload bot and refresh the admin data +» /userbotjoin - invite the userbot to join group +» /userbotleave - order userbot to leave from group + +⚡️ __Powered by {BOT_NAME} AI__""", + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton("🔙 Go Back", callback_data="cbcmds")]] + ), + ) + +@Client.on_callback_query(filters.regex("cbsudo")) +async def cbsudo(_, query: CallbackQuery): + await query.answer("sudo commands") + await query.edit_message_text( + f"""🏮 here is the sudo commands: + +» /gban (`username` or `user id`) - for global banned people +» /ungban (`username` or `user id`) - for un-global banned people +» /speedtest - run the bot server speedtest +» /sysinfo - show the system information +» /update - update your bot to latest version +» /restart - restart your bot +» /leaveall - order userbot to leave from all group + +» /broadcast (`message`) - send a broadcast message to all groups entered by bot +» /broadcast_pin (`message`) - send a broadcast message to all groups entered by bot with the chat pin + +⚡ __Powered by {BOT_NAME} AI__""", + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton("🔙 Go Back", callback_data="cbcmds")]] + ), + ) + + +@Client.on_callback_query(filters.regex("cbmenu")) +async def cbmenu(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + chat_id = query.message.chat.id + user_id = query.message.from_user.id + buttons = menu_markup(user_id) + chat = query.message.chat.title + if chat_id in QUEUE: + await query.edit_message_text( + f"⚙️ **Settings of** {chat}\n\n⏸ : pause stream\n▶️ : resume stream\n🔇 : mute userbot\n🔊 : unmute userbot\n⏹ : stop stream", + reply_markup=InlineKeyboardMarkup(buttons), + ) + else: + await query.answer("❌ nothing is currently streaming", show_alert=True) + + +@Client.on_callback_query(filters.regex("cls")) +async def close(_, query: CallbackQuery): + a = await _.get_chat_member(query.message.chat.id, query.from_user.id) + if not a.can_manage_voice_chats: + return await query.answer("💡 Only admin with manage video chat permission that can tap this button !", show_alert=True) + await query.message.delete() diff --git a/program/developer.py b/program/developer.py new file mode 100644 index 0000000..e9aad80 --- /dev/null +++ b/program/developer.py @@ -0,0 +1,188 @@ +import os +import re +import sys +import shutil +import subprocess +import traceback + +from time import time +from io import StringIO +from sys import version as pyver +from inspect import getfullargspec + +from config import BOT_USERNAME as bname +from driver.veez import bot +from driver.filters import command, other_filters +from pyrogram import Client, filters +from driver.decorators import sudo_users_only, errors +from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup + + +async def aexec(code, client, message): + exec( + "async def __aexec(client, message): " + + "".join(f"\n {a}" for a in code.split("\n")) + ) + return await locals()["__aexec"](client, message) + +async def edit_or_reply(msg: Message, **kwargs): + func = msg.edit_text if msg.from_user.is_self else msg.reply + spec = getfullargspec(func.__wrapped__).args + await func(**{k: v for k, v in kwargs.items() if k in spec}) + + +@Client.on_message(command(["eval", f"eval{bname}"]) & other_filters) +@sudo_users_only +async def executor(client, message): + if len(message.command) < 2: + return await edit_or_reply(message, text="» Give a command to execute") + try: + cmd = message.text.split(" ", maxsplit=1)[1] + except IndexError: + return await message.delete() + t1 = time() + old_stderr = sys.stderr + old_stdout = sys.stdout + redirected_output = sys.stdout = StringIO() + redirected_error = sys.stderr = StringIO() + stdout, stderr, exc = None, None, None + try: + await aexec(cmd, client, message) + except Exception: + exc = traceback.format_exc() + stdout = redirected_output.getvalue() + stderr = redirected_error.getvalue() + sys.stdout = old_stdout + sys.stderr = old_stderr + evaluation = "" + if exc: + evaluation = exc + elif stderr: + evaluation = stderr + elif stdout: + evaluation = stdout + else: + evaluation = "SUCCESS" + final_output = f"`OUTPUT:`\n\n```{evaluation.strip()}```" + if len(final_output) > 4096: + filename = "output.txt" + with open(filename, "w+", encoding="utf8") as out_file: + out_file.write(str(evaluation.strip())) + t2 = time() + keyboard = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + text="⏳", callback_data=f"runtime {t2-t1} Seconds" + ) + ] + ] + ) + await message.reply_document( + document=filename, + caption=f"`INPUT:`\n`{cmd[0:980]}`\n\n`OUTPUT:`\n`attached document`", + quote=False, + reply_markup=keyboard, + ) + await message.delete() + os.remove(filename) + else: + t2 = time() + keyboard = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + text="⏳", + callback_data=f"runtime {round(t2-t1, 3)} Seconds", + ) + ] + ] + ) + await edit_or_reply(message, text=final_output, reply_markup=keyboard) + + +@Client.on_callback_query(filters.regex(r"runtime")) +async def runtime_func_cq(_, cq): + runtime = cq.data.split(None, 1)[1] + await cq.answer(runtime, show_alert=True) + + +@Client.on_message(command(["sh", f"sh{bname}"]) & other_filters) +@sudo_users_only +async def shellrunner(client, message): + if len(message.command) < 2: + return await edit_or_reply(message, text="**usage:**\n\n» /sh git pull") + text = message.text.split(None, 1)[1] + if "\n" in text: + code = text.split("\n") + output = "" + for x in code: + shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x) + try: + process = subprocess.Popen( + shell, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + except Exception as err: + print(err) + await edit_or_reply(message, text=f"`ERROR:`\n```{err}```") + output += f"**{code}**\n" + output += process.stdout.read()[:-1].decode("utf-8") + output += "\n" + else: + shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text) + for a in range(len(shell)): + shell[a] = shell[a].replace('"', "") + try: + process = subprocess.Popen( + shell, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + except Exception as err: + print(err) + exc_type, exc_obj, exc_tb = sys.exc_info() + errors = traceback.format_exception( + etype=exc_type, + value=exc_obj, + tb=exc_tb, + ) + return await edit_or_reply( + message, text=f"`ERROR:`\n```{''.join(errors)}```" + ) + output = process.stdout.read()[:-1].decode("utf-8") + if str(output) == "\n": + output = None + if output: + if len(output) > 4096: + with open("output.txt", "w+") as file: + file.write(output) + await bot.send_document( + message.chat.id, + "output.txt", + reply_to_message_id=message.message_id, + caption="`OUTPUT`", + ) + return os.remove("output.txt") + await edit_or_reply(message, text=f"`OUTPUT:`\n```{output}```") + else: + await edit_or_reply(message, text="`OUTPUT:`\n`no output`") + + +@Client.on_message(command(["leavebot", f"leavebot{bname}"]) & other_filters) +@sudo_users_only +async def bot_leave_group(_, message): + if len(message.command) != 2: + await message.reply_text( + "**usage:**\n\n» /leavebot [chat id]" + ) + return + chat = message.text.split(None, 2)[1] + try: + await bot.leave_chat(chat) + except Exception as e: + await message.reply_text(f"❌ procces failed\n\nreason: `{e}`") + print(e) + return + await message.reply_text(f"✅ Bot successfully left from chat: `{chat}`") diff --git a/program/downloader.py b/program/downloader.py new file mode 100644 index 0000000..45c15cb --- /dev/null +++ b/program/downloader.py @@ -0,0 +1,170 @@ +# Copyright (C) 2021 By Veez Music-Project + +from __future__ import unicode_literals + +import os +import re +import math +import time +import asyncio +import lyricsgenius +from random import randint +from urllib.parse import urlparse + +import aiofiles +import aiohttp +import requests +import wget +import yt_dlp +from pyrogram import Client, filters +from pyrogram.errors import FloodWait, MessageNotModified +from pyrogram.types import Message +from youtube_search import YoutubeSearch +from youtubesearchpython import VideosSearch +from yt_dlp import YoutubeDL + +from config import BOT_USERNAME as bn +from driver.decorators import humanbytes +from driver.filters import command, other_filters + + +ydl_opts = { + 'format': 'best', + 'keepvideo': True, + 'prefer_ffmpeg': False, + 'geo_bypass': True, + 'outtmpl': '%(title)s.%(ext)s', + 'quite': True +} + + +@Client.on_message(command(["song", f"song@{bn}"]) & ~filters.edited) +def song(_, message): + query = " ".join(message.command[1:]) + m = message.reply("🔎 finding song...") + ydl_ops = {"format": "bestaudio[ext=m4a]"} + try: + results = YoutubeSearch(query, max_results=1).to_dict() + link = f"https://youtube.com{results[0]['url_suffix']}" + title = results[0]["title"][:40] + thumbnail = results[0]["thumbnails"][0] + thumb_name = f"{title}.jpg" + thumb = requests.get(thumbnail, allow_redirects=True) + open(thumb_name, "wb").write(thumb.content) + duration = results[0]["duration"] + + except Exception as e: + m.edit("❌ song not found.\n\nplease give a valid song name.") + print(str(e)) + return + m.edit("📥 downloading file...") + try: + with yt_dlp.YoutubeDL(ydl_ops) as ydl: + info_dict = ydl.extract_info(link, download=False) + audio_file = ydl.prepare_filename(info_dict) + ydl.process_info(info_dict) + rep = f"• uploader @{bn}" + secmul, dur, dur_arr = 1, 0, duration.split(":") + for i in range(len(dur_arr) - 1, -1, -1): + dur += int(float(dur_arr[i])) * secmul + secmul *= 60 + m.edit("📤 uploading file...") + message.reply_audio( + audio_file, + caption=rep, + thumb=thumb_name, + parse_mode="md", + title=title, + duration=dur, + ) + m.delete() + except Exception as e: + m.edit("❌ error, wait for bot owner to fix") + print(e) + + try: + os.remove(audio_file) + os.remove(thumb_name) + except Exception as e: + print(e) + + +@Client.on_message( + command(["vsong", f"vsong@{bn}", "video", f"video@{bn}"]) & ~filters.edited +) +async def vsong(client, message): + ydl_opts = { + "format": "best", + "keepvideo": True, + "prefer_ffmpeg": False, + "geo_bypass": True, + "outtmpl": "%(title)s.%(ext)s", + "quite": True, + } + query = " ".join(message.command[1:]) + try: + results = YoutubeSearch(query, max_results=1).to_dict() + link = f"https://youtube.com{results[0]['url_suffix']}" + title = results[0]["title"][:40] + thumbnail = results[0]["thumbnails"][0] + thumb_name = f"{title}.jpg" + thumb = requests.get(thumbnail, allow_redirects=True) + open(thumb_name, "wb").write(thumb.content) + results[0]["duration"] + results[0]["url_suffix"] + results[0]["views"] + message.from_user.mention + except Exception as e: + print(e) + try: + msg = await message.reply("📥 **downloading video...**") + with YoutubeDL(ydl_opts) as ytdl: + ytdl_data = ytdl.extract_info(link, download=True) + file_name = ytdl.prepare_filename(ytdl_data) + except Exception as e: + return await msg.edit(f"🚫 **error:** {e}") + preview = wget.download(thumbnail) + await msg.edit("📤 **uploading video...**") + await message.reply_video( + file_name, + duration=int(ytdl_data["duration"]), + thumb=preview, + caption=ytdl_data["title"], + ) + try: + os.remove(file_name) + await msg.delete() + except Exception as e: + print(e) + + +@Client.on_message(command(["lyric", f"lyric@{bn}", "lyrics"])) +async def get_lyric_genius(_, message: Message): + if len(message.command) < 2: + return await message.reply_text("**usage:**\n\n/lyrics (song name)") + m = await message.reply_text("🔍 Searching lyrics...") + query = message.text.split(None, 1)[1] + x = "OXaVabSRKQLqwpiYOn-E4Y7k3wj-TNdL5RfDPXlnXhCErbcqVvdCF-WnMR5TBctI" + y = lyricsgenius.Genius(x) + y.verbose = False + S = y.search_song(query, get_full_info=False) + if S is None: + return await m.edit("❌ `404` lyrics not found") + xxx = f""" +**Song Name:** __{query}__ +**Artist Name:** {S.artist} +**__Lyrics:__** +{S.lyrics}""" + if len(xxx) > 4096: + await m.delete() + filename = "lyrics.txt" + with open(filename, "w+", encoding="utf8") as out_file: + out_file.write(str(xxx.strip())) + await message.reply_document( + document=filename, + caption=f"**OUTPUT:**\n\n`Lyrics Text`", + quote=False, + ) + os.remove(filename) + else: + await m.edit(xxx) diff --git a/program/extra.py b/program/extra.py new file mode 100644 index 0000000..782c50c --- /dev/null +++ b/program/extra.py @@ -0,0 +1,112 @@ +""" broadcast & statistic collector """ + +import asyncio +from pyrogram import Client, filters +from pyrogram.types import Message +from driver.filters import command +from driver.decorators import sudo_users_only +from driver.database.dbchat import get_served_chats + +from config import BOT_USERNAME as bn + + +@Client.on_message(command(["broadcast", f"broadcast@{bn}"]) & ~filters.edited) +@sudo_users_only +async def broadcast(c: Client, message: Message): + if not message.reply_to_message: + pass + else: + x = message.reply_to_message.message_id + y = message.chat.id + sent = 0 + chats = [] + schats = await get_served_chats() + for chat in schats: + chats.append(int(chat["chat_id"])) + for i in chats: + try: + m = await c.forward_messages(i, y, x) + await asyncio.sleep(0.3) + sent += 1 + except Exception: + pass + await message.reply_text(f"✅ Broadcast complete in {sent} Group.") + return + if len(message.command) < 2: + await message.reply_text( + "**usage**:\n\n/broadcast (`message`) or (`reply to message`)" + ) + return + text = message.text.split(None, 1)[1] + sent = 0 + chats = [] + schats = await get_served_chats() + for chat in schats: + chats.append(int(chat["chat_id"])) + for i in chats: + try: + m = await c.send_message(i, text=text) + await asyncio.sleep(0.3) + sent += 1 + except Exception: + pass + await message.reply_text(f"✅ Broadcast complete in {sent} Group.") + + +@Client.on_message(command(["broadcast_pin", f"broadcast_pin@{bn}"]) & ~filters.edited) +@sudo_users_only +async def broadcast_pin(c: Client, message: Message): + if not message.reply_to_message: + pass + else: + x = message.reply_to_message.message_id + y = message.chat.id + sent = 0 + pin = 0 + chats = [] + schats = await get_served_chats() + for chat in schats: + chats.append(int(chat["chat_id"])) + for i in chats: + try: + m = await c.forward_messages(i, y, x) + try: + await m.pin(disable_notification=True) + pin += 1 + except Exception: + pass + await asyncio.sleep(0.3) + sent += 1 + except Exception: + pass + await message.reply_text( + f"✅ Broadcast complete in {sent} Group.\n📌 With the {pin} pins." + ) + return + if len(message.command) < 2: + await message.reply_text( + "**usage**:\n\n/broadcast (`message`) or (`reply to message`)" + ) + return + text = message.text.split(None, 1)[1] + sent = 0 + pin = 0 + chats = [] + schats = await get_served_chats() + for chat in schats: + chats.append(int(chat["chat_id"])) + for i in chats: + try: + m = await c.send_message(i, text=text) + try: + await m.pin(disable_notification=True) + pin += 1 + except Exception: + pass + await asyncio.sleep(0.3) + sent += 1 + except Exception: + pass + await message.reply_text( + f"✅ Broadcast complete in {sent} Group.\n📌 With the {pin} pins." + ) diff --git a/program/inline.py b/program/inline.py new file mode 100644 index 0000000..a54377f --- /dev/null +++ b/program/inline.py @@ -0,0 +1,48 @@ +from pyrogram import Client, errors +from pyrogram.types import ( + InlineQuery, + InlineQueryResultArticle, + InputTextMessageContent, +) +from youtubesearchpython import VideosSearch + + +@Client.on_inline_query() +async def inline(client: Client, query: InlineQuery): + answers = [] + search_query = query.query.lower().strip().rstrip() + + if search_query == "": + await client.answer_inline_query( + query.id, + results=answers, + switch_pm_text="type a youtube video name...", + switch_pm_parameter="help", + cache_time=0, + ) + else: + search = VideosSearch(search_query, limit=50) + + for result in search.result()["result"]: + answers.append( + InlineQueryResultArticle( + title=result["title"], + description="{}, {} views.".format( + result["duration"], result["viewCount"]["short"] + ), + input_message_content=InputTextMessageContent( + "🔗 https://www.youtube.com/watch?v={}".format(result["id"]) + ), + thumb_url=result["thumbnails"][0]["url"], + ) + ) + + try: + await query.answer(results=answers, cache_time=0) + except errors.QueryIdInvalid: + await query.answer( + results=answers, + cache_time=0, + switch_pm_text="error: search timed out", + switch_pm_parameter="", + ) diff --git a/program/playlist.py b/program/playlist.py new file mode 100644 index 0000000..9f39444 --- /dev/null +++ b/program/playlist.py @@ -0,0 +1,39 @@ +# Copyright (C) 2021 By Veez Music-Project +# Commit Start Date 20/10/2021 +# Finished On 28/10/2021 + +from config import BOT_USERNAME +from pyrogram.types import ( + CallbackQuery, + InlineKeyboardButton, + InlineKeyboardMarkup, + Message, +) +from pyrogram import Client, filters +from driver.queues import QUEUE, get_queue +from driver.filters import command, other_filters + + +keyboard = InlineKeyboardMarkup( + [[InlineKeyboardButton("🗑 Close", callback_data="cls")]] +) + + +@Client.on_message(command(["playlist", f"playlist@{BOT_USERNAME}", "queue", f"queue@{BOT_USERNAME}"]) & other_filters) +async def playlist(client, m: Message): + chat_id = m.chat.id + if chat_id in QUEUE: + chat_queue = get_queue(chat_id) + if len(chat_queue)==1: + await m.reply(f"💡 **Currently Streaming:**\n\n• [{chat_queue[0][0]}]({chat_queue[0][2]}) | `{chat_queue[0][3]}`", reply_markup=keyboard, disable_web_page_preview=True) + else: + QUE = f"💡 **Currently Streaming:**\n\n• [{chat_queue[0][0]}]({chat_queue[0][2]}) | `{chat_queue[0][3]}` \n\n**📖 Queue List:**\n" + l = len(chat_queue) + for x in range (1, l): + han = chat_queue[x][0] + hok = chat_queue[x][2] + hap = chat_queue[x][3] + QUE = QUE + "\n" + f"**#{x}** - [{han}]({hok}) | `{hap}`" + await m.reply(QUE, reply_markup=keyboard, disable_web_page_preview=True) + else: + await m.reply("❌ **nothing is currently streaming.**") diff --git a/program/punishment.py b/program/punishment.py new file mode 100644 index 0000000..ae3129f --- /dev/null +++ b/program/punishment.py @@ -0,0 +1,173 @@ +""" global banned and un-global banned module """ + +import asyncio + +from pyrogram import Client, filters +from pyrogram.types import Message +from pyrogram.errors import FloodWait +from driver.filters import command +from driver.decorators import sudo_users_only +from driver.database.dbchat import get_served_chats +from driver.database.dbpunish import add_gban_user, is_gbanned_user, remove_gban_user + +from config import BOT_NAME, SUDO_USERS, BOT_USERNAME as bn + + +@Client.on_message(command(["gban", f"gban@{bn}"]) & ~filters.edited) +@sudo_users_only +async def global_banned(c: Client, message: Message): + if not message.reply_to_message: + if len(message.command) < 2: + await message.reply_text("**usage:**\n\n/gban [username | user_id]") + return + user = message.text.split(None, 2)[1] + if "@" in user: + user = user.replace("@", "") + user = await c.get_users(user) + from_user = message.from_user + BOT_ID = await c.get_me() + if user.id == from_user.id: + return await message.reply_text( + "You can't gban yourself !" + ) + elif user.id == BOT_ID: + await message.reply_text("I can't gban myself !") + elif user.id in SUDO_USERS: + await message.reply_text("You can't gban sudo user !") + else: + await add_gban_user(user.id) + served_chats = [] + chats = await get_served_chats() + for chat in chats: + served_chats.append(int(chat["chat_id"])) + m = await message.reply_text( + f"🚷 **Globally banning {user.mention}**\n⏱ Expected time: `{len(served_chats)}`" + ) + number_of_chats = 0 + for num in served_chats: + try: + await c.ban_chat_member(num, user.id) + number_of_chats += 1 + await asyncio.sleep(1) + except FloodWait as e: + await asyncio.sleep(int(e.x)) + except Exception: + pass + ban_text = f""" +🚷 **New Global ban on [{BOT_NAME}](https://t.me/{bn}) + +**Origin:** {message.chat.title} [`{message.chat.id}`] +**Sudo User:** {from_user.mention} +**Banned User:** {user.mention} +**Banned User ID:** `{user.id}` +**Chats:** `{number_of_chats}`""" + try: + await m.delete() + except Exception: + pass + await message.reply_text( + f"{ban_text}", + disable_web_page_preview=True, + ) + return + from_user_id = message.from_user.id + from_user_mention = message.from_user.mention + user_id = message.reply_to_message.from_user.id + mention = message.reply_to_message.from_user.mention + BOT_ID = await c.get_me() + if user_id == from_user_id: + await message.reply_text("You can't gban yourself !") + elif user_id == BOT_ID: + await message.reply_text("I can't gban myself !") + elif user_id in SUDO_USERS: + await message.reply_text("You can't gban sudo user !") + else: + is_gbanned = await is_gbanned_user(user_id) + if is_gbanned: + await message.reply_text("This user already gbanned !") + else: + await add_gban_user(user_id) + served_chats = [] + chats = await get_served_chats() + for chat in chats: + served_chats.append(int(chat["chat_id"])) + m = await message.reply_text( + f"🚷 **Globally banning {mention}**\n⏱ Expected time: `{len(served_chats)}`" + ) + number_of_chats = 0 + for num in served_chats: + try: + await c.ban_chat_member(num, user_id) + number_of_chats += 1 + await asyncio.sleep(1) + except FloodWait as e: + await asyncio.sleep(int(e.x)) + except Exception: + pass + ban_text = f""" +🚷 **New Global ban on [{BOT_NAME}](https://t.me/{bn}) + +**Origin:** {message.chat.title} [`{message.chat.id}`] +**Sudo User:** {from_user_mention} +**Banned User:** {mention} +**Banned User ID:** `{user_id}` +**Chats:** `{number_of_chats}`""" + try: + await m.delete() + except Exception: + pass + await message.reply_text( + f"{ban_text}", + disable_web_page_preview=True, + ) + return + + +@Client.on_message(command(["ungban", f"ungban@{bn}"]) & ~filters.edited) +@sudo_users_only +async def ungban_global(c: Client, message: Message): + if not message.reply_to_message: + if len(message.command) != 2: + await message.reply_text( + "**usage:**\n\n/ungban [username | user_id]" + ) + return + user = message.text.split(None, 1)[1] + if "@" in user: + user = user.replace("@", "") + user = await c.get_users(user) + from_user = message.from_user + BOT_ID = await c.get_me() + if user.id == from_user.id: + await message.reply_text("You can't ungban yourself because you can't be gbanned !") + elif user.id == BOT_ID: + await message.reply_text("I can't ungban myself because i can't be gbanned !") + elif user.id in SUDO_USERS: + await message.reply_text("Sudo users can't be gbanned/ungbanned !") + else: + is_gbanned = await is_gbanned_user(user.id) + if not is_gbanned: + await message.reply_text("This user already ungbanned.") + else: + await remove_gban_user(user.id) + await message.reply_text("✅ This user has ungbanned.") + return + from_user_id = message.from_user.id + user_id = message.reply_to_message.from_user.id + mention = message.reply_to_message.from_user.mention + BOT_ID = await c.get_me() + if user_id == from_user_id: + await message.reply_text("You can't ungban yourself because you can't be gbanned !") + elif user_id == BOT_ID: + await message.reply_text( + "I can't ungban myself because i can't be gbanned !" + ) + elif user_id in SUDO_USERS: + await message.reply_text("Sudo users can't be gbanned/ungbanned !") + else: + is_gbanned = await is_gbanned_user(user_id) + if not is_gbanned: + await message.reply_text("This user already un-gbanned") + else: + await remove_gban_user(user_id) + await message.reply_text("✅ This user has ungbanned.") diff --git a/program/rmtrash b/program/rmtrash new file mode 100644 index 0000000..b5e8ff1 --- /dev/null +++ b/program/rmtrash @@ -0,0 +1,52 @@ +# Copyright (C) 2021 By VeezMusicProject + +import os +from pyrogram import Client, filters +from pyrogram.types import Message +from driver.filters import command, other_filters +from driver.decorators import sudo_users_only, errors + +downloads = os.path.realpath("program/downloads") +raw = os.path.realpath(".") + +@Client.on_message(command(["rmd", "clear"]) & ~filters.edited) +@errors +@sudo_users_only +async def clear_downloads(_, message: Message): + ls_dir = os.listdir(downloads) + if ls_dir: + for file in os.listdir(downloads): + os.remove(os.path.join(downloads, file)) + await message.reply_text("✅ **deleted all downloaded files**") + else: + await message.reply_text("❌ **no files downloaded**") + + +@Client.on_message(command(["rmw", "clean"]) & ~filters.edited) +@errors +@sudo_users_only +async def clear_raw(_, message: Message): + ls_dir = os.listdir(raw) + if ls_dir: + for file in os.listdir(raw): + if file.endswith('.raw'): + os.remove(os.path.join(raw, file)) + await message.reply_text("✅ **deleted all raw files**") + else: + await message.reply_text("❌ **no raw files found**") + + +@Client.on_message(command(["cleanup"]) & ~filters.edited) +@errors +@sudo_users_only +async def cleanup(_, message: Message): + pth = os.path.realpath(".") + ls_dir = os.listdir(pth) + if ls_dir: + for dta in os.listdir(pth): + os.system("rm -rf *.raw *.jpg") + await message.reply_text("✅ **cleaned**") + else: + await message.reply_text("✅ **already cleaned**") + +# this module has deactivated because no longer used if you want to take the code just take it and use it, Thanks diff --git a/program/speedtest.py b/program/speedtest.py new file mode 100644 index 0000000..2edbc9e --- /dev/null +++ b/program/speedtest.py @@ -0,0 +1,52 @@ +# credit to TeamYukki for this speedtest module + +import os +import wget +import speedtest + +from program.utils.formatters import bytes +from driver.filters import command, other_filters +from driver.decorators import sudo_users_only +from config import BOT_USERNAME as bname +from driver.veez import bot as app +from pyrogram import Client, filters +from pyrogram.types import Message + + +@Client.on_message(command(["speedtest", f"speedtest@{bname}"]) & ~filters.edited) +@sudo_users_only +async def run_speedtest(_, message: Message): + m = await message.reply_text("⚡️ running server speedtest") + try: + test = speedtest.Speedtest() + test.get_best_server() + m = await m.edit("⚡️ running download speedtest..") + test.download() + m = await m.edit("⚡️ running upload speedtest...") + test.upload() + test.results.share() + result = test.results.dict() + except Exception as e: + await m.edit(e) + return + m = await m.edit("🔄 sharing speedtest results") + path = wget.download(result["share"]) + + output = f"""💡 **SpeedTest Results** + +**Client:** +**ISP:** {result['client']['isp']} +**Country:** {result['client']['country']} + +**Server:** +**Name:** {result['server']['name']} +**Country:** {result['server']['country']}, {result['server']['cc']} +**Sponsor:** {result['server']['sponsor']} +**Latency:** {result['server']['latency']} + +⚡️ **Ping:** {result['ping']}""" + msg = await app.send_photo( + chat_id=message.chat.id, photo=path, caption=output + ) + os.remove(path) + await m.delete() diff --git a/program/start.py b/program/start.py new file mode 100644 index 0000000..b5c3679 --- /dev/null +++ b/program/start.py @@ -0,0 +1,186 @@ +from datetime import datetime +from sys import version_info +from time import time + +from config import ( + ALIVE_IMG, + ALIVE_NAME, + BOT_NAME, + BOT_USERNAME, + GROUP_SUPPORT, + OWNER_NAME, + UPDATES_CHANNEL, +) +from program import __version__ +from driver.veez import user +from driver.filters import command, other_filters +from driver.database.dbpunish import is_gbanned_user +from pyrogram import Client, filters +from pyrogram import __version__ as pyrover +from pytgcalls import (__version__ as pytover) +from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message + +__major__ = 0 +__minor__ = 2 +__micro__ = 1 + +__python_version__ = f"{version_info[0]}.{version_info[1]}.{version_info[2]}" + + +START_TIME = datetime.utcnow() +START_TIME_ISO = START_TIME.replace(microsecond=0).isoformat() +TIME_DURATION_UNITS = ( + ("week", 60 * 60 * 24 * 7), + ("day", 60 * 60 * 24), + ("hour", 60 * 60), + ("min", 60), + ("sec", 1), +) + + +async def _human_time_duration(seconds): + if seconds == 0: + return "inf" + parts = [] + for unit, div in TIME_DURATION_UNITS: + amount, seconds = divmod(int(seconds), div) + if amount > 0: + parts.append("{} {}{}".format(amount, unit, "" if amount == 1 else "s")) + return ", ".join(parts) + + +@Client.on_message( + command(["start", f"start@{BOT_USERNAME}"]) & filters.private & ~filters.edited +) +async def start_(client: Client, message: Message): + await message.reply_text( + f"""✨ **Welcome {message.from_user.mention()} !**\n +💭 [{BOT_NAME}](https://t.me/{BOT_USERNAME}) **Allows you to play music and video on groups through the new Telegram's video chats!** + +💡 **Find out all the Bot's commands and how they work by clicking on the » 📚 Commands button!** + +🔖 **To know how to use this bot, please click on the » ❓ Basic Guide button!** +""", + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + "➕ Add me to your Group ➕", + url=f"https://t.me/{BOT_USERNAME}?startgroup=true", + ) + ], + [InlineKeyboardButton("❓ Basic Guide", callback_data="cbhowtouse")], + [ + InlineKeyboardButton("📚 Commands", callback_data="cbcmds"), + InlineKeyboardButton("❤️ Donate", url=f"https://t.me/{OWNER_NAME}"), + ], + [ + InlineKeyboardButton( + "👥 Official Group", url=f"https://t.me/{GROUP_SUPPORT}" + ), + InlineKeyboardButton( + "📣 Official Channel", url=f"https://t.me/{UPDATES_CHANNEL}" + ), + ], + [ + InlineKeyboardButton( + "🌐 Source Code", url="https://github.com/levina-lab/video-stream" + ) + ], + ] + ), + disable_web_page_preview=True, + ) + + +@Client.on_message( + command(["alive", f"alive@{BOT_USERNAME}"]) & filters.group & ~filters.edited +) +async def alive(c: Client, message: Message): + chat_id = message.chat.id + current_time = datetime.utcnow() + uptime_sec = (current_time - START_TIME).total_seconds() + uptime = await _human_time_duration(int(uptime_sec)) + + keyboard = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton("✨ Group", url=f"https://t.me/{GROUP_SUPPORT}"), + InlineKeyboardButton( + "📣 Channel", url=f"https://t.me/{UPDATES_CHANNEL}" + ), + ] + ] + ) + + alive = f"**Hello {message.from_user.mention()}, i'm {BOT_NAME}**\n\n🧑🏼‍💻 My Master: [{ALIVE_NAME}](https://t.me/{OWNER_NAME})\n👾 Bot Version: `v{__version__}`\n🔥 Pyrogram Version: `{pyrover}`\n🐍 Python Version: `{__python_version__}`\n✨ PyTgCalls Version: `{pytover.__version__}`\n🆙 Uptime Status: `{uptime}`\n\n❤ **Thanks for Adding me here, for playing video & music on your Group's video chat**" + + await c.send_photo( + chat_id, + photo=f"{ALIVE_IMG}", + caption=alive, + reply_markup=keyboard, + ) + + +@Client.on_message(command(["ping", f"ping@{BOT_USERNAME}"]) & ~filters.edited) +async def ping_pong(client: Client, message: Message): + start = time() + m_reply = await message.reply_text("pinging...") + delta_ping = time() - start + await m_reply.edit_text("🏓 `PONG!!`\n" f"⚡️ `{delta_ping * 1000:.3f} ms`") + + +@Client.on_message(command(["uptime", f"uptime@{BOT_USERNAME}"]) & ~filters.edited) +async def get_uptime(client: Client, message: Message): + current_time = datetime.utcnow() + uptime_sec = (current_time - START_TIME).total_seconds() + uptime = await _human_time_duration(int(uptime_sec)) + await message.reply_text( + "🤖 bot status:\n" + f"• **uptime:** `{uptime}`\n" + f"• **start time:** `{START_TIME_ISO}`" + ) + + +@Client.on_message(filters.new_chat_members) +async def new_chat(c: Client, m: Message): + ass_uname = (await user.get_me()).username + bot_id = (await c.get_me()).id + for member in m.new_chat_members: + if member.id == bot_id: + return await m.reply( + "❤️ Thanks for adding me to the **Group** !\n\n" + "Appoint me as administrator in the **Group**, otherwise I will not be able to work properly, and don't forget to type `/userbotjoin` for invite the assistant.\n\n" + "Once done, then type `/reload`", + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton("📣 Channel", url=f"https://t.me/{UPDATES_CHANNEL}"), + InlineKeyboardButton("💭 Support", url=f"https://t.me/{GROUP_SUPPORT}") + ], + [ + InlineKeyboardButton("👤 Assistant", url=f"https://t.me/{ass_uname}") + ] + ] + ) + ) + + +chat_watcher_group = 5 + +@Client.on_message(group=chat_watcher_group) +async def chat_watcher_func(_, message: Message): + try: + userid = message.from_user.id + except Exception: + return + suspect = f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})" + if await is_gbanned_user(userid): + try: + await message.chat.ban_member(userid) + except Exception: + return + await message.reply_text( + f"👮🏼 (> {suspect} <)\n\n**Gbanned** user joined, that user has been gbanned by sudo user and was blocked from this Chat !\n\n🚫 **Reason:** potential spammer and abuser." + ) diff --git a/program/sysinfo.py b/program/sysinfo.py new file mode 100644 index 0000000..d85bb6d --- /dev/null +++ b/program/sysinfo.py @@ -0,0 +1,53 @@ +# Copyright (C) 2021 Veez Project + +import re +import uuid +import socket + +import psutil +import platform +from config import BOT_USERNAME +from driver.filters import command +from pyrogram import Client, filters +from driver.decorators import sudo_users_only, humanbytes + + +# FETCH SYSINFO + +@Client.on_message(command(["sysinfo", f"sysinfo@{BOT_USERNAME}"]) & ~filters.edited) +@sudo_users_only +async def give_sysinfo(client, message): + splatform = platform.system() + platform_release = platform.release() + platform_version = platform.version() + architecture = platform.machine() + hostname = socket.gethostname() + ip_address = socket.gethostbyname(socket.gethostname()) + mac_address = ":".join(re.findall("..", "%012x" % uuid.getnode())) + processor = platform.processor() + ram = humanbytes(round(psutil.virtual_memory().total)) + cpu_freq = psutil.cpu_freq().current + if cpu_freq >= 1000: + cpu_freq = f"{round(cpu_freq / 1000, 2)}GHz" + else: + cpu_freq = f"{round(cpu_freq, 2)}MHz" + du = psutil.disk_usage(client.workdir) + psutil.disk_io_counters() + disk = f"{humanbytes(du.used)} / {humanbytes(du.total)} " f"({du.percent}%)" + cpu_len = len(psutil.Process().cpu_affinity()) + somsg = f"""🖥 **System Information** + +**PlatForm :** `{splatform}` +**PlatForm - Release :** `{platform_release}` +**PlatForm - Version :** `{platform_version}` +**Architecture :** `{architecture}` +**HostName :** `{hostname}` +**IP :** `{ip_address}` +**Mac :** `{mac_address}` +**Processor :** `{processor}` +**Ram : ** `{ram}` +**CPU :** `{cpu_len}` +**CPU FREQ :** `{cpu_freq}` +**DISK :** `{disk}` + """ + await message.reply(somsg) diff --git a/program/updater.py b/program/updater.py new file mode 100644 index 0000000..5fdf9d2 --- /dev/null +++ b/program/updater.py @@ -0,0 +1,78 @@ +import os +import re +import sys +import asyncio +import subprocess +from asyncio import sleep + +from git import Repo +from pyrogram.types import Message +from driver.filters import command +from pyrogram import Client, filters +from os import system, execle, environ +from driver.decorators import sudo_users_only +from git.exc import InvalidGitRepositoryError +from config import UPSTREAM_REPO, BOT_USERNAME + + + +def gen_chlog(repo, diff): + upstream_repo_url = Repo().remotes[0].config_reader.get("url").replace(".git", "") + ac_br = repo.active_branch.name + ch_log = tldr_log = "" + ch = f"updates for [{ac_br}]:" + ch_tl = f"updates for {ac_br}:" + d_form = "%d/%m/%y || %H:%M" + for c in repo.iter_commits(diff): + ch_log += ( + f"\n\n💬 {c.count()} 🗓 [{c.committed_datetime.strftime(d_form)}]\n" + f"[{c.summary}] 👨‍💻 {c.author}" + ) + tldr_log += f"\n\n💬 {c.count()} 🗓 [{c.committed_datetime.strftime(d_form)}]\n[{c.summary}] 👨‍💻 {c.author}" + if ch_log: + return str(ch + ch_log), str(ch_tl + tldr_log) + return ch_log, tldr_log + + +def updater(): + try: + repo = Repo() + except InvalidGitRepositoryError: + repo = Repo.init() + origin = repo.create_remote("upstream", UPSTREAM_REPO) + origin.fetch() + repo.create_head("main", origin.refs.main) + repo.heads.main.set_tracking_branch(origin.refs.main) + repo.heads.main.checkout(True) + ac_br = repo.active_branch.name + if "upstream" in repo.remotes: + ups_rem = repo.remote("upstream") + else: + ups_rem = repo.create_remote("upstream", UPSTREAM_REPO) + ups_rem.fetch(ac_br) + changelog, tl_chnglog = gen_chlog(repo, f"HEAD..upstream/{ac_br}") + return bool(changelog) + + +@Client.on_message(command(["update", f"update@{BOT_USERNAME}"]) & ~filters.edited) +@sudo_users_only +async def update_repo(_, message: Message): + chat_id = message.chat.id + msg = await message.reply("🔄 `processing update...`") + update_avail = updater() + if update_avail: + await msg.edit("✅ update finished\n\n• bot restarted, back active again in 1 minutes.") + system("git pull -f && pip3 install --no-cache-dir -r requirements.txt") + execle(sys.executable, sys.executable, "main.py", environ) + return + await msg.edit(f"bot is **up-to-date** with [main]({UPSTREAM_REPO}/tree/main)", disable_web_page_preview=True) + + +@Client.on_message(command(["restart", f"restart@{BOT_USERNAME}"]) & ~filters.edited) +@sudo_users_only +async def restart_bot(_, message: Message): + msg = await message.reply("`restarting bot...`") + args = [sys.executable, "main.py"] + await msg.edit("✅ bot restarted\n\n• now you can use this bot again.") + execle(sys.executable, *args, environ) + return diff --git a/program/userbot_tools.py b/program/userbot_tools.py new file mode 100644 index 0000000..499185d --- /dev/null +++ b/program/userbot_tools.py @@ -0,0 +1,86 @@ +import asyncio +from driver.veez import user +from pyrogram.types import Message +from pyrogram import Client, filters +from config import BOT_USERNAME, SUDO_USERS +from driver.filters import command, other_filters +from pyrogram.errors import UserAlreadyParticipant, UserNotParticipant +from driver.decorators import authorized_users_only, sudo_users_only + + +@Client.on_message( + command(["userbotjoin", f"userbotjoin@{BOT_USERNAME}"]) & other_filters +) +@authorized_users_only +async def join_chat(c: Client, m: Message): + chat_id = m.chat.id + try: + invitelink = await c.export_chat_invite_link(chat_id) + if invitelink.startswith("https://t.me/+"): + invitelink = invitelink.replace( + "https://t.me/+", "https://t.me/joinchat/" + ) + await user.join_chat(invitelink) + return await user.send_message(chat_id, "✅ userbot joined chat") + except UserAlreadyParticipant: + return await user.send_message(chat_id, "✅ userbot already in chat") + + +@Client.on_message( + command(["userbotleave", f"userbotleave@{BOT_USERNAME}"]) & other_filters +) +@authorized_users_only +async def leave_chat(_, m: Message): + chat_id = m.chat.id + try: + await user.leave_chat(chat_id) + return await _.send_message( + chat_id, + "✅ userbot leaved chat", + ) + except UserNotParticipant: + return await _.send_message( + chat_id, + "❌ userbot already leave chat", + ) + + +@Client.on_message(command(["leaveall", f"leaveall@{BOT_USERNAME}"])) +@sudo_users_only +async def leave_all(client, message): + if message.from_user.id not in SUDO_USERS: + return + + left = 0 + failed = 0 + + msg = await message.reply("🔄 Userbot leaving all Group !") + async for dialog in user.iter_dialogs(): + try: + await user.leave_chat(dialog.chat.id) + left += 1 + await msg.edit( + f"Userbot leaving all Group...\n\nLeft: {left} chats.\nFailed: {failed} chats." + ) + except BaseException: + failed += 1 + await msg.edit( + f"Userbot leaving...\n\nLeft: {left} chats.\nFailed: {failed} chats." + ) + await asyncio.sleep(0.7) + await msg.delete() + await client.send_message( + message.chat.id, f"✅ Left from: {left} chats.\n❌ Failed in: {failed} chats." + ) + + +@Client.on_message(filters.left_chat_member) +async def ubot_leave(c: Client, m: Message): +# ass_id = (await user.get_me()).id + bot_id = (await c.get_me()).id + chat_id = m.chat.id + left_member = m.left_chat_member + if left_member.id == bot_id: + await user.leave_chat(chat_id) +# elif left_member.id == ass_id: +# await c.leave_chat(chat_id) diff --git a/program/utils/formatters.py b/program/utils/formatters.py new file mode 100644 index 0000000..d97f7c3 --- /dev/null +++ b/program/utils/formatters.py @@ -0,0 +1,10 @@ +def bytes(size: float) -> str: + if not size: + return "" + power = 1024 + t_n = 0 + power_dict = {0: " ", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} + while size > power: + size /= power + t_n += 1 + return "{:.2f} {}B".format(size, power_dict[t_n]) diff --git a/program/utils/inline.py b/program/utils/inline.py new file mode 100644 index 0000000..bdb21d5 --- /dev/null +++ b/program/utils/inline.py @@ -0,0 +1,58 @@ +""" inline section button """ + +from pyrogram.types import ( + CallbackQuery, + InlineKeyboardButton, + InlineKeyboardMarkup, + Message, +) + + +def stream_markup(user_id): + buttons = [ + [ + InlineKeyboardButton(text="• Mᴇɴᴜ", callback_data=f'cbmenu | {user_id}'), + InlineKeyboardButton(text="• Cʟᴏsᴇ", callback_data=f'cls'), + ], + ] + return buttons + + +def menu_markup(user_id): + buttons = [ + [ + InlineKeyboardButton(text="⏹", callback_data=f'cbstop | {user_id}'), + InlineKeyboardButton(text="⏸", callback_data=f'cbpause | {user_id}'), + InlineKeyboardButton(text="▶️", callback_data=f'cbresume | {user_id}'), + ], + [ + InlineKeyboardButton(text="🔇", callback_data=f'cbmute | {user_id}'), + InlineKeyboardButton(text="🔊", callback_data=f'cbunmute | {user_id}'), + ], + [ + InlineKeyboardButton(text="🗑 Close", callback_data='cls'), + ] + ] + return buttons + + +close_mark = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + "🗑 Close", callback_data="cls" + ) + ] + ] +) + + +back_mark = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + "🔙 Go Back", callback_data="cbmenu" + ) + ] + ] +) diff --git a/program/ytsearch.py b/program/ytsearch.py new file mode 100644 index 0000000..a11f748 --- /dev/null +++ b/program/ytsearch.py @@ -0,0 +1,31 @@ +from config import BOT_USERNAME +from driver.filters import command +from pyrogram import Client +from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message +from youtube_search import YoutubeSearch + + +@Client.on_message(command(["search", f"search@{BOT_USERNAME}"])) +async def ytsearch(_, message: Message): + if len(message.command) < 2: + return await message.reply_text("/search **needs an argument !**") + query = message.text.split(None, 1)[1] + m = await message.reply_text("🔎 **Searching...**") + results = YoutubeSearch(query, max_results=5).to_dict() + text = "" + for i in range(5): + try: + text += f"🏷 **Name:** __{results[i]['title']}__\n" + text += f"⏱ **Duration:** `{results[i]['duration']}`\n" + text += f"👀 **Views:** `{results[i]['views']}`\n" + text += f"📣 **Channel:** {results[i]['channel']}\n" + text += f"🔗: https://www.youtube.com{results[i]['url_suffix']}\n\n" + except IndexError: + break + await m.edit_text( + text, + disable_web_page_preview=True, + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton("🗑 Close", callback_data="cls")]] + ), + )