├── runtime.txt
├── Procfile
├── bot
├── database
│ ├── __init__.py
│ └── database.py
├── __main__.py
├── user.py
├── __init__.py
├── bot.py
├── translation.py
└── plugins
│ ├── settings.py
│ ├── commands.py
│ ├── auto_filter.py
│ ├── channel.py
│ └── callback.py
├── requirements.txt
├── app.json
├── .gitignore
├── README.md
└── LICENSE
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.9.1
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: python3 -m bot
--------------------------------------------------------------------------------
/bot/database/__init__.py:
--------------------------------------------------------------------------------
1 | from .database import Database
2 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Dnspython
2 | Motor
3 | Pyrogram
4 | Pymongo
5 | Requests
6 | TgCrypto
7 |
--------------------------------------------------------------------------------
/bot/__main__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @AlbertEinsteinTG
4 |
5 | from .bot import Bot
6 |
7 | app = Bot()
8 | app.run()
--------------------------------------------------------------------------------
/bot/user.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @AlbertEinsteinTG
4 |
5 | from pyrogram import Client, __version__
6 |
7 | from . import API_HASH, APP_ID, LOGGER, \
8 | USER_SESSION
9 |
10 |
11 | class User(Client):
12 | def __init__(self):
13 | super().__init__(
14 | "userbot",
15 | api_hash=API_HASH,
16 | api_id=APP_ID,
17 | session_string=USER_SESSION,
18 | workers=20
19 | )
20 | self.LOGGER = LOGGER
21 |
22 | async def start(self):
23 | await super().start()
24 | try: await self.export_session_string()
25 | except: pass
26 | usr_bot_me = await self.get_me()
27 | return (self, usr_bot_me.id)
28 |
29 | async def stop(self, *args):
30 | await super().stop()
31 | self.LOGGER(__name__).info("Bot stopped. Bye.")
32 |
--------------------------------------------------------------------------------
/bot/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @AlbertEinsteinTG
4 |
5 | import os
6 | import logging
7 | import time
8 |
9 | from logging.handlers import RotatingFileHandler
10 |
11 | from .translation import Translation
12 |
13 | # Change Accordingly While Deploying To A VPS
14 | APP_ID = int(os.environ.get("APP_ID"))
15 |
16 | API_HASH = os.environ.get("API_HASH")
17 |
18 | BOT_TOKEN = os.environ.get("BOT_TOKEN")
19 |
20 | DB_URI = os.environ.get("DB_URI")
21 |
22 | USER_SESSION = os.environ.get("USER_SESSION")
23 |
24 | VERIFY = {}
25 |
26 | logging.basicConfig(
27 | level=logging.INFO,
28 | format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s",
29 | datefmt='%d-%b-%y %H:%M:%S',
30 | handlers=[
31 | RotatingFileHandler(
32 | "autofilterbot.txt",
33 | maxBytes=50000000,
34 | backupCount=10
35 | ),
36 | logging.StreamHandler()
37 | ]
38 | )
39 | logging.getLogger("pyrogram").setLevel(logging.WARNING)
40 |
41 | start_uptime = time.time()
42 |
43 |
44 | def LOGGER(name: str) -> logging.Logger:
45 | return logging.getLogger(name)
46 |
--------------------------------------------------------------------------------
/bot/bot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @SpEcHIDe
4 |
5 | from pyrogram import Client, enums, __version__
6 |
7 | from . import API_HASH, APP_ID, LOGGER, BOT_TOKEN
8 |
9 | from .user import User
10 |
11 | class Bot(Client):
12 | USER: User = None
13 | USER_ID: int = None
14 |
15 | def __init__(self):
16 | super().__init__(
17 | "bot",
18 | api_hash=API_HASH,
19 | api_id=APP_ID,
20 | plugins={
21 | "root": "bot/plugins"
22 | },
23 | workers=200,
24 | bot_token=BOT_TOKEN,
25 | sleep_threshold=10
26 | )
27 | self.LOGGER = LOGGER
28 |
29 | async def start(self):
30 | await super().start()
31 | bot_details = await self.get_me()
32 | self.set_parse_mode(enums.ParseMode.HTML)
33 | self.LOGGER(__name__).info(
34 | f"@{bot_details.username} started! "
35 | )
36 | self.USER, self.USER_ID = await User().start()
37 |
38 | async def stop(self, *args):
39 | await super().stop()
40 | self.LOGGER(__name__).info("Bot stopped. Bye.")
41 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Auto Filter Bot V2",
3 | "description": "A Filter Bot Which Doesnt Need Manuall Filter Adding",
4 | "logo": "https://telegra.ph/file/667e15c821117633d07bd.png",
5 | "keywords": [
6 | "Auto",
7 | "Filter",
8 | "Mongo DB"
9 | ],
10 | "website": "https://github.com/CrazyBotsz",
11 | "repository": "https://github.com/CrazyBotsz/Adv-Auto-Filter-Bot-V2",
12 | "success_url": "https://telegram.dog/CrazyBotsz",
13 | "env": {
14 | "APP_ID": {
15 | "description": "Your APP ID From my.telegram.org or @UseTGXBot",
16 | "value": ""
17 | },
18 | "API_HASH": {
19 | "description": "Your API Hash From my.telegram.org or @UseTGXBot",
20 | "value": ""
21 | },
22 | "BOT_TOKEN": {
23 | "description": "Your Bot Token From @BotFather",
24 | "value": ""
25 | },
26 | "DB_URI": {
27 | "description": "Your Mongo DB URL Obtained From mongodb.com",
28 | "value": ""
29 | },
30 | "USER_SESSION": {
31 | "description": "A Pyrogram User Session String. Generated From @PyrogramStringBot",
32 | "value": ""
33 | }
34 | },
35 | "buildpacks": [
36 | {
37 | "url": "heroku/python"
38 | }
39 | ],
40 | "formation": {
41 | "worker": {
42 | "quantity": 1,
43 | "size": "free"
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
--------------------------------------------------------------------------------
/bot/translation.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @AlbertEinsteinTG
4 |
5 | class Translation(object):
6 |
7 | START_TEXT = """Hey {}!!
8 | Am Just A Advance Auto Filter Bot....😉
9 |
10 | Just Add Me To Your Group And Channel And Connect Them And See My Pevers 🔥🔥😝
11 |
12 | For More Details Click Help Button Below..
13 | @CrazyBotsz
14 | """
15 |
16 | HELP_TEXT = """
17 | How To Use Me!?
18 |
19 |
20 | -> Add Me To Any Group And Make Me Admin
21 | -> Add Me To Your Desired Channel
22 |
23 |
24 | Bot Commands (Works Only In Groups) :
25 |
26 | -> /add chat_id
27 | OR - To Connect A Group With A Channel (Bot Should Be Admin With Full Previlages In Both Group And Channel)
28 | /add @Username
29 |
30 | -> /del chat_id
31 | OR - To disconnect A Group With A Channel
32 | /del @Username
33 |
34 | -> /delall - This Command Will Disconnect All Connected Channel With The Group And Deletes All Its File From DB
35 |
36 | -> /settings - This Command Will Display You A Settings Pannel Instance Which Can Be Used To Tweek Bot's Settings Accordingly
37 |
38 | -> Channel - Button Will Show You All The Connected Chats With The Group And Will Show Buttons Correspnding To There Order For Furthur Controls
39 |
40 | -> Filter Types - Button Will Show You The 3 Filter Option Available In Bot... Pressing Each Buttons Will Either Enable or Disable Them And This Will Take Into Action As Soon As You Use Them Without The Need Of A Restart
41 |
42 | -> Configure - Button Will Helps You To Change No. of Pages/ Buttons Per Page/ Total Result Without Acutally Editing The Repo... Also It Provide Option To Enable/Disable For Showing Invite Link In Each Results
43 |
44 | -> Status - Button Will Shows The Stats Of Your Channel
45 |
46 | @CrazyBotsz
47 | """
48 |
49 | ABOUT_TEXT = """➥ Name : Auto Filter Bot
50 |
51 | ➥ Creator : AlbertEinstein_TG
52 |
53 | ➥ Language : Python3
54 |
55 | ➥ Library : Pyrogram Asyncio 1.13.0
56 |
57 | ➥ Source Code : Click Me
58 | """
--------------------------------------------------------------------------------
/bot/plugins/settings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @AlbertEinsteinTG
4 |
5 | import re
6 | from pyrogram import Client, filters, enums
7 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
8 |
9 | from bot import VERIFY # pylint: disable=import-error
10 |
11 | @Client.on_message(filters.command(["settings"]) & filters.group, group=1)
12 | async def settings(bot, update):
13 |
14 | chat_id = update.chat.id
15 | user_id = update.from_user.id if update.from_user else None
16 | global VERIFY
17 |
18 | if VERIFY.get(str(chat_id)) == None: # Make Admin's ID List
19 | admin_list = []
20 | async for x in bot.get_chat_members(chat_id=chat_id, filter=enums.ChatMembersFilter.ADMINISTRATORS):
21 | admin_id = x.user.id
22 | admin_list.append(admin_id)
23 | admin_list.append(None)
24 | VERIFY[str(chat_id)] = admin_list
25 |
26 | if not user_id in VERIFY.get(str(chat_id)): # Checks if user is admin of the chat
27 | return
28 |
29 | bot_info = await bot.get_me()
30 | bot_first_name= bot_info.first_name
31 |
32 | text =f"{bot_first_name}'s Settings Pannel.....\n"
33 | text+=f"\nYou Can Use This Menu To Change Connectivity And Know Status Of Your Every Connected Channel, Change Filter Types, Configure Filter Results And To Know Status Of Your Group..."
34 |
35 | buttons = [
36 | [
37 | InlineKeyboardButton
38 | (
39 | "Channels", callback_data=f"channel_list({chat_id})"
40 | ),
41 |
42 | InlineKeyboardButton
43 | (
44 | "Filter Types", callback_data=f"types({chat_id})"
45 | )
46 | ],
47 | [
48 | InlineKeyboardButton
49 | (
50 | "Configure 🛠", callback_data=f"config({chat_id})"
51 | )
52 | ],
53 | [
54 | InlineKeyboardButton
55 | (
56 | "Status", callback_data=f"status({chat_id})"
57 | ),
58 |
59 | InlineKeyboardButton
60 | (
61 | "About", callback_data=f"about({chat_id})"
62 | )
63 | ],
64 | [
65 | InlineKeyboardButton
66 | (
67 | "Close 🔐", callback_data="close"
68 | )
69 | ]
70 | ]
71 |
72 | reply_markup = InlineKeyboardMarkup(buttons)
73 |
74 | await bot.send_message (
75 |
76 | chat_id=chat_id,
77 | text=text,
78 | reply_markup=reply_markup,
79 | parse_mode=enums.ParseMode.HTML,
80 | reply_to_message_id=update.id
81 |
82 | )
83 |
84 |
85 | def remove_emoji(string):
86 | emoji_pattern = re.compile("["
87 | u"\U0001F600-\U0001F64F"
88 | u"\U0001F300-\U0001F5FF"
89 | u"\U0001F680-\U0001F6FF"
90 | u"\U0001F1E0-\U0001F1FF"
91 | u"\U00002500-\U00002BEF"
92 | u"\U00002702-\U000027B0"
93 | u"\U00002702-\U000027B0"
94 | u"\U000024C2-\U0001F251"
95 | u"\U0001f926-\U0001f937"
96 | u"\U00010000-\U0010ffff"
97 | u"\u2640-\u2642"
98 | u"\u2600-\u2B55"
99 | u"\u200d"
100 | u"\u23cf"
101 | u"\u23e9"
102 | u"\u231a"
103 | u"\ufe0f"
104 | u"\u3030"
105 | "]+", flags=re.UNICODE)
106 |
107 | return emoji_pattern.sub(r' ', str(string))
108 |
--------------------------------------------------------------------------------
/bot/plugins/commands.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # (c) @AlbertEinsteinTG
4 |
5 | from pyrogram import filters, Client, enums
6 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery
7 | from bot import Translation, LOGGER # pylint: disable=import-error
8 | from bot.database import Database # pylint: disable=import-error
9 |
10 | db = Database()
11 |
12 | @Client.on_message(filters.command(["start"]) & filters.private, group=1)
13 | async def start(bot, update):
14 |
15 | try:
16 | file_uid = update.command[1]
17 | except IndexError:
18 | file_uid = False
19 |
20 | if file_uid:
21 | file_id, file_name, file_caption, file_type = await db.get_file(file_uid)
22 |
23 | if (file_id or file_type) == None:
24 | return
25 |
26 | caption = file_caption if file_caption != ("" or None) else ("" + file_name + "")
27 | try:
28 | await update.reply_cached_media(
29 | file_id,
30 | quote=True,
31 | caption = caption,
32 | parse_mode=enums.ParseMode.HTML,
33 | reply_markup=InlineKeyboardMarkup(
34 | [
35 | [
36 | InlineKeyboardButton
37 | (
38 | 'Developers', url="https://t.me/CrazyBotsz"
39 | )
40 | ]
41 | ]
42 | )
43 | )
44 | except Exception as e:
45 | await update.reply_text(f"Error:\n{e}", True, parse_mode=enums.ParseMode.HTML)
46 | LOGGER(__name__).error(e)
47 | return
48 |
49 | buttons = [[
50 | InlineKeyboardButton('Developers', url='https://t.me/CrazyBotsz'),
51 | InlineKeyboardButton('Source Code 🧾', url ='https://github.com/CrazyBotsz/Adv-Auto-Filter-Bot-V2')
52 | ],[
53 | InlineKeyboardButton('Support 🛠', url='https://t.me/CrazyBotszGrp')
54 | ],[
55 | InlineKeyboardButton('Help ⚙', callback_data="help")
56 | ]]
57 |
58 | reply_markup = InlineKeyboardMarkup(buttons)
59 |
60 | await bot.send_message(
61 | chat_id=update.chat.id,
62 | text=Translation.START_TEXT.format(
63 | update.from_user.first_name),
64 | reply_markup=reply_markup,
65 | parse_mode=enums.ParseMode.HTML,
66 | reply_to_message_id=update.id
67 | )
68 |
69 |
70 | @Client.on_message(filters.command(["help"]) & filters.private, group=1)
71 | async def help(bot, update):
72 | buttons = [[
73 | InlineKeyboardButton('Home ⚡', callback_data='start'),
74 | InlineKeyboardButton('About 🚩', callback_data='about')
75 | ],[
76 | InlineKeyboardButton('Close 🔐', callback_data='close')
77 | ]]
78 |
79 | reply_markup = InlineKeyboardMarkup(buttons)
80 |
81 | await bot.send_message(
82 | chat_id=update.chat.id,
83 | text=Translation.HELP_TEXT,
84 | reply_markup=reply_markup,
85 | parse_mode=enums.ParseMode.HTML,
86 | reply_to_message_id=update.id
87 | )
88 |
89 |
90 | @Client.on_message(filters.command(["about"]) & filters.private, group=1)
91 | async def about(bot, update):
92 |
93 | buttons = [[
94 | InlineKeyboardButton('Home ⚡', callback_data='start'),
95 | InlineKeyboardButton('Close 🔐', callback_data='close')
96 | ]]
97 | reply_markup = InlineKeyboardMarkup(buttons)
98 |
99 | await bot.send_message(
100 | chat_id=update.chat.id,
101 | text=Translation.ABOUT_TEXT,
102 | reply_markup=reply_markup,
103 | disable_web_page_preview=True,
104 | parse_mode=enums.ParseMode.HTML,
105 | reply_to_message_id=update.id
106 | )
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Adv Auto Filter Bot V2
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
75 |
76 |
77 |
78 |
79 |
84 |
85 | git clone https://github.com/CrazyBotsz/Adv-Auto-Filter-Bot-V2 86 | cd Adv-Auto-Filter-Bot-V2 87 | pip3 install -r requirements.txt 88 | # Change The Vars Of bot/__init__.py File Accordingly 89 | python3 -m bot 90 |91 | 92 |
{query}",
207 | reply_markup=reply_markup,
208 | parse_mode=enums.ParseMode.HTML,
209 | reply_to_message_id=update.id
210 | )
211 |
212 | except ButtonDataInvalid:
213 | print(result[0])
214 |
215 | except Exception as e:
216 | print(e)
217 |
218 |
219 | async def gen_invite_links(db, group_id, bot, update):
220 | """
221 | A Funtion To Generate Invite Links For All Active
222 | Connected Chats In A Group
223 | """
224 | chats = db.get("chat_ids")
225 | global INVITE_LINK
226 |
227 | if INVITE_LINK.get(str(group_id)):
228 | return
229 |
230 | Links = []
231 | if chats:
232 | for x in chats:
233 | Name = x["chat_name"]
234 |
235 | if Name == None:
236 | continue
237 |
238 | chatId=int(x["chat_id"])
239 |
240 | Link = await bot.export_chat_invite_link(chatId)
241 | Links.append({"chat_id": chatId, "chat_name": Name, "invite_link": Link})
242 |
243 | INVITE_LINK[str(group_id)] = Links
244 | return
245 |
246 |
247 | async def recacher(group_id, ReCacheInvite=True, ReCacheActive=False, bot=Bot, update=Message):
248 | """
249 | A Funtion To rechase invite links and active chats of a specific chat
250 | """
251 | global INVITE_LINK, ACTIVE_CHATS
252 |
253 | if ReCacheInvite:
254 | if INVITE_LINK.get(str(group_id)):
255 | INVITE_LINK.pop(str(group_id))
256 |
257 | Links = []
258 | chats = await db.find_chat(group_id)
259 | chats = chats["chat_ids"]
260 |
261 | if chats:
262 | for x in chats:
263 | Name = x["chat_name"]
264 | chat_id = x["chat_id"]
265 | if (Name == None or chat_id == None):
266 | continue
267 |
268 | chat_id = int(chat_id)
269 |
270 | Link = await bot.export_chat_invite_link(chat_id)
271 | Links.append({"chat_id": chat_id, "chat_name": Name, "invite_link": Link})
272 |
273 | INVITE_LINK[str(group_id)] = Links
274 |
275 | if ReCacheActive:
276 |
277 | if ACTIVE_CHATS.get(str(group_id)):
278 | ACTIVE_CHATS.pop(str(group_id))
279 |
280 | achats = await db.find_active(group_id)
281 | achatId = []
282 | if achats:
283 | for x in achats["chats"]:
284 | achatId.append(int(x["chat_id"]))
285 |
286 | ACTIVE_CHATS[str(group_id)] = achatId
287 | return
288 |
289 |
--------------------------------------------------------------------------------
/bot/plugins/channel.py:
--------------------------------------------------------------------------------
1 | import random
2 | import string
3 | import asyncio
4 |
5 | from pyrogram import Client, filters, enums
6 | from pyrogram.errors import UserAlreadyParticipant, FloodWait
7 |
8 | from bot import VERIFY, LOGGER # pylint: disable=import-error
9 | from bot.bot import Bot # pylint: disable=import-error
10 | from bot.database import Database # pylint: disable=import-error
11 | from bot.plugins.auto_filter import recacher # pylint: disable=import-error
12 |
13 | db = Database()
14 | logger = LOGGER(__name__)
15 |
16 | @Client.on_message(filters.command(["add"]) & filters.group, group=1)
17 | async def connect(bot: Bot, update):
18 | """
19 | A Funtion To Handle Incoming /add Command TO COnnect A Chat With Group
20 | """
21 | chat_id = update.chat.id
22 | user_id = update.from_user.id if update.from_user else None
23 | target_chat = update.text.split(None, 1)
24 | global VERIFY
25 |
26 | if VERIFY.get(str(chat_id)) == None: # Make Admin's ID List
27 | admin_list = []
28 | async for x in bot.get_chat_members(chat_id=chat_id, filter=enums.ChatMembersFilter.ADMINISTRATORS):
29 | admin_id = x.user.id
30 | admin_list.append(admin_id)
31 | admin_list.append(None)
32 | VERIFY[str(chat_id)] = admin_list
33 |
34 | if not user_id in VERIFY.get(str(chat_id)):
35 | return
36 |
37 | try:
38 | if target_chat[1].startswith("@"):
39 | if len(target_chat[1]) < 5:
40 | await update.reply_text("Invalid Username...!!!")
41 | return
42 | target = target_chat[1]
43 |
44 | elif not target_chat[1].startswith("@"):
45 | if len(target_chat[1]) < 14:
46 | await update.reply_text("Invalid Chat Id...\nChat ID Should Be Something Like This: -100xxxxxxxxxx")
47 | return
48 | target = int(target_chat[1])
49 |
50 | except Exception:
51 | await update.reply_text("Invalid Input...\nYou Should Specify Valid chat_id(-100xxxxxxxxxx) or @username")
52 | return
53 |
54 | # Exports invite link from target channel for user to join
55 | try:
56 | join_link = await bot.export_chat_invite_link(target)
57 | join_link = join_link.replace('+', 'joinchat/')
58 | except Exception as e:
59 | logger.exception(e, exc_info=True)
60 | await update.reply_text(f"Make Sure Im Admin At {target} And Have Permission For Inviting Users via Link And Try Again.....!!!\n\nError Logged: {e}", parse_mode='html')
61 | return
62 |
63 | userbot_info = await bot.USER.get_me()
64 |
65 | # Joins to targeted chat using above exported invite link
66 | # If aldready joined, code just pass on to next code
67 | try:
68 | await bot.USER.join_chat(join_link)
69 | except UserAlreadyParticipant:
70 | pass
71 | except Exception as e:
72 | logger.exception(e, exc_info=True)
73 | await update.reply_text(f"{userbot_info.mention} Couldnt Join The Channel {target} Make Sure Userbot Is Not Banned There Or Add It Manually And Try Again....!!\n\nError Logged: {e}", parse_mode='html')
74 | return
75 |
76 | try:
77 | c_chat = await bot.get_chat(target)
78 | channel_id = c_chat.id
79 | channel_name = c_chat.title
80 |
81 | except Exception as e:
82 | await update.reply_text("Encountered Some Issue..Please Check Logs..!!")
83 | raise e
84 |
85 |
86 | in_db = await db.in_db(chat_id, channel_id)
87 |
88 | if in_db:
89 | await update.reply_text("Channel Aldready In Db...!!!")
90 | return
91 |
92 | wait_msg = await update.reply_text("Please Wait Till I Add All Your Files From Channel To Db\n\nThis May Take 10 or 15 Mins Depending On Your No. Of Files In Channel.....\n\nUntil Then Please Dont Sent Any Other Command Or This Operation May Be Intrupted....")
93 |
94 | try:
95 | mf = enums.MessagesFilter
96 | type_list = [mf.VIDEO, mf.DOCUMENT, mf.AUDIO]
97 | data = []
98 | skipCT = 0
99 |
100 | for typ in type_list:
101 |
102 | async for msgs in bot.USER.search_messages(channel_id, filter=typ): #Thanks To @PrgOfficial For Suggesting
103 |
104 | # Using 'if elif' instead of 'or' to determine 'file_type'
105 | # Better Way? Make A PR
106 | try:
107 | try:
108 | file_id = await bot.get_messages(channel_id, message_ids=msgs.id)
109 | except FloodWait as e:
110 | await asyncio.sleep(e.value)
111 | file_id = await bot.get_messages(channel_id, message_ids=msgs.id)
112 | except Exception as e:
113 | print(e)
114 | continue
115 |
116 | if msgs.video:
117 | file_id = file_id.video.file_id
118 | file_name = msgs.video.file_name[0:-4]
119 | file_caption = msgs.caption if msgs.caption else ""
120 | file_size = msgs.video.file_size
121 | file_type = "video"
122 |
123 | elif msgs.audio:
124 | file_id = file_id.audio.file_id
125 | file_name = msgs.audio.file_name[0:-4]
126 | file_caption = msgs.caption if msgs.caption else ""
127 | file_size = msgs.audio.file_size
128 | file_type = "audio"
129 |
130 | elif msgs.document:
131 | file_id = file_id.document.file_id
132 | file_name = msgs.document.file_name[0:-4]
133 | file_caption = msgs.caption if msgs.caption else ""
134 | file_size = msgs.document.file_size
135 | file_type = "document"
136 |
137 | else:
138 | return
139 |
140 | for i in ["_", "|", "-", "."]: # Work Around
141 | try:
142 | file_name = file_name.replace(i, " ")
143 | except Exception:
144 | pass
145 |
146 | file_link = msgs.link
147 | group_id = chat_id
148 | unique_id = ''.join(
149 | random.choice(
150 | string.ascii_lowercase +
151 | string.ascii_uppercase +
152 | string.digits
153 | ) for _ in range(15)
154 | )
155 |
156 | dicted = dict(
157 | file_id=file_id, # Done
158 | unique_id=unique_id,
159 | file_name=file_name,
160 | file_caption=file_caption,
161 | file_size=file_size,
162 | file_type=file_type,
163 | file_link=file_link,
164 | chat_id=channel_id,
165 | group_id=group_id,
166 | )
167 |
168 | data.append(dicted)
169 | except Exception as e:
170 | if 'NoneType' in str(e): # For Some Unknown Reason Some File Names are NoneType
171 | skipCT +=1
172 | continue
173 | print(e)
174 |
175 | print(f"{skipCT} Files Been Skipped Due To File Name Been None..... #BlameTG")
176 | except Exception as e:
177 | await wait_msg.edit_text("Couldnt Fetch Files From Channel... Please look Into Logs For More Details")
178 | raise e
179 |
180 | await db.add_filters(data)
181 | await db.add_chat(chat_id, channel_id, channel_name)
182 | await recacher(chat_id, True, True, bot, update)
183 |
184 | await wait_msg.edit_text(f"Channel Was Sucessfully Added With {len(data)} Files..")
185 |
186 |
187 | @Client.on_message(filters.command(["del"]) & filters.group, group=1)
188 | async def disconnect(bot: Bot, update):
189 | """
190 | A Funtion To Handle Incoming /del Command TO Disconnect A Chat With A Group
191 | """
192 | chat_id = update.chat.id
193 | user_id = update.from_user.id if update.from_user else None
194 | target_chat = update.text.split(None, 1)
195 | global VERIFY
196 |
197 | if VERIFY.get(str(chat_id)) == None: # Make Admin's ID List
198 | admin_list = []
199 | async for x in bot.get_chat_members(chat_id=chat_id, filter=enums.ChatMembersFilter.ADMINISTRATORS):
200 | admin_id = x.user.id
201 | admin_list.append(admin_id)
202 | admin_list.append(None)
203 | VERIFY[str(chat_id)] = admin_list
204 |
205 | if not user_id in VERIFY.get(str(chat_id)):
206 | return
207 |
208 | try:
209 | if target_chat[1].startswith("@"):
210 | if len(target_chat[1]) < 5:
211 | await update.reply_text("Invalid Username...!!!")
212 | return
213 | target = target_chat[1]
214 |
215 | elif not target_chat.startswith("@"):
216 | if len(target_chat[1]) < 14:
217 | await update.reply_text("Invalid Chat Id...\nChat ID Should Be Something Like This: -100xxxxxxxxxx")
218 | return
219 | target = int(target_chat[1])
220 |
221 | except Exception:
222 | await update.reply_text("Invalid Input...\nYou Should Specify Valid chat_id(-100xxxxxxxxxx) or @username")
223 | return
224 |
225 | userbot = await bot.USER.get_me()
226 | userbot_name = userbot.first_name
227 | userbot_id = userbot.id
228 |
229 | try:
230 | channel_info = await bot.USER.get_chat(target)
231 | channel_id = channel_info.id
232 | except Exception:
233 | await update.reply_text(f"My UserBot [{userbot_name}](tg://user?id={userbot_id}) Couldnt Fetch Details Of `{target}` Make Sure Userbot Is Not Banned There Or Add It Manually And Try Again....!!")
234 | return
235 |
236 | in_db = await db.in_db(chat_id, channel_id)
237 |
238 | if not in_db:
239 | await update.reply_text("This Channel Is Not Connected With The Group...")
240 | return
241 |
242 | wait_msg = await update.reply_text("Deleting All Files Of This Channel From DB....!!!\n\nPlease Be Patience...Dont Sent Another Command Until This Process Finishes..")
243 |
244 | await db.del_filters(chat_id, channel_id)
245 | await db.del_active(chat_id, channel_id)
246 | await db.del_chat(chat_id, channel_id)
247 | await recacher(chat_id, True, True, bot, update)
248 |
249 | await wait_msg.edit_text("Sucessfully Deleted All Files From DB....")
250 |
251 |
252 | @Client.on_message(filters.command(["delall"]) & filters.group, group=1)
253 | async def delall(bot: Bot, update):
254 | """
255 | A Funtion To Handle Incoming /delall Command TO Disconnect All Chats From A Group
256 | """
257 | chat_id=update.chat.id
258 | user_id = update.from_user.id if update.from_user else None
259 | global VERIFY
260 |
261 | if VERIFY.get(str(chat_id)) == None: # Make Admin's ID List
262 | admin_list = []
263 | async for x in bot.get_chat_members(chat_id=chat_id, filter=enums.ChatMembersFilter.ADMINISTRATORS):
264 | admin_id = x.user.id
265 | admin_list.append(admin_id)
266 | admin_list.append(None)
267 | VERIFY[str(chat_id)] = admin_list
268 |
269 | if not user_id in VERIFY.get(str(chat_id)):
270 | return
271 |
272 | await db.delete_all(chat_id)
273 | await recacher(chat_id, True, True, bot, update)
274 |
275 | await update.reply_text("Sucessfully Deleted All Connected Chats From This Group....")
276 |
277 |
278 | @Client.on_message(filters.channel & (filters.video | filters.audio | filters.document), group=0)
279 | async def new_files(bot: Bot, update):
280 | """
281 | A Funtion To Handle Incoming New Files In A Channel ANd Add Them To Respective Channels..
282 | """
283 | channel_id = update.chat.id
284 |
285 | # Using 'if elif' instead of 'or' to determine 'file_type'
286 | # Better Way? Make A PR
287 |
288 | try:
289 | if update.video:
290 | file_type = "video"
291 | file_id = update.video.file_id
292 | file_name = update.video.file_name[0:-4]
293 | file_caption = update.caption if update.caption else ""
294 | file_size = update.video.file_size
295 |
296 | elif update.audio:
297 | file_type = "audio"
298 | file_id = update.audio.file_id
299 | file_name = update.audio.file_name[0:-4]
300 | file_caption = update.caption if update.caption else ""
301 | file_size = update.audio.file_size
302 |
303 | elif update.document:
304 | file_type = "document"
305 | file_id = update.document.file_id
306 | file_name = update.document.file_name[0:-4]
307 | file_caption = update.caption if update.caption else ""
308 | file_size = update.document.file_size
309 |
310 | for i in ["_", "|", "-", "."]: # Work Around
311 | try:
312 | file_name = file_name.replace(i, " ")
313 | except Exception:
314 | pass
315 | except Exception as e:
316 | print(e)
317 | return
318 |
319 |
320 | file_link = update.link
321 | group_ids = await db.find_group_id(channel_id)
322 | unique_id = ''.join(
323 | random.choice(
324 | string.ascii_lowercase +
325 | string.ascii_uppercase +
326 | string.digits
327 | ) for _ in range(15)
328 | )
329 |
330 | data = []
331 |
332 | if group_ids:
333 | for group_id in group_ids:
334 | data_packets = dict(
335 | file_id=file_id, # File Id For Future Updates Maybe...
336 | unique_id=unique_id,
337 | file_name=file_name,
338 | file_caption=file_caption,
339 | file_size = file_size,
340 | file_type=file_type,
341 | file_link=file_link,
342 | chat_id=channel_id,
343 | group_id=group_id,
344 | )
345 |
346 | data.append(data_packets)
347 | await db.add_filters(data)
348 | return
349 |
350 |
--------------------------------------------------------------------------------
/bot/database/database.py:
--------------------------------------------------------------------------------
1 | import os
2 | import motor.motor_asyncio # pylint: disable=import-error
3 | from bot import DB_URI
4 |
5 | DB_NAME = os.environ.get("DB_NAME", "Adv_Auto_Filter")
6 |
7 | class Database:
8 |
9 | def __init__(self):
10 | self._client = motor.motor_asyncio.AsyncIOMotorClient(DB_URI)
11 | self.db = self._client[DB_NAME]
12 | self.col = self.db["Main"]
13 | self.acol = self.db["Active_Chats"]
14 | self.fcol = self.db["Filter_Collection"]
15 |
16 | self.cache = {}
17 | self.acache = {}
18 |
19 |
20 | async def create_index(self):
21 | """
22 | Create text index if not in db
23 | """
24 | await self.fcol.create_index([("file_name", "text")])
25 |
26 |
27 | def new_chat(self, group_id, channel_id, channel_name):
28 | """
29 | Create a document in db if the chat is new
30 | """
31 | try:
32 | group_id, channel_id = int(group_id), int(channel_id)
33 | except:
34 | pass
35 |
36 | return dict(
37 | _id = group_id,
38 | chat_ids = [{
39 | "chat_id": channel_id,
40 | "chat_name": channel_name
41 | }],
42 | types = dict(
43 | audio=False,
44 | document=True,
45 | video=True
46 | ),
47 | configs = dict(
48 | accuracy=0.80,
49 | max_pages=5,
50 | max_results=50,
51 | max_per_page=10,
52 | pm_fchat=True,
53 | show_invite_link=True
54 | )
55 | )
56 |
57 |
58 | async def status(self, group_id: int):
59 | """
60 | Get the total filters, total connected
61 | chats and total active chats of a chat
62 | """
63 | group_id = int(group_id)
64 |
65 | total_filter = await self.tf_count(group_id)
66 |
67 | chats = await self.find_chat(group_id)
68 | chats = chats.get("chat_ids")
69 | total_chats = len(chats) if chats is not None else 0
70 |
71 | achats = await self.find_active(group_id)
72 | if achats not in (None, False):
73 | achats = achats.get("chats")
74 | if achats == None:
75 | achats = []
76 | else:
77 | achats = []
78 | total_achats = len(achats)
79 |
80 | return total_filter, total_chats, total_achats
81 |
82 |
83 | async def find_group_id(self, channel_id: int):
84 | """
85 | Find all group id which is connected to a channel
86 | for add a new files to db
87 | """
88 | data = self.col.find({})
89 | group_list = []
90 |
91 | for group_id in await data.to_list(length=50): # No Need Of Even 50
92 | for y in group_id["chat_ids"]:
93 | if int(y["chat_id"]) == int(channel_id):
94 | group_list.append(group_id["_id"])
95 | else:
96 | continue
97 | return group_list
98 |
99 | # Related TO Finding Channel(s)
100 | async def find_chat(self, group_id: int):
101 | """
102 | A funtion to fetch a group's settings
103 | """
104 | connections = self.cache.get(str(group_id))
105 |
106 | if connections is not None:
107 | return connections
108 |
109 | connections = await self.col.find_one({'_id': group_id})
110 |
111 | if connections:
112 | self.cache[str(group_id)] = connections
113 |
114 | return connections
115 | else:
116 | return self.new_chat(None, None, None)
117 |
118 |
119 | async def add_chat(self, group_id: int, channel_id: int, channel_name):
120 | """
121 | A funtion to add/update a chat document when a new chat is connected
122 | """
123 | new = self.new_chat(group_id, channel_id, channel_name)
124 | update_d = {"$push" : {"chat_ids" : {"chat_id": channel_id, "chat_name" : channel_name}}}
125 | prev = await self.col.find_one({'_id':group_id})
126 |
127 | if prev:
128 | await self.col.update_one({'_id':group_id}, update_d)
129 | await self.update_active(group_id, channel_id, channel_name)
130 | await self.refresh_cache(group_id)
131 |
132 | return True
133 |
134 | self.cache[str(group_id)] = new
135 |
136 | await self.col.insert_one(new)
137 | await self.add_active(group_id, channel_id, channel_name)
138 | await self.refresh_cache(group_id)
139 |
140 | return True
141 |
142 |
143 | async def del_chat(self, group_id: int, channel_id: int):
144 | """
145 | A Funtion to delete a channel and its files from db of a chat connection
146 | """
147 | group_id, channel_id = int(group_id), int(channel_id) # group_id and channel_id Didnt type casted to int for some reason
148 |
149 | prev = self.col.find_one({"_id": group_id})
150 |
151 | if prev:
152 |
153 | await self.col.update_one(
154 | {"_id": group_id},
155 | {"$pull" :
156 | {"chat_ids" :
157 | {"chat_id":
158 | channel_id
159 | }
160 | }
161 | }
162 | )
163 |
164 | await self.del_active(group_id, channel_id)
165 | await self.refresh_cache(group_id)
166 |
167 | return True
168 |
169 | return False
170 |
171 |
172 | async def in_db(self, group_id: int, channel_id: int):
173 | """
174 | Check whether if the given channel id is in db or not...
175 | """
176 | connections = self.cache.get(group_id)
177 |
178 | if connections is None:
179 | connections = await self.col.find_one({'_id': group_id})
180 |
181 | check_list = []
182 |
183 | if connections:
184 | for x in connections["chat_ids"]:
185 | check_list.append(int(x.get("chat_id")))
186 |
187 | if int(channel_id) in check_list:
188 | return True
189 |
190 | return False
191 |
192 |
193 | async def update_settings(self, group_id: int, settings):
194 | """
195 | A Funtion to update a chat's filter types in db
196 | """
197 | group_id = int(group_id)
198 | prev = await self.col.find_one({"_id": group_id})
199 |
200 | if prev:
201 | try:
202 | await self.col.update_one({"_id": group_id}, {"$set": {"types": settings}})
203 | await self.refresh_cache(group_id)
204 | return True
205 |
206 | except Exception as e:
207 | print (e)
208 | return False
209 | print("You Should First Connect To A Chat To Use This Funtion..... 'databse.py/#201' ")
210 | return False
211 |
212 |
213 | async def update_configs(self, group_id: int, configs):
214 | """
215 | A Funtion to update a chat's configs in db
216 | """
217 | prev = await self.col.find_one({"_id": group_id})
218 |
219 | if prev:
220 | try:
221 | await self.col.update_one(prev, {"$set":{"configs": configs}})
222 | await self.refresh_cache(group_id)
223 | return True
224 |
225 | except Exception as e:
226 | print (e)
227 | return False
228 | print("You Should First Connect To A Chat To Use This")
229 | return False
230 |
231 |
232 | async def delete_all(self, group_id: int):
233 | """
234 | A Funtion to delete all documents related to a
235 | chat from db
236 | """
237 | prev = await self.col.find_one({"_id": group_id})
238 | if prev:
239 | await self.delall_active(group_id)
240 | await self.delall_filters(group_id)
241 | await self.del_main(group_id)
242 | await self.refresh_cache(group_id)
243 |
244 | return
245 |
246 |
247 | async def del_main(self, group_id: int):
248 | """
249 | A Funtion To Delete the chat's main db document
250 | """
251 | await self.col.delete_one({"_id": group_id})
252 | await self.refresh_cache(group_id)
253 |
254 | return True
255 |
256 |
257 | async def refresh_cache(self, group_id: int):
258 | """
259 | A Funtion to refresh a chat's chase data
260 | in case of update in db
261 | """
262 | if self.cache.get(str(group_id)):
263 | self.cache.pop(str(group_id))
264 |
265 | prev = await self.col.find_one({"_id": group_id})
266 |
267 | if prev:
268 | self.cache[str(group_id)] = prev
269 | return True
270 |
271 | # Related To Finding Active Channel(s)
272 | async def add_active(self, group_id: int, channel_id: int, channel_name):
273 | """
274 | A Funtion to add a channel as an active chat the a connected group
275 | (This Funtion will be used only if its the first time)
276 | """
277 | templ = {"_id": group_id, "chats":[{"chat_id": channel_id, "chat_name": channel_name}]}
278 |
279 | try:
280 | await self.acol.insert_one(templ)
281 | await self.refresh_acache(group_id)
282 | except Exception as e:
283 | print(e)
284 | return False
285 |
286 | return True
287 |
288 |
289 | async def del_active(self, group_id: int, channel_id: int):
290 | """
291 | A funtion to delete a channel from active chat colletion in db
292 | """
293 | templ = {"$pull": {"chats": dict(chat_id = channel_id)}}
294 |
295 | try:
296 | await self.acol.update_one({"_id": group_id}, templ)
297 | except Exception as e:
298 | print(e)
299 | pass
300 |
301 | await self.refresh_acache(group_id)
302 | return True
303 |
304 |
305 | async def update_active(self, group_id: int, channel_id: int, channel_name):
306 | """
307 | A Funtion to add a new active chat to the connected group
308 | """
309 | group_id, channel_id = int(group_id), int(channel_id)
310 |
311 | prev = await self.acol.find_one({"_id": group_id})
312 | templ = {"$push" : {"chats" : dict(chat_id = channel_id, chat_name = channel_name)}}
313 | in_c = await self.in_active(group_id, channel_id)
314 |
315 | if prev:
316 | if not in_c:
317 | await self.acol.update_one({"_id": group_id}, templ)
318 | else:
319 | return False
320 | else:
321 | await self.add_active(group_id, channel_id, channel_name)
322 | return True
323 |
324 |
325 | async def find_active(self, group_id: int):
326 | """
327 | A Funtion to find all active chats of
328 | a group from db
329 | """
330 | if self.acache.get(str(group_id)):
331 | self.acache.get(str(group_id))
332 |
333 | connection = await self.acol.find_one({"_id": group_id})
334 |
335 | if connection:
336 | return connection
337 | return False
338 |
339 |
340 | async def in_active(self, group_id: int, channel_id: int):
341 | """
342 | A Funtion to check if a chat id is in the active
343 | chat id list in db
344 | """
345 | prev = await self.acol.find_one({"_id": group_id})
346 |
347 | if prev:
348 | for x in prev["chats"]:
349 | if x["chat_id"] == channel_id:
350 | return True
351 |
352 | return False
353 |
354 | return False
355 |
356 |
357 | async def delall_active(self, group_id: int):
358 | """
359 | A Funtion to Delete all active chats of
360 | a group from db
361 | """
362 | await self.acol.delete_one({"_id":int(group_id)})
363 | await self.refresh_acache(group_id)
364 | return
365 |
366 |
367 | async def refresh_acache(self, group_id: int):
368 | """
369 | A Funtion to refresh a active chat's chase data
370 | in case of update in db
371 | """
372 | if self.acache.get(str(group_id)):
373 | self.acache.pop(str(group_id))
374 |
375 | prev = await self.acol.find_one({"_id": group_id})
376 |
377 | if prev:
378 | self.acache[str(group_id)] = prev
379 | return True
380 |
381 | # Related To Finding Filter(s)
382 | async def add_filters(self, data):
383 | """
384 | A Funtion to add document as
385 | a bulk to db
386 | """
387 | try:
388 | await self.fcol.insert_many(data)
389 | except Exception as e:
390 | print(e)
391 |
392 | return True
393 |
394 |
395 | async def del_filters(self, group_id: int, channel_id: int):
396 | """
397 | A Funtion to delete all filters of a specific
398 | chat and group from db
399 | """
400 | group_id, channel_id = int(group_id), int(channel_id)
401 |
402 | try:
403 | await self.fcol.delete_many({"chat_id": channel_id, "group_id": group_id})
404 | print(await self.cf_count(group_id, channel_id))
405 | return True
406 | except Exception as e:
407 | print(e)
408 | return False
409 |
410 |
411 | async def delall_filters(self, group_id: int):
412 | """
413 | A Funtion To delete all filters of a group
414 | """
415 | await self.fcol.delete_many({"group_id": int(group_id)})
416 | return True
417 |
418 |
419 | async def get_filters(self, group_id: int, keyword: str):
420 | """
421 | A Funtion to fetch all similar results for a keyowrd
422 | from using text index
423 | """
424 | await self.create_index()
425 |
426 | chat = await self.find_chat(group_id)
427 | chat_accuracy = float(chat["configs"].get("accuracy", 0.80))
428 | achats = await self.find_active(group_id)
429 |
430 | achat_ids=[]
431 | if not achats:
432 | return False
433 |
434 | for chats in achats["chats"]:
435 | achat_ids.append(chats.get("chat_id"))
436 |
437 | filters = []
438 |
439 | pipeline= {
440 | 'group_id': int(group_id), '$text':{'$search': keyword}
441 | }
442 |
443 |
444 | db_list = self.fcol.find(
445 | pipeline,
446 | {'score': {'$meta':'textScore'}} # Makes A New Filed With Match Score In Each Document
447 | )
448 |
449 | db_list.sort([("score", {'$meta': 'textScore'})]) # Sort all document on the basics of the score field
450 |
451 | for document in await db_list.to_list(length=600):
452 | if document["score"] < chat_accuracy:
453 | continue
454 |
455 | if document["chat_id"] in achat_ids:
456 | filters.append(document)
457 | else:
458 | continue
459 |
460 | return filters
461 |
462 |
463 | async def get_file(self, unique_id: str):
464 | """
465 | A Funtion to get a specific files using its
466 | unique id
467 | """
468 | file = await self.fcol.find_one({"unique_id": unique_id})
469 | file_id = None
470 | file_type = None
471 | file_name = None
472 | file_caption = None
473 |
474 | if file:
475 | file_id = file.get("file_id")
476 | file_name = file.get("file_name")
477 | file_type = file.get("file_type")
478 | file_caption = file.get("file_caption")
479 | return file_id, file_name, file_caption, file_type
480 |
481 |
482 | async def cf_count(self, group_id: int, channel_id: int):
483 | """
484 | A Funtion To count number of filter in channel
485 | w.r.t the connect group
486 | """
487 | return await self.fcol.count_documents({"chat_id": channel_id, "group_id": group_id})
488 |
489 |
490 | async def tf_count(self, group_id: int):
491 | """
492 | A Funtion to count total filters of a group
493 | """
494 | return await self.fcol.count_documents({"group_id": group_id})
495 |
496 |
497 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc. {leng} Results For Your Query: {query}"
146 |
147 | try:
148 | await update.message.edit(
149 | text,
150 | reply_markup=reply_markup,
151 | parse_mode=enums.ParseMode.HTML
152 | )
153 |
154 | except FloodWait as f: # Flood Wait Caused By Spamming Next/Back Buttons
155 | await asyncio.sleep(f.value)
156 | await update.message.edit(
157 | text,
158 | reply_markup=reply_markup,
159 | parse_mode=enums.ParseMode.HTML
160 | )
161 |
162 |
163 |
164 | @Client.on_callback_query(filters.regex(r"settings"), group=2)
165 | async def cb_settings(bot, update: CallbackQuery):
166 | """
167 | A Callback Funtion For Back Button in /settings Command
168 | """
169 | global VERIFY
170 | chat_id = update.message.chat.id
171 | user_id = update.from_user.id
172 |
173 | if user_id not in VERIFY.get(str(chat_id)): # Check If User Is Admin
174 | return
175 |
176 | bot_status = await bot.get_me()
177 | bot_fname= bot_status.first_name
178 |
179 | text =f"{bot_fname}'s Settings Pannel.....\n"
180 | text+=f"\nYou Can Use This Menu To Change Connectivity And Know Status Of Your Every Connected Channel, Change Filter Types, Configure Filter Results And To Know Status Of Your Group..."
181 |
182 | buttons = [
183 | [
184 | InlineKeyboardButton
185 | (
186 | "Channels", callback_data=f"channel_list({chat_id})"
187 | ),
188 |
189 | InlineKeyboardButton
190 | (
191 | "Filter Types", callback_data=f"types({chat_id})"
192 | )
193 | ],
194 | [
195 | InlineKeyboardButton
196 | (
197 | "Configure 🛠", callback_data=f"config({chat_id})"
198 | )
199 | ],
200 | [
201 | InlineKeyboardButton
202 | (
203 | "Status", callback_data=f"status({chat_id})"
204 | ),
205 |
206 | InlineKeyboardButton
207 | (
208 | "About", callback_data=f"about({chat_id})"
209 | )
210 | ],
211 | [
212 | InlineKeyboardButton
213 | (
214 | "Close 🔐", callback_data="close"
215 | )
216 | ]
217 | ]
218 |
219 | reply_markup = InlineKeyboardMarkup(buttons)
220 |
221 | await update.message.edit_text(
222 | text,
223 | reply_markup=reply_markup,
224 | parse_mode=enums.ParseMode.HTML
225 | )
226 |
227 |
228 |
229 | @Client.on_callback_query(filters.regex(r"warn\((.+)\)"), group=2)
230 | async def cb_warn(bot, update: CallbackQuery):
231 | """
232 | A Callback Funtion For Acknowledging User's About What Are They Upto
233 | """
234 | global VERIFY
235 | query_data = update.data
236 | chat_id = update.message.chat.id
237 | chat_name = remove_emoji(update.message.chat.title)
238 | chat_name = chat_name.encode('ascii', 'ignore').decode('ascii')[:35]
239 | user_id = update.from_user.id
240 |
241 | if user_id not in VERIFY.get(str(chat_id)):
242 | return
243 |
244 | channel_id, channel_name, action = re.findall(r"warn\((.+)\)", query_data)[0].split("|", 2)
245 |
246 | if action == "connect":
247 | text=f"Are You Sure You Want To Enable Connection With {channel_name}..???\n"
248 | text+=f"\nThis Will Show File Links From {channel_name} While Showing Results..."
249 |
250 | elif action == "disconnect":
251 | text=f"Are You Sure You Want To Disable {channel_name} Connection With The Group???....\n"
252 | text+=f"\nThe DB Files Will Still Be There And You Can Connect Back To This Channel Anytime From Settings Menu Without Adding Files To DB Again...\n"
253 | text+=f"\nThis Disabling Just Hide Results From The Filter Results..."
254 |
255 | elif action == "c_delete":
256 | text=f"Are You Sure You Want To Disconnect {channel_name} From This Group??\n"
257 | text+=f"\nThis Will Delete Channel And All Its Files From DB Too....!!\n"
258 | text+=f"\nYou Need To Add Channel Again If You Need To Shows It Result..."
259 |
260 |
261 | elif action=="f_delete":
262 | text=f"Are You Sure That You Want To Clear All Filter From This Chat {channel_name}???\n"
263 | text+=f"\nThis Will Erase All Files From DB.."
264 |
265 | buttons = [
266 | [
267 | InlineKeyboardButton
268 | (
269 | "Yes", callback_data=f"{action}({channel_id}|{channel_name})"
270 | ),
271 |
272 | InlineKeyboardButton
273 | (
274 | "No", callback_data="close"
275 | )
276 | ]
277 | ]
278 |
279 | reply_markup = InlineKeyboardMarkup(buttons)
280 |
281 | await update.message.edit_text(
282 | text,
283 | reply_markup=reply_markup,
284 | parse_mode=enums.ParseMode.HTML
285 | )
286 |
287 |
288 |
289 | @Client.on_callback_query(filters.regex(r"channel_list\((.+)\)"), group=2)
290 | async def cb_channel_list(bot, update: CallbackQuery):
291 | """
292 | A Callback Funtion For Displaying All Channel List And Providing A Menu To Navigate
293 | To Every COnnect Chats For Furthur Control
294 | """
295 | global VERIFY
296 | query_data = update.data
297 | chat_id = update.message.chat.id
298 | chat_name = remove_emoji(update.message.chat.title)
299 | chat_name = chat_name.encode('ascii', 'ignore').decode('ascii')[:35]
300 | user_id = update.from_user.id
301 |
302 | if user_id not in VERIFY.get(str(chat_id)):
303 | return
304 |
305 | chat_id = re.findall(r"channel_list\((.+)\)", query_data)[0]
306 |
307 | text = "Semms Like You Dont Have Any Channel Connected...\n\nConnect To Any Chat To Continue With This Settings..."
308 |
309 | db_list = await db.find_chat(int(chat_id))
310 |
311 | channel_id_list = []
312 | channel_name_list = []
313 |
314 | if db_list:
315 | for x in db_list["chat_ids"]:
316 | channel_id = x["chat_id"]
317 | channel_name = x["chat_name"]
318 |
319 | try:
320 | if (channel_id == None or channel_name == None):
321 | continue
322 | except:
323 | break
324 |
325 | channel_name = remove_emoji(channel_name).encode('ascii', 'ignore').decode('ascii')[:35]
326 | channel_id_list.append(channel_id)
327 | channel_name_list.append(channel_name)
328 |
329 | buttons = []
330 |
331 | buttons.append(
332 | [
333 | InlineKeyboardButton
334 | (
335 | "🔙 Back", callback_data="settings"
336 | ),
337 |
338 | InlineKeyboardButton
339 | (
340 | "Close 🔐", callback_data="close"
341 | )
342 | ]
343 | )
344 |
345 | if channel_name_list:
346 |
347 | text=f"List Of Connected Channels With {chat_name} With There Settings..\n"
348 |
349 | for x in range(1, (len(channel_name_list)+1)):
350 | text+=f"\n{x}. {channel_name_list[x-1]}\n"
351 |
352 | text += "\nChoose Appropriate Buttons To Navigate Through Respective Channels"
353 |
354 |
355 | btn_key = [
356 | "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟",
357 | "1️⃣1️⃣", "1️⃣2️⃣", "1️⃣3️⃣", "1️⃣4️⃣", "1️⃣5️⃣", "1️⃣6️⃣", "1️⃣7️⃣",
358 | "1️⃣8️⃣", "1️⃣9️⃣", "2️⃣0️⃣" # Just In Case 😂🤣
359 | ]
360 |
361 | for i in range(1, (len(channel_name_list) + 1)): # Append The Index Number of Channel In Just A Single Line
362 | if i == 1:
363 | buttons.insert(0,
364 | [
365 | InlineKeyboardButton
366 | (
367 | btn_key[i-1], callback_data=f"info({channel_id_list[i-1]}|{channel_name_list[i-1]})"
368 | )
369 | ]
370 | )
371 |
372 | else:
373 | buttons[0].append(
374 | InlineKeyboardButton
375 | (
376 | btn_key[i-1], callback_data=f"info({channel_id_list[i-1]}|{channel_name_list[i-1]})"
377 | )
378 | )
379 |
380 | reply_markup=InlineKeyboardMarkup(buttons)
381 |
382 | await update.message.edit_text(
383 | text = text,
384 | reply_markup=reply_markup,
385 | parse_mode=enums.ParseMode.HTML
386 | )
387 |
388 |
389 |
390 | @Client.on_callback_query(filters.regex(r"info\((.+)\)"), group=2)
391 | async def cb_info(bot, update: CallbackQuery):
392 | """
393 | A Callback Funtion For Displaying Details Of The Connected Chat And Provide
394 | Ability To Connect / Disconnect / Delete / Delete Filters of That Specific Chat
395 | """
396 | global VERIFY
397 | query_data = update.data
398 | chat_id = update.message.chat.id
399 | user_id = update.from_user.id
400 |
401 | if user_id not in VERIFY.get(str(chat_id)):
402 | return
403 |
404 | channel_id, channel_name = re.findall(r"info\((.+)\)", query_data)[0].split("|", 1)
405 |
406 | f_count = await db.cf_count(chat_id, int(channel_id))
407 | active_chats = await db.find_active(chat_id)
408 |
409 | if active_chats: # Checks for active chats connected to a chat
410 | dicts = active_chats["chats"]
411 | db_cids = [ int(x["chat_id"]) for x in dicts ]
412 |
413 | if int(channel_id) in db_cids:
414 | active_chats = True
415 | status = "Connected"
416 |
417 | else:
418 | active_chats = False
419 | status = "Disconnected"
420 |
421 | else:
422 | active_chats = False
423 | status = "Disconnected"
424 |
425 | text=f"Info About {channel_name}\n"
426 | text+=f"\nChannel Name: {channel_name}\n"
427 | text+=f"\nChannel ID: {channel_id}\n"
428 | text+=f"\nChannel Files: {f_count}\n"
429 | text+=f"\nCurrent Status: {status}\n"
430 |
431 |
432 | if active_chats:
433 | buttons = [
434 | [
435 | InlineKeyboardButton
436 | (
437 | "🚨 Disconnect 🚨", callback_data=f"warn({channel_id}|{channel_name}|disconnect)"
438 | ),
439 |
440 | InlineKeyboardButton
441 | (
442 | "Delete ❌", callback_data=f"warn({channel_id}|{channel_name}|c_delete)"
443 | )
444 | ]
445 | ]
446 |
447 | else:
448 | buttons = [
449 | [
450 | InlineKeyboardButton
451 | (
452 | "💠 Connect 💠", callback_data=f"warn({channel_id}|{channel_name}|connect)"
453 | ),
454 |
455 | InlineKeyboardButton
456 | (
457 | "Delete ❌", callback_data=f"warn({channel_id}|{channel_name}|c_delete)"
458 | )
459 | ]
460 | ]
461 |
462 | buttons.append(
463 | [
464 | InlineKeyboardButton
465 | (
466 | "Delete Filters ⚠", callback_data=f"warn({channel_id}|{channel_name}|f_delete)"
467 | )
468 | ]
469 | )
470 |
471 | buttons.append(
472 | [
473 | InlineKeyboardButton
474 | (
475 | "🔙 Back", callback_data=f"channel_list({chat_id})"
476 | )
477 | ]
478 | )
479 |
480 | reply_markup = InlineKeyboardMarkup(buttons)
481 |
482 | await update.message.edit_text(
483 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
484 | )
485 |
486 |
487 |
488 | @Client.on_callback_query(filters.regex(r"^connect\((.+)\)"), group=2)
489 | async def cb_connect(bot, update: CallbackQuery):
490 | """
491 | A Callback Funtion Helping The user To Make A Chat Active Chat Which Will
492 | Make The Bot To Fetch Results From This Channel Too
493 | """
494 | global VERIFY
495 | query_data = update.data
496 | chat_id = update.message.chat.id
497 | user_id = update.from_user.id
498 |
499 |
500 | if user_id not in VERIFY.get(str(chat_id)):
501 | return
502 |
503 | channel_id, channel_name = re.findall(r"connect\((.+)\)", query_data)[0].split("|", 1)
504 | channel_id = int(channel_id)
505 |
506 | f_count = await db.cf_count(chat_id, channel_id)
507 |
508 | add_active = await db.update_active(chat_id, channel_id, channel_name)
509 |
510 | if not add_active:
511 | await update.answer(f"{channel_name} Is Aldready in Active Connection", show_alert=True)
512 | return
513 |
514 | text= f"Sucessfully Connected To {channel_name}\n"
515 | text+=f"\nInfo About {channel_name}\n"
516 | text+=f"\nChannel Name: {channel_name}\n"
517 | text+=f"\nChannel ID: {channel_id}\n"
518 | text+=f"\nChannel Files: {f_count}\n"
519 | text+=f"\nCurrent Status: Connected\n"
520 |
521 | buttons = [
522 | [
523 | InlineKeyboardButton
524 | (
525 | "🚨 Disconnect 🚨", callback_data=f"warn({channel_id}|{channel_name}|disconnect)"
526 | ),
527 |
528 | InlineKeyboardButton
529 | (
530 | "Delete ❌", callback_data=f"warn({channel_id}|{channel_name}|c_delete)"
531 | )
532 | ]
533 | ]
534 |
535 | buttons.append(
536 | [
537 | InlineKeyboardButton
538 | (
539 | "Delete Filters ⚠", callback_data=f"warn({channel_id}|{channel_name}|f_delete)"
540 | )
541 | ]
542 | )
543 |
544 | buttons.append(
545 | [
546 | InlineKeyboardButton
547 | (
548 | "🔙 Back", callback_data=f"channel_list({chat_id})"
549 | )
550 | ]
551 | )
552 | await recacher(chat_id, False, True, bot, update)
553 |
554 | reply_markup = InlineKeyboardMarkup(buttons)
555 |
556 | await update.message.edit_text(
557 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
558 | )
559 |
560 |
561 |
562 | @Client.on_callback_query(filters.regex(r"disconnect\((.+)\)"), group=2)
563 | async def cb_disconnect(bot, update: CallbackQuery):
564 | """
565 | A Callback Funtion Helping The user To Make A Chat inactive Chat Which Will
566 | Make The Bot To Avoid Fetching Results From This Channel
567 | """
568 | global VERIFY
569 | query_data = update.data
570 | chat_id = update.message.chat.id
571 | user_id = update.from_user.id
572 |
573 | if user_id not in VERIFY.get(str(chat_id)):
574 | return
575 |
576 | channel_id, channel_name = re.findall(r"connect\((.+)\)", query_data)[0].split("|", 1)
577 |
578 | f_count = await db.cf_count(chat_id, int(channel_id))
579 |
580 | remove_active = await db.del_active(chat_id, int(channel_id))
581 |
582 | if not remove_active:
583 | await update.answer("Couldnt Full Fill YOur Request...\n Report This @CrazyBotszGrp Along With Bot's Log", show_alert=True)
584 | return
585 |
586 | text= f"Sucessfully Disconnected From {channel_name}\n"
587 | text+=f"\nInfo About {channel_name}\n"
588 | text+=f"\nChannel Name: {channel_name}\n"
589 | text+=f"\nChannel ID: {channel_id}\n"
590 | text+=f"\nChannel Files: {f_count}\n"
591 | text+=f"\nCurrent Status: Disconnected\n"
592 |
593 | buttons = [
594 | [
595 | InlineKeyboardButton
596 | (
597 | "💠 Connect 💠", callback_data=f"warn({channel_id}|{channel_name}|connect)"
598 | ),
599 |
600 | InlineKeyboardButton
601 | (
602 | "Delete ❌", callback_data=f"warn({channel_id}|{channel_name}|c_delete)"
603 | )
604 | ]
605 | ]
606 |
607 | buttons.append(
608 | [
609 | InlineKeyboardButton
610 | (
611 | "Delete Filters ⚠", callback_data=f"warn({channel_id}|{channel_name}|f_delete)"
612 | )
613 | ]
614 | )
615 |
616 | buttons.append(
617 | [
618 | InlineKeyboardButton
619 | (
620 | "🔙 Back", callback_data=f"channel_list({chat_id})"
621 | )
622 | ]
623 | )
624 |
625 | reply_markup = InlineKeyboardMarkup(buttons)
626 |
627 | await recacher(chat_id, False, True, bot, update)
628 |
629 | await update.message.edit_text(
630 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
631 | )
632 |
633 |
634 |
635 | @Client.on_callback_query(filters.regex(r"c_delete\((.+)\)"), group=2)
636 | async def cb_channel_delete(bot, update: CallbackQuery):
637 | """
638 | A Callback Funtion For Delete A Channel Connection From A Group Chat History
639 | Along With All Its Filter Files
640 | """
641 | global VERIFY
642 | query_data = update.data
643 | chat_id = update.message.chat.id
644 | user_id = update.from_user.id
645 |
646 | if user_id not in VERIFY.get(str(chat_id)):
647 | return
648 |
649 | channel_id, channel_name = re.findall(r"c_delete\((.+)\)", query_data)[0].split("|", 1)
650 | channel_id = int(channel_id)
651 |
652 | c_delete = await db.del_chat(chat_id, channel_id)
653 | a_delete = await db.del_active(chat_id, channel_id) # pylint: disable=unused-variable
654 | f_delete = await db.del_filters(chat_id, channel_id)
655 |
656 | if (c_delete and f_delete ):
657 | text=f"{channel_name} [ {channel_id} ] Has Been Sucessfully Deleted And All Its Files Were Cleared From DB...."
658 |
659 | else:
660 | text=f"Couldn't Delete Channel And All Its Files From DB Sucessfully....\nPlease Try Again After Sometimes...Also Make Sure To Check The Logs..!!"
661 | await update.answer(text=text, show_alert=True)
662 |
663 | buttons = [
664 | [
665 | InlineKeyboardButton
666 | (
667 | "🔙 Back", callback_data=f"channel_list({chat_id})"
668 | ),
669 |
670 | InlineKeyboardButton
671 | (
672 | "Close 🔐", callback_data="close"
673 | )
674 | ]
675 | ]
676 |
677 | await recacher(chat_id, True, True, bot, update)
678 |
679 | reply_markup=InlineKeyboardMarkup(buttons)
680 |
681 | await update.message.edit_text(
682 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
683 | )
684 |
685 |
686 |
687 | @Client.on_callback_query(filters.regex(r"f_delete\((.+)\)"), group=2)
688 | async def cb_filters_delete(bot, update: CallbackQuery):
689 | """
690 | A Callback Funtion For Delete A Specific Channel's Filters Connected To A Group
691 | """
692 | global VERIFY
693 | query_data = update.data
694 | chat_id = update.message.chat.id
695 | user_id = update.from_user.id
696 |
697 | if user_id not in VERIFY.get(str(chat_id)):
698 | return
699 |
700 | channel_id, channel_name = re.findall(r"f_delete\((.+)\)", query_data)[0].split("|", 1)
701 |
702 | f_delete = await db.del_filters(chat_id, int(channel_id))
703 |
704 | if not f_delete:
705 | text="Oops..!!\n\nEncountered Some Error While Deleteing Filters....\nPlease Check The Logs...."
706 | await update.answer(text=text, show_alert=True)
707 | return
708 |
709 | text =f"All Filters Of {channel_id}[{channel_name}] Has Been Deleted Sucessfully From My DB.."
710 |
711 | buttons=[
712 | [
713 | InlineKeyboardButton
714 | (
715 | "Back", callback_data="settings"
716 | ),
717 |
718 | InlineKeyboardButton
719 | (
720 | "Close", callback_data="close"
721 | )
722 | ]
723 | ]
724 |
725 | reply_markup = InlineKeyboardMarkup(buttons)
726 |
727 | await update.message.edit_text(
728 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
729 | )
730 |
731 |
732 |
733 | @Client.on_callback_query(filters.regex(r"types\((.+)\)"), group=2)
734 | async def cb_types(bot, update: CallbackQuery):
735 | """
736 | A Callback Funtion For Changing The Result Types To Be Shown In While Sending Results
737 | """
738 | global VERIFY
739 | query_data = update.data
740 | chat_id = update.message.chat.id
741 | chat_name = remove_emoji(update.message.chat.title)
742 | user_id = update.from_user.id
743 |
744 | if user_id not in VERIFY.get(str(chat_id)):
745 | return
746 |
747 | chat_id = re.findall(r"types\((.+)\)", query_data)[0]
748 |
749 | _types = await db.find_chat(int(chat_id))
750 |
751 | text=f"Filter Types Enabled/Disbled In {chat_name}\n"
752 |
753 | _types = _types["types"]
754 | vid = _types["video"]
755 | doc = _types["document"]
756 | aud = _types["audio"]
757 |
758 | buttons = []
759 |
760 | if vid:
761 | text+="\nVideo Index: Enabled\n"
762 | v_e = "✅"
763 | vcb_data = f"toggle({chat_id}|video|False)"
764 |
765 | else:
766 | text+="\nVideo Index: Disabled\n"
767 | v_e="❎"
768 | vcb_data = f"toggle({chat_id}|video|True)"
769 |
770 | if doc:
771 | text+="\nDocument Index: Enabled\n"
772 | d_e = "✅"
773 | dcb_data = f"toggle({chat_id}|document|False)"
774 |
775 | else:
776 | text+="\nDocument Index: Disabled\n"
777 | d_e="❎"
778 | dcb_data = f"toggle({chat_id}|document|True)"
779 |
780 | if aud:
781 | text+="\nAudio Index: Enabled\n"
782 | a_e = "✅"
783 | acb_data = f"toggle({chat_id}|audio|False)"
784 |
785 | else:
786 | text+="\nAudio Index: Disabled\n"
787 | a_e="❎"
788 | acb_data = f"toggle({chat_id}|audio|True)"
789 |
790 |
791 | text+="\nBelow Buttons Will Toggle Respective Media Types As Enabled Or Disabled....\n"
792 | text+="This Will Take Into Action As Soon As You Change Them...."
793 |
794 | buttons.append([InlineKeyboardButton(f"Video Index: {v_e}", callback_data=vcb_data)])
795 | buttons.append([InlineKeyboardButton(f"Audio Index: {a_e}", callback_data=acb_data)])
796 | buttons.append([InlineKeyboardButton(f"Document Index: {d_e}", callback_data=dcb_data)])
797 |
798 | buttons.append(
799 | [
800 | InlineKeyboardButton
801 | (
802 | "🔙 Back", callback_data=f"settings"
803 | )
804 | ]
805 | )
806 |
807 | reply_markup = InlineKeyboardMarkup(buttons)
808 |
809 | await update.message.edit_text(
810 | text,
811 | reply_markup=reply_markup,
812 | parse_mode=enums.ParseMode.HTML
813 | )
814 |
815 |
816 |
817 | @Client.on_callback_query(filters.regex(r"toggle\((.+)\)"), group=2)
818 | async def cb_toggle(bot, update: CallbackQuery):
819 | """
820 | A Callback Funtion Support handler For types()
821 | """
822 | global VERIFY
823 | query_data = update.data
824 | chat_id = update.message.chat.id
825 | user_id = update.from_user.id
826 |
827 | if user_id not in VERIFY.get(str(chat_id)):
828 | return
829 |
830 | chat_id, types, val = re.findall(r"toggle\((.+)\)", query_data)[0].split("|", 2)
831 |
832 | _types = await db.find_chat(int(chat_id))
833 |
834 | _types = _types["types"]
835 | vid = _types["video"]
836 | doc = _types["document"]
837 | aud = _types["audio"]
838 |
839 | if types == "video":
840 | vid = True if val=="True" else False
841 | elif types == "audio":
842 | aud = True if val=="True" else False
843 | elif types == "document":
844 | doc = True if val=="True" else False
845 |
846 |
847 | settings = {
848 | "video": vid,
849 | "audio": aud,
850 | "document": doc
851 | }
852 |
853 | process = await db.update_settings(chat_id, settings)
854 |
855 | if process:
856 | await update.answer(text="Filter Types Updated Sucessfully", show_alert=True)
857 |
858 | else:
859 | text="Something Wrong Please Check Bot Log For More Information...."
860 | await update.answer(text, show_alert=True)
861 | return
862 |
863 | _types = await db.find_chat(int(chat_id))
864 |
865 | text =f"Filter Types Enabled In {update.message.chat.title}\n"
866 |
867 | _types = _types["types"]
868 | vid = _types["video"]
869 | doc = _types["document"]
870 | aud = _types["audio"]
871 |
872 | buttons = []
873 |
874 | if vid:
875 | text+="\nVideo Index: Enabled\n"
876 | v_e = "✅"
877 | vcb_data = f"toggle({chat_id}|video|False)"
878 |
879 | else:
880 | text+="\nVideo Index: Disabled\n"
881 | v_e="❎"
882 | vcb_data = f"toggle({chat_id}|video|True)"
883 |
884 | if doc:
885 | text+="\nDocument Index: Enabled\n"
886 | d_e = "✅"
887 | dcb_data = f"toggle({chat_id}|document|False)"
888 |
889 | else:
890 | text+="\nDocument Index: Disabled\n"
891 | d_e="❎"
892 | dcb_data = f"toggle({chat_id}|document|True)"
893 |
894 | if aud:
895 | text+="\nAudio Index: Enabled\n"
896 | a_e = "✅"
897 | acb_data = f"toggle({chat_id}|audio|False)"
898 |
899 | else:
900 | text+="\nAudio Index: Disabled\n"
901 | a_e="❎"
902 | acb_data = f"toggle({chat_id}|audio|True)"
903 |
904 |
905 | text+="\nBelow Buttons Will Toggle Respective Media Types As Enabled Or Disabled....\n"
906 | text+="This Will Take Into Action As Soon As You Change Them...."
907 |
908 | buttons.append([InlineKeyboardButton(f"Video Index : {v_e}", callback_data=vcb_data)])
909 | buttons.append([InlineKeyboardButton(f"Audio Index : {a_e}", callback_data=acb_data)])
910 | buttons.append([InlineKeyboardButton(f"Document Index : {d_e}", callback_data=dcb_data)])
911 |
912 | buttons.append(
913 | [
914 | InlineKeyboardButton
915 | (
916 | "🔙 Back", callback_data=f"settings"
917 | )
918 | ]
919 | )
920 |
921 | reply_markup = InlineKeyboardMarkup(buttons)
922 |
923 | await update.message.edit_text(
924 | text,
925 | reply_markup=reply_markup,
926 | parse_mode=enums.ParseMode.HTML
927 | )
928 |
929 |
930 |
931 | @Client.on_callback_query(filters.regex(r"config\((.+)\)"), group=2)
932 | async def cb_config(bot, update: CallbackQuery):
933 | """
934 | A Callback Funtion For Chaning The Number Of Total Pages /
935 | Total Results / Results Per pages / Enable or Diable Invite Link /
936 | Enable or Disable PM File Chat
937 | """
938 | global VERIFY
939 | query_data = update.data
940 | chat_id = update.message.chat.id
941 | chat_name = remove_emoji(update.message.chat.title)
942 | user_id = update.from_user.id
943 |
944 | if user_id not in VERIFY.get(str(chat_id)):
945 | return
946 |
947 | chat_id = re.findall(r"config\((.+)\)", query_data)[0]
948 |
949 | settings = await db.find_chat(int(chat_id))
950 |
951 | mp_count = settings["configs"]["max_pages"]
952 | mf_count = settings["configs"]["max_results"]
953 | mr_count = settings["configs"]["max_per_page"]
954 | show_invite = settings["configs"]["show_invite_link"]
955 | pm_file_chat = settings["configs"].get("pm_fchat", False)
956 | accuracy_point = settings["configs"].get("accuracy", 0.80)
957 |
958 | text=f"Configure Your {chat_name} Group's Filter Settings...\n"
959 |
960 | text+=f"\n{chat_name} Current Settings:\n"
961 |
962 | text+=f"\n - Max Filter: {mf_count}\n"
963 |
964 | text+=f"\n - Max Pages: {mp_count}\n"
965 |
966 | text+=f"\n - Max Filter Per Page: {mr_count}\n"
967 |
968 | text+=f"\n - Accuracy Percentage: {accuracy_point}\n"
969 |
970 | text+=f"\n - Show Invitation Link: {show_invite}\n"
971 |
972 | text+=f"\n - Provide File In Bot PM: {pm_file_chat}\n"
973 |
974 | text+="\nAdjust Above Value Using Buttons Below... "
975 | buttons=[
976 | [
977 | InlineKeyboardButton
978 | (
979 | "Filter Per Page", callback_data=f"mr_count({mr_count}|{chat_id})"
980 | ),
981 |
982 | InlineKeyboardButton
983 | (
984 | "Max Pages", callback_data=f"mp_count({mp_count}|{chat_id})"
985 | )
986 | ]
987 | ]
988 |
989 |
990 | buttons.append(
991 | [
992 | InlineKeyboardButton
993 | (
994 | "Total Filter Count", callback_data=f"mf_count({mf_count}|{chat_id})"
995 | )
996 | ]
997 | )
998 |
999 |
1000 | buttons.append(
1001 | [
1002 | InlineKeyboardButton
1003 | (
1004 | "Show Invite Links", callback_data=f"show_invites({show_invite}|{chat_id})"
1005 | ),
1006 |
1007 | InlineKeyboardButton
1008 | (
1009 | "Bot File Chat", callback_data=f"inPM({pm_file_chat}|{chat_id})"
1010 | )
1011 | ]
1012 | )
1013 |
1014 |
1015 | buttons.append(
1016 | [
1017 | InlineKeyboardButton
1018 | (
1019 | "Result's Accuracy", callback_data=f"accuracy({accuracy_point}|{chat_id})"
1020 | )
1021 | ]
1022 | )
1023 |
1024 |
1025 | buttons.append(
1026 | [
1027 | InlineKeyboardButton
1028 | (
1029 | "🔙 Back", callback_data=f"settings"
1030 | )
1031 | ]
1032 | )
1033 |
1034 |
1035 | reply_markup=InlineKeyboardMarkup(buttons)
1036 |
1037 | await update.message.edit_text(
1038 | text,
1039 | reply_markup=reply_markup,
1040 | parse_mode=enums.ParseMode.HTML
1041 | )
1042 |
1043 |
1044 |
1045 | @Client.on_callback_query(filters.regex(r"mr_count\((.+)\)"), group=2)
1046 | async def cb_max_buttons(bot, update: CallbackQuery):
1047 | """
1048 | A Callback Funtion For Changing The Count Of Result To Be Shown Per Page
1049 | """
1050 | global VERIFY
1051 | query_data = update.data
1052 | chat_id = update.message.chat.id
1053 | chat_name = remove_emoji(update.message.chat.title)
1054 | user_id = update.from_user.id
1055 |
1056 | if user_id not in VERIFY.get(str(chat_id)):
1057 | return
1058 |
1059 | count, chat_id = re.findall(r"mr_count\((.+)\)", query_data)[0].split("|", 1)
1060 |
1061 | text = f"Choose Your Desired 'Max Filter Count Per Page' For Every Filter Results Shown In {chat_name}"
1062 |
1063 | buttons = [
1064 | [
1065 | InlineKeyboardButton
1066 | (
1067 | "5 Filters", callback_data=f"set(per_page|5|{chat_id}|{count})"
1068 | )
1069 | ],
1070 | [
1071 | InlineKeyboardButton
1072 | (
1073 | "10 Filters", callback_data=f"set(per_page|10|{chat_id}|{count})"
1074 | )
1075 | ],
1076 | [
1077 | InlineKeyboardButton
1078 | (
1079 | "15 Filters", callback_data=f"set(per_page|15|{chat_id}|{count})"
1080 | )
1081 | ],
1082 | [
1083 | InlineKeyboardButton
1084 | (
1085 | "20 Filters", callback_data=f"set(per_page|20|{chat_id}|{count})"
1086 | )
1087 | ],
1088 | [
1089 | InlineKeyboardButton
1090 | (
1091 | "25 Filters", callback_data=f"set(per_page|25|{chat_id}|{count})"
1092 | )
1093 | ],
1094 | [
1095 | InlineKeyboardButton
1096 | (
1097 | "30 Filters", callback_data=f"set(per_page|30|{chat_id}|{count})"
1098 | )
1099 | ],
1100 | [
1101 | InlineKeyboardButton
1102 | (
1103 | "🔙 Back", callback_data=f"config({chat_id})"
1104 | )
1105 | ]
1106 | ]
1107 |
1108 | reply_markup = InlineKeyboardMarkup(buttons)
1109 |
1110 | await update.message.edit_text(
1111 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1112 | )
1113 |
1114 |
1115 |
1116 | @Client.on_callback_query(filters.regex(r"mp_count\((.+)\)"), group=2)
1117 | async def cb_max_page(bot, update: CallbackQuery):
1118 | """
1119 | A Callback Funtion For Changing The Count Of Maximum Result Pages To Be Shown
1120 | """
1121 | global VERIFY
1122 | query_data = update.data
1123 | chat_id = update.message.chat.id
1124 | chat_name = remove_emoji(update.message.chat.title)
1125 | user_id = update.from_user.id
1126 |
1127 | if user_id not in VERIFY.get(str(chat_id)):
1128 | return
1129 |
1130 | count, chat_id = re.findall(r"mp_count\((.+)\)", query_data)[0].split("|", 1)
1131 |
1132 | text = f"Choose Your Desired 'Max Filter Page Count' For Every Filter Results Shown In {chat_name}"
1133 |
1134 | buttons = [
1135 |
1136 | [
1137 | InlineKeyboardButton
1138 | (
1139 | "2 Pages", callback_data=f"set(pages|2|{chat_id}|{count})"
1140 | )
1141 | ],
1142 | [
1143 | InlineKeyboardButton
1144 | (
1145 | "4 Pages", callback_data=f"set(pages|4|{chat_id}|{count})"
1146 | )
1147 | ],
1148 | [
1149 | InlineKeyboardButton
1150 | (
1151 | "6 Pages", callback_data=f"set(pages|6|{chat_id}|{count})"
1152 | )
1153 | ],
1154 | [
1155 | InlineKeyboardButton
1156 | (
1157 | "8 Pages", callback_data=f"set(pages|8|{chat_id}|{count})"
1158 | )
1159 | ],
1160 | [
1161 | InlineKeyboardButton
1162 | (
1163 | "10 Pages", callback_data=f"set(pages|10|{chat_id}|{count})"
1164 | )
1165 | ],
1166 | [
1167 | InlineKeyboardButton
1168 | (
1169 | "🔙 Back", callback_data=f"config({chat_id})"
1170 | )
1171 | ]
1172 |
1173 | ]
1174 |
1175 | reply_markup = InlineKeyboardMarkup(buttons)
1176 |
1177 | await update.message.edit_text(
1178 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1179 | )
1180 |
1181 |
1182 |
1183 | @Client.on_callback_query(filters.regex(r"mf_count\((.+)\)"), group=2)
1184 | async def cb_max_results(bot, update: CallbackQuery):
1185 | """
1186 | A Callback Funtion For Changing The Count Of Maximum Files TO Be Fetched From Database
1187 | """
1188 | global VERIFY
1189 | query_data = update.data
1190 | chat_id = update.message.chat.id
1191 | chat_name = remove_emoji(update.message.chat.title)
1192 | user_id = update.from_user.id
1193 |
1194 | if user_id not in VERIFY.get(str(chat_id)):
1195 | return
1196 |
1197 | count, chat_id = re.findall(r"mf_count\((.+)\)", query_data)[0].split("|", 1)
1198 |
1199 | text = f"Choose Your Desired 'Max Filter' To Be Fetched From DB For Every Filter Results Shown In {chat_name}"
1200 |
1201 | buttons = [
1202 |
1203 | [
1204 | InlineKeyboardButton
1205 | (
1206 | "50 Results", callback_data=f"set(results|50|{chat_id}|{count})"
1207 | )
1208 | ],
1209 | [
1210 | InlineKeyboardButton
1211 | (
1212 | "100 Results", callback_data=f"set(results|100|{chat_id}|{count})"
1213 | )
1214 | ],
1215 | [
1216 | InlineKeyboardButton
1217 | (
1218 | "150 Results", callback_data=f"set(results|150|{chat_id}|{count})"
1219 | )
1220 | ],
1221 | [
1222 | InlineKeyboardButton
1223 | (
1224 | "200 Results", callback_data=f"set(results|200|{chat_id}|{count})"
1225 | )
1226 | ],
1227 | [
1228 | InlineKeyboardButton
1229 | (
1230 | "250 Results", callback_data=f"set(results|250|{chat_id}|{count})"
1231 | )
1232 | ],
1233 | [
1234 | InlineKeyboardButton
1235 | (
1236 | "300 Results", callback_data=f"set(results|300|{chat_id}|{count})"
1237 | )
1238 | ],
1239 | [
1240 | InlineKeyboardButton
1241 | (
1242 | "🔙 Back", callback_data=f"config({chat_id})"
1243 | )
1244 | ]
1245 | ]
1246 |
1247 | reply_markup = InlineKeyboardMarkup(buttons)
1248 |
1249 | await update.message.edit_text(
1250 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1251 | )
1252 |
1253 |
1254 |
1255 | @Client.on_callback_query(filters.regex(r"show_invites\((.+)\)"), group=2)
1256 | async def cb_show_invites(bot, update: CallbackQuery):
1257 | """
1258 | A Callback Funtion For Enabling Or Diabling Invite Link Buttons
1259 | """
1260 | global VERIFY
1261 | query_data = update.data
1262 | chat_id = update.message.chat.id
1263 | user_id = update.from_user.id
1264 |
1265 | if user_id not in VERIFY.get(str(chat_id)):
1266 | return
1267 |
1268 | value, chat_id = re.findall(r"show_invites\((.+)\)", query_data)[0].split("|", 1)
1269 |
1270 | value = True if value=="True" else False
1271 |
1272 | if value:
1273 | buttons= [
1274 | [
1275 | InlineKeyboardButton
1276 | (
1277 | "Disable ❌", callback_data=f"set(showInv|False|{chat_id}|{value})"
1278 | )
1279 | ],
1280 | [
1281 | InlineKeyboardButton
1282 | (
1283 | "Back 🔙", callback_data=f"config({chat_id})"
1284 | )
1285 | ]
1286 | ]
1287 |
1288 | else:
1289 | buttons =[
1290 | [
1291 | InlineKeyboardButton
1292 | (
1293 | "Enable ✔", callback_data=f"set(showInv|True|{chat_id}|{value})"
1294 | )
1295 | ],
1296 | [
1297 | InlineKeyboardButton
1298 | (
1299 | "Back 🔙", callback_data=f"config({chat_id})"
1300 | )
1301 | ]
1302 | ]
1303 |
1304 | text=f"This Config Will Help You To Show Invitation Link Of All Active Chats Along With The Filter Results For The Users To Join....."
1305 |
1306 | reply_markup=InlineKeyboardMarkup(buttons)
1307 |
1308 | await update.message.edit_text(
1309 | text,
1310 | reply_markup=reply_markup,
1311 | parse_mode=enums.ParseMode.HTML
1312 | )
1313 |
1314 |
1315 |
1316 | @Client.on_callback_query(filters.regex(r"inPM\((.+)\)"), group=2)
1317 | async def cb_pm_file(bot, update: CallbackQuery):
1318 | """
1319 | A Callback Funtion For Enabling Or Diabling File Transfer Through Bot PM
1320 | """
1321 | global VERIFY
1322 | query_data = update.data
1323 | chat_id = update.message.chat.id
1324 | user_id = update.from_user.id
1325 |
1326 | if user_id not in VERIFY.get(str(chat_id)):
1327 | return
1328 |
1329 | value, chat_id = re.findall(r"inPM\((.+)\)", query_data)[0].split("|", 1)
1330 |
1331 | value = True if value=="True" else False
1332 |
1333 | if value:
1334 | buttons= [
1335 | [
1336 | InlineKeyboardButton
1337 | (
1338 | "Disable ❎", callback_data=f"set(inPM|False|{chat_id}|{value})"
1339 | )
1340 | ],
1341 | [
1342 | InlineKeyboardButton
1343 | (
1344 | "Back 🔙", callback_data=f"config({chat_id})"
1345 | )
1346 | ]
1347 | ]
1348 |
1349 | else:
1350 | buttons =[
1351 | [
1352 | InlineKeyboardButton
1353 | (
1354 | "Enable ✅", callback_data=f"set(inPM|True|{chat_id}|{value})"
1355 | )
1356 | ],
1357 | [
1358 | InlineKeyboardButton
1359 | (
1360 | "Back 🔙", callback_data=f"config({chat_id})"
1361 | )
1362 | ]
1363 | ]
1364 |
1365 | text=f"This Config Will Help You To Enable/Disable File Transfer Through Bot PM Without Redirecting Them To Channel...."
1366 |
1367 | reply_markup=InlineKeyboardMarkup(buttons)
1368 |
1369 | await update.message.edit_text(
1370 | text,
1371 | reply_markup=reply_markup,
1372 | parse_mode=enums.ParseMode.HTML
1373 | )
1374 |
1375 |
1376 |
1377 | @Client.on_callback_query(filters.regex(r"accuracy\((.+)\)"), group=2)
1378 | async def cb_accuracy(bot, update: CallbackQuery):
1379 | """
1380 | A Callaback Funtion to control the accuracy of matching results
1381 | that the bot should return for a query....
1382 | """
1383 | global VERIFY
1384 | chat_id = update.message.chat.id
1385 | chat_name = update.message.chat.title
1386 | user_id = update.from_user.id
1387 | query_data = update.data
1388 |
1389 |
1390 | if user_id not in VERIFY.get(str(chat_id)):
1391 | return
1392 |
1393 | val, chat_id = re.findall(r"accuracy\((.+)\)", query_data)[0].split("|", 1)
1394 |
1395 | text = f"Choose Your Desired 'Accuracy Perceentage' For Every Filter Results Shown In {chat_name}\n\n"
1396 | text+= f"NB: Higher The Value Better Matching Results Will Be Provided... And If Value Is Lower It Will Show More Results \
1397 | Which Is Fimilary To Query Search (Wont Be Accurate)...."
1398 |
1399 | buttons = [
1400 | [
1401 | InlineKeyboardButton
1402 | (
1403 | "100 %", callback_data=f"set(accuracy|1.00|{chat_id}|{val})"
1404 | )
1405 | ],
1406 | [
1407 | InlineKeyboardButton
1408 | (
1409 | "80 %", callback_data=f"set(accuracy|0.80|{chat_id}|{val})"
1410 | )
1411 | ],
1412 | [
1413 | InlineKeyboardButton
1414 | (
1415 | "65 %", callback_data=f"set(accuracy|0.65|{chat_id}|{val})"
1416 | )
1417 | ],
1418 | [
1419 | InlineKeyboardButton
1420 | (
1421 | "60 %", callback_data=f"set(accuracy|0.60|{chat_id}|{val})"
1422 | )
1423 | ],
1424 | [
1425 | InlineKeyboardButton
1426 | (
1427 | "55 %", callback_data=f"set(accuracy|0.55|{chat_id}|{val})"
1428 | )
1429 | ],
1430 | [
1431 | InlineKeyboardButton
1432 | (
1433 | "50 %", callback_data=f"set(accuracy|0.50|{chat_id}|{val})"
1434 | )
1435 | ],
1436 | [
1437 | InlineKeyboardButton
1438 | (
1439 | "🔙 Back", callback_data=f"config({chat_id})"
1440 | )
1441 | ]
1442 | ]
1443 |
1444 | reply_markup = InlineKeyboardMarkup(buttons)
1445 |
1446 | await update.message.edit_text(
1447 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1448 | )
1449 |
1450 |
1451 |
1452 | @Client.on_callback_query(filters.regex(r"set\((.+)\)"), group=2)
1453 | async def cb_set(bot, update: CallbackQuery):
1454 | """
1455 | A Callback Funtion Support For config()
1456 | """
1457 | global VERIFY
1458 | query_data = update.data
1459 | chat_id = update.message.chat.id
1460 | user_id = update.from_user.id
1461 |
1462 | if user_id not in VERIFY.get(str(chat_id)):
1463 | return
1464 |
1465 | action, val, chat_id, curr_val = re.findall(r"set\((.+)\)", query_data)[0].split("|", 3)
1466 |
1467 | try:
1468 | val, chat_id, curr_val = float(val), int(chat_id), float(curr_val)
1469 | except:
1470 | chat_id = int(chat_id)
1471 |
1472 | if val == curr_val:
1473 | await update.answer("New Value Cannot Be Old Value...Please Choose Different Value...!!!", show_alert=True)
1474 | return
1475 |
1476 | prev = await db.find_chat(chat_id)
1477 |
1478 | accuracy = float(prev["configs"].get("accuracy", 0.80))
1479 | max_pages = int(prev["configs"].get("max_pages"))
1480 | max_results = int(prev["configs"].get("max_results"))
1481 | max_per_page = int(prev["configs"].get("max_per_page"))
1482 | pm_file_chat = True if prev["configs"].get("pm_fchat") == (True or "True") else False
1483 | show_invite_link = True if prev["configs"].get("show_invite_link") == (True or "True") else False
1484 |
1485 | if action == "accuracy": # Scophisticated way 😂🤣
1486 | accuracy = val
1487 |
1488 | elif action == "pages":
1489 | max_pages = int(val)
1490 |
1491 | elif action == "results":
1492 | max_results = int(val)
1493 |
1494 | elif action == "per_page":
1495 | max_per_page = int(val)
1496 |
1497 | elif action =="showInv":
1498 | show_invite_link = True if val=="True" else False
1499 |
1500 | elif action == "inPM":
1501 | pm_file_chat = True if val=="True" else False
1502 |
1503 |
1504 | new = dict(
1505 | accuracy=accuracy,
1506 | max_pages=max_pages,
1507 | max_results=max_results,
1508 | max_per_page=max_per_page,
1509 | pm_fchat=pm_file_chat,
1510 | show_invite_link=show_invite_link
1511 | )
1512 |
1513 | append_db = await db.update_configs(chat_id, new)
1514 |
1515 | if not append_db:
1516 | text="Something Wrong Please Check Bot Log For More Information...."
1517 | await update.answer(text=text, show_alert=True)
1518 | return
1519 |
1520 | text=f"Your Request Was Updated Sucessfully....\nNow All Upcoming Results Will Show According To This Settings..."
1521 |
1522 | buttons = [
1523 | [
1524 | InlineKeyboardButton
1525 | (
1526 | "Back 🔙", callback_data=f"config({chat_id})"
1527 | ),
1528 |
1529 | InlineKeyboardButton
1530 | (
1531 | "Close 🔐", callback_data="close"
1532 | )
1533 | ]
1534 | ]
1535 |
1536 | reply_markup=InlineKeyboardMarkup(buttons)
1537 |
1538 | await update.message.edit_text(
1539 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1540 | )
1541 |
1542 |
1543 |
1544 | @Client.on_callback_query(filters.regex(r"status\((.+)\)"), group=2)
1545 | async def cb_status(bot, update: CallbackQuery):
1546 | """
1547 | A Callback Funtion For Showing Overall Status Of A Group
1548 | """
1549 | global VERIFY
1550 | query_data = update.data
1551 | chat_id = update.message.chat.id
1552 | chat_name = remove_emoji(update.message.chat.title)
1553 | user_id = update.from_user.id
1554 |
1555 | if user_id not in VERIFY.get(str(chat_id)):
1556 | return
1557 |
1558 | chat_id = re.findall(r"status\((.+)\)", query_data)[0]
1559 |
1560 | total_filters, total_chats, total_achats = await db.status(chat_id)
1561 |
1562 | text = f"Status Of {chat_name}\n"
1563 | text += f"\nTotal Connected Chats: {total_chats}\n"
1564 | text += f"\nTotal Active Chats: {total_achats}\n"
1565 | text += f"\nTotal Filters: {total_filters}"
1566 |
1567 | buttons = [
1568 | [
1569 | InlineKeyboardButton
1570 | (
1571 | "🔙 Back", callback_data="settings"
1572 | ),
1573 |
1574 | InlineKeyboardButton
1575 | (
1576 | "Close 🔐", callback_data="close"
1577 | )
1578 | ]
1579 | ]
1580 |
1581 | reply_markup = InlineKeyboardMarkup(buttons)
1582 |
1583 | await update.message.edit_text(
1584 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1585 | )
1586 |
1587 |
1588 |
1589 | @Client.on_callback_query(filters.regex(r"about\((.+)\)"), group=2)
1590 | async def cb_about(bot, update: CallbackQuery):
1591 | """
1592 | A Callback Funtion For Showing About Section In Bot Setting Menu
1593 | """
1594 | global VERIFY
1595 | chat_id = update.message.chat.id
1596 | user_id = update.from_user.id
1597 |
1598 | if user_id not in VERIFY.get(str(chat_id)):
1599 | return
1600 |
1601 | text=f"Bot's Status\n"
1602 | text+=f"\nBot's Uptime: {time_formatter(time.time() - start_uptime)}\n"
1603 | text+=f"\nBot Funtion: Auto Filter Files\n"
1604 | text+=f"""\nBot Support: @CrazyBotszGrp\n"""
1605 | text+="""\nSource Code: Source"""
1606 |
1607 | buttons = [
1608 | [
1609 | InlineKeyboardButton
1610 | (
1611 | "My Dev ⚡", url="https://t.me/AlbertEinstein_TG"
1612 | ),
1613 |
1614 | InlineKeyboardButton
1615 | (
1616 | "🔙 Back", callback_data="settings"
1617 | )
1618 | ],
1619 | [
1620 | InlineKeyboardButton
1621 | (
1622 | "Close 🔐", callback_data="close"
1623 | )
1624 | ]
1625 | ]
1626 |
1627 | reply_markup = InlineKeyboardMarkup(buttons)
1628 |
1629 | await update.message.edit_text(
1630 | text, reply_markup=reply_markup, parse_mode=enums.ParseMode.HTML
1631 | )
1632 |
1633 |
1634 |
1635 | @Client.on_callback_query(filters.regex(r"^(start|help|about|close)$"), group=2)
1636 | async def callback_data(bot, update: CallbackQuery):
1637 |
1638 | query_data = update.data
1639 |
1640 | if query_data == "start":
1641 | buttons = [[
1642 | InlineKeyboardButton('My Dev 👨🔬', url='https://t.me/AlbertEinstein_TG'),
1643 | InlineKeyboardButton('Source Code 🧾', url ='https://github.com/CrazyBotsz/Adv-Filter-Bot-V2')
1644 | ],[
1645 | InlineKeyboardButton('Support 🛠', url='https://t.me/CrazyBotszGrp')
1646 | ],[
1647 | InlineKeyboardButton('Help ⚙', callback_data="help")
1648 | ]]
1649 |
1650 | reply_markup = InlineKeyboardMarkup(buttons)
1651 |
1652 | await update.message.edit_text(
1653 | Translation.START_TEXT.format(update.from_user.mention),
1654 | reply_markup=reply_markup,
1655 | parse_mode=enums.ParseMode.HTML,
1656 | disable_web_page_preview=True
1657 | )
1658 |
1659 |
1660 | elif query_data == "help":
1661 | buttons = [[
1662 | InlineKeyboardButton('Home ⚡', callback_data='start'),
1663 | InlineKeyboardButton('About 🚩', callback_data='about')
1664 | ],[
1665 | InlineKeyboardButton('Close 🔐', callback_data='close')
1666 | ]]
1667 |
1668 | reply_markup = InlineKeyboardMarkup(buttons)
1669 |
1670 | await update.message.edit_text(
1671 | Translation.HELP_TEXT,
1672 | reply_markup=reply_markup,
1673 | parse_mode=enums.ParseMode.HTML,
1674 | disable_web_page_preview=True
1675 | )
1676 |
1677 |
1678 | elif query_data == "about":
1679 | buttons = [[
1680 | InlineKeyboardButton('Home ⚡', callback_data='start'),
1681 | InlineKeyboardButton('Close 🔐', callback_data='close')
1682 | ]]
1683 |
1684 | reply_markup = InlineKeyboardMarkup(buttons)
1685 |
1686 | await update.message.edit_text(
1687 | Translation.ABOUT_TEXT,
1688 | reply_markup=reply_markup,
1689 | parse_mode=enums.ParseMode.HTML
1690 | )
1691 |
1692 |
1693 | elif query_data == "close":
1694 | await update.message.delete()
1695 |
1696 |
1697 |
1698 | def time_formatter(seconds: float) -> str:
1699 | """
1700 | humanize time
1701 | """
1702 | minutes, seconds = divmod(int(seconds),60)
1703 | hours, minutes = divmod(minutes, 60)
1704 | days, hours = divmod(hours, 24)
1705 | tmp = ((str(days) + "d, ") if days else "") + \
1706 | ((str(hours) + "h, ") if hours else "") + \
1707 | ((str(minutes) + "m, ") if minutes else "") + \
1708 | ((str(seconds) + "s") if seconds else "")
1709 | return tmp
1710 |
1711 |
--------------------------------------------------------------------------------