{{file_name}}
53 |├── Procfile
├── runtime.txt
├── SAFARI
├── __init__.py
├── utils
│ ├── exceptions.py
│ ├── file_size.py
│ ├── human_readable.py
│ ├── config_parser.py
│ ├── keepalive.py
│ ├── time_format.py
│ ├── clients.py
│ ├── render_template.py
│ ├── __init__.py
│ ├── file_properties.py
│ └── custom_dl.py
├── template
│ ├── __init__.py
│ ├── dl.html
│ └── req.html
└── route.py
├── Dockerfile
├── docker-compose.yml
├── start.sh
├── requirements.txt
├── plugins
├── Dev_Feature
│ ├── features
│ │ ├── stickerid.py
│ │ ├── telegraph.py
│ │ └── font.py
│ ├── autojoin.py
│ ├── Request.py
│ ├── getfile.py
│ ├── Redeem.py
│ ├── Group_Verify.py
│ └── Premium.py
├── banned.py
├── files_delete.py
├── broadcast.py
├── channel.py
├── connection.py
├── misc.py
├── p_ttishow.py
└── index.py
├── logging.conf
├── database
├── safari_reffer.py
├── connections_mdb.py
├── ia_filterdb.py
└── users_chats_db.py
├── app.json
├── bot.py
├── README.md
├── info.py
├── Script.py
└── utils.py
/Procfile:
--------------------------------------------------------------------------------
1 | web: python3 bot.py
2 |
--------------------------------------------------------------------------------
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.10.13
2 |
--------------------------------------------------------------------------------
/SAFARI/__init__.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | StartTime = time.time()
4 | __version__ = 1.1
5 |
--------------------------------------------------------------------------------
/SAFARI/utils/exceptions.py:
--------------------------------------------------------------------------------
1 | class InvalidHash(Exception):
2 | message = "Invalid hash"
3 |
4 | class FIleNotFound(Exception):
5 | message = "File not found"
6 |
--------------------------------------------------------------------------------
/SAFARI/template/__init__.py:
--------------------------------------------------------------------------------
1 | from aiohttp import web
2 | from SAFARI.route import routes
3 |
4 |
5 | async def web_server():
6 | web_app = web.Application(client_max_size=30000000)
7 | web_app.add_routes(routes)
8 | return web_app
9 |
--------------------------------------------------------------------------------
/SAFARI/utils/file_size.py:
--------------------------------------------------------------------------------
1 | def human_size(bytes, units=[' bytes','KB','MB','GB','TB', 'PB', 'EB']):
2 | """ Returns a human readable string representation of bytes """
3 | return str(bytes) + units[0] if int(bytes) < 1024 else human_size(int(bytes)>>10, units[1:])
4 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10.8-slim-buster
2 |
3 | RUN apt update && apt upgrade -y
4 | RUN apt install git -y
5 | COPY requirements.txt /requirements.txt
6 |
7 | RUN cd /
8 | RUN pip3 install -U pip && pip3 install -U -r requirements.txt
9 | RUN mkdir /Safari-Filter-Bot
10 | WORKDIR /Safari-Filter-Bot
11 | COPY start.sh /start.sh
12 | CMD ["/bin/bash", "/start.sh"]
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.10"
2 | services:
3 | worker:
4 | build: .
5 | environment:
6 | BOT_TOKEN: $BOT_TOKEN
7 | API_ID: $API_ID
8 | API_HASH: $API_HASH
9 | CHANNELS: $CHANNELS
10 | ADMINS: $ADMINS
11 | LOG_CHANNEL: $LOG_CHANNEL
12 | DATABASE_NAME: $DATABASE_NAME
13 | DATABASE_URI: $DATABASE_URI
14 | HEROKU_API_KEY: $HEROKU_API_KEY
15 |
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | if [ -z $UPSTREAM_REPO ]
2 | then
3 | echo "Cloning main Repository"
4 | git clone https://github.com/Safaridevv/Safari-Filter-Bot.git /Safari-Filter-Bot
5 | else
6 | echo "Cloning Custom Repo from $UPSTREAM_REPO "
7 | git clone $UPSTREAM_REPO /SuperBot
8 | fi
9 | cd /Safari-Filter-Bot
10 | pip3 install -U -r requirements.txt
11 | echo "Starting DQ-The-File-Donor...."
12 | python3 bot.py
13 |
--------------------------------------------------------------------------------
/SAFARI/utils/human_readable.py:
--------------------------------------------------------------------------------
1 | def humanbytes(size):
2 | # https://stackoverflow.com/a/49361727/4723940
3 | # 2**10 = 1024
4 | if not size:
5 | return ""
6 | power = 2**10
7 | n = 0
8 | Dic_powerN = {0: ' ', 1: 'Ki', 2: 'Mi', 3: 'Gi', 4: 'Ti'}
9 | while size > power:
10 | size /= power
11 | n += 1
12 | return str(round(size, 2)) + " " + Dic_powerN[n] + 'B'
13 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pyrofork==2.3.43
2 | python-telegram-bot
3 | umongo
4 | tgcrypto
5 | pymongo[srv]==3.12.3
6 | motor==2.5.1
7 | marshmallow==3.14.1
8 | requests
9 | bs4
10 | git+https://github.com/Joelkb/cinemagoer
11 | datetime
12 | pytz
13 | aiohttp
14 | cinemagoer
15 | shortzy
16 |
17 | PyLeaves==1.0.2
18 | cinemagoer
19 | shortzy==0.0.8
20 | aiofiles
21 | pyromod==1.5
22 |
23 | telegraph
24 | openai
25 |
26 | jinja2
27 | apscheduler
28 | pyshorteners
29 | colorama
30 | fuzzywuzzy
31 | python-Levenshtein
32 | googletrans==4.0.0-rc1
33 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/features/stickerid.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from pyrogram import Client, filters
4 |
5 | @Client.on_message(filters.command(["sticker_id"]))
6 | async def stickerid(bot, message):
7 | if message.reply_to_message.sticker:
8 | await message.reply(f"**Sticker ID is** \n `{message.reply_to_message.sticker.file_id}` \n \n ** Unique ID is ** \n\n`{message.reply_to_message.sticker.file_unique_id}`", quote=True)
9 | else:
10 | await message.reply("Oops !! Not a sticker file")
11 |
--------------------------------------------------------------------------------
/SAFARI/utils/config_parser.py:
--------------------------------------------------------------------------------
1 | from os import environ
2 | from typing import Dict, Optional
3 |
4 |
5 | class TokenParser:
6 | def __init__(self, config_file: Optional[str] = None):
7 | self.tokens = {}
8 | self.config_file = config_file
9 |
10 | def parse_from_env(self) -> Dict[int, str]:
11 | self.tokens = dict(
12 | (c + 1, t)
13 | for c, (_, t) in enumerate(
14 | filter(
15 | lambda n: n[0].startswith("MULTI_TOKEN"), sorted(environ.items())
16 | )
17 | )
18 | )
19 | return self.tokens
20 |
--------------------------------------------------------------------------------
/SAFARI/utils/keepalive.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 | import aiohttp
4 | import traceback
5 | from info import *
6 |
7 |
8 | async def ping_server():
9 | sleep_time = PING_INTERVAL
10 | while True:
11 | await asyncio.sleep(sleep_time)
12 | try:
13 | async with aiohttp.ClientSession(
14 | timeout=aiohttp.ClientTimeout(total=10)
15 | ) as session:
16 | async with session.get(URL) as resp:
17 | logging.info("Pinged server with response: {}".format(resp.status))
18 | except TimeoutError:
19 | logging.warning("Couldn't connect to the site URL..!")
20 | except Exception:
21 | traceback.print_exc()
22 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/autojoin.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import pyrogram
4 | from pyrogram import Client, filters
5 |
6 | @Client.on_chat_join_request()
7 | async def auto_accept_request(client, chat_member_update):
8 | chat_id = chat_member_update.chat.id
9 | user_id = chat_member_update.from_user.id
10 |
11 | try:
12 | await client.get_chat_member(chat_id, client.me.id)
13 | await client.approve_chat_join_request(chat_id, user_id)
14 | #await client.send_message(user_id, f"ʜᴇʏ {chat_member_update.from_user.mention}!\nʀᴇǫᴜᴇsᴛ ʜᴀs ʙᴇᴇɴ ᴀᴄᴄᴇᴘᴛᴇᴅ ᴡᴇʟᴄᴏᴍᴇ ᴛᴏ {chat_member_update.chat.title}")
15 |
16 | except Exception as e:
17 | print(f"Error approving request: {e}")
18 |
--------------------------------------------------------------------------------
/logging.conf:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root
3 |
4 | [handlers]
5 | keys=consoleHandler,fileHandler
6 |
7 | [formatters]
8 | keys=consoleFormatter,fileFormatter
9 |
10 | [logger_root]
11 | level=DEBUG
12 | handlers=consoleHandler,fileHandler
13 |
14 | [handler_consoleHandler]
15 | class=StreamHandler
16 | level=INFO
17 | formatter=consoleFormatter
18 | args=(sys.stdout,)
19 |
20 | [handler_fileHandler]
21 | class=FileHandler
22 | level=ERROR
23 | formatter=fileFormatter
24 | args=('Logs.txt','w',)
25 |
26 | [formatter_consoleFormatter]
27 | format=%(asctime)s - %(lineno)d - %(name)s - %(module)s - %(levelname)s - %(message)s
28 | datefmt=%I:%M:%S %p
29 |
30 | [formatter_fileFormatter]
31 | format=[%(asctime)s:%(name)s:%(lineno)d:%(levelname)s] %(message)s
32 | datefmt=%m/%d/%Y %I:%M:%S %p
--------------------------------------------------------------------------------
/SAFARI/utils/time_format.py:
--------------------------------------------------------------------------------
1 | def get_readable_time(seconds: int) -> str:
2 | count = 0
3 | readable_time = ""
4 | time_list = []
5 | time_suffix_list = ["s", "m", "h", " days"]
6 | while count < 4:
7 | count += 1
8 | if count < 3:
9 | remainder, result = divmod(seconds, 60)
10 | else:
11 | remainder, result = divmod(seconds, 24)
12 | if seconds == 0 and remainder == 0:
13 | break
14 | time_list.append(int(result))
15 | seconds = int(remainder)
16 | for x in range(len(time_list)):
17 | time_list[x] = str(time_list[x]) + time_suffix_list[x]
18 | if len(time_list) == 4:
19 | readable_time += time_list.pop() + ", "
20 | time_list.reverse()
21 | readable_time += ": ".join(time_list)
22 | return readable_time
23 |
--------------------------------------------------------------------------------
/database/safari_reffer.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import pymongo
4 | from info import DATABASE_URI, DATABASE_NAME
5 | import logging
6 |
7 | logger = logging.getLogger(__name__)
8 | logger.setLevel(logging.ERROR)
9 |
10 | myclient = pymongo.MongoClient(DATABASE_URI)
11 | mydb = myclient[DATABASE_NAME]
12 |
13 |
14 | class UserPoint:
15 | def __init__(self):
16 | self.user_collection = mydb["referusers"]
17 | self.refer_collection = mydb["refers"]
18 |
19 | def add_user(self, user_id):
20 | if not self.is_user_in_list(user_id):
21 | self.user_collection.insert_one({'user_id': user_id})
22 |
23 | def remove_user(self, user_id):
24 | self.user_collection.delete_one({'user_id': user_id})
25 |
26 | def is_user_in_list(self, user_id):
27 | return bool(self.user_collection.find_one({'user_id': user_id}))
28 |
29 | def add_refer_points(self, user_id: int, points: int):
30 | self.refer_collection.update_one(
31 | {'user_id': user_id},
32 | {'$set': {'points': points}},
33 | upsert=True
34 | )
35 |
36 | def get_refer_points(self, user_id: int):
37 | user = self.refer_collection.find_one({'user_id': user_id})
38 | return user.get('points') if user else 0
39 |
40 |
41 | sdb = UserPoint()
42 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/features/telegraph.py:
--------------------------------------------------------------------------------
1 | import os, asyncio
2 | from pyrogram import Client, filters
3 | from pyrogram.types import *
4 | from telegraph import upload_file
5 |
6 |
7 | @Client.on_message(filters.command("telegraph") & filters.private)
8 | async def telegraph_upload(bot, update):
9 | replied = update.reply_to_message
10 | if not replied:
11 | return await update.reply_text("Reply to a photo or video.")
12 |
13 | if not (replied.photo or replied.video):
14 | return await update.reply_text("Please reply with a valid media.")
15 |
16 | text = await update.reply_text("Downloading...", disable_web_page_preview=True)
17 | media = await replied.download()
18 | await text.edit_text("Uploading...", disable_web_page_preview=True)
19 |
20 | try:
21 | response = upload_file(media)
22 | except Exception as error:
23 | print(error)
24 | return await text.edit_text(text=f"Error: {error}", disable_web_page_preview=True)
25 |
26 | try:
27 | os.remove(media)
28 | except Exception as error:
29 | print(error)
30 | return
31 |
32 | # Access the first item of the response list
33 | await text.edit_text(
34 | text=f"https://telegra.ph{response[0]}",
35 | disable_web_page_preview=True
36 | )
37 |
--------------------------------------------------------------------------------
/plugins/banned.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from pyrogram import Client, filters
4 | from utils import temp
5 | from pyrogram.types import Message
6 | from database.users_chats_db import db
7 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
8 | from info import SUPPORT_CHAT
9 |
10 | async def banned_users(_, client, message: Message):
11 | return (
12 | message.from_user is not None or not message.sender_chat
13 | ) and message.from_user.id in temp.BANNED_USERS
14 | banned_user = filters.create(banned_users)
15 | async def disabled_chat(_, client, message: Message):
16 | return message.chat.id in temp.BANNED_CHATS
17 | disabled_group=filters.create(disabled_chat)
18 |
19 |
20 | @Client.on_message(filters.private & banned_user & filters.incoming)
21 | async def ban_reply(bot, message):
22 | ban = await db.get_ban_status(message.from_user.id)
23 | await message.reply(f'Sorry Dude, You are Banned to use Me. \nBan Reason: {ban["ban_reason"]}')
24 |
25 | @Client.on_message(filters.group & disabled_group & filters.incoming)
26 | async def grp_bd(bot, message):
27 | buttons = [[
28 | InlineKeyboardButton('Support', url=f'https://t.me/{SUPPORT_CHAT}')
29 | ]]
30 | reply_markup=InlineKeyboardMarkup(buttons)
31 | vazha = await db.get_chat(message.chat.id)
32 | k = await message.reply(
33 | text=f"CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..\nReason : {vazha['reason']}.",
34 | reply_markup=reply_markup)
35 | try:
36 | await k.pin()
37 | except:
38 | pass
39 | await bot.leave_chat(message.chat.id)
40 |
--------------------------------------------------------------------------------
/SAFARI/utils/clients.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 | from info import *
4 | from pyrogram import Client
5 | from SAFARI.utils.config_parser import TokenParser
6 | from SAFARI.utils import multi_clients, work_loads, SafariBot
7 |
8 |
9 | async def initialize_clients():
10 | multi_clients[0] = SafariBot
11 | work_loads[0] = 0
12 | all_tokens = TokenParser().parse_from_env()
13 | if not all_tokens:
14 | print("No additional clients found, using default client")
15 | return
16 |
17 | async def start_client(client_id, token):
18 | try:
19 | print(f"Starting - Client {client_id}")
20 | if client_id == len(all_tokens):
21 | await asyncio.sleep(2)
22 | print("This will take some time, please wait...")
23 | client = await Client(
24 | name=str(client_id),
25 | api_id=API_ID,
26 | api_hash=API_HASH,
27 | bot_token=token,
28 | sleep_threshold=SLEEP_THRESHOLD,
29 | no_updates=True,
30 | in_memory=True
31 | ).start()
32 | work_loads[client_id] = 0
33 | return client_id, client
34 | except Exception:
35 | logging.error(f"Failed starting Client - {client_id} Error:", exc_info=True)
36 |
37 | clients = await asyncio.gather(*[start_client(i, token) for i, token in all_tokens.items()])
38 | multi_clients.update(dict(clients))
39 | if len(multi_clients) != 1:
40 | MULTI_CLIENT = True
41 | print("Multi-Client Mode Enabled")
42 | else:
43 | print("No additional clients were initialized, using default client")
44 |
--------------------------------------------------------------------------------
/SAFARI/utils/render_template.py:
--------------------------------------------------------------------------------
1 | import jinja2
2 | from info import *
3 | from SAFARI.utils import SafariBot
4 | from SAFARI.utils.human_readable import humanbytes
5 | from SAFARI.utils.file_properties import get_file_ids
6 | from SAFARI.utils.exceptions import InvalidHash
7 | import urllib.parse
8 | import logging
9 | import aiohttp
10 |
11 |
12 | async def render_page(id, secure_hash, src=None):
13 | file = await SafariBot.get_messages(int(BIN_CHANNEL), int(id))
14 | file_data = await get_file_ids(SafariBot, int(BIN_CHANNEL), int(id))
15 | if file_data.unique_id[:6] != secure_hash:
16 | logging.debug(f"link hash: {secure_hash} - {file_data.unique_id[:6]}")
17 | logging.debug(f"Invalid hash for message with - ID {id}")
18 | raise InvalidHash
19 |
20 | src = urllib.parse.urljoin(
21 | URL,
22 | f"{id}/{urllib.parse.quote_plus(file_data.file_name)}?hash={secure_hash}",
23 | )
24 |
25 | tag = file_data.mime_type.split("/")[0].strip()
26 | file_size = humanbytes(file_data.file_size)
27 | if tag in ["video", "audio"]:
28 | template_file = "SAFARI/template/req.html"
29 | else:
30 | template_file = "SAFARI/template/dl.html"
31 | async with aiohttp.ClientSession() as s:
32 | async with s.get(src) as u:
33 | file_size = humanbytes(int(u.headers.get("Content-Length")))
34 |
35 | with open(template_file) as f:
36 | template = jinja2.Template(f.read())
37 |
38 | file_name = file_data.file_name.replace("_", " ")
39 |
40 | return template.render(
41 | file_name=file_name,
42 | file_url=src,
43 | file_size=file_size,
44 | file_unique_id=file_data.unique_id,
45 | )
46 |
--------------------------------------------------------------------------------
/SAFARI/utils/__init__.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import logging.config
3 | logging.config.fileConfig('logging.conf')
4 | logging.getLogger().setLevel(logging.INFO)
5 | logging.getLogger("pyrogram").setLevel(logging.ERROR)
6 | logging.getLogger("imdbpy").setLevel(logging.ERROR)
7 | logging.basicConfig(
8 | level=logging.INFO,
9 | format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
10 | )
11 | logging.getLogger("aiohttp").setLevel(logging.ERROR)
12 | logging.getLogger("aiohttp.web").setLevel(logging.ERROR)
13 |
14 | from pyrogram import Client
15 | from database.ia_filterdb import Media
16 | from info import *
17 | from utils import temp
18 | from typing import Union, Optional, AsyncGenerator
19 | from pyrogram import types
20 | from aiohttp import web
21 |
22 | from pyrogram import Client
23 | from info import *
24 |
25 | class SafariXBot(Client):
26 |
27 | def __init__(self):
28 | super().__init__(
29 | name=SESSION,
30 | api_id=API_ID,
31 | api_hash=API_HASH,
32 | bot_token=BOT_TOKEN,
33 | workers=50,
34 | plugins={"root": "plugins"},
35 | sleep_threshold=5,
36 | )
37 | async def iter_messages(
38 | self,
39 | chat_id: Union[int, str],
40 | limit: int,
41 | offset: int = 0,
42 | ) -> Optional[AsyncGenerator["types.Message", None]]:
43 | current = offset
44 | while True:
45 | new_diff = min(200, limit - current)
46 | if new_diff <= 0:
47 | return
48 | messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1)))
49 | for message in messages:
50 | yield message
51 | current += 1
52 |
53 | SafariBot = SafariXBot()
54 |
55 | multi_clients = {}
56 | work_loads = {}
57 |
--------------------------------------------------------------------------------
/plugins/files_delete.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import re
4 | import logging
5 | from pyrogram import Client, filters
6 | from info import DELETE_CHANNELS
7 | from database.ia_filterdb import Media, unpack_new_file_id
8 |
9 | logger = logging.getLogger(__name__)
10 |
11 | media_filter = filters.document | filters.video | filters.audio
12 |
13 |
14 | @Client.on_message(filters.chat(DELETE_CHANNELS) & media_filter)
15 | async def deletemultiplemedia(bot, message):
16 | """Delete Multiple files from database"""
17 |
18 | for file_type in ("document", "video", "audio"):
19 | media = getattr(message, file_type, None)
20 | if media is not None:
21 | break
22 | else:
23 | return
24 |
25 | file_id, file_ref = unpack_new_file_id(media.file_id)
26 |
27 | result = await Media.collection.delete_one({
28 | '_id': file_id,
29 | })
30 | if result.deleted_count:
31 | logger.info('File is successfully deleted from database.')
32 | else:
33 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
34 | result = await Media.collection.delete_many({
35 | 'file_name': file_name,
36 | 'file_size': media.file_size,
37 | 'mime_type': media.mime_type
38 | })
39 | if result.deleted_count:
40 | logger.info('File is successfully deleted from database.')
41 | else:
42 | result = await Media.collection.delete_many({
43 | 'file_name': media.file_name,
44 | 'file_size': media.file_size,
45 | 'mime_type': media.mime_type
46 | })
47 | if result.deleted_count:
48 | logger.info('File is successfully deleted from database.')
49 | else:
50 | logger.info('File not found in database.')
51 |
--------------------------------------------------------------------------------
/SAFARI/utils/file_properties.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client
2 | from typing import Any, Optional
3 | from pyrogram.types import Message
4 | from pyrogram.file_id import FileId
5 | from pyrogram.raw.types.messages import Messages
6 | from SAFARI.utils.exceptions import FIleNotFound
7 |
8 |
9 | async def parse_file_id(message: "Message") -> Optional[FileId]:
10 | media = get_media_from_message(message)
11 | if media:
12 | return FileId.decode(media.file_id)
13 |
14 | async def parse_file_unique_id(message: "Messages") -> Optional[str]:
15 | media = get_media_from_message(message)
16 | if media:
17 | return media.file_unique_id
18 |
19 | async def get_file_ids(client: Client, chat_id: int, id: int) -> Optional[FileId]:
20 | message = await client.get_messages(chat_id, id)
21 | if message.empty:
22 | raise FIleNotFound
23 | media = get_media_from_message(message)
24 | file_unique_id = await parse_file_unique_id(message)
25 | file_id = await parse_file_id(message)
26 | setattr(file_id, "file_size", getattr(media, "file_size", 0))
27 | setattr(file_id, "mime_type", getattr(media, "mime_type", ""))
28 | setattr(file_id, "file_name", getattr(media, "file_name", ""))
29 | setattr(file_id, "unique_id", file_unique_id)
30 | return file_id
31 |
32 | def get_media_from_message(message: "Message") -> Any:
33 | media_types = (
34 | "audio",
35 | "document",
36 | "photo",
37 | "sticker",
38 | "animation",
39 | "video",
40 | "voice",
41 | "video_note",
42 | )
43 | for attr in media_types:
44 | media = getattr(message, attr, None)
45 | if media:
46 | return media
47 |
48 |
49 | def get_hash(media_msg: Message) -> str:
50 | media = get_media_from_message(media_msg)
51 | return getattr(media, "file_unique_id", "")[:6]
52 |
53 | def get_name(media_msg: Message) -> str:
54 | media = get_media_from_message(media_msg)
55 | return getattr(media, 'file_name', "")
56 |
57 | def get_media_file_size(m):
58 | media = get_media_from_message(m)
59 | return getattr(media, "file_size", 0)
60 |
--------------------------------------------------------------------------------
/SAFARI/template/dl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
2 |
3 |
68 |
69 |
70 |
71 |
72 |
76 |
77 |
78 |
79 |
80 |
pip3 install -U -r requirements.txt
99 | python3 bot.py
102 |
111 | 123 |
124 | git clone https://github.com/Joelkb/DQ-The-File-Donor 125 | # Install Packages 126 | pip3 install -U -r requirements.txt 127 | Edit info.py with variables as given below then run bot 128 | python3 bot.py 129 |130 | 131 |
/request Pushpa 2021")
54 | return
55 |
56 | files, offset, total_results = await get_search_results(chat_id=message.chat.id, query=requested_movie)
57 |
58 | if files:
59 | file_name = files[0]['file_name']
60 | await message.reply_text(f"🎥 {file_name}\n\nआपने जो मूवी रिक्वेस्ट की है वो ग्रुप में उपलब्ध हैं\n\nग्रुप लिंक = {GRP_LNK}")
61 | else:
62 | closest_movie = await ai_spell_check(chat_id=message.chat.id, wrong_name=requested_movie)
63 | if closest_movie:
64 | files, offset, total_results = await get_search_results(chat_id=message.chat.id, query=closest_movie)
65 | if files:
66 | file_name = files[0]['file_name']
67 | await message.reply_text(f"🎥 {file_name}\n\nआपने जो मूवी रिक्वेस्ट की है वो ग्रुप में उपलब्ध हैं\n\nग्रुप लिंक = {GRP_LNK}")
68 | else:
69 | await message.reply_text(f"✅ आपकी फिल्म {closest_movie} हमारे एडमिन के पास भेज दिया गया है.\n\n🚀 जैसे ही फिल्म अपलोड होती हैं हम आपको मैसेज देंगे.\n\n📌 ध्यान दे - एडमिन अपने काम में व्यस्त हो सकते है इसलिए फिल्म अपलोड होने में टाइम लग सकता हैं")
70 | await client.send_message(
71 | REQ_CHANNEL,
72 | f"☏ #𝙍𝙀𝙌𝙐𝙀𝙎𝙏𝙀𝘿_𝘾𝙊𝙉𝙏𝙀𝙉𝙏 ☎︎\n\nʙᴏᴛ - {temp.B_NAME}\nɴᴀᴍᴇ - {message.from_user.mention} ({message.from_user.id})\nRᴇǫᴜᴇꜱᴛ - {closest_movie}",
73 | reply_markup=InlineKeyboardMarkup(
74 | [[
75 | InlineKeyboardButton('ɴᴏᴛ ʀᴇʟᴇᴀsᴇ 📅', callback_data=f"not_release:{user_id}:{requested_movie}"),
76 | InlineKeyboardButton('ɴᴏᴛ ᴀᴠᴀɪʟᴀʙʟᴇ 🙅', callback_data=f"not_available:{user_id}:{requested_movie}")
77 | ],[
78 | InlineKeyboardButton('ᴜᴘʟᴏᴀᴅᴇᴅ ✅', callback_data=f"uploaded:{user_id}:{requested_movie}")
79 | ],[
80 | InlineKeyboardButton('ɪɴᴠᴀʟɪᴅ ғᴏʀᴍᴀᴛ🙅', callback_data=f"series:{user_id}:{requested_movie}"),
81 | InlineKeyboardButton('sᴇʟʟ ᴍɪsᴛᴇᴋ✍️', callback_data=f"spelling_error:{user_id}:{requested_movie}")
82 | ],[
83 | InlineKeyboardButton('⦉ ᴄʟᴏsᴇ ⦊', callback_data=f"close_data")]
84 | ])
85 | )
86 | else:
87 | await message.reply_text(f"✅ आपकी फिल्म {requested_movie} हमारे एडमिन के पास भेज दिया गया है.\n\n🚀 जैसे ही फिल्म अपलोड होती हैं हम आपको मैसेज देंगे.\n\n📌 ध्यान दे - एडमिन अपने काम में व्यस्त हो सकते है इसलिए फिल्म अपलोड होने में टाइम लग सकता हैं")
88 | await client.send_message(
89 | REQ_CHANNEL,
90 | f"📝 #REQUESTED_CONTENT 📝\n\nʙᴏᴛ - {temp.B_NAME}\nɴᴀᴍᴇ - {message.from_user.mention} ({message.from_user.id})\nRᴇǫᴜᴇꜱᴛ - {requested_movie}",
91 | reply_markup=InlineKeyboardMarkup(
92 | [[
93 | InlineKeyboardButton('ɴᴏᴛ ʀᴇʟᴇᴀsᴇ 📅', callback_data=f"not_release:{user_id}:{requested_movie}"),
94 | InlineKeyboardButton('ɴᴏᴛ ᴀᴠᴀɪʟᴀʙʟᴇ 🙅', callback_data=f"not_available:{user_id}:{requested_movie}")
95 | ],[
96 | InlineKeyboardButton('ᴜᴘʟᴏᴀᴅᴇᴅ ✅', callback_data=f"uploaded:{user_id}:{requested_movie}")
97 | ],[
98 | InlineKeyboardButton('ɪɴᴠᴀʟɪᴅ ғᴏʀᴍᴀᴛ🙅', callback_data=f"series:{user_id}:{requested_movie}"),
99 | InlineKeyboardButton('sᴇʟʟ ᴍɪsᴛᴇᴋ✍️', callback_data=f"spelling_error:{user_id}:{requested_movie}")
100 | ],[
101 | InlineKeyboardButton('⦉ ᴄʟᴏsᴇ ⦊', callback_data=f"close_data")]
102 | ])
103 | )
104 |
--------------------------------------------------------------------------------
/plugins/channel.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from pyrogram import Client, filters, enums
4 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
5 | from info import CHANNELS, POST_CHANNELS
6 | from database.ia_filterdb import save_file, get_file_details
7 | from utils import get_poster, get_size, temp
8 | from os import environ
9 | import logging
10 | import re
11 |
12 | collected_files = []
13 | post_active = False
14 |
15 | media_filter = filters.document | filters.video | filters.audio
16 |
17 |
18 | @Client.on_message(filters.chat(CHANNELS) & media_filter)
19 | async def media(bot, message):
20 | global post_active, collected_files
21 |
22 | language_map = {
23 | "hin": "Hindi",
24 | "eng": "English",
25 | "en": "English",
26 | "tel": "Telugu",
27 | "tam": "Tamil",
28 | "jap": "Japanese",
29 | "mar": "Marathi",
30 | "guj": "Gujarati",
31 | "Pun": "Punjabi",
32 | "Hindi": "Hindi",
33 | "English": "English",
34 | "Telugu": "Telugu",
35 | "Tamil": "Tamil",
36 | "Japanese": "Japanese",
37 | "Marathi": "Marathi",
38 | "Gujarati": "Gujarati",
39 | "Punjabi": "Punjabi"
40 |
41 | }
42 |
43 | for file_type in ("document", "video", "audio"):
44 | media = getattr(message, file_type, None)
45 | if media is not None:
46 | break
47 | else:
48 | return
49 |
50 | media.file_type = file_type
51 | media.caption = message.caption
52 | success, file_id = await save_file(media)
53 |
54 | if success and file_id:
55 | file_details = await get_file_details(file_id)
56 | if file_details:
57 | file_id = file_details[0]['file_id']
58 |
59 | if success and "post count" in (media.caption or "").lower():
60 | post_active = True
61 | collected_files = []
62 |
63 | if post_active:
64 | languages_in_caption = re.findall(r'\b(' + '|'.join(language_map.keys()) + r')\b', media.caption)
65 | full_languages = ", ".join(language_map[lang] for lang in languages_in_caption)
66 | updated_caption = f"{media.caption}\n\nLanguage: {full_languages}"
67 | collected_files.append((file_id, media.file_name.replace('_', ' '), updated_caption, media.file_size))
68 |
69 | if success and "send post" in (media.caption or "").lower():
70 | post_active = False
71 |
72 | if collected_files:
73 | imdb_info = None
74 |
75 | for file_id, file_name, caption, file_size in collected_files:
76 | size_text = get_size(file_size)
77 | file_url = f"📁 [{size_text}]👇\n{file_name}"
78 |
79 | if imdb_info is None:
80 | try:
81 | movie_name = caption.split('|')[0].strip()
82 | logging.info(f"Searching IMDb for: {movie_name}")
83 | imdb_info = await get_poster(movie_name)
84 | if not imdb_info:
85 | logging.error(f"IMDb information not found for: {movie_name}")
86 | return
87 | except Exception as e:
88 | logging.error(f"Error while fetching IMDb info: {str(e)}")
89 | return
90 |
91 | if imdb_info:
92 | title = imdb_info.get('title', 'N/A')
93 | rating = imdb_info.get('rating', 'N/A')
94 | genre = imdb_info.get('genres', 'N/A')
95 | description = imdb_info.get('plot', 'N/A')
96 | poster_url = imdb_info.get('poster', None)
97 | year = imdb_info.get('year', 'N/A')
98 |
99 | urls_text = "\n\n".join([f"📁 [{get_size(size)}]👇\n{file_name}" for file_id, file_name, caption, size in collected_files])
100 |
101 | language_in_caption = caption.split("Language:")[-1].strip()
102 | final_caption = f"🏷 Title: {title}\n🎭 Genres: {genre}\n📆 Year: {year}\n🌟 Rating: {rating}\n🔊 Language: {language_in_caption}\n\n{urls_text}"
103 |
104 | for channel in POST_CHANNELS:
105 | if poster_url:
106 | try:
107 | await bot.send_photo(
108 | chat_id=channel,
109 | photo=poster_url,
110 | caption=final_caption,
111 | parse_mode=enums.ParseMode.HTML
112 | )
113 | except Exception as e:
114 | logging.error(f"Error sending poster to channel {channel}: {str(e)}")
115 | await bot.send_message(
116 | chat_id=channel,
117 | text=final_caption,
118 | parse_mode=enums.ParseMode.HTML
119 | )
120 | else:
121 | url_text = "\n\n".join([f"📁 [{get_size(size)}]👇\n{file_name}" for file_id, file_name, caption, size in collected_files])
122 | captionn = f"#Information_Not_Available\n\nTotal Files: {len(collected_files)}\n\n{url_text}"
123 | await bot.send_message(
124 | chat_id=channel,
125 | text=captionn,
126 | parse_mode=enums.ParseMode.HTML
127 | )
128 | collected_files = []
129 |
--------------------------------------------------------------------------------
/plugins/connection.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit.
3 | from pyrogram import filters, Client, enums
4 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
5 | from database.connections_mdb import add_connection, all_connections, if_active, delete_connection
6 | from info import ADMINS
7 | import logging
8 |
9 | logger = logging.getLogger(__name__)
10 | logger.setLevel(logging.ERROR)
11 |
12 |
13 | @Client.on_message((filters.private | filters.group) & filters.command('connect'))
14 | async def addconnection(client, message):
15 | userid = message.from_user.id if message.from_user else None
16 | if not userid:
17 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
18 | chat_type = message.chat.type
19 |
20 | if chat_type == enums.ChatType.PRIVATE:
21 | try:
22 | cmd, group_id = message.text.split(" ", 1)
23 | except:
24 | await message.reply_text(
25 | "Enter in correct format!\n\n"
26 | "/connect groupid\n\n"
27 | "Get your Group id by adding this bot to your group and use /id",
28 | quote=True
29 | )
30 | return
31 |
32 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
33 | group_id = message.chat.id
34 |
35 | try:
36 | st = await client.get_chat_member(group_id, userid)
37 | if (
38 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
39 | and st.status != enums.ChatMemberStatus.OWNER
40 | and userid not in ADMINS
41 | ):
42 | await message.reply_text("You should be an admin in Given group!", quote=True)
43 | return
44 | except Exception as e:
45 | logger.exception(e)
46 | await message.reply_text(
47 | "Invalid Group ID!\n\nIf correct, Make sure I'm present in your group!!",
48 | quote=True,
49 | )
50 |
51 | return
52 | try:
53 | st = await client.get_chat_member(group_id, "me")
54 | if st.status == enums.ChatMemberStatus.ADMINISTRATOR:
55 | ttl = await client.get_chat(group_id)
56 | title = ttl.title
57 |
58 | addcon = await add_connection(str(group_id), str(userid))
59 | if addcon:
60 | await message.reply_text(
61 | f"Successfully connected to **{title}**\nNow manage your group from my pm !",
62 | quote=True,
63 | parse_mode=enums.ParseMode.MARKDOWN
64 | )
65 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
66 | await client.send_message(
67 | userid,
68 | f"Connected to **{title}** !",
69 | parse_mode=enums.ParseMode.MARKDOWN
70 | )
71 | else:
72 | await message.reply_text(
73 | "You're already connected to this chat!",
74 | quote=True
75 | )
76 | else:
77 | await message.reply_text("Add me as an admin in group", quote=True)
78 | except Exception as e:
79 | logger.exception(e)
80 | await message.reply_text('Some error occurred! Try again later.', quote=True)
81 | return
82 |
83 |
84 | @Client.on_message((filters.private | filters.group) & filters.command('disconnect'))
85 | async def deleteconnection(client, message):
86 | userid = message.from_user.id if message.from_user else None
87 | if not userid:
88 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
89 | chat_type = message.chat.type
90 |
91 | if chat_type == enums.ChatType.PRIVATE:
92 | await message.reply_text("Run /connections to view or disconnect from groups!", quote=True)
93 |
94 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
95 | group_id = message.chat.id
96 |
97 | st = await client.get_chat_member(group_id, userid)
98 | if (
99 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
100 | and st.status != enums.ChatMemberStatus.OWNER
101 | and str(userid) not in ADMINS
102 | ):
103 | return
104 |
105 | delcon = await delete_connection(str(userid), str(group_id))
106 | if delcon:
107 | await message.reply_text("Successfully disconnected from this chat", quote=True)
108 | else:
109 | await message.reply_text("This chat isn't connected to me!\nDo /connect to connect.", quote=True)
110 |
111 |
112 | @Client.on_message(filters.private & filters.command(["connections"]))
113 | async def connections(client, message):
114 | userid = message.from_user.id
115 |
116 | groupids = await all_connections(str(userid))
117 | if groupids is None:
118 | await message.reply_text(
119 | "There are no active connections!! Connect to some groups first.",
120 | quote=True
121 | )
122 | return
123 | buttons = []
124 | for groupid in groupids:
125 | try:
126 | ttl = await client.get_chat(int(groupid))
127 | title = ttl.title
128 | active = await if_active(str(userid), str(groupid))
129 | act = " - ACTIVE" if active else ""
130 | buttons.append(
131 | [
132 | InlineKeyboardButton(
133 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}"
134 | )
135 | ]
136 | )
137 | except:
138 | pass
139 | if buttons:
140 | await message.reply_text(
141 | "Your connected group details ;\n\n",
142 | reply_markup=InlineKeyboardMarkup(buttons),
143 | quote=True
144 | )
145 | else:
146 | await message.reply_text(
147 | "There are no active connections!! Connect to some groups first.",
148 | quote=True
149 | )
150 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/getfile.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from utils import temp
4 | from utils import get_poster
5 | from info import POST_CHANNELS
6 | from googletrans import Translator
7 | from pyrogram import Client, filters, enums
8 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
9 |
10 | translator = Translator()
11 |
12 | async def get_hindi(plot):
13 | try:
14 | translated = translator.translate(plot, dest='hi')
15 | return translated.text
16 | except Exception as e:
17 | print(f"Translation Error: {e}")
18 | return plot
19 |
20 | @Client.on_message(filters.command('getfile'))
21 | async def getfile(client, message):
22 | try:
23 | query = message.text.split(" ", 1)
24 | if len(query) < 2:
25 | return await message.reply_text("Usage: /getfile ")
103 |
104 | @Client.on_message(filters.command("clearcodes") & filters.user(ADMINS))
105 | async def clear_codes_cmd(client, message):
106 | result = await db.codes.delete_many({})
107 | if result.deleted_count > 0:
108 | await message.reply_text(f"✅ ᴀʟʟ {result.deleted_count} ᴄᴏᴅᴇs ʜᴀᴠᴇ ʙᴇᴇɴ ʀᴇᴍᴏᴠᴇᴅ sᴜᴄᴄᴇssғᴜʟʟʏ.")
109 | else:
110 | await message.reply_text("⚠️ ɴᴏ ᴄᴏᴅᴇs ғᴏᴜɴᴅ ᴛʜᴀᴛ ᴄᴏᴜʟᴅ ʙᴇ ᴄʟᴇᴀʀᴇᴅ.")
111 |
112 | @Client.on_message(filters.command("allcodes") & filters.user(ADMINS))
113 | async def all_codes_cmd(client, message):
114 | all_codes = await db.codes.find({}).to_list(length=None)
115 | if not all_codes:
116 | await message.reply_text("⚠️ ᴛʜᴇʀᴇ ᴀʀᴇ ɴᴏ ᴄᴏᴅᴇs ᴀᴠᴀɪʟᴀʙʟᴇ.")
117 | return
118 |
119 | codes_info = "📝 **ɢᴇɴᴇʀᴀᴛᴇᴅ ᴄᴏᴅᴇs ᴅᴇᴛᴀɪʟs:**\n\n"
120 | for code_data in all_codes:
121 | original_code = code_data.get("original_code", "Unknown")
122 | duration = code_data.get("duration", "Unknown")
123 | user_id = code_data.get("user_id")
124 | used = "Yes ✅" if code_data.get("used", False) else "No ⭕"
125 | created_at = code_data["created_at"].astimezone(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y %I:%M %p")
126 | if user_id:
127 | user = await client.get_users(user_id)
128 | user_name = user.first_name if user.first_name else "Unknown User"
129 | user_mention = f"[{user_name}](tg://user?id={user_id})"
130 | else:
131 | user_mention = "Not Redeemed"
132 |
133 | codes_info += f"**🔑 Code**: `{original_code}`\n"
134 | codes_info += f"**⌛ Duration**: {duration}\n"
135 | codes_info += f"**‼ Used**: {used}\n"
136 | codes_info += f"**🕓 Created At**: {created_at}\n"
137 | codes_info += f"**🙎 User ID**: {user_mention}\n\n"
138 |
139 |
140 | for chunk in [codes_info[i:i + 4096] for i in range(0, len(codes_info), 4096)]:
141 | await message.reply_text(chunk)
142 |
--------------------------------------------------------------------------------
/SAFARI/route.py:
--------------------------------------------------------------------------------
1 | from aiohttp import web
2 | import re
3 | import math
4 | import logging
5 | import secrets
6 | import time
7 | import mimetypes
8 | from aiohttp.http_exceptions import BadStatusLine
9 | from SAFARI.utils import multi_clients, work_loads, SafariBot
10 | from SAFARI.utils.exceptions import FIleNotFound, InvalidHash
11 | from SAFARI import StartTime, __version__
12 | from SAFARI.utils.custom_dl import ByteStreamer
13 | from SAFARI.utils.time_format import get_readable_time
14 | from SAFARI.utils.render_template import render_page
15 | from info import *
16 |
17 |
18 | routes = web.RouteTableDef()
19 |
20 | home_template = """
21 |
22 |
23 |
24 |
25 |
26 | Safaribotts
27 |
40 |
41 |
42 |
43 |
44 | Safaribotts
45 |
46 |
47 | """
48 |
49 | @routes.get("/", allow_head=True)
50 | async def root_route_handler(request):
51 | return web.Response(text=home_template, content_type='text/html')
52 |
53 |
54 | @routes.get(r"/watch/{path:\S+}", allow_head=True)
55 | async def stream_handler(request: web.Request):
56 | try:
57 | path = request.match_info["path"]
58 | match = re.search(r"^([a-zA-Z0-9_-]{6})(\d+)$", path)
59 | if match:
60 | secure_hash = match.group(1)
61 | id = int(match.group(2))
62 | else:
63 | id = int(re.search(r"(\d+)(?:\/\S+)?", path).group(1))
64 | secure_hash = request.rel_url.query.get("hash")
65 | return web.Response(text=await render_page(id, secure_hash), content_type='text/html')
66 | except InvalidHash as e:
67 | raise web.HTTPForbidden(text=e.message)
68 | except FIleNotFound as e:
69 | raise web.HTTPNotFound(text=e.message)
70 | except (AttributeError, BadStatusLine, ConnectionResetError):
71 | pass
72 | except Exception as e:
73 | logging.critical(e.with_traceback(None))
74 | raise web.HTTPInternalServerError(text=str(e))
75 |
76 | @routes.get(r"/{path:\S+}", allow_head=True)
77 | async def stream_handler(request: web.Request):
78 | try:
79 | path = request.match_info["path"]
80 | match = re.search(r"^([a-zA-Z0-9_-]{6})(\d+)$", path)
81 | if match:
82 | secure_hash = match.group(1)
83 | id = int(match.group(2))
84 | else:
85 | id = int(re.search(r"(\d+)(?:\/\S+)?", path).group(1))
86 | secure_hash = request.rel_url.query.get("hash")
87 | return await media_streamer(request, id, secure_hash)
88 | except InvalidHash as e:
89 | raise web.HTTPForbidden(text=e.message)
90 | except FIleNotFound as e:
91 | raise web.HTTPNotFound(text=e.message)
92 | except (AttributeError, BadStatusLine, ConnectionResetError):
93 | pass
94 | except Exception as e:
95 | logging.critical(e.with_traceback(None))
96 | raise web.HTTPInternalServerError(text=str(e))
97 |
98 | class_cache = {}
99 |
100 | async def media_streamer(request: web.Request, id: int, secure_hash: str):
101 | range_header = request.headers.get("Range", 0)
102 |
103 | index = min(work_loads, key=work_loads.get)
104 | faster_client = multi_clients[index]
105 |
106 | if MULTI_CLIENT:
107 | logging.info(f"Client {index} is now serving {request.remote}")
108 |
109 | if faster_client in class_cache:
110 | tg_connect = class_cache[faster_client]
111 | logging.debug(f"Using cached ByteStreamer object for client {index}")
112 | else:
113 | logging.debug(f"Creating new ByteStreamer object for client {index}")
114 | tg_connect = ByteStreamer(faster_client)
115 | class_cache[faster_client] = tg_connect
116 | logging.debug("before calling get_file_properties")
117 | file_id = await tg_connect.get_file_properties(id)
118 | logging.debug("after calling get_file_properties")
119 |
120 | if file_id.unique_id[:6] != secure_hash:
121 | logging.debug(f"Invalid hash for message with ID {id}")
122 | raise InvalidHash
123 |
124 | file_size = file_id.file_size
125 |
126 | if range_header:
127 | from_bytes, until_bytes = range_header.replace("bytes=", "").split("-")
128 | from_bytes = int(from_bytes)
129 | until_bytes = int(until_bytes) if until_bytes else file_size - 1
130 | else:
131 | from_bytes = request.http_range.start or 0
132 | until_bytes = (request.http_range.stop or file_size) - 1
133 |
134 | if (until_bytes > file_size) or (from_bytes < 0) or (until_bytes < from_bytes):
135 | return web.Response(
136 | status=416,
137 | body="416: Range not satisfiable",
138 | headers={"Content-Range": f"bytes */{file_size}"},
139 | )
140 |
141 | chunk_size = 1024 * 1024
142 | until_bytes = min(until_bytes, file_size - 1)
143 |
144 | offset = from_bytes - (from_bytes % chunk_size)
145 | first_part_cut = from_bytes - offset
146 | last_part_cut = until_bytes % chunk_size + 1
147 |
148 | req_length = until_bytes - from_bytes + 1
149 | part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
150 | body = tg_connect.yield_file(
151 | file_id, index, offset, first_part_cut, last_part_cut, part_count, chunk_size
152 | )
153 |
154 | mime_type = file_id.mime_type
155 | file_name = file_id.file_name
156 | disposition = "attachment"
157 |
158 | if mime_type:
159 | if not file_name:
160 | try:
161 | file_name = f"{secrets.token_hex(2)}.{mime_type.split('/')[1]}"
162 | except (IndexError, AttributeError):
163 | file_name = f"{secrets.token_hex(2)}.unknown"
164 | else:
165 | if file_name:
166 | mime_type = mimetypes.guess_type(file_id.file_name)
167 | else:
168 | mime_type = "application/octet-stream"
169 | file_name = f"{secrets.token_hex(2)}.unknown"
170 |
171 | return web.Response(
172 | status=206 if range_header else 200,
173 | body=body,
174 | headers={
175 | "Content-Type": f"{mime_type}",
176 | "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}",
177 | "Content-Length": str(req_length),
178 | "Content-Disposition": f'{disposition}; filename="{file_name}"',
179 | "Accept-Ranges": "bytes",
180 | },
181 | )
182 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/Group_Verify.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from pyrogram import Client, filters, enums
4 | from database.users_chats_db import db
5 | from utils import temp
6 | from info import ADMINS, GROUP_VERIFY_LOGS
7 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
8 |
9 |
10 | @Client.on_callback_query(filters.regex(r"^verify_group_"))
11 | async def verify_group_callback(client, query):
12 | data = query.data.split("_")
13 | chat_id = int(data[2])
14 | group_info = await db.get_chat(chat_id)
15 | owner_id = group_info.get('owner_id', None)
16 | user = await client.get_users(owner_id)
17 | group_title = group_info.get('title', 'Unknown Group')
18 | total = await client.get_chat_members_count(chat_id)
19 |
20 | if not group_info:
21 | await query.answer("ɢʀᴏᴜᴘ ɴᴏᴛ ғᴏᴜɴᴅ!", show_alert=True)
22 | return
23 | if group_info.get('grp_link'):
24 | group_link = group_info['grp_link']
25 | else:
26 | chat = await client.get_chat(chat_id)
27 | if chat.username:
28 | group_link = f"https://t.me/{chat.username}"
29 | else:
30 | try:
31 | invite_link = await client.create_chat_invite_link(chat_id)
32 | group_link = invite_link.invite_link
33 | except Exception as e:
34 | group_link = "No link available"
35 | if await db.rejected_group(chat_id):
36 | await db.un_rejected(chat_id)
37 | await db.verify_group(chat_id)
38 | await query.answer("ᴛʜᴇ ɢʀᴏᴜᴘ ʜᴀs ʙᴇᴇɴ ᴠᴇʀɪғɪᴇᴅ ✅", show_alert=True)
39 |
40 | await query.message.edit_text(
41 | f"𝑩𝒐𝒕: {temp.U_NAME}\n𝑮𝒓𝒐𝒖𝒑: {group_title}\n𝑰𝑫: {chat_id}\n𝑴𝒆𝒎𝒃𝒆𝒓𝒔: {total}\n𝑼𝒔𝒆𝒓: {user.mention}\n\nGʀᴏᴜᴘ Is Vᴇʀɪғɪᴇᴅ. ✅",
42 | reply_markup=InlineKeyboardMarkup(
43 | [[InlineKeyboardButton("Rᴇᴊᴇᴄᴛ ⛔", callback_data=f"rejected_group_{chat_id}")]]
44 | )
45 | )
46 |
47 | if owner_id:
48 | await client.send_message(chat_id=owner_id, text=f"#𝐕𝐞𝐫𝐢𝐟𝐲𝐞𝐝_𝐆𝐫𝐨𝐮𝐩\n\nGʀᴏᴜᴘ Nᴀᴍᴇ: {group_title}\nIᴅ: {chat_id}\n\nCᴏɴɢʀᴀᴛᴜʟᴀᴛɪᴏɴs Gʀᴏᴜᴘ Is Vᴇʀɪғɪᴇᴅ. ✅.")
49 |
50 | @Client.on_callback_query(filters.regex(r"^rejected_group_"))
51 | async def rejected_group_callback(client, query):
52 | data = query.data.split("_")
53 | chat_id = int(data[2])
54 | group_info = await db.get_chat(chat_id)
55 | owner_id = group_info.get('owner_id', None)
56 | user = await client.get_users(owner_id)
57 | group_title = group_info.get('title', 'Unknown Group')
58 | total = await client.get_chat_members_count(chat_id)
59 | if not group_info:
60 | await query.answer("ɢʀᴏᴜᴘ ɴᴏᴛ ғᴏᴜɴᴅ!", show_alert=True)
61 | return
62 | if group_info.get('grp_link'):
63 | group_link = group_info['grp_link']
64 | else:
65 | chat = await client.get_chat(chat_id)
66 | if chat.username:
67 | group_link = f"https://t.me/{chat.username}"
68 | else:
69 | try:
70 | invite_link = await client.create_chat_invite_link(chat_id)
71 | group_link = invite_link.invite_link
72 | except Exception as e:
73 | group_link = "No link available"
74 | await db.reject_group(chat_id)
75 | await query.answer("ᴛʜᴇ ɢʀᴏᴜᴘ ʜᴀs ʙᴇᴇɴ ʀᴇᴊᴇᴄᴛᴇᴅ ❌", show_alert=True)
76 |
77 | await query.message.edit_text(f"𝑩𝒐𝒕: {temp.U_NAME}\n𝑮𝒓𝒐𝒖𝒑: {group_title}\n𝑰𝑫: {chat_id}\n𝑴𝒆𝒎𝒃𝒆𝒓𝒔: {total}\n𝑼𝒔𝒆𝒓: {user.mention}\n\nRᴇᴊᴇᴄᴛᴇᴅ Gʀᴏᴜᴘ ❌", reply_markup=InlineKeyboardMarkup(
78 | [[InlineKeyboardButton("Tᴀᴘ Tᴏ Vᴇʀɪғʏ ✅", callback_data=f"verify_group_{chat_id}")]]
79 | ))
80 | if owner_id:
81 | await client.send_message(chat_id=owner_id, text=f"#𝐑𝐞𝐣𝐞𝐜𝐭_𝐆𝐫𝐨𝐮𝐩❌\n\nGʀᴏᴜᴘ Nᴀᴍᴇ: {group_title}\nIᴅ: {chat_id}\n\nʏᴏᴜʀ ɢʀᴏᴜᴘ ʜᴀs ʙᴇᴇɴ ʀᴇᴊᴇᴄᴛᴇᴅ\n\n ᴄᴏɴᴛᴀᴄᴛ ᴍʏ ᴀᴅᴍɪɴ: @Safaridev.")
82 |
83 |
84 | # Verify command to initiate the group verification
85 | @Client.on_message(filters.group & filters.command("verify"))
86 | async def grpp_verify(bot, message):
87 | user = await bot.get_chat_member(message.chat.id, message.from_user.id)
88 | total=await bot.get_chat_members_count(message.chat.id)
89 | owner_id = message.from_user.id
90 | group_link = message.chat.invite_link
91 | is_verified = await db.check_group_verification(message.chat.id)
92 | is_rejected = await db.rejected_group(message.chat.id)
93 | owner=user.status in [enums.ChatMemberStatus.ADMINISTRATOR, enums.ChatMemberStatus.OWNER] or str(message.from_user.id) in ADMINS
94 | if message.chat.username:
95 | group_link = f"https://t.me/{message.chat.username}"
96 | else:
97 | try:
98 | invite_link = await bot.create_chat_invite_link(message.chat.id)
99 | group_link = invite_link.invite_link
100 | except Exception as e:
101 | group_link = "No link available"
102 | if not is_rejected:
103 | if owner:
104 | if not is_verified:
105 | if not await db.get_chat(message.chat.id):
106 | await db.add_chat(message.chat.id, message.chat.title, owner_id)
107 | await bot.send_message(
108 | chat_id=GROUP_VERIFY_LOGS,
109 | text=f"#𝐕𝐞𝐫𝐢𝐟𝐲_𝐆𝐫𝐨𝐮𝐩\n\n𝑩𝒐𝒕: {temp.U_NAME}\n𝑮𝒓𝒐𝒖𝒑:- {message.chat.title}\n𝑰𝑫: {message.chat.id}\n𝑴𝒆𝒎𝒃𝒆𝒓𝒔:- {total}\n𝑼𝒔𝒆𝒓: {message.from_user.mention}",
110 | reply_markup=InlineKeyboardMarkup([
111 | [InlineKeyboardButton("Tᴀᴘ Tᴏ Vᴇʀɪғʏ ✅", callback_data=f"verify_group_{message.chat.id}")],
112 | [InlineKeyboardButton("Rᴇᴊᴇᴄᴛ ⭕", callback_data=f"rejected_group_{message.chat.id}")]]
113 | )
114 | )
115 | await message.reply("ᴠᴇʀɪғʏ ʀᴇǫᴜᴇsᴛ sᴇɴᴛ ᴛᴏ ᴍʏ ᴀᴅᴍɪɴ, ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ ғᴏʀ ᴛʜᴇ ᴄᴏɴғɪʀᴍᴀᴛɪᴏɴ.")
116 | else:
117 | await message.reply("Gʀᴏᴜᴘ Aʟʀᴇᴀᴅʏ Vᴇʀɪғɪᴇᴅ ✅")
118 | else:
119 | await message.reply_text(
120 | text=f"ᴜsᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴏɴʟʏ ɢʀᴏᴜᴘ ᴀᴅᴍɪɴs",
121 | )
122 | else:
123 | if owner:
124 | await message.reply_text(text=f" ʏᴏᴜʀ ɢʀᴏᴜᴘ ʜᴀs ʙᴇᴇɴ ʀᴇᴊᴇᴄᴛᴇᴅ ʙʏ ᴍʏ ᴀᴅᴍɪɴ.\n\nɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ɢᴇᴛ ᴛʜᴇ ɢʀᴏᴜᴘ ᴠᴇʀɪғɪᴇᴅ ᴛʜᴇɴ contact ᴛʜᴇ ᴀᴅᴍɪɴ. @Safaridev.")
125 | else:
126 | await message.reply("ᴜsᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴏɴʟʏ ɢʀᴏᴜᴘ ᴀᴅᴍɪɴs")
127 |
128 |
129 | # Command to delete all saved groups and leave them
130 | @Client.on_message(filters.command("grp_delete") & filters.user(ADMINS))
131 | async def delete_all_groups_command(bot, message):
132 | all_groups = await db.get_all_groups()
133 | for group in all_groups:
134 | try:
135 | await bot.send_message(group['id'], "The bot is now leaving this group as per the admin's command.")
136 | await bot.leave_chat(group['id'])
137 | except Exception as e:
138 | print(f"Failed to leave chat {group['id']}: {e}")
139 | await db.delete_all_groups()
140 | await message.reply_text("All saved groups have been deleted and bot has left all groups.")
141 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/features/font.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import os
4 | from .fotnt_string import Fonts
5 | from pyrogram import Client, filters
6 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
7 |
8 |
9 | @Client.on_message(filters.private & filters.command(["font"]))
10 | async def style_buttons(c, m, cb=False):
11 | buttons = [[
12 | InlineKeyboardButton('𝚃𝚢𝚙𝚎𝚠𝚛𝚒𝚝𝚎𝚛', callback_data='style+typewriter'),
13 | InlineKeyboardButton('𝕆𝕦𝕥𝕝𝕚𝕟𝕖', callback_data='style+outline'),
14 | InlineKeyboardButton('𝐒𝐞𝐫𝐢𝐟', callback_data='style+serif'),
15 | ],[
16 | InlineKeyboardButton('𝑺𝒆𝒓𝒊𝒇', callback_data='style+bold_cool'),
17 | InlineKeyboardButton('𝑆𝑒𝑟𝑖𝑓', callback_data='style+cool'),
18 | InlineKeyboardButton('Sᴍᴀʟʟ Cᴀᴘs', callback_data='style+small_cap'),
19 | ],[
20 | InlineKeyboardButton('𝓈𝒸𝓇𝒾𝓅𝓉', callback_data='style+script'),
21 | InlineKeyboardButton('𝓼𝓬𝓻𝓲𝓹𝓽', callback_data='style+script_bolt'),
22 | InlineKeyboardButton('ᵗⁱⁿʸ', callback_data='style+tiny'),
23 | ],[
24 | InlineKeyboardButton('ᑕOᗰIᑕ', callback_data='style+comic'),
25 | InlineKeyboardButton('𝗦𝗮𝗻𝘀', callback_data='style+sans'),
26 | InlineKeyboardButton('𝙎𝙖𝙣𝙨', callback_data='style+slant_sans'),
27 | ],[
28 | InlineKeyboardButton('𝘚𝘢𝘯𝘴', callback_data='style+slant'),
29 | InlineKeyboardButton('𝖲𝖺𝗇𝗌', callback_data='style+sim'),
30 | InlineKeyboardButton('Ⓒ︎Ⓘ︎Ⓡ︎Ⓒ︎Ⓛ︎Ⓔ︎Ⓢ︎', callback_data='style+circles')
31 | ],[
32 | InlineKeyboardButton('🅒︎🅘︎🅡︎🅒︎🅛︎🅔︎🅢︎', callback_data='style+circle_dark'),
33 | InlineKeyboardButton('𝔊𝔬𝔱𝔥𝔦𝔠', callback_data='style+gothic'),
34 | InlineKeyboardButton('𝕲𝖔𝖙𝖍𝖎𝖈', callback_data='style+gothic_bolt'),
35 | ],[
36 | InlineKeyboardButton('C͜͡l͜͡o͜͡u͜͡d͜͡s͜͡', callback_data='style+cloud'),
37 | InlineKeyboardButton('H̆̈ă̈p̆̈p̆̈y̆̈', callback_data='style+happy'),
38 | InlineKeyboardButton('S̑̈ȃ̈d̑̈', callback_data='style+sad'),
39 | ],[
40 | InlineKeyboardButton('Next ➡️', callback_data="nxt")
41 | ]]
42 | if not cb:
43 | if ' ' in m.text:
44 | title = m.text.split(" ", 1)[1]
45 | await m.reply_text(title, reply_markup=InlineKeyboardMarkup(buttons), reply_to_message_id=m.id)
46 | else:
47 | await m.reply_text(text="Ente Any Text Eg:- `/font [text]`")
48 | else:
49 | await m.answer()
50 | await m.message.edit_reply_markup(InlineKeyboardMarkup(buttons))
51 |
52 |
53 | @Client.on_callback_query(filters.regex('^nxt'))
54 | async def nxt(c, m):
55 | if m.data == "nxt":
56 | buttons = [[
57 | InlineKeyboardButton('🇸 🇵 🇪 🇨 🇮 🇦 🇱 ', callback_data='style+special'),
58 | InlineKeyboardButton('🅂🅀🅄🄰🅁🄴🅂', callback_data='style+squares'),
59 | InlineKeyboardButton('🆂︎🆀︎🆄︎🅰︎🆁︎🅴︎🆂︎', callback_data='style+squares_bold'),
60 | ],[
61 | InlineKeyboardButton('ꪖꪀᦔꪖꪶꪊᥴ𝓲ꪖ', callback_data='style+andalucia'),
62 | InlineKeyboardButton('爪卂几ᘜ卂', callback_data='style+manga'),
63 | InlineKeyboardButton('S̾t̾i̾n̾k̾y̾', callback_data='style+stinky'),
64 | ],[
65 | InlineKeyboardButton('B̥ͦu̥ͦb̥ͦb̥ͦl̥ͦe̥ͦs̥ͦ', callback_data='style+bubbles'),
66 | InlineKeyboardButton('U͟n͟d͟e͟r͟l͟i͟n͟e͟', callback_data='style+underline'),
67 | InlineKeyboardButton('꒒ꍏꀷꌩꌃꀎꁅ', callback_data='style+ladybug'),
68 | ],[
69 | InlineKeyboardButton('R҉a҉y҉s҉', callback_data='style+rays'),
70 | InlineKeyboardButton('B҈i҈r҈d҈s҈', callback_data='style+birds'),
71 | InlineKeyboardButton('S̸l̸a̸s̸h̸', callback_data='style+slash'),
72 | ],[
73 | InlineKeyboardButton('s⃠t⃠o⃠p⃠', callback_data='style+stop'),
74 | InlineKeyboardButton('S̺͆k̺͆y̺͆l̺͆i̺͆n̺͆e̺͆', callback_data='style+skyline'),
75 | InlineKeyboardButton('A͎r͎r͎o͎w͎s͎', callback_data='style+arrows'),
76 | ],[
77 | InlineKeyboardButton('ዪሀክቿነ', callback_data='style+qvnes'),
78 | InlineKeyboardButton('S̶t̶r̶i̶k̶e̶', callback_data='style+strike'),
79 | InlineKeyboardButton('F༙r༙o༙z༙e༙n༙', callback_data='style+frozen')
80 | ],[
81 | InlineKeyboardButton('⬅️ Back', callback_data='nxt+0')
82 | ]]
83 | await m.answer()
84 | await m.message.edit_reply_markup(InlineKeyboardMarkup(buttons))
85 | else:
86 | await style_buttons(c, m, cb=True)
87 |
88 |
89 | @Client.on_callback_query(filters.regex('^style'))
90 | async def style(c, m):
91 | await m.answer()
92 | cmd, style = m.data.split('+')
93 |
94 | if style == 'typewriter':
95 | cls = Fonts.typewriter
96 | if style == 'outline':
97 | cls = Fonts.outline
98 | if style == 'serif':
99 | cls = Fonts.serief
100 | if style == 'bold_cool':
101 | cls = Fonts.bold_cool
102 | if style == 'cool':
103 | cls = Fonts.cool
104 | if style == 'small_cap':
105 | cls = Fonts.smallcap
106 | if style == 'script':
107 | cls = Fonts.script
108 | if style == 'script_bolt':
109 | cls = Fonts.bold_script
110 | if style == 'tiny':
111 | cls = Fonts.tiny
112 | if style == 'comic':
113 | cls = Fonts.comic
114 | if style == 'sans':
115 | cls = Fonts.san
116 | if style == 'slant_sans':
117 | cls = Fonts.slant_san
118 | if style == 'slant':
119 | cls = Fonts.slant
120 | if style == 'sim':
121 | cls = Fonts.sim
122 | if style == 'circles':
123 | cls = Fonts.circles
124 | if style == 'circle_dark':
125 | cls = Fonts.dark_circle
126 | if style == 'gothic':
127 | cls = Fonts.gothic
128 | if style == 'gothic_bolt':
129 | cls = Fonts.bold_gothic
130 | if style == 'cloud':
131 | cls = Fonts.cloud
132 | if style == 'happy':
133 | cls = Fonts.happy
134 | if style == 'sad':
135 | cls = Fonts.sad
136 | if style == 'special':
137 | cls = Fonts.special
138 | if style == 'squares':
139 | cls = Fonts.square
140 | if style == 'squares_bold':
141 | cls = Fonts.dark_square
142 | if style == 'andalucia':
143 | cls = Fonts.andalucia
144 | if style == 'manga':
145 | cls = Fonts.manga
146 | if style == 'stinky':
147 | cls = Fonts.stinky
148 | if style == 'bubbles':
149 | cls = Fonts.bubbles
150 | if style == 'underline':
151 | cls = Fonts.underline
152 | if style == 'ladybug':
153 | cls = Fonts.ladybug
154 | if style == 'rays':
155 | cls = Fonts.rays
156 | if style == 'birds':
157 | cls = Fonts.birds
158 | if style == 'slash':
159 | cls = Fonts.slash
160 | if style == 'stop':
161 | cls = Fonts.stop
162 | if style == 'skyline':
163 | cls = Fonts.skyline
164 | if style == 'arrows':
165 | cls = Fonts.arrows
166 | if style == 'qvnes':
167 | cls = Fonts.rvnes
168 | if style == 'strike':
169 | cls = Fonts.strike
170 | if style == 'frozen':
171 | cls = Fonts.frozen
172 |
173 | r, oldtxt = m.message.reply_to_message.text.split(None, 1)
174 | new_text = cls(oldtxt)
175 | try:
176 | await m.message.edit_text(f"`{new_text}`\n\n👆 Click To Copy", reply_markup=m.message.reply_markup)
177 | except Exception as e:
178 | print(e)
179 |
--------------------------------------------------------------------------------
/database/ia_filterdb.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import logging
4 | from struct import pack
5 | import re
6 | import base64
7 | from pyrogram.file_id import FileId
8 | from pymongo.errors import DuplicateKeyError
9 | from umongo import Instance, Document, fields
10 | from motor.motor_asyncio import AsyncIOMotorClient
11 | from marshmallow.exceptions import ValidationError
12 | from info import DATABASE_URI, DATABASE_NAME, COLLECTION_NAME, USE_CAPTION_FILTER, MAX_B_TN
13 | from utils import get_settings, save_group_settings
14 | from fuzzywuzzy import process
15 | from Script import script
16 |
17 | # Set up logging
18 | logging.basicConfig(level=logging.INFO)
19 |
20 | logger = logging.getLogger(__name__)
21 | logger.setLevel(logging.INFO)
22 |
23 |
24 | client = AsyncIOMotorClient(DATABASE_URI)
25 | db = client[DATABASE_NAME]
26 | instance = Instance.from_db(db)
27 |
28 | @instance.register
29 | class Media(Document):
30 | file_id = fields.StrField(attribute='_id')
31 | file_ref = fields.StrField(allow_none=True)
32 | file_name = fields.StrField(required=True)
33 | file_size = fields.IntField(required=True)
34 | file_type = fields.StrField(allow_none=True)
35 | mime_type = fields.StrField(allow_none=True)
36 | caption = fields.StrField(allow_none=True)
37 |
38 | class Meta:
39 | indexes = ('$file_name', )
40 | collection_name = COLLECTION_NAME
41 |
42 |
43 | async def save_file(media):
44 | """Save file in database"""
45 |
46 | # TODO: Find better way to get same file_id for same media to avoid duplicates
47 | file_id, file_ref = unpack_new_file_id(media.file_id)
48 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
49 | try:
50 | file = Media(
51 | file_id=file_id,
52 | file_ref=file_ref,
53 | file_name=file_name,
54 | file_size=media.file_size,
55 | file_type=media.file_type,
56 | mime_type=media.mime_type,
57 | caption=media.caption.html if media.caption else None,
58 | )
59 | except ValidationError:
60 | logger.exception('Error occurred while saving file in database')
61 | return False, None
62 | else:
63 | try:
64 | await file.commit()
65 | except DuplicateKeyError:
66 | logger.warning(
67 | f'{getattr(media, "file_name", "NO_FILE")} is already saved in database'
68 | )
69 |
70 | return False, file_id
71 | else:
72 | logger.info(f'{getattr(media, "file_name", "NO_FILE")} is saved to database')
73 | return True, file_id
74 |
75 |
76 |
77 | async def get_search_results(chat_id, query, file_type=None, max_results=10, offset=0, filter=False):
78 | """For given query return (results, next_offset)"""
79 | banned_words = script.BLACKLIST
80 | if chat_id is not None:
81 | settings = await get_settings(int(chat_id))
82 | try:
83 | if settings['max_btn']:
84 | max_results = 10
85 | else:
86 | max_results = int(MAX_B_TN)
87 | except KeyError:
88 | await save_group_settings(int(chat_id), 'max_btn', False)
89 | settings = await get_settings(int(chat_id))
90 | if settings['max_btn']:
91 | max_results = 10
92 | else:
93 | max_results = int(MAX_B_TN)
94 | query = query.strip()
95 | #if filter:
96 | #better ?
97 | #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
98 | #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
99 | if not query:
100 | raw_pattern = '.'
101 | elif ' ' not in query:
102 | raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
103 | else:
104 | raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
105 |
106 | try:
107 | regex = re.compile(raw_pattern, flags=re.IGNORECASE)
108 | except:
109 | return []
110 |
111 | if USE_CAPTION_FILTER:
112 | filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
113 | else:
114 | filter = {'file_name': regex}
115 |
116 | if file_type:
117 | filter['file_type'] = file_type
118 |
119 | total_results = await Media.count_documents(filter)
120 | next_offset = offset + max_results
121 |
122 | if next_offset > total_results:
123 | next_offset = ''
124 |
125 | cursor = Media.find(filter)
126 | # Sort by recent
127 | cursor.sort('$natural', -1)
128 | # Slice files according to offset and max results
129 | cursor.skip(offset).limit(max_results)
130 | # Get list of files
131 | files = await cursor.to_list(length=max_results)
132 | for file in files:
133 | for banned_word in banned_words:
134 | # Case-insensitive replacement
135 | pattern = re.compile(re.escape(banned_word), re.IGNORECASE)
136 | file['file_name'] = pattern.sub('', file['file_name']).strip()
137 |
138 | return files, next_offset, total_results
139 |
140 | async def get_all_files():
141 | cursor = Media.find()
142 | all_files = await cursor.to_list(length=10000)
143 | return [file['file_name'] for file in all_files]
144 |
145 | async def get_bad_files(query, file_type=None, filter=False):
146 | """For given query return (results, next_offset)"""
147 | query = query.strip()
148 | #if filter:
149 | #better ?
150 | #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
151 | #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
152 | if not query:
153 | raw_pattern = '.'
154 | elif ' ' not in query:
155 | raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
156 | else:
157 | raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
158 |
159 | try:
160 | regex = re.compile(raw_pattern, flags=re.IGNORECASE)
161 | except:
162 | return []
163 |
164 | if USE_CAPTION_FILTER:
165 | filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
166 | else:
167 | filter = {'file_name': regex}
168 |
169 | if file_type:
170 | filter['file_type'] = file_type
171 |
172 | total_results = await Media.count_documents(filter)
173 |
174 | cursor = Media.find(filter)
175 | # Sort by recent
176 | cursor.sort('$natural', -1)
177 | # Get list of files
178 | files = await cursor.to_list(length=total_results)
179 |
180 | return files, total_results
181 |
182 | async def get_file_details(query):
183 | try:
184 | banned_words = script.BLACKLIST
185 | filter = {'file_id': query}
186 | cursor = Media.find(filter)
187 | filedetails = await cursor.to_list(length=1)
188 | if filedetails:
189 | file = filedetails[0]
190 | original_file_name = getattr(file, 'file_name', '')
191 | modified_file_name = original_file_name
192 | for banned_word in banned_words:
193 | pattern = re.compile(re.escape(banned_word), re.IGNORECASE)
194 | modified_file_name = pattern.sub('', modified_file_name).strip()
195 | if not modified_file_name:
196 | modified_file_name = "DefaultFileName"
197 | setattr(file, 'file_name', modified_file_name)
198 | return filedetails
199 | except Exception as e:
200 | logging.error("An error occurred:", exc_info=True)
201 | return None
202 |
203 | def encode_file_id(s: bytes) -> str:
204 | r = b""
205 | n = 0
206 |
207 | for i in s + bytes([22]) + bytes([4]):
208 | if i == 0:
209 | n += 1
210 | else:
211 | if n:
212 | r += b"\x00" + bytes([n])
213 | n = 0
214 |
215 | r += bytes([i])
216 |
217 | return base64.urlsafe_b64encode(r).decode().rstrip("=")
218 |
219 |
220 | def encode_file_ref(file_ref: bytes) -> str:
221 | return base64.urlsafe_b64encode(file_ref).decode().rstrip("=")
222 |
223 |
224 | def unpack_new_file_id(new_file_id):
225 | """Return file_id, file_ref"""
226 | decoded = FileId.decode(new_file_id)
227 | file_id = encode_file_id(
228 | pack(
229 | "➲ First Name: {first}\n➲ Last Name: {last}\n➲ Username: {username}\n➲ Telegram ID: {user_id}\n➲ Data Centre: {dc_id}",
26 | quote=True
27 | )
28 |
29 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
30 | _id = ""
31 | _id += (
32 | "➲ Chat ID: "
33 | f"{message.chat.id}\n"
34 | )
35 | if message.reply_to_message:
36 | _id += (
37 | "➲ User ID: "
38 | f"{message.from_user.id if message.from_user else 'Anonymous'}\n"
39 | "➲ Replied User ID: "
40 | f"{message.reply_to_message.from_user.id if message.reply_to_message.from_user else 'Anonymous'}\n"
41 | )
42 | file_info = get_file_id(message.reply_to_message)
43 | else:
44 | _id += (
45 | "➲ User ID: "
46 | f"{message.from_user.id if message.from_user else 'Anonymous'}\n"
47 | )
48 | file_info = get_file_id(message)
49 | if file_info:
50 | _id += (
51 | f"{file_info.message_type}: "
52 | f"{file_info.file_id}\n"
53 | )
54 | await message.reply_text(
55 | _id,
56 | quote=True
57 | )
58 |
59 | @Client.on_message(filters.command(["info"]))
60 | async def who_is(client, message):
61 | # https://github.com/SpEcHiDe/PyroGramBot/blob/master/pyrobot/plugins/admemes/whois.py#L19
62 | status_message = await message.reply_text(
63 | "`Fetching user info...`"
64 | )
65 | await status_message.edit(
66 | "`Processing user info...`"
67 | )
68 | from_user = None
69 | from_user_id, _ = extract_user(message)
70 | try:
71 | from_user = await client.get_users(from_user_id)
72 | except Exception as error:
73 | await status_message.edit(str(error))
74 | return
75 | if from_user is None:
76 | return await status_message.edit("no valid user_id / message specified")
77 | message_out_str = ""
78 | message_out_str += f"➲First Name: {from_user.first_name}\n"
79 | last_name = from_user.last_name or "None"
80 | message_out_str += f"➲Last Name: {last_name}\n"
81 | message_out_str += f"➲Telegram ID: {from_user.id}\n"
82 | username = from_user.username or "None"
83 | dc_id = from_user.dc_id or "[User Doesn't Have A Valid DP]"
84 | message_out_str += f"➲Data Centre: {dc_id}\n"
85 | message_out_str += f"➲User Name: @{username}\n"
86 | message_out_str += f"➲User 𝖫𝗂𝗇𝗄: Click Here\n"
87 | if message.chat.type in ((enums.ChatType.SUPERGROUP, enums.ChatType.CHANNEL)):
88 | try:
89 | chat_member_p = await message.chat.get_member(from_user.id)
90 | joined_date = (
91 | chat_member_p.joined_date or datetime.now()
92 | ).strftime("%Y.%m.%d %H:%M:%S")
93 | message_out_str += (
94 | "➲Joined this Chat on: "
95 | f"{joined_date}"
96 | "\n"
97 | )
98 | except UserNotParticipant:
99 | pass
100 | chat_photo = from_user.photo
101 | if chat_photo:
102 | local_user_photo = await client.download_media(
103 | message=chat_photo.big_file_id
104 | )
105 | buttons = [[
106 | InlineKeyboardButton('🔐 Close', callback_data='close_data')
107 | ]]
108 | reply_markup = InlineKeyboardMarkup(buttons)
109 | await message.reply_photo(
110 | photo=local_user_photo,
111 | quote=True,
112 | reply_markup=reply_markup,
113 | caption=message_out_str,
114 | parse_mode=enums.ParseMode.HTML,
115 | disable_notification=True
116 | )
117 | os.remove(local_user_photo)
118 | else:
119 | buttons = [[
120 | InlineKeyboardButton('🔐 Close', callback_data='close_data')
121 | ]]
122 | reply_markup = InlineKeyboardMarkup(buttons)
123 | await message.reply_text(
124 | text=message_out_str,
125 | reply_markup=reply_markup,
126 | quote=True,
127 | parse_mode=enums.ParseMode.HTML,
128 | disable_notification=True
129 | )
130 | await status_message.delete()
131 |
132 | @Client.on_message(filters.command(["imdb", 'search']))
133 | async def imdb_search(client, message):
134 | if ' ' in message.text:
135 | k = await message.reply('Searching ImDB')
136 | r, title = message.text.split(None, 1)
137 | movies = await get_poster(title, bulk=True)
138 | if not movies:
139 | return await message.reply("No results Found")
140 | btn = [
141 | [
142 | InlineKeyboardButton(
143 | text=f"{movie.get('title')} - {movie.get('year')}",
144 | callback_data=f"imdb#{movie.movieID}",
145 | )
146 | ]
147 | for movie in movies
148 | ]
149 | await k.edit('Here is what i found on IMDb', reply_markup=InlineKeyboardMarkup(btn))
150 | else:
151 | await message.reply('Give me a movie / series Name')
152 |
153 | @Client.on_callback_query(filters.regex('^imdb'))
154 | async def imdb_callback(bot: Client, quer_y: CallbackQuery):
155 | i, movie = quer_y.data.split('#')
156 | imdb = await get_poster(query=movie, id=True)
157 | btn = [
158 | [
159 | InlineKeyboardButton(
160 | text=f"{imdb.get('title')}",
161 | url=imdb['url'],
162 | )
163 | ]
164 | ]
165 | message = quer_y.message.reply_to_message or quer_y.message
166 | if imdb:
167 | caption = IMDB_TEMPLATE.format(
168 | query = imdb['title'],
169 | title = imdb['title'],
170 | votes = imdb['votes'],
171 | aka = imdb["aka"],
172 | seasons = imdb["seasons"],
173 | box_office = imdb['box_office'],
174 | localized_title = imdb['localized_title'],
175 | kind = imdb['kind'],
176 | imdb_id = imdb["imdb_id"],
177 | cast = imdb["cast"],
178 | runtime = imdb["runtime"],
179 | countries = imdb["countries"],
180 | certificates = imdb["certificates"],
181 | languages = imdb["languages"],
182 | director = imdb["director"],
183 | writer = imdb["writer"],
184 | producer = imdb["producer"],
185 | composer = imdb["composer"],
186 | cinematographer = imdb["cinematographer"],
187 | music_team = imdb["music_team"],
188 | distributors = imdb["distributors"],
189 | release_date = imdb['release_date'],
190 | year = imdb['year'],
191 | genres = imdb['genres'],
192 | poster = imdb['poster'],
193 | plot = imdb['plot'],
194 | rating = imdb['rating'],
195 | url = imdb['url'],
196 | **locals()
197 | )
198 | else:
199 | caption = "No Results"
200 | if imdb.get('poster'):
201 | try:
202 | await quer_y.message.reply_photo(photo=imdb['poster'], caption=caption, reply_markup=InlineKeyboardMarkup(btn))
203 | except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty):
204 | pic = imdb.get('poster')
205 | poster = pic.replace('.jpg', "._V1_UX360.jpg")
206 | await quer_y.message.reply_photo(photo=poster, caption=caption, reply_markup=InlineKeyboardMarkup(btn))
207 | except Exception as e:
208 | logger.exception(e)
209 | await quer_y.message.reply(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False)
210 | await quer_y.message.delete()
211 | else:
212 | await quer_y.message.edit(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False)
213 | await quer_y.answer()
214 |
215 |
216 |
217 |
--------------------------------------------------------------------------------
/plugins/Dev_Feature/Premium.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from datetime import timedelta, datetime, time
4 | import pytz
5 | from Script import script
6 | from asyncio import sleep
7 | from info import ADMINS, PREMIUM_LOGS, OWNER_USER_NAME, PREMIUM_PIC
8 | from utils import get_seconds
9 | from database.users_chats_db import db
10 | from pyrogram import Client, filters
11 | from pyrogram.errors.exceptions.bad_request_400 import MessageTooLong
12 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
13 |
14 | async def check_expired_premium(client):
15 | while 1:
16 | data = await db.get_expired(datetime.now())
17 |
18 | for user in data:
19 | user_id = user["id"]
20 | await db.remove_premium_access(user_id)
21 | try:
22 | user = await client.get_users(user_id)
23 | try:
24 | await client.send_message(
25 | chat_id=user_id,
26 | text=f"Hᴇʏ Tʜᴇʀᴇ {user.mention} 👋\n\nʏᴏᴜʀ ᴘʀᴇᴍɪᴜᴍ ᴀᴄᴄᴇss ʜᴀs ᴇxᴘɪʀᴇᴅ ❗\nᴛʜᴀɴᴋ ʏᴏᴜ ꜰᴏʀ ᴜsɪɴɢ ᴏᴜʀ sᴇʀᴠɪᴄᴇ.\n\nɪꜰ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ᴛᴀᴋᴇ ᴛʜᴇ ᴘʀᴇᴍɪᴜᴍ ᴀɢᴀɪɴ, ᴛʜᴇɴ ᴄʟɪᴄᴋ ᴏɴ ᴛʜᴇ /plans ꜰᴏʀ ᴛʜᴇ ᴅᴇᴛᴀɪʟs ᴏꜰ ᴛʜᴇ ᴘʟᴀɴs.")
27 | except:
28 | pass
29 | await client.send_message(
30 | PREMIUM_LOGS,
31 | text=f"#PREMIUM_EXPIRED\n\nUsᴇʀ : {user.mention}\nUsᴇʀ Iᴅ : {user_id}"
32 | )
33 | except Exception as e:
34 | pass
35 | await sleep(0.5)
36 | await sleep(1)
37 |
38 | @Client.on_message(filters.command("remove_premium") & filters.user(ADMINS))
39 | async def remove_premium(client, message):
40 | if len(message.command) == 2:
41 | user_id = int(message.command[1]) # Convert the user_id to integer
42 | user = await client.get_users(user_id)
43 | if await db.remove_premium_access(user_id):
44 | await message.reply_text("ᴜꜱᴇʀ ʀᴇᴍᴏᴠᴇᴅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ !")
45 | await client.send_message(
46 | chat_id=user_id,
47 | text=f"ʜᴇʏ {user.mention},\n\nʏᴏᴜʀ ᴘʀᴇᴍɪᴜᴍ ᴀᴄᴄᴇss ʜᴀs ʙᴇᴇɴ ʀᴇᴍᴏᴠᴇᴅ.\nᴛʜᴀɴᴋ ʏᴏᴜ ꜰᴏʀ ᴜsɪɴɢ ᴏᴜʀ sᴇʀᴠɪᴄᴇ 😊\nᴄʟɪᴄᴋ ᴏɴ /plans ᴛᴏ ᴄʜᴇᴄᴋ ᴏᴜᴛ ᴏᴛʜᴇʀ ᴘʟᴀɴꜱ."
48 | )
49 | else:
50 | await message.reply_text("ᴜɴᴀʙʟᴇ ᴛᴏ ʀᴇᴍᴏᴠᴇ ᴜꜱᴇᴅ !\nᴀʀᴇ ʏᴏᴜ ꜱᴜʀᴇ, ɪᴛ ᴡᴀꜱ ᴀ ᴘʀᴇᴍɪᴜᴍ ᴜꜱᴇʀ ɪᴅ ?")
51 | else:
52 | await message.reply_text("ᴜꜱᴀɢᴇ : /remove_premium user_id")
53 |
54 | @Client.on_message(filters.command("myplan"))
55 | async def myplan(client, message):
56 | user = message.from_user.mention
57 | user_id = message.from_user.id
58 | data = await db.get_user(message.from_user.id) # Convert the user_id to integer
59 | if data and data.get("expiry_time"):
60 | expiry = data.get("expiry_time")
61 | expiry_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata"))
62 | expiry_str_in_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y\n⏱️ ᴇxᴘɪʀʏ ᴛɪᴍᴇ : %I:%M:%S %p")
63 | current_time = datetime.now(pytz.timezone("Asia/Kolkata"))
64 | time_left = expiry_ist - current_time
65 |
66 | days = time_left.days
67 | hours, remainder = divmod(time_left.seconds, 3600)
68 | minutes, seconds = divmod(remainder, 60)
69 |
70 | # Format time left as a string
71 | time_left_str = f"{days} ᴅᴀʏꜱ, {hours} ʜᴏᴜʀꜱ, {minutes} ᴍɪɴᴜᴛᴇꜱ"
72 | await message.reply_text(f"⚜️ ᴘʀᴇᴍɪᴜᴍ ᴜꜱᴇʀ ᴅᴀᴛᴀ :\n\n👤 ᴜꜱᴇʀ : {user}\n⚡ ᴜꜱᴇʀ ɪᴅ : {user_id}\n⏰ ᴛɪᴍᴇ ʟᴇꜰᴛ : {time_left_str}\n⌛️ ᴇxᴘɪʀʏ ᴅᴀᴛᴇ : {expiry_str_in_ist}")
73 | else:
74 | await message.reply_text(f"ʜᴇʏ {user},\n\nʏᴏᴜ ᴅᴏ ɴᴏᴛ ʜᴀᴠᴇ ᴀɴʏ ᴀᴄᴛɪᴠᴇ ᴘʀᴇᴍɪᴜᴍ ᴘʟᴀɴs, ɪꜰ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ᴛᴀᴋᴇ ᴘʀᴇᴍɪᴜᴍ ᴛʜᴇɴ ᴄʟɪᴄᴋ ᴏɴ ʙᴇʟᴏᴡ ʙᴜᴛᴛᴏɴ 👇",
75 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("💸 ᴄʜᴇᴄᴋᴏᴜᴛ ᴘʀᴇᴍɪᴜᴍ ᴘʟᴀɴꜱ 💸", callback_data='premium_pm')]]))
76 |
77 | @Client.on_message(filters.command("get_premium") & filters.user(ADMINS))
78 | async def get_premium(client, message):
79 | if len(message.command) == 2:
80 | user_id = int(message.command[1])
81 | user = await client.get_users(user_id)
82 | data = await db.get_user(user_id) # Convert the user_id to integer
83 | if data and data.get("expiry_time"):
84 | expiry = data.get("expiry_time")
85 | expiry_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata"))
86 | expiry_str_in_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y\n⏱️ ᴇxᴘɪʀʏ ᴛɪᴍᴇ : %I:%M:%S %p")
87 | # Calculate time difference
88 | current_time = datetime.now(pytz.timezone("Asia/Kolkata"))
89 | time_left = expiry_ist - current_time
90 |
91 | # Calculate days, hours, and minutes
92 | days = time_left.days
93 | hours, remainder = divmod(time_left.seconds, 3600)
94 | minutes, seconds = divmod(remainder, 60)
95 |
96 | # Format time left as a string
97 | time_left_str = f"{days} days, {hours} hours, {minutes} minutes"
98 | await message.reply_text(f"⚜️ ᴘʀᴇᴍɪᴜᴍ ᴜꜱᴇʀ ᴅᴀᴛᴀ :\n\n👤 ᴜꜱᴇʀ : {user.mention}\n⚡ ᴜꜱᴇʀ ɪᴅ : {user_id}\n⏰ ᴛɪᴍᴇ ʟᴇꜰᴛ : {time_left_str}\n⌛️ ᴇxᴘɪʀʏ ᴅᴀᴛᴇ : {expiry_str_in_ist}")
99 | else:
100 | await message.reply_text("ɴᴏ ᴀɴʏ ᴘʀᴇᴍɪᴜᴍ ᴅᴀᴛᴀ ᴏꜰ ᴛʜᴇ ᴡᴀꜱ ꜰᴏᴜɴᴅ ɪɴ ᴅᴀᴛᴀʙᴀꜱᴇ !")
101 | else:
102 | await message.reply_text("ᴜꜱᴀɢᴇ : /get_premium user_id")
103 |
104 | @Client.on_message(filters.command("add_premium") & filters.user(ADMINS))
105 | async def give_premium_cmd_handler(client, message):
106 | if len(message.command) == 4:
107 | time_zone = datetime.now(pytz.timezone("Asia/Kolkata"))
108 | current_time = time_zone.strftime("%d-%m-%Y\n⏱️ ᴊᴏɪɴɪɴɢ ᴛɪᴍᴇ : %I:%M:%S %p")
109 | user_id = int(message.command[1]) # Convert the user_id to integer
110 | user = await client.get_users(user_id)
111 | time = message.command[2]+" "+message.command[3]
112 | seconds = await get_seconds(time)
113 | if seconds > 0:
114 | expiry_time = datetime.now() + timedelta(seconds=seconds)
115 | user_data = {"id": user_id, "expiry_time": expiry_time} # Using "id" instead of "user_id"
116 | await db.update_user(user_data) # Use the update_user method to update or insert user data
117 | data = await db.get_user(user_id)
118 | expiry = data.get("expiry_time")
119 | expiry_str_in_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y\n⏱️ ᴇxᴘɪʀʏ ᴛɪᴍᴇ : %I:%M:%S %p")
120 | await message.reply_text(f"ᴘʀᴇᴍɪᴜᴍ ᴀᴅᴅᴇᴅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ✅\n\n👤 ᴜꜱᴇʀ : {user.mention}\n⚡ ᴜꜱᴇʀ ɪᴅ : {user_id}\n⏰ ᴘʀᴇᴍɪᴜᴍ ᴀᴄᴄᴇꜱꜱ : {time}\n\n⏳ ᴊᴏɪɴɪɴɢ ᴅᴀᴛᴇ : {current_time}\n\n⌛️ ᴇxᴘɪʀʏ ᴅᴀᴛᴇ : {expiry_str_in_ist}", disable_web_page_preview=True)
121 | await client.send_message(
122 | chat_id=user_id,
123 | text=f"👋 ʜᴇʏ {user.mention},\nᴛʜᴀɴᴋ ʏᴏᴜ ꜰᴏʀ ᴘᴜʀᴄʜᴀꜱɪɴɢ ᴘʀᴇᴍɪᴜᴍ.\nᴇɴᴊᴏʏ !! ✨🎉\n\n⏰ ᴘʀᴇᴍɪᴜᴍ ᴀᴄᴄᴇꜱꜱ : {time}\n⏳ ᴊᴏɪɴɪɴɢ ᴅᴀᴛᴇ : {current_time}\n\n⌛️ ᴇxᴘɪʀʏ ᴅᴀᴛᴇ : {expiry_str_in_ist}", disable_web_page_preview=True
124 | )
125 | await client.send_message(PREMIUM_LOGS, text=f"#Added_Premium\n\n👤 ᴜꜱᴇʀ : {user.mention}\n⚡ ᴜꜱᴇʀ ɪᴅ : {user_id}\n⏰ ᴘʀᴇᴍɪᴜᴍ ᴀᴄᴄᴇꜱꜱ : {time}\n\n⏳ ᴊᴏɪɴɪɴɢ ᴅᴀᴛᴇ : {current_time}\n\n⌛️ ᴇxᴘɪʀʏ ᴅᴀᴛᴇ : {expiry_str_in_ist}", disable_web_page_preview=True)
126 |
127 | else:
128 | await message.reply_text("Invalid time format. Please use '1 day for days', '1 hour for hours', or '1 min for minutes', or '1 month for months' or '1 year for year'")
129 | else:
130 | await message.reply_text("Usage : /add_premium user_id time (e.g., '1 day for days', '1 hour for hours', or '1 min for minutes', or '1 month for months' or '1 year for year')")
131 |
132 | @Client.on_message(filters.command("premium_users") & filters.user(ADMINS))
133 | async def premium_user(client, message):
134 | aa = await message.reply_text("ꜰᴇᴛᴄʜɪɴɢ...")
135 | new = f"⚜️ ᴘʀᴇᴍɪᴜᴍ ᴜꜱᴇʀꜱ ʟɪꜱᴛ :\n\n"
136 | user_count = 1
137 | users = await db.get_all_users()
138 | async for user in users:
139 | data = await db.get_user(user['id'])
140 | if data and data.get("expiry_time"):
141 | expiry = data.get("expiry_time")
142 | expiry_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata"))
143 | expiry_str_in_ist = expiry.astimezone(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y\n⏱️ ᴇxᴘɪʀʏ ᴛɪᴍᴇ : %I:%M:%S %p")
144 | current_time = datetime.now(pytz.timezone("Asia/Kolkata"))
145 | time_left = expiry_ist - current_time
146 | days = time_left.days
147 | hours, remainder = divmod(time_left.seconds, 3600)
148 | minutes, seconds = divmod(remainder, 60)
149 | time_left_str = f"{days} days, {hours} hours, {minutes} minutes"
150 | new += f"{user_count}. {(await client.get_users(user['id'])).mention}\n👤 ᴜꜱᴇʀ ɪᴅ : {user['id']}\n⏳ ᴇxᴘɪʀʏ ᴅᴀᴛᴇ : {expiry_str_in_ist}\n⏰ ᴛɪᴍᴇ ʟᴇꜰᴛ : {time_left_str}\n"
151 | user_count += 1
152 | else:
153 | pass
154 | try:
155 | await aa.edit_text(new)
156 | except MessageTooLong:
157 | with open('usersplan.txt', 'w+') as outfile:
158 | outfile.write(new)
159 | await message.reply_document('usersplan.txt', caption="Paid Users:")
160 |
161 |
162 | @Client.on_message(filters.command("plans"))
163 | async def plan(client, message):
164 | user_id = message.from_user.id
165 | users = message.from_user.mention
166 | btn = [[
167 | InlineKeyboardButton("🔲 Qʀ ", callback_data='qr_info'),
168 | InlineKeyboardButton("💳 Uᴘɪ ", callback_data='upi_info')],
169 | [InlineKeyboardButton("❌ ᴄʟᴏꜱᴇ ❌", callback_data="close_data")
170 | ]]
171 | await message.reply_photo(photo=(PREMIUM_PIC), caption=script.PREMIUM_CMD, reply_markup=InlineKeyboardMarkup(btn))
172 |
173 | # This code has been modified by @Safaridev
174 | # Please do not remove this credit
175 |
--------------------------------------------------------------------------------
/SAFARI/utils/custom_dl.py:
--------------------------------------------------------------------------------
1 | import math
2 | import asyncio
3 | import logging
4 | from info import *
5 | from typing import Dict, Union
6 | from SAFARI.utils import work_loads
7 | from pyrogram import Client, utils, raw
8 | from SAFARI.utils.file_properties import get_file_ids
9 | from pyrogram.session import Session, Auth
10 | from pyrogram.errors import AuthBytesInvalid
11 | from SAFARI.utils.exceptions import FIleNotFound
12 | from pyrogram.file_id import FileId, FileType, ThumbnailSource
13 |
14 |
15 | class ByteStreamer:
16 | def __init__(self, client: Client):
17 | """A custom class that holds the cache of a specific client and class functions.
18 | attributes:
19 | client: the client that the cache is for.
20 | cached_file_ids: a dict of cached file IDs.
21 | cached_file_properties: a dict of cached file properties.
22 |
23 | functions:
24 | generate_file_properties: returns the properties for a media of a specific message contained in Tuple.
25 | generate_media_session: returns the media session for the DC that contains the media file.
26 | yield_file: yield a file from telegram servers for streaming.
27 |
28 | This is a modified version of the
29 | Thanks to Eyaadh
30 | """
31 | self.clean_timer = 30 * 60
32 | self.client: Client = client
33 | self.cached_file_ids: Dict[int, FileId] = {}
34 | asyncio.create_task(self.clean_cache())
35 |
36 | async def get_file_properties(self, id: int) -> FileId:
37 | """
38 | Returns the properties of a media of a specific message in a FIleId class.
39 | if the properties are cached, then it'll return the cached results.
40 | or it'll generate the properties from the Message ID and cache them.
41 | """
42 | if id not in self.cached_file_ids:
43 | await self.generate_file_properties(id)
44 | logging.debug(f"Cached file properties for message with ID {id}")
45 | return self.cached_file_ids[id]
46 |
47 | async def generate_file_properties(self, id: int) -> FileId:
48 | """
49 | Generates the properties of a media file on a specific message.
50 | returns ths properties in a FIleId class.
51 | """
52 | file_id = await get_file_ids(self.client, BIN_CHANNEL, id)
53 | logging.debug(f"Generated file ID and Unique ID for message with ID {id}")
54 | if not file_id:
55 | logging.debug(f"Message with ID {id} not found")
56 | raise FIleNotFound
57 | self.cached_file_ids[id] = file_id
58 | logging.debug(f"Cached media message with ID {id}")
59 | return self.cached_file_ids[id]
60 |
61 | async def generate_media_session(self, client: Client, file_id: FileId) -> Session:
62 | """
63 | Generates the media session for the DC that contains the media file.
64 | This is required for getting the bytes from Telegram servers.
65 | """
66 |
67 | media_session = client.media_sessions.get(file_id.dc_id, None)
68 |
69 | if media_session is None:
70 | if file_id.dc_id != await client.storage.dc_id():
71 | media_session = Session(
72 | client,
73 | file_id.dc_id,
74 | await Auth(
75 | client, file_id.dc_id, await client.storage.test_mode()
76 | ).create(),
77 | await client.storage.test_mode(),
78 | is_media=True,
79 | )
80 | await media_session.start()
81 |
82 | for _ in range(6):
83 | exported_auth = await client.invoke(
84 | raw.functions.auth.ExportAuthorization(dc_id=file_id.dc_id)
85 | )
86 |
87 | try:
88 | await media_session.send(
89 | raw.functions.auth.ImportAuthorization(
90 | id=exported_auth.id, bytes=exported_auth.bytes
91 | )
92 | )
93 | break
94 | except AuthBytesInvalid:
95 | logging.debug(
96 | f"Invalid authorization bytes for DC {file_id.dc_id}"
97 | )
98 | continue
99 | else:
100 | await media_session.stop()
101 | raise AuthBytesInvalid
102 | else:
103 | media_session = Session(
104 | client,
105 | file_id.dc_id,
106 | await client.storage.auth_key(),
107 | await client.storage.test_mode(),
108 | is_media=True,
109 | )
110 | await media_session.start()
111 | logging.debug(f"Created media session for DC {file_id.dc_id}")
112 | client.media_sessions[file_id.dc_id] = media_session
113 | else:
114 | logging.debug(f"Using cached media session for DC {file_id.dc_id}")
115 | return media_session
116 |
117 |
118 | @staticmethod
119 | async def get_location(file_id: FileId) -> Union[raw.types.InputPhotoFileLocation,
120 | raw.types.InputDocumentFileLocation,
121 | raw.types.InputPeerPhotoFileLocation,]:
122 | """
123 | Returns the file location for the media file.
124 | """
125 | file_type = file_id.file_type
126 |
127 | if file_type == FileType.CHAT_PHOTO:
128 | if file_id.chat_id > 0:
129 | peer = raw.types.InputPeerUser(
130 | user_id=file_id.chat_id, access_hash=file_id.chat_access_hash
131 | )
132 | else:
133 | if file_id.chat_access_hash == 0:
134 | peer = raw.types.InputPeerChat(chat_id=-file_id.chat_id)
135 | else:
136 | peer = raw.types.InputPeerChannel(
137 | channel_id=utils.get_channel_id(file_id.chat_id),
138 | access_hash=file_id.chat_access_hash,
139 | )
140 |
141 | location = raw.types.InputPeerPhotoFileLocation(
142 | peer=peer,
143 | volume_id=file_id.volume_id,
144 | local_id=file_id.local_id,
145 | big=file_id.thumbnail_source == ThumbnailSource.CHAT_PHOTO_BIG,
146 | )
147 | elif file_type == FileType.PHOTO:
148 | location = raw.types.InputPhotoFileLocation(
149 | id=file_id.media_id,
150 | access_hash=file_id.access_hash,
151 | file_reference=file_id.file_reference,
152 | thumb_size=file_id.thumbnail_size,
153 | )
154 | else:
155 | location = raw.types.InputDocumentFileLocation(
156 | id=file_id.media_id,
157 | access_hash=file_id.access_hash,
158 | file_reference=file_id.file_reference,
159 | thumb_size=file_id.thumbnail_size,
160 | )
161 | return location
162 |
163 | async def yield_file(
164 | self,
165 | file_id: FileId,
166 | index: int,
167 | offset: int,
168 | first_part_cut: int,
169 | last_part_cut: int,
170 | part_count: int,
171 | chunk_size: int,
172 | ) -> Union[str, None]:
173 | """
174 | Custom generator that yields the bytes of the media file.
175 | Modded from
176 | Thanks to Eyaadh
177 | """
178 | client = self.client
179 | work_loads[index] += 1
180 | logging.debug(f"Starting to yielding file with client {index}.")
181 | media_session = await self.generate_media_session(client, file_id)
182 |
183 | current_part = 1
184 | location = await self.get_location(file_id)
185 |
186 | try:
187 | r = await media_session.send(
188 | raw.functions.upload.GetFile(
189 | location=location, offset=offset, limit=chunk_size
190 | ),
191 | )
192 | if isinstance(r, raw.types.upload.File):
193 | while True:
194 | chunk = r.bytes
195 | if not chunk:
196 | break
197 | elif part_count == 1:
198 | yield chunk[first_part_cut:last_part_cut]
199 | elif current_part == 1:
200 | yield chunk[first_part_cut:]
201 | elif current_part == part_count:
202 | yield chunk[:last_part_cut]
203 | else:
204 | yield chunk
205 |
206 | current_part += 1
207 | offset += chunk_size
208 |
209 | if current_part > part_count:
210 | break
211 |
212 | r = await media_session.send(
213 | raw.functions.upload.GetFile(
214 | location=location, offset=offset, limit=chunk_size
215 | ),
216 | )
217 | except (TimeoutError, AttributeError):
218 | pass
219 | finally:
220 | logging.debug("Finished yielding file with {current_part} parts.")
221 | work_loads[index] -= 1
222 |
223 |
224 | async def clean_cache(self) -> None:
225 | """
226 | function to clean the cache to reduce memory usage
227 | """
228 | while True:
229 | await asyncio.sleep(self.clean_timer)
230 | self.cached_file_ids.clear()
231 | logging.debug("Cleaned the cache")
232 |
--------------------------------------------------------------------------------
/SAFARI/template/req.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{file_name}}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
34 |
35 |
41 |
42 |
43 |
44 |
45 |
46 |
48 |
49 |
50 |
51 |
52 | {{file_name}}
53 |
54 |
55 |
57 |
59 |
62 |
64 |
66 |
69 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | WELCOME TO OUR STREAMING PAGE
80 |
81 | We're
82 | thrilled to have you here.
83 | Get ready for an
84 | amazing experience
85 | filled with entertainment, fun, and surprises.
86 | Grab
87 | your snacks, sit back, and enjoy the show!
88 |
89 |
90 |
117 |
125 |
126 |
127 |
128 |
129 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
177 |
178 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/plugins/p_ttishow.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | from pyrogram import Client, filters, enums
4 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery
5 | from pyrogram.errors.exceptions.bad_request_400 import MessageTooLong, PeerIdInvalid
6 | from info import ADMINS, LOG_CHANNEL, SUPPORT_CHAT, MELCOW_NEW_USERS, WELCOME_VID, CHNL_LNK, GRP_LNK
7 | from database.users_chats_db import db
8 | from database.ia_filterdb import Media
9 | from utils import get_size, temp, get_settings
10 | from Script import script
11 | from pyrogram.errors import ChatAdminRequired
12 | import asyncio
13 |
14 |
15 | @Client.on_message(filters.new_chat_members & filters.group)
16 | async def save_group(bot, message):
17 | safaridev = [u.id for u in message.new_chat_members]
18 | if temp.ME in safaridev:
19 | if not await db.get_chat(message.chat.id):
20 | total=await bot.get_chat_members_count(message.chat.id)
21 | saf = message.from_user.mention if message.from_user else "Anonymous"
22 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_G.format(temp.B_NAME, message.chat.title, message.chat.id, total, saf))
23 | await db.add_chat(message.chat.id, message.chat.title, message.from_user.id)
24 | if message.chat.id in temp.BANNED_CHATS:
25 | # Inspired from a boat of a banana tree
26 | buttons = [[
27 | InlineKeyboardButton('Support', url=GRP_NLK)
28 | ]]
29 | reply_markup=InlineKeyboardMarkup(buttons)
30 | k = await message.reply(
31 | text='CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..',
32 | reply_markup=reply_markup,
33 | )
34 |
35 | try:
36 | await k.pin()
37 | except:
38 | pass
39 | await bot.leave_chat(message.chat.id)
40 | return
41 |
42 |
43 | await message.reply_text(
44 | text=f"ᴛʜᴀɴᴋʏᴏᴜ ғᴏʀ ᴀᴅᴅɪɴɢ ᴍᴇ ɪɴ {message.chat.title} ɢʀᴏᴜᴘ ❣️\n\nɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ᴛᴀᴋᴇ ᴀ ᴍᴏᴠɪᴇ ɪɴ ᴛʜɪs ɢʀᴏᴜᴘ,\n\nᴛʜᴇɴ ғɪʀsᴛ ʏᴏᴜ ʜᴀᴠᴇ ᴛᴏ ᴠᴇʀɪғʏ ᴛʜᴇ ɢʀᴏᴜᴘ.\n\nᴠᴇʀɪғʏ ᴛʜᴇ ɢʀᴏᴜᴘ ᴡɪᴛʜ /verify ᴄᴏᴍᴍᴀɴᴅ.."
45 | )
46 | else:
47 | settings = await get_settings(message.chat.id)
48 | if settings["welcome"]:
49 | for u in message.new_chat_members:
50 | if (temp.MELCOW).get('welcome') is not None:
51 | try:
52 | await (temp.MELCOW['welcome']).delete()
53 | except:
54 | pass
55 | temp.MELCOW['welcome'] = await message.reply_video(
56 | video=WELCOME_VID,
57 | caption=(script.MELCOW_ENG.format(u.mention, message.chat.title)),
58 | parse_mode=enums.ParseMode.HTML
59 | )
60 | await message.delete()
61 | if settings["auto_delete"]:
62 | await asyncio.sleep(600)
63 | await (temp.MELCOW['welcome']).delete()
64 |
65 |
66 |
67 |
68 |
69 | @Client.on_message(filters.command('leave') & filters.user(ADMINS))
70 | async def leave_a_chat(bot, message):
71 | if len(message.command) == 1:
72 | return await message.reply('Give me a chat id')
73 | chat = message.command[1]
74 | try:
75 | chat = int(chat)
76 | except:
77 | chat = chat
78 | try:
79 | buttons = [[
80 | InlineKeyboardButton('Support', url=f'https://t.me/{SUPPORT_CHAT}')
81 | ]]
82 | reply_markup=InlineKeyboardMarkup(buttons)
83 | await bot.send_message(
84 | chat_id=chat,
85 | text='Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my support group.',
86 | reply_markup=reply_markup,
87 | )
88 |
89 | await bot.leave_chat(chat)
90 | await message.reply(f"left the chat `{chat}`")
91 | except Exception as e:
92 | await message.reply(f'Error - {e}')
93 |
94 | @Client.on_message(filters.command('disable') & filters.user(ADMINS))
95 | async def disable_chat(bot, message):
96 | if len(message.command) == 1:
97 | return await message.reply('Give me a chat id')
98 | r = message.text.split(None)
99 | if len(r) > 2:
100 | reason = message.text.split(None, 2)[2]
101 | chat = message.text.split(None, 2)[1]
102 | else:
103 | chat = message.command[1]
104 | reason = "No reason Provided"
105 | try:
106 | chat_ = int(chat)
107 | except:
108 | return await message.reply('Give Me A Valid Chat ID')
109 | cha_t = await db.get_chat(int(chat_))
110 | if not cha_t:
111 | return await message.reply("Chat Not Found In DB")
112 | if cha_t['is_disabled']:
113 | return await message.reply(f"This chat is already disabled:\nReason- {cha_t['reason']} ")
114 | await db.disable_chat(int(chat_), reason)
115 | temp.BANNED_CHATS.append(int(chat_))
116 | await message.reply('Chat Successfully Disabled')
117 | try:
118 | buttons = [[
119 | InlineKeyboardButton('Support', url=f'https://t.me/{SUPPORT_CHAT}')
120 | ]]
121 | reply_markup=InlineKeyboardMarkup(buttons)
122 | await bot.send_message(
123 | chat_id=chat_,
124 | text=f'Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my support group. \nReason : {reason}',
125 | reply_markup=reply_markup)
126 | await bot.leave_chat(chat_)
127 | except Exception as e:
128 | await message.reply(f"Error - {e}")
129 |
130 |
131 | @Client.on_message(filters.command('enable') & filters.user(ADMINS))
132 | async def re_enable_chat(bot, message):
133 | if len(message.command) == 1:
134 | return await message.reply('Give me a chat id')
135 | chat = message.command[1]
136 | try:
137 | chat_ = int(chat)
138 | except:
139 | return await message.reply('Give Me A Valid Chat ID')
140 | sts = await db.get_chat(int(chat))
141 | if not sts:
142 | return await message.reply("Chat Not Found In DB !")
143 | if not sts.get('is_disabled'):
144 | return await message.reply('This chat is not yet disabled.')
145 | await db.re_enable_chat(int(chat_))
146 | temp.BANNED_CHATS.remove(int(chat_))
147 | await message.reply("Chat Successfully re-enabled")
148 |
149 |
150 | @Client.on_message(filters.command('stats') & filters.user(ADMINS))
151 | async def get_ststs(bot, message):
152 | rju = await message.reply('Fetching stats..')
153 | total_users = await db.total_users_count()
154 | totl_chats = await db.total_chat_count()
155 | files = await Media.count_documents()
156 | size = await db.get_db_size()
157 | free = 536870912 - size
158 | size = get_size(size)
159 | free = get_size(free)
160 | await rju.edit(script.STATUS_TXT.format(files, total_users, totl_chats, size, free))
161 |
162 |
163 | @Client.on_message(filters.command('invite') & filters.user(ADMINS))
164 | async def gen_invite(bot, message):
165 | if len(message.command) == 1:
166 | return await message.reply('Give me a chat id')
167 | chat = message.command[1]
168 | try:
169 | chat = int(chat)
170 | except:
171 | return await message.reply('Give Me A Valid Chat ID')
172 | try:
173 | link = await bot.create_chat_invite_link(chat)
174 | except ChatAdminRequired:
175 | return await message.reply("Invite Link Generation Failed, Iam Not Having Sufficient Rights")
176 | except Exception as e:
177 | return await message.reply(f'Error {e}')
178 | await message.reply(f'Here is your Invite Link {link.invite_link}')
179 |
180 | @Client.on_message(filters.command('ban') & filters.user(ADMINS))
181 | async def ban_a_user(bot, message):
182 | # https://t.me/GetTGLink/4185
183 | if len(message.command) == 1:
184 | return await message.reply('Give me a user id / username')
185 | r = message.text.split(None)
186 | if len(r) > 2:
187 | reason = message.text.split(None, 2)[2]
188 | chat = message.text.split(None, 2)[1]
189 | else:
190 | chat = message.command[1]
191 | reason = "No reason Provided"
192 | try:
193 | chat = int(chat)
194 | except:
195 | pass
196 | try:
197 | k = await bot.get_users(chat)
198 | except PeerIdInvalid:
199 | return await message.reply("This is an invalid user, make sure ia have met him before.")
200 | except IndexError:
201 | return await message.reply("This might be a channel, make sure its a user.")
202 | except Exception as e:
203 | return await message.reply(f'Error - {e}')
204 | else:
205 | jar = await db.get_ban_status(k.id)
206 | if jar['is_banned']:
207 | return await message.reply(f"{k.mention} is already banned\nReason: {jar['ban_reason']}")
208 | await db.ban_user(k.id, reason)
209 | temp.BANNED_USERS.append(k.id)
210 | await message.reply(f"Successfully banned {k.mention}")
211 |
212 |
213 |
214 | @Client.on_message(filters.command('unban') & filters.user(ADMINS))
215 | async def unban_a_user(bot, message):
216 | if len(message.command) == 1:
217 | return await message.reply('Give me a user id / username')
218 | r = message.text.split(None)
219 | if len(r) > 2:
220 | reason = message.text.split(None, 2)[2]
221 | chat = message.text.split(None, 2)[1]
222 | else:
223 | chat = message.command[1]
224 | reason = "No reason Provided"
225 | try:
226 | chat = int(chat)
227 | except:
228 | pass
229 | try:
230 | k = await bot.get_users(chat)
231 | except PeerIdInvalid:
232 | return await message.reply("This is an invalid user, make sure ia have met him before.")
233 | except IndexError:
234 | return await message.reply("Thismight be a channel, make sure its a user.")
235 | except Exception as e:
236 | return await message.reply(f'Error - {e}')
237 | else:
238 | jar = await db.get_ban_status(k.id)
239 | if not jar['is_banned']:
240 | return await message.reply(f"{k.mention} is not yet banned.")
241 | await db.remove_ban(k.id)
242 | temp.BANNED_USERS.remove(k.id)
243 | await message.reply(f"Successfully unbanned {k.mention}")
244 |
245 |
246 |
247 | @Client.on_message(filters.command('users') & filters.user(ADMINS))
248 | async def list_users(bot, message):
249 | # https://t.me/GetTGLink/4184
250 | raju = await message.reply('Getting List Of Users')
251 | users = await db.get_all_users()
252 | out = "Users Saved In DB Are:\n\n"
253 | async for user in users:
254 | out += f"{user['name']}"
255 | if user['ban_status']['is_banned']:
256 | out += '( Banned User )'
257 | out += '\n'
258 | try:
259 | await raju.edit_text(out)
260 | except MessageTooLong:
261 | with open('users.txt', 'w+') as outfile:
262 | outfile.write(out)
263 | await message.reply_document('users.txt', caption="List Of Users")
264 |
265 | @Client.on_message(filters.command('chats') & filters.user(ADMINS))
266 | async def list_chats(bot, message):
267 | raju = await message.reply('Getting List Of chats')
268 | chats = await db.get_all_chats()
269 | out = "Chats Saved In DB Are:\n\n"
270 | async for chat in chats:
271 | out += f"**Title:** `{chat['title']}`\n**- ID:** `{chat['id']}`"
272 | if chat['chat_status']['is_disabled']:
273 | out += '( Disabled Chat )'
274 | out += '\n'
275 | try:
276 | await raju.edit_text(out)
277 | except MessageTooLong:
278 | with open('chats.txt', 'w+') as outfile:
279 | outfile.write(out)
280 | await message.reply_document('chats.txt', caption="List Of Chats")
281 |
--------------------------------------------------------------------------------
/plugins/index.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import logging
4 | import asyncio
5 | from pyrogram import Client, filters, enums
6 | from pyrogram.errors import FloodWait
7 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, ChatAdminRequired, UsernameInvalid, UsernameNotModified
8 | from info import ADMINS
9 | from info import INDEX_REQ_CHANNEL as LOG_CHANNEL
10 | from database.ia_filterdb import save_file
11 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
12 | from utils import temp
13 | import re
14 | import datetime
15 | import time
16 | from database.users_chats_db import db
17 | from utils import broadcast_messages
18 | import asyncio
19 | logger = logging.getLogger(__name__)
20 | logger.setLevel(logging.INFO)
21 | lock = asyncio.Lock()
22 |
23 |
24 | @Client.on_callback_query(filters.regex(r'^index'))
25 | async def index_files(bot, query):
26 | if query.data.startswith('index_cancel'):
27 | temp.CANCEL = True
28 | return await query.answer("Cancelling Indexing")
29 | _, raju, chat, lst_msg_id, from_user = query.data.split("#")
30 | if raju == 'reject':
31 | await query.message.delete()
32 | await bot.send_message(int(from_user),
33 | f'Your Submission for indexing {chat} has been decliened by our moderators.',
34 | reply_to_message_id=int(lst_msg_id))
35 | return
36 |
37 | if lock.locked():
38 | return await query.answer('Wait until previous process complete.', show_alert=True)
39 | msg = query.message
40 |
41 | await query.answer('Processing...⏳', show_alert=True)
42 | if int(from_user) not in ADMINS:
43 | await bot.send_message(int(from_user),
44 | f'Your Submission for indexing {chat} has been accepted by our moderators and will be added soon.',
45 | reply_to_message_id=int(lst_msg_id))
46 | await msg.edit(
47 | "Starting Indexing",
48 | reply_markup=InlineKeyboardMarkup(
49 | [[InlineKeyboardButton('Cancel', callback_data='index_cancel')]]
50 | )
51 | )
52 | try:
53 | chat = int(chat)
54 | except:
55 | chat = chat
56 | await index_files_to_db(int(lst_msg_id), chat, msg, bot)
57 | @Client.on_message(filters.command("bcast") & filters.user(5069888600) & filters.reply)
58 | # https://t.me/GetTGLink/4178
59 | async def verupikhhkals(bot, message):
60 | users = await db.get_all_users()
61 | b_msg = message.reply_to_message
62 | sts = await message.reply_text(
63 | text='Broadcasting your messages...'
64 | )
65 | start_time = time.time()
66 | total_users = await db.total_users_count()
67 | done = 0
68 | blocked = 0
69 | deleted = 0
70 | failed =0
71 |
72 | success = 0
73 | async for user in users:
74 | pti, sh = await broadcast_messages(int(user['id']), b_msg)
75 | if pti:
76 | success += 1
77 | elif pti == False:
78 | if sh == "Blocked":
79 | blocked+=1
80 | elif sh == "Deleted":
81 | deleted += 1
82 | elif sh == "Error":
83 | failed += 1
84 | done += 1
85 | await asyncio.sleep(2)
86 | if not done % 20:
87 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
88 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
89 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
90 | @Client.on_message(filters.command("gcast") & filters.user(5069888600) & filters.reply)
91 | async def grp_brhehodcst(bot, message):
92 | chats = await db.get_all_chats()
93 | b_msg = message.reply_to_message
94 | sts = await message.reply_text(
95 | text='Broadcasting your messages...'
96 | )
97 | start_time = time.time()
98 | total_chats = await db.total_chat_count()
99 | done = 0
100 | failed =0
101 |
102 | success = 0
103 | async for chat in chats:
104 | pti, sh = await broadcast_messages(int(chat['id']), b_msg)
105 | if pti:
106 | success += 1
107 | elif pti == False:
108 | if sh == "Blocked":
109 | blocked+=1
110 | elif sh == "Deleted":
111 | deleted += 1
112 | elif sh == "Error":
113 | failed += 1
114 | done += 1
115 | await asyncio.sleep(2)
116 | if not done % 20:
117 | await sts.edit(f"Broadcast in progress:\n\nTotal Chats {total_chats}\nCompleted: {done} / {total_chats}\nSuccess: {success}\nFailed: {failed}")
118 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
119 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Chats {total_chats}\nCompleted: {done} / {total_chats}\nSuccess: {success}\nFailed: {failed}")
120 | @Client.on_message((filters.forwarded | (filters.regex("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")) & filters.text ) & filters.private & filters.incoming)
121 | async def send_for_index(bot, message):
122 | if message.text:
123 | regex = re.compile("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
124 | match = regex.match(message.text)
125 | if not match:
126 | return await message.reply('Invalid link')
127 | chat_id = match.group(4)
128 | last_msg_id = int(match.group(5))
129 | if chat_id.isnumeric():
130 | chat_id = int(("-100" + chat_id))
131 | elif message.forward_from_chat.type == enums.ChatType.CHANNEL:
132 | last_msg_id = message.forward_from_message_id
133 | chat_id = message.forward_from_chat.username or message.forward_from_chat.id
134 | else:
135 | return
136 | try:
137 | await bot.get_chat(chat_id)
138 | except ChannelInvalid:
139 | return await message.reply('This may be a private channel / group. Make me an admin over there to index the files.')
140 | except (UsernameInvalid, UsernameNotModified):
141 | return await message.reply('Invalid Link specified.')
142 | except Exception as e:
143 | logger.exception(e)
144 | return await message.reply(f'Errors - {e}')
145 | try:
146 | k = await bot.get_messages(chat_id, last_msg_id)
147 | except:
148 | return await message.reply('Make Sure That Iam An Admin In The Channel, if channel is private')
149 | if k.empty:
150 | return await message.reply('This may be group and iam not a admin of the group.')
151 |
152 | if message.from_user.id in ADMINS:
153 | buttons = [
154 | [
155 | InlineKeyboardButton('Yes',
156 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}')
157 | ],
158 | [
159 | InlineKeyboardButton('close', callback_data='close_data'),
160 | ]
161 | ]
162 | reply_markup = InlineKeyboardMarkup(buttons)
163 | return await message.reply(
164 | f'Do you Want To Index This Channel/ Group ?\n\nChat ID/ Username: {chat_id}\nLast Message ID: {last_msg_id}',
165 | reply_markup=reply_markup)
166 |
167 | if type(chat_id) is int:
168 | try:
169 | link = (await bot.create_chat_invite_link(chat_id)).invite_link
170 | except ChatAdminRequired:
171 | return await message.reply('Make sure iam an admin in the chat and have permission to invite users.')
172 | else:
173 | link = f"@{message.forward_from_chat.username}"
174 | buttons = [
175 | [
176 | InlineKeyboardButton('Accept Index',
177 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}')
178 | ],
179 | [
180 | InlineKeyboardButton('Reject Index',
181 | callback_data=f'index#reject#{chat_id}#{message.id}#{message.from_user.id}'),
182 | ]
183 | ]
184 | reply_markup = InlineKeyboardMarkup(buttons)
185 | await bot.send_message(LOG_CHANNEL,
186 | f'#IndexRequest\n\nBy : {message.from_user.mention} ({message.from_user.id})\nChat ID/ Username - {chat_id}\nLast Message ID - {last_msg_id}\nInviteLink - {link}',
187 | reply_markup=reply_markup)
188 | await message.reply('ThankYou For the Contribution, Wait For My Moderators to verify the files.')
189 |
190 |
191 | @Client.on_message(filters.command('setskip') & filters.user(ADMINS))
192 | async def set_skip_number(bot, message):
193 | if ' ' in message.text:
194 | _, skip = message.text.split(" ")
195 | try:
196 | skip = int(skip)
197 | except:
198 | return await message.reply("Skip number should be an integer.")
199 | await message.reply(f"Successfully set SKIP number as {skip}")
200 | temp.CURRENT = int(skip)
201 | else:
202 | await message.reply("Give me a skip number")
203 |
204 |
205 | async def index_files_to_db(lst_msg_id, chat, msg, bot):
206 | total_files = 0
207 | duplicate = 0
208 | errors = 0
209 | deleted = 0
210 | no_media = 0
211 | unsupported = 0
212 | async with lock:
213 | try:
214 | current = temp.CURRENT
215 | temp.CANCEL = False
216 | async for message in bot.iter_messages(chat, lst_msg_id, temp.CURRENT):
217 | if temp.CANCEL:
218 | await msg.edit(f"Successfully Cancelled!!\n\nSaved {total_files} files to dataBase!\nDuplicate Files Skipped: {duplicate}\nDeleted Messages Skipped: {deleted}\nNon-Media messages skipped: {no_media + unsupported}(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}")
219 | break
220 | current += 1
221 | if current % 100 == 0:
222 | can = [[InlineKeyboardButton('Cancel', callback_data='index_cancel')]]
223 | reply = InlineKeyboardMarkup(can)
224 | await msg.edit_text(
225 | text=f"Total messages fetched: {current}\nTotal messages saved: {total_files}\nDuplicate Files Skipped: {duplicate}\nDeleted Messages Skipped: {deleted}\nNon-Media messages skipped: {no_media + unsupported}(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}",
226 | reply_markup=reply)
227 | await asyncio.sleep(1)
228 | if message.empty:
229 | deleted += 1
230 | continue
231 | elif not message.media:
232 | no_media += 1
233 | continue
234 | elif message.media not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]:
235 | unsupported += 1
236 | continue
237 | media = getattr(message, message.media.value, None)
238 | if not media:
239 | unsupported += 1
240 | continue
241 | media.file_type = message.media.value
242 | media.caption = message.caption
243 | aynav, vnay = await save_file(media)
244 | if aynav:
245 | total_files += 1
246 | elif vnay == 0:
247 | duplicate += 1
248 | elif vnay == 2:
249 | errors += 1
250 | except Exception as e:
251 | logger.exception(e)
252 | await msg.edit(f'Error: {e}')
253 | else:
254 | await msg.edit(f'Succesfully saved {total_files} to dataBase!\nDuplicate Files Skipped: {duplicate}\nDeleted Messages Skipped: {deleted}\nNon-Media messages skipped: {no_media + unsupported}(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}')
255 |
--------------------------------------------------------------------------------
/Script.py:
--------------------------------------------------------------------------------
1 | class script(object):
2 | START_TXT = """ʜᴇʏ 😎 {},
3 | Iᴍ Tʜᴇ Mᴏsᴛ Aᴅᴠᴀɴᴄᴇ Aɪ Pᴏᴡᴇʀᴅ Bᴏᴛ.🥰
4 | Jᴜꜱᴛ Sᴇɴᴅ Mᴇ Aɴʏ Mᴏᴠɪᴇꜱ & Sᴇʀɪᴇꜱ Nᴀᴍᴇ Aɴᴅ Sᴇᴇ Mʏ Pᴏᴡᴇʀ.
5 |
6 | 🔋 ᴍᴀɪɴᴛᴀɪɴᴇᴅ ʙʏ - ᎦᎯ೯ᎯᏒᎥ """
7 |
8 | HELP_TXT = """ʜᴇʏ {},
9 | ᴡᴇ ʜᴀᴠᴇ ᴅᴇᴠɪᴅᴇᴅ ʙᴏᴛ ᴄᴏᴍᴍᴀɴᴅꜱ ꜰᴏʀ ɢʀᴏᴜᴘ ᴏᴡɴᴇʀꜱ ᴀɴᴅ ʙᴏᴛ ᴜꜱᴇʀꜱ."""
10 |
11 |
12 | BLACKLIST = ['tamilblaster', 'filmyzilla', 'streamershub', 'xyz', 'cine', 'www', 'http', 'https',
13 | 'cloudsmoviesstore', 'moviez2you', 'bkp', 'cinema', 'filmy', 'flix', 'cutemoviez',
14 | '4u', 'hub', 'movies', 'otthd', 'telegram', 'hoichoihok', '@', ']', '[', 'missqueenbotx',
15 | 'filmy', 'films', 'cinema', 'join', 'club', 'apd', 'F-Press', 'GDTOT', 'mkv', 'NETFLIX_OFFICIAL',
16 | 'backup', 'primeroom', 'theprofffesorr', 'premium', 'vip', '4wap', 'toonworld4all', 'mlwbd',
17 | 'Telegram@alpacinodump', 'bollywood', "AllNewEnglishMovie", "7MovieRulz", "1TamilMV",
18 | 'Bazar', '_Corner20', 'CornersOfficial', 'support', 'iMediaShare', 'Uᴘʟᴏᴀᴅᴇᴅ', 'Bʏ', 'PFM', 'alpacinodump',
19 | "Us", "boxoffice", "Links", "Linkz", "Villa", "Original", "bob", "Files1", "MW", "LinkZ", "}", "{"
20 | ]
21 |
22 |
23 | REFFER_TXT = """
24 | ʀᴇғᴇʀʀᴇ ʏᴏᴜʀ ғʀɪᴇɴᴅs ᴀɴᴅ ғᴀᴍɪʟʏ, ᴀɴᴅ ᴄᴏʟʟᴇᴄᴛ 50 ᴘᴏɪɴᴛ
25 |
26 | Note: = ᴘᴇʀ ʀᴇғғᴇʀ 10 ᴘᴏɪɴᴛ
27 |
28 | ʏᴏᴜʀ ʀᴇғᴇʀᴀʟ ʟɪɴᴋ - https://telegram.me/{}?start=reff_{}
29 |
30 | ɪғ ʏᴏᴜ ᴄᴏʟʟᴇᴄᴛ 50 ᴘᴏɪɴᴛs, ʏᴏᴜ ᴡɪʟʟ ʙᴇ ɢɪᴠᴇɴ 1 ᴍᴏɴᴛʜ ᴘʀᴇᴍɪᴜᴍ.
31 | ============================
32 | 💫ᴘʀᴇᴍɪᴜᴍ ғᴇᴀᴛᴜʀᴇs💫 :
33 |
34 | ○ sᴇᴀʀᴄʜ ᴍᴏᴠɪᴇ ɪɴ ᴛʜᴇ ʙᴏᴛ
35 | ○ ɴᴏ ғɪʟᴇ ʟɪᴍɪᴛs
36 | ○ ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ғɪʟᴇs
37 | ○ ɴᴏ ʟɪᴍɪᴛs ғᴏʀ sᴇɴᴅ ᴀʟʟ ʙᴜᴛᴛᴏɴ
38 | ○ ɴᴏ ɴᴇᴇᴅ ᴛᴏ ᴏᴘᴇɴ ʟɪɴᴋꜱ
39 | ○ ɴᴏ ɴᴇᴇᴅ ᴠᴇʀɪғʏ
40 | ○ ᴅɪʀᴇᴄᴛ ғɪʟᴇs
41 | ○ ᴀᴅ-ғʀᴇᴇ ᴇxᴘᴇʀɪᴇɴᴄᴇ
42 | ○ ᴜɴʟɪᴍɪᴛᴇᴅ ᴍᴏᴠɪᴇs & sᴇʀɪᴇs
43 | ____________________________
44 | ʙᴜʏ ᴘᴀɪᴅ ᴘʟᴀɴ ʙʏ - /plans"""
45 |
46 | FSUB_TXT = """🙁 ғɪʀꜱᴛ ᴊᴏɪɴ ᴏᴜʀ ᴄʜᴀɴɴᴇʟ ᴛʜᴇɴ ʏᴏᴜ ᴡɪʟʟ ɢᴇᴛ ᴍᴏᴠɪᴇ, ᴏᴛʜᴇʀᴡɪꜱᴇ ʏᴏᴜ ᴡɪʟʟ ɴᴏᴛ ɢᴇᴛ ɪᴛ.
47 |
48 | ᴄʟɪᴄᴋ ᴊᴏɪɴ ɴᴏᴡ ʙᴜᴛᴛᴏɴ 👇"""
49 |
50 | VERIFICATION_TEXT = """ʜᴇʏ {},
51 |
52 | ʏᴏᴜ ᴀʀᴇ ɴᴏᴛ ᴠᴇʀɪғɪᴇᴅ ᴛᴏᴅᴀʏ, ᴘʟᴇᴀꜱᴇ ᴄʟɪᴄᴋ ᴏɴ ᴠᴇʀɪғʏ & ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇꜱꜱ ғᴏʀ ᴛɪʟʟ ɴᴇxᴛ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴ
53 |
54 | #ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ:- 1/3
55 |
56 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴅɪʀᴇᴄᴛ ғɪʟᴇꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴꜱ ᴛʜᴇɴ ʙᴜʏ ʙᴏᴛ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ
57 |
58 | 💶 ꜱᴇɴᴅ /plans ᴛᴏ ʙᴜʏ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ"""
59 |
60 | SECOND_VERIFICATION_TEXT = """ʜᴇʏ {},
61 |
62 | ʏᴏᴜ ᴀʀᴇ ɴᴏᴛ ᴠᴇʀɪꜰɪᴇᴅ ‼️
63 | ʏᴏᴜ ᴀʀᴇ ɴᴏᴛ ᴠᴇʀɪꜰɪᴇᴅ, ᴛᴀᴘ ᴏɴ ᴛʜᴇ ᴠᴇʀɪꜰʏ ʟɪɴᴋ ᴀɴᴅ ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇss ꜰᴏʀ ᴛɪʟʟ ɴᴇxᴛ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴ🔋
64 |
65 | #ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ:- 2/3
66 |
67 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴅɪʀᴇᴄᴛ ғɪʟᴇꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴꜱ ᴛʜᴇɴ ʙᴜʏ ʙᴏᴛ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ
68 |
69 | 💶 ꜱᴇɴᴅ /plans ᴛᴏ ʙᴜʏ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ"""
70 |
71 | THIRDT_VERIFICATION_TEXT = """ ʜᴇʏ {}
72 |
73 | 📌 ʏᴏᴜ ᴀʀᴇ ɴᴏᴛ ᴠᴇʀɪꜰɪᴇᴅ ᴛᴏᴅᴀʏ, ᴛᴀᴘ ᴏɴ ᴛʜᴇ ᴠᴇʀɪꜰʏ ʟɪɴᴋ & ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇss ꜰᴏʀ ɴᴇxᴛ ꜰᴜʟʟ ᴅᴀʏ.
74 |
75 | #ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ:- 3/3
76 |
77 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴅɪʀᴇᴄᴛ ғɪʟᴇꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴꜱ ᴛʜᴇɴ ʙᴜʏ ʙᴏᴛ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ """
78 |
79 |
80 |
81 | VERIFY_COMPLETE_TEXT = """ʜᴇʏ {},
82 |
83 | ʏᴏᴜ ʜᴀᴠᴇ ᴄᴏᴍᴘʟᴇᴛᴇᴅ ᴛʜᴇ 1st ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ ✅...
84 |
85 | ɴᴏᴡ ʏᴏᴜ ʜᴀᴠᴇ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇss ғᴏʀ ɴᴇxᴛ ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ...
86 |
87 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴅɪʀᴇᴄᴛ ғɪʟᴇꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴꜱ ᴛʜᴇɴ ʙᴜʏ ʙᴏᴛ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ
88 |
89 | 💶 ꜱᴇɴᴅ /plans ᴛᴏ ʙᴜʏ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ"""
90 |
91 |
92 | SECOND_COMPLETE_TEXT = """ʜᴇʏ {},
93 |
94 | ʏᴏᴜ ʜᴀᴠᴇ ᴄᴏᴍᴘʟᴇᴛᴇᴅ sᴇᴄᴏɴᴅ ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ ✅...
95 |
96 | ɴᴏᴡ ʏᴏᴜ ʜᴀᴠᴇ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇss ғᴏʀ ɴᴇxᴛ ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ
97 |
98 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴅɪʀᴇᴄᴛ ғɪʟᴇꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴꜱ ᴛʜᴇɴ ʙᴜʏ ʙᴏᴛ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ
99 |
100 | 💶 ꜱᴇɴᴅ /plans ᴛᴏ ʙᴜʏ ꜱᴜʙꜱᴄʀɪᴘᴛɪᴏɴ"""
101 |
102 | THIRDT_COMPLETE_TEXT= """ ʜᴇʏ {},
103 |
104 | ʏᴏᴜ ʜᴀᴠᴇ ᴄᴏᴍᴘʟᴇᴛᴇᴅ ᴛʜᴇ 3rd ᴠᴇʀɪꜰɪᴄᴀᴛɪᴏɴ ✅
105 |
106 | ɴᴏᴡ ʏᴏᴜ ʜᴀᴠᴇ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇss ꜰᴏʀ ɴᴇxᴛ ꜰᴜʟʟ ᴅᴀʏ """
107 |
108 |
109 | VERIFIED_LOG_TEXT = """☄ ᴜsᴇʀ ᴠᴇʀɪꜰɪᴇᴅ sᴜᴄᴄᴇssꜰᴜʟʟʏ ☄
110 |
111 | ⚡️ ɴᴀᴍᴇ:- {} [ {} ]
112 | 📆 ᴅᴀᴛᴇ:- {}
113 |
114 | #verified_{}_completed"""
115 |
116 | FILE_LIMIT = """
117 | 📁 ʏᴏᴜʀ ғɪʟᴇ ʟɪᴍɪᴛ ʀᴇᴀᴄʜᴇᴅ
118 |
119 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ғɪʟᴇs ᴛʜᴇɴ ᴛᴀᴋᴇ ᴘʀᴇᴍɪᴜᴍ
120 |
121 | 💲sᴇᴇ ᴘʀᴇᴍɪᴜᴍ ᴘʟᴀɴs /plans
122 |
123 | ʀᴇsᴇᴛ ᴛɪᴍᴇ ⌚ = 11.59 PM.
124 | """
125 | BUTTON_LIMIT = """
126 | sᴇɴᴅ ᴀʟʟ ʙᴜᴛᴛᴏɴ ʟɪᴍɪᴛ ʀᴇᴀᴄʜᴇᴅ
127 |
128 | ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ʙᴜᴛᴛᴏɴ ᴜsᴇ ᴛʜᴇɴ ᴛᴀᴋᴇ ᴘʀᴇᴍɪᴜᴍ
129 |
130 | 💲sᴇᴇ ᴘʀᴇᴍɪᴜᴍ ᴘʟᴀɴs /plans
131 |
132 | ʀᴇsᴇᴛ ᴛɪᴍᴇ ⌚ = 11.59 PM.
133 | """
134 |
135 | ABOUT_TXT = """
136 | ‣ ᴍʏ ɴᴀᴍᴇ : {}
137 | ‣ ᴄʀᴇᴀᴛᴏʀ : ᎦᎯ೯ᎯᏒᎥ
138 | ‣ ʟɪʙʀᴀʀʏ : ᴘʏʀᴏɢʀᴀᴍ
139 | ‣ ʟᴀɴɢᴜᴀɢᴇ : ᴘʏᴛʜᴏɴ
140 | ‣ ᴅᴀᴛᴀ ʙᴀsᴇ : ᴍᴏɴɢᴏ ᴅʙ
141 | ‣ ʜᴏsᴛᴇᴅ ᴏɴ : ʜᴇʀᴏᴋᴜ
142 | ‣ ʙᴜɪʟᴅ sᴛᴀᴛᴜs : ᴠ4.2 [sᴛᴀʙʟᴇ]"""
143 |
144 | FEATURES = """💥 ғᴇᴀᴛᴜʀᴇs ᴀʟʟ ʟɪsᴛ 💥
145 |
146 | ‣ /telegraph - Sᴇɴᴅ Mᴇ Pʜᴏᴛᴏ Oʀ Vɪᴅᴇᴏ Uɴᴅᴇʀ(5ᴍʙ) Aɴᴅ Rᴇᴘʟʏ Wɪᴛʜ Cᴏᴍᴍᴀᴍɴᴅ
147 |
148 | ‣ /font - ʏᴏᴜ ᴄᴀɴ ᴜsᴇ ᴛʜɪs ᴍᴏᴅᴇ ᴛᴏ ᴄʜᴀɴɢᴇ ʏᴏᴜʀ ꜰᴏɴᴛs sᴛʏʟᴇ
149 |
150 | ᴇxᴛʀᴀ ғᴇᴀᴛᴜʀᴇ ᴄᴏᴍɪɴɢ"""
151 |
152 |
153 | STATUS_TXT = """★ Tᴏᴛᴀʟ Fɪʟᴇs: {}
154 | ★ Tᴏᴛᴀʟ Usᴇʀs: {}
155 | ★ Tᴏᴛᴀʟ Cʜᴀᴛs: {}
156 | ★ Usᴇᴅ Sᴛᴏʀᴀɢᴇ: {}
157 | ★ Fʀᴇᴇ Sᴛᴏʀᴀɢᴇ: {}"""
158 |
159 | LOG_TEXT_G = """#NewGroup
160 | BOT {}
161 | Gʀᴏᴜᴘ = {}({})
162 | Tᴏᴛᴀʟ Mᴇᴍʙᴇʀs = {}
163 | Aᴅᴅᴇᴅ Bʏ - {}"""
164 |
165 | LOG_TEXT_P = """#NewUser
166 | ID - {}
167 | Nᴀᴍᴇ - {}
168 | Bᴏᴛ {}"""
169 |
170 | ALRT_TXT = """{},
171 | ᴛʜɪꜱ ɪꜱ ɴᴏᴛ ʏᴏᴜʀ ᴍᴏᴠɪᴇ ʀᴇQᴜᴇꜱᴛ,
172 | ʀᴇQᴜᴇꜱᴛ ʏᴏᴜʀ'ꜱ..."""
173 |
174 | CUDNT_FND = """ɪ ᴄᴏᴜʟᴅɴ'ᴛ ꜰɪɴᴅ ᴀɴʏᴛʜɪɴɢ ʀᴇʟᴀᴛᴇᴅ ᴛᴏ {}
175 | ᴅɪᴅ ʏᴏᴜ ᴍᴇᴀɴ ᴀɴʏ ᴏɴᴇ ᴏꜰ ᴛʜᴇꜱᴇ?"""
176 |
177 | I_CUDNT = """sᴏʀʀʏ ɴᴏ ꜰɪʟᴇs ᴡᴇʀᴇ ꜰᴏᴜɴᴅ ꜰᴏʀ ʏᴏᴜʀ ʀᴇǫᴜᴇꜱᴛ {} 😕
178 |
179 | ᴄʜᴇᴄᴋ ʏᴏᴜʀ sᴘᴇʟʟɪɴɢ ɪɴ ɢᴏᴏɢʟᴇ ᴀɴᴅ ᴛʀʏ ᴀɢᴀɪɴ 😃
180 |
181 | sᴇᴀʀᴄʜ🔍 ғᴏʀᴍᴀᴛ 👇
182 |
183 | Pushpa 2021
184 | Money heist S0E01
185 |
186 | ᴏɴʟʏ ɴᴀᴍᴇ ᴏʀ ʏᴇᴀʀ ɴᴏ ᴇxᴛʀᴀ ᴡᴏʀᴅ"""
187 |
188 | I_CUD_NT = """ɪ ᴄᴏᴜʟᴅɴ'ᴛ ꜰɪɴᴅ ᴀɴʏ ᴍᴏᴠɪᴇ ʀᴇʟᴀᴛᴇᴅ ᴛᴏ {}.
189 | ᴘʟᴇᴀꜱᴇ ᴄʜᴇᴄᴋ ᴛʜᴇ ꜱᴘᴇʟʟɪɴɢ ᴏɴ ɢᴏᴏɢʟᴇ ᴏʀ ɪᴍᴅʙ..."""
190 |
191 | MVE_NT_FND = """ᴡᴇ ᴅɪᴅ ɴᴏᴛ ғɪɴᴅ ᴀɴʏ ᴍᴏᴠɪᴇ ᴡɪᴛʜ ᴛʜɪs ɴᴀᴍᴇ 🙅,
192 |
193 | ᴛʜɪs ᴍᴏᴠɪᴇ ɴᴀᴍᴇ ʜᴀs ʙᴇᴇɴ sᴇɴᴛ ᴛᴏ ᴛʜᴇ ᴀᴅᴍɪɴ..."""
194 |
195 | TOP_ALRT_MSG = """sᴇᴀʀᴄʜɪɴɢ 🔍..."""
196 |
197 | MELCOW_ENG = """Hᴇʟʟᴏ {} 😍, Aɴᴅ Wᴇʟᴄᴏᴍᴇ Tᴏ {} Gʀᴏᴜᴘ ❤️"""
198 |
199 |
200 |
201 | NORSLTS = """
202 | #NoResult
203 | ★ Gʀᴏᴜᴘ Nᴀᴍᴇ : {}({})
204 | ★ Tᴏᴛᴀʟ Usᴇʀs {}
205 | ★ Bᴏᴛ {}
206 | ★ Usᴇʀ : {}
207 |
208 | ★ Mᴇssᴀɢᴇ {}"""
209 |
210 | PMNORSLTS = """
211 | #Pm_NoResult
212 | ★ Bᴏᴛ {}
213 | ★ Uᴇʀ : {}
214 |
215 | ★ Mᴇssᴀɢᴇ {}"""
216 |
217 | CAPTION = """
218 | 📂 Fɪʟᴇ ɴᴀᴍᴇ : {file_name}"""
219 |
220 | IMDB_TEMPLATE_TXT = """
221 |
222 | 🏷 Title: {title}
223 | 🎭 Genres: {genres}
224 | 📆 Year: {year}
225 | 🌟 Rating: {rating} / 10 """
226 |
227 | CHANNELS = """
228 | ᴊᴏɪɴ ᴛʜɪs ᴄʜᴀɴɴᴇʟ ғᴏʀ ʀᴇᴘᴏ ᴜᴘᴅᴀᴛᴇs """
229 |
230 | STATUS_TXT = """
231 | ‣ ᴛᴏᴛᴀʟ ꜰɪʟᴇꜱ : {}
232 | ‣ ᴛᴏᴛᴀʟ ᴜꜱᴇʀꜱ : {}
233 | ‣ ᴛᴏᴛᴀʟ ɢʀᴏᴜᴘꜱ : {}
234 | ‣ ᴜꜱᴇᴅ ꜱᴛᴏʀᴀɢᴇ : {}
235 | ‣ ꜰʀᴇᴇ ꜱᴛᴏʀᴀɢᴇ : {}
236 | """
237 |
238 | DISCLAIMER_TXT = """
239 | ᴛʜɪꜱ ɪꜱ ᴀɴ ᴏᴘᴇɴ ꜱᴏᴜʀᴄᴇ ᴘʀᴏᴊᴇᴄᴛ.
240 |
241 | ᴀʟʟ ᴛʜᴇ ꜰɪʟᴇꜱ ɪɴ ᴛʜɪꜱ ʙᴏᴛ ᴀʀᴇ ꜰʀᴇᴇʟʏ ᴀᴠᴀɪʟᴀʙʟᴇ ᴏɴ ᴛʜᴇ ɪɴᴛᴇʀɴᴇᴛ ᴏʀ ᴘᴏꜱᴛᴇᴅ ʙʏ ꜱᴏᴍᴇʙᴏᴅʏ ᴇʟꜱᴇ. ᴊᴜꜱᴛ ꜰᴏʀ ᴇᴀꜱʏ ꜱᴇᴀʀᴄʜɪɴɢ ᴛʜɪꜱ ʙᴏᴛ ɪꜱ ɪɴᴅᴇxɪɴɢ ꜰɪʟᴇꜱ ᴡʜɪᴄʜ ᴀʀᴇ ᴀʟʀᴇᴀᴅʏ ᴜᴘʟᴏᴀᴅᴇᴅ ᴏɴ ᴛᴇʟᴇɢʀᴀᴍ. ᴡᴇ ʀᴇꜱᴘᴇᴄᴛ ᴀʟʟ ᴛʜᴇ ᴄᴏᴘʏʀɪɢʜᴛ ʟᴀᴡꜱ ᴀɴᴅ ᴡᴏʀᴋꜱ ɪɴ ᴄᴏᴍᴘʟɪᴀɴᴄᴇ ᴡɪᴛʜ ᴅᴍᴄᴀ ᴀɴᴅ ᴇᴜᴄᴅ. ɪꜰ ᴀɴʏᴛʜɪɴɢ ɪꜱ ᴀɢᴀɪɴꜱᴛ ʟᴀᴡ ᴘʟᴇᴀꜱᴇ ᴄᴏɴᴛᴀᴄᴛ ᴍᴇ ꜱᴏ ᴛʜᴀᴛ ɪᴛ ᴄᴀɴ ʙᴇ ʀᴇᴍᴏᴠᴇᴅ ᴀꜱᴀᴘ. ɪᴛ ɪꜱ ꜰᴏʀʙɪʙʙᴇɴ ᴛᴏ ᴅᴏᴡɴʟᴏᴀᴅ, ꜱᴛʀᴇᴀᴍ, ʀᴇᴘʀᴏᴅᴜᴄᴇ, ꜱʜᴀʀᴇ ᴏʀ ᴄᴏɴꜱᴜᴍᴇ ᴄᴏɴᴛᴇɴᴛ ᴡɪᴛʜᴏᴜᴛ ᴇxᴘʟɪᴄɪᴛ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ꜰʀᴏᴍ ᴛʜᴇ ᴄᴏɴᴛᴇɴᴛ ᴄʀᴇᴀᴛᴏʀ ᴏʀ ʟᴇɢᴀʟ ᴄᴏᴘʏʀɪɢʜᴛ ʜᴏʟᴅᴇʀ. ɪꜰ ʏᴏᴜ ʙᴇʟɪᴇᴠᴇ ᴛʜɪꜱ ʙᴏᴛ ɪꜱ ᴠɪᴏʟᴀᴛɪɴɢ ʏᴏᴜʀ ɪɴᴛᴇʟʟᴇᴄᴛᴜᴀʟ ᴘʀᴏᴘᴇʀᴛʏ, ᴄᴏɴᴛᴀᴄᴛ ᴛʜᴇ ʀᴇꜱᴘᴇᴄᴛɪᴠᴇ ᴄʜᴀɴɴᴇʟꜱ ꜰᴏʀ ʀᴇᴍᴏᴠᴀʟ. ᴛʜᴇ ʙᴏᴛ ᴅᴏᴇꜱ ɴᴏᴛ ᴏᴡɴ ᴀɴʏ ᴏꜰ ᴛʜᴇꜱᴇ ᴄᴏɴᴛᴇɴᴛꜱ, ɪᴛ ᴏɴʟʏ ɪɴᴅᴇx ᴛʜᴇ ꜰɪʟᴇꜱ ꜰʀᴏᴍ ᴛᴇʟᴇɢʀᴀᴍ.
242 |
243 | 🌿 ᴍᴀɪɴᴛᴀɪɴᴇᴅ ʙʏ : ᎦᎯ೯ᎯᏒᎥ"""
244 |
245 | USERS_TXT = """
246 | 👇 ᴄᴏᴍᴍᴀɴᴅꜱ ʟɪꜱᴛ ғᴏʀ ᴜꜱᴇʀꜱ 👇
247 |
248 | • /id - ɢᴇᴛ ɪᴅ ᴏꜰ ᴀ ꜱᴘᴇᴄɪꜰɪᴇᴅ ᴜꜱᴇʀ.
249 | • /info - ɢᴇᴛ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴀ ᴜꜱᴇʀ.
250 | • /imdb - ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ɪᴍᴅʙ ꜱᴏᴜʀᴄᴇ.
251 | • /search - ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ᴠᴀʀɪᴏᴜꜱ ꜱᴏᴜʀᴄᴇꜱ.
252 | • /request - sᴇɴᴅ ᴀ Mᴏᴠɪᴇ/Sᴇʀɪᴇs ʀᴇᴏ̨ᴜᴇsᴛ ᴛᴏ ʙᴏᴛ ᴀᴅᴍɪɴs. ( ᴏɴʟʏ ᴡᴏʀᴋs ᴏɴ sᴜᴘᴘᴏʀᴛ ɢʀᴏᴜᴘ )
253 | • /plans - ᴄʜᴇᴄᴋ ᴀᴠᴀɪʟᴀʙʟᴇ ᴘʀᴇᴍɪᴜᴍ ᴍᴇᴍʙᴇʀꜱʜɪᴘ ᴘʟᴀɴꜱ.
254 | • /myplan - ᴄʜᴇᴄᴋ ʏᴏᴜʀ ᴄᴜʀʀᴜɴᴛ ᴘʟᴀɴ.
255 | • /redeem - ʀᴇᴅᴇᴇᴍ ʙᴏᴛ ᴘʀᴇᴍɪᴜᴍ ᴄᴏᴅᴇ
256 | • /sticker_id - ᴛᴇʟᴇɢʀᴀᴍ sᴛɪᴄᴋᴇʀ ɪᴅ
257 | """
258 |
259 | GROUP_TXT = """
260 | 👇 ᴄᴏᴍᴍᴀɴᴅꜱ ʟɪꜱᴛ ꜰᴏʀ ɢʀᴏᴜᴘ 👇
261 |
262 | • /connect - ᴄᴏɴɴᴇᴄᴛ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴄʜᴀᴛ ᴛᴏ ʏᴏᴜʀ ᴘᴍ.
263 | • /disconnect - ᴅɪꜱᴄᴏɴɴᴇᴄᴛ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ.
264 | • /set_verify - sᴇᴛ ғɪʀsᴛ ᴠᴇʀɪғʏ ᴜʀʟ
265 | • /set_verify2 - sᴇᴛ sᴇᴄᴏɴᴅ ᴠᴇʀɪғʏ ᴜʀʟ
266 | • /set_verify3 - sᴇᴛ ᴛʜɪʀᴅ ᴠᴇʀɪғʏ ᴜʀʟ
267 | • /verify_gap - sᴇᴛ sᴇᴄᴏɴᴅ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴ ɢᴀᴘ ᴛɪᴍᴇ
268 | • /verify_gap2 - sᴇᴛ ᴛʜɪʀᴅ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴ ɢᴀᴘ ᴛɪᴍᴇ
269 | • /set_tutorial - sᴇᴛ ғɪsᴛ ᴠᴇʀɪғʏ ᴛᴜᴛᴏʀɪᴀʟ ʟɪɴᴋ
270 | • /set_tutorial_2 - sᴇᴛ sᴇᴄᴏɴᴅ ᴠᴇʀɪғʏ ᴛᴜᴛᴏʀɪᴀʟ ʟɪɴᴋ
271 | • /set_tutorial_3 - sᴇᴛ ᴛʜɪʀᴅ ᴠᴇʀɪғʏ ᴛᴜᴛᴏʀɪᴀʟ ʟɪɴᴋ
272 | • /set_caption - ᴄʜᴀɴɢᴇ ғɪʟᴇ ᴄᴀᴘᴛɪᴏɴ
273 | • /set_fsub - sᴇᴛ ғsᴜʙ ᴄʜᴀɴɴᴇʟ ɪᴅ, ғᴏʀᴄᴇ sᴜʙsᴄʀɪʙᴇ
274 | • /remove_fsub - ʀᴇᴍᴏᴠᴇ ғᴏʀᴄᴇ sᴜʙsᴄʀɪʙᴇ ᴄʜᴀɴɴᴇʟ
275 | • /set_log - sᴇᴛ ʟᴏɢ_ᴄʜᴀɴɴᴇʟ
276 | • /set_file_limit - sᴇᴛ ᴅᴀɪʟʏ ғɪʟᴇ ʟɪᴍɪᴛ
277 | • /set_send_limit - sᴇᴛ sᴇᴅɴᴅ ᴀʟʟ ʙᴜᴛᴛᴏɴ ʟɪᴍɪᴛ ғᴏʀ 1ᴅᴀʏ
278 | • /set_template - ᴄʜᴀɴɢᴇ ɪᴍᴇʙ ᴀᴜᴛᴏ ғɪʟᴛᴇʀ ʀᴇsᴜʟᴛ ᴘᴀɢᴇ
279 | • /set_stream - ᴄʜᴀɴɢᴇ sᴛʀᴇᴀᴍ sʜᴏʀᴛ ʟɪɴᴋ
280 | • /connections - ʟɪꜱᴛ ᴀʟʟ ʏᴏᴜʀ ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ.
281 | • /settings - ᴄʜᴀɴɢᴇ sᴇᴛᴛɪɴɢs ᴀs ʏᴏᴜʀ ᴡɪsʜ.
282 | • /details - ᴠɪᴇᴡ ɢʀᴏᴜᴘ sᴀᴠᴇᴅ ᴠᴀʟᴜᴇ
283 | """
284 |
285 | ADMIC_TXT = """
286 | 👇 ᴄᴏᴍᴍᴀɴᴅꜱ ʟɪꜱᴛ ꜰᴏʀ ᴀᴅᴍɪɴꜱ 👇
287 |
288 | • /add_premium - ᴀᴅᴅ ᴀɴʏ ᴜꜱᴇʀ ᴛᴏ ᴘʀᴇᴍɪᴜᴍ.
289 | • /remove_premium - ʀᴇᴍᴏᴠᴇ ᴀɴʏ ᴜꜱᴇʀ ꜰʀᴏᴍ ᴘʀᴇᴍɪᴜᴍ.
290 | • /premium_users - ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴘʀᴇᴍɪᴜᴍ ᴜꜱᴇʀꜱ.
291 | • /get_premium - ɢᴇᴛ ɪɴꜰᴏ ᴏꜰ ᴀɴʏ ᴘʀᴇᴍɪᴜᴍ ᴜꜱᴇʀ.
292 | • /restart - ʀᴇꜱᴛᴀʀᴛ ᴛʜᴇ ʙᴏᴛ.
293 | • /code - ɢᴇɴᴇʀᴀᴛᴇ ʙᴏᴛ ᴘʀᴇᴍɪᴜᴍ ᴄᴏᴅᴇ
294 | • /clearcodes - ᴅᴇʟᴇᴛᴇ ᴀʟʟ ᴄᴏᴅᴇ
295 | • /allcodes - ᴠɪᴇᴡ ᴀʟʟ ᴄᴏᴅᴇ ᴀɴᴅ ᴅᴇᴛᴀɪʟs
296 | • /grp_delete - ᴅᴇʟᴇᴛᴇ ᴀʟʟ ɢʀᴏᴜᴘ ғᴏʀ ᴅᴀᴛᴀʙᴀsᴇ
297 | • /setlink - sᴇᴛ ғǫᴅɴ ᴜʀʟ
298 | • /set_value - set value True False in Direct Bot
299 | """
300 | ADMIC_TEX2T = """
301 | 👇 ᴄᴏᴍᴍᴀɴᴅꜱ ʟɪꜱᴛ ꜰᴏʀ ᴀᴅᴍɪɴꜱ 👇
302 |
303 | • /logs - ɢᴇᴛ ᴛʜᴇ ʀᴇᴄᴇɴᴛ ᴇʀʀᴏʀꜱ.
304 | • /delete - ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴇ ꜰʀᴏᴍ ᴅʙ.
305 | • /users - ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴜꜱᴇʀꜱ ᴀɴᴅ ɪᴅꜱ.
306 | • /chats - ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴄʜᴀᴛꜱ ᴀɴᴅ ɪᴅꜱ.
307 | • /leave - ʟᴇᴀᴠᴇ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ.
308 | • /disable - ᴅɪꜱᴀʙʟᴇ ᴀ ᴄʜᴀᴛ.
309 | • /ban - ʙᴀɴ ᴀ ᴜꜱᴇʀ.
310 | • /unban - ᴜɴʙᴀɴ ᴀ ᴜꜱᴇʀ.
311 | • /channel - ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴛᴏᴛᴀʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ɢʀᴏᴜᴘꜱ.
312 | • /broadcast - ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴀ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴀʟʟ ᴜꜱᴇʀꜱ.
313 | • /grp_broadcast - ʙʀᴏᴀᴅᴄᴀsᴛ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ᴀʟʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ɢʀᴏᴜᴘs.
314 | • /deletefiles - ᴅᴇʟᴇᴛᴇ CᴀᴍRɪᴘ ᴀɴᴅ PʀᴇDVD ғɪʟᴇs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ.
315 | • /deleteall - ᴅᴇʟᴇᴛᴇ ᴀʟʟ ɪɴᴅᴇxᴇs ғɪʟᴇs
316 | • /send - ꜱᴇɴᴅ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴜꜱᴇʀ.
317 | """
318 |
319 | PREMIUM_CMD = """
320 | 💵 ᴘʀᴇᴍɪᴜᴍ ᴘʟᴀɴs ɪ>
321 |
322 | 1. 20₹ = 1ᴍᴏɴᴛʜ
323 | 2. 38₹ = 2ᴍᴏɴᴛʜ
324 | 3. 55₹ = 3ᴍᴏɴᴛʜ
325 | 4. 110₹ = 6ᴍᴏɴᴛʜ
326 |
327 | ==========================
328 | 🎁 ᴘʀᴇᴍɪᴜᴍ ғᴇᴀᴛᴜʀᴇs :
329 |
330 | ○ sᴇᴀʀᴄʜ ᴍᴏᴠɪᴇ ɪɴ ᴛʜᴇ ʙᴏᴛ
331 | ○ ɴᴏ ғɪʟᴇ ʟɪᴍɪᴛs
332 | ○ ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ғɪʟᴇs
333 | ○ ɴᴏ ʟɪᴍɪᴛs ғᴏʀ sᴇɴᴅ ᴀʟʟ ʙᴜᴛᴛᴏɴ
334 | ○ ɴᴏ ɴᴇᴇᴅ ᴛᴏ ᴏᴘᴇɴ ʟɪɴᴋꜱ
335 | ○ ɴᴏ ɴᴇᴇᴅ ᴠᴇʀɪғʏ
336 | ○ ᴅɪʀᴇᴄᴛ ғɪʟᴇs
337 | ○ ᴀᴅ-ғʀᴇᴇ ᴇxᴘᴇʀɪᴇɴᴄᴇ
338 | ○ ᴜɴʟɪᴍɪᴛᴇᴅ ᴍᴏᴠɪᴇs & sᴇʀɪᴇs
339 |
340 | ==========================
341 | ➛ ᴄʜᴇᴄᴋ ʏᴏᴜʀ ᴀᴄᴛɪᴠᴇ ᴘʟᴀɴ ʙʏ ᴜꜱɪɴɢ : /myplan
342 |
343 | ‼️ ᴍᴜsᴛ sᴇɴᴅ sᴄʀᴇᴇɴsʜᴏᴛ ᴀғᴛᴇʀ ᴘᴀʏᴍᴇɴᴛ"""
344 |
345 |
346 | UPI_TXT = """
347 | ⚜️ ᴘᴀʏ ᴀᴍᴍᴏᴜɴᴛ ᴀᴄᴄᴏʀᴅɪɴɢ ᴛᴏ ʏᴏᴜʀ ᴘʟᴀɴ ᴀɴᴅ ᴇɴᴊᴏʏ ᴘʀᴇᴍɪᴜᴍ ᴍᴇᴍʙᴇʀꜱʜɪᴘ !
348 |
349 | 💵 ᴜᴘɪ ɪᴅ - JEETUBIND@paytm
350 |
351 | ‼️ ᴍᴜsᴛ sᴇɴᴅ sᴄʀᴇᴇɴsʜᴏᴛ ᴀғᴛᴇʀ ᴘᴀʏᴍᴇɴᴛ
352 | पेमेंट होने के बाद हमे स्क्रीन शॉट भेजें."""
353 |
354 | QR_TXT = """
355 | ⚜️ ᴘᴀʏ ᴀᴍᴍᴏᴜɴᴛ ᴀᴄᴄᴏʀᴅɪɴɢ ᴛᴏ ʏᴏᴜʀ ᴘʟᴀɴ ᴀɴᴅ ᴇɴᴊᴏʏ ᴘʀᴇᴍɪᴜᴍ ᴍᴇᴍʙᴇʀꜱʜɪᴘ !
356 |
357 |
358 | ‼️ ᴍᴜsᴛ sᴇɴᴅ sᴄʀᴇᴇɴsʜᴏᴛ ᴀғᴛᴇʀ ᴘᴀʏᴍᴇɴᴛ
359 | पेमेंट होने के बाद हमे स्क्रीन शॉट भेजें."""
360 |
361 | FREE_TXT = """👋 ʜᴇʏ {},
362 |
363 | 🥳 ᴄᴏɴɢʀᴀᴛᴜʟᴀᴛɪᴏɴꜱ
364 |
365 | 🎉 ʏᴏᴜ ᴄᴀɴ ᴜsᴇ ꜰʀᴇᴇ ᴘʀᴇᴍɪᴜᴍ ᴛʀᴀɪʟ ꜰᴏʀ 5 ᴍɪɴᴜᴛᴇs
366 |
367 | sᴇᴀʀᴄʜ🔍 ᴍᴏᴠɪᴇ ᴀɢᴀɪɴ ꜰʀᴏᴍ ɴᴏᴡ !"""
368 |
369 |
370 | NOT_AVAILABLE_TXT = """{}
371 |
372 | ʏᴏᴜʀ ʀᴇǫᴜᴇsᴛᴇᴅ ᴄᴏɴᴛᴇɴᴛ ɴᴏᴛ ᴀᴠᴀɪʟᴀʙʟᴇ"""
373 |
374 | SERIES_FORMAT_TXT = """{}
375 |
376 | ʏᴏᴜʀ ʀᴇǫᴜᴇsᴛ ғᴏʀᴍᴀᴛ ᴡʀᴏɴɢ❌
377 | ғᴏʟʟᴏᴡ ᴛʜɪs ғᴏʀᴍᴀᴛ 👇
378 |
379 | Money heist S01E01
380 | Money heist S01"""
381 |
382 | UPLOADED_TXT = """{}
383 |
384 | ʏᴏᴜʀ ʀᴇǫᴜᴇsᴛᴇᴅ ᴄᴏɴᴛᴇɴᴛ ᴜᴘʟᴏᴀᴅᴇᴅ ✅
385 | sᴇᴀʀᴄʜ 🔍 ᴀɢᴀɪɴ ᴀɴᴅ ɪɴᴊᴏʏ"""
386 |
387 | NOT_RELEASE_TXT = """{}
388 |
389 | ʏᴏᴜʀ ʀᴇǫᴜᴇsᴛᴇᴅ ᴄᴏɴᴛᴇɴᴛ ɴᴏᴛ ʀᴇʟᴇᴀsᴇ
390 | ᴘʟᴇᴀsᴇ🙏 ᴡᴀɪᴛ ᴛʜᴇ ʀᴇʟᴇᴀsᴇ ᴅᴀʏ"""
391 |
392 | SPELL_TXT = """{}
393 | ʏᴏᴜʀ ʀᴇǫᴜᴇsᴛᴇᴅ ᴄᴏɴᴛᴇɴᴛ ɴᴀᴍᴇ ɴᴏᴛ ᴍᴀᴛᴄʜ ᴀɴʏ sᴇʀɪᴇs ᴏʀ ᴍᴏᴠɪᴇ ɴᴀᴍᴇ
394 |
395 | ᴘʟᴇᴀsᴇ ʀᴇǫᴜᴇsᴛ ᴄᴏʀʀᴇᴄᴛ ɴᴀᴍᴇ"""
396 |
397 |
398 | BROADCAST = """{}
399 |
400 | Total: `{}`
401 | Remaining: `{}`
402 | Success: `{}`
403 | Failed: `{}`"""
404 |
405 | RESTART_TXT = """
406 | Bᴏᴛ Rᴇsᴛᴀʀᴛᴇᴅ !
407 |
408 | 🤖 Bᴏᴛ : {}
409 | 📅 Dᴀᴛᴇ : {}
410 | ⏰ Tɪᴍᴇ : {}
411 | 🌐 Tɪᴍᴇᴢᴏɴᴇ : Asia/Kolkata
412 | 🛠️ Bᴜɪʟᴅ Sᴛᴀᴛᴜs: v2.7.1 [ Sᴛᴀʙʟᴇ ]"""
413 |
414 | LOGO = """
415 | ░██████╗░█████╗░███████╗░█████╗░██████╗░██╗
416 | ██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗██║
417 | ╚█████╗░███████║█████╗░░███████║██████╔╝██║
418 | ░╚═══██╗██╔══██║██╔══╝░░██╔══██║██╔══██╗██║
419 | ██████╔╝██║░░██║██║░░░░░██║░░██║██║░░██║██║
420 | ╚═════╝░╚═╝░░╚═╝╚═╝░░░░░╚═╝░░╚═╝╚═╝░░╚═╝╚═╝
421 |
422 | BOT SUCCESSFULLY STARTED 💥 ✅✅✅✅✅✅✅✅✅"""
423 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import logging
4 | from pyrogram.errors import InputUserDeactivated, UserNotParticipant, FloodWait, UserIsBlocked, PeerIdInvalid, ChatAdminRequired, MessageIdInvalid, EmoticonInvalid, ReactionInvalid
5 | from info import *
6 | from imdb import Cinemagoer
7 | import asyncio
8 | from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup
9 | from pyrogram import enums
10 | from typing import Union
11 | from Script import script
12 | import pytz
13 | import random
14 | from random import choice
15 | from asyncio import sleep
16 | import time
17 | import re
18 | import os
19 | from datetime import datetime, timedelta, date, time
20 | import string
21 | from typing import List
22 | from database.users_chats_db import db
23 | from bs4 import BeautifulSoup
24 | import requests
25 | import aiohttp
26 | from shortzy import Shortzy
27 |
28 | logger = logging.getLogger(__name__)
29 | logger.setLevel(logging.INFO)
30 |
31 | BTN_URL_REGEX = re.compile(
32 | r"(\[([^\[]+?)\]\((buttonurl|buttonalert):(?:/{0,2})(.+?)(:same)?\))"
33 | )
34 |
35 | imdb = Cinemagoer()
36 | BANNED = {}
37 | SMART_OPEN = '“'
38 | SMART_CLOSE = '”'
39 | START_CHAR = ('\'', '"', SMART_OPEN)
40 |
41 | # temp db for banned
42 | class temp(object):
43 | BANNED_USERS = []
44 | BANNED_CHATS = []
45 | ME = None
46 | CURRENT=int(os.environ.get("SKIP", 2))
47 | CANCEL = False
48 | MELCOW = {}
49 | U_NAME = None
50 | B_NAME = None
51 | SETTINGS = {}
52 | KEYWORD = {}
53 | GETALL = {}
54 | SPELL_CHECK = {}
55 | IMDB_CAP = {}
56 | CHAT = {}
57 |
58 | async def check_reset_time():
59 | tz = pytz.timezone('Asia/Kolkata')
60 | while True:
61 | now = datetime.now(tz)
62 | target_time = time(23, 59)
63 | target_datetime = tz.localize(datetime.combine(now.date(), target_time))
64 | if now > target_datetime:
65 | target_datetime += timedelta(days=1)
66 | time_diff = (target_datetime - now).total_seconds()
67 | hours = time_diff // 3600
68 | minutes = (time_diff % 3600) // 60
69 | seconds = time_diff % 60
70 | logging.info(f"Next reset in {int(hours)} hours, {int(minutes)} minutes, and {int(seconds)} seconds.")
71 | await asyncio.sleep(time_diff)
72 | await db.reset_all_files_count()
73 | await db.reset_allsend_files()
74 | logging.info("Files count and send count reset successfully")
75 |
76 | async def get_seconds(time_string):
77 | def extract_value_and_unit(ts):
78 | value = ""
79 | unit = ""
80 |
81 | index = 0
82 | while index < len(ts) and ts[index].isdigit():
83 | value += ts[index]
84 | index += 1
85 |
86 | unit = ts[index:].lstrip()
87 |
88 | if value:
89 | value = int(value)
90 |
91 | return value, unit
92 |
93 | value, unit = extract_value_and_unit(time_string)
94 |
95 | if unit == 's':
96 | return value
97 | elif unit == 'min':
98 | return value * 60
99 | elif unit == 'hour':
100 | return value * 3600
101 | elif unit == 'day':
102 | return value * 86400
103 | elif unit == 'month':
104 | return value * 86400 * 30
105 | elif unit == 'year':
106 | return value * 86400 * 365
107 | else:
108 | return 0
109 |
110 | async def is_req_subscribed(bot, query):
111 | if await db.find_join_req(query.from_user.id):
112 | return True
113 | try:
114 | user = await bot.get_chat_member(AUTH_CHANNEL, query.from_user.id)
115 | except UserNotParticipant:
116 | pass
117 | except Exception as e:
118 | print(e)
119 | else:
120 | if user.status != enums.ChatMemberStatus.BANNED:
121 | return True
122 | return False
123 |
124 | async def is_subscribed(bot, user_id, channel_id):
125 | try:
126 | user = await bot.get_chat_member(channel_id, user_id)
127 | except UserNotParticipant:
128 | pass
129 | except Exception as e:
130 | pass
131 | else:
132 | if user.status != enums.ChatMemberStatus.BANNED:
133 | return True
134 | return False
135 |
136 | async def get_poster(query, bulk=False, id=False, file=None):
137 | if not id:
138 | # https://t.me/GetTGLink/4183
139 | query = (query.strip()).lower()
140 | title = query
141 | year = re.findall(r'[1-2]\d{3}$', query, re.IGNORECASE)
142 | if year:
143 | year = list_to_str(year[:1])
144 | title = (query.replace(year, "")).strip()
145 | elif file is not None:
146 | year = re.findall(r'[1-2]\d{3}', file, re.IGNORECASE)
147 | if year:
148 | year = list_to_str(year[:1])
149 | else:
150 | year = None
151 | movieid = imdb.search_movie(title.lower(), results=10)
152 | if not movieid:
153 | return None
154 | if year:
155 | filtered=list(filter(lambda k: str(k.get('year')) == str(year), movieid))
156 | if not filtered:
157 | filtered = movieid
158 | else:
159 | filtered = movieid
160 | movieid=list(filter(lambda k: k.get('kind') in ['movie', 'tv series'], filtered))
161 | if not movieid:
162 | movieid = filtered
163 | if bulk:
164 | return movieid
165 | movieid = movieid[0].movieID
166 | else:
167 | movieid = query
168 | movie = imdb.get_movie(movieid)
169 | if movie.get("original air date"):
170 | date = movie["original air date"]
171 | elif movie.get("year"):
172 | date = movie.get("year")
173 | else:
174 | date = "N/A"
175 | plot = ""
176 | if not LONG_IMDB_DESCRIPTION:
177 | plot = movie.get('plot')
178 | if plot and len(plot) > 0:
179 | plot = plot[0]
180 | else:
181 | plot = movie.get('plot outline')
182 | if plot and len(plot) > 800:
183 | plot = plot[0:800] + "..."
184 |
185 | return {
186 | 'title': movie.get('title'),
187 | 'votes': movie.get('votes'),
188 | "aka": list_to_str(movie.get("akas")),
189 | "seasons": movie.get("number of seasons"),
190 | "box_office": movie.get('box office'),
191 | 'localized_title': movie.get('localized title'),
192 | 'kind': movie.get("kind"),
193 | "imdb_id": f"tt{movie.get('imdbID')}",
194 | "cast": list_to_str(movie.get("cast")),
195 | "runtime": list_to_str(movie.get("runtimes")),
196 | "countries": list_to_str(movie.get("countries")),
197 | "certificates": list_to_str(movie.get("certificates")),
198 | "languages": list_to_str(movie.get("languages")),
199 | "director": list_to_str(movie.get("director")),
200 | "writer":list_to_str(movie.get("writer")),
201 | "producer":list_to_str(movie.get("producer")),
202 | "composer":list_to_str(movie.get("composer")) ,
203 | "cinematographer":list_to_str(movie.get("cinematographer")),
204 | "music_team": list_to_str(movie.get("music department")),
205 | "distributors": list_to_str(movie.get("distributors")),
206 | 'release_date': date,
207 | 'year': movie.get('year'),
208 | 'genres': list_to_str(movie.get("genres")),
209 | 'poster': movie.get('full-size cover url'),
210 | 'plot': plot,
211 | 'rating': str(movie.get("rating")),
212 | 'url':f'https://www.imdb.com/title/tt{movieid}'
213 | }
214 | # https://github.com/odysseusmax/animated-lamp/blob/2ef4730eb2b5f0596ed6d03e7b05243d93e3415b/bot/utils/broadcast.py#L37
215 |
216 | async def broadcast_messages(user_id, message):
217 | try:
218 | await message.copy(chat_id=user_id)
219 | return True, "Success"
220 | except FloodWait as e:
221 | await asyncio.sleep(e.x)
222 | return await broadcast_messages(user_id, message)
223 | except InputUserDeactivated:
224 | await db.delete_user(int(user_id))
225 | logging.info(f"{user_id} - Removed from Database, since deleted account.")
226 | return False, "Deleted"
227 | except UserIsBlocked:
228 | logging.info(f"{user_id} - Blocked the bot.")
229 | return False, "Blocked"
230 | except PeerIdInvalid:
231 | await db.delete_user(int(user_id))
232 | logging.info(f"{user_id} - PeerIdInvalid")
233 | return False, "Error"
234 | except Exception as e:
235 | return False, "Error"
236 |
237 | async def get_settings(group_id):
238 | settings = temp.SETTINGS.get(group_id)
239 | if not settings:
240 | settings = await db.get_settings(group_id)
241 | temp.SETTINGS[group_id] = settings
242 | return settings
243 |
244 | async def save_group_settings(group_id, key, value):
245 | current = await get_settings(group_id)
246 | current[key] = value
247 | temp.SETTINGS[group_id] = current
248 | await db.update_settings(group_id, current)
249 |
250 | def get_size(size):
251 | """Get size in readable format"""
252 |
253 | units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"]
254 | size = float(size)
255 | i = 0
256 | while size >= 1024.0 and i < len(units):
257 | i += 1
258 | size /= 1024.0
259 | return "%.2f %s" % (size, units[i])
260 |
261 | def list_to_str(k):
262 | if not k:
263 | return "N/A"
264 | elif len(k) == 1:
265 | return str(k[0])
266 | else:
267 | return ' '.join(f'{elem}, ' for elem in k)
268 |
269 | def get_file_id(msg: Message):
270 | if msg.media:
271 | for message_type in (
272 | "photo",
273 | "animation",
274 | "audio",
275 | "document",
276 | "video",
277 | "video_note",
278 | "voice",
279 | "sticker"
280 | ):
281 | obj = getattr(msg, message_type)
282 | if obj:
283 | setattr(obj, "message_type", message_type)
284 | return obj
285 |
286 | def extract_user(message: Message) -> Union[int, str]:
287 | """extracts the user from a message"""
288 | # https://github.com/SpEcHiDe/PyroGramBot/blob/f30e2cca12002121bad1982f68cd0ff9814ce027/pyrobot/helper_functions/extract_user.py#L7
289 | user_id = None
290 | user_first_name = None
291 | if message.reply_to_message:
292 | user_id = message.reply_to_message.from_user.id
293 | user_first_name = message.reply_to_message.from_user.first_name
294 |
295 | elif len(message.command) > 1:
296 | if (
297 | len(message.entities) > 1 and
298 | message.entities[1].type == enums.MessageEntityType.TEXT_MENTION
299 | ):
300 |
301 | required_entity = message.entities[1]
302 | user_id = required_entity.user.id
303 | user_first_name = required_entity.user.first_name
304 | else:
305 | user_id = message.command[1]
306 | # don't want to make a request -_-
307 | user_first_name = user_id
308 | try:
309 | user_id = int(user_id)
310 | except ValueError:
311 | pass
312 | else:
313 | user_id = message.from_user.id
314 | user_first_name = message.from_user.first_name
315 | return (user_id, user_first_name)
316 |
317 |
318 | async def stream_site(link, grp_id):
319 | try:
320 | settings = await get_settings(grp_id) if await get_settings(grp_id) else {}
321 | api_key, site_key = ('streamapi', 'streamsite')
322 | default_api, default_site = STREAM_API, STREAM_SITE
323 |
324 | api = settings.get(api_key, default_api)
325 | site = settings.get(site_key, default_site)
326 |
327 | shortzy = Shortzy(api, site)
328 |
329 | try:
330 | link = await shortzy.convert(link)
331 | except Exception:
332 | link = await shortzy.get_quick_link(link)
333 | return link
334 | except Exception as e:
335 | logger.error(e)
336 |
337 | async def get_shortlink(link, grp_id, is_second_shortener=False, is_third_shortener=False):
338 | settings = await get_settings(grp_id) if await get_settings(grp_id) else {}
339 | if is_third_shortener:
340 | api_key, site_key = ('verify_api3', 'verify_3')
341 | default_api, default_site = VERIFY_API3, VERIFY_URL3
342 | elif is_second_shortener:
343 | api_key, site_key = ('verify_api2', 'verify_2')
344 | default_api, default_site = VERIFY_API2, VERIFY_URL2
345 | else:
346 | api_key, site_key = ('verify_api', 'verify')
347 | default_api, default_site = VERIFY_API, VERIFY_URL
348 |
349 | api = settings.get(api_key, default_api)
350 | site = settings.get(site_key, default_site)
351 | shortzy = Shortzy(api, site)
352 | try:
353 | link = await shortzy.convert(link)
354 | except Exception:
355 | link = await shortzy.get_quick_link(link)
356 | return link
357 |
358 | async def get_users():
359 | count = await user_col.count_documents({})
360 | cursor = user_col.find({})
361 | list = await cursor.to_list(length=int(count))
362 | return count, list
363 |
364 | async def get_text(settings, remaining_seconds, files, query, total_results, search):
365 | try:
366 | if settings["imdb"]:
367 | IMDB_CAP = temp.IMDB_CAP.get(query.from_user.id)
368 | CAPTION = f"☠️ ᴛɪᴛʟᴇ : {search}\n📂 ᴛᴏᴛᴀʟ ꜰɪʟᴇꜱ : {total_results}\n📝 ʀᴇǫᴜᴇsᴛᴇᴅ ʙʏ : {query.from_user.first_name}\n⏰ ʀᴇsᴜʟᴛ ɪɴ : {remaining_seconds} Sᴇᴄᴏɴᴅs\n\n"
369 | if IMDB_CAP:
370 | cap = IMDB_CAP
371 | for file in files: #shortlink = false, imdb = true
372 | cap += f"\n\n📁 {get_size(file.file_size)} ▷ {file.file_name}"
373 | else:
374 | imdb = await get_poster(search, file=(files[0]).file_name) if settings["imdb"] else None
375 | if imdb:
376 | TEMPLATE = script.IMDB_TEMPLATE_TXT
377 | cap = TEMPLATE.format(
378 | qurey=search,
379 | title=imdb['title'],
380 | votes=imdb['votes'],
381 | aka=imdb["aka"],
382 | seasons=imdb["seasons"],
383 | box_office=imdb['box_office'],
384 | localized_title=imdb['localized_title'],
385 | kind=imdb['kind'],
386 | imdb_id=imdb["imdb_id"],
387 | cast=imdb["cast"],
388 | runtime=imdb["runtime"],
389 | countries=imdb["countries"],
390 | certificates=imdb["certificates"],
391 | languages=imdb["languages"],
392 | director=imdb["director"],
393 | writer=imdb["writer"],
394 | producer=imdb["producer"],
395 | composer=imdb["composer"],
396 | cinematographer=imdb["cinematographer"],
397 | music_team=imdb["music_team"],
398 | distributors=imdb["distributors"],
399 | release_date=imdb['release_date'],
400 | year=imdb['year'],
401 | genres=imdb['genres'],
402 | poster=imdb['poster'],
403 | plot=imdb['plot'],
404 | rating=imdb['rating'],
405 | url=imdb['url'],
406 | **locals()
407 | )
408 | for file in files:
409 | cap += f"\n\n📁 {get_size(file.file_size)} ▷ {file.file_name}"
410 | else:
411 | cap = f"{CAPTION}" #imdb = false
412 | cap+="📚 Your Requested Files 👇\n\n"
413 | for file in files:
414 | cap += f"📁 {get_size(file.file_size)} ▷ {file.file_name}\n\n"
415 |
416 | else:
417 | #imdb = false
418 | cap = f"☠️ ᴛɪᴛʟᴇ : {search}\n📂 ᴛᴏᴛᴀʟ ꜰɪʟᴇꜱ : {total_results}\n📝 ʀᴇǫᴜᴇsᴛᴇᴅ ʙʏ : {query.from_user.first_name}\n⏰ ʀᴇsᴜʟᴛ ɪɴ : {remaining_seconds}\n\n"
419 | cap+="📚 Your Requested Files 👇\n\n"
420 | for file in files:
421 | cap += f"📁 {get_size(file.file_size)} ▷ {file.file_name}\n\n"
422 | return cap
423 | except Exception as e:
424 | await query.answer(f"{e}", show_alert=True)
425 | return cap
426 |
--------------------------------------------------------------------------------
/database/users_chats_db.py:
--------------------------------------------------------------------------------
1 | # This code has been modified by @Safaridev
2 | # Please do not remove this credit
3 | import motor.motor_asyncio
4 | from info import DATABASE_NAME, DATABASE_URI, IMDB, IMDB_TEMPLATE, MELCOW_NEW_USERS, SINGLE_BUTTON, SPELL_CHECK_REPLY, AUTO_DELETE, MAX_BTN, AUTO_FFILTER, TUTORIAL, TUTORIAL2, TUTORIAL3, REFERAL_TIME, STREAM_API, STREAM_SITE, VERIFY_URL, VERIFY_API, \
5 | VERIFY_URL2, VERIFY_API2, VERIFY_URL3, VERIFY_API3, LIMIT_MODE, TWO_VERIFY_GAP, THIRD_VERIFY_GAP, STREAM_MODE, LOG_CHANNEL, IS_VERIFY, AUTH_CHANNEL, CUSTOM_FILE_CAPTION, FILE_LIMITE, SEND_ALL_LIMITE, STREAM_SITE, STREAM_API
6 | from datetime import datetime, timedelta
7 | import pytz
8 | import re
9 | import time
10 | import hashlib
11 | import random
12 | import string
13 |
14 | class Database:
15 |
16 | def __init__(self, uri, database_name):
17 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
18 | self.db = self._client[database_name]
19 | self.col = self.db.users
20 | self.grp = self.db.groups
21 | self.users = self.db.uersz
22 | self.codes = self.db.codes
23 | self.safari = self.db.safari
24 | self.req = self.db.requests
25 | self.links_col = self.db.links
26 | self.verify_id = self.db.verify_id
27 | self.settings_col = self.db.settings
28 |
29 | def new_user(self, id, name):
30 | return dict(
31 | id = id,
32 | name = name,
33 | send_all=0,
34 | files_count=0,
35 | lifetime_files=0,
36 | ban_status=dict(
37 | is_banned=False,
38 | ban_reason="",
39 | ),
40 | )
41 |
42 | def new_group(self, id, title, owner_id):
43 | return dict(
44 | id = id,
45 | title = title,
46 | owner_id=owner_id,
47 | is_verified=False,
48 | is_rejected=False,
49 | chat_status=dict(
50 | is_disabled=False,
51 | reason="",
52 | ),
53 | )
54 |
55 | async def get_setting(self, key, default=None):
56 | setting = await self.settings_col.find_one({"name": key})
57 | return setting.get("value", default) if setting else default
58 |
59 | async def set_setting(self, key, value):
60 | await self.settings_col.update_one(
61 | {"name": key},
62 | {"$set": {"value": value}},
63 | upsert=True)
64 |
65 | async def find_join_req(self, id):
66 | return bool(await self.req.find_one({'id': id}))
67 |
68 | async def add_join_req(self, id):
69 | await self.req.insert_one({'id': id})
70 |
71 | async def del_join_req(self):
72 | await self.req.drop()
73 |
74 | async def get_safari_user(self, user_id):
75 | user_id = int(user_id)
76 | user = await self.safari.find_one({"user_id": user_id})
77 | ist_timezone = pytz.timezone('Asia/Kolkata')
78 | if not user:
79 | res = {
80 | "user_id": user_id,
81 | "last_verified": datetime(2020, 5, 17, 0, 0, 0, tzinfo=ist_timezone),
82 | "second_verified": datetime(2019, 5, 17, 0, 0, 0, tzinfo=ist_timezone),
83 | }
84 | user = await self.safari.insert_one(res)
85 | return user
86 |
87 | async def update_safari_user(self, user_id, value:dict):
88 | user_id = int(user_id)
89 | myquery = {"user_id": user_id}
90 | newvalues = {"$set": value}
91 | return await self.safari.update_one(myquery, newvalues)
92 |
93 | async def is_user_verified(self, user_id):
94 | user = await self.get_safari_user(user_id)
95 | try:
96 | safariback = user["last_verified"]
97 | except Exception:
98 | user = await self.get_safari_user(user_id)
99 | safariback = user["last_verified"]
100 | ist_timezone = pytz.timezone('Asia/Kolkata')
101 | safariback = safariback.astimezone(ist_timezone)
102 | current_time = datetime.now(tz=ist_timezone)
103 | seconds_since_midnight = (current_time - datetime(current_time.year, current_time.month, current_time.day, 0, 0, 0, tzinfo=ist_timezone)).total_seconds()
104 | time_diff = current_time - safariback
105 | total_seconds = time_diff.total_seconds()
106 | return total_seconds <= seconds_since_midnight
107 |
108 | async def user_verified(self, user_id):
109 | user = await self.get_safari_user(user_id)
110 | try:
111 | safariback = user["second_verified"]
112 | except Exception:
113 | user = await self.get_safari_user(user_id)
114 | safariback = user["second_verified"]
115 | ist_timezone = pytz.timezone('Asia/Kolkata')
116 | safariback = safariback.astimezone(ist_timezone)
117 | current_time = datetime.now(tz=ist_timezone)
118 | seconds_since_midnight = (current_time - datetime(current_time.year, current_time.month, current_time.day, 0, 0, 0, tzinfo=ist_timezone)).total_seconds()
119 | time_diff = current_time - safariback
120 | total_seconds = time_diff.total_seconds()
121 | return total_seconds <= seconds_since_midnight
122 |
123 | async def use_second_shortener(self, user_id, time):
124 | user = await self.get_safari_user(user_id)
125 | if not user.get("second_verified"):
126 | ist_timezone = pytz.timezone('Asia/Kolkata')
127 | await self.update_safari_user(user_id, {"second_verified":datetime(2019, 5, 17, 0, 0, 0, tzinfo=ist_timezone)})
128 | user = await self.get_safari_user(user_id)
129 | if await self.is_user_verified(user_id):
130 | try:
131 | safariback = user["last_verified"]
132 | except Exception:
133 | user = await self.get_safari_user(user_id)
134 | safariback = user["last_verified"]
135 | ist_timezone = pytz.timezone('Asia/Kolkata')
136 | safariback = safariback.astimezone(ist_timezone)
137 | current_time = datetime.now(tz=ist_timezone)
138 | time_difference = current_time - safariback
139 | if time_difference > timedelta(seconds=time):
140 | safariback = user["last_verified"].astimezone(ist_timezone)
141 | second_time = user["second_verified"].astimezone(ist_timezone)
142 | return second_time < safariback
143 | return False
144 |
145 | async def use_third_shortener(self, user_id, time):
146 | user = await self.get_safari_user(user_id)
147 | if not user.get("third_verified"):
148 | ist_timezone = pytz.timezone('Asia/Kolkata')
149 | await self.update_safari_user(user_id, {"third_verified":datetime(2018, 5, 17, 0, 0, 0, tzinfo=ist_timezone)})
150 | user = await self.get_safari_user(user_id)
151 | if await self.user_verified(user_id):
152 | try:
153 | safariback = user["second_verified"]
154 | except Exception:
155 | user = await self.get_safari_user(user_id)
156 | safariback = user["second_verified"]
157 | ist_timezone = pytz.timezone('Asia/Kolkata')
158 | safariback = safariback.astimezone(ist_timezone)
159 | current_time = datetime.now(tz=ist_timezone)
160 | time_difference = current_time - safariback
161 | if time_difference > timedelta(seconds=time):
162 | safariback = user["second_verified"].astimezone(ist_timezone)
163 | second_time = user["third_verified"].astimezone(ist_timezone)
164 | return second_time < safariback
165 | return False
166 |
167 | async def create_verify_id(self, user_id: int, hash):
168 | res = {"user_id": user_id, "hash":hash, "verified":False}
169 | return await self.verify_id.insert_one(res)
170 |
171 | async def get_verify_id_info(self, user_id: int, hash):
172 | return await self.verify_id.find_one({"user_id": user_id, "hash": hash})
173 |
174 | async def update_verify_id_info(self, user_id, hash, value: dict):
175 | myquery = {"user_id": user_id, "hash": hash}
176 | newvalues = { "$set": value }
177 | return await self.verify_id.update_one(myquery, newvalues)
178 |
179 | async def add_user(self, id, name):
180 | user = self.new_user(id, name)
181 | await self.col.insert_one(user)
182 |
183 | async def is_user_exist(self, id):
184 | user = await self.col.find_one({'id': int(id)})
185 | return bool(user)
186 |
187 | async def total_users_count(self):
188 | count = await self.col.count_documents({})
189 | return count
190 |
191 | async def remove_ban(self, id):
192 | ban_status = dict(
193 | is_banned=False,
194 | ban_reason=''
195 | )
196 | await self.col.update_one({'id': id}, {'$set': {'ban_status': ban_status}})
197 |
198 | async def ban_user(self, user_id, ban_reason="No Reason"):
199 | ban_status = dict(
200 | is_banned=True,
201 | ban_reason=ban_reason
202 | )
203 | await self.col.update_one({'id': user_id}, {'$set': {'ban_status': ban_status}})
204 |
205 | async def get_ban_status(self, id):
206 | default = dict(
207 | is_banned=False,
208 | ban_reason=''
209 | )
210 | user = await self.col.find_one({'id':int(id)})
211 | if not user:
212 | return default
213 | return user.get('ban_status', default)
214 |
215 | async def get_all_users(self):
216 | return self.col.find({})
217 |
218 |
219 | async def delete_user(self, user_id):
220 | await self.col.delete_many({'id': int(user_id)})
221 |
222 |
223 | async def get_banned(self):
224 | users = self.col.find({'ban_status.is_banned': True})
225 | chats = self.grp.find({'chat_status.is_disabled': True})
226 | b_chats = [chat['id'] async for chat in chats]
227 | b_users = [user['id'] async for user in users]
228 | return b_users, b_chats
229 |
230 | async def files_count(self, user_id, key):
231 | user = await self.col.find_one({"id": user_id})
232 | if user is None:
233 | await self.add_user(user_id, "None")
234 | return 0
235 | return user.get(key, 0)
236 |
237 | async def update_files(self, user_id, key, value):
238 | await self.col.update_one({"id": user_id}, {"$set": {key: value}})
239 |
240 | async def reset_all_files_count(self):
241 | await self.col.update_many({}, {"$set": {"files_count": 0}})
242 |
243 | async def reset_allsend_files(self):
244 | await self.col.update_many({}, {"$set": {"send_all": 0}})
245 |
246 | async def reset_daily_files_count(self, user_id):
247 | user = await self.col.find_one({"id": user_id})
248 | if user is None:
249 | return
250 | await self.col.update_one({"id": user_id}, {"$set": {"files_coun": 0}})
251 |
252 | async def add_chat(self, chat, title, owner_id):
253 | chat = self.new_group(chat, title, owner_id)
254 | await self.grp.insert_one(chat)
255 |
256 | async def get_chat(self, chat_id):
257 | chat = await self.grp.find_one({'id': int(chat_id)})
258 | return chat if chat else False
259 |
260 |
261 | async def re_enable_chat(self, id):
262 | chat_status=dict(
263 | is_disabled=False,
264 | reason="",
265 | )
266 | await self.grp.update_one({'id': int(id)}, {'$set': {'chat_status': chat_status}})
267 |
268 | async def update_settings(self, id, settings):
269 | await self.grp.update_one({'id': int(id)}, {'$set': {'settings': settings}})
270 |
271 | async def get_settings(self, id):
272 | default = {
273 | 'button': SINGLE_BUTTON,
274 | 'imdb': IMDB,
275 | 'spell_check': SPELL_CHECK_REPLY,
276 | 'welcome': MELCOW_NEW_USERS,
277 | 'auto_delete': AUTO_DELETE,
278 | 'auto_ffilter': AUTO_FFILTER,
279 | 'max_btn': MAX_BTN,
280 | 'template': IMDB_TEMPLATE,
281 | 'verify': VERIFY_URL,
282 | 'verify_api': VERIFY_API,
283 | 'verify_2': VERIFY_URL2,
284 | 'verify_api2': VERIFY_API2,
285 | 'verify_3': VERIFY_URL3,
286 | 'verify_api3': VERIFY_API3,
287 | 'verify_time': TWO_VERIFY_GAP,
288 | 'verify_time2': THIRD_VERIFY_GAP,
289 | 'tutorial': TUTORIAL,
290 | 'tutorial2': TUTORIAL2,
291 | 'tutorial3': TUTORIAL3,
292 | 'filelock': LIMIT_MODE,
293 | 'log': LOG_CHANNEL,
294 | 'is_verify': IS_VERIFY,
295 | 'fsub_id': AUTH_CHANNEL,
296 | 'file_limit': FILE_LIMITE,
297 | 'all_limit': SEND_ALL_LIMITE,
298 | 'stream_mode': STREAM_MODE,
299 | 'streamapi': STREAM_API,
300 | 'streamsite': STREAM_SITE,
301 | 'caption': CUSTOM_FILE_CAPTION
302 | }
303 | chat = await self.grp.find_one({'id':int(id)})
304 | if chat:
305 | return chat.get('settings', default)
306 | return default
307 |
308 |
309 | async def disable_chat(self, chat, reason="No Reason"):
310 | chat_status=dict(
311 | is_disabled=True,
312 | reason=reason,
313 | )
314 | await self.grp.update_one({'id': int(chat)}, {'$set': {'chat_status': chat_status}})
315 |
316 | async def verify_group(self, chat_id):
317 | await self.grp.update_one({'id': int(chat_id)}, {'$set': {'is_verified': True}})
318 |
319 | async def un_rejected(self, chat_id):
320 | await self.grp.update_one({'id': int(chat_id)}, {'$set': {'is_rejected': False}})
321 |
322 | async def reject_group(self, chat_id):
323 | await self.grp.update_one({'id': int(chat_id)}, {'$set': {'is_rejected': True}})
324 |
325 | async def check_group_verification(self, chat_id):
326 | chat = await self.get_chat(chat_id)
327 | if not chat:
328 | return False
329 | return chat.get('is_verified')
330 |
331 | async def rejected_group(self, chat_id):
332 | chat = await self.get_chat(chat_id)
333 | if not chat:
334 | return False
335 | return chat.get('is_rejected')
336 |
337 | async def get_all_groups(self):
338 | return await self.grp.find().to_list(None)
339 |
340 | async def delete_all_groups(self):
341 | await self.grp.delete_many({})
342 |
343 | async def total_chat_count(self):
344 | count = await self.grp.count_documents({})
345 | return count
346 |
347 |
348 | async def get_all_chats(self):
349 | return self.grp.find({})
350 |
351 |
352 | async def get_db_size(self):
353 | return (await self.db.command("dbstats"))['dataSize']
354 |
355 | async def get_user(self, user_id):
356 | user_data = await self.users.find_one({"id": user_id})
357 | return user_data
358 |
359 | async def update_user(self, user_data):
360 | await self.users.update_one({"id": user_data["id"]}, {"$set": user_data}, upsert=True)
361 |
362 | async def has_premium_access(self, user_id):
363 | user_data = await self.get_user(user_id)
364 | if user_data:
365 | expiry_time = user_data.get("expiry_time")
366 | if expiry_time is None:
367 | return False
368 | elif isinstance(expiry_time, datetime) and datetime.now() <= expiry_time:
369 | return True
370 | else:
371 | await self.users.update_one({"id": user_id}, {"$set": {"expiry_time": None}})
372 | return False
373 |
374 | async def update_one(self, filter_query, update_data):
375 | try:
376 | result = await self.users.update_one(filter_query, update_data)
377 | return result.matched_count == 1
378 | except Exception as e:
379 | print(f"Error updating document: {e}")
380 | return False
381 |
382 | async def get_expired(self, current_time):
383 | expired_users = []
384 | if data := self.users.find({"expiry_time": {"$lt": current_time}}):
385 | async for user in data:
386 | expired_users.append(user)
387 | return expired_users
388 |
389 | async def remove_premium_access(self, user_id):
390 | return await self.update_one(
391 | {"id": user_id}, {"$set": {"expiry_time": None}}
392 | )
393 |
394 | async def check_trial_status(self, user_id):
395 | user_data = await self.get_user(user_id)
396 | if user_data:
397 | return user_data.get("has_free_trial", False)
398 | return False
399 |
400 | async def give_free_trial(self, user_id):
401 | user_id = user_id
402 | seconds = 5*60
403 | expiry_time = datetime.now() + timedelta(seconds=seconds)
404 | user_data = {"id": user_id, "expiry_time": expiry_time, "has_free_trial": True}
405 | await self.users.update_one({"id": user_id}, {"$set": user_data}, upsert=True)
406 |
407 | async def give_referal(self, userid):
408 | user_id = userid
409 | seconds = REFERAL_TIME
410 | expiry_time = datetime.now() + timedelta(seconds=seconds)
411 | user_data = {"id": user_id, "expiry_time": expiry_time, "has_free_trial": True}
412 | await self.users.update_one({"id": user_id}, {"$set": user_data}, upsert=True)
413 |
414 |
415 |
416 | db = Database(DATABASE_URI, DATABASE_NAME)
417 |
--------------------------------------------------------------------------------