├── runtime.txt
├── Procfile
├── heroku.yml
├── assets
└── logo.jpg
├── plugins
├── route.py
├── __init__.py
├── channel.py
├── approve.py
├── json.py
├── banned.py
├── delete_files.py
├── broadcast.py
├── check_alive.py
├── inline.py
├── gfilters.py
├── genlink.py
├── connection.py
├── misc.py
├── index.py
├── filters.py
├── p_ttishow.py
└── commands.py
├── requirements.txt
├── Dockerfile
├── start.sh
├── docker-compose.yml
├── render.yaml
├── logging.conf
├── sample_info.py
├── .gitignore
├── app.json
├── database
├── filters_mdb.py
├── gfilters_mdb.py
├── connections_mdb.py
├── users_chats_db.py
└── ia_filterdb.py
├── bot.py
├── info.py
├── README.md
├── Script.py
├── utils.py
└── LICENSE
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.10.8
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: python3 bot.py
2 |
--------------------------------------------------------------------------------
/heroku.yml:
--------------------------------------------------------------------------------
1 | build:
2 | docker:
3 | worker: Dockerfile
--------------------------------------------------------------------------------
/assets/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ritheshrkrm/PiroAutoFilterBot/HEAD/assets/logo.jpg
--------------------------------------------------------------------------------
/plugins/route.py:
--------------------------------------------------------------------------------
1 | from aiohttp import web
2 |
3 | routes = web.RouteTableDef()
4 |
5 | @routes.get("/", allow_head=True)
6 | async def root_route_handler(request):
7 | return web.json_response("PIROBOTS")
--------------------------------------------------------------------------------
/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | from aiohttp import web
2 | from .route import routes
3 |
4 |
5 | async def web_server():
6 | web_app = web.Application(client_max_size=30000000)
7 | web_app.add_routes(routes)
8 | return web_app
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pyrogram>=2.0.30
2 | tgcrypto
3 | pymongo[srv]==3.12.3
4 | motor==2.5.1
5 | marshmallow==3.14.1
6 | umongo==3.0.1
7 | requests
8 | bs4
9 | git+https://github.com/ritheshrkrm/cinemagoer
10 | datetime
11 | pytz
12 | aiohttp
13 | psutil==5.9.4
--------------------------------------------------------------------------------
/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 /PiroAutoFilterBot
10 |
11 | COPY . .
12 |
13 | CMD ["python3", "bot.py"]
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | if [ -z $UPSTREAM_REPO ]
2 | then
3 | echo "Cloning main Repository"
4 | git clone https://github.com/ritheshrkrm/PiroAutoFilterBot.git /PiroAutoFilterBot
5 | else
6 | echo "Cloning Custom Repo from $UPSTREAM_REPO "
7 | git clone $UPSTREAM_REPO /PiroAutoFilterBot
8 | fi
9 | cd /PiroAutoFilterBot
10 | pip3 install -U -r requirements.txt
11 | echo "Starting PiroAutoFilterBot...."
12 | python3 bot.py
13 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.10"
2 | services:
3 | worker:
4 | build: .
5 | environment:
6 | BOT_TOKEN: $BOT_TOKEN
7 | API_ID: $API_ID
8 | API_HASH: $API_HASH
9 | CHANNELS: $CHANNELS
10 | ADMINS: $ADMINS
11 | LOG_CHANNEL: $LOG_CHANNEL
12 | DATABASE_NAME: $DATABASE_NAME
13 | DATABASE_URI: $DATABASE_URI
14 | HEROKU_API_KEY: $HEROKU_API_KEY
15 |
--------------------------------------------------------------------------------
/render.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | # A Docker web service
3 | - type: web
4 | name: PiroAutoFilterBot
5 | env: python
6 | startCommand: python3 bot.py
7 | buildCommand: pip3 install -U -r requirements.txt
8 | repo: https://github/ritheshrkrm/PiroAutoFilterBot.git # optional
9 | region: oregon # optional (defaults to oregon)
10 | plan: free # optional (defaults to starter)
11 | branch: master # optional (defaults to master)
12 | numInstances: 1 # optional (defaults to 1)
13 | healthCheckPath: /
14 |
15 | #End of yaml
16 |
--------------------------------------------------------------------------------
/plugins/channel.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from info import CHANNELS
3 | from database.ia_filterdb import save_file
4 |
5 | media_filter = filters.document | filters.video
6 |
7 |
8 | @Client.on_message(filters.chat(CHANNELS) & media_filter)
9 | async def media(bot, message):
10 | """Media Handler"""
11 | for file_type in ("document", "video"):
12 | media = getattr(message, file_type, None)
13 | if media is not None:
14 | break
15 | else:
16 | return
17 |
18 | media.file_type = file_type
19 | media.caption = message.caption
20 | await save_file(media)
--------------------------------------------------------------------------------
/logging.conf:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root
3 |
4 | [handlers]
5 | keys=consoleHandler,fileHandler
6 |
7 | [formatters]
8 | keys=consoleFormatter,fileFormatter
9 |
10 | [logger_root]
11 | level=DEBUG
12 | handlers=consoleHandler,fileHandler
13 |
14 | [handler_consoleHandler]
15 | class=StreamHandler
16 | level=INFO
17 | formatter=consoleFormatter
18 | args=(sys.stdout,)
19 |
20 | [handler_fileHandler]
21 | class=FileHandler
22 | level=ERROR
23 | formatter=fileFormatter
24 | args=('Logs.txt','w',)
25 |
26 | [formatter_consoleFormatter]
27 | format=%(asctime)s - %(lineno)d - %(name)s - %(module)s - %(levelname)s - %(message)s
28 | datefmt=%I:%M:%S %p
29 |
30 | [formatter_fileFormatter]
31 | format=[%(asctime)s:%(name)s:%(lineno)d:%(levelname)s] %(message)s
32 | datefmt=%m/%d/%Y %I:%M:%S %p
--------------------------------------------------------------------------------
/sample_info.py:
--------------------------------------------------------------------------------
1 | # Bot information
2 | SESSION = 'Media_search'
3 | USER_SESSION = 'User_Bot'
4 | API_ID = 12345
5 | API_HASH = '0123456789abcdef0123456789abcdef'
6 | BOT_TOKEN = '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'
7 | USERBOT_STRING_SESSION = ''
8 |
9 | # Bot settings
10 | CACHE_TIME = 300
11 | USE_CAPTION_FILTER = False
12 |
13 | # Admins, Channels & Users
14 | ADMINS = [12345789, 'admin123', 98765432]
15 | CHANNELS = [-10012345678, -100987654321, 'channelusername']
16 | AUTH_USERS = []
17 | AUTH_CHANNEL = None
18 |
19 | # MongoDB information
20 | DATABASE_URI = "mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb]?retryWrites=true&w=majority"
21 | DATABASE_NAME = 'Telegram'
22 | COLLECTION_NAME = 'channel_files' # If you are using the same database, then use different collection name for each bot
23 |
24 |
25 |
--------------------------------------------------------------------------------
/plugins/approve.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client
2 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
3 | from pyrogram.errors import UserIsBlocked, PeerIdInvalid
4 |
5 |
6 | @Client.on_chat_join_request()
7 | async def accept_request(client, r):
8 |
9 | rm = InlineKeyboardMarkup([[
10 | InlineKeyboardButton("❤️🔥 𝖡𝖫𝖠𝖲𝖳𝖤𝖱 𝖧𝖴𝖡 ❤️🔥", url=f"https://t.me/blaster_hub"),
11 | InlineKeyboardButton("⚡𝖴𝗉𝖽𝖺𝗍𝖾𝗌 ⚡", url=f"https://t.me/piroxbots")
12 | ]])
13 |
14 | try:
15 | await client.send_photo(
16 | r.from_user.id,
17 | 'https://graph.org/file/5cb80fa6096997b7226b3.jpg',
18 | f"**𝖧𝖾𝗅𝗅𝗈 {r.from_user.mention} 👻, 𝖶𝖾𝗅𝖼𝗈𝗆𝖾 𝖳𝗈 {r.chat.title}\n𝖸𝗈𝗎𝗋 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 𝖧𝖺𝗌 𝖡𝖾𝖾𝗇 𝖠𝗉𝗉𝗋𝗈𝗏𝖾𝖽...!!!**",
19 | reply_markup=rm)
20 |
21 | except UserIsBlocked:
22 | print("User blocked the bot")
23 | except PeerIdInvalid:
24 | print("Err")
25 | except Exception as e:
26 | print(f"#Error\n{str(e)}")
27 |
28 | await r.approve()
29 |
--------------------------------------------------------------------------------
/plugins/json.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyrogram import Client, filters
3 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message, CallbackQuery
4 |
5 | @Client.on_message(filters.command(["json", 'js', 'showjson']))
6 | async def jsonify(_, message):
7 | the_real_message = None
8 | reply_to_id = None
9 |
10 | if message.reply_to_message:
11 | the_real_message = message.reply_to_message
12 | else:
13 | the_real_message = message
14 | try:
15 | pk = InlineKeyboardMarkup(
16 | [
17 | [
18 | InlineKeyboardButton(
19 | text="🔐 𝖢𝗅𝗈𝗌𝖾",
20 | callback_data="close_data"
21 | )
22 | ]
23 | ]
24 | )
25 | await message.reply_text(f"{the_real_message}", reply_markup=pk, quote=True)
26 | except Exception as e:
27 | with open("json.text", "w+", encoding="utf8") as out_file:
28 | out_file.write(str(the_real_message))
29 | reply_markup = InlineKeyboardMarkup(
30 | [
31 | [
32 | InlineKeyboardButton(
33 | text="🔐 𝖢𝗅𝗈𝗌𝖾",
34 | callback_data="close_data"
35 | )
36 | ]
37 | ]
38 | )
39 | await message.reply_document(
40 | document="json.text",
41 | caption=str(e),
42 | disable_notification=True,
43 | quote=True,
44 | reply_markup=reply_markup
45 | )
46 | os.remove("json.text")
47 |
48 |
--------------------------------------------------------------------------------
/plugins/banned.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from utils import temp
3 | from pyrogram.types import Message
4 | from database.users_chats_db import db
5 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
6 | from info import SUPPORT_CHAT
7 |
8 | async def banned_users(_, client, message: Message):
9 | return (
10 | message.from_user is not None or not message.sender_chat
11 | ) and message.from_user.id in temp.BANNED_USERS
12 |
13 | banned_user = filters.create(banned_users)
14 |
15 | async def disabled_chat(_, client, message: Message):
16 | return message.chat.id in temp.BANNED_CHATS
17 |
18 | disabled_group=filters.create(disabled_chat)
19 |
20 |
21 | @Client.on_message(filters.private & banned_user & filters.incoming)
22 | async def ban_reply(bot, message):
23 | ban = await db.get_ban_status(message.from_user.id)
24 | await message.reply(f'‼️Sorry Dude, You are Banned to use Me.‼️ \n\nBan Reason: {ban["ban_reason"]}')
25 |
26 | @Client.on_message(filters.group & disabled_group & filters.incoming)
27 | async def grp_bd(bot, message):
28 | buttons = [[
29 | InlineKeyboardButton('🧩 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 🧩', url=f"https://t.me/{SUPPORT_CHAT}")
30 | ]]
31 | reply_markup=InlineKeyboardMarkup(buttons)
32 | vazha = await db.get_chat(message.chat.id)
33 | k = await message.reply(
34 | text=f"CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 GROUP..\nReason : {vazha['reason']}.",
35 | reply_markup=reply_markup)
36 | try:
37 | await k.pin()
38 | except:
39 | pass
40 | await bot.leave_chat(message.chat.id)
41 |
--------------------------------------------------------------------------------
/plugins/delete_files.py:
--------------------------------------------------------------------------------
1 | import re
2 | import logging
3 | from pyrogram import Client, filters
4 | from info import DELETE_CHANNELS
5 | from database.ia_filterdb import Media, unpack_new_file_id
6 |
7 | logger = logging.getLogger(__name__)
8 |
9 | media_filter = filters.document | filters.video | filters.audio
10 |
11 |
12 | @Client.on_message(filters.chat(DELETE_CHANNELS) & media_filter)
13 | async def deletemultiplemedia(bot, message):
14 | """Delete Multiple files from database"""
15 |
16 | for file_type in ("document", "video", "audio"):
17 | media = getattr(message, file_type, None)
18 | if media is not None:
19 | break
20 | else:
21 | return
22 |
23 | file_id, file_ref = unpack_new_file_id(media.file_id)
24 |
25 | result = await Media.collection.delete_one({
26 | '_id': file_id,
27 | })
28 | if result.deleted_count:
29 | logger.info('File is successfully deleted from database.')
30 | else:
31 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
32 | result = await Media.collection.delete_many({
33 | 'file_name': file_name,
34 | 'file_size': media.file_size,
35 | 'mime_type': media.mime_type
36 | })
37 | if result.deleted_count:
38 | logger.info('File is successfully deleted from database.')
39 | else:
40 | result = await Media.collection.delete_many({
41 | 'file_name': media.file_name,
42 | 'file_size': media.file_size,
43 | 'mime_type': media.mime_type
44 | })
45 | if result.deleted_count:
46 | logger.info('File is successfully deleted from database.')
47 | else:
48 | logger.info('File not found in database.')
49 |
--------------------------------------------------------------------------------
/plugins/broadcast.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | import datetime
3 | import time
4 | from database.users_chats_db import db
5 | from info import ADMINS
6 | from utils import broadcast_messages, broadcast_messages_group
7 | import asyncio
8 |
9 | @Client.on_message(filters.command("broadcast") & filters.user(ADMINS) & filters.reply)
10 | async def verupikkals(bot, message):
11 | users = await db.get_all_users()
12 | b_msg = message.reply_to_message
13 | sts = await message.reply_text(
14 | text='🔊 Broadcasting your messages...'
15 | )
16 | start_time = time.time()
17 | total_users = await db.total_users_count()
18 | done = 0
19 | blocked = 0
20 | deleted = 0
21 | failed =0
22 |
23 | success = 0
24 | async for user in users:
25 | pti, sh = await broadcast_messages(int(user['id']), b_msg)
26 | if pti:
27 | success += 1
28 | elif pti == False:
29 | if sh == "Blocked":
30 | blocked+=1
31 | elif sh == "Deleted":
32 | deleted += 1
33 | elif sh == "Error":
34 | failed += 1
35 | done += 1
36 | await asyncio.sleep(2)
37 | if not done % 20:
38 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
39 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
40 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
41 |
42 | @Client.on_message(filters.command("group_broadcast") & filters.user(ADMINS) & filters.reply)
43 | async def broadcast_group(bot, message):
44 | groups = await db.get_all_chats()
45 | b_msg = message.reply_to_message
46 | sts = await message.reply_text(
47 | text='🔊 Broadcasting your messages To Groups...'
48 | )
49 | start_time = time.time()
50 | total_groups = await db.total_chat_count()
51 | done = 0
52 | failed =0
53 |
54 | success = 0
55 | async for group in groups:
56 | pti, sh = await broadcast_messages_group(int(group['id']), b_msg)
57 | if pti:
58 | success += 1
59 | elif sh == "Error":
60 | failed += 1
61 | done += 1
62 | if not done % 20:
63 | await sts.edit(f"Broadcast in progress:\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}")
64 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
65 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}")
66 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Personal files
2 | *.session
3 | *.session-journal
4 | .vscode
5 | *test*.py
6 | setup.cfg
7 |
8 | # Byte-compiled / optimized / DLL files
9 | __pycache__/
10 | *.py[cod]
11 | *$py.class
12 |
13 | # C extensions
14 | *.so
15 |
16 | # Distribution / packaging
17 | .Python
18 | build/
19 | develop-eggs/
20 | dist/
21 | downloads/
22 | eggs/
23 | .eggs/
24 | lib/
25 | lib64/
26 | parts/
27 | sdist/
28 | var/
29 | wheels/
30 | share/python-wheels/
31 | *.egg-info/
32 | .installed.cfg
33 | *.egg
34 | MANIFEST
35 |
36 | # PyInstaller
37 | # Usually these files are written by a python script from a template
38 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
39 | *.manifest
40 | *.spec
41 |
42 | # Installer logs
43 | pip-log.txt
44 | pip-delete-this-directory.txt
45 |
46 | # Unit test / coverage reports
47 | htmlcov/
48 | .tox/
49 | .nox/
50 | .coverage
51 | .coverage.*
52 | .cache
53 | nosetests.xml
54 | coverage.xml
55 | *.cover
56 | *.py,cover
57 | .hypothesis/
58 | .pytest_cache/
59 | cover/
60 |
61 | # Translations
62 | *.mo
63 | *.pot
64 |
65 | # Django stuff:
66 | *.log
67 | local_settings.py
68 | db.sqlite3
69 | db.sqlite3-journal
70 |
71 | # Flask stuff:
72 | instance/
73 | .webassets-cache
74 |
75 | # Scrapy stuff:
76 | .scrapy
77 |
78 | # Sphinx documentation
79 | docs/_build/
80 |
81 | # PyBuilder
82 | .pybuilder/
83 | target/
84 |
85 | # Jupyter Notebook
86 | .ipynb_checkpoints
87 |
88 | # IPython
89 | profile_default/
90 | ipython_config.py
91 |
92 | # pyenv
93 | # For a library or package, you might want to ignore these files since the code is
94 | # intended to run in multiple environments; otherwise, check them in:
95 | # .python-version
96 |
97 | # pipenv
98 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
99 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
100 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
101 | # install all needed dependencies.
102 | #Pipfile.lock
103 |
104 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
105 | __pypackages__/
106 |
107 | # Celery stuff
108 | celerybeat-schedule
109 | celerybeat.pid
110 |
111 | # SageMath parsed files
112 | *.sage.py
113 |
114 | # Environments
115 | .env
116 | .venv
117 | env/
118 | venv/
119 | ENV/
120 | env.bak/
121 | venv.bak/
122 |
123 | # Spyder project settings
124 | .spyderproject
125 | .spyproject
126 |
127 | # Rope project settings
128 | .ropeproject
129 |
130 | # mkdocs documentation
131 | /site
132 |
133 | # mypy
134 | .mypy_cache/
135 | .dmypy.json
136 | dmypy.json
137 |
138 | # Pyre type checker
139 | .pyre/
140 |
141 | # pytype static type analyzer
142 | .pytype/
143 |
144 | # Cython debug symbols
145 | cython_debug/
146 | config.py
147 | .goutputstream-VAFWB1
148 | result.json
149 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "PiroAutoFilterBot",
3 | "description": "When you going to send file on telegram channel this bot will save that in database, So you can search that easily in inline mode",
4 | "stack": "container",
5 | "keywords": [
6 | "telegram",
7 | "auto-filter",
8 | "filter",
9 | "best",
10 | "indian",
11 | "pyrogram",
12 | "media",
13 | "search",
14 | "channel",
15 | "index",
16 | "inline"
17 | ],
18 | "website": "https://github.com/ritheshrkrm/PiroAutoFilterBot",
19 | "repository": "https://github.com/ritheshrkrm/PiroAutoFilterBot",
20 | "env": {
21 | "BOT_TOKEN": {
22 | "description": "Your bot token.",
23 | "required": true
24 | },
25 | "API_ID": {
26 | "description": "Get this value from https://my.telegram.org",
27 | "required": true
28 | },
29 | "API_HASH": {
30 | "description": "Get this value from https://my.telegram.org",
31 | "required": true
32 | },
33 | "CHANNELS": {
34 | "description": "Username or ID of channel or group. Separate multiple IDs by space.",
35 | "required": false
36 | },
37 | "ADMINS": {
38 | "description": "Username or ID of Admin. Separate multiple Admins by space.",
39 | "required": true
40 | },
41 | "PICS": {
42 | "description": "Add some telegraph link of pictures .",
43 | "required": false
44 | },
45 | "LOG_CHANNEL": {
46 | "description": "Bot Logs,Give a channel id with -100xxxxxxx",
47 | "required": true
48 | },
49 | "AUTH_USERS": {
50 | "description": "Username or ID of users to give access of inline search. Separate multiple users by space.\nLeave it empty if you don't want to restrict bot usage.",
51 | "required": false
52 | },
53 | "AUTH_CHANNEL": {
54 | "description": "ID of channel.Make sure bot is admin in this channel. Without subscribing this channel users cannot use bot.",
55 | "required": false
56 | },
57 | "DATABASE_URI": {
58 | "description": "mongoDB URI. Get this value from https://www.mongodb.com. For more help watch this video - https://youtu.be/dsuTn4qV2GA",
59 | "required": true
60 | },
61 | "DATABASE_NAME": {
62 | "description": "Name of the database in mongoDB. For more help watch this video - https://youtu.be/dsuTn4qV2GA",
63 | "required": false
64 | },
65 | "COLLECTION_NAME": {
66 | "description": "Name of the collections. Defaults to Telegram_files. If you are using the same database, then use different collection name for each bot",
67 | "value": "Telegram_files",
68 | "required": false
69 | }
70 | },
71 | "addons": [],
72 | "buildpacks": [{
73 | "url": "heroku/python"
74 | }],
75 | "formation": {
76 | "worker": {
77 | "quantity": 1,
78 | "size": "free"
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/database/filters_mdb.py:
--------------------------------------------------------------------------------
1 | import pymongo
2 | from info import DATABASE_URI, DATABASE_NAME
3 | from pyrogram import enums
4 | import logging
5 | logger = logging.getLogger(__name__)
6 | logger.setLevel(logging.ERROR)
7 |
8 | myclient = pymongo.MongoClient(DATABASE_URI)
9 | mydb = myclient[DATABASE_NAME]
10 |
11 |
12 |
13 | async def add_filter(grp_id, text, reply_text, btn, file, alert):
14 | mycol = mydb[str(grp_id)]
15 | # mycol.create_index([('text', 'text')])
16 |
17 | data = {
18 | 'text':str(text),
19 | 'reply':str(reply_text),
20 | 'btn':str(btn),
21 | 'file':str(file),
22 | 'alert':str(alert)
23 | }
24 |
25 | try:
26 | mycol.update_one({'text': str(text)}, {"$set": data}, upsert=True)
27 | except:
28 | logger.exception('Some error occured!', exc_info=True)
29 |
30 |
31 | async def find_filter(group_id, name):
32 | mycol = mydb[str(group_id)]
33 |
34 | query = mycol.find( {"text":name})
35 | # query = mycol.find( { "$text": {"$search": name}})
36 | try:
37 | for file in query:
38 | reply_text = file['reply']
39 | btn = file['btn']
40 | fileid = file['file']
41 | try:
42 | alert = file['alert']
43 | except:
44 | alert = None
45 | return reply_text, btn, alert, fileid
46 | except:
47 | return None, None, None, None
48 |
49 |
50 | async def get_filters(group_id):
51 | mycol = mydb[str(group_id)]
52 |
53 | texts = []
54 | query = mycol.find()
55 | try:
56 | for file in query:
57 | text = file['text']
58 | texts.append(text)
59 | except:
60 | pass
61 | return texts
62 |
63 |
64 | async def delete_filter(message, text, group_id):
65 | mycol = mydb[str(group_id)]
66 |
67 | myquery = {'text':text }
68 | query = mycol.count_documents(myquery)
69 | if query == 1:
70 | mycol.delete_one(myquery)
71 | await message.reply_text(
72 | f"'`{text}`' deleted. I'll not respond to that filter anymore.",
73 | quote=True,
74 | parse_mode=enums.ParseMode.MARKDOWN
75 | )
76 | else:
77 | await message.reply_text("Couldn't find that filter!", quote=True)
78 |
79 |
80 | async def del_all(message, group_id, title):
81 | if str(group_id) not in mydb.list_collection_names():
82 | await message.edit_text(f"Nothing to remove in {title}!")
83 | return
84 |
85 | mycol = mydb[str(group_id)]
86 | try:
87 | mycol.drop()
88 | await message.edit_text(f"All filters from {title} has been removed")
89 | except:
90 | await message.edit_text("Couldn't remove all filters from group!")
91 | return
92 |
93 |
94 | async def count_filters(group_id):
95 | mycol = mydb[str(group_id)]
96 |
97 | count = mycol.count()
98 | return False if count == 0 else count
99 |
100 |
101 | async def filter_stats():
102 | collections = mydb.list_collection_names()
103 |
104 | if "CONNECTION" in collections:
105 | collections.remove("CONNECTION")
106 |
107 | totalcount = 0
108 | for collection in collections:
109 | mycol = mydb[collection]
110 | count = mycol.count()
111 | totalcount += count
112 |
113 | totalcollections = len(collections)
114 |
115 | return totalcollections, totalcount
116 |
--------------------------------------------------------------------------------
/database/gfilters_mdb.py:
--------------------------------------------------------------------------------
1 | import pymongo
2 | from info import DATABASE_URI, DATABASE_NAME
3 | from pyrogram import enums
4 | import logging
5 | logger = logging.getLogger(__name__)
6 | logger.setLevel(logging.ERROR)
7 |
8 | myclient = pymongo.MongoClient(DATABASE_URI)
9 | mydb = myclient[DATABASE_NAME]
10 |
11 |
12 |
13 | async def add_gfilter(gfilters, text, reply_text, btn, file, alert):
14 | mycol = mydb[str(gfilters)]
15 |
16 | data = {
17 | 'text':str(text),
18 | 'reply':str(reply_text),
19 | 'btn':str(btn),
20 | 'file':str(file),
21 | 'alert':str(alert)
22 | }
23 |
24 | try:
25 | mycol.update_one({'text': str(text)}, {"$set": data}, upsert=True)
26 | except:
27 | logger.exception('Some error occured!', exc_info=True)
28 |
29 |
30 | async def find_gfilter(gfilters, name):
31 | mycol = mydb[str(gfilters)]
32 |
33 | query = mycol.find( {"text":name})
34 | # query = mycol.find( { "$text": {"$search": name}})
35 | try:
36 | for file in query:
37 | reply_text = file['reply']
38 | btn = file['btn']
39 | fileid = file['file']
40 | try:
41 | alert = file['alert']
42 | except:
43 | alert = None
44 | return reply_text, btn, alert, fileid
45 | except:
46 | return None, None, None, None
47 |
48 |
49 | async def get_gfilters(gfilters):
50 | mycol = mydb[str(gfilters)]
51 |
52 | texts = []
53 | query = mycol.find()
54 | try:
55 | for file in query:
56 | text = file['text']
57 | texts.append(text)
58 | except:
59 | pass
60 | return texts
61 |
62 |
63 | async def delete_gfilter(message, text, gfilters):
64 | mycol = mydb[str(gfilters)]
65 |
66 | myquery = {'text':text }
67 | query = mycol.count_documents(myquery)
68 | if query == 1:
69 | mycol.delete_one(myquery)
70 | await message.reply_text(
71 | f"'`{text}`' deleted. I'll not respond to that gfilter anymore.",
72 | quote=True,
73 | parse_mode=enums.ParseMode.MARKDOWN
74 | )
75 | else:
76 | await message.reply_text("Couldn't find that gfilter!", quote=True)
77 |
78 | async def del_allg(message, gfilters):
79 | if str(gfilters) not in mydb.list_collection_names():
80 | await message.edit_text("Nothing to Remove !")
81 | return
82 |
83 | mycol = mydb[str(gfilters)]
84 | try:
85 | mycol.drop()
86 | await message.edit_text(f"All gfilters has been removed !")
87 | except:
88 | await message.edit_text("Couldn't remove all gfilters !")
89 | return
90 |
91 | async def count_gfilters(gfilters):
92 | mycol = mydb[str(gfilters)]
93 |
94 | count = mycol.count()
95 | return False if count == 0 else count
96 |
97 |
98 | async def gfilter_stats():
99 | collections = mydb.list_collection_names()
100 |
101 | if "CONNECTION" in collections:
102 | collections.remove("CONNECTION")
103 |
104 | totalcount = 0
105 | for collection in collections:
106 | mycol = mydb[collection]
107 | count = mycol.count()
108 | totalcount += count
109 |
110 | totalcollections = len(collections)
111 |
112 | return totalcollections, totalcount
113 |
--------------------------------------------------------------------------------
/database/connections_mdb.py:
--------------------------------------------------------------------------------
1 | import pymongo
2 |
3 | from info import DATABASE_URI, DATABASE_NAME
4 |
5 | import logging
6 | logger = logging.getLogger(__name__)
7 | logger.setLevel(logging.ERROR)
8 |
9 | myclient = pymongo.MongoClient(DATABASE_URI)
10 | mydb = myclient[DATABASE_NAME]
11 | mycol = mydb['CONNECTION']
12 |
13 |
14 | async def add_connection(group_id, user_id):
15 | query = mycol.find_one(
16 | { "_id": user_id },
17 | { "_id": 0, "active_group": 0 }
18 | )
19 | if query is not None:
20 | group_ids = [x["group_id"] for x in query["group_details"]]
21 | if group_id in group_ids:
22 | return False
23 |
24 | group_details = {
25 | "group_id" : group_id
26 | }
27 |
28 | data = {
29 | '_id': user_id,
30 | 'group_details' : [group_details],
31 | 'active_group' : group_id,
32 | }
33 |
34 | if mycol.count_documents( {"_id": user_id} ) == 0:
35 | try:
36 | mycol.insert_one(data)
37 | return True
38 | except:
39 | logger.exception('Some error occurred!', exc_info=True)
40 |
41 | else:
42 | try:
43 | mycol.update_one(
44 | {'_id': user_id},
45 | {
46 | "$push": {"group_details": group_details},
47 | "$set": {"active_group" : group_id}
48 | }
49 | )
50 | return True
51 | except:
52 | logger.exception('Some error occurred!', exc_info=True)
53 |
54 |
55 | async def active_connection(user_id):
56 |
57 | query = mycol.find_one(
58 | { "_id": user_id },
59 | { "_id": 0, "group_details": 0 }
60 | )
61 | if not query:
62 | return None
63 |
64 | group_id = query['active_group']
65 | return int(group_id) if group_id != None else None
66 |
67 |
68 | async def all_connections(user_id):
69 | query = mycol.find_one(
70 | { "_id": user_id },
71 | { "_id": 0, "active_group": 0 }
72 | )
73 | if query is not None:
74 | return [x["group_id"] for x in query["group_details"]]
75 | else:
76 | return None
77 |
78 |
79 | async def if_active(user_id, group_id):
80 | query = mycol.find_one(
81 | { "_id": user_id },
82 | { "_id": 0, "group_details": 0 }
83 | )
84 | return query is not None and query['active_group'] == group_id
85 |
86 |
87 | async def make_active(user_id, group_id):
88 | update = mycol.update_one(
89 | {'_id': user_id},
90 | {"$set": {"active_group" : group_id}}
91 | )
92 | return update.modified_count != 0
93 |
94 |
95 | async def make_inactive(user_id):
96 | update = mycol.update_one(
97 | {'_id': user_id},
98 | {"$set": {"active_group" : None}}
99 | )
100 | return update.modified_count != 0
101 |
102 |
103 | async def delete_connection(user_id, group_id):
104 |
105 | try:
106 | update = mycol.update_one(
107 | {"_id": user_id},
108 | {"$pull" : { "group_details" : {"group_id":group_id} } }
109 | )
110 | if update.modified_count == 0:
111 | return False
112 | query = mycol.find_one(
113 | { "_id": user_id },
114 | { "_id": 0 }
115 | )
116 | if len(query["group_details"]) >= 1:
117 | if query['active_group'] == group_id:
118 | prvs_group_id = query["group_details"][len(query["group_details"]) - 1]["group_id"]
119 |
120 | mycol.update_one(
121 | {'_id': user_id},
122 | {"$set": {"active_group" : prvs_group_id}}
123 | )
124 | else:
125 | mycol.update_one(
126 | {'_id': user_id},
127 | {"$set": {"active_group" : None}}
128 | )
129 | return True
130 | except Exception as e:
131 | logger.exception(f'Some error occurred! {e}', exc_info=True)
132 | return False
133 |
134 |
--------------------------------------------------------------------------------
/bot.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import logging.config
3 |
4 | # Get logging configurations
5 | logging.config.fileConfig('logging.conf')
6 | logging.getLogger().setLevel(logging.INFO)
7 | logging.getLogger("pyrogram").setLevel(logging.ERROR)
8 | logging.getLogger("imdbpy").setLevel(logging.ERROR)
9 |
10 | from pyrogram import Client, __version__
11 | from pyrogram.raw.all import layer
12 | from database.ia_filterdb import Media
13 | from database.users_chats_db import db
14 | from info import SESSION, API_ID, API_HASH, BOT_TOKEN, LOG_STR, LOG_CHANNEL, PORT ,SUPPORT_CHAT_ID
15 | from utils import temp
16 | from typing import Union, Optional, AsyncGenerator
17 | from pyrogram import types
18 | from Script import script
19 | from datetime import date, datetime
20 | import pytz
21 | from aiohttp import web
22 | from plugins import web_server
23 |
24 | class Bot(Client):
25 |
26 | def __init__(self):
27 | super().__init__(
28 | name=SESSION,
29 | api_id=API_ID,
30 | api_hash=API_HASH,
31 | bot_token=BOT_TOKEN,
32 | workers=50,
33 | plugins={"root": "plugins"},
34 | sleep_threshold=5,
35 | )
36 |
37 | async def start(self):
38 | b_users, b_chats = await db.get_banned()
39 | temp.BANNED_USERS = b_users
40 | temp.BANNED_CHATS = b_chats
41 | await super().start()
42 | await Media.ensure_indexes()
43 | me = await self.get_me()
44 | temp.ME = me.id
45 | temp.U_NAME = me.username
46 | temp.B_NAME = me.first_name
47 | self.username = '@' + me.username
48 | logging.info(f"{me.first_name} with for Pyrogram v{__version__} (Layer {layer}) started on {me.username}.")
49 | logging.info(LOG_STR)
50 | logging.info(script.LOGO)
51 | tz = pytz.timezone('Asia/Kolkata')
52 | today = date.today()
53 | now = datetime.now(tz)
54 | time = now.strftime("%H:%M:%S %p")
55 | await self.send_message(chat_id=LOG_CHANNEL, text=script.RESTART_TXT.format(today, time))
56 | await self.send_message(chat_id=SUPPORT_CHAT_ID, text=script.RESTART_GC_TXT.format(today, time))
57 | app = web.AppRunner(await web_server())
58 | await app.setup()
59 | bind_address = "0.0.0.0"
60 | await web.TCPSite(app, bind_address, PORT).start()
61 |
62 | async def stop(self, *args):
63 | await super().stop()
64 | logging.info("Bot stopped. Bye.")
65 |
66 | async def iter_messages(
67 | self,
68 | chat_id: Union[int, str],
69 | limit: int,
70 | offset: int = 0,
71 | ) -> Optional[AsyncGenerator["types.Message", None]]:
72 | """Iterate through a chat sequentially.
73 | This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_messages` in a loop, thus saving
74 | you from the hassle of setting up boilerplate code. It is useful for getting the whole chat messages with a
75 | single call.
76 | Parameters:
77 | chat_id (``int`` | ``str``):
78 | Unique identifier (int) or username (str) of the target chat.
79 | For your personal cloud (Saved Messages) you can simply use "me" or "self".
80 | For a contact that exists in your Telegram address book you can use his phone number (str).
81 |
82 | limit (``int``):
83 | Identifier of the last message to be returned.
84 |
85 | offset (``int``, *optional*):
86 | Identifier of the first message to be returned.
87 | Defaults to 0.
88 | Returns:
89 | ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
90 | Example:
91 | .. code-block:: python
92 | for message in app.iter_messages("pyrogram", 1, 15000):
93 | print(message.text)
94 | """
95 | current = offset
96 | while True:
97 | new_diff = min(200, limit - current)
98 | if new_diff <= 0:
99 | return
100 | messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1)))
101 | for message in messages:
102 | yield message
103 | current += 1
104 |
105 |
106 | app = Bot()
107 | app.run()
108 |
--------------------------------------------------------------------------------
/plugins/check_alive.py:
--------------------------------------------------------------------------------
1 | import random
2 | import re, asyncio, time, shutil, psutil, os, sys
3 | from pyrogram import Client, filters, enums
4 | from pyrogram.types import *
5 | from info import BOT_START_TIME, ADMINS
6 | from utils import humanbytes
7 |
8 | CMD = ["/", "."]
9 |
10 | @Client.on_message(filters.command("alive", CMD))
11 | async def check_alive(_, message):
12 | await message.reply_text("𝖡𝗎𝖽𝖽𝗒 𝖨𝖺𝗆 𝖠𝗅𝗂𝗏𝖾 :) 𝖧𝗂𝗍 /start \n\n𝖧𝗂𝗍 /help 𝖥𝗈𝗋 𝖧𝖾𝗅𝗉 ;)\n\n\n𝖧𝗂𝗍 /ping 𝖳𝗈 𝖢𝗁𝖾𝖼𝗄 𝖡𝗈𝗍 𝖯𝗂𝗇𝗀 😁")
13 |
14 | @Client.on_message(filters.command("help", CMD))
15 | async def help(_, message):
16 | await message.reply_text("𝖧𝗂𝗍 /movie 𝖥𝗈𝗋 𝖬𝗈𝗏𝗂𝖾 𝖲𝖾𝖺𝗋𝖼𝗁 𝖱𝗎𝗅𝖾𝗌 📃\n\n𝖧𝗂𝗍 /series 𝖥𝗈𝗋 𝖲𝖾𝗋𝗂𝖾𝗌 𝖲𝖾𝖺𝗋𝖼𝗁 𝖱𝗎𝗅𝖾𝗌 📃\n\n\n𝖧𝗂𝗍 /tutorial 𝖥𝗈𝗋 𝖯𝗋𝗈𝗉𝖾𝗋 𝖳𝗎𝗍𝗈𝗋𝗂𝖺𝗅 𝖵𝗂𝖽𝖾𝗈𝗌 🤗")
17 |
18 |
19 | @Client.on_message(filters.command("movie", CMD))
20 | async def movie(_, message):
21 | await message.reply_text("⚠️❗️ 𝗠𝗼𝘃𝗶𝗲 𝗥𝗲𝗾𝘂𝗲𝘀𝘁 𝗙𝗼𝗿𝗺𝗮𝘁 ❗️⚠️\n\n📝 𝖬𝗈𝗏𝗂𝖾 𝖭𝖺𝗆𝖾, 𝖸𝖾𝖺𝗋,(𝖨𝖿 𝗒𝗈𝗎 𝖪𝗇𝗈𝗐) 𝖶𝗂𝗍𝗁 𝖢𝗈𝗋𝗋𝖾𝖼𝗍 𝖲𝗉𝖾𝗅𝗅𝗂𝗇𝗀 📚\n\n🗣 𝖨𝖿 𝖨𝗍 𝗂𝗌 𝖺 𝖥𝗂𝗅𝗆 𝖲𝖾𝗋𝗂𝖾𝗌. 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 𝖮𝗇𝖾 𝖡𝗒 𝖮𝗇𝖾 𝖶𝗂𝗍𝗁 𝖯𝗋𝗈𝗉𝖾𝗋 𝖭𝖺𝗆𝖾 🧠\n\n🖇𝐄𝐱𝐚𝐦𝐩𝐥𝐞:\n\n• Robin Hood ✅\n• Robin Hood 2010✅\n• Kurup 2021 Kan✅ \n• Harry Potter and the Philosophers Stone✅\n• Harry Potter and the Prisoner of Azkaban✅\n\n🥱 𝖥𝗈𝗋 𝖫𝖺𝗇𝗀𝗎𝖺𝗀𝖾 𝖠𝗎𝖽𝗂𝗈𝗌 - 𝖪𝖺𝗇 𝖿𝗈𝗋 𝖪𝖺𝗇𝗇𝖺𝖽𝖺, 𝖬𝖺𝗅 - 𝖬𝖺𝗅𝖺𝗒𝖺𝗅𝖺𝗆, 𝖳𝖺𝗆 - 𝖳𝖺𝗆𝗂𝗅\n\n🔎 𝖴𝗌𝖾 𝖥𝗂𝗋𝗌𝗍 3 𝖫𝖾𝗍𝗍𝖾𝗋𝗌 𝖮𝖿 𝖫𝖺𝗇𝗀𝗎𝖺𝗀𝖾 𝖥𝗈𝗋 𝖠𝗎𝖽𝗂𝗈𝗌 [𝖪𝖺𝗇 𝖳𝖺𝗆 𝖳𝖾𝗅 𝖬𝖺𝗅 𝖧𝗂𝗇 𝖲𝗉𝖺 𝖤𝗇𝗀 𝖪𝗈𝗋 𝖾𝗍𝖼...]\n\n❌ [𝗗𝗼𝗻𝘁 𝗨𝘀𝗲 𝘄𝗼𝗿𝗱𝘀 𝗟𝗶𝗸𝗲 𝗗𝘂𝗯𝗯𝗲𝗱/𝗠𝗼𝘃𝗶𝗲𝘀/𝗦𝗲𝗻𝗱/𝗛𝗗 , . : - 𝗲𝘁𝗰] ❌")
22 |
23 | @Client.on_message(filters.command("series", CMD))
24 | async def series(_, message):
25 | await message.reply_text("⚠️❗️ 𝗦𝗲𝗿𝗶𝗲𝘀 𝗥𝗲𝗾𝘂𝗲𝘀𝘁 𝗙𝗼𝗿𝗺𝗮𝘁 ❗️⚠️\n\n🗣 𝖲𝖾𝗋𝗂𝖾𝗌 𝖭𝖺𝗆𝖾,𝖲𝖾𝖺𝗌𝗈𝗇 (𝖶𝗁𝗂𝖼𝗁 𝖲𝖾𝖺𝗌𝗈𝗇 𝗒𝗈𝗎 𝗐𝖺𝗇𝗍) 🧠\n\n🖇𝐄𝐱𝐚𝐦𝐩𝐥𝐞: \n\n• Game Of Thrones S03𝖤02 720𝗉✅\n• Sex Education S02 720p✅ \n• Breaking Bad S01E05✅ \n• Prison Break 1080p✅ \n• Witcher S02✅\n\n🥱 𝖥𝗈𝗋 𝖲𝖾𝖺𝗌𝗈𝗇 𝖬𝖾𝗇𝗍𝗂𝗈𝗇 𝖠𝗌 𝖲01 𝖥𝗈𝗋 𝖲𝖾𝖺𝗌𝗈𝗇 1, 𝖲02 𝖥𝗈𝗋 𝖲𝖾𝖺𝗌𝗈𝗇 2 𝖾𝗍𝖼 [𝖲03,𝖲04 ,𝖲06,𝖲10,𝖲17] 𝖦𝗈𝖾𝗌 𝖫𝗂𝗄𝖾 𝖳𝗁𝖺𝗍\n\n🔎 𝖥𝗈𝗋 𝖤𝗉𝗂𝗌𝗈𝖽𝖾 𝖬𝖾𝗇𝗍𝗂𝗈𝗇 𝖠𝗌 𝖤𝗉01 𝖥𝗈𝗋 𝖤𝗉𝗂𝗌𝗈𝖽𝖾 1, 𝖤𝗉02 𝖥𝗈𝗋 𝖤𝗉𝗂𝗌𝗈𝖽𝖾 2 𝖾𝗍𝖼 [𝖤𝗉03,𝖤𝗉07,𝖤𝗉17,𝖤𝗉21] 𝖦𝗈'𝗌 𝖫𝗂𝗄𝖾 𝖳𝗁𝖺𝗍 \n\n❌ [𝗗𝗼𝗻𝘁 𝗨𝘀𝗲 𝘄𝗼𝗿𝗱𝘀 𝗟𝗶𝗸𝗲 𝗦𝗲𝗮𝘀𝗼𝗻/𝗘𝗽𝗶𝘀𝗼𝗱𝗲/𝗦𝗲𝗿𝗶𝗲𝘀 , . : - 𝗲𝘁𝗰] ❌")
26 |
27 | @Client.on_message(filters.command("tutorial", CMD))
28 | async def tutorial(_, message):
29 | await message.reply_text("𝖢𝗁𝖾𝖼𝗄𝗈𝗎𝗍 @piro_tuts 𝖥𝗈𝗋 𝖳𝗎𝗍𝗈𝗋𝗂𝖺𝗅𝗌 😎")
30 |
31 | @Client.on_message(filters.command("ping", CMD))
32 | async def ping(_, message):
33 | start_t = time.time()
34 | rm = await message.reply_text("...........")
35 | end_t = time.time()
36 | time_taken_s = (end_t - start_t) * 1000
37 | await rm.edit(f"𝖯𝗂𝗇𝗀!\n{time_taken_s:.3f} ms")
38 |
39 | @Client.on_message(filters.command("status"))
40 | async def stats(bot, update):
41 | currentTime = time.strftime("%Hh%Mm%Ss", time.gmtime(time.time() - BOT_START_TIME))
42 | total, used, free = shutil.disk_usage(".")
43 | total = humanbytes(total)
44 | used = humanbytes(used)
45 | free = humanbytes(free)
46 | cpu_usage = psutil.cpu_percent()
47 | ram_usage = psutil.virtual_memory().percent
48 | disk_usage = psutil.disk_usage('/').percent
49 |
50 | ms_g = f"""⚙️ 𝖡𝗈𝗍 𝖲𝗍𝖺𝗍𝗎𝗌
51 |
52 | 🕔 𝖴𝗉𝗍𝗂𝗆𝖾: {currentTime}
53 | 🛠 𝖢𝖯𝖴 𝖴𝗌𝖺𝗀𝖾: {cpu_usage}%
54 | 🗜 𝖱𝖠𝖬 𝖴𝗌𝖺𝗀𝖾: {ram_usage}%
55 | 🗂 𝖳𝗈𝗍𝖺𝗅 𝖣𝗂𝗌𝗄 𝖲𝗉𝖺𝖼𝖾: {total}
56 | 🗳 𝖴𝗌𝖾𝖽 𝖲𝗉𝖺𝖼𝖾: {used} ({disk_usage}%)
57 | 📝 𝖥𝗋𝖾𝖾 𝖲𝗉𝖺𝖼𝖾: {free} """
58 |
59 | msg = await bot.send_message(chat_id=update.chat.id, text="__𝖯𝗋𝗈𝖼𝖾𝗌𝗌𝗂𝗇𝗀...__", parse_mode=enums.ParseMode.MARKDOWN)
60 | await msg.edit_text(text=ms_g, parse_mode=enums.ParseMode.HTML)
61 |
62 | @Client.on_message(filters.command("restart") & filters.user(ADMINS))
63 | async def stop_button(bot, message):
64 | msg = await bot.send_message(text="**𝖡𝗈𝗍 𝖨𝗌 𝖱𝖾𝗌𝗍𝖺𝗋𝗍𝗂𝗇𝗀...🪄**", chat_id=message.chat.id)
65 | await asyncio.sleep(3)
66 | await msg.edit("**𝖡𝗈𝗍 𝖱𝖾𝗌𝗍𝖺𝗋𝗍𝖾𝖽 𝖲𝗎𝖼𝖼𝖾𝗌𝗌𝖿𝗎𝗅𝗅𝗒 ! 𝖱𝖾𝖺𝖽𝗒 𝖳𝗈 𝖬𝗈𝗏𝖾 𝖮𝗇 💯**")
67 | os.execl(sys.executable, sys.executable, *sys.argv)
--------------------------------------------------------------------------------
/database/users_chats_db.py:
--------------------------------------------------------------------------------
1 | import motor.motor_asyncio
2 | from info import DATABASE_NAME, DATABASE_URI, IMDB, IMDB_TEMPLATE, MELCOW_NEW_USERS, P_TTI_SHOW_OFF, SINGLE_BUTTON, SPELL_CHECK_REPLY, PROTECT_CONTENT, AUTO_DELETE, AUTO_FFILTER, MAX_BTN
3 |
4 | class Database:
5 |
6 | def __init__(self, uri, database_name):
7 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
8 | self.db = self._client[database_name]
9 | self.col = self.db.users
10 | self.grp = self.db.groups
11 |
12 |
13 | def new_user(self, id, name):
14 | return dict(
15 | id = id,
16 | name = name,
17 | ban_status=dict(
18 | is_banned=False,
19 | ban_reason="",
20 | ),
21 | )
22 |
23 |
24 | def new_group(self, id, title):
25 | return dict(
26 | id = id,
27 | title = title,
28 | chat_status=dict(
29 | is_disabled=False,
30 | reason="",
31 | ),
32 | )
33 |
34 | async def add_user(self, id, name):
35 | user = self.new_user(id, name)
36 | await self.col.insert_one(user)
37 |
38 | async def is_user_exist(self, id):
39 | user = await self.col.find_one({'id':int(id)})
40 | return bool(user)
41 |
42 | async def total_users_count(self):
43 | count = await self.col.count_documents({})
44 | return count
45 |
46 | async def remove_ban(self, id):
47 | ban_status = dict(
48 | is_banned=False,
49 | ban_reason=''
50 | )
51 | await self.col.update_one({'id': id}, {'$set': {'ban_status': ban_status}})
52 |
53 | async def ban_user(self, user_id, ban_reason="No Reason"):
54 | ban_status = dict(
55 | is_banned=True,
56 | ban_reason=ban_reason
57 | )
58 | await self.col.update_one({'id': user_id}, {'$set': {'ban_status': ban_status}})
59 |
60 | async def get_ban_status(self, id):
61 | default = dict(
62 | is_banned=False,
63 | ban_reason=''
64 | )
65 | user = await self.col.find_one({'id':int(id)})
66 | if not user:
67 | return default
68 | return user.get('ban_status', default)
69 |
70 | async def get_all_users(self):
71 | return self.col.find({})
72 |
73 |
74 | async def delete_user(self, user_id):
75 | await self.col.delete_many({'id': int(user_id)})
76 |
77 |
78 | async def get_banned(self):
79 | users = self.col.find({'ban_status.is_banned': True})
80 | chats = self.grp.find({'chat_status.is_disabled': True})
81 | b_chats = [chat['id'] async for chat in chats]
82 | b_users = [user['id'] async for user in users]
83 | return b_users, b_chats
84 |
85 |
86 |
87 | async def add_chat(self, chat, title):
88 | chat = self.new_group(chat, title)
89 | await self.grp.insert_one(chat)
90 |
91 |
92 | async def get_chat(self, chat):
93 | chat = await self.grp.find_one({'id':int(chat)})
94 | return False if not chat else chat.get('chat_status')
95 |
96 |
97 | async def re_enable_chat(self, id):
98 | chat_status=dict(
99 | is_disabled=False,
100 | reason="",
101 | )
102 | await self.grp.update_one({'id': int(id)}, {'$set': {'chat_status': chat_status}})
103 |
104 | async def update_settings(self, id, settings):
105 | await self.grp.update_one({'id': int(id)}, {'$set': {'settings': settings}})
106 |
107 |
108 | async def get_settings(self, id):
109 | default = {
110 | 'button': SINGLE_BUTTON,
111 | 'botpm': P_TTI_SHOW_OFF,
112 | 'file_secure': PROTECT_CONTENT,
113 | 'imdb': IMDB,
114 | 'spell_check': SPELL_CHECK_REPLY,
115 | 'welcome': MELCOW_NEW_USERS,
116 | 'auto_delete': AUTO_DELETE,
117 | 'auto_ffilter': AUTO_FFILTER,
118 | 'max_btn': MAX_BTN,
119 | 'template': IMDB_TEMPLATE
120 | }
121 | chat = await self.grp.find_one({'id':int(id)})
122 | if chat:
123 | return chat.get('settings', default)
124 | return default
125 |
126 |
127 | async def disable_chat(self, chat, reason="No Reason"):
128 | chat_status=dict(
129 | is_disabled=True,
130 | reason=reason,
131 | )
132 | await self.grp.update_one({'id': int(chat)}, {'$set': {'chat_status': chat_status}})
133 |
134 |
135 | async def total_chat_count(self):
136 | count = await self.grp.count_documents({})
137 | return count
138 |
139 |
140 | async def get_all_chats(self):
141 | return self.grp.find({})
142 |
143 |
144 | async def get_db_size(self):
145 | return (await self.db.command("dbstats"))['dataSize']
146 |
147 |
148 | db = Database(DATABASE_URI, DATABASE_NAME)
149 |
--------------------------------------------------------------------------------
/plugins/inline.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from pyrogram import Client, emoji, filters
3 | from pyrogram.errors.exceptions.bad_request_400 import QueryIdInvalid
4 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, InlineQueryResultCachedDocument, InlineQuery
5 | from database.ia_filterdb import get_search_results
6 | from utils import is_subscribed, get_size, temp
7 | from info import CACHE_TIME, AUTH_USERS, AUTH_CHANNEL, CUSTOM_FILE_CAPTION
8 | from database.connections_mdb import active_connection
9 |
10 | logger = logging.getLogger(__name__)
11 | cache_time = 0 if AUTH_USERS or AUTH_CHANNEL else CACHE_TIME
12 |
13 | async def inline_users(query: InlineQuery):
14 | if AUTH_USERS:
15 | if query.from_user and query.from_user.id in AUTH_USERS:
16 | return True
17 | else:
18 | return False
19 | if query.from_user and query.from_user.id not in temp.BANNED_USERS:
20 | return True
21 | return False
22 |
23 | @Client.on_inline_query()
24 | async def answer(bot, query):
25 | """𝖲𝗁𝗈𝗐 𝖲𝖾𝖺𝗋𝖼𝗁 𝖱𝖾𝗌𝗎𝗅𝗍𝗌 𝖥𝗈𝗋 𝖦𝗂𝗏𝖾𝗇 𝖨𝗇𝗅𝗂𝗇𝖾 𝖰𝗎𝖾𝗋𝗒"""
26 | chat_id = await active_connection(str(query.from_user.id))
27 |
28 | if not await inline_users(query):
29 | await query.answer(results=[],
30 | cache_time=0,
31 | switch_pm_text='okDa',
32 | switch_pm_parameter="hehe")
33 | return
34 |
35 | if AUTH_CHANNEL and not await is_subscribed(bot, query):
36 | await query.answer(results=[],
37 | cache_time=0,
38 | switch_pm_text='𝖸𝗈𝗎 𝖧𝖺𝗏𝖾 𝖳𝗈 𝖲𝗎𝖻𝗌𝖼𝗋𝗂𝖻𝖾 𝖬𝗒 𝖢𝗁𝖺𝗇𝗇𝖾𝗅 𝖳𝗈 𝖴𝗌𝖾 𝖬𝖾 :)',
39 | switch_pm_parameter="subscribe")
40 | return
41 |
42 | results = []
43 | if '|' in query.query:
44 | string, file_type = query.query.split('|', maxsplit=1)
45 | string = string.strip()
46 | file_type = file_type.strip().lower()
47 | else:
48 | string = query.query.strip()
49 | file_type = None
50 |
51 | offset = int(query.offset or 0)
52 | reply_markup = get_reply_markup(query=string)
53 | files, next_offset, total = await get_search_results(
54 | chat_id,
55 | string,
56 | file_type=file_type,
57 | max_results=10,
58 | offset=offset)
59 |
60 | for file in files:
61 | title=file.file_name
62 | size=get_size(file.file_size)
63 | f_caption=file.caption
64 | if CUSTOM_FILE_CAPTION:
65 | try:
66 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='' if f_caption is None else f_caption)
67 | except Exception as e:
68 | logger.exception(e)
69 | f_caption=f_caption
70 | if f_caption is None:
71 | f_caption = f"{file.file_name}"
72 | results.append(
73 | InlineQueryResultCachedDocument(
74 | title=file.file_name,
75 | document_file_id=file.file_id,
76 | caption=f_caption,
77 | description=f'Size: {get_size(file.file_size)}\nType: {file.file_type}',
78 | reply_markup=reply_markup))
79 |
80 | if results:
81 | switch_pm_text = f"{emoji.FILE_FOLDER} 𝖧𝖾𝗋𝖾 𝖨𝗌 𝖳𝗁𝖾 𝖱𝖾𝗌𝗎𝗅𝗍𝗌 "
82 | if string:
83 | switch_pm_text += f" for {string}"
84 | try:
85 | await query.answer(results=results,
86 | is_personal = True,
87 | cache_time=cache_time,
88 | switch_pm_text=switch_pm_text,
89 | switch_pm_parameter="start",
90 | next_offset=str(next_offset))
91 | except QueryIdInvalid:
92 | pass
93 | except Exception as e:
94 | logging.exception(str(e))
95 | else:
96 | switch_pm_text = f'{emoji.CROSS_MARK} 𝖭𝗈 𝖱𝖾𝗌𝗎𝗅𝗍𝗌 𝖥𝗈𝗎𝗇𝖽'
97 | if string:
98 | switch_pm_text += f' for "{string}"'
99 |
100 | await query.answer(results=[],
101 | is_personal = True,
102 | cache_time=cache_time,
103 | switch_pm_text=switch_pm_text,
104 | switch_pm_parameter="okay")
105 |
106 |
107 | def get_reply_markup(query):
108 | buttons = [
109 | [
110 | InlineKeyboardButton('🔎 𝖲𝖾𝖺𝗋𝖼𝗁 𝖠𝗀𝖺𝗂𝗇', switch_inline_query_current_chat=query),
111 | InlineKeyboardButton('⚡𝖴𝗉𝖽𝖺𝗍𝖾𝗌 ⚡', url="https://t.me/piroxbots")
112 | ]
113 | ]
114 | return InlineKeyboardMarkup(buttons)
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/plugins/gfilters.py:
--------------------------------------------------------------------------------
1 | import io
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
4 | from database.gfilters_mdb import(
5 | add_gfilter,
6 | get_gfilters,
7 | delete_gfilter,
8 | count_gfilters
9 | )
10 |
11 | from database.connections_mdb import active_connection
12 | from utils import get_file_id, gfilterparser, split_quotes
13 | from info import ADMINS
14 |
15 |
16 | @Client.on_message(filters.command(['gfilter', 'addg']) & filters.incoming & filters.user(ADMINS))
17 | async def addgfilter(client, message):
18 | args = message.text.html.split(None, 1)
19 |
20 | if len(args) < 2:
21 | await message.reply_text("Command Incomplete :(", quote=True)
22 | return
23 |
24 | extracted = split_quotes(args[1])
25 | text = extracted[0].lower()
26 |
27 | if not message.reply_to_message and len(extracted) < 2:
28 | await message.reply_text("Add some content to save your filter!", quote=True)
29 | return
30 |
31 | if (len(extracted) >= 2) and not message.reply_to_message:
32 | reply_text, btn, alert = gfilterparser(extracted[1], text)
33 | fileid = None
34 | if not reply_text:
35 | await message.reply_text("You cannot have buttons alone, give some text to go with it!", quote=True)
36 | return
37 |
38 | elif message.reply_to_message and message.reply_to_message.reply_markup:
39 | try:
40 | rm = message.reply_to_message.reply_markup
41 | btn = rm.inline_keyboard
42 | msg = get_file_id(message.reply_to_message)
43 | if msg:
44 | fileid = msg.file_id
45 | reply_text = message.reply_to_message.caption.html
46 | else:
47 | reply_text = message.reply_to_message.text.html
48 | fileid = None
49 | alert = None
50 | except:
51 | reply_text = ""
52 | btn = "[]"
53 | fileid = None
54 | alert = None
55 |
56 | elif message.reply_to_message and message.reply_to_message.media:
57 | try:
58 | msg = get_file_id(message.reply_to_message)
59 | fileid = msg.file_id if msg else None
60 | reply_text, btn, alert = gfilterparser(extracted[1], text) if message.reply_to_message.sticker else gfilterparser(message.reply_to_message.caption.html, text)
61 | except:
62 | reply_text = ""
63 | btn = "[]"
64 | alert = None
65 | elif message.reply_to_message and message.reply_to_message.text:
66 | try:
67 | fileid = None
68 | reply_text, btn, alert = gfilterparser(message.reply_to_message.text.html, text)
69 | except:
70 | reply_text = ""
71 | btn = "[]"
72 | alert = None
73 | else:
74 | return
75 |
76 | await add_gfilter('gfilters', text, reply_text, btn, fileid, alert)
77 |
78 | await message.reply_text(
79 | f"GFilter for `{text}` added",
80 | quote=True,
81 | parse_mode=enums.ParseMode.MARKDOWN
82 | )
83 |
84 |
85 | @Client.on_message(filters.command(['viewgfilters', 'gfilters']) & filters.incoming & filters.user(ADMINS))
86 | async def get_all_gfilters(client, message):
87 | texts = await get_gfilters('gfilters')
88 | count = await count_gfilters('gfilters')
89 | if count:
90 | gfilterlist = f"Total number of gfilters : {count}\n\n"
91 |
92 | for text in texts:
93 | keywords = " × `{}`\n".format(text)
94 |
95 | gfilterlist += keywords
96 |
97 | if len(gfilterlist) > 4096:
98 | with io.BytesIO(str.encode(gfilterlist.replace("`", ""))) as keyword_file:
99 | keyword_file.name = "keywords.txt"
100 | await message.reply_document(
101 | document=keyword_file,
102 | quote=True
103 | )
104 | return
105 | else:
106 | gfilterlist = f"There are no active gfilters."
107 |
108 | await message.reply_text(
109 | text=gfilterlist,
110 | quote=True,
111 | parse_mode=enums.ParseMode.MARKDOWN
112 | )
113 |
114 | @Client.on_message(filters.command('delg') & filters.incoming & filters.user(ADMINS))
115 | async def deletegfilter(client, message):
116 | try:
117 | cmd, text = message.text.split(" ", 1)
118 | except:
119 | await message.reply_text(
120 | "Mention the gfiltername which you wanna delete!\n\n"
121 | "/delg gfiltername\n\n"
122 | "Use /viewgfilters to view all available gfilters",
123 | quote=True
124 | )
125 | return
126 |
127 | query = text.lower()
128 |
129 | await delete_gfilter(message, query, 'gfilters')
130 |
131 | @Client.on_message(filters.command('delallg') & filters.user(ADMINS))
132 | async def delallgfilters(client, message):
133 | await message.reply_text(
134 | f"Do you want to continue??",
135 | reply_markup=InlineKeyboardMarkup([
136 | [InlineKeyboardButton(text="YES",callback_data="gfiltersdeleteallconfirm")],
137 | [InlineKeyboardButton(text="CANCEL",callback_data="gfiltersdeleteallcancel")]
138 | ]),
139 | quote=True
140 | )
--------------------------------------------------------------------------------
/plugins/genlink.py:
--------------------------------------------------------------------------------
1 | import re
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, UsernameInvalid, UsernameNotModified
4 | from info import ADMINS, LOG_CHANNEL, FILE_STORE_CHANNEL, PUBLIC_FILE_STORE
5 | from database.ia_filterdb import unpack_new_file_id
6 | from utils import temp
7 | import re
8 | import os
9 | import json
10 | import base64
11 | import logging
12 |
13 | logger = logging.getLogger(__name__)
14 | logger.setLevel(logging.INFO)
15 |
16 | async def allowed(_, __, message):
17 | if PUBLIC_FILE_STORE:
18 | return True
19 | if message.from_user and message.from_user.id in ADMINS:
20 | return True
21 | return False
22 |
23 | @Client.on_message(filters.command(['link', 'plink']) & filters.create(allowed))
24 | async def gen_link_s(bot, message):
25 | replied = message.reply_to_message
26 | if not replied:
27 | return await message.reply('Reply to a message to get a shareable link.')
28 | file_type = replied.media
29 | if file_type not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]:
30 | return await message.reply("Reply to a supported media")
31 | if message.has_protected_content and message.chat.id not in ADMINS:
32 | return await message.reply("okDa")
33 | file_id, ref = unpack_new_file_id((getattr(replied, file_type.value)).file_id)
34 | string = 'filep_' if message.text.lower().strip() == "/plink" else 'file_'
35 | string += file_id
36 | outstr = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
37 | await message.reply(f"Here is your Link:\nhttps://t.me/{temp.U_NAME}?start={outstr}")
38 |
39 |
40 | @Client.on_message(filters.command(['batch', 'pbatch']) & filters.create(allowed))
41 | async def gen_link_batch(bot, message):
42 | if " " not in message.text:
43 | return await message.reply("Use correct format.\nExample /batch https://t.me/piroxbots/10 https://t.me/piroxbots/20.")
44 | links = message.text.strip().split(" ")
45 | if len(links) != 3:
46 | return await message.reply("Use correct format.\nExample /batch https://t.me/piroxbots/10 https://t.me/piroxbots/20.")
47 | cmd, first, last = links
48 | regex = re.compile("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
49 | match = regex.match(first)
50 | if not match:
51 | return await message.reply('Invalid link')
52 | f_chat_id = match.group(4)
53 | f_msg_id = int(match.group(5))
54 | if f_chat_id.isnumeric():
55 | f_chat_id = int(("-100" + f_chat_id))
56 |
57 | match = regex.match(last)
58 | if not match:
59 | return await message.reply('Invalid link')
60 | l_chat_id = match.group(4)
61 | l_msg_id = int(match.group(5))
62 | if l_chat_id.isnumeric():
63 | l_chat_id = int(("-100" + l_chat_id))
64 |
65 | if f_chat_id != l_chat_id:
66 | return await message.reply("Chat ids not matched.")
67 | try:
68 | chat_id = (await bot.get_chat(f_chat_id)).id
69 | except ChannelInvalid:
70 | return await message.reply('This may be a private channel / group. Make me an admin over there to index the files.')
71 | except (UsernameInvalid, UsernameNotModified):
72 | return await message.reply('Invalid Link specified.')
73 | except Exception as e:
74 | return await message.reply(f'Errors - {e}')
75 |
76 | sts = await message.reply("Generating link for your message.\nThis may take time depending upon number of messages")
77 | if chat_id in FILE_STORE_CHANNEL:
78 | string = f"{f_msg_id}_{l_msg_id}_{chat_id}_{cmd.lower().strip()}"
79 | b_64 = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
80 | return await sts.edit(f"Here is your link https://t.me/{temp.U_NAME}?start=DSTORE-{b_64}")
81 |
82 | FRMT = "Generating Link...\nTotal Messages: `{total}`\nDone: `{current}`\nRemaining: `{rem}`\nStatus: `{sts}`"
83 |
84 | outlist = []
85 |
86 | # file store without db channel
87 | og_msg = 0
88 | tot = 0
89 | async for msg in bot.iter_messages(f_chat_id, l_msg_id, f_msg_id):
90 | tot += 1
91 | if msg.empty or msg.service:
92 | continue
93 | if not msg.media:
94 | # only media messages supported.
95 | continue
96 | try:
97 | file_type = msg.media
98 | file = getattr(msg, file_type.value)
99 | caption = getattr(msg, 'caption', '')
100 | if caption:
101 | caption = caption.html
102 | if file:
103 | file = {
104 | "file_id": file.file_id,
105 | "caption": caption,
106 | "title": getattr(file, "file_name", ""),
107 | "size": file.file_size,
108 | "protect": cmd.lower().strip() == "/pbatch",
109 | }
110 |
111 | og_msg +=1
112 | outlist.append(file)
113 | except:
114 | pass
115 | if not og_msg % 20:
116 | try:
117 | await sts.edit(FRMT.format(total=l_msg_id-f_msg_id, current=tot, rem=((l_msg_id-f_msg_id) - tot), sts="Saving Messages"))
118 | except:
119 | pass
120 | with open(f"batchmode_{message.from_user.id}.json", "w+") as out:
121 | json.dump(outlist, out)
122 | post = await bot.send_document(LOG_CHANNEL, f"batchmode_{message.from_user.id}.json", file_name="Batch.json", caption="⚠️Generated for filestore.")
123 | os.remove(f"batchmode_{message.from_user.id}.json")
124 | file_id, ref = unpack_new_file_id(post.document.file_id)
125 | await sts.edit(f"Here is your link\nContains `{og_msg}` files.\n https://t.me/{temp.U_NAME}?start=BATCH-{file_id}")
126 |
--------------------------------------------------------------------------------
/info.py:
--------------------------------------------------------------------------------
1 | import re
2 | from os import environ
3 | import asyncio
4 | import json
5 | from collections import defaultdict
6 | from typing import Dict, List, Union
7 | from pyrogram import Client
8 | from time import time
9 |
10 | id_pattern = re.compile(r'^.\d+$')
11 | def is_enabled(value, default):
12 | if value.strip().lower() in ["on", "true", "yes", "1", "enable", "y"]:
13 | return True
14 | elif value.strip().lower() in ["off", "false", "no", "0", "disable", "n"]:
15 | return False
16 | else:
17 | return default
18 |
19 | # Bot information
20 | SESSION = environ.get('SESSION', 'Media_search')
21 | API_ID = int(environ.get('API_ID', ''))
22 | API_HASH = environ.get('API_HASH', '')
23 | BOT_TOKEN = environ.get('BOT_TOKEN', '')
24 | PORT = environ.get("PORT", "8080")
25 |
26 | # Bot settings
27 | CACHE_TIME = int(environ.get('CACHE_TIME', 300))
28 | USE_CAPTION_FILTER = bool(environ.get('USE_CAPTION_FILTER', True))
29 | BOT_START_TIME = time()
30 |
31 | # Bot images & videos
32 | PICS = (environ.get('PICS', 'https://telegra.ph/file/5553dc39f968b364d4856.jpg')).split()
33 | REQ_PICS = (environ.get('REQ_PICS', 'https://graph.org/file/5cb80fa6096997b7226b3.jpg')).split()
34 | NOR_IMG = environ.get("NOR_IMG", "https://telegra.ph/file/0593a3103ba1b9a5855bf.jpg")
35 | MELCOW_VID = environ.get("MELCOW_VID", "https://graph.org/file/72dff2b65352ba85d0a34.mp4")
36 | SPELL_IMG = environ.get("SPELL_IMG", "https://telegra.ph/file/2a888a370f479f4338f7c.jpg")
37 |
38 | # Admins, Channels & Users
39 | ADMINS = [int(admin) if id_pattern.search(admin) else admin for admin in environ.get('ADMINS', '').split()]
40 | CHANNELS = [int(ch) if id_pattern.search(ch) else ch for ch in environ.get('CHANNELS', '0').split()]
41 | auth_users = [int(user) if id_pattern.search(user) else user for user in environ.get('AUTH_USERS', '').split()]
42 | AUTH_USERS = (auth_users + ADMINS) if auth_users else []
43 | auth_channel = environ.get('AUTH_CHANNEL')
44 | auth_grp = environ.get('AUTH_GROUP')
45 | AUTH_CHANNEL = int(auth_channel) if auth_channel and id_pattern.search(auth_channel) else None
46 | AUTH_GROUPS = [int(ch) for ch in auth_grp.split()] if auth_grp else None
47 | support_chat_id = environ.get('SUPPORT_CHAT_ID')
48 | reqst_channel = environ.get('REQST_CHANNEL_ID')
49 | REQST_CHANNEL = int(reqst_channel) if reqst_channel and id_pattern.search(reqst_channel) else None
50 | SUPPORT_CHAT_ID = -1001792675255
51 | NO_RESULTS_MSG = bool(environ.get("NO_RESULTS_MSG", False))
52 |
53 | # MongoDB information
54 | DATABASE_URI = environ.get('DATABASE_URI', "")
55 | DATABASE_NAME = environ.get('DATABASE_NAME', "PIRO")
56 | COLLECTION_NAME = environ.get('COLLECTION_NAME', 'FILES')
57 |
58 | # Others
59 | DELETE_CHANNELS = [int(dch) if id_pattern.search(dch) else dch for dch in environ.get('DELETE_CHANNELS', '0').split()]
60 | MAX_B_TN = environ.get("MAX_B_TN", "10")
61 | MAX_BTN = is_enabled((environ.get('MAX_BTN', "True")), True)
62 | LOG_CHANNEL = int(environ.get('LOG_CHANNEL', 0))
63 | SUPPORT_CHAT = environ.get('SUPPORT_CHAT', 'raixchat')
64 | P_TTI_SHOW_OFF = is_enabled((environ.get('P_TTI_SHOW_OFF', "True")), False)
65 | IMDB = is_enabled((environ.get('IMDB', "False")), True)
66 | AUTO_FFILTER = is_enabled((environ.get('AUTO_FFILTER', "True")), True)
67 | AUTO_DELETE = is_enabled((environ.get('AUTO_DELETE', "True")), True)
68 | SINGLE_BUTTON = is_enabled((environ.get('SINGLE_BUTTON', "True")), True)
69 | CUSTOM_FILE_CAPTION = environ.get("CUSTOM_FILE_CAPTION", '📂 File Name: {file_name} \n\n❤️🔥 Join [𝗕𝗟𝗔𝗦𝗧𝗘𝗥 𝗟𝗜𝗡𝗞𝗭](https://t.me/blaster_linkz)')
70 | BATCH_FILE_CAPTION = environ.get("BATCH_FILE_CAPTION", '')
71 | IMDB_TEMPLATE = environ.get("IMDB_TEMPLATE", '🏷 𝖳𝗂𝗍𝗅𝖾: {title} \n🔮 𝖸𝖾𝖺𝗋: {year} \n⭐️ 𝖱𝖺𝗍𝗂𝗇𝗀𝗌: {rating}/ 10 \n🎭 𝖦𝖾𝗇𝖾𝗋𝗌: {genres} \n\n🎊 𝖯𝗈𝗐𝖾𝗋𝖾𝖽 𝖡𝗒 [[𝖯𝖨𝖱𝖮]](t.me/piroxbots)')
72 | LONG_IMDB_DESCRIPTION = is_enabled(environ.get("LONG_IMDB_DESCRIPTION", "False"), False)
73 | SPELL_CHECK_REPLY = is_enabled(environ.get("SPELL_CHECK_REPLY", "True"), True)
74 | MAX_LIST_ELM = environ.get("MAX_LIST_ELM", None)
75 | INDEX_REQ_CHANNEL = int(environ.get('INDEX_REQ_CHANNEL', LOG_CHANNEL))
76 | FILE_STORE_CHANNEL = [int(ch) for ch in (environ.get('FILE_STORE_CHANNEL', '')).split()]
77 | MELCOW_NEW_USERS = is_enabled((environ.get('MELCOW_NEW_USERS', "True")), True)
78 | PROTECT_CONTENT = is_enabled((environ.get('PROTECT_CONTENT', "False")), False)
79 | PUBLIC_FILE_STORE = is_enabled((environ.get('PUBLIC_FILE_STORE', "False")), True)
80 |
81 | LOG_STR = "Current Cusomized Configurations are:-\n"
82 | LOG_STR += ("IMDB Results are enabled, Bot will be showing imdb details for you queries.\n" if IMDB else "IMBD Results are disabled.\n")
83 | LOG_STR += ("P_TTI_SHOW_OFF found , Users will be redirected to send /start to Bot PM instead of sending file file directly\n" if P_TTI_SHOW_OFF else "P_TTI_SHOW_OFF is disabled files will be send in PM, instead of sending start.\n")
84 | LOG_STR += ("SINGLE_BUTTON is Found, filename and files size will be shown in a single button instead of two separate buttons\n" if SINGLE_BUTTON else "SINGLE_BUTTON is disabled , filename and file_sixe will be shown as different buttons\n")
85 | LOG_STR += (f"CUSTOM_FILE_CAPTION enabled with value {CUSTOM_FILE_CAPTION}, your files will be send along with this customized caption.\n" if CUSTOM_FILE_CAPTION else "No CUSTOM_FILE_CAPTION Found, Default captions of file will be used.\n")
86 | LOG_STR += ("Long IMDB storyline enabled." if LONG_IMDB_DESCRIPTION else "LONG_IMDB_DESCRIPTION is disabled , Plot will be shorter.\n")
87 | LOG_STR += ("Spell Check Mode Is Enabled, bot will be suggesting related movies if movie not found\n" if SPELL_CHECK_REPLY else "SPELL_CHECK_REPLY Mode disabled\n")
88 | LOG_STR += (f"MAX_LIST_ELM Found, long list will be shortened to first {MAX_LIST_ELM} elements\n" if MAX_LIST_ELM else "Full List of casts and crew will be shown in imdb template, restrict them by adding a value to MAX_LIST_ELM\n")
89 | LOG_STR += f"Your current IMDB template is {IMDB_TEMPLATE}"
90 |
--------------------------------------------------------------------------------
/plugins/connection.py:
--------------------------------------------------------------------------------
1 | from pyrogram import filters, Client, enums
2 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
3 | from database.connections_mdb import add_connection, all_connections, if_active, delete_connection
4 | from info import ADMINS
5 | from utils import temp
6 | import logging
7 |
8 | logger = logging.getLogger(__name__)
9 | logger.setLevel(logging.ERROR)
10 |
11 |
12 | @Client.on_message((filters.private | filters.group) & filters.command('connect'))
13 | async def addconnection(client, message):
14 | userid = message.from_user.id if message.from_user else None
15 | if not userid:
16 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
17 | chat_type = message.chat.type
18 |
19 | if chat_type == enums.ChatType.PRIVATE:
20 | try:
21 | cmd, group_id = message.text.split(" ", 1)
22 | except:
23 | await message.reply_text(
24 | "Enter in correct format!\n\n"
25 | "/connect groupid\n\n"
26 | "Get your Group id by adding this bot to your group and use /id",
27 | quote=True
28 | )
29 | return
30 |
31 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
32 | group_id = message.chat.id
33 |
34 | try:
35 | st = await client.get_chat_member(group_id, userid)
36 | if (
37 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
38 | and st.status != enums.ChatMemberStatus.OWNER
39 | and userid not in ADMINS
40 | ):
41 | await message.reply_text("You should be an admin in Given group!", quote=True)
42 | return
43 | except Exception as e:
44 | logger.exception(e)
45 | await message.reply_text(
46 | "Invalid Group ID!\n\nIf correct, Make sure I'm present in your group!!",
47 | quote=True,
48 | )
49 |
50 | return
51 | try:
52 | st = await client.get_chat_member(group_id, "me")
53 | if st.status == enums.ChatMemberStatus.ADMINISTRATOR:
54 | ttl = await client.get_chat(group_id)
55 | title = ttl.title
56 |
57 | addcon = await add_connection(str(group_id), str(userid))
58 | if addcon:
59 | await message.reply_text(
60 | f"Successfully connected to **{title}**\nNow manage your group from my pm !",
61 | quote=True,
62 | parse_mode=enums.ParseMode.MARKDOWN
63 | )
64 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
65 | await client.send_message(
66 | userid,
67 | f"Connected to **{title}** !",
68 | parse_mode=enums.ParseMode.MARKDOWN
69 | )
70 | else:
71 | await message.reply_text(
72 | "You're already connected to this chat!",
73 | quote=True
74 | )
75 | else:
76 | await message.reply_text("Add me as an admin in group", quote=True)
77 | except Exception as e:
78 | logger.exception(e)
79 | await message.reply_text('Some error occurred! Try again later.', quote=True)
80 | return
81 |
82 |
83 | @Client.on_message((filters.private | filters.group) & filters.command('disconnect'))
84 | async def deleteconnection(client, message):
85 | userid = message.from_user.id if message.from_user else None
86 | if not userid:
87 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
88 | chat_type = message.chat.type
89 |
90 | if chat_type == enums.ChatType.PRIVATE:
91 | await message.reply_text("Run /connections to view or disconnect from groups!", quote=True)
92 |
93 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
94 | group_id = message.chat.id
95 |
96 | st = await client.get_chat_member(group_id, userid)
97 | if (
98 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
99 | and st.status != enums.ChatMemberStatus.OWNER
100 | and str(userid) not in ADMINS
101 | ):
102 | return
103 |
104 | delcon = await delete_connection(str(userid), str(group_id))
105 | if delcon:
106 | await message.reply_text("Successfully disconnected from this chat", quote=True)
107 | else:
108 | await message.reply_text("This chat isn't connected to me!\nDo /connect to connect.", quote=True)
109 |
110 |
111 | @Client.on_message(filters.private & filters.command(["connections"]))
112 | async def connections(client, message):
113 | userid = message.from_user.id
114 |
115 | groupids = await all_connections(str(userid))
116 | if groupids is None:
117 | await message.reply_text(
118 | "There are no active connections!! Connect to some groups first.",
119 | quote=True
120 | )
121 | return
122 | buttons = []
123 | for groupid in groupids:
124 | try:
125 | ttl = await client.get_chat(int(groupid))
126 | title = ttl.title
127 | active = await if_active(str(userid), str(groupid))
128 | act = " - ACTIVE" if active else ""
129 | buttons.append(
130 | [
131 | InlineKeyboardButton(
132 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}"
133 | )
134 | ]
135 | )
136 | except:
137 | pass
138 | if buttons:
139 | await message.reply_text(
140 | "Your connected group details ;\n\n",
141 | reply_markup=InlineKeyboardMarkup(buttons),
142 | quote=True
143 | )
144 | else:
145 | await message.reply_text(
146 | "There are no active connections!! Connect to some groups first.",
147 | quote=True
148 | )
149 |
--------------------------------------------------------------------------------
/database/ia_filterdb.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from struct import pack
3 | import re
4 | import base64
5 | from pyrogram.file_id import FileId
6 | from pymongo.errors import DuplicateKeyError
7 | from umongo import Instance, Document, fields
8 | from motor.motor_asyncio import AsyncIOMotorClient
9 | from marshmallow.exceptions import ValidationError
10 | from info import DATABASE_URI, DATABASE_NAME, COLLECTION_NAME, USE_CAPTION_FILTER, MAX_B_TN
11 | from utils import get_settings, save_group_settings
12 |
13 | logger = logging.getLogger(__name__)
14 | logger.setLevel(logging.INFO)
15 |
16 |
17 | client = AsyncIOMotorClient(DATABASE_URI)
18 | db = client[DATABASE_NAME]
19 | instance = Instance.from_db(db)
20 |
21 | @instance.register
22 | class Media(Document):
23 | file_id = fields.StrField(attribute='_id')
24 | file_ref = fields.StrField(allow_none=True)
25 | file_name = fields.StrField(required=True)
26 | file_size = fields.IntField(required=True)
27 | file_type = fields.StrField(allow_none=True)
28 | mime_type = fields.StrField(allow_none=True)
29 | caption = fields.StrField(allow_none=True)
30 |
31 | class Meta:
32 | indexes = ('$file_name', )
33 | collection_name = COLLECTION_NAME
34 |
35 |
36 | async def save_file(media):
37 | """Save file in database"""
38 |
39 | # TODO: Find better way to get same file_id for same media to avoid duplicates
40 | file_id, file_ref = unpack_new_file_id(media.file_id)
41 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
42 | try:
43 | file = Media(
44 | file_id=file_id,
45 | file_ref=file_ref,
46 | file_name=file_name,
47 | file_size=media.file_size,
48 | file_type=media.file_type,
49 | mime_type=media.mime_type,
50 | caption=media.caption.html if media.caption else None,
51 | )
52 | except ValidationError:
53 | logger.exception('Error occurred while saving file in database')
54 | return False, 2
55 | else:
56 | try:
57 | await file.commit()
58 | except DuplicateKeyError:
59 | logger.warning(
60 | f'{getattr(media, "file_size", "NO_FILE")} is already saved in database'
61 | )
62 |
63 | return False, 0
64 | else:
65 | logger.info(f'{getattr(media, "file_size", "NO_FILE")} is saved to database')
66 | return True, 1
67 |
68 |
69 |
70 | async def get_search_results(chat_id, query, file_type=None, max_results=10, offset=0, filter=False):
71 | """For given query return (results, next_offset)"""
72 | if chat_id is not None:
73 | settings = await get_settings(int(chat_id))
74 | try:
75 | if settings['max_btn']:
76 | max_results = 10
77 | else:
78 | max_results = int(MAX_B_TN)
79 | except KeyError:
80 | await save_group_settings(int(chat_id), 'max_btn', False)
81 | settings = await get_settings(int(chat_id))
82 | if settings['max_btn']:
83 | max_results = 10
84 | else:
85 | max_results = int(MAX_B_TN)
86 | query = query.strip()
87 | #if filter:
88 | #better ?
89 | #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
90 | #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
91 | if not query:
92 | raw_pattern = '.'
93 | elif ' ' not in query:
94 | raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
95 | else:
96 | raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
97 |
98 | try:
99 | regex = re.compile(raw_pattern, flags=re.IGNORECASE)
100 | except:
101 | return []
102 |
103 | if USE_CAPTION_FILTER:
104 | filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
105 | else:
106 | filter = {'file_name': regex}
107 |
108 | if file_type:
109 | filter['file_type'] = file_type
110 |
111 | total_results = await Media.count_documents(filter)
112 | next_offset = offset + max_results
113 |
114 | if next_offset > total_results:
115 | next_offset = ''
116 |
117 | cursor = Media.find(filter)
118 | # Sort by recent
119 | cursor.sort('$natural', -1)
120 | # Slice files according to offset and max results
121 | cursor.skip(offset).limit(max_results)
122 | # Get list of files
123 | files = await cursor.to_list(length=max_results)
124 |
125 | return files, next_offset, total_results
126 |
127 | async def get_bad_files(query, file_type=None, filter=False):
128 | """For given query return (results, next_offset)"""
129 | query = query.strip()
130 | #if filter:
131 | #better ?
132 | #query = query.replace(' ', r'(\s|\.|\+|\-|_)')
133 | #raw_pattern = r'(\s|_|\-|\.|\+)' + query + r'(\s|_|\-|\.|\+)'
134 | if not query:
135 | raw_pattern = '.'
136 | elif ' ' not in query:
137 | raw_pattern = r'(\b|[\.\+\-_])' + query + r'(\b|[\.\+\-_])'
138 | else:
139 | raw_pattern = query.replace(' ', r'.*[\s\.\+\-_]')
140 |
141 | try:
142 | regex = re.compile(raw_pattern, flags=re.IGNORECASE)
143 | except:
144 | return []
145 |
146 | if USE_CAPTION_FILTER:
147 | filter = {'$or': [{'file_name': regex}, {'caption': regex}]}
148 | else:
149 | filter = {'file_name': regex}
150 |
151 | if file_type:
152 | filter['file_type'] = file_type
153 |
154 | total_results = await Media.count_documents(filter)
155 |
156 | cursor = Media.find(filter)
157 | # Sort by recent
158 | cursor.sort('$natural', -1)
159 | # Get list of files
160 | files = await cursor.to_list(length=total_results)
161 |
162 | return files, total_results
163 |
164 | async def get_file_details(query):
165 | filter = {'file_id': query}
166 | cursor = Media.find(filter)
167 | filedetails = await cursor.to_list(length=1)
168 | return filedetails
169 |
170 |
171 | def encode_file_id(s: bytes) -> str:
172 | r = b""
173 | n = 0
174 |
175 | for i in s + bytes([22]) + bytes([4]):
176 | if i == 0:
177 | n += 1
178 | else:
179 | if n:
180 | r += b"\x00" + bytes([n])
181 | n = 0
182 |
183 | r += bytes([i])
184 |
185 | return base64.urlsafe_b64encode(r).decode().rstrip("=")
186 |
187 |
188 | def encode_file_ref(file_ref: bytes) -> str:
189 | return base64.urlsafe_b64encode(file_ref).decode().rstrip("=")
190 |
191 |
192 | def unpack_new_file_id(new_file_id):
193 | """Return file_id, file_ref"""
194 | decoded = FileId.decode(new_file_id)
195 | file_id = encode_file_id(
196 | pack(
197 | "
3 |
68 |
69 |
70 |
71 |
72 |
96 |
97 | Use VPS Branch 98 | git clone https://github.com/ritheshrkrm/PiroAutoFilterBot 99 | # Install Packages 100 | pip3 install -U -r requirements.txt 101 | Edit info.py with variables as given below then run bot 102 | python3 bot.py 103 |104 | 105 |
{user_id}\n➲ Data Centre: {dc_id}",
24 | quote=True
25 | )
26 |
27 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
28 | _id = ""
29 | _id += (
30 | "➲ Chat ID: "
31 | f"{message.chat.id}\n"
32 | )
33 | if message.reply_to_message:
34 | _id += (
35 | "➲ User ID: "
36 | f"{message.from_user.id if message.from_user else 'Anonymous'}\n"
37 | "➲ Replied User ID: "
38 | f"{message.reply_to_message.from_user.id if message.reply_to_message.from_user else 'Anonymous'}\n"
39 | )
40 | file_info = get_file_id(message.reply_to_message)
41 | else:
42 | _id += (
43 | "➲ User ID: "
44 | f"{message.from_user.id if message.from_user else 'Anonymous'}\n"
45 | )
46 | file_info = get_file_id(message)
47 | if file_info:
48 | _id += (
49 | f"{file_info.message_type}: "
50 | f"{file_info.file_id}\n"
51 | )
52 | await message.reply_text(
53 | _id,
54 | quote=True
55 | )
56 |
57 | @Client.on_message(filters.command(["info"]))
58 | async def who_is(client, message):
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('🔐 𝖢𝗅𝗈𝗌𝖾', 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('🔐 𝖢𝗅𝗈𝗌𝖾', 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 |
129 | @Client.on_message(filters.command(["imdb", 'search']))
130 | async def imdb_search(client, message):
131 | if ' ' in message.text:
132 | k = await message.reply('Searching IMDb....')
133 | r, title = message.text.split(None, 1)
134 | movies = await get_poster(title, bulk=True)
135 | if not movies:
136 | return await message.reply("No results Found")
137 | btn = [
138 | [
139 | InlineKeyboardButton(
140 | text=f"{movie.get('title')} - {movie.get('year')}",
141 | callback_data=f"imdb#{movie.movieID}",
142 | )
143 | ]
144 | for movie in movies
145 | ]
146 | await k.edit('𝖧𝖾𝗋𝖾 𝗂𝗌 𝗐𝗁𝖺𝗍 𝗂 𝖿𝗈𝗎𝗇𝖽 𝗈𝗇 𝖨𝖬𝖣𝖻', reply_markup=InlineKeyboardMarkup(btn))
147 | else:
148 | await message.reply('Give me a movie / series Name')
149 |
150 | @Client.on_callback_query(filters.regex('^imdb'))
151 | async def imdb_callback(bot: Client, quer_y: CallbackQuery):
152 | i, movie = quer_y.data.split('#')
153 | imdb = await get_poster(query=movie, id=True)
154 | btn = [
155 | [
156 | InlineKeyboardButton(
157 | text=f"{imdb.get('title')}",
158 | url=imdb['url'],
159 | )
160 | ]
161 | ]
162 | message = quer_y.message.reply_to_message or quer_y.message
163 | if imdb:
164 | caption = IMDB_TEMPLATE.format(
165 | query = imdb['title'],
166 | title = imdb['title'],
167 | votes = imdb['votes'],
168 | aka = imdb["aka"],
169 | seasons = imdb["seasons"],
170 | box_office = imdb['box_office'],
171 | localized_title = imdb['localized_title'],
172 | kind = imdb['kind'],
173 | imdb_id = imdb["imdb_id"],
174 | cast = imdb["cast"],
175 | runtime = imdb["runtime"],
176 | countries = imdb["countries"],
177 | certificates = imdb["certificates"],
178 | languages = imdb["languages"],
179 | director = imdb["director"],
180 | writer = imdb["writer"],
181 | producer = imdb["producer"],
182 | composer = imdb["composer"],
183 | cinematographer = imdb["cinematographer"],
184 | music_team = imdb["music_team"],
185 | distributors = imdb["distributors"],
186 | release_date = imdb['release_date'],
187 | year = imdb['year'],
188 | genres = imdb['genres'],
189 | poster = imdb['poster'],
190 | plot = imdb['plot'],
191 | rating = imdb['rating'],
192 | url = imdb['url'],
193 | **locals()
194 | )
195 | else:
196 | caption = "No Results"
197 | if imdb.get('poster'):
198 | try:
199 | await quer_y.message.reply_photo(photo=imdb['poster'], caption=caption, reply_markup=InlineKeyboardMarkup(btn))
200 | except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty):
201 | pic = imdb.get('poster')
202 | poster = pic.replace('.jpg', "._V1_UX360.jpg")
203 | await quer_y.message.reply_photo(photo=poster, caption=caption, reply_markup=InlineKeyboardMarkup(btn))
204 | except Exception as e:
205 | logger.exception(e)
206 | await quer_y.message.reply(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False)
207 | await quer_y.message.delete()
208 | else:
209 | await quer_y.message.edit(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False)
210 | await quer_y.answer()
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/plugins/index.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import asyncio
3 | from pyrogram import Client, filters, enums
4 | from pyrogram.errors import FloodWait
5 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, ChatAdminRequired, UsernameInvalid, UsernameNotModified
6 | from info import ADMINS
7 | from info import INDEX_REQ_CHANNEL as LOG_CHANNEL
8 | from database.ia_filterdb import save_file
9 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
10 | from utils import temp
11 | import re
12 | logger = logging.getLogger(__name__)
13 | logger.setLevel(logging.INFO)
14 | lock = asyncio.Lock()
15 |
16 |
17 | @Client.on_callback_query(filters.regex(r'^index'))
18 | async def index_files(bot, query):
19 | if query.data.startswith('index_cancel'):
20 | temp.CANCEL = True
21 | return await query.answer("Cancelling Indexing")
22 | _, raju, chat, lst_msg_id, from_user = query.data.split("#")
23 | if raju == 'reject':
24 | await query.message.delete()
25 | await bot.send_message(int(from_user),
26 | f'Your Submission for indexing {chat} has been decliened by our moderators.',
27 | reply_to_message_id=int(lst_msg_id))
28 | return
29 |
30 | if lock.locked():
31 | return await query.answer('Wait until previous process complete.', show_alert=True)
32 | msg = query.message
33 |
34 | await query.answer('Processing...⏳', show_alert=True)
35 | if int(from_user) not in ADMINS:
36 | await bot.send_message(int(from_user),
37 | f'Your Submission for indexing {chat} has been accepted by our moderators and will be added soon.',
38 | reply_to_message_id=int(lst_msg_id))
39 | await msg.edit(
40 | "Starting Indexing",
41 | reply_markup=InlineKeyboardMarkup(
42 | [[InlineKeyboardButton('Cancel', callback_data='index_cancel')]]
43 | )
44 | )
45 | try:
46 | chat = int(chat)
47 | except:
48 | chat = chat
49 | await index_files_to_db(int(lst_msg_id), chat, msg, bot)
50 |
51 |
52 | @Client.on_message((filters.forwarded | (filters.regex("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")) & filters.text ) & filters.private & filters.incoming)
53 | async def send_for_index(bot, message):
54 | if message.text:
55 | regex = re.compile("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
56 | match = regex.match(message.text)
57 | if not match:
58 | return await message.reply('Invalid link')
59 | chat_id = match.group(4)
60 | last_msg_id = int(match.group(5))
61 | if chat_id.isnumeric():
62 | chat_id = int(("-100" + chat_id))
63 | elif message.forward_from_chat.type == enums.ChatType.CHANNEL:
64 | last_msg_id = message.forward_from_message_id
65 | chat_id = message.forward_from_chat.username or message.forward_from_chat.id
66 | else:
67 | return
68 | try:
69 | await bot.get_chat(chat_id)
70 | except ChannelInvalid:
71 | return await message.reply('This may be a private channel / group. Make me an admin over there to index the files.')
72 | except (UsernameInvalid, UsernameNotModified):
73 | return await message.reply('Invalid Link specified.')
74 | except Exception as e:
75 | logger.exception(e)
76 | return await message.reply(f'Errors - {e}')
77 | try:
78 | k = await bot.get_messages(chat_id, last_msg_id)
79 | except:
80 | return await message.reply('Make Sure That Iam An Admin In The Channel, if channel is private')
81 | if k.empty:
82 | return await message.reply('This may be group and iam not a admin of the group.')
83 |
84 | if message.from_user.id in ADMINS:
85 | buttons = [
86 | [
87 | InlineKeyboardButton('Yes',
88 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}')
89 | ],
90 | [
91 | InlineKeyboardButton('close', callback_data='close_data'),
92 | ]
93 | ]
94 | reply_markup = InlineKeyboardMarkup(buttons)
95 | return await message.reply(
96 | f'Do you Want To Index This Channel/ Group ?\n\nChat ID/ Username: {chat_id}\nLast Message ID: {last_msg_id}',
97 | reply_markup=reply_markup)
98 |
99 | if type(chat_id) is int:
100 | try:
101 | link = (await bot.create_chat_invite_link(chat_id)).invite_link
102 | except ChatAdminRequired:
103 | return await message.reply('Make sure iam an admin in the chat and have permission to invite users.')
104 | else:
105 | link = f"@{message.forward_from_chat.username}"
106 | buttons = [
107 | [
108 | InlineKeyboardButton('Accept Index',
109 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}')
110 | ],
111 | [
112 | InlineKeyboardButton('Reject Index',
113 | callback_data=f'index#reject#{chat_id}#{message.id}#{message.from_user.id}'),
114 | ]
115 | ]
116 | reply_markup = InlineKeyboardMarkup(buttons)
117 | await bot.send_message(LOG_CHANNEL,
118 | f'#IndexRequest\n\nBy : {message.from_user.mention} ({message.from_user.id})\nChat ID/ Username - {chat_id}\nLast Message ID - {last_msg_id}\nInviteLink - {link}',
119 | reply_markup=reply_markup)
120 | await message.reply('ThankYou For the Contribution, Wait For My Moderators to verify the files.')
121 |
122 |
123 | @Client.on_message(filters.command('setskip') & filters.user(ADMINS))
124 | async def set_skip_number(bot, message):
125 | if ' ' in message.text:
126 | _, skip = message.text.split(" ")
127 | try:
128 | skip = int(skip)
129 | except:
130 | return await message.reply("Skip number should be an integer.")
131 | await message.reply(f"Successfully set SKIP number as {skip}")
132 | temp.CURRENT = int(skip)
133 | else:
134 | await message.reply("Give me a skip number")
135 |
136 |
137 | async def index_files_to_db(lst_msg_id, chat, msg, bot):
138 | total_files = 0
139 | duplicate = 0
140 | errors = 0
141 | deleted = 0
142 | no_media = 0
143 | unsupported = 0
144 | async with lock:
145 | try:
146 | current = temp.CURRENT
147 | temp.CANCEL = False
148 | async for message in bot.iter_messages(chat, lst_msg_id, temp.CURRENT):
149 | if temp.CANCEL:
150 | await msg.edit(f"Successfully Cancelled!!\n\nSaved {total_files} files to dataBase!\nDuplicate Files Skipped: {duplicate}\nDeleted Messages Skipped: {deleted}\nNon-Media messages skipped: {no_media + unsupported}(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}")
151 | break
152 | current += 1
153 | if current % 20 == 0:
154 | can = [[InlineKeyboardButton('Cancel', callback_data='index_cancel')]]
155 | reply = InlineKeyboardMarkup(can)
156 | await asyncio.sleep(2)
157 | await msg.edit_text(
158 | text=f"Total messages fetched: {current}\nTotal messages saved: {total_files}\nDuplicate Files Skipped: {duplicate}\nDeleted Messages Skipped: {deleted}\nNon-Media messages skipped: {no_media + unsupported}(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}",
159 | reply_markup=reply)
160 | if message.empty:
161 | deleted += 1
162 | continue
163 | elif not message.media:
164 | no_media += 1
165 | continue
166 | elif message.media not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]:
167 | unsupported += 1
168 | continue
169 | media = getattr(message, message.media.value, None)
170 | if not media:
171 | unsupported += 1
172 | continue
173 | media.file_type = message.media.value
174 | media.caption = message.caption
175 | aynav, vnay = await save_file(media)
176 | if aynav:
177 | total_files += 1
178 | elif vnay == 0:
179 | duplicate += 1
180 | elif vnay == 2:
181 | errors += 1
182 | except Exception as e:
183 | logger.exception(e)
184 | await msg.edit(f'Error: {e}')
185 | else:
186 | await msg.edit(f'Succesfully saved {total_files} to dataBase!\nDuplicate Files Skipped: {duplicate}\nDeleted Messages Skipped: {deleted}\nNon-Media messages skipped: {no_media + unsupported}(Unsupported Media - `{unsupported}` )\nErrors Occurred: {errors}')
187 |
--------------------------------------------------------------------------------
/plugins/filters.py:
--------------------------------------------------------------------------------
1 | import io
2 | from pyrogram import filters, Client, enums
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
4 | from database.filters_mdb import(
5 | add_filter,
6 | get_filters,
7 | delete_filter,
8 | count_filters
9 | )
10 |
11 | from database.connections_mdb import active_connection
12 | from utils import get_file_id, parser, split_quotes
13 | from info import ADMINS
14 |
15 |
16 | @Client.on_message(filters.command(['filter', 'addf']) & filters.incoming)
17 | async def addfilter(client, message):
18 | userid = message.from_user.id if message.from_user else None
19 | if not userid:
20 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
21 | chat_type = message.chat.type
22 | args = message.text.html.split(None, 1)
23 |
24 | if chat_type == enums.ChatType.PRIVATE:
25 | grpid = await active_connection(str(userid))
26 | if grpid is not None:
27 | grp_id = grpid
28 | try:
29 | chat = await client.get_chat(grpid)
30 | title = chat.title
31 | except:
32 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
33 | return
34 | else:
35 | await message.reply_text("I'm not connected to any groups!", quote=True)
36 | return
37 |
38 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
39 | grp_id = message.chat.id
40 | title = message.chat.title
41 |
42 | else:
43 | return
44 |
45 | st = await client.get_chat_member(grp_id, userid)
46 | if (
47 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
48 | and st.status != enums.ChatMemberStatus.OWNER
49 | and str(userid) not in ADMINS
50 | ):
51 | return
52 |
53 |
54 | if len(args) < 2:
55 | await message.reply_text("Command Incomplete :(", quote=True)
56 | return
57 |
58 | extracted = split_quotes(args[1])
59 | text = extracted[0].lower()
60 |
61 | if not message.reply_to_message and len(extracted) < 2:
62 | await message.reply_text("Add some content to save your filter!", quote=True)
63 | return
64 |
65 | if (len(extracted) >= 2) and not message.reply_to_message:
66 | reply_text, btn, alert = parser(extracted[1], text)
67 | fileid = None
68 | if not reply_text:
69 | await message.reply_text("You cannot have buttons alone, give some text to go with it!", quote=True)
70 | return
71 |
72 | elif message.reply_to_message and message.reply_to_message.reply_markup:
73 | try:
74 | rm = message.reply_to_message.reply_markup
75 | btn = rm.inline_keyboard
76 | msg = get_file_id(message.reply_to_message)
77 | if msg:
78 | fileid = msg.file_id
79 | reply_text = message.reply_to_message.caption.html
80 | else:
81 | reply_text = message.reply_to_message.text.html
82 | fileid = None
83 | alert = None
84 | except:
85 | reply_text = ""
86 | btn = "[]"
87 | fileid = None
88 | alert = None
89 |
90 | elif message.reply_to_message and message.reply_to_message.media:
91 | try:
92 | msg = get_file_id(message.reply_to_message)
93 | fileid = msg.file_id if msg else None
94 | reply_text, btn, alert = parser(extracted[1], text) if message.reply_to_message.sticker else parser(message.reply_to_message.caption.html, text)
95 | except:
96 | reply_text = ""
97 | btn = "[]"
98 | alert = None
99 | elif message.reply_to_message and message.reply_to_message.text:
100 | try:
101 | fileid = None
102 | reply_text, btn, alert = parser(message.reply_to_message.text.html, text)
103 | except:
104 | reply_text = ""
105 | btn = "[]"
106 | alert = None
107 | else:
108 | return
109 |
110 | await add_filter(grp_id, text, reply_text, btn, fileid, alert)
111 |
112 | await message.reply_text(
113 | f"Filter for `{text}` added in **{title}**",
114 | quote=True,
115 | parse_mode=enums.ParseMode.MARKDOWN
116 | )
117 |
118 |
119 | @Client.on_message(filters.command(['viewfilters', 'filters']) & filters.incoming)
120 | async def get_all(client, message):
121 |
122 | chat_type = message.chat.type
123 | userid = message.from_user.id if message.from_user else None
124 | if not userid:
125 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
126 | if chat_type == enums.ChatType.PRIVATE:
127 | userid = message.from_user.id
128 | grpid = await active_connection(str(userid))
129 | if grpid is not None:
130 | grp_id = grpid
131 | try:
132 | chat = await client.get_chat(grpid)
133 | title = chat.title
134 | except:
135 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
136 | return
137 | else:
138 | await message.reply_text("I'm not connected to any groups!", quote=True)
139 | return
140 |
141 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
142 | grp_id = message.chat.id
143 | title = message.chat.title
144 |
145 | else:
146 | return
147 |
148 | st = await client.get_chat_member(grp_id, userid)
149 | if (
150 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
151 | and st.status != enums.ChatMemberStatus.OWNER
152 | and str(userid) not in ADMINS
153 | ):
154 | return
155 |
156 | texts = await get_filters(grp_id)
157 | count = await count_filters(grp_id)
158 | if count:
159 | filterlist = f"Total number of filters in **{title}** : {count}\n\n"
160 |
161 | for text in texts:
162 | keywords = " × `{}`\n".format(text)
163 |
164 | filterlist += keywords
165 |
166 | if len(filterlist) > 4096:
167 | with io.BytesIO(str.encode(filterlist.replace("`", ""))) as keyword_file:
168 | keyword_file.name = "keywords.txt"
169 | await message.reply_document(
170 | document=keyword_file,
171 | quote=True
172 | )
173 | return
174 | else:
175 | filterlist = f"There are no active filters in **{title}**"
176 |
177 | await message.reply_text(
178 | text=filterlist,
179 | quote=True,
180 | parse_mode=enums.ParseMode.MARKDOWN
181 | )
182 |
183 | @Client.on_message(filters.command('del') & filters.incoming)
184 | async def deletefilter(client, message):
185 | userid = message.from_user.id if message.from_user else None
186 | if not userid:
187 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
188 | chat_type = message.chat.type
189 |
190 | if chat_type == enums.ChatType.PRIVATE:
191 | grpid = await active_connection(str(userid))
192 | if grpid is not None:
193 | grp_id = grpid
194 | try:
195 | chat = await client.get_chat(grpid)
196 | title = chat.title
197 | except:
198 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
199 | return
200 | else:
201 | await message.reply_text("I'm not connected to any groups!", quote=True)
202 | return
203 |
204 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
205 | grp_id = message.chat.id
206 | title = message.chat.title
207 |
208 | else:
209 | return
210 |
211 | st = await client.get_chat_member(grp_id, userid)
212 | if (
213 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
214 | and st.status != enums.ChatMemberStatus.OWNER
215 | and str(userid) not in ADMINS
216 | ):
217 | return
218 |
219 | try:
220 | cmd, text = message.text.split(" ", 1)
221 | except:
222 | await message.reply_text(
223 | "Mention the filtername which you wanna delete!\n\n"
224 | "/del filtername\n\n"
225 | "Use /viewfilters to view all available filters",
226 | quote=True
227 | )
228 | return
229 |
230 | query = text.lower()
231 |
232 | await delete_filter(message, query, grp_id)
233 |
234 |
235 | @Client.on_message(filters.command('delall') & filters.incoming)
236 | async def delallconfirm(client, message):
237 | userid = message.from_user.id if message.from_user else None
238 | if not userid:
239 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
240 | chat_type = message.chat.type
241 |
242 | if chat_type == enums.ChatType.PRIVATE:
243 | grpid = await active_connection(str(userid))
244 | if grpid is not None:
245 | grp_id = grpid
246 | try:
247 | chat = await client.get_chat(grpid)
248 | title = chat.title
249 | except:
250 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
251 | return
252 | else:
253 | await message.reply_text("I'm not connected to any groups!", quote=True)
254 | return
255 |
256 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
257 | grp_id = message.chat.id
258 | title = message.chat.title
259 |
260 | else:
261 | return
262 |
263 |
264 | st = await client.get_chat_member(grp_id, userid)
265 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS):
266 | await message.reply_text(
267 | f"This will delete all filters from '{title}'.\nDo you want to continue??",
268 | reply_markup=InlineKeyboardMarkup([
269 | [InlineKeyboardButton(text="YES",callback_data="delallconfirm")],
270 | [InlineKeyboardButton(text="CANCEL",callback_data="delallcancel")]
271 | ]),
272 | quote=True
273 | )
274 |
275 |
--------------------------------------------------------------------------------
/Script.py:
--------------------------------------------------------------------------------
1 | class script(object):
2 | START_TXT = """𝖸𝗈...𝖸𝗈... {} 💖
3 |
4 | 𝖨'𝗆 𝖯𝗈𝗐𝖾𝗋𝖿𝗎𝗅 𝖠𝗎𝗍𝗈-𝖥𝗂𝗅𝗍𝖾𝗋 𝖡𝗈𝗍 𝖸𝗈𝗎 𝖢𝖺𝗇 𝖴𝗌𝖾 𝖬𝖾 𝖠𝗌 𝖠 𝖠𝗎𝗍𝗈-𝖿𝗂𝗅𝗍𝖾𝗋 𝗂𝗇 𝖸𝗈𝗎𝗋 𝖦𝗋𝗈𝗎𝗉
5 |
6 | 𝖨𝗍𝗌 𝖤𝖺𝗌𝗒 𝖳𝗈 𝖴𝗌𝖾 𝖬𝖾; 𝖩𝗎𝗌𝗍 𝖠𝖽𝖽 𝖬𝖾 𝖳𝗈 𝖸𝗈𝗎𝗋 𝖦𝗋𝗈𝗎𝗉 𝖠𝗌 𝖠𝖽𝗆𝗂𝗇,
7 | 𝖳𝗁𝖺𝗍𝗌 𝖠𝗅𝗅, 𝗂 𝗐𝗂𝗅𝗅 𝖯𝗋𝗈𝗏𝗂𝖽𝖾 𝖬𝗈𝗏𝗂𝖾𝗌 𝖳𝗁𝖾𝗋𝖾...🤓🤪
8 |
9 | ⚠️ 𝖬𝗈𝗋𝖾 𝖧𝖾𝗅𝗉 𝖧𝗂𝗍 /help
10 |
11 | 🙋🏻♂️ 𝖳𝗎𝗍𝗈𝗋𝗂𝖺𝗅 𝖦𝗎𝗂𝖽𝖾 @piro_tuts
12 |
13 | 😎 𝖯𝗈𝗐𝖾𝗋𝖾𝖽 𝖻𝗒 @piroxbots"""
14 |
15 | HELP_TXT = """🙋🏻♂️ 𝖧𝖾𝗅𝗅𝗈𝗈𝗈 {} 🤓
16 |
17 | ○ 𝗂𝗍'𝗌 𝖭𝗈𝗍𝖾 𝖢𝗈𝗆𝗉𝗅𝗂𝖼𝖺𝗍𝖾𝖽...🤓
18 |
19 | ○ 𝖲𝖾𝖺𝗋𝖼𝗁 𝗎𝗌𝗂𝗇𝗀 𝗂𝗇𝗅𝗂𝗇𝖾 𝗆𝗈𝖽𝖾
20 | 𝖳𝗁𝗂𝗌 𝗆𝖾𝗍𝗁𝗈𝖽 𝗐𝗈𝗋𝗄𝗌 𝗈𝗇 𝖺𝗇𝗒 𝖼𝗁𝖺𝗍, 𝖩𝗎𝗌𝗍 𝗍𝗒𝗉𝖾 Bot Username 𝖺𝗇𝖽 𝗍𝗁𝖾𝗇 𝗅𝖾𝖺𝗏𝖾 𝖺 𝗌𝗉𝖺𝖼𝖾 𝖺𝗇𝖽 𝗌𝖾𝖺𝗋𝖼𝗁 𝖺𝗇𝗒 𝗆𝗈𝗏𝗂𝖾 𝗒𝗈𝗎 𝗐𝖺𝗇𝗍...
21 |
22 | 🙋🏻♂️ 𝖳𝗎𝗍𝗈𝗋𝗂𝖺𝗅 𝖦𝗎𝗂𝖽𝖾 @piro_tuts
23 |
24 | ○ 𝖠𝗏𝖺𝗂𝗅𝖺𝖻𝗅𝖾 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌
25 |
26 | /alive - Check I'm Alive..
27 | /info - User info
28 | /ping - To get your ping
29 | /id - User id
30 | /stats - Db status
31 | /broadcast - Broadcast (𝖮𝗐𝗇𝖾𝗋 𝖮𝗇𝗅𝗒)
32 |
33 | ○ 𝖭𝗈𝗍𝗂𝖼𝖾 📙:-
34 |
35 | 𝖣𝗈𝗇𝗍 𝖲𝗉𝖺𝗆 𝖬𝖾...🤒
36 |
37 | 😎 𝖯𝗈𝗐𝖾𝗋𝖾𝖽 𝖻𝗒 @piroxbots"""
38 |
39 | ABOUT_TXT = """○ 𝖬𝗒 𝖭𝖺𝗆𝖾: {}
40 | ○ 𝖢𝗋𝖾𝖺𝗍𝗈𝗋 : 𝖳𝗁𝗂𝗌 𝖯𝖾𝗋𝗌𝗈𝗇
41 | ○ 𝖫𝖺𝗇𝗀𝗎𝖺𝗀𝖾 : 𝖯𝗒𝗍𝗁𝗈𝗇 𝟥
42 | ○ 𝖫𝗂𝖻𝗋𝖺𝗋𝗒 : 𝖯𝗒𝗋𝗈𝗀𝗋𝖺𝗆 𝖺𝗌𝗒𝗇𝖼𝗂𝗈 𝟢.𝟣𝟩.𝟣
43 | ○ 𝖲𝖾𝗋𝗏𝖾𝗋 : Contabo
44 | ○ 𝖣𝖺𝗍𝖺𝖻𝖺𝗌𝖾 : 𝖬𝗈𝗇𝗀𝗈𝖣𝖡 𝖥𝗋𝖾𝖾 𝖳𝗂𝖾𝗋
45 | ○ 𝖡𝗎𝗂𝗅𝖽 𝖲𝗍𝖺𝗍𝗎𝗌 : v1.0.1 [BeTa]
46 | ○ 𝖲𝗎𝗉𝗉𝗈𝗋𝗍 𝖦𝗋𝗈𝗎𝗉 : 𝖳𝖺𝗉 𝖧𝖾𝗋𝖾"""
47 |
48 | SOURCE_TXT = """NOTE:
49 | Special Thanks to EvaMaria Devs & Cloners for the codes
50 | DEV:
51 |
52 | - [𝖯𝖨𝖱𝖮]
53 |
54 | - Source - https://github.com/ritheshrkrm/PiroAutoFilterBot""" #please don't change repo link give credit :)
55 |
56 | MANUELFILTER_TXT = """ʜᴇʟᴘ: ꜰɪʟᴛᴇʀꜱ
57 | - ꜰɪʟᴛᴇʀ ɪꜱ ᴀ ꜰᴇᴀᴛᴜʀᴇ ᴡᴇʀᴇ ᴜꜱᴇʀꜱ ᴄᴀɴ ꜱᴇᴛ ᴀᴜᴛᴏᴍᴀᴛᴇᴅ ʀᴇᴘʟɪᴇꜱ ꜰᴏʀ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴋᴇʏᴡᴏʀᴅ ᴀɴᴅ ɪ ᴡɪʟʟ ʀᴇꜱᴘᴏɴᴅ ᴡʜᴇɴᴇᴠᴇʀ ᴀ ᴋᴇʏᴡᴏʀᴅ ɪꜱ ꜰᴏᴜɴᴅ ɪɴ ᴛʜᴇ ᴍᴇꜱꜱᴀɢᴇ
58 | ɴᴏᴛᴇ:
59 | 1. ᴛʜɪꜱ ʙᴏᴛ ꜱʜᴏᴜʟᴅ ʜᴀᴠᴇ ᴀᴅᴍɪɴ ᴘʀɪᴠɪʟᴇɢᴇ.
60 | 2. ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴀᴅᴅ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴀ ᴄʜᴀᴛ.
61 | 3. ᴀʟᴇʀᴛ ʙᴜᴛᴛᴏɴꜱ ʜᴀᴠᴇ ᴀ ʟɪᴍɪᴛ ᴏꜰ 64 ᴄʜᴀʀᴀᴄᴛᴇʀꜱ.
62 |
63 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
64 |
65 | • /filter - ᴀᴅᴅ ᴀ ꜰɪʟᴛᴇʀ ɪɴ ᴀ ᴄʜᴀᴛ
66 | • /filters - ʟɪꜱᴛ ᴀʟʟ ᴛʜᴇ ꜰɪʟᴛᴇʀꜱ ᴏꜰ ᴀ ᴄʜᴀᴛ
67 | • /del - ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴛᴇʀ ɪɴ ᴀ ᴄʜᴀᴛ
68 | • /delall - ᴅᴇʟᴇᴛᴇ ᴛʜᴇ ᴡʜᴏʟᴇ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴀ ᴄʜᴀᴛ (ᴄʜᴀᴛ ᴏᴡɴᴇʀ ᴏɴʟʏ)"""
69 |
70 | BUTTON_TXT = """ʜᴇʟᴘ: ʙᴜᴛᴛᴏɴꜱ
71 | - ᴛʜɪꜱ ʙᴏᴛ ꜱᴜᴘᴘᴏʀᴛꜱ ʙᴏᴛʜ ᴜʀʟ ᴀɴᴅ ᴀʟᴇʀᴛ ɪɴʟɪɴᴇ ʙᴜᴛᴛᴏɴꜱ.
72 | ɴᴏᴛᴇ:
73 | 1. ᴛᴇʟᴇɢʀᴀᴍ ᴡɪʟʟ ɴᴏᴛ ᴀʟʟᴏᴡꜱ ʏᴏᴜ ᴛᴏ ꜱᴇɴᴅ ʙᴜᴛᴛᴏɴꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴄᴏɴᴛᴇɴᴛ, ꜱᴏ ᴄᴏɴᴛᴇɴᴛ ɪꜱ ᴍᴀɴᴅᴀᴛᴏʀʏ.
74 | 2. ᴛʜɪꜱ ʙᴏᴛ ꜱᴜᴘᴘᴏʀᴛꜱ ʙᴜᴛᴛᴏɴꜱ ᴡɪᴛʜ ᴀɴʏ ᴛᴇʟᴇɢʀᴀᴍ ᴍᴇᴅɪᴀ ᴛʏᴘᴇ.
75 | 3. ʙᴜᴛᴛᴏɴꜱ ꜱʜᴏᴜʟᴅ ʙᴇ ᴘʀᴏᴘᴇʀʟʏ ᴘᴀʀꜱᴇᴅ ᴀꜱ ᴍᴀʀᴋᴅᴏᴡɴ ꜰᴏʀᴍᴀᴛ
76 | ᴜʀʟ ʙᴜᴛᴛᴏɴꜱ:
77 | [Button Text](buttonurl:https://t.me/piroxbots)
78 | ᴀʟᴇʀᴛ ʙᴜᴛᴛᴏɴꜱ:
79 | [Button Text](buttonalert:ᴛʜɪꜱ ɪꜱ ᴀɴ ᴀʟᴇʀᴛ ᴍᴇꜱꜱᴀɢᴇ)"""
80 |
81 | AUTOFILTER_TXT = """ʜᴇʟᴘ: ᴀᴜᴛᴏ ꜰɪʟᴛᴇʀ
82 | ɴᴏᴛᴇ: Fɪʟᴇ Iɴᴅᴇx
83 | 1. ᴍᴀᴋᴇ ᴍᴇ ᴛʜᴇ ᴀᴅᴍɪɴ ᴏꜰ ʏᴏᴜʀ ᴄʜᴀɴɴᴇʟ ɪꜰ ɪᴛ'ꜱ ᴘʀɪᴠᴀᴛᴇ.
84 | 2. ᴍᴀᴋᴇ ꜱᴜʀᴇ ᴛʜᴀᴛ ʏᴏᴜʀ ᴄʜᴀɴɴᴇʟ ᴅᴏᴇꜱ ɴᴏᴛ ᴄᴏɴᴛᴀɪɴꜱ ᴄᴀᴍʀɪᴘꜱ, ᴘᴏʀɴ ᴀɴᴅ ꜰᴀᴋᴇ ꜰɪʟᴇꜱ.
85 | 3. ꜰᴏʀᴡᴀʀᴅ ᴛʜᴇ ʟᴀꜱᴛ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴍᴇ ᴡɪᴛʜ Qᴜᴏᴛᴇꜱ. ɪ'ʟʟ ᴀᴅᴅ ᴀʟʟ ᴛʜᴇ ꜰɪʟᴇꜱ ɪɴ ᴛʜᴀᴛ ᴄʜᴀɴɴᴇʟ ᴛᴏ ᴍʏ ᴅʙ.
86 |
87 | Nᴏᴛᴇ: AᴜᴛᴏFɪʟᴛᴇʀ
88 | 1. Aᴅᴅ ᴛʜᴇ ʙᴏᴛ ᴀs ᴀᴅᴍɪɴ ᴏɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ.
89 | 2. Usᴇ /connect ᴀɴᴅ ᴄᴏɴɴᴇᴄᴛ ʏᴏᴜʀ ɢʀᴏᴜᴘ ᴛᴏ ᴛʜᴇ ʙᴏᴛ.
90 | 3. Usᴇ /settings ᴏɴ ʙᴏᴛ's PM ᴀɴᴅ ᴛᴜʀɴ ᴏɴ AᴜᴛᴏFɪʟᴛᴇʀ ᴏɴ ᴛʜᴇ sᴇᴛᴛɪɴɢs ᴍᴇɴᴜ."""
91 |
92 | CONNECTION_TXT = """ʜᴇʟᴘ: ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ
93 | - ᴜꜱᴇᴅ ᴛᴏ ᴄᴏɴɴᴇᴄᴛ ʙᴏᴛ ᴛᴏ ᴘᴍ ꜰᴏʀ ᴍᴀɴᴀɢɪɴɢ ꜰɪʟᴛᴇʀꜱ
94 | - ɪᴛ ʜᴇʟᴘꜱ ᴛᴏ ᴀᴠᴏɪᴅ ꜱᴘᴀᴍᴍɪɴɢ ɪɴ ɢʀᴏᴜᴘꜱ.
95 | ɴᴏᴛᴇ:
96 | 1. ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴀᴅᴅ ᴀ ᴄᴏɴɴᴇᴄᴛɪᴏɴ.
97 | 2. ꜱᴇɴᴅ /ᴄᴏɴɴᴇᴄᴛ ꜰᴏʀ ᴄᴏɴɴᴇᴄᴛɪɴɢ ᴍᴇ ᴛᴏ ʏᴏᴜʀ ᴘᴍ
98 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
99 | • /connect - ᴄᴏɴɴᴇᴄᴛ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴄʜᴀᴛ ᴛᴏ ʏᴏᴜʀ ᴘᴍ
100 | • /disconnect - ᴅɪꜱᴄᴏɴɴᴇᴄᴛ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ
101 | • /connections - ʟɪꜱᴛ ᴀʟʟ ʏᴏᴜʀ ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ"""
102 |
103 | EXTRAMOD_TXT = """ʜᴇʟᴘ: Exᴛʀᴀ Mᴏᴅᴜʟᴇs
104 | ɴᴏᴛᴇ:
105 | ᴛʜᴇꜱᴇ ᴀʀᴇ ᴛʜᴇ ᴇxᴛʀᴀ ꜰᴇᴀᴛᴜʀᴇꜱ ᴏꜰ ᴛʜɪꜱ ʙᴏᴛ
106 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
107 | • /id - ɢᴇᴛ ɪᴅ ᴏꜰ ᴀ ꜱᴘᴇᴄɪꜰɪᴇᴅ ᴜꜱᴇʀ.
108 | • /info - ɢᴇᴛ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴀ ᴜꜱᴇʀ.
109 | • /imdb - ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ɪᴍᴅʙ ꜱᴏᴜʀᴄᴇ.
110 | • /search - ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ᴠᴀʀɪᴏᴜꜱ ꜱᴏᴜʀᴄᴇꜱ."""
111 |
112 | ADMIN_TXT = """ʜᴇʟᴘ: Aᴅᴍɪɴ Mᴏᴅs
113 | ɴᴏᴛᴇ:
114 | Tʜɪs Mᴏᴅᴜʟᴇ Oɴʟʏ Wᴏʀᴋs Fᴏʀ Mʏ Aᴅᴍɪɴs
115 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ:
116 | • /logs - ᴛᴏ ɢᴇᴛ ᴛʜᴇ ʀᴇᴄᴇɴᴛ ᴇʀʀᴏʀꜱ
117 | • /stats - ᴛᴏ ɢᴇᴛ ꜱᴛᴀᴛᴜꜱ ᴏꜰ ꜰɪʟᴇꜱ ɪɴ ᴅʙ. [Tʜɪs Cᴏᴍᴍᴀɴᴅ Cᴀɴ Bᴇ Usᴇᴅ Bʏ Aɴʏᴏɴᴇ]
118 | • /delete - ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴇ ꜰʀᴏᴍ ᴅʙ.
119 | • /users - ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴜꜱᴇʀꜱ ᴀɴᴅ ɪᴅꜱ.
120 | • /chats - ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴄʜᴀᴛꜱ ᴀɴᴅ ɪᴅꜱ
121 | • /leave - ᴛᴏ ʟᴇᴀᴠᴇ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ.
122 | • /disable - ᴛᴏ ᴅɪꜱᴀʙʟᴇ ᴀ ᴄʜᴀᴛ.
123 | • /ban - ᴛᴏ ʙᴀɴ ᴀ ᴜꜱᴇʀ.
124 | • /unban - ᴛᴏ ᴜɴʙᴀɴ ᴀ ᴜꜱᴇʀ.
125 | • /channel - ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴛᴏᴛᴀʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ᴄʜᴀɴɴᴇʟꜱ
126 | • /broadcast - ᴛᴏ ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴀ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴀʟʟ ᴜꜱᴇʀꜱ
127 | • /group_broadcast - Tᴏ ʙʀᴏᴀᴅᴄᴀsᴛ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ᴀʟʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ɢʀᴏᴜᴘs.
128 | • /gfilter - ᴛᴏ ᴀᴅᴅ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs
129 | • /gfilters - ᴛᴏ ᴠɪᴇᴡ ʟɪsᴛ ᴏғ ᴀʟʟ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs
130 | • /delg - ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀ sᴘᴇᴄɪғɪᴄ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ
131 | • /request - Tᴏ sᴇɴᴅ ᴀ Mᴏᴠɪᴇ/Sᴇʀɪᴇs ʀᴇᴏ̨ᴜᴇsᴛ ᴛᴏ ʙᴏᴛ ᴀᴅᴍɪɴs. Oɴʟʏ ᴡᴏʀᴋs ᴏɴ sᴜᴘᴘᴏʀᴛ ɢʀᴏᴜᴘ. [Tʜɪs Cᴏᴍᴍᴀɴᴅ Cᴀɴ Bᴇ Usᴇᴅ Bʏ Aɴʏᴏɴᴇ]
132 | • /delallg - Tᴏ ᴅᴇʟᴇᴛᴇ ᴀʟʟ Gғɪʟᴛᴇʀs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ.
133 | • /deletefiles - Tᴏ ᴅᴇʟᴇᴛᴇ CᴀᴍRɪᴘ ᴀɴᴅ PʀᴇDVD Fɪʟᴇs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ."""
134 |
135 | STATUS_TXT = """𝖳𝗈𝗍𝖺𝗅 𝖥𝗂𝗅𝖾𝗌: {}
136 | 𝖳𝗈𝗍𝖺𝗅 𝖬𝖾𝗆𝖻𝖾𝗋𝗌: {}
137 | 𝖳𝗈𝗍𝖺𝗅 𝖢𝗁𝖺𝗍𝗌: {}
138 | 𝖴𝗌𝖾𝖽 𝖲𝗍𝗈𝗋𝖺𝗀𝖾: {}
139 |
140 | 😎 𝖯𝗈𝗐𝖾𝗋𝖾𝖽 𝖻𝗒 @piroxbots"""
141 |
142 | LOG_TEXT_G = """#NewGroup
143 | 𝖦𝗋𝗈𝗎𝗉 = {}({})
144 | 𝖳𝗈𝗍𝖺𝗅 𝖬𝖾𝗆𝖻𝖾𝗋𝗌 = {}
145 | 𝖠𝖽𝖽𝖾𝖽 𝖡𝗒 - {}"""
146 |
147 | LOG_TEXT_P = """#NewUser
148 | 𝖨𝖽 - {}
149 | 𝖭𝖺𝗆𝖾 - {}"""
150 |
151 | REQ_TXT = """𝖧𝖾𝗅𝗅𝗈 {}
152 | 𝖸𝗈𝗎𝗋 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 𝖧𝖺𝗌 𝖡𝖾𝖾𝗇 𝖠𝗉𝗉𝗋𝗈𝗏𝖾𝖽...!!!"""
153 |
154 | ALRT_TXT = """Hello {},
155 | This is Not your Request
156 | Request Yourself...!!"""
157 |
158 | OLD_ALRT_TXT = """Hey {},
159 | You are using one of old message,
160 | Request Again"""
161 |
162 | CUDNT_FND = """
163 | 𝖨 𝖼𝗈𝗎𝗅𝖽𝗇'𝗍 𝖿𝗂𝗇𝖽 𝖺𝗇𝗒𝗍𝗁𝗂𝗇𝗀 𝗋𝖾𝗅𝖺𝗍𝖾𝖽 𝗍𝗈 𝗍𝗁𝖺𝗍
164 | 𝖣𝗂𝖽 𝗒𝗈𝗎 𝗆𝖾𝖺𝗇 𝖺𝗇𝗒 𝗈𝗇𝖾 𝗈𝖿 𝗍𝗁𝖾𝗌𝖾?"""
165 |
166 | I_CUDNT = """❌ 𝖨 𝖼𝗈𝗎𝗅𝖽𝗇'𝗍 𝖿𝗂𝗇𝖽 𝖺𝗇𝗒𝗍𝗁𝗂𝗇𝗀 𝗋𝖾𝗅𝖺𝗍𝖾𝖽 𝗍𝗈 𝗍𝗁𝖺𝗍\n\n‼ 𝖱𝖾𝗉𝗈𝗋𝗍 𝗍𝗈 𝖺𝖽𝗆𝗂𝗇 ▶ @raixchat"""
167 |
168 | I_CUD_NT = """❌ 𝖨 𝖼𝗈𝗎𝗅𝖽𝗇'𝗍 𝖿𝗂𝗇𝖽 𝖺𝗇𝗒𝗍𝗁𝗂𝗇𝗀 𝗋𝖾𝗅𝖺𝗍𝖾𝖽 𝗍𝗈 𝗍𝗁𝖺𝗍\n\n‼ 𝖱𝖾𝗉𝗈𝗋𝗍 𝗍𝗈 𝖺𝖽𝗆𝗂𝗇 ▶ @raixchat"""
169 |
170 | MVE_NT_FND = """❌ 𝖨 𝖼𝗈𝗎𝗅𝖽𝗇'𝗍 𝖿𝗂𝗇𝖽 𝖺𝗇𝗒𝗍𝗁𝗂𝗇𝗀 𝗋𝖾𝗅𝖺𝗍𝖾𝖽 𝗍𝗈 𝗍𝗁𝖺𝗍\n\n‼ 𝖱𝖾𝗉𝗈𝗋𝗍 𝗍𝗈 𝖺𝖽𝗆𝗂𝗇 ▶ @raixchat"""
171 |
172 | TOP_ALRT_MSG = """𝖢𝗁𝖾𝖼𝗄𝗂𝗇𝗀 𝖿𝗈𝗋 𝗊𝗎𝖾𝗋𝗒 𝗂𝗇 𝖣𝖺𝗍𝖺𝖻𝖺𝗌𝖾..."""
173 |
174 | MELCOW_ENG = """Hey {}, Welcome to {}
175 |
176 | • 𝖭𝗈 𝖯𝗋𝗈𝗆𝗈, 𝖭𝗈 𝖯𝗈𝗋𝗇, 𝖭𝗈 𝖮𝗍𝗁𝖾𝗋 𝖠𝖻𝗎𝗌𝖾𝗌
177 | • 𝖠𝗌𝗄 𝖸𝗈𝗎𝗋 𝖬𝗈𝗏𝗂𝖾𝗌 𝖶𝗂𝗍𝗁 𝖢𝗈𝗋𝗋𝖾𝖼𝗍 𝖲𝗉𝖾𝗅𝗅𝗂𝗇𝗀
178 | • 𝖲𝗉𝖺𝗆𝗆𝖾𝗋𝗌 𝖲𝗍𝖺𝗒 𝖠𝗐𝖺𝗒
179 | • 𝖥𝖾𝖾𝗅 𝖥𝗋𝖾𝖾 𝖳𝗈 𝖱𝖾𝗉𝗈𝗋𝗍 𝖠𝗇𝗒 𝖤𝗋𝗋𝗈𝗋𝗌 𝖳𝗈 𝖠𝖽𝗆𝗂𝗇𝗌 𝗎𝗌𝗂𝗇𝗀 @admin
180 |
181 | 𝗥𝗲𝗾𝘂𝗲𝘀𝘁𝘀 𝗙𝗼𝗿𝗺𝗮𝘁𝘀
182 |
183 | • 𝖲𝗈𝗅𝗈 2017
184 | • 𝖣𝗁𝗈𝗈𝗆 3 𝖧𝗂𝗇𝖽𝗂
185 | • 𝖪𝗎𝗋𝗎𝗉 𝖪𝖺𝗇
186 | • 𝖣𝖺𝗋𝗄 𝗌01
187 | • 𝖲𝗁𝖾 𝖧𝗎𝗅𝗄 720𝗉
188 | • 𝖥𝗋𝗂𝖾𝗇𝖽𝗌 𝗌03 1080𝗉
189 | • 𝖬𝗎𝗌𝗍 𝗋𝖾𝖺𝖽 𝗍𝗁𝗂𝗌 https://te.legra.ph/𝖯𝗈𝗐𝖾𝗋𝖾𝖽-𝖡𝗒-𝖯𝖨𝖱𝖮-12-11-2
190 |
191 | ‼️𝗗𝗼𝗻𝘁 𝗮𝗱𝗱 𝘄𝗼𝗿𝗱𝘀 & 𝘀𝘆𝗺𝗯𝗼𝗹𝘀 𝗹𝗶𝗸𝗲 , . - send link movie series 𝗲𝘁𝗰‼️"""
192 |
193 | OWNER_INFO = """
194 | ○ 𝖢𝗋𝖾𝖺𝗍𝗈𝗋 : 𝖳𝗁𝗂𝗌 𝖯𝖾𝗋𝗌𝗈𝗇
195 |
196 | ○ 𝖲𝗎𝗉𝗉𝗈𝗋𝗍 𝖦𝗋𝗈𝗎𝗉 : 𝖳𝖺𝗉 𝖧𝖾𝗋𝖾
197 | """
198 |
199 | NORSLTS = """
200 | #NoResults
201 |
202 | ID : {}
203 |
204 | Name : {}
205 |
206 | Message : {}"""
207 |
208 | CAPTION = """
209 | 📂 File Name: {file_name}
210 |
211 | ❤️🔥 Join [𝗕𝗟𝗔𝗦𝗧𝗘𝗥 𝗟𝗜𝗡𝗞𝗭](https://t.me/blaster_linkz)
212 | """
213 |
214 | IMDB_TEMPLATE_TXT = """
215 | 🏷 𝖳𝗂𝗍𝗅𝖾: {title}
216 | 🔮 𝖸𝖾𝖺𝗋: {year} \n⭐️ 𝖱𝖺𝗍𝗂𝗇𝗀𝗌: {rating}/ 10
217 | 🎭 𝖦𝖾𝗇𝖾𝗋𝗌: {genres}
218 |
219 | 🎊 𝖯𝗈𝗐𝖾𝗋𝖾𝖽 𝖡𝗒 [[𝖯𝖨𝖱𝖮]](t.me/piroxbots)"""
220 |
221 | ALL_FILTERS = """
222 | Hᴇʏ {}, Tʜᴇsᴇ ᴀʀᴇ ᴍʏ ᴛʜʀᴇᴇ ᴛʏᴘᴇs ᴏғ ғɪʟᴛᴇʀs."""
223 |
224 | GFILTER_TXT = """
225 | Wᴇʟᴄᴏᴍᴇ ᴛᴏ Gʟᴏʙᴀʟ Fɪʟᴛᴇʀs. Gʟᴏʙᴀʟ Fɪʟᴛᴇʀs ᴀʀᴇ ᴛʜᴇ ғɪʟᴛᴇʀs sᴇᴛ ʙʏ ʙᴏᴛ ᴀᴅᴍɪɴs ᴡʜɪᴄʜ ᴡɪʟʟ ᴡᴏʀᴋ ᴏɴ ᴀʟʟ ɢʀᴏᴜᴘs.
226 |
227 | Aᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs:
228 | • /gfilter - Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ.
229 | • /gfilters - Tᴏ ᴠɪᴇᴡ ᴀʟʟ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs.
230 | • /delg - Tᴏ ᴅᴇʟᴇᴛᴇ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ.
231 | • /delallg - ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀʟʟ ɢʟᴏʙᴀʟ ꜰɪʟᴛᴇʀꜱ."""
232 |
233 | FILE_STORE_TXT = """
234 | Fɪʟᴇ sᴛᴏʀᴇ ɪs ᴛʜᴇ ғᴇᴀᴛᴜʀᴇ ᴡʜɪᴄʜ ᴡɪʟʟ ᴄʀᴇᴀᴛᴇ ᴀ sʜᴀʀᴇᴀʙʟᴇ ʟɪɴᴋ ᴏғ ᴀ sɪɴɢʟᴇ ᴏʀ ᴍᴜʟᴛɪᴘʟᴇ ғɪʟᴇs.
235 |
236 | Aᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs:
237 | • /batch - Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ ʙᴀᴛᴄʜ ʟɪɴᴋ ᴏғ ᴍᴜʟᴛɪᴘʟᴇ ғɪʟᴇs.
238 | • /link - Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ sɪɴɢʟᴇ ғɪʟᴇ sᴛᴏʀᴇ ʟɪɴᴋ.
239 | • /pbatch - Jᴜsᴛ ʟɪᴋᴇ /batch, ʙᴜᴛ ᴛʜᴇ ғɪʟᴇs ᴡɪʟʟ ʙᴇ sᴇɴᴅ ᴡɪᴛʜ ғᴏʀᴡᴀʀᴅ ʀᴇsᴛʀɪᴄᴛɪᴏɴs.
240 | • /plink - Jᴜsᴛ ʟɪᴋᴇ /link, ʙᴜᴛ ᴛʜᴇ ғɪʟᴇ ᴡɪʟʟ ʙᴇ sᴇɴᴅ ᴡɪᴛʜ ғᴏʀᴡᴀʀᴅ ʀᴇsᴛʀɪᴄᴛɪᴏɴ."""
241 |
242 | RESTART_TXT = """
243 | 𝖡𝗈𝗍 𝖱𝖾𝗌𝗍𝖺𝗋𝗍𝖾𝖽 !
244 |
245 | 📅 𝖣𝖺𝗍𝖾 : {}
246 | ⏰ 𝖳𝗂𝗆𝖾 : {}
247 | 🌐 𝖳𝗂𝗆𝖾𝗓𝗈𝗇𝖾 : Asia/Kolkata
248 | 🛠️ 𝖡𝗎𝗂𝗅𝖽 𝖲𝗍𝖺𝗍𝗎𝗌 : 𝗏2.7.3 [ 𝖲𝗍𝖺𝖻𝗅𝖾 ]"""
249 |
250 | RESTART_GC_TXT = """
251 | 𝖡𝗈𝗍 𝖱𝖾𝗌𝗍𝖺𝗋𝗍𝖾𝖽 ✅"""
252 |
253 | LOGO = """
254 | PIRO BOTS"""
255 |
--------------------------------------------------------------------------------
/plugins/p_ttishow.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters, enums
2 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery
3 | from pyrogram.errors.exceptions.bad_request_400 import MessageTooLong, PeerIdInvalid
4 | from info import ADMINS, LOG_CHANNEL, SUPPORT_CHAT, MELCOW_VID
5 | from database.users_chats_db import db
6 | from database.ia_filterdb import Media
7 | from utils import get_size, temp, get_settings
8 | from Script import script
9 | from pyrogram.errors import ChatAdminRequired
10 | import asyncio
11 |
12 |
13 |
14 | @Client.on_message(filters.new_chat_members & filters.group)
15 | async def save_group(bot, message):
16 | r_j_check = [u.id for u in message.new_chat_members]
17 | if temp.ME in r_j_check:
18 | if not await db.get_chat(message.chat.id):
19 | total=await bot.get_chat_members_count(message.chat.id)
20 | r_j = message.from_user.mention if message.from_user else "Anonymous"
21 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_G.format(message.chat.title, message.chat.id, total, r_j))
22 | await db.add_chat(message.chat.id, message.chat.title)
23 | if message.chat.id in temp.BANNED_CHATS:
24 | buttons = [[
25 | InlineKeyboardButton('🌐 𝖲𝗎𝗉𝗉𝗈𝗋𝗍 🌐', url=f"https://t.me/{SUPPORT_CHAT}")
26 | ]]
27 | reply_markup=InlineKeyboardMarkup(buttons)
28 | k = await message.reply(
29 | text='CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..',
30 | reply_markup=reply_markup,
31 | )
32 |
33 | try:
34 | await k.pin()
35 | except:
36 | pass
37 | await bot.leave_chat(message.chat.id)
38 | return
39 | buttons = [[
40 | InlineKeyboardButton('🧩 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 🧩', url=f"https://t.me/{SUPPORT_CHAT}"),
41 | InlineKeyboardButton('⚡𝖴𝗉𝖽𝖺𝗍𝖾𝗌 ⚡', url=f"https://t.me/piroxbots")
42 | ]]
43 | reply_markup=InlineKeyboardMarkup(buttons)
44 | await message.reply_text(
45 | text=f"Thankyou For Adding Me In {message.chat.title} ❣️\n\nIf you have any questions & doubts about using me contact 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 GROUP.",
46 | reply_markup=reply_markup)
47 | else:
48 | settings = await get_settings(message.chat.id)
49 | if settings["welcome"]:
50 | for u in message.new_chat_members:
51 | if (temp.MELCOW).get('welcome') is not None:
52 | try:
53 | await (temp.MELCOW['welcome']).delete()
54 | except:
55 | pass
56 | temp.MELCOW['welcome'] = await message.reply_video(
57 | video=(MELCOW_VID),
58 | caption=(script.MELCOW_ENG.format(u.mention, message.chat.title)),
59 | reply_markup=InlineKeyboardMarkup(
60 | [[
61 | InlineKeyboardButton('🧩 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 🧩', url=f"https://t.me/{SUPPORT_CHAT}"),
62 | InlineKeyboardButton('⚡𝖴𝗉𝖽𝖺𝗍𝖾𝗌 ⚡', url=f"https://t.me/piroxbots")
63 | ]]
64 | ),
65 | parse_mode=enums.ParseMode.HTML
66 | )
67 |
68 | if settings["auto_delete"]:
69 | await asyncio.sleep(300)
70 | await (temp.MELCOW['welcome']).delete()
71 |
72 |
73 |
74 |
75 |
76 | @Client.on_message(filters.command('leave') & filters.user(ADMINS))
77 | async def leave_a_chat(bot, message):
78 | if len(message.command) == 1:
79 | return await message.reply('Give me a chat id')
80 | chat = message.command[1]
81 | try:
82 | chat = int(chat)
83 | except:
84 | chat = chat
85 | try:
86 | buttons = [[
87 | InlineKeyboardButton('🧩 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 🧩', url=f"https://t.me/{SUPPORT_CHAT}"),
88 | InlineKeyboardButton('⚡𝖴𝗉𝖽𝖺𝗍𝖾𝗌 ⚡', url=f"https://t.me/piroxbots")
89 | ]]
90 | reply_markup=InlineKeyboardMarkup(buttons)
91 | await bot.send_message(
92 | chat_id=chat,
93 | text='Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 GROUP.',
94 | reply_markup=reply_markup,
95 | )
96 |
97 | await bot.leave_chat(chat)
98 | await message.reply(f"left the chat `{chat}`")
99 | except Exception as e:
100 | await message.reply(f'Error - {e}')
101 |
102 | @Client.on_message(filters.command('disable') & filters.user(ADMINS))
103 | async def disable_chat(bot, message):
104 | if len(message.command) == 1:
105 | return await message.reply('Give me a chat id')
106 | r = message.text.split(None)
107 | if len(r) > 2:
108 | reason = message.text.split(None, 2)[2]
109 | chat = message.text.split(None, 2)[1]
110 | else:
111 | chat = message.command[1]
112 | reason = "No reason Provided"
113 | try:
114 | chat_ = int(chat)
115 | except:
116 | return await message.reply('Give Me A Valid Chat ID')
117 | cha_t = await db.get_chat(int(chat_))
118 | if not cha_t:
119 | return await message.reply("Chat Not Found In DB")
120 | if cha_t['is_disabled']:
121 | return await message.reply(f"This chat is already disabled:\nReason- {cha_t['reason']} ")
122 | await db.disable_chat(int(chat_), reason)
123 | temp.BANNED_CHATS.append(int(chat_))
124 | await message.reply('Chat Successfully Disabled')
125 | try:
126 | buttons = [[
127 | InlineKeyboardButton('🧩 𝖲𝖴𝖯𝖯𝖮𝖱𝖳 🧩', url=f"https://t.me/{SUPPORT_CHAT}"),
128 | InlineKeyboardButton('⚡𝖴𝗉𝖽𝖺𝗍𝖾𝗌 ⚡', url=f"https://t.me/piroxbots")
129 | ]]
130 | reply_markup=InlineKeyboardMarkup(buttons)
131 | await bot.send_message(
132 | chat_id=chat_,
133 | text=f'𝖧𝖾𝗅𝗅𝗈 𝖥𝗋𝗂𝖾𝗇𝖽𝗌, \n𝖬𝗒 𝖺𝖽𝗆𝗂𝗇 𝗁𝖺𝗌 𝗍𝗈𝗅𝖽 𝗆𝖾 𝗍𝗈 𝗅𝖾𝖺𝗏𝖾 𝖿𝗋𝗈𝗆 𝗀𝗋𝗈𝗎𝗉 𝗌𝗈 𝗂 𝗀𝗈! 𝖨𝖿 𝗒𝗈𝗎 𝗐𝖺𝗇𝗇𝖺 𝖺𝖽𝖽 𝗆𝖾 𝖺𝗀𝖺𝗂𝗇 𝖼𝗈𝗇𝗍𝖺𝖼𝗍 𝗆𝗒 𝗌𝗎𝗉𝗉𝗈𝗋𝗍 𝗀𝗋𝗈𝗎𝗉. \nReason : {reason}',
134 | reply_markup=reply_markup)
135 | await bot.leave_chat(chat_)
136 | except Exception as e:
137 | await message.reply(f"Error - {e}")
138 |
139 |
140 | @Client.on_message(filters.command('enable') & filters.user(ADMINS))
141 | async def re_enable_chat(bot, message):
142 | if len(message.command) == 1:
143 | return await message.reply('Give me a chat id')
144 | chat = message.command[1]
145 | try:
146 | chat_ = int(chat)
147 | except:
148 | return await message.reply('Give Me A Valid Chat ID')
149 | sts = await db.get_chat(int(chat))
150 | if not sts:
151 | return await message.reply("Chat Not Found In DB !")
152 | if not sts.get('is_disabled'):
153 | return await message.reply('This chat is not yet disabled.')
154 | await db.re_enable_chat(int(chat_))
155 | temp.BANNED_CHATS.remove(int(chat_))
156 | await message.reply("Chat Successfully re-enabled")
157 |
158 |
159 | @Client.on_message(filters.command('stats') & filters.incoming)
160 | async def get_ststs(bot, message):
161 | rju = await message.reply('Fetching stats...')
162 | total_users = await db.total_users_count()
163 | totl_chats = await db.total_chat_count()
164 | files = await Media.count_documents()
165 | size = await db.get_db_size()
166 | free = 536870912 - size
167 | size = get_size(size)
168 | free = get_size(free)
169 | await rju.edit(script.STATUS_TXT.format(files, total_users, totl_chats, size, free))
170 |
171 | @Client.on_message(filters.command('invite') & filters.user(ADMINS))
172 | async def gen_invite(bot, message):
173 | if len(message.command) == 1:
174 | return await message.reply('Give me a chat id')
175 | chat = message.command[1]
176 | try:
177 | chat = int(chat)
178 | except:
179 | return await message.reply('Give Me A Valid Chat ID')
180 | try:
181 | link = await bot.create_chat_invite_link(chat)
182 | except ChatAdminRequired:
183 | return await message.reply("Invite Link Generation Failed, Iam Not Having Sufficient Rights")
184 | except Exception as e:
185 | return await message.reply(f'Error {e}')
186 | await message.reply(f'Here is your Invite Link {link.invite_link}')
187 |
188 | @Client.on_message(filters.command('ban') & filters.user(ADMINS))
189 | async def ban_a_user(bot, message):
190 | if len(message.command) == 1:
191 | return await message.reply('Give me a user id / username')
192 | r = message.text.split(None)
193 | if len(r) > 2:
194 | reason = message.text.split(None, 2)[2]
195 | chat = message.text.split(None, 2)[1]
196 | else:
197 | chat = message.command[1]
198 | reason = "No reason Provided"
199 | try:
200 | chat = int(chat)
201 | except:
202 | pass
203 | try:
204 | k = await bot.get_users(chat)
205 | except PeerIdInvalid:
206 | return await message.reply("This is an invalid user, make sure ia have met him before.")
207 | except IndexError:
208 | return await message.reply("This might be a channel, make sure its a user.")
209 | except Exception as e:
210 | return await message.reply(f'Error - {e}')
211 | else:
212 | jar = await db.get_ban_status(k.id)
213 | if jar['is_banned']:
214 | return await message.reply(f"{k.mention} is already banned\nReason: {jar['ban_reason']}")
215 | await db.ban_user(k.id, reason)
216 | temp.BANNED_USERS.append(k.id)
217 | await message.reply(f"Successfully banned {k.mention}")
218 |
219 |
220 |
221 | @Client.on_message(filters.command('unban') & filters.user(ADMINS))
222 | async def unban_a_user(bot, message):
223 | if len(message.command) == 1:
224 | return await message.reply('Give me a user id / username')
225 | r = message.text.split(None)
226 | if len(r) > 2:
227 | reason = message.text.split(None, 2)[2]
228 | chat = message.text.split(None, 2)[1]
229 | else:
230 | chat = message.command[1]
231 | reason = "No reason Provided"
232 | try:
233 | chat = int(chat)
234 | except:
235 | pass
236 | try:
237 | k = await bot.get_users(chat)
238 | except PeerIdInvalid:
239 | return await message.reply("This is an invalid user, make sure ia have met him before.")
240 | except IndexError:
241 | return await message.reply("Thismight be a channel, make sure its a user.")
242 | except Exception as e:
243 | return await message.reply(f'Error - {e}')
244 | else:
245 | jar = await db.get_ban_status(k.id)
246 | if not jar['is_banned']:
247 | return await message.reply(f"{k.mention} is not yet banned.")
248 | await db.remove_ban(k.id)
249 | temp.BANNED_USERS.remove(k.id)
250 | await message.reply(f"Successfully unbanned {k.mention}")
251 |
252 |
253 |
254 | @Client.on_message(filters.command('users') & filters.user(ADMINS))
255 | async def list_users(bot, message):
256 | raju = await message.reply('Getting List Of Users')
257 | users = await db.get_all_users()
258 | out = "Users Saved In DB Are:\n\n"
259 | async for user in users:
260 | out += f"{user['name']}"
261 | if user['ban_status']['is_banned']:
262 | out += '( Banned User )'
263 | out += '\n'
264 | try:
265 | await raju.edit_text(out)
266 | except MessageTooLong:
267 | with open('users.txt', 'w+') as outfile:
268 | outfile.write(out)
269 | await message.reply_document('users.txt', caption="List Of Users")
270 |
271 | @Client.on_message(filters.command('chats') & filters.user(ADMINS))
272 | async def list_chats(bot, message):
273 | raju = await message.reply('Getting List Of chats')
274 | chats = await db.get_all_chats()
275 | out = "Chats Saved In DB Are:\n\n"
276 | async for chat in chats:
277 | out += f"**Title:** `{chat['title']}`\n**- ID:** `{chat['id']}`"
278 | if chat['chat_status']['is_disabled']:
279 | out += '( Disabled Chat )'
280 | out += '\n'
281 | try:
282 | await raju.edit_text(out)
283 | except MessageTooLong:
284 | with open('chats.txt', 'w+') as outfile:
285 | outfile.write(out)
286 | await message.reply_document('chats.txt', caption="List Of Chats")
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from pyrogram.errors import InputUserDeactivated, UserNotParticipant, FloodWait, UserIsBlocked, PeerIdInvalid
3 | from info import AUTH_CHANNEL, LONG_IMDB_DESCRIPTION, MAX_LIST_ELM, CUSTOM_FILE_CAPTION
4 | from imdb import Cinemagoer
5 | import asyncio
6 | from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup
7 | from pyrogram import enums
8 | from typing import Union
9 | import random
10 | import re
11 | import os
12 | from datetime import datetime
13 | from typing import List
14 | from database.users_chats_db import db
15 | from bs4 import BeautifulSoup
16 | import requests
17 |
18 | logger = logging.getLogger(__name__)
19 | logger.setLevel(logging.INFO)
20 |
21 | BTN_URL_REGEX = re.compile(
22 | r"(\[([^\[]+?)\]\((buttonurl|buttonalert):(?:/{0,2})(.+?)(:same)?\))"
23 | )
24 |
25 | imdb = Cinemagoer()
26 |
27 | BANNED = {}
28 | SMART_OPEN = '“'
29 | SMART_CLOSE = '”'
30 | START_CHAR = ('\'', '"', SMART_OPEN)
31 |
32 | # temp db for banned
33 | class temp(object):
34 | BANNED_USERS = []
35 | BANNED_CHATS = []
36 | ME = None
37 | CURRENT=int(os.environ.get("SKIP", 2))
38 | CANCEL = False
39 | MELCOW = {}
40 | FILES = {}
41 | U_NAME = None
42 | B_NAME = None
43 | SETTINGS = {}
44 | FILES_IDS = {}
45 | SPELL_CHECK = {}
46 |
47 | async def is_subscribed(bot, query):
48 | try:
49 | user = await bot.get_chat_member(AUTH_CHANNEL, query.from_user.id)
50 | except UserNotParticipant:
51 | pass
52 | except Exception as e:
53 | logger.exception(e)
54 | else:
55 | if user.status != enums.ChatMemberStatus.BANNED:
56 | return True
57 |
58 | return False
59 |
60 | async def get_poster(query, bulk=False, id=False, file=None):
61 | if not id:
62 | query = (query.strip()).lower()
63 | title = query
64 | year = re.findall(r'[1-2]\d{3}$', query, re.IGNORECASE)
65 | if year:
66 | year = list_to_str(year[:1])
67 | title = (query.replace(year, "")).strip()
68 | elif file is not None:
69 | year = re.findall(r'[1-2]\d{3}', file, re.IGNORECASE)
70 | if year:
71 | year = list_to_str(year[:1])
72 | else:
73 | year = None
74 | movieid = imdb.search_movie(title.lower(), results=10)
75 | if not movieid:
76 | return None
77 | if year:
78 | filtered=list(filter(lambda k: str(k.get('year')) == str(year), movieid))
79 | if not filtered:
80 | filtered = movieid
81 | else:
82 | filtered = movieid
83 | movieid=list(filter(lambda k: k.get('kind') in ['movie', 'tv series'], filtered))
84 | if not movieid:
85 | movieid = filtered
86 | if bulk:
87 | return movieid
88 | movieid = movieid[0].movieID
89 | else:
90 | movieid = query
91 | movie = imdb.get_movie(movieid)
92 | if movie.get("original air date"):
93 | date = movie["original air date"]
94 | elif movie.get("year"):
95 | date = movie.get("year")
96 | else:
97 | date = "N/A"
98 | plot = ""
99 | if not LONG_IMDB_DESCRIPTION:
100 | plot = movie.get('plot')
101 | if plot and len(plot) > 0:
102 | plot = plot[0]
103 | else:
104 | plot = movie.get('plot outline')
105 | if plot and len(plot) > 800:
106 | plot = plot[0:800] + "..."
107 |
108 | return {
109 | 'title': movie.get('title'),
110 | 'votes': movie.get('votes'),
111 | "aka": list_to_str(movie.get("akas")),
112 | "seasons": movie.get("number of seasons"),
113 | "box_office": movie.get('box office'),
114 | 'localized_title': movie.get('localized title'),
115 | 'kind': movie.get("kind"),
116 | "imdb_id": f"tt{movie.get('imdbID')}",
117 | "cast": list_to_str(movie.get("cast")),
118 | "runtime": list_to_str(movie.get("runtimes")),
119 | "countries": list_to_str(movie.get("countries")),
120 | "certificates": list_to_str(movie.get("certificates")),
121 | "languages": list_to_str(movie.get("languages")),
122 | "director": list_to_str(movie.get("director")),
123 | "writer":list_to_str(movie.get("writer")),
124 | "producer":list_to_str(movie.get("producer")),
125 | "composer":list_to_str(movie.get("composer")) ,
126 | "cinematographer":list_to_str(movie.get("cinematographer")),
127 | "music_team": list_to_str(movie.get("music department")),
128 | "distributors": list_to_str(movie.get("distributors")),
129 | 'release_date': date,
130 | 'year': movie.get('year'),
131 | 'genres': list_to_str(movie.get("genres")),
132 | 'poster': movie.get('full-size cover url'),
133 | 'plot': plot,
134 | 'rating': str(movie.get("rating")),
135 | 'url':f'https://www.imdb.com/title/tt{movieid}'
136 | }
137 |
138 | async def broadcast_messages(user_id, message):
139 | try:
140 | await message.copy(chat_id=user_id)
141 | return True, "Success"
142 | except FloodWait as e:
143 | await asyncio.sleep(e.x)
144 | return await broadcast_messages(user_id, message)
145 | except InputUserDeactivated:
146 | await db.delete_user(int(user_id))
147 | logging.info(f"{user_id}-Removed from Database, since deleted account.")
148 | return False, "Deleted"
149 | except UserIsBlocked:
150 | logging.info(f"{user_id} -Blocked the bot.")
151 | return False, "Blocked"
152 | except PeerIdInvalid:
153 | await db.delete_user(int(user_id))
154 | logging.info(f"{user_id} - PeerIdInvalid")
155 | return False, "Error"
156 | except Exception as e:
157 | return False, "Error"
158 |
159 | async def broadcast_messages_group(chat_id, message):
160 | try:
161 | kd = await message.copy(chat_id=chat_id)
162 | try:
163 | await kd.pin()
164 | except:
165 | pass
166 | return True, "Succes"
167 | except FloodWait as e:
168 | await asyncio.sleep(e.x)
169 | return await broadcast_messages_group(chat_id, message)
170 | except Exception as e:
171 | return False, "Error"
172 |
173 | async def search_gagala(text):
174 | usr_agent = {
175 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
176 | 'Chrome/61.0.3163.100 Safari/537.36'
177 | }
178 | text = text.replace(" ", '+')
179 | url = f'https://www.google.com/search?q={text}'
180 | response = requests.get(url, headers=usr_agent)
181 | response.raise_for_status()
182 | soup = BeautifulSoup(response.text, 'html.parser')
183 | titles = soup.find_all( 'h3' )
184 | return [title.getText() for title in titles]
185 |
186 |
187 | async def get_settings(group_id):
188 | settings = temp.SETTINGS.get(group_id)
189 | if not settings:
190 | settings = await db.get_settings(group_id)
191 | temp.SETTINGS[group_id] = settings
192 | return settings
193 |
194 | async def save_group_settings(group_id, key, value):
195 | current = await get_settings(group_id)
196 | current[key] = value
197 | temp.SETTINGS[group_id] = current
198 | await db.update_settings(group_id, current)
199 |
200 | def get_size(size):
201 | """Get size in readable format"""
202 |
203 | units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"]
204 | size = float(size)
205 | i = 0
206 | while size >= 1024.0 and i < len(units):
207 | i += 1
208 | size /= 1024.0
209 | return "%.2f %s" % (size, units[i])
210 |
211 | def split_list(l, n):
212 | for i in range(0, len(l), n):
213 | yield l[i:i + n]
214 |
215 | def get_file_id(msg: Message):
216 | if msg.media:
217 | for message_type in (
218 | "photo",
219 | "animation",
220 | "audio",
221 | "document",
222 | "video",
223 | "video_note",
224 | "voice",
225 | "sticker"
226 | ):
227 | obj = getattr(msg, message_type)
228 | if obj:
229 | setattr(obj, "message_type", message_type)
230 | return obj
231 |
232 | def extract_user(message: Message) -> Union[int, str]:
233 | """extracts the user from a message"""
234 | user_id = None
235 | user_first_name = None
236 | if message.reply_to_message:
237 | user_id = message.reply_to_message.from_user.id
238 | user_first_name = message.reply_to_message.from_user.first_name
239 |
240 | elif len(message.command) > 1:
241 | if (
242 | len(message.entities) > 1 and
243 | message.entities[1].type == enums.MessageEntityType.TEXT_MENTION
244 | ):
245 |
246 | required_entity = message.entities[1]
247 | user_id = required_entity.user.id
248 | user_first_name = required_entity.user.first_name
249 | else:
250 | user_id = message.command[1]
251 | # don't want to make a request -_-
252 | user_first_name = user_id
253 | try:
254 | user_id = int(user_id)
255 | except ValueError:
256 | pass
257 | else:
258 | user_id = message.from_user.id
259 | user_first_name = message.from_user.first_name
260 | return (user_id, user_first_name)
261 |
262 | def list_to_str(k):
263 | if not k:
264 | return "N/A"
265 | elif len(k) == 1:
266 | return str(k[0])
267 | elif MAX_LIST_ELM:
268 | k = k[:int(MAX_LIST_ELM)]
269 | return ' '.join(f'{elem}, ' for elem in k)
270 | else:
271 | return ' '.join(f'{elem}, ' for elem in k)
272 |
273 | def last_online(from_user):
274 | time = ""
275 | if from_user.is_bot:
276 | time += "🤖 Bot :("
277 | elif from_user.status == enums.UserStatus.RECENTLY:
278 | time += "Recently"
279 | elif from_user.status == enums.UserStatus.LAST_WEEK:
280 | time += "Within the last week"
281 | elif from_user.status == enums.UserStatus.LAST_MONTH:
282 | time += "Within the last month"
283 | elif from_user.status == enums.UserStatus.LONG_AGO:
284 | time += "A long time ago :("
285 | elif from_user.status == enums.UserStatus.ONLINE:
286 | time += "Currently Online"
287 | elif from_user.status == enums.UserStatus.OFFLINE:
288 | time += from_user.last_online_date.strftime("%a, %d %b %Y, %H:%M:%S")
289 | return time
290 |
291 |
292 | def split_quotes(text: str) -> List:
293 | if not any(text.startswith(char) for char in START_CHAR):
294 | return text.split(None, 1)
295 | counter = 1 # ignore first char -> is some kind of quote
296 | while counter < len(text):
297 | if text[counter] == "\\":
298 | counter += 1
299 | elif text[counter] == text[0] or (text[0] == SMART_OPEN and text[counter] == SMART_CLOSE):
300 | break
301 | counter += 1
302 | else:
303 | return text.split(None, 1)
304 |
305 | # 1 to avoid starting quote, and counter is exclusive so avoids ending
306 | key = remove_escapes(text[1:counter].strip())
307 | # index will be in range, or `else` would have been executed and returned
308 | rest = text[counter + 1:].strip()
309 | if not key:
310 | key = text[0] + text[0]
311 | return list(filter(None, [key, rest]))
312 |
313 | def gfilterparser(text, keyword):
314 | if "buttonalert" in text:
315 | text = (text.replace("\n", "\\n").replace("\t", "\\t"))
316 | buttons = []
317 | note_data = ""
318 | prev = 0
319 | i = 0
320 | alerts = []
321 | for match in BTN_URL_REGEX.finditer(text):
322 | # Check if btnurl is escaped
323 | n_escapes = 0
324 | to_check = match.start(1) - 1
325 | while to_check > 0 and text[to_check] == "\\":
326 | n_escapes += 1
327 | to_check -= 1
328 |
329 | # if even, not escaped -> create button
330 | if n_escapes % 2 == 0:
331 | note_data += text[prev:match.start(1)]
332 | prev = match.end(1)
333 | if match.group(3) == "buttonalert":
334 | # create a thruple with button label, url, and newline status
335 | if bool(match.group(5)) and buttons:
336 | buttons[-1].append(InlineKeyboardButton(
337 | text=match.group(2),
338 | callback_data=f"gfilteralert:{i}:{keyword}"
339 | ))
340 | else:
341 | buttons.append([InlineKeyboardButton(
342 | text=match.group(2),
343 | callback_data=f"gfilteralert:{i}:{keyword}"
344 | )])
345 | i += 1
346 | alerts.append(match.group(4))
347 | elif bool(match.group(5)) and buttons:
348 | buttons[-1].append(InlineKeyboardButton(
349 | text=match.group(2),
350 | url=match.group(4).replace(" ", "")
351 | ))
352 | else:
353 | buttons.append([InlineKeyboardButton(
354 | text=match.group(2),
355 | url=match.group(4).replace(" ", "")
356 | )])
357 |
358 | else:
359 | note_data += text[prev:to_check]
360 | prev = match.start(1) - 1
361 | else:
362 | note_data += text[prev:]
363 |
364 | try:
365 | return note_data, buttons, alerts
366 | except:
367 | return note_data, buttons, None
368 |
369 | def parser(text, keyword):
370 | if "buttonalert" in text:
371 | text = (text.replace("\n", "\\n").replace("\t", "\\t"))
372 | buttons = []
373 | note_data = ""
374 | prev = 0
375 | i = 0
376 | alerts = []
377 | for match in BTN_URL_REGEX.finditer(text):
378 | # Check if btnurl is escaped
379 | n_escapes = 0
380 | to_check = match.start(1) - 1
381 | while to_check > 0 and text[to_check] == "\\":
382 | n_escapes += 1
383 | to_check -= 1
384 |
385 | # if even, not escaped -> create button
386 | if n_escapes % 2 == 0:
387 | note_data += text[prev:match.start(1)]
388 | prev = match.end(1)
389 | if match.group(3) == "buttonalert":
390 | # create a thruple with button label, url, and newline status
391 | if bool(match.group(5)) and buttons:
392 | buttons[-1].append(InlineKeyboardButton(
393 | text=match.group(2),
394 | callback_data=f"alertmessage:{i}:{keyword}"
395 | ))
396 | else:
397 | buttons.append([InlineKeyboardButton(
398 | text=match.group(2),
399 | callback_data=f"alertmessage:{i}:{keyword}"
400 | )])
401 | i += 1
402 | alerts.append(match.group(4))
403 | elif bool(match.group(5)) and buttons:
404 | buttons[-1].append(InlineKeyboardButton(
405 | text=match.group(2),
406 | url=match.group(4).replace(" ", "")
407 | ))
408 | else:
409 | buttons.append([InlineKeyboardButton(
410 | text=match.group(2),
411 | url=match.group(4).replace(" ", "")
412 | )])
413 |
414 | else:
415 | note_data += text[prev:to_check]
416 | prev = match.start(1) - 1
417 | else:
418 | note_data += text[prev:]
419 |
420 | try:
421 | return note_data, buttons, alerts
422 | except:
423 | return note_data, buttons, None
424 |
425 | def remove_escapes(text: str) -> str:
426 | res = ""
427 | is_escaped = False
428 | for counter in range(len(text)):
429 | if is_escaped:
430 | res += text[counter]
431 | is_escaped = False
432 | elif text[counter] == "\\":
433 | is_escaped = True
434 | else:
435 | res += text[counter]
436 | return res
437 |
438 |
439 | def humanbytes(size):
440 | if not size:
441 | return ""
442 | power = 2**10
443 | n = 0
444 | Dic_powerN = {0: ' ', 1: 'Ki', 2: 'Mi', 3: 'Gi', 4: 'Ti'}
445 | while size > power:
446 | size /= power
447 | n += 1
448 | return str(round(size, 2)) + " " + Dic_powerN[n] + 'B'
449 |
450 | async def send_all(bot, userid, files, ident):
451 | for file in files:
452 | f_caption = file.caption
453 | title = file.file_name
454 | size = get_size(file.file_size)
455 | if CUSTOM_FILE_CAPTION:
456 | try:
457 | f_caption = CUSTOM_FILE_CAPTION.format(file_name='' if title is None else title,
458 | file_size='' if size is None else size,
459 | file_caption='' if f_caption is None else f_caption)
460 | except Exception as e:
461 | print(e)
462 | f_caption = f_caption
463 | if f_caption is None:
464 | f_caption = f"{title}"
465 | await bot.send_cached_media(
466 | chat_id=userid,
467 | file_id=file.file_id,
468 | caption=f_caption,
469 | protect_content=True if ident == "filep" else False,
470 | reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton('⚔️ 𝖯𝖨𝖱𝖮 𝖴𝖯𝖣𝖠𝖳𝖤𝖲 ⚔️', url="https://t.me/piroxbots") ] ] ))
471 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {title}"
260 | if CUSTOM_FILE_CAPTION:
261 | try:
262 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='')
263 | except:
264 | return
265 | await msg.edit_caption(f_caption)
266 | return
267 | except:
268 | pass
269 | return await message.reply('No such file exist.')
270 | files = files_[0]
271 | title = files.file_name
272 | size=get_size(files.file_size)
273 | f_caption=files.caption
274 | if CUSTOM_FILE_CAPTION:
275 | try:
276 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='' if f_caption is None else f_caption)
277 | except Exception as e:
278 | logger.exception(e)
279 | f_caption=f_caption
280 | if f_caption is None:
281 | f_caption = f"{files.file_name}"
282 | await client.send_cached_media(
283 | chat_id=message.from_user.id,
284 | file_id=file_id,
285 | caption=f_caption,
286 | protect_content=True if pre == 'filep' else False,
287 | reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton('⚔️ 𝖯𝖨𝖱𝖮 𝖴𝖯𝖣𝖠𝖳𝖤𝖲 ⚔️', url="https://t.me/piroxbots") ] ] ),
288 | )
289 |
290 |
291 | @Client.on_message(filters.command('channel') & filters.user(ADMINS))
292 | async def channel_info(bot, message):
293 |
294 | """Send basic information of channel"""
295 | if isinstance(CHANNELS, (int, str)):
296 | channels = [CHANNELS]
297 | elif isinstance(CHANNELS, list):
298 | channels = CHANNELS
299 | else:
300 | raise ValueError("Unexpected type of CHANNELS")
301 |
302 | text = '📑 **Indexed channels/groups**\n'
303 | for channel in channels:
304 | chat = await bot.get_chat(channel)
305 | if chat.username:
306 | text += '\n@' + chat.username
307 | else:
308 | text += '\n' + chat.title or chat.first_name
309 |
310 | text += f'\n\n**Total:** {len(CHANNELS)}'
311 |
312 | if len(text) < 4096:
313 | await message.reply(text)
314 | else:
315 | file = 'Indexed channels.txt'
316 | with open(file, 'w') as f:
317 | f.write(text)
318 | await message.reply_document(file)
319 | os.remove(file)
320 |
321 |
322 | @Client.on_message(filters.command('logs') & filters.user(ADMINS))
323 | async def log_file(bot, message):
324 | """Send log file"""
325 | try:
326 | await message.reply_document('Logs.txt')
327 | except Exception as e:
328 | await message.reply(str(e))
329 |
330 | @Client.on_message(filters.command('delete') & filters.user(ADMINS))
331 | async def delete(bot, message):
332 | """Delete file from database"""
333 | reply = message.reply_to_message
334 | if reply and reply.media:
335 | msg = await message.reply("Processing...⏳", quote=True)
336 | else:
337 | await message.reply('Reply to file with /delete which you want to delete', quote=True)
338 | return
339 |
340 | for file_type in ("document", "video", "audio"):
341 | media = getattr(reply, file_type, None)
342 | if media is not None:
343 | break
344 | else:
345 | await msg.edit('This is not supported file format')
346 | return
347 |
348 | file_id, file_ref = unpack_new_file_id(media.file_id)
349 |
350 | result = await Media.collection.delete_one({
351 | '_id': file_id,
352 | })
353 | if result.deleted_count:
354 | await msg.edit('File is successfully deleted from database')
355 | else:
356 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name))
357 | result = await Media.collection.delete_many({
358 | 'file_name': file_name,
359 | 'file_size': media.file_size,
360 | 'mime_type': media.mime_type
361 | })
362 | if result.deleted_count:
363 | await msg.edit('File is successfully deleted from database')
364 | else:
365 | result = await Media.collection.delete_many({
366 | 'file_name': media.file_name,
367 | 'file_size': media.file_size,
368 | 'mime_type': media.mime_type
369 | })
370 | if result.deleted_count:
371 | await msg.edit('File is successfully deleted from database')
372 | else:
373 | await msg.edit('File not found in database')
374 |
375 |
376 | @Client.on_message(filters.command('deleteall') & filters.user(ADMINS))
377 | async def delete_all_index(bot, message):
378 | await message.reply_text(
379 | 'This will delete all indexed files.\nDo you want to continue??',
380 | reply_markup=InlineKeyboardMarkup(
381 | [
382 | [
383 | InlineKeyboardButton(
384 | text="YES", callback_data="autofilter_delete"
385 | )
386 | ],
387 | [
388 | InlineKeyboardButton(
389 | text="CANCEL", callback_data="close_data"
390 | )
391 | ],
392 | ]
393 | ),
394 | quote=True,
395 | )
396 |
397 |
398 | @Client.on_callback_query(filters.regex(r'^autofilter_delete'))
399 | async def delete_all_index_confirm(bot, message):
400 | await Media.collection.drop()
401 | await message.answer('Piracy Is Crime')
402 | await message.message.edit('Succesfully Deleted All The Indexed Files.')
403 |
404 |
405 | @Client.on_message(filters.command('settings'))
406 | async def settings(client, message):
407 | userid = message.from_user.id if message.from_user else None
408 | if not userid:
409 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
410 | chat_type = message.chat.type
411 |
412 | if chat_type == enums.ChatType.PRIVATE:
413 | grpid = await active_connection(str(userid))
414 | if grpid is not None:
415 | grp_id = grpid
416 | try:
417 | chat = await client.get_chat(grpid)
418 | title = chat.title
419 | except:
420 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
421 | return
422 | else:
423 | await message.reply_text("I'm not connected to any groups!", quote=True)
424 | return
425 |
426 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
427 | grp_id = message.chat.id
428 | title = message.chat.title
429 |
430 | else:
431 | return
432 |
433 | st = await client.get_chat_member(grp_id, userid)
434 | if (
435 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
436 | and st.status != enums.ChatMemberStatus.OWNER
437 | and str(userid) not in ADMINS
438 | ):
439 | return
440 |
441 | settings = await get_settings(grp_id)
442 |
443 | try:
444 | if settings['max_btn']:
445 | settings = await get_settings(grp_id)
446 | except KeyError:
447 | await save_group_settings(grp_id, 'max_btn', False)
448 | settings = await get_settings(grp_id)
449 |
450 | if settings is not None:
451 | buttons = [
452 | [
453 | InlineKeyboardButton(
454 | '𝖥𝗂𝗅𝗍𝖾𝗋 𝖡𝗎𝗍𝗍𝗈𝗇',
455 | callback_data=f'setgs#button#{settings["button"]}#{grp_id}',
456 | ),
457 | InlineKeyboardButton(
458 | '𝖲𝗂𝗇𝗀𝗅𝖾 𝖡𝗎𝗍𝗍𝗈𝗇' if settings["button"] else '𝖣𝗈𝗎𝖻𝗅𝖾',
459 | callback_data=f'setgs#button#{settings["button"]}#{grp_id}',
460 | ),
461 | ],
462 | [
463 | InlineKeyboardButton(
464 | '𝖥𝗂𝗅𝖾 𝖲𝖾𝗇𝖽 𝖬𝗈𝖽𝖾',
465 | callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}',
466 | ),
467 | InlineKeyboardButton(
468 | '𝖬𝖺𝗇𝗎𝖺𝗅 𝖲𝗍𝖺𝗋𝗍' if settings["botpm"] else '𝖠𝗎𝗍𝗈 𝖲𝖾𝗇𝖽',
469 | callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}',
470 | ),
471 | ],
472 | [
473 | InlineKeyboardButton(
474 | '𝖯𝗋𝗈𝗍𝖾𝖼𝗍 𝖢𝗈𝗇𝗍𝖾𝗇𝗍',
475 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}',
476 | ),
477 | InlineKeyboardButton(
478 | '✅ 𝖮𝗇' if settings["file_secure"] else '❌ 𝖮𝖿𝖿',
479 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}',
480 | ),
481 | ],
482 | [
483 | InlineKeyboardButton(
484 | '𝖨𝖬𝖣𝖻',
485 | callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}',
486 | ),
487 | InlineKeyboardButton(
488 | '✅ 𝖮𝗇' if settings["imdb"] else '❌ 𝖮𝖿𝖿',
489 | callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}',
490 | ),
491 | ],
492 | [
493 | InlineKeyboardButton(
494 | '𝖲𝗉𝖾𝗅𝗅 𝖢𝗁𝖾𝖼𝗄',
495 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}',
496 | ),
497 | InlineKeyboardButton(
498 | '✅ 𝖮𝗇' if settings["spell_check"] else '❌ 𝖮𝖿𝖿',
499 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}',
500 | ),
501 | ],
502 | [
503 | InlineKeyboardButton(
504 | '𝖶𝖾𝗅𝖼𝗈𝗆𝖾 𝖬𝖾𝗌𝗌𝖺𝗀𝖾',
505 | callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}',
506 | ),
507 | InlineKeyboardButton(
508 | '✅ 𝖮𝗇' if settings["welcome"] else '❌ 𝖮𝖿𝖿',
509 | callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}',
510 | ),
511 | ],
512 | [
513 | InlineKeyboardButton(
514 | '𝖠𝗎𝗍𝗈 𝖣𝖾𝗅𝖾𝗍𝖾',
515 | callback_data=f'setgs#auto_delete#{settings["auto_delete"]}#{grp_id}',
516 | ),
517 | InlineKeyboardButton(
518 | '5 𝖬𝗂𝗇' if settings["auto_delete"] else '❌ 𝖮𝖿𝖿',
519 | callback_data=f'setgs#auto_delete#{settings["auto_delete"]}#{grp_id}',
520 | ),
521 | ],
522 | [
523 | InlineKeyboardButton(
524 | '𝖠𝗎𝗍𝗈-𝖥𝗂𝗅𝗍𝖾𝗋',
525 | callback_data=f'setgs#auto_ffilter#{settings["auto_ffilter"]}#{grp_id}',
526 | ),
527 | InlineKeyboardButton(
528 | '✅ 𝖮𝗇' if settings["auto_ffilter"] else '❌ 𝖮𝖿𝖿',
529 | callback_data=f'setgs#auto_ffilter#{settings["auto_ffilter"]}#{grp_id}',
530 | ),
531 | ],
532 | [
533 | InlineKeyboardButton(
534 | '𝖬𝖺𝗑 𝖡𝗎𝗍𝗍𝗈𝗇𝗌',
535 | callback_data=f'setgs#max_btn#{settings["max_btn"]}#{grp_id}',
536 | ),
537 | InlineKeyboardButton(
538 | '10' if settings["max_btn"] else f'{MAX_B_TN}',
539 | callback_data=f'setgs#max_btn#{settings["max_btn"]}#{grp_id}',
540 | ),
541 | ],
542 | ]
543 |
544 | btn = [[
545 | InlineKeyboardButton("⬇ 𝖮𝗉𝖾𝗇 𝖧𝖾𝗋𝖾 ⬇", callback_data=f"opnsetgrp#{grp_id}"),
546 | InlineKeyboardButton("➡ 𝖮𝗉𝖾𝗇 𝗂𝗇 𝖯𝖬 ➡", callback_data=f"opnsetpm#{grp_id}")
547 | ]]
548 |
549 | reply_markup = InlineKeyboardMarkup(buttons)
550 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
551 | await message.reply_text(
552 | text="𝖣𝗈 𝖸𝗈𝗎 𝖶𝖺𝗇𝗍 𝖳𝗈 𝖮𝗉𝖾𝗇 𝖲𝖾𝗍𝗍𝗂𝗇𝗀𝗌 𝖧𝖾𝗋𝖾 ?",
553 | reply_markup=InlineKeyboardMarkup(btn),
554 | disable_web_page_preview=True,
555 | parse_mode=enums.ParseMode.HTML,
556 | reply_to_message_id=message.id
557 | )
558 | else:
559 | await message.reply_text(
560 | text=f"𝖢𝗁𝖺𝗇𝗀𝖾 𝖸𝗈𝗎𝗋 𝖲𝖾𝗍𝗍𝗂𝗇𝗀𝗌 𝖥𝗈𝗋 {title} 𝖠𝗌 𝖸𝗈𝗎𝗋 𝖶𝗂𝗌𝗁",
561 | reply_markup=reply_markup,
562 | disable_web_page_preview=True,
563 | parse_mode=enums.ParseMode.HTML,
564 | reply_to_message_id=message.id
565 | )
566 |
567 | @Client.on_message(filters.command("send") & filters.user(ADMINS))
568 | async def send_msg(bot, message):
569 | if message.reply_to_message:
570 | target_id = message.text
571 | command = ["/send"]
572 | out = "Users Saved In DB Are:\n\n"
573 | for cmd in command:
574 | if cmd in target_id:
575 | target_id = target_id.replace(cmd, "")
576 | success = False
577 | try:
578 | user = await bot.get_users(target_id)
579 | users = await db.get_all_users()
580 | async for usr in users:
581 | out += f"{usr['id']}"
582 | out += '\n'
583 | if str(user.id) in str(out):
584 | await message.reply_to_message.copy(int(user.id))
585 | success = True
586 | else:
587 | success = False
588 | if success:
589 | await message.reply_text(f"Your message has been successfully send to {user.mention}.")
590 | else:
591 | await message.reply_text("This user didn't started this bot yet !")
592 | except Exception as e:
593 | await message.reply_text(f"Error: {e}")
594 | else:
595 | await message.reply_text("Use this command as a reply to any message using the target chat id. For eg: /send userid")
596 |
597 | @Client.on_message(filters.command('set_template'))
598 | async def save_template(client, message):
599 | sts = await message.reply("Checking template")
600 | userid = message.from_user.id if message.from_user else None
601 | if not userid:
602 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM")
603 | chat_type = message.chat.type
604 |
605 | if chat_type == enums.ChatType.PRIVATE:
606 | grpid = await active_connection(str(userid))
607 | if grpid is not None:
608 | grp_id = grpid
609 | try:
610 | chat = await client.get_chat(grpid)
611 | title = chat.title
612 | except:
613 | await message.reply_text("Make sure I'm present in your group!!", quote=True)
614 | return
615 | else:
616 | await message.reply_text("I'm not connected to any groups!", quote=True)
617 | return
618 |
619 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]:
620 | grp_id = message.chat.id
621 | title = message.chat.title
622 |
623 | else:
624 | return
625 |
626 | st = await client.get_chat_member(grp_id, userid)
627 | if (
628 | st.status != enums.ChatMemberStatus.ADMINISTRATOR
629 | and st.status != enums.ChatMemberStatus.OWNER
630 | and str(userid) not in ADMINS
631 | ):
632 | return
633 |
634 | if len(message.command) < 2:
635 | return await sts.edit("No Input!!")
636 | template = message.text.split(" ", 1)[1]
637 | await save_group_settings(grp_id, 'template', template)
638 | await sts.edit(f"Successfully changed template for {title} to\n\n{template}")
639 |
640 |
641 | @Client.on_message((filters.command(["request", "Request"]) | filters.regex("#request") | filters.regex("#Request")) & filters.group)
642 | async def requests(bot, message):
643 | if REQST_CHANNEL is None or SUPPORT_CHAT_ID is None: return # Must add REQST_CHANNEL and SUPPORT_CHAT_ID to use this feature
644 | if message.reply_to_message and SUPPORT_CHAT_ID == message.chat.id:
645 | chat_id = message.chat.id
646 | reporter = str(message.from_user.id)
647 | mention = message.from_user.mention
648 | success = True
649 | content = message.reply_to_message.text
650 | try:
651 | if REQST_CHANNEL is not None:
652 | btn = [[
653 | InlineKeyboardButton('📥 𝖵𝗂𝖾𝗐 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 📥', url=f"{message.reply_to_message.link}"),
654 | InlineKeyboardButton('📝 𝖲𝗁𝗈𝗐 𝖮𝗉𝗍𝗂𝗈𝗇𝗌 📝', callback_data=f'show_option#{reporter}')
655 | ]]
656 | reported_post = await bot.send_message(chat_id=REQST_CHANNEL, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn))
657 | success = True
658 | elif len(content) >= 3:
659 | for admin in ADMINS:
660 | btn = [[
661 | InlineKeyboardButton('📥 𝖵𝗂𝖾𝗐 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 📥', url=f"{message.reply_to_message.link}"),
662 | InlineKeyboardButton('📝 𝖲𝗁𝗈𝗐 𝖮𝗉𝗍𝗂𝗈𝗇𝗌 📝', callback_data=f'show_option#{reporter}')
663 | ]]
664 | reported_post = await bot.send_message(chat_id=admin, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn))
665 | success = True
666 | else:
667 | if len(content) < 3:
668 | await message.reply_text("You must type about your request [Minimum 3 Characters]. Requests can't be empty.")
669 | if len(content) < 3:
670 | success = False
671 | except Exception as e:
672 | await message.reply_text(f"Error: {e}")
673 | pass
674 |
675 | elif SUPPORT_CHAT_ID == message.chat.id:
676 | chat_id = message.chat.id
677 | reporter = str(message.from_user.id)
678 | mention = message.from_user.mention
679 | success = True
680 | content = message.text
681 | keywords = ["#request", "/request", "#Request", "/Request"]
682 | for keyword in keywords:
683 | if keyword in content:
684 | content = content.replace(keyword, "")
685 | try:
686 | if REQST_CHANNEL is not None and len(content) >= 3:
687 | btn = [[
688 | InlineKeyboardButton('📥 𝖵𝗂𝖾𝗐 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 📥', url=f"{message.link}"),
689 | InlineKeyboardButton('📝 𝖲𝗁𝗈𝗐 𝖮𝗉𝗍𝗂𝗈𝗇𝗌 📝', callback_data=f'show_option#{reporter}')
690 | ]]
691 | reported_post = await bot.send_message(chat_id=REQST_CHANNEL, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn))
692 | success = True
693 | elif len(content) >= 3:
694 | for admin in ADMINS:
695 | btn = [[
696 | InlineKeyboardButton('📥 𝖵𝗂𝖾𝗐 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 📥', url=f"{message.link}"),
697 | InlineKeyboardButton('📝 𝖲𝗁𝗈𝗐 𝖮𝗉𝗍𝗂𝗈𝗇𝗌 📝', callback_data=f'show_option#{reporter}')
698 | ]]
699 | reported_post = await bot.send_message(chat_id=admin, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn))
700 | success = True
701 | else:
702 | if len(content) < 3:
703 | await message.reply_text("You must type about your request [Minimum 3 Characters]. Requests can't be empty.")
704 | if len(content) < 3:
705 | success = False
706 | except Exception as e:
707 | await message.reply_text(f"Error: {e}")
708 | pass
709 |
710 | else:
711 | success = False
712 |
713 | if success:
714 | btn = [[
715 | InlineKeyboardButton('📥 𝖵𝗂𝖾𝗐 𝖱𝖾𝗊𝗎𝖾𝗌𝗍 📥', url=f"{reported_post.link}")
716 | ]]
717 | await message.reply_text("Your request has been added! Please wait for some time.", reply_markup=InlineKeyboardMarkup(btn))
718 |
719 | @Client.on_message(filters.command("usend") & filters.user(ADMINS))
720 | async def send_msg(bot, message):
721 | if message.reply_to_message:
722 | target_id = message.text.split(" ", 1)[1]
723 | out = "Users Saved In DB Are:\n\n"
724 | success = False
725 | try:
726 | user = await bot.get_users(target_id)
727 | users = await db.get_all_users()
728 | async for usr in users:
729 | out += f"{usr['id']}"
730 | out += '\n'
731 | if str(user.id) in str(out):
732 | await message.reply_to_message.copy(int(user.id))
733 | success = True
734 | else:
735 | success = False
736 | if success:
737 | await message.reply_text(f"𝖸𝗈𝗎𝗋 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖧𝖺𝗌 𝖲𝗎𝖼𝖼𝖾𝗌𝗌𝖿𝗎𝗅𝗅𝗒 𝖲𝖾𝗇𝗍 𝖳𝗈 {user.mention}.")
738 | else:
739 | await message.reply_text("An Error Occured !")
740 | except Exception as e:
741 | await message.reply_text(f"Error :- {e}")
742 | else:
743 | await message.reply_text("Error𝖢𝗈𝗆𝗆𝖺𝗇𝖽 𝖨𝗇𝖼𝗈𝗆𝗉𝗅𝖾𝗍𝖾 !")
744 |
745 | @Client.on_message(filters.command("send") & filters.user(ADMINS))
746 | async def send_msg(bot, message):
747 | if message.reply_to_message:
748 | target_id = message.text.split(" ", 1)[1]
749 | out = "Users Saved In DB Are:\n\n"
750 | success = False
751 | try:
752 | user = await bot.get_users(target_id)
753 | users = await db.get_all_users()
754 | async for usr in users:
755 | out += f"{usr['id']}"
756 | out += '\n'
757 | if str(user.id) in str(out):
758 | await message.reply_to_message.copy(int(user.id))
759 | success = True
760 | else:
761 | success = False
762 | if success:
763 | await message.reply_text(f"Your message has been successfully send to {user.mention}.")
764 | else:
765 | await message.reply_text("This user didn't started this bot yet !")
766 | except Exception as e:
767 | await message.reply_text(f"Error: {e}")
768 | else:
769 | await message.reply_text("Use this command as a reply to any message using the target chat id. For eg: /send userid")
770 |
771 | @Client.on_message(filters.command("gsend") & filters.user(ADMINS))
772 | async def send_chatmsg(bot, message):
773 | if message.reply_to_message:
774 | target_id = message.text.split(" ", 1)[1]
775 | out = "Chats Saved In DB Are:\n\n"
776 | success = False
777 | try:
778 | chat = await bot.get_chat(target_id)
779 | chats = await db.get_all_chats()
780 | async for cht in chats:
781 | out += f"{cht['id']}"
782 | out += '\n'
783 | if str(chat.id) in str(out):
784 | await message.reply_to_message.copy(int(chat.id))
785 | success = True
786 | else:
787 | success = False
788 | if success:
789 | await message.reply_text(f"Your message has been successfully send to {chat.id}.")
790 | else:
791 | await message.reply_text("An Error Occured !")
792 | except Exception as e:
793 | await message.reply_text(f"Error :- {e}")
794 | else:
795 | await message.reply_text("Error𝖢𝗈𝗆𝗆𝖺𝗇𝖽 𝖨𝗇𝖼𝗈𝗆𝗉𝗅𝖾𝗍𝖾 !")
796 |
797 | @Client.on_message(filters.command("deletefiles") & filters.user(ADMINS))
798 | async def deletemultiplefiles(bot, message):
799 | chat_type = message.chat.type
800 | if chat_type != enums.ChatType.PRIVATE:
801 | return await message.reply_text(f"Hey {message.from_user.mention}, This command won't work in groups. It only works on my PM !")
802 | else:
803 | pass
804 | try:
805 | keyword = message.text.split(" ", 1)[1]
806 | except:
807 | return await message.reply_text(f"Hey {message.from_user.mention}, Give me a keyword along with the command to delete files.")
808 | k = await bot.send_message(chat_id=message.chat.id, text=f"Fetching Files for your query {keyword} on DB... Please wait...")
809 | files, total = await get_bad_files(keyword)
810 | await k.edit_text(f"Found {total} files for your query {keyword} !\n\nFile deletion process will start in 5 seconds !")
811 | await asyncio.sleep(5)
812 | deleted = 0
813 | for file in files:
814 | await k.edit_text(f"Process started for deleting files from DB. Successfully deleted {str(deleted)} files from DB for your query {keyword} !\n\nPlease wait...")
815 | file_ids = file.file_id
816 | file_name = file.file_name
817 | result = await Media.collection.delete_one({
818 | '_id': file_ids,
819 | })
820 | if result.deleted_count:
821 | logger.info(f'File Found for your query {keyword}! Successfully deleted {file_name} from database.')
822 | deleted += 1
823 | await k.edit_text(text=f"Process Completed for file deletion !\n\nSuccessfully deleted {str(deleted)} files from database for your query {keyword}.")
824 |
--------------------------------------------------------------------------------