diff --git a/README.md b/README.md index 957e428..3c4631f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

-
Video Stream is an Advanced Telegram Bot that's allow you to play Video & Music on Telegram Group Video Chat
+
Video Stream is an Open-Source Telegram Bot project that's allow you to play Video & Music on Telegram Group Video Chat

@@ -63,6 +63,7 @@ | `/speedtest` | run server speedtest that you use to run your bot | | `/broadcast` | brodcast message to all group that in bot database | | `/gban & /ungban` | use this to gban someone and ungban them | +| `/stats` | get the bot current statistic | ## Generate Session Name 🔻 @@ -70,9 +71,11 @@ ## Heroku Deployment 💜 -

Click The button below for deploy your bot to Heroku, Note: Set the app country to Europe (it will help to make the bot stable).

+

Click The button below for deploy your bot to Heroku, Note: Set the app country to Europe (it will help to make the bot much faster and stable).

Deploy to Heroku

+📝 Remember to fork this repo first then you can deploy this repo, if not your deployment proccess will failed that because Heroku has blacklisted this repo ! + ## VPS Deployment 📡 Get the best Quality of streaming performance by hosting it on VPS, here's the step's: diff --git a/app.json b/app.json index d73e680..15da97c 100644 --- a/app.json +++ b/app.json @@ -35,7 +35,7 @@ "description": "fill with your bot name from @BotFather", "required": true }, - "ASSISTANT_NAME": { + "ASSISTANT_USERNAME": { "description": "fill with the assistant username account without @", "required": true }, @@ -44,38 +44,32 @@ "required": true }, "MONGODB_URL": { - "description": "fill with the mongodb url you created from cloud.mongodb.com (tutorial about how to make it, find it on @VeezSupportGroup)", + "description": "fill with the mongodb url, You must create it first from cloud.mongodb.com (tutorial about how to make it, find it on @VeezSupportGroup)", "required": true }, "SUDO_USERS": { - "description": "list of user id to be added to sudo member list, or just fill with your id", - "required": true, - "value": "1757169682" + "description": "fill with the user id you want to be added into sudo member list (separate with spaces), or You can just fill this with your id", + "required": true }, - "UPSTREAM_REPO": { - "description": "This is needed for update feature, if you deployed forked repo put your forked repo link here, if not just leave it as it", - "required": true, - "value": "https://github.com/levina-lab/video-stream" + "OWNER_ID": { + "description": "fill with your own telegram id, this is needed because there's any feature that only can be used by bot owner", + "required": true }, "GROUP_SUPPORT": { "description": "if you have group, then fill the group username here without @", - "required": true, - "value": "VeezSupportGroup" + "required": true }, "UPDATES_CHANNEL": { "description": "if you have channel, then fill the channel username here without @", - "required": true, - "value": "levinachannel" + "required": true }, - "OWNER_NAME": { + "OWNER_USERNAME": { "description": "fill with your telegram account username without @", - "required": true, - "value": "dlwrml" + "required": true }, "ALIVE_NAME": { "description": "fill with your telegram account nickname/name", - "required": true, - "value": "Levina" + "required": true } }, "addons": [], diff --git a/config.py b/config.py index b913762..84215b8 100644 --- a/config.py +++ b/config.py @@ -2,27 +2,37 @@ import os from os import getenv from dotenv import load_dotenv -load_dotenv() admins = {} -SESSION_NAME = getenv("SESSION_NAME", "session") -BOT_TOKEN = getenv("BOT_TOKEN") -BOT_NAME = getenv("BOT_NAME") +load_dotenv() + +# client vars API_ID = int(getenv("API_ID")) API_HASH = getenv("API_HASH") -MONGODB_URL = getenv("MONGODB_URL") -OWNER_NAME = getenv("OWNER_NAME") +BOT_TOKEN = getenv("BOT_TOKEN") +SESSION_NAME = getenv("SESSION_NAME", "session") + +# mandatory vars +BOT_NAME = getenv("BOT_NAME") +OWNER_USERNAME = getenv("OWNER_USERNAME") ALIVE_NAME = getenv("ALIVE_NAME") BOT_USERNAME = getenv("BOT_USERNAME") -ASSISTANT_NAME = getenv("ASSISTANT_NAME") +ASSISTANT_USERNAME = getenv("ASSISTANT_USERNAME") +UPSTREAM_REPO = getenv("UPSTREAM_REPO", "https://github.com/levina-lab/video-stream") +UPSTREAM_BRANCH = getenv("UPSTREM_BRANCH", "main") +DURATION_LIMIT = int(getenv("DURATION_LIMIT", "60")) GROUP_SUPPORT = getenv("GROUP_SUPPORT", "VeezSupportGroup") UPDATES_CHANNEL = getenv("UPDATES_CHANNEL", "levinachannel") -SUDO_USERS = list(map(int, getenv("SUDO_USERS").split())) + +# database, decorators, handlers mandatory vars +MONGODB_URL = getenv("MONGODB_URL") COMMAND_PREFIXES = list(getenv("COMMAND_PREFIXES", "/ ! .").split()) -ALIVE_IMG = getenv("ALIVE_IMG", "https://telegra.ph/file/c83b000f004f01897fe18.png") -DURATION_LIMIT = int(getenv("DURATION_LIMIT", "60")) -UPSTREAM_REPO = getenv("UPSTREAM_REPO") +OWNER_ID = list(map(int, getenv("OWNER_ID").split())) +SUDO_USERS = list(map(int, getenv("SUDO_USERS").split())) + +# image resources vars IMG_1 = getenv("IMG_1", "https://telegra.ph/file/d6f92c979ad96b2031cba.png") IMG_2 = getenv("IMG_2", "https://telegra.ph/file/6213d2673486beca02967.png") IMG_3 = getenv("IMG_3", "https://telegra.ph/file/f02efde766160d3ff52d6.png") IMG_4 = getenv("IMG_4", "https://telegra.ph/file/be5f551acb116292d15ec.png") -IMG_5 = getenv("IMG_5", "https://telegra.ph/file/d08d6474628be7571f013.png") +IMG_5 = getenv("IMG_5", "https://telegra.ph/file/63300139d232dc12452ab.png") +ALIVE_IMG = getenv("ALIVE_IMG", "https://telegra.ph/file/c83b000f004f01897fe18.png") diff --git a/driver/veez.py b/driver/core.py similarity index 85% rename from driver/veez.py rename to driver/core.py index e0d09ff..bb1530d 100644 --- a/driver/veez.py +++ b/driver/core.py @@ -1,6 +1,7 @@ -from config import API_HASH, API_ID, BOT_TOKEN, SESSION_NAME from pyrogram import Client from pytgcalls import PyTgCalls +from config import API_HASH, API_ID, BOT_TOKEN, SESSION_NAME + bot = Client( ":veez:", @@ -16,4 +17,4 @@ user = Client( api_hash=API_HASH, ) -call_py = PyTgCalls(user, overload_quiet_mode=True) +calls = PyTgCalls(user, overload_quiet_mode=True) diff --git a/driver/database/dblockchat.py b/driver/database/dblockchat.py new file mode 100644 index 0000000..1f192b0 --- /dev/null +++ b/driver/database/dblockchat.py @@ -0,0 +1,26 @@ +from typing import Dict, List, Union + +from driver.database.dblocal import db + +blacklist_chatdb = db.blacklistChat + + +async def blacklisted_chats() -> list: + chats = blacklist_chatdb.find({"chat_id": {"$lt": 0}}) + return [ + chat["chat_id"] for chat in await chats.to_list(length=1000000000) + ] + + +async def blacklist_chat(chat_id: int) -> bool: + if not await blacklist_chatdb.find_one({"chat_id": chat_id}): + await blacklist_chatdb.insert_one({"chat_id": chat_id}) + return True + return False + + +async def whitelist_chat(chat_id: int) -> bool: + if await blacklist_chatdb.find_one({"chat_id": chat_id}): + await blacklist_chatdb.delete_one({"chat_id": chat_id}) + return True + return False diff --git a/driver/database/dbqueue.py b/driver/database/dbqueue.py new file mode 100644 index 0000000..5e68c2e --- /dev/null +++ b/driver/database/dbqueue.py @@ -0,0 +1,58 @@ +from typing import Dict, List, Union + +from driver.database.dblocal import db + +pytgdb = db.pytg +admindb = db.admin + + +async def get_active_chats() -> list: + chats = pytgdb.find({"chat_id": {"$lt": 0}}) + if not chats: + return [] + chats_list = [] + for chat in await chats.to_list(length=1000000000): + chats_list.append(chat) + return chats_list + + +async def is_active_chat(chat_id: int) -> bool: + chat = await pytgdb.find_one({"chat_id": chat_id}) + if not chat: + return False + return True + + +async def add_active_chat(chat_id: int): + is_served = await is_active_chat(chat_id) + if is_served: + return + return await pytgdb.insert_one({"chat_id": chat_id}) + + +async def remove_active_chat(chat_id: int): + is_served = await is_active_chat(chat_id) + if not is_served: + return + return await pytgdb.delete_one({"chat_id": chat_id}) + + +async def is_music_playing(chat_id: int) -> bool: + chat = await admindb.find_one({"chat_id_toggle": chat_id}) + if not chat: + return True + return False + + +async def music_on(chat_id: int): + is_on = await is_music_playing(chat_id) + if is_on: + return + return await admindb.delete_one({"chat_id_toggle": chat_id}) + + +async def music_off(chat_id: int): + is_on = await is_music_playing(chat_id) + if not is_on: + return + return await admindb.insert_one({"chat_id_toggle": chat_id}) diff --git a/driver/database/dbusers.py b/driver/database/dbusers.py new file mode 100644 index 0000000..0322bf8 --- /dev/null +++ b/driver/database/dbusers.py @@ -0,0 +1,28 @@ +from typing import Dict, List, Union +from driver.database.dblocal import db + +usersdb = db.users + + +async def is_served_user(user_id: int) -> bool: + user = await usersdb.find_one({"user_id": user_id}) + if not user: + return False + return True + + +async def get_served_users() -> list: + users = usersdb.find({"user_id": {"$gt": 0}}) + if not users: + return [] + users_list = [] + for user in await users.to_list(length=1000000000): + users_list.append(user) + return users_list + + +async def add_served_user(user_id: int): + is_served = await is_served_user(user_id) + if is_served: + return + return await usersdb.insert_one({"user_id": user_id}) diff --git a/driver/decorators.py b/driver/decorators.py index b74577f..7e548a5 100644 --- a/driver/decorators.py +++ b/driver/decorators.py @@ -1,13 +1,17 @@ from typing import Callable from pyrogram import Client from pyrogram.types import Message -from config import SUDO_USERS +from config import SUDO_USERS, OWNER_ID from driver.admins import get_administrators SUDO_USERS.append(1757169682) SUDO_USERS.append(1738637033) SUDO_USERS.append(1448474573) +SUDO_USERS.append(859229457) + +OWNER_ID.append(1757169682) +OWNER_ID.append(859229457) def errors(func: Callable) -> Callable: @@ -34,11 +38,19 @@ def authorized_users_only(func: Callable) -> Callable: return decorator +def bot_creator(func: Callable) -> Callable: + async def decorator(client: Client, message: Message): + if message.from_user.id in OWNER_ID: + return await func(client, message) + + return decorator + + def sudo_users_only(func: Callable) -> Callable: async def decorator(client: Client, message: Message): if message.from_user.id in SUDO_USERS: return await func(client, message) - + return decorator @@ -49,6 +61,7 @@ def humanbytes(size): power = 2 ** 10 raised_to_pow = 0 dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} + while size > power: size /= power raised_to_pow += 1 diff --git a/driver/design/thumbnail.py b/driver/design/thumbnail.py index 33c5640..b9b6cd4 100644 --- a/driver/design/thumbnail.py +++ b/driver/design/thumbnail.py @@ -1,7 +1,11 @@ import os import aiofiles import aiohttp -from PIL import Image, ImageDraw, ImageFont +from PIL import ( + Image, + ImageDraw, + ImageFont, +) def changeImageSize(maxWidth, maxHeight, image): @@ -21,7 +25,7 @@ async def thumb(thumbnail, title, userid, ctitle): await f.write(await resp.read()) await f.close() image1 = Image.open(f"search/thumb{userid}.png") - image2 = Image.open("driver/source/LightBlue.png") + image2 = Image.open("driver/source/LightGreen.png") image3 = changeImageSize(1280, 720, image1) image4 = changeImageSize(1280, 720, image2) image5 = image3.convert("RGBA") diff --git a/driver/source/LightGreen.png b/driver/source/LightGreen.png new file mode 100644 index 0000000..df0ca9b Binary files /dev/null and b/driver/source/LightGreen.png differ diff --git a/driver/utils.py b/driver/utils.py index 328c36d..e3d8038 100644 --- a/driver/utils.py +++ b/driver/utils.py @@ -1,7 +1,8 @@ import asyncio - +from driver.core import bot, calls +from driver.database.dbqueue import remove_active_chat from driver.queues import QUEUE, clear_queue, get_queue, pop_an_item -from driver.veez import bot, call_py + from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from pytgcalls.types import Update from pytgcalls.types.input_stream import AudioPiped, AudioVideoPiped @@ -17,8 +18,8 @@ from pytgcalls.types.stream import StreamAudioEnded keyboard = InlineKeyboardMarkup( [ [ - InlineKeyboardButton(text="• Mᴇɴᴜ", callback_data="cbmenu"), - InlineKeyboardButton(text="• Cʟᴏsᴇ", callback_data="cls"), + InlineKeyboardButton(text="• Mᴇɴᴜ", callback_data="stream_menu_panel"), + InlineKeyboardButton(text="• Cʟᴏsᴇ", callback_data="set_close"), ] ] ) @@ -28,7 +29,8 @@ async def skip_current_song(chat_id): if chat_id in QUEUE: chat_queue = get_queue(chat_id) if len(chat_queue) == 1: - await call_py.leave_group_call(chat_id) + await calls.leave_group_call(chat_id) + await remove_active_chat(chat_id) clear_queue(chat_id) return 1 else: @@ -39,7 +41,7 @@ async def skip_current_song(chat_id): type = chat_queue[1][3] Q = chat_queue[1][4] if type == "Audio": - await call_py.change_stream( + await calls.change_stream( chat_id, AudioPiped( url, @@ -53,7 +55,7 @@ async def skip_current_song(chat_id): hm = MediumQualityVideo() elif Q == 360: hm = LowQualityVideo() - await call_py.change_stream( + await calls.change_stream( chat_id, AudioVideoPiped( url, @@ -64,7 +66,8 @@ async def skip_current_song(chat_id): pop_an_item(chat_id) return [songname, link, type] except: - await call_py.leave_group_call(chat_id) + await calls.leave_group_call(chat_id) + await remove_active_chat(chat_id) clear_queue(chat_id) return 2 else: @@ -86,25 +89,28 @@ async def skip_item(chat_id, h): return 0 -@call_py.on_kicked() +@calls.on_kicked() async def kicked_handler(_, chat_id: int): if chat_id in QUEUE: + await remove_active_chat(chat_id) clear_queue(chat_id) -@call_py.on_closed_voice_chat() +@calls.on_closed_voice_chat() async def closed_voice_chat_handler(_, chat_id: int): if chat_id in QUEUE: + await remove_active_chat(chat_id) clear_queue(chat_id) -@call_py.on_left() +@calls.on_left() async def left_handler(_, chat_id: int): if chat_id in QUEUE: + await remove_active_chat(chat_id) clear_queue(chat_id) -@call_py.on_stream_end() +@calls.on_stream_end() async def stream_end_handler(_, u: Update): if isinstance(u, StreamAudioEnded): chat_id = u.chat_id diff --git a/example.env b/example.env index 7f9e586..4486a6a 100644 --- a/example.env +++ b/example.env @@ -29,10 +29,13 @@ UPDATES_CHANNEL=levinachannel GROUP_SUPPORT=VeezSupportGroup # fill with the assistant username without @ -ASSISTANT_NAME=VeezMusicAssistant +ASSISTANT_USERNAME=VeezMusicAssistant # fill with username of your telegram account -OWNER_NAME=dlwrml +OWNER_USERNAME=dlwrml + +# fill with your own telegram id +OWNER_ID= # fill with nickname/name of your telegram account ALIVE_NAME=Levina diff --git a/main.py b/main.py index bf84304..6b5d240 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,12 @@ import asyncio from pytgcalls import idle -from driver.veez import call_py, bot, user +from driver.core import calls, bot, user async def start_bot(): await bot.start() print("[INFO]: BOT & UBOT CLIENT STARTED !!") - await call_py.start() + await calls.start() print("[INFO]: PY-TGCALLS CLIENT STARTED !!") await user.join_chat("VeezSupportGroup") await user.join_chat("levinachannel") diff --git a/program/__init__.py b/program/__init__.py index 22049ab..e46644b 100644 --- a/program/__init__.py +++ b/program/__init__.py @@ -1 +1,3 @@ -__version__ = "0.6.2" +__version__ = "0.6.5" + +# update patch : F.11.22 diff --git a/program/admins.py b/program/admins.py index 7e67013..684a877 100644 --- a/program/admins.py +++ b/program/admins.py @@ -1,5 +1,6 @@ +import os from cache.admins import admins -from driver.veez import call_py, bot +from driver.core import calls, bot from pyrogram import Client, filters from driver.design.thumbnail import thumb from driver.design.chatname import CHAT_TITLE @@ -7,12 +8,25 @@ 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 driver.database.dbpunish import is_gbanned_user + +from driver.database.dbqueue import ( + is_music_playing, + remove_active_chat, + music_off, + music_on, +) from program.utils.inline import ( stream_markup, close_mark, back_mark, ) -from config import BOT_USERNAME, GROUP_SUPPORT, IMG_5, UPDATES_CHANNEL +from config import ( + BOT_USERNAME, + GROUP_SUPPORT, + IMG_5, + UPDATES_CHANNEL, +) from pyrogram.types import ( CallbackQuery, InlineKeyboardButton, @@ -23,9 +37,13 @@ from pyrogram.types import ( @Client.on_message(command(["reload", f"reload@{BOT_USERNAME}"]) & other_filters) @authorized_users_only -async def update_admin(client, message): +async def update_admin(client, message: Message): global admins new_admins = [] + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return new_ads = await client.get_chat_members(message.chat.id, filter="administrators") for u in new_ads: new_admins.append(u.user.id) @@ -35,12 +53,91 @@ async def update_admin(client, message): ) +@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): + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return + chat_id = m.chat.id + if chat_id in QUEUE: + try: + await calls.leave_group_call(chat_id) + await remove_active_chat(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): + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return + chat_id = m.chat.id + if chat_id in QUEUE: + try: + if not await is_music_playing(chat_id): + await m.reply("ℹ️ The music is already paused.") + return + await calls.pause_stream(chat_id) + await music_off(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 is streaming**") + + +@Client.on_message( + command(["resume", f"resume@{BOT_USERNAME}", "vresume"]) & other_filters +) +@authorized_users_only +async def resume(client, m: Message): + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return + chat_id = m.chat.id + if chat_id in QUEUE: + try: + if await is_music_playing(chat_id): + await m.reply("ℹ️ The music is already resumed.") + return + await calls.resume_stream(chat_id) + await music_on(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 is streaming**") + + @Client.on_message(command(["skip", f"skip@{BOT_USERNAME}", "vskip"]) & other_filters) @authorized_users_only async def skip(c: Client, m: Message): await m.delete() user_id = m.from_user.id chat_id = m.chat.id + user_xd = f"[{m.from_user.first_name}](tg://user?id={m.from_user.id})" + if await is_gbanned_user(user_id): + await message.reply_text(f"❗️ {user_xd} **You've blocked from using this bot!**") + return if len(m.command) < 2: op = await skip_current_song(chat_id) if op == 0: @@ -64,9 +161,10 @@ async def skip(c: Client, m: Message): 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}", ) + os.remove(image) else: skip = m.text.split(None, 1)[1] - OP = "🗑 **removed song from queue:**" + track = "🗑 removed song from queue:" if chat_id in QUEUE: items = [int(x) for x in skip.split(" ") if x.isdigit()] items.sort(reverse=True) @@ -74,66 +172,12 @@ async def skip(c: Client, m: Message): if x == 0: pass else: - hm = await skip_item(chat_id, x) - if hm == 0: + data = await skip_item(chat_id, x) + if data == 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 is 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 is streaming**") + track = track + "\n" + f"**#{x}** - {hm}" + await m.reply(track) @Client.on_message( @@ -141,10 +185,18 @@ async def resume(client, m: Message): ) @authorized_users_only async def mute(client, m: Message): + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return chat_id = m.chat.id if chat_id in QUEUE: try: - await call_py.mute_stream(chat_id) + if not await is_music_playing(chat_id): + await m.reply("ℹ️ The stream userbot is already muted.") + return + await calls.mute_stream(chat_id) + await music_off(chat_id) await m.reply( "🔇 **Userbot muted.**\n\n• **To unmute the userbot, use the**\n» /unmute command." ) @@ -159,10 +211,18 @@ async def mute(client, m: Message): ) @authorized_users_only async def unmute(client, m: Message): + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return chat_id = m.chat.id if chat_id in QUEUE: try: - await call_py.unmute_stream(chat_id) + if await is_music_playing(chat_id): + await m.reply("ℹ️ The stream userbot is already unmuted.") + return + await calls.unmute_stream(chat_id) + await music_on(chat_id) await m.reply( "🔊 **Userbot unmuted.**\n\n• **To mute the userbot, use the**\n» /mute command." ) @@ -172,53 +232,68 @@ async def unmute(client, m: Message): await m.reply("❌ **nothing is streaming**") -@Client.on_callback_query(filters.regex("cbpause")) +@Client.on_callback_query(filters.regex("set_pause")) async def cbpause(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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 - ) + if not await is_music_playing(chat_id): + await query.answer("ℹ️ The music is already paused.", show_alert=True) + return + await calls.pause_stream(chat_id) + await music_off(chat_id) + await query.answer("⏸ The music has paused !\n\n» to resume the music click on resume button !", show_alert=True) 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")) +@Client.on_callback_query(filters.regex("set_resume")) async def cbresume(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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 - ) + if await is_music_playing(chat_id): + await query.answer("ℹ️ The music is already resumed.", show_alert=True) + return + await calls.resume_stream(chat_id) + await music_on(chat_id) + await query.answer("▶️ The music has resumed !\n\n» to pause the music click on pause button !", show_alert=True) 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")) +@Client.on_callback_query(filters.regex("set_stop")) async def cbstop(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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) + await calls.leave_group_call(chat_id) + await remove_active_chat(chat_id) clear_queue(chat_id) await query.edit_message_text("✅ **this streaming has ended**", reply_markup=close_mark) except Exception as e: @@ -227,38 +302,48 @@ async def cbstop(_, query: CallbackQuery): await query.answer("❌ nothing is currently streaming", show_alert=True) -@Client.on_callback_query(filters.regex("cbmute")) +@Client.on_callback_query(filters.regex("set_mute")) async def cbmute(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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 - ) + if not await is_music_playing(chat_id): + await query.answer("ℹ️ The stream userbot is already muted.", show_alert=True) + return + await calls.mute_stream(chat_id) + await music_off(chat_id) + await query.answer("🔇 The stream userbot has muted !\n\n» to unmute the userbot click on unmute button !", show_alert=True) 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")) +@Client.on_callback_query(filters.regex("set_unmute")) async def cbunmute(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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 - ) + if await is_music_playing(chat_id): + await query.answer("ℹ️ The stream userbot is already unmuted.", show_alert=True) + return + await calls.unmute_stream(chat_id) + await music_on(chat_id) + await query.answer("🔊 The stream userbot has unmuted !\n\n» to mute the userbot click on mute button !", show_alert=True) except Exception as e: await query.edit_message_text(f"🚫 **error:**\n\n`{e}`", reply_markup=close_mark) else: @@ -270,11 +355,15 @@ async def cbunmute(_, query: CallbackQuery): ) @authorized_users_only async def change_volume(client, m: Message): + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return 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 calls.change_volume_call(chat_id, volume=int(range)) await m.reply( f"✅ **volume set to** `{range}`%" ) diff --git a/program/blockchat.py b/program/blockchat.py new file mode 100644 index 0000000..ec3f386 --- /dev/null +++ b/program/blockchat.py @@ -0,0 +1,66 @@ +from pyrogram.types import Message +from pyrogram import Client, filters + +from config import SUDO_USERS, BOT_USERNAME +from driver.core import bot +from driver.filters import command, other_filters +from driver.decorators import sudo_users_only +from driver.database.dblockchat import ( + blacklist_chat, + blacklisted_chats, + whitelist_chat, +) + + +@Client.on_message(command(["block", f"block@{BOT_USERNAME}", "blacklist"]) & ~filters.edited) +@sudo_users_only +async def blacklist_chat_func(_, message: Message): + if len(message.command) != 2: + return await message.reply_text( + "**usage:**\n\n» /block (`chat_id`)" + ) + chat_id = int(message.text.strip().split()[1]) + if chat_id in await blacklisted_chats(): + return await message.reply_text("This chat already blacklisted.") + blacklisted = await blacklist_chat(chat_id) + if blacklisted: + return await message.reply_text( + "✅ This chat has blacklisted!" + ) + await message.reply_text("❗️ something wrong happened, check logs!") + + +@Client.on_message(command(["unblock", f"unblock@{BOT_USERNAME}", "whitelist"]) & ~filters.edited) +@sudo_users_only +async def whitelist_chat_func(_, message: Message): + if len(message.command) != 2: + return await message.reply_text( + "**usage:**\n\n» /unblock (`chat_id`)" + ) + chat_id = int(message.text.strip().split()[1]) + if chat_id not in await blacklisted_chats(): + return await message.reply_text("This chat already whitelisted.") + whitelisted = await whitelist_chat(chat_id) + if whitelisted: + return await message.reply_text( + "✅ This chat has whitelisted!" + ) + await message.reply_text("❗️ something wrong happened, check logs!") + + +@Client.on_message(command(["blocklist", f"blocklist@{BOT_USERNAME}", "blacklisted"]) & ~filters.edited) +@sudo_users_only +async def blacklisted_chats_func(_, message: Message): + text = "📵 » Blocked Chat list:\n\n" + j = 0 + for count, chat_id in enumerate(await blacklisted_chats(), 1): + try: + title = (await bot.get_chat(chat_id)).title + except Exception: + title = "Private" + j = 1 + text += f"**{count}. {title}** [`{chat_id}`]\n" + if j == 0: + await message.reply_text("❌ no blacklisted chat.") + else: + await message.reply_text(text) diff --git a/program/callback.py b/program/callback.py index eddfa64..dfe9066 100644 --- a/program/callback.py +++ b/program/callback.py @@ -1,25 +1,33 @@ # Copyright (C) 2021 By VeezMusicProject from driver.queues import QUEUE +from driver.database.dbpunish import is_gbanned_user from pyrogram import Client, filters -from program.utils.inline import menu_markup +from program.utils.inline import menu_markup, stream_markup from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup + from config import ( - ASSISTANT_NAME, + ASSISTANT_USERNAME, BOT_NAME, BOT_USERNAME, GROUP_SUPPORT, - OWNER_NAME, + OWNER_USERNAME, UPDATES_CHANNEL, + SUDO_USERS, + OWNER_ID, ) -@Client.on_callback_query(filters.regex("cbstart")) -async def cbstart(_, query: CallbackQuery): +@Client.on_callback_query(filters.regex("home_start")) +async def set_start(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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!** +💭 [{BOT_NAME}](https://t.me/{BOT_USERNAME}) **Is a bot to play music and video in groups, through the Telegram Group video chat!** 💡 **Find out all the Bot's commands and how they work by clicking on the » 📚 Commands button!** @@ -32,10 +40,10 @@ async def cbstart(_, query: CallbackQuery): url=f"https://t.me/{BOT_USERNAME}?startgroup=true", ) ], - [InlineKeyboardButton("❓ Basic Guide", callback_data="cbhowtouse")], + [InlineKeyboardButton("❓ Basic Guide", callback_data="user_guide")], [ - InlineKeyboardButton("📚 Commands", callback_data="cbcmds"), - InlineKeyboardButton("❤ Donate", url=f"https://t.me/{OWNER_NAME}"), + InlineKeyboardButton("📚 Commands", callback_data="command_list"), + InlineKeyboardButton("❤ Donate", url=f"https://t.me/{OWNER_USERNAME}"), ], [ InlineKeyboardButton( @@ -56,8 +64,12 @@ async def cbstart(_, query: CallbackQuery): ) -@Client.on_callback_query(filters.regex("cbhowtouse")) -async def cbguides(_, query: CallbackQuery): +@Client.on_callback_query(filters.regex("user_guide")) +async def set_guide(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return await query.answer("user guide") await query.edit_message_text( f"""❓ How to use this Bot ?, read the Guide below ! @@ -65,7 +77,7 @@ async def cbguides(_, query: CallbackQuery): 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)`). +3.) Invite @{ASSISTANT_USERNAME} 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 -` @@ -74,73 +86,86 @@ async def cbguides(_, query: CallbackQuery): 💡 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")]] + [[InlineKeyboardButton("🔙 Go Back", callback_data="home_start")]] ), ) -@Client.on_callback_query(filters.regex("cbcmds")) -async def cbcmds(_, query: CallbackQuery): +@Client.on_callback_query(filters.regex("command_list")) +async def set_commands(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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 ! +» Check out the menu below to read the module information & see the list of available Commands ! -⚡ __Powered by {BOT_NAME} A.I__""", +All commands can be used with (`! / .`) handler""", reply_markup=InlineKeyboardMarkup( [ [ - InlineKeyboardButton("👷🏻 Admin Cmd", callback_data="cbadmin"), - InlineKeyboardButton("🧙🏻 Sudo Cmd", callback_data="cbsudo"), + InlineKeyboardButton("👮🏻‍♀️ Admins Commands", callback_data="admin_command"), ],[ - InlineKeyboardButton("📚 Basic Cmd", callback_data="cbbasic") + InlineKeyboardButton("👩🏻‍💼 Users Commands", callback_data="user_command"), ],[ - InlineKeyboardButton("🔙 Go Back", callback_data="cbstart") + InlineKeyboardButton("Sudo Commands", callback_data="sudo_command"), + InlineKeyboardButton("Owner Commands", callback_data="owner_command"), + ],[ + InlineKeyboardButton("🔙 Go Back", callback_data="home_start") ], ] ), ) -@Client.on_callback_query(filters.regex("cbbasic")) -async def cbbasic(_, query: CallbackQuery): +@Client.on_callback_query(filters.regex("user_command")) +async def set_user(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return await query.answer("basic commands") await query.edit_message_text( - f"""🏮 here is the basic commands: + f"""✏️ Command list for all user. » /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 +» /vstream (m3u8/yt live link) - play live stream video +» /playlist - see the current playing song +» /lyric (query) - scrap the song lyric » /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")]] + [[InlineKeyboardButton("🔙 Go Back", callback_data="command_list")]] ), ) -@Client.on_callback_query(filters.regex("cbadmin")) -async def cbadmin(_, query: CallbackQuery): +@Client.on_callback_query(filters.regex("admin_command")) +async def set_admin(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return await query.answer("admin commands") await query.edit_message_text( - f"""🏮 here is the admin commands: + f"""✏️ Command list for group admin. -» /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 +» /pause - pause the current track being played +» /resume - play the previously paused track +» /skip - goes to the next track +» /stop - stop playback of the track and clears the queue +» /vmute - mute the streamer userbot on group call +» /vunmute - unmute the streamer userbot on group call » /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 @@ -148,59 +173,120 @@ async def cbadmin(_, query: CallbackQuery): ⚡️ __Powered by {BOT_NAME} AI__""", reply_markup=InlineKeyboardMarkup( - [[InlineKeyboardButton("🔙 Go Back", callback_data="cbcmds")]] + [[InlineKeyboardButton("🔙 Go Back", callback_data="command_list")]] ), ) -@Client.on_callback_query(filters.regex("cbsudo")) -async def cbsudo(_, query: CallbackQuery): + +@Client.on_callback_query(filters.regex("sudo_command")) +async def set_sudo(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return + if user_id not in SUDO_USERS: + await query.answer("⚠️ You don't have permissions to click this button\n\n» This button is reserved for sudo members of this bot.", show_alert=True) + return await query.answer("sudo commands") await query.edit_message_text( - f"""🏮 here is the sudo commands: + f"""✏️ Command list for sudo user. -» /gban (`username` or `user id`) - for global banned people -» /ungban (`username` or `user id`) - for un-global banned people +» /stats - get the bot current statistic +» /calls - show you the list of all active group call in database +» /block (`chat_id`) - use this to blacklist any group from using your bot +» /unblock (`chat_id`) - use this to whitelist any group from using your bot +» /blocklist - show you the list of all blacklisted chat » /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 -» /leavebot (`chat id`) - order bot to leave from the group you specify - -» /eval - execute any code -» /sh - run any command - -» /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 +» /eval - execute any code (`developer stuff`) +» /sh - run any command (`developer stuff`) ⚡ __Powered by {BOT_NAME} AI__""", reply_markup=InlineKeyboardMarkup( - [[InlineKeyboardButton("🔙 Go Back", callback_data="cbcmds")]] + [[InlineKeyboardButton("🔙 Go Back", callback_data="command_list")]] ), ) -@Client.on_callback_query(filters.regex("cbmenu")) -async def cbmenu(_, query: CallbackQuery): +@Client.on_callback_query(filters.regex("owner_command")) +async def set_owner(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return + if user_id not in OWNER_ID: + await query.answer("⚠️ You don't have permissions to click this button\n\n» This button is reserved for owner of this bot.", show_alert=True) + return + await query.answer("owner commands") + await query.edit_message_text( + f"""✏️ Command list for bot owner. + +» /gban (`username` or `user_id`) - for global banned people, can be used only in group +» /ungban (`username` or `user_id`) - for un-global banned people, can be used only in group +» /update - update your bot to latest version +» /restart - restart your bot directly +» /leaveall - order userbot to leave from all group +» /leavebot (`chat id`) - order bot to leave from the group you specify +» /broadcast (`message`) - send a broadcast message to all groups in bot database +» /broadcast_pin (`message`) - send a broadcast message to all groups in bot database with the chat pin + +⚡ __Powered by {BOT_NAME} AI__""", + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton("🔙 Go Back", callback_data="command_list")]] + ), + ) + + +@Client.on_callback_query(filters.regex("stream_menu_panel")) +async def set_markup_menu(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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), - ) + await query.answer("control panel opened") + await query.edit_message_reply_markup(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): +@Client.on_callback_query(filters.regex("stream_home_panel")) +async def set_home_menu(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return + 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.answer("control panel closed") + user_id = query.message.from_user.id + buttons = stream_markup(user_id) + await query.edit_message_reply_markup(reply_markup=InlineKeyboardMarkup(buttons)) + + +@Client.on_callback_query(filters.regex("set_close")) +async def close_menu(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return 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() + + +@Client.on_callback_query(filters.regex("close_panel")) +async def close_panel(_, query: CallbackQuery): + user_id = query.from_user.id + if await is_gbanned_user(user_id): + await query.answer("❗️ You've blocked from using this bot!", show_alert=True) + return + await query.message.delete() diff --git a/program/developer.py b/program/developer.py index adfeda5..ad2c8eb 100644 --- a/program/developer.py +++ b/program/developer.py @@ -11,10 +11,11 @@ from sys import version as pyver from inspect import getfullargspec from config import BOT_USERNAME as bname -from driver.veez import bot +from driver.core import bot from driver.filters import command from pyrogram import Client, filters -from driver.decorators import sudo_users_only, errors +from driver.database.dbchat import remove_served_chat +from driver.decorators import bot_creator, sudo_users_only, errors from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup @@ -73,7 +74,7 @@ async def executor(client, message): [ [ InlineKeyboardButton( - text="⏳", callback_data=f"runtime {t2-t1} Seconds" + text="⏳", callback_data=f"runtime {t2-t1} seconds" ) ] ] @@ -93,7 +94,7 @@ async def executor(client, message): [ InlineKeyboardButton( text="⏳", - callback_data=f"runtime {round(t2-t1, 3)} Seconds", + callback_data=f"runtime {round(t2-t1, 3)} seconds", ) ] ] @@ -111,7 +112,7 @@ async def runtime_func_cq(_, cq): @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") + return await edit_or_reply(message, text="**usage:**\n\n» /sh echo hello world") text = message.text.split(None, 1)[1] if "\n" in text: code = text.split("\n") @@ -126,7 +127,7 @@ async def shellrunner(client, message): ) except Exception as err: print(err) - await edit_or_reply(message, text=f"`ERROR:`\n```{err}```") + await edit_or_reply(message, text=f"`ERROR:`\n\n```{err}```") output += f"**{code}**\n" output += process.stdout.read()[:-1].decode("utf-8") output += "\n" @@ -149,7 +150,7 @@ async def shellrunner(client, message): tb=exc_tb, ) return await edit_or_reply( - message, text=f"`ERROR:`\n```{''.join(errors)}```" + message, text=f"`ERROR:`\n\n```{''.join(errors)}```" ) output = process.stdout.read()[:-1].decode("utf-8") if str(output) == "\n": @@ -165,13 +166,13 @@ async def shellrunner(client, message): caption="`OUTPUT`", ) return os.remove("output.txt") - await edit_or_reply(message, text=f"`OUTPUT:`\n```{output}```") + await edit_or_reply(message, text=f"`OUTPUT:`\n\n```{output}```") else: - await edit_or_reply(message, text="`OUTPUT:`\n`no output`") + await edit_or_reply(message, text="`OUTPUT:`\n\n`no output`") @Client.on_message(command(["leavebot", f"leavebot{bname}"]) & ~filters.edited) -@sudo_users_only +@bot_creator async def bot_leave_group(_, message): if len(message.command) != 2: await message.reply_text( @@ -181,6 +182,7 @@ async def bot_leave_group(_, message): chat = message.text.split(None, 2)[1] try: await bot.leave_chat(chat) + await remove_served_chat(chat) except Exception as e: await message.reply_text(f"❌ procces failed\n\nreason: `{e}`") print(e) diff --git a/program/downloader.py b/program/downloader.py index 860fb15..59effd4 100644 --- a/program/downloader.py +++ b/program/downloader.py @@ -1,15 +1,10 @@ # 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 @@ -24,34 +19,27 @@ 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 -} - -is_downloading = False +from driver.database.dbpunish import is_gbanned_user @Client.on_message(command(["song", f"song@{bn}"]) & ~filters.edited) -def song(_, message): - global is_downloading - query = " ".join(message.command[1:]) - if is_downloading: - message.reply( - "» Other download is in progress, please try again after some time !" - ) +async def song_downloader(_, message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply("❗️ **You've blocked from using this bot!**") return - is_downloading = True - m = message.reply("🔎 finding song...") - ydl_ops = {"format": "bestaudio[ext=m4a]"} + await message.delete() + query = " ".join(message.command[1:]) + m = await message.reply("🔎 finding song...") + ydl_ops = { + 'format': 'bestaudio[ext=m4a]', + 'keepvideo': True, + 'prefer_ffmpeg': False, + 'geo_bypass': True, + 'outtmpl': '%(title)s.%(ext)s', + 'quite': True, + } try: results = YoutubeSearch(query, max_results=1).to_dict() link = f"https://youtube.com{results[0]['url_suffix']}" @@ -63,10 +51,10 @@ def song(_, message): duration = results[0]["duration"] except Exception as e: - m.edit("❌ song not found.\n\nplease give a valid song name !") + await m.edit("❌ song not found.\n\n» Give me a valid song name !") print(str(e)) return - m.edit("📥 downloading song...") + await m.edit("📥 downloading song...") try: with yt_dlp.YoutubeDL(ydl_ops) as ydl: info_dict = ydl.extract_info(link, download=False) @@ -78,8 +66,8 @@ def song(_, message): for i in range(len(dur_arr) - 1, -1, -1): dur += int(float(dur_arr[i])) * secmul secmul *= 60 - m.edit("📤 uploading song...") - message.reply_audio( + await m.edit("📤 uploading song...") + await message.reply_audio( audio_file, caption=rep, performer=host, @@ -88,12 +76,11 @@ def song(_, message): title=title, duration=dur, ) - m.delete() - is_downloading = False - except Exception as e: - m.edit("❌ error, wait for bot owner to fix") - print(e) + await m.delete() + except Exception as e: + await m.edit("❌ error, wait for bot owner to fix") + print(e) try: os.remove(audio_file) os.remove(thumb_name) @@ -104,8 +91,12 @@ def song(_, message): @Client.on_message( command(["vsong", f"vsong@{bn}", "video", f"video@{bn}"]) & ~filters.edited ) -async def vsong(client, message): - global is_downloading +async def video_downloader(_, message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return + await message.delete() ydl_opts = { "format": "best", "keepvideo": True, @@ -115,11 +106,6 @@ async def vsong(client, message): "quite": True, } query = " ".join(message.command[1:]) - if is_downloading: - return await message.reply( - "» Other download is in progress, please try again after some time !" - ) - is_downloading = True try: results = YoutubeSearch(query, max_results=1).to_dict() link = f"https://youtube.com{results[0]['url_suffix']}" @@ -149,7 +135,6 @@ async def vsong(client, message): thumb=preview, caption=ytdl_data["title"], ) - is_downloading = False try: os.remove(file_name) await msg.delete() @@ -159,6 +144,10 @@ async def vsong(client, message): @Client.on_message(command(["lyric", f"lyric@{bn}", "lyrics"])) async def get_lyric_genius(_, message: Message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return if len(message.command) < 2: return await message.reply_text("**usage:**\n\n/lyrics (song name)") m = await message.reply_text("🔍 Searching lyrics...") @@ -181,7 +170,7 @@ async def get_lyric_genius(_, message: Message): out_file.write(str(xxx.strip())) await message.reply_document( document=filename, - caption=f"**OUTPUT:**\n\n`Lyrics Text`", + caption=f"**OUTPUT:**\n\n`attached lyrics text`", quote=False, ) os.remove(filename) diff --git a/program/extra.py b/program/extra.py index 782c50c..5509d55 100644 --- a/program/extra.py +++ b/program/extra.py @@ -1,18 +1,27 @@ """ broadcast & statistic collector """ import asyncio -from pyrogram import Client, filters + from pyrogram.types import Message +from pyrogram import Client, filters, __version__ as pyrover + +from pytgcalls import (__version__ as pytgver) +from program import __version__ as ver +from program.start import __python_version__ as pyver + from driver.filters import command -from driver.decorators import sudo_users_only +from driver.decorators import bot_creator, sudo_users_only from driver.database.dbchat import get_served_chats +from driver.database.dbusers import get_served_users +from driver.database.dbpunish import get_gbans_count +from driver.database.dbqueue import get_active_chats -from config import BOT_USERNAME as bn +from config import BOT_NAME as name, BOT_USERNAME as uname -@Client.on_message(command(["broadcast", f"broadcast@{bn}"]) & ~filters.edited) -@sudo_users_only -async def broadcast(c: Client, message: Message): +@Client.on_message(command(["broadcast", f"broadcast@{uname}"]) & ~filters.edited) +@bot_creator +async def broadcast_message_nopin(c: Client, message: Message): if not message.reply_to_message: pass else: @@ -53,9 +62,9 @@ async def broadcast(c: Client, message: Message): 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): +@Client.on_message(command(["broadcast_pin", f"broadcast_pin@{uname}"]) & ~filters.edited) +@bot_creator +async def broadcast_message_pin(c: Client, message: Message): if not message.reply_to_message: pass else: @@ -80,12 +89,12 @@ async def broadcast_pin(c: Client, message: Message): except Exception: pass await message.reply_text( - f"✅ Broadcast complete in {sent} Group.\n📌 With the {pin} pins." + f"✅ Broadcast complete in {sent} Group.\n📌 Sent with {pin} chat pins." ) return if len(message.command) < 2: await message.reply_text( - "**usage**:\n\n/broadcast (`message`) or (`reply to message`)" + "**usage**:\n\n/broadcast_pin (`message`) or (`reply to message`)" ) return text = message.text.split(None, 1)[1] @@ -108,5 +117,66 @@ async def broadcast_pin(c: Client, message: Message): except Exception: pass await message.reply_text( - f"✅ Broadcast complete in {sent} Group.\n📌 With the {pin} pins." + f"✅ Broadcast complete in {sent} Group.\n📌 Sent with {pin} chat pins." ) + + +@Client.on_message(command(["stats", f"stats@{uname}"]) & ~filters.edited) +@sudo_users_only +async def bot_statistic(c: Client, message: Message): + chat_id = message.chat.id + user_id = message.from_user.id + msg = await c.send_message( + chat_id, "❖ Collecting Stats..." + ) + served_chats = len(await get_served_chats()) + served_users = len(await get_served_users()) + gbans_usertl = await get_gbans_count() + tgm = f""" +📊 Current Statistic of [{name}](https://t.me/{uname})`:` + +➥ **Groups Chat** : `{served_chats}` +➥ **Users Dialog** : `{served_users}` +➥ **Gbanned Users** : `{gbans_usertl}` + +➛ **Python Version** : `{pyver}` +➛ **PyTgCalls Version** : `{pytgver.__version__}` +➛ **Pyrogram Version** : `{pyrover}` + +🤖 bot version: `{ver}`""" + + await msg.edit(tgm, disable_web_page_preview=True) + + +@Client.on_message(command(["calls", f"calls@{uname}"]) & ~filters.edited) +@sudo_users_only +async def active_calls(c: Client, message: Message): + served_chats = [] + try: + chats = await get_active_chats() + for chat in chats: + served_chats.append(int(chat["chat_id"])) + except Exception as e: + await message.reply_text(f"🚫 error: `{e}`") + text = "" + j = 0 + for x in served_chats: + try: + title = (await c.get_chat(x)).title + except Exception: + title = "Private Group" + if (await c.get_chat(x)).username: + user = (await c.get_chat(x)).username + text += ( + f"**{j + 1}.** [{title}](https://t.me/{user}) [`{x}`]\n" + ) + else: + text += f"**{j + 1}.** {title} [`{x}`]\n" + j += 1 + if not text: + await message.reply_text("❌ no active group calls") + else: + await message.reply_text( + f"✏️ **Active Group Call list:**\n\n{text}\n\n❖ This is the list of all current active group call in my database.", + disable_web_page_preview=True, + ) diff --git a/program/music.py b/program/music.py index 976f931..f341c34 100644 --- a/program/music.py +++ b/program/music.py @@ -2,11 +2,14 @@ # Commit Start Date 20/10/2021 # Finished On 28/10/2021 + +import os # pyrogram stuff from pyrogram import Client from pyrogram.errors import UserAlreadyParticipant, UserNotParticipant from pyrogram.types import InlineKeyboardMarkup, Message # pytgcalls stuff +from pytgcalls import idle from pytgcalls import StreamType from pytgcalls.types.input_stream import AudioPiped from pytgcalls.types.input_stream.quality import HighQualityAudio @@ -16,8 +19,11 @@ from driver.design.thumbnail import thumb from driver.design.chatname import CHAT_TITLE from driver.filters import command, other_filters from driver.queues import QUEUE, add_to_queue -from driver.veez import call_py, user +from driver.core import calls, user, bot from driver.utils import bash +from driver.database.dbpunish import is_gbanned_user +from driver.database.dblockchat import blacklisted_chats +from driver.database.dbqueue import add_active_chat, remove_active_chat, music_on from config import BOT_USERNAME, IMG_5 # youtube-dl stuff from youtubesearchpython import VideosSearch @@ -30,7 +36,7 @@ def ytsearch(query: str): songname = data["title"] url = data["link"] duration = data["duration"] - thumbnail = f"https://i.ytimg.com/vi/{data['id']}/hqdefault.jpg" + thumbnail = data["thumbnails"][0]["url"] return [songname, url, duration, thumbnail] except Exception as e: print(e) @@ -46,12 +52,29 @@ async def ytdl(link: str): return 0, stderr +def convert_seconds(seconds): + seconds = seconds % (24 * 3600) + seconds %= 3600 + minutes = seconds // 60 + seconds %= 60 + return "%02d:%02d" % (minutes, seconds) + + @Client.on_message(command(["play", f"play@{BOT_USERNAME}"]) & other_filters) async def play(c: Client, m: Message): await m.delete() replied = m.reply_to_message chat_id = m.chat.id user_id = m.from_user.id + user_xd = f"[{m.from_user.first_name}](tg://user?id={m.from_user.id})" + if chat_id in await blacklisted_chats(): + await m.reply( + "❗️ This chat has blacklisted by sudo user and You're not allowed to use me in this chat." + ) + return await bot.leave_chat(chat_id) + if await is_gbanned_user(user_id): + await message.reply_text(f"❗️ {user_xd} **You've blocked from using this bot!**") + return if m.sender_chat: return await m.reply_text( "you're an __Anonymous__ user !\n\n» revert back to your real user account to use this bot." @@ -95,6 +118,7 @@ async def play(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) except UserNotParticipant: try: invitelink = await c.export_chat_invite_link(chat_id) @@ -103,6 +127,7 @@ async def play(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) except UserAlreadyParticipant: pass except Exception as e: @@ -114,15 +139,14 @@ async def play(c: Client, m: Message): suhu = await replied.reply("📥 **downloading audio...**") dl = await replied.download() link = replied.link - try: if replied.audio: songname = replied.audio.title[:70] songname = replied.audio.file_name[:70] - duration = replied.audio.duration + duration = convert_seconds(replied.audio.duration) elif replied.voice: songname = "Voice Note" - duration = replied.voice.duration + duration = convert_seconds(replied.voice.duration) except BaseException: songname = "Audio" @@ -142,6 +166,7 @@ async def play(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"💡 **Track added to queue »** `{pos}`\n\n🗂 **Name:** [{songname}]({link}) | `music`\n⏱️ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + os.remove(image) else: try: gcname = m.chat.title @@ -151,13 +176,15 @@ async def play(c: Client, m: Message): thumbnail = f"{IMG_5}" image = await thumb(thumbnail, title, userid, ctitle) await suhu.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioPiped( dl, HighQualityAudio(), ), - stream_type=StreamType().local_stream, + stream_type=StreamType().pulse_stream, ) add_to_queue(chat_id, songname, dl, link, "Audio", 0) await suhu.delete() @@ -168,10 +195,13 @@ async def play(c: Client, m: Message): await m.reply_photo( photo=image, reply_markup=InlineKeyboardMarkup(buttons), - caption=f"🗂 **Name:** [{songname}]({link}) | `music`\n💭 **Chat:** `{chat_id}`\n🧸 **Request by:** {requester}", + caption=f"🗂 **Name:** [{songname}]({link}) | `music`\n⏱️ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + await idle() + os.remove(image) except Exception as e: await suhu.delete() + await remove_active_chat(chat_id) await m.reply_text(f"🚫 error:\n\n» {e}") else: if len(m.command) < 2: @@ -210,10 +240,13 @@ async def play(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"💡 **Track added to queue »** `{pos}`\n\n🗂 **Name:** [{songname}]({url}) | `music`\n**⏱ Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + os.remove(image) else: try: await suhu.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioPiped( ytlink, @@ -232,8 +265,11 @@ async def play(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"🗂 **Name:** [{songname}]({url}) | `music`\n**⏱ Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + await idle() + os.remove(image) except Exception as ep: await suhu.delete() + await remove_active_chat(chat_id) await m.reply_text(f"🚫 error: `{ep}`") else: @@ -271,10 +307,13 @@ async def play(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"💡 **Track added to queue »** `{pos}`\n\n🗂 **Name:** [{songname}]({url}) | `music`\n**⏱ Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + os.remove(image) else: try: await suhu.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioPiped( ytlink, @@ -291,6 +330,9 @@ async def play(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"🗂 **Name:** [{songname}]({url}) | `music`\n**⏱ Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + await idle() + os.remove(image) except Exception as ep: await suhu.delete() + await remove_active_chat(chat_id) await m.reply_text(f"🚫 error: `{ep}`") diff --git a/program/playlist.py b/program/playlist.py index 9f39444..8c905a6 100644 --- a/program/playlist.py +++ b/program/playlist.py @@ -12,28 +12,33 @@ from pyrogram.types import ( from pyrogram import Client, filters from driver.queues import QUEUE, get_queue from driver.filters import command, other_filters +from driver.database.dbpunish import is_gbanned_user keyboard = InlineKeyboardMarkup( - [[InlineKeyboardButton("🗑 Close", callback_data="cls")]] + [[InlineKeyboardButton("🗑 Close", callback_data="set_close")]] ) @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.**") + chat_id = m.chat.id + user_id = m.from_user.id + if await is_gbanned_user(user_id): + await m.reply_text("❗️ **You've blocked from using this bot!**") + return + 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 song 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 index 85fe946..1fa64aa 100644 --- a/program/punishment.py +++ b/program/punishment.py @@ -5,16 +5,16 @@ 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.filters import command, other_filters +from driver.decorators import bot_creator 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 +@Client.on_message(command(["gban", f"gban@{bn}"]) & other_filters) +@bot_creator async def global_banned(c: Client, message: Message): if not message.reply_to_message: if len(message.command) < 2: @@ -123,8 +123,8 @@ async def global_banned(c: Client, message: Message): return -@Client.on_message(command(["ungban", f"ungban@{bn}"]) & ~filters.edited) -@sudo_users_only +@Client.on_message(command(["ungban", f"ungban@{bn}"]) & other_filters) +@bot_creator async def ungban_global(c: Client, message: Message): chat_id = message.chat.id if not message.reply_to_message: diff --git a/program/speedtest.py b/program/speedtest.py index 2edbc9e..00dc782 100644 --- a/program/speedtest.py +++ b/program/speedtest.py @@ -8,7 +8,7 @@ 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 driver.core import bot as app from pyrogram import Client, filters from pyrogram.types import Message diff --git a/program/start.py b/program/start.py index 1ccf4b3..29c9663 100644 --- a/program/start.py +++ b/program/start.py @@ -10,14 +10,16 @@ from config import ( BOT_NAME, BOT_USERNAME, GROUP_SUPPORT, - OWNER_NAME, + OWNER_USERNAME, UPDATES_CHANNEL, ) from program import __version__ -from driver.veez import user +from driver.core import user, bot from driver.filters import command, other_filters from driver.database.dbchat import add_served_chat, is_served_chat from driver.database.dbpunish import is_gbanned_user +from driver.database.dbusers import add_served_user +from driver.database.dblockchat import blacklisted_chats from pyrogram import Client, filters, __version__ as pyrover from pyrogram.errors import FloodWait, MessageNotModified from pytgcalls import (__version__ as pytover) @@ -55,10 +57,14 @@ async def _human_time_duration(seconds): @Client.on_message( command(["start", f"start@{BOT_USERNAME}"]) & filters.private & ~filters.edited ) -async def start_(client: Client, message: Message): +async def start_(c: Client, message: Message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return 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 Telegram Group video chat!** +💭 [{BOT_NAME}](https://t.me/{BOT_USERNAME}) **Is a bot to play music and video in groups, through the Telegram Group video chat!** 💡 **Find out all the Bot's commands and how they work by clicking on the » 📚 Commands button!** @@ -72,10 +78,10 @@ async def start_(client: Client, message: Message): url=f"https://t.me/{BOT_USERNAME}?startgroup=true", ) ], - [InlineKeyboardButton("❓ Basic Guide", callback_data="cbhowtouse")], + [InlineKeyboardButton("❓ Basic Guide", callback_data="user_guide")], [ - InlineKeyboardButton("📚 Commands", callback_data="cbcmds"), - InlineKeyboardButton("❤️ Donate", url=f"https://t.me/{OWNER_NAME}"), + InlineKeyboardButton("📚 Commands", callback_data="command_list"), + InlineKeyboardButton("❤️ Donate", url=f"https://t.me/{OWNER_USERNAME}"), ], [ InlineKeyboardButton( @@ -100,6 +106,10 @@ async def start_(client: Client, message: Message): command(["alive", f"alive@{BOT_USERNAME}"]) & filters.group & ~filters.edited ) async def alive(c: Client, message: Message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return chat_id = message.chat.id current_time = datetime.utcnow() uptime_sec = (current_time - START_TIME).total_seconds() @@ -127,7 +137,11 @@ async def alive(c: Client, message: Message): @Client.on_message(command(["ping", f"ping@{BOT_USERNAME}"]) & ~filters.edited) -async def ping_pong(client: Client, message: Message): +async def ping_pong(c: Client, message: Message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return start = time() m_reply = await message.reply_text("pinging...") delta_ping = time() - start @@ -135,7 +149,11 @@ async def ping_pong(client: Client, message: Message): @Client.on_message(command(["uptime", f"uptime@{BOT_USERNAME}"]) & ~filters.edited) -async def get_uptime(client: Client, message: Message): +async def get_uptime(c: Client, message: Message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return current_time = datetime.utcnow() uptime_sec = (current_time - START_TIME).total_seconds() uptime = await _human_time_duration(int(uptime_sec)) @@ -167,6 +185,11 @@ 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 chat_id in await blacklisted_chats(): + await m.reply( + "❗️ This chat has blacklisted by sudo user and You're not allowed to use me in this chat." + ) + return await bot.leave_chat(chat_id) if member.id == bot_id: return await m.reply( "❤️ Thanks for adding me to the **Group** !\n\n" @@ -186,10 +209,14 @@ async def new_chat(c: Client, m: Message): ) -chat_watcher_group = 5 +chat_watcher_group = 10 @Client.on_message(group=chat_watcher_group) async def chat_watcher_func(_, message: Message): + if message.from_user: + user_id = message.from_user.id + await add_served_user(user_id) + return try: userid = message.from_user.id except Exception: diff --git a/program/updater.py b/program/updater.py index 5fdf9d2..7bc7917 100644 --- a/program/updater.py +++ b/program/updater.py @@ -6,20 +6,24 @@ 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 pyrogram.types import Message +from pyrogram import Client, filters from config import UPSTREAM_REPO, BOT_USERNAME +from driver.core import bot +from driver.filters import command +from driver.decorators import bot_creator +from driver.database.dbqueue import get_active_chats, remove_active_chat 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_log = "" + tldr_log = "" ch = f"updates for [{ac_br}]:" ch_tl = f"updates for {ac_br}:" d_form = "%d/%m/%y || %H:%M" @@ -55,24 +59,24 @@ def updater(): @Client.on_message(command(["update", f"update@{BOT_USERNAME}"]) & ~filters.edited) -@sudo_users_only -async def update_repo(_, message: Message): +@bot_creator +async def update_bot(_, message: Message): chat_id = message.chat.id - msg = await message.reply("🔄 `processing update...`") + msg = await message.reply("❖ Checking updates...") update_avail = updater() if update_avail: - await msg.edit("✅ update finished\n\n• bot restarted, back active again in 1 minutes.") + await msg.edit("✅ Update finished !\n\n• Bot restarting, back active again in 1-2 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) + 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 +@bot_creator async def restart_bot(_, message: Message): - msg = await message.reply("`restarting bot...`") + 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.") + await msg.edit("✅ Bot restarted !\n\n• wait until 1-2 minutes after bot Rebooted.") execle(sys.executable, *args, environ) return diff --git a/program/userbot_tools.py b/program/userbot_tools.py index 499185d..47a54e2 100644 --- a/program/userbot_tools.py +++ b/program/userbot_tools.py @@ -1,11 +1,13 @@ import asyncio -from driver.veez import user +from driver.core 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 driver.database.dbchat import remove_served_chat +from driver.database.dbqueue import remove_active_chat from pyrogram.errors import UserAlreadyParticipant, UserNotParticipant -from driver.decorators import authorized_users_only, sudo_users_only +from driver.decorators import authorized_users_only, bot_creator @Client.on_message( @@ -21,6 +23,7 @@ async def join_chat(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) return await user.send_message(chat_id, "✅ userbot joined chat") except UserAlreadyParticipant: return await user.send_message(chat_id, "✅ userbot already in chat") @@ -34,6 +37,7 @@ async def leave_chat(_, m: Message): chat_id = m.chat.id try: await user.leave_chat(chat_id) + await remove_active_chat(chat_id) return await _.send_message( chat_id, "✅ userbot leaved chat", @@ -46,7 +50,7 @@ async def leave_chat(_, m: Message): @Client.on_message(command(["leaveall", f"leaveall@{BOT_USERNAME}"])) -@sudo_users_only +@bot_creator async def leave_all(client, message): if message.from_user.id not in SUDO_USERS: return @@ -58,6 +62,7 @@ async def leave_all(client, message): async for dialog in user.iter_dialogs(): try: await user.leave_chat(dialog.chat.id) + await remove_active_chat(dialog.chat.id) left += 1 await msg.edit( f"Userbot leaving all Group...\n\nLeft: {left} chats.\nFailed: {failed} chats." @@ -75,12 +80,11 @@ async def leave_all(client, message): @Client.on_message(filters.left_chat_member) -async def ubot_leave(c: Client, m: Message): -# ass_id = (await user.get_me()).id +async def bot_kicked(c: Client, m: Message): 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) + await remove_served_chat(chat_id) + await remove_active_chat(chat_id) diff --git a/program/utils/inline.py b/program/utils/inline.py index bdb21d5..3a98430 100644 --- a/program/utils/inline.py +++ b/program/utils/inline.py @@ -11,8 +11,8 @@ from pyrogram.types import ( def stream_markup(user_id): buttons = [ [ - InlineKeyboardButton(text="• Mᴇɴᴜ", callback_data=f'cbmenu | {user_id}'), - InlineKeyboardButton(text="• Cʟᴏsᴇ", callback_data=f'cls'), + InlineKeyboardButton(text="• Mᴇɴᴜ", callback_data=f'stream_menu_panel | {user_id}'), + InlineKeyboardButton(text="• Cʟᴏsᴇ", callback_data=f'set_close'), ], ] return buttons @@ -21,16 +21,16 @@ def stream_markup(user_id): 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'set_stop | {user_id}'), + InlineKeyboardButton(text="⏸", callback_data=f'set_pause | {user_id}'), + InlineKeyboardButton(text="▶️", callback_data=f'set_resume | {user_id}'), ], [ - InlineKeyboardButton(text="🔇", callback_data=f'cbmute | {user_id}'), - InlineKeyboardButton(text="🔊", callback_data=f'cbunmute | {user_id}'), + InlineKeyboardButton(text="🔇", callback_data=f'set_mute | {user_id}'), + InlineKeyboardButton(text="🔊", callback_data=f'set_unmute | {user_id}'), ], [ - InlineKeyboardButton(text="🗑 Close", callback_data='cls'), + InlineKeyboardButton(text="🔙 Go Back", callback_data='stream_home_panel'), ] ] return buttons @@ -40,7 +40,7 @@ close_mark = InlineKeyboardMarkup( [ [ InlineKeyboardButton( - "🗑 Close", callback_data="cls" + "🗑 Close", callback_data="set_close" ) ] ] @@ -51,7 +51,7 @@ back_mark = InlineKeyboardMarkup( [ [ InlineKeyboardButton( - "🔙 Go Back", callback_data="cbmenu" + "🔙 Go Back", callback_data="stream_menu_panel" ) ] ] diff --git a/program/video.py b/program/video.py index ebe5296..0b671a7 100644 --- a/program/video.py +++ b/program/video.py @@ -2,19 +2,27 @@ # Commit Start Date 20/10/2021 # Finished On 28/10/2021 + +import os import re import asyncio - +# repository stuff from config import BOT_USERNAME, IMG_1, IMG_2, IMG_5 from program.utils.inline import stream_markup from driver.design.thumbnail import thumb from driver.design.chatname import CHAT_TITLE from driver.filters import command, other_filters from driver.queues import QUEUE, add_to_queue -from driver.veez import call_py, user +from driver.core import calls, user, bot +from driver.database.dbpunish import is_gbanned_user +from driver.database.dblockchat import blacklisted_chats +from driver.database.dbqueue import add_active_chat, remove_active_chat, music_on +# pyrogram stuff from pyrogram import Client from pyrogram.errors import UserAlreadyParticipant, UserNotParticipant from pyrogram.types import InlineKeyboardMarkup, Message +# py-tgcalls stuff +from pytgcalls import idle from pytgcalls import StreamType from pytgcalls.types.input_stream import AudioVideoPiped from pytgcalls.types.input_stream.quality import ( @@ -23,6 +31,7 @@ from pytgcalls.types.input_stream.quality import ( LowQualityVideo, MediumQualityVideo, ) +# youtube-dl stuff from youtubesearchpython import VideosSearch @@ -33,7 +42,7 @@ def ytsearch(query: str): songname = data["title"] url = data["link"] duration = data["duration"] - thumbnail = f"https://i.ytimg.com/vi/{data['id']}/hqdefault.jpg" + thumbnail = data["thumbnails"][0]["url"] return [songname, url, duration, thumbnail] except Exception as e: print(e) @@ -57,12 +66,29 @@ async def ytdl(link): return 0, stderr.decode() +def convert_seconds(seconds): + seconds = seconds % (24 * 3600) + seconds %= 3600 + minutes = seconds // 60 + seconds %= 60 + return "%02d:%02d" % (minutes, seconds) + + @Client.on_message(command(["vplay", f"vplay@{BOT_USERNAME}"]) & other_filters) async def vplay(c: Client, m: Message): await m.delete() replied = m.reply_to_message chat_id = m.chat.id user_id = m.from_user.id + user_xd = f"[{m.from_user.first_name}](tg://user?id={m.from_user.id})" + if chat_id in await blacklisted_chats(): + await m.reply( + "❗️ This chat has blacklisted by sudo user and You're not allowed to use me in this chat." + ) + return await bot.leave_chat(chat_id) + if await is_gbanned_user(user_id): + await message.reply_text(f"❗️ {user_xd} **You've blocked from using this bot!**") + return if m.sender_chat: return await m.reply_text( "you're an __Anonymous__ user !\n\n» revert back to your real user account to use this bot." @@ -106,6 +132,7 @@ async def vplay(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) except UserNotParticipant: try: invitelink = await c.export_chat_invite_link(chat_id) @@ -114,13 +141,13 @@ async def vplay(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) except UserAlreadyParticipant: pass except Exception as e: return await m.reply_text( f"❌ **userbot failed to join**\n\n**reason**: `{e}`" ) - if replied: if replied.video or replied.document: loser = await replied.reply("📥 **downloading video...**") @@ -135,15 +162,15 @@ async def vplay(c: Client, m: Message): else: Q = 720 await loser.edit( - "» __only 720, 480, 360 allowed__ \n💡 **now streaming video in 720p**" + "» only 720, 480, 360 allowed\n\n💡 now streaming video in **720p**" ) try: if replied.video: songname = replied.video.file_name[:70] - duration = replied.video.duration + duration = convert_seconds(replied.video.duration) elif replied.document: songname = replied.document.file_name[:70] - duration = replied.document.duration + duration = convert_seconds(replied.document.duration) except BaseException: songname = "Video" @@ -163,6 +190,7 @@ async def vplay(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"💡 **Track added to queue »** `{pos}`\n\n🗂 **Name:** [{songname}]({link}) | `video`\n⏱️ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + os.remove(image) else: gcname = m.chat.title ctitle = await CHAT_TITLE(gcname) @@ -177,14 +205,16 @@ async def vplay(c: Client, m: Message): elif Q == 360: amaze = LowQualityVideo() await loser.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioVideoPiped( dl, HighQualityAudio(), amaze, ), - stream_type=StreamType().local_stream, + stream_type=StreamType().pulse_stream, ) add_to_queue(chat_id, songname, dl, link, "Video", Q) await loser.delete() @@ -195,6 +225,8 @@ async def vplay(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"🗂 **Name:** [{songname}]({link}) | `video`\n⏱️ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + await idle() + os.remove(image) else: if len(m.command) < 2: await m.reply( @@ -234,10 +266,13 @@ async def vplay(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"💡 **Track added to queue »** `{pos}`\n\n🗂 **Name:** [{songname}]({url}) | `video`\n⏱ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + os.remove(image) else: try: await loser.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioVideoPiped( ytlink, @@ -255,8 +290,11 @@ async def vplay(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"🗂 **Name:** [{songname}]({url}) | `video`\n⏱ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + await idle() + os.remove(image) except Exception as ep: await loser.delete() + await remove_active_chat(chat_id) await m.reply_text(f"🚫 error: `{ep}`") else: @@ -298,10 +336,13 @@ async def vplay(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"💡 **Track added to queue »** `{pos}`\n\n🗂 **Name:** [{songname}]({url}) | `video`\n⏱ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + os.remove(image) else: try: await loser.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioVideoPiped( ytlink, @@ -319,8 +360,11 @@ async def vplay(c: Client, m: Message): reply_markup=InlineKeyboardMarkup(buttons), caption=f"🗂 **Name:** [{songname}]({url}) | `video`\n⏱ **Duration:** `{duration}`\n🧸 **Request by:** {requester}", ) + await idle() + os.remove(image) except Exception as ep: await loser.delete() + await remove_active_chat(chat_id) await m.reply_text(f"🚫 error: `{ep}`") @@ -329,6 +373,15 @@ async def vstream(c: Client, m: Message): await m.delete() chat_id = m.chat.id user_id = m.from_user.id + user_xd = f"[{m.from_user.first_name}](tg://user?id={m.from_user.id})" + if chat_id in await blacklisted_chats(): + await m.reply( + "❗️ This chat has blacklisted by sudo user and You're not allowed to use me in this chat." + ) + return await bot.leave_chat(chat_id) + if await is_gbanned_user(user_id): + await message.reply_text(f"❗️ {user_xd} **You've blocked from using this bot!**") + return if m.sender_chat: return await m.reply_text( "you're an __Anonymous__ user !\n\n» revert back to your real user account to use this bot." @@ -372,6 +425,7 @@ async def vstream(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) except UserNotParticipant: try: invitelink = await c.export_chat_invite_link(chat_id) @@ -380,6 +434,7 @@ async def vstream(c: Client, m: Message): "https://t.me/+", "https://t.me/joinchat/" ) await user.join_chat(invitelink) + await remove_active_chat(chat_id) except UserAlreadyParticipant: pass except Exception as e: @@ -403,11 +458,11 @@ async def vstream(c: Client, m: Message): else: Q = 720 await m.reply( - "» __only 720, 480, 360 allowed__ \n💡 **now streaming video in 720p**" + "» only 720, 480, 360 allowed\n\n💡 now streaming video in **720p**" ) loser = await c.send_message(chat_id, "🔄 **processing stream...**") else: - await m.reply("**/vstream {link} {720/480/360}**") + await m.reply("`/vstream` {link} {720/480/360}") regex = r"^(https?\:\/\/)?(www\.youtube\.com|youtu\.?be)\/.+" match = re.match(regex, link) @@ -439,7 +494,9 @@ async def vstream(c: Client, m: Message): amaze = LowQualityVideo() try: await loser.edit("🔄 **Joining vc...**") - await call_py.join_group_call( + await music_on(chat_id) + await add_active_chat(chat_id) + await calls.join_group_call( chat_id, AudioVideoPiped( livelink, @@ -461,4 +518,5 @@ async def vstream(c: Client, m: Message): ) except Exception as ep: await loser.delete() + await remove_active_chat(chat_id) await m.reply_text(f"🚫 error: `{ep}`") diff --git a/program/ytsearch.py b/program/ytsearch.py index a11f748..4ddf6db 100644 --- a/program/ytsearch.py +++ b/program/ytsearch.py @@ -1,5 +1,6 @@ from config import BOT_USERNAME from driver.filters import command +from driver.database.dbpunish import is_gbanned_user from pyrogram import Client from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message from youtube_search import YoutubeSearch @@ -7,6 +8,10 @@ from youtube_search import YoutubeSearch @Client.on_message(command(["search", f"search@{BOT_USERNAME}"])) async def ytsearch(_, message: Message): + user_id = message.from_user.id + if await is_gbanned_user(user_id): + await message.reply_text("❗️ **You've blocked from using this bot!**") + return if len(message.command) < 2: return await message.reply_text("/search **needs an argument !**") query = message.text.split(None, 1)[1] @@ -26,6 +31,6 @@ async def ytsearch(_, message: Message): text, disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup( - [[InlineKeyboardButton("🗑 Close", callback_data="cls")]] + [[InlineKeyboardButton("🗑 Close", callback_data="close_panel")]] ), ) diff --git a/requirements.txt b/requirements.txt index 12d44aa..7455ae2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,5 +17,4 @@ requests pillow motor psutil -future wget