├── Procfile ├── runtime.txt ├── plugins ├── __init__.py ├── route.py ├── channel.py ├── banned.py ├── files_delete.py ├── broadcast.py ├── inline.py ├── gfilters.py ├── genlink.py ├── connection.py ├── ExtraMods │ └── font.py ├── misc.py ├── index.py ├── filters.py ├── p_ttishow.txt └── commands.py ├── Dockerfile ├── requirements.txt ├── render.yaml ├── start.sh ├── logging.conf ├── app.py ├── app.json ├── README.md ├── database ├── gfilters_mdb.py ├── filters_mdb.py ├── connections_mdb.py ├── users_chats_db.py └── ia_filterdb.py ├── bot.py ├── info.py ├── Script.py └── utils.py /Procfile: -------------------------------------------------------------------------------- 1 | web: python3 bot.py 2 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.10.7 2 | -------------------------------------------------------------------------------- /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 9 | -------------------------------------------------------------------------------- /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("Bot Deployed join us - @kissuxbots on telegram") 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10 2 | RUN apt update && apt upgrade -y 3 | RUN apt install git -y 4 | COPY requirements.txt /requirements.txt 5 | 6 | RUN cd / 7 | RUN pip install -U pip && pip install -U -r requirements.txt 8 | WORKDIR /app 9 | 10 | COPY . . 11 | CMD ["bash", "start.sh"] 12 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # ⚙️ Core Dependencies 2 | pyrofork 3 | tgcrypto 4 | pymongo[srv]==3.12.3 5 | motor==2.5.1 6 | marshmallow==3.14.1 7 | umongo==3.0.1 8 | requests 9 | beautifulsoup4 10 | shortzy 11 | pytz 12 | 13 | # 🌐 Flask App Server 14 | Flask==2.2.2 15 | gunicorn==20.1.0 16 | aiohttp==3.8.1 17 | aiofiles==22.1.0 18 | 19 | # 📦 Telegram & Media Handling 20 | telegraph==2.2.0 21 | Pillow==9.4.0 22 | qrcode 23 | 24 | # 🎥 External Git Repo 25 | git+https://github.com/Joelkb/cinemagoer 26 | -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - type: web 3 | name: tele-filter-bot 4 | env: python 5 | plan: free 6 | buildCommand: "pip install -r requirements.txt" 7 | startCommand: "python3 bot.py" 8 | envVars: 9 | - key: API_ID 10 | sync: false 11 | - key: API_HASH 12 | sync: false 13 | - key: BOT_TOKEN 14 | sync: false 15 | - key: DATABASE_URL 16 | sync: false 17 | - key: LOG_CHANNEL 18 | sync: false 19 | - key: ADMINS 20 | sync: false 21 | 22 | -------------------------------------------------------------------------------- /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 | filters.audio 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", "audio"): 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) 21 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Update & upgrade system 4 | apt update && apt upgrade -y 5 | 6 | apt install git -y 7 | pip install -U pip 8 | 9 | # Clone the repo 10 | if [ -z $UPSTREAM_REPO ] 11 | then 12 | echo "Cloning main Repository" 13 | git clone https://github.com/pyKinsu/Tele-Filter-Bot /Tele-Filter-Bot 14 | else 15 | echo "Cloning Custom Repo from $UPSTREAM_REPO " 16 | git clone $UPSTREAM_REPO /Tele-Filter-Bot 17 | fi 18 | 19 | # Upgrade pip and install requirements 20 | cd /Tele-Filter-Bot 21 | pip install -U -r requirements.txt --force-reinstall 22 | 23 | # Start bot 24 | echo "Starting Bot...." 25 | python3 bot.py 26 | -------------------------------------------------------------------------------- /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=('TelegramBot.log','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 33 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from time import sleep, time 3 | from psutil import boot_time, disk_usage, net_io_counters 4 | from subprocess import check_output 5 | from os import path as ospath 6 | app = Flask(__name__) 7 | botStartTime = time() 8 | if ospath.exists('.git'): 9 | commit_date = check_output(["git log -1 --date=format:'%y/%m/%d %H:%M' --pretty=format:'%cd'"], shell=True).decode() 10 | else: 11 | commit_date = 'No UPSTREAM_REPO' 12 | 13 | @app.route('/status', methods=['GET']) 14 | def status(): 15 | bot_uptime = time() - botStartTime 16 | uptime = time() - boot_time() 17 | sent = net_io_counters().bytes_sent 18 | recv = net_io_counters().bytes_recv 19 | return { 20 | 'commit_date': commit_date, 21 | 'uptime': uptime, 22 | 'on_time': bot_uptime, 23 | 'free_disk': disk_usage('.').free, 24 | 'total_disk': disk_usage('.').total, 25 | 'network': { 26 | 'sent': sent, 27 | 'recv': recv, 28 | }, 29 | } 30 | @app.route('/') 31 | def hello_world(): 32 | return 'TGNVS' 33 | 34 | 35 | if __name__ == "__main__": 36 | app.run() 37 | -------------------------------------------------------------------------------- /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. \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('Support', url=f'https://t.me/kissuhelp') 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 support..\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/files_delete.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 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tele-Filter-Bot", 3 | "description": "A simple telefilter bot created by @pykinsu.", 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://t.me/kissuxbots", 19 | "repository": "https://github.com/pyKinsu/Tele-Filter-Bot/", 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 | "DATABASE_URI": { 50 | "description": "MongoDB URI. Get this value from https://www.mongodb.com. For more help, watch this video - https://youtu.be/dsuTn4qV2GA", 51 | "required": true 52 | }, 53 | "DATABASE_NAME": { 54 | "description": "Name of the database in MongoDB. For more help, watch this video - https://youtu.be/dsuTn4qV2GA", 55 | "value": "AutoFilter", 56 | "required": false 57 | }, 58 | "COLLECTION_NAME": { 59 | "description": "Name of the collections. Defaults to Telegram_files. If you are using the same database, then use a different collection name for each bot.", 60 | "value": "AutoFilter", 61 | "required": false 62 | } 63 | }, 64 | "addons": [], 65 | "buildpacks": [{ 66 | "url": "heroku/python" 67 | }], 68 | "formation": { 69 | "worker": { 70 | "quantity": 1, 71 | "size": "eco" 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Please [Star](https://github.com/pykinsu/tele-filter-bot/) This Repository and [Follow Me](https://github.com/pykinsu/) 2 | 3 | ## check bot [sanya movies bot](https://t.me/sanyamoviesbot/) 4 | 5 | ### Required Variables 6 | * `BOT_TOKEN`: Create a bot using [@BotFather](https://telegram.dog/BotFather), and get the Telegram API token. 7 | * `API_ID`: Get this value from [telegram.org](https://my.telegram.org/apps) 8 | * `API_HASH`: Get this value from [telegram.org](https://my.telegram.org/apps) 9 | * `CHANNELS`: Username or ID of channel or group. Separate multiple IDs by space 10 | * `ADMINS`: Username or ID of Admin. Separate multiple Admins by space 11 | * `DATABASE_URI`: [mongoDB](https://www.mongodb.com) URI. Get this value from [mongoDB](https://www.mongodb.com). For more help watch this [video](https://youtu.be/1G1XwEOnxxo) 12 | * `DATABASE_NAME`: Name of the database in [mongoDB](https://www.mongodb.com). 13 | * `LOG_CHANNEL` : A channel to log the activities of bot. Make sure bot is an admin in the channel. 14 | 15 | * Check [info.py](https://github.com/pykinsu/tele-filter-bot/blob/main/info.py) for more optional variables 16 | 17 | --- 18 | 19 | ## 🎯 Getting Started — Setup Guides 20 | 21 | - 📽️ [How to Create a MongoDB Database](https://youtube.com/shorts/pIHvoXkwmq4) 22 | - 📽️ [How to Create a Telegram Bot with BotFather](https://youtube.com/shorts/HhSIHIbFTF4) 23 | - 📽️ [Get Telegram API ID and Hash](https://youtube.com/shorts/DtaShUUlxrs) 24 | - 📽️ [Deploy Python Telegram Bot on Render](https://youtu.be/kYDTu1UYOzM) 25 | 26 | --- 27 | 28 | ## Deploy On Koyeb 29 | [![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?name=tele-filter-bot&repository=pyKinsu%2FTele-Filter-Bot&branch=main&instance_type=free&instances_min=0&autoscaling_sleep_idle_delay=300&env%5BADMINS%5D=&env%5BAPI_HASH%5D=&env%5BAPI_ID%5D=&env%5BBOT_TOKEN%5D=&env%5BDATABASE_URI%5D=&env%5BLOG_CHANNEL%5D=) 30 | 31 | --- 32 | 33 | ## 🚀 Deploy on Render 34 | 35 | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/pyKinsu/Tele-Filter-Bot) 36 | 37 | > 🛠️ **Note:** Please make sure to **fork** the repository and use your own copy. 38 | 39 | --- 40 | 41 | 42 | ## 🔘 Connect With Me 43 | 44 | [![Telegram Channel](https://img.shields.io/badge/Join-Telegram-blue?style=for-the-badge&logo=telegram)](https://t.me/kissuxbots) 45 | [![Support Group](https://img.shields.io/badge/Support-Group-orange?style=for-the-badge&logo=telegram)](https://t.me/ur_movie_group) 46 | [![GitHub](https://img.shields.io/badge/GitHub-pyKinsu-333?style=for-the-badge&logo=github)](https://github.com/pyKinsu) 47 | 48 | --- 49 | -------------------------------------------------------------------------------- /plugins/broadcast.py: -------------------------------------------------------------------------------- 1 | 2 | from pyrogram import Client, filters 3 | import datetime 4 | import time 5 | from database.users_chats_db import db 6 | from info import ADMINS 7 | from utils import broadcast_messages, broadcast_messages_group 8 | import asyncio 9 | 10 | @Client.on_message(filters.command("broadcast") & filters.user(ADMINS) & filters.reply) 11 | # https://t.me/GetTGLink/4178 12 | async def verupikkals(bot, message): 13 | users = await db.get_all_users() 14 | b_msg = message.reply_to_message 15 | sts = await message.reply_text( 16 | text='Broadcasting your messages...' 17 | ) 18 | start_time = time.time() 19 | total_users = await db.total_users_count() 20 | done = 0 21 | blocked = 0 22 | deleted = 0 23 | failed =0 24 | 25 | success = 0 26 | async for user in users: 27 | pti, sh = await broadcast_messages(int(user['id']), b_msg) 28 | if pti: 29 | success += 1 30 | elif pti == False: 31 | if sh == "Blocked": 32 | blocked+=1 33 | elif sh == "Deleted": 34 | deleted += 1 35 | elif sh == "Error": 36 | failed += 1 37 | done += 1 38 | await asyncio.sleep(2) 39 | if not done % 20: 40 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}") 41 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time)) 42 | 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}") 43 | 44 | @Client.on_message(filters.command("group_broadcast") & filters.user(ADMINS) & filters.reply) 45 | async def broadcast_group(bot, message): 46 | groups = await db.get_all_chats() 47 | b_msg = message.reply_to_message 48 | sts = await message.reply_text( 49 | text='Broadcasting your messages To Groups...' 50 | ) 51 | start_time = time.time() 52 | total_groups = await db.total_chat_count() 53 | done = 0 54 | failed =0 55 | 56 | success = 0 57 | async for group in groups: 58 | pti, sh = await broadcast_messages_group(int(group['id']), b_msg) 59 | if pti: 60 | success += 1 61 | elif sh == "Error": 62 | failed += 1 63 | done += 1 64 | if not done % 20: 65 | await sts.edit(f"Broadcast in progress:\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}") 66 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time)) 67 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Groups {total_groups}\nCompleted: {done} / {total_groups}\nSuccess: {success}") 68 | 69 | -------------------------------------------------------------------------------- /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 | # 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_gfilter(gfilters, name): 32 | mycol = mydb[str(gfilters)] 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_gfilters(gfilters): 51 | mycol = mydb[str(gfilters)] 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_gfilter(message, text, gfilters): 65 | mycol = mydb[str(gfilters)] 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 gfilter anymore.", 73 | quote=True, 74 | parse_mode=enums.ParseMode.MARKDOWN 75 | ) 76 | else: 77 | await message.reply_text("Couldn't find that gfilter!", quote=True) 78 | 79 | async def del_allg(message, gfilters): 80 | if str(gfilters) not in mydb.list_collection_names(): 81 | await message.edit_text("Nothing to Remove !") 82 | return 83 | 84 | mycol = mydb[str(gfilters)] 85 | try: 86 | mycol.drop() 87 | await message.edit_text(f"All gfilters has been removed !") 88 | except: 89 | await message.edit_text("Couldn't remove all gfilters !") 90 | return 91 | 92 | async def count_gfilters(gfilters): 93 | mycol = mydb[str(gfilters)] 94 | 95 | count = mycol.count() 96 | return False if count == 0 else count 97 | 98 | 99 | async def gfilter_stats(): 100 | collections = mydb.list_collection_names() 101 | 102 | if "CONNECTION" in collections: 103 | collections.remove("CONNECTION") 104 | 105 | totalcount = 0 106 | for collection in collections: 107 | mycol = mydb[collection] 108 | count = mycol.count() 109 | totalcount += count 110 | 111 | totalcollections = len(collections) 112 | 113 | return totalcollections, totalcount 114 | -------------------------------------------------------------------------------- /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/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 | 135 | -------------------------------------------------------------------------------- /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 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 | app = web.AppRunner(await web_server()) 57 | await app.setup() 58 | bind_address = "0.0.0.0" 59 | await web.TCPSite(app, bind_address, PORT).start() 60 | 61 | async def stop(self, *args): 62 | await super().stop() 63 | logging.info("Bot stopped. Bye.") 64 | 65 | async def iter_messages( 66 | self, 67 | chat_id: Union[int, str], 68 | limit: int, 69 | offset: int = 0, 70 | ) -> Optional[AsyncGenerator["types.Message", None]]: 71 | """Iterate through a chat sequentially. 72 | This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_messages` in a loop, thus saving 73 | you from the hassle of setting up boilerplate code. It is useful for getting the whole chat messages with a 74 | single call. 75 | Parameters: 76 | chat_id (``int`` | ``str``): 77 | Unique identifier (int) or username (str) of the target chat. 78 | For your personal cloud (Saved Messages) you can simply use "me" or "self". 79 | For a contact that exists in your Telegram address book you can use his phone number (str). 80 | 81 | limit (``int``): 82 | Identifier of the last message to be returned. 83 | 84 | offset (``int``, *optional*): 85 | Identifier of the first message to be returned. 86 | Defaults to 0. 87 | Returns: 88 | ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects. 89 | Example: 90 | .. code-block:: python 91 | for message in app.iter_messages("pyrogram", 1, 15000): 92 | print(message.text) 93 | """ 94 | current = offset 95 | while True: 96 | new_diff = min(200, limit - current) 97 | if new_diff <= 0: 98 | return 99 | messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1))) 100 | for message in messages: 101 | yield message 102 | current += 1 103 | 104 | 105 | app = Bot() 106 | app.run() 107 | -------------------------------------------------------------------------------- /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 | """Show search results for given inline query""" 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='You have to subscribe my channel to use the bot', 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} Results - {total}" 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} No results' 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('Search again', switch_inline_query_current_chat=query) 111 | ] 112 | ] 113 | return InlineKeyboardMarkup(buttons) 114 | 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 | ) 141 | -------------------------------------------------------------------------------- /database/users_chats_db.py: -------------------------------------------------------------------------------- 1 | # https://github.com/odysseusmax/animated-lamp/blob/master/bot/database/database.py 2 | import motor.motor_asyncio 3 | 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, MAX_BTN, AUTO_FFILTER, SHORTLINK_API, SHORTLINK_URL, IS_SHORTLINK, TUTORIAL, IS_TUTORIAL 4 | 5 | class Database: 6 | 7 | def __init__(self, uri, database_name): 8 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri) 9 | self.db = self._client[database_name] 10 | self.col = self.db.users 11 | self.grp = self.db.groups 12 | 13 | 14 | def new_user(self, id, name): 15 | return dict( 16 | id = id, 17 | name = name, 18 | ban_status=dict( 19 | is_banned=False, 20 | ban_reason="", 21 | ), 22 | ) 23 | 24 | 25 | def new_group(self, id, title): 26 | return dict( 27 | id = id, 28 | title = title, 29 | chat_status=dict( 30 | is_disabled=False, 31 | reason="", 32 | ), 33 | ) 34 | 35 | async def add_user(self, id, name): 36 | user = self.new_user(id, name) 37 | await self.col.insert_one(user) 38 | 39 | async def is_user_exist(self, id): 40 | user = await self.col.find_one({'id':int(id)}) 41 | return bool(user) 42 | 43 | async def total_users_count(self): 44 | count = await self.col.count_documents({}) 45 | return count 46 | 47 | async def remove_ban(self, id): 48 | ban_status = dict( 49 | is_banned=False, 50 | ban_reason='' 51 | ) 52 | await self.col.update_one({'id': id}, {'$set': {'ban_status': ban_status}}) 53 | 54 | async def ban_user(self, user_id, ban_reason="No Reason"): 55 | ban_status = dict( 56 | is_banned=True, 57 | ban_reason=ban_reason 58 | ) 59 | await self.col.update_one({'id': user_id}, {'$set': {'ban_status': ban_status}}) 60 | 61 | async def get_ban_status(self, id): 62 | default = dict( 63 | is_banned=False, 64 | ban_reason='' 65 | ) 66 | user = await self.col.find_one({'id':int(id)}) 67 | if not user: 68 | return default 69 | return user.get('ban_status', default) 70 | 71 | async def get_all_users(self): 72 | return self.col.find({}) 73 | 74 | 75 | async def delete_user(self, user_id): 76 | await self.col.delete_many({'id': int(user_id)}) 77 | 78 | 79 | async def get_banned(self): 80 | users = self.col.find({'ban_status.is_banned': True}) 81 | chats = self.grp.find({'chat_status.is_disabled': True}) 82 | b_chats = [chat['id'] async for chat in chats] 83 | b_users = [user['id'] async for user in users] 84 | return b_users, b_chats 85 | 86 | 87 | 88 | async def add_chat(self, chat, title): 89 | chat = self.new_group(chat, title) 90 | await self.grp.insert_one(chat) 91 | 92 | 93 | async def get_chat(self, chat): 94 | chat = await self.grp.find_one({'id':int(chat)}) 95 | return False if not chat else chat.get('chat_status') 96 | 97 | 98 | async def re_enable_chat(self, id): 99 | chat_status=dict( 100 | is_disabled=False, 101 | reason="", 102 | ) 103 | await self.grp.update_one({'id': int(id)}, {'$set': {'chat_status': chat_status}}) 104 | 105 | async def update_settings(self, id, settings): 106 | await self.grp.update_one({'id': int(id)}, {'$set': {'settings': settings}}) 107 | 108 | 109 | async def get_settings(self, id): 110 | default = { 111 | 'button': SINGLE_BUTTON, 112 | 'botpm': P_TTI_SHOW_OFF, 113 | 'file_secure': PROTECT_CONTENT, 114 | 'imdb': IMDB, 115 | 'spell_check': SPELL_CHECK_REPLY, 116 | 'welcome': MELCOW_NEW_USERS, 117 | 'auto_delete': AUTO_DELETE, 118 | 'auto_ffilter': AUTO_FFILTER, 119 | 'max_btn': MAX_BTN, 120 | 'template': IMDB_TEMPLATE, 121 | 'shortlink': SHORTLINK_URL, 122 | 'shortlink_api': SHORTLINK_API, 123 | 'is_shortlink': IS_SHORTLINK, 124 | 'tutorial': TUTORIAL, 125 | 'is_tutorial': IS_TUTORIAL 126 | } 127 | chat = await self.grp.find_one({'id':int(id)}) 128 | if chat: 129 | return chat.get('settings', default) 130 | return default 131 | 132 | 133 | async def disable_chat(self, chat, reason="No Reason"): 134 | chat_status=dict( 135 | is_disabled=True, 136 | reason=reason, 137 | ) 138 | await self.grp.update_one({'id': int(chat)}, {'$set': {'chat_status': chat_status}}) 139 | 140 | 141 | async def total_chat_count(self): 142 | count = await self.grp.count_documents({}) 143 | return count 144 | 145 | 146 | async def get_all_chats(self): 147 | return self.grp.find({}) 148 | 149 | 150 | async def get_db_size(self): 151 | return (await self.db.command("dbstats"))['dataSize'] 152 | 153 | 154 | db = Database(DATABASE_URI, DATABASE_NAME) 155 | -------------------------------------------------------------------------------- /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/TeamEvamaria/10 https://t.me/TeamEvamaria/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/TeamEvamaria/10 https://t.me/TeamEvamaria/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 | -------------------------------------------------------------------------------- /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 | import logging 6 | 7 | logger = logging.getLogger(__name__) 8 | logger.setLevel(logging.ERROR) 9 | 10 | 11 | @Client.on_message((filters.private | filters.group) & filters.command('connect')) 12 | async def addconnection(client, message): 13 | userid = message.from_user.id if message.from_user else None 14 | if not userid: 15 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM") 16 | chat_type = message.chat.type 17 | 18 | if chat_type == enums.ChatType.PRIVATE: 19 | try: 20 | cmd, group_id = message.text.split(" ", 1) 21 | except: 22 | await message.reply_text( 23 | "Enter in correct format!\n\n" 24 | "/connect groupid\n\n" 25 | "Get your Group id by adding this bot to your group and use /id", 26 | quote=True 27 | ) 28 | return 29 | 30 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 31 | group_id = message.chat.id 32 | 33 | try: 34 | st = await client.get_chat_member(group_id, userid) 35 | if ( 36 | st.status != enums.ChatMemberStatus.ADMINISTRATOR 37 | and st.status != enums.ChatMemberStatus.OWNER 38 | and userid not in ADMINS 39 | ): 40 | await message.reply_text("You should be an admin in Given group!", quote=True) 41 | return 42 | except Exception as e: 43 | logger.exception(e) 44 | await message.reply_text( 45 | "Invalid Group ID!\n\nIf correct, Make sure I'm present in your group!!", 46 | quote=True, 47 | ) 48 | 49 | return 50 | try: 51 | st = await client.get_chat_member(group_id, "me") 52 | if st.status == enums.ChatMemberStatus.ADMINISTRATOR: 53 | ttl = await client.get_chat(group_id) 54 | title = ttl.title 55 | 56 | addcon = await add_connection(str(group_id), str(userid)) 57 | if addcon: 58 | await message.reply_text( 59 | f"Successfully connected to **{title}**\nNow manage your group from my pm !", 60 | quote=True, 61 | parse_mode=enums.ParseMode.MARKDOWN 62 | ) 63 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 64 | await client.send_message( 65 | userid, 66 | f"Connected to **{title}** !", 67 | parse_mode=enums.ParseMode.MARKDOWN 68 | ) 69 | else: 70 | await message.reply_text( 71 | "You're already connected to this chat!", 72 | quote=True 73 | ) 74 | else: 75 | await message.reply_text("Add me as an admin in group", quote=True) 76 | except Exception as e: 77 | logger.exception(e) 78 | await message.reply_text('Some error occurred! Try again later.', quote=True) 79 | return 80 | 81 | 82 | @Client.on_message((filters.private | filters.group) & filters.command('disconnect')) 83 | async def deleteconnection(client, message): 84 | userid = message.from_user.id if message.from_user else None 85 | if not userid: 86 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM") 87 | chat_type = message.chat.type 88 | 89 | if chat_type == enums.ChatType.PRIVATE: 90 | await message.reply_text("Run /connections to view or disconnect from groups!", quote=True) 91 | 92 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 93 | group_id = message.chat.id 94 | 95 | st = await client.get_chat_member(group_id, userid) 96 | if ( 97 | st.status != enums.ChatMemberStatus.ADMINISTRATOR 98 | and st.status != enums.ChatMemberStatus.OWNER 99 | and str(userid) not in ADMINS 100 | ): 101 | return 102 | 103 | delcon = await delete_connection(str(userid), str(group_id)) 104 | if delcon: 105 | await message.reply_text("Successfully disconnected from this chat", quote=True) 106 | else: 107 | await message.reply_text("This chat isn't connected to me!\nDo /connect to connect.", quote=True) 108 | 109 | 110 | @Client.on_message(filters.private & filters.command(["connections"])) 111 | async def connections(client, message): 112 | userid = message.from_user.id 113 | 114 | groupids = await all_connections(str(userid)) 115 | if groupids is None: 116 | await message.reply_text( 117 | "There are no active connections!! Connect to some groups first.", 118 | quote=True 119 | ) 120 | return 121 | buttons = [] 122 | for groupid in groupids: 123 | try: 124 | ttl = await client.get_chat(int(groupid)) 125 | title = ttl.title 126 | active = await if_active(str(userid), str(groupid)) 127 | act = " - ACTIVE" if active else "" 128 | buttons.append( 129 | [ 130 | InlineKeyboardButton( 131 | text=f"{title}{act}", callback_data=f"groupcb:{groupid}:{act}" 132 | ) 133 | ] 134 | ) 135 | except: 136 | pass 137 | if buttons: 138 | await message.reply_text( 139 | "Your connected group details ;\n\n", 140 | reply_markup=InlineKeyboardMarkup(buttons), 141 | quote=True 142 | ) 143 | else: 144 | await message.reply_text( 145 | "There are no active connections!! Connect to some groups first.", 146 | quote=True 147 | ) 148 | -------------------------------------------------------------------------------- /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_name", "NO_FILE")} is already saved in database' 61 | ) 62 | 63 | return False, 0 64 | else: 65 | logger.info(f'{getattr(media, "file_name", "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 | "➲ First Name: {first}\n➲ Last Name: {last}\n➲ Username: {username}\n➲ Telegram ID: {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 | # https://github.com/SpEcHiDe/PyroGramBot/blob/master/pyrobot/plugins/admemes/whois.py#L19 60 | status_message = await message.reply_text( 61 | "`Fetching user info...`" 62 | ) 63 | await status_message.edit( 64 | "`Processing user info...`" 65 | ) 66 | from_user = None 67 | from_user_id, _ = extract_user(message) 68 | try: 69 | from_user = await client.get_users(from_user_id) 70 | except Exception as error: 71 | await status_message.edit(str(error)) 72 | return 73 | if from_user is None: 74 | return await status_message.edit("no valid user_id / message specified") 75 | message_out_str = "" 76 | message_out_str += f"➲First Name: {from_user.first_name}\n" 77 | last_name = from_user.last_name or "None" 78 | message_out_str += f"➲Last Name: {last_name}\n" 79 | message_out_str += f"➲Telegram ID: {from_user.id}\n" 80 | username = from_user.username or "None" 81 | dc_id = from_user.dc_id or "[User Doesn't Have A Valid DP]" 82 | message_out_str += f"➲Data Centre: {dc_id}\n" 83 | message_out_str += f"➲User Name: @{username}\n" 84 | message_out_str += f"➲User 𝖫𝗂𝗇𝗄: Click Here\n" 85 | if message.chat.type in ((enums.ChatType.SUPERGROUP, enums.ChatType.CHANNEL)): 86 | try: 87 | chat_member_p = await message.chat.get_member(from_user.id) 88 | joined_date = ( 89 | chat_member_p.joined_date or datetime.now() 90 | ).strftime("%Y.%m.%d %H:%M:%S") 91 | message_out_str += ( 92 | "➲Joined this Chat on: " 93 | f"{joined_date}" 94 | "\n" 95 | ) 96 | except UserNotParticipant: 97 | pass 98 | chat_photo = from_user.photo 99 | if chat_photo: 100 | local_user_photo = await client.download_media( 101 | message=chat_photo.big_file_id 102 | ) 103 | buttons = [[ 104 | InlineKeyboardButton('🔐 Close', callback_data='close_data') 105 | ]] 106 | reply_markup = InlineKeyboardMarkup(buttons) 107 | await message.reply_photo( 108 | photo=local_user_photo, 109 | quote=True, 110 | reply_markup=reply_markup, 111 | caption=message_out_str, 112 | parse_mode=enums.ParseMode.HTML, 113 | disable_notification=True 114 | ) 115 | os.remove(local_user_photo) 116 | else: 117 | buttons = [[ 118 | InlineKeyboardButton('🔐 Close', callback_data='close_data') 119 | ]] 120 | reply_markup = InlineKeyboardMarkup(buttons) 121 | await message.reply_text( 122 | text=message_out_str, 123 | reply_markup=reply_markup, 124 | quote=True, 125 | parse_mode=enums.ParseMode.HTML, 126 | disable_notification=True 127 | ) 128 | await status_message.delete() 129 | 130 | @Client.on_message(filters.command(["imdb", 'search'])) 131 | async def imdb_search(client, message): 132 | if ' ' in message.text: 133 | k = await message.reply('Searching ImDB') 134 | r, title = message.text.split(None, 1) 135 | movies = await get_poster(title, bulk=True) 136 | if not movies: 137 | return await message.reply("No results Found") 138 | btn = [ 139 | [ 140 | InlineKeyboardButton( 141 | text=f"{movie.get('title')} - {movie.get('year')}", 142 | callback_data=f"imdb#{movie.movieID}", 143 | ) 144 | ] 145 | for movie in movies 146 | ] 147 | await k.edit('Here is what i found on IMDb', reply_markup=InlineKeyboardMarkup(btn)) 148 | else: 149 | await message.reply('Give me a movie / series Name') 150 | 151 | @Client.on_callback_query(filters.regex('^imdb')) 152 | async def imdb_callback(bot: Client, quer_y: CallbackQuery): 153 | i, movie = quer_y.data.split('#') 154 | imdb = await get_poster(query=movie, id=True) 155 | btn = [ 156 | [ 157 | InlineKeyboardButton( 158 | text=f"{imdb.get('title')}", 159 | url=imdb['url'], 160 | ) 161 | ] 162 | ] 163 | message = quer_y.message.reply_to_message or quer_y.message 164 | if imdb: 165 | caption = IMDB_TEMPLATE.format( 166 | query = imdb['title'], 167 | title = imdb['title'], 168 | votes = imdb['votes'], 169 | aka = imdb["aka"], 170 | seasons = imdb["seasons"], 171 | box_office = imdb['box_office'], 172 | localized_title = imdb['localized_title'], 173 | kind = imdb['kind'], 174 | imdb_id = imdb["imdb_id"], 175 | cast = imdb["cast"], 176 | runtime = imdb["runtime"], 177 | countries = imdb["countries"], 178 | certificates = imdb["certificates"], 179 | languages = imdb["languages"], 180 | director = imdb["director"], 181 | writer = imdb["writer"], 182 | producer = imdb["producer"], 183 | composer = imdb["composer"], 184 | cinematographer = imdb["cinematographer"], 185 | music_team = imdb["music_team"], 186 | distributors = imdb["distributors"], 187 | release_date = imdb['release_date'], 188 | year = imdb['year'], 189 | genres = imdb['genres'], 190 | poster = imdb['poster'], 191 | plot = imdb['plot'], 192 | rating = imdb['rating'], 193 | url = imdb['url'], 194 | **locals() 195 | ) 196 | else: 197 | caption = "No Results" 198 | if imdb.get('poster'): 199 | try: 200 | await quer_y.message.reply_photo(photo=imdb['poster'], caption=caption, reply_markup=InlineKeyboardMarkup(btn)) 201 | except (MediaEmpty, PhotoInvalidDimensions, WebpageMediaEmpty): 202 | pic = imdb.get('poster') 203 | poster = pic.replace('.jpg', "._V1_UX360.jpg") 204 | await quer_y.message.reply_photo(photo=poster, caption=caption, reply_markup=InlineKeyboardMarkup(btn)) 205 | except Exception as e: 206 | logger.exception(e) 207 | await quer_y.message.reply(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False) 208 | await quer_y.message.delete() 209 | else: 210 | await quer_y.message.edit(caption, reply_markup=InlineKeyboardMarkup(btn), disable_web_page_preview=False) 211 | await quer_y.answer() 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /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('Yᴇs ✓', 88 | callback_data=f'index#accept#{chat_id}#{last_msg_id}#{message.from_user.id}') 89 | ], 90 | [ 91 | InlineKeyboardButton('Cʟᴏsᴇ ', 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 msg.edit_text( 157 | 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}", 158 | reply_markup=reply) 159 | if message.empty: 160 | deleted += 1 161 | continue 162 | elif not message.media: 163 | no_media += 1 164 | continue 165 | elif message.media not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]: 166 | unsupported += 1 167 | continue 168 | media = getattr(message, message.media.value, None) 169 | if not media: 170 | unsupported += 1 171 | continue 172 | media.file_type = message.media.value 173 | media.caption = message.caption 174 | aynav, vnay = await save_file(media) 175 | if aynav: 176 | total_files += 1 177 | elif vnay == 0: 178 | duplicate += 1 179 | elif vnay == 2: 180 | errors += 1 181 | except Exception as e: 182 | logger.exception(e) 183 | await msg.edit(f'Error: {e}') 184 | else: 185 | 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}') 186 | -------------------------------------------------------------------------------- /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', 'add']) & 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 | 203 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 204 | grp_id = message.chat.id 205 | title = message.chat.title 206 | 207 | else: 208 | return 209 | 210 | st = await client.get_chat_member(grp_id, userid) 211 | if ( 212 | st.status != enums.ChatMemberStatus.ADMINISTRATOR 213 | and st.status != enums.ChatMemberStatus.OWNER 214 | and str(userid) not in ADMINS 215 | ): 216 | return 217 | 218 | try: 219 | cmd, text = message.text.split(" ", 1) 220 | except: 221 | await message.reply_text( 222 | "Mention the filtername which you wanna delete!\n\n" 223 | "/del filtername\n\n" 224 | "Use /viewfilters to view all available filters", 225 | quote=True 226 | ) 227 | return 228 | 229 | query = text.lower() 230 | 231 | await delete_filter(message, query, grp_id) 232 | 233 | 234 | @Client.on_message(filters.command('delall') & filters.incoming) 235 | async def delallconfirm(client, message): 236 | userid = message.from_user.id if message.from_user else None 237 | if not userid: 238 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM") 239 | chat_type = message.chat.type 240 | 241 | if chat_type == enums.ChatType.PRIVATE: 242 | grpid = await active_connection(str(userid)) 243 | if grpid is not None: 244 | grp_id = grpid 245 | try: 246 | chat = await client.get_chat(grpid) 247 | title = chat.title 248 | except: 249 | await message.reply_text("Make sure I'm present in your group!!", quote=True) 250 | return 251 | else: 252 | await message.reply_text("I'm not connected to any groups!", quote=True) 253 | return 254 | 255 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 256 | grp_id = message.chat.id 257 | title = message.chat.title 258 | 259 | else: 260 | return 261 | 262 | st = await client.get_chat_member(grp_id, userid) 263 | if (st.status == enums.ChatMemberStatus.OWNER) or (str(userid) in ADMINS): 264 | await message.reply_text( 265 | f"This will delete all filters from '{title}'.\nDo you want to continue??", 266 | reply_markup=InlineKeyboardMarkup([ 267 | [InlineKeyboardButton(text="YES",callback_data="delallconfirm")], 268 | [InlineKeyboardButton(text="CANCEL",callback_data="delallcancel")] 269 | ]), 270 | quote=True 271 | ) 272 | 273 | -------------------------------------------------------------------------------- /plugins/p_ttishow.txt: -------------------------------------------------------------------------------- 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, SPRT_CHNL, SUPPORT_CHAT, MELCOW_NEW_USERS, MELCOW_VID, CHNL_LNK, GRP_LNK 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 | """-----------------------------------------https://t.me/GetTGLink/4179 --------------------------------------""" 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 | # Inspired from a boat of a banana tree 25 | buttons = [[ 26 | InlineKeyboardButton('Support', url=f'https://t.me/{SUPPORT_CHAT}') 27 | ]] 28 | reply_markup=InlineKeyboardMarkup(buttons) 29 | k = await message.reply( 30 | text='CHAT NOT ALLOWED 🐞\n\nMy admins has restricted me from working here ! If you want to know more about it contact support..', 31 | reply_markup=reply_markup, 32 | ) 33 | 34 | try: 35 | await k.pin() 36 | except: 37 | pass 38 | await bot.leave_chat(message.chat.id) 39 | return 40 | buttons = [[ 41 | InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ', url=GRP_LNK), 42 | InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK) 43 | ],[ 44 | InlineKeyboardButton("Bᴏᴛ Oᴡɴᴇʀ", url="t.me/UNKNOWN_MAN_ON_MISSION") 45 | ]] 46 | reply_markup=InlineKeyboardMarkup(buttons) 47 | await message.reply_text( 48 | text=f"Thankyou For Adding Me In {message.chat.title} ❣️\n\nIf you have any questions & doubts about using me contact support.", 49 | reply_markup=reply_markup) 50 | else: 51 | settings = await get_settings(message.chat.id) 52 | if settings["welcome"]: 53 | for u in message.new_chat_members: 54 | if (temp.MELCOW).get('welcome') is not None: 55 | try: 56 | await (temp.MELCOW['welcome']).delete() 57 | except: 58 | pass 59 | temp.MELCOW['welcome'] = await message.reply_video( 60 | video=(MELCOW_VID), 61 | caption=(script.MELCOW_ENG.format(u.mention, message.chat.title)), 62 | reply_markup=InlineKeyboardMarkup( 63 | [[ 64 | InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=GRP_LNK), 65 | InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url=CHNL_LNK) 66 | ],[ 67 | InlineKeyboardButton("Bᴏᴛ Oᴡɴᴇʀ", url="t.me/UNKNOWN_MAN_ON_MISSION") 68 | ]] 69 | ), 70 | parse_mode=enums.ParseMode.HTML 71 | ) 72 | 73 | if settings["auto_delete"]: 74 | await asyncio.sleep(600) 75 | await (temp.MELCOW['welcome']).delete() 76 | 77 | 78 | 79 | 80 | 81 | @Client.on_message(filters.command('leave') & filters.user(ADMINS)) 82 | async def leave_a_chat(bot, message): 83 | if len(message.command) == 1: 84 | return await message.reply('Give me a chat id') 85 | chat = message.command[1] 86 | try: 87 | chat = int(chat) 88 | except: 89 | chat = chat 90 | try: 91 | buttons = [[ 92 | InlineKeyboardButton('Support ', url=SPRT_CHNL), 93 | InlineKeyboardButton('Owner', url="t.me/UNKNOWN_MAN_ON_MISSION") 94 | ],[ 95 | InlineKeyboardButton('Use Me Here', url=f'https://t.me/{SUPPORT_CHAT}') 96 | ]] 97 | reply_markup=InlineKeyboardMarkup(buttons) 98 | await bot.send_message( 99 | chat_id=chat, 100 | text='Hello Friends, \nMy admin has told me to leave from group, so i go! If you wanna add me again contact my Support Group or My Owner', 101 | reply_markup=reply_markup, 102 | ) 103 | 104 | await bot.leave_chat(chat) 105 | await message.reply(f"left the chat `{chat}`") 106 | except Exception as e: 107 | await message.reply(f'Error - {e}') 108 | 109 | @Client.on_message(filters.command('disable') & filters.user(ADMINS)) 110 | async def disable_chat(bot, message): 111 | if len(message.command) == 1: 112 | return await message.reply('Give me a chat id') 113 | r = message.text.split(None) 114 | if len(r) > 2: 115 | reason = message.text.split(None, 2)[2] 116 | chat = message.text.split(None, 2)[1] 117 | else: 118 | chat = message.command[1] 119 | reason = "No reason Provided" 120 | try: 121 | chat_ = int(chat) 122 | except: 123 | return await message.reply('Give Me A Valid Chat ID') 124 | cha_t = await db.get_chat(int(chat_)) 125 | if not cha_t: 126 | return await message.reply("Chat Not Found In DB") 127 | if cha_t['is_disabled']: 128 | return await message.reply(f"This chat is already disabled:\nReason- {cha_t['reason']} ") 129 | await db.disable_chat(int(chat_), reason) 130 | temp.BANNED_CHATS.append(int(chat_)) 131 | await message.reply('Chat Successfully Disabled') 132 | try: 133 | buttons = [[ 134 | InlineKeyboardButton('Support', url=f'https://t.me/{SUPPORT_CHAT}') 135 | ]] 136 | reply_markup=InlineKeyboardMarkup(buttons) 137 | await bot.send_message( 138 | chat_id=chat_, 139 | text=f'Hello Friends, \nMy admin has told me to leave from group so i go! If you wanna add me again contact my support group. \nReason : {reason}', 140 | reply_markup=reply_markup) 141 | await bot.leave_chat(chat_) 142 | except Exception as e: 143 | await message.reply(f"Error - {e}") 144 | 145 | 146 | @Client.on_message(filters.command('enable') & filters.user(ADMINS)) 147 | async def re_enable_chat(bot, message): 148 | if len(message.command) == 1: 149 | return await message.reply('Give me a chat id') 150 | chat = message.command[1] 151 | try: 152 | chat_ = int(chat) 153 | except: 154 | return await message.reply('Give Me A Valid Chat ID') 155 | sts = await db.get_chat(int(chat)) 156 | if not sts: 157 | return await message.reply("Chat Not Found In DB !") 158 | if not sts.get('is_disabled'): 159 | return await message.reply('This chat is not yet disabled.') 160 | await db.re_enable_chat(int(chat_)) 161 | temp.BANNED_CHATS.remove(int(chat_)) 162 | await message.reply("Chat Successfully re-enabled") 163 | 164 | 165 | @Client.on_message(filters.command('stats') & filters.incoming) 166 | async def get_ststs(bot, message): 167 | rju = await message.reply('Fetching stats..') 168 | total_users = await db.total_users_count() 169 | totl_chats = await db.total_chat_count() 170 | files = await Media.count_documents() 171 | size = await db.get_db_size() 172 | free = 536870912 - size 173 | size = get_size(size) 174 | free = get_size(free) 175 | await rju.edit(script.STATUS_TXT.format(files, total_users, totl_chats, size, free)) 176 | 177 | 178 | @Client.on_message(filters.command('invite') & filters.user(ADMINS)) 179 | async def gen_invite(bot, message): 180 | if len(message.command) == 1: 181 | return await message.reply('Give me a chat id') 182 | chat = message.command[1] 183 | try: 184 | chat = int(chat) 185 | except: 186 | return await message.reply('Give Me A Valid Chat ID') 187 | try: 188 | link = await bot.create_chat_invite_link(chat) 189 | except ChatAdminRequired: 190 | return await message.reply("Invite Link Generation Failed, Iam Not Having Sufficient Rights") 191 | except Exception as e: 192 | return await message.reply(f'Error {e}') 193 | await message.reply(f'Here is your Invite Link {link.invite_link}') 194 | 195 | @Client.on_message(filters.command('ban') & filters.user(ADMINS)) 196 | async def ban_a_user(bot, message): 197 | # https://t.me/GetTGLink/4185 198 | if len(message.command) == 1: 199 | return await message.reply('Give me a user id / username') 200 | r = message.text.split(None) 201 | if len(r) > 2: 202 | reason = message.text.split(None, 2)[2] 203 | chat = message.text.split(None, 2)[1] 204 | else: 205 | chat = message.command[1] 206 | reason = "No reason Provided" 207 | try: 208 | chat = int(chat) 209 | except: 210 | pass 211 | try: 212 | k = await bot.get_users(chat) 213 | except PeerIdInvalid: 214 | return await message.reply("This is an invalid user, make sure ia have met him before.") 215 | except IndexError: 216 | return await message.reply("This might be a channel, make sure its a user.") 217 | except Exception as e: 218 | return await message.reply(f'Error - {e}') 219 | else: 220 | jar = await db.get_ban_status(k.id) 221 | if jar['is_banned']: 222 | return await message.reply(f"{k.mention} is already banned\nReason: {jar['ban_reason']}") 223 | await db.ban_user(k.id, reason) 224 | temp.BANNED_USERS.append(k.id) 225 | await message.reply(f"Successfully banned {k.mention}") 226 | 227 | 228 | 229 | @Client.on_message(filters.command('unban') & filters.user(ADMINS)) 230 | async def unban_a_user(bot, message): 231 | if len(message.command) == 1: 232 | return await message.reply('Give me a user id / username') 233 | r = message.text.split(None) 234 | if len(r) > 2: 235 | reason = message.text.split(None, 2)[2] 236 | chat = message.text.split(None, 2)[1] 237 | else: 238 | chat = message.command[1] 239 | reason = "No reason Provided" 240 | try: 241 | chat = int(chat) 242 | except: 243 | pass 244 | try: 245 | k = await bot.get_users(chat) 246 | except PeerIdInvalid: 247 | return await message.reply("This is an invalid user, make sure ia have met him before.") 248 | except IndexError: 249 | return await message.reply("Thismight be a channel, make sure its a user.") 250 | except Exception as e: 251 | return await message.reply(f'Error - {e}') 252 | else: 253 | jar = await db.get_ban_status(k.id) 254 | if not jar['is_banned']: 255 | return await message.reply(f"{k.mention} is not yet banned.") 256 | await db.remove_ban(k.id) 257 | temp.BANNED_USERS.remove(k.id) 258 | await message.reply(f"Successfully unbanned {k.mention}") 259 | 260 | 261 | 262 | @Client.on_message(filters.command('users') & filters.user(ADMINS)) 263 | async def list_users(bot, message): 264 | # https://t.me/GetTGLink/4184 265 | raju = await message.reply('Getting List Of Users') 266 | users = await db.get_all_users() 267 | out = "Users Saved In DB Are:\n\n" 268 | async for user in users: 269 | out += f"{user['name']}" 270 | if user['ban_status']['is_banned']: 271 | out += '( Banned User )' 272 | out += '\n' 273 | try: 274 | await raju.edit_text(out) 275 | except MessageTooLong: 276 | with open('users.txt', 'w+') as outfile: 277 | outfile.write(out) 278 | await message.reply_document('users.txt', caption="List Of Users") 279 | 280 | @Client.on_message(filters.command('chats') & filters.user(ADMINS)) 281 | async def list_chats(bot, message): 282 | raju = await message.reply('Getting List Of chats') 283 | chats = await db.get_all_chats() 284 | out = "Chats Saved In DB Are:\n\n" 285 | async for chat in chats: 286 | out += f"**Title:** `{chat['title']}`\n**- ID:** `{chat['id']}`" 287 | if chat['chat_status']['is_disabled']: 288 | out += '( Disabled Chat )' 289 | out += '\n' 290 | try: 291 | await raju.edit_text(out) 292 | except MessageTooLong: 293 | with open('chats.txt', 'w+') as outfile: 294 | outfile.write(out) 295 | await message.reply_document('chats.txt', caption="List Of Chats") 296 | -------------------------------------------------------------------------------- /Script.py: -------------------------------------------------------------------------------- 1 | class script(object): 2 | 3 | START_TXT = """ 4 | Hello {},
5 | Mʏ ɴᴀᴍᴇ ɪs {}. I ᴄᴀɴ ᴘʀᴏᴠɪᴅᴇ ᴍᴏᴠɪᴇs – ᴊᴜsᴛ ᴀᴅᴅ ᴍᴇ ᴛᴏ ʏᴏᴜʀ ɢʀᴏᴜᴘ ᴀs ᴀɴ ᴀᴅᴍɪɴ ᴀɴᴅ ᴇɴᴊᴏʏ! 😍
6 |
Mᴀɪɴᴛᴀɪɴᴇᴅ ʙʏ @kissuxbots
7 |
""" 8 | 9 | HELP_TXT = """Hᴇʏ {} 10 | Hᴇʀᴇ Is Tʜᴇ Hᴇʟᴘ Fᴏʀ Mʏ Cᴏᴍᴍᴀɴᴅs.""" 11 | 12 | ABOUT_TXT = """• Mʏ Nᴀᴍᴇ: {} 13 | • Oᴡɴᴇʀ : 𓆩•𝐊𝐢𝐬𝐬𝐮 💞•𓆪 14 | • Lɪʙʀᴀʀʏ: Pʏʀᴏɢʀᴀᴍ 15 | • Lᴀɴɢᴜᴀɢᴇ: Pʏᴛʜᴏɴ 3 16 | • DᴀᴛᴀBᴀsᴇ: MᴏɴɢᴏDB""" 17 | 18 | 19 | MANUELFILTER_TXT = """ʜᴇʟᴘ: ꜰɪʟᴛᴇʀꜱ 20 | - ꜰɪʟᴛᴇʀ ɪꜱ ᴀ ꜰᴇᴀᴛᴜʀᴇ ᴡᴇʀᴇ ᴜꜱᴇʀꜱ ᴄᴀɴ ꜱᴇᴛ ᴀᴜᴛᴏᴍᴀᴛᴇᴅ ʀᴇᴘʟɪᴇꜱ ꜰᴏʀ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴋᴇʏᴡᴏʀᴅ ᴀɴᴅ ɪ ᴡɪʟʟ ʀᴇꜱᴘᴏɴᴅ ᴡʜᴇɴᴇᴠᴇʀ ᴀ ᴋᴇʏᴡᴏʀᴅ ɪꜱ ꜰᴏᴜɴᴅ ɪɴ ᴛʜᴇ ᴍᴇꜱꜱᴀɢᴇ 21 | ɴᴏᴛᴇ: 22 | 1. ᴛʜɪꜱ ʙᴏᴛ ꜱʜᴏᴜʟᴅ ʜᴀᴠᴇ ᴀᴅᴍɪɴ ᴘʀɪᴠɪʟᴇɢᴇ. 23 | 2. ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴀᴅᴅ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴀ ᴄʜᴀᴛ. 24 | 3. ᴀʟᴇʀᴛ ʙᴜᴛᴛᴏɴꜱ ʜᴀᴠᴇ ᴀ ʟɪᴍɪᴛ ᴏꜰ 64 ᴄʜᴀʀᴀᴄᴛᴇʀꜱ. 25 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ: 26 | • /filter - ᴀᴅᴅ ᴀ ꜰɪʟᴛᴇʀ ɪɴ ᴀ ᴄʜᴀᴛ 27 | • /filters - ʟɪꜱᴛ ᴀʟʟ ᴛʜᴇ ꜰɪʟᴛᴇʀꜱ ᴏꜰ ᴀ ᴄʜᴀᴛ 28 | • /del - ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴛᴇʀ ɪɴ ᴀ ᴄʜᴀᴛ 29 | • /delall - ᴅᴇʟᴇᴛᴇ ᴛʜᴇ ᴡʜᴏʟᴇ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴀ ᴄʜᴀᴛ (ᴄʜᴀᴛ ᴏᴡɴᴇʀ ᴏɴʟʏ)""" 30 | 31 | BUTTON_TXT = """ʜᴇʟᴘ: ʙᴜᴛᴛᴏɴꜱ 32 | - ᴛʜɪꜱ ʙᴏᴛ ꜱᴜᴘᴘᴏʀᴛꜱ ʙᴏᴛʜ ᴜʀʟ ᴀɴᴅ ᴀʟᴇʀᴛ ɪɴʟɪɴᴇ ʙᴜᴛᴛᴏɴꜱ. 33 | ɴᴏᴛᴇ: 34 | 1. ᴛᴇʟᴇɢʀᴀᴍ ᴡɪʟʟ ɴᴏᴛ ᴀʟʟᴏᴡꜱ ʏᴏᴜ ᴛᴏ ꜱᴇɴᴅ ʙᴜᴛᴛᴏɴꜱ ᴡɪᴛʜᴏᴜᴛ ᴀɴʏ ᴄᴏɴᴛᴇɴᴛ, ꜱᴏ ᴄᴏɴᴛᴇɴᴛ ɪꜱ ᴍᴀɴᴅᴀᴛᴏʀʏ. 35 | 2. ᴛʜɪꜱ ʙᴏᴛ ꜱᴜᴘᴘᴏʀᴛꜱ ʙᴜᴛᴛᴏɴꜱ ᴡɪᴛʜ ᴀɴʏ ᴛᴇʟᴇɢʀᴀᴍ ᴍᴇᴅɪᴀ ᴛʏᴘᴇ. 36 | 3. ʙᴜᴛᴛᴏɴꜱ ꜱʜᴏᴜʟᴅ ʙᴇ ᴘʀᴏᴘᴇʀʟʏ ᴘᴀʀꜱᴇᴅ ᴀꜱ ᴍᴀʀᴋᴅᴏᴡɴ ꜰᴏʀᴍᴀᴛ 37 | ᴜʀʟ ʙᴜᴛᴛᴏɴꜱ: 38 | [Button Text](buttonurl:https://t.me/kissuxbots) 39 | ᴀʟᴇʀᴛ ʙᴜᴛᴛᴏɴꜱ: 40 | [Button Text](buttonalert:ᴛʜɪꜱ ɪꜱ ᴀɴ ᴀʟᴇʀᴛ ᴍᴇꜱꜱᴀɢᴇ)""" 41 | 42 | AUTOFILTER_TXT = """ʜᴇʟᴘ: ᴀᴜᴛᴏ ꜰɪʟᴛᴇʀ 43 | ɴᴏᴛᴇ: Fɪʟᴇ Iɴᴅᴇx 44 | 1. ᴍᴀᴋᴇ ᴍᴇ ᴛʜᴇ ᴀᴅᴍɪɴ ᴏꜰ ʏᴏᴜʀ ᴄʜᴀɴɴᴇʟ ɪꜰ ɪᴛ'ꜱ ᴘʀɪᴠᴀᴛᴇ. 45 | 2. ᴍᴀᴋᴇ ꜱᴜʀᴇ ᴛʜᴀᴛ ʏᴏᴜʀ ᴄʜᴀɴɴᴇʟ ᴅᴏᴇꜱ ɴᴏᴛ ᴄᴏɴᴛᴀɪɴꜱ ᴄᴀᴍʀɪᴘꜱ, ᴘᴏʀɴ ᴀɴᴅ ꜰᴀᴋᴇ ꜰɪʟᴇꜱ. 46 | 3. ꜰᴏʀᴡᴀʀᴅ ᴛʜᴇ ʟᴀꜱᴛ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴍᴇ ᴡɪᴛʜ Qᴜᴏᴛᴇꜱ. ɪ'ʟʟ ᴀᴅᴅ ᴀʟʟ ᴛʜᴇ ꜰɪʟᴇꜱ ɪɴ ᴛʜᴀᴛ ᴄʜᴀɴɴᴇʟ ᴛᴏ ᴍʏ ᴅʙ. 47 | 48 | Nᴏᴛᴇ: AᴜᴛᴏFɪʟᴛᴇʀ 49 | 1. Aᴅᴅ ᴛʜᴇ ʙᴏᴛ ᴀs ᴀᴅᴍɪɴ ᴏɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ. 50 | 2. Usᴇ /connect ᴀɴᴅ ᴄᴏɴɴᴇᴄᴛ ʏᴏᴜʀ ɢʀᴏᴜᴘ ᴛᴏ ᴛʜᴇ ʙᴏᴛ. 51 | 3. Usᴇ /settings ᴏɴ ʙᴏᴛ's PM ᴀɴᴅ ᴛᴜʀɴ ᴏɴ AᴜᴛᴏFɪʟᴛᴇʀ ᴏɴ ᴛʜᴇ sᴇᴛᴛɪɴɢs ᴍᴇɴᴜ.""" 52 | 53 | CONNECTION_TXT = """ʜᴇʟᴘ: ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ 54 | - ᴜꜱᴇᴅ ᴛᴏ ᴄᴏɴɴᴇᴄᴛ ʙᴏᴛ ᴛᴏ ᴘᴍ ꜰᴏʀ ᴍᴀɴᴀɢɪɴɢ ꜰɪʟᴛᴇʀꜱ 55 | - ɪᴛ ʜᴇʟᴘꜱ ᴛᴏ ᴀᴠᴏɪᴅ ꜱᴘᴀᴍᴍɪɴɢ ɪɴ ɢʀᴏᴜᴘꜱ. 56 | ɴᴏᴛᴇ: 57 | 1. ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴀᴅᴅ ᴀ ᴄᴏɴɴᴇᴄᴛɪᴏɴ. 58 | 2. ꜱᴇɴᴅ /ᴄᴏɴɴᴇᴄᴛ ꜰᴏʀ ᴄᴏɴɴᴇᴄᴛɪɴɢ ᴍᴇ ᴛᴏ ʏᴏᴜʀ ᴘᴍ 59 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ: 60 | • /connect - ᴄᴏɴɴᴇᴄᴛ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ᴄʜᴀᴛ ᴛᴏ ʏᴏᴜʀ ᴘᴍ 61 | • /disconnect - ᴅɪꜱᴄᴏɴɴᴇᴄᴛ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ 62 | • /connections - ʟɪꜱᴛ ᴀʟʟ ʏᴏᴜʀ ᴄᴏɴɴᴇᴄᴛɪᴏɴꜱ""" 63 | 64 | EXTRAMOD_TXT = """ʜᴇʟᴘ: Exᴛʀᴀ Mᴏᴅᴜʟᴇs 65 | ɴᴏᴛᴇ: 66 | ᴛʜᴇꜱᴇ ᴀʀᴇ ᴛʜᴇ ᴇxᴛʀᴀ ꜰᴇᴀᴛᴜʀᴇꜱ ᴏꜰ ᴛʜɪꜱ ʙᴏᴛ 67 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ: 68 | • /id - ɢᴇᴛ ɪᴅ ᴏꜰ ᴀ ꜱᴘᴇᴄɪꜰɪᴇᴅ ᴜꜱᴇʀ. 69 | • /info - ɢᴇᴛ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴀ ᴜꜱᴇʀ. 70 | • /imdb - ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ɪᴍᴅʙ ꜱᴏᴜʀᴄᴇ. 71 | • /search - ɢᴇᴛ ᴛʜᴇ ꜰɪʟᴍ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ꜰʀᴏᴍ ᴠᴀʀɪᴏᴜꜱ ꜱᴏᴜʀᴄᴇꜱ.""" 72 | 73 | ADMIN_TXT = """ʜᴇʟᴘ: Aᴅᴍɪɴ Mᴏᴅs 74 | ɴᴏᴛᴇ: 75 | Tʜɪs Mᴏᴅᴜʟᴇ Oɴʟʏ Wᴏʀᴋs Fᴏʀ Mʏ Aᴅᴍɪɴs 76 | Cᴏᴍᴍᴀɴᴅs Aɴᴅ Usᴀɢᴇ: 77 | • /logs - ᴛᴏ ɢᴇᴛ ᴛʜᴇ ʀᴇᴄᴇɴᴛ ᴇʀʀᴏʀꜱ 78 | • /stats - ᴛᴏ ɢᴇᴛ ꜱᴛᴀᴛᴜꜱ ᴏꜰ ꜰɪʟᴇꜱ ɪɴ ᴅʙ. [Tʜɪs Cᴏᴍᴍᴀɴᴅ Cᴀɴ Bᴇ Usᴇᴅ Bʏ Aɴʏᴏɴᴇ] 79 | • /delete - ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀ ꜱᴘᴇᴄɪꜰɪᴄ ꜰɪʟᴇ ꜰʀᴏᴍ ᴅʙ. 80 | • /users - ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴜꜱᴇʀꜱ ᴀɴᴅ ɪᴅꜱ. 81 | • /chats - ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴍʏ ᴄʜᴀᴛꜱ ᴀɴᴅ ɪᴅꜱ 82 | • /leave - ᴛᴏ ʟᴇᴀᴠᴇ ꜰʀᴏᴍ ᴀ ᴄʜᴀᴛ. 83 | • /disable - ᴛᴏ ᴅɪꜱᴀʙʟᴇ ᴀ ᴄʜᴀᴛ. 84 | • /ban - ᴛᴏ ʙᴀɴ ᴀ ᴜꜱᴇʀ. 85 | • /unban - ᴛᴏ ᴜɴʙᴀɴ ᴀ ᴜꜱᴇʀ. 86 | • /channel - ᴛᴏ ɢᴇᴛ ʟɪꜱᴛ ᴏꜰ ᴛᴏᴛᴀʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ᴄʜᴀɴɴᴇʟꜱ 87 | • /broadcast - ᴛᴏ ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴀ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴀʟʟ ᴜꜱᴇʀꜱ 88 | • /grp_broadcast - Tᴏ ʙʀᴏᴀᴅᴄᴀsᴛ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ᴀʟʟ ᴄᴏɴɴᴇᴄᴛᴇᴅ ɢʀᴏᴜᴘs. 89 | • /gfilter - ᴛᴏ ᴀᴅᴅ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs 90 | • /gfilters - ᴛᴏ ᴠɪᴇᴡ ʟɪsᴛ ᴏғ ᴀʟʟ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs 91 | • /delg - ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀ sᴘᴇᴄɪғɪᴄ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ 92 | • /request - Tᴏ sᴇɴᴅ ᴀ Mᴏᴠɪᴇ/Sᴇʀɪᴇs ʀᴇᴏ̨ᴜᴇsᴛ ᴛᴏ ʙᴏᴛ ᴀᴅᴍɪɴs. Oɴʟʏ ᴡᴏʀᴋs ᴏɴ sᴜᴘᴘᴏʀᴛ ɢʀᴏᴜᴘ. [Tʜɪs Cᴏᴍᴍᴀɴᴅ Cᴀɴ Bᴇ Usᴇᴅ Bʏ Aɴʏᴏɴᴇ] 93 | • /delallg - Tᴏ ᴅᴇʟᴇᴛᴇ ᴀʟʟ Gғɪʟᴛᴇʀs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ. 94 | • /deletefiles - Tᴏ ᴅᴇʟᴇᴛᴇ CᴀᴍRɪᴘ ᴀɴᴅ PʀᴇDVD Fɪʟᴇs ғʀᴏᴍ ᴛʜᴇ ʙᴏᴛ's ᴅᴀᴛᴀʙᴀsᴇ.""" 95 | 96 | STATUS_TXT = """⍟────[ ʙᴏᴛ sᴛᴀᴛᴜ𝗌 ]────⍟ 97 | • Tᴏᴛᴀʟ Fɪʟᴇs: {} 98 | • Tᴏᴛᴀʟ Usᴇʀs: {} 99 | • Tᴏᴛᴀʟ Cʜᴀᴛs: {} 100 | • Usᴇᴅ Sᴛᴏʀᴀɢᴇ: {} 101 | • Fʀᴇᴇ Sᴛᴏʀᴀɢᴇ: {} 102 | 103 | •❅─────✧❅✦❅✧─────❅•""" 104 | 105 | LOG_TEXT_G = """#NewGroup 106 | Gʀᴏᴜᴘ = {}({}) 107 | Tᴏᴛᴀʟ Mᴇᴍʙᴇʀs = {} 108 | Aᴅᴅᴇᴅ Bʏ - {}""" 109 | 110 | LOG_TEXT_P = """#NewUser 111 | ID - {} 112 | Nᴀᴍᴇ - {}""" 113 | 114 | ALRT_TXT = """ʜᴇʟʟᴏ {}, 115 | ᴛʜɪꜱ ɪꜱ ɴᴏᴛ ʏᴏᴜʀ ᴍᴏᴠɪᴇ ʀᴇQᴜᴇꜱᴛ, 116 | ʀᴇQᴜᴇꜱᴛ ʏᴏᴜʀ'ꜱ...""" 117 | 118 | OLD_ALRT_TXT = """ʜᴇʏ {}, 119 | ʏᴏᴜ ᴀʀᴇ ᴜꜱɪɴɢ ᴏɴᴇ ᴏꜰ ᴍʏ ᴏʟᴅ ᴍᴇꜱꜱᴀɢᴇꜱ, 120 | ᴘʟᴇᴀꜱᴇ ꜱᴇɴᴅ ᴛʜᴇ ʀᴇQᴜᴇꜱᴛ ᴀɢᴀɪɴ.""" 121 | 122 | CUDNT_FND = """Sᴘᴇʟʟɪɴɢ Mɪsᴛᴀᴋᴇ Bʀᴏ ‼️ 123 | Dᴏɴ'ᴛ Wᴏʀʀʏ 😊, Cʜᴏᴏsᴇ Tʜᴇ Cᴏʀʀᴇᴄᴛ Oɴᴇ Bᴇʟᴏᴡ👇""" 124 | 125 | I_CUDNT = """sᴏʀʀʏ ɪ ᴄᴏᴜʟᴅɴ'ᴛ ғɪɴᴅ ᴀɴʏ ᴍᴏᴠɪᴇ/sᴇʀɪᴇs ʀᴇʟᴀᴛᴇᴅ ᴛᴏ ᴛʜᴇ ɢɪᴠᴇɴ ᴡᴏʀᴅ ~~{}~~ 😕 126 | 127 | ᴄʜᴇᴄᴋ ʏᴏᴜʀ sᴘᴇʟʟɪɴɢ ɪɴ ɢᴏᴏɢʟᴇ ᴀɴᴅ ᴛʀʏ ᴀɢᴀɪɴ 😃 128 | 129 | ᴍᴏᴠɪᴇ ʀᴇǫᴜᴇꜱᴛ ꜰᴏʀᴍᴀᴛ 👇 130 | 131 | ᴇxᴀᴍᴘʟᴇ : Maalik or maalik 2025 or Infinity War 2019 Hindi 132 | 133 | ꜱᴇʀɪᴇꜱ ʀᴇǫᴜᴇꜱᴛ ꜰᴏʀᴍᴀᴛ 👇 134 | 135 | ᴇxᴀᴍᴘʟᴇ : Squid Game S02 or Squid Game S01E04 136 | 137 | 🚯 Dᴏɴᴛ ᴜꜱᴇ ➠ ':(!,./)""" 138 | 139 | I_CUD_NT = """ɪ ᴄᴏᴜʟᴅɴ'ᴛ ꜰɪɴᴅ ᴀɴʏ ᴍᴏᴠɪᴇ ʀᴇʟᴀᴛᴇᴅ ᴛᴏ {}. 140 | ᴘʟᴇᴀꜱᴇ ᴄʜᴇᴄᴋ ᴛʜᴇ ꜱᴘᴇʟʟɪɴɢ ᴏɴ ɢᴏᴏɢʟᴇ ᴏʀ ɪᴍᴅʙ...""" 141 | 142 | MVE_NT_FND = """ᴍᴏᴠɪᴇ ɴᴏᴛ ꜰᴏᴜɴᴅ ɪɴ ᴅᴀᴛᴀʙᴀꜱᴇ...""" 143 | 144 | TOP_ALRT_MSG = """Cʜᴇᴄᴋɪɴɢ Fᴏʀ Mᴏᴠɪᴇ Iɴ Dᴀᴛᴀʙᴀsᴇ...""" 145 | 146 | MELCOW_ENG = """Hᴇʟʟᴏ {} 😍, Aɴᴅ Wᴇʟᴄᴏᴍᴇ Tᴏ {} Gʀᴏᴜᴘ ❤️""" 147 | 148 | SHORTLINK_INFO = """ 149 | ─────「 Hᴏᴡ ᴛᴏ Eᴀʀɴ Mᴏɴᴇʏ 」───── 150 | 151 | Yᴏᴜ ᴄᴀɴ Eᴀʀɴ Mᴏɴᴇʏ Fʀᴏᴍ Tʜɪs Bᴏᴛ Uɴᴛɪʟ ᴛʜɪs ʙᴏᴛ ɪs ᴀʟɪᴠᴇ. 152 | 153 | Wᴀɴᴛ ᴛᴏ Kɴᴏᴡ Hᴏᴡ? Fᴏʟʟᴏᴡ Tʜᴇsᴇ Sᴛᴇᴘs:- 154 | 155 | sᴛᴇᴘ 𝟷 : ʏᴏᴜ ᴍᴜsᴛ ʜᴀᴠᴇ ᴀᴛʟᴇᴀsᴛ ᴏɴᴇ ɢʀᴏᴜᴘ ᴡɪᴛʜ ᴍɪɴɪᴍᴜᴍ 1𝟶𝟶 ᴍᴇᴍʙᴇʀs. 156 | 157 | sᴛᴇᴘ 𝟸 : ᴍᴀᴋᴇ ᴀᴄᴄᴏᴜɴᴛ ᴏɴ Aɴʏ Sʜᴏʀᴛᴇɴᴇʀ Wᴇʙsɪᴛᴇ. 158 | 159 | sᴛᴇᴘ 𝟹 : ꜰᴏʟʟᴏᴡ ᴛʜᴇsᴇ ɪɴꜱᴛʀᴜᴄᴛɪᴏɴꜱ Tᴏ ᴄᴏɴɴᴇᴄᴛ sʜᴏʀᴛᴇɴᴇʀ. 160 | 161 | ➣ Yᴏᴜ ᴄᴀɴ ᴄᴏɴɴᴇᴄᴛ ᴀs ᴍᴀɴʏ ɢʀᴏᴜᴘ ʏᴏᴜ ʜᴀᴠᴇ. 162 | 163 | ᴀɴʏ ᴅᴏᴜʙᴛs ᴏʀ ɴᴏᴛ ᴄᴏɴɴᴇᴄᴛɪɴɢ? ᴄᴏɴᴛᴀᴄᴛ ᴏᴡɴᴇʀ 164 | """ 165 | 166 | REQINFO = """ 167 | ⚠ ɪɴꜰᴏʀᴍᴀᴛɪᴏɴ ⚠ 168 | 169 | ᴀꜰᴛᴇʀ 5 ᴍɪɴᴜᴛᴇꜱ ᴛʜɪꜱ ᴍᴇꜱꜱᴀɢᴇ ᴡɪʟʟ ʙᴇ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ᴅᴇʟᴇᴛᴇᴅ 170 | 171 | ɪꜰ ʏᴏᴜ ᴅᴏ ɴᴏᴛ ꜱᴇᴇ ᴛʜᴇ ʀᴇǫᴜᴇsᴛᴇᴅ ᴍᴏᴠɪᴇ / sᴇʀɪᴇs ꜰɪʟᴇ, ʟᴏᴏᴋ ᴀᴛ ᴛʜᴇ ɴᴇxᴛ ᴘᴀɢᴇ""" 172 | 173 | SELECT = """ 174 | MOVIES ➢ Sᴇʟᴇᴄᴛ "Lᴀɴɢᴜᴀɢᴇs" 175 | 176 | SERIES ➢ Sᴇʟᴇᴄᴛ "Sᴇᴀsᴏɴs" 177 | 178 | Tɪᴘ: Sᴇʟᴇᴄᴛ "Lᴀɴɢᴜᴀɢᴇs" ᴏʀ "Sᴇᴀsᴏɴs" Bᴜᴛᴛᴏɴ ᴀɴᴅ Cʟɪᴄᴋ "Sᴇɴᴅ Aʟʟ" Tᴏ ɢᴇᴛ Aʟʟ Fɪʟᴇ Lɪɴᴋs ɪɴ ᴀ Sɪɴɢʟᴇ ᴄʟɪᴄᴋ""" 179 | 180 | SINFO = """ 181 | ⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯ 182 | ꜱᴇʀɪᴇꜱ ʀᴇǫᴜᴇꜱᴛ ꜰᴏʀᴍᴀᴛ 183 | ⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯ 184 | 185 | ɢᴏ ᴛᴏ ɢᴏᴏɢʟᴇ ➠ ᴛʏᴘᴇ ꜱᴇʀɪᴇꜱ ɴᴀᴍᴇ ➠ ᴄᴏᴘʏ ᴄᴏʀʀᴇᴄᴛ ɴᴀᴍᴇ ➠ ᴘᴀꜱᴛᴇ ᴛʜɪꜱ ɢʀᴏᴜᴘ 186 | 187 | ᴇxᴀᴍᴘʟᴇ : Loki S01E01 188 | 189 | 🚯 ᴅᴏɴᴛ ᴜꜱᴇ ➠ ':(!,./)""" 190 | 191 | NORSLTS = """ 192 | ★ #NoResult ★ 193 | 194 | 𝗜𝗗 : {} 195 | 196 | 𝗡𝗮𝗺𝗲 : {} 197 | 198 | 𝗠𝗲𝘀𝘀𝗮𝗴𝗲 : {}""" 199 | 200 | CAPTION = """ 201 | {file_caption}""" 202 | 203 | FORCE_SUB = """ 204 | **⚠️ Pʟᴇᴀsᴇ ғᴏʟʟᴏᴡ ᴛʜɪs ʀᴜʟe ⚠️ 205 | 206 | Iɴ ᴏʀᴅᴇʀ ᴛᴏ ɢᴇᴛ ᴛʜᴇ ᴍᴏᴠɪᴇ ʀᴇǫᴜᴇsᴛᴇᴅ ʙʏ ʏᴏᴜ. 207 | 208 | Yᴏᴜ ᴡɪʟʟ ʜᴀᴠᴇ ᴛᴏ ᴊᴏɪɴ ᴏᴜʀ ᴏғғɪᴄɪᴀʟ ᴏʀ ʙᴀᴄᴋ-ᴜᴘ ᴄʜᴀɴɴᴇʟ ғɪʀsᴛ. 209 | 210 | Tʜᴇɴ ᴄʟɪᴄᴋ ᴏɴ ᴛʜᴇ '🔄 Tʀʏ Aɢᴀɪɴ' ʙᴜᴛᴛᴏɴ ʙᴇʟᴏᴡ. 211 | 212 | Aғᴛᴇʀ ᴛʜᴀᴛ ɪ'ʟʟ sᴇɴᴅ ʏᴏᴜ ᴛʜᴀᴛ ᴍᴏᴠɪᴇ ᴘʀɪᴠᴀᴛᴇʟʏ.**""" 213 | 214 | IMDB_TEMPLATE_TXT = """ 215 | Query: {qurey} 216 | 217 | IMDb Data: 218 | 🏷 Title: {title} 219 | 🎭 Genres: {genres} 220 | 📆 Year: {year} 221 | ⏱️ Result Shown in: {remaining_seconds} seconds 🔥 222 | 🌟 Rating: {rating} / 10""" 223 | 224 | 225 | ALL_FILTERS = """ 226 | Hᴇʏ {}, Tʜᴇsᴇ ᴀʀᴇ ᴍʏ ᴛʜʀᴇᴇ ᴛʏᴘᴇs ᴏғ ғɪʟᴛᴇʀs.""" 227 | 228 | GFILTER_TXT = """ 229 | Wᴇʟᴄᴏᴍᴇ ᴛᴏ Gʟᴏʙᴀʟ Fɪʟᴛᴇʀs. Gʟᴏʙᴀʟ Fɪʟᴛᴇʀs ᴀʀᴇ ᴛʜᴇ ғɪʟᴛᴇʀs sᴇᴛ ʙʏ ʙᴏᴛ ᴀᴅᴍɪɴs ᴡʜɪᴄʜ ᴡɪʟʟ ᴡᴏʀᴋ ᴏɴ ᴀʟʟ ɢʀᴏᴜᴘs. 230 | 231 | Aᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs: 232 | • /gfilter - Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ. 233 | • /gfilters - Tᴏ ᴠɪᴇᴡ ᴀʟʟ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀs. 234 | • /delg - Tᴏ ᴅᴇʟᴇᴛᴇ ᴀ ᴘᴀʀᴛɪᴄᴜʟᴀʀ ɢʟᴏʙᴀʟ ғɪʟᴛᴇʀ. 235 | • /delallg - ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴀʟʟ ɢʟᴏʙᴀʟ ꜰɪʟᴛᴇʀꜱ.""" 236 | 237 | FILE_STORE_TXT = """ 238 | Fɪʟᴇ sᴛᴏʀᴇ ɪs ᴛʜᴇ ғᴇᴀᴛᴜʀᴇ ᴡʜɪᴄʜ ᴡɪʟʟ ᴄʀᴇᴀᴛᴇ ᴀ sʜᴀʀᴇᴀʙʟᴇ ʟɪɴᴋ ᴏғ ᴀ sɪɴɢʟᴇ ᴏʀ ᴍᴜʟᴛɪᴘʟᴇ ғɪʟᴇs. 239 | 240 | Aᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs: 241 | • /batch - Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ ʙᴀᴛᴄʜ ʟɪɴᴋ ᴏғ ᴍᴜʟᴛɪᴘʟᴇ ғɪʟᴇs. 242 | • /link - Tᴏ ᴄʀᴇᴀᴛᴇ ᴀ sɪɴɢʟᴇ ғɪʟᴇ sᴛᴏʀᴇ ʟɪɴᴋ. 243 | • /pbatch - Jᴜsᴛ ʟɪᴋᴇ /batch, ʙᴜᴛ ᴛʜᴇ ғɪʟᴇs ᴡɪʟʟ ʙᴇ sᴇɴᴅ ᴡɪᴛʜ ғᴏʀᴡᴀʀᴅ ʀᴇsᴛʀɪᴄᴛɪᴏɴs. 244 | • /plink - Jᴜsᴛ ʟɪᴋᴇ /link, ʙᴜᴛ ᴛʜᴇ ғɪʟᴇ ᴡɪʟʟ ʙᴇ sᴇɴᴅ ᴡɪᴛʜ ғᴏʀᴡᴀʀᴅ ʀᴇsᴛʀɪᴄᴛɪᴏɴ.""" 245 | 246 | OWNER_INFO = """ 247 | ⍟───[ ᴏᴡɴᴇʀ ᴅᴇᴛᴀɪʟꜱ ]───⍟
248 | ◈ ꜰᴜʟʟ ɴᴀᴍᴇ : 𓆩•𝐊𝐢𝐬𝐬𝐮 💞•𓆪
249 | ◈ ʜᴇʀᴇ ɪs ᴘᴜʙʟɪᴄ sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ ᴀɴᴅ ɪɴsᴛʀᴜᴄᴛɪᴏɴs — ᴛᴀᴘ ʙᴇʟᴏᴡ ᴏʀ ʜᴇʀᴇ ᴛᴏ sᴇᴇ. 250 |
""" 251 | 252 | DISL_TXT = """ 253 | 254 | ᴛʜɪꜱ ɪꜱ ᴀɴ ᴏᴘᴇɴ ꜱᴏᴜʀᴄᴇ ᴘʀᴏᴊᴇᴄᴛ.

255 | ᴀʟʟ ᴛʜᴇ ꜰɪʟᴇꜱ ɪɴ ᴛʜɪꜱ ʙᴏᴛ ᴀʀᴇ ꜰʀᴇᴇʟʏ ᴀᴠᴀɪʟᴀʙʟᴇ ᴏɴ ᴛʜᴇ ɪɴᴛᴇʀɴᴇᴛ ᴏʀ ᴘᴏꜱᴛᴇᴅ ʙʏ ꜱᴏᴍᴇʙᴏᴅʏ ᴇʟꜱᴇ. ᴊᴜꜱᴛ ꜰᴏʀ ᴇᴀꜱʏ ꜱᴇᴀʀᴄʜɪɴɢ, ᴛʜɪꜱ ʙᴏᴛ ɪꜱ ɪɴᴅᴇxɪɴɢ ꜰɪʟᴇꜱ ᴡʜɪᴄʜ ᴀʀᴇ ᴀʟʀᴇᴀᴅʏ ᴜᴘʟᴏᴀᴅᴇᴅ ᴏɴ ᴛᴇʟᴇɢʀᴀᴍ.

256 | ᴡᴇ ʀᴇꜱᴘᴇᴄᴛ ᴀʟʟ ᴛʜᴇ ᴄᴏᴘʏʀɪɢʜᴛ ʟᴀᴡꜱ ᴀɴᴅ ᴡᴏʀᴋ ɪɴ ᴄᴏᴍᴘʟɪᴀɴᴄᴇ ᴡɪᴛʜ DMCA ᴀɴᴅ EUCD. ɪꜰ ᴀɴʏᴛʜɪɴɢ ɪꜱ ᴀɢᴀɪɴꜱᴛ ʟᴀᴡ, ᴘʟᴇᴀꜱᴇ ᴄᴏɴᴛᴀᴄᴛ ᴍᴇ ꜱᴏ ɪᴛ ᴄᴀɴ ʙᴇ ʀᴇᴍᴏᴠᴇᴅ ᴀꜱᴀᴘ.

257 | ɪᴛ ɪꜱ ꜰᴏʀʙɪᴅᴅᴇɴ ᴛᴏ ᴅᴏᴡɴʟᴏᴀᴅ, ꜱᴛʀᴇᴀᴍ, ʀᴇᴘʀᴏᴅᴜᴄᴇ, ꜱʜᴀʀᴇ, ᴏʀ ᴄᴏɴꜱᴜᴍᴇ ᴄᴏɴᴛᴇɴᴛ ᴡɪᴛʜᴏᴜᴛ ᴇxᴘʟɪᴄɪᴛ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ꜰʀᴏᴍ ᴛʜᴇ ᴄᴏɴᴛᴇɴᴛ ᴄʀᴇᴀᴛᴏʀ ᴏʀ ᴄᴏᴘʏʀɪɢʜᴛ ʜᴏʟᴅᴇʀ.

258 | ɪꜰ ʏᴏᴜ ʙᴇʟɪᴇᴠᴇ ᴛʜɪꜱ ʙᴏᴛ ɪꜱ ᴠɪᴏʟᴀᴛɪɴɢ ʏᴏᴜʀ ɪɴᴛᴇʟʟᴇᴄᴛᴜᴀʟ ᴘʀᴏᴘᴇʀᴛʏ, ᴄᴏɴᴛᴀᴄᴛ ᴛʜᴇ ʀᴇꜱᴘᴇᴄᴛɪᴠᴇ ᴄʜᴀɴɴᴇʟꜱ ꜰᴏʀ ʀᴇᴍᴏᴠᴀʟ.

259 | ᴛʜᴇ ʙᴏᴛ ᴅᴏᴇꜱ ɴᴏᴛ ᴏᴡɴ ᴀɴʏ ᴏꜰ ᴛʜᴇꜱᴇ ᴄᴏɴᴛᴇɴᴛꜱ — ɪᴛ ᴏɴʟʏ ɪɴᴅᴇxᴇꜱ ꜰɪʟᴇꜱ ꜰʀᴏᴍ ᴛᴇʟᴇɢʀᴀᴍ.

260 | 🔗 View Public Source Code 261 |
262 | """ 263 | 264 | MODS_TXT = """Yᴏᴜ Cᴀɴ Tʀʏ Aʟʟ Tʜᴇsᴇ Fᴇᴀᴛᴜʀᴇ Fʀᴏᴍ Bᴇʟᴏᴡ Oᴘᴛɪᴏɴ..!!!""" 265 | 266 | STICKER_TXT = """𝚈𝙾ᴜ 𝙲𝙰ɴ 𝚄𝚂𝙴 𝚃𝙷𝙸𝚂 𝙼𝙾𝙳𝚄𝙻𝙴 𝚃𝙾 𝙵𝙸𝙽𝙳 𝙰𝙽𝚈 𝚂𝚃𝙸𝙲𝙺𝙴𝚁𝚂 𝙸𝙳. 267 | • 𝐔𝐒𝐀𝐆𝐄 268 | To Get Sticker ID 269 | 270 | ⭕ 𝙃𝙤𝙬 𝙏𝙤 𝙐𝙨𝙚 271 | 272 | ◉ ʀᴇᴘʟʏ ᴛᴏ ᴀɴʏ sᴛɪᴄᴋᴇʀ [/stickerid]""" 273 | 274 | 275 | FONT_TXT= """ 𝐔𝐒𝐀𝐆ᴇ 276 | 277 | 𝐘𝐎ᴜ ᴄᴀɴ 𝐔𝐒𝐄 𝐓𝐇𝐈𝐒 𝐌𝐎𝐃𝐔𝐋𝐄 𝐓𝐎 𝐂𝐇𝐀𝐍𝐆𝐄 𝐅𝐎𝐍𝐓 𝐒𝐓𝐘𝐋𝐄 278 | 279 | ᴄᴏᴍᴍᴀɴᴅ : /font ʏᴏᴜʀ ᴛᴇxᴛ ( ᴏᴘᴛɪᴏɴᴀʟ) 280 | Eg:- /font ʜᴇʟʟᴏ""" 281 | 282 | TELE_TXT = """▫️Hᴇʟᴘ: ▪️ Tᴇʟᴇɢʀᴀᴘʜ ▪️ 283 | Tᴇʟᴇɢʀᴀᴘʜ Lɪɴᴋ Gᴇɴᴇʀᴀᴛᴏʀ 284 | Usᴀɢᴇ 285 | 🤧 /telegraph - Sᴇɴᴅ Mᴇ Pʜᴏᴛᴏ Oʀ Vɪᴅᴇᴏ Uɴᴅᴇʀ(5ᴍʙ) Aɴᴅ Rᴇᴘʟʏ Wɪᴛʜ Cᴏᴍᴍᴀᴍɴᴅ""" 286 | 287 | CON_TXT = """ᴄᴏᴜɴᴛʀʏ ɪɴғᴏ 288 | Tʜɪs ᴍᴏᴅᴜʟᴇ ɪs ᴛᴏ ғɪɴᴅ ɪɴғᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴄᴏᴜɴᴛʀɪᴇs 289 | • /country [𝖼𝗈𝗎𝗇𝗍𝗋𝗒 𝗇𝖺𝗆𝖾] 290 | 𝖤𝗑𝖺𝗆𝗉𝗅𝖾 :- /country India""" 291 | 292 | SOURCE_TXT = """ 293 | ✭ ғᴏʀ ᴀɴʏ ǫᴜᴇʀʏ ᴄᴏɴᴛᴀᴄᴛ ᴛᴏ ᴛʜᴇ 𓆩•𝐊𝐢𝐬𝐬𝐮 💞•𓆪
294 | ✭ ʜᴇʀᴇ ɪs ᴘᴜʙʟɪᴄ sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ ᴀɴᴅ ɪɴsᴛʀᴜᴄᴛɪᴏɴs — ᴛᴀᴘ ʙᴇʟᴏᴡ ᴏʀ ʜᴇʀᴇ ᴛᴏ sᴇᴇ. 295 |
296 | """ 297 | 298 | 299 | RULE_TXT = """ 300 | ♨️ 𝗚𝗥𝗢𝗨𝗣 𝗥𝗨𝗟𝗘𝗦 ♨️

301 | 302 | 🔹 Sᴇᴀʀᴄʜ Mᴏᴠɪᴇ Wɪᴛʜ Cᴏʀʀᴇᴄᴛ Sᴘᴇʟʟɪɴɢ :
303 | › ᴀᴠᴀᴛᴀʀ 2009 ✅
304 | › ᴀᴠᴀᴛᴀʀ ʜɪɴᴅɪ ✅
305 | › ᴀᴠᴀᴛᴀʀ ᴍᴏᴠɪᴇ ❌
306 | › ᴀᴠᴀᴛᴀʀ ʜɪɴᴅɪ ᴅᴜʙʙᴇᴅ.. ❌

307 | 308 | 🔹 Sᴇᴀʀᴄʜ Wᴇʙ Sᴇʀɪᴇs Iɴ ᴛʜɪs Fᴏʀᴍᴀᴛ :
309 | › ᴠɪᴋɪɴɢs S01 ✅
310 | › ᴠɪᴋɪɴɢs S01E01 ✅
311 | › ᴠɪᴋɪɴɢs S01 ʜɪɴᴅɪ ✅
312 | › ᴠɪᴋɪɴɢs S01 ʜɪɴᴅɪ ᴅᴜʙʙ. ❌
313 | › ᴠɪᴋɪɴɢs sᴇᴀsᴏɴ 1 ❌
314 | › ᴠɪᴋɪɴɢs ᴡᴇʙ sᴇʀɪᴇs ❌

315 | 316 | 🔹 ᴅᴏɴ'ᴛ ᴅᴏ ᴀɴʏ sᴇʟғ ᴘʀᴏᴍᴏᴛɪᴏɴ.
317 | 🔹 ᴅᴏɴ'ᴛ sᴇɴᴅ ᴀɴʏ ᴋɪɴᴅ ᴏғ ᴘʜᴏᴛᴏ, ᴠɪᴅᴇᴏ, ᴅᴏᴄᴜᴍᴇɴᴛꜱ, ᴜʀʟꜱ, ᴇᴛᴄ.
318 | 🔹 ᴅᴏɴ'ᴛ ʀᴇǫᴜᴇsᴛ ᴀɴʏᴛʜɪɴɢ ᴏᴛʜᴇʀ ᴛʜᴀɴ ᴍᴏᴠɪᴇs, ꜱᴇʀɪᴇꜱ, ᴀɴɪᴍᴇꜱ.

319 | 320 | ⚙️ 𝖭ᴏᴛᴇ : 𝖠ʟʟ ᴍᴇ𝘀𝘀ᴀɢᴇ𝘀 ᴡɪʟʟ ʙᴇ ᴀᴜᴛᴏ-ᴅᴇʟᴇᴛᴇᴅ ᴀғᴛᴇʀ 𝟷𝟶 ᴍɪɴᴜᴛᴇ𝘀 ᴛᴏ ᴀᴠᴏɪᴅ ᴄᴏᴘʏʀɪɢʜᴛ ɪ𝘀𝘀ᴜᴇ𝘀.""" 321 | 322 | SETTING_TXT = """ 323 | ѕeттιngѕ 324 | ~ sᴇᴛᴛɪɴɢs ɪs ᴍᴏsᴛ ɪᴍᴘᴏʀᴛᴀɴᴛ ғᴇᴀᴛᴜʀᴇs ɪɴ ᴛʜɪs ʙᴏᴛ. 325 | ~ ʏᴏᴜ ᴄᴀɴ ᴇᴀsɪʟʏ ᴄᴜsᴛᴏᴍɪᴢᴇ ᴛʜɪs ʙᴏᴛ ғᴏʀ ʏᴏᴜʀ ɢʀᴏᴜᴘ. 326 | 327 | noтe 328 | 1. ᴏɴʟʏ ɢʀᴏᴜᴘ ᴀᴅᴍɪɴ ᴄᴀɴ ᴜsᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴀɴᴅ ᴄʜᴀɴɢᴇs sᴇᴛᴛɪɴɢs. 329 | 2. ɪᴛ ᴡᴏʀᴋs ᴏɴʟʏ ᴡʜᴇɴ ʏᴏᴜ ᴀʟʀᴇᴀᴅʏ ᴄᴏɴɴᴇᴄᴛ ʏᴏᴜʀ ɢʀᴏᴜᴘ. 330 | 331 | coммand and υѕeѕ 332 | • /settings - ᴄʜᴀɴɢᴇ sᴇᴛᴛɪɴɢs ᴀs ʏᴏᴜʀ ᴡɪsʜ""" 333 | 334 | CHNL_INFO = """ 335 | ɢʀᴏᴜᴘs & ᴄʜᴀɴɴᴇʟs ɪɴғᴏ \⁠(⁠°⁠o⁠°⁠)⁠/ 336 | 337 | ▫ ᴄᴏᴍᴘʟᴇᴛᴇ ᴍᴏᴠɪᴇs ʀᴇǫᴜᴇsᴛɪɴɢ ɢʀᴏᴜᴘ. 338 | ▫ ᴀʟʟ ʟᴀɴɢᴜᴀɢᴇ ᴍᴏᴠɪᴇs & sᴇʀɪᴇs. 339 | ▫ ғᴀsᴛᴇsᴛ ʙᴏᴛs ᴀʀᴇ ᴀᴅᴅᴇᴅ. 340 | ▫ ғʀᴇᴇ & ᴇᴀsʏ ᴛᴏ ᴜsᴇ. 341 | ▫ 𝟸𝟺x𝟽 sᴇʀᴠɪᴄᴇs ᴀᴠᴀɪʟᴀʙʟᴇ. """ 342 | 343 | VERIFED_TXT = """ʜᴇʏ {}, 344 | ʏᴏᴜ ᴀʀᴇ sᴜᴄᴄᴇssғᴜʟʟʏ ᴠᴇʀɪғɪᴇᴅ ! 345 | ɴᴏᴡ ʏᴏᴜ ʜᴀᴠᴇ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇss ғᴏʀ ᴀʟʟ ᴍᴏᴠɪᴇs ᴛɪʟʟ ᴛᴏᴅᴀʏ ᴍɪᴅɴɪɢʜᴛ.""" 346 | 347 | VERIFY_TXT = """ʜᴇʟʟᴏ {}, 348 | ʏᴏᴜʀ ᴀʀᴇ ɴᴏᴛ ᴠᴇʀɪғɪᴇᴅ ᴛᴏᴅᴀʏ,ᴘʟᴇᴀꜱᴇ ᴠᴇʀɪғʏ ɴᴏᴡ ᴀɴᴅ ɢᴇᴛ ᴜɴʟɪᴍɪᴛᴇᴅ ᴀᴄᴄᴇꜱꜱ ғᴏʀ ɴᴇxᴛ ᴠᴇʀɪғɪᴄᴀᴛɪᴏɴ... 349 | इस बाॅट को इस्तेमाल करने के लिए आपको ᴠᴇʀɪғʏ करना होगा नहीं तो आप इसका इस्तेमाल नहीं कर पाएंगे |""" 350 | 351 | VERIFY2_TXT = """ 352 | Vᴇʀɪғʏ Sᴛᴀᴛᴜꜱ 353 | Nᴀᴍᴇ : {} 354 | Uꜱᴇʀ Sᴛᴀᴛᴜꜱ : Vᴇʀɪғɪᴇᴅ 355 | """ 356 | 357 | RESTART_TXT = """ 358 | Bᴏᴛ Rᴇsᴛᴀʀᴛᴇᴅ ! 359 | 360 | 📅 Dᴀᴛᴇ : {} 361 | ⏰ Tɪᴍᴇ : {} 362 | 🌐 Tɪᴍᴇᴢᴏɴᴇ : Asia/Kolkata 363 | 🛠️ Bᴜɪʟᴅ Sᴛᴀᴛᴜs: v2.7.1 [ Sᴛᴀʙʟᴇ ]""" 364 | 365 | LOGO = """┏━━━━━━━━━━━━━━┓ 366 | ┃ Made by → @KissuBots ┃ 367 | ┗━━━━━━━━━━━━━━┛""" 368 | -------------------------------------------------------------------------------- /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, SHORTLINK_URL, SHORTLINK_API, IS_SHORTLINK, LOG_CHANNEL, TUTORIAL, GRP_LNK, CHNL_LNK, CUSTOM_FILE_CAPTION, HOW_TO_VERIFY 4 | from imdb import Cinemagoer 5 | import asyncio 6 | from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup 7 | from pyrogram.errors import FloodWait, UserIsBlocked, MessageNotModified, PeerIdInvalid 8 | from pyrogram import enums 9 | from typing import Union 10 | from Script import script 11 | import pytz 12 | import random 13 | import re 14 | import os 15 | from datetime import datetime, date 16 | import string 17 | from typing import List 18 | from database.users_chats_db import db 19 | from bs4 import BeautifulSoup 20 | import requests 21 | import aiohttp 22 | from shortzy import Shortzy 23 | import http.client 24 | import json 25 | 26 | logger = logging.getLogger(__name__) 27 | logger.setLevel(logging.INFO) 28 | 29 | BTN_URL_REGEX = re.compile( 30 | r"(\[([^\[]+?)\]\((buttonurl|buttonalert):(?:/{0,2})(.+?)(:same)?\))" 31 | ) 32 | 33 | imdb = Cinemagoer() 34 | TOKENS = {} 35 | VERIFIED = {} 36 | BANNED = {} 37 | SECOND_SHORTENER = {} 38 | SMART_OPEN = '“' 39 | SMART_CLOSE = '”' 40 | START_CHAR = ('\'', '"', SMART_OPEN) 41 | 42 | # temp db for banned 43 | class temp(object): 44 | BANNED_USERS = [] 45 | BANNED_CHATS = [] 46 | ME = None 47 | CURRENT=int(os.environ.get("SKIP", 2)) 48 | CANCEL = False 49 | MELCOW = {} 50 | U_NAME = None 51 | B_NAME = None 52 | GETALL = {} 53 | SHORT = {} 54 | SETTINGS = {} 55 | CAP = {} 56 | 57 | async def is_subscribed(bot, query): 58 | try: 59 | user = await bot.get_chat_member(AUTH_CHANNEL, query.from_user.id) 60 | except UserNotParticipant: 61 | pass 62 | except Exception as e: 63 | logger.exception(e) 64 | else: 65 | if user.status != enums.ChatMemberStatus.BANNED: 66 | return True 67 | 68 | return False 69 | 70 | async def get_poster(query, bulk=False, id=False, file=None): 71 | if not id: 72 | # https://t.me/GetTGLink/4183 73 | query = (query.strip()).lower() 74 | title = query 75 | year = re.findall(r'[1-2]\d{3}$', query, re.IGNORECASE) 76 | if year: 77 | year = list_to_str(year[:1]) 78 | title = (query.replace(year, "")).strip() 79 | elif file is not None: 80 | year = re.findall(r'[1-2]\d{3}', file, re.IGNORECASE) 81 | if year: 82 | year = list_to_str(year[:1]) 83 | else: 84 | year = None 85 | movieid = imdb.search_movie(title.lower(), results=10) 86 | if not movieid: 87 | return None 88 | if year: 89 | filtered=list(filter(lambda k: str(k.get('year')) == str(year), movieid)) 90 | if not filtered: 91 | filtered = movieid 92 | else: 93 | filtered = movieid 94 | movieid=list(filter(lambda k: k.get('kind') in ['movie', 'tv series'], filtered)) 95 | if not movieid: 96 | movieid = filtered 97 | if bulk: 98 | return movieid 99 | movieid = movieid[0].movieID 100 | else: 101 | movieid = query 102 | movie = imdb.get_movie(movieid) 103 | if movie.get("original air date"): 104 | date = movie["original air date"] 105 | elif movie.get("year"): 106 | date = movie.get("year") 107 | else: 108 | date = "N/A" 109 | plot = "" 110 | if not LONG_IMDB_DESCRIPTION: 111 | plot = movie.get('plot') 112 | if plot and len(plot) > 0: 113 | plot = plot[0] 114 | else: 115 | plot = movie.get('plot outline') 116 | if plot and len(plot) > 800: 117 | plot = plot[0:800] + "..." 118 | 119 | return { 120 | 'title': movie.get('title'), 121 | 'votes': movie.get('votes'), 122 | "aka": list_to_str(movie.get("akas")), 123 | "seasons": movie.get("number of seasons"), 124 | "box_office": movie.get('box office'), 125 | 'localized_title': movie.get('localized title'), 126 | 'kind': movie.get("kind"), 127 | "imdb_id": f"tt{movie.get('imdbID')}", 128 | "cast": list_to_str(movie.get("cast")), 129 | "runtime": list_to_str(movie.get("runtimes")), 130 | "countries": list_to_str(movie.get("countries")), 131 | "certificates": list_to_str(movie.get("certificates")), 132 | "languages": list_to_str(movie.get("languages")), 133 | "director": list_to_str(movie.get("director")), 134 | "writer":list_to_str(movie.get("writer")), 135 | "producer":list_to_str(movie.get("producer")), 136 | "composer":list_to_str(movie.get("composer")) , 137 | "cinematographer":list_to_str(movie.get("cinematographer")), 138 | "music_team": list_to_str(movie.get("music department")), 139 | "distributors": list_to_str(movie.get("distributors")), 140 | 'release_date': date, 141 | 'year': movie.get('year'), 142 | 'genres': list_to_str(movie.get("genres")), 143 | 'poster': movie.get('full-size cover url'), 144 | 'plot': plot, 145 | 'rating': str(movie.get("rating")), 146 | 'url':f'https://www.imdb.com/title/tt{movieid}' 147 | } 148 | # https://github.com/odysseusmax/animated-lamp/blob/2ef4730eb2b5f0596ed6d03e7b05243d93e3415b/bot/utils/broadcast.py#L37 149 | 150 | async def broadcast_messages(user_id, message): 151 | try: 152 | await message.copy(chat_id=user_id) 153 | return True, "Success" 154 | except FloodWait as e: 155 | await asyncio.sleep(e.x) 156 | return await broadcast_messages(user_id, message) 157 | except InputUserDeactivated: 158 | await db.delete_user(int(user_id)) 159 | logging.info(f"{user_id}-Removed from Database, since deleted account.") 160 | return False, "Deleted" 161 | except UserIsBlocked: 162 | logging.info(f"{user_id} -Blocked the bot.") 163 | return False, "Blocked" 164 | except PeerIdInvalid: 165 | await db.delete_user(int(user_id)) 166 | logging.info(f"{user_id} - PeerIdInvalid") 167 | return False, "Error" 168 | except Exception as e: 169 | return False, "Error" 170 | 171 | async def broadcast_messages_group(chat_id, message): 172 | try: 173 | kd = await message.copy(chat_id=chat_id) 174 | try: 175 | await kd.pin() 176 | except: 177 | pass 178 | return True, "Success" 179 | except FloodWait as e: 180 | await asyncio.sleep(e.x) 181 | return await broadcast_messages_group(chat_id, message) 182 | except Exception as e: 183 | return False, "Error" 184 | 185 | async def search_gagala(text): 186 | usr_agent = { 187 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' 188 | 'Chrome/61.0.3163.100 Safari/537.36' 189 | } 190 | text = text.replace(" ", '+') 191 | url = f'https://www.google.com/search?q={text}' 192 | response = requests.get(url, headers=usr_agent) 193 | response.raise_for_status() 194 | soup = BeautifulSoup(response.text, 'html.parser') 195 | titles = soup.find_all( 'h3' ) 196 | return [title.getText() for title in titles] 197 | 198 | async def get_settings(group_id): 199 | settings = temp.SETTINGS.get(group_id) 200 | if not settings: 201 | settings = await db.get_settings(group_id) 202 | temp.SETTINGS[group_id] = settings 203 | return settings 204 | 205 | async def save_group_settings(group_id, key, value): 206 | current = await get_settings(group_id) 207 | current[key] = value 208 | temp.SETTINGS[group_id] = current 209 | await db.update_settings(group_id, current) 210 | 211 | def get_size(size): 212 | """Get size in readable format""" 213 | 214 | units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"] 215 | size = float(size) 216 | i = 0 217 | while size >= 1024.0 and i < len(units): 218 | i += 1 219 | size /= 1024.0 220 | return "%.2f %s" % (size, units[i]) 221 | 222 | def split_list(l, n): 223 | for i in range(0, len(l), n): 224 | yield l[i:i + n] 225 | 226 | def get_file_id(msg: Message): 227 | if msg.media: 228 | for message_type in ( 229 | "photo", 230 | "animation", 231 | "audio", 232 | "document", 233 | "video", 234 | "video_note", 235 | "voice", 236 | "sticker" 237 | ): 238 | obj = getattr(msg, message_type) 239 | if obj: 240 | setattr(obj, "message_type", message_type) 241 | return obj 242 | 243 | def extract_user(message: Message) -> Union[int, str]: 244 | """extracts the user from a message""" 245 | # https://github.com/SpEcHiDe/PyroGramBot/blob/f30e2cca12002121bad1982f68cd0ff9814ce027/pyrobot/helper_functions/extract_user.py#L7 246 | user_id = None 247 | user_first_name = None 248 | if message.reply_to_message: 249 | user_id = message.reply_to_message.from_user.id 250 | user_first_name = message.reply_to_message.from_user.first_name 251 | 252 | elif len(message.command) > 1: 253 | if ( 254 | len(message.entities) > 1 and 255 | message.entities[1].type == enums.MessageEntityType.TEXT_MENTION 256 | ): 257 | 258 | required_entity = message.entities[1] 259 | user_id = required_entity.user.id 260 | user_first_name = required_entity.user.first_name 261 | else: 262 | user_id = message.command[1] 263 | # don't want to make a request -_- 264 | user_first_name = user_id 265 | try: 266 | user_id = int(user_id) 267 | except ValueError: 268 | pass 269 | else: 270 | user_id = message.from_user.id 271 | user_first_name = message.from_user.first_name 272 | return (user_id, user_first_name) 273 | 274 | def list_to_str(k): 275 | if not k: 276 | return "N/A" 277 | elif len(k) == 1: 278 | return str(k[0]) 279 | elif MAX_LIST_ELM: 280 | k = k[:int(MAX_LIST_ELM)] 281 | return ' '.join(f'{elem}, ' for elem in k) 282 | else: 283 | return ' '.join(f'{elem}, ' for elem in k) 284 | 285 | def last_online(from_user): 286 | time = "" 287 | if from_user.is_bot: 288 | time += "🤖 Bot :(" 289 | elif from_user.status == enums.UserStatus.RECENTLY: 290 | time += "Recently" 291 | elif from_user.status == enums.UserStatus.LAST_WEEK: 292 | time += "Within the last week" 293 | elif from_user.status == enums.UserStatus.LAST_MONTH: 294 | time += "Within the last month" 295 | elif from_user.status == enums.UserStatus.LONG_AGO: 296 | time += "A long time ago :(" 297 | elif from_user.status == enums.UserStatus.ONLINE: 298 | time += "Currently Online" 299 | elif from_user.status == enums.UserStatus.OFFLINE: 300 | time += from_user.last_online_date.strftime("%a, %d %b %Y, %H:%M:%S") 301 | return time 302 | 303 | 304 | def split_quotes(text: str) -> List: 305 | if not any(text.startswith(char) for char in START_CHAR): 306 | return text.split(None, 1) 307 | counter = 1 # ignore first char -> is some kind of quote 308 | while counter < len(text): 309 | if text[counter] == "\\": 310 | counter += 1 311 | elif text[counter] == text[0] or (text[0] == SMART_OPEN and text[counter] == SMART_CLOSE): 312 | break 313 | counter += 1 314 | else: 315 | return text.split(None, 1) 316 | 317 | # 1 to avoid starting quote, and counter is exclusive so avoids ending 318 | key = remove_escapes(text[1:counter].strip()) 319 | # index will be in range, or `else` would have been executed and returned 320 | rest = text[counter + 1:].strip() 321 | if not key: 322 | key = text[0] + text[0] 323 | return list(filter(None, [key, rest])) 324 | 325 | def gfilterparser(text, keyword): 326 | if "buttonalert" in text: 327 | text = (text.replace("\n", "\\n").replace("\t", "\\t")) 328 | buttons = [] 329 | note_data = "" 330 | prev = 0 331 | i = 0 332 | alerts = [] 333 | for match in BTN_URL_REGEX.finditer(text): 334 | # Check if btnurl is escaped 335 | n_escapes = 0 336 | to_check = match.start(1) - 1 337 | while to_check > 0 and text[to_check] == "\\": 338 | n_escapes += 1 339 | to_check -= 1 340 | 341 | # if even, not escaped -> create button 342 | if n_escapes % 2 == 0: 343 | note_data += text[prev:match.start(1)] 344 | prev = match.end(1) 345 | if match.group(3) == "buttonalert": 346 | # create a thruple with button label, url, and newline status 347 | if bool(match.group(5)) and buttons: 348 | buttons[-1].append(InlineKeyboardButton( 349 | text=match.group(2), 350 | callback_data=f"gfilteralert:{i}:{keyword}" 351 | )) 352 | else: 353 | buttons.append([InlineKeyboardButton( 354 | text=match.group(2), 355 | callback_data=f"gfilteralert:{i}:{keyword}" 356 | )]) 357 | i += 1 358 | alerts.append(match.group(4)) 359 | elif bool(match.group(5)) and buttons: 360 | buttons[-1].append(InlineKeyboardButton( 361 | text=match.group(2), 362 | url=match.group(4).replace(" ", "") 363 | )) 364 | else: 365 | buttons.append([InlineKeyboardButton( 366 | text=match.group(2), 367 | url=match.group(4).replace(" ", "") 368 | )]) 369 | 370 | else: 371 | note_data += text[prev:to_check] 372 | prev = match.start(1) - 1 373 | else: 374 | note_data += text[prev:] 375 | 376 | try: 377 | return note_data, buttons, alerts 378 | except: 379 | return note_data, buttons, None 380 | 381 | def parser(text, keyword): 382 | if "buttonalert" in text: 383 | text = (text.replace("\n", "\\n").replace("\t", "\\t")) 384 | buttons = [] 385 | note_data = "" 386 | prev = 0 387 | i = 0 388 | alerts = [] 389 | for match in BTN_URL_REGEX.finditer(text): 390 | # Check if btnurl is escaped 391 | n_escapes = 0 392 | to_check = match.start(1) - 1 393 | while to_check > 0 and text[to_check] == "\\": 394 | n_escapes += 1 395 | to_check -= 1 396 | 397 | # if even, not escaped -> create button 398 | if n_escapes % 2 == 0: 399 | note_data += text[prev:match.start(1)] 400 | prev = match.end(1) 401 | if match.group(3) == "buttonalert": 402 | # create a thruple with button label, url, and newline status 403 | if bool(match.group(5)) and buttons: 404 | buttons[-1].append(InlineKeyboardButton( 405 | text=match.group(2), 406 | callback_data=f"alertmessage:{i}:{keyword}" 407 | )) 408 | else: 409 | buttons.append([InlineKeyboardButton( 410 | text=match.group(2), 411 | callback_data=f"alertmessage:{i}:{keyword}" 412 | )]) 413 | i += 1 414 | alerts.append(match.group(4)) 415 | elif bool(match.group(5)) and buttons: 416 | buttons[-1].append(InlineKeyboardButton( 417 | text=match.group(2), 418 | url=match.group(4).replace(" ", "") 419 | )) 420 | else: 421 | buttons.append([InlineKeyboardButton( 422 | text=match.group(2), 423 | url=match.group(4).replace(" ", "") 424 | )]) 425 | 426 | else: 427 | note_data += text[prev:to_check] 428 | prev = match.start(1) - 1 429 | else: 430 | note_data += text[prev:] 431 | 432 | try: 433 | return note_data, buttons, alerts 434 | except: 435 | return note_data, buttons, None 436 | 437 | def remove_escapes(text: str) -> str: 438 | res = "" 439 | is_escaped = False 440 | for counter in range(len(text)): 441 | if is_escaped: 442 | res += text[counter] 443 | is_escaped = False 444 | elif text[counter] == "\\": 445 | is_escaped = True 446 | else: 447 | res += text[counter] 448 | return res 449 | 450 | 451 | def humanbytes(size): 452 | if not size: 453 | return "" 454 | power = 2**10 455 | n = 0 456 | Dic_powerN = {0: ' ', 1: 'Ki', 2: 'Mi', 3: 'Gi', 4: 'Ti'} 457 | while size > power: 458 | size /= power 459 | n += 1 460 | return str(round(size, 2)) + " " + Dic_powerN[n] + 'B' 461 | 462 | async def get_shortlink(chat_id, link): 463 | settings = await get_settings(chat_id) #fetching settings for group 464 | if 'shortlink' in settings.keys(): 465 | URL = settings['shortlink'] 466 | API = settings['shortlink_api'] 467 | else: 468 | URL = SHORTLINK_URL 469 | API = SHORTLINK_API 470 | if URL.startswith("shorturllink") or URL.startswith("terabox.in") or URL.startswith("urlshorten.in"): 471 | URL = SHORTLINK_URL 472 | API = SHORTLINK_API 473 | if URL == "api.shareus.io": 474 | # method 1: 475 | # https = link.split(":")[0] #splitting https or http from link 476 | # if "http" == https: #if https == "http": 477 | # https = "https" 478 | # link = link.replace("http", https) #replacing http to https 479 | # conn = http.client.HTTPSConnection("api.shareus.io") 480 | # payload = json.dumps({ 481 | # "api_key": "4c1YTBacB6PTuwogBiEIFvZN5TI3", 482 | # "monetization": True, 483 | # "destination": link, 484 | # "ad_page": 3, 485 | # "category": "Entertainment", 486 | # "tags": ["trendinglinks"], 487 | # "monetize_with_money": False, 488 | # "price": 0, 489 | # "currency": "INR", 490 | # "purchase_note":"" 491 | 492 | # }) 493 | # headers = { 494 | # 'Keep-Alive': '', 495 | # 'Content-Type': 'application/json' 496 | # } 497 | # conn.request("POST", "/generate_link", payload, headers) 498 | # res = conn.getresponse() 499 | # data = res.read().decode("utf-8") 500 | # parsed_data = json.loads(data) 501 | # if parsed_data["status"] == "success": 502 | # return parsed_data["link"] 503 | #method 2 504 | url = f'https://{URL}/easy_api' 505 | params = { 506 | "key": API, 507 | "link": link, 508 | } 509 | try: 510 | async with aiohttp.ClientSession() as session: 511 | async with session.get(url, params=params, raise_for_status=True, ssl=False) as response: 512 | data = await response.text() 513 | return data 514 | except Exception as e: 515 | logger.error(e) 516 | return link 517 | else: 518 | shortzy = Shortzy(api_key=API, base_site=URL) 519 | link = await shortzy.convert(link) 520 | return link 521 | 522 | async def get_tutorial(chat_id): 523 | settings = await get_settings(chat_id) #fetching settings for group 524 | if 'tutorial' in settings.keys(): 525 | if settings['is_tutorial']: 526 | TUTORIAL_URL = settings['tutorial'] 527 | else: 528 | TUTORIAL_URL = TUTORIAL 529 | else: 530 | TUTORIAL_URL = TUTORIAL 531 | return TUTORIAL_URL 532 | 533 | async def get_verify_shorted_link(link): 534 | API = SHORTLINK_API 535 | URL = SHORTLINK_URL 536 | https = link.split(":")[0] 537 | if "http" == https: 538 | https = "https" 539 | link = link.replace("http", https) 540 | 541 | if URL == "api.shareus.in": 542 | url = f"https://{URL}/shortLink" 543 | params = {"token": API, 544 | "format": "json", 545 | "link": link, 546 | } 547 | try: 548 | async with aiohttp.ClientSession() as session: 549 | async with session.get(url, params=params, raise_for_status=True, ssl=False) as response: 550 | data = await response.json(content_type="text/html") 551 | if data["status"] == "success": 552 | return data["shortlink"] 553 | else: 554 | logger.error(f"Error: {data['message']}") 555 | return f'https://{URL}/shortLink?token={API}&format=json&link={link}' 556 | 557 | except Exception as e: 558 | logger.error(e) 559 | return f'https://{URL}/shortLink?token={API}&format=json&link={link}' 560 | else: 561 | url = f'https://{URL}/api' 562 | params = {'api': API, 563 | 'url': link, 564 | } 565 | try: 566 | async with aiohttp.ClientSession() as session: 567 | async with session.get(url, params=params, raise_for_status=True, ssl=False) as response: 568 | data = await response.json() 569 | if data["status"] == "success": 570 | return data['shortenedUrl'] 571 | else: 572 | logger.error(f"Error: {data['message']}") 573 | return f'https://{URL}/api?api={API}&link={link}' 574 | 575 | except Exception as e: 576 | logger.error(e) 577 | return f'{URL}/api?api={API}&link={link}' 578 | 579 | async def check_token(bot, userid, token): 580 | user = await bot.get_users(userid) 581 | if not await db.is_user_exist(user.id): 582 | await db.add_user(user.id, user.first_name) 583 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(user.id, user.mention)) 584 | if user.id in TOKENS.keys(): 585 | TKN = TOKENS[user.id] 586 | if token in TKN.keys(): 587 | is_used = TKN[token] 588 | if is_used == True: 589 | return False 590 | else: 591 | return True 592 | else: 593 | return False 594 | 595 | async def get_token(bot, userid, link): 596 | user = await bot.get_users(userid) 597 | if not await db.is_user_exist(user.id): 598 | await db.add_user(user.id, user.first_name) 599 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(user.id, user.mention)) 600 | token = ''.join(random.choices(string.ascii_letters + string.digits, k=7)) 601 | TOKENS[user.id] = {token: False} 602 | link = f"{link}verify-{user.id}-{token}" 603 | shortened_verify_url = await get_verify_shorted_link(link) 604 | return str(shortened_verify_url) 605 | 606 | async def verify_user(bot, userid, token): 607 | user = await bot.get_users(userid) 608 | if not await db.is_user_exist(user.id): 609 | await db.add_user(user.id, user.first_name) 610 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(user.id, user.mention)) 611 | TOKENS[user.id] = {token: True} 612 | tz = pytz.timezone('Asia/Kolkata') 613 | today = date.today() 614 | VERIFIED[user.id] = str(today) 615 | 616 | async def check_verification(bot, userid): 617 | user = await bot.get_users(userid) 618 | if not await db.is_user_exist(user.id): 619 | await db.add_user(user.id, user.first_name) 620 | await bot.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(user.id, user.mention)) 621 | tz = pytz.timezone('Asia/Kolkata') 622 | today = date.today() 623 | if user.id in VERIFIED.keys(): 624 | EXP = VERIFIED[user.id] 625 | years, month, day = EXP.split('-') 626 | comp = date(int(years), int(month), int(day)) 627 | if compHᴇʏ ᴛʜᴇʀᴇ {user_name} 👋🏽 \n\n✅ Sᴇᴄᴜʀᴇ ʟɪɴᴋ ᴛᴏ ʏᴏᴜʀ ғɪʟᴇ ʜᴀs sᴜᴄᴄᴇssғᴜʟʟʏ ʙᴇᴇɴ ɢᴇɴᴇʀᴀᴛᴇᴅ ᴘʟᴇᴀsᴇ ᴄʟɪᴄᴋ ᴅᴏᴡɴʟᴏᴀᴅ ʙᴜᴛᴛᴏɴ\n\n🗃️ Fɪʟᴇ Nᴀᴍᴇ : {title}\n🔖 Fɪʟᴇ Sɪᴢᴇ : {size}
", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("📤 Dᴏᴡɴʟᴏᴀᴅ 📥", url=await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=files_{file.file_id}"))]])) 648 | else: 649 | for file in files: 650 | f_caption = file.caption 651 | title = file.file_name 652 | size = get_size(file.file_size) 653 | if CUSTOM_FILE_CAPTION: 654 | try: 655 | f_caption = CUSTOM_FILE_CAPTION.format(file_name='' if title is None else title, 656 | file_size='' if size is None else size, 657 | file_caption='' if f_caption is None else f_caption) 658 | except Exception as e: 659 | print(e) 660 | f_caption = f_caption 661 | if f_caption is None: 662 | f_caption = f"{title}" 663 | await bot.send_cached_media( 664 | chat_id=userid, 665 | file_id=file.file_id, 666 | caption=f_caption, 667 | protect_content=True if ident == "filep" else False, 668 | reply_markup=InlineKeyboardMarkup( 669 | [ 670 | [ 671 | InlineKeyboardButton('Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url="https://t.me/kissuhelp"), 672 | InlineKeyboardButton('Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ', url="https://t.me/kissuxbots") 673 | ],[ 674 | InlineKeyboardButton("Bᴏᴛ Oᴡɴᴇʀ", url="t.me/xaekks") 675 | ] 676 | ] 677 | ) 678 | ) 679 | except UserIsBlocked: 680 | await query.answer('Uɴʙʟᴏᴄᴋ ᴛʜᴇ ʙᴏᴛ ᴍᴀʜɴ !', show_alert=True) 681 | except PeerIdInvalid: 682 | await query.answer('Hᴇʏ, Sᴛᴀʀᴛ Bᴏᴛ Fɪʀsᴛ Aɴᴅ Cʟɪᴄᴋ Sᴇɴᴅ Aʟʟ', show_alert=True) 683 | except Exception as e: 684 | await query.answer('Hᴇʏ, Sᴛᴀʀᴛ Bᴏᴛ Fɪʀsᴛ Aɴᴅ Cʟɪᴄᴋ Sᴇɴᴅ Aʟʟ', show_alert=True) 685 | -------------------------------------------------------------------------------- /plugins/commands.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import random 4 | import asyncio 5 | from Script import script 6 | from pyrogram import Client, filters, enums 7 | from pyrogram.errors import ChatAdminRequired, FloodWait 8 | from pyrogram.types import * 9 | from database.ia_filterdb import Media, get_file_details, unpack_new_file_id, get_bad_files 10 | from database.users_chats_db import db 11 | from info import CHANNELS, ADMINS, AUTH_CHANNEL, LOG_CHANNEL, PICS, VRFIED_IMG, VRFY_IMG, BATCH_FILE_CAPTION, CUSTOM_FILE_CAPTION, PROTECT_CONTENT, CHNL_LNK, GRP_LNK, SPRT_CHNL, REQ_GRP, REQST_CHANNEL, SUPPORT_CHAT_ID, SUPPORT_CHAT, MAX_B_TN, VERIFY, SHORTLINK_API, SHORTLINK_URL, TUTORIAL, IS_TUTORIAL, HOW_TO_VERIFY, PREMIUM_USER 12 | from utils import get_settings, get_size, is_subscribed, save_group_settings, temp, verify_user, check_token, check_verification, get_token, get_shortlink, get_tutorial 13 | from database.connections_mdb import active_connection 14 | # from plugins.pm_filter import ENABLE_SHORTLINK 15 | import re, asyncio, os, sys 16 | import json 17 | import base64 18 | logger = logging.getLogger(__name__) 19 | 20 | 21 | BATCH_FILES = {} 22 | 23 | @Client.on_message(filters.command("start") & filters.incoming) 24 | async def start(client, message): 25 | if message.chat.type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 26 | buttons = [[ 27 | InlineKeyboardButton('🛡️ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ 🛡️', url=f'http://t.me/{temp.U_NAME}?startgroup=true') 28 | ],[ 29 | InlineKeyboardButton('↼ Sᴜᴘᴘᴏʀᴛ Gʀᴏᴜᴘ', url=SPRT_CHNL), 30 | InlineKeyboardButton('Sᴇᴀʀᴄʜ 🔎 ', url=GRP_LNK) 31 | ]] 32 | reply_markup = InlineKeyboardMarkup(buttons) 33 | await message.reply(script.START_TXT.format(message.from_user.mention if message.from_user else message.chat.title, temp.U_NAME, temp.B_NAME), reply_markup=reply_markup, disable_web_page_preview=True) 34 | await asyncio.sleep(2) # 😢 https://github.com/EvamariaTG/EvaMaria/blob/master/plugins/p_ttishow.py#L17 😬 wait a bit, before checking. 35 | if not await db.get_chat(message.chat.id): 36 | total=await client.get_chat_members_count(message.chat.id) 37 | await client.send_message(LOG_CHANNEL, script.LOG_TEXT_G.format(message.chat.title, message.chat.id, total, "Unknown")) 38 | await db.add_chat(message.chat.id, message.chat.title) 39 | return 40 | if not await db.is_user_exist(message.from_user.id): 41 | await db.add_user(message.from_user.id, message.from_user.first_name) 42 | await client.send_message(LOG_CHANNEL, script.LOG_TEXT_P.format(message.from_user.id, message.from_user.mention)) 43 | if len(message.command) != 2: 44 | buttons = [[ 45 | InlineKeyboardButton('➕ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ ➕', url=f'http://t.me/{temp.U_NAME}?startgroup=true') 46 | ],[ 47 | InlineKeyboardButton("Sᴇᴀʀᴄʜ 🔎",url=REQ_GRP), 48 | InlineKeyboardButton("📌 Uᴘᴅᴀᴛᴇs", url="https://t.me/kissuxbots") 49 | ],[ 50 | InlineKeyboardButton("Hᴇʟᴩ 💡", callback_data="help"), 51 | InlineKeyboardButton("Aʙᴏᴜᴛ 📰", callback_data="about") 52 | ],[ 53 | InlineKeyboardButton(" Make Your Own Bot", url="https://GitHub.com/pykinsu/tele-filter-bot/") 54 | ]] 55 | reply_markup = InlineKeyboardMarkup(buttons) 56 | m=await message.reply_sticker("CAACAgQAAxkBAAEOHdZn2piuieMXbUOL_7I2Iqb9ArF19QACKwoAArAqAVIMufqlVovwXzYE") 57 | await asyncio.sleep(1) 58 | await m.delete() 59 | await message.reply_photo( 60 | photo=random.choice(PICS), 61 | caption=script.START_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME), 62 | reply_markup=reply_markup, 63 | parse_mode=enums.ParseMode.HTML 64 | ) 65 | return 66 | 67 | if AUTH_CHANNEL and not await is_subscribed(client, message): 68 | try: 69 | invite_link = await client.create_chat_invite_link(int(AUTH_CHANNEL)) 70 | except ChatAdminRequired: 71 | logger.error("Make sure Bot is admin in Forcesub channel") 72 | return 73 | btn = [ 74 | [ 75 | InlineKeyboardButton( 76 | "↺ Jᴏɪɴ Oᴜʀ Bᴀᴄᴋ-ᴜᴘ Cʜᴀɴɴᴇʟ ↺", url=invite_link.invite_link 77 | ) 78 | ] 79 | ] 80 | 81 | if message.command[1] != "subscribe": 82 | try: 83 | kk, file_id = message.command[1].split("_", 1) 84 | btn.append([InlineKeyboardButton("↺ Tʀʏ Aɢᴀɪɴ", callback_data=f"checksub#{kk}#{file_id}")]) 85 | except (IndexError, ValueError): 86 | btn.append([InlineKeyboardButton("↺ Tʀʏ Aɢᴀɪɴ", url=f"https://t.me/{temp.U_NAME}?start={message.command[1]}")]) 87 | await client.send_photo( 88 | photo=random.choice(PICS), 89 | chat_id=message.from_user.id, 90 | # text="**You are not in our channel given below so you don't get the movie file...\n\nIf you want the movie file, click on the '🍿ᴊᴏɪɴ ᴏᴜʀ ʙᴀᴄᴋ-ᴜᴘ ᴄʜᴀɴɴᴇʟ🍿' button below and join our back-up channel, then click on the '🔄 Try Again' button below...\n\nThen you will get the movie files...**", 91 | caption=script.FORCE_SUB, 92 | reply_markup=InlineKeyboardMarkup(btn), 93 | parse_mode=enums.ParseMode.MARKDOWN 94 | ) 95 | return 96 | if len(message.command) == 2 and message.command[1] in ["subscribe", "error", "okay", "help"]: 97 | buttons = [[ 98 | InlineKeyboardButton('➕ Aᴅᴅ Mᴇ Tᴏ Yᴏᴜʀ Gʀᴏᴜᴘ ➕', url=f'http://t.me/{temp.U_NAME}?startgroup=true') 99 | ],[ 100 | InlineKeyboardButton("Sᴇᴀʀᴄʜ 🔎",url=REQ_GRP), 101 | InlineKeyboardButton("📌 Uᴘᴅᴀᴛᴇs", url="https://t.me/kissuxbots") 102 | ],[ 103 | InlineKeyboardButton("Hᴇʟᴩ 💡", callback_data="help"), 104 | InlineKeyboardButton("Aʙᴏᴜᴛ 📰", callback_data="about") 105 | ],[ 106 | InlineKeyboardButton(" Make Your Own Bot", url="https://GitHub.com/pykinsu/tele-filter-bot/") 107 | ]] 108 | reply_markup = InlineKeyboardMarkup(buttons) 109 | await message.reply_photo( 110 | photo=random.choice(PICS), 111 | caption=script.START_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME), 112 | reply_markup=reply_markup, 113 | parse_mode=enums.ParseMode.HTML 114 | ) 115 | return 116 | data = message.command[1] 117 | try: 118 | pre, file_id = data.split('_', 1) 119 | except: 120 | file_id = data 121 | pre = "" 122 | if data.split("-", 1)[0] == "BATCH": 123 | sts = await message.reply("Please wait...") 124 | file_id = data.split("-", 1)[1] 125 | msgs = BATCH_FILES.get(file_id) 126 | if not msgs: 127 | file = await client.download_media(file_id) 128 | try: 129 | with open(file) as file_data: 130 | msgs=json.loads(file_data.read()) 131 | except: 132 | await sts.edit("FAILED") 133 | return await client.send_message(LOG_CHANNEL, "UNABLE TO OPEN FILE.") 134 | os.remove(file) 135 | BATCH_FILES[file_id] = msgs 136 | for msg in msgs: 137 | title = msg.get("title") 138 | size=get_size(int(msg.get("size", 0))) 139 | f_caption=msg.get("caption", "") 140 | if BATCH_FILE_CAPTION: 141 | try: 142 | f_caption=BATCH_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) 143 | except Exception as e: 144 | logger.exception(e) 145 | f_caption=f_caption 146 | if f_caption is None: 147 | f_caption = f"{title}" 148 | try: 149 | await client.send_cached_media( 150 | chat_id=message.from_user.id, 151 | file_id=msg.get("file_id"), 152 | caption=f_caption, 153 | protect_content=msg.get('protect', False)) 154 | except FloodWait as e: 155 | await asyncio.sleep(e.x) 156 | logger.warning(f"Floodwait of {e.x} sec.") 157 | await client.send_cached_media( 158 | chat_id=message.from_user.id, 159 | file_id=msg.get("file_id"), 160 | caption=f_caption, 161 | protect_content=msg.get('protect', False), 162 | ) 163 | except Exception as e: 164 | logger.warning(e, exc_info=True) 165 | continue 166 | await asyncio.sleep(1) 167 | await sts.delete() 168 | return 169 | 170 | elif data.split("-", 1)[0] == "DSTORE": 171 | sts = await message.reply("Please wait...") 172 | b_string = data.split("-", 1)[1] 173 | decoded = (base64.urlsafe_b64decode(b_string + "=" * (-len(b_string) % 4))).decode("ascii") 174 | try: 175 | f_msg_id, l_msg_id, f_chat_id, protect = decoded.split("_", 3) 176 | except: 177 | f_msg_id, l_msg_id, f_chat_id = decoded.split("_", 2) 178 | protect = "/pbatch" if PROTECT_CONTENT else "batch" 179 | diff = int(l_msg_id) - int(f_msg_id) 180 | async for msg in client.iter_messages(int(f_chat_id), int(l_msg_id), int(f_msg_id)): 181 | if msg.media: 182 | media = getattr(msg, msg.media.value) 183 | if BATCH_FILE_CAPTION: 184 | try: 185 | f_caption=BATCH_FILE_CAPTION.format(file_name=getattr(media, 'file_name', ''), file_size=getattr(media, 'file_size', ''), file_caption=getattr(msg, 'caption', '')) 186 | except Exception as e: 187 | logger.exception(e) 188 | f_caption = getattr(msg, 'caption', '') 189 | else: 190 | media = getattr(msg, msg.media.value) 191 | file_name = getattr(media, 'file_name', '') 192 | f_caption = getattr(msg, 'caption', file_name) 193 | try: 194 | await msg.copy(message.chat.id, caption=f_caption, protect_content=True if protect == "/pbatch" else False) 195 | except FloodWait as e: 196 | await asyncio.sleep(e.x) 197 | await msg.copy(message.chat.id, caption=f_caption, protect_content=True if protect == "/pbatch" else False) 198 | except Exception as e: 199 | logger.exception(e) 200 | continue 201 | elif msg.empty: 202 | continue 203 | else: 204 | try: 205 | await msg.copy(message.chat.id, protect_content=True if protect == "/pbatch" else False) 206 | except FloodWait as e: 207 | await asyncio.sleep(e.x) 208 | await msg.copy(message.chat.id, protect_content=True if protect == "/pbatch" else False) 209 | except Exception as e: 210 | logger.exception(e) 211 | continue 212 | await asyncio.sleep(1) 213 | return await sts.delete() 214 | 215 | elif data.split("-", 1)[0] == "verify": 216 | userid = data.split("-", 2)[1] 217 | token = data.split("-", 3)[2] 218 | if str(message.from_user.id) != str(userid): 219 | return await message.reply_text( 220 | text="Iɴᴠᴀʟɪᴅ Lɪɴᴋ ᴏʀ Exᴘɪʀᴇᴅ Lɪɴᴋ !", 221 | protect_content=True 222 | ) 223 | is_valid = await check_token(client, userid, token) 224 | if is_valid == True: 225 | await message.reply_photo( 226 | photo = VRFIED_IMG, 227 | caption = script.VERIFED_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME), 228 | # protect_content=True 229 | ) 230 | await verify_user(client, userid, token) 231 | else: 232 | return await message.reply_text( 233 | text="Iɴᴠᴀʟɪᴅ Lɪɴᴋ ᴏʀ Exᴘɪʀᴇᴅ Lɪɴᴋ !", 234 | # protect_content=True 235 | ) 236 | if data.startswith("sendfiles"): 237 | chat_id = int("-" + file_id.split("-")[1]) 238 | userid = message.from_user.id if message.from_user else None 239 | g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=allfiles_{file_id}") 240 | k = await client.send_message(chat_id=message.from_user.id,text=f"Get All Files in a Single Click!!!\n\n📂 ʟɪɴᴋ ➠ : {g}\n\nNote: This message is deleted in 5 mins to avoid copyrights. Save the link to Somewhere else", reply_markup=InlineKeyboardMarkup( 241 | [ 242 | [ 243 | InlineKeyboardButton('📂 Dᴏᴡɴʟᴏᴀᴅ Nᴏᴡ 📂', url=g) 244 | ], [ 245 | InlineKeyboardButton('🤔 Hᴏᴡ Tᴏ Dᴏᴡɴʟᴏᴀᴅ 🤔', url=await get_tutorial(chat_id)) 246 | ] 247 | ] 248 | ) 249 | ) 250 | await asyncio.sleep(300) 251 | await k.edit("Yᴏᴜʀ ᴍᴇssᴀɢᴇ ɪs sᴜᴄᴄᴇssғᴜʟʟʏ ᴅᴇʟᴇᴛᴇᴅ!!!") 252 | return 253 | 254 | 255 | elif data.startswith("short"): 256 | user = message.from_user.id 257 | chat_id = temp.SHORT.get(user) 258 | files_ = await get_file_details(file_id) 259 | files = files_[0] 260 | g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=file_{file_id}") 261 | k = await client.send_message(chat_id=user,text=f"📕Nᴀᴍᴇ ➠ : {files.file_name} \n\n🔗Sɪᴢᴇ ➠ : {get_size(files.file_size)}\n\n📂Fɪʟᴇ ʟɪɴᴋ ➠ : {g}\n\nNote: This message is deleted in 20 mins to avoid copyrights. Save the link to Somewhere else", reply_markup=InlineKeyboardMarkup( 262 | [ 263 | [ 264 | InlineKeyboardButton('📂 Dᴏᴡɴʟᴏᴀᴅ Nᴏᴡ 📂', url=g) 265 | ], [ 266 | InlineKeyboardButton('🤔 Hᴏᴡ Tᴏ Dᴏᴡɴʟᴏᴀᴅ 🤔', url=await get_tutorial(chat_id)) 267 | ] 268 | ] 269 | ) 270 | ) 271 | await asyncio.sleep(1200) 272 | await k.edit("Yᴏᴜʀ ᴍᴇssᴀɢᴇ ɪs sᴜᴄᴄᴇssғᴜʟʟʏ ᴅᴇʟᴇᴛᴇᴅ!!!") 273 | return 274 | 275 | elif data.startswith("all"): 276 | files = temp.GETALL.get(file_id) 277 | if not files: 278 | return await message.reply('Nᴏ Sᴜᴄʜ Fɪʟᴇ Eᴇxɪsᴛ.') 279 | filesarr = [] 280 | for file in files: 281 | file_id = file.file_id 282 | files_ = await get_file_details(file_id) 283 | files1 = files_[0] 284 | title = ' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files1.file_name.split())) 285 | size=get_size(files1.file_size) 286 | f_caption=files1.caption 287 | if CUSTOM_FILE_CAPTION: 288 | try: 289 | 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) 290 | except Exception as e: 291 | logger.exception(e) 292 | f_caption=f_caption 293 | if f_caption is None: 294 | f_caption = f"{' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files1.file_name.split()))}" 295 | if not await check_verification(client, message.from_user.id) and VERIFY == True: 296 | btn = [[ 297 | InlineKeyboardButton("♻️ Vᴇʀɪғʏ ♻️", url=await get_token(client, message.from_user.id, f"https://telegram.me/{temp.U_NAME}?start=")), 298 | InlineKeyboardButton("⚠️ Hᴏᴡ Tᴏ Vᴇʀɪғʏ ⚠️", url=HOW_TO_VERIFY) 299 | ]] 300 | await message.reply_photo( 301 | photo = VRFY_IMG, 302 | caption=script.VERIFY_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME), 303 | # protect_content=True, 304 | reply_markup=InlineKeyboardMarkup(btn) 305 | ) 306 | return 307 | msg = await client.send_cached_media( 308 | chat_id=message.from_user.id, 309 | file_id=file_id, 310 | caption=f_caption, 311 | protect_content=True if pre == 'filep' else False, 312 | ) 313 | # filesarr.append(msg) 314 | # k = await client.send_message(chat_id = message.from_user.id, text=f"❗️❗️❗️IMPORTANT❗️️❗️❗️\n\nThis Movie Files/Videos will be deleted in 10 mins 🫥 (Due to Copyright Issues).\n\nPlease forward this ALL Files/Videos to your Saved Messages and Start Download there") 315 | # await asyncio.sleep(600) 316 | # for x in filesarr: 317 | # await x.delete() 318 | # await k.edit_text("Your All Files/Videos is successfully deleted!!!") 319 | # return 320 | 321 | elif data.startswith("files"): 322 | user = message.from_user.id 323 | if temp.SHORT.get(user)==None: 324 | await message.reply_text(text="Please Search Again in Group") 325 | else: 326 | chat_id = temp.SHORT.get(user) 327 | settings = await get_settings(chat_id) 328 | if settings['is_shortlink'] and user not in PREMIUM_USER: 329 | files_ = await get_file_details(file_id) 330 | files = files_[0] 331 | g = await get_shortlink(chat_id, f"https://telegram.me/{temp.U_NAME}?start=file_{file_id}") 332 | k = await client.send_message(chat_id=message.from_user.id,text=f"📕Nᴀᴍᴇ ➠ : {files.file_name} \n\n🔗Sɪᴢᴇ ➠ : {get_size(files.file_size)}\n\n📂Fɪʟᴇ ʟɪɴᴋ ➠ : {g}\n\nNote: This message is deleted in 20 mins to avoid copyrights. Save the link to Somewhere else", reply_markup=InlineKeyboardMarkup( 333 | [ 334 | [ 335 | InlineKeyboardButton('📂 Dᴏᴡɴʟᴏᴀᴅ Nᴏᴡ 📂', url=g) 336 | ], [ 337 | InlineKeyboardButton('🤔 Hᴏᴡ Tᴏ Dᴏᴡɴʟᴏᴀᴅ 🤔', url=await get_tutorial(chat_id)) 338 | ] 339 | ] 340 | ) 341 | ) 342 | await asyncio.sleep(1200) 343 | await k.edit("Yᴏᴜʀ ᴍᴇssᴀɢᴇ ɪs sᴜᴄᴄᴇssғᴜʟʟʏ ᴅᴇʟᴇᴛᴇᴅ!!!") 344 | return 345 | user = message.from_user.id 346 | files_ = await get_file_details(file_id) 347 | if not files_: 348 | pre, file_id = ((base64.urlsafe_b64decode(data + "=" * (-len(data) % 4))).decode("ascii")).split("_", 1) 349 | try: 350 | if not await check_verification(client, message.from_user.id) and VERIFY == True: 351 | btn = [[ 352 | InlineKeyboardButton("♻️ Vᴇʀɪғʏ ♻️", url=await get_token(client, message.from_user.id, f"https://telegram.me/{temp.U_NAME}?start=")), 353 | InlineKeyboardButton("⚠️ Hᴏᴡ Tᴏ Vᴇʀɪғʏ ⚠️", url=HOW_TO_VERIFY) 354 | ]] 355 | await message.reply_photo( 356 | photo = VRFY_IMG, 357 | caption=script.VERIFY_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME), 358 | # protect_content=True, 359 | reply_markup=InlineKeyboardMarkup(btn) 360 | ) 361 | return 362 | msg = await client.send_cached_media( 363 | chat_id=message.from_user.id, 364 | file_id=file_id, 365 | protect_content=True if pre == 'filep' else False, 366 | ) 367 | filetype = msg.media 368 | file = getattr(msg, filetype.value) 369 | title = ''.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files.file_name.split())) 370 | size=get_size(file.file_size) 371 | f_caption = f"{title}" 372 | if CUSTOM_FILE_CAPTION: 373 | try: 374 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='') 375 | except: 376 | return 377 | # await msg.edit_caption(f_caption) 378 | # btn = [[ 379 | # InlineKeyboardButton("Get File Again", callback_data=f'delfile#{file_id}') 380 | # ]] 381 | # k = await msg.reply("❗️❗️❗️IMPORTANT❗️️❗️❗️\n\nThis Movie File/Video will be deleted in 10 mins 🫥 (Due to Copyright Issues).\n\nPlease forward this File/Video to your Saved Messages and Start Download there",quote=True) 382 | # await asyncio.sleep(600) 383 | # await msg.delete() 384 | # await k.edit_text("Your File/Video is successfully deleted!!!\n\nClick below button to get your deleted file 👇",reply_markup=InlineKeyboardMarkup(btn)) 385 | # return 386 | except: 387 | pass 388 | return await message.reply('Nᴏ Sᴜᴄʜ Fɪʟᴇ Eᴇxɪsᴛ.') 389 | files = files_[0] 390 | title = ''.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files.file_name.split())) 391 | size=get_size(files.file_size) 392 | f_caption=files.caption 393 | if CUSTOM_FILE_CAPTION: 394 | try: 395 | 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) 396 | except Exception as e: 397 | logger.exception(e) 398 | f_caption=f_caption 399 | if f_caption is None: 400 | f_caption = f"{' '.join(filter(lambda x: not x.startswith('[') and not x.startswith('@'), files.file_name.split()))}" 401 | if not await check_verification(client, message.from_user.id) and VERIFY == True: 402 | btn = [[ 403 | InlineKeyboardButton("♻️ Vᴇʀɪғʏ ♻️", url=await get_token(client, message.from_user.id, f"https://telegram.me/{temp.U_NAME}?start=")), 404 | InlineKeyboardButton("⚠️ Hᴏᴡ Tᴏ Vᴇʀɪғʏ ⚠️", url=HOW_TO_VERIFY) 405 | ]] 406 | await message.reply_photo( 407 | photo = VRFY_IMG, 408 | caption=script.VERIFY_TXT.format(message.from_user.mention, temp.U_NAME, temp.B_NAME), 409 | # protect_content=True, 410 | reply_markup=InlineKeyboardMarkup(btn) 411 | ) 412 | return 413 | msg = await client.send_cached_media( 414 | chat_id=message.from_user.id, 415 | file_id=file_id, 416 | caption=f_caption, 417 | protect_content=True if pre == 'filep' else False, 418 | ) 419 | # btn = [[ 420 | # InlineKeyboardButton("Get File Again", callback_data=f'delfile#{file_id}') 421 | # ]] 422 | # k = await msg.reply("❗️❗️❗️IMPORTANT❗️️❗️❗️\n\nThis Movie File/Video will be deleted in 10 mins 🫥 (Due to Copyright Issues).\n\nPlease forward this File/Video to your Saved Messages and Start Download there",quote=True) 423 | # await asyncio.sleep(600) 424 | # await msg.delete() 425 | # await k.edit_text("Your File/Video is successfully deleted!!!\n\nClick below button to get your deleted file 👇",reply_markup=InlineKeyboardMarkup(btn)) 426 | # return 427 | 428 | @Client.on_message(filters.command('channel') & filters.user(ADMINS)) 429 | async def channel_info(bot, message): 430 | 431 | """Send basic information of channel""" 432 | if isinstance(CHANNELS, (int, str)): 433 | channels = [CHANNELS] 434 | elif isinstance(CHANNELS, list): 435 | channels = CHANNELS 436 | else: 437 | raise ValueError("Unexpected type of CHANNELS") 438 | 439 | text = '📑 **Indexed channels/groups**\n' 440 | for channel in channels: 441 | chat = await bot.get_chat(channel) 442 | if chat.username: 443 | text += '\n@' + chat.username 444 | else: 445 | text += '\n' + chat.title or chat.first_name 446 | 447 | text += f'\n\n**Total:** {len(CHANNELS)}' 448 | 449 | if len(text) < 4096: 450 | await message.reply(text) 451 | else: 452 | file = 'Indexed channels.txt' 453 | with open(file, 'w') as f: 454 | f.write(text) 455 | await message.reply_document(file) 456 | os.remove(file) 457 | 458 | 459 | @Client.on_message(filters.command('logs') & filters.user(ADMINS)) 460 | async def log_file(bot, message): 461 | """Send log file""" 462 | try: 463 | await message.reply_document('TelegramBot.log') 464 | except Exception as e: 465 | await message.reply(str(e)) 466 | 467 | @Client.on_message(filters.command('delete') & filters.user(ADMINS)) 468 | async def delete(bot, message): 469 | """Delete file from database""" 470 | reply = message.reply_to_message 471 | if reply and reply.media: 472 | msg = await message.reply("Processing...⏳", quote=True) 473 | else: 474 | await message.reply('Reply to file with /delete which you want to delete', quote=True) 475 | return 476 | 477 | for file_type in ("document", "video", "audio"): 478 | media = getattr(reply, file_type, None) 479 | if media is not None: 480 | break 481 | else: 482 | await msg.edit('This is not supported file format') 483 | return 484 | 485 | file_id, file_ref = unpack_new_file_id(media.file_id) 486 | 487 | result = await Media.collection.delete_one({ 488 | '_id': file_id, 489 | }) 490 | if result.deleted_count: 491 | await msg.edit('File is successfully deleted from database') 492 | else: 493 | file_name = re.sub(r"(_|\-|\.|\+)", " ", str(media.file_name)) 494 | result = await Media.collection.delete_many({ 495 | 'file_name': file_name, 496 | 'file_size': media.file_size, 497 | 'mime_type': media.mime_type 498 | }) 499 | if result.deleted_count: 500 | await msg.edit('File is successfully deleted from database') 501 | else: 502 | # files indexed before https://github.com/EvamariaTG/EvaMaria/commit/f3d2a1bcb155faf44178e5d7a685a1b533e714bf#diff-86b613edf1748372103e94cacff3b578b36b698ef9c16817bb98fe9ef22fb669R39 503 | # have original file name. 504 | result = await Media.collection.delete_many({ 505 | 'file_name': media.file_name, 506 | 'file_size': media.file_size, 507 | 'mime_type': media.mime_type 508 | }) 509 | if result.deleted_count: 510 | await msg.edit('File is successfully deleted from database') 511 | else: 512 | await msg.edit('File not found in database') 513 | 514 | 515 | @Client.on_message(filters.command('deleteall') & filters.user(ADMINS)) 516 | async def delete_all_index(bot, message): 517 | await message.reply_text( 518 | 'This will delete all indexed files.\nDo you want to continue??', 519 | reply_markup=InlineKeyboardMarkup( 520 | [ 521 | [ 522 | InlineKeyboardButton( 523 | text="YES", callback_data="autofilter_delete" 524 | ) 525 | ], 526 | [ 527 | InlineKeyboardButton( 528 | text="CANCEL", callback_data="close_data" 529 | ) 530 | ], 531 | ] 532 | ), 533 | quote=True, 534 | ) 535 | 536 | 537 | @Client.on_callback_query(filters.regex(r'^autofilter_delete')) 538 | async def delete_all_index_confirm(bot, message): 539 | await Media.collection.drop() 540 | await message.answer('Piracy Is Crime') 541 | await message.message.edit('Succesfully Deleted All The Indexed Files.') 542 | 543 | 544 | @Client.on_message(filters.command('settings')) 545 | async def settings(client, message): 546 | userid = message.from_user.id if message.from_user else None 547 | if not userid: 548 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM") 549 | chat_type = message.chat.type 550 | 551 | if chat_type == enums.ChatType.PRIVATE: 552 | grpid = await active_connection(str(userid)) 553 | if grpid is not None: 554 | grp_id = grpid 555 | try: 556 | chat = await client.get_chat(grpid) 557 | title = chat.title 558 | except: 559 | await message.reply_text("Make sure I'm present in your group!!", quote=True) 560 | return 561 | else: 562 | await message.reply_text("I'm not connected to any groups!", quote=True) 563 | return 564 | 565 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 566 | grp_id = message.chat.id 567 | title = message.chat.title 568 | 569 | else: 570 | return 571 | 572 | st = await client.get_chat_member(grp_id, userid) 573 | if ( 574 | st.status != enums.ChatMemberStatus.ADMINISTRATOR 575 | and st.status != enums.ChatMemberStatus.OWNER 576 | and str(userid) not in ADMINS 577 | ): 578 | return 579 | 580 | settings = await get_settings(grp_id) 581 | 582 | try: 583 | if settings['max_btn']: 584 | settings = await get_settings(grp_id) 585 | except KeyError: 586 | await save_group_settings(grp_id, 'max_btn', False) 587 | settings = await get_settings(grp_id) 588 | if 'is_shortlink' not in settings.keys(): 589 | await save_group_settings(grp_id, 'is_shortlink', False) 590 | else: 591 | pass 592 | 593 | if settings is not None: 594 | buttons = [ 595 | [ 596 | InlineKeyboardButton( 597 | 'Rᴇsᴜʟᴛ Pᴀɢᴇ', 598 | callback_data=f'setgs#button#{settings["button"]}#{grp_id}', 599 | ), 600 | InlineKeyboardButton( 601 | 'Bᴜᴛᴛᴏɴ' if settings["button"] else 'Tᴇxᴛ', 602 | callback_data=f'setgs#button#{settings["button"]}#{grp_id}', 603 | ), 604 | ], 605 | [ 606 | InlineKeyboardButton( 607 | 'Fɪʟᴇ Sᴇɴᴅ Mᴏᴅᴇ', 608 | callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}', 609 | ), 610 | InlineKeyboardButton( 611 | 'Mᴀɴᴜᴀʟ Sᴛᴀʀᴛ' if settings["botpm"] else 'Aᴜᴛᴏ Sᴇɴᴅ', 612 | callback_data=f'setgs#botpm#{settings["botpm"]}#{grp_id}', 613 | ), 614 | ], 615 | [ 616 | InlineKeyboardButton( 617 | 'Pʀᴏᴛᴇᴄᴛ Cᴏɴᴛᴇɴᴛ', 618 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}', 619 | ), 620 | InlineKeyboardButton( 621 | '✔ Oɴ' if settings["file_secure"] else '✘ Oғғ', 622 | callback_data=f'setgs#file_secure#{settings["file_secure"]}#{grp_id}', 623 | ), 624 | ], 625 | [ 626 | InlineKeyboardButton( 627 | 'Iᴍᴅʙ', 628 | callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}', 629 | ), 630 | InlineKeyboardButton( 631 | '✔ Oɴ' if settings["imdb"] else '✘ Oғғ', 632 | callback_data=f'setgs#imdb#{settings["imdb"]}#{grp_id}', 633 | ), 634 | ], 635 | [ 636 | InlineKeyboardButton( 637 | 'Sᴘᴇʟʟ Cʜᴇᴄᴋ', 638 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}', 639 | ), 640 | InlineKeyboardButton( 641 | '✔ Oɴ' if settings["spell_check"] else '✘ Oғғ', 642 | callback_data=f'setgs#spell_check#{settings["spell_check"]}#{grp_id}', 643 | ), 644 | ], 645 | [ 646 | InlineKeyboardButton( 647 | 'Wᴇʟᴄᴏᴍᴇ Msɢ', 648 | callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}', 649 | ), 650 | InlineKeyboardButton( 651 | '✔ Oɴ' if settings["welcome"] else '✘ Oғғ', 652 | callback_data=f'setgs#welcome#{settings["welcome"]}#{grp_id}', 653 | ), 654 | ], 655 | [ 656 | InlineKeyboardButton( 657 | 'Aᴜᴛᴏ-Dᴇʟᴇᴛᴇ', 658 | callback_data=f'setgs#auto_delete#{settings["auto_delete"]}#{grp_id}', 659 | ), 660 | InlineKeyboardButton( 661 | '10 Mɪɴs' if settings["auto_delete"] else '✘ Oғғ', 662 | callback_data=f'setgs#auto_delete#{settings["auto_delete"]}#{grp_id}', 663 | ), 664 | ], 665 | [ 666 | InlineKeyboardButton( 667 | 'Aᴜᴛᴏ-Fɪʟᴛᴇʀ', 668 | callback_data=f'setgs#auto_ffilter#{settings["auto_ffilter"]}#{grp_id}', 669 | ), 670 | InlineKeyboardButton( 671 | '✔ Oɴ' if settings["auto_ffilter"] else '✘ Oғғ', 672 | callback_data=f'setgs#auto_ffilter#{settings["auto_ffilter"]}#{grp_id}', 673 | ), 674 | ], 675 | [ 676 | InlineKeyboardButton( 677 | 'Mᴀx Bᴜᴛᴛᴏɴs', 678 | callback_data=f'setgs#max_btn#{settings["max_btn"]}#{grp_id}', 679 | ), 680 | InlineKeyboardButton( 681 | '10' if settings["max_btn"] else f'{MAX_B_TN}', 682 | callback_data=f'setgs#max_btn#{settings["max_btn"]}#{grp_id}', 683 | ), 684 | ], 685 | [ 686 | InlineKeyboardButton( 687 | 'ShortLink', 688 | callback_data=f'setgs#is_shortlink#{settings["is_shortlink"]}#{grp_id}', 689 | ), 690 | InlineKeyboardButton( 691 | '✔ Oɴ' if settings["is_shortlink"] else '✘ Oғғ', 692 | callback_data=f'setgs#is_shortlink#{settings["is_shortlink"]}#{grp_id}', 693 | ), 694 | ], 695 | ] 696 | 697 | btn = [[ 698 | InlineKeyboardButton("Oᴘᴇɴ Hᴇʀᴇ ↓", callback_data=f"opnsetgrp#{grp_id}"), 699 | InlineKeyboardButton("Oᴘᴇɴ Iɴ PM ⇲", callback_data=f"opnsetpm#{grp_id}") 700 | ]] 701 | 702 | reply_markup = InlineKeyboardMarkup(buttons) 703 | if chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 704 | await message.reply_text( 705 | text="Dᴏ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ᴏᴘᴇɴ sᴇᴛᴛɪɴɢs ʜᴇʀᴇ ?", 706 | reply_markup=InlineKeyboardMarkup(btn), 707 | disable_web_page_preview=True, 708 | parse_mode=enums.ParseMode.HTML, 709 | reply_to_message_id=message.id 710 | ) 711 | else: 712 | await message.reply_text( 713 | text=f"Cʜᴀɴɢᴇ Yᴏᴜʀ Sᴇᴛᴛɪɴɢs Fᴏʀ {title} As Yᴏᴜʀ Wɪsʜ ⚙", 714 | reply_markup=reply_markup, 715 | disable_web_page_preview=True, 716 | parse_mode=enums.ParseMode.HTML, 717 | reply_to_message_id=message.id 718 | ) 719 | 720 | 721 | 722 | @Client.on_message(filters.command('set_template')) 723 | async def save_template(client, message): 724 | sts = await message.reply("Checking template") 725 | userid = message.from_user.id if message.from_user else None 726 | if not userid: 727 | return await message.reply(f"You are anonymous admin. Use /connect {message.chat.id} in PM") 728 | chat_type = message.chat.type 729 | 730 | if chat_type == enums.ChatType.PRIVATE: 731 | grpid = await active_connection(str(userid)) 732 | if grpid is not None: 733 | grp_id = grpid 734 | try: 735 | chat = await client.get_chat(grpid) 736 | title = chat.title 737 | except: 738 | await message.reply_text("Make sure I'm present in your group!!", quote=True) 739 | return 740 | else: 741 | await message.reply_text("I'm not connected to any groups!", quote=True) 742 | return 743 | 744 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 745 | grp_id = message.chat.id 746 | title = message.chat.title 747 | 748 | else: 749 | return 750 | 751 | st = await client.get_chat_member(grp_id, userid) 752 | if ( 753 | st.status != enums.ChatMemberStatus.ADMINISTRATOR 754 | and st.status != enums.ChatMemberStatus.OWNER 755 | and str(userid) not in ADMINS 756 | ): 757 | return 758 | 759 | if len(message.command) < 2: 760 | return await sts.edit("No Input!!") 761 | template = message.text.split(" ", 1)[1] 762 | await save_group_settings(grp_id, 'template', template) 763 | await sts.edit(f"Successfully changed template for {title} to\n\n{template}") 764 | 765 | 766 | @Client.on_message((filters.command(["request", "Request"]) | filters.regex("#request") | filters.regex("#Request")) & filters.group) 767 | async def requests(bot, message): 768 | if REQST_CHANNEL is None or SUPPORT_CHAT_ID is None: return # Must add REQST_CHANNEL and SUPPORT_CHAT_ID to use this feature 769 | if message.reply_to_message and SUPPORT_CHAT_ID == message.chat.id: 770 | chat_id = message.chat.id 771 | reporter = str(message.from_user.id) 772 | mention = message.from_user.mention 773 | success = True 774 | content = message.reply_to_message.text 775 | try: 776 | if REQST_CHANNEL is not None: 777 | btn = [[ 778 | InlineKeyboardButton('View Request', url=f"{message.reply_to_message.link}"), 779 | InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}') 780 | ]] 781 | reported_post = await bot.send_message(chat_id=REQST_CHANNEL, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn)) 782 | success = True 783 | elif len(content) >= 3: 784 | for admin in ADMINS: 785 | btn = [[ 786 | InlineKeyboardButton('View Request', url=f"{message.reply_to_message.link}"), 787 | InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}') 788 | ]] 789 | reported_post = await bot.send_message(chat_id=admin, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn)) 790 | success = True 791 | else: 792 | if len(content) < 3: 793 | await message.reply_text("You must type about your request [Minimum 3 Characters]. Requests can't be empty.") 794 | if len(content) < 3: 795 | success = False 796 | except Exception as e: 797 | await message.reply_text(f"Error: {e}") 798 | pass 799 | 800 | elif SUPPORT_CHAT_ID == message.chat.id: 801 | chat_id = message.chat.id 802 | reporter = str(message.from_user.id) 803 | mention = message.from_user.mention 804 | success = True 805 | content = message.text 806 | keywords = ["#request", "/request", "#Request", "/Request"] 807 | for keyword in keywords: 808 | if keyword in content: 809 | content = content.replace(keyword, "") 810 | try: 811 | if REQST_CHANNEL is not None and len(content) >= 3: 812 | btn = [[ 813 | InlineKeyboardButton('View Request', url=f"{message.link}"), 814 | InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}') 815 | ]] 816 | reported_post = await bot.send_message(chat_id=REQST_CHANNEL, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn)) 817 | success = True 818 | elif len(content) >= 3: 819 | for admin in ADMINS: 820 | btn = [[ 821 | InlineKeyboardButton('View Request', url=f"{message.link}"), 822 | InlineKeyboardButton('Show Options', callback_data=f'show_option#{reporter}') 823 | ]] 824 | reported_post = await bot.send_message(chat_id=admin, text=f"𝖱𝖾𝗉𝗈𝗋𝗍𝖾𝗋 : {mention} ({reporter})\n\n𝖬𝖾𝗌𝗌𝖺𝗀𝖾 : {content}", reply_markup=InlineKeyboardMarkup(btn)) 825 | success = True 826 | else: 827 | if len(content) < 3: 828 | await message.reply_text("You must type about your request [Minimum 3 Characters]. Requests can't be empty.") 829 | if len(content) < 3: 830 | success = False 831 | except Exception as e: 832 | await message.reply_text(f"Error: {e}") 833 | pass 834 | 835 | else: 836 | success = False 837 | 838 | if success: 839 | '''if isinstance(REQST_CHANNEL, (int, str)): 840 | channels = [REQST_CHANNEL] 841 | elif isinstance(REQST_CHANNEL, list): 842 | channels = REQST_CHANNEL 843 | for channel in channels: 844 | chat = await bot.get_chat(channel) 845 | #chat = int(chat)''' 846 | link = await bot.create_chat_invite_link(int(REQST_CHANNEL)) 847 | btn = [[ 848 | InlineKeyboardButton('Join Channel', url=link.invite_link), 849 | InlineKeyboardButton('View Request', url=f"{reported_post.link}") 850 | ]] 851 | await message.reply_text("Your request has been added! Please wait for some time.\n\nJoin Channel First & View Request", reply_markup=InlineKeyboardMarkup(btn)) 852 | 853 | @Client.on_message(filters.command("send") & filters.user(ADMINS)) 854 | async def send_msg(bot, message): 855 | if message.reply_to_message: 856 | target_id = message.text.split(" ", 1)[1] 857 | out = "Users Saved In DB Are:\n\n" 858 | success = False 859 | try: 860 | user = await bot.get_users(target_id) 861 | users = await db.get_all_users() 862 | async for usr in users: 863 | out += f"{usr['id']}" 864 | out += '\n' 865 | if str(user.id) in str(out): 866 | await message.reply_to_message.copy(int(user.id)) 867 | success = True 868 | else: 869 | success = False 870 | if success: 871 | await message.reply_text(f"Your message has been successfully send to {user.mention}.") 872 | else: 873 | await message.reply_text("This user didn't started this bot yet !") 874 | except Exception as e: 875 | await message.reply_text(f"Error: {e}") 876 | else: 877 | await message.reply_text("Use this command as a reply to any message using the target chat id. For eg: /send userid") 878 | 879 | @Client.on_message(filters.command("deletefiles") & filters.user(ADMINS)) 880 | async def deletemultiplefiles(bot, message): 881 | chat_type = message.chat.type 882 | if chat_type != enums.ChatType.PRIVATE: 883 | return await message.reply_text(f"Hey {message.from_user.mention}, This command won't work in groups. It only works on my PM !") 884 | else: 885 | pass 886 | try: 887 | keyword = message.text.split(" ", 1)[1] 888 | except: 889 | return await message.reply_text(f"Hey {message.from_user.mention}, Give me a keyword along with the command to delete files.") 890 | k = await bot.send_message(chat_id=message.chat.id, text=f"Fetching Files for your query {keyword} on DB... Please wait...") 891 | files, total = await get_bad_files(keyword) 892 | await k.delete() 893 | #await k.edit_text(f"Found {total} files for your query {keyword} !\n\nFile deletion process will start in 5 seconds !") 894 | #await asyncio.sleep(5) 895 | btn = [[ 896 | InlineKeyboardButton("Yes, Continue !", callback_data=f"killfilesdq#{keyword}") 897 | ],[ 898 | InlineKeyboardButton("No, Abort operation !", callback_data="close_data") 899 | ]] 900 | await message.reply_text( 901 | text=f"Found {total} files for your query {keyword} !\n\nDo you want to delete?", 902 | reply_markup=InlineKeyboardMarkup(btn), 903 | parse_mode=enums.ParseMode.HTML 904 | ) 905 | 906 | @Client.on_message(filters.command("set_shortner")) 907 | async def shortlink(bot, message): 908 | userid = message.from_user.id if message.from_user else None 909 | if not userid: 910 | return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command") 911 | chat_type = message.chat.type 912 | if chat_type == enums.ChatType.PRIVATE: 913 | return await message.reply_text(f"Hey {message.from_user.mention}, This command only works on groups !\n\nFollow These Steps to Connect Shortener:\n\n1. Add Me in Your Group with Full Admin Rights\n\n2. After Adding in Grp, Set your Shortener\n\nSend this command in your group\n\n—> /set_shortner ""{your_shortener_website_name} {your_shortener_api}\n\n#Sample:-\n/set_shortner urlshortx.com aacda989a636df49b60ebd363b56dd5e82095eec\n\nThat's it!!! Enjoy Earning Money 💲\n\n[[[ Trusted Earning Site - https://urlshortx.com/ref/Spidynaik ]]]\n\nIf you have any Doubts, Feel Free to Ask me - @Mr_SPIDYBot") 914 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 915 | grpid = message.chat.id 916 | title = message.chat.title 917 | else: 918 | return 919 | data = message.text 920 | userid = message.from_user.id 921 | user = await bot.get_chat_member(grpid, userid) 922 | if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS: 923 | return await message.reply_text("You don't have access to use this command!\n\nAdd Me to Your Own Group as Admin and Try This Command\n\nFor More PM Me With This Command") 924 | else: 925 | pass 926 | try: 927 | command, shortlink_url, api = data.split(" ") 928 | except: 929 | return await message.reply_text("Command Incomplete :(\n\nGive me a shortener website link and api along with the command !\n\nFormat: /shortlink .com aacda989a636df49b60ebd363b56dd5e82095eec1") 930 | reply = await message.reply_text("Please Wait...") 931 | shortlink_url = re.sub(r"https?://?", "", shortlink_url) 932 | shortlink_url = re.sub(r"[:/]", "", shortlink_url) 933 | await save_group_settings(grpid, 'shortlink', shortlink_url) 934 | await save_group_settings(grpid, 'shortlink_api', api) 935 | await save_group_settings(grpid, 'is_shortlink', True) 936 | await reply.edit_text(f"Successfully added shortlink API for {title}.\n\nCurrent Shortlink Website: {shortlink_url}\nCurrent API: {api}") 937 | 938 | @Client.on_message(filters.command("setshortlinkoff") & filters.user(ADMINS)) 939 | async def offshortlink(bot, message): 940 | chat_type = message.chat.type 941 | if chat_type == enums.ChatType.PRIVATE: 942 | return await message.reply_text("I will Work Only in group") 943 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 944 | grpid = message.chat.id 945 | title = message.chat.title 946 | else: 947 | return 948 | await save_group_settings(grpid, 'is_shortlink', False) 949 | # ENABLE_SHORTLINK = False 950 | return await message.reply_text("Successfully disabled shortlink") 951 | 952 | @Client.on_message(filters.command("setshortlinkon") & filters.user(ADMINS)) 953 | async def onshortlink(bot, message): 954 | chat_type = message.chat.type 955 | if chat_type == enums.ChatType.PRIVATE: 956 | return await message.reply_text("I will Work Only in group") 957 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 958 | grpid = message.chat.id 959 | title = message.chat.title 960 | else: 961 | return 962 | await save_group_settings(grpid, 'is_shortlink', True) 963 | # ENABLE_SHORTLINK = True 964 | return await message.reply_text("Successfully enabled shortlink") 965 | 966 | @Client.on_message(filters.command("get_info")) 967 | async def showshortlink(bot, message): 968 | userid = message.from_user.id if message.from_user else None 969 | if not userid: 970 | return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command") 971 | chat_type = message.chat.type 972 | if chat_type == enums.ChatType.PRIVATE: 973 | return await message.reply_text(f"Hey {message.from_user.mention}, This Command Only Works in Group\n\nTry this command in your own group, if you are using me in your group") 974 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 975 | grpid = message.chat.id 976 | title = message.chat.title 977 | else: 978 | return 979 | chat_id=message.chat.id 980 | userid = message.from_user.id 981 | user = await bot.get_chat_member(grpid, userid) 982 | # if 'shortlink' in settings.keys(): 983 | # su = settings['shortlink'] 984 | # sa = settings['shortlink_api'] 985 | # else: 986 | # return await message.reply_text("Shortener Url Not Connected\n\nYou can Connect Using /shortlink command") 987 | # if 'tutorial' in settings.keys(): 988 | # st = settings['tutorial'] 989 | # else: 990 | # return await message.reply_text("Tutorial Link Not Connected\n\nYou can Connect Using /set_tutorial command") 991 | if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS: 992 | return await message.reply_text("Tʜɪs ᴄᴏᴍᴍᴀɴᴅ Wᴏʀᴋs Oɴʟʏ Fᴏʀ ᴛʜɪs Gʀᴏᴜᴘ Oᴡɴᴇʀ/Aᴅᴍɪɴ\n\nTʀʏ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪɴ ʏᴏᴜʀ Oᴡɴ Gʀᴏᴜᴘ, Iғ Yᴏᴜ Aʀᴇ Usɪɴɢ Mᴇ Iɴ Yᴏᴜʀ Gʀᴏᴜᴘ") 993 | else: 994 | settings = await get_settings(chat_id) #fetching settings for group 995 | if 'shortlink' in settings.keys() and 'tutorial' in settings.keys(): 996 | su = settings['shortlink'] 997 | sa = settings['shortlink_api'] 998 | st = settings['tutorial'] 999 | return await message.reply_text(f"Shortlink Website: {su}\n\nApi: {sa}\n\nTutorial: {st}") 1000 | elif 'shortlink' in settings.keys() and 'tutorial' not in settings.keys(): 1001 | su = settings['shortlink'] 1002 | sa = settings['shortlink_api'] 1003 | return await message.reply_text(f"Shortener Website: {su}\n\nApi: {sa}\n\nTutorial Link Not Connected\n\nYou can Connect Using /set_tutorial command") 1004 | elif 'shortlink' not in settings.keys() and 'tutorial' in settings.keys(): 1005 | st = settings['tutorial'] 1006 | return await message.reply_text(f"Tutorial: {st}\n\nShortener Url Not Connected\n\nYou can Connect Using /shortlink command") 1007 | else: 1008 | return await message.reply_text("Shortener url and Tutorial Link Not Connected. Check this commands, /shortlink and /set_tutorial") 1009 | 1010 | 1011 | @Client.on_message(filters.command("set_tutorial")) 1012 | async def settutorial(bot, message): 1013 | userid = message.from_user.id if message.from_user else None 1014 | if not userid: 1015 | return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command") 1016 | chat_type = message.chat.type 1017 | if chat_type == enums.ChatType.PRIVATE: 1018 | return await message.reply_text("This Command Work Only in group\n\nTry it in your own group") 1019 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 1020 | grpid = message.chat.id 1021 | title = message.chat.title 1022 | else: 1023 | return 1024 | userid = message.from_user.id 1025 | user = await bot.get_chat_member(grpid, userid) 1026 | if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS: 1027 | return 1028 | else: 1029 | pass 1030 | if len(message.command) == 1: 1031 | return await message.reply("Give me a tutorial link along with this command\n\nCommand Usage: /set_tutorial your tutorial link") 1032 | elif len(message.command) == 2: 1033 | reply = await message.reply_text("Please Wait...") 1034 | tutorial = message.command[1] 1035 | await save_group_settings(grpid, 'tutorial', tutorial) 1036 | await save_group_settings(grpid, 'is_tutorial', True) 1037 | await reply.edit_text(f"Successfully Added Tutorial\n\nHere is your tutorial link for your group {title} - {tutorial}") 1038 | else: 1039 | return await message.reply("You entered Incorrect Format\n\nFormat: /set_tutorial your tutorial link") 1040 | 1041 | @Client.on_message(filters.command("remove_tutorial")) 1042 | async def removetutorial(bot, message): 1043 | userid = message.from_user.id if message.from_user else None 1044 | if not userid: 1045 | return await message.reply(f"You are anonymous admin. Turn off anonymous admin and try again this command") 1046 | chat_type = message.chat.type 1047 | if chat_type == enums.ChatType.PRIVATE: 1048 | return await message.reply_text("This Command Work Only in group\n\nTry it in your own group") 1049 | elif chat_type in [enums.ChatType.GROUP, enums.ChatType.SUPERGROUP]: 1050 | grpid = message.chat.id 1051 | title = message.chat.title 1052 | else: 1053 | return 1054 | userid = message.from_user.id 1055 | user = await bot.get_chat_member(grpid, userid) 1056 | if user.status != enums.ChatMemberStatus.ADMINISTRATOR and user.status != enums.ChatMemberStatus.OWNER and str(userid) not in ADMINS: 1057 | return 1058 | else: 1059 | pass 1060 | reply = await message.reply_text("Please Wait...") 1061 | await save_group_settings(grpid, 'is_tutorial', False) 1062 | await reply.edit_text(f"Successfully Removed Your Tutorial Link!!!") 1063 | 1064 | @Client.on_message(filters.command("restart") & filters.user(ADMINS)) 1065 | async def stop_button(bot, message): 1066 | msg = await bot.send_message(text="**🔄 𝙿𝚁𝙾𝙲𝙴𝚂𝚂𝙴𝚂 𝚂𝚃𝙾𝙿𝙴𝙳. 𝙱𝙾𝚃 𝙸𝚂 𝚁𝙴𝚂𝚃𝙰𝚁𝚃𝙸𝙽𝙶...**", chat_id=message.chat.id) 1067 | await asyncio.sleep(3) 1068 | await msg.edit("**✅️ 𝙱𝙾𝚃 𝙸𝚂 𝚁𝙴𝚂𝚃𝙰𝚁𝚃𝙴𝙳. 𝙽𝙾𝚆 𝚈𝙾𝚄 𝙲𝙰𝙽 𝚄𝚂𝙴 𝙼𝙴**") 1069 | os.execl(sys.executable, sys.executable, *sys.argv) 1070 | --------------------------------------------------------------------------------