├── .gitignore
├── Dockerfile
├── FilterBot
├── callback.py
├── commands.py
├── connections.py
├── database.py
├── filters.py
├── misc.py
└── utils.py
├── LICENSE
├── Procfile
├── README.md
├── app.json
├── configs.py
├── docker-compose.yml
├── main.py
├── render.yaml
├── requirements.txt
├── routes.py
├── script.py
└── variables
/.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 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.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 | WORKDIR /Filter-Bot
10 |
11 | COPY . .
12 |
13 | CMD ["python3", "main.py"]
14 |
--------------------------------------------------------------------------------
/FilterBot/callback.py:
--------------------------------------------------------------------------------
1 | import ast, pyrogram
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery
4 | from FilterBot.database import db
5 | from configs import ADMINS
6 |
7 | @Client.on_callback_query(filters.regex("(close_data|delallconfirm|delallcancel|groupcb|connectcb|disconnect|deletecb|backcb|alertmessage)"))
8 | async def cb_handler(client: Client, query: CallbackQuery):
9 | if query.data == "close_data":
10 | await query.message.delete()
11 | elif query.data == "delallconfirm":
12 | userid = query.from_user.id
13 | chat_type = query.message.chat.type
14 |
15 | if chat_type == enums.ChatType.PRIVATE:
16 | grpid = await db.active_connection(str(userid))
17 | if grpid is not None:
18 | grp_id = grpid
19 | try:
20 | chat = await client.get_chat(grpid)
21 | title = chat.title
22 | except:
23 | await query.message.edit_text("Make sure I'm present in your group!!", quote=True)
24 | return await query.answer('Piracy Is Crime')
25 | else:
26 | await query.message.edit_text(
27 | "I'm not connected to any groups!\nCheck /connections or connect to any groups",
28 | quote=True
29 | )
30 | return await query.answer('Piracy Is Crime')
31 |
32 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
33 | grp_id = query.message.chat.id
34 | title = query.message.chat.title
35 |
36 | else:
37 | return await query.answer('Piracy Is Crime')
38 |
39 | st = await client.get_chat_member(grp_id, userid)
40 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
41 | await db.del_all(query.message, grp_id, title)
42 | else:
43 | await query.answer("You need to be Group Owner or an Auth User to do that!", show_alert=True)
44 | elif query.data == "delallcancel":
45 | userid = query.from_user.id
46 | chat_type = query.message.chat.type
47 |
48 | if chat_type == enums.ChatType.PRIVATE:
49 | await query.message.reply_to_message.delete()
50 | await query.message.delete()
51 |
52 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
53 | grp_id = query.message.chat.id
54 | st = await client.get_chat_member(grp_id, userid)
55 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
56 | await query.message.delete()
57 | try:
58 | await query.message.reply_to_message.delete()
59 | except:
60 | pass
61 | else:
62 | await query.answer("That's not for you!!", show_alert=True)
63 | elif "groupcb" in query.data:
64 | await query.answer()
65 |
66 | group_id = query.data.split(":")[1]
67 |
68 | act = query.data.split(":")[2]
69 | hr = await client.get_chat(int(group_id))
70 | title = hr.title
71 | user_id = query.from_user.id
72 |
73 | if act == "":
74 | stat = "CONNECT"
75 | cb = "connectcb"
76 | else:
77 | stat = "DISCONNECT"
78 | cb = "disconnect"
79 |
80 | keyboard = InlineKeyboardMarkup([
81 | [InlineKeyboardButton(f"{stat}", callback_data=f"{cb}:{group_id}"),
82 | InlineKeyboardButton("DELETE", callback_data=f"deletecb:{group_id}")],
83 | [InlineKeyboardButton("BACK", callback_data="backcb")]
84 | ])
85 |
86 | await query.message.edit_text(
87 | f"Group Name : **{title}**\nGroup ID : `{group_id}`",
88 | reply_markup=keyboard,
89 | parse_mode=enums.ParseMode.MARKDOWN
90 | )
91 | return await query.answer('Piracy Is Crime')
92 | elif "connectcb" in query.data:
93 | await query.answer()
94 |
95 | group_id = query.data.split(":")[1]
96 |
97 | hr = await client.get_chat(int(group_id))
98 |
99 | title = hr.title
100 |
101 | user_id = query.from_user.id
102 |
103 | mkact = await db.make_active(str(user_id), str(group_id))
104 |
105 | if mkact:
106 | await query.message.edit_text(
107 | f"Connected to **{title}**",
108 | parse_mode=enums.ParseMode.MARKDOWN
109 | )
110 | else:
111 | await query.message.edit_text('Some error occurred!!', parse_mode=enums.ParseMode.MARKDOWN)
112 | return await query.answer('Piracy Is Crime')
113 | elif "disconnect" in query.data:
114 | await query.answer()
115 |
116 | group_id = query.data.split(":")[1]
117 |
118 | hr = await client.get_chat(int(group_id))
119 |
120 | title = hr.title
121 | user_id = query.from_user.id
122 |
123 | mkinact = await db.make_inactive(str(user_id))
124 |
125 | if mkinact:
126 | await query.message.edit_text(
127 | f"Disconnected from **{title}**",
128 | parse_mode=enums.ParseMode.MARKDOWN
129 | )
130 | else:
131 | await query.message.edit_text(
132 | f"Some error occurred!!",
133 | parse_mode=enums.ParseMode.MARKDOWN
134 | )
135 | return await query.answer('Piracy Is Crime')
136 | elif "deletecb" in query.data:
137 | await query.answer()
138 |
139 | user_id = query.from_user.id
140 | group_id = query.data.split(":")[1]
141 |
142 | delcon = await db.delete_connection(str(user_id), str(group_id))
143 |
144 | if delcon:
145 | await query.message.edit_text(
146 | "Successfully deleted connection"
147 | )
148 | else:
149 | await query.message.edit_text(
150 | f"Some error occurred!!",
151 | parse_mode=enums.ParseMode.MARKDOWN
152 | )
153 | return await query.answer('Piracy Is Crime')
154 | elif query.data == "backcb":
155 | await query.answer()
156 |
157 | userid = query.from_user.id
158 |
159 | groupids = await db.all_connections(str(userid))
160 | if groupids is None:
161 | await query.message.edit_text(
162 | "There are no active connections!! Connect to some groups first.",
163 | )
164 | return await query.answer('Piracy Is Crime')
165 | buttons = []
166 | for groupid in groupids:
167 | try:
168 | ttl = await client.get_chat(int(groupid))
169 | title = ttl.title
170 | active = await db.if_active(str(userid), str(groupid))
171 | act = " - ACTIVE" if active else ""
172 | buttons.append(
173 | [
174 | InlineKeyboardButton(
175 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}"
176 | )
177 | ]
178 | )
179 | except:
180 | pass
181 | if buttons:
182 | await query.message.edit_text(
183 | "Your connected group details ;\n\n",
184 | reply_markup=InlineKeyboardMarkup(buttons)
185 | )
186 | elif "alertmessage" in query.data:
187 | grp_id = query.message.chat.id
188 | i = query.data.split(":")[1]
189 | keyword = query.data.split(":")[2]
190 | reply_text, btn, alerts, fileid = await db.find_filter(grp_id, keyword)
191 | if alerts is not None:
192 | alerts = ast.literal_eval(alerts)
193 | alert = alerts[int(i)]
194 | alert = alert.replace("\\n", "\n").replace("\\t", "\t")
195 | await query.answer(alert, show_alert=True)
196 |
--------------------------------------------------------------------------------
/FilterBot/commands.py:
--------------------------------------------------------------------------------
1 | import random
2 | from pyrogram import Client as FilterBot, filters
3 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
4 | from configs import BOT_PICS, StartTxT, HelpTxT, AboutTxT, LOGGER
5 | from FilterBot.database import db
6 |
7 | @FilterBot.on_message(filters.private & filters.command("start"))
8 | async def startCMD(client: FilterBot, message: Message):
9 |
10 | if not await db.is_user_exist(message.from_user.id):
11 | await db.add_user(message.from_user.first_name, message.from_user.id)
12 |
13 | bot = await client.get_me()
14 | keyboard = [[
15 | InlineKeyboardButton('Add Me To Your Chat', url=f"https://t.me/{bot.username}?startgroup=true")
16 | ],[
17 | InlineKeyboardButton('Help', callback_data='main#help'),
18 | InlineKeyboardButton('About', callback_data='main#about')
19 | ],[
20 | InlineKeyboardButton('Update', url='t.me/learningbots79'),
21 | InlineKeyboardButton('Support', url='t.me/learning_bots')
22 | ]]
23 |
24 | if "motech" == BOT_PICS[0]:
25 | await message.reply_text(text=StartTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard))
26 | else:
27 | await message.reply_photo(photo=random.choice(BOT_PICS), caption=StartTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard))
28 |
29 |
30 |
31 | @FilterBot.on_message(filters.private & filters.command("help"))
32 | async def helpCMD(client: FilterBot, message: Message):
33 |
34 | if not await db.is_user_exist(message.from_user.id):
35 | await db.add_user(message.from_user.first_name, message.from_user.id)
36 |
37 | keyboard = [[ InlineKeyboardButton('Home', callback_data='main#start'),
38 | InlineKeyboardButton('Close', callback_data='main#close') ]]
39 |
40 | if "motech" == BOT_PICS[0]:
41 | await message.reply_text(text=HelpTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard))
42 | else:
43 | await message.reply_photo(photo=random.choice(BOT_PICS), caption=HelpTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard))
44 |
45 | @FilterBot.on_message(filters.private & filters.command("about"))
46 | async def aboutCMD(client: FilterBot, message: Message):
47 |
48 | if not await db.is_user_exist(message.from_user.id):
49 | await db.add_user(message.from_user.first_name, message.from_user.id)
50 |
51 | keyboard = [[ InlineKeyboardButton('Tutorial', url='https://youtu.be/vbloWcdxjxg'),
52 | InlineKeyboardButton('Repo', url='https://github.com/Learningbots79/BestFilterbot') ],
53 | [ InlineKeyboardButton('Home', callback_data='main#start'),
54 | InlineKeyboardButton('Help', callback_data='main#help') ]]
55 |
56 | if "motech" == BOT_PICS[0]:
57 | await message.reply_text(text=AboutTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard))
58 | else:
59 | await message.reply_photo(photo=random.choice(BOT_PICS), caption=AboutTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard))
60 |
61 |
62 | @FilterBot.on_callback_query(filters.regex('main'))
63 | async def maincallback(client: FilterBot, message):
64 |
65 | try:
66 | x, type = message.data.split("#")
67 | except:
68 | await message.answer("Erorrrr....")
69 | await message.message.delete()
70 | return
71 |
72 | if type == "start":
73 | bot = await client.get_me()
74 | keyboard = [[ InlineKeyboardButton('Add Me To Your Chat', url=f"t.me/{bot.username}?startgroup=true") ],
75 | [ InlineKeyboardButton('Help', callback_data='main#help'),
76 | InlineKeyboardButton('About', callback_data='main#about') ],
77 | [ InlineKeyboardButton('Update', url='t.me/learningbots79'),
78 | InlineKeyboardButton('Support', url='t.me/learning_bots') ]]
79 | await message.message.edit(text=StartTxT.format(mention=message.from_user.mention), reply_markup=InlineKeyboardMarkup(keyboard), disable_web_page_preview=True)
80 |
81 | elif type == "help":
82 | keyboard = [[ InlineKeyboardButton('Home', callback_data='main#start'),
83 | InlineKeyboardButton('Close', callback_data='main#close') ]]
84 | await message.message.edit(text=HelpTxT, reply_markup=InlineKeyboardMarkup(keyboard), disable_web_page_preview=True)
85 |
86 | elif type == "about":
87 | keyboard = [[ InlineKeyboardButton('Tutorial', url='https://youtu.be/vbloWcdxjxg'),
88 | InlineKeyboardButton('Repo', url='https://github.com/Learningbots79/BestFilterbot') ],
89 | [ InlineKeyboardButton('Home', callback_data='main#start'),
90 | InlineKeyboardButton('Help', callback_data='main#help') ]]
91 | await message.message.edit(text=AboutTxT, reply_markup=InlineKeyboardMarkup(keyboard), disable_web_page_preview=True)
92 |
--------------------------------------------------------------------------------
/FilterBot/connections.py:
--------------------------------------------------------------------------------
1 | import logging, pyrogram
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
4 | from FilterBot.database import db
5 | from configs import ADMINS
6 |
7 | logger = logging.getLogger(__name__)
8 | logger.setLevel(logging.ERROR)
9 |
10 | @Client.on_message((filters.private | filters.group) & filters.command('connect'))
11 | async def addconnection(client, message):
12 | userid = message.from_user.id if message.from_user else None
13 | if not userid:
14 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
15 | chat_type = message.chat.type
16 |
17 | if chat_type == enums.ChatType.PRIVATE:
18 | try:
19 | cmd, group_id = message.text.split(" ", 1)
20 | except:
21 | await message.reply_text(
22 | "Enter in correct format!\n\n"
23 | "/connect groupid
\n\n"
24 | "Get your Group id by adding this bot to your group and use /id
",
25 | quote=True
26 | )
27 | return
28 |
29 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
30 | group_id = message.chat.id
31 |
32 | try:
33 | st = await client.get_chat_member(group_id, userid)
34 | if (
35 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
36 | and st.status != enums.ChatMemberStatus.OWNER
37 | and userid not in ADMINS
38 | ):
39 | await message.reply_text("You should be an admin in Given group!", quote=True)
40 | return
41 | except Exception as e:
42 | logger.exception(e)
43 | await message.reply_text(
44 | "Invalid Group ID!\n\nIf correct, Make sure I'm present in your group!!",
45 | quote=True,
46 | )
47 |
48 | return
49 | try:
50 | st = await client.get_chat_member(group_id, "me")
51 | if st.status == enums.ChatMemberStatus.ADMINISTRATOR:
52 | ttl = await client.get_chat(group_id)
53 | title = ttl.title
54 |
55 | addcon = await db.add_connection(str(group_id), str(userid))
56 | if addcon:
57 | await message.reply_text(
58 | f"Successfully connected to **{title}**\nNow manage your group from my pm !",
59 | quote=True,
60 | parse_mode=enums.ParseMode.MARKDOWN
61 | )
62 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
63 | await client.send_message(
64 | userid,
65 | f"Connected to **{title}** !",
66 | parse_mode=enums.ParseMode.MARKDOWN
67 | )
68 | else:
69 | await message.reply_text(
70 | "You're already connected to this chat!",
71 | quote=True
72 | )
73 | else:
74 | await message.reply_text("Add me as an admin in group", quote=True)
75 | except Exception as e:
76 | logger.exception(e)
77 | await message.reply_text('Some error occurred! Try again later.', quote=True)
78 | return
79 |
80 |
81 | @Client.on_message((filters.private | filters.group) & filters.command('disconnect'))
82 | async def deleteconnection(client, message):
83 | userid = message.from_user.id if message.from_user else None
84 | if not userid:
85 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
86 | chat_type = message.chat.type
87 |
88 | if chat_type == enums.ChatType.PRIVATE:
89 | await message.reply_text("Run /connections to view or disconnect from groups!", quote=True)
90 |
91 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
92 | group_id = message.chat.id
93 |
94 | st = await client.get_chat_member(group_id, userid)
95 | if (
96 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
97 | and st.status != enums.ChatMemberStatus.OWNER
98 | and str(userid) not in ADMINS
99 | ):
100 | return
101 |
102 | delcon = await db.delete_connection(str(userid), str(group_id))
103 | if delcon:
104 | await message.reply_text("Successfully disconnected from this chat", quote=True)
105 | else:
106 | await message.reply_text("This chat isn't connected to me!\nDo /connect to connect.", quote=True)
107 |
108 | @Client.on_message(filters.private & filters.command(["connections"]))
109 | async def connections(client, message):
110 | userid = message.from_user.id
111 |
112 | groupids = await db.all_connections(str(userid))
113 | if groupids is None:
114 | await message.reply_text(
115 | "There are no active connections!! Connect to some groups first.",
116 | quote=True
117 | )
118 | return
119 | buttons = []
120 | for groupid in groupids:
121 | try:
122 | ttl = await client.get_chat(int(groupid))
123 | title = ttl.title
124 | active = await db.if_active(str(userid), str(groupid))
125 | act = " - ACTIVE" if active else ""
126 | buttons.append(
127 | [
128 | InlineKeyboardButton(
129 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}"
130 | )
131 | ]
132 | )
133 | except:
134 | pass
135 | if buttons:
136 | await message.reply_text(
137 | "Your connected group details ;\n\n",
138 | reply_markup=InlineKeyboardMarkup(buttons),
139 | quote=True
140 | )
141 | else:
142 | await message.reply_text(
143 | "There are no active connections!! Connect to some groups first.",
144 | quote=True
145 | )
146 |
--------------------------------------------------------------------------------
/FilterBot/database.py:
--------------------------------------------------------------------------------
1 | import pyrogram
2 | from pymongo import MongoClient
3 | from configs import DATABASE_URI, DATABASE_NAME
4 |
5 | class Database:
6 |
7 | def __init__(self):
8 | self.client0 = MongoClient(DATABASE_URI)
9 | self.client0 = self.client0[DATABASE_NAME]
10 | self.client1 = self.client0["FILTERS"]
11 | self.client2 = self.client0["CONNECTION"]
12 | self.client3 = self.client0["USERS"]
13 |
14 | def new_user(self, name, id):
15 | return dict(name=name, id=id, ban_status=dict(is_banned=False, ban_reason=""))
16 |
17 | # save new user
18 | async def add_user(self, name, id):
19 | user = self.new_user(name, id)
20 | self.client3.insert_one(user)
21 |
22 | # is user exist
23 | async def is_user_exist(self, id):
24 | data = {'id': int(id)}
25 | user = self.client3.find_one(data)
26 | return bool(user)
27 |
28 | # total number of save users
29 | async def total_users_count(self):
30 | count = self.client3.count()
31 | return count
32 |
33 | async def get_all_users(self):
34 | return self.client3.find()
35 |
36 | async def delete_user(self, id):
37 | await self.client3.delete_many({'id': id})
38 |
39 | async def add_filter(self, grp_id, text, reply_text, btn, file, alert):
40 | mycol = self.client1[str(grp_id)]
41 | data = { 'text':str(text), 'reply':str(reply_text), 'btn':str(btn), 'file':str(file), 'alert':str(alert) }
42 | try:
43 | mycol.update_one({'text': str(text)}, {"$set": data}, upsert=True)
44 | except:
45 | print('Couldnt save, check your db')
46 |
47 | async def get_filters(self, group_id):
48 | mycol = self.client1[str(group_id)]
49 |
50 | texts = []
51 | query = mycol.find()
52 | try:
53 | for file in query:
54 | text = file['text']
55 | texts.append(text)
56 | except:
57 | pass
58 | return texts
59 |
60 | async def find_filter(self, group_id, name):
61 | mycol = self.client1[str(group_id)]
62 |
63 | query = mycol.find( {"text":name})
64 | try:
65 | for file in query:
66 | reply_text = file['reply']
67 | btn = file['btn']
68 | fileid = file['file']
69 | try:
70 | alert = file['alert']
71 | except:
72 | alert = None
73 | return reply_text, btn, alert, fileid
74 | except:
75 | return None, None, None, None
76 |
77 | async def delete_filter(self, message, text, group_id):
78 | mycol = self.client1[str(group_id)]
79 |
80 | myquery = {'text':text }
81 | query = mycol.count_documents(myquery)
82 | if query == 1:
83 | mycol.delete_one(myquery)
84 | await message.reply_text(f"'`{text}`' deleted. I'll not respond to that filter anymore.", quote=True, parse_mode=pyrogram.enums.ParseMode.MARKDOWN)
85 | else:
86 | await message.reply_text("Couldn't find that filter!", quote=True)
87 |
88 | async def del_all(self, message, group_id, title):
89 | if str(group_id) not in self.client1.list_collection_names():
90 | await message.edit_text(f"Nothing to remove in {title}!")
91 | return
92 |
93 | mycol = self.client1[str(group_id)]
94 | try:
95 | mycol.drop()
96 | await message.edit_text(f"All filters from {title} has been removed")
97 | except:
98 | await message.edit_text(f"Couldn't remove all filters from group!")
99 | return
100 |
101 | async def count_filters(self, group_id):
102 | mycol = self.client1[str(group_id)]
103 |
104 | count = mycol.count()
105 | if count == 0:
106 | return False
107 | else:
108 | return count
109 |
110 | async def filter_stats(self):
111 | collections = self.client1.list_collection_names()
112 |
113 | if "CONNECTION" in collections:
114 | collections.remove("CONNECTION")
115 |
116 | totalcount = 0
117 | for collection in collections:
118 | mycol = mydb[collection]
119 | count = mycol.count()
120 | totalcount = totalcount + count
121 |
122 | totalcollections = len(collections)
123 |
124 | return totalcollections, totalcount
125 |
126 |
127 | async def add_connection(self, group_id, user_id):
128 | query = self.client2.find_one({ "_id": user_id }, { "_id": 0, "active_group": 0 })
129 | if query is not None:
130 | group_ids = []
131 | for x in query["group_details"]:
132 | group_ids.append(x["group_id"])
133 |
134 | if group_id in group_ids:
135 | return False
136 |
137 | group_details = {"group_id" : group_id}
138 |
139 | data = {'_id': user_id, 'group_details' : [group_details], 'active_group' : group_id}
140 |
141 | if self.client2.count_documents( {"_id": user_id} ) == 0:
142 | try:
143 | self.client2.insert_one(data)
144 | return True
145 | except:
146 | print('Some error occured!')
147 |
148 | else:
149 | try:
150 | self.client2.update_one({'_id': user_id}, { "$push": {"group_details": group_details}, "$set": {"active_group" : group_id} })
151 | return True
152 | except:
153 | print('Some error occured!')
154 |
155 | async def active_connection(self, user_id):
156 | query = self.client2.find_one({ "_id": user_id }, { "_id": 0, "group_details": 0 })
157 | if query:
158 | group_id = query['active_group']
159 | if group_id != None:
160 | return int(group_id)
161 | else:
162 | return None
163 | else:
164 | return None
165 |
166 |
167 | async def all_connections(self, user_id):
168 | query = self.client2.find_one({ "_id": user_id }, { "_id": 0, "active_group": 0 })
169 | if query is not None:
170 | group_ids = []
171 | for x in query["group_details"]:
172 | group_ids.append(x["group_id"])
173 | return group_ids
174 | else:
175 | return None
176 |
177 |
178 | async def if_active(self, user_id, group_id):
179 | query = self.client2.find_one({ "_id": user_id }, { "_id": 0, "group_details": 0 })
180 | if query is not None:
181 | if query['active_group'] == group_id:
182 | return True
183 | else:
184 | return False
185 | else:
186 | return False
187 |
188 |
189 | async def make_active(self, user_id, group_id):
190 | update = self.client2.update_one({'_id': user_id}, {"$set": {"active_group" : group_id}})
191 | if update.modified_count == 0:
192 | return False
193 | else:
194 | return True
195 |
196 | async def make_inactive(self, user_id):
197 | update = self.client2.update_one({'_id': user_id}, {"$set": {"active_group" : None}})
198 | if update.modified_count == 0:
199 | return False
200 | else:
201 | return True
202 |
203 | async def delete_connection(self, user_id, group_id):
204 |
205 | try:
206 | update = self.client2.update_one({"_id": user_id}, {"$pull" : { "group_details" : {"group_id":group_id} } })
207 | if update.modified_count == 0:
208 | return False
209 | else:
210 | query = self.client2.find_one({ "_id": user_id }, { "_id": 0 })
211 | if len(query["group_details"]) >= 1:
212 | if query['active_group'] == group_id:
213 | prvs_group_id = query["group_details"][len(query["group_details"]) - 1]["group_id"]
214 |
215 | mycol.update_one({'_id': user_id},{"$set": {"active_group" : prvs_group_id}})
216 | else:
217 | mycol.update_one({'_id': user_id}, {"$set": {"active_group" : None}})
218 | return True
219 | except Exception as e:
220 | print(e)
221 | return False
222 |
223 | db = Database()
224 |
--------------------------------------------------------------------------------
/FilterBot/filters.py:
--------------------------------------------------------------------------------
1 | import io, re, pyrogram
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
4 | from FilterBot.database import db
5 | from FilterBot.utils import get_file_id, parser, split_quotes
6 | from configs import ADMINS, ADD_FILTER_CMD, DELETE_FILTER_CMD, DELETE_ALL_CMD, AUTO_DELETE, AUTO_DELETE_SECOND
7 |
8 | @Client.on_message(filters.command(ADD_FILTER_CMD) & filters.incoming)
9 | async def addfilter(client, message):
10 |
11 | userid = message.from_user.id if message.from_user else None
12 | if not userid:
13 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
14 |
15 | chat_type = message.chat.type
16 | args = message.text.html.split(None, 1)
17 |
18 | if chat_type == enums.ChatType.PRIVATE:
19 | grpid = await db.active_connection(str(userid))
20 | if grpid is not None:
21 | grp_id = grpid
22 | try:
23 | chat = await client.get_chat(grpid)
24 | title = chat.title
25 | except:
26 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
27 | return
28 | else:
29 | await message.reply_text("I'm not connected to any groups!", quote=True)
30 | return
31 |
32 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
33 | grp_id = message.chat.id
34 | title = message.chat.title
35 |
36 | else:
37 | return
38 |
39 | st = await client.get_chat_member(grp_id, userid)
40 | if (
41 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
42 | and st.status != enums.ChatMemberStatus.OWNER
43 | and str(userid) not in ADMINS
44 | ):
45 | return
46 |
47 |
48 | if len(args) < 2:
49 | await message.reply_text("Command Incomplete :(", quote=True)
50 | return
51 |
52 | extracted = split_quotes(args[1])
53 | text = extracted[0].lower()
54 |
55 | if not message.reply_to_message and len(extracted) < 2:
56 | await message.reply_text("Add some content to save your filter!", quote=True)
57 | return
58 |
59 | if (len(extracted) >= 2) and not message.reply_to_message:
60 | reply_text, btn, alert = parser(extracted[1], text)
61 | fileid = None
62 | if not reply_text:
63 | await message.reply_text("You cannot have buttons alone, give some text to go with it!", quote=True)
64 | return
65 |
66 | elif message.reply_to_message and message.reply_to_message.reply_markup:
67 | try:
68 | rm = message.reply_to_message.reply_markup
69 | btn = rm.inline_keyboard
70 | msg = get_file_id(message.reply_to_message)
71 | if msg:
72 | fileid = msg.file_id
73 | reply_text = message.reply_to_message.caption.html
74 | else:
75 | reply_text = message.reply_to_message.text.html
76 | fileid = None
77 | alert = None
78 | except:
79 | reply_text = ""
80 | btn = "[]"
81 | fileid = None
82 | alert = None
83 |
84 | elif message.reply_to_message and message.reply_to_message.media:
85 | try:
86 | msg = get_file_id(message.reply_to_message)
87 | fileid = msg.file_id if msg else None
88 | reply_text, btn, alert = parser(extracted[1], text) if message.reply_to_message.sticker else parser(message.reply_to_message.caption.html, text)
89 | except:
90 | reply_text = ""
91 | btn = "[]"
92 | alert = None
93 | elif message.reply_to_message and message.reply_to_message.text:
94 | try:
95 | fileid = None
96 | reply_text, btn, alert = parser(message.reply_to_message.text.html, text)
97 | except:
98 | reply_text = ""
99 | btn = "[]"
100 | alert = None
101 | else:
102 | return
103 |
104 | await db.add_filter(grp_id, text, reply_text, btn, fileid, alert)
105 |
106 | await message.reply_text(f"Filter for `{text}` added in **{title}**", quote=True, parse_mode=enums.ParseMode.MARKDOWN)
107 |
108 | @Client.on_message(filters.command(['viewfilters', 'filters']) & filters.incoming)
109 | async def get_all(client, message):
110 |
111 | chat_type = message.chat.type
112 | userid = message.from_user.id if message.from_user else None
113 | if not userid:
114 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
115 | if chat_type == enums.ChatType.PRIVATE:
116 | grpid = await db.active_connection(str(userid))
117 | if grpid is not None:
118 | grp_id = grpid
119 | try:
120 | chat = await client.get_chat(grpid)
121 | title = chat.title
122 | except:
123 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
124 | return
125 | else:
126 | await message.reply_text("I'm not connected to any groups!", quote=True)
127 | return
128 |
129 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
130 | grp_id = message.chat.id
131 | title = message.chat.title
132 |
133 | else:
134 | return
135 |
136 | st = await client.get_chat_member(grp_id, userid)
137 | if (
138 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
139 | and st.status != enums.ChatMemberStatus.OWNER
140 | and str(userid) not in ADMINS
141 | ):
142 | return
143 |
144 | texts = await db.get_filters(grp_id)
145 | count = await db.count_filters(grp_id)
146 | if count:
147 | filterlist = f"Total number of filters in **{title}** : {count}\n\n"
148 |
149 | for text in texts:
150 | keywords = " × `{}`\n".format(text)
151 |
152 | filterlist += keywords
153 |
154 | if len(filterlist) > 4096:
155 | with io.BytesIO(str.encode(filterlist.replace("`", ""))) as keyword_file:
156 | keyword_file.name = "keywords.txt"
157 | await message.reply_document(
158 | document=keyword_file,
159 | quote=True
160 | )
161 | return
162 | else:
163 | filterlist = f"There are no active filters in **{title}**"
164 |
165 | await message.reply_text(text=filterlist, quote=True, parse_mode=enums.ParseMode.MARKDOWN)
166 |
167 | @Client.on_message(filters.command(DELETE_FILTER_CMD) & filters.incoming)
168 | async def deletefilter(client, message):
169 | userid = message.from_user.id if message.from_user else None
170 | if not userid:
171 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
172 | chat_type = message.chat.type
173 |
174 | if chat_type == enums.ChatType.PRIVATE:
175 | grpid = await db.active_connection(str(userid))
176 | if grpid is not None:
177 | grp_id = grpid
178 | try:
179 | chat = await client.get_chat(grpid)
180 | title = chat.title
181 | except:
182 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
183 | return
184 | else:
185 | await message.reply_text("I'm not connected to any groups!", quote=True)
186 | return
187 |
188 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
189 | grp_id = message.chat.id
190 | title = message.chat.title
191 |
192 | else:
193 | return
194 |
195 | st = await client.get_chat_member(grp_id, userid)
196 | if (
197 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
198 | and st.status != enums.ChatMemberStatus.OWNER
199 | and str(userid) not in ADMINS
200 | ):
201 | return
202 |
203 | try:
204 | cmd, text = message.text.split(" ", 1)
205 | except:
206 | await message.reply_text(
207 | "Mention the filtername which you wanna delete!\n\n"
208 | "/del filtername
\n\n"
209 | "Use /viewfilters to view all available filters",
210 | quote=True
211 | )
212 | return
213 |
214 | query = text.lower()
215 |
216 | await db.delete_filter(message, query, grp_id)
217 |
218 |
219 | @Client.on_message(filters.command(DELETE_ALL_CMD) & filters.incoming)
220 | async def delallconfirm(client, message):
221 | userid = message.from_user.id if message.from_user else None
222 | if not userid:
223 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
224 | chat_type = message.chat.type
225 |
226 | if chat_type == enums.ChatType.PRIVATE:
227 | grpid = await db.active_connection(str(userid))
228 | if grpid is not None:
229 | grp_id = grpid
230 | try:
231 | chat = await client.get_chat(grpid)
232 | title = chat.title
233 | except:
234 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
235 | return
236 | else:
237 | await message.reply_text("I'm not connected to any groups!", quote=True)
238 | return
239 |
240 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
241 | grp_id = message.chat.id
242 | title = message.chat.title
243 |
244 | else:
245 | return
246 |
247 |
248 | st = await client.get_chat_member(grp_id, userid)
249 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
250 | await message.reply_text(
251 | f"This will delete all filters from '{title}'.\nDo you want to continue??",
252 | reply_markup=InlineKeyboardMarkup([
253 | [InlineKeyboardButton(text="YES",callback_data="delallconfirm")],
254 | [InlineKeyboardButton(text="CANCEL",callback_data="delallcancel")]
255 | ]),
256 | quote=True
257 | )
258 |
259 |
260 | @Client.on_message(filters.group & filters.text)
261 | async def give_filter(client,message):
262 | group_id = message.chat.id
263 | name = message.text
264 | reply_id = message.reply_to_message.id if message.reply_to_message else message.id
265 |
266 | keywords = await db.get_filters(group_id)
267 | for keyword in reversed(sorted(keywords, key=len)):
268 | pattern = r"( |^|[^\w])" + re.escape(keyword) + r"( |$|[^\w])"
269 | if re.search(pattern, name, flags=re.IGNORECASE):
270 | reply_text, btn, alert, fileid = await db.find_filter(group_id, keyword)
271 |
272 | if reply_text:
273 | reply_text = reply_text.replace("\\n", "\n").replace("\\t", "\t")
274 |
275 |
276 | if btn is not None:
277 | try:
278 | if fileid == "None":
279 | if btn == "[]":
280 | if AUTO_DELETE:
281 | delete = await client.send_message(group_id, reply_text, disable_web_page_preview=True, reply_to_message_id=reply_id)
282 | await asyncio.sleep(AUTO_DELETE_SECOND)
283 | await delete.delete()
284 | else:
285 | await client.send_message(group_id, reply_text, disable_web_page_preview=True, reply_to_message_id=reply_id)
286 |
287 | else:
288 | if AUTO_DELETE:
289 | button = eval(btn)
290 | delete = await client.send_message(
291 | group_id,
292 | reply_text,
293 | disable_web_page_preview=True,
294 | reply_markup=InlineKeyboardMarkup(button),
295 | reply_to_message_id=reply_id
296 | )
297 | await asyncio.sleep(AUTO_DELETE_SECOND)
298 | await delete.delete()
299 | else:
300 | button = eval(btn)
301 | await client.send_message(
302 | group_id,
303 | reply_text,
304 | disable_web_page_preview=True,
305 | reply_markup=InlineKeyboardMarkup(button),
306 | reply_to_message_id=reply_id
307 | )
308 | elif btn == "[]":
309 | if AUTO_DELETE:
310 | delete = await client.send_cached_media(
311 | group_id,
312 | fileid,
313 | caption=reply_text or "",
314 | reply_to_message_id=reply_id
315 | )
316 | await asyncio.sleep(AUTO_DELETE_SECOND)
317 | await delete.delete()
318 | else:
319 | await client.send_cached_media(
320 | group_id,
321 | fileid,
322 | caption=reply_text or "",
323 | reply_to_message_id=reply_id
324 | )
325 |
326 | else:
327 | if AUTO_DELETE:
328 | button = eval(btn)
329 | await message.reply_cached_media(
330 | fileid,
331 | caption=reply_text or "",
332 | reply_markup=InlineKeyboardMarkup(button),
333 | reply_to_message_id=reply_id
334 | )
335 | else:
336 | button = eval(btn)
337 | await message.reply_cached_media(
338 | fileid,
339 | caption=reply_text or "",
340 | reply_markup=InlineKeyboardMarkup(button),
341 | reply_to_message_id=reply_id
342 | )
343 | except Exception as e:
344 | print(e)
345 | break
346 |
--------------------------------------------------------------------------------
/FilterBot/misc.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyrogram import Client, filters, enums
3 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant, MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty
4 | from FilterBot.utils import extract_user, get_file_id, last_online
5 | import time
6 | from datetime import datetime
7 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
8 | import logging
9 | logger = logging.getLogger(__name__)
10 | logger.setLevel(logging.ERROR)
11 |
12 | @Client.on_message(filters.command('id'))
13 | async def showid(client, message):
14 | chat_type = message.chat.type
15 | if chat_type == enums.ChatType.PRIVATE:
16 | user_id = message.chat.id
17 | first = message.from_user.first_name
18 | last = message.from_user.last_name or ""
19 | username = message.from_user.username
20 | dc_id = message.from_user.dc_id or ""
21 | await message.reply_text(
22 | f"➲ First Name: {first}\n➲ Last Name: {last}\n➲ Username: {username}\n➲ Telegram ID: {user_id}
\n➲ Data Centre: {dc_id}
",
23 | quote=True
24 | )
25 |
26 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
27 | _id = ""
28 | _id += (
29 | "➲ Chat ID: "
30 | f"{message.chat.id}
\n"
31 | )
32 | if message.reply_to_message:
33 | _id += (
34 | "➲ User ID: "
35 | f"{message.from_user.id if message.from_user else 'Anonymous'}
\n"
36 | "➲ Replied User ID: "
37 | f"{message.reply_to_message.from_user.id if message.reply_to_message.from_user else 'Anonymous'}
\n"
38 | )
39 | file_info = get_file_id(message.reply_to_message)
40 | else:
41 | _id += (
42 | "➲ User ID: "
43 | f"{message.from_user.id if message.from_user else 'Anonymous'}
\n"
44 | )
45 | file_info = get_file_id(message)
46 | if file_info:
47 | _id += (
48 | f"{file_info.message_type}: "
49 | f"{file_info.file_id}
\n"
50 | )
51 | await message.reply_text(
52 | _id,
53 | quote=True
54 | )
55 |
56 | @Client.on_message(filters.command(["info"]))
57 | async def who_is(client, message):
58 | # https://github.com/SpEcHiDe/PyroGramBot/blob/master/pyrobot/plugins/admemes/whois.py#L19
59 | status_message = await message.reply_text(
60 | "`Fetching user info...`"
61 | )
62 | await status_message.edit(
63 | "`Processing user info...`"
64 | )
65 | from_user = None
66 | from_user_id, _ = extract_user(message)
67 | try:
68 | from_user = await client.get_users(from_user_id)
69 | except Exception as error:
70 | await status_message.edit(str(error))
71 | return
72 | if from_user is None:
73 | return await status_message.edit("no valid user_id / message specified")
74 | message_out_str = ""
75 | message_out_str += f"➲First Name: {from_user.first_name}\n"
76 | last_name = from_user.last_name or "None"
77 | message_out_str += f"➲Last Name: {last_name}\n"
78 | message_out_str += f"➲Telegram ID: {from_user.id}
\n"
79 | username = from_user.username or "None"
80 | dc_id = from_user.dc_id or "[User Doesn't Have A Valid DP]"
81 | message_out_str += f"➲Data Centre: {dc_id}
\n"
82 | message_out_str += f"➲User Name: @{username}\n"
83 | message_out_str += f"➲User 𝖫𝗂𝗇𝗄: Click Here\n"
84 | if message.chat.type in ((enums.ChatType.SUPERGROUP, enums.ChatType.CHANNEL)):
85 | try:
86 | chat_member_p = await message.chat.get_member(from_user.id)
87 | joined_date = (
88 | chat_member_p.joined_date or datetime.now()
89 | ).strftime("%Y.%m.%d %H:%M:%S")
90 | message_out_str += (
91 | "➲Joined this Chat on: "
92 | f"{joined_date}"
93 | "
\n"
94 | )
95 | except UserNotParticipant:
96 | pass
97 | chat_photo = from_user.photo
98 | if chat_photo:
99 | local_user_photo = await client.download_media(
100 | message=chat_photo.big_file_id
101 | )
102 | buttons = [[
103 | InlineKeyboardButton('🔐 Close', callback_data='close_data')
104 | ]]
105 | reply_markup = InlineKeyboardMarkup(buttons)
106 | await message.reply_photo(
107 | photo=local_user_photo,
108 | quote=True,
109 | reply_markup=reply_markup,
110 | caption=message_out_str,
111 | parse_mode=enums.ParseMode.HTML,
112 | disable_notification=True
113 | )
114 | os.remove(local_user_photo)
115 | else:
116 | buttons = [[
117 | InlineKeyboardButton('🔐 Close', callback_data='close_data')
118 | ]]
119 | reply_markup = InlineKeyboardMarkup(buttons)
120 | await message.reply_text(
121 | text=message_out_str,
122 | reply_markup=reply_markup,
123 | quote=True,
124 | parse_mode=enums.ParseMode.HTML,
125 | disable_notification=True
126 | )
127 | await status_message.delete()
128 |
--------------------------------------------------------------------------------
/FilterBot/utils.py:
--------------------------------------------------------------------------------
1 | import re, os
2 | from datetime import datetime
3 | from typing import List, Union
4 | from pyrogram import enums
5 | from pyrogram.types import InlineKeyboardButton, Message
6 |
7 | BTN_URL_REGEX = re.compile(
8 | r"(\[([^\[]+?)\]\((buttonurl|buttonalert):(?:/{0,2})(.+?)(:same)?\))"
9 | )
10 |
11 | SMART_OPEN = '“'
12 | SMART_CLOSE = '”'
13 | START_CHAR = ('\'', '"', SMART_OPEN)
14 |
15 | def get_file_id(msg: Message):
16 | if msg.media:
17 | for message_type in (
18 | "photo",
19 | "animation",
20 | "audio",
21 | "document",
22 | "video",
23 | "video_note",
24 | "voice",
25 | "sticker"
26 | ):
27 | obj = getattr(msg, message_type)
28 | if obj:
29 | setattr(obj, "message_type", message_type)
30 | return obj
31 |
32 | def split_quotes(text: str) -> List:
33 | if any(text.startswith(char) for char in START_CHAR):
34 | counter = 1 # ignore first char -> is some kind of quote
35 | while counter < len(text):
36 | if text[counter] == "\\":
37 | counter += 1
38 | elif text[counter] == text[0] or (text[0] == SMART_OPEN and text[counter] == SMART_CLOSE):
39 | break
40 | counter += 1
41 | else:
42 | return text.split(None, 1)
43 |
44 | # 1 to avoid starting quote, and counter is exclusive so avoids ending
45 | key = remove_escapes(text[1:counter].strip())
46 | # index will be in range, or `else` would have been executed and returned
47 | rest = text[counter + 1:].strip()
48 | if not key:
49 | key = text[0] + text[0]
50 | return list(filter(None, [key, rest]))
51 | else:
52 | return text.split(None, 1)
53 |
54 | def parser(text, keyword):
55 | if "buttonalert" in text:
56 | text = (text.replace("\n", "\\n").replace("\t", "\\t"))
57 | buttons = []
58 | note_data = ""
59 | prev = 0
60 | i = 0
61 | alerts = []
62 | for match in BTN_URL_REGEX.finditer(text):
63 | # Check if btnurl is escaped
64 | n_escapes = 0
65 | to_check = match.start(1) - 1
66 | while to_check > 0 and text[to_check] == "\\":
67 | n_escapes += 1
68 | to_check -= 1
69 |
70 | # if even, not escaped -> create button
71 | if n_escapes % 2 == 0:
72 | note_data += text[prev:match.start(1)]
73 | prev = match.end(1)
74 | if match.group(3) == "buttonalert":
75 | # create a thruple with button label, url, and newline status
76 | if bool(match.group(5)) and buttons:
77 | buttons[-1].append(InlineKeyboardButton(
78 | text=match.group(2),
79 | callback_data=f"alertmessage:{i}:{keyword}"
80 | ))
81 | else:
82 | buttons.append([InlineKeyboardButton(
83 | text=match.group(2),
84 | callback_data=f"alertmessage:{i}:{keyword}"
85 | )])
86 | i = i + 1
87 | alerts.append(match.group(4))
88 | else:
89 | if bool(match.group(5)) and buttons:
90 | buttons[-1].append(InlineKeyboardButton(
91 | text=match.group(2),
92 | url=match.group(4).replace(" ", "")
93 | ))
94 | else:
95 | buttons.append([InlineKeyboardButton(
96 | text=match.group(2),
97 | url=match.group(4).replace(" ", "")
98 | )])
99 |
100 | # if odd, escaped -> move along
101 | else:
102 | note_data += text[prev:to_check]
103 | prev = match.start(1) - 1
104 | else:
105 | note_data += text[prev:]
106 |
107 | try:
108 | return note_data, buttons, alerts
109 | except:
110 | return note_data, buttons, None
111 |
112 | def remove_escapes(text: str) -> str:
113 | counter = 0
114 | res = ""
115 | is_escaped = False
116 | while counter < len(text):
117 | if is_escaped:
118 | res += text[counter]
119 | is_escaped = False
120 | elif text[counter] == "\\":
121 | is_escaped = True
122 | else:
123 | res += text[counter]
124 | counter += 1
125 | return res
126 |
127 | def get_file_id(msg: Message):
128 | if msg.media:
129 | for message_type in (
130 | "photo",
131 | "animation",
132 | "audio",
133 | "document",
134 | "video",
135 | "video_note",
136 | "voice",
137 | "sticker"
138 | ):
139 | obj = getattr(msg, message_type)
140 | if obj:
141 | setattr(obj, "message_type", message_type)
142 | return obj
143 |
144 | def extract_user(message: Message) -> Union[int, str]:
145 | """extracts the user from a message"""
146 | # https://github.com/SpEcHiDe/PyroGramBot/blob/f30e2cca12002121bad1982f68cd0ff9814ce027/pyrobot/helper_functions/extract_user.py#L7
147 | user_id = None
148 | user_first_name = None
149 | if message.reply_to_message:
150 | user_id = message.reply_to_message.from_user.id
151 | user_first_name = message.reply_to_message.from_user.first_name
152 |
153 | elif len(message.command) > 1:
154 | if (
155 | len(message.entities) > 1 and
156 | message.entities[1].type == enums.MessageEntityType.TEXT_MENTION
157 | ):
158 |
159 | required_entity = message.entities[1]
160 | user_id = required_entity.user.id
161 | user_first_name = required_entity.user.first_name
162 | else:
163 | user_id = message.command[1]
164 | # don't want to make a request -_-
165 | user_first_name = user_id
166 | try:
167 | user_id = int(user_id)
168 | except ValueError:
169 | pass
170 | else:
171 | user_id = message.from_user.id
172 | user_first_name = message.from_user.first_name
173 | return (user_id, user_first_name)
174 |
175 | def last_online(from_user):
176 | time = ""
177 | if from_user.is_bot:
178 | time += "🤖 Bot :("
179 | elif from_user.status == enums.UserStatus.RECENTLY:
180 | time += "Recently"
181 | elif from_user.status == enums.UserStatus.LAST_WEEK:
182 | time += "Within the last week"
183 | elif from_user.status == enums.UserStatus.LAST_MONTH:
184 | time += "Within the last month"
185 | elif from_user.status == enums.UserStatus.LONG_AGO:
186 | time += "A long time ago :("
187 | elif from_user.status == enums.UserStatus.ONLINE:
188 | time += "Currently Online"
189 | elif from_user.status == enums.UserStatus.OFFLINE:
190 | time += from_user.last_online_date.strftime("%a, %d %b %Y, %H:%M:%S")
191 | return time
192 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Muhammed
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: python3 main.py
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Filter-Bot
2 |
3 | 
4 |
5 | - [x] An advanced Telegram Filter Bot with nearly unlimitted filters!
6 |
7 | - [x] Nearly unlimited filters.Supports all type of filters (Including Alert Button Filter).
8 |
9 | - [x] Can save button filters directly (Rose Bot Feature).
10 |
11 | - [x] Supports multiple PM connections.
12 |
13 | - [x] And all other features of a Filter Bot :D.
14 |
15 | - [x] broadcasting users
16 |
17 | - [x] force subscribers
18 |
19 | - [x] AutoDelete Filters.
20 |
21 | ### How to use the bot
22 |
23 |
Add bot to your group with admin rights.
24 | 25 |Add your filters :)
26 | 27 | 28 | ### Bot Commands 29 | 30 | > Filter Commands 31 | 32 | - `/filter/add name reply
- Add filter for name
23 | /del name
- Delete filter
24 | /delall
- Delete entire filters (Group Owner Only!)
25 | /viewfilters
- List all filters in chat
26 |
27 | Connection Commands;
28 | /connect groupid
- Connect your group to my PM. You can also simply use,
29 | /connect
in groups.
30 | /connections
- Manage your connections.
31 |
32 | Extras;
33 | /status - Shows current status of your bot (Auth User Only)
34 | /id - Shows ID information
35 | /info userid - Shows User Information. Use /info
as reply to some message for their details!
36 |
37 | © @learningbots79
38 | """
39 |
40 | AboutTxT = """
41 | ⭕️ Official Channel : @learningbots79
42 | ⭕️ Developers : @TroJanzHEX
43 | ⭕️ Upgrader : @Mo_Tech_YT
44 | ⭕️ Language : Python3
45 | ⭕️ Library : Pyrogram 2.0.102
46 | """
47 |
--------------------------------------------------------------------------------
/variables:
--------------------------------------------------------------------------------
1 | ADMINS = 1233567890
2 | API_ID = 123456
3 | API_HASH = a1b2c3d4e5f6g7h8i9j0
4 | BOT_TOKEN = 1234567890:abcdefghijklmnopqrstuvwxyz
5 | PICS = url url url
6 |
--------------------------------------------------------------------------------