-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5886bbc
Showing
66 changed files
with
1,989 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
BOT_TOKEN= | ||
API_ID= | ||
MONGO_URL= | ||
API_HASH= | ||
webhookUrl= | ||
WEBHOOK_AUTH= | ||
BOT_URL=https://t.me/vcplayerbot | ||
PARENT_URL=https://t.me/sktechhub | ||
SUPPORT_GROUP=https://t.me/voicechatsupport | ||
HELPER_ACT= | ||
HELPER_ACT_ID= | ||
BOT_ID= | ||
LOG_INSIGHT_KEY= | ||
LOG_INSIGHT_REGION= | ||
BOT_SESSION= | ||
USERBOT_SESSION= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
venv | ||
songs | ||
images | ||
Logs | ||
.env | ||
.env.local |
Binary file not shown.
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from callmanager import user_app | ||
from utils.Logger import * | ||
import asyncio | ||
from utils.MongoClient import MongoDBClient | ||
from utils.Config import Config | ||
from bson import json_util | ||
import asyncio | ||
import schedule | ||
from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant | ||
|
||
mongo_client = MongoDBClient() | ||
config = Config() | ||
|
||
|
||
async def handle_db_calls(): | ||
while True: | ||
try: | ||
# for runtime data | ||
run_data = mongo_client.fetchRunTimeData() | ||
# logInfo(f"Making call to fetch runtime data") | ||
if run_data is not None: | ||
if run_data.get("alowed_chat_types") not in [None]: | ||
config.setAllowedChatTypes( | ||
run_data.get("alowed_chat_types")) | ||
if run_data.get("global_admins") not in [None]: | ||
config.saveGlobalAdmins(run_data.get("global_admins")) | ||
if isinstance(run_data.get("simultaneous_calls"), int) is True: | ||
config.save_simultaneous_calls( | ||
run_data.get("simultaneous_calls")) | ||
if isinstance(run_data.get("playlist_size"), int) is True: | ||
config.save_playlist_size( | ||
run_data.get("playlist_size")) | ||
if run_data.get("playback_footer") not in [None, '']: | ||
config.save_playback_footer( | ||
run_data.get("playback_footer")) | ||
else: | ||
config.save_playback_footer('') | ||
else: | ||
logException("DB handler runtime data is none", True) | ||
|
||
# fetch active clients | ||
active_clients = mongo_client.get_all_chats() | ||
# logInfo( | ||
# f"Making call to fetch active clients : {len(active_clients)}") | ||
config.setActiveClients(active_clients) | ||
schedule.run_pending() | ||
except Exception as ex: | ||
logException(f"Error in handle_db_calls: {ex}", True) | ||
finally: | ||
if config.get("env") == "local": | ||
await asyncio.sleep(5) | ||
else: | ||
await asyncio.sleep(30) | ||
|
||
|
||
async def leaveStaleChats(): | ||
try: | ||
left = [] | ||
failed = [] | ||
distinct_docs = mongo_client.chats_to_disconnect() | ||
for chat in distinct_docs: | ||
try: | ||
chat_id = None | ||
c = chat.get("chat") | ||
if c is not None: | ||
chat_id = c.get("chat_id") | ||
await user_app.leave_chat(chat_id) | ||
left.append(chat_id) | ||
await asyncio.sleep(5) | ||
except UserNotParticipant as e: | ||
left.append(chat_id) | ||
except Exception as ex: | ||
failed.append(chat_id) | ||
logWarning(f"Error in leave chat inside loop {ex}") | ||
logException(f"Left the chats : Done {left} , Failed : {failed} ") | ||
except Exception as ex: | ||
logException(f"Error in leaveStaeChats , {ex}", True) |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[ZoneTransfer] | ||
ZoneId=3 | ||
ReferrerUrl=about:blank | ||
HostUrl=https://www35.online-convert.com/dl/web7/download-file/c32fcf71-c971-4985-ac1a-9ded3e572501/skumar1.png |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import asyncio | ||
import os | ||
import aiofiles | ||
import aiohttp | ||
from PIL import Image, ImageDraw, ImageFont, ImageFilter | ||
import uuid | ||
from utils.Logger import * | ||
from urllib.request import urlopen | ||
|
||
|
||
# ITC_BOLD = ImageFont.truetype( | ||
# "etc/ITC Avant Garde Gothic LT Bold.otf", 32) | ||
KRONA = ImageFont.truetype("etc/KronaOne-Regular.ttf", 48) | ||
KRONA_52 = ImageFont.truetype("etc/KronaOne-Regular.ttf", 52) | ||
ITC_REG = ImageFont.truetype( | ||
"etc/ITC Avant Garde Gothic LT Book Regular.otf", 48) | ||
KRONA_SMALL = ImageFont.truetype("etc/KronaOne-Regular.ttf", 32) | ||
|
||
|
||
def changeImageSize(maxWidth, maxHeight, image): | ||
widthRatio = maxWidth / image.size[0] | ||
heightRatio = maxHeight / image.size[1] | ||
newWidth = int(widthRatio * image.size[0]) | ||
newHeight = int(heightRatio * image.size[1]) | ||
newImage = image.resize((newWidth, newHeight), Image.NEAREST) | ||
return newImage | ||
|
||
|
||
async def generate_cover(title, thumbnail, result_file_name): | ||
temp_file = uuid.uuid4() | ||
final_img = None | ||
try: | ||
logInfo( | ||
f"Request to generate cover for title : {title} , thumbnail : {thumbnail} , filename : {result_file_name}") | ||
if len(title) == 0: | ||
return None | ||
title = title.strip() | ||
if len(title) > 25: | ||
title = title[:22]+str('...') | ||
|
||
downloaded_thumbnail = Image.open(urlopen(thumbnail)) | ||
|
||
foreground = Image.open(f"etc/foreground_converted_rgba.png") | ||
resized_thumbnail = changeImageSize(1280, 720, downloaded_thumbnail) | ||
|
||
background = resized_thumbnail.convert("RGBA") | ||
|
||
Image.alpha_composite(background, foreground).save( | ||
f"images/{temp_file}.png", optimize=True, quality=10) | ||
|
||
img = Image.open(f"images/{temp_file}.png") | ||
draw = ImageDraw.Draw(img) | ||
|
||
draw.text((10, 580), f"Now Playing", fill="white", font=ITC_REG) | ||
|
||
draw.text((10, 640), f"{title}", fill="white", font=KRONA_52) | ||
|
||
draw.text((985, 20), f"A SkTechHub", fill="white", font=KRONA_SMALL) | ||
draw.text((1100, 50), f"Product", fill="white", font=KRONA_SMALL) | ||
|
||
img.save(result_file_name, optimize=True, quality=20) | ||
final_img = result_file_name | ||
except Exception as ex: | ||
logException(f"Error while generating cover : {ex}", True) | ||
final_img = None | ||
finally: | ||
return result_file_name if final_img is not None else None | ||
|
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import asyncio | ||
from typing import Callable | ||
from bson import json_util | ||
from pyrogram import Client | ||
from pyrogram.types import Message | ||
from utils.Logger import * | ||
from utils.Config import Config | ||
from utils.MongoClient import MongoDBClient | ||
from helpers.fromatMessages import getMessage | ||
|
||
config = Config() | ||
MongoDBClient = MongoDBClient() | ||
|
||
|
||
def errors(func: Callable) -> Callable: | ||
async def decorator(client: Client, message: Message): | ||
try: | ||
return await func(client, message) | ||
except Exception as e: | ||
await message.reply(f"{type(e).__name__}: {e}") | ||
|
||
return decorator | ||
|
||
|
||
def hasRequiredPermission(user): | ||
try: | ||
required = ['can_post_messages', 'can_edit_messages', 'can_invite_users', | ||
'can_delete_messages', 'can_manage_voice_chats', 'can_promote_members'] | ||
not_present = [] | ||
for _ in required: | ||
if hasattr(user, _) is not True or user[_] is False: | ||
not_present.append(_) | ||
return len(not_present) == 0 | ||
except Exception as ex: | ||
logWarning(f"Error while checking for required permission : {ex}") | ||
return False | ||
|
||
|
||
async def delayDelete(message, delay): | ||
try: | ||
await asyncio.sleep(delay) | ||
await message.delete() | ||
except Exception as ex: | ||
logException("Error while deleteing message : {message} , {ex}", True) | ||
|
||
|
||
def chat_allowed(func: Callable) -> Callable: | ||
async def decorator(client: Client, message: Message): | ||
try: | ||
ALLOWED_CHAT_TYPES = config.get("ALLOWED_CHAT_TYPES") | ||
current_client = config.fetchClient(message.chat.id) | ||
|
||
# if the user is from a disallowed chat type show error message | ||
if message.chat.type not in ALLOWED_CHAT_TYPES: | ||
logInfo( | ||
f"user not allowed to perform action in chat : {message.chat.id} , {message.chat.type}") | ||
|
||
# if this is a provate message then add to database | ||
if message.chat and message.chat.type == "private": | ||
document = {"chat_id": message.chat.id, "type": "private", "username": message.chat.username if hasattr(message.chat, 'username') else "", "first_name": message.chat.first_name if hasattr(message.chat, 'first_name') else "", | ||
"last_name": message.chat.last_name if hasattr(message.chat, 'last_name') else "", "updated_at": datetime.now()} | ||
MongoDBClient.add_tgcalls_users(document) | ||
msg, kbd = getMessage(message, 'private-chat') | ||
return await client.send_message(message.chat.id, f"{msg}", disable_web_page_preview=True, reply_markup=kbd) | ||
if current_client in [None, []]: | ||
logInfo(f"Added a new client in db => {message.chat.id}") | ||
document = {"chat_id": message.chat.id, "type": message.chat.type, "username": message.chat.username if hasattr(message.chat, 'username') else "", "title": message.chat.title if hasattr(message.chat, 'title') else "", | ||
"permissions": {}, "updated_at": datetime.now(), 'admins': [], 'active': True, 'remove_messages': -1, 'admin_mode': False} | ||
MongoDBClient.add_tgcalls_chats(document) | ||
current_client = config.fetchClient(message.chat.id) | ||
|
||
if current_client.get('active') is not True: | ||
logInfo( | ||
f"chat not allowed to perform action : {message.chat.id} , {message.chat.type}") | ||
|
||
msg, kbd = getMessage(message, 'chat-not-allowed') | ||
return await client.send_message(message.chat.id, f"{msg}", disable_web_page_preview=True, reply_markup=kbd) | ||
|
||
return await func(client, message, current_client) | ||
except Exception as ex: | ||
logException(f"Error in chat_allowed : {ex}", True) | ||
return decorator | ||
|
||
|
||
def admin_check(func: Callable) -> Callable: | ||
async def decorator(client: Client, message: Message, current_client=None): | ||
try: | ||
chat_id = message.chat.id | ||
admins = config.getAdminForChat(chat_id) | ||
if message.from_user is None or message.from_user.id in [a['chat_id'] for a in admins]: | ||
current_client = config.fetchClient(message.chat.id) | ||
return await func(client, message, current_client) | ||
else: | ||
logWarning( | ||
f"Action blocked as user is not admin : {message.from_user} in chat {chat_id}, current_chat admins : {admins}") | ||
m = await client.send_message(message.chat.id, f"**__This action can be performed only by admins.__**") | ||
await delayDelete(m, 10) | ||
except Exception as ex: | ||
logException(f"Error in admin_check : {ex}", True) | ||
return decorator | ||
|
||
|
||
def admin_mode_check(func: Callable) -> Callable: | ||
async def decorator(client: Client, message: Message, current_client): | ||
try: | ||
chat_id = message.chat.id | ||
if current_client is not None and current_client.get('admin_mode') is not True: | ||
return await func(client, message, current_client) | ||
admins = config.getAdminForChat(chat_id) | ||
if message.from_user is None or message.from_user.id in [a['chat_id'] for a in admins]: | ||
return await func(client, message, current_client) | ||
|
||
logWarning( | ||
f"Action blocked as user is not admin and admin_mode is on : {message.from_user} , current_chat admins : {admins}") | ||
msg = f"**❌ Admin mode is on in chat and your are not an admin[ Bot Admin ].**" | ||
msg = msg + f"\n\n__Ask the admin to add you as admin using /auth command or disable the admin mode.__" | ||
m = await client.send_message(message.chat.id, f"{msg}") | ||
await delayDelete(m, 10) | ||
except Exception as ex: | ||
logException(f"Error in admin_mode_check : {ex}", True) | ||
return decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message | ||
from utils.Logger import * | ||
from utils.Config import Config | ||
|
||
Config = Config() | ||
|
||
|
||
def getMessage(message, action): | ||
try: | ||
ALLOWED_CHAT_TYPES = config.get("ALLOWED_CHAT_TYPES") | ||
|
||
if action == "private-chat": | ||
send_message = f"**Hi 🎵 {message.chat.first_name if hasattr(message.chat, 'first_name') else 'User'}**" | ||
send_message = send_message + \ | ||
f"\n\n**[Voice Chat Music Player]({config.get('BOT_URL')})** is a [SkTechHub Product]({config.get('PARENT_URL')})." | ||
send_message = send_message + \ | ||
f"\n__It is designed to play, as simple as possible, music in your groups through the **new voice chats** introduced by Telegram.__" | ||
send_message = send_message + \ | ||
f"\n\n**So why wait 🌀 add the bot to a group and get started 🎧**" | ||
return send_message, getReplyKeyBoard(message, action) | ||
|
||
elif action == "help-msg": | ||
helpMessage = f"**VoiceChat Music Player (b1.5)**\n__Currently Available in **limited groups**.__" | ||
helpMessage = helpMessage + \ | ||
f"\n\n• **/play song name/song url : ** __Start a song / add to queue.__" | ||
helpMessage = helpMessage + f"\n• **/skip : ** __Skip to the next song in queue.__" | ||
helpMessage = helpMessage + f"\n• **/stop : ** __Stop the playback.__" | ||
helpMessage = helpMessage + \ | ||
f"\n• **/refreshadmins : ** __Refreshes the admin list.__" | ||
helpMessage = helpMessage + \ | ||
f"\n• **/auth : ** __Adds the user in reply to the message as admin.__" | ||
helpMessage = helpMessage + \ | ||
f"\n• **/unauth : ** __Removes the user in reply to the message as admin.__" | ||
helpMessage = helpMessage + \ | ||
f"\n• **/listadmins : ** __Lists the users assigned as admins for the bot.__" | ||
helpMessage = helpMessage + \ | ||
f"\n• **/adminmode on|off : ** __Turning this on makes the bot actions available only to bot admins.__" | ||
helpMessage = helpMessage + \ | ||
f"\n• **/loop [2-5]|off : ** __Loop the playback [x] times(x is between 2-5) / Turn off the loop playback.__" | ||
helpMessage = helpMessage + f"\n\n**__For any issues contact @voicechatsupport__**" | ||
return helpMessage, getReplyKeyBoard(message, action) | ||
|
||
elif action == "chat-not-allowed": | ||
send_message = f"**😖 Sorry but this chat is not yet allowed to access the service. You can always check the demo in [Support Group]({config.get('SUPPORT_GROUP')}).**" | ||
send_message = send_message + \ | ||
f"\n\n**Why ❓**\n1. __This service is still in testing phase and we are allowing access on an invite basis. To get access contact [Support Group]({config.get('SUPPORT_GROUP')}) __" | ||
send_message = send_message + \ | ||
f"\n2. __Or your account has been banned. Contact [Support Group]({config.get('SUPPORT_GROUP')}).__" | ||
|
||
return send_message, getReplyKeyBoard(message, action) | ||
|
||
elif action == "start-voice-chat": | ||
send_message = f"**Please start a voice chat and then send the command again**" | ||
send_message = send_message + \ | ||
f"\n**1.** __To start a group chat, you can head over to your group’s description page.__" | ||
send_message = send_message + \ | ||
f"\n**2.** __Then tap the three-dot button next to Mute and Search start a Voice Chat.__" | ||
return send_message, getReplyKeyBoard(message, action) | ||
|
||
except Exception as ex: | ||
logException(f"**__Error : {ex}__**", True) | ||
|
||
|
||
def getReplyKeyBoard(message, action): | ||
try: | ||
if action == "private-chat": | ||
keyboard = InlineKeyboardMarkup( | ||
[ | ||
[ | ||
InlineKeyboardButton( | ||
"➕ Add the bot to Group ➕", url=f"{config.get('BOT_URL')}?startgroup=bot"), | ||
], | ||
[ | ||
InlineKeyboardButton( | ||
"👥 Support Group", url=f"{config.get('SUPPORT_GROUP')}"), | ||
|
||
InlineKeyboardButton( | ||
"🌐 Website", url=f"{config.get('PARENT_URL')}"), | ||
], | ||
|
||
] | ||
) | ||
return keyboard | ||
return None | ||
except Exception as ex: | ||
logException(f"**__Error : {ex}__**", True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from helpers.queues.queues import ( | ||
clear, | ||
get, | ||
is_empty, | ||
put, | ||
task_done, | ||
size | ||
) |
Binary file not shown.
Binary file not shown.
Oops, something went wrong.