Save-Restricted-Content-Bot-v3/utils/func.py
2025-05-23 22:18:58 +05:30

341 lines
11 KiB
Python

# Copyright (c) 2025 devgagan : https://github.com/devgaganin.
# Licensed under the GNU General Public License v3.0.
# See LICENSE file in the repository root for full license text.
import concurrent.futures
import time
import os
import re
import cv2
import logging
import asyncio
from datetime import datetime, timedelta
from motor.motor_asyncio import AsyncIOMotorClient
from config import MONGO_DB as MONGO_URI, DB_NAME
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
PUBLIC_LINK_PATTERN = re.compile(r'(https?://)?(t\.me|telegram\.me)/([^/]+)(/(\d+))?')
PRIVATE_LINK_PATTERN = re.compile(r'(https?://)?(t\.me|telegram\.me)/c/(\d+)(/(\d+))?')
VIDEO_EXTENSIONS = {"mp4", "mkv", "avi", "mov", "wmv", "flv", "webm", "mpeg", "mpg", "3gp"}
mongo_client = AsyncIOMotorClient(MONGO_URI)
db = mongo_client[DB_NAME]
users_collection = db["users"]
premium_users_collection = db["premium_users"]
statistics_collection = db["statistics"]
codedb = db["redeem_code"]
# ------- < start > Session Encoder don't change -------
a1 = "c2F2ZV9yZXN0cmljdGVkX2NvbnRlbnRfYm90cw=="
a2 = "Nzk2"
a3 = "Z2V0X21lc3NhZ2Vz"
a4 = "cmVwbHlfcGhvdG8="
a5 = "c3RhcnQ="
attr1 = "cGhvdG8="
attr2 = "ZmlsZV9pZA=="
a7 = "SGkg8J+RiyBXZWxjb21lLCBXYW5uYSBpbnRyby4uLj8gCgrinLPvuI8gSSBjYW4gc2F2ZSBwb3N0cyBmcm9tIGNoYW5uZWxzIG9yIGdyb3VwcyB3aGVyZSBmb3J3YXJkaW5nIGlzIG9mZi4gSSBjYW4gZG93bmxvYWQgdmlkZW9zL2F1ZGlvIGZyb20gWVQsIElOU1RBLCAuLi4gc29jaWFsIHBsYXRmb3JtcwrinLPvuI8gU2ltcGx5IHNlbmQgdGhlIHBvc3QgbGluayBvZiBhIHB1YmxpYyBjaGFubmVsLiBGb3IgcHJpdmF0ZSBjaGFubmVscywgZG8gL2xvZ2luLiBTZW5kIC9oZWxwIHRvIGtub3cgbW9yZS4="
a8 = "Sm9pbiBDaGFubmVs"
a9 = "R2V0IFByZW1pdW0="
a10 = "aHR0cHM6Ly90Lm1lL3RlYW1fc3B5X3Bybw=="
a11 = "aHR0cHM6Ly90Lm1lL2tpbmdvZnBhdGFs"
# ------- < end > Session Encoder don't change --------
def is_private_link(link):
return bool(PRIVATE_LINK_PATTERN.match(link))
def thumbnail(sender):
return f'{sender}.jpg' if os.path.exists(f'{sender}.jpg') else None
def hhmmss(seconds):
return time.strftime('%H:%M:%S', time.gmtime(seconds))
def E(L):
private_match = re.match(r'https://t\.me/c/(\d+)/(?:\d+/)?(\d+)', L)
public_match = re.match(r'https://t\.me/([^/]+)/(?:\d+/)?(\d+)', L)
if private_match:
return f'-100{private_match.group(1)}', int(private_match.group(2)), 'private'
elif public_match:
return public_match.group(1), int(public_match.group(2)), 'public'
return None, None, None
def get_display_name(user):
if user.first_name and user.last_name:
return f"{user.first_name} {user.last_name}"
elif user.first_name:
return user.first_name
elif user.last_name:
return user.last_name
elif user.username:
return user.username
else:
return "Unknown User"
def sanitize_filename(filename):
return re.sub(r'[<>:"/\\|?*]', '_', filename)
def get_dummy_filename(info):
file_type = info.get("type", "file")
extension = {
"video": "mp4",
"photo": "jpg",
"document": "pdf",
"audio": "mp3"
}.get(file_type, "bin")
return f"downloaded_file_{int(time.time())}.{extension}"
async def is_private_chat(event):
return event.is_private
async def save_user_data(user_id, key, value):
await users_collection.update_one(
{"user_id": user_id},
{"$set": {key: value}},
upsert=True
)
# print(users_collection)
async def get_user_data_key(user_id, key, default=None):
user_data = await users_collection.find_one({"user_id": int(user_id)})
# print(f"Fetching key '{key}' for user {user_id}: {user_data}")
return user_data.get(key, default) if user_data else default
async def get_user_data(user_id):
try:
user_data = await users_collection.find_one({"user_id": user_id})
return user_data
except Exception as e:
# logger.error(f"Error retrieving user data for {user_id}: {e}")
return None
async def save_user_session(user_id, session_string):
try:
await users_collection.update_one(
{"user_id": user_id},
{"$set": {
"session_string": session_string,
"updated_at": datetime.now()
}},
upsert=True
)
logger.info(f"Saved session for user {user_id}")
return True
except Exception as e:
logger.error(f"Error saving session for user {user_id}: {e}")
return False
async def remove_user_session(user_id):
try:
await users_collection.update_one(
{"user_id": user_id},
{"$unset": {"session_string": ""}}
)
logger.info(f"Removed session for user {user_id}")
return True
except Exception as e:
logger.error(f"Error removing session for user {user_id}: {e}")
return False
async def save_user_bot(user_id, bot_token):
try:
await users_collection.update_one(
{"user_id": user_id},
{"$set": {
"bot_token": bot_token,
"updated_at": datetime.now()
}},
upsert=True
)
logger.info(f"Saved bot token for user {user_id}")
return True
except Exception as e:
logger.error(f"Error saving bot token for user {user_id}: {e}")
return False
async def remove_user_bot(user_id):
try:
await users_collection.update_one(
{"user_id": user_id},
{"$unset": {"bot_token": ""}}
)
logger.info(f"Removed bot token for user {user_id}")
return True
except Exception as e:
logger.error(f"Error removing bot token for user {user_id}: {e}")
return False
async def process_text_with_rules(user_id, text):
if not text:
return ""
try:
replacements = await get_user_data_key(user_id, "replacement_words", {})
delete_words = await get_user_data_key(user_id, "delete_words", [])
processed_text = text
for word, replacement in replacements.items():
processed_text = processed_text.replace(word, replacement)
if delete_words:
words = processed_text.split()
filtered_words = [w for w in words if w not in delete_words]
processed_text = " ".join(filtered_words)
return processed_text
except Exception as e:
logger.error(f"Error processing text with rules: {e}")
return text
async def screenshot(video: str, duration: int, sender: str) -> str | None:
existing_screenshot = f"{sender}.jpg"
if os.path.exists(existing_screenshot):
return existing_screenshot
time_stamp = hhmmss(duration // 2)
output_file = datetime.now().isoformat("_", "seconds") + ".jpg"
cmd = [
"ffmpeg",
"-ss", time_stamp,
"-i", video,
"-frames:v", "1",
output_file,
"-y"
]
process = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
if os.path.isfile(output_file):
return output_file
else:
print(f"FFmpeg Error: {stderr.decode().strip()}")
return None
async def get_video_metadata(file_path):
default_values = {'width': 1, 'height': 1, 'duration': 1}
loop = asyncio.get_event_loop()
executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)
try:
def _extract_metadata():
try:
vcap = cv2.VideoCapture(file_path)
if not vcap.isOpened():
return default_values
width = round(vcap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = round(vcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = vcap.get(cv2.CAP_PROP_FPS)
frame_count = vcap.get(cv2.CAP_PROP_FRAME_COUNT)
if fps <= 0:
return default_values
duration = round(frame_count / fps)
if duration <= 0:
return default_values
vcap.release()
return {'width': width, 'height': height, 'duration': duration}
except Exception as e:
logger.error(f"Error in video_metadata: {e}")
return default_values
return await loop.run_in_executor(executor, _extract_metadata)
except Exception as e:
logger.error(f"Error in get_video_metadata: {e}")
return default_values
async def add_premium_user(user_id, duration_value, duration_unit):
try:
now = datetime.now()
expiry_date = None
if duration_unit == "min":
expiry_date = now + timedelta(minutes=duration_value)
elif duration_unit == "hours":
expiry_date = now + timedelta(hours=duration_value)
elif duration_unit == "days":
expiry_date = now + timedelta(days=duration_value)
elif duration_unit == "weeks":
expiry_date = now + timedelta(weeks=duration_value)
elif duration_unit == "month":
expiry_date = now + timedelta(days=30 * duration_value)
elif duration_unit == "year":
expiry_date = now + timedelta(days=365 * duration_value)
elif duration_unit == "decades":
expiry_date = now + timedelta(days=3650 * duration_value)
else:
return False, "Invalid duration unit"
await premium_users_collection.update_one(
{"user_id": user_id},
{"$set": {
"user_id": user_id,
"subscription_start": now,
"subscription_end": expiry_date,
"expireAt": expiry_date
}},
upsert=True
)
await premium_users_collection.create_index("expireAt", expireAfterSeconds=0)
return True, expiry_date
except Exception as e:
logger.error(f"Error adding premium user {user_id}: {e}")
return False, str(e)
async def is_premium_user(user_id):
try:
user = await premium_users_collection.find_one({"user_id": user_id})
if user and "subscription_end" in user:
now = datetime.now()
return now < user["subscription_end"]
return False
except Exception as e:
logger.error(f"Error checking premium status for {user_id}: {e}")
return False
async def get_premium_details(user_id):
try:
user = await premium_users_collection.find_one({"user_id": user_id})
if user and "subscription_end" in user:
return user
return None
except Exception as e:
logger.error(f"Error getting premium details for {user_id}: {e}")
return None